Re: How to get request object inside decorator?
See http://docs.pylonsproject.org/projects/pyramid/en/1.3-branch/designdefense.html#stacked-object-proxies-are-too-clever-thread-locals-are-a-nuisance When a request object is provided magically by the framework, then the unit tests have to create a fake request object and then jump through whatever hooks the framework requires to make the request available. When a request object is expected as an argument, you don't have to do this, you can just create the request object and pass it in to the function that you're calling. Even so, as Chris said, it's your software. `get_current_request` is available. Do what you want. There's no need to get indignant just because someone has an opinion that contradicts yours, even if your opinion *is* based on 3 years of Pylons experience. -r On Wed Jun 20 09:14:33 2012, Max Avanov wrote: I don't used to blindly believe something just because it was written that way. The docs are not just a collection of essay about web development. It should be explanatory and clear. That is their main purpose. I came to Pyramid after three years of Pylons-based web development. It wasn't hard to test pylons-based applications. So, why the get_current_request makes it possible to write code that can be neither easily tested nor scripted? On Wednesday, June 20, 2012 7:57:34 PM UTC+4, Chris McDonough wrote: On 06/20/2012 11:55 AM, Max Avanov wrote: I wonder why pyramid documentation prefers one solution to another. If some method is objectively better than another, I would like to know it before I make a decision. It's discussed in the docs about get_current_registry and threadlocals. You can read it and believe it, or not (it says something like makes testing harder and more fragile). If you believe it, don't use threadlocals. If you don't believe it or don't care, use them. - C -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To view this discussion on the web visit https://groups.google.com/d/msg/pylons-discuss/-/ZmB9gWa-zkMJ. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en. -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
Re: Storing settings on module level -- bad idea?
These are reasonable points to make. But Pyramid is explicitly not trying to be the same thing that either Django or Rails is trying to be. Those are what we call opinionated frameworks, which make things easier on less experienced developers by making many choices for them. This usually comes at a cost; you lose flexibility, and you have to wrestle w/ the framework when you realize that the choice you want to make isn't in fact the one your tool has made. Pyramid has some opinions, sure, but far fewer of them. It's intended to strike the right balance between flexibility, performance, and ease of use for more experienced developers. Some people complain about certain features b/c I'm never gonna need this, and it confuses me, can't we just rip it out? But in every case that feature is there b/c SOMEone had to solve a hard problem and that was the best way to do it. Ripping it out would make those hard problems harder to solve. But Pyramid targets those hard problems, and thus the features stay. This case w/ globals is similar, although slightly inverted. In many cases module-level global settings are fine; they make the developers life a little bit easier, and they don't cause any problems. But in some cases they *do* cause problems. Real, honest to god developer pain. Django and Pylons have both hit this in the real world. For Django it's fine, it's a trade-off that makes sense given their philosophy and their target audience. For Pyramid it doesn't, b/c Pyramid is just as interested in reducing developer friction in the hard cases as it is the easy cases, and so they make a different set of trade-offs. Does this mean that Pyramid will never be as widely used as Django? Probably. Does that matter? Nope. -r On 1/31/12 8:16 PM, Jonathan Vanasco wrote: my .02¢ is this: App Developers like features like 'Globals'. It's something that is familiar-from, and present-in many other frameworks. Granted, pyramid is a low-level framework - and one that a more 'webmonkey' friendly framework might be built upon itself. But those frameworks are likely to end up implementing those features themselves... both in bad ways, and in many numerous different ways. If pyramid can find a way to pull it off correctly, it would be great. Rails didn't succeed because it was a great framework, its success is largely do to it being usable-by and appealing-to really bad developers ( i mean really awful ones ). PHP got to be ubiquitous and installed on every platform, by just doing a shoddy job implementing everything, so even the worst developers flocked to it. People I've been introduced to by recruiters as Top Django Pros! commanding 160k salaries, have been robots that barely know python. I loved pylons, I love pyramid. I only get to code about 20% of my time, and love being able to work in them, because they're implemented in a way that really resonates with how I like to work. The problem though, is that I'm usually running operations, tech or product at a company -- not implementing it. Having to source people to execute on goals is a pain. I understand why technically some things might not be right or ideal, and why they shouldn't be done -- but sometimes the best route for adoption and continued health isn't to do the right thing. sorry for ranting on this. /j -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To view this discussion on the web visit https://groups.google.com/d/msg/pylons-discuss/-/ddSQnMKjZZ4J. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en. -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
Re: Crazy behavior of `Making A “User Object” Available as a Request Attribute`
On 10/17/11 1:42 PM, neurino wrote: Reading one more time Michael mail about the recipe: It advocates a mechanism to query the user the first time you access that property of the request object and cache the result in memory for the lifetime of that request *That's right the way I wanted it to work!* So why if I reload a page my user is not queried again and stills to an older state? Um, is it possible that you're just getting the same page from your browser cache, and therefore you're not hitting your server at all? Have you tried shift-reload to see if that changes the behaviour? -r I *don't want* at all to have session variables, I want a brand new queried request.user attribute each time the user loads its profile page. Thanks for your support neurino On Mon, Oct 17, 2011 at 7:24 PM, Michael Merickel mmeri...@gmail.com mailto:mmeri...@gmail.com wrote: It advocates a mechanism to query the user the first time you access that property of the request object and cache the result in memory for the lifetime of that request -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en. -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
Re: in defense of traversal
On 10/12/11 10:10 AM, Iain Duncan wrote: (was going to be one post, split in two). I'm wondering about making this into a larger article that could be posted on the docs. This is insightful, thanks for sharing your experiences here. If you're serious about contributing to the docs, you might consider revising the Much Ado About Traversal chapter to include some of this information in the Use Cases section. You could even move that section to the start of the chapter, renaming it to Why should you care about traversal? or something similar, so folks can decide up front if they care enough to bother reading the rest of it to learn how traversal works. -r A lot of people don't get what the heck good traversal is. Part of the issue is that it's a bit harder to make it really shine without using the zodb, but it's certainly possible. We've done it using SQLAlchemy by having all content types in our cms inherit from one base content type using SA table inheritance. The base type holds the parent child relationships, the path, the title, and links into our system wide permission persistancy scheme. This works like a charm. Sure, the table structure is more complicated, but security is rock solid, and the real kicker: USERS FREAKING LOVE TRAVERSAL! I challenge anyone who has dismissed it, to sit a client down in front of a traversal based CMS and watch them. Wow, you don't need to tell them anything, they get it right away because it looks and acts *just like their file system*. We, the *developers*, love Rest APIs. They make perfect clean sense, but look at those urls. They match our persistancy scheme, they match how the database thinks, not how the user thinks. As we try to sell people on our CMS compared to Drupal, the main selling point is honestly that they find administering a traversal based CMS very easy to understand, and they can find things easily. Users hate not being able to find how to changes something ( looking at you, Drupal, gag! ) We use rest-ful schemes all the time in our admin back end and for ajax serving, I'm not anti rest by any stretch. But since we changed to a traversal scheme for the public side of our cms and introduced admin features on that side ( much like plone ), our users are way way happier. Even administering row-level permissions is simple for them, because they get the idea instantly that by default every child has the same permissions as it's parent. They are way happier thinking about the tree and not the content type. It makes more sense to user that a piece of content has a set of permissions because of *where* it is than *what it is*. You put something somewhere, it's in that folder. Of course if you can't access a folder you can't access it's contents, it makes intrinsic sense. Users think in traversal. Bottom line, that's what matters. Now aside from ranting, would it perhaps be useful for me to post sometime a more detailed example of how we accomplished traversal based permissions and editing using an SQLAlchemy back end? ( It will be a while, but I need to write lots of documentation for internal company purposes anyway so maybe could kill two birds with one stone) iain -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en. -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
Re: in defense of traversal
On 10/12/11 11:00 AM, Parnell Springmeyer wrote: One quick thing to add: I am building/maintaining a *big* production application that is 100% on top of Pyramid and strictly uses Traversal and SQLAlchemy. One thing worth noting when using traversal w/ SQL is that you often pay a lookup penalty, since every part of the requested URL path usually results in an additional database query (e.g. GET /foo/bar/baz would be at least 3 queries). And modeling trees in SQL is trickier than it seems, it's easy to build inefficient lookups (although to be fair usually find child of X named Y isn't too heavy). This won't matter for many uses, but at scale it can have significant impact. -r -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
Re: in defense of traversal
On 10/12/11 2:18 PM, Thomas G. Willis wrote: On Wednesday, October 12, 2011 2:53:09 PM UTC-4, Rob Miller wrote: On 10/12/11 11:00 AM, Parnell Springmeyer wrote: One quick thing to add: I am building/maintaining a *big* production application that is 100% on top of Pyramid and strictly uses Traversal and SQLAlchemy. One thing worth noting when using traversal w/ SQL is that you often pay a lookup penalty, since every part of the requested URL path usually results in an additional database query (e.g. GET /foo/bar/baz would be at least 3 queries). or 3 requests to memcached. :) Indeed. Also, I can imagine that it would be possible in the root factory to have enough information to everything for the context path that it can in one batch. I haven't needed to implement this yet, but it's in the tech debt at work for if things go down in flames. Right, as Michael suggested a custom traverser could be used here. -r -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
Re: uhh web2pyramid?
Yup, and docs.pylonshq.com was misconfigured to still be pointing at the joke page. Now fixed. -r On 9/7/11 11:30 AM, Joe Dallago wrote: Nah it was an April Fools' Day joke. On Wed, Sep 7, 2011 at 12:54 PM, Siddhartha Kasivajhula countvajh...@gmail.com mailto:countvajh...@gmail.com wrote: Has the pylons site been hacked? http://docs.pylonshq.com/ -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com mailto:pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com mailto:pylons-discuss%2bunsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en. -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en. -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
Re: pyramid - traversal struggle
yeah, if you want to nest your URLs arbitrarily deep and you want human-readable URLs traversal might be a good choice... that need wasn't clear from your original description. in any event, i tried to point you in the right direction. hopefully it was useful. :) -r On 06/15/2011 03:07 AM, toudi wrote: I did read 'Much ado about traversal and it was one of the reasons i decided to go that way. Let me give you a quick example: Let's assume, that in e-commerce application we have a place for logged in user. He can access it via: /account So far so good. Now, this account panel should have some modules. Let's say, that it has a 'shop' module which gives some basic information about user's shop: /account/shop now we can have another submodule, let's say about products: /account/shop/products and so on. When using URL matching approach we would need to define those routes manually: config.add_route(/account, views.account) config.add_route(/account/shop, views.account.shop) and so on (because we don't know how nested the modules can be i believe we cannot regexp it) But it isn't very flexible - an ideal approach for me would be the sittuation when somebody could somehow create url matches and / or traversal contexts inside the actual modules. So for example: #/views/account/account.py config.add_route(/account/ ... ) #/views/account/shop.py and so on. however, when using URL matching we still must define those routes. I was hoping to use traversal in order to do something like this: #views/account/account.py root.add_child(account) #views/account/shop.py root[account].add_child(shop) #views/account/shop/products.py root[account][shop].add_child(products) and so on. (however i believe i cannot have both shop.py and a folder named shop, but that's just an example ;) ) Another classic scenario is an admin backend for application - it also has many submodules. And i used a dict because i was trying to follow the docs section about Resources - there's an example there: class Resource(dict): pass however when i used it like this i got some error about a dict not being callable or hashable ( i don't know for sure right now because i don't have the code ). Then i read about locations and the need of using __name__ and __parent__ in resources therefore i created an object. The wiki tutorial had another implementation of resources, however it used ZODB which i was not going to use ( in pylons i used sqlalchemy ). Also, a wiki tutorial didn't quite fit into my problem because (i don't know the technical term for that) wiki uses 'flat' urls ( i.e. / wiki/pagename/action ). On 15 Cze, 02:30, Rob Millerr...@kalistra.com wrote: /me dons his traversal explainer cape and mask... first, and foremost, i don't think you actually need or want traversal here. you say you read the traversal and resources chapters of the docs, but did you read the much ado about traversal piece (http://tinyurl.com/4exxjvw)? especially the use cases section, where it describes the cases where traversal is a better choice than URL matching. your use case meets none of those criteria, AFAICT, so you probably don't want to use traversal at all. i'm pretty sure you CAN still use config.scan to register your views even w/o traversal, so i'm not entirely sure what the problem is there. but, just for the fun of it, let's say traversal was a good idea. what are you doing wrong? there are a few things that seem a bit wonky in the code (e.g. the fact that your resource class inherits from dict but then doesn't act like a dict, delegating to a contained dictionary attribute instead), but i'll ignore those for now. the main problem seems to be that you're trying to use specific instances as your context, when really context is better suited to using types. something like this is probably closer to what you want (totally untested, use at your own risk, this code may steal your car and eat your cookies, etc.): class Resource(object): def __init__(self, name=None, parent=None): self.__name__ = name self.__parent__ = parent self.children = {} def add_child(self, name, klass=None, **kw): if klass is None: child = Resource(name, self) else: child = klass(name, self, **kw) self.children[name] = child def __getitem__(self, name): return self.children[name] class Task(Resource): pass then you'll need to instantiate some of these things: root = Resource('root') root.add_child('some_task', Task) root.add_child('another_task', Task) now you can register a view on Task objects like this: @view_config(name=method, context=Task) def task_method(request): task = request.context ... do something w/ your task object ... return Response(...) if this is all wired up correctly then the following paths should resolve to your view: /some_task/method /another_task/method now it might be
Re: pyramid - traversal struggle
/me dons his traversal explainer cape and mask... first, and foremost, i don't think you actually need or want traversal here. you say you read the traversal and resources chapters of the docs, but did you read the much ado about traversal piece (http://tinyurl.com/4exxjvw)? especially the use cases section, where it describes the cases where traversal is a better choice than URL matching. your use case meets none of those criteria, AFAICT, so you probably don't want to use traversal at all. i'm pretty sure you CAN still use config.scan to register your views even w/o traversal, so i'm not entirely sure what the problem is there. but, just for the fun of it, let's say traversal was a good idea. what are you doing wrong? there are a few things that seem a bit wonky in the code (e.g. the fact that your resource class inherits from dict but then doesn't act like a dict, delegating to a contained dictionary attribute instead), but i'll ignore those for now. the main problem seems to be that you're trying to use specific instances as your context, when really context is better suited to using types. something like this is probably closer to what you want (totally untested, use at your own risk, this code may steal your car and eat your cookies, etc.): class Resource(object): def __init__(self, name=None, parent=None): self.__name__ = name self.__parent__ = parent self.children = {} def add_child(self, name, klass=None, **kw): if klass is None: child = Resource(name, self) else: child = klass(name, self, **kw) self.children[name] = child def __getitem__(self, name): return self.children[name] class Task(Resource): pass then you'll need to instantiate some of these things: root = Resource('root') root.add_child('some_task', Task) root.add_child('another_task', Task) now you can register a view on Task objects like this: @view_config(name=method, context=Task) def task_method(request): task = request.context ... do something w/ your task object ... return Response(...) if this is all wired up correctly then the following paths should resolve to your view: /some_task/method /another_task/method now it might be possible to achieve the same thing by using a specific instance as your context rather than a class... the view config docs don't say anything about that, though, and i've never done it; i'd find it a bit confusing. hope this helps, -r On 06/14/2011 01:58 PM, toudi wrote: hello. before i begin i would like to say, that i have read both 'Traversal' and 'Resources' chapters from pyramid docs. I also read this thread - http://groups.google.com/group/pylons-devel/browse_thread/thread/a8d4cc7e8d0c9855 which is a similar problem i have, but i still cannot wrap my mind around traversal. However, i think it's the best approach for me, because of it's config.scan() capabilities. I also have a background in pylons, which i was using without any problems. So - to keep my long story short, i am trying to implement a fairly simplistic application (task / bugtracker) in order to learn pyramid. Here are the models: User - a developer Task - a Bug, that can have one developer and many comments. Comment - a Task comment. i have named my project 'flyswatter', therefore: #flyswatter/__init__.py ... config = Configurator(settings=settings) config.add_static_view('static', 'flyswatter:static') config.scan(.views) ... #flyswatter/resources.py class Resource(dict, object): def __init__(self, name = None, parent = None): self.__name__ = name self.__parent__ = parent self.children = {} def add_child(self, name): self.children[name] = Resource(name = name, parent = self) def __getitem__(self, name): return self.children.get(name) root = Resource() now - onto my problem. I would like to use config.scan() and traversal in order to map url's to the views. my view directory structure looks like this: #flyswatter/flyswatter/views __init__.py default.py task.py admin admin/__init__.py admin/foo.py The only way i managed to combine the traversal with views mapping is like this: #views/default.py from flyswatter.resources import root @view_config(context = root) def index(request): return Response('root::index') @view_config(name=method, context = root) def method(self): return Response('root::method') so far so good - url's / and /method are correctly mapped. #views/task.py from flyswatter.resources import root, Resource root.add_child(task) root[task].add_child(method) @view_config(name=task_index, context = root[task]) def index(request): return Response('task::index') @view_config(name=task_method, context=root[task]) def method(request): return Response('task::method') not so good - in order to access task.method
Re: Pyramid question...
On 03/02/2011 07:34 PM, Joe Dallago wrote: So I am relatively new to the Pyramid scene, so correct me if I am wrong, but this is the conclusion I have come to on this topic. B/c I too struggled for a few days over this. Resources: First of all, resources were originally called models, but the name was purposely changed to avoid confusion with SQLAlchemy models or with the normal idea of what a MVC model is. A resource is simply one element in the resource tree. The entire purpose of the resource tree is to define the structure of your site. A resource isn't necessarily connected to a persistence system, such as an RDBMS, but it definitely can be. It is also important to note that the resource tree is only used when traversal is used as the routing system. Traversal is simply the process by which the router moves down the resource tree according to the url, and assigns the context and view. Context: In traversal, the context is the last resource that is loaded as the router traverses the resource tree, either due to the fact that there are no elements left in the url or that the router has reached the bottom of the tree. View: The view is element of the url that directly follows the context(i.e. /pages/add, if 'pages' is loaded as the context, then 'add' becomes the view). It is essentially the function that does all of the business logic and sends important information to the template. In traversal the context found through the traversal is passed into this view function, whereas in Url Dispatch, the root_factory defined when the view is added to the registry creates an object that is passed into the view as the context(this could be the root of your application or even another resource that you might want to use in the view, it just has to be a class). As Chris said, great description, thank you! I don't know about the zope.interfaces question. Disclaimer: Many (most?) Pyramid apps, even ones that use traversal, never need to use interfaces. You can build all sorts of useful stuff w/o interfaces. If you don't want to know about interfaces, please happily pretend they don't exist, and don't read any further. For those of you still interested, however, interfaces can be useful when you want more pluggability. In most of Pyramid's traversal examples, views are registered against resource classes, so the edit view for a BlogPost class would be different than the edit view for a User class, which would be different again from the edit view for a Photo class. But what if all of your different resource types support tags, and you have a single ``tags`` view that would work for all of them? You could register the same view 3 times, for 3 different context types. Or you could register your view against an ITaggable interface: from myproject.interfaces import ITaggable @view_config(name='tags', context=ITaggable) def tags_view(request): context = request.context ... {do tags stuff here } .. Now you'd declare that all of the taggable resource types support the ITaggable interface, by putting an ``implements(ITaggable)`` in the class definition, like so: from zope.interface import implements from myproject.interfaces import ITaggable class BlogPost(object): implements(ITaggable) def __init__(self): ... {do blogpost stuff here} ... If you're building a framework of some sort, then someone else who develops a taggable custom resource type can get the tags view for free by adding the ``implements(ITaggable)`` line to their class definition. Note that interfaces used as such are really just flags on the class; an interface doesn't actually have to define an API. In fact, an interface can be completely empty: from zope.interface import Interface class ITaggable(Interface): pass An interface CAN define an API, however. If it does so, then any class that declares support for the interface should implement the specified API. This will not be enforced... you can lie about it and declare a class to support an interface when it actually doesn't. Not typically a good idea, though. ;) -r -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
Re: Using DB-API with Pyramid
On 2/10/11 6:40 PM, Christopher Weimann wrote: I'm using DB-API in my Pylons app as described in on this wiki page. http://wiki.pylonshq.com/display/pylonscookbook/Using+the+DB-API+in+Pylons The gist of which is to add the following to lib/app_globals.py from pylons import config import psycopg2 from DBUtils.PooledDB import PooledDB class Globals(object): def __init__(self): self.pool = PooledDB( psycopg2, 5, database=config['app_conf']['pool.database'], user=config['app_conf']['pool.user'], host=config['app_conf']['pool.host'] ) then in a controller you can get a connection with conn = g.pool.connection() How would I do the equivalent with Pyramid? This is untested, but i think you could do something like this in your startup code:: from pyramid.registry import global_registry global_registry.pool = PooledDB(...) Then in your view code, or anywhere you have a request object, you should be able to get at it via `request.registry.pool`. -r -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
Re: pyramid doc bugs/requests/suggestions
On 02/06/2011 12:45 PM, Iain Duncan wrote: I'm a reasonably competent BFG user who was a pylons user before that, and am now going through the pyramid docs. Can someone tell me where I should send details of mistakes, typos, or things that could be clearer? The sphinx source for the docs are in the source tree, which is on github. You can file bug reports on the github tracker, or (even better) clone the repo, make some edits, and make a pull request to have your changes reviewed. :) -r -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
Re: [Pylons 1.0] Decomposing complex actions, DB queries in model's methods
On 01/21/2011 01:47 AM, Andrey Popp wrote: Hello, On Jan 21, 2011, at 1:48 AM, Juliusz Gonera wrote: Is it considered bad practice to make DB queries in model's methods? Or is this the way to go? Yes, it's a bad practice in general -- model should be persistence-agnostic. for the record, there are lots of folks who disagree with this statement. while there are certainly cases where the extra abstractions that you detail below are useful, IMHO they're overkill for most applications, which are only intended to work w/ a single persistence engine and which gain little benefit from the added complexity. -r And even if you're not planning to use the same models with different storage options or outside of SQLAlchemy context, I still recommend you to separate queries and data manipulation routines in separate class -- ModelManager, ModelRepository, ... The rules that I follow are: * If function operates on entire table (insert something into table, query from table or etc.) -- it should become a member or model's manager. * If function is a part of behavior of model (in a sense of its domain)-- it should become model's method. So, I think it's worth to delegate such relationship management to model's manager: class MainModelManager(object): def add_some_related_object(self, main_obj, param1, param2): # query something related = SomeRelatedObject() main_obj.some_related_objects.append(related) If you think, that this method would require also some participation of main model's inner state, you can replace `main_obj.some_related_objects.append(related)` with special method of MainModel: class MainModel(object): def add_some_related_object(self, related): # some business logic, which is not require database access main_obj.some_related_objects.append(related) class MainModelManager(object): def add_some_related_object(self, main_obj, param1, param2): # query something related = SomeRelatedObject() main_obj.add_some_related_objects(related) This way you can separate business logic from persistence. It also helps to provide better testability of you code, cause you can test domain logic inside `MainModel.add_some_related_object` without requiring existence of test SQL database. -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
Re: [Pylons 1.0] Decomposing complex actions, DB queries in model's methods
On 1/21/11 9:31 AM, Juliusz Gonera wrote: Rob Miller wrote: for the record, there are lots of folks who disagree with this statement. while there are certainly cases where the extra abstractions that you detail below are useful, IMHO they're overkill for most applications, which are only intended to work w/ a single persistence engine and which gain little benefit from the added complexity. I'm also a bit scared of this because I don't want my Pylons app to look like Spring or EJB app ;) It looks a bit like the anemic model anti-pattern: http://martinfowler.com/bliki/AnemicDomainModel.html I mean, making separate manager object could be useful, but I'm 99% sure that I won't replace SQLAlchemy with something else. I just remember reading that using SQLAlchemy queries makes transition to Pyramid harder. do you happen to remember where you read this? i wouldn't think this would be the case. while the sqlalchemy idioms used in the documentation and/or paster templates might vary a bit btn pylons and pyramid (specifically pyramid usually shows the use of the repoze.tm2 middleware to handle transaction commits), neither framework actually has any formal opinion about how persistence should be handled, and i can't think of any reason why you'd have to make any significant changes to how you interact w/ the database when porting from one to the other. This also isn't something I would worry about, but I just wondered if using the Session object in model is actually a bad practice. i don't see anything inherently wrong w/ it, as long as you're willing to accept the repercussions: you'll be more closely tied to sqlalchemy, and you'll have to either provide or mock a database session in order to test your models. -r -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
Re: [Pylons 1.0] Decomposing complex actions, DB queries in model's methods
On 1/20/11 11:36 PM, Nathan Wright wrote: As Mariano was saying, it might be possible save yourself some trouble by using mappers directly instead of DeclarativeBase. You'd likely be able to make your python objects easier to work with because they won't be tied 1-to-1 to the schema that you're building on. This isn't about defining relations so much as composing your mapped classes into their most logical form. A single mapped class can span multiple tables or do practically whatever else you want. YMMV but it's worth a look. this! sqlalchemy is deliberately very flexible, and it allows you to have nice separation between your data model and your object model. you might pay a performance hit for this abstraction, of course, but in many (most?) cases it's an acceptable one. sqlalchemy is the only ORM i've used with which i've never had to make any design compromises. i can put together my table structures and my object models separately, and then wire them up with mappers so they work as desired. and i've done some pretty weird stuff, where the attributes for a given class were actually dynamically generated by an attributes table, with a separate table storing the values of these attributes. i had to dig in pretty deeply (i had to implement my own MappedCollection subclass to handle some tricky relationships between my models), but it worked like a charm when i fully expected it to be impossible. -r -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
Re: setup.py
On 01/14/2011 07:05 PM, webjunkie wrote: I'm in the process of deploying my app, and when I take a look at setup.py I see that the install_requires section only has Pylons and SQLAlchemy but I've been installing other components through easy install like turbomail,repoze.who, etc. Why they don't show up in the install_requires section?, do I have to type them manually?, is there a way to update install_requires in setup.py when you add new components?. as mentioned, your project's setup.py doesn't get automatically updated, tracking dependencies is primarily a manual process. however, if you've got a virtualenv that has only your requirements installed, you can use pip freeze to generate a list of the installed packages. then you can either use this as a requirements file for future installs w/ pip, or you can extract the pertinent package info and put it into your package's setup.py. -r -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
Re: setup.py
On 01/14/2011 10:23 PM, Rob Miller wrote: On 01/14/2011 07:05 PM, webjunkie wrote: I'm in the process of deploying my app, and when I take a look at setup.py I see that the install_requires section only has Pylons and SQLAlchemy but I've been installing other components through easy install like turbomail,repoze.who, etc. Why they don't show up in the install_requires section?, do I have to type them manually?, is there a way to update install_requires in setup.py when you add new components?. as mentioned, your project's setup.py doesn't get automatically updated, tracking dependencies is primarily a manual process. however, if you've got a virtualenv that has only your requirements installed, you can use pip freeze to generate a list of the installed packages. then you can either use this as a requirements file for future installs w/ pip, or you can extract the pertinent package info and put it into your package's setup.py. whoops, meant to include this url: http://pip.openplans.org/#freezing-requirements -r -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
Much Ado About Traversal
Since resource traversal is a new concept to most Pylons-ers, and since it's clear that many folks are having a hard time understanding it and why they'd want to use it, I decided to write up an article demystifying the topic: http://blog.nonsequitarian.org/2010/much-ado-about-traversal/ It was conveniently also an excuse for me to finally get off my ass and get a blog together... I'm still working out the kinks and getting feeds set up, but I hope to get it wired through Planet Python soon. Expect more posts on Pyramid-related topics in the future. -r -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-disc...@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
Re: Pyramid Traversal
On 12/30/10 5:15 PM, Burak Cankurtaran wrote: Thanks Rob, I'll look into using the predicates to narrow down the traversal. I guess in the future there will be higher-level wrappers built into pyramid to hide the resource tree etc when it is only used for URL matching. Not sure what you mean here. If you're only doing URL matching, there IS no resource tree. A resource tree is only in play when you're using traversal, in which case you most certainly don't want to hide it. P.S The reason I'm not using URL dispatch is because my problem is not properly defined yet. Traversal seems more powerful than URL dispatch even though I can't fully yet appreciate/comprehend using traversal as a persistent data store, so better safe than sorry. If your problem isn't properly defined, you probably shouldn't yet be building software to solve it. Traversal is preferable to URL matching in a handful of well-defined cases: - your URL structures may be nested arbitrarily deep - your users may be modifying your URL structures at run-time, e.g. w/ a CMS-type application, where people are adding new content in a specific place. (note that this is really a special case of the first condition.) - you need context-sensitive ACL type (sometimes known as instance-based or row-level) security. If you have none of these requirements, then URL matching is probably a better bet for you. -r Happy New Year! On 31 December 2010 05:23, Rob Millerr...@kalistra.com wrote: On 12/30/10 6:43 AM, Burak Cankurtaran wrote: Hi, I'm new to python and pyramid. I am currently trying to get traversal working. I started with the pyramid_starter project template. Currently there is the default view generated by the template and a Welcome view I created. Question at bottom of post. The views.py module: # from pyramid.response import Response def my_view(request): return {'project':'test'} def welcome(request): return Response(Welcome) ### My resource tree is generated in the resources.py module: ### class Resource(dict): pass root = Resource({'Welcome': Resource()}) def get_root(request): return root ### and the views are configured in the __init__ module as: ### from pyramid.config import Configurator from test.resources import get_root, Resource def main(global_config, **settings): This function returns a Pyramid WSGI application. config = Configurator(root_factory=get_root, settings=settings) config.add_view('test.views.my_view', context='test.Resource', renderer='test:templates/mytemplate.pt') if i'm understanding correctly, the context here should actually be 'test:resources.Resource', correct? config.add_view('test.views.welcome', context='test:resources.Resource', renderer='welcome.mak') config.add_static_view('static', 'test:static') return config.make_wsgi_app() ## I am having issues with the context of the welcome view configuration. As you can see it is defined as context='test:resources.Resource' which is the same as my_view. I realise that the context must somehow reference the Welcome resource in the resource tree. Actually, this isn't quite true. A view context must be a class or an interface, not an instance. Another way to put this is that, with the context predicate, you're registering views against particular _types_ of objects, not specific instances. Let's suppose that you do want to register the welcome view so that it only shows up on your Welcome object and no other one. You've got a couple of options. You could define a Welcome class:: class Welcome(Resource): Empty subclass used for view registration then you'd define your root like so:: root = Resource({'Welcome': Welcome()}) and your view registration would look like this:: config.add_view('test.views.welcome', context='test:resources.Welcome', renderer='welcome.mak') That'd work, but if that's the only ``Welcome`` object you're going to have in the entire site, it smells a bit funny to be creating a subclass just for the view registration. Luckily, you can use any of the other view predicates (see http://docs.pylonshq.com/pyramid/dev/narr/views.html#predicate-arguments). In this case, you'd still use ``test:resources.Resource`` as the context. But then you could use the ``path_info`` predicate to check that the request path starts with ``/Welcome``. Or you could pass in a ``custom_predicates`` with a single callable that will simply check to see whether the context is the object you expect it to be. However, I cannot use something like test:resources.Resource.Welcome as Welcome is not a member of the Resource class. Can somebody point out what I should do get this simple case working. I am having difficulties in constructing a proper and well defined resource tree. Maybe I
Re: Adventures in Pylons - Pyramid: WSGIController.__call__
On 12/14/10 9:25 AM, Chris McDonough wrote: In trying to think this through I've come up w/ a couple of ideas: - I could write my own set of action decorators that implement the desired functionality in addition to marking the wrapped functions as exposed actions. This would essentially be the same thing as stacking multiple decorators around each of the functions, except that it avoids having to stack multiple decorators around each of the functions. ;) - I could override the router itself, to allow me to keep the wrapped functionality closer to the WSGI level. Pyramid doesn't really provide any hooks for this, however. It'd be easy enough to change Pyramid to fetch the router by interface rather than by class, making it possible to supply an alternate router implementation, but there's a lot of code in that __call__ method; I'm not terribly fond of copy/pasting large blocks of code only to add a handful of additional lines to the middle somewhere. Does anyone have any other suggestions? Opinions on the suggestions I've made? Has anybody out there thought about how to handle this pattern in a Pyramid upgrade? This is probably not a 100% solution, but have you seen http://docs.pylonshq.com/pyramid/dev/narr/hooks.html#using-finished-callbacks ? Yeah, I saw both the response and the finished callbacks, and am already using them for other purposes. But, as you said, they don't handle all of the cases, especially not those where try: excepts are put around the entire WSGIController.__call__ invocation. Right now I'm leaning towards using a custom @action decorator. This decorator would call a method on the handler that would wrap the view callable before adding the view callable to the registry. I'll let you know how it turns out. -r -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-disc...@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
Re: Adventures in Pylons - Pyramid: WSGIController.__call__
On 12/14/10 11:24 AM, Chris McDonough wrote: On Tue, 2010-12-14 at 10:36 -0800, Rob Miller wrote: On 12/14/10 9:25 AM, Chris McDonough wrote: In trying to think this through I've come up w/ a couple of ideas: - I could write my own set of action decorators that implement the desired functionality in addition to marking the wrapped functions as exposed actions. This would essentially be the same thing as stacking multiple decorators around each of the functions, except that it avoids having to stack multiple decorators around each of the functions. ;) - I could override the router itself, to allow me to keep the wrapped functionality closer to the WSGI level. Pyramid doesn't really provide any hooks for this, however. It'd be easy enough to change Pyramid to fetch the router by interface rather than by class, making it possible to supply an alternate router implementation, but there's a lot of code in that __call__ method; I'm not terribly fond of copy/pasting large blocks of code only to add a handful of additional lines to the middle somewhere. Does anyone have any other suggestions? Opinions on the suggestions I've made? Has anybody out there thought about how to handle this pattern in a Pyramid upgrade? This is probably not a 100% solution, but have you seen http://docs.pylonshq.com/pyramid/dev/narr/hooks.html#using-finished-callbacks ? Yeah, I saw both the response and the finished callbacks, and am already using them for other purposes. But, as you said, they don't handle all of the cases, especially not those where try: excepts are put around the entire WSGIController.__call__ invocation. Right now I'm leaning towards using a custom @action decorator. This decorator would call a method on the handler that would wrap the view callable before adding the view callable to the registry. I'll let you know how it turns out. I'd probably do it the other way around: @view_config(...) @mydecorator(...) def aview(request): ... or class AHandler(object): def __init__(self, request): self.request = request @action() @mydecorator(...) def aview(self): Both cases would add the *decorated* function / method to the registry, which is probably what you want (the @action and @view_config dectorators just attach attributes to the function / method, they don't actually wrap the callable when it is called). Yeah, that's essentially what I meant, sorry for being unclear. I'm thinking a bit more syntactic sugar, though, something along the lines of: class AHandler(object): def __init__(self, request): self.request = request @classmethod def _action_wrapper(klass, wrapped): def action_method_wrapper(self, *args, **kw): do stuff ret = wrapped(self, *args, **kw) do more stuff return ret return action_method_wrapper @myaction(...) def aview(self): regular view code Then the myaction decorator would call AHandler._action_wrapper(aview) to generate a wrapped view callable, which would then finally be registered. This is only half-baked; I'm not even sure I can _get_ to the AHandler class from within the myaction decorator yet, but if I can then this would let me mirror the existing controller class hierarchy with a set of handler classes, moving the code from the older __call__ methods to the newer _action_wrapper class methods w/o too much of a conceptual leap. does this seem like it would work? -r -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-disc...@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
Adventures in Pylons - Pyramid: WSGIController.__call__
Hi all, So I've started taking a look at what it would take to port a large suite of Pylons 0.9.6 apps to Pyramid. Most of what needs to happen looks pretty straightforward; we'd need to convert all of the routes wiring to the new handler / action mechanisms, and make some superficial changes to the code within the action methods. Maybe a bit painstaking and repetitive, but not particularly mind-bending. There's one pattern in use that presents a bigger problem, however. These apps have a shared set of controller base classes, from which the actual controller implementations within the apps themselves inherit. Some of what happens in these controller base classes is just additional API stuff, fairly easily converted to a parallel set of handler base classes. The tricky parts, though, are the cases where these controllers have overridden the __call__ method to effectively wrap the entire WSGI invocation to do such handy things as logging, caching, and error handling. This isn't easy to replicate, because with Pyramid there's no way to get control of the outer layers of the request processing cycle like there is with Pylons (see http://docs.pylonshq.com/pyramid/dev/narr/router.html). In trying to think this through I've come up w/ a couple of ideas: - I could write my own set of action decorators that implement the desired functionality in addition to marking the wrapped functions as exposed actions. This would essentially be the same thing as stacking multiple decorators around each of the functions, except that it avoids having to stack multiple decorators around each of the functions. ;) - I could override the router itself, to allow me to keep the wrapped functionality closer to the WSGI level. Pyramid doesn't really provide any hooks for this, however. It'd be easy enough to change Pyramid to fetch the router by interface rather than by class, making it possible to supply an alternate router implementation, but there's a lot of code in that __call__ method; I'm not terribly fond of copy/pasting large blocks of code only to add a handful of additional lines to the middle somewhere. Does anyone have any other suggestions? Opinions on the suggestions I've made? Has anybody out there thought about how to handle this pattern in a Pyramid upgrade? Thanks! -r -- You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-disc...@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.