Hypergolix Python Integration
latest
  • Hypergolix installation
  • Running Hypergolix
  • Hypergolix addresses: Ghid
  • Hypergolix IPC: the HGXLink
  • Basic bytes interface
  • Serialized Python objects
  • “Telemeter” remote monitoring example application
Hypergolix Python Integration
  • Docs »
  • Hypergolix IPC: the HGXLink
  • Edit on GitHub

Hypergolix IPC: the HGXLink¶

class HGXLink(ipc_port=7772, autostart=True, *args, threaded=True, **kwargs)¶

New in version 0.1.

The inter-process communications link to the Hypergolix service. Uses Websockets over localhost, by default on port 7772. Runs in a dedicated event loop, typically within a separate thread. Must be explicitly stopped during cleanup.

Parameters:
  • ipc_port (int) – The localhost port where the Hypergolix service is currently running.
  • autostart (bool) – Automatically connect to Hypergolix and start the HGXLink during __init__. If False, the HGXLink must be explicitly started with start().
  • *args – Passed to loopa.TaskCommander.
  • threaded (bool) – If True, run the HGXLink in a separate thread; if False, run it in the current thread. In non-threaded mode, the HGXLink will block all operations.
  • **kwargs – Passed to loopa.TaskCommander.
Returns:

The HGXLink instance.

>>> import hgx
>>> hgxlink = hgx.HGXLink()
whoami¶

The Ghid representing the public key fingerprint of the currently-logged-in Hypergolix user. This address may be used for sharing objects. This attribute is read-only.

Return Ghid:if successful
Raises:RuntimeError – if the Hypergolix service is unavailable.
>>> hgxlink.whoami
Ghid(algo=1, address=b'\xf8A\xd6`\x11\xedN\x14\xab\xe5"\x16\x0fs\n\x02\x08\xa1\xca\xa6\xc6$\xa7D\xf7\xb9\xa2\xbc\xc0\x8c\xf3\xe1\xefP\xa1]dE\x87\tw\xb1\xc8\x003\xac>\x89U\xdd\xcc\xb5X\x1d\xcf\x8c\x0e\x0e\x03\x7f\x1e]IQ')
token¶

The token for the current application (Python session). Only available after registering the application with the Hypergolix service through one of the register_token() methods. This attribute is read-only.

Return bytes:if the current application has a token.
Raises:RuntimeError – if the current application has no token.
>>> hgxlink.token
AppToken(b'(\x19i\x07&\xff$!h\xa6\x84\xbcr\xd0\xba\xd1')
wrap_threadsafe(callback)¶

Wraps a blocking/synchronous function for use as a callback. The wrapped function will be called from within a single-use, dedicated thread from the HGXLink‘s internal ThreadPoolExecutor, so as not to block the HGXLink event loop.

This may also be used as a decorator.

>>> def threadsafe_callback(obj):
...     print(obj.state)
...
>>> threadsafe_callback
<function threadsafe_callback at 0x00000000051CD620>

>>> # Note that the memory address changes due to wrapping
>>> hgxlink.wrap_threadsafe(threadsafe_callback)
<function threadsafe_callback at 0x00000000051CD6A8>

>>> @hgxlink.wrap_threadsafe
>>> def threadsafe_callback(obj):
...     print(obj.state)
...
>>> threadsafe_callback
<function threadsafe_callback at 0x000000000520B488>
wrap_loopsafe(callback, *, target_loop)¶

Wraps an asynchronous coroutine for use as a callback. The callback will be run in target_loop, which must be different from the HGXLink event loop (there is no need to wrap callbacks running natively from within the HGXLink loop). Use this to have the HGXLink run callbacks from within a different event loop (if your application is also using asyncio and providing its own event loop).

This may also be used as a decorator.

>>> async def loopsafe_callback(obj):
...     print(obj.state)
...
>>> loopsafe_callback
<function loopsafe_callback at 0x0000000005222488>

>>> # Note that the memory address changes due to wrapping
>>> hgxlink.wrap_loopsafe(loopsafe_callback, target_loop=byo_loop)
<function loopsafe_callback at 0x00000000051CD6A8>

