def test_request(request, dbsession, registry) -> IRequest: """Create a dummy HTTP request object which can be used to obtain services and adapters. This fixture gives you an instance of :py:class:`pyramid.testing.DummyRequest` object which looks like a request as it would have arrived through HTTP interface. It has request-like properties, namely * registry * dbsession ... and thus can be used to access services, utilies and such which normally would take a request as an argument. Example: .. code-block:: python from websauna.system.user.utils import get_login_service def test_order(dbsession, test_request): service = get_login_service(test_request) The ``request.tm`` is bound to thread-local ``transaction.mananger``. """ request = make_routable_request(dbsession, registry) request.tm = transaction.manager return request
def on_task_init(self, task_id, task): """This method is called before a task is executed. Pass our request context to the task. http://docs.celeryproject.org/en/latest/userguide/tasks.html#context .. note :: The same request object is recycled over and over again. Pyramid does not have correctly mechanisms for having retryable request factory. """ # TODO: How Celery handles retries? # We must not have on-going transaction when worker spawns a task # - otherwise it means init code has left transaction open ensure_transactionless( "Thread local TX was ongoing when Celery fired up a new task {}: {}" .format(task_id, task)) # When using celery groups, the request is not available, we set it here. if not hasattr(self, 'request'): self._set_request() # Each tasks gets a new request with its own transaction manager and dbsession request = make_routable_request(dbsession=None, registry=self.request.registry) task.request.update(request=request)
def on_task_init(self, task_id, task): """This method is called before a task is executed. Pass our request context to the task. http://docs.celeryproject.org/en/latest/userguide/tasks.html#context .. note :: The same request object is recycled over and over again. Pyramid does not have correctly mechanisms for having retryable request factory. """ # TODO: How Celery handles retries? # We must not have on-going transaction when worker spawns a task # - otherwise it means init code has left transaction open ensure_transactionless( "Thread local TX was ongoing when Celery fired up a new task {}: {}" .format(task_id, task)) # Kill thread-local transaction manager, so we minimize issues # with different Celery threading models. # Always use request.tm instead. import transaction transaction.manager = None # Each tasks gets a new request with its own transaction manager and dbsession request = make_routable_request(dbsession=None, registry=self.request.registry) task.request.update(request=request)
def init_websauna_script_env(config_uri: str) -> dict: """Initialize Websauna WSGI application for a IPython notebook. :param config_uri: Path to config INI file :return: Dictionary of shell variables """ options = {"sanity_check": False} app = get_wsgi_app(config_uri, defaults=options) initializer = initializer_from_app(app) registry = initializer.config.registry dbsession = create_dbsession(registry) pyramid_env = scripting.prepare(registry=app.initializer.config.registry) pyramid_env["app"] = app pyramid_env["initializer"] = initializer # Websauna specific # Set up the request with websauna.site_url setting as the base URL request = make_routable_request(dbsession, registry) pyramid_env["request"] = request pyramid_env["dbsession"] = dbsession return pyramid_env
def on_task_init(self, task_id, task): """This method is called before a task is executed. Pass our request context to the task. http://docs.celeryproject.org/en/latest/userguide/tasks.html#context .. note :: The same request object is recycled over and over again. Pyramid does not have correctly mechanisms for having retryable request factory. """ # TODO: How Celery handles retries? # We must not have on-going transaction when worker spawns a task # - otherwise it means init code has left transaction open ensure_transactionless("Thread local TX was ongoing when Celery fired up a new task {}: {}".format(task_id, task)) # Kill thread-local transaction manager, so we minimize issues # with different Celery threading models. # Always use request.tm instead. import transaction transaction.manager = None # Each tasks gets a new request with its own transaction manager and dbsession request = make_routable_request(dbsession=None, registry=self.request.registry) task.request.update(request=request)
def get_traverse_endpoint_context(self, router: Router, route: Route) -> Resource: """Get root object for a traversable route. E.g. resolve /container/* to a SampleContainer context. """ # chop off last part /container/*traverse' start_path = "/".join(route.pattern.split("/")[0:-2]) + "/" # create a new request to traverse based on detected route pattern # dbsession must be passed here to prevent creating new dbsession sample_request = make_routable_request( dbsession=self.request.dbsession, registry=self.request.registry, path=start_path) root = route.factory(sample_request) traverser = self.request.registry.queryAdapter(root, ITraverser) # We are about to traverse and find a context if traverser is None: traverser = ResourceTreeTraverser(root) # {'virtual_root': <websauna.tests.sitemapsamples.SampleContainer object at 0x104656f98>, 'traversed': (), 'root': <websauna.tests.sitemapsamples.SampleContainer object at 0x104656f98>, 'virtual_root_path': (), 'view_name': 'container', 'subpath': (), 'context': <websauna.tests.sitemapsamples.SampleContainer object at 0x104656f98>} tdict = traverser(sample_request) context = tdict["context"] return context
def test_push_render_email(dbsession: Session, registry, user_id): """Create a new activity and generates rendered email notification..""" # Create a request with route_url() request = make_routable_request(dbsession, registry) # Reset test mailer at the beginnign of the test mailer = get_mailer(registry) # Check we got a right type of mailer for our unit test assert isinstance(mailer, DummyMailer) assert len(mailer.outbox) == 0 with transaction.manager: u = dbsession.query(User).get(user_id) # Create an activity a = create_activity(request, "demo_msg", {"text": "foobar"}, uuid4(), u) # Push it through notification channel channel = Email(request) channel.push_notification(a) # DummyMailer updates it outbox immediately, no need to wait transaction.commit assert len(mailer.outbox) == 1
def init_websauna_script_env(config_uri: str) -> dict: """Initialize Websauna WSGI application for a IPython notebook. :param config_uri: Path to config INI file :return: Dictionary of shell variables """ monkey_patch_paster_config_parser() setup_logging(config_uri) bootstrap_env = bootstrap(config_uri, options=dict(sanity_check=False)) app = bootstrap_env["app"] initializer = getattr(app, "initializer", None) assert initializer is not None, "Configuration did not yield to Websauna application with Initializer set up" registry = initializer.config.registry dbsession = create_dbsession(registry) pyramid_env = scripting.prepare(registry=app.initializer.config.registry) pyramid_env["app"] = app pyramid_env["initializer"] = initializer # Websauna specific # Set up the request with websauna.site_url setting as the base URL request = make_routable_request(dbsession, registry) pyramid_env["request"] = request pyramid_env["dbsession"] = dbsession return pyramid_env
def init_websauna(config_uri: str, sanity_check: bool = False, console_app: bool = False, extra_options: dict = None) -> Request: """Initialize Websauna WSGI application for a command line oriented script. Example: .. code-block:: python import sys from websauna.system.devop.cmdline import init_websauna config_uri = sys.argv[1] request = init_websauna(config_uri) :param config_uri: Path to config INI file :param sanity_check: Perform database sanity check on start :param console_app: Set true to setup console-mode logging. See :func:`setup_console_logging` :param extra_options: Passed through bootstrap() and is available as :attr:`websauna.system.Initializer.global_options`. :return: Faux Request object pointing to a site root, having registry and every configured. """ # Paster thinks we are a string if sanity_check: sanity_check = "true" else: sanity_check = "false" options = {"sanity_check": sanity_check} if extra_options: options.update(extra_options) app = get_wsgi_app(config_uri, defaults=options) initializer = initializer_from_app(app) registry = initializer.config.registry dbsession = create_dbsession(registry) # Set up the request with websauna.site_url setting as the base URL request = make_routable_request(dbsession, registry) # This exposes the app object for the integration tests e.g test_static_asset # TODO: Find a cleaner way to do this request.app = app return request
def get_traverse_endpoint_context(self, router: Router, route: Route) -> Resource: """Get root object for a traversable route. E.g. resolve /container/* to a SampleContainer context. """ # chop off last part /container/*traverse' start_path = "/".join(route.pattern.split("/")[0:-2]) + "/" sample_request = make_routable_request(path=start_path, registry=self.request.registry) root = route.factory(sample_request) traverser = self.request.registry.queryAdapter(root, ITraverser) # We are about to traverse and find a context if traverser is None: traverser = ResourceTreeTraverser(root) # {'virtual_root': <websauna.tests.sitemapsamples.SampleContainer object at 0x104656f98>, 'traversed': (), 'root': <websauna.tests.sitemapsamples.SampleContainer object at 0x104656f98>, 'virtual_root_path': (), 'view_name': 'container', 'subpath': (), 'context': <websauna.tests.sitemapsamples.SampleContainer object at 0x104656f98>} tdict = traverser(sample_request) context = tdict["context"] return context
def sitemap_request(sitemap_app): """Create a dummy request object useable for sitemap building tests.""" return make_routable_request(dbsession=None, registry=sitemap_app.init.config.registry)