On Sat, 2010-12-11 at 23:49 +0300, Andrey Popp wrote:
> Hello,
> 
> 
> it's looking just great!
> 
> 
> How do you think, can this behavior be extracted into some pattern for
> imperative configuration? I would like to have this in my toolchain in
> addition to zope.configuration.

Not sure.. I haven't thought about how to generalize it.

> 
> -- 
> Andrey Popp
> 
> 
> On Thursday, December 9, 2010 at 11:19 AM, Chris McDonough wrote:
> 
> > Hi all,
> > 
> > I just merged a branch I've been working on for some time to the
> > Pyramid
> > master branch on Github. The branch was named "twophase", and its
> > goal
> > was to provide imperative configuration extensibility and two-phase
> > configuration much like that currently offered by ZCML.
> > 
> > As a result, the ``pyramid.configuration`` module has been
> > deprecated
> > and exists now only to support backwards compatibility. In its place
> > a
> > new ``pyramid.config`` module exists with fundamentally the same
> > API.
> > Paster template authors beware.
> > 
> > What does this change get us? Imperative extensibility was the
> > primary
> > goal (the ability to write "extensible" applications by including
> > configuration from other non-local sources). This was always a
> > feature
> > offered to us by ZCML, but now folks don't have to use ZCML to get
> > it.
> > 
> > Here's an example of using imperative configuration to include
> > configuration from a non-local source. If the ``configure`` function
> > below lives in a module named ``myapp.myconfig``:
> > 
> > # myapp.myconfig module
> > 
> > def my_view(request):
> > from pyramid.response import Response
> > return Response('OK')
> > 
> > def configure(config):
> > config.add__view(my_view)
> > 
> > You might cause it be included within your Pyramid application like
> > so:
> > 
> > from pyramid.config import Configurator
> > 
> > def main(global_config, **settings):
> > config = Configurator()
> > config.include('myapp.myconfig.configure')
> > return config.make_wsgi_app()
> > 
> > When application extensibility of this kind is used, often
> > configuration
> > conflicts are an issue. When you reuse some configuration from
> > another
> > module, it's more likely that the configuration in that module will
> > conflict with configuration statements you execute "locally" or
> > other
> > configuration statements executed as the result of including some
> > other
> > configuration. For this reason, *configuration conflict detection*
> > is
> > now a feature by default.
> > 
> > Included configuration statements will be overridden by local
> > configuration statements if an included callable causes a
> > configuration
> > conflict by registering something with the same configuration
> > parameters. So for instance, in the below, the local "add_view" call
> > will "win" even though both views are registered for the same thing:
> > 
> > from pyramid.config import Configurator
> > 
> > def someview(request):
> > from pyramid.response import Response
> > return Response('OK')
> > 
> > def main(global__config, **settings):
> > config = Configurator()
> > config.add_view(someview)
> > config.include('myapp.myconfig.configure')
> > return config.make_wsgi_app()
> > 
> > However, if two *included* configuration callables register the same
> > configuration parameters, a ConfigurationConflictError will now
> > occur.
> > For example:
> > 
> > # myapp.myconfig module
> > 
> > def my_view(request):
> > from pyramid.response import Response
> > return Response('OK')
> > 
> > def configure(config):
> > config.add_view(my_view)
> > 
> > # myapp.myconfig2 module
> > 
> > def my_view(request):
> > from pyramid.response import Response
> > return Response('OK')
> > 
> > def configure(config):
> > config.add_view(my_view)
> > 
> > # your application's __init__
> > 
> > from pyramid.config import Configurator
> > 
> > def main(global_config, **settings):
> > config = Configurator()
> > config.include('myapp.myconfig.configure')
> > config.include('myapp.myconfig2.configure')
> > return config.make__wsgi_app()
> > 
> > When ``make_wsgi_app`` is called, the configuration will be
> > "committed",
> > and a conflict will be detected, because both
> > myapp.myconfig.configure
> > and myapp.myconfig2.configure registered a view with the same
> > configuration parameters. To avoid a conflict, and make
> > "myapp.myconfig2.configure" "win", you can call "commit" between the
> > calls to "include":
> > 
> > # your application's __init__
> > 
> > from pyramid.config import Configurator
> > 
> > def main(global_config, **settings):
> > config = Configurator()
> > config.include('myapp.myconfig.configure')
> > config.commit()
> > config.include('myapp.myconfig2.configure')
> > return configg.make_wsgi_app()
> > 
> > Calling "commit" executes all pending configuration and clears the
> > configuration stack. It is safe to call commit() at any time.
> > "make_wsgi_app" calls commit on your behalf usually, but you can
> > issue
> > commits at any time.
> > 
> > A conflict error will now occur if you register two configuration
> > statements for the same set of arguments locally too:
> > 
> > from pyramid.config import Configurator
> > 
> > def someview(request):
> > from pyramid.response import Response
> > return Response('OK')
> > 
> > def someotherview(request):
> > from pyramid.response import Respponse
> > return Response('OK')
> > 
> > def main(global_config, **settings):
> > config = Configurator()
> > config.add_view(someview)
> > config.add_view(someotherview)
> > return config.make__wsgi_app()
> > 
> > Because both calls to "add_view" above are registered for the same
> > set
> > of circumstances, a ConfigurationConflictError will occur when
> > "make_wsgi_app" is run. To avoid this, use commit between those
> > calls:
> > 
> > from pyramid.config import Configurator
> > 
> > def someview(request):
> > from pyramid.response import Response
> > return Response(('OK')
> > 
> > def someotherview(request):
> > from pyramid.response import Response
> > return Response('OK')
> > 
> > def main(global_config, **settings):
> > config = Configurator()
> > config.add_view(someview)
> > config.commit()
> > config.add__view(someotherview)
> > return config.make_wsgi_app()
> > 
> > By default, the pyramid.config.Configurator behaves like this,
> > deferring
> > configuration actions until "commit" or "make_wsgi_app" is called.
> > If
> > you want the older behavior back (no conflicts, every configuration
> > method executes immediately, later configuration statements override
> > earlier ones), you can use an "autocommitting" configurator:
> > 
> > from pyramid.config import Configurator
> > 
> > def someview(request):
> > from pyramid.response import Response
> > return Response('OK')
> > 
> > def someotherview(request):
> > from pyramid.response import Response
> > return Response('OK')
> > 
> > def main(global__config, **settings):
> > config = Configurator(autocommit=True)
> > config.add_view(someview)
> > config.add_view(someotherview)
> > return config.make_wsgi_app()
> > 
> > The "someotherview" registered above will "win" in this
> > circumstance.
> > 
> > I've used "add_view" in all the examples above, but all methods of
> > the
> > configurator make use of this feature (add_route, add_handler,
> > set_session_factory, etc).
> > 
> > If you can imagine a future where folks factor reusable
> > configuration
> > into these configuration callables, and those callables are included
> > by
> > your application, you can imagine a future where applications can be
> > composed of other applications more cleanly than today. This isn't
> > exactly a "reusable application" story (reusable applications
> > require
> > more "rails" than just this can provide), but it does allow
> > configuration to live cleanly outside of the main() function, and
> > allows
> > for composability of multiple applications written by the same
> > person or
> > organization fairly cleanly without ZCML.
> > 
> > - C
> > 
> > 
> > -- 
> > You received this message because you are subscribed to the Google
> > Groups "pylons-devel" group.
> > To post to this group, send email to pylons-de...@googlegroups.com.
> > To unsubscribe from this group, send email to pylons-devel
> > +unsubscr...@googlegroups.com.
> > For more options, visit this group at
> > http://groups.google.com/group/pylons-devel?hl=en.
> > 
> 
> 
> 
> -- 
> You received this message because you are subscribed to the Google
> Groups "pylons-devel" group.
> To post to this group, send email to pylons-de...@googlegroups.com.
> To unsubscribe from this group, send email to pylons-devel
> +unsubscr...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/pylons-devel?hl=en.


-- 
You received this message because you are subscribed to the Google Groups 
"pylons-devel" group.
To post to this group, send email to pylons-de...@googlegroups.com.
To unsubscribe from this group, send email to 
pylons-devel+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/pylons-devel?hl=en.

Reply via email to