>>> @hgxlink.wrap_loopsafe(target_loop=byo_loop)
>>> async def loopsafe_callback(obj):
...     print(obj.state)
...
>>> loopsafe_callback
<function loopsafe_callback at 0x000000000521A228>
start()¶

Starts the HGXLink, connecting to Hypergolix and obtaining the current whoami. Must be called explicitly if autostart was False; otherwise, is called during HGXLink.__init__.

>>> hgxlink.start()
>>>

Note

The following methods each expose three equivalent APIs:

  1. an API for the HGXLink event loop, written plainly (ex: register_token()).

    Warning

    This method must only be awaited from within the internal HGXLink event loop, or it may break the HGXLink, and will likely fail to work.

    This method is a coroutine. Example usage:

    token = await register_token()
    
  2. a threadsafe external API, denoted by the _threadsafe suffix (ex: register_token_threadsafe()).

    Warning

    This method must not be called from within the internal HGXLink event loop, or it will deadlock.

    This method is a standard, blocking, synchronous method. Example usage:

    token = register_token_threadsafe()
    
  3. a loopsafe external API, denoted by the _loopsafe suffix (ex: register_token_loopsafe()).

    Warning

    This method must not be awaited from within the internal HGXLink event loop, or it will deadlock.

    This method is a coroutine that may be awaited from your own external event loop. Example usage:

    token = await register_token_loopsafe()
    
stop()¶
stop_threadsafe()¶
stop_loopsafe()¶

Called to stop the HGXLink and disconnect from Hypergolix. Must be called before exiting the main thread, or the Python process will not exit, and must be manually halted from an operating system process manager.

new(cls, state, api_id=None, dynamic=True, private=False)¶
new_threadsafe(cls, state, api_id=None, dynamic=True, private=False)¶
new_loopsafe(cls, state, api_id=None, dynamic=True, private=False)¶

Makes a new Hypergolix object.

Parameters:
  • cls (type) – the Hypergolix object class to use for this object. See Basic bytes interface.
  • state – the state to initialize the object with. It will be immediately pushed upstream to Hypergolix during creation of the object.
  • api_id (bytes) – the API id to use for this object. If None, defaults to the cls._hgx_DEFAULT_API.
  • dynamic (bool) – determines whether the created object will be dynamic (and therefore mutable), or static (and wholly immutable).
  • private (bool) – determines whether the created object will be restricted to this specific application, for this specific Hypergolix user. By default, objects created by any Hypergolix application are available to all other Hypergolix apps for the current Hypergolix user.
Returns:

the created object.

Raises:
  • hypergolix.exceptions.IPCError – upon IPC failure, or improper object declaration.
  • Exception – for serialization failures. The specific exception type is determined by the serialization process itself.
>>> obj = hgxlink.new_threadsafe(
...     cls = hgx.Obj,
...     state = b'Hello world!'
... )
>>> obj
<Obj with state b'Hello world!' at Ghid('Abf3d...')>
>>> # Get the full address to retrieve the object later
>>> obj.ghid.as_str()
'Abf3dRNZAPhrqY93q4Q-wG0QvPnP_anV8XfauVMlFOvAgeC5JVWeXTUftJ6tmYveH0stGaAJ0jN9xKriTT1F6Mk='
get(cls, ghid)¶
get_threadsafe(cls, ghid)¶
get_loopsafe(cls, ghid)¶

Retrieves an existing Hypergolix object.

Parameters:
  • cls (type) – the Hypergolix object class to use for this object. See Basic bytes interface.
  • ghid (Ghid) – the Ghid address of the object to retrieve.
Returns:

the retrieved object.

Raises:
  • hypergolix.exceptions.IPCError – upon IPC failure, or improper object declaration.
  • Exception – for serialization failures. The specific exception type is determined by the serialization process itself.
>>> address = hgx.Ghid.from_str('Abf3dRNZAPhrqY93q4Q-wG0QvPnP_anV8XfauVMlFOvAgeC5JVWeXTUftJ6tmYveH0stGaAJ0jN9xKriTT1F6Mk=')
>>> obj = hgxlink.get_threadsafe(
...     cls = hgx.ObjBase,
...     ghid = address
... )
>>> obj
<Obj with state b'Hello world!' at Ghid('Abf3d...')>
register_token(token=None)¶
register_token_threadsafe(token=None)¶
register_token_loopsafe(token=None)¶

