"stackless" pylons?

2 views
Skip to first unread message

Hans Lellelid

unread,
Mar 14, 2010, 11:38:42 AM3/14/10
to pylons-devel
Hi pylons devs,

First of all, I've been using Pylons for awhile now and want to thank
the developers for a great project. Typically, the way that we use
Pylons is for web services applications, not actually "web sites" --
typically AMF or JSON-RPC (we have very little need for templates and
basically no use for forms, form validation, etc.). The fact that
Pylons is built on WSGI is priceless for this type of application and
make integrating new gateways, etc. so trivial. We love that about
Pylons.

So, here's my question: is there any plan or interest in a Pylons
(Paste?) that does *not* use stacked object proxies for things like
request, session, etc?

I think I understand the use-case for this, but have to say that it
really adds a lot of complexity -- particularly in the area of testing
-- and it seems to only enable a very specific (rare?) use case. If
there was only some sort of flag ... or a Pylons fork that just used
thread-local storage for these "globals". I never want to run
multiple applications in the same thread context; does anyone really
*need* to do that? These stacked object proxies are just a royal pain
to debug. I imagine most developers just throw up a white flag when
they have a run in with one of these quizzical beasts.

Or maybe another way of asking my question (which I've done on pylons-
discuss without any success/response): Is there any easy way to
inject values into the pylons.session or pylons.request in a test case
and have them picked up by the application? This has provided no end
of frustration with Pylons when trying to run quasi-functional tests.
Maybe there's a real obvious solution here and I've just missed it.

I'm not writing just to vent; I'd be more than happy to participate in
a solution here. If a patch would be helpful, I'd be happy to provide
it, but obviously a patch that removes current functionality seems a
little unlikely to be accepted. :)

Thanks,
Hans

Mike Orr

unread,
Mar 14, 2010, 2:10:37 PM3/14/10
to pylons...@googlegroups.com
On Sun, Mar 14, 2010 at 8:38 AM, Hans Lellelid <ha...@velum.net> wrote:
> Hi pylons devs,
>
> First of all, I've been using Pylons for awhile now and want to thank
> the developers for a great project.  Typically, the way that we use
> Pylons is for web services applications, not actually "web sites" --
> typically AMF or JSON-RPC (we have very little need for templates and
> basically no use for forms, form validation, etc.).  The fact that
> Pylons is built on WSGI is priceless for this type of application and
> make integrating new gateways, etc. so trivial.  We love that about
> Pylons.
>
> So, here's my question: is there any plan or interest in a Pylons
> (Paste?) that does *not* use stacked object proxies for things like
> request, session, etc?

SOPs have been controversial for a long time. You might find it
interesting searching the pylons-discuss archives.

I think there's an attribute on the controller instance,
``._py_object``, that contains the request/response/session, etc. And
I think you can disable the magic globals by commenting out the
RegistryManager in middleware.py. You can hunt about in the
interactive traceback.

> I think I understand the use-case for this, but have to say that it
> really adds a lot of complexity -- particularly in the area of testing
> -- and it seems to only enable a very specific (rare?) use case.  If
> there was only some sort of flag ... or a Pylons fork that just used
> thread-local storage for these "globals".  I never want to run
> multiple applications in the same thread context; does anyone really
> *need* to do that?

It's a rare use case. There has been a lot of discussion about
replacing the SOPs with threadlocals. Also, Pylons 2, built on Marco,
will not depend on them, although the compatibility layer will have to
support them for existing apps.

> These stacked object proxies are just a royal pain
> to debug.  I imagine most developers just throw up a white flag when
> they have a run in with one of these quizzical beasts.

The main thing to remember is that ``sop._current_obj()`` returns the
original object. Some builtin functions aren't proxied -- I don't
remember if it's dir(), vars(), or dict() -- so you get back the SOP's
attributes rather than the original object's attributes. In those
cases you have to use ._current_obj().

Otherwise, what actual problems are you having with the SOPs? They
work most of the time; that's why there hasn't been a major push to
get rid of them.

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

Hans Lellelid

unread,
Mar 14, 2010, 5:18:54 PM3/14/10
to pylons...@googlegroups.com
Hi Mike,

Thanks for the response!

>> So, here's my question: is there any plan or interest in a Pylons
>> (Paste?) that does *not* use stacked object proxies for things like
>> request, session, etc?
>
> SOPs have been controversial for a long time. You might find it
> interesting searching the pylons-discuss archives.
>
> I think there's an attribute on the controller instance,
> ``._py_object``, that contains the request/response/session, etc. And
> I think you can disable the magic globals by commenting out the
> RegistryManager in middleware.py. You can hunt about in the
> interactive traceback.

Ah, thank you; I have not yet experimented with the RegistryManager; I
will go down that route to see if it provides a path for achieving what
we want (elaborated below). (And maybe setting them directly on
controllers would provide workaround for certain test cases.)

