Chris McDonough
2011-09-04 90737d6b24775cab3a3816b426c0dc65c03fe43d
commit | author | age
672bbe 1 .. _design_defense:
CM 2
edd915 3 Defending Pyramid's Design
CM 4 ==========================
fbfea7 5
8cdb1b 6 From time to time, challenges to various aspects of :app:`Pyramid` design are
CM 7 lodged.  To give context to discussions that follow, we detail some of the
8 design decisions and trade-offs here.  In some cases, we acknowledge that the
9 framework can be made better and we describe future steps which will be taken
10 to improve it; in some cases we just file the challenge as "noted", as
11 obviously you can't please everyone all of the time.
70f7c3 12
6cdbba 13 Pyramid Provides More Than One Way to Do It
CM 14 -------------------------------------------
15
dfc9d6 16 A canon of Python popular culture is "TIOOWTDI" ("there is only one way to do
6cdbba 17 it", a slighting, tongue-in-cheek reference to Perl's "TIMTOWTDI", which is
CM 18 an acronym for "there is more than one way to do it").
19
20 :app:`Pyramid` is, for better or worse, a "TIMTOWTDI" system.  For example,
21 it includes more than one way to resolve a URL to a :term:`view callable`:
22 via :term:`url dispatch` or :term:`traversal`.  Multiple methods of
23 configuration exist: :term:`imperative configuration`, :term:`configuration
bee624 24 decoration`, and :term:`ZCML` (optionally via :term:`pyramid_zcml`). It works
CM 25 with multiple different kinds of persistence and templating systems.  And so
26 on.  However, the existence of most of these overlapping ways to do things
27 are not without reason and purpose: we have a number of audiences to serve,
28 and we believe that TIMTOWTI at the web framework level actually *prevents* a
29 much more insidious and harmful set of duplication at higher levels in the
30 Python web community.
6cdbba 31
CM 32 :app:`Pyramid` began its life as :mod:`repoze.bfg`, written by a team of
a9ff22 33 people with many years of prior :term:`Zope` experience.  The idea of
bee624 34 :term:`traversal` and the way :term:`view lookup` works was stolen entirely
CM 35 from Zope.  The authorization subsystem provided by :app:`Pyramid` is a
36 derivative of Zope's.  The idea that an application can be *extended* without
37 forking is also a Zope derivative.
6cdbba 38
CM 39 Implementations of these features were *required* to allow the :app:`Pyramid`
40 authors to build the bread-and-butter CMS-type systems for customers in the
41 way they were accustomed to building them.  No other system save Zope itself
b36921 42 had such features.  And Zope itself was beginning to show signs of its age.
2ce478 43 We were becoming hampered by consequences of its early design mistakes.
CM 44 Zope's lack of documentation was also difficult to work around: it was hard
45 to hire smart people to work on Zope applications, because there was no
46 comprehensive documentation set to point them at which explained "it all" in
47 one consumble place, and it was too large and self-inconsistent to document
48 properly.  Before :mod:`repoze.bfg` went under development, its authors
b36921 49 obviously looked around for other frameworks that fit the bill.  But no
CM 50 non-Zope framework did.  So we embarked on building :mod:`repoze.bfg`.
6cdbba 51
CM 52 As the result of our research, however, it became apparent that, despite the
53 fact that no *one* framework had all the features we required, lots of
54 existing frameworks had good, and sometimes very compelling ideas.  In
55 particular, :term:`URL dispatch` is a more direct mechanism to map URLs to
56 code.
57
58 So although we couldn't find a framework save for Zope that fit our needs,
59 and while we incorporated a lot of Zope ideas into BFG, we also emulated the
60 features we found compelling in other frameworks (such as :term:`url
61 dispatch`).  After the initial public release of BFG, as time went on,
62 features were added to support people allergic to various Zope-isms in the
63 system, such as the ability to configure the application using
55ce9d 64 :term:`imperative configuration` and :term:`configuration decoration` rather
CM 65 than solely using :term:`ZCML`, and the elimination of the required use of
66 :term:`interface` objects.  It soon became clear that we had a system that
67 was very generic, and was beginning to appeal to non-Zope users as well as
68 ex-Zope users.
6cdbba 69
CM 70 As the result of this generalization, it became obvious BFG shared 90% of its
b36921 71 featureset with the featureset of Pylons 1, and thus had a very similar
CM 72 target market.  Because they were so similar, choosing between the two
73 systems was an exercise in frustration for an otherwise non-partisan
2ce478 74 developer.  It was also strange for the Pylons and BFG development
CM 75 communities to be in competition for the same set of users, given how similar
76 the two frameworks were.  So the Pylons and BFG teams began to work together
77 to form a plan to "merge".  The features missing from BFG (notably
b36921 78 :term:`view handler` classes, flash messaging, and other minor missing bits),
CM 79 were added, to provide familiarity to ex-Pylons users.  The result is
80 :app:`Pyramid`.
6cdbba 81
0bdbdf 82 The Python web framework space is currently notoriously balkanized.  We're
CM 83 truly hoping that the amalgamation of components in :app:`Pyramid` will
6cdbba 84 appeal to at least two currently very distinct sets of users: Pylons and BFG
b36921 85 users.  By unifying the best concepts from Pylons and BFG into a single
CM 86 codebase and leaving the bad concepts from their ancestors behind, we'll be
87 able to consolidate our efforts better, share more code, and promote our
88 efforts as a unit rather than competing pointlessly.  We hope to be able to
89 shortcut the pack mentality which results in a *much larger* duplication of
90 effort, represented by competing but incredibly similar applications and
91 libraries, each built upon a specific low level stack that is incompatible
92 with the other.  We'll also shrink the choice of credible Python web
93 frameworks down by at least one.  We're also hoping to attract users from
94 other communities (such as Zope's and TurboGears') by providing the features
291bcc 95 they require, while allowing enough flexibility to do things in a familiar
b36921 96 fashion.  Some overlap of functionality to achieve these goals is expected
CM 97 and unavoidable, at least if we aim to prevent pointless duplication at
98 higher levels.  If we've done our job well enough, the various audiences will
99 be able to coexist and cooperate rather than firing at each other across some
100 imaginary web framework "DMZ".
6cdbba 101
edd915 102 Pyramid Uses A Zope Component Architecture ("ZCA") Registry
CM 103 -----------------------------------------------------------
fbfea7 104
8cdb1b 105 :app:`Pyramid` uses a :term:`Zope Component Architecture` (ZCA) "component
CM 106 registry" as its :term:`application registry` under the hood.  This is a
107 point of some contention.  :app:`Pyramid` is of a :term:`Zope` pedigree, so
108 it was natural for its developers to use a ZCA registry at its inception.
109 However, we understand that using a ZCA registry has issues and consequences,
110 which we've attempted to address as best we can.  Here's an introspection
111 about :app:`Pyramid` use of a ZCA registry, and the trade-offs its usage
0435ce 112 involves.
fbfea7 113
CM 114 Problems
115 ++++++++
116
fa8994 117 The "global" API that may be used to access data in a ZCA "component
8cdb1b 118 registry" is not particularly pretty or intuitive, and sometimes it's just
CM 119 plain obtuse.  Likewise, the conceptual load on a casual source code reader
120 of code that uses the ZCA global API is somewhat high.  Consider a ZCA
121 neophyte reading the code that performs a typical "unnamed utility" lookup
122 using the :func:`zope.component.getUtility` global API:
fbfea7 123
0ac7b0 124 .. ignore-next-block
fbfea7 125 .. code-block:: python
CM 126    :linenos:
127
edd915 128    from pyramid.interfaces import ISettings
fbfea7 129    from zope.component import getUtility
CM 130    settings = getUtility(ISettings)
131
8cdb1b 132 After this code runs, ``settings`` will be a Python dictionary.  But it's
CM 133 unlikely that any "civilian" would know that just by reading the code.  There
134 are a number of comprehension issues with the bit of code above that are
135 obvious.
fbfea7 136
8cdb1b 137 First, what's a "utility"?  Well, for the purposes of this discussion, and
CM 138 for the purpose of the code above, it's just not very important.  If you
139 really want to know, you can read `this
140 <http://www.muthukadan.net/docs/zca.html#utility>`_.  However, still, readers
141 of such code need to understand the concept in order to parse it.  This is
142 problem number one.
fbfea7 143
8cdb1b 144 Second, what's this ``ISettings`` thing?  It's an :term:`interface`.  Is that
CM 145 important here?  Not really, we're just using it as a "key" for some lookup
146 based on its identity as a marker: it represents an object that has the
147 dictionary API, but that's not very important in this context.  That's
148 problem number two.
fbfea7 149
8cdb1b 150 Third of all, what does the ``getUtility`` function do?  It's performing a
CM 151 lookup for the ``ISettings`` "utility" that should return.. well, a utility.
152 Note how we've already built up a dependency on the understanding of an
153 :term:`interface` and the concept of "utility" to answer this question: a bad
154 sign so far.  Note also that the answer is circular, a *really* bad sign.
fbfea7 155
8cdb1b 156 Fourth, where does ``getUtility`` look to get the data?  Well, the "component
CM 157 registry" of course.  What's a component registry?  Problem number four.
fbfea7 158
8cdb1b 159 Fifth, assuming you buy that there's some magical registry hanging around,
CM 160 where *is* this registry?  *Homina homina*... "around"?  That's sort of the
161 best answer in this context (a more specific answer would require knowledge
162 of internals).  Can there be more than one registry?  Yes.  So *which*
163 registry does it find the registration in?  Well, the "current" registry of
164 course.  In terms of :app:`Pyramid`, the current registry is a thread local
165 variable.  Using an API that consults a thread local makes understanding how
166 it works non-local.
fbfea7 167
0435ce 168 You've now bought in to the fact that there's a registry that is just
bee624 169 "hanging around".  But how does the registry get populated?  Why, via code
CM 170 that calls directives like ``config.add_view``.  In this particular case,
171 however, the registration of ``ISettings`` is made by the framework itself
172 "under the hood": it's not present in any user configuration.  This is
173 extremely hard to comprehend.  Problem number six.
fbfea7 174
8cdb1b 175 Clearly there's some amount of cognitive load here that needs to be borne by
CM 176 a reader of code that extends the :app:`Pyramid` framework due to its use of
177 the ZCA, even if he or she is already an expert Python programmer and whom is
178 an expert in the domain of web applications.  This is suboptimal.
fbfea7 179
CM 180 Ameliorations
181 +++++++++++++
182
8cdb1b 183 First, the primary amelioration: :app:`Pyramid` *does not expect application
CM 184 developers to understand ZCA concepts or any of its APIs*.  If an
185 *application* developer needs to understand a ZCA concept or API during the
186 creation of a :app:`Pyramid` application, we've failed on some axis.
fbfea7 187
fa8994 188 Instead, the framework hides the presence of the ZCA registry behind
8cdb1b 189 special-purpose API functions that *do* use ZCA APIs.  Take for example the
CM 190 ``pyramid.security.authenticated_userid`` function, which returns the userid
191 present in the current request or ``None`` if no userid is present in the
192 current request.  The application developer calls it like so:
fbfea7 193
0ac7b0 194 .. ignore-next-block
fbfea7 195 .. code-block:: python
CM 196    :linenos:
197
edd915 198    from pyramid.security import authenticated_userid
1b7aaf 199    userid = authenticated_userid(request)
fbfea7 200
CM 201 He now has the current user id.
202
203 Under its hood however, the implementation of ``authenticated_userid``
204 is this:
205
b7fdea 206 .. code-block:: python
fbfea7 207    :linenos:
CM 208
209    def authenticated_userid(request):
210        """ Return the userid of the currently authenticated user or
211        ``None`` if there is no authentication policy in effect or there
212        is no currently authenticated user. """
213
c91abc 214        registry = request.registry # the ZCA component registry
CM 215        policy = registry.queryUtility(IAuthenticationPolicy)
fbfea7 216        if policy is None:
CM 217            return None
218        return policy.authenticated_userid(request)
219
8cdb1b 220 Using such wrappers, we strive to always hide the ZCA API from application
CM 221 developers.  Application developers should just never know about the ZCA API:
222 they should call a Python function with some object germane to the domain as
223 an argument, and it should returns a result.  A corollary that follows is
224 that any reader of an application that has been written using :app:`Pyramid`
225 needn't understand the ZCA API either.
fbfea7 226
8cdb1b 227 Hiding the ZCA API from application developers and code readers is a form of
CM 228 enhancing "domain specificity".  No application developer wants to need to
d141dd 229 understand the small, detailed mechanics of how a web framework does its
8cdb1b 230 thing.  People want to deal in concepts that are closer to the domain they're
CM 231 working in: for example, web developers want to know about *users*, not
232 *utilities*.  :app:`Pyramid` uses the ZCA as an implementation detail, not as
233 a feature which is exposed to end users.
fbfea7 234
8cdb1b 235 However, unlike application developers, *framework developers*, including
CM 236 people who want to override :app:`Pyramid` functionality via preordained
237 framework plugpoints like traversal or view lookup *must* understand the ZCA
238 registry API.
fbfea7 239
8cdb1b 240 :app:`Pyramid` framework developers were so concerned about conceptual load
CM 241 issues of the ZCA registry API for framework developers that a `replacement
242 registry implementation <http://svn.repoze.org/repoze.component/trunk>`_
243 named :mod:`repoze.component` was actually developed.  Though this package
244 has a registry implementation which is fully functional and well-tested, and
245 its API is much nicer than the ZCA registry API, work on it was largely
246 abandoned and it is not used in :app:`Pyramid`.  We continued to use a ZCA
247 registry within :app:`Pyramid` because it ultimately proved a better fit.
aade46 248
fa8994 249 .. note:: We continued using ZCA registry rather than disusing it in
CM 250    favor of using the registry implementation in
aade46 251    :mod:`repoze.component` largely because the ZCA concept of
CM 252    interfaces provides for use of an interface hierarchy, which is
253    useful in a lot of scenarios (such as context type inheritance).
254    Coming up with a marker type that was something like an interface
255    that allowed for this functionality seemed like it was just
256    reinventing the wheel.
fbfea7 257
8cdb1b 258 Making framework developers and extenders understand the ZCA registry API is
CM 259 a trade-off.  We (the :app:`Pyramid` developers) like the features that the
260 ZCA registry gives us, and we have long-ago borne the weight of understanding
261 what it does and how it works.  The authors of :app:`Pyramid` understand the
262 ZCA deeply and can read code that uses it as easily as any other code.
fbfea7 263
ea32d6 264 But we recognize that developers who might want to extend the framework are not
8cdb1b 265 as comfortable with the ZCA registry API as the original developers are with
CM 266 it.  So, for the purposes of being kind to third-party :app:`Pyramid`
267 framework developers in, we've drawn some lines in the sand.
fbfea7 268
8cdb1b 269 In all "core" code, We've made use of ZCA global API functions such as
CM 270 ``zope.component.getUtility`` and ``zope.component.getAdapter`` the exception
271 instead of the rule.  So instead of:
fbfea7 272
8cdb1b 273 .. code-block:: python
CM 274    :linenos:
fbfea7 275
8cdb1b 276    from pyramid.interfaces import IAuthenticationPolicy
CM 277    from zope.component import getUtility
278    policy = getUtility(IAuthenticationPolicy)
fbfea7 279
8cdb1b 280 :app:`Pyramid` code will usually do:
fbfea7 281
8cdb1b 282 .. code-block:: python
CM 283    :linenos:
fbfea7 284
8cdb1b 285    from pyramid.interfaces import IAuthenticationPolicy
CM 286    from pyramid.threadlocal import get_current_registry
287    registry = get_current_registry()
288    policy = registry.getUtility(IAuthenticationPolicy)
fbfea7 289
8cdb1b 290 While the latter is more verbose, it also arguably makes it more obvious
CM 291 what's going on.  All of the :app:`Pyramid` core code uses this pattern
292 rather than the ZCA global API.
fbfea7 293
CM 294 Rationale
295 +++++++++
296
8cdb1b 297 Here are the main rationales involved in the :app:`Pyramid` decision to use
CM 298 the ZCA registry:
fbfea7 299
d141dd 300 - History.  A nontrivial part of the answer to this question is "history".
8cdb1b 301   Much of the design of :app:`Pyramid` is stolen directly from :term:`Zope`.
CM 302   Zope uses the ZCA registry to do a number of tricks.  :app:`Pyramid` mimics
303   these tricks, and, because the ZCA registry works well for that set of
304   tricks, :app:`Pyramid` uses it for the same purposes.  For example, the way
305   that :app:`Pyramid` maps a :term:`request` to a :term:`view callable` using
306   :term:`traversal` is lifted almost entirely from Zope.  The ZCA registry
307   plays an important role in the particulars of how this request to view
308   mapping is done.
fbfea7 309
8cdb1b 310 - Features.  The ZCA component registry essentially provides what can be
CM 311   considered something like a "superdictionary", which allows for more
312   complex lookups than retrieving a value based on a single key.  Some of
313   this lookup capability is very useful for end users, such as being able to
314   register a view that is only found when the context is some class of
315   object, or when the context implements some :term:`interface`.
fbfea7 316
8cdb1b 317 - Singularity.  There's only one "place" where "application configuration"
CM 318   lives in a :app:`Pyramid` application: in a component registry.  The
319   component registry answers questions made to it by the framework at runtime
320   based on the configuration of *an application*.  Note: "an application" is
321   not the same as "a process", multiple independently configured copies of
322   the same :app:`Pyramid` application are capable of running in the same
0435ce 323   process space.
fbfea7 324
8cdb1b 325 - Composability.  A ZCA component registry can be populated imperatively, or
CM 326   there's an existing mechanism to populate a registry via the use of a
55ce9d 327   configuration file (ZCML, via the optional :term:`pyramid_zcml` package).
CM 328   We didn't need to write a frontend from scratch to make use of
329   configuration-file-driven registry population.
fbfea7 330
8cdb1b 331 - Pluggability.  Use of the ZCA registry allows for framework extensibility
CM 332   via a well-defined and widely understood plugin architecture.  As long as
333   framework developers and extenders understand the ZCA registry, it's
334   possible to extend :app:`Pyramid` almost arbitrarily.  For example, it's
bee624 335   relatively easy to build a directive that registers several views "all at
CM 336   once", allowing app developers to use that directive as a "macro" in code
337   that they write.  This is somewhat of a differentiating feature from other
338   (non-Zope) frameworks.
fbfea7 339
8cdb1b 340 - Testability.  Judicious use of the ZCA registry in framework code makes
CM 341   testing that code slightly easier.  Instead of using monkeypatching or
342   other facilities to register mock objects for testing, we inject
343   dependencies via ZCA registrations and then use lookups in the code find
344   our mock objects.
fbfea7 345
8cdb1b 346 - Speed.  The ZCA registry is very fast for a specific set of complex lookup
CM 347   scenarios that :app:`Pyramid` uses, having been optimized through the years
348   for just these purposes.  The ZCA registry contains optional C code for
349   this purpose which demonstrably has no (or very few) bugs.
fbfea7 350
bee624 351 - Ecosystem.  Many existing Zope packages can be used in :app:`Pyramid` with
CM 352   few (or no) changes due to our use of the ZCA registry.
fbfea7 353
CM 354 Conclusion
355 ++++++++++
356
fd5ae9 357 If you only *develop applications* using :app:`Pyramid`, there's not much to
0d43ed 358 complain about here.  You just should never need to understand the ZCA
8cdb1b 359 registry API: use documented :app:`Pyramid` APIs instead.  However, you may
CM 360 be an application developer who doesn't read API documentation because it's
361 unmanly. Instead you read the raw source code, and because you haven't read
362 the documentation, you don't know what functions, classes, and methods even
363 *form* the :app:`Pyramid` API.  As a result, you've now written code that
364 uses internals and you've painted yourself into a conceptual corner as a
365 result of needing to wrestle with some ZCA-using implementation detail.  If
366 this is you, it's extremely hard to have a lot of sympathy for you.  You'll
367 either need to get familiar with how we're using the ZCA registry or you'll
368 need to use only the documented APIs; that's why we document them as APIs.
fbfea7 369
bee624 370 If you *extend* or *develop* :app:`Pyramid` (create new directives, use some
CM 371 of the more obscure "hooks" as described in :ref:`hooks_chapter`, or work on
372 the :app:`Pyramid` core code), you will be faced with needing to understand
373 at least some ZCA concepts.  In some places it's used unabashedly, and will
374 be forever.  We know it's quirky, but it's also useful and fundamentally
375 understandable if you take the time to do some reading about it.
fbfea7 376
edd915 377 Pyramid Uses Interfaces Too Liberally
CM 378 -------------------------------------
621dd7 379
CM 380 In this `TOPP Engineering blog entry
381 <http://www.coactivate.org/projects/topp-engineering/blog/2008/10/20/what-bothers-me-about-the-component-architecture/>`_,
809744 382 Ian Bicking asserts that the way :mod:`repoze.bfg` used a Zope interface to
CM 383 represent an HTTP request method added too much indirection for not enough
8cdb1b 384 gain.  We agreed in general, and for this reason, :mod:`repoze.bfg` version
CM 385 1.1 (and subsequent versions including :app:`Pyramid` 1.0+) added :term:`view
809744 386 predicate` and :term:`route predicate` modifiers to view configuration.
CM 387 Predicates are request-specific (or :term:`context` -specific) matching
388 narrowers which don't use interfaces.  Instead, each predicate uses a
621dd7 389 domain-specific string as a match value.
CM 390
8cdb1b 391 For example, to write a view configuration which matches only requests with
CM 392 the ``POST`` HTTP request method, you might write a ``@view_config``
621dd7 393 decorator which mentioned the ``request_method`` predicate:
CM 394
395 .. code-block:: python
396    :linenos:
397
197f0c 398    from pyramid.view import view_config
CM 399    @view_config(name='post_view', request_method='POST', renderer='json')
621dd7 400    def post_view(request):
CM 401        return 'POSTed'
402
403 You might further narrow the matching scenario by adding an ``accept``
8cdb1b 404 predicate that narrows matching to something that accepts a JSON response:
621dd7 405
CM 406 .. code-block:: python
407    :linenos:
408
197f0c 409    from pyramid.view import view_config
809744 410    @view_config(name='post_view', request_method='POST', 
CM 411                 accept='application/json', renderer='json')
621dd7 412    def post_view(request):
CM 413        return 'POSTed'
414
8cdb1b 415 Such a view would only match when the request indicated that HTTP request
CM 416 method was ``POST`` and that the remote user agent passed
621dd7 417 ``application/json`` (or, for that matter, ``application/*``) in its
CM 418 ``Accept`` request header.
419
420 "Under the hood", these features make no use of interfaces.
421
809744 422 Many "prebaked" predicates exist.  However, use of only "prebaked" predicates,
CM 423 however, doesn't entirely meet Ian's criterion.  He would like to be able to
424 match a request using a lambda or another function which interrogates the
425 request imperatively.  In :mod:`repoze.bfg` version 1.2, we acommodate this by
426 allowing people to define "custom" view predicates:
6225a2 427
CM 428 .. code-block:: python
429    :linenos:
430
197f0c 431    from pyramid.view import view_config
d868ff 432    from pyramid.response import Response
6225a2 433
CM 434    def subpath(context, request):
435        return request.subpath and request.subpath[0] == 'abc'
436
197f0c 437    @view_config(custom_predicates=(subpath,))
6225a2 438    def aview(request):
CM 439        return Response('OK')
440
441 The above view will only match when the first element of the request's
442 :term:`subpath` is ``abc``.
621dd7 443
b1d4c0 444 .. _zcml_encouragement:
CM 445
edd915 446 Pyramid "Encourages Use of ZCML"
CM 447 --------------------------------
fbfea7 448
809744 449 :term:`ZCML` is a configuration language that can be used to configure the
8cdb1b 450 :term:`Zope Component Architecture` registry that :app:`Pyramid` uses for
809744 451 application configuration.  Often people claim that Pyramid "needs ZCML".
fbfea7 452
c9c3c4 453 It doesn't.  In :app:`Pyramid` 1.0, ZCML doesn't ship as part of the core;
CM 454 instead it ships in the :term:`pyramid_zcml` add-on package, which is
455 completely optional.  No ZCML is required at all to use :app:`Pyramid`, nor
456 any other sort of frameworky declarative frontend to application
457 configuration.
fbfea7 458
7bb032 459 .. _model_traversal_confusion:
CM 460
edd915 461 Pyramid Uses "Model" To Represent A Node In The Graph of Objects Traversed
CM 462 --------------------------------------------------------------------------
7bb032 463
a5ffd6 464 The ``repoze.bfg`` documentation used to refer to the graph being traversed
CM 465 when :term:`traversal` is used as a "model graph".  A terminology overlap
466 confused people who wrote applications that always use ORM packages such as
467 SQLAlchemy, which has a different notion of the definition of a "model".  As
a44b4f 468 a result, in Pyramid 1.0a7, the tree of objects traversed is now renamed to
a5ffd6 469 :term:`resource tree` and its components are now named :term:`resource`
CM 470 objects.  Associated APIs have been changed.  This hopefully alleviates the
471 terminology confusion caused by overriding the term "model".
7bb032 472
edd915 473 Pyramid Does Traversal, And I Don't Like Traversal
CM 474 --------------------------------------------------
7bb032 475
a5ffd6 476 In :app:`Pyramid`, :term:`traversal` is the act of resolving a URL path to a
CM 477 :term:`resource` object in a resource tree.  Some people are uncomfortable
ae1d22 478 with this notion, and believe it is wrong.  Thankfully, if you use
CM 479 :app:`Pyramid`, and you don't want to model your application in terms of a
480 resource tree, you needn't use it at all.  Instead, use :term:`URL dispatch`
481 to map URL paths to views.
c58cf2 482
ae1d22 483 The idea that some folks believe traversal is unilaterally "wrong" is
CM 484 understandable.  The people who believe it is wrong almost invariably have
485 all of their data in a relational database.  Relational databases aren't
a5ffd6 486 naturally hierarchical, so "traversing" one like a tree is not possible.
c58cf2 487
ae1d22 488 However, folks who deem traversal unilaterally wrong are neglecting to take
CM 489 into account that many persistence mechanisms *are* hierarchical.  Examples
a5ffd6 490 include a filesystem, an LDAP database, a :term:`ZODB` (or another type of
CM 491 graph) database, an XML document, and the Python module namespace.  It is
492 often convenient to model the frontend to a hierarchical data store as a
493 graph, using traversal to apply views to objects that either *are* the
494 resources in the tree being traversed (such as in the case of ZODB) or at
495 least ones which stand in for them (such as in the case of wrappers for files
496 from the filesystem).
c58cf2 497
a5ffd6 498 Also, many website structures are naturally hierarchical, even if the data
CM 499 which drives them isn't.  For example, newspaper websites are often extremely
500 hierarchical: sections within sections within sections, ad infinitum.  If you
501 want your URLs to indicate this structure, and the structure is indefinite
502 (the number of nested sections can be "N" instead of some fixed number), a
503 resource tree is an excellent way to model this, even if the backend is a
504 relational database.  In this situation, the resource tree a just a site
505 structure.
c58cf2 506
ae1d22 507 Traversal also offers better composability of applications than URL dispatch,
CM 508 because it doesn't rely on a fixed ordering of URL matching.  You can compose
509 a set of disparate functionality (and add to it later) around a mapping of
510 view to resource more predictably than trying to get "the right" ordering of
511 URL pattern matching.
512
513 But the point is ultimately moot.  If you don't want to use traversal, you
514 needn't.  Use URL dispatch instead.
c58cf2 515
edd915 516 Pyramid Does URL Dispatch, And I Don't Like URL Dispatch
CM 517 --------------------------------------------------------
c58cf2 518
ae1d22 519 In :app:`Pyramid`, :term:`url dispatch` is the act of resolving a URL path to
CM 520 a :term:`view` callable by performing pattern matching against some set of
521 ordered route definitions.  The route definitions are examined in order: the
522 first pattern which matches is used to associate the URL with a view
523 callable.
c58cf2 524
ae1d22 525 Some people are uncomfortable with this notion, and believe it is wrong.
CM 526 These are usually people who are steeped deeply in :term:`Zope`.  Zope does
527 not provide any mechanism except :term:`traversal` to map code to URLs.  This
528 is mainly because Zope effectively requires use of :term:`ZODB`, which is a
529 hierarchical object store.  Zope also supports relational databases, but
530 typically the code that calls into the database lives somewhere in the ZODB
531 object graph (or at least is a :term:`view` related to a node in the object
532 graph), and traversal is required to reach this code.
c58cf2 533
589ee7 534 I'll argue that URL dispatch is ultimately useful, even if you want to use
CM 535 traversal as well.  You can actually *combine* URL dispatch and traversal in
fd5ae9 536 :app:`Pyramid` (see :ref:`hybrid_chapter`).  One example of such a usage: if
589ee7 537 you want to emulate something like Zope 2's "Zope Management Interface" UI on
CM 538 top of your object graph (or any administrative interface), you can register
62a48b 539 a route like ``config.add_route('manage', '/manage/*traverse')`` and then
589ee7 540 associate "management" views in your code by using the ``route_name``
62a48b 541 argument to a ``view`` configuration,
CM 542 e.g. ``config.add_view('.some.callable', context=".some.Resource",
543 route_name='manage')``.  If you wire things up this way someone then walks up
544 to for example, ``/manage/ob1/ob2``, they might be presented with a
545 management interface, but walking up to ``/ob1/ob2`` would present them with
546 the default object view.  There are other tricks you can pull in these hybrid
547 configurations if you're clever (and maybe masochistic) too.
c58cf2 548
ae1d22 549 Also, if you are a URL dispatch hater, if you should ever be asked to write
CM 550 an application that must use some legacy relational database structure, you
551 might find that using URL dispatch comes in handy for one-off associations
552 between views and URL paths.  Sometimes it's just pointless to add a node to
553 the object graph that effectively represents the entry point for some bit of
554 code.  You can just use a route and be done with it.  If a route matches, a
555 view associated with the route will be called; if no route matches,
556 :app:`Pyramid` falls back to using traversal.
c58cf2 557
ae1d22 558 But the point is ultimately moot.  If you use :app:`Pyramid`, and you really
CM 559 don't want to use URL dispatch, you needn't use it at all.  Instead, use
560 :term:`traversal` exclusively to map URL paths to views, just like you do in
561 :term:`Zope`.
c58cf2 562
edd915 563 Pyramid Views Do Not Accept Arbitrary Keyword Arguments
CM 564 -------------------------------------------------------
f34859 565
589ee7 566 Many web frameworks (Zope, TurboGears, Pylons 1.X, Django) allow for their
CM 567 variant of a :term:`view callable` to accept arbitrary keyword or positional
568 arguments, which are "filled in" using values present in the ``request.POST``
569 or ``request.GET`` dictionaries or by values present in the "route match
570 dictionary".  For example, a Django view will accept positional arguments
571 which match information in an associated "urlconf" such as
572 ``r'^polls/(?P<poll_id>\d+)/$``:
f34859 573
CM 574 .. code-block:: python
575    :linenos:
576
577    def aview(request, poll_id):
578        return HttpResponse(poll_id)
579
580 Zope, likewise allows you to add arbitrary keyword and positional
a5ffd6 581 arguments to any method of a resource object found via traversal:
f34859 582
0ac7b0 583 .. ignore-next-block
f34859 584 .. code-block:: python
CM 585    :linenos:
0ac7b0 586
CM 587    from persistent import Persistent
f34859 588
CM 589    class MyZopeObject(Persistent):
590         def aview(self, a, b, c=None):
591             return '%s %s %c' % (a, b, c)
592
ae1d22 593 When this method is called as the result of being the published callable, the
CM 594 Zope request object's GET and POST namespaces are searched for keys which
595 match the names of the positional and keyword arguments in the request, and
596 the method is called (if possible) with its argument list filled with values
597 mentioned therein.  TurboGears and Pylons 1.X operate similarly.
f34859 598
ae1d22 599 Out of the box, :app:`Pyramid` is configured to have none of these features.
522c23 600 By default, :mod:`pyramid` view callables always accept only ``request`` and
ae1d22 601 no other arguments.  The rationale: this argument specification matching done
CM 602 aggressively can be costly, and :app:`Pyramid` has performance as one of its
603 main goals, so we've decided to make people, by default, obtain information
604 by interrogating the request object within the view callable body instead of
605 providing magic to do unpacking into the view argument list.
f34859 606
ae1d22 607 However, as of :app:`Pyramid` 1.0a9, user code can influence the way view
CM 608 callables are expected to be called, making it possible to compose a system
609 out of view callables which are called with arbitrary arguments.  See
610 :ref:`using_a_view_mapper`.
f34859 611
edd915 612 Pyramid Provides Too Few "Rails"
CM 613 --------------------------------
6956a8 614
fd5ae9 615 By design, :app:`Pyramid` is not a particularly "opinionated" web framework.
f52ff2 616 It has a relatively parsimonious feature set.  It contains no built in ORM
CM 617 nor any particular database bindings.  It contains no form generation
618 framework.  It has no administrative web user interface.  It has no built in
619 text indexing.  It does not dictate how you arrange your code.
6956a8 620
f52ff2 621 Such opinionated functionality exists in applications and frameworks built
fd5ae9 622 *on top* of :app:`Pyramid`.  It's intended that higher-level systems emerge
CM 623 built using :app:`Pyramid` as a base.  See also :ref:`apps_are_extensible`.
6956a8 624
edd915 625 Pyramid Provides Too Many "Rails"
CM 626 ---------------------------------
6956a8 627
a09149 628 :app:`Pyramid` provides some features that other web frameworks do not.
CM 629 These are features meant for use cases that might not make sense to you if
630 you're building a simple "bespoke" web application:
6956a8 631
a09149 632 - An optional way to map URLs to code using :term:`traversal` which implies a
CM 633   walk of a :term:`resource tree`.
6956a8 634
a09149 635 - The ability to aggregate Pyramid application configuration from multiple
CM 636   sources using :meth:`pyramid.config.Configurator.include`.
6956a8 637
a09149 638 - View and subscriber registrations made using :term:`interface` objects
CM 639   instead of class objects (e.g. :ref:`using_resource_interfaces`).
640
641 - A declarative :term:`authorization` system.
642
643 - Multiple separate I18N :term:`translation string` factories, each of which
644   can name its own "domain".
645
646 These features are important to the authors of :app:`Pyramid`.  The
647 :app:`Pyramid` authors are often commissioned to build CMS-style
648 applications.  Such applications are often "frameworky" because they have
649 more than one deployment.  Each deployment requires a slightly different
ae1d22 650 composition of sub-applications, and the framework and sub-applications often
a09149 651 need to be *extensible*.  Because the application has more than one
CM 652 deployment, pluggability and extensibility is important, as maintaining
653 multiple forks of the application, one per deployment, is extremely
654 undesirable.  Because it's easier to extend a system that uses
655 :term:`traversal` "from the outside" than it is to do the same in a system
656 that uses :term:`URL dispatch`, each deployment uses a :term:`resource tree`
657 composed of a persistent tree of domain model objects, and uses
658 :term:`traversal` to map :term:`view callable` code to resources in the tree.
659 The resource tree contains very granular security declarations, as resources
ae1d22 660 are owned and accessible by different sets of users.  Interfaces are used to
CM 661 make unit testing and implementation substitutability easier.
a09149 662
CM 663 In a bespoke web application, usually there's a single canonical deployment,
664 and therefore no possibility of multiple code forks.  Extensibility is not
ae1d22 665 required; the code is just changed in-place.  Security requirements are often
CM 666 less granular.  Using the features listed above will often be overkill for
667 such an application.
a09149 668
CM 669 If you don't like these features, it doesn't mean you can't or shouldn't use
ae1d22 670 :app:`Pyramid`.  They are all optional, and a lot of time has been spent
a09149 671 making sure you don't need to know about them up-front.  You can build
CM 672 "Pylons-1.X-style" applications using :app:`Pyramid` that are purely bespoke
673 by ignoring the features above.  You may find these features handy later
674 after building a "bespoke" web application that suddenly becomes popular and
675 requires extensibility because it must be deployed in multiple locations.
6956a8 676
edd915 677 Pyramid Is Too Big
CM 678 ------------------
4b32c8 679
fd5ae9 680 "The :app:`Pyramid` compressed tarball is almost 2MB.  It must be
0435ce 681 enormous!"
4b32c8 682
CM 683 No.  We just ship it with test code and helper templates.  Here's a
684 breakdown of what's included in subdirectories of the package tree:
685
686 docs/
687
5c1510 688   3.0MB
4b32c8 689
5c1510 690 pyramid/tests/
4b32c8 691
5c1510 692   1.1MB
4b32c8 693
5c1510 694 pyramid/paster_templates/
4b32c8 695
5c1510 696   804KB
4b32c8 697
5c1510 698 pyramid/ (except for ``pyramd/tests and pyramid/paster_templates``)
4b32c8 699
5c1510 700   539K
4b32c8 701
fd5ae9 702 The actual :app:`Pyramid` runtime code is about 10% of the total size of the
589ee7 703 tarball omitting docs, helper templates used for package generation, and test
CM 704 code.  Of the approximately 19K lines of Python code in the package, the code
705 that actually has a chance of executing during normal operation, excluding
706 tests and paster template Python files, accounts for approximately 5K lines
707 of Python code.  This is comparable to Pylons 1.X, which ships with a little
708 over 2K lines of Python code, excluding tests.
4b32c8 709
edd915 710 Pyramid Has Too Many Dependencies
CM 711 ---------------------------------
4b32c8 712
ddb6a8 713 This is true.  At the time of this writing, the total number of Python
8cdb1b 714 package distributions that :app:`Pyramid` depends upon transitively is 18 if
48d4c8 715 you use Python 2.6 or 2.7, or 16 if you use Python 2.5.  This is a lot more
CM 716 than zero package distribution dependencies: a metric which various Python
717 microframeworks and Django boast.
4b32c8 718
8cdb1b 719 The :mod:`zope.component` and :mod:`zope.configuration` packages on which
CM 720 :app:`Pyramid` depends have transitive dependencies on several other packages
721 (:mod:`zope.schema`, :mod:`zope.i18n`, :mod:`zope.event`,
722 :mod:`zope.interface`, :mod:`zope.deprecation`, :mod:`zope.i18nmessageid`).
723 We've been working with the Zope community to try to collapse and untangle
724 some of these dependencies.  We'd prefer that these packages have fewer
725 packages as transitive dependencies, and that much of the functionality of
726 these packages was moved into a smaller *number* of packages.
ddb6a8 727
fd5ae9 728 :app:`Pyramid` also has its own direct dependencies, such as :term:`Paste`,
809744 729 :term:`Chameleon`, :term:`Mako` and :term:`WebOb`, and some of these in turn
CM 730 have their own transitive dependencies.
4b32c8 731
8cdb1b 732 It should be noted that :app:`Pyramid` is positively lithe compared to
CM 733 :term:`Grok`, a different Zope-based framework.  As of this writing, in its
ef9f29 734 default configuration, Grok has 109 package distribution dependencies. The
8cdb1b 735 number of dependencies required by :app:`Pyramid` is many times fewer than
CM 736 Grok (or Zope itself, upon which Grok is based).  :app:`Pyramid` has a number
737 of package distribution dependencies comparable to similarly-targeted
738 frameworks such as Pylons 1.X.
4b32c8 739
8cdb1b 740 We try not to reinvent too many wheels (at least the ones that don't need
CM 741 reinventing), and this comes at the cost of some number of dependencies.
742 However, "number of package distributions" is just not a terribly great
743 metric to measure complexity.  For example, the :mod:`zope.event`
744 distribution on which :app:`Pyramid` depends has a grand total of four lines
745 of runtime code.  As noted above, we're continually trying to agitate for a
746 collapsing of these sorts of packages into fewer distribution files.
93f694 747
edd915 748 Pyramid "Cheats" To Obtain Speed
CM 749 --------------------------------
93f694 750
8cdb1b 751 Complaints have been lodged by other web framework authors at various times
CM 752 that :app:`Pyramid` "cheats" to gain performance.  One claimed cheating
753 mechanism is our use (transitively) of the C extensions provided by
754 :mod:`zope.interface` to do fast lookups.  Another claimed cheating mechanism
755 is the religious avoidance of extraneous function calls.
93f694 756
8cdb1b 757 If there's such a thing as cheating to get better performance, we want to
CM 758 cheat as much as possible.  We optimize :app:`Pyramid` aggressively.  This
759 comes at a cost: the core code has sections that could be expressed more
760 readably.  As an amelioration, we've commented these sections liberally.
4b32c8 761
edd915 762 Pyramid Gets Its Terminology Wrong ("MVC")
CM 763 ------------------------------------------
384ead 764
8cdb1b 765 "I'm a MVC web framework user, and I'm confused.  :app:`Pyramid` calls the
CM 766 controller a view!  And it doesn't have any controllers."
384ead 767
5df6be 768 If you are in this camp, you might have come to expect things about how your
CM 769 existing "MVC" framework uses its terminology.  For example, you probably
770 expect that models are ORM models, controllers are classes that have methods
fd5ae9 771 that map to URLs, and views are templates.  :app:`Pyramid` indeed has each of
5df6be 772 these concepts, and each probably *works* almost exactly like your existing
CM 773 "MVC" web framework. We just don't use the "MVC" terminology, as we can't
774 square its usage in the web framework space with historical reality.
775
8cdb1b 776 People very much want to give web applications the same properties as common
CM 777 desktop GUI platforms by using similar terminology, and to provide some frame
778 of reference for how various components in the common web framework might
779 hang together.  But in the opinion of the author, "MVC" doesn't match the web
780 very well in general. Quoting from the `Model-View-Controller Wikipedia entry
16cd50 781 <http://en.wikipedia.org/wiki/Model–view–controller>`_:
BL 782
783 .. code-block:: text
384ead 784
CM 785   Though MVC comes in different flavors, control flow is generally as
786   follows:
787
788     The user interacts with the user interface in some way (for
789     example, presses a mouse button).
790
791     The controller handles the input event from the user interface,
792     often via a registered handler or callback and converts the event
793     into appropriate user action, understandable for the model.
794
795     The controller notifies the model of the user action, possibly  
796     resulting in a change in the model's state. (For example, the
797     controller updates the user's shopping cart.)[5]
798
799     A view queries the model in order to generate an appropriate
800     user interface (for example, the view lists the shopping cart's     
801     contents). Note that the view gets its own data from the model.
802
803     The controller may (in some implementations) issue a general
804     instruction to the view to render itself. In others, the view is
805     automatically notified by the model of changes in state
806     (Observer) which require a screen update.
807
808     The user interface waits for further user interactions, which
809     restarts the cycle.
810
8cdb1b 811 To the author, it seems as if someone edited this Wikipedia definition,
CM 812 tortuously couching concepts in the most generic terms possible in order to
813 account for the use of the term "MVC" by current web frameworks.  I doubt
814 such a broad definition would ever be agreed to by the original authors of
815 the MVC pattern.  But *even so*, it seems most "MVC" web frameworks fail to
816 meet even this falsely generic definition.
384ead 817
8cdb1b 818 For example, do your templates (views) always query models directly as is
CM 819 claimed in "note that the view gets its own data from the model"?  Probably
820 not.  My "controllers" tend to do this, massaging the data for easier use by
821 the "view" (template). What do you do when your "controller" returns JSON? Do
822 your controllers use a template to generate JSON? If not, what's the "view"
823 then?  Most MVC-style GUI web frameworks have some sort of event system
824 hooked up that lets the view detect when the model changes.  The web just has
825 no such facility in its current form: it's effectively pull-only.
384ead 826
a5ffd6 827 So, in the interest of not mistaking desire with reality, and instead of
CM 828 trying to jam the square peg that is the web into the round hole of "MVC", we
829 just punt and say there are two things: resources and views. The resource
830 tree represents a site structure, the view presents a resource.  The
831 templates are really just an implementation detail of any given view: a view
832 doesn't need a template to return a response.  There's no "controller": it
833 just doesn't exist.  The "model" is either represented by the resource tree
834 or by a "domain model" (like a SQLAlchemy model) that is separate from the
835 framework entirely.  This seems to us like more reasonable terminology, given
836 the current constraints of the web.
384ead 837
0435ce 838 .. _apps_are_extensible:
CM 839
edd915 840 Pyramid Applications are Extensible; I Don't Believe In Application Extensibility
CM 841 ---------------------------------------------------------------------------------
1df991 842
8cdb1b 843 Any :app:`Pyramid` application written obeying certain constraints is
CM 844 *extensible*. This feature is discussed in the :app:`Pyramid` documentation
55f967 845 chapters named :ref:`extending_chapter` and :ref:`advconfig_narr`.  It is
CM 846 made possible by the use of the :term:`Zope Component Architecture` and
847 within :app:`Pyramid`.
ddb6a8 848
CM 849 "Extensible", in this context, means:
1df991 850
CM 851 - The behavior of an application can be overridden or extended in a
852   particular *deployment* of the application without requiring that
853   the deployer modify the source of the original application.
854
ddb6a8 855 - The original developer is not required to anticipate any
CM 856   extensibility plugpoints at application creation time to allow
857   fundamental application behavior to be overriden or extended.
1df991 858
ddb6a8 859 - The original developer may optionally choose to anticipate an
0d43ed 860   application-specific set of plugpoints, which may be hooked by
ddb6a8 861   a deployer.  If he chooses to use the facilities provided by the
CM 862   ZCA, the original developer does not need to think terribly hard
863   about the mechanics of introducing such a plugpoint.
1df991 864
8cdb1b 865 Many developers seem to believe that creating extensible applications is "not
CM 866 worth it".  They instead suggest that modifying the source of a given
867 application for each deployment to override behavior is more reasonable.
868 Much discussion about version control branching and merging typically ensues.
1df991 869
8cdb1b 870 It's clear that making every application extensible isn't required.  The
CM 871 majority of web applications only have a single deployment, and thus needn't
872 be extensible at all.  However, some web applications have multiple
873 deployments, and some have *many* deployments.  For example, a generic
874 "content management" system (CMS) may have basic functionality that needs to
875 be extended for a particular deployment.  That CMS system may be deployed for
876 many organizations at many places.  Some number of deployments of this CMS
877 may be deployed centrally by a third party and managed as a group.  It's
878 useful to be able to extend such a system for each deployment via preordained
879 plugpoints than it is to continually keep each software branch of the system
880 in sync with some upstream source: the upstream developers may change code in
881 such a way that your changes to the same codebase conflict with theirs in
882 fiddly, trivial ways.  Merging such changes repeatedly over the lifetime of a
883 deployment can be difficult and time consuming, and it's often useful to be
884 able to modify an application for a particular deployment in a less invasive
885 way.
1df991 886
8cdb1b 887 If you don't want to think about :app:`Pyramid` application extensibility at
CM 888 all, you needn't.  You can ignore extensibility entirely.  However, if you
889 follow the set of rules defined in :ref:`extending_chapter`, you don't need
890 to *make* your application extensible: any application you write in the
891 framework just *is* automatically extensible at a basic level.  The
892 mechanisms that deployers use to extend it will be necessarily coarse:
893 typically, views, routes, and resources will be capable of being
894 overridden. But for most minor (and even some major) customizations, these
895 are often the only override plugpoints necessary: if the application doesn't
896 do exactly what the deployment requires, it's often possible for a deployer
897 to override a view, route, or resource and quickly make it do what he or she
898 wants it to do in ways *not necessarily anticipated by the original
899 developer*.  Here are some example scenarios demonstrating the benefits of
900 such a feature.
1df991 901
8cdb1b 902 - If a deployment needs a different styling, the deployer may override the
CM 903   main template and the CSS in a separate Python package which defines
904   overrides.
f5d708 905
8cdb1b 906 - If a deployment needs an application page to do something differently needs
CM 907   it to expose more or different information, the deployer may override the
908   view that renders the page within a separate Python package.
f5d708 909
8cdb1b 910 - If a deployment needs an additional feature, the deployer may add a view to
CM 911   the override package.
f5d708 912
8cdb1b 913 As long as the fundamental design of the upstream package doesn't change,
CM 914 these types of modifications often survive across many releases of the
915 upstream package without needing to be revisited.
ddb6a8 916
8cdb1b 917 Extending an application externally is not a panacea, and carries a set of
CM 918 risks similar to branching and merging: sometimes major changes upstream will
919 cause you to need to revisit and update some of your modifications.  But you
920 won't regularly need to deal wth meaningless textual merge conflicts that
921 trivial changes to upstream packages often entail when it comes time to
922 update the upstream package, because if you extend an application externally,
923 there just is no textual merge done.  Your modifications will also, for
924 whatever its worth, be contained in one, canonical, well-defined place.
ddb6a8 925
8cdb1b 926 Branching an application and continually merging in order to get new features
CM 927 and bugfixes is clearly useful.  You can do that with a :app:`Pyramid`
928 application just as usefully as you can do it with any application.  But
929 deployment of an application written in :app:`Pyramid` makes it possible to
930 avoid the need for this even if the application doesn't define any plugpoints
931 ahead of time.  It's possible that promoters of competing web frameworks
932 dismiss this feature in favor of branching and merging because applications
933 written in their framework of choice aren't extensible out of the box in a
f5d708 934 comparably fundamental way.
CM 935
8cdb1b 936 While :app:`Pyramid` application are fundamentally extensible even if you
CM 937 don't write them with specific extensibility in mind, if you're moderately
938 adventurous, you can also take it a step further.  If you learn more about
939 the :term:`Zope Component Architecture`, you can optionally use it to expose
940 other more domain-specific configuration plugpoints while developing an
941 application.  The plugpoints you expose needn't be as coarse as the ones
942 provided automatically by :app:`Pyramid` itself.  For example, you might
bee624 943 compose your own directive that configures a set of views for a prebaked
CM 944 purpose (e.g. ``restview`` or somesuch) , allowing other people to refer to
945 that directive when they make declarations in the ``includeme`` of their
946 customization package.  There is a cost for this: the developer of an
947 application that defines custom plugpoints for its deployers will need to
8cdb1b 948 understand the ZCA or he will need to develop his own similar extensibility
CM 949 system.
1df991 950
8cdb1b 951 Ultimately, any argument about whether the extensibility features lent to
e8db03 952 applications by :app:`Pyramid` are "good" or "bad" is mostly pointless. You
8cdb1b 953 needn't take advantage of the extensibility features provided by a particular
CM 954 :app:`Pyramid` application in order to affect a modification for a particular
955 set of its deployments.  You can ignore the application's extensibility
956 plugpoints entirely, and instead use version control branching and merging to
957 manage application deployment modifications instead, as if you were deploying
15be26 958 an application written using any other web framework.
CM 959
edd915 960 Zope 3 Enforces "TTW" Authorization Checks By Default; Pyramid Does Not
CM 961 -----------------------------------------------------------------------
a39aca 962
CM 963 Challenge
672bbe 964 +++++++++
a39aca 965
8cdb1b 966 :app:`Pyramid` performs automatic authorization checks only at :term:`view`
CM 967 execution time.  Zope 3 wraps context objects with a `security proxy
83fa67 968 <http://wiki.zope.org/zope3/WhatAreSecurityProxies>`_, which causes Zope 3 to
8cdb1b 969 do also security checks during attribute access.  I like this, because it
CM 970 means:
a39aca 971
CM 972 #) When I use the security proxy machinery, I can have a view that
973    conditionally displays certain HTML elements (like form fields) or
0d43ed 974    prevents certain attributes from being modified depending on the the
CM 975    permissions that the accessing user possesses with respect to a context
976    object.
a39aca 977
a5ffd6 978 #) I want to also expose my resources via a REST API using Twisted Web. If
0d43ed 979    Pyramid performed authorization based on attribute access via Zope3's
a5ffd6 980    security proxies, I could enforce my authorization policy in both
fd5ae9 981    :app:`Pyramid` and in the Twisted-based system the same way.
a39aca 982
CM 983 Defense
672bbe 984 +++++++
a39aca 985
8cdb1b 986 :app:`Pyramid` was developed by folks familiar with Zope 2, which has a
CM 987 "through the web" security model.  This "TTW" security model was the
988 precursor to Zope 3's security proxies.  Over time, as the :app:`Pyramid`
989 developers (working in Zope 2) created such sites, we found authorization
990 checks during code interpretation extremely useful in a minority of projects.
991 But much of the time, TTW authorization checks usually slowed down the
992 development velocity of projects that had no delegation requirements.  In
993 particular, if we weren't allowing "untrusted" users to write arbitrary
994 Python code to be executed by our application, the burden of "through the
995 web" security checks proved too costly to justify.  We (collectively) haven't
996 written an application on top of which untrusted developers are allowed to
997 write code in many years, so it seemed to make sense to drop this model by
998 default in a new web framework.
a39aca 999
8cdb1b 1000 And since we tend to use the same toolkit for all web applications, it's just
CM 1001 never been a concern to be able to use the same set of restricted-execution
1002 code under two web different frameworks.
a39aca 1003
8cdb1b 1004 Justifications for disabling security proxies by default notwithstanding,
CM 1005 given that Zope 3 security proxies are "viral" by nature, the only
1006 requirement to use one is to make sure you wrap a single object in a security
1007 proxy and make sure to access that object normally when you want proxy
1008 security checks to happen.  It is possible to override the :app:`Pyramid`
1009 "traverser" for a given application (see :ref:`changing_the_traverser`).  To
1010 get Zope3-like behavior, it is possible to plug in a different traverser
1011 which returns Zope3-security-proxy-wrapped objects for each traversed object
1012 (including the :term:`context` and the :term:`root`).  This would have the
1013 effect of creating a more Zope3-like environment without much effort.
a39aca 1014
8cbbd9 1015 .. _http_exception_hierarchy:
CM 1016
1017 Pyramid Uses its Own HTTP Exception Class Hierarchy Rather Than ``webob.exc``
1018 -----------------------------------------------------------------------------
1e5e31 1019
CM 1020 .. note:: This defense is new as of Pyramid 1.1.
1021
1022 The HTTP exception classes defined in :mod:`pyramid.httpexceptions` are very
1023 much like the ones defined in ``webob.exc``
1024 (e.g. :class:`~pyramid.httpexceptions.HTTPNotFound`,
1025 :class:`~pyramid.httpexceptions.HTTPForbidden`, etc).  They have the same
1026 names and largely the same behavior and all have a very similar
1027 implementation, but not the same identity.  Here's why they have a separate
1028 identity:
1029
1030 - Making them separate allows the HTTP exception classes to subclass
1031   :class:`pyramid.response.Response`.  This speeds up response generation
1032   slightly due to the way the Pyramid router works.  The same speedup could
1033   be gained by monkeypatching ``webob.response.Response`` but it's usually
1034   the case that monkeypatching turns out to be evil and wrong.
1035
1036 - Making them separate allows them to provide alternate ``__call__`` logic
1037   which also speeds up response generation.
1038
1039 - Making them separate allows the exception classes to provide for the proper
1040   value of ``RequestClass`` (:class:`pyramid.request.Request`).
1041
1042 - Making them separate allows us freedom from having to think about backwards
1043   compatibility code present in ``webob.exc`` having to do with Python 2.4,
1044   which we no longer support in Pyramid 1.1+.
1045
1046 - We change the behavior of two classes
1047   (:class:`~pyramid.httpexceptions.HTTPNotFound` and
1048   :class:`~pyramid.httpexceptions.HTTPForbidden`) in the module so that they
1049   can be used by Pyramid internally for notfound and forbidden exceptions.
1050
1051 - Making them separate allows us to influence the docstrings of the exception
1052   classes to provide Pyramid-specific documentation.
1053
1054 - Making them separate allows us to silence a stupid deprecation warning
1055   under Python 2.6 when the response objects are used as exceptions (related
1056   to ``self.message``).
1057
8f521b 1058 .. _simpler_traversal_model:
CM 1059
1060 Pyramid has Simpler Traversal Machinery than Does Zope
1061 ------------------------------------------------------
1062
1063 Zope's default traverser:
1064
1065 - Allows developers to mutate the traversal name stack while traversing (they
1066   can add and remove path elements).
1067
1068 - Attempts to use an adaptation to obtain the "next" element in the path from
1069   the currently traversed object, falling back to ``__bobo_traverse__``,
1070   ``__getitem__`` and eventually ``__getattr__``.
1071
1072 Zope's default traverser allows developers to mutate the traversal name stack
1073 during traversal by mutating ``REQUEST['TraversalNameStack']``.  Pyramid's
1074 default traverser (``pyramid.traversal.ResourceTreeTraverser``) does not
1075 offer a way to do this; it does not maintain a stack as a request attribute
1076 and, even if it did, it does not pass the request to resource objects while
1077 it's traversing.  While it was handy at times, this feature was abused in
1078 frameworks built atop Zope (like CMF and Plone), often making it difficult to
1079 tell exactly what was happening when a traversal didn't match a view.  I felt
1080 it was better to make folks that wanted the feature replace the traverser
1081 rather than build that particular honey pot in to the default traverser.
1082
1083 Zope uses multiple mechanisms to attempt to obtain the next element in the
1084 resource tree based on a name.  It first tries an adaptation of the current
1085 resource to ``ITraversable``, and if that fails, it falls back to attempting
1086 number of magic methods on the resource (``__bobo_traverse__``,
1087 ``__getitem__``, and ``__getattr__``).  My experience while both using Zope
1088 and attempting to reimplement its publisher in ``repoze.zope2`` led me to
1089 believe the following:
1090
1091 - The *default* traverser should be as simple as possible.  Zope's publisher
1092   is somewhat difficult to follow and replicate due to the fallbacks it tried
1093   when one traversal method failed.  It is also slow.
1094
1095 - The *entire traverser* should be replaceable, not just elements of the
1096   traversal machinery.  Pyramid has a few "big" components rather than a
1097   plethora of small ones.  If the entire traverser is replaceable, it's an
1098   antipattern to make portions of the default traverser replaceable.  Doing
1099   so is a "knobs on knobs" pattern, which is unfortunately somewhat endemic
1100   in Zope.  In a "knobs on knobs" pattern, a replaceable subcomponent of a
1101   larger component is made configurable using the same configuration
1102   mechanism that can be used to replace the larger component.  For example,
1103   in Zope, you can replace the default traverser by registering an adapter.
1104   But you can also (or alternately) control how the default traverser
1105   traverses by registering one or more adapters.  As a result of being able
1106   to either replace the larger component entirely or turn knobs on the
1107   default implementation of the larger component, no one understands when (or
1108   whether) they should ever override the larger component entrirely.  This
1109   results, over time, in a "rusting together" of the larger "replaceable"
1110   component and the framework itself, because people come to depend on the
1111   availability of the default component in order just to turn its knobs. The
1112   default component effectively becomes part of the framework, which entirely
1113   subverts the goal of making it replaceable.  In Pyramid, typically if a
1114   component is replaceable, it will itself have no knobs (it will be "solid
1115   state").  If you want to influence behavior controlled by that component,
1116   you will replace the component instead of turning knobs attached to the
1117   component.
1118
7b511a 1119 .. _microframeworks_smaller_hello_world:
CM 1120
1121 Microframeworks Have Smaller Hello World Programs
1122 -------------------------------------------------
1123
8cdb1b 1124 Self-described "microframeworks" exist: `Bottle <http://bottle.paws.de>`_ and
CM 1125 `Flask <http://flask.pocoo.org/>`_ are two that are becoming popular.  `Bobo
1126 <http://bobo.digicool.com/>`_ doesn't describe itself as a microframework,
1127 but its intended userbase is much the same.  Many others exist.  We've
1128 actually even (only as a teaching tool, not as any sort of official project)
d3255c 1129 `created one using Pyramid <http://bfg.repoze.org/videos#groundhog1>`_ (the
CM 1130 videos use BFG, a precursor to Pyramid, but the resulting code is `available
1131 for Pyramid too <http://github.com/Pylons/groundhog>`_). Microframeworks are
1132 small frameworks with one common feature: each allows its users to create a
1133 fully functional application that lives in a single Python file.
7b511a 1134
8cdb1b 1135 Some developers and microframework authors point out that Pyramid's "hello
CM 1136 world" single-file program is longer (by about five lines) than the
965fe1 1137 equivalent program in their favorite microframework.  Guilty as charged.
26a0fd 1138
965fe1 1139 This loss isn't for lack of trying. Pyramid is useful in the same
8cdb1b 1140 circumstance in which microframeworks claim dominance: single-file
CM 1141 applications.  But Pyramid doesn't sacrifice its ability to credibly support
1142 larger applications in order to achieve hello-world LoC parity with the
1143 current crop of microframeworks.  Pyramid's design instead tries to avoid
1144 some common pitfalls associated with naive declarative configuration schemes.
1145 The subsections which follow explain the rationale.
7b511a 1146
CM 1147 .. _you_dont_own_modulescope:
1148
1149 Application Programmers Don't Control The Module-Scope Codepath (Import-Time Side-Effects Are Evil)
1150 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1151
8cdb1b 1152 Please imagine a directory structure with a set of Python files in it:
7b511a 1153
CM 1154 .. code-block:: text
1155
1156     .
1157     |-- app.py
1158     |-- app2.py
1159     `-- config.py
1160
1161 The contents of ``app.py``:
1162
1163 .. code-block:: python
16cd50 1164     :linenos:
7b511a 1165
CM 1166     from config import decorator
1167     from config import L
1168     import pprint
1169
1170     @decorator
1171     def foo():
1172         pass
1173
1174     if __name__ == '__main__':
1175         import app2
1176         pprint.pprint(L)
1177
1178 The contents of ``app2.py``:
1179
1180 .. code-block:: python
16cd50 1181     :linenos:
7b511a 1182
CM 1183     import app
1184
1185     @app.decorator
1186     def bar():
1187         pass
1188
1189 The contents of ``config.py``:
1190
1191 .. code-block:: python
16cd50 1192   :linenos:
7b511a 1193
CM 1194     L = []
1195
1196     def decorator(func):
1197         L.append(func)
1198         return func
1199
8cdb1b 1200 If we cd to the directory that holds these files and we run ``python app.py``
CM 1201 given the directory structure and code above, what happens?  Presumably, our
1202 ``decorator`` decorator will be used twice, once by the decorated function
1203 ``foo`` in ``app.py`` and once by the decorated function ``bar`` in
1204 ``app2.py``.  Since each time the decorator is used, the list ``L`` in
1205 ``config.py`` is appended to, we'd expect a list with two elements to be
1206 printed, right?  Sadly, no:
7b511a 1207
16cd50 1208 .. code-block:: text
7b511a 1209
CM 1210     [chrism@thinko]$ python app.py 
1211     [<function foo at 0x7f4ea41ab1b8>,
1212      <function foo at 0x7f4ea41ab230>,
1213      <function bar at 0x7f4ea41ab2a8>]
1214
8cdb1b 1215 By visual inspection, that outcome (three different functions in the list)
CM 1216 seems impossible.  We only defined two functions and we decorated each of
1217 those functions only once, so we believe that the ``decorator`` decorator
1218 will only run twice.  However, what we believe is wrong because the code at
1219 module scope in our ``app.py`` module was *executed twice*.  The code is
1220 executed once when the script is run as ``__main__`` (via ``python app.py``),
1221 and then it is executed again when ``app2.py`` imports the same file as
1222 ``app``.
7b511a 1223
8cdb1b 1224 What does this have to do with our comparison to microframeworks?  Many
CM 1225 microframeworks in the current crop (e.g. Bottle, Flask) encourage you to
1226 attach configuration decorators to objects defined at module scope.  These
1227 decorators execute arbitrarily complex registration code which populates a
1228 singleton registry that is a global defined in external Python module.  This
1229 is analogous to the above example: the "global registry" in the above example
1230 is the list ``L``.
7b511a 1231
8cdb1b 1232 Let's see what happens when we use the same pattern with the `Groundhog
965fe1 1233 <https://github.com/Pylons/groundhog>`_ microframework.  Replace the contents
CM 1234 of ``app.py`` above with this:
7b511a 1235
CM 1236 .. code-block:: python
16cd50 1237     :linenos:
7b511a 1238
CM 1239     from config import gh
1240
1241     @gh.route('/foo/')
1242     def foo():
1243         return 'foo'
1244
1245     if __name__ == '__main__':
1246         import app2
1247         pprint.pprint(L)
1248
1249 Replace the contents of ``app2.py`` above with this:
1250
1251 .. code-block:: python
16cd50 1252     :linenos:
7b511a 1253
CM 1254     import app
1255
1256     @app.gh.route('/bar/')
1257     def bar():
1258         'return bar'
1259
1260 Replace the contents of ``config.py`` above with this:
1261
1262 .. code-block:: python
16cd50 1263     :linenos:
7b511a 1264
CM 1265     from groundhog import Groundhog
1266     gh = Groundhog('myapp', 'seekrit')
1267
8cdb1b 1268 How many routes will be registered within the routing table of the "gh"
CM 1269 Groundhog application?  If you answered three, you are correct.  How many
1270 would a casual reader (and any sane developer) expect to be registered?  If
1271 you answered two, you are correct.  Will the double registration be a
965fe1 1272 problem?  With our Groundhog framework's ``route`` method backing this
CM 1273 application, not really.  It will slow the application down a little bit,
1274 because it will need to miss twice for a route when it does not match.  Will
1275 it be a problem with another framework, another application, or another
8cdb1b 1276 decorator?  Who knows.  You need to understand the application in its
CM 1277 totality, the framework in its totality, and the chronology of execution to
1278 be able to predict what the impact of unintentional code double-execution
1279 will be.
7b511a 1280
8cdb1b 1281 The encouragement to use decorators which perform population of an external
CM 1282 registry has an unintended consequence: the application developer now must
1283 assert ownership of every codepath that executes Python module scope
1284 code. Module-scope code is presumed by the current crop of decorator-based
1285 microframeworks to execute once and only once; if it executes more than once,
1286 weird things will start to happen.  It is up to the application developer to
1287 maintain this invariant.  Unfortunately, however, in reality, this is an
1288 impossible task, because, Python programmers *do not own the module scope
1289 codepath, and never will*.  Anyone who tries to sell you on the idea that
1290 they do is simply mistaken.  Test runners that you may want to use to run
1291 your code's tests often perform imports of arbitrary code in strange orders
1292 that manifest bugs like the one demonstrated above.  API documentation
965fe1 1293 generation tools do the same.  Some people even think it's safe to use the
CM 1294 Python ``reload`` command or delete objects from ``sys.modules``, each of
1295 which has hilarious effects when used against code that has import-time side
1296 effects.
7b511a 1297
8cdb1b 1298 Global-registry-mutating microframework programmers therefore will at some
CM 1299 point need to start reading the tea leaves about what *might* happen if
1300 module scope code gets executed more than once like we do in the previous
1301 paragraph.  When Python programmers assume they can use the module-scope
1302 codepath to run arbitrary code (especially code which populates an external
1303 registry), and this assumption is challenged by reality, the application
1304 developer is often required to undergo a painful, meticulous debugging
1305 process to find the root cause of an inevitably obscure symptom.  The
1306 solution is often to rearrange application import ordering or move an import
1307 statement from module-scope into a function body.  The rationale for doing so
1308 can never be expressed adequately in the checkin message which accompanies
1309 the fix and can't be documented succinctly enough for the benefit of the rest
1310 of the development team so that the problem never happens again.  It will
1311 happen again, especially if you are working on a project with other people
1312 who haven't yet internalized the lessons you learned while you stepped
1313 through module-scope code using ``pdb``.  This is a really pretty poor
1314 situation to find yourself in as an application developer: you probably
1315 didn't even know your or your team signed up for the job, because the
1316 documentation offered by decorator-based microframeworks don't warn you about
1317 it.
7b511a 1318
8cdb1b 1319 Folks who have a large investment in eager decorator-based configuration that
CM 1320 populates an external data structure (such as microframework authors) may
1321 argue that the set of circumstances I outlined above is anomalous and
1322 contrived.  They will argue that it just will never happen.  If you never
1323 intend your application to grow beyond one or two or three modules, that's
1324 probably true.  However, as your codebase grows, and becomes spread across a
1325 greater number of modules, the circumstances in which module-scope code will
1326 be executed multiple times will become more and more likely to occur and less
1327 and less predictable.  It's not responsible to claim that double-execution of
1328 module-scope code will never happen.  It will; it's just a matter of luck,
1329 time, and application complexity.
7b511a 1330
8cdb1b 1331 If microframework authors do admit that the circumstance isn't contrived,
CM 1332 they might then argue that "real" damage will never happen as the result of
1333 the double-execution (or triple-execution, etc) of module scope code.  You
1334 would be wise to disbelieve this assertion.  The potential outcomes of
1335 multiple execution are too numerous to predict because they involve delicate
1336 relationships between application and framework code as well as chronology of
1337 code execution.  It's literally impossible for a framework author to know
1338 what will happen in all circumstances.  But even if given the gift of
1339 omniscience for some limited set of circumstances, the framework author
1340 almost certainly does not have the double-execution anomaly in mind when
1341 coding new features.  He's thinking of adding a feature, not protecting
1342 against problems that might be caused by the 1% multiple execution case.
1343 However, any 1% case may cause 50% of your pain on a project, so it'd be nice
1344 if it never occured.
7b511a 1345
CM 1346 Responsible microframeworks actually offer a back-door way around the
8cdb1b 1347 problem.  They allow you to disuse decorator based configuration entirely.
CM 1348 Instead of requiring you to do the following:
7b511a 1349
CM 1350 .. code-block:: python
16cd50 1351     :linenos:
7b511a 1352
CM 1353     gh = Groundhog('myapp', 'seekrit')
1354
1355     @gh.route('/foo/')
1356     def foo():
1357         return 'foo'
1358
1359     if __name__ == '__main__':
1360         gh.run()
1361
8cdb1b 1362 They allow you to disuse the decorator syntax and go almost-all-imperative:
7b511a 1363
CM 1364 .. code-block:: python
16cd50 1365     :linenos:
7b511a 1366
CM 1367     def foo():
1368         return 'foo'
1369
1370     gh = Groundhog('myapp', 'seekrit')
1371
1372     if __name__ == '__main__':
1373         gh.add_route(foo, '/foo/')
1374         gh.run()
1375
edd915 1376 This is a generic mode of operation that is encouraged in the Pyramid
8cdb1b 1377 documentation. Some existing microframeworks (Flask, in particular) allow for
CM 1378 it as well.  None (other than Pyramid) *encourage* it.  If you never expect
1379 your application to grow beyond two or three or four or ten modules, it
1380 probably doesn't matter very much which mode you use.  If your application
1381 grows large, however, imperative configuration can provide better
1382 predictability.
7b511a 1383
CM 1384 .. note::
1385
8cdb1b 1386   Astute readers may notice that Pyramid has configuration decorators too.
CM 1387   Aha!  Don't these decorators have the same problems?  No.  These decorators
1388   do not populate an external Python module when they are executed.  They
1389   only mutate the functions (and classes and methods) they're attached to.
1390   These mutations must later be found during a "scan" process that has a
1391   predictable and structured import phase.  Module-localized mutation is
1392   actually the best-case circumstance for double-imports; if a module only
1393   mutates itself and its contents at import time, if it is imported twice,
1394   that's OK, because each decorator invocation will always be mutating an
1395   independent copy of the object its attached to, not a shared resource like
1396   a registry in another module.  This has the effect that
1397   double-registrations will never be performed.
7b511a 1398
0a585a 1399 Routes Need Relative Ordering
CM 1400 +++++++++++++++++++++++++++++
7b511a 1401
CM 1402 Consider the following simple `Groundhog
e9bf10 1403 <https://github.com/Pylons/groundhog>`_ application:
7b511a 1404
CM 1405 .. code-block:: python
16cd50 1406     :linenos:
7b511a 1407
CM 1408     from groundhog import Groundhog
1409     app = Groundhog('myapp', 'seekrit')
1410
1411     app.route('/admin')
1412     def admin():
1413         return '<html>admin page</html>'
1414
1415     app.route('/:action')
1416     def action():
1417         if action == 'add':
7be3b1 1418            return '<html>add</html>'
7b511a 1419         if action == 'delete':
7be3b1 1420            return '<html>delete</html>'
7b511a 1421         return app.abort(404)
CM 1422
1423     if __name__ == '__main__':
1424         app.run()
1425
1426 If you run this application and visit the URL ``/admin``, you will see
8cdb1b 1427 "admin" page.  This is the intended result.  However, what if you rearrange
CM 1428 the order of the function definitions in the file?
7b511a 1429
CM 1430 .. code-block:: python
16cd50 1431     :linenos:
7b511a 1432
CM 1433     from groundhog import Groundhog
1434     app = Groundhog('myapp', 'seekrit')
1435
1436     app.route('/:action')
1437     def action():
1438         if action == 'add':
7be3b1 1439            return '<html>add</html>'
7b511a 1440         if action == 'delete':
7be3b1 1441            return '<html>delete</html>'
7b511a 1442         return app.abort(404)
CM 1443
1444     app.route('/admin')
1445     def admin():
1446         return '<html>admin page</html>'
1447
1448     if __name__ == '__main__':
1449         app.run()
1450
8cdb1b 1451 If you run this application and visit the URL ``/admin``, you will now be
CM 1452 returned a 404 error.  This is probably not what you intended.  The reason
1453 you see a 404 error when you rearrange function definition ordering is that
1454 routing declarations expressed via our microframework's routing decorators
1455 have an *ordering*, and that ordering matters.
7b511a 1456
8cdb1b 1457 In the first case, where we achieved the expected result, we first added a
CM 1458 route with the pattern ``/admin``, then we added a route with the pattern
1459 ``/:action`` by virtue of adding routing patterns via decorators at module
1460 scope.  When a request with a ``PATH_INFO`` of ``/admin`` enters our
1461 application, the web framework loops over each of our application's route
1462 patterns in the order in which they were defined in our module.  As a result,
1463 the view associated with the ``/admin`` routing pattern will be invoked: it
1464 matches first.  All is right with the world.
7b511a 1465
8cdb1b 1466 In the second case, where we did not achieve the expected result, we first
CM 1467 added a route with the pattern ``/:action``, then we added a route with the
1468 pattern ``/admin``.  When a request with a ``PATH_INFO`` of ``/admin`` enters
1469 our application, the web framework loops over each of our application's route
1470 patterns in the order in which they were defined in our module.  As a result,
1471 the view associated with the ``/:action`` routing pattern will be invoked: it
1472 matches first.  A 404 error is raised.  This is not what we wanted; it just
1473 happened due to the order in which we defined our view functions.
7b511a 1474
0a585a 1475 This is because "Groundhog" routes are added to the routing map in import
CM 1476 order, and matched in the same order when a request comes in.  Bottle, like
1477 Groundhog, as of this writing, matches routes in the order in which they're
1478 defined at Python execution time.  Flask, on the other hand, does not order
1479 route matching based on import order; it reorders the routes you add to your
1480 application based on their "complexity".  Other microframeworks have varying
1481 strategies to do route ordering.
7b511a 1482
0a585a 1483 Your application may be small enough where route ordering will never cause an
CM 1484 issue.  If your application becomes large enough, however, being able to
1485 specify or predict that ordering as your application grows larger will be
1486 difficult.  At some point, you will likely need to more explicitly start
1487 controlling route ordering, especially in applications that require
1488 extensibility.
1489
1490 If your microframework orders route matching based on "complexity", you'll
1491 need to understand what that "complexity" ordering is and attempt to inject a
1492 "less complex" route to have it get matched before any "more complex" one to
1493 ensure that it's tried first.
1494
1495 If your microframework orders its route matching based on relative
1496 import/execution of function decorator definitions, you will need to ensure
1497 you execute all of these statements in the "right" order, and you'll need to
1498 be cognizant of this import/execution ordering as you grow your application
1499 or try to extend it.  This is a difficult invariant to maintain for all but
1500 the smallest applications.
1501
1502 In either case, your application must import the non-``__main__`` modules
1503 which contain configuration decorations somehow for their configuration to be
1504 executed.  Does that make you a little uncomfortable?  It should, because
8cdb1b 1505 :ref:`you_dont_own_modulescope`.
7b511a 1506
0428ed 1507 Pyramid uses neither decorator import time ordering nor does it attempt to
CM 1508 divine the relative "complexity" of one route to another in order to define a
1509 route match ordering.  In Pyramid, you have to maintain relative route
1510 ordering imperatively via the chronology of multiple executions of the
1511 :meth:`pyramid.config.Configurator.add_route` method.  The order in which you
1512 repeatedly call ``add_route`` becomes the order of route matching.
1513
1514 If needing to maintain this imperative ordering truly bugs you, you can use
1515 :term:`traversal` instead of route matching, which is a completely
1516 declarative (and completely predictable) mechanism to map code to URLs.
1517 While URL dispatch is easier to understand for small non-extensible
1518 applications, traversal is a great fit for very large applications and
1519 applications that need to be arbitrarily extensible.
1d1975 1520
7b511a 1521 "Stacked Object Proxies" Are Too Clever / Thread Locals Are A Nuisance
CM 1522 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1523
8cdb1b 1524 In another manifestation of "import fascination", some microframeworks use
CM 1525 the ``import`` statement to get a handle to an object which *is not logically
1526 global*:
7b511a 1527
CM 1528 .. code-block:: python
16cd50 1529     :linenos:
7b511a 1530
CM 1531     from flask import request
1532
1533     @app.route('/login', methods=['POST', 'GET'])
1534     def login():
1535         error = None
1536         if request.method == 'POST':
1537             if valid_login(request.form['username'],
1538                            request.form['password']):
1539                 return log_the_user_in(request.form['username'])
1540             else:
1541                 error = 'Invalid username/password'
1542         # this is executed if the request method was GET or the
1543         # credentials were invalid    
1544
e7b5fe 1545 The `Pylons 1.X <http://pylonsproject.org>`_ web framework uses a similar
8cdb1b 1546 strategy.  It calls these things "Stacked Object Proxies", so, for purposes
CM 1547 of this discussion, I'll do so as well.
7b511a 1548
8cdb1b 1549 Import statements in Python (``import foo``, ``from bar import baz``) are
CM 1550 most frequently performed to obtain a reference to an object defined globally
1551 within an external Python module.  However, in "normal" programs, they are
1552 never used to obtain a reference to an object that has a lifetime measured by
1553 the scope of the body of a function.  It would be absurd to try to import,
1554 for example, a variable named ``i`` representing a loop counter defined in
1555 the body of a function.  For example, we'd never try to import ``i`` from the
7b511a 1556 code below:
CM 1557
1558 .. code-block::  python
16cd50 1559    :linenos:
7b511a 1560
CM 1561    def afunc():
1562        for i in range(10):
1563            print i
1564
8cdb1b 1565 By its nature, the *request* object created as the result of a WSGI server's
CM 1566 call into a long-lived web framework cannot be global, because the lifetime
1567 of a single request will be much shorter than the lifetime of the process
1568 running the framework.  A request object created by a web framework actually
1569 has more similarity to the ``i`` loop counter in our example above than it
1570 has to any comparable importable object defined in the Python standard
1571 library or in "normal" library code.
7b511a 1572
8cdb1b 1573 However, systems which use stacked object proxies promote locally scoped
CM 1574 objects such as ``request`` out to module scope, for the purpose of being
1575 able to offer users a "nice" spelling involving ``import``.  They, for what I
1576 consider dubious reasons, would rather present to their users the canonical
1577 way of getting at a ``request`` as ``from framework import request`` instead
1578 of a saner ``from myframework.threadlocals import get_request; request =
1579 get_request()`` even though the latter is more explicit.
7b511a 1580
8cdb1b 1581 It would be *most* explicit if the microframeworks did not use thread local
CM 1582 variables at all.  Pyramid view functions are passed a request object; many
1583 of Pyramid's APIs require that an explicit request object be passed to them.
1584 It is *possible* to retrieve the current Pyramid request as a threadlocal
1585 variable but it is a "in case of emergency, break glass" type of activity.
1586 This explicitness makes Pyramid view functions more easily unit testable, as
1587 you don't need to rely on the framework to manufacture suitable "dummy"
1588 request (and other similarly-scoped) objects during test setup.  It also
1589 makes them more likely to work on arbitrary systems, such as async servers
1590 that do no monkeypatching.
7b511a 1591
CM 1592 Explicitly WSGI
1593 +++++++++++++++
1594
8cdb1b 1595 Some microframeworks offer a ``run()`` method of an application object that
CM 1596 executes a default server configuration for easy execution.
7b511a 1597
8cdb1b 1598 Pyramid doesn't currently try to hide the fact that its router is a WSGI
CM 1599 application behind a convenience ``run()`` API.  It just tells people to
1600 import a WSGI server and use it to serve up their Pyramid application as per
1601 the documentation of that WSGI server.
7b511a 1602
8cdb1b 1603 The extra lines saved by abstracting away the serving step behind ``run()``
CM 1604 seem to have driven dubious second-order decisions related to API in some
1605 microframeworks.  For example, Bottle contains a ``ServerAdapter`` subclass
1606 for each type of WSGI server it supports via its ``app.run()`` mechanism.
1607 This means that there exists code in ``bottle.py`` that depends on the
1608 following modules: ``wsgiref``, ``flup``, ``paste``, ``cherrypy``, ``fapws``,
1609 ``tornado``, ``google.appengine``, ``twisted.web``, ``diesel``, ``gevent``,
1610 ``gunicorn``, ``eventlet``, and ``rocket``.  You choose the kind of server
1611 you want to run by passing its name into the ``run`` method.  In theory, this
1612 sounds great: I can try Bottle out on ``gunicorn`` just by passing in a name!
1613 However, to fully test Bottle, all of these third-party systems must be
1614 installed and functional; the Bottle developers must monitor changes to each
1615 of these packages and make sure their code still interfaces properly with
1616 them.  This expands the packages required for testing greatly; this is a
1617 *lot* of requirements.  It is likely difficult to fully automate these tests
7b511a 1618 due to requirements conflicts and build issues.
CM 1619
8cdb1b 1620 As a result, for single-file apps, we currently don't bother to offer a
CM 1621 ``run()`` shortcut; we tell folks to import their WSGI server of choice and
1622 run it "by hand".  For the people who want a server abstraction layer, we
1623 suggest that they use PasteDeploy.  In PasteDeploy-based systems, the onus
1624 for making sure that the server can interface with a WSGI application is
1625 placed on the server developer, not the web framework developer, making it
1626 more likely to be timely and correct.
7b511a 1627
CM 1628 Wrapping Up
1629 +++++++++++
1630
8cdb1b 1631 Here's a diagrammed version of the simplest pyramid application, where
CM 1632 comments take into account what we've discussed in the
7b511a 1633 :ref:`microframeworks_smaller_hello_world` section.
CM 1634
1635 .. code-block:: python
16cd50 1636    :linenos:
7b511a 1637
d868ff 1638    from pyramid.response import Response      # explicit response objects, no TL
7b511a 1639    from paste.httpserver import serve         # explicitly WSGI
CM 1640
1641    def hello_world(request):  # accepts a request; no request thread local reqd
1642        # explicit response object means no response threadlocal
1643        return Response('Hello world!') 
1644
1645    if __name__ == '__main__':
d7f259 1646        from pyramid.config import Configurator
7b511a 1647        config = Configurator()       # no global application object.
CM 1648        config.add_view(hello_world)  # explicit non-decorator registration
1649        app = config.make_wsgi_app()  # explicitly WSGI
1650        serve(app, host='0.0.0.0')    # explicitly WSGI
1651
82e3e3 1652 Pyramid Doesn't Offer Pluggable Apps
CM 1653 ------------------------------------
1654
1655 It is "Pyramidic" to compose multiple external sources into the same
98b28d 1656 configuration using :meth:`~pyramid.config.Configuration.include`.  Any
CM 1657 number of includes can be done to compose an application; includes can even
1658 be done from within other includes.  Any directive can be used within an
1659 include that can be used outside of one (such as
1660 :meth:`~pyramid.config.Configurator.add_view`, etc).
82e3e3 1661
CM 1662 Pyramid has a conflict detection system that will throw an error if two 
1663 included externals try to add "the same" configuration in a conflicting 
1664 way (such as both externals trying to add a route using the same name, 
1665 or both externals trying to add a view with the same set of predicates). 
1666 It's awful tempting to call this set of features something that can be 
1667 used to compose a system out of "pluggable applications".  But in 
1668 reality, there are a number of problems with claiming this: 
1669
1670 - The terminology is strained. Pyramid really has no notion of a 
1671   plurality of "applications", just a way to compose configuration 
1672   from multiple sources to create a single WSGI application.  That 
1673   WSGI application may gain behavior by including or disincluding 
1674   configuration, but once it's all composed together, Pyramid 
1675   doesn't really provide any machinery which can be used to demarcate 
1676   the boundaries of one "application" (in the sense of configuration 
1677   from an external that adds routes, views, etc) from another. 
1678
1679 - Pyramid doesn't provide enough "rails" to make it possible to 
1680   integrate truly honest-to-god, download-an-app-from-a-random-place 
1681   and-plug-it-in-to-create-a-system "pluggable" applications. 
1682   Because Pyramid itself isn't opinionated (it doesn't mandate a 
1683   particular kind of database, it offers multiple ways to map URLs 
1684   to code, etc), it's unlikely that someone who creates something 
1685   "application-like" will be able to casually redistribute it 
1686   to J. Random Pyramid User and have it "just work" by asking him 
1687   to config.include a function from the package. 
1688   This is particularly true of very high level components such 
1689   as blogs, wikis, twitter clones, commenting systems, etc. 
1690   The "integrator" (the Pyramid developer who has downloaded a 
1691   package advertised as a "pluggable app") will almost certainly 
1692   have made different choices about e.g. what type of persistence 
1693   system he's using, and for the integrator to appease the 
1694   requirements of the "pluggable application", he may be required 
1695   to set up a different database, make changes to his own code 
1696   to prevent his application from "shadowing" the pluggable 
1697   app (or vice versa), and any other number of arbitrary 
1698   changes. 
1699
1700 For this reason, we claim that Pyramid has "extensible" applications, 
1701 not pluggable applications.  Any Pyramid application can be extended 
1702 without forking it as long as its configuration statements have been 
1703 composed into things that can be pulled in via "config.include". 
1704
1705 It's also perfectly reasonable for a single developer or team to create a set
1706 of interoperating components which can be enabled or disabled by using
1707 config.include.  That developer or team will be able to provide the "rails"
1708 (by way of making high-level choices about the technology used to create the
1709 project, so there won't be any issues with plugging all of the components
1710 together.  The problem only rears its head when the components need to be
1711 distributed to *arbitrary* users.  Note that Django has a similar problem
1712 with "pluggable applications" that need to work for arbitrary third parties,
1713 even though they provide many, many more rails than does Pyramid.  Even the
1714 rails they provide are not enough to make the "pluggable application" story
1715 really work without local modification.
1716
1717 Truly pluggable applications need to be created at a much higher level than a
1718 web framework, as no web framework can offer enough constraints to really
1719 make them "work out of the box".  They really need to plug into an
1720 application, instead.  It would be a noble goal to build an application with
1721 Pyramid that provides these constraints and which truly does offer a way to
1722 plug in applications (Joomla, Plone, Drupal come to mind).
1723
8cdb1b 1724 Pyramid Has Zope Things In It, So It's Too Complex
CM 1725 --------------------------------------------------
1726
1727 On occasion, someone will feel compelled to post a mailing list message that
1728 reads something like this:
1729
1730 .. code-block:: text
1731
1732    had a quick look at pyramid ... too complex to me and not really
1733    understand for which benefits.. I feel should consider whether it's time
1734    for me to step back to django .. I always hated zope (useless ?)
1735    complexity and I love simple way of thinking
1736
1737 (Paraphrased from a real email, actually.)
1738
1739 Let's take this criticism point-by point.
1740
1741 Too Complex
1742 +++++++++++
1743
03fc30 1744 If you can understand this hello world program, you can use Pyramid:
8cdb1b 1745
CM 1746 .. code-block:: python
1747    :linenos:
1748
1749    from paste.httpserver import serve
1750    from pyramid.config import Configurator
1751    from pyramid.response import Response
1752
1753    def hello_world(request):
1754        return Response('Hello world!')
1755
1756    if __name__ == '__main__':
1757        config = Configurator()
1758        config.add_view(hello_world)
1759        app = config.make_wsgi_app()
1760        serve(app)
1761
adfcf6 1762 Pyramid has ~ 650 pages of documentation (printed), covering topics from the
TS 1763 very basic to the most advanced.  *Nothing* is left undocumented, quite
1764 literally.  It also has an *awesome*, very helpful community.  Visit the
16b93e 1765 #pyramid and/or #pylons IRC channels on freenode.net and see.
8cdb1b 1766
CM 1767 Hate Zope
1768 +++++++++
1769
1770 I'm sorry you feel that way.  The Zope brand has certainly taken its share of
1771 lumps over the years, and has a reputation for being insular and mysterious.
1772 But the word "Zope" is literally quite meaningless without qualification.
1773 What *part* of Zope do you hate?  "Zope" is a brand, not a technology.
1774
1775 If it's Zope2-the-web-framework, Pyramid is not that.  The primary designers
1776 and developers of Pyramid, if anyone, should know.  We wrote Pyramid's
1777 predecessor (:mod:`repoze.bfg`), in part, because *we* knew that Zope 2 had
1778 usability issues and limitations.  :mod:`repoze.bfg` (and now :app:`Pyramid`)
1779 was written to address these issues.
1780
1781 If it's Zope3-the-web-framework, Pyramid is *definitely* not that.  Making
1782 use of lots of Zope 3 technologies is territory already staked out by the
1783 :term:`Grok` project.  Save for the obvious fact that they're both web
1784 frameworks, :mod:`Pyramid` is very, very different than Grok.  Grok exposes
1785 lots of Zope technologies to end users.  On the other hand, if you need to
1786 understand a Zope-only concept while using Pyramid, then we've failed on some
1787 very basic axis.
1788
1789 If it's just the word Zope: this can only be guilt by association.  Because a
1790 piece of software internally uses some package named ``zope.foo``, it doesn't
1791 turn the piece of software that uses it into "Zope".  There is a lot of
1792 *great* software written that has the word Zope in its name.  Zope is not
1793 some sort of monolithic thing, and a lot of its software is usable
1794 externally.  And while it's not really the job of this document to defend it,
1795 Zope has been around for over 10 years and has an incredibly large, active
1796 community.  If you don't believe this,
1797 http://taichino.appspot.com/pypi_ranking/authors is an eye-opening reality
1798 check.
1799
1800 Love Simplicity
1801 +++++++++++++++
1802
1803 Years of effort have gone into honing this package and its documentation to
1804 make it as simple as humanly possible for developers to use.  Everything is a
1805 tradeoff, of course, and people have their own ideas about what "simple" is.
1806 You may have a style difference if you believe Pyramid is complex.  Its
1807 developers obviously disagree.
1808
fa2e24 1809 Other Challenges
CM 1810 ----------------
fbfea7 1811
809744 1812 Other challenges are encouraged to be sent to the `Pylons-devel
CM 1813 <http://groups.google.com/group/pylons-devel>`_ maillist.  We'll try to address
1814 them by considering a design change, or at very least via exposition here.