def test_use_asyncio(framework_aio): pytest.importorskip('asyncio') import txaio txaio.use_asyncio() assert txaio.using_asyncio assert not txaio.using_twisted
def __init__(self, url, realm, session_factory): self._url = url self._realm = realm self._loop = asyncio.get_event_loop() self._factory = session_factory txaio.use_asyncio() txaio.config.loop = self._loop
async def test_04_rejoin_realm(servicefactory, event_loop): # in this case, autobahn requires explicit configuration of the loop via txaio # alternatively, use the regular loop (in some cases may need to init txaio even then) import txaio txaio.use_asyncio() txaio.config.loop = event_loop server = servicefactory() server.set_loop(event_loop) async with CrossbarRouter() as cb: print("----- router starting, waiting for connect: -------") await asyncio.sleep(2, loop=event_loop) await server.start() print("------- router stopped, connection lost: -------") await asyncio.sleep(1, loop=event_loop) async with CrossbarRouter() as cb: print("------ router starting again, waiting for reconnect: -------") await asyncio.sleep(2, loop=event_loop) await server.stop() await asyncio.sleep(1, loop=event_loop)
def run(self, make): """ Run the application component. :param make: A factory that produces instances of :class:`autobahn.asyncio.wamp.ApplicationSession` when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`. :type make: callable """ # 1) factory for use ApplicationSession def create(): cfg = ComponentConfig(self.realm, self.extra) try: session = make(cfg) except Exception as e: # the app component could not be created .. fatal print(e) asyncio.get_event_loop().stop() else: session.debug_app = self.debug_app return session isSecure, host, port, resource, path, params = parseWsUrl(self.url) if self.ssl is None: ssl = isSecure else: if self.ssl and not isSecure: raise RuntimeError( 'ssl argument value passed to %s conflicts with the "ws:" ' 'prefix of the url argument. Did you mean to use "wss:"?' % self.__class__.__name__) ssl = self.ssl # 2) create a WAMP-over-WebSocket transport client factory transport_factory = WampWebSocketClientFactory(create, url=self.url, serializers=self.serializers, debug=self.debug, debug_wamp=self.debug_wamp) # 3) start the client loop = asyncio.get_event_loop() txaio.use_asyncio() txaio.config.loop = loop coro = loop.create_connection(transport_factory, host, port, ssl=ssl) (transport, protocol) = loop.run_until_complete(coro) loop.add_signal_handler(signal.SIGTERM, loop.stop) # 4) now enter the asyncio event loop try: loop.run_forever() except KeyboardInterrupt: # wait until we send Goodbye if user hit ctrl-c # (done outside this except so SIGTERM gets the same handling) pass # give Goodbye message a chance to go through, if we still # have an active session if protocol._session: loop.run_until_complete(protocol._session.leave()) loop.close()
def __init__(self, handler, proto_id, auth_strategy, loop): txaio.use_asyncio() websocket.WebSocketServerProtocol.__init__(self) self._handler = handler self.proto_id = proto_id self._auth_strategy = auth_strategy self._loop = loop self._authentified = False self._auth_app = None self._deauth_handle = None
def run(self, make): """ Run the application component. :param make: A factory that produces instances of :class:`autobahn.asyncio.wamp.ApplicationSession` when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`. :type make: callable """ # 1) factory for use ApplicationSession def create(): cfg = ComponentConfig(self.realm, self.extra) try: session = make(cfg) except Exception as e: # the app component could not be created .. fatal print(e) asyncio.get_event_loop().stop() else: session.debug_app = self.debug_app return session isSecure, host, port, resource, path, params = parseWsUrl(self.url) if self.ssl is None: ssl = isSecure else: if self.ssl and not isSecure: raise RuntimeError( 'ssl argument value passed to %s conflicts with the "ws:" ' 'prefix of the url argument. Did you mean to use "wss:"?' % self.__class__.__name__) ssl = self.ssl # 2) create a WAMP-over-WebSocket transport client factory transport_factory = WampWebSocketClientFactory(create, url=self.url, serializers=self.serializers, debug=self.debug, debug_wamp=self.debug_wamp) # 3) start the client loop = asyncio.get_event_loop() txaio.use_asyncio() txaio.config.loop = loop coro = loop.create_connection(transport_factory, host, port, ssl=ssl) (transport, protocol) = loop.run_until_complete(coro) loop.add_signal_handler(signal.SIGTERM, loop.stop) # 4) now enter the asyncio event loop try: loop.run_forever() except KeyboardInterrupt: # wait until we send Goodbye if user hit ctrl-c # (done outside this except so SIGTERM gets the same handling) pass loop.run_until_complete(protocol._session.leave()) loop.close()
def __init__(self, dbpath=None, maxsize=10485760, readonly=False, sync=True, open=True, log=None): """ :param dbpath: LMDB database path: a directory with (at least) 2 files, a ``data.mdb`` and a ``lock.mdb``. If no database exists at the given path, create a new one. :type dbpath: str :param maxsize: Database size limit in bytes, with a default of 1MB. :type maxsize: int :param read_only: Open database read-only. When ``True``, deny any modifying database operations. Note that the LMDB lock file (``lock.mdb``) still needs to be written (by readers also), and hence at the filesystem level, a LMDB database directory must be writable. :type read_only: bool :param sync: Open database with sync on commit. :type sync: bool """ assert dbpath is None or type(dbpath) == str assert type(maxsize) == int assert type(readonly) == bool assert type(sync) == bool if log: self.log = log else: if not txaio._explicit_framework: txaio.use_asyncio() self.log = txaio.make_logger() if dbpath: self._is_temp = False self._dbpath = dbpath else: self._is_temp = True self._tempdir = tempfile.TemporaryDirectory() self._dbpath = self._tempdir.name self._maxsize = maxsize self._readonly = readonly self._sync = sync self._slots = None self._slots_by_index = None # in a context manager environment we initialize with LMDB handle # when we enter the actual temporary, managed context .. self._env = None # in a direct run environment, we immediately open LMDB if open: self.__enter__()
def run(self, make): """ Run the application component. :param make: A factory that produces instances of :class:`autobahn.asyncio.wamp.ApplicationSession` when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`. :type make: callable """ def _create_app_session(): cfg = ComponentConfig(self._realm, self._extra) try: session = make(cfg) except Exception as e: # the app component could not be created .. fatal asyncio.get_event_loop().stop() raise e else: session.debug_app = self._debug_app return session self._transport_factory = WampWebSocketClientFactory( _create_app_session, url=self._url, serializers=self._serializers) if self._auto_ping_interval is not None and self._auto_ping_timeout is not None: self._transport_factory.setProtocolOptions( openHandshakeTimeout=self._open_handshake_timeout, autoPingInterval=self._auto_ping_interval, autoPingTimeout=self._auto_ping_timeout) txaio.use_asyncio() txaio.config.loop = self._loop asyncio. async (self._connect(), loop=self._loop) try: self._loop.add_signal_handler(signal.SIGTERM, self.stop) except NotImplementedError: # Ignore if not implemented. Means this program is running in windows. pass try: self._loop.run_forever() except KeyboardInterrupt: # wait until we send Goodbye if user hit ctrl-c # (done outside this except so SIGTERM gets the same handling) pass self._closing = True if self._active_protocol and self._active_protocol._session: self._loop.run_until_complete( self._active_protocol._session.leave()) self._loop.close()
def run(self): try: asyncio.set_event_loop(self._loop) txaio.use_asyncio() txaio.config.loop = self._loop # Info is too verbose, use error by default # TODO: Make logging level for autobahn configurable txaio.start_logging(level='error') # create a WAMP-over-WebSocket transport client factory transport_factory = WampWebSocketClientFactory( lambda: self._akcomponent_factory(self._decoupler, self. _callback_executor, self. _allow_exception), url=self._url) # Basic settings with most features disabled transport_factory.setProtocolOptions(failByDrop=False, openHandshakeTimeout=5., closeHandshakeTimeout=1.) isSecure, host, port, _, _, _ = parse_ws_url(self._url) transport, protocol = self._loop.run_until_complete( self._loop.create_connection(transport_factory, host, port, ssl=isSecure)) try: self._loop.run_forever() except KeyboardInterrupt: # wait until we send Goodbye if user hit ctrl-c # (done outside this except so SIGTERM gets the same handling) pass # give Goodbye message a chance to go through, if we still # have an active session if protocol._session: self._loop.run_until_complete(protocol._session.leave()) self._loop.close() except Exception as e: errorStr = pformat(e) stderr.write(errorStr + "\n") # Wake the caller, this thread will terminate right after so the # error can be detected by checking if the thread is alive self._decoupler.set_joined() self._decoupler.unblock_caller()
async def start(self, ctx: Context): # Autobahn uses txaio to bridge the API gap between asyncio and Twisted so we need to set # it up for asyncio here txaio.use_asyncio() txaio.config.loop = get_event_loop() for resource_name, context_attr, client in self.clients: await client.start(ctx) ctx.publish_resource(client, resource_name, context_attr) logger.info( 'Configured WAMP client (%s / ctx.%s; host=%s; port=%d; realm=%s)', resource_name, context_attr, client.host, client.port, client.realm)
def run(self, make): """ Run the application component. :param make: A factory that produces instances of :class:`autobahn.asyncio.wamp.ApplicationSession` when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`. :type make: callable """ # 1) factory for use ApplicationSession def create(): cfg = ComponentConfig(self.realm, self.extra) try: session = make(cfg) except Exception as e: # the app component could not be created .. fatal print(e) asyncio.get_event_loop().stop() else: session.debug_app = self.debug_app return session isSecure, host, port, resource, path, params = parseWsUrl(self.url) if self.ssl is None: ssl = isSecure else: if self.ssl and not isSecure: raise RuntimeError( 'ssl argument value passed to %s conflicts with the "ws:" ' 'prefix of the url argument. Did you mean to use "wss:"?' % self.__class__.__name__) ssl = self.ssl # 2) create a WAMP-over-WebSocket transport client factory transport_factory = WampWebSocketClientFactory(create, url=self.url, serializers=self.serializers, debug=self.debug, debug_wamp=self.debug_wamp) # 3) start the client loop = asyncio.get_event_loop() txaio.use_asyncio() txaio.config.loop = loop coro = loop.create_connection(transport_factory, host, port, ssl=ssl) loop.run_until_complete(coro) # 4) now enter the asyncio event loop loop.run_forever() loop.close()
def run(self, make, app_cfg=None): """ Run the application component. :param make: A factory that produces instances of :class:`autobahn.asyncio.wamp.ApplicationSession` when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`. :type make: callable """ self.loop = self.loop or asyncio.get_event_loop() txaio.use_asyncio() txaio.config.loop = self.loop # 1) factory for use ApplicationSession def create(): cfg = ComponentConfig(self.realm, self.extra) session = make(cfg, app_cfg=app_cfg, loop=self.loop) session.debug_app = self.debug_app return session isSecure, host, port, resource, path, params = parseWsUrl(self.url) if self.ssl is None: ssl = isSecure else: if self.ssl and not isSecure: raise RuntimeError( 'ssl argument value passed to %s conflicts with the "ws:" ' 'prefix of the url argument. Did you mean to use "wss:"?' % self.__class__.__name__) ssl = self.ssl # 2) create a WAMP-over-WebSocket transport client factory transport_factory = WampWebSocketClientFactory( create, url=self.url, serializers=self.serializers, debug=self.debug, debug_wamp=self.debug_wamp, loop=self.loop) # 3) start the client coro = self.loop.create_connection(transport_factory, host, port, ssl=ssl) (self.transport, self.protocol) = self.loop.run_until_complete(coro)
def run(self, make): """ Run the application component. :param make: A factory that produces instances of :class:`autobahn.asyncio.wamp.ApplicationSession` when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`. :type make: callable """ # 1) factory for use ApplicationSession def create(): cfg = ComponentConfig(self.realm, self.extra) try: session = make(cfg) except Exception as e: # the app component could not be created .. fatal print(e) get_event_loop().stop() else: session.debug_app = self.debug_app return session isSecure, host, port, resource, path, params = parseWsUrl(self.url) # 2) create a WAMP-over-WebSocket transport client factory transport_factory = WampWebSocketClientFactory( create, url=self.url, serializers=self.serializers, debug=self.debug, debug_wamp=self.debug_wamp) # 3) start the client loop = get_event_loop() txaio.use_asyncio() txaio.config.loop = loop coro = loop.create_connection(transport_factory, host, port, ssl=isSecure) loop.run_until_complete(coro) # 4) now enter the asyncio event loop loop.run_forever() loop.close()
async def test_03_asyncio_join_realm(servicefactory, event_loop, crossbar_router_running): # in this case, autobahn requires explicit configuration of the loop via txaio # alternatively, use the regular loop (in some cases may need to init txaio even then) import txaio txaio.use_asyncio() txaio.config.loop = event_loop server = servicefactory() server.set_loop(event_loop) await asyncio.sleep(1, loop=event_loop) print("--- waiting for server start() ---") await server.start() await asyncio.sleep(2, loop=event_loop) print("--- waiting for server stop() ---") await server.stop()
def run(self, make): """ Run the application component. :param make: A factory that produces instances of :class:`autobahn.asyncio.wamp.ApplicationSession` when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`. :type make: callable """ def _create_app_session(): cfg = ComponentConfig(self._realm, self._extra) try: session = make(cfg) except Exception as e: # the app component could not be created .. fatal asyncio.get_event_loop().stop() raise e else: session.debug_app = self._debug_app return session self._transport_factory = WampWebSocketClientFactory(_create_app_session, url=self._url, serializers=self._serializers) if self._auto_ping_interval is not None and self._auto_ping_timeout is not None: self._transport_factory.setProtocolOptions(autoPingInterval=self._auto_ping_interval, autoPingTimeout=self._auto_ping_timeout) txaio.use_asyncio() txaio.config.loop = self._loop asyncio.async(self._connect(), loop=self._loop) self._loop.add_signal_handler(signal.SIGTERM, self.stop) try: self._loop.run_forever() except KeyboardInterrupt: # wait until we send Goodbye if user hit ctrl-c # (done outside this except so SIGTERM gets the same handling) pass self._closing = True if self._active_protocol and self._active_protocol._session: self._loop.run_until_complete(self._active_protocol._session.leave()) self._loop.close()
async def start(self, ctx: Context): # Autobahn uses txaio to bridge the API gap between asyncio and Twisted so we need to set # it up for asyncio here txaio.use_asyncio() txaio.config.loop = ctx.loop ctx.add_resource(WAMPExtrasProvider(), 'wamp', types=[ExtrasProvider]) for resource_name, context_attr, client in self.clients: await client.start(ctx) ctx.add_resource(client, resource_name, context_attr) logger.info('Configured WAMP client (%s / ctx.%s; host=%s; port=%d; realm=%s)', resource_name, context_attr, client.host, client.port, client.realm) await yield_() for resource_name, context_attr, client in self.clients: await client.stop() logger.info('Shut down WAMP client (%s)', resource_name)
def run(self, make): # 1) factory for use ApplicationSession def create(): cfg = ComponentConfig(self.realm, self.extra) try: session = make(cfg) except Exception as e: # the app component could not be created .. fatal print(e) asyncio.get_event_loop().stop() else: session.debug_app = self.debug_app return session isSecure, host, port, resource, path, params = parse_url(self.url) if self.ssl is None: ssl = isSecure else: if self.ssl and not isSecure: raise RuntimeError( 'ssl argument value passed to %s conflicts with the "ws:" ' 'prefix of the url argument. Did you mean to use "wss:"?' % self.__class__.__name__) ssl = self.ssl # 2) create a WAMP-over-WebSocket transport client factory transport_factory = WampWebSocketClientFactory(create, url=self.url, serializers=self.serializers) # transport_factory.setProtocolOptions(failByDrop=False, openHandshakeTimeout=90, closeHandshakeTimeout=5) # 3) start the client loop = asyncio.get_event_loop() txaio.use_asyncio() txaio.config.loop = loop coro = loop.create_connection(transport_factory, host, port, ssl=ssl) (transport, protocol) = loop.run_until_complete(coro) try: loop.add_signal_handler(signal.SIGTERM, loop.stop) except NotImplementedError: # signals are not available on Windows pass
def main(): prefix = 'opendna.autobahn.repl' dest__class = { 'connection_manager': f'{prefix}.connections.ConnectionManager', 'connection': f'{prefix}.connections.Connection', 'session': f'{prefix}.sessions.Session', 'call_manager': f'{prefix}.rpc.CallManager', 'call': f'{prefix}.rpc.Call', 'invocation': f'{prefix}.rpc.Invocation', 'registration_manager': f'{prefix}.rpc.RegistrationManager', 'registration': f'{prefix}.rpc.Registration', 'publisher_manager': f'{prefix}.pubsub.PublisherManager', 'publisher': f'{prefix}.pubsub.Publisher', 'publication': f'{prefix}.pubsub.Publication', 'subscription_manager': f'{prefix}.pubsub.SubscriptionManager', 'subscription': f'{prefix}.pubsub.Subscription', 'application_runner': 'autobahn.asyncio.wamp.ApplicationRunner', 'application_session': f'{prefix}.wamp.REPLApplicationSession' } parser = ArgumentParser( description='Python REPL for interacting with Crossbar') for dest, class_ in dest__class.items(): parser.add_argument(f'--{dest.replace("_", "-")}', default=class_, dest=dest) parser.add_argument('--history-file', dest='history_file', default=DEFAULT_HISTORY_FILE) parser.add_argument('--config-file', dest='config_file', default=DEFAULT_CONFIG_FILE) args = parser.parse_args() environ.update({ key: value for key, value in vars(args).items() if key in dest__class or key in {'history_file', 'config_file'} }) loop = asyncio.get_event_loop() txaio.use_asyncio() txaio.config.loop = loop loop.run_until_complete(start_repl(loop)) loop.stop()
def test_01_join_realm(servicefactory, event_loop, crossbar_router_running): # in this case, autobahn requires explicit configuration of the loop via txaio # alternatively, use the regular loop (in some cases may need to init txaio even then) import txaio txaio.use_asyncio() txaio.config.loop = event_loop loop = event_loop server = servicefactory() server.set_loop(loop) time.sleep(1) print("--- running server start() ---") loop.run_until_complete(server.start()) time.sleep(1) print("--- running server stop() ---") loop.run_until_complete(server.stop()) remaining = asyncio.Task.all_tasks(loop=loop) loop.run_until_complete(asyncio.gather(*remaining))
def run(self, make): """ Run the application component. :param make: A factory that produces instances of :class:`autobahn.asyncio.wamp.ApplicationSession` when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`. :type make: callable """ # 1) factory for use ApplicationSession def create(): cfg = ComponentConfig(self.realm, self.extra) try: session = make(cfg) except Exception as e: # the app component could not be created .. fatal print(e) get_event_loop().stop() else: session.debug_app = self.debug_app return session isSecure, host, port, resource, path, params = parseWsUrl(self.url) # 2) create a WAMP-over-WebSocket transport client factory transport_factory = WampWebSocketClientFactory(create, url=self.url, serializers=self.serializers, debug=self.debug, debug_wamp=self.debug_wamp) # 3) start the client loop = get_event_loop() txaio.use_asyncio() txaio.config.loop = loop coro = loop.create_connection(transport_factory, host, port, ssl=isSecure) loop.run_until_complete(coro) # 4) now enter the asyncio event loop loop.run_forever() loop.close()
def _start(self): if self.session: return import asyncio import txaio txaio.use_asyncio() txaio.config.loop = self.loop = asyncio.get_event_loop() from autobahn.wamp import protocol from autobahn.wamp.types import ComponentConfig from autobahn.websocket.util import parse_url from autobahn.asyncio.websocket import WampWebSocketClientFactory from ..remote.client import ClientSession @asyncio.coroutine def _connected(session): self.ready.set() def create(): cfg = ComponentConfig(self.realm, { 'loop': self.loop, 'func': _connected, }) self.session = ClientSession(cfg) return self.session transport_factory = WampWebSocketClientFactory(create, url=self.url) _, host, port, _, _, _ = parse_url(self.url) self.ready = asyncio.Event() coro = self.loop.create_connection(transport_factory, host, port) (transport, protocol) = self.loop.run_until_complete(coro) print(transport, protocol) self.loop.run_until_complete(self.ready.wait())
# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # ############################################################################### import sys import logging import txaio txaio.use_asyncio() # some library you use is using txaio logging stuff class Library(object): log = txaio.make_logger() def something(self): self.log.info("info log from library foo={foo}", foo='bar') self.log.debug("debug information") self.log.error("An error in the library num={num}", num=42) lib = Library() print("logging not started")
from __future__ import absolute_import import signal import six try: import asyncio except ImportError: # Trollius >= 0.3 was renamed to asyncio # noinspection PyUnresolvedReferences import trollius as asyncio import txaio txaio.use_asyncio() # noqa from autobahn.util import public from autobahn.wamp import protocol from autobahn.wamp.types import ComponentConfig from autobahn.websocket.util import parse_url as parse_ws_url from autobahn.rawsocket.util import parse_url as parse_rs_url from autobahn.asyncio.websocket import WampWebSocketClientFactory from autobahn.asyncio.rawsocket import WampRawSocketClientFactory from autobahn.websocket.compress import PerMessageDeflateOffer, \ PerMessageDeflateResponse, PerMessageDeflateResponseAccept __all__ = ('ApplicationSession', 'ApplicationSessionFactory',
def run(self, make, start_loop=True, log_level='info'): """ Run the application component. Under the hood, this runs the event loop (unless `start_loop=False` is passed) so won't return until the program is done. :param make: A factory that produces instances of :class:`autobahn.asyncio.wamp.ApplicationSession` when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`. :type make: callable :param start_loop: When ``True`` (the default) this method start a new asyncio loop. :type start_loop: bool :returns: None is returned, unless you specify `start_loop=False` in which case the coroutine from calling `loop.create_connection()` is returned. This will yield the (transport, protocol) pair. """ if callable(make): def create(): cfg = ComponentConfig(self.realm, self.extra) try: session = make(cfg) except Exception as e: self.log.error( 'ApplicationSession could not be instantiated: {}'. format(e)) loop = asyncio.get_event_loop() if loop.is_running(): loop.stop() raise else: return session else: create = make if self.url.startswith(u'rs'): # try to parse RawSocket URL .. isSecure, host, port = parse_rs_url(self.url) # use the first configured serializer if any (which means, auto-choose "best") serializer = self.serializers[0] if self.serializers else None # create a WAMP-over-RawSocket transport client factory transport_factory = WampRawSocketClientFactory( create, serializer=serializer) else: # try to parse WebSocket URL .. isSecure, host, port, resource, path, params = parse_ws_url( self.url) # create a WAMP-over-WebSocket transport client factory transport_factory = WampWebSocketClientFactory( create, url=self.url, serializers=self.serializers, proxy=self.proxy, headers=self.headers) # client WebSocket settings - similar to: # - http://crossbar.io/docs/WebSocket-Compression/#production-settings # - http://crossbar.io/docs/WebSocket-Options/#production-settings # The permessage-deflate extensions offered to the server .. offers = [PerMessageDeflateOffer()] # Function to accept permessage_delate responses from the server .. def accept(response): if isinstance(response, PerMessageDeflateResponse): return PerMessageDeflateResponseAccept(response) # set WebSocket options for all client connections transport_factory.setProtocolOptions( maxFramePayloadSize=1048576, maxMessagePayloadSize=1048576, autoFragmentSize=65536, failByDrop=False, openHandshakeTimeout=2.5, closeHandshakeTimeout=1., tcpNoDelay=True, autoPingInterval=10., autoPingTimeout=5., autoPingSize=4, perMessageCompressionOffers=offers, perMessageCompressionAccept=accept) # SSL context for client connection if self.ssl is None: ssl = isSecure else: if self.ssl and not isSecure: raise RuntimeError( 'ssl argument value passed to %s conflicts with the "ws:" ' 'prefix of the url argument. Did you mean to use "wss:"?' % self.__class__.__name__) ssl = self.ssl # start the client connection loop = asyncio.get_event_loop() txaio.use_asyncio() txaio.config.loop = loop coro = loop.create_connection(transport_factory, host, port, ssl=ssl) # start a asyncio loop if not start_loop: return coro else: (transport, protocol) = loop.run_until_complete(coro) # start logging txaio.start_logging(level=log_level) try: loop.add_signal_handler(signal.SIGTERM, loop.stop) except NotImplementedError: # signals are not available on Windows pass # 4) now enter the asyncio event loop try: loop.run_forever() except KeyboardInterrupt: # wait until we send Goodbye if user hit ctrl-c # (done outside this except so SIGTERM gets the same handling) pass # give Goodbye message a chance to go through, if we still # have an active session if protocol._session: loop.run_until_complete(protocol._session.leave()) loop.close()
def run(self, make, logging_level='info'): """ Run the application component. :param make: A factory that produces instances of :class:`autobahn.asyncio.wamp.ApplicationSession` when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`. :type make: callable """ def create(): cfg = ComponentConfig(self.realm, self.extra) try: session = make(cfg) except Exception: self.log.failure("App session could not be created! ") asyncio.get_event_loop().stop() else: return session parsed_url = urlparse(self.url) if parsed_url.scheme == 'tcp': is_unix = False if not parsed_url.hostname or not parsed_url.port: raise ValueError('Host and port is required in URL') elif parsed_url.scheme == 'unix' or parsed_url.scheme == '': is_unix = True if not parsed_url.path: raise ValueError('Path to unix socket must be in URL') transport_factory = WampRawSocketClientFactory(create, serializer=self.serializer) loop = asyncio.get_event_loop() if logging_level == 'debug': loop.set_debug(True) txaio.use_asyncio() txaio.config.loop = loop try: loop.add_signal_handler(signal.SIGTERM, loop.stop) except NotImplementedError: # signals are not available on Windows pass def handle_error(loop, context): self.log.error('Application Error: {err}', err=context) loop.stop() loop.set_exception_handler(handle_error) if is_unix: coro = loop.create_unix_connection(transport_factory, parsed_url.path) else: coro = loop.create_connection(transport_factory, parsed_url.hostname, parsed_url.port) (_transport, protocol) = loop.run_until_complete(coro) txaio.start_logging(level=logging_level) # @UndefinedVariable try: loop.run_forever() except KeyboardInterrupt: pass self.log.debug('Left main loop waiting for completion') # give Goodbye message a chance to go through, if we still # have an active session # it's not working now - because protocol is_closed must return Future if protocol._session: loop.run_until_complete(protocol._session.leave()) loop.close()
import six from autobahn.wamp import protocol from autobahn.wamp.types import ComponentConfig from autobahn.websocket.util import parse_url from autobahn.asyncio.websocket import WampWebSocketClientFactory try: import asyncio except ImportError: # Trollius >= 0.3 was renamed to asyncio # noinspection PyUnresolvedReferences import trollius as asyncio import txaio txaio.use_asyncio() __all__ = ( 'ApplicationSession', 'ApplicationSessionFactory', 'ApplicationRunner' ) class ApplicationSession(protocol.ApplicationSession): """ WAMP application session for asyncio-based applications. """ class ApplicationSessionFactory(protocol.ApplicationSessionFactory):
def run(self, make, start_loop=True, log_level='info'): """ Run the application component. Under the hood, this runs the event loop (unless `start_loop=False` is passed) so won't return until the program is done. :param make: A factory that produces instances of :class:`autobahn.asyncio.wamp.ApplicationSession` when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`. :type make: callable :param start_loop: When ``True`` (the default) this method start a new asyncio loop. :type start_loop: bool :returns: None is returned, unless you specify `start_loop=False` in which case the coroutine from calling `loop.create_connection()` is returned. This will yield the (transport, protocol) pair. """ if callable(make): def create(): cfg = ComponentConfig(self.realm, self.extra) try: session = make(cfg) except Exception as e: self.log.error('ApplicationSession could not be instantiated: {}'.format(e)) loop = asyncio.get_event_loop() if loop.is_running(): loop.stop() raise else: return session else: create = make if self.url.startswith(u'rs'): # try to parse RawSocket URL .. isSecure, host, port = parse_rs_url(self.url) # use the first configured serializer if any (which means, auto-choose "best") serializer = self.serializers[0] if self.serializers else None # create a WAMP-over-RawSocket transport client factory transport_factory = WampRawSocketClientFactory(create, serializer=serializer) else: # try to parse WebSocket URL .. isSecure, host, port, resource, path, params = parse_ws_url(self.url) # create a WAMP-over-WebSocket transport client factory transport_factory = WampWebSocketClientFactory(create, url=self.url, serializers=self.serializers, proxy=self.proxy, headers=self.headers) # client WebSocket settings - similar to: # - http://crossbar.io/docs/WebSocket-Compression/#production-settings # - http://crossbar.io/docs/WebSocket-Options/#production-settings # The permessage-deflate extensions offered to the server .. offers = [PerMessageDeflateOffer()] # Function to accept permessage_delate responses from the server .. def accept(response): if isinstance(response, PerMessageDeflateResponse): return PerMessageDeflateResponseAccept(response) # set WebSocket options for all client connections transport_factory.setProtocolOptions(maxFramePayloadSize=1048576, maxMessagePayloadSize=1048576, autoFragmentSize=65536, failByDrop=False, openHandshakeTimeout=2.5, closeHandshakeTimeout=1., tcpNoDelay=True, autoPingInterval=10., autoPingTimeout=5., autoPingSize=4, perMessageCompressionOffers=offers, perMessageCompressionAccept=accept) # SSL context for client connection if self.ssl is None: ssl = isSecure else: if self.ssl and not isSecure: raise RuntimeError( 'ssl argument value passed to %s conflicts with the "ws:" ' 'prefix of the url argument. Did you mean to use "wss:"?' % self.__class__.__name__) ssl = self.ssl # start the client connection loop = asyncio.get_event_loop() if loop.is_closed() and start_loop: asyncio.set_event_loop(asyncio.new_event_loop()) loop = asyncio.get_event_loop() txaio.use_asyncio() txaio.config.loop = loop coro = loop.create_connection(transport_factory, host, port, ssl=ssl) # start a asyncio loop if not start_loop: return coro else: (transport, protocol) = loop.run_until_complete(coro) # start logging txaio.start_logging(level=log_level) try: loop.add_signal_handler(signal.SIGTERM, loop.stop) except NotImplementedError: # signals are not available on Windows pass # 4) now enter the asyncio event loop try: loop.run_forever() except KeyboardInterrupt: # wait until we send Goodbye if user hit ctrl-c # (done outside this except so SIGTERM gets the same handling) pass # give Goodbye message a chance to go through, if we still # have an active session if protocol._session: loop.run_until_complete(protocol._session.leave()) loop.close()
def run(self, make): """ Run the application component. :param make: A factory that produces instances of :class:`autobahn.asyncio.wamp.ApplicationSession` when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`. :type make: callable """ # 1) factory for use ApplicationSession def create(): cfg = ComponentConfig(self.realm, self.extra) try: session = make(cfg) except Exception as e: self.log.error( 'ApplicationSession could not be instantiated: {}'.format( e)) loop = asyncio.get_event_loop() if loop.is_running(): loop.stop() raise else: return session isSecure, host, port, resource, path, params = parse_url(self.url) if self.ssl is None: ssl = isSecure else: if self.ssl and not isSecure: raise RuntimeError( 'ssl argument value passed to %s conflicts with the "ws:" ' 'prefix of the url argument. Did you mean to use "wss:"?' % self.__class__.__name__) ssl = self.ssl # 2) create a WAMP-over-WebSocket transport client factory transport_factory = WampWebSocketClientFactory( create, url=self.url, serializers=self.serializers) # 3) start the client loop = asyncio.get_event_loop() txaio.use_asyncio() txaio.config.loop = loop coro = loop.create_connection(transport_factory, host, port, ssl=ssl) (transport, protocol) = loop.run_until_complete(coro) # start logging txaio.start_logging(level='info') try: loop.add_signal_handler(signal.SIGTERM, loop.stop) except NotImplementedError: # signals are not available on Windows pass # 4) now enter the asyncio event loop try: loop.run_forever() except KeyboardInterrupt: # wait until we send Goodbye if user hit ctrl-c # (done outside this except so SIGTERM gets the same handling) pass # give Goodbye message a chance to go through, if we still # have an active session if protocol._session: loop.run_until_complete(protocol._session.leave()) loop.close()
############################################################################### from __future__ import absolute_import import signal import six try: import asyncio except ImportError: # Trollius >= 0.3 was renamed to asyncio # noinspection PyUnresolvedReferences import trollius as asyncio import txaio txaio.use_asyncio() # noqa from autobahn.util import public from autobahn.wamp import protocol from autobahn.wamp.types import ComponentConfig from autobahn.websocket.util import parse_url as parse_ws_url from autobahn.rawsocket.util import parse_url as parse_rs_url from autobahn.asyncio.websocket import WampWebSocketClientFactory from autobahn.asyncio.rawsocket import WampRawSocketClientFactory from autobahn.websocket.compress import PerMessageDeflateOffer, \ PerMessageDeflateResponse, PerMessageDeflateResponseAccept __all__ = (
def run(): parser = RunnerArgumentParser() parser.add_argument( '-c', '--component', action='append', dest='components', required=True, help= 'Fully-qualified path to a Component class. Can be used multiple times' ) parser.add_argument( '-n', '--necromancy', action='store_true', default=False, help= 'Enable necromancy. Attempts to revive Components whose connection to the WAMP router has failed' ) parser.add_argument( '--necromancy-sleep', default=10, type=int, help='Configure sleep-time between transport death checks') args = parser.parse_args() extras = {} serializers = None if args.extra_file is not None: extras = json.load(open(args.extra_file)) if args.serializers is not None: serializers = [ get_class(serializer) for serializer in args.serializers ] components__runners = [ (get_class(component), ApplicationRunner(extra=extras.get(component), serializers=serializers, **{ key: value for key, value in vars(args).items() if key not in ('components', 'log_level', 'extra_file', 'serializers', 'necromancy', 'necromancy_sleep') })) for component in args.components ] loop = asyncio.get_event_loop() txaio.use_asyncio() txaio.config.loop = loop coros = [ runner.run(component, start_loop=False, log_level=args.log_level) for component, runner in components__runners ] results = loop.run_until_complete(asyncio.gather(*coros)) txaio.start_logging(level=args.log_level) logger = logging.getLogger('autobahn-python-runners') if args.necromancy: logging.info('Necromancy enabled') @asyncio.coroutine def necromancy_check(): nonlocal results, components__runners while True: yield from asyncio.sleep(args.necromancy_sleep) logger.info('Checking for dead transports...') data = enumerate(zip(components__runners, results)) for index, ((component, runner), (transport, protocol)) in data: if transport.is_closing() and not protocol._session: logger.info( 'Dead transport detected. Attempting to raise the dead...' ) results[index] = yield from runner.run( component, start_loop=False, log_level=args.log_level) asyncio.ensure_future(necromancy_check(), loop=loop) try: loop.add_signal_handler(signal.SIGTERM, loop.stop) except NotImplementedError: # signals are not available on Windows pass try: loop.run_forever() except KeyboardInterrupt: # wait until we send Goodbye if user hit ctrl-c # (done outside this except so SIGTERM gets the same handling) pass coros = [ loop.run_until_complete(protocol._session.leave()) for tranport, protocol in results if protocol._session ] loop.close()
def setup_txaio(event_loop): txaio.use_asyncio() txaio.config.loop = event_loop
def run(self, make, logging_level='info'): """ Run the application component. :param make: A factory that produces instances of :class:`autobahn.asyncio.wamp.ApplicationSession` when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`. :type make: callable """ def create(): cfg = ComponentConfig(self.realm, self.extra) try: session = make(cfg) except Exception: self.log.failure("App session could not be created! ") asyncio.get_event_loop().stop() else: return session parsed_url = urlparse(self.url) if parsed_url.scheme == 'tcp': is_unix = False if not parsed_url.hostname or not parsed_url.port: raise ValueError('Host and port is required in URL') elif parsed_url.scheme == 'unix' or parsed_url.scheme == '': is_unix = True if not parsed_url.path: raise ValueError('Path to unix socket must be in URL') transport_factory = WampRawSocketClientFactory( create, serializer=self.serializer) loop = asyncio.get_event_loop() if logging_level == 'debug': loop.set_debug(True) txaio.use_asyncio() txaio.config.loop = loop try: loop.add_signal_handler(signal.SIGTERM, loop.stop) except NotImplementedError: # signals are not available on Windows pass def handle_error(loop, context): self.log.error('Application Error: {err}', err=context) loop.stop() loop.set_exception_handler(handle_error) if is_unix: coro = loop.create_unix_connection(transport_factory, parsed_url.path) else: coro = loop.create_connection(transport_factory, parsed_url.hostname, parsed_url.port) (_transport, protocol) = loop.run_until_complete(coro) txaio.start_logging(level=logging_level) # @UndefinedVariable try: loop.run_forever() except KeyboardInterrupt: pass self.log.debug('Left main loop waiting for completion') # give Goodbye message a chance to go through, if we still # have an active session # it's not working now - because protocol is_closed must return Future if protocol._session: loop.run_until_complete(protocol._session.leave()) loop.close()