Hello community, here is the log from the commit of package python-pecan for openSUSE:Factory checked in at 2013-03-08 09:47:04 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pecan (Old) and /work/SRC/openSUSE:Factory/.python-pecan.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pecan", Maintainer is "" Changes: -------- --- /work/SRC/openSUSE:Factory/python-pecan/python-pecan.changes 2013-01-21 17:45:34.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.python-pecan.new/python-pecan.changes 2013-03-08 09:47:05.000000000 +0100 @@ -1,0 +2,6 @@ +Fri Feb 22 13:11:11 UTC 2013 - [email protected] + +- Update to version 0.2.1: + + Upstream provides no changelog + +------------------------------------------------------------------- Old: ---- pecan-0.2.0b2.tar.gz New: ---- pecan-0.2.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pecan.spec ++++++ --- /var/tmp/diff_new_pack.YF9JZY/_old 2013-03-08 09:47:07.000000000 +0100 +++ /var/tmp/diff_new_pack.YF9JZY/_new 2013-03-08 09:47:07.000000000 +0100 @@ -13,32 +13,35 @@ # published by the Open Source Initiative. # Please submit bugfixes or comments via http://bugs.opensuse.org/ +# Name: python-pecan -Version: 0.2.0b2 +Version: 0.2.1 Release: 0 -License: BSD-3-Clause Summary: A WSGI object-dispatching web framework, designed to be lean and fast -Url: http://github.com/dreamhost/pecan +License: BSD-3-Clause Group: Development/Languages/Python +Url: http://github.com/dreamhost/pecan Source: http://pypi.python.org/packages/source/p/pecan/pecan-%{version}.tar.gz BuildRequires: python-devel BuildRequires: python-distribute # Test requirements: -#BuildRequires: python-simplegeneric >= 0.8 #BuildRequires: python-Genshi #BuildRequires: python-Jinja2 #BuildRequires: python-Mako >= 0.4.0 #BuildRequires: python-WebOb >= 1.2dev #BuildRequires: python-WebTest >= 1.3.1 +#BuildRequires: python-gunicorn +#BuildRequires: python-simplegeneric >= 0.8 #BuildRequires: python-virtualenv -Requires: python-simplegeneric >= 0.8 Requires: python-Mako >= 0.4.0 Requires: python-WebOb >= 1.2dev Requires: python-WebTest >= 1.3.1 +Requires: python-simplegeneric >= 0.8 Suggests: python-Jinja2 Suggests: python-Genshi +Suggests: python-gunicorn BuildRoot: %{_tmppath}/%{name}-%{version}-build %if 0%{?suse_version} && 0%{?suse_version} <= 1110 %{!?python_sitelib: %global python_sitelib %(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} @@ -51,9 +54,7 @@ %prep %setup -q -n pecan-%{version} -# Fix wrong test requirement, see https://github.com/dreamhost/pecan/pull/166 -sed -i "s|Jinja|Jinja2|" setup.py -# Let's not depend on Kajiki, a Genshi clone. Genshi should be enough +# Let's not depend on Kajiki, a Genshi clone. Genshi should be enough: sed -i "/'Kajiki',/d" setup.py %build @@ -68,6 +69,7 @@ %files %defattr(-,root,root,-) %{_bindir}/pecan +%{_bindir}/gunicorn_pecan %{python_sitelib}/* %changelog ++++++ pecan-0.2.0b2.tar.gz -> pecan-0.2.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/LICENSE new/pecan-0.2.1/LICENSE --- old/pecan-0.2.0b2/LICENSE 1970-01-01 01:00:00.000000000 +0100 +++ new/pecan-0.2.1/LICENSE 2012-03-31 03:13:50.000000000 +0200 @@ -0,0 +1,24 @@ +Copyright (c) <2011>, Jonathan LaCour +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the <organization> nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/MANIFEST.in new/pecan-0.2.1/MANIFEST.in --- old/pecan-0.2.0b2/MANIFEST.in 2012-12-07 18:01:32.000000000 +0100 +++ new/pecan-0.2.1/MANIFEST.in 2013-02-08 21:14:48.000000000 +0100 @@ -1,3 +1,4 @@ recursive-include pecan/scaffolds/base * include pecan/scaffolds/base/* include pecan/middleware/resources/* +include LICENSE README.rst requirements.txt diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/PKG-INFO new/pecan-0.2.1/PKG-INFO --- old/pecan-0.2.0b2/PKG-INFO 2012-12-07 18:04:47.000000000 +0100 +++ new/pecan-0.2.1/PKG-INFO 2013-02-08 21:24:20.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: pecan -Version: 0.2.0b2 +Version: 0.2.1 Summary: A WSGI object-dispatching web framework, designed to be lean and fast, with few dependancies. Home-page: http://github.com/dreamhost/pecan Author: Jonathan LaCour diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/README.rst new/pecan-0.2.1/README.rst --- old/pecan-0.2.0b2/README.rst 1970-01-01 01:00:00.000000000 +0100 +++ new/pecan-0.2.1/README.rst 2013-01-18 21:54:46.000000000 +0100 @@ -0,0 +1,50 @@ +Pecan +===== + +A WSGI object-dispatching web framework, designed to be lean and fast with few +dependencies. + +.. _travis: http://travis-ci.org/dreamhost/pecan +.. |travis| image:: https://secure.travis-ci.org/dreamhost/pecan.png + +|travis|_ + +Installing +---------- + +:: + + $ pip install pecan + +...or, for the latest (unstable) tip:: + + $ git clone https://github.com/dreamhost/pecan.git -b next + $ cd pecan && python setup.py install + +Running Tests +------------- + +:: + + $ python setup.py test + +...or, to run all tests across all supported environments:: + + $ pip install tox && tox + +Viewing Documentation +--------------------- +`Available online <http://pecan.readthedocs.org>`_, or to build manually:: + + $ cd docs && make html + $ open docs/build/html/index.html + +...or:: + + $ cd docs && make man + $ man docs/build/man/pecan.1 + +Additional Help/Support +----------------------- +Most Pecan interaction is done via the #pecanpy channel on `FreeNode +<http://freenode.net/>`_ IRC. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan/__init__.py new/pecan-0.2.1/pecan/__init__.py --- old/pecan-0.2.0b2/pecan/__init__.py 2012-12-07 18:01:29.000000000 +0100 +++ new/pecan-0.2.1/pecan/__init__.py 2013-01-18 21:54:46.000000000 +0100 @@ -15,7 +15,7 @@ try: from logging.config import dictConfig as load_logging_config except ImportError: - from .compat.dictconfig import dictConfig as load_logging_config + from .compat.dictconfig import dictConfig as load_logging_config # noqa __all__ = [ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan/commands/__init__.py new/pecan-0.2.1/pecan/commands/__init__.py --- old/pecan-0.2.0b2/pecan/commands/__init__.py 2012-12-07 18:01:29.000000000 +0100 +++ new/pecan-0.2.1/pecan/commands/__init__.py 2013-01-18 21:54:46.000000000 +0100 @@ -1,4 +1,4 @@ -from base import CommandRunner, BaseCommand -from serve import ServeCommand -from shell import ShellCommand -from create import CreateCommand +from base import CommandRunner, BaseCommand # noqa +from serve import ServeCommand # noqa +from shell import ShellCommand # noqa +from create import CreateCommand # noqa diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan/commands/base.py new/pecan-0.2.1/pecan/commands/base.py --- old/pecan-0.2.0b2/pecan/commands/base.py 2012-12-07 18:01:29.000000000 +0100 +++ new/pecan-0.2.1/pecan/commands/base.py 2013-01-18 21:54:46.000000000 +0100 @@ -94,14 +94,7 @@ @property def version(self): - try: - dist = pkg_resources.get_distribution('Pecan') - if os.path.dirname(os.path.dirname(__file__)) == dist.location: - return dist.version # pragma: nocover - else: - return '(development)' - except: # pragma: nocover - return '(development)' + return pkg_resources.get_distribution('pecan').version @property def commands(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan/commands/serve.py new/pecan-0.2.1/pecan/commands/serve.py --- old/pecan-0.2.0b2/pecan/commands/serve.py 2012-12-07 18:01:29.000000000 +0100 +++ new/pecan-0.2.1/pecan/commands/serve.py 2013-01-18 21:54:46.000000000 +0100 @@ -132,3 +132,49 @@ print(' $ pip install watchdog') else: self._serve(app, conf) + + +def gunicorn_run(): + """ + The ``gunicorn_pecan`` command for launching ``pecan`` applications + """ + try: + from gunicorn.app.wsgiapp import WSGIApplication + except ImportError as exc: + args = exc.args + arg0 = args[0] if args else '' + arg0 += ' (are you sure `gunicorn` is installed?)' + exc.args = (arg0,) + args[1:] + raise + + class PecanApplication(WSGIApplication): + + def init(self, parser, opts, args): + if len(args) != 1: + parser.error("No configuration file was specified.") + + self.cfgfname = os.path.normpath( + os.path.join(os.getcwd(), args[0]) + ) + self.cfgfname = os.path.abspath(self.cfgfname) + if not os.path.exists(self.cfgfname): + parser.error("Config file not found: %s" % self.cfgfname) + + from pecan.configuration import _runtime_conf, set_config + set_config(self.cfgfname, overwrite=True) + + # If available, use the host and port from the pecan config file + cfg = {} + if _runtime_conf.get('server'): + server = _runtime_conf['server'] + if hasattr(server, 'host') and hasattr(server, 'port'): + cfg['bind'] = '%s:%s' % ( + server.host, server.port + ) + return cfg + + def load(self): + from pecan.deploy import deploy + return deploy(self.cfgfname) + + PecanApplication("%(prog)s [OPTIONS] config.py").run() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan/core.py new/pecan-0.2.1/pecan/core.py --- old/pecan-0.2.0b2/pecan/core.py 2012-12-07 18:01:29.000000000 +0100 +++ new/pecan-0.2.1/pecan/core.py 2013-02-08 21:14:48.000000000 +0100 @@ -1,5 +1,4 @@ import urllib -import sys try: from simplejson import loads except ImportError: # pragma: no cover @@ -39,6 +38,11 @@ def __delattr__(self, attr): obj = getattr(state, key) return delattr(obj, attr) + + def __dir__(self): + obj = getattr(state, key) + return dir(obj) + return ObjectProxy() @@ -178,11 +182,15 @@ namespace automatically. :param force_canonical: A boolean indicating if this project should require canonical URLs. + :param guess_content_type_from_ext: A boolean indicating if this project + should use the extension in the URL for guessing + the content type to return. ''' def __init__(self, root, default_renderer='mako', template_path='templates', hooks=[], custom_renderers={}, - extra_template_vars={}, force_canonical=True): + extra_template_vars={}, force_canonical=True, + guess_content_type_from_ext=True): if isinstance(root, basestring): root = self.__translate_root__(root) @@ -193,6 +201,7 @@ self.hooks = hooks self.template_path = template_path self.force_canonical = force_canonical + self.guess_content_type_from_ext = guess_content_type_from_ext def __translate_root__(self, item): ''' @@ -308,7 +317,7 @@ valid_args = valid_args[len(args):] # handle wildcard arguments - if remainder: + if filter(None, remainder): if not argspec[1]: abort(404) args.extend(remainder) @@ -359,8 +368,9 @@ # get a sorted list of hooks, by priority (no controller hooks yet) state.hooks = self.determine_hooks() - # store the routing path to allow hooks to modify it - request.pecan['routing_path'] = request.path + # store the routing path for the current application to allow hooks to + # modify it + request.pecan['routing_path'] = request.path_info # handle "on_route" hooks self.handle_hooks('on_route', state) @@ -368,13 +378,21 @@ # lookup the controller, respecting content-type as requested # by the file extension on the URI path = request.pecan['routing_path'] + request.pecan['extension'] = None # attempt to guess the content type based on the file extension - if not request.pecan['content_type'] and '.' in path.split('/')[-1]: - path, extension = splitext(path) - request.pecan['extension'] = extension + if self.guess_content_type_from_ext \ + and not request.pecan['content_type'] \ + and '.' in path.split('/')[-1]: + new_path, extension = splitext(path) + # preface with a letter to ensure compat for 2.5 - request.pecan['content_type'] = guess_type('x' + extension)[0] + potential_type = guess_type('x' + extension)[0] + + if potential_type is not None: + path = new_path + request.pecan['extension'] = extension + request.pecan['content_type'] = potential_type controller, remainder = self.route(self.root, path) cfg = _cfg(controller) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan/decorators.py new/pecan-0.2.1/pecan/decorators.py --- old/pecan-0.2.0b2/pecan/decorators.py 2012-12-07 18:01:29.000000000 +0100 +++ new/pecan-0.2.1/pecan/decorators.py 2013-01-18 21:54:46.000000000 +0100 @@ -117,7 +117,7 @@ :param action: The callable to call after the commit is successfully issued. ''' - return after_action('commit', action) + return after_action('commit', action) def after_rollback(action): @@ -129,7 +129,7 @@ :param action: The callable to call after the rollback is successfully issued. ''' - return after_action('rollback', action) + return after_action('rollback', action) def accept_noncanonical(func): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan/jsonify.py new/pecan-0.2.1/pecan/jsonify.py --- old/pecan-0.2.0b2/pecan/jsonify.py 2012-12-07 18:01:29.000000000 +0100 +++ new/pecan-0.2.1/pecan/jsonify.py 2013-01-18 21:54:46.000000000 +0100 @@ -23,10 +23,10 @@ except ImportError: # pragma no cover # dummy classes since we don't have SQLAlchemy installed - class ResultProxy: + class ResultProxy: # noqa pass - class RowProxy: + class RowProxy: # noqa pass diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan/scaffolds/base/+package+/app.py_tmpl new/pecan-0.2.1/pecan/scaffolds/base/+package+/app.py_tmpl --- old/pecan-0.2.0b2/pecan/scaffolds/base/+package+/app.py_tmpl 2012-12-07 18:01:29.000000000 +0100 +++ new/pecan-0.2.1/pecan/scaffolds/base/+package+/app.py_tmpl 2013-01-18 21:54:46.000000000 +0100 @@ -1,15 +1,20 @@ from pecan import make_app from ${package} import model + def setup_app(config): - + model.init_model() - + return make_app( config.app.root, - static_root = config.app.static_root, - template_path = config.app.template_path, - logging = getattr(config, 'logging', {}), - debug = getattr(config.app, 'debug', False), - force_canonical = getattr(config.app, 'force_canonical', True) + static_root=config.app.static_root, + template_path=config.app.template_path, + logging=getattr(config, 'logging', {}), + debug=getattr(config.app, 'debug', False), + force_canonical=getattr(config.app, 'force_canonical', True), + guess_content_type_from_ext=getattr( + config.app, + 'guess_content_type_from_ext', + True), ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan/scaffolds/base/+package+/templates/error.html new/pecan-0.2.1/pecan/scaffolds/base/+package+/templates/error.html --- old/pecan-0.2.0b2/pecan/scaffolds/base/+package+/templates/error.html 2012-12-07 18:01:29.000000000 +0100 +++ new/pecan-0.2.1/pecan/scaffolds/base/+package+/templates/error.html 2013-01-18 21:54:46.000000000 +0100 @@ -7,6 +7,6 @@ ## now define the body of the template <header> - <h1>Server Error ${status}</h1> + <h1>Server Error ${status}</h1> </header> <p>${message}</p> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan/scaffolds/base/+package+/templates/index.html new/pecan-0.2.1/pecan/scaffolds/base/+package+/templates/index.html --- old/pecan-0.2.0b2/pecan/scaffolds/base/+package+/templates/index.html 2012-12-07 18:01:29.000000000 +0100 +++ new/pecan-0.2.1/pecan/scaffolds/base/+package+/templates/index.html 2013-01-18 21:54:46.000000000 +0100 @@ -7,28 +7,28 @@ ## now define the body of the template <header> - <h1><img src="/images/logo.png" /></h1> + <h1><img src="/images/logo.png" /></h1> </header> <div id="content"> - <p>This is a sample Pecan project.</p> + <p>This is a sample Pecan project.</p> - <p> - Instructions for getting started can be found online at <a - href="http://pecanpy.org" target="window">pecanpy.org</a> - </p> - - <p> - ...or you can search the documentation here: - </p> - - <form method="POST" action="/"> - <fieldset> - <input name="q" /> - <input type="submit" value="Search" /> - <fieldset> - <small>Enter search terms or a module, class or function name.</small> - </form> + <p> + Instructions for getting started can be found online at <a + href="http://pecanpy.org" target="window">pecanpy.org</a> + </p> + + <p> + ...or you can search the documentation here: + </p> + + <form method="POST" action="/"> + <fieldset> + <input name="q" /> + <input type="submit" value="Search" /> + <fieldset> + <small>Enter search terms or a module, class or function name.</small> + </form> </div> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan/scaffolds/base/+package+/templates/layout.html new/pecan-0.2.1/pecan/scaffolds/base/+package+/templates/layout.html --- old/pecan-0.2.0b2/pecan/scaffolds/base/+package+/templates/layout.html 2012-12-07 18:01:29.000000000 +0100 +++ new/pecan-0.2.1/pecan/scaffolds/base/+package+/templates/layout.html 2013-01-18 21:54:46.000000000 +0100 @@ -1,12 +1,12 @@ <html> - <head> - <title>${self.title()}</title> - ${self.style()} - ${self.javascript()} - </head> - <body> - ${self.body()} - </body> + <head> + <title>${self.title()}</title> + ${self.style()} + ${self.javascript()} + </head> + <body> + ${self.body()} + </body> </html> <%def name="title()"> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan/scaffolds/base/+package+/tests/__init__.py_tmpl new/pecan-0.2.1/pecan/scaffolds/base/+package+/tests/__init__.py_tmpl --- old/pecan-0.2.0b2/pecan/scaffolds/base/+package+/tests/__init__.py_tmpl 2012-12-07 18:01:29.000000000 +0100 +++ new/pecan-0.2.1/pecan/scaffolds/base/+package+/tests/__init__.py_tmpl 2013-01-18 21:54:46.000000000 +0100 @@ -11,7 +11,7 @@ Used for functional tests where you need to test your literal application and its integration with the framework. """ - + def setUp(self): self.app = load_test_app(os.path.join( os.path.dirname(__file__), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan/scaffolds/base/+package+/tests/config.py_tmpl new/pecan-0.2.1/pecan/scaffolds/base/+package+/tests/config.py_tmpl --- old/pecan-0.2.0b2/pecan/scaffolds/base/+package+/tests/config.py_tmpl 2012-12-07 18:01:29.000000000 +0100 +++ new/pecan-0.2.1/pecan/scaffolds/base/+package+/tests/config.py_tmpl 2013-01-18 21:54:46.000000000 +0100 @@ -1,25 +1,25 @@ # Server Specific Configurations server = { - 'port' : '8080', - 'host' : '0.0.0.0' + 'port': '8080', + 'host': '0.0.0.0' } # Pecan Application Configurations app = { - 'root' : '${package}.controllers.root.RootController', - 'modules' : ['${package}'], - 'static_root' : '%(confdir)s/../../public', - 'template_path' : '%(confdir)s/../templates', - 'debug' : True, - 'errors' : { - '404' : '/error/404', - '__force_dict__' : True + 'root': '${package}.controllers.root.RootController', + 'modules': ['${package}'], + 'static_root': '%(confdir)s/../../public', + 'template_path': '%(confdir)s/../templates', + 'debug': True, + 'errors': { + '404': '/error/404', + '__force_dict__': True } } # Custom Configurations must be in Python dictionary format:: # # foo = {'bar':'baz'} -# +# # All configurations are accessible at:: # pecan.conf diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan/scaffolds/base/+package+/tests/test_functional.py_tmpl new/pecan-0.2.1/pecan/scaffolds/base/+package+/tests/test_functional.py_tmpl --- old/pecan-0.2.0b2/pecan/scaffolds/base/+package+/tests/test_functional.py_tmpl 2012-12-07 18:01:29.000000000 +0100 +++ new/pecan-0.2.1/pecan/scaffolds/base/+package+/tests/test_functional.py_tmpl 2013-01-18 21:54:46.000000000 +0100 @@ -4,16 +4,19 @@ class TestRootController(FunctionalTest): - + def test_get(self): response = self.app.get('/') assert response.status_int == 200 def test_search(self): - response = self.app.post('/', params={'q' : 'RestController'}) + response = self.app.post('/', params={'q': 'RestController'}) assert response.status_int == 302 - assert response.headers['Location'] == 'http://pecan.readthedocs.org/en/latest/search.html?q=RestController' - + assert response.headers['Location'] == ( + 'http://pecan.readthedocs.org/en/latest/search.html' + '?q=RestController' + ) + def test_get_not_found(self): response = self.app.get('/a/bogus/url', expect_errors=True) assert response.status_int == 404 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan/scaffolds/base/config.py_tmpl new/pecan-0.2.1/pecan/scaffolds/base/config.py_tmpl --- old/pecan-0.2.0b2/pecan/scaffolds/base/config.py_tmpl 2012-12-07 18:01:29.000000000 +0100 +++ new/pecan-0.2.1/pecan/scaffolds/base/config.py_tmpl 2013-01-18 21:54:46.000000000 +0100 @@ -8,7 +8,7 @@ app = { 'root': '${package}.controllers.root.RootController', 'modules': ['${package}'], - 'static_root': '%(confdir)s/public', + 'static_root': '%(confdir)s/public', 'template_path': '%(confdir)s/${package}/templates', 'debug': True, 'errors': { @@ -19,7 +19,7 @@ logging = { 'loggers': { - 'root' : {'level': 'INFO', 'handlers': ['console']}, + 'root': {'level': 'INFO', 'handlers': ['console']}, '${package}': {'level': 'DEBUG', 'handlers': ['console']} }, 'handlers': { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan/scaffolds/base/setup.py_tmpl new/pecan-0.2.1/pecan/scaffolds/base/setup.py_tmpl --- old/pecan-0.2.0b2/pecan/scaffolds/base/setup.py_tmpl 2012-12-07 18:01:29.000000000 +0100 +++ new/pecan-0.2.1/pecan/scaffolds/base/setup.py_tmpl 2013-01-18 21:54:46.000000000 +0100 @@ -7,16 +7,16 @@ from setuptools import setup, find_packages setup( - name = '${package}', - version = '0.1', - description = '', - author = '', - author_email = '', - install_requires = [ + name='${package}', + version='0.1', + description='', + author='', + author_email='', + install_requires=[ "pecan", ], - test_suite = '${package}', - zip_safe = False, - include_package_data = True, - packages = find_packages(exclude=['ez_setup']) + test_suite='${package}', + zip_safe=False, + include_package_data=True, + packages=find_packages(exclude=['ez_setup']) ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan/tests/test_base.py new/pecan-0.2.1/pecan/tests/test_base.py --- old/pecan-0.2.0b2/pecan/tests/test_base.py 2012-12-07 18:01:29.000000000 +0100 +++ new/pecan-0.2.1/pecan/tests/test_base.py 2013-02-08 21:14:48.000000000 +0100 @@ -725,6 +725,22 @@ assert r.status_int == 401 +class TestSriptName(unittest.TestCase): + + def setUp(self): + self.environ = {'SCRIPT_NAME': '/foo'} + + def test_handle_script_name(self): + class RootController(object): + @expose() + def index(self): + return 'Root Index' + + app = TestApp(Pecan(RootController()), extra_environ=self.environ) + r = app.get('/foo/') + assert r.status_int == 200 + + class TestRedirect(unittest.TestCase): @property @@ -863,7 +879,11 @@ class RootController(object): @expose(content_type=None) def _default(self, *args): - return request.pecan['extension'] + ext = request.pecan['extension'] + assert len(args) == 1 + if ext: + assert ext not in args[0] + return ext or '' return TestApp(Pecan(RootController())) @@ -883,7 +903,7 @@ assert r.body == '' def test_multi_dot_extension(self): - r = self.app_.get('/gradient.js.js') + r = self.app_.get('/gradient.min.js') assert r.status_int == 200 assert r.body == '.js' @@ -907,6 +927,35 @@ r = app.get('/index.txt', expect_errors=True) assert r.status_int == 404 + def test_unknown_file_extension(self): + class RootController(object): + @expose(content_type=None) + def _default(self, *args): + assert 'example:x.tiny' in args + assert request.pecan['extension'] is None + return 'SOME VALUE' + + app = TestApp(Pecan(RootController())) + + r = app.get('/example:x.tiny') + assert r.status_int == 200 + assert r.body == 'SOME VALUE' + + def test_guessing_disabled(self): + class RootController(object): + @expose(content_type=None) + def _default(self, *args): + assert 'index.html' in args + assert request.pecan['extension'] is None + return 'SOME VALUE' + + app = TestApp(Pecan(RootController(), + guess_content_type_from_ext=False)) + + r = app.get('/index.html') + assert r.status_int == 200 + assert r.body == 'SOME VALUE' + class TestContentTypeByAcceptHeaders(unittest.TestCase): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan/tests/test_hooks.py new/pecan-0.2.1/pecan/tests/test_hooks.py --- old/pecan-0.2.0b2/pecan/tests/test_hooks.py 2012-12-07 18:01:29.000000000 +0100 +++ new/pecan-0.2.1/pecan/tests/test_hooks.py 2013-01-18 21:54:46.000000000 +0100 @@ -1082,7 +1082,7 @@ RootController(), hooks=[ RequestViewerHook( - config={'items':['path']}, writer=_stdout + config={'items': ['path']}, writer=_stdout ) ] ) @@ -1117,7 +1117,7 @@ RootController(), hooks=[ RequestViewerHook( - config={'blacklist':['/']}, writer=_stdout + config={'blacklist': ['/']}, writer=_stdout ) ] ) @@ -1144,7 +1144,7 @@ RootController(), hooks=[ RequestViewerHook( - config={'items':['date']}, writer=_stdout + config={'items': ['date']}, writer=_stdout ) ] ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan/tests/test_rest.py new/pecan-0.2.1/pecan/tests/test_rest.py --- old/pecan-0.2.0b2/pecan/tests/test_rest.py 2012-12-07 18:01:29.000000000 +0100 +++ new/pecan-0.2.1/pecan/tests/test_rest.py 2013-01-18 21:54:46.000000000 +0100 @@ -863,3 +863,28 @@ r = app.get('/foos/bars/bazs/final/named') assert r.status_int == 200 assert r.body == 'NAMED' + + def test_post_with_kwargs_only(self): + + class RootController(RestController): + + @expose() + def get_all(self): + return 'INDEX' + + @expose('json') + def post(self, **kw): + return kw + + # create the app + app = TestApp(make_app(RootController())) + + r = app.get('/') + assert r.status_int == 200 + assert r.body == 'INDEX' + + kwargs = {'foo': 'bar', 'spam': 'eggs'} + r = app.post('/', kwargs) + assert r.status_int == 200 + assert r.namespace['foo'] == 'bar' + assert r.namespace['spam'] == 'eggs' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan/tests/test_scaffolds.py new/pecan-0.2.1/pecan/tests/test_scaffolds.py --- old/pecan-0.2.0b2/pecan/tests/test_scaffolds.py 2012-12-07 18:01:29.000000000 +0100 +++ new/pecan-0.2.1/pecan/tests/test_scaffolds.py 2013-01-18 21:54:46.000000000 +0100 @@ -182,13 +182,13 @@ def setUp(self): # Make a temp install location and record the cwd - self.install() + self.install_scaffolded_package() def tearDown(self): shutil.rmtree(self.install_dir) os.chdir(self.cwd) - def install(self): + def create_virtualenv(self): # Create a new virtualenv in the temp install location import virtualenv virtualenv.create_environment( @@ -198,6 +198,8 @@ # chdir into the pecan source os.chdir(pkg_resources.get_distribution('pecan').location) + def install_scaffolded_package(self): + self.create_virtualenv() py_exe = os.path.join(self.install_dir, 'bin', 'python') pecan_exe = os.path.join(self.install_dir, 'bin', 'pecan') @@ -219,6 +221,22 @@ 'develop' ]) + def install_dependency(self, name): + pip_exe = os.path.join(self.install_dir, 'bin', 'pip') + proc = subprocess.Popen([ + pip_exe, + 'install', + '-U', + name + ]) + proc.wait() + + return os.path.join( + self.install_dir, + 'bin', + name + ) + def poll(self, proc): limit = 30 for i in range(limit): @@ -228,7 +246,7 @@ if proc.returncode is None: break elif i == limit: # pragma: no cover - raise RuntimeError("pecan serve config.py didn't start.") + raise RuntimeError("Server process didn't start.") time.sleep(.1) @unittest.skipUnless(has_internet(), 'Internet connectivity unavailable.') @@ -322,3 +340,96 @@ proc.wait() assert proc.stderr.read().splitlines()[-1].strip() == 'OK' + + @unittest.skipUnless(has_internet(), 'Internet connectivity unavailable.') + @unittest.skipUnless( + getattr(pecan, '__run_all_tests__', False) is True, + 'Skipping (slow). To run, `$ python setup.py test --functional.`' + ) + def test_project_passes_pep8(self): + # Install pep8 + pep8_exe = self.install_dependency('pep8') + + # Run pep8 on setup.py and the project + proc = subprocess.Popen([ + pep8_exe, + 'setup.py', + 'testing123' + ], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE + ) + proc.wait() + + # No output == good + output = proc.stdout.read() + assert output == '' + + +class TestGunicornServeCommand(TestTemplateBuilds): + + def create_virtualenv(self): + super(TestGunicornServeCommand, self).create_virtualenv() + + # Install gunicorn + self.install_dependency('gunicorn') + + @property + def gunicorn_exe(self): + return os.path.join( + self.install_dir, + 'bin', + 'gunicorn_pecan' + ) + + def poll_gunicorn(self, proc, port): + try: + self.poll(proc) + retries = 30 + while True: + retries -= 1 + if retries < 0: # pragma: nocover + raise RuntimeError( + "The gunicorn server has not replied within 3 seconds." + ) + try: + # ...and that it's serving (valid) content... + resp = urllib2.urlopen('http://localhost:%d/' % port) + assert resp.getcode() == 200 + assert 'This is a sample Pecan project.' in resp.read() + except urllib2.URLError: + pass + else: + break + time.sleep(.1) + finally: + proc.terminate() + + @unittest.skipUnless(has_internet(), 'Internet connectivity unavailable.') + @unittest.skipUnless( + getattr(pecan, '__run_all_tests__', False) is True, + 'Skipping (slow). To run, `$ python setup.py test --functional.`' + ) + def test_serve_from_config(self): + # Start the server + proc = subprocess.Popen([ + self.gunicorn_exe, + 'config.py' + ]) + + self.poll_gunicorn(proc, 8080) + + @unittest.skipUnless(has_internet(), 'Internet connectivity unavailable.') + @unittest.skipUnless( + getattr(pecan, '__run_all_tests__', False) is True, + 'Skipping (slow). To run, `$ python setup.py test --functional.`' + ) + def test_serve_with_custom_bind(self): + # Start the server + proc = subprocess.Popen([ + self.gunicorn_exe, + '--bind=0.0.0.0:9191', + 'config.py' + ]) + + self.poll_gunicorn(proc, 9191) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan.egg-info/PKG-INFO new/pecan-0.2.1/pecan.egg-info/PKG-INFO --- old/pecan-0.2.0b2/pecan.egg-info/PKG-INFO 2012-12-07 18:04:47.000000000 +0100 +++ new/pecan-0.2.1/pecan.egg-info/PKG-INFO 2013-02-08 21:24:20.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: pecan -Version: 0.2.0b2 +Version: 0.2.1 Summary: A WSGI object-dispatching web framework, designed to be lean and fast, with few dependancies. Home-page: http://github.com/dreamhost/pecan Author: Jonathan LaCour diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan.egg-info/SOURCES.txt new/pecan-0.2.1/pecan.egg-info/SOURCES.txt --- old/pecan-0.2.0b2/pecan.egg-info/SOURCES.txt 2012-12-07 18:04:47.000000000 +0100 +++ new/pecan-0.2.1/pecan.egg-info/SOURCES.txt 2013-02-08 21:24:20.000000000 +0100 @@ -1,4 +1,7 @@ +LICENSE MANIFEST.in +README.rst +requirements.txt setup.cfg setup.py bin/pecan diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/pecan.egg-info/entry_points.txt new/pecan-0.2.1/pecan.egg-info/entry_points.txt --- old/pecan-0.2.0b2/pecan.egg-info/entry_points.txt 2012-12-07 18:04:47.000000000 +0100 +++ new/pecan-0.2.1/pecan.egg-info/entry_points.txt 2013-02-08 21:24:20.000000000 +0100 @@ -7,4 +7,5 @@ base = pecan.scaffolds:BaseScaffold [console_scripts] pecan = pecan.commands:CommandRunner.handle_command_line + gunicorn_pecan = pecan.commands.serve:gunicorn_run \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/requirements.txt new/pecan-0.2.1/requirements.txt --- old/pecan-0.2.0b2/requirements.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/pecan-0.2.1/requirements.txt 2012-03-31 03:13:50.000000000 +0200 @@ -0,0 +1,6 @@ +Mako==0.6.2 +MarkupSafe==0.15 +WebOb==1.2b3 +WebTest==1.3.3 +simplegeneric==0.8 +wsgiref==0.1.2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pecan-0.2.0b2/setup.py new/pecan-0.2.1/setup.py --- old/pecan-0.2.0b2/setup.py 2012-12-07 18:01:32.000000000 +0100 +++ new/pecan-0.2.1/setup.py 2013-02-08 21:14:48.000000000 +0100 @@ -2,7 +2,7 @@ from setuptools import setup, find_packages from setuptools.command.test import test as TestCommand -version = '0.2.0b2' +version = '0.2.1' # # determine requirements @@ -31,7 +31,8 @@ 'virtualenv', 'Genshi', 'Kajiki', - 'Jinja' + 'Jinja2', + 'gunicorn' ] if sys.version_info < (2, 7): tests_require += ['unittest2'] @@ -102,5 +103,6 @@ base = pecan.scaffolds:BaseScaffold [console_scripts] pecan = pecan.commands:CommandRunner.handle_command_line + gunicorn_pecan = pecan.commands.serve:gunicorn_run """ ) -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
