Adding custom properties to the request, or how is the request meant to be used?

36 views
Skip to first unread message

Torsten Irländer

unread,
Jan 29, 2016, 7:35:04 AM1/29/16
to pylons-devel
Hi all,

The request is  available almost everywhere is a pyramid application. This makes it seductive to use the request to pack many more properties to the request und (mis?)use it as a carrier for some kind of "dependency injection".

I already added the current DB connection (which seems to be a widley used pattern) to it, and some other small thing. But I am wondering how the request is meant to be used. Is it OK to use the request for such things? I tend to say that adding more and more properties to the request (even if they are related to the request) is some kind of misuse and not intended by the developers.

What do you think?

For those who are interested in some background of this question: This questions arised when talking about how to implement Feature Toggles. See https://github.com/ringo-framework/ringo/issues/6

best regards,
Torsten


Paul Everitt

unread,
Jan 29, 2016, 8:00:08 AM1/29/16
to pylons...@googlegroups.com
I think what some people do is put *one* object on the request, such as request.api, as an instance of a class with a bunch of @reify properties and methods such as request.api.db.

This lets you avoid the kind of pollution and potential collisions that you warned about.

—Paul

--
You received this message because you are subscribed to the Google Groups "pylons-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pylons-devel...@googlegroups.com.
To post to this group, send email to pylons...@googlegroups.com.
Visit this group at https://groups.google.com/group/pylons-devel.
For more options, visit https://groups.google.com/d/optout.

Torsten Irländer

unread,
Jan 29, 2016, 8:07:30 AM1/29/16
to pylons-devel
Hi Paul, 

Thanks for the hint. This might be an option! Do you have concerns that the request might get to big and and slows the application down when there are to many things under the namespace "api"? And when is big too big?

Torsten

Paul Everitt

unread,
Jan 29, 2016, 8:29:06 AM1/29/16
to pylons...@googlegroups.com
Make the stuff under request.api either as methods or @reified properties. That way, on each request, you only pay for what you eat. Anything you don’t use in that request, doesn’t get evaluated.

—Paul

Jonathan Vanasco

unread,
Jan 29, 2016, 2:09:07 PM1/29/16
to pylons-devel
I have about a dozen reified request properties on an application.  They're great.

It's entirely possible to abuse it – but that's what coding standards are for.

We have about a dozen objects on our request.  They could be consolidated into a smaller, nested, hierarchy... but they're all "request specific".  

A few of our properties are documented as "public" – and ensured to work across our application.  A few of them are documented as "private" -- they're enabled(registered) by a single component that may or may not be enabled.  No code outside that component can touch it.   (for example, our caching layer and some environment-specific debugging).

Pyramid's implementation of add_request_method + reify meant there's virtually no overhead during runtime (95% of them are never called during a request).  We could have created a singular "api" namespace, but then we would need to re-implement the add_request_method for registration and management.  That seemed onerous.

Looking at the example you gave, since you're doing this on a framework, I think it would be a bit different.

Personally, I would create a reify'd '.ringo' property on each request for the "public api" (and possibly use `_ringo` for non-public/core usage).  I would have that property be a request-specific context object.  `request.features.FOO` could be a way to handle the `request.registry.settings` data.  functions could then either rely on `request.ringo` or be invoked with the context object as an argument.  

Torsten Irländer

unread,
Jan 29, 2016, 5:33:40 PM1/29/16
to pylons-devel
Jonathan,

Thanks for your reply. It helps me to mitigate my concerns on how to use the request. Especially yours and Pauls pointer to @reify is of great value.  I must admit that I wasn't aware of this. What a pitty after working so long with pyramid :/

Thanks to your answers, I am now equipped with new options to solve problems! 

Jonathan Vanasco

unread,
Jan 29, 2016, 6:42:36 PM1/29/16
to pylons-devel
Read the docs on `add_request_method`.  It's pretty great.  I think the docs continue on the set property method, and explain the pattern a bit more.

Anyways, combined with reify, there is very little overhead.  You can also use dotted-name strings to register, which can make things a bit easier for writing extensions/plugins.

