def get_resource_args(cls, app, resource, request_method, content_type, resource_method=None, include_defaults=False): """Get config args for resource, method, & content type. This fetches the args for a resource, method, and content type from the app registry. Those args can then be used to construct a :class:`Config` instance. By default, only args for the specified content type will be included. .. note:: This is intended primarily for internal use. """ resource_cls = resource.__class__ resource_method = resource_method or request_method resource_method = getattr(resource_cls, resource_method) cls_name = fully_qualified_name(resource_cls) meth_name = fully_qualified_name(resource_method) kwargs = {} if include_defaults: kwargs.update(app.get(config, (cls_name, '*/*'), default={})) kwargs.update(app.get(config, (cls_name, content_type), default={})) if include_defaults: kwargs.update(app.get(config, (meth_name, '*/*'), default={})) kwargs.update(app.get(config, (meth_name, content_type), default={})) return kwargs
def register_action(wrapped, action, tag=None, _registry=_ACTION_REGISTRY): """Register a deferred decorator action. The action will be performed later when :func:`fire_actions` is called with the specified ``tag``. This is used like so:: # mymodule.py def my_decorator(wrapped): def action(some_arg): # do something with some_arg register_action(wrapped, action, tag='x') return wrapped # <-- IMPORTANT @my_decorator def my_func(): # do some stuff Later, :func:`fire_actions` can be called to run ``action``:: fire_actions(mymodule, tags='x', args=('some arg')) """ _registry.setdefault(tag, {}) fq_name = fully_qualified_name(wrapped) actions = _registry[tag].setdefault(fq_name, []) actions.append(action)
def run(self): if self.args.reload and not os.environ.get('MONITOR'): return self.run_with_monitor() print('[{}]'.format(datetime.datetime.now())) factory_name = fully_qualified_name(self.args.app_factory) print('Creating app from {} factory'.format(factory_name)) app = self.make_app() server = None try: message = 'Starting server on http://{0.host}:{0.port}/' server = make_server(self.args.host, self.args.port, app) if self.args.reload: message += ' with file monitor' reload_interval = self.args.reload_interval monitor_thread = MonitorThread(server, reload_interval) monitor_thread.start() message += '...' print(message.format(self.args)) server.serve_forever() # Blocks until server.shutdown() except KeyboardInterrupt: print('\rAborted') except: traceback.print_exc() self.exit('\nCould not start server', 2) finally: if server is not None: server.shutdown() server.server_close()
def run(self): reload = self.args.reload if reload and not os.environ.get('MONITOR'): return self.run_with_monitor() print('[{}]'.format(datetime.datetime.now())) factory_name = fully_qualified_name(self.args.app_factory) print('Creating app from {} factory'.format(factory_name)) app = self.make_app() server = None try: message = 'Starting server on http://{0.host}:{0.port}/' server = make_server(self.args.host, self.args.port, app) if reload: message += ' with file monitor' reload_interval = self.args.reload_interval monitor_thread = MonitorThread(server, reload_interval) monitor_thread.start() message += '...' print(message.format(self.args)) server.serve_forever() # Blocks until server.shutdown() except KeyboardInterrupt: print() except Exception: traceback.print_exc() print('\nCould not start server') return 2 finally: if server is not None: server.shutdown() server.server_close()
def for_resource(cls, app, resource, request_method, content_type, resource_method=None): """Get :class:`Config` for resource, method, & content type. This collects all the relevant config set via ``@config`` and combines it with the default config. Default config is set when ``@config`` args are added via :meth:`add_config_field` and :meth:`add_representation_arg`. Returns an info structure populated with class level defaults for */* plus method level info for ``content_type``. If the resource method name differs from the request method name, pass ``resource_method`` so the method level config can be found. Typically, this wouldn't be used directly; usually :meth:`Request.resource_config` would be used to get the info for the resource associated with the current request. """ resource_cls = resource.__class__ resource_method = resource_method or request_method resource_method = getattr(resource_cls, resource_method) cls_name = fully_qualified_name(resource_cls) meth_name = fully_qualified_name(resource_method) data = [app.get(config, (cls_name, '*/*'))] if content_type != '*/*': data.append(app.get(config, (cls_name, content_type))) data.append(app.get(config, (meth_name, '*/*'))) if content_type != '*/*': data.append(app.get(config, (meth_name, content_type))) kwargs = {} for d in data: if d: kwargs.update(d) return cls(app, request_method, content_type, **kwargs)
def action(app): # This is here so the app won't start if any of the args # passed to @config are invalid. Otherwise, the invalid args # wouldn't be detected until a request is made to a resource # that was decorated with invalid args. NOTE: We can't check # *everything* pre-emptively here, but we do what we can. if isinstance(wrapped, type): Config(app, 'GET', content_type, **kwargs) elif wrapped.__name__ in ALL_HTTP_METHODS: Config(app, wrapped.__name__, content_type, **kwargs) differentiator = fully_qualified_name(wrapped), content_type if app.contains(config, differentiator): app.get(config, differentiator).update(kwargs) else: app.register(config, kwargs, differentiator)
def fire_actions(where, tags=(), args=(), kwargs=None, _registry=_ACTION_REGISTRY): """Fire actions previously registered via :func:`register_action`. ``where`` is typically a package or module. Only actions registered in that package or module will be fired. ``where`` can also be some other type of object, such as a class, in which case only the actions registered on the class and its methods will be fired. Currently, this is considered non-standard usage, but it's useful for testing. If no ``tags`` are specified, all registered actions under ``where`` will be fired. ``*args`` and ``**kwargs`` will be passed to each action that is fired. """ where = load_object(where) where_fq_name = fully_qualified_name(where) tags = (tags, ) if isinstance(tags, str) else tags kwargs = {} if kwargs is None else kwargs if hasattr(where, '__path__'): # Load all modules in package path = where.__path__ prefix = where.__name__ + '.' for (_, name, is_pkg) in pkgutil.walk_packages(path, prefix): if name not in sys.modules: __import__(name) tags = _registry.keys() if not tags else tags for tag in tags: tag_actions = _registry[tag] for fq_name, wrapped_actions in tag_actions.items(): if fq_name.startswith(where_fq_name): for action in wrapped_actions: action(*args, **kwargs)
def fire_actions(where, tags=(), args=(), kwargs=None, _registry=_ACTION_REGISTRY): """Fire actions previously registered via :func:`register_action`. ``where`` is typically a package or module. Only actions registered in that package or module will be fired. ``where`` can also be some other type of object, such as a class, in which case only the actions registered on the class and its methods will be fired. Currently, this is considered non-standard usage, but it's useful for testing. If no ``tags`` are specified, all registered actions under ``where`` will be fired. ``*args`` and ``**kwargs`` will be passed to each action that is fired. """ where = load_object(where) where_fq_name = fully_qualified_name(where) tags = (tags,) if isinstance(tags, str) else tags kwargs = {} if kwargs is None else kwargs if hasattr(where, '__path__'): # Load all modules in package path = where.__path__ prefix = where.__name__ + '.' for (_, name, is_pkg) in pkgutil.walk_packages(path, prefix): if name not in sys.modules: __import__(name) tags = _registry.keys() if not tags else tags for tag in tags: tag_actions = _registry[tag] for fq_name, wrapped_actions in tag_actions.items(): if fq_name.startswith(where_fq_name): for action in wrapped_actions: action(*args, **kwargs)