From 208e5f6dfc0a1165ffae9dc737ca526abc37c277 2010-08-27 09:14:44 From: Fernando Perez Date: 2010-08-27 09:14:44 Subject: [PATCH] Update message spec with details about attribute, prompts, etc. From discussions over the past few days with Brian and Evan. --- diff --git a/docs/source/development/messaging.txt b/docs/source/development/messaging.txt index 453f5eb..7f9c609 100644 --- a/docs/source/development/messaging.txt +++ b/docs/source/development/messaging.txt @@ -140,6 +140,11 @@ inputs, and run all multiline input in 'exec' mode. This would preserve the natural behavior of single-line inputs while allowing long cells to behave more likea a script. This design will be refined as we complete the implementation. +.. Note:: + + What today we call 'prompt requests' will be encoded in the + ``state_template`` field. + Message type: ``execute_request``:: content = { @@ -148,17 +153,44 @@ Message type: ``execute_request``:: # A boolean flag which, if True, signals the kernel to execute this # code as quietly as possible. This means that the kernel will compile - # the code with 'exec' instead of 'single' (so sys.displayhook will not - # fire), and will *not*: + # the code witIPython/core/tests/h 'exec' instead of 'single' (so + # sys.displayhook will not fire), and will *not*: # - broadcast exceptions on the PUB socket # - do any logging # - populate any history + # # The default is False. 'silent' : bool, + + # An optional string to request arbitrary state information from the + # kernel. This string is evaluated via the itpl module, and it can + # therefore contain arbitrary code for execution. + + 'state_template' : str, } -Upon execution, the kernel *always* sends a reply, with a status code -indicating what happened and additional data depending on the outcome. +Execution semantics + Upon execution of the ``code`` field, the kernel *always* sends a reply, + with a status code indicating what happened and additional data depending + on the outcome. + + Any code in the ``state_template`` string is evaluated, but full exceptions + that may occur are *not* propagated back. If any error occurs during the + evaluation, the value of the string will simply be:: + + [ERROR in : ExceptionType - Exception message] + + The user can simply send the same code contained in the template for normal + evaluation to see a regular traceback. + +Execution counter (old prompt number) + The kernel has a single, monotonically increasing counter of all execution + requests that are made with ``silent=False``. This counter is used to + populate the ``In[n]``, ``Out[n]`` and ``_n`` variables, so clients will + likely want to display it in some form to the user, which will typically + (but not necessarily) be done in the prompts. The value of this counter + will be returned as the ``execution_count`` field of all ``execute_reply``` + messages. Message type: ``execute_reply``:: @@ -166,30 +198,25 @@ Message type: ``execute_reply``:: # One of: 'ok' OR 'error' OR 'abort' 'status' : str, - # This has the same structure as the output of a prompt request, but is - # for the client to set up the *next* prompt (with identical limitations - # to a prompt request) - 'next_prompt' : { - 'prompt_string' : str, - 'prompt_number' : int, - 'input_sep' : str - }, - - # The prompt number of the actual execution for this code, which may be - # different from the one used when the code was typed, which was the - # 'next_prompt' field of the *previous* request. They will differ in the - # case where there is more than one client talking simultaneously to a - # kernel, since the numbers can go out of sync. GUI clients can use this - # to correct the previously written number in-place, terminal ones may - # re-print a corrected one if desired. - 'prompt_number' : int, + # The global kernel counter that increases by one with each non-silent + # executed request. This will typically be used by clients to display + # prompt numbers to the user. If the request was a silent one, this will + # be the current value of the counter in the kernel. + 'execution_count' : int, + + # If the state_template was provided, this will contain the evaluated + # form of the template. + 'state' : str, } When status is 'ok', the following extra fields are present:: { - # The kernel will often transform the input provided to it. This - # contains the transformed code, which is what was actually executed. + # The kernel will often transform the input provided to it. If the + # '---->' transform had been applied, this is filled, otherwise it's the + # empty string. So transformations like magics don't appear here, only + # autocall ones. + 'transformed_code' : str, # The execution payload is a dict with string keys that may have been @@ -235,31 +262,65 @@ When status is 'error', the following extra fields are present:: When status is 'abort', there are for now no additional data fields. This happens when the kernel was interrupted by a signal. +Kernel attribute access +----------------------- -Prompt ------- +While this protocol does not specify full RPC access to arbitrary methods of +the kernel object, the kernel does allow read (and in some cases write) access +to certain attributes. -A simple request for a current prompt string. +The policy for which attributes can be read is: any attribute of the kernel, or +its sub-objects, that belongs to a :class:`Configurable` object and has been +declared at the class-level with Traits validation, is in principle accessible +as long as its name does not begin with a leading underscore. The attribute +itself will have metadata indicating whether it allows remote read and/or write +access. The message spec follows for attribute read and write requests. -Message type: ``prompt_request``:: +Message type: ``getattr_request``:: - content = {} + content = { + # The (possibly dotted) name of the attribute + 'name' : str + } -In the reply, the prompt string comes back with the prompt number placeholder -*unevaluated*. The message format is: - -Message type: ``prompt_reply``:: +When a ``getattr_request`` fails, there are two possible error types: + +- AttributeError: this type of error was raised when trying to access the + given name by the kernel itself. This means that the attribute likely + doesn't exist. + +- AccessError: the attribute exists but its value is not readable remotely. + + +Message type: ``getattr_reply``:: + + content = { + # One of ['ok', 'AttributeError', 'AccessError']. + 'status' : str + # If status is 'ok', a JSON object. + 'value' : object + } + +Message type: ``setattr_request``:: content = { - 'prompt_string' : str, - 'prompt_number' : int, - 'input_sep' : str + # The (possibly dotted) name of the attribute + 'name' : str + + # A JSON-encoded object, that will be validated by the Traits + # information in the kernel + 'value' : object } -Clients can produce a prompt with ``prompt_string.format(prompt_number)``, but -they should be aware that the actual prompt number for that input could change -later, in the case where multiple clients are interacting with a single -kernel. +When a ``setattr_request`` fails, there are also two possible error types with +similar meanings as those of the ``getattr_request`` case, but for writing. + +Message type: ``setattr_reply``:: + + content = { + # One of ['ok', 'AttributeError', 'AccessError']. + 'status' : str + } Object information @@ -276,12 +337,12 @@ Message type: ``object_info_request``:: content = { # The (possibly dotted) name of the object to be searched in all - # relevant namespaces - 'name' : str, + # relevant namespaces + 'name' : str, - # The level of detail desired. The default (0) is equivalent to typing - # 'x?' at the prompt, 1 is equivalent to 'x??'. - 'detail_level' : int, + # The level of detail desired. The default (0) is equivalent to typing + # 'x?' at the prompt, 1 is equivalent to 'x??'. + 'detail_level' : int, } The returned information will be a dictionary with keys very similar to the @@ -315,9 +376,29 @@ Message type: ``object_info_reply``:: 'file' : str, # For pure Python callable objects, we can reconstruct the object - # definition line which provides its call signature + # definition line which provides its call signature. For convenience this + # is returned as a single 'definition' field, but below the raw parts that + # compose it are also returned as the argspec field. 'definition' : str, + # The individual parts that together form the definition string. Clients + # with rich display capabilities may use this to provide a richer and more + # precise representation of the definition line (e.g. by highlighting + # arguments based on the user's cursor position). For non-callable + # objects, this field is empty. + 'argspec' : { # The names of all the arguments + args : list, + # The name of the varargs (*args), if any + varargs : str, + # The name of the varkw (**kw), if any + varkw : str + # The values (as strings) of all default arguments. Note + # that these must be matched *in reverse* with the 'args' + # list above, since the first positional args have no default + # value at all. + func_defaults : list + } + # For instances, provide the constructor signature (the definition of # the __init__ method): 'init_definition' : str,