Just to clarify my earlier point: If you were merely building your own application, I would do everything on the request itself.  Since you're building/maintaing a framework though, I think you may be better off with your own "context" objects that gets tossed onto the request.  That could give you better control of modules/plugins registering with your application.  

Mike Orr

unread,
Jan 29, 2016, 11:25:41 PM1/29/16
to pylons...@googlegroups.com
The request is for anything you need. Some frameworks pass a request
and response to the view and have other global objects and things, but
Pyramid tends to use the request to put all that stuff in one place.
Even semi-exceptions like 'context' that can be received separately
are also in the request. So I would do likewise, starting with
database connections.

In one application I have SQLAlchemy sessions to three databases, the
underlying engines to them, a Redis connection pool, an ldap3 pool,
things from tweens, and maybe other things. I tried different
strategies like add_request_method, a request subclass, and
pyramid_services. I ended up using a request subclass just because it
was easier to manage all those things together rather than piecemeal,
If I had only one or two I'd use add_request_method. And I use reify
as much as feasable.

Global things used across all requests can go into 'registry' or
'registry.settings', or you can use pyramid_services or the registry
interface API. Things like engines and connection pools are global and
thread-save so you can use them directly, although I ultimately found
it more convenient to make reified request properties that shadow
them. SQLAlchemy sessions have to be created for each request, so I
use reified properties for those, getting the engine from the
registry.

The features example you cited has an object that knows about the
features. But aren't boolean features ultimiately controlled by
configuration settings to enable them? You may be able to just use the
settings, or define your own settings, and then you wouldn't have to
make custom request properties.
> --
> You received this message because you are subscribed to the Google Groups
> "pylons-devel" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to pylons-devel...@googlegroups.com.
> To post to this group, send email to pylons...@googlegroups.com.
> Visit this group at https://groups.google.com/group/pylons-devel.
> For more options, visit https://groups.google.com/d/optout.



--
Mike Orr <slugg...@gmail.com>

Torsten Irländer

unread,
Jan 30, 2016, 6:10:53 AM1/30/16
to pylons-devel
Maik,


Am Samstag, 30. Januar 2016 05:25:41 UTC+1 schrieb Mike Orr:
The request is for anything you need. Some frameworks pass a request
and response to the view and have other global objects and things, but
Pyramid tends to use the request to put all that stuff in one place.
Even semi-exceptions like 'context' that can be received separately
are also in the request. So I would do likewise, starting with
database connections.

In one application I have SQLAlchemy sessions to three databases, the
underlying engines to them, a Redis connection pool, an ldap3 pool,
things from tweens, and maybe other things. I tried different
strategies like add_request_method, a request subclass, and
pyramid_services. I ended up using a request subclass just because it
was easier to manage all those things together rather than piecemeal,
If I had only one or two I'd use add_request_method. And I use reify
as much as feasable.

Thanks for sharing your experience. I have currently only the need for little things to be added to the request so the add_request_method seems to be my way, but the more I think about using the request object for more things I like the idea of a subclass also :)
 

The features example you cited has an object that knows about the
features. But aren't boolean features ultimiately controlled by
configuration settings to enable them?

Yes, I thought of putting the configuration into the ini file.
 
You may be able to just use the
settings, or define your own settings, and then you wouldn't have to
make custom request properties.

This was definitly the preferred way before I know that I have other options to make the flag for the feature directly available in the request. I was about to  write a helper method which returns the value of from registry.settings. This is pretty simple and straight forward and just does its job.

Especially for the "Feature Toogle" thing I think I'll stick with the helper method appraoch to stay consistend with the current way to do things in my application. 

The biggest challange for me now is to stay calm in the face of the new and very interesting and tempting alternatives and ideas you have offered to me. And to *not* change things just for the reason there is a more elegant way ;)

Torsten Irländer

unread,
Jan 30, 2016, 2:09:39 PM1/30/16
to pylons-devel


Am Samstag, 30. Januar 2016 12:10:53 UTC+1 schrieb Torsten Irländer:
Maik,

Mike of course. Sorry.

Torsten 
Reply all
Reply to author
Forward
0 new messages