>> I think I understand the use-case for this, but have to say that it
>> really adds a lot of complexity -- particularly in the area of testing
>> -- and it seems to only enable a very specific (rare?) use case. If
>> there was only some sort of flag ... or a Pylons fork that just used
>> thread-local storage for these "globals". I never want to run
>> multiple applications in the same thread context; does anyone really
>> *need* to do that?
>
> It's a rare use case. There has been a lot of discussion about
> replacing the SOPs with threadlocals. Also, Pylons 2, built on Marco,
> will not depend on them, although the compatibility layer will have to
> support them for existing apps.

Ah, that's excellent (especially if the compat layer can be disabled).
I haven't been following Pylons 2 plans; I'll start reading up on that.

>> These stacked object proxies are just a royal pain
>> to debug. I imagine most developers just throw up a white flag when
>> they have a run in with one of these quizzical beasts.
>
> The main thing to remember is that ``sop._current_obj()`` returns the
> original object. Some builtin functions aren't proxied -- I don't
> remember if it's dir(), vars(), or dict() -- so you get back the SOP's
> attributes rather than the original object's attributes. In those
> cases you have to use ._current_obj().

Yes, I did discover how to pull stuff out of them. I think it takes a
bit more digging than it should, though. I certainly remember wrestling
a bit before figuring out that what I was looking at was actually an SOP
and not an "actual object".

> Otherwise, what actual problems are you having with the SOPs? They
> work most of the time; that's why there hasn't been a major push to
> get rid of them.

Well, my main problem is testing-related; I agree that in the normal
course of events they don't get in the way much, but it feels like they
get in the way all the time when unit testing (but this is important to
us). Here's a very specific case, but seemed to be a general problem we
ran into with SOPs:

We use generic services modules; say we have services/user.py which
contains methods like createUser(), deleteUser(), etc. These services
are exposed via JSON-RPC or AMF gateways (often both), which are just
WSGI apps that we plug in as Pylons controllers. So, (for example) our
services.user module will probably be doing checks against
`pylons.session`. I want to be able to have my UserServiceTest.setUp()
method inject authentication information into `pylons.session` so that
tests in our service layer think we have a valid session (for example).
What we've found is that the `pylons.session` in our test case is not
the same as the `pylons.session` that the services.user service imports.
(Does that make sense? -- I may be misremembering something here.)

Thanks-
Hans

Mike Orr

unread,
Mar 14, 2010, 5:46:09 PM3/14/10
to pylons...@googlegroups.com
On Sun, Mar 14, 2010 at 2:18 PM, Hans Lellelid <ha...@velum.net> wrote:
>> I think there's an attribute on the controller instance,
>> ``._py_object``, that contains the request/response/session, etc. And
>> I think you can disable the magic globals by commenting out the
>> RegistryManager in middleware.py.  You can hunt about in the
>> interactive traceback.
>
> Ah, thank you; I have not yet experimented with the RegistryManager; I will
> go down that route to see if it provides a path for achieving what we want
> (elaborated below).  (And maybe setting them directly on controllers would
> provide workaround for certain test cases.)

I think non-SOPs were originally necessary for asynchronous
applications. I don't know much about that though.

>> There has been a lot of discussion about
>> replacing the SOPs with threadlocals. Also, Pylons 2, built on Marco,
>> will not depend on them, although the compatibility layer will have to
>> support them for existing apps.
>
> Ah, that's excellent (especially if the compat layer can be disabled). I
> haven't been following Pylons 2 plans; I'll start reading up on that.

There's not much to see, and no alphas have been released yet. But Ben
says Pylons runs on Marco at least for a few simple apps. There should
be an announcement later this year when an alpha is ready. But first
1.0 needs to be finished.

> Well, my main problem is testing-related; I agree that in the normal course
> of events they don't get in the way much, but it feels like they get in the
> way all the time when unit testing (but this is important to us).  Here's a
> very specific case, but seemed to be a general problem we ran into with
> SOPs:
>
>  We use generic services modules; say we have services/user.py which
> contains methods like createUser(), deleteUser(), etc.  These services are
> exposed via JSON-RPC or AMF gateways (often both), which are just WSGI apps
> that we plug in as Pylons controllers.  So, (for example) our services.user
> module will probably be doing checks against `pylons.session`.  I want to be
> able to have my UserServiceTest.setUp() method inject authentication
> information into `pylons.session` so that tests in our service layer think
> we have a valid session (for example).  What we've found is that the
> `pylons.session` in our test case is not the same as the `pylons.session`
> that the services.user service imports.  (Does that make sense? -- I may be
> misremembering something here.)

There are a lot of potential problems in the testing environment,
ranging from getting the config early enough, to post-testing the
session. Ben and Philip and Ian have done a good job of building as
much of that as possible into the TestController and WebError. I
still don't understand it very well, and the docs help only so far.
You'll probably get a better answer on pylons-discuss, and we can
invoke Ian if necessary for advice.

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

Reply all
Reply to author
Forward
0 new messages