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]

Reply via email to