Requests a new application token from the Hypergolix service or re-registers an existing application with the Hypergolix service. If previous instances of the app token have declared a startup object with the Hypergolix service, returns its address.

Tokens can only be registered once per application. Subsequent attempts to register a token will raise IPCError. Newly-registered tokens will be available at token.

App tokens are required for some advanced features of Hypergolix. This token should be reused whenever (and wherever) that exact application is restarted. It is unique for every application, and every Hypergolix user.

Parameters:token (hypergolix.utils.AppToken) – the application’s pre-registered Hypergolix token, or None to create one.
Raises:hypergolix.exceptions.IPCError – if unsuccessful.
Return None:if no startup object has been declared.
Return hypergolix.Ghid:
 if a startup object has been declared. This is the address of the object, and can be used in a subsequent get() call to retrieve it.
>>> hgxlink.register_token_threadsafe()
>>> hgxlink.token
AppToken(b'(\x19i\x07&\xff$!h\xa6\x84\xbcr\xd0\xba\xd1')

>>> # Some other time, in some other session
>>> app_token = AppToken(b'(\x19i\x07&\xff$!h\xa6\x84\xbcr\xd0\xba\xd1')
>>> hgxlink.register_token_threadsafe(app_token)
register_startup(obj)¶
register_startup_threadsafe(obj)¶
register_startup_loopsafe(obj)¶

Registers an object as the startup object. Startup objects are useful to bootstrap configuration, settings, etc. They can be any Hypergolix object, and will be returned to the application at every subsequent call to register_token(). Startup objects may only be declared after registering an app token.

Parameters:obj – The object to register. May be any Hypergolix object.
Raises:hypergolix.exceptions.UnknownToken – if no token has been registered for the application.
>>> obj = hgxlink.new_threadsafe(Obj, state=b'hello world')
>>> hgxlink.register_startup_threadsafe(obj)
deregister_startup()¶
deregister_startup_threadsafe()¶
deregister_startup_loopsafe()¶

Registers an object as the startup object. Startup objects are useful to bootstrap configuration, settings, etc. They can be any Hypergolix object, and will be returned to the application at every subsequent call to register_token(). Startup objects may only be declared after registering an app token.

Raises:
  • hypergolix.exceptions.UnknownToken – if no token has been registered for the application.
  • Exception – if no object has be registered for startup.
>>> hgxlink.deregister_startup_threadsafe()
register_share_handler(api_id, handler)¶
register_share_handler_threadsafe(api_id, handler)¶
register_share_handler_loopsafe(api_id, handler)¶

Registers a handler for incoming, unsolicited object shares from other Hypergolix users. Without registering a share handler, Hypergolix applications cannot receive shared objects from other users.

The share handler will also be called when other applications from the same Hypergolix user create an object with the appropriate api_id.

The share handler callback will be invoked with three arguments: the Ghid of the incoming object, the fingerprint Ghid of the share origin, and the hypergolix.utils.ApiID of the incoming object.

Parameters:
  • api_id (hypergolix.utils.ApiID) – determines what objects will be sent to the application. Any objects shared with the current Hypergolix user with a matching api_id will be sent to the application.
  • handler – the share handler. Unless the handler can be used safely from within the HGXLink internal event loop, it must be wrapped through wrap_threadsafe() or wrap_loopsafe() prior to registering it as a share handler.
Raises:

TypeError – If the api_id is not hypergolix.utils.ApiID or the handler is not a coroutine (wrap it using wrap_threadsafe() or wrap_loopsafe() prior to registering it as a share handler).

Warning

Any given API ID can have at most a single share handler per app. Subsequent calls to any of the register_share_handler() methods will overwrite the existing share handler without warning.

>>> @hgxlink.wrap_threadsafe
... def handler(ghid, origin, api_id):
...     print('Incoming object: ' + str(ghid))
...     print('Sent by: ' + str(origin))
...     print('With API ID: ' + str(api_id))
...
>>> hgxlink.register_share_handler_threadsafe(
...     api_id = hypergolix.utils.ApiID.pseudorandom(),
...     handler = handler
... )
Next Previous

© Copyright 2016, Muterra, Inc. Revision 9cb0d5c6.

Built with Sphinx using a theme provided by Read the Docs.