Pylons-1.0.2/0000755000175000017500000000000012553621453012336 5ustar benben00000000000000Pylons-1.0.2/setup.py0000644000175000017500000001101512456613642014051 0ustar benben00000000000000import sys try: from setuptools import setup, find_packages except ImportError: from ez_setup import use_setuptools use_setuptools() from setuptools import setup, find_packages version = '1.0.2' tests_require = ['nose', 'Jinja2>=2.2.1'] if not sys.platform.startswith('java'): tests_require.extend(['Genshi', 'coverage>=2.85']) setup( name="Pylons", version=version, description='Pylons Web Framework', long_description=""" Pylons ====== The Pylons web framework is designed for building web applications and sites in an easy and concise manner. They can range from as small as a single Python module, to a substantial directory layout for larger and more complex web applications. Pylons comes with project templates that help boot-strap a new web application project, or you can start from scratch and set things up exactly as desired. Example `Hello World` --------------------- .. from paste.httpserver import serve from pylons import Configurator, Response class Hello(object): def __init__(self, request): self.request = request def index(self): return Response(body="Hello World!") if __name__ == '__main__': config = Configurator() config.begin() config.add_handler('home', '/', handler=Hello, action='index') config.end() serve(config.make_wsgi_app(), host='0.0.0.0') Core Features ------------- * A framework to make writing web applications in Python easy * Utilizes a minimalist, component-based philosophy that makes it easy to expand on * Harness existing knowledge about Python * Extensible application design * Fast and efficient, an incredibly small per-request call-stack providing top performance * Uses existing and well tested Python packages Current Status -------------- Pylons 1.0 series is stable and production ready. The Pylons Project now maintains the Pyramid web framework for future development. Pylons 1.0 users should strongly consider using it for their next project. Download and Installation ------------------------- Pylons can be installed with `Easy Install `_ by typing:: > easy_install Pylons Dependant packages are automatically installed from the `Pylons download page `_ . Development Version ------------------- Pylons development uses the Mercuial distributed version control system (DVCS) with BitBucket hosting the main repository here: `Pylons Bitbucket repository `_ """, keywords='web wsgi lightweight framework sqlalchemy formencode mako templates', license='BSD', author='Ben Bangert, Philip Jenvey, James Gardner', author_email='ben@groovie.org, pjenvey@underboss.org', url='http://www.pylonshq.com/', packages=find_packages(exclude=['ez_setup', 'tests', 'tests.*']), zip_safe=False, include_package_data=True, test_suite='nose.collector', tests_require=tests_require, install_requires=[ "Routes>=1.12.3", "WebHelpers>=0.6.4", "Beaker>=1.5.4", "Paste>=1.7.5.1", "PasteDeploy>=1.5.0", "PasteScript>=1.7.4.2", "FormEncode>=1.2.4", "simplejson>=2.2.1", "decorator>=3.3.2", "nose>=1.1.2", "Mako>=0.5.0", "WebError>=0.10.3", "WebTest>=1.3.1", "Tempita>=0.5.1", "MarkupSafe>=0.15", "WebOb>=1.1.1", ], classifiers=[ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Framework :: Pylons", "Programming Language :: Python", "Programming Language :: Python :: 2 :: Only", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Internet :: WWW/HTTP :: WSGI", "Topic :: Software Development :: Libraries :: Python Modules", ], extras_require={ 'genshi': ['Genshi>=0.6'], 'jinja2': ['Jinja2'], }, entry_points=""" [paste.paster_command] controller = pylons.commands:ControllerCommand restcontroller = pylons.commands:RestControllerCommand routes = pylons.commands:RoutesCommand shell = pylons.commands:ShellCommand [paste.paster_create_template] pylons = pylons.util:PylonsTemplate pylons_minimal = pylons.util:MinimalPylonsTemplate [paste.filter_factory] debugger = pylons.middleware:debugger_filter_factory [paste.filter_app_factory] debugger = pylons.middleware:debugger_filter_app_factory """, ) Pylons-1.0.2/setup.cfg0000644000175000017500000000024212553621453014155 0ustar benben00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 [nosetests] where = tests cover-package = pylons cover-erase = True with-doctest = True nocapture = 1 Pylons-1.0.2/pylons/0000755000175000017500000000000012553621453013662 5ustar benben00000000000000Pylons-1.0.2/pylons/commands.py0000644000175000017500000005433712515223101016033 0ustar benben00000000000000"""Paster Commands, for use with paster in your project .. highlight:: bash The following commands are made available via paster utilizing setuptools points discovery. These can be used from the command line when the directory is the Pylons project. Commands available: ``controller`` Create a Controller and accompanying functional test ``restcontroller`` Create a REST Controller and accompanying functional test ``shell`` Open an interactive shell with the Pylons app loaded Example usage:: ~/sample$ paster controller account Creating /Users/ben/sample/sample/controllers/account.py Creating /Users/ben/sample/sample/tests/functional/test_account.py ~/sample$ .. admonition:: How it Works :command:`paster` is a command line script (from the PasteScript package) that allows the creation of context sensitive commands. :command:`paster` looks in the current directory for a ``.egg-info`` directory, then loads the ``paster_plugins.txt`` file. Using setuptools entry points, :command:`paster` looks for functions registered with setuptools as :func:`paste.paster_command`. These are defined in the entry_points block in each packages :file:`setup.py` module. This same system is used when running :command:`paster create` to determine what templates are available when creating new projects. """ import os import sys import paste.fixture import paste.registry from paste.deploy import loadapp from paste.script.command import Command, BadCommand from paste.script.filemaker import FileOp from tempita import paste_script_template_renderer import pylons import pylons.util as util __all__ = ['ControllerCommand', 'RestControllerCommand', 'ShellCommand'] def can_import(name): """Attempt to __import__ the specified package/module, returning True when succeeding, otherwise False""" try: __import__(name) return True except ImportError: return False def is_minimal_template(package, fail_fast=False): """Determine if the specified Pylons project (package) uses the Pylons Minimal Template. fail_fast causes ImportErrors encountered during detection to be raised. """ minimal_template = False try: # Check if PACKAGE.lib.base exists __import__(package + '.lib.base') except ImportError, ie: if 'No module named lib.base' in str(ie): minimal_template = True except: # PACKAGE.lib.base exists but throws an error if fail_fast: raise return minimal_template def defines_render(package): """Determine if the specified Pylons project (package) defines a render callable in their base module """ base_module = (is_minimal_template(package) and package + '.controllers' or package + '.lib.base') try: base = __import__(base_module, globals(), locals(), ['__doc__']) except: return False return callable(getattr(base, 'render', None)) def validate_name(name): """Validate that the name for the controller isn't present on the path already""" if not name: # This happens when the name is an existing directory raise BadCommand('Please give the name of a controller.') # 'setup' is a valid controller name, but when paster controller is ran # from the root directory of a project, importing setup will import the # project's setup.py causing a sys.exit(). Blame relative imports if name != 'setup' and can_import(name): raise BadCommand( "\n\nA module named '%s' is already present in your " "PYTHON_PATH.\nChoosing a conflicting name will likely cause " "import problems in\nyour controller at some point. It's " "suggested that you choose an\nalternate name, and if you'd " "like that name to be accessible as\n'%s', add a route " "to your projects config/routing.py file similar\nto:\n" " map.connect('%s', controller='my_%s')" \ % (name, name, name, name)) return True def check_controller_existence(base_package, directory, name): """Check if given controller already exists in project.""" filename = os.path.join(base_package, 'controllers', directory, name + '.py') if os.path.exists(filename): raise BadCommand('Controller %s already exists.' % os.path.join(directory, name)) class ControllerCommand(Command): """Create a Controller and accompanying functional test The Controller command will create the standard controller template file and associated functional test to speed creation of controllers. Example usage:: yourproj% paster controller comments Creating yourproj/yourproj/controllers/comments.py Creating yourproj/yourproj/tests/functional/test_comments.py If you'd like to have controllers underneath a directory, just include the path as the controller name and the necessary directories will be created for you:: yourproj% paster controller admin/trackback Creating yourproj/controllers/admin Creating yourproj/yourproj/controllers/admin/trackback.py Creating yourproj/yourproj/tests/functional/test_admin_trackback.py """ summary = __doc__.splitlines()[0] usage = '\n' + __doc__ min_args = 1 max_args = 1 group_name = 'pylons' default_verbosity = 3 parser = Command.standard_parser(simulate=True) parser.add_option('--no-test', action='store_true', dest='no_test', help="Don't create the test; just the controller") def command(self): """Main command to create controller""" try: file_op = FileOp(source_dir=('pylons', 'templates')) try: name, directory = file_op.parse_path_name_args(self.args[0]) except: raise BadCommand('No egg_info directory was found') # Check the name isn't the same as the package base_package = file_op.find_dir('controllers', True)[0] if base_package.lower() == name.lower(): raise BadCommand( 'Your controller name should not be the same as ' 'the package name %r.' % base_package) # Validate the name name = name.replace('-', '_') validate_name(name) # Determine the module's import statement if is_minimal_template(base_package): importstatement = ('from %s.controllers import BaseController' % base_package) else: importstatement = ('from %s.lib.base import BaseController' % base_package) if defines_render(base_package): importstatement += ', render' # Setup the controller fullname = os.path.join(directory, name) controller_name = util.class_name_from_module_name( name.split('/')[-1]) if not fullname.startswith(os.sep): fullname = os.sep + fullname testname = fullname.replace(os.sep, '_')[1:] module_dir = directory.replace('/', os.path.sep) check_controller_existence(base_package, module_dir, name) file_op.template_vars.update( {'name': controller_name, 'fname': os.path.join(directory, name).replace('\\', '/'), 'tmpl_name': name, 'package': base_package, 'importstatement': importstatement}) file_op.copy_file(template='controller.py_tmpl', dest=os.path.join('controllers', directory), filename=name, template_renderer=paste_script_template_renderer) if not self.options.no_test: file_op.copy_file( template='test_controller.py_tmpl', dest=os.path.join('tests', 'functional'), filename='test_' + testname, template_renderer=paste_script_template_renderer) except BadCommand, e: raise BadCommand('An error occurred. %s' % e) except: msg = str(sys.exc_info()[1]) raise BadCommand('An unknown error occurred. %s' % msg) class RestControllerCommand(Command): """Create a REST Controller and accompanying functional test The RestController command will create a REST-based Controller file for use with the :meth:`~routes.mapper.Mapper.resource` REST-based dispatching. This template includes the methods that :meth:`~routes.mapper.Mapper.resource` dispatches to in addition to doc strings for clarification on when the methods will be called. The first argument should be the singular form of the REST resource. The second argument is the plural form of the word. If its a nested controller, put the directory information in front as shown in the second example below. Example usage:: yourproj% paster restcontroller comment comments Creating yourproj/yourproj/controllers/comments.py Creating yourproj/yourproj/tests/functional/test_comments.py If you'd like to have controllers underneath a directory, just include the path as the controller name and the necessary directories will be created for you:: yourproj% paster restcontroller admin/tracback admin/trackbacks Creating yourproj/controllers/admin Creating yourproj/yourproj/controllers/admin/trackbacks.py Creating yourproj/yourproj/tests/functional/test_admin_trackbacks.py """ summary = __doc__.splitlines()[0] usage = '\n' + __doc__ min_args = 2 max_args = 2 group_name = 'pylons' default_verbosity = 3 parser = Command.standard_parser(simulate=True) parser.add_option('--no-test', action='store_true', dest='no_test', help="Don't create the test; just the controller") def command(self): """Main command to create controller""" try: file_op = FileOp(source_dir=('pylons', 'templates')) try: singularname, singulardirectory = \ file_op.parse_path_name_args(self.args[0]) pluralname, pluraldirectory = \ file_op.parse_path_name_args(self.args[1]) except: raise BadCommand('No egg_info directory was found') # Check the name isn't the same as the package base_package = file_op.find_dir('controllers', True)[0] if base_package.lower() == pluralname.lower(): raise BadCommand( 'Your controller name should not be the same as ' 'the package name %r.' % base_package) # Validate the name for name in [pluralname]: name = name.replace('-', '_') validate_name(name) # Determine the module's import statement if is_minimal_template(base_package): importstatement = ('from %s.controllers import BaseController' % base_package) else: importstatement = ('from %s.lib.base import BaseController' % base_package) if defines_render(base_package): importstatement += ', render' module_dir = pluraldirectory.replace('/', os.path.sep) check_controller_existence(base_package, module_dir, name) # Setup the controller fullname = os.path.join(pluraldirectory, pluralname) controller_name = util.class_name_from_module_name( pluralname.split('/')[-1]) if not fullname.startswith(os.sep): fullname = os.sep + fullname testname = fullname.replace(os.sep, '_')[1:] nameprefix = '' path = '' if pluraldirectory: nameprefix = pluraldirectory.replace(os.path.sep, '_') + '_' path = pluraldirectory + '/' controller_c = '' if nameprefix: controller_c = ", controller='%s', \n\t" % \ '/'.join([pluraldirectory, pluralname]) controller_c += "path_prefix='/%s', name_prefix='%s'" % \ (pluraldirectory, nameprefix) command = "map.resource('%s', '%s'%s)\n" % \ (singularname, pluralname, controller_c) file_op.template_vars.update( {'classname': controller_name, 'pluralname': pluralname, 'singularname': singularname, 'name': controller_name, 'nameprefix': nameprefix, 'package': base_package, 'path': path, 'resource_command': command.replace('\n\t', '\n%s#%s' % \ (' ' * 4, ' ' * 9)), 'fname': os.path.join(pluraldirectory, pluralname), 'importstatement': importstatement}) resource_command = ("\nTo create the appropriate RESTful mapping, " "add a map statement to your\n") resource_command += ("config/routing.py file near the top like " "this:\n\n") resource_command += command file_op.copy_file(template='restcontroller.py_tmpl', dest=os.path.join('controllers', pluraldirectory), filename=pluralname, template_renderer=paste_script_template_renderer) if not self.options.no_test: file_op.copy_file( template='test_restcontroller.py_tmpl', dest=os.path.join('tests', 'functional'), filename='test_' + testname, template_renderer=paste_script_template_renderer) print resource_command except BadCommand, e: raise BadCommand('An error occurred. %s' % e) except: msg = str(sys.exc_info()[1]) raise BadCommand('An unknown error occurred. %s' % msg) class RoutesCommand(Command): """Print the applications routes The optional CONFIG_FILE argument specifies the config file to use. CONFIG_FILE defaults to 'development.ini'. Example:: $ paster routes my-development.ini """ summary = __doc__.splitlines()[0] usage = '\n' + __doc__ min_args = 0 max_args = 1 group_name = 'pylons' parser = Command.standard_parser(simulate=True) parser.add_option('-q', action='count', dest='quiet', default=0, help=("Do not load logging configuration from the " "config file")) def command(self): """Main command to create a new shell""" self.verbose = 3 if len(self.args) == 0: # Assume the .ini file is ./development.ini config_file = 'development.ini' if not os.path.isfile(config_file): raise BadCommand('%sError: CONFIG_FILE not found at: .%s%s\n' 'Please specify a CONFIG_FILE' % \ (self.parser.get_usage(), os.path.sep, config_file)) else: config_file = self.args[0] config_name = 'config:%s' % config_file here_dir = os.getcwd() if not self.options.quiet: # Configure logging from the config file self.logging_file_config(config_file) # Load the wsgi app first so that everything is initialized right wsgiapp = loadapp(config_name, relative_to=here_dir) test_app = paste.fixture.TestApp(wsgiapp) # Query the test app to setup the environment and get the mapper tresponse = test_app.get('/_test_vars') mapper = tresponse.config.get('routes.map') if mapper: print mapper class ShellCommand(Command): """Open an interactive shell with the Pylons app loaded The optional CONFIG_FILE argument specifies the config file to use for the interactive shell. CONFIG_FILE defaults to 'development.ini'. This allows you to test your mapper, models, and simulate web requests using ``paste.fixture``. Example:: $ paster shell my-development.ini """ summary = __doc__.splitlines()[0] usage = '\n' + __doc__ min_args = 0 max_args = 1 group_name = 'pylons' parser = Command.standard_parser(simulate=True) parser.add_option('-d', '--disable-ipython', action='store_true', dest='disable_ipython', help="Don't use IPython if it is available") parser.add_option('-q', action='count', dest='quiet', default=0, help=("Do not load logging configuration from the " "config file")) def command(self): """Main command to create a new shell""" self.verbose = 3 if len(self.args) == 0: # Assume the .ini file is ./development.ini config_file = 'development.ini' if not os.path.isfile(config_file): raise BadCommand('%sError: CONFIG_FILE not found at: .%s%s\n' 'Please specify a CONFIG_FILE' % \ (self.parser.get_usage(), os.path.sep, config_file)) else: config_file = self.args[0] config_name = 'config:%s' % config_file here_dir = os.getcwd() locs = dict(__name__="pylons-admin") if not self.options.quiet: # Configure logging from the config file self.logging_file_config(config_file) # Load locals and populate with objects for use in shell sys.path.insert(0, here_dir) # Load the wsgi app first so that everything is initialized right wsgiapp = loadapp(config_name, relative_to=here_dir) test_app = paste.fixture.TestApp(wsgiapp) # Query the test app to setup the environment tresponse = test_app.get('/_test_vars') request_id = int(tresponse.body) # Disable restoration during test_app requests test_app.pre_request_hook = lambda self: \ paste.registry.restorer.restoration_end() test_app.post_request_hook = lambda self: \ paste.registry.restorer.restoration_begin(request_id) # Restore the state of the Pylons special objects # (StackedObjectProxies) paste.registry.restorer.restoration_begin(request_id) # Determine the package name from the pylons.config object pkg_name = pylons.config['pylons.package'] # Start the rest of our imports now that the app is loaded if is_minimal_template(pkg_name, True): model_module = None helpers_module = pkg_name + '.helpers' base_module = pkg_name + '.controllers' else: model_module = pkg_name + '.model' helpers_module = pkg_name + '.lib.helpers' base_module = pkg_name + '.lib.base' if model_module and can_import(model_module): locs['model'] = sys.modules[model_module] if can_import(helpers_module): locs['h'] = sys.modules[helpers_module] exec ('from pylons import app_globals, config, request, response, ' 'session, tmpl_context, url') in locs exec ('from pylons.controllers.util import abort, redirect') in locs exec 'from pylons.i18n import _, ungettext, N_' in locs locs.pop('__builtins__', None) # Import all objects from the base module __import__(base_module) base = sys.modules[base_module] base_public = [__name for __name in dir(base) if not \ __name.startswith('_') or __name == '_'] locs.update((name, getattr(base, name)) for name in base_public) locs.update(dict(wsgiapp=wsgiapp, app=test_app)) mapper = tresponse.config.get('routes.map') if mapper: locs['mapper'] = mapper banner = " All objects from %s are available\n" % base_module banner += " Additional Objects:\n" if mapper: banner += " %-10s - %s\n" % ('mapper', 'Routes mapper object') banner += " %-10s - %s\n" % ('wsgiapp', "This project's WSGI App instance") banner += " %-10s - %s\n" % ('app', 'paste.fixture wrapped around wsgiapp') try: if self.options.disable_ipython: raise ImportError() # try to use IPython if possible try: try: # 1.0 <= ipython from IPython.terminal.embed import InteractiveShellEmbed except ImportError: # 0.11 <= ipython < 1.0 from IPython.frontend.terminal.embed import InteractiveShellEmbed shell = InteractiveShellEmbed(banner2=banner) except ImportError: # ipython < 0.11 from IPython.Shell import IPShellEmbed shell = IPShellEmbed(argv=self.args) shell.set_banner(shell.IP.BANNER + '\n\n' + banner) try: shell(local_ns=locs, global_ns={}) finally: paste.registry.restorer.restoration_end() except ImportError: import code py_prefix = sys.platform.startswith('java') and 'J' or 'P' newbanner = "Pylons Interactive Shell\n%sython %s\n\n" % \ (py_prefix, sys.version) banner = newbanner + banner shell = code.InteractiveConsole(locals=locs) try: import readline except ImportError: pass try: shell.interact(banner) finally: paste.registry.restorer.restoration_end() Pylons-1.0.2/pylons/middleware.py0000644000175000017500000001552412553617762016370 0ustar benben00000000000000"""Pylons' WSGI middlewares""" import logging import os.path from paste.deploy.converters import asbool from paste.urlparser import StaticURLParser from weberror.evalexception import EvalException from weberror.errormiddleware import ErrorMiddleware from webhelpers.html import literal import pylons from pylons.controllers.util import Request, Response from pylons.error import template_error_formatters from pylons.util import call_wsgi_application __all__ = ['ErrorHandler', 'error_document_template', 'footer_html', 'head_html', 'media_path'] log = logging.getLogger(__name__) media_path = os.path.join(os.path.dirname(__file__), 'media') head_html = """\ """ footer_html = """\

Online Assistance

 
Looking for help?

Here are a few tips for troubleshooting if the above traceback isn't helping out.

  1. Search the mail list
  2. Post a message to the mail list

The following mail lists will be searched:
Pylons
Python
Mako
SQLAlchemy

for:

Pylons version %s
""" report_libs = ['pylons', 'genshi', 'sqlalchemy'] def DebugHandler(app, global_conf, **kwargs): footer = footer_html % (kwargs.get('traceback_host', 'pylonshq.com'), pylons.__version__) py_media = dict(pylons=media_path) app = EvalException(app, global_conf, templating_formatters=template_error_formatters, media_paths=py_media, head_html=head_html, footer_html=footer, libraries=report_libs) return app def ErrorHandler(app, global_conf, **errorware): """ErrorHandler Toggle If debug is enabled, this function will return the app wrapped in the WebError ``EvalException`` middleware which displays interactive debugging sessions when a traceback occurs. Otherwise, the app will be wrapped in the WebError ``ErrorMiddleware``, and the ``errorware`` dict will be passed into it. The ``ErrorMiddleware`` handles sending an email to the address listed in the .ini file, under ``email_to``. """ if asbool(global_conf.get('debug')): footer = footer_html % (pylons.config.get('traceback_host', 'pylonshq.com'), pylons.__version__) py_media = dict(pylons=media_path) app = EvalException(app, global_conf, templating_formatters=template_error_formatters, media_paths=py_media, head_html=head_html, footer_html=footer, libraries=report_libs) else: app = ErrorMiddleware(app, global_conf, **errorware) return app class StatusCodeRedirect(object): """Internally redirects a request based on status code StatusCodeRedirect watches the response of the app it wraps. If the response is an error code in the errors sequence passed the request will be re-run with the path URL set to the path passed in. This operation is non-recursive and the output of the second request will be used no matter what it is. Should an application wish to bypass the error response (ie, to purposely return a 401), set ``environ['pylons.status_code_redirect'] = True`` in the application. """ def __init__(self, app, errors=(400, 401, 403, 404), path='/error/document'): """Initialize the ErrorRedirect ``errors`` A sequence (list, tuple) of error code integers that should be caught. ``path`` The path to set for the next request down to the application. """ self.app = app self.error_path = path # Transform errors to str for comparison self.errors = tuple([str(x) for x in errors]) def __call__(self, environ, start_response): status, headers, app_iter, exc_info = call_wsgi_application( self.app, environ, catch_exc_info=True) if status[:3] in self.errors and \ 'pylons.status_code_redirect' not in environ and self.error_path: # Create a response object environ['pylons.original_response'] = Response( status=status, headerlist=headers, app_iter=app_iter) environ['pylons.original_request'] = Request(environ) # Create a new environ to avoid touching the original request data new_environ = environ.copy() new_environ['PATH_INFO'] = self.error_path newstatus, headers, app_iter, exc_info = call_wsgi_application( self.app, new_environ, catch_exc_info=True) start_response(status, headers, exc_info) return app_iter error_document_template = literal("""\ Server Error %(code)s
%(message)s
""") def debugger_filter_factory(global_conf, **kwargs): def filter(app): return DebugHandler(app, global_conf, **kwargs) return filter def debugger_filter_app_factory(app, global_conf, **kwargs): return DebugHandler(app, global_conf, **kwargs) Pylons-1.0.2/pylons/wsgiapp.py0000644000175000017500000003173612451647626015727 0ustar benben00000000000000"""WSGI App Creator This module is responsible for creating the basic Pylons WSGI application (PylonsApp). It's generally assumed that it will be called by Paste, though any WSGI server could create and call the WSGI app as well. """ import logging import sys import paste.registry import pkg_resources from webob.exc import HTTPNotFound import pylons import pylons.templating from pylons.controllers.util import Request, Response from pylons.i18n.translation import _get_translator from pylons.util import (AttribSafeContextObj, ContextObj, PylonsContext, class_name_from_module_name) __all__ = ['PylonsApp'] log = logging.getLogger(__name__) class PylonsApp(object): """Pylons WSGI Application This basic WSGI app is provided should a web developer want to get access to the most basic Pylons web application environment available. By itself, this Pylons web application does little more than dispatch to a controller and setup the context object, the request object, and the globals object. Additional functionality like sessions, and caching can be setup by altering the ``environ['pylons.environ_config']`` setting to indicate what key the ``session`` and ``cache`` functionality should come from. Resolving the URL and dispatching can be customized by sub-classing or "monkey-patching" this class. Subclassing is the preferred approach. """ def __init__(self, config=None, **kwargs): """Initialize a base Pylons WSGI application The base Pylons WSGI application requires several keywords, the package name, and the globals object. If no helpers object is provided then h will be None. """ self.config = config = config or pylons.config._current_obj() package_name = config['pylons.package'] self.helpers = config['pylons.h'] self.globals = config.get('pylons.app_globals') self.environ_config = config['pylons.environ_config'] self.package_name = package_name self.request_options = config['pylons.request_options'] self.response_options = config['pylons.response_options'] self.controller_classes = {} self.log_debug = False self.config.setdefault('lang', None) # Cache some options for use during requests self._session_key = self.environ_config.get('session', 'beaker.session') self._cache_key = self.environ_config.get('cache', 'beaker.cache') def __call__(self, environ, start_response): """Setup and handle a web request PylonsApp splits its functionality into several methods to make it easier to subclass and customize core functionality. The methods are called in the following order: 1. :meth:`~PylonsApp.setup_app_env` 2. :meth:`~PylonsApp.load_test_env` (Only if operating in testing mode) 3. :meth:`~PylonsApp.resolve` 4. :meth:`~PylonsApp.dispatch` The response from :meth:`~PylonsApp.dispatch` is expected to be an iterable (valid :pep:`333` WSGI response), which is then sent back as the response. """ # Cache the logging level for the request log_debug = self.log_debug = logging.DEBUG >= log.getEffectiveLevel() environ['pylons.log_debug'] = log_debug self.setup_app_env(environ, start_response) if 'paste.testing_variables' in environ: self.load_test_env(environ) if environ['PATH_INFO'] == '/_test_vars': paste.registry.restorer.save_registry_state(environ) start_response('200 OK', [('Content-type', 'text/plain')]) return ['%s' % paste.registry.restorer.get_request_id(environ)] controller = self.resolve(environ, start_response) response = self.dispatch(controller, environ, start_response) response_obj = callable(response) if 'paste.testing_variables' in environ and response_obj: environ['paste.testing_variables']['response'] = response try: if response_obj: return response(environ, start_response) elif response is not None: return response raise Exception("No content returned by controller (Did you " "remember to 'return' it?) in: %r" % controller.__name__) finally: # Help Python collect ram a bit faster by removing the reference # cycle that the pylons object causes if 'pylons.pylons' in environ: del environ['pylons.pylons'] def register_globals(self, environ): """Registers globals in the environment, called from :meth:`~PylonsApp.setup_app_env` Override this to control how the Pylons API is setup. Note that a custom render function will need to be used if the ``pylons.app_globals`` global is not available. """ pylons_obj = environ['pylons.pylons'] registry = environ['paste.registry'] registry.register(pylons.response, pylons_obj.response) registry.register(pylons.request, pylons_obj.request) registry.register(pylons.app_globals, self.globals) registry.register(pylons.config, self.config) registry.register(pylons.tmpl_context, pylons_obj.tmpl_context) registry.register(pylons.translator, pylons_obj.translator) if 'session' in pylons_obj.__dict__: registry.register(pylons.session, pylons_obj.session) if 'cache' in pylons_obj.__dict__: registry.register(pylons.cache, pylons_obj.cache) elif 'cache' in pylons_obj.app_globals.__dict__: registry.register(pylons.cache, pylons_obj.app_globals.cache) if 'routes.url' in environ: registry.register(pylons.url, environ['routes.url']) def setup_app_env(self, environ, start_response): """Setup and register all the Pylons objects with the registry After creating all the global objects for use in the request, :meth:`~PylonsApp.register_globals` is called to register them in the environment. """ if self.log_debug: log.debug("Setting up Pylons stacked object globals") # Setup the basic pylons global objects req_options = self.request_options req = Request(environ, charset=req_options['charset'], unicode_errors=req_options['errors'], decode_param_names=req_options['decode_param_names']) req.language = req_options['language'] req.config = self.config req.link, req.route_dict = environ['wsgiorg.routing_args'] response = Response( content_type=self.response_options['content_type'], charset=self.response_options['charset']) response.headers.update(self.response_options['headers']) # Store a copy of the request/response in environ for faster access pylons_obj = PylonsContext() pylons_obj.config = self.config pylons_obj.request = req pylons_obj.response = response pylons_obj.app_globals = self.globals pylons_obj.h = self.helpers if 'routes.url' in environ: pylons_obj.url = environ['routes.url'] environ['pylons.pylons'] = pylons_obj environ['pylons.environ_config'] = self.environ_config # Setup the translator object lang = self.config['lang'] pylons_obj.translator = _get_translator(lang, pylons_config=self.config) if self.config['pylons.strict_tmpl_context']: tmpl_context = ContextObj() else: tmpl_context = AttribSafeContextObj() pylons_obj.tmpl_context = req.tmpl_context = tmpl_context if self._session_key in environ: pylons_obj.session = req.session = environ[self._session_key] if self._cache_key in environ: pylons_obj.cache = environ[self._cache_key] # Load the globals with the registry if around if 'paste.registry' in environ: self.register_globals(environ) def resolve(self, environ, start_response): """Uses dispatching information found in ``environ['wsgiorg.routing_args']`` to retrieve a controller name and return the controller instance from the appropriate controller module. Override this to change how the controller name is found and returned. """ match = environ['wsgiorg.routing_args'][1] environ['pylons.routes_dict'] = match controller = match.get('controller', match.get('responder')) if not controller: return if self.log_debug: log.debug("Resolved URL to controller: %r", controller) return self.find_controller(controller) def find_controller(self, controller): """Locates a controller by attempting to import it then grab the SomeController instance from the imported module. Controller name is assumed to be a module in the controllers directory unless it contains a '.' or ':' which is then assumed to be a dotted path to the module and name of the controller object. Override this to change how the controller object is found once the URL has been resolved. """ # If this isn't a basestring, its an object, assume that its the # proper instance to begin with if not isinstance(controller, basestring): return controller # Check to see if we've cached the class instance for this name if controller in self.controller_classes: return self.controller_classes[controller] # Check to see if its a dotted name if '.' in controller or ':' in controller: mycontroller = pkg_resources.EntryPoint.parse( 'x=%s' % controller).load(False) self.controller_classes[controller] = mycontroller return mycontroller # Pull the controllers class name, import controller full_module_name = self.package_name + '.controllers.' \ + controller.replace('/', '.') # Hide the traceback here if the import fails (bad syntax and such) __traceback_hide__ = 'before_and_this' __import__(full_module_name) if hasattr(sys.modules[full_module_name], '__controller__'): mycontroller = getattr(sys.modules[full_module_name], sys.modules[full_module_name].__controller__) else: module_name = controller.split('/')[-1] class_name = class_name_from_module_name(module_name) + 'Controller' if self.log_debug: log.debug("Found controller, module: '%s', class: '%s'", full_module_name, class_name) mycontroller = getattr(sys.modules[full_module_name], class_name) self.controller_classes[controller] = mycontroller return mycontroller def dispatch(self, controller, environ, start_response): """Dispatches to a controller, will instantiate the controller if necessary. Override this to change how the controller dispatch is handled. """ log_debug = self.log_debug if not controller: if log_debug: log.debug("No controller found, returning 404 HTTP Not Found") return HTTPNotFound()(environ, start_response) # Is it a responder? if 'responder' in environ['pylons.routes_dict']: return controller(environ['pylons.pylons'].request) # Is it a class? Then its a WSGIController if hasattr(controller, '__bases__'): if log_debug: log.debug("Controller appears to be a class, instantiating") controller = controller() controller._pylons_log_debug = log_debug # Add a reference to the controller app located environ['pylons.controller'] = controller # Controller is assumed to handle a WSGI call if log_debug: log.debug("Calling controller class with WSGI interface") return controller(environ, start_response) def load_test_env(self, environ): """Sets up our Paste testing environment""" if self.log_debug: log.debug("Setting up paste testing environment variables") testenv = environ['paste.testing_variables'] pylons_obj = environ['pylons.pylons'] testenv['req'] = pylons_obj.request testenv['response'] = pylons_obj.response testenv['tmpl_context'] = pylons_obj.tmpl_context testenv['app_globals'] = testenv['g'] = pylons_obj.app_globals testenv['h'] = self.config['pylons.h'] testenv['config'] = self.config if hasattr(pylons_obj, 'session'): testenv['session'] = pylons_obj.session if hasattr(pylons_obj, 'cache'): testenv['cache'] = pylons_obj.cache elif hasattr(pylons_obj.app_globals, 'cache'): testenv['cache'] = pylons_obj.app_globals.cache Pylons-1.0.2/pylons/controllers/0000755000175000017500000000000012553621453016230 5ustar benben00000000000000Pylons-1.0.2/pylons/controllers/core.py0000644000175000017500000002547312451647626017554 0ustar benben00000000000000"""The core WSGIController""" import inspect import logging import types from webob.exc import HTTPException, HTTPNotFound import pylons __all__ = ['WSGIController'] log = logging.getLogger(__name__) class WSGIController(object): """WSGI Controller that follows WSGI spec for calling and return values The Pylons WSGI Controller handles incoming web requests that are dispatched from the PylonsBaseWSGIApp. These requests result in a new instance of the WSGIController being created, which is then called with the dict options from the Routes match. The standard WSGI response is then returned with start_response called as per the WSGI spec. Special WSGIController methods you may define: ``__before__`` This method is called before your action is, and should be used for setting up variables/objects, restricting access to other actions, or other tasks which should be executed before the action is called. ``__after__`` This method is called after the action is, unless an unexpected exception was raised. Subclasses of :class:`~webob.exc.HTTPException` (such as those raised by ``redirect_to`` and ``abort``) are expected; e.g. ``__after__`` will be called on redirects. Each action to be called is inspected with :meth:`_inspect_call` so that it is only passed the arguments in the Routes match dict that it asks for. The arguments passed into the action can be customized by overriding the :meth:`_get_method_args` function which is expected to return a dict. In the event that an action is not found to handle the request, the Controller will raise an "Action Not Found" error if in debug mode, otherwise a ``404 Not Found`` error will be returned. """ _pylons_log_debug = False def _perform_call(self, func, args): """Hide the traceback for everything above this method""" __traceback_hide__ = 'before_and_this' return func(**args) def _inspect_call(self, func): """Calls a function with arguments from :meth:`_get_method_args` Given a function, inspect_call will inspect the function args and call it with no further keyword args than it asked for. If the function has been decorated, it is assumed that the decorator preserved the function signature. """ # Check to see if the class has a cache of argspecs yet try: cached_argspecs = self.__class__._cached_argspecs except AttributeError: self.__class__._cached_argspecs = cached_argspecs = {} # function could be callable func_key = getattr(func, 'im_func', func.__call__) try: argspec = cached_argspecs[func_key] except KeyError: argspec = cached_argspecs[func_key] = inspect.getargspec(func_key) kargs = self._get_method_args() log_debug = self._pylons_log_debug c = self._py_object.tmpl_context environ = self._py_object.request.environ args = None if argspec[2]: if self._py_object.config['pylons.tmpl_context_attach_args']: for k, val in kargs.iteritems(): setattr(c, k, val) args = kargs else: args = {} argnames = argspec[0][isinstance(func, types.MethodType) and 1 or 0:] for name in argnames: if name in kargs: if self._py_object.config['pylons.tmpl_context_attach_args']: setattr(c, name, kargs[name]) args[name] = kargs[name] if log_debug: log.debug("Calling %r method with keyword args: **%r", func.__name__, args) try: result = self._perform_call(func, args) except HTTPException, httpe: if log_debug: log.debug("%r method raised HTTPException: %s (code: %s)", func.__name__, httpe.__class__.__name__, httpe.wsgi_response.code, exc_info=True) result = httpe # Store the exception in the environ environ['pylons.controller.exception'] = httpe # 304 Not Modified's shouldn't have a content-type set if result.wsgi_response.status_int == 304: result.wsgi_response.headers.pop('Content-Type', None) result._exception = True return result def _get_method_args(self): """Retrieve the method arguments to use with inspect call By default, this uses Routes to retrieve the arguments, override this method to customize the arguments your controller actions are called with. This method should return a dict. """ req = self._py_object.request kargs = req.environ['pylons.routes_dict'].copy() kargs['environ'] = req.environ kargs['start_response'] = self.start_response kargs['pylons'] = self._py_object return kargs def _dispatch_call(self): """Handles dispatching the request to the function using Routes""" log_debug = self._pylons_log_debug req = self._py_object.request try: action = req.environ['pylons.routes_dict']['action'] except KeyError: raise Exception("No action matched from Routes, unable to" "determine action dispatch.") action_method = action.replace('-', '_') if log_debug: log.debug("Looking for %r method to handle the request", action_method) try: func = getattr(self, action_method, None) except UnicodeEncodeError: func = None if action_method != 'start_response' and callable(func): # Store function used to handle request req.environ['pylons.action_method'] = func response = self._inspect_call(func) else: if log_debug: log.debug("Couldn't find %r method to handle response", action) if pylons.config['debug']: raise NotImplementedError('Action %r is not implemented' % action) else: response = HTTPNotFound() return response def __call__(self, environ, start_response): """The main call handler that is called to return a response""" log_debug = self._pylons_log_debug # Keep a local reference to the req/response objects self._py_object = environ['pylons.pylons'] # Keep private methods private try: if environ['pylons.routes_dict']['action'][:1] in ('_', '-'): if log_debug: log.debug("Action starts with _, private action not " "allowed. Returning a 404 response") return HTTPNotFound()(environ, start_response) except KeyError: # The check later will notice that there's no action pass start_response_called = [] def repl_start_response(status, headers, exc_info=None): response = self._py_object.response start_response_called.append(None) # Copy the headers from the global response if log_debug: log.debug("Merging pylons.response headers into " "start_response call, status: %s", status) headers.extend(header for header in response.headerlist if header[0] == 'Set-Cookie' or header[0].startswith('X-')) return start_response(status, headers, exc_info) self.start_response = repl_start_response if hasattr(self, '__before__'): response = self._inspect_call(self.__before__) if hasattr(response, '_exception'): return response(environ, self.start_response) response = self._dispatch_call() if not start_response_called: self.start_response = start_response py_response = self._py_object.response # If its not a WSGI response, and we have content, it needs to # be wrapped in the response object if isinstance(response, str): if log_debug: log.debug("Controller returned a string " ", writing it to pylons.response") py_response.body = py_response.body + response elif isinstance(response, unicode): if log_debug: log.debug("Controller returned a unicode string " ", writing it to pylons.response") py_response.unicode_body = py_response.unicode_body + \ response elif hasattr(response, 'wsgi_response'): # It's an exception that got tossed. if log_debug: log.debug("Controller returned a Response object, merging " "it with pylons.response") for name, value in py_response.headers.items(): if name.lower() == 'set-cookie': response.headers.add(name, value) else: response.headers.setdefault(name, value) try: registry = environ['paste.registry'] registry.replace(pylons.response, response) except KeyError: # Ignore the case when someone removes the registry pass py_response = response elif response is None: if log_debug: log.debug("Controller returned None") else: if log_debug: log.debug("Assuming controller returned an iterable, " "setting it as pylons.response.app_iter") py_response.app_iter = response response = py_response if hasattr(self, '__after__'): after = self._inspect_call(self.__after__) if hasattr(after, '_exception'): after.wsgi_response = True response = after if hasattr(response, 'wsgi_response'): # Copy the response object into the testing vars if we're testing if 'paste.testing_variables' in environ: environ['paste.testing_variables']['response'] = response if log_debug: log.debug("Calling Response object to return WSGI data") return response(environ, self.start_response) if log_debug: log.debug("Response assumed to be WSGI content, returning " "un-touched") return response Pylons-1.0.2/pylons/controllers/util.py0000644000175000017500000001626712460016440017562 0ustar benben00000000000000"""Utility functions and classes available for use by Controllers Pylons subclasses the `WebOb `_ :class:`webob.Request` and :class:`webob.Response` classes to provide backwards compatible functions for earlier versions of Pylons as well as add a few helper functions to assist with signed cookies. For reference use, refer to the :class:`Request` and :class:`Response` below. Functions available: :func:`abort`, :func:`forward`, :func:`etag_cache`, :func:`mimetype` and :func:`redirect` """ import base64 import binascii import hmac import logging import re try: import cPickle as pickle except ImportError: import pickle try: from hashlib import sha1 except ImportError: import sha as sha1 from webob import BaseRequest as WebObRequest from webob import Response as WebObResponse from webob.exc import status_map import pylons __all__ = ['abort', 'etag_cache', 'redirect', 'Request', 'Response'] log = logging.getLogger(__name__) IF_NONE_MATCH = re.compile('(?:W/)?(?:"([^"]*)",?\s*)') class Request(WebObRequest): """WebOb Request subclass The WebOb :class:`webob.Request` has no charset, or other defaults. This subclass adds defaults, along with several methods for backwards compatibility with paste.wsgiwrappers.WSGIRequest. """ def determine_browser_charset(self): """Legacy method to return the :attr:`webob.Request.accept_charset`""" return self.accept_charset def languages(self): # And we now have the old best_matches code that webob ditched! al = self.accept_language try: items = [i for i, q in sorted(al._parsed, key=lambda iq: -iq[1])] for index, item in enumerate(items): if al._match(item, self.language): items[index:] = [self.language] break else: items.append(self.language) return items except AttributeError: # If its a NilAccept, there won't be a _parsed attribute # Return the best match instead return [self.accept_language.best_match(self.language)] languages = property(languages) def match_accept(self, mimetypes): return self.accept.first_match(mimetypes) def signed_cookie(self, name, secret): """Extract a signed cookie of ``name`` from the request The cookie is expected to have been created with ``Response.signed_cookie``, and the ``secret`` should be the same as the one used to sign it. Any failure in the signature of the data will result in None being returned. """ cookie = self.str_cookies.get(name) if not cookie: return None try: input_sig, pickled = cookie[:40], base64.standard_b64decode(cookie[40:]) except binascii.Error: # Badly formed data can make base64 die return None sig = hmac.new(secret, pickled, sha1).hexdigest() # Avoid timing attacks invalid_bits = 0 if len(sig) != len(input_sig): return None for a, b in zip(sig, input_sig): invalid_bits += a != b if invalid_bits: return None else: return pickle.loads(pickled) class Response(WebObResponse): """WebOb Response subclass The WebOb Response has no default content type, or error defaults. This subclass adds defaults, along with several methods for backwards compatibility with paste.wsgiwrappers.WSGIResponse. """ content = WebObResponse.body def determine_charset(self): return self.charset def has_header(self, header): return header in self.headers def get_content(self): return self.body def wsgi_response(self): return self.status, self.headers, self.body def signed_cookie(self, name, data, secret=None, **kwargs): """Save a signed cookie with ``secret`` signature Saves a signed cookie of the pickled data. All other keyword arguments that ``WebOb.set_cookie`` accepts are usable and passed to the WebOb set_cookie method after creating the signed cookie value. """ pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL) sig = hmac.new(secret, pickled, sha1).hexdigest() self.set_cookie(name, sig + base64.standard_b64encode(pickled), **kwargs) def etag_cache(key=None): """Use the HTTP Entity Tag cache for Browser side caching If a "If-None-Match" header is found, and equivilant to ``key``, then a ``304`` HTTP message will be returned with the ETag to tell the browser that it should use its current cache of the page. Otherwise, the ETag header will be added to the response headers. Suggested use is within a Controller Action like so: .. code-block:: python import pylons class YourController(BaseController): def index(self): etag_cache(key=1) return render('/splash.mako') .. note:: This works because etag_cache will raise an HTTPNotModified exception if the ETag received matches the key provided. """ if_none_matches = IF_NONE_MATCH.findall( pylons.request.environ.get('HTTP_IF_NONE_MATCH', '')) response = pylons.response._current_obj() response.headers['ETag'] = '"%s"' % key if str(key) in if_none_matches: log.debug("ETag match, returning 304 HTTP Not Modified Response") response.headers.pop('Content-Type', None) response.headers.pop('Cache-Control', None) response.headers.pop('Pragma', None) raise status_map[304]() else: log.debug("ETag didn't match, returning response object") def forward(wsgi_app): """Forward the request to a WSGI application. Returns its response. .. code-block:: python return forward(FileApp('filename')) """ environ = pylons.request.environ controller = environ.get('pylons.controller') if not controller or not hasattr(controller, 'start_response'): raise RuntimeError("Unable to forward: environ['pylons.controller'] " "is not a valid Pylons controller") return wsgi_app(environ, controller.start_response) def abort(status_code=None, detail="", headers=None, comment=None): """Aborts the request immediately by returning an HTTP exception In the event that the status_code is a 300 series error, the detail attribute will be used as the Location header should one not be specified in the headers attribute. """ exc = status_map[status_code](detail=detail, headers=headers, comment=comment) log.debug("Aborting request, status: %s, detail: %r, headers: %r, " "comment: %r", status_code, detail, headers, comment) raise exc def redirect(url, code=302): """Raises a redirect exception to the specified URL Optionally, a code variable may be passed with the status code of the redirect, ie:: redirect(url(controller='home', action='index'), code=303) """ log.debug("Generating %s redirect" % code) exc = status_map[code] raise exc(location=url.encode('utf-8')) Pylons-1.0.2/pylons/controllers/__init__.py0000644000175000017500000000036712451647626020356 0ustar benben00000000000000"""Standard Controllers intended for subclassing by web developers""" from pylons.controllers.core import WSGIController from pylons.controllers.xmlrpc import XMLRPCController from pylons.controllers.jsonrpc import JSONRPCController, JSONRPCError Pylons-1.0.2/pylons/controllers/xmlrpc.py0000644000175000017500000002526012451647626020123 0ustar benben00000000000000"""The base WSGI XMLRPCController""" import inspect import logging import types import xmlrpclib from paste.response import replace_header from pylons.controllers import WSGIController from pylons.controllers.util import abort, Response __all__ = ['XMLRPCController'] log = logging.getLogger(__name__) XMLRPC_MAPPING = ((basestring, 'string'), (list, 'array'), (bool, 'boolean'), (int, 'int'), (float, 'double'), (dict, 'struct'), (xmlrpclib.DateTime, 'dateTime.iso8601'), (xmlrpclib.Binary, 'base64')) def xmlrpc_sig(args): """Returns a list of the function signature in string format based on a tuple provided by xmlrpclib.""" signature = [] for param in args: for type, xml_name in XMLRPC_MAPPING: if isinstance(param, type): signature.append(xml_name) break return signature def xmlrpc_fault(code, message): """Convienence method to return a Pylons response XMLRPC Fault""" fault = xmlrpclib.Fault(code, message) return Response(body=xmlrpclib.dumps(fault, methodresponse=True)) class XMLRPCController(WSGIController): """XML-RPC Controller that speaks WSGI This controller handles XML-RPC responses and complies with the `XML-RPC Specification `_ as well as the `XML-RPC Introspection `_ specification. By default, methods with names containing a dot are translated to use an underscore. For example, the `system.methodHelp` is handled by the method :meth:`system_methodHelp`. Methods in the XML-RPC controller will be called with the method given in the XMLRPC body. Methods may be annotated with a signature attribute to declare the valid arguments and return types. For example:: class MyXML(XMLRPCController): def userstatus(self): return 'basic string' userstatus.signature = [ ['string'] ] def userinfo(self, username, age=None): user = LookUpUser(username) response = {'username':user.name} if age and age > 10: response['age'] = age return response userinfo.signature = [['struct', 'string'], ['struct', 'string', 'int']] Since XML-RPC methods can take different sets of data, each set of valid arguments is its own list. The first value in the list is the type of the return argument. The rest of the arguments are the types of the data that must be passed in. In the last method in the example above, since the method can optionally take an integer value both sets of valid parameter lists should be provided. Valid types that can be checked in the signature and their corresponding Python types:: 'string' - str 'array' - list 'boolean' - bool 'int' - int 'double' - float 'struct' - dict 'dateTime.iso8601' - xmlrpclib.DateTime 'base64' - xmlrpclib.Binary The class variable ``allow_none`` is passed to xmlrpclib.dumps; enabling it allows translating ``None`` to XML (an extension to the XML-RPC specification) .. note:: Requiring a signature is optional. """ allow_none = False max_body_length = 4194304 def _get_method_args(self): return self.rpc_kargs def __call__(self, environ, start_response): """Parse an XMLRPC body for the method, and call it with the appropriate arguments""" # Pull out the length, return an error if there is no valid # length or if the length is larger than the max_body_length. log_debug = self._pylons_log_debug length = environ.get('CONTENT_LENGTH') if length: length = int(length) else: # No valid Content-Length header found if log_debug: log.debug("No Content-Length found, returning 411 error") abort(411) if length > self.max_body_length or length == 0: if log_debug: log.debug("Content-Length larger than max body length. Max: " "%s, Sent: %s. Returning 413 error", self.max_body_length, length) abort(413, "XML body too large") body = environ['wsgi.input'].read(int(environ['CONTENT_LENGTH'])) rpc_args, orig_method = xmlrpclib.loads(body) method = self._find_method_name(orig_method) func = self._find_method(method) if not func: if log_debug: log.debug("Method: %r not found, returning xmlrpc fault", method) return xmlrpc_fault(0, "No such method name %r" % method)(environ, start_response) # Signature checking for params if hasattr(func, 'signature'): if log_debug: log.debug("Checking XMLRPC argument signature") valid_args = False params = xmlrpc_sig(rpc_args) for sig in func.signature: # Next sig if we don't have the same amount of args if len(sig) - 1 != len(rpc_args): continue # If the params match, we're valid if params == sig[1:]: valid_args = True break if not valid_args: if log_debug: log.debug("Bad argument signature recieved, returning " "xmlrpc fault") msg = ("Incorrect argument signature. %r recieved does not " "match %r signature for method %r" % \ (params, func.signature, orig_method)) return xmlrpc_fault(0, msg)(environ, start_response) # Change the arg list into a keyword dict based off the arg # names in the functions definition arglist = inspect.getargspec(func)[0][1:] kargs = dict(zip(arglist, rpc_args)) kargs['action'], kargs['environ'] = method, environ kargs['start_response'] = start_response self.rpc_kargs = kargs self._func = func # Now that we know the method is valid, and the args are valid, # we can dispatch control to the default WSGIController status = [] headers = [] exc_info = [] def change_content(new_status, new_headers, new_exc_info=None): status.append(new_status) headers.extend(new_headers) exc_info.append(new_exc_info) output = WSGIController.__call__(self, environ, change_content) output = list(output) headers.append(('Content-Length', str(len(output[0])))) replace_header(headers, 'Content-Type', 'text/xml') start_response(status[0], headers, exc_info[0]) return output def _dispatch_call(self): """Dispatch the call to the function chosen by __call__""" raw_response = self._inspect_call(self._func) if not isinstance(raw_response, xmlrpclib.Fault): raw_response = (raw_response,) response = xmlrpclib.dumps(raw_response, methodresponse=True, allow_none=self.allow_none) return response def _find_method(self, name): """Locate a method in the controller by the specified name and return it""" # Keep private methods private if name.startswith('_'): if self._pylons_log_debug: log.debug("Action starts with _, private action not allowed") return if self._pylons_log_debug: log.debug("Looking for XMLRPC method: %r", name) try: func = getattr(self, name, None) except UnicodeEncodeError: return if isinstance(func, types.MethodType): return func def _find_method_name(self, name): """Locate a method in the controller by the appropriate name By default, this translates method names like 'system.methodHelp' into 'system_methodHelp'. """ return name.replace('.', '_') def _publish_method_name(self, name): """Translate an internal method name to a publicly viewable one By default, this translates internal method names like 'blog_view' into 'blog.view'. """ return name.replace('_', '.') def system_listMethods(self): """Returns a list of XML-RPC methods for this XML-RPC resource""" methods = [] for method in dir(self): meth = getattr(self, method) if not method.startswith('_') and isinstance(meth, types.MethodType): methods.append(self._publish_method_name(method)) return methods system_listMethods.signature = [['array']] def system_methodSignature(self, name): """Returns an array of array's for the valid signatures for a method. The first value of each array is the return value of the method. The result is an array to indicate multiple signatures a method may be capable of. """ method = self._find_method(self._find_method_name(name)) if method: return getattr(method, 'signature', '') else: return xmlrpclib.Fault(0, 'No such method name') system_methodSignature.signature = [['array', 'string'], ['string', 'string']] def system_methodHelp(self, name): """Returns the documentation for a method""" method = self._find_method(self._find_method_name(name)) if method: help = MethodHelp.getdoc(method) sig = getattr(method, 'signature', None) if sig: help += "\n\nMethod signature: %s" % sig return help return xmlrpclib.Fault(0, "No such method name") system_methodHelp.signature = [['string', 'string']] class MethodHelp(object): """Wrapper for formatting doc strings from XMLRPCController methods""" def __init__(self, doc): self.__doc__ = doc def getdoc(method): """Return a formatted doc string, via inspect.getdoc, from the specified XMLRPCController method The method's help attribute is used if it exists, otherwise the method's doc string is used. """ help = getattr(method, 'help', None) if help is None: help = method.__doc__ doc = inspect.getdoc(MethodHelp(help)) if doc is None: return '' return doc getdoc = staticmethod(getdoc) Pylons-1.0.2/pylons/controllers/jsonrpc.py0000644000175000017500000001722012451647626020271 0ustar benben00000000000000"""The base WSGI JSONRPCController""" import inspect import json import logging import types import urllib from paste.response import replace_header from pylons.controllers import WSGIController from pylons.controllers.util import abort, Response __all__ = ['JSONRPCController', 'JSONRPCError', 'JSONRPC_PARSE_ERROR', 'JSONRPC_INVALID_REQUEST', 'JSONRPC_METHOD_NOT_FOUND', 'JSONRPC_INVALID_PARAMS', 'JSONRPC_INTERNAL_ERROR'] log = logging.getLogger(__name__) JSONRPC_VERSION = '2.0' class JSONRPCError(BaseException): def __init__(self, code, message): self.code = code self.message = message self.data = None def __str__(self): return str(self.code) + ': ' + self.message def as_dict(self): """Return a dictionary representation of this object for serialization in a JSON-RPC response.""" error = dict(code=self.code, message=self.message) if self.data: error['data'] = self.data return error JSONRPC_PARSE_ERROR = JSONRPCError(-32700, "Parse error") JSONRPC_INVALID_REQUEST = JSONRPCError(-32600, "Invalid Request") JSONRPC_METHOD_NOT_FOUND = JSONRPCError(-32601, "Method not found") JSONRPC_INVALID_PARAMS = JSONRPCError(-32602, "Invalid params") JSONRPC_INTERNAL_ERROR = JSONRPCError(-32603, "Internal error") _reserved_errors = dict(parse_error=JSONRPC_PARSE_ERROR, invalid_request=JSONRPC_INVALID_REQUEST, method_not_found=JSONRPC_METHOD_NOT_FOUND, invalid_params=JSONRPC_INVALID_PARAMS, internal_error=JSONRPC_INTERNAL_ERROR) def jsonrpc_error(req_id, error): """Generate a Response object with a JSON-RPC error body. Used to raise top-level pre-defined errors that happen outside the controller.""" if error in _reserved_errors: err = _reserved_errors[error] return Response(body=json.dumps(dict(jsonrpc=JSONRPC_VERSION, id=req_id, error=err.as_dict()))) class JSONRPCController(WSGIController): """ A WSGI-speaking JSON-RPC 2.0 controller class See the specification: ``. Many parts of this controller are modelled after XMLRPCController from Pylons 0.9.7 Valid controller return values should be json-serializable objects. Sub-classes should catch their exceptions and raise JSONRPCError if they want to pass meaningful errors to the client. Unhandled errors should be caught and return JSONRPC_INTERNAL_ERROR to the client. Parts of the specification not supported (yet): - Notifications - Batch """ def _get_method_args(self): """Return `self._rpc_args` to dispatched controller method chosen by __call__""" return self._rpc_args def __call__(self, environ, start_response): """Parse the request body as JSON, look up the method on the controller and if it exists, dispatch to it. """ length = 0 if 'CONTENT_LENGTH' not in environ: log.debug("No Content-Length") abort(411) else: if environ['CONTENT_LENGTH'] == '': abort(411) length = int(environ['CONTENT_LENGTH']) log.debug('Content-Length: %s', length) if length == 0: log.debug("Content-Length is 0") abort(411) raw_body = environ['wsgi.input'].read(length) json_body = json.loads(urllib.unquote_plus(raw_body)) self._req_id = json_body['id'] self._req_method = json_body['method'] self._req_params = json_body['params'] log.debug('id: %s, method: %s, params: %s', self._req_id, self._req_method, self._req_params) self._error = None try: self._func = self._find_method() except AttributeError: err = jsonrpc_error(self._req_id, 'method_not_found') return err(environ, start_response) # now that we have a method, make sure we have enough # parameters and pass off control to the controller. if not isinstance(self._req_params, dict): # JSON-RPC version 1 request. arglist = inspect.getargspec(self._func)[0][1:] if len(self._req_params) < len(arglist): err = jsonrpc_error(self._req_id, 'invalid_params') return err(environ, start_response) else: kargs = dict(zip(arglist, self._req_params)) else: # JSON-RPC version 2 request. Params may be default, and # are already a dict, so skip the parameter length check here. kargs = self._req_params # XX Fix this namespace clash. One cannot use names below as # method argument names as this stands! kargs['action'], kargs['environ'] = self._req_method, environ kargs['start_response'] = start_response self._rpc_args = kargs status = [] headers = [] exc_info = [] def change_content(new_status, new_headers, new_exc_info=None): status.append(new_status) headers.extend(new_headers) exc_info.append(new_exc_info) output = WSGIController.__call__(self, environ, change_content) output = list(output) headers.append(('Content-Length', str(len(output[0])))) replace_header(headers, 'Content-Type', 'application/json') start_response(status[0], headers, exc_info[0]) return output def _dispatch_call(self): """Implement dispatch interface specified by WSGIController""" try: raw_response = self._inspect_call(self._func) except JSONRPCError, e: self._error = e.as_dict() except TypeError, e: # Insufficient args in an arguments dict v2 call. if 'takes at least' in str(e): err = _reserved_errors['invalid_params'] self._error = err.as_dict() else: raise except Exception, e: log.debug('Encountered unhandled exception: %s', repr(e)) err = _reserved_errors['internal_error'] self._error = err.as_dict() response = dict(jsonrpc=JSONRPC_VERSION, id=self._req_id) if self._error is not None: response['error'] = self._error else: response['result'] = raw_response try: return json.dumps(response) except TypeError, e: log.debug('Error encoding response: %s', e) err = _reserved_errors['internal_error'] return json.dumps(dict( jsonrpc=JSONRPC_VERSION, id=self._req_id, error=err.as_dict())) def _find_method(self): """Return method named by `self._req_method` in controller if able""" log.debug('Trying to find JSON-RPC method: %s', self._req_method) if self._req_method.startswith('_'): raise AttributeError("Method not allowed") try: func = getattr(self, self._req_method, None) except UnicodeEncodeError: # XMLRPCController catches this, not sure why. raise AttributeError("Problem decoding unicode in requested " "method name.") if isinstance(func, types.MethodType): return func else: raise AttributeError("No such method: %s" % self._req_method) Pylons-1.0.2/pylons/util.py0000644000175000017500000001776312451647626015236 0ustar benben00000000000000"""Paste Template and Pylons utility functions PylonsTemplate is a Paste Template sub-class that configures the source directory and default plug-ins for a new Pylons project. The minimal template a more minimal template with less additional directories and layout. """ import logging import sys import pkg_resources from paste.deploy.converters import asbool from paste.script.appinstall import Installer from paste.script.templates import Template, var from tempita import paste_script_template_renderer import pylons import pylons.configuration import pylons.i18n __all__ = ['AttribSafeContextObj', 'ContextObj', 'PylonsContext', 'class_name_from_module_name', 'call_wsgi_application'] log = logging.getLogger(__name__) def call_wsgi_application(application, environ, catch_exc_info=False): """ Call the given WSGI application, returning ``(status_string, headerlist, app_iter)`` Be sure to call ``app_iter.close()`` if it's there. If catch_exc_info is true, then returns ``(status_string, headerlist, app_iter, exc_info)``, where the fourth item may be None, but won't be if there was an exception. If you don't do this and there was an exception, the exception will be raised directly. """ captured = [] output = [] def start_response(status, headers, exc_info=None): if exc_info is not None and not catch_exc_info: raise exc_info[0], exc_info[1], exc_info[2] captured[:] = [status, headers, exc_info] return output.append app_iter = application(environ, start_response) if not captured or output: try: output.extend(app_iter) finally: if hasattr(app_iter, 'close'): app_iter.close() app_iter = output if catch_exc_info: return (captured[0], captured[1], app_iter, captured[2]) else: return (captured[0], captured[1], app_iter) def class_name_from_module_name(module_name): """Takes a module name and returns the name of the class it defines. If the module name contains dashes, they are replaced with underscores. Example:: >>> class_name_from_module_name('with-dashes') 'WithDashes' >>> class_name_from_module_name('with_underscores') 'WithUnderscores' >>> class_name_from_module_name('oneword') 'Oneword' """ words = module_name.replace('-', '_').split('_') return ''.join(w.title() for w in words) class PylonsContext(object): """Pylons context object All the Pylons Stacked Object Proxies are also stored here, for use in generators and async based operation where the globals can't be used. This object is attached in :class:`~pylons.controllers.core.WSGIController` instances as :attr:`~WSGIController._py_object`. For example:: class MyController(WSGIController): def index(self): pyobj = self._py_object return "Environ is %s" % pyobj.request.environ """ pass class ContextObj(object): """The :term:`tmpl_context` object, with strict attribute access (raises an Exception when the attribute does not exist)""" def __repr__(self): attrs = sorted((name, value) for name, value in self.__dict__.iteritems() if not name.startswith('_')) parts = [] for name, value in attrs: value_repr = repr(value) if len(value_repr) > 70: value_repr = value_repr[:60] + '...' + value_repr[-5:] parts.append(' %s=%s' % (name, value_repr)) return '<%s.%s at %s%s>' % ( self.__class__.__module__, self.__class__.__name__, hex(id(self)), ','.join(parts)) class AttribSafeContextObj(ContextObj): """The :term:`tmpl_context` object, with lax attribute access ( returns '' when the attribute does not exist)""" def __getattr__(self, name): try: return object.__getattribute__(self, name) except AttributeError: log.debug("No attribute called %s found on c object, returning " "empty string", name) return '' class PylonsTemplate(Template): _template_dir = ('pylons', 'templates/default_project') template_renderer = staticmethod(paste_script_template_renderer) summary = 'Pylons application template' egg_plugins = ['PasteScript', 'Pylons'] vars = [ var('template_engine', 'mako/genshi/jinja2/etc: Template language', default='mako'), var('sqlalchemy', 'True/False: Include SQLAlchemy configuration', default=False), ] ensure_names = ['description', 'author', 'author_email', 'url'] def pre(self, command, output_dir, vars): """Called before template is applied.""" package_logger = vars['package'] if package_logger == 'root': # Rename the app logger in the rare case a project is named 'root' package_logger = 'app' vars['package_logger'] = package_logger vars['template_engine'] = 'mako' template_engine = 'mako' if template_engine == 'mako': # Support a Babel extractor default for Mako vars['babel_templates_extractor'] = \ ("('templates/**.mako', 'mako', {'input_encoding': 'utf-8'})" ",\n%s#%s" % (' ' * 4, ' ' * 8)) else: vars['babel_templates_extractor'] = '' # Ensure these exist in the namespace for name in self.ensure_names: vars.setdefault(name, '') vars['version'] = vars.get('version', '0.1') vars['zip_safe'] = asbool(vars.get('zip_safe', 'false')) vars['sqlalchemy'] = asbool(vars.get('sqlalchemy', 'false')) class MinimalPylonsTemplate(PylonsTemplate): _template_dir = ('pylons', 'templates/minimal_project') summary = 'Pylons minimal application template' vars = [ var('template_engine', 'mako/genshi/jinja2/etc: Template language', default='mako'), ] class LegacyPylonsTemplate(PylonsTemplate): _template_dir = ('pylons', 'templates/legacy_project') summary = 'Pylons legacy application template' vars = [ var('template_engine', 'mako/genshi/jinja2/etc: Template language', default='mako'), ] class NewPylonsTemplate(PylonsTemplate): _template_dir = ('pylons', 'templates/new_project') summary = 'Pylons "newstyle" application template' vars = [] class NewMinimalPylonsTemplate(PylonsTemplate): _template_dir = ('pylons', 'templates/newminimal_project') summary = 'Pylons "newstyle" minimal application template' vars = [] class NewSQLAlchemyTemplate(PylonsTemplate): _template_dir = ('pylons', 'templates/newsqla_project') summary = 'Pylons "newstyle" SQLAlchemy template' vars = [] class PylonsInstaller(Installer): use_cheetah = False config_file = 'config/deployment.ini_tmpl' def config_content(self, command, vars): """ Called by ``self.write_config``, this returns the text content for the config file, given the provided variables. """ modules = [line.strip() for line in self.dist.get_metadata_lines('top_level.txt') if line.strip() and not line.strip().startswith('#')] if not modules: print >> sys.stderr, 'No modules are listed in top_level.txt' print >> sys.stderr, \ 'Try running python setup.py egg_info to regenerate that file' for module in modules: if pkg_resources.resource_exists(module, self.config_file): return self.template_renderer( pkg_resources.resource_string(module, self.config_file), vars, filename=self.config_file) # Legacy support for the old location in egg-info return super(PylonsInstaller, self).config_content(command, vars) def resolve_dotted(name): return pkg_resources.EntryPoint.parse('x=%s' % name).load(False) Pylons-1.0.2/pylons/templating.py0000644000175000017500000002667712451647626016431 0ustar benben00000000000000"""Render functions and helpers Render functions and helpers ============================ :mod:`pylons.templating` includes several basic render functions, :func:`render_mako`, :func:`render_genshi` and :func:`render_jinja2` that render templates from the file-system with the assumption that variables intended for the will be attached to :data:`tmpl_context` (hereafter referred to by its short name of :data:`c` which it is commonly imported as). The default render functions work with the template language loader object that is setup on the :data:`app_globals` object in the project's :file:`config/environment.py`. Usage ----- Generally, one of the render functions will be imported in the controller. Variables intended for the template are attached to the :data:`c` object. The render functions return unicode (they actually return :class:`~webhelpers.html.literal` objects, a subclass of unicode). .. admonition :: Tip :data:`tmpl_context` (template context) is abbreviated to :data:`c` instead of its full name since it will likely be used extensively and it's much faster to use :data:`c`. Of course, for users that can't tolerate one-letter variables, feel free to not import :data:`tmpl_context` as :data:`c` since both names are available in templates as well. Example of rendering a template with some variables:: from pylons import tmpl_context as c from pylons.templating import render_mako as render from sampleproject.lib.base import BaseController class SampleController(BaseController): def index(self): c.first_name = "Joe" c.last_name = "Smith" return render('/some/template.mako') And the accompanying Mako template: .. code-block:: mako Hello ${c.first name}, I see your lastname is ${c.last_name}! Your controller will have additional default imports for commonly used functions. Template Globals ---------------- Templates rendered in Pylons should include the default Pylons globals as the :func:`render_mako`, :func:`render_genshi` and :func:`render_jinja2` functions. The full list of Pylons globals that are included in the template's namespace are: - :term:`c` -- Template context object - :term:`tmpl_context` -- Template context object - :data:`config` -- Pylons :class:`~pylons.configuration.PylonsConfig` object (acts as a dict) - :term:`app_globals` -- Project application globals object - :term:`h` -- Project helpers module reference - :data:`request` -- Pylons :class:`~pylons.controllers.util.Request` object for this request - :data:`response` -- Pylons :class:`~pylons.controllers.util.Response` object for this request - :class:`session` -- Pylons session object (unless Sessions are removed) - :class:`url ` -- Routes url generator object - :class:`translator` -- Gettext translator object configured for current locale - :func:`ungettext` -- Unicode capable version of gettext's ngettext function (handles plural translations) - :func:`_` -- Unicode capable gettext translate function - :func:`N_` -- gettext no-op function to mark a string for translation, but doesn't actually translate Configuring the template language --------------------------------- The template engine is created in the projects ``config/environment.py`` and attached to the ``app_globals`` (g) instance. Configuration options can be directly passed into the template engine, and are used by the render functions. .. warning:: Don't change the variable name on :data:`app_globals` that the template loader is attached to if you want to use the render_* functions that :mod:`pylons.templating` comes with. The render_* functions look for the template loader to render the template. """ import logging from webhelpers.html import literal import pylons __all__ = ['render_genshi', 'render_jinja2', 'render_mako'] PYLONS_VARS = ['c', 'app_globals', 'config', 'h', 'render', 'request', 'session', 'translator', 'ungettext', '_', 'N_'] log = logging.getLogger(__name__) def pylons_globals(): """Create and return a dictionary of global Pylons variables Render functions should call this to retrieve a list of global Pylons variables that should be included in the global template namespace if possible. Pylons variables that are returned in the dictionary: ``c``, ``h``, ``_``, ``N_``, config, request, response, translator, ungettext, ``url`` If SessionMiddleware is being used, ``session`` will also be available in the template namespace. """ conf = pylons.config._current_obj() c = pylons.tmpl_context._current_obj() app_globals = conf.get('pylons.app_globals') pylons_vars = dict( c=c, tmpl_context=c, config=conf, app_globals=app_globals, h=conf.get('pylons.h'), request=pylons.request._current_obj(), response=pylons.response._current_obj(), url=pylons.url._current_obj(), translator=pylons.translator._current_obj(), ungettext=pylons.i18n.ungettext, _=pylons.i18n._, N_=pylons.i18n.N_ ) # If the session was overriden to be None, don't populate the session # var econf = pylons.config['pylons.environ_config'] if 'beaker.session' in pylons.request.environ or \ ('session' in econf and econf['session'] in pylons.request.environ): pylons_vars['session'] = pylons.session._current_obj() log.debug("Created render namespace with pylons vars: %s", pylons_vars) return pylons_vars def cached_template(template_name, render_func, ns_options=(), cache_key=None, cache_type=None, cache_expire=None, **kwargs): """Cache and render a template Cache a template to the namespace ``template_name``, along with a specific key if provided. Basic Options ``template_name`` Name of the template, which is used as the template namespace. ``render_func`` Function used to generate the template should it no longer be valid or doesn't exist in the cache. ``ns_options`` Tuple of strings, that should correspond to keys likely to be in the ``kwargs`` that should be used to construct the namespace used for the cache. For example, if the template language supports the 'fragment' option, the namespace should include it so that the cached copy for a template is not the same as the fragment version of it. Caching options (uses Beaker caching middleware) ``cache_key`` Key to cache this copy of the template under. ``cache_type`` Valid options are ``dbm``, ``file``, ``memory``, ``database``, or ``memcached``. ``cache_expire`` Time in seconds to cache this template with this ``cache_key`` for. Or use 'never' to designate that the cache should never expire. The minimum key required to trigger caching is ``cache_expire='never'`` which will cache the template forever seconds with no key. """ # If one of them is not None then the user did set something if cache_key is not None or cache_expire is not None or cache_type \ is not None: if not cache_type: cache_type = 'dbm' if not cache_key: cache_key = 'default' if cache_expire == 'never': cache_expire = None namespace = template_name for name in ns_options: namespace += str(kwargs.get(name)) cache = pylons.cache.get_cache(namespace, type=cache_type) content = cache.get_value(cache_key, createfunc=render_func, expiretime=cache_expire) return content else: return render_func() def render_mako(template_name, extra_vars=None, cache_key=None, cache_type=None, cache_expire=None): """Render a template with Mako Accepts the cache options ``cache_key``, ``cache_type``, and ``cache_expire``. """ # Create a render callable for the cache function def render_template(): # Pull in extra vars if needed globs = extra_vars or {} # Second, get the globals globs.update(pylons_globals()) # Grab a template reference template = globs['app_globals'].mako_lookup.get_template(template_name) return literal(template.render_unicode(**globs)) return cached_template(template_name, render_template, cache_key=cache_key, cache_type=cache_type, cache_expire=cache_expire) def render_mako_def(template_name, def_name, cache_key=None, cache_type=None, cache_expire=None, **kwargs): """Render a def block within a Mako template Takes the template name, and the name of the def within it to call. If the def takes arguments, they should be passed in as keyword arguments. Example:: # To call the def 'header' within the 'layout.mako' template # with a title argument render_mako_def('layout.mako', 'header', title='Testing') Also accepts the cache options ``cache_key``, ``cache_type``, and ``cache_expire``. """ # Create a render callable for the cache function def render_template(): # Pull in extra vars if needed globs = kwargs or {} # Second, get the globals globs.update(pylons_globals()) # Grab a template reference template = globs['app_globals'].mako_lookup.get_template( template_name).get_def(def_name) return literal(template.render_unicode(**globs)) return cached_template(template_name, render_template, cache_key=cache_key, cache_type=cache_type, cache_expire=cache_expire) def render_genshi(template_name, extra_vars=None, cache_key=None, cache_type=None, cache_expire=None, method='xhtml'): """Render a template with Genshi Accepts the cache options ``cache_key``, ``cache_type``, and ``cache_expire`` in addition to method which are passed to Genshi's render function. """ # Create a render callable for the cache function def render_template(): # Pull in extra vars if needed globs = extra_vars or {} # Second, get the globals globs.update(pylons_globals()) # Grab a template reference template = globs['app_globals'].genshi_loader.load(template_name) return literal(template.generate(**globs).render(method=method, encoding=None)) return cached_template(template_name, render_template, cache_key=cache_key, cache_type=cache_type, cache_expire=cache_expire, ns_options=('method'), method=method) def render_jinja2(template_name, extra_vars=None, cache_key=None, cache_type=None, cache_expire=None): """Render a template with Jinja2 Accepts the cache options ``cache_key``, ``cache_type``, and ``cache_expire``. """ # Create a render callable for the cache function def render_template(): # Pull in extra vars if needed globs = extra_vars or {} # Second, get the globals globs.update(pylons_globals()) # Grab a template reference template = \ globs['app_globals'].jinja2_env.get_template(template_name) return literal(template.render(**globs)) return cached_template(template_name, render_template, cache_key=cache_key, cache_type=cache_type, cache_expire=cache_expire) Pylons-1.0.2/pylons/__init__.py0000644000175000017500000000265112451647626016006 0ustar benben00000000000000"""Base objects to be exported for use in Controllers""" # Import pkg_resources first so namespace handling is properly done so the # paste imports work import pkg_resources from paste.registry import StackedObjectProxy from pylons.configuration import config from pylons.controllers.util import Request from pylons.controllers.util import Response __all__ = ['app_globals', 'cache', 'config', 'request', 'response', 'session', 'tmpl_context', 'url', 'Request', 'Response'] def __figure_version(): try: from pkg_resources import require import os # NOTE: this only works when the package is either installed, # or has an .egg-info directory present (i.e. wont work with raw # SVN checkout) info = require('pylons')[0] if os.path.normcase(os.path.realpath(os.path.dirname( os.path.dirname(__file__)))) == info.location: return info.version else: return '(not installed)' except: return '(not installed)' __version__ = __figure_version() app_globals = StackedObjectProxy(name="app_globals") cache = StackedObjectProxy(name="cache") request = StackedObjectProxy(name="request") response = StackedObjectProxy(name="response") session = StackedObjectProxy(name="session") tmpl_context = StackedObjectProxy(name="tmpl_context or C") url = StackedObjectProxy(name="url") translator = StackedObjectProxy(name="translator") Pylons-1.0.2/pylons/i18n/0000755000175000017500000000000012553621453014441 5ustar benben00000000000000Pylons-1.0.2/pylons/i18n/__init__.py0000644000175000017500000000014012451647626016554 0ustar benben00000000000000"""Internationalization and Localization functionality""" from pylons.i18n.translation import * Pylons-1.0.2/pylons/i18n/translation.py0000644000175000017500000001337012451647626017364 0ustar benben00000000000000"""Translation/Localization functions. Provides :mod:`gettext` translation functions via an app's ``pylons.translator`` and get/set_lang for changing the language translated to. """ import os from gettext import NullTranslations, translation import pylons __all__ = ['_', 'add_fallback', 'get_lang', 'gettext', 'gettext_noop', 'lazy_gettext', 'lazy_ngettext', 'lazy_ugettext', 'lazy_ungettext', 'ngettext', 'set_lang', 'ugettext', 'ungettext', 'LanguageError', 'N_'] class LanguageError(Exception): """Exception raised when a problem occurs with changing languages""" pass class LazyString(object): """Has a number of lazily evaluated functions replicating a string. Just override the eval() method to produce the actual value. This method copied from TurboGears. """ def __init__(self, func, *args, **kwargs): self.func = func self.args = args self.kwargs = kwargs def eval(self): return self.func(*self.args, **self.kwargs) def __unicode__(self): return unicode(self.eval()) def __str__(self): return str(self.eval()) def __mod__(self, other): return self.eval() % other def format(self, *args): return self.eval().format(*args) def lazify(func): """Decorator to return a lazy-evaluated version of the original""" def newfunc(*args, **kwargs): return LazyString(func, *args, **kwargs) newfunc.__name__ = 'lazy_%s' % func.__name__ newfunc.__doc__ = 'Lazy-evaluated version of the %s function\n\n%s' % \ (func.__name__, func.__doc__) return newfunc def gettext_noop(value): """Mark a string for translation without translating it. Returns value. Used for global strings, e.g.:: foo = N_('Hello') class Bar: def __init__(self): self.local_foo = _(foo) h.set_lang('fr') assert Bar().local_foo == 'Bonjour' h.set_lang('es') assert Bar().local_foo == 'Hola' assert foo == 'Hello' """ return value N_ = gettext_noop def gettext(value): """Mark a string for translation. Returns the localized string of value. Mark a string to be localized as follows:: gettext('This should be in lots of languages') """ return pylons.translator.gettext(value) lazy_gettext = lazify(gettext) def ugettext(value): """Mark a string for translation. Returns the localized unicode string of value. Mark a string to be localized as follows:: _('This should be in lots of languages') """ return pylons.translator.ugettext(value) _ = ugettext lazy_ugettext = lazify(ugettext) def ngettext(singular, plural, n): """Mark a string for translation. Returns the localized string of the pluralized value. This does a plural-forms lookup of a message id. ``singular`` is used as the message id for purposes of lookup in the catalog, while ``n`` is used to determine which plural form to use. The returned message is a string. Mark a string to be localized as follows:: ngettext('There is %(num)d file here', 'There are %(num)d files here', n) % {'num': n} """ return pylons.translator.ngettext(singular, plural, n) lazy_ngettext = lazify(ngettext) def ungettext(singular, plural, n): """Mark a string for translation. Returns the localized unicode string of the pluralized value. This does a plural-forms lookup of a message id. ``singular`` is used as the message id for purposes of lookup in the catalog, while ``n`` is used to determine which plural form to use. The returned message is a Unicode string. Mark a string to be localized as follows:: ungettext('There is %(num)d file here', 'There are %(num)d files here', n) % {'num': n} """ return pylons.translator.ungettext(singular, plural, n) lazy_ungettext = lazify(ungettext) def _get_translator(lang, **kwargs): """Utility method to get a valid translator object from a language name""" if not lang: return NullTranslations() if 'pylons_config' in kwargs: conf = kwargs.pop('pylons_config') else: conf = pylons.config.current_conf() localedir = os.path.join(conf['pylons.paths']['root'], 'i18n') if not isinstance(lang, list): lang = [lang] try: translator = translation(conf['pylons.package'], localedir, languages=lang, **kwargs) except IOError, ioe: raise LanguageError('IOError: %s' % ioe) translator.pylons_lang = lang return translator def set_lang(lang, set_environ=True, **kwargs): """Set the current language used for translations. ``lang`` should be a string or a list of strings. If a list of strings, the first language is set as the main and the subsequent languages are added as fallbacks. """ translator = _get_translator(lang, **kwargs) if not set_environ: return translator environ = pylons.request.environ environ['pylons.pylons'].translator = translator if 'paste.registry' in environ: environ['paste.registry'].replace(pylons.translator, translator) def get_lang(): """Return the current i18n language used""" return getattr(pylons.translator, 'pylons_lang', None) def add_fallback(lang, **kwargs): """Add a fallback language from which words not matched in other languages will be translated to. This fallback will be associated with the currently selected language -- that is, resetting the language via set_lang() resets the current fallbacks. This function can be called multiple times to add multiple fallbacks. """ return pylons.translator.add_fallback(_get_translator(lang, **kwargs)) Pylons-1.0.2/pylons/configuration.py0000644000175000017500000002011712451647626017113 0ustar benben00000000000000"""Configuration object and defaults setup The PylonsConfig object is initialized in pylons projects inside the :file:`config/environment.py` module. Importing the :data:`config` object from module causes the PylonsConfig object to be created, and setup in app-safe manner so that multiple apps being setup avoid conflicts. After importing :data:`config`, the project should then call :meth:`~PylonsConfig.init_app` with the appropriate options to setup the configuration. In the config data passed with :meth:`~PylonsConfig.init_app`, various defaults are set use with Paste and Routes. """ import copy import logging import os from paste.config import DispatchingConfig from paste.deploy.converters import asbool from webhelpers.mimehelper import MIMETypes request_defaults = dict(charset='utf-8', errors='replace', decode_param_names=False, language='en-us') response_defaults = dict(content_type='text/html', charset='utf-8', errors='strict', headers={'Cache-Control': 'no-cache', 'Pragma': 'no-cache'}) log = logging.getLogger(__name__) config = DispatchingConfig() class PylonsConfig(dict): """Pylons configuration object The Pylons configuration object is a per-application instance object that retains the information regarding the global and app conf's as well as per-application instance specific data such as the mapper, and the paths for this instance. The config object is available in your application as the Pylons global :data:`pylons.config`. For example:: from pylons import config template_paths = config['pylons.paths']['templates'] There's several useful keys of the config object most people will be interested in: ``pylons.paths`` A dict of absolute paths that were defined in the applications ``config/environment.py`` module. ``pylons.environ_config`` Dict of environ keys for where in the environ to pickup various objects for registering with Pylons. If these are present then PylonsApp will use them from environ rather than using default middleware from Beaker. Valid keys are: ``session, cache`` ``pylons.strict_tmpl_context`` Whether or not the ``tmpl_context`` object should throw an attribute error when access is attempted to an attribute that doesn't exist. Defaults to True. ``pylons.tmpl_context_attach_args`` Whethor or not Routes variables should automatically be attached to the tmpl_context object when specified in a controllers method. ``pylons.request_options`` A dict of Content-Type related default settings for new instances of :class:`~pylons.controllers.util.Request`. May contain the values ``charset`` and ``errors`` and ``decode_param_names``. Overrides the Pylons default values specified by the ``request_defaults`` dict. ``pylons.response_options`` A dict of Content-Type related default settings for new instances of :class:`~pylons.controllers.util.Response`. May contain the values ``content_type``, ``charset`` and ``errors``. Overrides the Pylons default values specified by the ``response_defaults`` dict. ``routes.map`` Mapper object used for Routing. Yes, it is possible to add routes after your application has started running. """ defaults = { 'debug': False, 'pylons.package': None, 'pylons.paths': {'root': None, 'controllers': None, 'templates': [], 'static_files': None}, 'pylons.environ_config': dict(session='beaker.session', cache='beaker.cache'), 'pylons.app_globals': None, 'pylons.h': None, 'pylons.request_options': request_defaults.copy(), 'pylons.response_options': response_defaults.copy(), 'pylons.strict_tmpl_context': True, 'pylons.tmpl_context_attach_args': False, } def init_app(self, global_conf, app_conf, package=None, paths=None): """Initialize configuration for the application .. note This *must* be called at least once, as soon as possible to setup all the configuration options. ``global_conf`` Several options are expected to be set for a Pylons web application. They will be loaded from the global_config which has the main Paste options. If ``debug`` is not enabled as a global config option, the following option *must* be set: * error_to - The email address to send the debug error to The optional config options in this case are: * smtp_server - The SMTP server to use, defaults to 'localhost' * error_log - A logfile to write the error to * error_subject_prefix - The prefix of the error email subject * from_address - Whom the error email should be from ``app_conf`` Defaults supplied via the [app:main] section from the Paste config file. ``load_config`` only cares about whether a 'prefix' option is set, if so it will update Routes to ensure URL's take that into account. ``package`` The name of the application package, to be stored in the app_conf. .. versionchanged:: 1.0 ``template_engine`` option is no longer supported. """ log.debug("Initializing configuration, package: '%s'", package) conf = global_conf.copy() conf.update(app_conf) conf.update(dict(app_conf=app_conf, global_conf=global_conf)) conf.update(self.pop('environment_load', {})) if paths: conf['pylons.paths'] = paths conf['pylons.package'] = package conf['debug'] = asbool(conf.get('debug')) # Load the MIMETypes with its default types MIMETypes.init() # Ensure all the keys from defaults are present, load them if not for key, val in copy.deepcopy(PylonsConfig.defaults).iteritems(): conf.setdefault(key, val) # Load the errorware configuration from the Paste configuration file # These all have defaults, and emails are only sent if configured and # if this application is running in production mode errorware = {} errorware['debug'] = conf['debug'] if not errorware['debug']: errorware['debug'] = False errorware['error_email'] = conf.get('email_to') errorware['error_log'] = conf.get('error_log', None) errorware['smtp_server'] = conf.get('smtp_server', 'localhost') errorware['error_subject_prefix'] = conf.get( 'error_subject_prefix', 'WebApp Error: ') errorware['from_address'] = conf.get( 'from_address', conf.get('error_email_from', 'pylons@yourapp.com')) errorware['error_message'] = conf.get('error_message', 'An internal server error occurred') # Copy in some defaults if 'cache_dir' in conf: conf.setdefault('beaker.session.data_dir', os.path.join(conf['cache_dir'], 'sessions')) conf.setdefault('beaker.cache.data_dir', os.path.join(conf['cache_dir'], 'cache')) conf['pylons.cache_dir'] = conf.pop('cache_dir', conf['app_conf'].get('cache_dir')) # Save our errorware values conf['pylons.errorware'] = errorware # Load conf dict into self self.update(conf) pylons_config = PylonsConfig() # Push an empty config so all accesses to config at import time have something # to look at and modify. This config will be merged with the app's when it's # built in the paste.app_factory entry point. pylons_config.update(copy.deepcopy(PylonsConfig.defaults)) config.push_process_config(pylons_config) Pylons-1.0.2/pylons/log.py0000644000175000017500000000502412451647626015025 0ustar benben00000000000000"""Logging related functionality This logging Handler logs to ``environ['wsgi.errors']`` as designated in :pep:`333`. """ import logging import types import pylons __all__ = ['WSGIErrorsHandler'] class WSGIErrorsHandler(logging.Handler): """A handler class that writes logging records to `environ['wsgi.errors']`. This code is derived from CherryPy's :class:`cherrypy._cplogging.WSGIErrorHandler`. ``cache`` Whether the `wsgi.errors` stream is cached (instead of looked up via `pylons.request.environ` per every logged message). Enabling this option is not recommended (particularly for the use case of logging to `wsgi.errors` outside of a request) as the behavior of a cached `wsgi.errors` stream is not strictly defined. In particular, `mod_wsgi `_'s `wsgi.errors` will raise an exception when used outside of a request. """ def __init__(self, cache=False, *args, **kwargs): logging.Handler.__init__(self, *args, **kwargs) self.cache = cache self.cached_stream = None def get_wsgierrors(self): """Return the wsgi.errors stream Raises a TypeError when outside of a web request (pylons.request is not setup) """ if not self.cache: return pylons.request.environ.get('wsgi.errors') elif not self.cached_stream: self.cached_stream = pylons.request.environ.get('wsgi.errors') return self.cached_stream return self.cached_stream def flush(self): """Flushes the stream""" try: stream = self.get_wsgierrors() except TypeError: pass else: if stream: stream.flush() def emit(self, record): """Emit a record""" try: stream = self.get_wsgierrors() except TypeError: pass else: if not stream: return try: msg = self.format(record) fs = "%s\n" if not hasattr(types, "UnicodeType"): # if no unicode support stream.write(fs % msg) else: try: stream.write(fs % msg) except UnicodeError: stream.write(fs % msg.encode("UTF-8")) self.flush() except (KeyboardInterrupt, SystemExit): raise except: self.handleError(record) Pylons-1.0.2/pylons/error.py0000644000175000017500000000225112451647626015374 0ustar benben00000000000000"""Custom EvalException support Provides template engine HTML error formatters for the Template tab of EvalException. """ import sys try: import mako.exceptions except ImportError: mako = None __all__ = ['handle_mako_error'] def handle_mako_error(context, exc): try: exc.is_mako_exception = True except: pass raise (exc, None, sys.exc_info()[2]) def myghty_html_data(exc_value): """Format a Myghty exception as HTML""" if hasattr(exc_value, 'htmlformat'): return exc_value.htmlformat()[333:-14] if hasattr(exc_value, 'mtrace'): return exc_value.mtrace.htmlformat()[333:-14] template_error_formatters = [myghty_html_data] if mako: def mako_html_data(exc_value): """Format a Mako exception as HTML""" if getattr(exc_value, 'is_mako_exception', False) or \ isinstance(exc_value, (mako.exceptions.CompileException, mako.exceptions.SyntaxException)): return mako.exceptions.html_error_template().render(full=False, css=False) template_error_formatters.insert(0, mako_html_data) Pylons-1.0.2/pylons/url.py0000644000175000017500000000274312451647626015053 0ustar benben00000000000000from repoze.bfg.encode import urlencode from repoze.bfg.threadlocal import get_current_registry from repoze.bfg.url import _join_elements from pylons.interfaces import IRoutesMapper def route_url(route_name, request, *elements, **kw): try: reg = request.registry except AttributeError: reg = get_current_registry() # b/c mapper = reg.getUtility(IRoutesMapper) route = mapper.routes.get(route_name) if route and 'custom_url_generator' in route.__dict__: route_name, request, elements, kw = route.custom_url_generator( route_name, request, *elements, **kw) anchor = '' qs = '' app_url = None if '_query' in kw: qs = '?' + urlencode(kw.pop('_query'), doseq=True) if '_anchor' in kw: anchor = kw.pop('_anchor') if isinstance(anchor, unicode): anchor = anchor.encode('utf-8') anchor = '#' + anchor if '_app_url' in kw: app_url = kw.pop('_app_url') path = mapper.generate(route_name, kw) # raises KeyError if generate fails if elements: suffix = _join_elements(elements) if not path.endswith('/'): suffix = '/' + suffix else: suffix = '' if app_url is None: # we only defer lookup of application_url until here because # it's somewhat expensive; we won't need to do it if we've # been passed _app_url app_url = request.application_url return app_url + path + suffix + qs + anchor Pylons-1.0.2/pylons/test.py0000644000175000017500000000522612456601140015211 0ustar benben00000000000000"""Test related functionality Adds a Pylons plugin to `nose `_ that loads the Pylons app *before* scanning for doc tests. This can be configured in the projects :file:`setup.cfg` under a ``[nosetests]`` block: .. code-block:: ini [nosetests] with-pylons=development.ini Alternate ini files may be specified if the app should be loaded using a different configuration. """ import os import sys import nose.plugins import pkg_resources from paste.deploy import loadapp import pylons from pylons.i18n.translation import _get_translator pylonsapp = None class PylonsPlugin(nose.plugins.Plugin): """Nose plugin extension For use with nose to allow a project to be configured before nose proceeds to scan the project for doc tests and unit tests. This prevents modules from being loaded without a configured Pylons environment. """ enabled = False enableOpt = 'pylons_config' name = 'pylons' def options(self, parser, env=os.environ): """Add command-line options for this plugin""" env_opt = 'NOSE_WITH_%s' % self.name.upper() env_opt.replace('-', '_') parser.add_option("--with-%s" % self.name, dest=self.enableOpt, type="string", default="", help="Setup Pylons environment with the config file" " specified by ATTR [NOSE_ATTR]") def configure(self, options, conf): """Configure the plugin""" self.config_file = None self.conf = conf if hasattr(options, self.enableOpt): self.enabled = bool(getattr(options, self.enableOpt)) self.config_file = getattr(options, self.enableOpt) def begin(self): """Called before any tests are collected or run Loads the application, and in turn its configuration. """ global pylonsapp path = os.getcwd() sys.path.insert(0, path) pkg_resources.working_set.add_entry(path) self.app = pylonsapp = loadapp('config:' + self.config_file, relative_to=path) # Setup the config and app_globals, only works if we can get # to the config object conf = getattr(pylonsapp, 'config') if conf: pylons.config._push_object(conf) if 'pylons.app_globals' in conf: pylons.app_globals._push_object(conf['pylons.app_globals']) # Initialize a translator for tests that utilize i18n translator = _get_translator(pylons.config.get('lang')) pylons.translator._push_object(translator) Pylons-1.0.2/pylons/decorators/0000755000175000017500000000000012553621453016027 5ustar benben00000000000000Pylons-1.0.2/pylons/decorators/util.py0000644000175000017500000000113612451647626017366 0ustar benben00000000000000"""Decorator internal utilities""" import pylons from pylons.controllers import WSGIController def get_pylons(decorator_args): """Return the `pylons` object: either the :mod`~pylons` module or the :attr:`~WSGIController._py_object` equivalent, searching a decorator's *args for the latter :attr:`~WSGIController._py_object` is more efficient as it provides direct access to the Pylons global variables. """ if decorator_args: controller = decorator_args[0] if isinstance(controller, WSGIController): return controller._py_object return pylons Pylons-1.0.2/pylons/decorators/__init__.py0000644000175000017500000001760712451647626020162 0ustar benben00000000000000"""Pylons Decorators Common decorators intended for use in controllers. Additional decorators for use with controllers are in the :mod:`~pylons.decorators.cache`, :mod:`~pylons.decorators.rest` and :mod:`~pylons.decorators.secure` modules. """ import logging import warnings import formencode import simplejson from decorator import decorator from formencode import api, htmlfill, variabledecode from pylons.decorators.util import get_pylons from pylons.i18n import _ as pylons_gettext __all__ = ['jsonify', 'validate'] log = logging.getLogger(__name__) class JSONEncoder(simplejson.JSONEncoder): def default(self, obj): encoder = getattr(obj, '__json__', None) if encoder is not None: return encoder() return super(JSONEncoder, self).default(obj) @decorator def jsonify(func, *args, **kwargs): """Action decorator that formats output for JSON Given a function that will return content, this decorator will turn the result into JSON, with a content-type of 'application/json' and output it. """ pylons = get_pylons(args) pylons.response.headers['Content-Type'] = 'application/json; charset=utf-8' data = func(*args, **kwargs) if isinstance(data, (list, tuple)): msg = "JSON responses with Array envelopes are susceptible to " \ "cross-site data leak attacks, see " \ "http://wiki.pylonshq.com/display/pylonsfaq/Warnings" warnings.warn(msg, Warning, 2) log.warning(msg) log.debug("Returning JSON wrapped action output") return simplejson.dumps(data, cls=JSONEncoder, encoding='utf-8') def validate(schema=None, validators=None, form=None, variable_decode=False, dict_char='.', list_char='-', post_only=True, state=None, on_get=False, **htmlfill_kwargs): """Validate input either for a FormEncode schema, or individual validators Given a form schema or dict of validators, validate will attempt to validate the schema or validator list. If validation was successful, the valid result dict will be saved as ``self.form_result``. Otherwise, the action will be re-run as if it was a GET, and the output will be filled by FormEncode's htmlfill to fill in the form field errors. ``schema`` Refers to a FormEncode Schema object to use during validation. ``form`` Method used to display the form, which will be used to get the HTML representation of the form for error filling. ``variable_decode`` Boolean to indicate whether FormEncode's variable decode function should be run on the form input before validation. ``dict_char`` Passed through to FormEncode. Toggles the form field naming scheme used to determine what is used to represent a dict. This option is only applicable when used with variable_decode=True. ``list_char`` Passed through to FormEncode. Toggles the form field naming scheme used to determine what is used to represent a list. This option is only applicable when used with variable_decode=True. ``post_only`` Boolean that indicates whether or not GET (query) variables should be included during validation. .. warning:: ``post_only`` applies to *where* the arguments to be validated come from. It does *not* restrict the form to only working with post, merely only checking POST vars. ``state`` Passed through to FormEncode for use in validators that utilize a state object. ``on_get`` Whether to validate on GET requests. By default only POST requests are validated. Example:: class SomeController(BaseController): def create(self, id): return render('/myform.mako') @validate(schema=model.forms.myshema(), form='create') def update(self, id): # Do something with self.form_result pass """ if state is None: state = PylonsFormEncodeState def wrapper(func, self, *args, **kwargs): """Decorator Wrapper function""" request = self._py_object.request errors = {} # Skip the validation if on_get is False and its a GET if not on_get and request.environ['REQUEST_METHOD'] == 'GET': return func(self, *args, **kwargs) # If they want post args only, use just the post args if post_only: params = request.POST else: params = request.params params = params.mixed() if variable_decode: log.debug("Running variable_decode on params") decoded = variabledecode.variable_decode(params, dict_char, list_char) else: decoded = params if schema: log.debug("Validating against a schema") try: self.form_result = schema.to_python(decoded, state) except formencode.Invalid, e: errors = e.unpack_errors(variable_decode, dict_char, list_char) if validators: log.debug("Validating against provided validators") if isinstance(validators, dict): if not hasattr(self, 'form_result'): self.form_result = {} for field, validator in validators.iteritems(): try: self.form_result[field] = \ validator.to_python(decoded.get(field), state) except formencode.Invalid, error: errors[field] = error if errors: log.debug("Errors found in validation, parsing form with htmlfill " "for errors") request.environ['REQUEST_METHOD'] = 'GET' self._py_object.tmpl_context.form_errors = errors # If there's no form supplied, just continue with the current # function call. if not form: return func(self, *args, **kwargs) request.environ['pylons.routes_dict']['action'] = form response = self._dispatch_call() # If the form_content is an exception response, return it if hasattr(response, '_exception'): return response htmlfill_kwargs2 = htmlfill_kwargs.copy() htmlfill_kwargs2.setdefault('encoding', request.charset) return htmlfill.render(response, defaults=params, errors=errors, **htmlfill_kwargs2) return func(self, *args, **kwargs) return decorator(wrapper) def pylons_formencode_gettext(value): """Translates a string ``value`` using pylons gettext first and if that fails, formencode gettext. This allows to "merge" localized error messages from built-in FormEncode's validators with application-specific validators. """ trans = pylons_gettext(value) if trans == value: # translation failed, try formencode trans = api._stdtrans(value) return trans class PylonsFormEncodeState(object): """A ``state`` for FormEncode validate API that includes smart ``_`` hook. The FormEncode library used by validate() decorator has some provision for localizing error messages. In particular, it looks for attribute ``_`` in the application-specific state object that gets passed to every ``.to_python()`` call. If it is found, the ``_`` is assumed to be a gettext-like function and is called to localize error messages. One complication is that FormEncode ships with localized error messages for standard validators so the user may want to re-use them instead of gathering and translating everything from scratch. To allow this, we pass as ``_`` a function which looks up translation both in application and formencode message catalogs. """ _ = staticmethod(pylons_formencode_gettext) Pylons-1.0.2/pylons/decorators/cache.py0000644000175000017500000001305612451647626017460 0ustar benben00000000000000"""Caching decorator""" import inspect import logging import time from decorator import decorator from paste.deploy.converters import asbool from pylons.decorators.util import get_pylons log = logging.getLogger(__name__) def beaker_cache(key="cache_default", expire="never", type=None, query_args=False, cache_headers=('content-type', 'content-length'), invalidate_on_startup=False, cache_response=True, **b_kwargs): """Cache decorator utilizing Beaker. Caches action or other function that returns a pickle-able object as a result. Optional arguments: ``key`` None - No variable key, uses function name as key "cache_default" - Uses all function arguments as the key string - Use kwargs[key] as key list - Use [kwargs[k] for k in list] as key ``expire`` Time in seconds before cache expires, or the string "never". Defaults to "never" ``type`` Type of cache to use: dbm, memory, file, memcached, or None for Beaker's default ``query_args`` Uses the query arguments as the key, defaults to False ``cache_headers`` A tuple of header names indicating response headers that will also be cached. ``invalidate_on_startup`` If True, the cache will be invalidated each time the application starts or is restarted. ``cache_response`` Determines whether the response at the time beaker_cache is used should be cached or not, defaults to True. .. note:: When cache_response is set to False, the cache_headers argument is ignored as none of the response is cached. If cache_enabled is set to False in the .ini file, then cache is disabled globally. """ if invalidate_on_startup: starttime = time.time() else: starttime = None cache_headers = set(cache_headers) def wrapper(func, *args, **kwargs): """Decorator wrapper""" pylons = get_pylons(args) log.debug("Wrapped with key: %s, expire: %s, type: %s, query_args: %s", key, expire, type, query_args) enabled = pylons.config.get("cache_enabled", "True") if not asbool(enabled): log.debug("Caching disabled, skipping cache lookup") return func(*args, **kwargs) if key: key_dict = kwargs.copy() key_dict.update(_make_dict_from_args(func, args)) if query_args: key_dict.update(pylons.request.GET.mixed()) if key != "cache_default": if isinstance(key, list): key_dict = dict((k, key_dict[k]) for k in key) else: key_dict = {key: key_dict[key]} else: key_dict = None self = None if args: self = args[0] namespace, cache_key = create_cache_key(func, key_dict, self) if type: b_kwargs['type'] = type cache_obj = getattr(pylons.app_globals, 'cache', None) if not cache_obj: cache_obj = getattr(pylons, 'cache', None) if not cache_obj: raise Exception('No CacheMiddleware or cache object on ' ' app_globals was found') my_cache = cache_obj.get_cache(namespace, **b_kwargs) if expire == "never": cache_expire = None else: cache_expire = expire def create_func(): log.debug("Creating new cache copy with key: %s, type: %s", cache_key, type) result = func(*args, **kwargs) glob_response = pylons.response headers = glob_response.headerlist status = glob_response.status full_response = dict(headers=headers, status=status, cookies=None, content=result) return full_response response = my_cache.get_value(cache_key, createfunc=create_func, expiretime=cache_expire, starttime=starttime) if cache_response: glob_response = pylons.response glob_response.headerlist = [header for header in response['headers'] if header[0].lower() in cache_headers] glob_response.status = response['status'] return response['content'] return decorator(wrapper) def create_cache_key(func, key_dict=None, self=None): """Get a cache namespace and key used by the beaker_cache decorator. Example:: from pylons import cache from pylons.decorators.cache import create_cache_key namespace, key = create_cache_key(MyController.some_method) cache.get_cache(namespace).remove(key) """ kls = None if hasattr(func, 'im_func'): kls = func.im_class func = func.im_func cache_key = func.__name__ else: cache_key = func.__name__ if key_dict: cache_key += " " + " ".join("%s=%s" % (k, v) for k, v in key_dict.iteritems()) if not kls and self: kls = getattr(self, '__class__', None) if kls: return '%s.%s' % (kls.__module__, kls.__name__), cache_key else: return func.__module__, cache_key def _make_dict_from_args(func, args): """Inspects function for name of args""" args_keys = {} for i, arg in enumerate(inspect.getargspec(func)[0]): if arg != "self": args_keys[arg] = args[i] return args_keys Pylons-1.0.2/pylons/decorators/secure.py0000644000175000017500000000714112451647626017701 0ustar benben00000000000000"""Security related decorators""" import logging import urlparse from decorator import decorator try: import webhelpers.html.secure_form as secure_form except ImportError: import webhelpers.pylonslib.secure_form as secure_form from pylons.controllers.util import abort, redirect from pylons.decorators.util import get_pylons __all__ = ['authenticate_form', 'https'] log = logging.getLogger(__name__) csrf_detected_message = ( "Cross-site request forgery detected, request denied. See " "http://en.wikipedia.org/wiki/Cross-site_request_forgery for more " "information.") def authenticated_form(params): submitted_token = params.get(secure_form.token_key) return submitted_token is not None and \ submitted_token == secure_form.authentication_token() @decorator def authenticate_form(func, *args, **kwargs): """Decorator for authenticating a form This decorator uses an authorization token stored in the client's session for prevention of certain Cross-site request forgery (CSRF) attacks (See http://en.wikipedia.org/wiki/Cross-site_request_forgery for more information). For use with the ``webhelpers.html.secure_form`` helper functions. """ request = get_pylons(args).request if authenticated_form(request.params): try: del request.POST[secure_form.token_key] except KeyError: del request.GET[secure_form.token_key] return func(*args, **kwargs) else: log.warn('Cross-site request forgery detected, request denied: %r ' 'REMOTE_ADDR: %s' % (request, request.remote_addr)) abort(403, detail=csrf_detected_message) def https(url_or_callable=None): """Decorator to redirect to the SSL version of a page if not currently using HTTPS. Apply this decorator to controller methods (actions). Takes a url argument: either a string url, or a callable returning a string url. The callable will be called with no arguments when the decorated method is called. The url's scheme will be rewritten to https if necessary. Non-HTTPS POST requests are aborted (405 response code) by this decorator. Example: .. code-block:: python # redirect to HTTPS /pylons @https('/pylons') def index(self): do_secure() # redirect to HTTPS /auth/login, delaying the url() call until # later (as the url object may not be functional when the # decorator/method are defined) @https(lambda: url(controller='auth', action='login')) def login(self): do_secure() # redirect to HTTPS version of myself @https() def get(self): do_secure() """ def wrapper(func, *args, **kwargs): """Decorator Wrapper function""" request = get_pylons(args).request if request.scheme.lower() == 'https': return func(*args, **kwargs) if request.method.upper() == 'POST': # don't allow POSTs (raises an exception) abort(405, headers=[('Allow', 'GET')]) if url_or_callable is None: url = request.url elif callable(url_or_callable): url = url_or_callable() else: url = url_or_callable # Ensure an https scheme, which also needs a host parts = urlparse.urlparse(url) url = urlparse.urlunparse(('https', parts[1] or request.host) + parts[2:]) log.debug('Redirecting non-https request: %s to: %s', request.path_info, url) redirect(url) return decorator(wrapper) Pylons-1.0.2/pylons/decorators/rest.py0000644000175000017500000000400312451647626017362 0ustar benben00000000000000"""REST decorators""" import logging from decorator import decorator from pylons.controllers.util import abort from pylons.decorators.util import get_pylons __all__ = ['dispatch_on', 'restrict'] log = logging.getLogger(__name__) def restrict(*methods): """Restricts access to the function depending on HTTP method Example: .. code-block:: python from pylons.decorators import rest class SomeController(BaseController): @rest.restrict('GET') def comment(self, id): """ def check_methods(func, *args, **kwargs): """Wrapper for restrict""" if get_pylons(args).request.method not in methods: log.debug("Method not allowed by restrict") abort(405, headers=[('Allow', ','.join(methods))]) return func(*args, **kwargs) return decorator(check_methods) def dispatch_on(**method_map): """Dispatches to alternate controller methods based on HTTP method Multiple keyword arguments should be passed, with the keyword corresponding to the HTTP method to dispatch on (DELETE, POST, GET, etc.) and the value being the function to call. The value should be a string indicating the name of the function to dispatch to. Example: .. code-block:: python from pylons.decorators import rest class SomeController(BaseController): @rest.dispatch_on(POST='create_comment') def comment(self): # Do something with the comment def create_comment(self, id): # Do something if its a post to comment """ def dispatcher(func, self, *args, **kwargs): """Wrapper for dispatch_on""" alt_method = method_map.get(get_pylons(args).request.method) if alt_method: alt_method = getattr(self, alt_method) log.debug("Dispatching to %s instead", alt_method) return self._inspect_call(alt_method, **kwargs) return func(self, *args, **kwargs) return decorator(dispatcher) Pylons-1.0.2/pylons/media/0000755000175000017500000000000012553621453014741 5ustar benben00000000000000Pylons-1.0.2/pylons/media/style/0000755000175000017500000000000012553621453016101 5ustar benben00000000000000Pylons-1.0.2/pylons/media/style/black.css0000644000175000017500000000275612451647626017710 0ustar benben00000000000000body { font-family: arial, helvetica, sans-serif; background-color: #ffc900; background-image: url(../img/bg.png); background-repeat: repeat-x; width:100%; height:100%; margin:0; max-height: 100%; padding:0; border:none; line-height:1.4; } #container { color:white; background-color:#111; position: absolute; left: 50%; width: 500px; margin-left: -300px; padding:50px; height:100%; } #footer { margin: 120px 0 0 0; padding: 3px; text-align:center; font-size:small; background-color:#222; letter-spacing: 1px; } h1 { text-align:center; font-size:xx-large; font-weight:normal; margin: 0 0 20px 0; border:none; padding:0; letter-spacing: 5px; } h2 { font-size:xx-large; font-weight:normal; margin: 0 0 20px 0; border:none; padding:0; } hr { margin-bottom:30px; border: 1px solid #222; background-color: #222; padding: 2px; } #logo { background-image: url(../img/pylons-logo.gif); background-repeat: no-repeat; height: 0; overflow: hidden; padding-top: 99px; width: 239px; } #left { float:left; width:250px; margin:0 50px 0 0; border:none; padding:0 0 0 10px; } #right { margin:0 0 0 330px; border:none; padding:0; } ul { list-style:none; margin:0; border:none; padding:0; } a:visited { color:white; text-decoration:none; } a:link { color:white; text-decoration:none; } Pylons-1.0.2/pylons/media/style/itraceback.css0000644000175000017500000000544712451647626020724 0ustar benben00000000000000/* @override http://localhost:5000/_debug/media/pylons/style/itraceback.css */ div.credits { padding: 5px 0 0 0; color: #777; font-size: 11px; } #footer { border-top: 1px solid #666666; padding: 0; margin: 20px 0 0 0; } #pylons_logo { float: right; margin: 5px 0 0 0; } div.widget_layout { margin: 30px 0 0 0; } div.feature-highlight { float: right; width: 400px; } div.feature-highlight button { margin: 15px 0 0 20px; } div#service_widget { width: 500px; padding: 0; margin: 0; margin-right: 10px; line-height: 1.4; } div#service_widget h4, div.overviewtab h3 { margin: 0; padding: 0; font-weight: bold; font-size: 100%; } div#service_widget h2 { color: #000; border-bottom: 1px solid #0a0; font-variant: small-caps; font-size: 20px; line-height: 1.3; font-weight: bold; } div.overviewtab, div.posttracebacktab, div.searchtab { padding: 13px 10px 10px 10px; background-color: #f8f8f8; border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; border-left: 1px solid #ccc; } div.clearfix { clear: left; margin: 0; padding: 0; height: 0; } .hide { display: none; } input.query { width: 350px; } p.query { margin: 0 0 0 20px; padding: 0; } /* Nav Bar */ #nv li { display:block; float:left; list-style-type:none; margin:0; padding:0; } #nv a { display:block; float:left; border: 0px; } /*** Tabs ***/ #supportnav { float: left; width: 500px; border-bottom: 1px solid #CCC; margin: 0px; padding: 0px; } #supportnav li { float: left; padding-left: 10px; margin-right: 3px; background: url("../img/tab-traceback.png") no-repeat left top; } #supportnav li.first-child { margin: 0; } #supportnav li a { display: block; padding: 3px 10px 3px 0; border: none; outline: none; background: url("../img/tab-traceback.png") no-repeat right top; color: #666; } #supportnav li a:hover { color: #333; } #supportnav li.active { position: relative; margin-bottom: -1px; background-position: 0 -40px; } #supportnav li.active a { display: block; padding: 3px 10px 4px 0; background: url("../img/tab-traceback.png") no-repeat right -40px; font-weight: bold; color: #333; } #supportnav li.active a { background-position: right -40px; } * html #supportnav { margin-bottom: 0; } div.searchresults div.result { margin-bottom: 5px; padding: 2px 0px 2px 4px; cursor: pointer; background-color: rgb(247, 247, 247); border: 1px solid rgb(235, 235, 235); } div.searchresults div.result div.meta { font-size: 0.8em; color: rgb(1, 116, 22); } p.results a { float: right; } div.searchresults div.blurb { font-size: 0.8em; } div.searchresults div.result a { text-decoration: underline; font-size: 0.9em; cursor: pointer; } Pylons-1.0.2/pylons/media/style/orange.css0000644000175000017500000002151012451647626020074 0ustar benben00000000000000body{ margin: 0px; padding: 0px;/* 4% 0 0;*/ background: #494943 url(../img/bg.jpg) top repeat-x; font-family: Verdana, Arial, sans-serif; font-size: 75%; line-height: 160%; color: #333; /*min-width:770px; max-width: 1100px;*/ } /* Layout Styles */ /*.top-bar{background: #fff url(../img/bar.png) right top no-repeat;} */ div.main-content-bg{ } div.main-content-bar{ } div#nav-bar{ border-top: 1px solid #fff; float: left; width: 100%; margin-top: 16px; background: #fff url(../img/bar-bg.png) right top repeat-x; } div#main-content{ float: left; width: 100%; background: #fff; } div#side-content{ /*background: #FFf url(../img/bar.png) top right no-repeat;*/ padding-top: 42px; float: left; margin-top: 0px; width: 30%; clear: right; height: 550px; } div.three, div.two, div.one{ width: 746px; padding: 0 12px 0px 12px; clear: both; } div.three div.a, div.two div.a{ float: left; clear: left; width: 204px; /*background-color: #ddd;*/ } div.a div.padding, div.b div.padding, div.c div.padding, div.one div.padding{ padding: 0px 12px 20px 12px; } div.three div.b{ float: left; width: 271px; /*background-color: #ccc;*/ } div.three div.c{ float: left; clear: right; width: 271px; /*background-color: #bbb;*/ } div.two div.b{ float: left; clear: right; width: 542px; /* background-color: #333;*/ } /* Logo */ h1#logo{ margin: 20px 5% 0 5%; padding: 0; float: left; width: 155px; height: 52px; /*padding: 25px 5% 0 5%; margin: 0 0 0 -2px; float: left;*/ } /* Nav Bar */ #nav-global { margin:0; white-space:nowrap; float: right; /*position: absolute; margin:0; left:380px; top: 0px;*/ padding-right: 5%; clear: right; padding-bottom: 20px; } #nav-global li { display:block; float:left; list-style-type:none; margin:0; padding:0; } #nav-global a { display:block; float:left; /*font-family:"Trebuchet MS"; font-size: 110%; */ padding:42px 18px 7px 18px; background:#000000; color: #ccc; border: 0px; text-decoration: underline; } #nav-global a:hover { color:white; background: url(../img/main-nav-bg-on.png) bottom repeat-x; border: 0px; } #homepage #nav-homepage a, #overview #nav-overview a, #download #nav-download a, #documentation #nav-documentation a, #weblog #nav-weblog a, #community #nav-community a, #code #nav-code a { color:white; background:#000 url(../img/main-nav-bg.png) bottom repeat-x; } ul#navlist { /*background: url(../img/bar.png) left top no-repeat;*/ margin: 0; padding:0; padding-left: 5%; padding-top: 8px; color: #eee; line-height: 34px; } ul#navlist li { display: inline; } ul#navlist li a { /*font-family: Tahoma, sans-serif; font-size: 11px;font-weight: bold;*/ border: 0px; border-left: 1px solid #49A200; /*padding: 0em 1em;*/ padding: 0 18px 0 18px; color: #fff; margin-right: 9px; text-decoration: none; float: left; background: url('../img/tab-brown.png') no-repeat top right; } ul#navlist li a#highlight , ul#navlist li a#highlight:hover { background: url('../img/tab-yellow-highlight.png') no-repeat top right; color: #fff; padding-right: 33px; } ul#navlist li a:hover { background: url('../img/tab-yellow.png') no-repeat top right; color: #fff; } ul#navlist li.active a.active, ul#main-nav li.active a.active:hover { background: url('../img/tab-white.png') no-repeat top left; color: #333; } /* Font Styles */ a, a:link, a:visited, a:active { color: #0040BB; text-decoration: none; border-bottom: 1px dotted #ccc; } a:hover{ color: #000; border-bottom: 1px dotted #000; } a.no-underline, a.no-underline:link, a.no-underline:visited, a.no-underline:active { border: 0px; } img.no-border{ border: 0px; } /* Paragraph Styles */ .last{ padding-bottom: 0px; margin-bottom: 0px; } .first{ margin-top: 0px; } blockquote { padding-left: 10px; padding-right: 10px; margin-left: 5px; margin-right: 0; border-left: #ddd; border-width: 0 0 0 1px; border-style: none none none solid; } p.first, form{ padding: 0px; margin: 0px; } .medium{ font-family: Verdana, Geneva, Arial, sans-serif; font-size: 11px; line-height: 19px; } .large{ font-size: 110%; } .small{ font-size: 90%; line-height: 150%; font-family: Verdana, sans-serif; color: #000; } p.indent{ padding-left: 15px; padding-bottom: 15px; } tt, code{ font-size: 130%; color: #800000; } pre{ /* border-top: 1px dotted #000; border-left: 1px dotted #000; border-right: 1px solid #999; border-bottom: 1px solid #999; background: #eee;*/ font-size: 120%; padding: 3px 5px 3px 10px; margin-right: 10px; } .go{ /*background: url(../img/go.png) no-repeat right bottom;*/ padding-right: 20px; } .help, a.help{ cursor: help; font-weight: normal; } .highlight{ background: #ffffcc url(../img/highlight.png) repeat; } /* Horizontal Rule */ div.hr { clear: both; line-height: 0px; font-size: 0px; margin: 0px; padding: 0px; /*height: 4px; url(../img/horizontal-rule.png) no-repeat;background: #000; margin-bottom: 20px; width: 770px;*/ } hr { height: 1em; visibility: hidden; margin: 0px; padding: 0px; } /* Form Styles */ .form-style input[type=submit]{ background: #87CD15; color: #fff; border-top: 1px solid #999; border-left: 1px solid #999; border-bottom: 1px solid #333; border-right: 1px solid #333; } .form-style input[type=text], textarea, input[type=file]{ font-family: Tahoma, sans-serif; font-size: 11px; color: #444; background: #EAFEC2; border: solid 1px #aaa; padding: 3px; } .form-style select{ font-family: Tahoma, sans-serif; font-size: 11px; color: #444; background: #EAFEC2; border: solid 1px #aaa; } /* Lists */ ul.large{ padding: 0 0 0 15px; margin: 0 0 15px 0px; } ul.large li a { font-weight: normal; } /* Header Styles */ h1.first{ margin-top: 0px; border-bottom: 1px solid #666; background: #fFF; padding: 3px; } h1, h2, h3 { font-size: 170%; line-height: normal; font-weight: normal; font-family: Arial, sans-serif; color: #000000; text-decoration: none; /*margin: 0 0 12px 0; padding: 0;*/ text-align: left; } h2{ font-size: 140%; } h3 { font-size: 120%; } h4{ font-size: 100%; } h4.asterix{ /*background: url(../img/box-small.png) no-repeat left center;*/ padding: 0px 0px 0px 15px; margin: 0px; /*font-size: 110%; */ color: #000000; } /* Boxes */ div.faq-box{ /*border-style: solid; border-color: #C6F27A; border-width: 1px;*/ /*background:url('../img/hatch-green.png');*/ padding: 10px; /*font-family: Verdana, Geneva, Arial, sans-serif; font-size: 11px; line-height: 17px;*/ } div.highlight-box{ border-style: solid; border-color: #cccccc; border-width: 1px; background:url('../img/hatch-yellow.png'); padding: 10px; color: #555; /*font-family: Verdana, Geneva, Arial, sans-serif; font-size: 11px; line-height: 17px;*/ } .box-top{ width: 518px; /*background: url(../img/box-top.png) no-repeat left top;*/ padding-top: 7px; margin-bottom: 15px; } .box-middle{ /*background: url(../img/box-middle.png) repeat-y left top;*/ } .box-bottom{ /*background: url(../img/box-bottom.png) no-repeat left bottom;*/ padding: 0 10px 11px 12px; } /* Utility Styles */ .content-padding{ padding: 20px 6.5% 40px 6.5%; } .sidebar-padding{ padding: 15px 15px 40px 25px; } .invisible{ visibility: hidden; font-size: 1px; padding: 0px; line-height: 0px; margin: 0px; } a.no-underline{ border: 0px; } img.no-border{ border: 0px; } br.clear{ clear: both; width: 100%; } /* Quotes */ .quote-top p{ padding: 0px; margin: 0px; } .quote-top{ font-family: tahoma; /*background: url(../img/quote-top.png) no-repeat left top;*/ padding-left: 25px; padding-top: 4px; } .quote-bottom{ /*background: url(../img/quote-bottom.png) no-repeat right bottom;*/ padding-right: 17px; padding-bottom: 7px; } .quote-author{ /*background: url(../img/quote-author.png) no-repeat left top;*/ padding-left: 20px; padding-bottom: 20px; } /* Footer Styles */ #footer{padding: 5px 5% 40px 5%;} #footer p{ color: #333; } #footer a{ font-weight: normal; } #footer a:visited{ color: #666; text-decoration: none; border-bottom: 1px dotted; } #footer a{ color: #888; font-weight: normal; } #footer a:hover{ color: #000; text-decoration: none; border-bottom: 1px dotted; } Pylons-1.0.2/pylons/media/javascripts/0000755000175000017500000000000012553621453017272 5ustar benben00000000000000Pylons-1.0.2/pylons/media/javascripts/traceback.js0000644000175000017500000000774212456606110021554 0ustar benben00000000000000$(document).ready(function() { var getProxyJSON = function(host, path, data, callback) { data['host'] = host; data['path'] = path; var uri = TRACEBACK.uri+'/relay'; $.getJSON(uri, data, callback); }; // Manipulate DOM to add the iframe, and move things around var newholder = $(document.createElement("div")).addClass('widget_layout'); $('div.feature-highlight').wrapAll(newholder[0])[0].appendChild( $('button:last').remove()[0]); $('div.widget_layout')[0].appendChild(document.getElementById('service_widget')); // Hide the tabs we shouldn't see $('.searchtab').hide(); // Bind the click functions for each tab $('a.overview').click(function () { $('#supportnav li').removeClass('active'); $(this).parent().addClass('active'); $('.overviewtab').show(); $('.posttracebacktab, .searchtab').hide(); return false; }); $('a.search').click(function () { $('#supportnav li').removeClass('active'); $(this).parent().addClass('active'); $('.searchtab').show(); $('.posttracebacktab, .overviewtab').hide(); return false; }); // Set the search field to the exception as the default search $('.searchtab input[@type="text"]')[0].value = $('code.main-exception').text(); // Bind the search button to hit the mail lists $('.searchtab input[@type="submit"]').click(function () { // Populate the lists array with the strings for the lists to include // in the search var lists = []; var options = $('.searchtab input[@type="checkbox"]').serializeArray(); $.each(options, function(i, val) { lists.push('list:' + val.value); }); // Setup the search data var data = {mode:'json', page:1}; data.q = lists.join(' ') + " " + $('.searchtab input[@type="text"]')[0].value; var sr = $('.searchresults'); sr.html('Loading...'); var searchResults = getProxyJSON('markmail.org', '/results.xqy', data, function(data, textStatus) { stuff = data; var numresults = $(document.createElement('p')); numresults.addClass('results'); numresults.html(data.search.start + ' to ' + data.search.end + ' of ' + data.search.estimation); var searchlink = document.createElement('a'); searchlink.href = 'http://markmail.org' + data.search.permalink; searchlink.target = '_blank'; $(searchlink).html('View all results'); numresults.prepend(searchlink); sr.html('').append(numresults); // If there's no search results, stop here if (!data.search.results) { return false; } // Iterate through the search results adding them dynamically // to the element $.each(data.search.results.result, function(i, val) { var result = $(document.createElement('div')).addClass('result'); var link = document.createElement('a'); link.href = 'http://markmail.org' + val.url; link.target = '_blank'; $(link).html(val.subject); result.append(link); var blurb = $(document.createElement('div')).addClass('blurb'); blurb.html(val.blurb); result.append(blurb); var meta = $(document.createElement('div')).addClass('meta'); meta.html(val.date + ' - ' + val.from + ' - ' + val.list); result.append(meta); sr.append(result); }); // Scroll the window down to the top of the service widget with some space window.scrollTo(0, $('#service_widget').offset().top-20); }); return false; }); }); Pylons-1.0.2/pylons/media/img/0000755000175000017500000000000012553621453015515 5ustar benben00000000000000Pylons-1.0.2/pylons/media/img/tab-white.png0000644000175000017500000000074512451647626020124 0ustar benben00000000000000PNG  IHDR,^\,tEXtCreation TimeThu 20 Oct 2005 13:22:14 -0000 9tIME':% pHYs B4gAMA a|hkk-,,9,5@ P]O pA$ٳg׃?~իUV|u޼ynnnz KgjJw>+V #l+0={ G-[,--w \CW)c$d %`Yo޼إKI}!P&_B4ܹ[%#;(5ogd/&ZeQaM HfAAhRLKM* MX]* J&Xd} K ֐!7otvv2Ο??eʔ`h'N6DSHϢ"`!SWW#,C`Y g< &&u- L8mQQQ@GA샫`={.8T_,Q0}tv;iuv0m?l`!4X( :`i ^/ZZּ2?~$M6s(|.//@g [@@`ǎX00\F)U 2biw/~@ '%e5@/409Rlug %Ma0LQ,^Bi у& AK1IFЋ%"C4(h97;ͮ e{*_#ʟo{[DIjRвx@,Ǒ~vyvCjW5>%I Tsko8d< .X-<& >cq%3KP~l""э ɿ(UDV>@=ul8}i$vGYG]j-/骅GY_H[WmRc$311Qvih4V1/%Rm,EEаn> B0لL!O(&Z&t#epI{K^oz&kؾ9}߹9Tj`YP[TX ΝgYCZ]]Exx\nLO}wM]_n}]ŝxːDj9٫_8~Լ#xh0Ժsݝ$&D*/Đ1s{zzHOoo/z%+<΋Q%/ʞ,-$*4ʋCtF0QAA0W(ύ ]__ܱyp( p:Юi8U*Hw<JHw9+//bLNNA;ArQSSSؾ㠧f9A\(=8 +-B\4L瀳h2("тb_\\L AϗĄ d.1Dp$0$7T$}Zj$=i44###h'_;c# (F__ё|+(T-Krń4, SKD,u›״Ǖi -//ZP&h8X~ BhcDG=%1DuB&*TyAoR~mi"H[,xEV9Oݧ@DmV+2 Yq1:vFBQA q88JE~O:Miau]ickaFD(4M /l(EpV^(bdwE=rHp@||w/m˕?v?j)1E:%@)N2$@xo{{{ 333[RZzxc{1KKK\ OL>P`+g|̣'Ǥ"{FYp_H\6l62LCCCv]Tb훚H$:<@.k"HO?bO"#uj"?k{b?Zޛ?~^x ]ɓ,ZEf%SfF99?NIYUI*ݟ[[#|Q6/[n+H;7nܸl:Ju`@vU`INNBZ__o>H,߂\VV֘1c`NBaDג S(ogϞ"^6~'gڇ-.FIvK7tU_9RP]vJH?O5#˗[D^e!!qB ^PP3gzȬxpݺuHOO[0Hʕ+SRRE;v,ʕ+W̛7oܹ̅v ;1bڸq#޴iӸ8qaf3W)..?~|PPЋCgϞO?^|8XmxUQ1̙3GM<jt>|75._,9P!ϒc5Yl,UTTf陂+Bf뢷N?,Z=1=)%''G L`͚5 _nll|8_]tAD ?&&q epE1cƒ%Kҵ_;l_{n>gZ->lÆ v"爅rH>.… qIbCk׮h锩gԩ@ycǎSD3oj P`¯6ܹa-l]jvZvmioÃTzIXnWt8*ׯ_%}ҤI-$N:%28X]@t޽$q@qJ@ȁ[ @PͳgX`d\,[0";'$L GI}L_kGUS Z2KxAEe/GvQoܸD<::Zd3!&億QO|EtAAj2Luuu ǘ'p\QVG7k9`p! F}Qd_)ww:RTA~V/=DNj\SSs!|322C _{s[/)~Q?2xkuAߺwRU2]Qّd6Hwȑ$'z*?mEzpÇCEd3"N *(,,$֬YÝ_ŦM=H¯ u_$ n3$V;Vmj25yQFxfrh;ڝb3h~*VuH}y%(뵐7X)D=yߣ+wvdgv rQ3n=/S &yA6/EXׁL>]7a(n=KPRҝqyjjQ<{?KR,Pu^Rfk#M TLk# CRd{A(,bb*R%Ĭ*))! )زe =TnbݵpHG7N8qw?#{dզO~MQ+ \gWXlVNQkx)@ N|Rk/nRVm0mȅs󧼎n.sU1}\p7?/Z2Y?Pylons-1.0.2/pylons/media/img/favicon.ico0000644000175000017500000000545612451647626017657 0ustar benben00000000000000(6h^ h( 333333033ff33036ffb303fnf300ff0ffnfdnfd`Ff  ??( N^ Z 6R&6 "bZb~ v Vn~"B^j  ~Rf*jFj vNj  b""f  >Zz^v&>n~Vj& Nb ^:RbjfvVr**>^j~Nf "*n R~zVj f&j>^ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ RRR 494 RRR #,G??CI=??',' - F ?,'!A/6X& J?#1 573>XX7E.1ZZZZZZZZZ!OQ ZZZZZZZZZ X+ZZZZZZZZZZZVSSZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ  ??(  WpTk Tk Tk Wn WkNaM_ViWo Tk Tk Tk Vn!iffkVq !`Z}cjOkl ffh)gdiC_ y  w=]j df(giPeb uMd jf( oa% } +)\w m * i:Qn%^&?~ O$6 V K Y ] >[#j c S| Y {7Q v  G w i4=\ e gEh C-n"u6 ??Pylons-1.0.2/pylons/media/img/tab-traceback.png0000644000175000017500000000064112451647626020716 0ustar benben00000000000000PNG  IHDRPkʂgAMAOX2tEXtSoftwareAdobe ImageReadyqe<`PLTEѬDIDATxٕч: gi!u25~ZW׮z cz""A Q D$?@~( @Y! AQ 9" d("!B"D!B"DȷBF>V\wiP  kDrGDrB  @!B"D!B"D!|FZBIENDB`Pylons-1.0.2/pylons/media/img/main-nav-bg.png0000644000175000017500000000036412451647626020331 0ustar benben00000000000000PNG  IHDRUh?,tEXtCreation TimeFri 21 Oct 2005 03:03:42 -0000_2tIME 4/̗ pHYs B4gAMA aKIDATxcqT2` iAf@iĘ.!ы)HU fߵ PǏfTIENDB`Pylons-1.0.2/pylons/media/img/tab-yellow-highlight.png0000644000175000017500000000243712451647626022264 0ustar benben00000000000000PNG  IHDR,^>9,tEXtCreation TimeThu 20 Oct 2005 13:22:14 -0000 9tIME 6 pHYs B4gAMA aPLTEB9BJRRRZZZZccckk!ckssJ{{քքք֌ބބJޜ!!!!!!)c) tRNSYjAIDATxJBQ@.L#V?\ &sf]'ðّjziZڱ~ղIcMXeylg,`ƪ{Lcuoz\xcG=><:cˋZ~4Vه7!iVՊ=ʶX[̎]4VM%iInqc 0`,Xc 0`,Xc 0`,Xc 0`,Xc 0`,Xc 0`,Xc 0`,Xc!qwg(rIENDB`Pylons-1.0.2/pylons/media/img/pylons-logo.gif0000755000175000017500000000453712451647626020511 0ustar benben00000000000000GIF89a;Dzyu)))ZZZHHH%%%2!!!Yna(,<<;޾9{.©A 221(('LD&##"'''&&&"""  (((###$$%'(($##$$$(''***+++onn0!,;DpH,Ȥrl:ШtJZجvzxLl$͆Rn+4||2dC lezxq?=N v n? =pwӗ pڣŒb\eMY,[# ‹S&0܈gP0S6ȑG1 Cj;/*sQز/1e&f):ٳ0A@ҫ1؀hp ޼֖/ -w$% oΫw$x%AT^bd_5;RNR`[ =0 P{,f ""QVz +`Pi@O2,+u*P w@%2'@H" bwaUu.Md%i3QfE{H`L}jEQEAV^1(m UBKti@6T@c\D4-PD>+W64@64"N=xDiRExLY@!gQr/U᧍B EDdIj*: DI:U 5EDaN^[bD99N: :J}cR`kN)Gi)F JZ$a@:DJbgN{붲 A+m;bp.q-&;BXnO2WDJ;%6ZVFN D@JpöʂpxD˶JRuy"A/Zos| n3pL S@bW@]4< T26/k q(:7{F/xnKRYDfv-M`/@5?L$[76Q(#%A1_F(Պ)Ƹt&>w٠] w( y桼7(Gd 5{e x@cn\֋Xڢx|(A>(˞ ΄] pz@D>"x x?0xy#XS9z8]bq6$hGs~7EI@Ji'sяqѓ6X\?=z6 UUFdB&88y+툗@)_?d9}v~jܞU;d 'i|]*e}bHv7̀WwW<03- p{q)ۇq(KeO ׏'Y$)L#}+lyYk+%F)5GTV@48sa>{S{US/?2IENDB`Pylons-1.0.2/pylons/media/img/bg.jpg0000644000175000017500000002450712451647626016626 0ustar benben00000000000000JFIFddDuckyXAdobed  Yc  a!Q1qA"2Br#3R$tu6b457cs%!1AQaq ?Wl)l)l)l)l)l)l)l)l)l)l)l)l)l)l)l)l)l)l)l)l)l)l)l)l)l)l`:YdhMLLn9Tg>EAo{^ø!`eZݏ88y~*enfb ܬnǵoeo"]2+񠻝6Oi {$Cxbe"۱ꐼ|(-0w$}q, D\m80su,tA 8!M= З+bϲ;s)Z#&Ecc|lG iF4%CE# ]&:3cz>pbv wQ>GH$3a+CD5B?u#B9ҒM:,ionNzy'`%͓:Yڟ+%i*`0d.ײeoC (O[tc^jUfўf 4tZ:F립#C⨿Ն2 ks.*kq6Bg3taˎ5(aݗ/t wLn8kꠇv.! 6k Z杆y1b# {0cTr1} ͷ>3Ƭ$Ƀ)ۮ_báE$<ЙDOwl]S0B>*;VmtR7ɒ?T[vow iВ᧭ZtQf4h%AB7:Pw R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R Q@E (P(Q@E (P(Q@E (P(Q@GRv=_ ^zyQ#GƪPun4xyYIX˾韲zӫu6ݣ]{sjMRas I^9P|1 <A]_̓ LJd|:2-w u# m#RY nle"Ǿ?#Cq>#O$bۼIa/#4|0BYbY{׈{y9̡ ɑW#TTAqa!tP-$ODWퟃMa5^+]!HOJ6pZyyBn3|"թcBbe_G"ѥ˄>]#ѰkBWJwDdcӛxvt/d63** GF/?,7$PƖʊY[1kâǽQ.vs#OAe3)ᰴaVΧ|@\J-B=P>a}>@E (P(Q@E (P(Q@E (P(Q@E (P(Q@E (P(Q@E (P(( !@( !@( !@( !@( !@( !@( !A598" (~KZ$hAc.pk Q{&X>!2'8H4#w:{k7~8џpe{~XGI` x>B'BG$@GTRa3kZj#l#xl8&n23/k924tS A}N{fCHng|IɴetrGFu:Ag52鰰ٮ$9ah hsX8bZKE 8v^ǭ@:䂵t,2ݱnSk;Ds~u$NL]r. )@ђ C$|]<°[lEԦ~wɆ>V'q<v:8m52\4xgUi-a3@cdcF駙g=ٽ?]$m䱹+# 4<|fܢ@wc6DZ:-.kNQ,zmldw$Lu05eh? :9\a|n)['S\4sLr0VkIݛO+eth5 3^ctf0鿲/ P)lPy{qw̼m8 uj[ us:{8ݒ\[L66N:ߪz 簖W&o)x ɣtofYLOw &(Gd ; Qv@(Gd ; Qv@(Gd ; Qv@(Gd ; Q:崎xcƤ{ ķ22SgvA,cϣh,z5өrAZn1һ L3'H<0~aF18pu Ѥ!h=J/TvP(Gd^DDl8H:5iGj`c2٧]J&$4yq$R.ֶmt_{ <3[()_SmZHن"y!v=9nU4C)vF~niZ֗COVϧr#1XˉVV+'H fN%(>d,H;\V h  v= Il^֖ۮc+. LKKk.̾%$\SKz;<6:(,FH?x _1pKwGG4v@(Gd ; Qv@(Gd ; Qv@(Gd ; Qv@(Gd ; Qv@(Gd ; Qv@(Gd ; Q-KbKbKbKbKbKbKbKbKbKbKbKbKbKbKbKbKbKbKbKbKbKbKbKbKbKbKbKbKbKb͗1:'4 ^qU]kp2A~AKbZ:9C#y&htI4 c-gVR.G4ԟ&6.cB쥱Au-wr{kv3kG(5j_[nZ7t\nt8Sm]AW?'ᦊ̳3tt8:<4G%oq8n$:8?Iyy'udlS'm6Z[&|tZVd7_%-&1B_›\t5mpdñ?0gzz$k[lyl7qJۻ fZhaԽޡ̐} U#i83ť0NZ-t/-av)m},kK{84DCuܗYo\7]mwhH-wKii ^V E<&wtp׃`KC}w~WVk@=8,ָjH gbk,ݜLz:w :hRب((((( { W{l#Fţ}BtWxcm;uzCc/OXT>ên#B?!'2lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lP)lPI@E (P(Q@E (P(Q@E (P(Q@E (P(źDz屝ilw86y#+.'T (1 zPd(B/S]:W /|ّa㈏BEze{-ghˉ&6{WGh'U+g1ݥ0~l2vși|tIrw>.7L>@5i|Uo2=ml>)kO]Ed(Q@E (#h-bp)\j8ﳈU09^jWlH]d xj Vg>]mt؟$P(Q@E (P(Q@E (P(Q@E (P(Q@E (P(Q@E (P(Q@E JGE))))))))))))))))`X4F[R5%EO޸uc|x>Q :Y@dA/Tzi4DPrȳ1C]ܙF;gL$8Bf#kLe% z75sq̩QCE]ǖk-la`Ź$qqk ~#U{t8ՖCc+W6ats17Gxy)prg;&np1|m1Mqd/2G@?r {mclfk <j(_Krxt}؞'ncvMVFs8 袚[5:߀xP~!_#d~'R9YӵY$# R># R># 蹲mռj+H.`(4nb.Hp$G nIlnD.d_mz4:fsG܂BJG@| G@| G@| G@| G@| G@| G@| G@| G@| G@| G@| G@| G@| G@| G@| G@| G@| G@| G@| G@| G@| G@| GA)G@GD >}( Q@GD >}( Q@GD >}( Q@GD >}( Q@̟Y{6<}m$ozG=H$kXM)xWj96{wUm[2rR[f\Dp~9S<dD;;cs[{_î|j`p+]܏&s|qv.ô[{7PIm ]q@-*k Yf]YnǧIPt; VIveC뼍YdėޗxooY Ƴ]iY6 GkYw^ӺձJ^u -C백9'qV&; / 'YgR&xia{k,L|eu`xK~6-Ǹǐ͉isA$cРYYdmwau崟'PGvYwpd?v2_#[=NV.ڌ.<\x|V?ErR짛4vIGF7]`?ܷl]ŀ"-&&28,}RD >}( Q@&XimE;> Xj*2bd%d"Jx9ڙ{cҨВN:]P|{.`]Z;MD >}( Q@GD >}( Q@GD >}( Q@GD >}( Q@GD >}( Q@GD >}( QA'HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH`{uC.zC0Cw/Ӌn/d7v3CqglBX ziׇܻ5ܽ3+?k$֢#:[o65\y^tjHgGؾu'WsptHoH:uO;3ocNk\FR| Gd\yPyK\vatd/xs:(ȭFYE9٥G=1͜qqy!~Ǵ<=d|cڴ[8f"ݷxx݊ž6{YM{7OYusw /?غ&9ͷ-ϼkҞFݱ=\JFI.{@t:u+8<}Pcq}6lG, a:rZ"+kg9سۮ׫Fj@;oGe)))))))t%8PcXHo>j#K_-vFZ[>FxI:Xn~V^,<fCBCy t7Cy t7Cy t7Cy t7Cy t7Cy t7Cy t7Cy t7Cy t7Cy t7Cy t7Cy t7Cy t7Cy t7Cy t7Cy t7Cy t7Cy ·dv:ӫi,6z]{o5y8;#N ok!Ksc:%$[oe -PqP5[P^v g}wUC$Wkض-> Llri0h0kؽ6VA{Ѡs{AY켆~Kߝ'*KojO=BojY}76X4#:Fߚ֍Ug` =b夓t=a`hxvo\d`1xc% s27-};'H H H H .G2%w2#O@uA?/*(7)O6(3D`v7J%Pylons-1.0.2/pylons/media/img/logo.gif0000644000175000017500000000744512451647626017165 0ustar benben00000000000000GIF89a4990 LLIeebzzJ{{z~~|NooErrH~墢333rrq,,(HHE??>``>fff]]APP:{{JttrWԨZ`QWnnmX"" vvGMM7T==<⒒QPPNiiAkkiEECbb?TTQBB6))&ppn[[>II9NNKeeB**'$$"[VV?fEE:R//,;;1M\00/``]GGDXX>9??;772@@;==922/..*YN00-~~I;;6??://+~~J::5XY_Ḹ_99444/c885>>:UçZK^KJNOTwwHZZ=33.::7ؓRǬllk[[?WW@WXX@ҥS@@5yyx11,ἼWW;b[Ѩ22-AA>!K,4H.9` NJHŋ3jL!*lIɓ;:ʗ0cʬV//3sif < 'PH4ӓLJj1*ի px`!4l]t6ZZXf%ǂRm fc' .j-|șFLHpB)eB$$8tg6 =13{l, wv2VLF%xxd1ct^HQgc^2H%q"qL#9gdx U|qyi y$@-؋! o66F"!wՂ*q p}-BG(Ap ,1lJ9 qDGTI.GZ Ԣ"KfPzd 8'&g]8BE'xD A  pژ !vpbGtJ/&E)!5 V"NZiZHk8Epgar&i&An gWX[p q@*@B ʊV d-U#Gi"z†\r*i nh&AF_}#yt&*nl-Jo*o#,3 o tXj<ٸa(/GڌyJ/aGP|PDf wΗ@Dе`f,,KVE7]p$6!Hޔhvƃ5{-:lPK ͺK:BsCScR 0 fDIGt$0oyt$m-eg9k!dLtA =2q" `)c]>A~7 *s)jD"Ab%@"kX+qj+lBIǛ <ؤ xE) tA[Dφ$!z\Y'ZMep趴:1"3ۃA,R\ "q78ac8= ݚXD7*dC#y"B5 0\jx%; Z4cS+*)!d*8IKъ3;X!rՁ3f.wi͕YhiH&YDt3q "Јt0`A 2ΔAl9R<8!A0WXlDH8Z!g& 6b!ZJF$H=R,X"Z4]B,ކ!Ǖq0-MEB9SG6*Q`bf5\dn в vӈW!RX.$ @jD"rp]|D@^DiD$aDxq$6 #a\1T8 %KjI%E,H8&B6\{ oĈH [,B2E\\Axib]-!x#fA1R`gG>qf)Q+1>Vʬ)0H>'D$. JH&@(<@%T@QJ8Z ƅ `Z1F4\mDD@{D @n @@$:G(D !msD!1qGKC!Qm<1(Da튐~ɽmM<"HD)I f'B8a("`x V@ ht!B"E!0B`!FnSB _BBty"Ns0!0l".Mj $ 6 !Lp BD &Qo4<E * MB!PB! B!0bh(D E lC! Ki0ʻQ(A6"dH!R (__X"+B$0AiE]Ri D@`E LQR@,D C~Ly$2r P,ZJ$!t K_7 xP= xo ~YP`~z ~>7rN)@ ܷx )pڲinWs- T 1 '` H6| & %P'Gr` zrn)PrwS&3}pY ~"r7 .7r ~ wX b` z1 F2Pg 'P`@ C@P nP P@ P-Ljz xy}ϗ zP py؄X gT yf0w}vϷiP70 Ө Yp W P}p0 iq ɀp gȋ7ЊhX.sI I3 NEf8P 0 ַZcvɒ`B}DY@,dOI@UIO"6 D.)0 gP da` 0 q P p0Kp z9 iy {9 vYp L 0 `I99 i|(p Gp iƩyI ͙‰^sigy;Pylons-1.0.2/pylons/media/img/tab-brown.png0000644000175000017500000000100412451647626020120 0ustar benben00000000000000PNG  IHDR,^\,tEXtCreation TimeThu 20 Oct 2005 13:22:14 -0000 9tIME=b+ pHYs B4gAMA a[IDATxA @@Q 8 HV A.a;<4noXz>cNcD1BL!D1BL!D1BL!D1BL!D1BL˲3Ԇ56*M1b^@l݄07b"(lBb !&BD%_Q@qbC'b"!&Bb"!&Bb"!&Bb"!&Bb"!&Bb"!&Bb"!&Bb"!&Bb"!&Bb"!&Bb"!&Bb"!&Bb"K4}MsIENDB`Pylons-1.0.2/pylons/media/img/bg.png0000755000175000017500000000052312451647626016625 0ustar benben00000000000000PNG  IHDR&#.sRGBbKGDY< pHYs  tIME2 ~p=tEXtCommentCreated with GIMPWIDATHǽUA0+?~o%@/% t~?_)}Rt1aNҤQtf Q\(E}Ւ%"R;`v]/. "mrGz%1Nƃԃtxm}*1(m?"|&5uqyO8ıIENDB`Pylons-1.0.2/pylons/media/img/warning.gif0000644000175000017500000000200012451647626017650 0ustar benben00000000000000GIF89a!!ZZsk{s{Ƶν޽B޽J޽R޽ZJZckBBJJRks{ΌJ{֌֔ޥޭJJR֔ޔޜޥJJRJ1J!1B)19BJ!,H A**\ J!B'bXDH! &Jx# 'ryFhbC"@BXY1b I!BE0Ҡ )> "B 40ac̞TH0"?vѐRaɠ?PPcC$5HpX   @p6!k3THB .8тo$F_1B8-;Pylons-1.0.2/pylons/media/img/highlight.png0000644000175000017500000000030412451647626020176 0ustar benben00000000000000PNG  IHDRJ"+tEXtCreation TimeSat 5 Feb 2005 02:45:25 -0000LCCtIME (b pHYs B4gAMA aIDATxc0`b ,0H]KXIENDB`Pylons-1.0.2/pylons/testutil.py0000644000175000017500000000604112451647626016121 0ustar benben00000000000000"""Utility classes for creating workable pylons controllers for unit testing. These classes are used solely by Pylons for unit testing controller functionality. """ import gettext import pylons from pylons.configuration import request_defaults, response_defaults from pylons.controllers.util import Request, Response from pylons.util import ContextObj, PylonsContext class ControllerWrap(object): def __init__(self, controller): self.controller = controller def __call__(self, environ, start_response): app = self.controller() app.start_response = None return app(environ, start_response) class SetupCacheGlobal(object): def __init__(self, app, environ, setup_g=True, setup_cache=False, setup_session=False): if setup_g: g = type('G object', (object,), {}) g.message = 'Hello' g.counter = 0 g.pylons_config = type('App conf', (object,), {}) g.pylons_config.app_conf = dict(cache_enabled='True') self.g = g self.app = app self.environ = environ self.setup_cache = setup_cache self.setup_session = setup_session self.setup_g = setup_g def __call__(self, environ, start_response): registry = environ['paste.registry'] py_obj = PylonsContext() environ_config = environ.setdefault('pylons.environ_config', {}) if self.setup_cache: py_obj.cache = environ['beaker.cache'] registry.register(pylons.cache, environ['beaker.cache']) environ_config['cache'] = 'beaker.cache' if self.setup_session: py_obj.session = environ['beaker.session'] registry.register(pylons.session, environ['beaker.session']) environ_config['session'] = 'beaker.session' if self.setup_g: py_obj.app_globals = self.g registry.register(pylons.app_globals, self.g) translator = gettext.NullTranslations() py_obj.translator = translator registry.register(pylons.translator, translator) # Update the environ req = Request(environ, charset=request_defaults['charset'], unicode_errors=request_defaults['errors'], decode_param_names=request_defaults['decode_param_names'] ) req.language = request_defaults['language'] response = Response( content_type=response_defaults['content_type'], charset=response_defaults['charset']) response.headers.update(response_defaults['headers']) environ.update(self.environ) py_obj.config = pylons.config._current_obj() py_obj.request = req py_obj.response = response py_obj.tmpl_context = ContextObj() environ['pylons.pylons'] = py_obj registry.register(pylons.request, req) registry.register(pylons.response, response) if 'routes.url' in environ: registry.register(pylons.url, environ['routes.url']) return self.app(environ, start_response) Pylons-1.0.2/pylons/templates/0000755000175000017500000000000012553621453015660 5ustar benben00000000000000Pylons-1.0.2/pylons/templates/default_project/0000755000175000017500000000000012553621453021032 5ustar benben00000000000000Pylons-1.0.2/pylons/templates/default_project/README.txt_tmpl0000644000175000017500000000072312451647626023575 0ustar benben00000000000000This file is for you to describe the {{project}} application. Typically you would include information such as the information below: Installation and Setup ====================== Install ``{{project}}`` using easy_install:: easy_install {{project}} Make a config file as follows:: paster make-config {{project}} config.ini Tweak the config file as appropriate and then setup the application:: paster setup-app config.ini Then you are ready to go. Pylons-1.0.2/pylons/templates/default_project/setup.cfg_tmpl0000644000175000017500000000107512451647626023721 0ustar benben00000000000000[egg_info] tag_build = dev tag_svn_revision = true [easy_install] find_links = http://www.pylonshq.com/download/ # Babel configuration [compile_catalog] domain = {{package}} directory = {{package}}/i18n statistics = true [extract_messages] add_comments = TRANSLATORS: output_file = {{package}}/i18n/{{package}}.pot width = 80 [init_catalog] domain = {{package}} input_file = {{package}}/i18n/{{package}}.pot output_dir = {{package}}/i18n [update_catalog] domain = {{package}} input_file = {{package}}/i18n/{{package}}.pot output_dir = {{package}}/i18n previous = true Pylons-1.0.2/pylons/templates/default_project/setup.py_tmpl0000644000175000017500000000230312451647626023605 0ustar benben00000000000000try: from setuptools import setup, find_packages except ImportError: from ez_setup import use_setuptools use_setuptools() from setuptools import setup, find_packages setup( name='{{project}}', version='{{version}}', description={{repr(description)}}, author={{repr(author)}}, author_email={{repr(author_email)}}, url={{repr(url)}}, install_requires=[ "Pylons>=1.0.1rc1", {{if sqlalchemy}} "SQLAlchemy>=0.5", {{endif}} {{if template_engine == 'genshi'}} "Genshi>=0.4", {{elif template_engine == 'jinja2'}} "Jinja2", {{endif}} ], setup_requires=["PasteScript>=1.6.3"], packages=find_packages(exclude=['ez_setup']), include_package_data=True, test_suite='nose.collector', package_data={'{{package}}': ['i18n/*/LC_MESSAGES/*.mo']}, #message_extractors={'{{package}}': [ # ('**.py', 'python', None), # {{babel_templates_extractor}}('public/**', 'ignore', None)]}, zip_safe={{zip_safe}}, paster_plugins={{egg_plugins}}, entry_points=""" [paste.app_factory] main = {{package}}.config.middleware:make_app [paste.app_install] main = pylons.util:PylonsInstaller """, ) Pylons-1.0.2/pylons/templates/default_project/+package+/0000755000175000017500000000000012553621453022553 5ustar benben00000000000000Pylons-1.0.2/pylons/templates/default_project/+package+/controllers/0000755000175000017500000000000012553621453025121 5ustar benben00000000000000Pylons-1.0.2/pylons/templates/default_project/+package+/controllers/error.py_tmpl0000644000175000017500000000321312451647626027666 0ustar benben00000000000000import cgi from paste.urlparser import PkgResourcesParser from pylons.middleware import error_document_template from webhelpers.html.builder import literal from {{package}}.lib.base import BaseController class ErrorController(BaseController): """Generates error documents as and when they are required. The ErrorDocuments middleware forwards to ErrorController when error related status codes are returned from the application. This behaviour can be altered by changing the parameters to the ErrorDocuments middleware in your config/middleware.py file. """ def document(self): """Render the error document""" request = self._py_object.request resp = request.environ.get('pylons.original_response') content = literal(resp.body) or cgi.escape(request.GET.get('message', '')) page = error_document_template % \ dict(prefix=request.environ.get('SCRIPT_NAME', ''), code=cgi.escape(request.GET.get('code', str(resp.status_int))), message=content) return page def img(self, id): """Serve Pylons' stock images""" return self._serve_file('/'.join(['media/img', id])) def style(self, id): """Serve Pylons' stock stylesheets""" return self._serve_file('/'.join(['media/style', id])) def _serve_file(self, path): """Call Paste's FileApp (a WSGI application) to serve the file at the specified path """ request = self._py_object.request request.environ['PATH_INFO'] = '/%s' % path return PkgResourcesParser('pylons', 'pylons')(request.environ, self.start_response) Pylons-1.0.2/pylons/templates/default_project/+package+/controllers/__init__.py_tmpl0000644000175000017500000000000012451647626030263 0ustar benben00000000000000Pylons-1.0.2/pylons/templates/default_project/+package+/model/0000755000175000017500000000000012553621453023653 5ustar benben00000000000000Pylons-1.0.2/pylons/templates/default_project/+package+/model/meta.py_tmpl0000644000175000017500000000061512451647626026220 0ustar benben00000000000000{{if sqlalchemy}} """SQLAlchemy Metadata and Session object""" from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import scoped_session, sessionmaker __all__ = ['Base', 'Session'] # SQLAlchemy session manager. Updated by model.init_model() Session = scoped_session(sessionmaker()) # The declarative Base Base = declarative_base() {{else}} {{skip_template()}} {{endif}} Pylons-1.0.2/pylons/templates/default_project/+package+/model/__init__.py_tmpl0000644000175000017500000000037212451647626027031 0ustar benben00000000000000{{if sqlalchemy}} """The application's model objects""" from {{package}}.model.meta import Session, Base def init_model(engine): """Call me before using any of the tables or classes in the model""" Session.configure(bind=engine) {{endif}} Pylons-1.0.2/pylons/templates/default_project/+package+/lib/0000755000175000017500000000000012553621453023321 5ustar benben00000000000000Pylons-1.0.2/pylons/templates/default_project/+package+/lib/helpers.py_tmpl0000644000175000017500000000042112451647626026375 0ustar benben00000000000000"""Helper functions Consists of functions to typically be used within templates, but also available to Controllers. This module is available to templates as 'h'. """ # Import helpers as desired, or define your own, ie: #from webhelpers.html.tags import checkbox, password Pylons-1.0.2/pylons/templates/default_project/+package+/lib/app_globals.py_tmpl0000644000175000017500000000103412451647626027217 0ustar benben00000000000000"""The application's Globals object""" from beaker.cache import CacheManager from beaker.util import parse_cache_config_options class Globals(object): """Globals acts as a container for objects available throughout the life of the application """ def __init__(self, config): """One instance of Globals is created during application initialization and is available during requests via the 'app_globals' variable """ self.cache = CacheManager(**parse_cache_config_options(config)) Pylons-1.0.2/pylons/templates/default_project/+package+/lib/__init__.py_tmpl0000644000175000017500000000000012451647626026463 0ustar benben00000000000000Pylons-1.0.2/pylons/templates/default_project/+package+/lib/base.py_tmpl0000644000175000017500000000157212451647626025655 0ustar benben00000000000000"""The base Controller API Provides the BaseController class for subclassing. """ from pylons.controllers import WSGIController {{if template_engine in ('genshi', 'jinja2', 'mako')}} from pylons.templating import render_{{template_engine}} as render {{endif}} {{if sqlalchemy}} from {{package}}.model.meta import Session {{endif}} class BaseController(WSGIController): def __call__(self, environ, start_response): """Invoke the Controller""" # WSGIController.__call__ dispatches to the Controller method # the request is routed to. This routing information is # available in environ['pylons.routes_dict'] {{if sqlalchemy}} try: return WSGIController.__call__(self, environ, start_response) finally: Session.remove(){{else}} return WSGIController.__call__(self, environ, start_response){{endif}} Pylons-1.0.2/pylons/templates/default_project/+package+/config/0000755000175000017500000000000012553621453024020 5ustar benben00000000000000Pylons-1.0.2/pylons/templates/default_project/+package+/config/environment.py_tmpl0000644000175000017500000000524212451647626030004 0ustar benben00000000000000"""Pylons environment configuration""" import os {{if template_engine == 'mako'}} from mako.lookup import TemplateLookup {{elif template_engine == 'genshi'}} from genshi.template import TemplateLoader {{elif template_engine == 'jinja2'}} from jinja2 import Environment, FileSystemLoader {{endif}} from pylons.configuration import PylonsConfig {{if template_engine == 'mako'}} from pylons.error import handle_mako_error {{endif}} {{if sqlalchemy}} from sqlalchemy import engine_from_config {{endif}} import {{package}}.lib.app_globals as app_globals import {{package}}.lib.helpers from {{package}}.config.routing import make_map {{if sqlalchemy}} from {{package}}.model import init_model {{endif}} def load_environment(global_conf, app_conf): """Configure the Pylons environment via the ``pylons.config`` object """ config = PylonsConfig() # Pylons paths root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) paths = dict(root=root, controllers=os.path.join(root, 'controllers'), static_files=os.path.join(root, 'public'), templates=[os.path.join(root, 'templates')]) # Initialize config with the basic options config.init_app(global_conf, app_conf, package='{{package}}', paths=paths) config['routes.map'] = make_map(config) config['pylons.app_globals'] = app_globals.Globals(config) config['pylons.h'] = {{package}}.lib.helpers # Setup cache object as early as possible import pylons pylons.cache._push_object(config['pylons.app_globals'].cache) {{if template_engine == 'mako'}} # Create the Mako TemplateLookup, with the default auto-escaping config['pylons.app_globals'].mako_lookup = TemplateLookup( directories=paths['templates'], error_handler=handle_mako_error, module_directory=os.path.join(app_conf['cache_dir'], 'templates'), input_encoding='utf-8', default_filters=['escape'], imports=['from markupsafe import escape']) {{elif template_engine == 'genshi'}} # Create the Genshi TemplateLoader config['pylons.app_globals'].genshi_loader = TemplateLoader( paths['templates'], auto_reload=True) {{elif template_engine == 'jinja2'}} # Create the Jinja2 Environment jinja2_env = Environment(loader=FileSystemLoader(paths['templates'])) config['pylons.app_globals'].jinja2_env = jinja2_env {{endif}}{{if sqlalchemy}} # Setup the SQLAlchemy database engine engine = engine_from_config(config, 'sqlalchemy.') init_model(engine) {{endif}} # CONFIGURATION OPTIONS HERE (note: all config options will override # any Pylons config options) return config Pylons-1.0.2/pylons/templates/default_project/+package+/config/routing.py_tmpl0000644000175000017500000000157112451647626027130 0ustar benben00000000000000"""Routes configuration The more specific and detailed routes should be defined first so they may take precedent over the more generic routes. For more information refer to the routes manual at http://routes.groovie.org/docs/ """ from routes import Mapper def make_map(config): """Create, configure and return the routes Mapper""" map = Mapper(directory=config['pylons.paths']['controllers'], always_scan=config['debug']) map.minimization = False map.explicit = False # The ErrorController route (handles 404/500 error pages); it should # likely stay at the top, ensuring it can always be resolved map.connect('/error/{action}', controller='error') map.connect('/error/{action}/{id}', controller='error') # CUSTOM ROUTES HERE map.connect('/{controller}/{action}') map.connect('/{controller}/{action}/{id}') return map Pylons-1.0.2/pylons/templates/default_project/+package+/config/middleware.py_tmpl0000644000175000017500000000455312451647626027561 0ustar benben00000000000000"""Pylons middleware initialization""" from beaker.middleware import SessionMiddleware from paste.cascade import Cascade from paste.registry import RegistryManager from paste.urlparser import StaticURLParser from paste.deploy.converters import asbool from pylons.middleware import ErrorHandler, StatusCodeRedirect from pylons.wsgiapp import PylonsApp from routes.middleware import RoutesMiddleware from {{package}}.config.environment import load_environment def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:] section of the Paste ini file (where defaults to main). """ # Configure the Pylons environment config = load_environment(global_conf, app_conf) # The Pylons WSGI app app = PylonsApp(config=config) # Routing/Session Middleware app = RoutesMiddleware(app, config['routes.map'], singleton=False) app = SessionMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # Display error documents for 401, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app) else: app = StatusCodeRedirect(app, [400, 401, 403, 404, 500]) # Establish the Registry for this application app = RegistryManager(app) if asbool(static_files): # Serve static files static_app = StaticURLParser(config['pylons.paths']['static_files']) app = Cascade([static_app, app]) app.config = config return app Pylons-1.0.2/pylons/templates/default_project/+package+/config/__init__.py_tmpl0000644000175000017500000000000012451647626027162 0ustar benben00000000000000Pylons-1.0.2/pylons/templates/default_project/+package+/config/deployment.ini_tmpl_tmpl0000644000175000017500000000264712451647626031011 0ustar benben00000000000000# # {{project}} - Pylons configuration # # The %(here)s variable will be replaced with the parent directory of this file # [DEFAULT] debug = true email_to = you@yourdomain.com smtp_server = localhost error_email_from = paste@localhost [server:main] use = egg:Paste#http host = 0.0.0.0 port = 5000 [app:main] use = egg:{{project}} full_stack = true static_files = true cache_dir = %(here)s/data beaker.session.key = {{package}} beaker.session.secret = ${app_instance_secret} app_instance_uuid = ${app_instance_uuid} # If you'd like to fine-tune the individual locations of the cache data dirs # for the Cache data, or the Session saves, un-comment the desired settings # here: #beaker.cache.data_dir = %(here)s/data/cache #beaker.session.data_dir = %(here)s/data/sessions {{if sqlalchemy}} # SQLAlchemy database URL sqlalchemy.url = sqlite:///production.db {{endif}} # WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* # Debug mode will enable the interactive debugging tool, allowing ANYONE to # execute malicious code after an exception is raised. set debug = false # Logging configuration [loggers] keys = root [handlers] keys = console [formatters] keys = generic [logger_root] level = INFO handlers = console [handler_console] class = StreamHandler args = (sys.stderr,) level = NOTSET formatter = generic [formatter_generic] format = %(asctime)s %(levelname)-5.5s [%(name)s] [%(threadName)s] %(message)s Pylons-1.0.2/pylons/templates/default_project/+package+/websetup.py_tmpl0000644000175000017500000000111312451647626026022 0ustar benben00000000000000"""Setup the {{project}} application""" import logging from {{package}}.config.environment import load_environment {{if sqlalchemy}} from {{package}}.model.meta import Session, Base {{endif}} log = logging.getLogger(__name__) def setup_app(command, conf, vars): """Place any commands to setup {{package}} here""" # Don't reload the app if it was loaded under the testing environment load_environment(conf.global_conf, conf.local_conf) {{if sqlalchemy}} # Create the tables if they don't already exist Base.metadata.create_all(bind=Session.bind) {{endif}} Pylons-1.0.2/pylons/templates/default_project/+package+/tests/0000755000175000017500000000000012553621453023715 5ustar benben00000000000000Pylons-1.0.2/pylons/templates/default_project/+package+/tests/test_models.py_tmpl0000644000175000017500000000000012451647626027642 0ustar benben00000000000000Pylons-1.0.2/pylons/templates/default_project/+package+/tests/functional/0000755000175000017500000000000012553621453026057 5ustar benben00000000000000Pylons-1.0.2/pylons/templates/default_project/+package+/tests/functional/__init__.py_tmpl0000644000175000017500000000000012451647626031221 0ustar benben00000000000000Pylons-1.0.2/pylons/templates/default_project/+package+/tests/__init__.py_tmpl0000644000175000017500000000273112451647626027074 0ustar benben00000000000000"""Pylons application test package This package assumes the Pylons environment is already loaded, such as when this script is imported from the `nosetests --with-pylons=test.ini` command. This module initializes the application via ``websetup`` (`paster setup-app`) and provides the base testing objects. """ from unittest import TestCase import os import sys import pylons from pylons.i18n.translation import _get_translator from paste.deploy import loadapp from pylons import url from paste.script.appinstall import SetupCommand from routes.util import URLGenerator from webtest import TestApp from {{package}}.config.environment import load_environment __all__ = ['environ', 'url', 'TestController'] environ = {} here_dir = os.path.dirname(os.path.abspath(__file__)) conf_dir = os.path.dirname(os.path.dirname(here_dir)) sys.path.insert(0, conf_dir) class TestController(TestCase): def __init__(self, *args, **kwargs): wsgiapp = loadapp('config:test.ini', relative_to=conf_dir) config = wsgiapp.config pylons.app_globals._push_object(config['pylons.app_globals']) pylons.config._push_object(config) # Initialize a translator for tests that utilize i18n translator = _get_translator(pylons.config.get('lang')) pylons.translator._push_object(translator) url._push_object(URLGenerator(config['routes.map'], environ)) self.app = TestApp(wsgiapp) TestCase.__init__(self, *args, **kwargs) Pylons-1.0.2/pylons/templates/default_project/+package+/public/0000755000175000017500000000000012553621453024031 5ustar benben00000000000000Pylons-1.0.2/pylons/templates/default_project/+package+/public/favicon.ico0000644000175000017500000000545612451647626026173 0ustar benben00000000000000(6h^ h( 333333033ff33036ffb303fnf300ff0ffnfdnfd`Ff  ??( N^ Z 6R&6 "bZb~ v Vn~"B^j  ~Rf*jFj vNj  b""f  >Zz^v&>n~Vj& Nb ^:RbjfvVr**>^j~Nf "*n R~zVj f&j>^ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ RRR 494 RRR #,G??CI=??',' - F ?,'!A/6X& J?#1 573>XX7E.1ZZZZZZZZZ!OQ ZZZZZZZZZ X+ZZZZZZZZZZZVSSZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ  ??(  WpTk Tk Tk Wn WkNaM_ViWo Tk Tk Tk Vn!iffkVq !`Z}cjOkl ffh)gdiC_ y  w=]j df(giPeb uMd jf( oa% } +)\w m * i:Qn%^&?~ O$6 V K Y ] >[#j c S| Y {7Q v  G w i4=\ e gEh C-n"u6 ??Pylons-1.0.2/pylons/templates/default_project/+package+/public/pylons-logo.gif0000755000175000017500000000453712451647626027025 0ustar benben00000000000000GIF89a;Dzyu)))ZZZHHH%%%2!!!Yna(,<<;޾9{.©A 221(('LD&##"'''&&&"""  (((###$$%'(($##$$$(''***+++onn0!,;DpH,Ȥrl:ШtJZجvzxLl$͆Rn+4||2dC lezxq?=N v n? =pwӗ pڣŒb\eMY,[# ‹S&0܈gP0S6ȑG1 Cj;/*sQز/1e&f):ٳ0A@ҫ1؀hp ޼֖/ -w$% oΫw$x%AT^bd_5;RNR`[ =0 P{,f ""QVz +`Pi@O2,+u*P w@%2'@H" bwaUu.Md%i3QfE{H`L}jEQEAV^1(m UBKti@6T@c\D4-PD>+W64@64"N=xDiRExLY@!gQr/U᧍B EDdIj*: DI:U 5EDaN^[bD99N: :J}cR`kN)Gi)F JZ$a@:DJbgN{붲 A+m;bp.q-&;BXnO2WDJ;%6ZVFN D@JpöʂpxD˶JRuy"A/Zos| n3pL S@bW@]4< T26/k q(:7{F/xnKRYDfv-M`/@5?L$[76Q(#%A1_F(Պ)Ƹt&>w٠] w( y桼7(Gd 5{e x@cn\֋Xڢx|(A>(˞ ΄] pz@D>"x x?0xy#XS9z8]bq6$hGs~7EI@Ji'sяqѓ6X\?=z6 UUFdB&88y+툗@)_?d9 Welcome to Pylons!

Welcome to Logo displaying the word Pylons


Let's begin!

If you haven't used Pylons before, start with the beginners' tutorial.

Pylons-1.0.2/pylons/templates/default_project/+package+/__init__.py_tmpl0000644000175000017500000000000012451647626025715 0ustar benben00000000000000Pylons-1.0.2/pylons/templates/default_project/+package+/templates/0000755000175000017500000000000012553621453024551 5ustar benben00000000000000Pylons-1.0.2/pylons/templates/default_project/+package+/templates/.distutils_placeholder0000644000175000017500000000000012451647626031135 0ustar benben00000000000000Pylons-1.0.2/pylons/templates/default_project/+package+/templates/__init__.py_tmpl0000644000175000017500000000011612451647626027723 0ustar benben00000000000000{{if template_engine not in ['genshi', 'kid']}} {{skip_template()}} {{endif}} Pylons-1.0.2/pylons/templates/default_project/development.ini_tmpl0000644000175000017500000000403412451647626025121 0ustar benben00000000000000# # {{project}} - Pylons development environment configuration # # The %(here)s variable will be replaced with the parent directory of this file # [DEFAULT] debug = true # Uncomment and replace with the address which should receive any error reports #email_to = you@yourdomain.com smtp_server = localhost error_email_from = paste@localhost [server:main] use = egg:Paste#http host = 127.0.0.1 port = 5000 [app:main] use = egg:{{project}} full_stack = true static_files = true cache_dir = %(here)s/data beaker.session.key = {{package}} beaker.session.secret = somesecret # If you'd like to fine-tune the individual locations of the cache data dirs # for the Cache data, or the Session saves, un-comment the desired settings # here: #beaker.cache.data_dir = %(here)s/data/cache #beaker.session.data_dir = %(here)s/data/sessions {{if sqlalchemy}} # SQLAlchemy database URL sqlalchemy.url = sqlite:///%(here)s/development.db {{endif}} # WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* # Debug mode will enable the interactive debugging tool, allowing ANYONE to # execute malicious code after an exception is raised. #set debug = false # Logging configuration [loggers] keys = root, routes, {{package_logger}}{{if sqlalchemy}}, sqlalchemy{{endif}} [handlers] keys = console [formatters] keys = generic [logger_root] level = INFO handlers = console [logger_routes] level = INFO handlers = qualname = routes.middleware # "level = DEBUG" logs the route matched and routing variables. [logger_{{package_logger}}] level = DEBUG handlers = qualname = {{package}} {{if sqlalchemy}} [logger_sqlalchemy] level = INFO handlers = qualname = sqlalchemy.engine # "level = INFO" logs SQL queries. # "level = DEBUG" logs SQL queries and results. # "level = WARN" logs neither. (Recommended for production systems.) {{endif}} [handler_console] class = StreamHandler args = (sys.stderr,) level = NOTSET formatter = generic [formatter_generic] format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] [%(threadName)s] %(message)s datefmt = %H:%M:%S Pylons-1.0.2/pylons/templates/default_project/test.ini_tmpl0000644000175000017500000000077612451647626023567 0ustar benben00000000000000# # {{project}} - Pylons testing environment configuration # # The %(here)s variable will be replaced with the parent directory of this file # [DEFAULT] debug = true # Uncomment and replace with the address which should receive any error reports #email_to = you@yourdomain.com smtp_server = localhost error_email_from = paste@localhost [server:main] use = egg:Paste#http host = 127.0.0.1 port = 5000 [app:main] use = config:development.ini # Add additional test specific configuration options as necessary. Pylons-1.0.2/pylons/templates/default_project/MANIFEST.in_tmpl0000644000175000017500000000020012451647626023623 0ustar benben00000000000000include {{package}}/config/deployment.ini_tmpl recursive-include {{package}}/public * recursive-include {{package}}/templates * Pylons-1.0.2/pylons/templates/default_project/ez_setup.py0000644000175000017500000002276412451647626023264 0ustar benben00000000000000#!python """Bootstrap setuptools installation If you want to use setuptools in your package's setup.py, just include this file in the same directory with it, and add this to the top of your setup.py:: from ez_setup import use_setuptools use_setuptools() If you want to require a specific version of setuptools, set a download mirror, or use an alternate download directory, you can do so by supplying the appropriate options to ``use_setuptools()``. This file can also be run as a script to install or upgrade setuptools. """ import sys DEFAULT_VERSION = "0.6c9" DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3] md5_data = { 'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca', 'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb', 'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b', 'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a', 'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618', 'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac', 'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5', 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4', 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c', 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b', 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27', 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277', 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa', 'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e', 'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e', 'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f', 'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2', 'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc', 'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167', 'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64', 'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d', 'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20', 'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab', 'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53', 'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2', 'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e', 'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372', 'setuptools-0.6c8-py2.3.egg': '50759d29b349db8cfd807ba8303f1902', 'setuptools-0.6c8-py2.4.egg': 'cba38d74f7d483c06e9daa6070cce6de', 'setuptools-0.6c8-py2.5.egg': '1721747ee329dc150590a58b3e1ac95b', 'setuptools-0.6c9-py2.3.egg': 'a83c4020414807b496e4cfbe08507c03', 'setuptools-0.6c9-py2.4.egg': '260a2be2e5388d66bdaee06abec6342a', 'setuptools-0.6c9-py2.5.egg': 'fe67c3e5a17b12c0e7c541b7ea43a8e6', 'setuptools-0.6c9-py2.6.egg': 'ca37b1ff16fa2ede6e19383e7b59245a', } import sys, os try: from hashlib import md5 except ImportError: from md5 import md5 def _validate_md5(egg_name, data): if egg_name in md5_data: digest = md5(data).hexdigest() if digest != md5_data[egg_name]: print >>sys.stderr, ( "md5 validation of %s failed! (Possible download problem?)" % egg_name ) sys.exit(2) return data def use_setuptools( version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, download_delay=15 ): """Automatically find/download setuptools and make it available on sys.path `version` should be a valid setuptools version number that is available as an egg for download under the `download_base` URL (which should end with a '/'). `to_dir` is the directory where setuptools will be downloaded, if it is not already available. If `download_delay` is specified, it should be the number of seconds that will be paused before initiating a download, should one be required. If an older version of setuptools is installed, this routine will print a message to ``sys.stderr`` and raise SystemExit in an attempt to abort the calling script. """ was_imported = 'pkg_resources' in sys.modules or 'setuptools' in sys.modules def do_download(): egg = download_setuptools(version, download_base, to_dir, download_delay) sys.path.insert(0, egg) import setuptools; setuptools.bootstrap_install_from = egg try: import pkg_resources except ImportError: return do_download() try: pkg_resources.require("setuptools>="+version); return except pkg_resources.VersionConflict, e: if was_imported: print >>sys.stderr, ( "The required version of setuptools (>=%s) is not available, and\n" "can't be installed while this script is running. Please install\n" " a more recent version first, using 'easy_install -U setuptools'." "\n\n(Currently using %r)" ) % (version, e.args[0]) sys.exit(2) else: del pkg_resources, sys.modules['pkg_resources'] # reload ok return do_download() except pkg_resources.DistributionNotFound: return do_download() def download_setuptools( version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, delay = 15 ): """Download setuptools from a specified location and return its filename `version` should be a valid setuptools version number that is available as an egg for download under the `download_base` URL (which should end with a '/'). `to_dir` is the directory where the egg will be downloaded. `delay` is the number of seconds to pause before an actual download attempt. """ import urllib2, shutil egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3]) url = download_base + egg_name saveto = os.path.join(to_dir, egg_name) src = dst = None if not os.path.exists(saveto): # Avoid repeated downloads try: from distutils import log if delay: log.warn(""" --------------------------------------------------------------------------- This script requires setuptools version %s to run (even to display help). I will attempt to download it for you (from %s), but you may need to enable firewall access for this script first. I will start the download in %d seconds. (Note: if this machine does not have network access, please obtain the file %s and place it in this directory before rerunning this script.) ---------------------------------------------------------------------------""", version, download_base, delay, url ); from time import sleep; sleep(delay) log.warn("Downloading %s", url) src = urllib2.urlopen(url) # Read/write all in one block, so we don't create a corrupt file # if the download is interrupted. data = _validate_md5(egg_name, src.read()) dst = open(saveto,"wb"); dst.write(data) finally: if src: src.close() if dst: dst.close() return os.path.realpath(saveto) def main(argv, version=DEFAULT_VERSION): """Install or upgrade setuptools and EasyInstall""" try: import setuptools except ImportError: egg = None try: egg = download_setuptools(version, delay=0) sys.path.insert(0,egg) from setuptools.command.easy_install import main return main(list(argv)+[egg]) # we're done here finally: if egg and os.path.exists(egg): os.unlink(egg) else: if setuptools.__version__ == '0.0.1': print >>sys.stderr, ( "You have an obsolete version of setuptools installed. Please\n" "remove it from your system entirely before rerunning this script." ) sys.exit(2) req = "setuptools>="+version import pkg_resources try: pkg_resources.require(req) except pkg_resources.VersionConflict: try: from setuptools.command.easy_install import main except ImportError: from easy_install import main main(list(argv)+[download_setuptools(delay=0)]) sys.exit(0) # try to force an exit else: if argv: from setuptools.command.easy_install import main main(argv) else: print "Setuptools version",version,"or greater has been installed." print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)' def update_md5(filenames): """Update our built-in md5 registry""" import re for name in filenames: base = os.path.basename(name) f = open(name,'rb') md5_data[base] = md5(f.read()).hexdigest() f.close() data = [" %r: %r,\n" % it for it in md5_data.items()] data.sort() repl = "".join(data) import inspect srcfile = inspect.getsourcefile(sys.modules[__name__]) f = open(srcfile, 'rb'); src = f.read(); f.close() match = re.search("\nmd5_data = {\n([^}]+)}", src) if not match: print >>sys.stderr, "Internal error!" sys.exit(2) src = src[:match.start(1)] + repl + src[match.end(1):] f = open(srcfile,'w') f.write(src) f.close() if __name__=='__main__': if len(sys.argv)>2 and sys.argv[1]=='--md5update': update_md5(sys.argv[2:]) else: main(sys.argv[1:]) Pylons-1.0.2/pylons/templates/test_restcontroller.py_tmpl0000644000175000017500000000317712451647626023425 0ustar benben00000000000000from {{base_package}}.tests import * class Test{{name}}Controller(TestController): def test_index(self): response = self.app.get(url('{{nameprefix}}{{pluralname}}')) # Test response... def test_index_as_xml(self): response = self.app.get(url('formatted_{{nameprefix}}{{pluralname}}', format='xml')) def test_create(self): response = self.app.post(url('{{nameprefix}}{{pluralname}}')) def test_new(self): response = self.app.get(url('{{nameprefix}}new_{{singularname}}')) def test_new_as_xml(self): response = self.app.get(url('formatted_{{nameprefix}}new_{{singularname}}', format='xml')) def test_update(self): response = self.app.put(url('{{nameprefix}}{{singularname}}', id=1)) def test_update_browser_fakeout(self): response = self.app.post(url('{{nameprefix}}{{singularname}}', id=1), params=dict(_method='put')) def test_delete(self): response = self.app.delete(url('{{nameprefix}}{{singularname}}', id=1)) def test_delete_browser_fakeout(self): response = self.app.post(url('{{nameprefix}}{{singularname}}', id=1), params=dict(_method='delete')) def test_show(self): response = self.app.get(url('{{nameprefix}}{{singularname}}', id=1)) def test_show_as_xml(self): response = self.app.get(url('formatted_{{nameprefix}}{{singularname}}', id=1, format='xml')) def test_edit(self): response = self.app.get(url('{{nameprefix}}edit_{{singularname}}', id=1)) def test_edit_as_xml(self): response = self.app.get(url('formatted_{{nameprefix}}edit_{{singularname}}', id=1, format='xml')) Pylons-1.0.2/pylons/templates/minimal_project/0000755000175000017500000000000012553621453021034 5ustar benben00000000000000Pylons-1.0.2/pylons/templates/minimal_project/README.txt_tmpl0000644000175000017500000000072312451647626023577 0ustar benben00000000000000This file is for you to describe the {{project}} application. Typically you would include information such as the information below: Installation and Setup ====================== Install ``{{project}}`` using easy_install:: easy_install {{project}} Make a config file as follows:: paster make-config {{project}} config.ini Tweak the config file as appropriate and then setup the application:: paster setup-app config.ini Then you are ready to go. Pylons-1.0.2/pylons/templates/minimal_project/setup.cfg_tmpl0000644000175000017500000000022612451647626023720 0ustar benben00000000000000[egg_info] tag_build = dev tag_svn_revision = true [easy_install] find_links = http://www.pylonshq.com/download/ [nosetests] with-pylons = test.ini Pylons-1.0.2/pylons/templates/minimal_project/setup.py_tmpl0000644000175000017500000000227112451647626023613 0ustar benben00000000000000try: from setuptools import setup, find_packages except ImportError: from ez_setup import use_setuptools use_setuptools() from setuptools import setup, find_packages setup( name='{{project}}', version='{{version}}', description={{repr(description)}}, author={{repr(author)}}, author_email={{repr(author_email)}}, url={{repr(url)}}, install_requires=[ "Pylons>=1.0.1rc1", {{if sqlalchemy}} "SQLAlchemy>=0.5", {{endif}} {{if template_engine == 'genshi'}} "Genshi>=0.4", {{elif template_engine == 'jinja2'}} "Jinja2", {{endif}} ], setup_requires=["PasteScript>=1.6.3"], packages=find_packages(exclude=['ez_setup']), include_package_data=True, test_suite='nose.collector', package_data={'{{package}}': ['i18n/*/LC_MESSAGES/*.mo']}, #message_extractors={'{{package}}': [ # ('**.py', 'python', None), # {{babel_templates_extractor}}('public/**', 'ignore', None)]}, zip_safe={{zip_safe}}, paster_plugins={{egg_plugins}}, entry_points=""" [paste.app_factory] main = {{package}}.wsgiapp:make_app [paste.app_install] main = pylons.util:PylonsInstaller """, ) Pylons-1.0.2/pylons/templates/minimal_project/+package+/0000755000175000017500000000000012553621453022555 5ustar benben00000000000000Pylons-1.0.2/pylons/templates/minimal_project/+package+/controllers/0000755000175000017500000000000012553621453025123 5ustar benben00000000000000Pylons-1.0.2/pylons/templates/minimal_project/+package+/controllers/__init__.py_tmpl0000644000175000017500000000120312451647626030273 0ustar benben00000000000000"""The base Controller API Provides the BaseController class for subclassing. """ from pylons.controllers import WSGIController {{if template_engine in ('genshi', 'jinja2', 'mako')}} from pylons.templating import render_{{template_engine}} as render {{endif}} class BaseController(WSGIController): def __call__(self, environ, start_response): """Invoke the Controller""" # WSGIController.__call__ dispatches to the Controller method # the request is routed to. This routing information is # available in environ['pylons.routes_dict'] return WSGIController.__call__(self, environ, start_response) Pylons-1.0.2/pylons/templates/minimal_project/+package+/routing.py_tmpl0000644000175000017500000000157112451647626025665 0ustar benben00000000000000"""Routes configuration The more specific and detailed routes should be defined first so they may take precedent over the more generic routes. For more information refer to the routes manual at http://routes.groovie.org/docs/ """ from routes import Mapper def make_map(config): """Create, configure and return the routes Mapper""" map = Mapper(directory=config['pylons.paths']['controllers'], always_scan=config['debug']) map.minimization = False map.explicit = False # The ErrorController route (handles 404/500 error pages); it should # likely stay at the top, ensuring it can always be resolved map.connect('/error/{action}', controller='error') map.connect('/error/{action}/{id}', controller='error') # CUSTOM ROUTES HERE map.connect('/{controller}/{action}') map.connect('/{controller}/{action}/{id}') return map Pylons-1.0.2/pylons/templates/minimal_project/+package+/helpers.py_tmpl0000644000175000017500000000042112451647626025631 0ustar benben00000000000000"""Helper functions Consists of functions to typically be used within templates, but also available to Controllers. This module is available to templates as 'h'. """ # Import helpers as desired, or define your own, ie: #from webhelpers.html.tags import checkbox, password Pylons-1.0.2/pylons/templates/minimal_project/+package+/config/0000755000175000017500000000000012553621453024022 5ustar benben00000000000000Pylons-1.0.2/pylons/templates/minimal_project/+package+/config/deployment.ini_tmpl_tmpl0000644000175000017500000000250512451647626031004 0ustar benben00000000000000# # {{project}} - Pylons configuration # # The %(here)s variable will be replaced with the parent directory of this file # [DEFAULT] debug = true email_to = you@yourdomain.com smtp_server = localhost error_email_from = paste@localhost [server:main] use = egg:Paste#http host = 0.0.0.0 port = 5000 [app:main] use = egg:{{project}} full_stack = true static_files = true cache_dir = %(here)s/data beaker.session.key = {{package}} beaker.session.secret = ${app_instance_secret} app_instance_uuid = ${app_instance_uuid} # If you'd like to fine-tune the individual locations of the cache data dirs # for the Cache data, or the Session saves, un-comment the desired settings # here: #beaker.cache.data_dir = %(here)s/data/cache #beaker.session.data_dir = %(here)s/data/sessions # WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* # Debug mode will enable the interactive debugging tool, allowing ANYONE to # execute malicious code after an exception is raised. set debug = false # Logging configuration [loggers] keys = root [handlers] keys = console [formatters] keys = generic [logger_root] level = INFO handlers = console [handler_console] class = StreamHandler args = (sys.stderr,) level = NOTSET formatter = generic [formatter_generic] format = %(asctime)s %(levelname)-5.5s [%(name)s] [%(threadName)s] %(message)s Pylons-1.0.2/pylons/templates/minimal_project/+package+/wsgiapp.py_tmpl0000644000175000017500000001204312451647626025644 0ustar benben00000000000000"""The {{project}} WSGI application""" import os from beaker.cache import CacheManager from beaker.middleware import SessionMiddleware from beaker.util import parse_cache_config_options {{if template_engine == 'mako'}} from mako.lookup import TemplateLookup {{elif template_engine == 'genshi'}} from genshi.template import TemplateLoader {{elif template_engine == 'jinja2'}} from jinja2 import ChoiceLoader, Environment, FileSystemLoader {{endif}} from paste.cascade import Cascade from paste.registry import RegistryManager from paste.urlparser import StaticURLParser from paste.deploy.converters import asbool from pylons.configuration import PylonsConfig {{if template_engine == 'mako'}} from pylons.error import handle_mako_error {{endif}} from pylons.middleware import ErrorHandler, StatusCodeRedirect from pylons.wsgiapp import PylonsApp from routes.middleware import RoutesMiddleware import {{package}}.helpers from {{package}}.routing import make_map def load_environment(global_conf, app_conf): """Configure the Pylons environment via the ``pylons.config`` object """ # Pylons paths config = PylonsConfig() root = os.path.dirname(os.path.abspath(__file__)) paths = dict(root=root, controllers=os.path.join(root, 'controllers'), static_files=os.path.join(root, 'public'), templates=[os.path.join(root, 'templates')]) # Initialize config with the basic options config.init_app(global_conf, app_conf, package='{{package}}', paths=paths) config['routes.map'] = make_map(config) config['pylons.app_globals'] = Globals(config) config['pylons.h'] = {{package}}.helpers {{if template_engine == 'mako'}} # Create the Mako TemplateLookup, with the default auto-escaping config['pylons.app_globals'].mako_lookup = TemplateLookup( directories=paths['templates'], error_handler=handle_mako_error, module_directory=os.path.join(app_conf['cache_dir'], 'templates'), input_encoding='utf-8', default_filters=['escape'], imports=['from markupsafe import escape']) {{elif template_engine == 'genshi'}} # Create the Genshi TemplateLoader config['pylons.app_globals'].genshi_loader = TemplateLoader( paths['templates'], auto_reload=True) {{elif template_engine == 'jinja2'}} # Create the Jinja2 Environment config['pylons.app_globals'].jinja2_env = Environment(loader=ChoiceLoader( [FileSystemLoader(path) for path in paths['templates']])) # Jinja2's unable to request c's attributes without strict_c config['pylons.strict_c'] = True {{endif}} # CONFIGURATION OPTIONS HERE (note: all config options will override # any Pylons config options) return config def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether or not this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:] section of the Paste ini file (where defaults to main). """ # Configure the Pylons environment config = load_environment(global_conf, app_conf) # The Pylons WSGI app app = PylonsApp(config=config) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map'], singleton=False) app = SessionMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # Display error documents for 401, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app) else: app = StatusCodeRedirect(app, [401, 403, 404, 500]) # Establish the Registry for this application app = RegistryManager(app) if asbool(static_files): # Serve static files static_app = StaticURLParser(config['pylons.paths']['static_files']) app = Cascade([static_app, app]) app.config = config return app class Globals(object): """Globals acts as a container for objects available throughout the life of the application """ def __init__(self, config): """One instance of Globals is created during application initialization and is available during requests via the 'app_globals' variable """ self.cache = CacheManager(**parse_cache_config_options(config)) Pylons-1.0.2/pylons/templates/minimal_project/+package+/tests/0000755000175000017500000000000012553621453023717 5ustar benben00000000000000Pylons-1.0.2/pylons/templates/minimal_project/+package+/tests/__init__.py_tmpl0000644000175000017500000000177212451647626027102 0ustar benben00000000000000"""Pylons application test package This package assumes the Pylons environment is already loaded, such as when this script is imported from the `nosetests --with-pylons=test.ini` command. This module initializes the application via ``websetup`` (`paster setup-app`) and provides the base testing objects. """ from unittest import TestCase from paste.deploy import loadapp from paste.script.appinstall import SetupCommand from pylons import url from routes.util import URLGenerator from webtest import TestApp import pylons.test __all__ = ['environ', 'url', 'TestController'] # Invoke websetup with the current config file SetupCommand('setup-app').run([pylons.test.pylonsapp.config['__file__']]) environ = {} class TestController(TestCase): def __init__(self, *args, **kwargs): wsgiapp = pylons.test.pylonsapp config = wsgiapp.config self.app = TestApp(wsgiapp) url._push_object(URLGenerator(config['routes.map'], environ)) TestCase.__init__(self, *args, **kwargs) Pylons-1.0.2/pylons/templates/minimal_project/+package+/public/0000755000175000017500000000000012553621453024033 5ustar benben00000000000000Pylons-1.0.2/pylons/templates/minimal_project/+package+/public/favicon.ico0000644000175000017500000000545612451647626026175 0ustar benben00000000000000(6h^ h( 333333033ff33036ffb303fnf300ff0ffnfdnfd`Ff  ??( N^ Z 6R&6 "bZb~ v Vn~"B^j  ~Rf*jFj vNj  b""f  >Zz^v&>n~Vj& Nb ^:RbjfvVr**>^j~Nf "*n R~zVj f&j>^ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ RRR 494 RRR #,G??CI=??',' - F ?,'!A/6X& J?#1 573>XX7E.1ZZZZZZZZZ!OQ ZZZZZZZZZ X+ZZZZZZZZZZZVSSZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ  ??(  WpTk Tk Tk Wn WkNaM_ViWo Tk Tk Tk Vn!iffkVq !`Z}cjOkl ffh)gdiC_ y  w=]j df(giPeb uMd jf( oa% } +)\w m * i:Qn%^&?~ O$6 V K Y ] >[#j c S| Y {7Q v  G w i4=\ e gEh C-n"u6 ??Pylons-1.0.2/pylons/templates/minimal_project/+package+/public/pylons-logo.gif0000755000175000017500000000453712451647626027027 0ustar benben00000000000000GIF89a;Dzyu)))ZZZHHH%%%2!!!Yna(,<<;޾9{.©A 221(('LD&##"'''&&&"""  (((###$$%'(($##$$$(''***+++onn0!,;DpH,Ȥrl:ШtJZجvzxLl$͆Rn+4||2dC lezxq?=N v n? =pwӗ pڣŒb\eMY,[# ‹S&0܈gP0S6ȑG1 Cj;/*sQز/1e&f):ٳ0A@ҫ1؀hp ޼֖/ -w$% oΫw$x%AT^bd_5;RNR`[ =0 P{,f ""QVz +`Pi@O2,+u*P w@%2'@H" bwaUu.Md%i3QfE{H`L}jEQEAV^1(m UBKti@6T@c\D4-PD>+W64@64"N=xDiRExLY@!gQr/U᧍B EDdIj*: DI:U 5EDaN^[bD99N: :J}cR`kN)Gi)F JZ$a@:DJbgN{붲 A+m;bp.q-&;BXnO2WDJ;%6ZVFN D@JpöʂpxD˶JRuy"A/Zos| n3pL S@bW@]4< T26/k q(:7{F/xnKRYDfv-M`/@5?L$[76Q(#%A1_F(Պ)Ƹt&>w٠] w( y桼7(Gd 5{e x@cn\֋Xڢx|(A>(˞ ΄] pz@D>"x x?0xy#XS9z8]bq6$hGs~7EI@Ji'sяqѓ6X\?=z6 UUFdB&88y+툗@)_?d9 Welcome to Pylons!

Welcome to Logo displaying the word Pylons


Let's begin!

If you haven't used Pylons before, start with the beginners' tutorial.

Pylons-1.0.2/pylons/templates/minimal_project/+package+/__init__.py_tmpl0000644000175000017500000000000012451647626025717 0ustar benben00000000000000Pylons-1.0.2/pylons/templates/minimal_project/+package+/templates/0000755000175000017500000000000012553621453024553 5ustar benben00000000000000Pylons-1.0.2/pylons/templates/minimal_project/+package+/templates/.distutils_placeholder0000644000175000017500000000000012451647626031137 0ustar benben00000000000000Pylons-1.0.2/pylons/templates/minimal_project/+package+/templates/__init__.py_tmpl0000644000175000017500000000011612451647626027725 0ustar benben00000000000000{{if template_engine not in ['genshi', 'kid']}} {{skip_template()}} {{endif}} Pylons-1.0.2/pylons/templates/minimal_project/development.ini_tmpl0000644000175000017500000000361112451647626025123 0ustar benben00000000000000# # {{project}} - Pylons development environment configuration # # The %(here)s variable will be replaced with the parent directory of this file # [DEFAULT] debug = true # Uncomment and replace with the address which should receive any error reports #email_to = you@yourdomain.com smtp_server = localhost error_email_from = paste@localhost [server:main] use = egg:Paste#http host = 127.0.0.1 port = 5000 [app:main] use = egg:{{project}} full_stack = true static_files = true cache_dir = %(here)s/data beaker.session.key = {{package}} beaker.session.secret = somesecret # If you'd like to fine-tune the individual locations of the cache data dirs # for the Cache data, or the Session saves, un-comment the desired settings # here: #beaker.cache.data_dir = %(here)s/data/cache #beaker.session.data_dir = %(here)s/data/sessions # WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* # Debug mode will enable the interactive debugging tool, allowing ANYONE to # execute malicious code after an exception is raised. #set debug = false # Logging configuration [loggers] keys = root, routes, {{package_logger}} [handlers] keys = console [formatters] keys = generic [logger_root] level = INFO handlers = console [logger_routes] level = INFO handlers = qualname = routes.middleware # "level = DEBUG" logs the route matched and routing variables. [logger_{{package_logger}}] level = DEBUG handlers = qualname = {{package}} {{if sqlalchemy}} [logger_sqlalchemy] level = INFO handlers = qualname = sqlalchemy.engine # "level = INFO" logs SQL queries. # "level = DEBUG" logs SQL queries and results. # "level = WARN" logs neither. (Recommended for production systems.) {{endif}} [handler_console] class = StreamHandler args = (sys.stderr,) level = NOTSET formatter = generic [formatter_generic] format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] [%(threadName)s] %(message)s datefmt = %H:%M:%S Pylons-1.0.2/pylons/templates/minimal_project/test.ini_tmpl0000644000175000017500000000077612451647626023571 0ustar benben00000000000000# # {{project}} - Pylons testing environment configuration # # The %(here)s variable will be replaced with the parent directory of this file # [DEFAULT] debug = true # Uncomment and replace with the address which should receive any error reports #email_to = you@yourdomain.com smtp_server = localhost error_email_from = paste@localhost [server:main] use = egg:Paste#http host = 127.0.0.1 port = 5000 [app:main] use = config:development.ini # Add additional test specific configuration options as necessary. Pylons-1.0.2/pylons/templates/minimal_project/MANIFEST.in_tmpl0000644000175000017500000000020012451647626023625 0ustar benben00000000000000include {{package}}/config/deployment.ini_tmpl recursive-include {{package}}/public * recursive-include {{package}}/templates * Pylons-1.0.2/pylons/templates/minimal_project/ez_setup.py0000644000175000017500000002276412451647626023266 0ustar benben00000000000000#!python """Bootstrap setuptools installation If you want to use setuptools in your package's setup.py, just include this file in the same directory with it, and add this to the top of your setup.py:: from ez_setup import use_setuptools use_setuptools() If you want to require a specific version of setuptools, set a download mirror, or use an alternate download directory, you can do so by supplying the appropriate options to ``use_setuptools()``. This file can also be run as a script to install or upgrade setuptools. """ import sys DEFAULT_VERSION = "0.6c9" DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3] md5_data = { 'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca', 'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb', 'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b', 'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a', 'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618', 'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac', 'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5', 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4', 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c', 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b', 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27', 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277', 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa', 'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e', 'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e', 'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f', 'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2', 'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc', 'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167', 'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64', 'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d', 'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20', 'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab', 'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53', 'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2', 'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e', 'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372', 'setuptools-0.6c8-py2.3.egg': '50759d29b349db8cfd807ba8303f1902', 'setuptools-0.6c8-py2.4.egg': 'cba38d74f7d483c06e9daa6070cce6de', 'setuptools-0.6c8-py2.5.egg': '1721747ee329dc150590a58b3e1ac95b', 'setuptools-0.6c9-py2.3.egg': 'a83c4020414807b496e4cfbe08507c03', 'setuptools-0.6c9-py2.4.egg': '260a2be2e5388d66bdaee06abec6342a', 'setuptools-0.6c9-py2.5.egg': 'fe67c3e5a17b12c0e7c541b7ea43a8e6', 'setuptools-0.6c9-py2.6.egg': 'ca37b1ff16fa2ede6e19383e7b59245a', } import sys, os try: from hashlib import md5 except ImportError: from md5 import md5 def _validate_md5(egg_name, data): if egg_name in md5_data: digest = md5(data).hexdigest() if digest != md5_data[egg_name]: print >>sys.stderr, ( "md5 validation of %s failed! (Possible download problem?)" % egg_name ) sys.exit(2) return data def use_setuptools( version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, download_delay=15 ): """Automatically find/download setuptools and make it available on sys.path `version` should be a valid setuptools version number that is available as an egg for download under the `download_base` URL (which should end with a '/'). `to_dir` is the directory where setuptools will be downloaded, if it is not already available. If `download_delay` is specified, it should be the number of seconds that will be paused before initiating a download, should one be required. If an older version of setuptools is installed, this routine will print a message to ``sys.stderr`` and raise SystemExit in an attempt to abort the calling script. """ was_imported = 'pkg_resources' in sys.modules or 'setuptools' in sys.modules def do_download(): egg = download_setuptools(version, download_base, to_dir, download_delay) sys.path.insert(0, egg) import setuptools; setuptools.bootstrap_install_from = egg try: import pkg_resources except ImportError: return do_download() try: pkg_resources.require("setuptools>="+version); return except pkg_resources.VersionConflict, e: if was_imported: print >>sys.stderr, ( "The required version of setuptools (>=%s) is not available, and\n" "can't be installed while this script is running. Please install\n" " a more recent version first, using 'easy_install -U setuptools'." "\n\n(Currently using %r)" ) % (version, e.args[0]) sys.exit(2) else: del pkg_resources, sys.modules['pkg_resources'] # reload ok return do_download() except pkg_resources.DistributionNotFound: return do_download() def download_setuptools( version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, delay = 15 ): """Download setuptools from a specified location and return its filename `version` should be a valid setuptools version number that is available as an egg for download under the `download_base` URL (which should end with a '/'). `to_dir` is the directory where the egg will be downloaded. `delay` is the number of seconds to pause before an actual download attempt. """ import urllib2, shutil egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3]) url = download_base + egg_name saveto = os.path.join(to_dir, egg_name) src = dst = None if not os.path.exists(saveto): # Avoid repeated downloads try: from distutils import log if delay: log.warn(""" --------------------------------------------------------------------------- This script requires setuptools version %s to run (even to display help). I will attempt to download it for you (from %s), but you may need to enable firewall access for this script first. I will start the download in %d seconds. (Note: if this machine does not have network access, please obtain the file %s and place it in this directory before rerunning this script.) ---------------------------------------------------------------------------""", version, download_base, delay, url ); from time import sleep; sleep(delay) log.warn("Downloading %s", url) src = urllib2.urlopen(url) # Read/write all in one block, so we don't create a corrupt file # if the download is interrupted. data = _validate_md5(egg_name, src.read()) dst = open(saveto,"wb"); dst.write(data) finally: if src: src.close() if dst: dst.close() return os.path.realpath(saveto) def main(argv, version=DEFAULT_VERSION): """Install or upgrade setuptools and EasyInstall""" try: import setuptools except ImportError: egg = None try: egg = download_setuptools(version, delay=0) sys.path.insert(0,egg) from setuptools.command.easy_install import main return main(list(argv)+[egg]) # we're done here finally: if egg and os.path.exists(egg): os.unlink(egg) else: if setuptools.__version__ == '0.0.1': print >>sys.stderr, ( "You have an obsolete version of setuptools installed. Please\n" "remove it from your system entirely before rerunning this script." ) sys.exit(2) req = "setuptools>="+version import pkg_resources try: pkg_resources.require(req) except pkg_resources.VersionConflict: try: from setuptools.command.easy_install import main except ImportError: from easy_install import main main(list(argv)+[download_setuptools(delay=0)]) sys.exit(0) # try to force an exit else: if argv: from setuptools.command.easy_install import main main(argv) else: print "Setuptools version",version,"or greater has been installed." print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)' def update_md5(filenames): """Update our built-in md5 registry""" import re for name in filenames: base = os.path.basename(name) f = open(name,'rb') md5_data[base] = md5(f.read()).hexdigest() f.close() data = [" %r: %r,\n" % it for it in md5_data.items()] data.sort() repl = "".join(data) import inspect srcfile = inspect.getsourcefile(sys.modules[__name__]) f = open(srcfile, 'rb'); src = f.read(); f.close() match = re.search("\nmd5_data = {\n([^}]+)}", src) if not match: print >>sys.stderr, "Internal error!" sys.exit(2) src = src[:match.start(1)] + repl + src[match.end(1):] f = open(srcfile,'w') f.write(src) f.close() if __name__=='__main__': if len(sys.argv)>2 and sys.argv[1]=='--md5update': update_md5(sys.argv[2:]) else: main(sys.argv[1:]) Pylons-1.0.2/pylons/templates/__init__.py0000644000175000017500000000000012451647626017766 0ustar benben00000000000000Pylons-1.0.2/pylons/templates/test_controller.py_tmpl0000644000175000017500000000032712451647626022521 0ustar benben00000000000000from {{base_package}}.tests import * class Test{{name}}Controller(TestController): def test_index(self): response = self.app.get(url(controller='{{fname}}', action='index')) # Test response... Pylons-1.0.2/pylons/templates/controller.py_tmpl0000644000175000017500000000062112451647626021457 0ustar benben00000000000000import logging from pylons import request, response, session, tmpl_context as c, url from pylons.controllers.util import abort, redirect {{importstatement}} log = logging.getLogger(__name__) class {{name}}Controller(BaseController): def index(self): # Return a rendered template #return render('/{{tmpl_name}}.mako') # or, return a string return 'Hello World' Pylons-1.0.2/pylons/templates/restcontroller.py_tmpl0000644000175000017500000000401612451647626022357 0ustar benben00000000000000import logging from pylons import request, response, session, tmpl_context as c, url from pylons.controllers.util import abort, redirect {{importstatement}} log = logging.getLogger(__name__) class {{classname}}Controller(BaseController): """REST Controller styled on the Atom Publishing Protocol""" # To properly map this controller, ensure your config/routing.py # file has a resource setup: # {{resource_command}} def index(self, format='html'): """GET /{{path}}{{pluralname}}: All items in the collection""" # url('{{nameprefix}}{{pluralname}}') def create(self): """POST /{{path}}{{pluralname}}: Create a new item""" # url('{{nameprefix}}{{pluralname}}') def new(self, format='html'): """GET /{{path}}{{pluralname}}/new: Form to create a new item""" # url('{{nameprefix}}new_{{singularname}}') def update(self, id): """PUT /{{path}}{{pluralname}}/id: Update an existing item""" # Forms posted to this method should contain a hidden field: # # Or using helpers: # h.form(url('{{nameprefix}}{{singularname}}', id=ID), # method='put') # url('{{nameprefix}}{{singularname}}', id=ID) def delete(self, id): """DELETE /{{path}}{{pluralname}}/id: Delete an existing item""" # Forms posted to this method should contain a hidden field: # # Or using helpers: # h.form(url('{{nameprefix}}{{singularname}}', id=ID), # method='delete') # url('{{nameprefix}}{{singularname}}', id=ID) def show(self, id, format='html'): """GET /{{path}}{{pluralname}}/id: Show a specific item""" # url('{{nameprefix}}{{singularname}}', id=ID) def edit(self, id, format='html'): """GET /{{path}}{{pluralname}}/id/edit: Form to edit an existing item""" # url('{{nameprefix}}edit_{{singularname}}', id=ID) Pylons-1.0.2/Pylons.egg-info/0000755000175000017500000000000012553621453015314 5ustar benben00000000000000Pylons-1.0.2/Pylons.egg-info/requires.txt0000644000175000017500000000044612553621447017723 0ustar benben00000000000000Routes>=1.12.3 WebHelpers>=0.6.4 Beaker>=1.5.4 Paste>=1.7.5.1 PasteDeploy>=1.5.0 PasteScript>=1.7.4.2 FormEncode>=1.2.4 simplejson>=2.2.1 decorator>=3.3.2 nose>=1.1.2 Mako>=0.5.0 WebError>=0.10.3 WebTest>=1.3.1 Tempita>=0.5.1 MarkupSafe>=0.15 WebOb>=1.1.1 [jinja2] Jinja2 [genshi] Genshi>=0.6Pylons-1.0.2/Pylons.egg-info/not-zip-safe0000644000175000017500000000000112456571516017550 0ustar benben00000000000000 Pylons-1.0.2/Pylons.egg-info/top_level.txt0000644000175000017500000000002212553621447020043 0ustar benben00000000000000pylons test_files Pylons-1.0.2/Pylons.egg-info/dependency_links.txt0000644000175000017500000000000112553621447021365 0ustar benben00000000000000 Pylons-1.0.2/Pylons.egg-info/entry_points.txt0000644000175000017500000000102712553621447020615 0ustar benben00000000000000 [paste.paster_command] controller = pylons.commands:ControllerCommand restcontroller = pylons.commands:RestControllerCommand routes = pylons.commands:RoutesCommand shell = pylons.commands:ShellCommand [paste.paster_create_template] pylons = pylons.util:PylonsTemplate pylons_minimal = pylons.util:MinimalPylonsTemplate [paste.filter_factory] debugger = pylons.middleware:debugger_filter_factory [paste.filter_app_factory] debugger = pylons.middleware:debugger_filter_app_factory Pylons-1.0.2/Pylons.egg-info/SOURCES.txt0000644000175000017500000002161712553621447017212 0ustar benben00000000000000CHANGELOG LICENSE MANIFEST.in README.rst UPGRADING setup.cfg setup.py Pylons.egg-info/PKG-INFO Pylons.egg-info/SOURCES.txt Pylons.egg-info/dependency_links.txt Pylons.egg-info/entry_points.txt Pylons.egg-info/not-zip-safe Pylons.egg-info/requires.txt Pylons.egg-info/top_level.txt pylons/__init__.py pylons/commands.py pylons/configuration.py pylons/error.py pylons/log.py pylons/middleware.py pylons/templating.py pylons/test.py pylons/testutil.py pylons/url.py pylons/util.py pylons/wsgiapp.py pylons/controllers/__init__.py pylons/controllers/core.py pylons/controllers/jsonrpc.py pylons/controllers/util.py pylons/controllers/xmlrpc.py pylons/decorators/__init__.py pylons/decorators/cache.py pylons/decorators/rest.py pylons/decorators/secure.py pylons/decorators/util.py pylons/i18n/__init__.py pylons/i18n/translation.py pylons/media/img/bar-bg.png pylons/media/img/bg.jpg pylons/media/img/bg.png pylons/media/img/favicon.ico pylons/media/img/hatch-yellow.png pylons/media/img/header.png pylons/media/img/highlight.png pylons/media/img/logo.gif pylons/media/img/main-nav-bg-on.png pylons/media/img/main-nav-bg.png pylons/media/img/plus.jpg pylons/media/img/pylons-logo.gif pylons/media/img/pylons-powered-02.png pylons/media/img/tab-brown.png pylons/media/img/tab-traceback.png pylons/media/img/tab-white.png pylons/media/img/tab-yellow-highlight.png pylons/media/img/tab-yellow.png pylons/media/img/warning.gif pylons/media/javascripts/traceback.js pylons/media/style/black.css pylons/media/style/itraceback.css pylons/media/style/orange.css pylons/templates/__init__.py pylons/templates/controller.py_tmpl pylons/templates/restcontroller.py_tmpl pylons/templates/test_controller.py_tmpl pylons/templates/test_restcontroller.py_tmpl pylons/templates/default_project/MANIFEST.in_tmpl pylons/templates/default_project/README.txt_tmpl pylons/templates/default_project/development.ini_tmpl pylons/templates/default_project/ez_setup.py pylons/templates/default_project/setup.cfg_tmpl pylons/templates/default_project/setup.py_tmpl pylons/templates/default_project/test.ini_tmpl pylons/templates/default_project/+package+/__init__.py_tmpl pylons/templates/default_project/+package+/websetup.py_tmpl pylons/templates/default_project/+package+/config/__init__.py_tmpl pylons/templates/default_project/+package+/config/deployment.ini_tmpl_tmpl pylons/templates/default_project/+package+/config/environment.py_tmpl pylons/templates/default_project/+package+/config/middleware.py_tmpl pylons/templates/default_project/+package+/config/routing.py_tmpl pylons/templates/default_project/+package+/controllers/__init__.py_tmpl pylons/templates/default_project/+package+/controllers/error.py_tmpl pylons/templates/default_project/+package+/lib/__init__.py_tmpl pylons/templates/default_project/+package+/lib/app_globals.py_tmpl pylons/templates/default_project/+package+/lib/base.py_tmpl pylons/templates/default_project/+package+/lib/helpers.py_tmpl pylons/templates/default_project/+package+/model/__init__.py_tmpl pylons/templates/default_project/+package+/model/meta.py_tmpl pylons/templates/default_project/+package+/public/bg.png pylons/templates/default_project/+package+/public/favicon.ico pylons/templates/default_project/+package+/public/index.html_tmpl pylons/templates/default_project/+package+/public/pylons-logo.gif pylons/templates/default_project/+package+/templates/.distutils_placeholder pylons/templates/default_project/+package+/templates/__init__.py_tmpl pylons/templates/default_project/+package+/tests/__init__.py_tmpl pylons/templates/default_project/+package+/tests/test_models.py_tmpl pylons/templates/default_project/+package+/tests/functional/__init__.py_tmpl pylons/templates/minimal_project/MANIFEST.in_tmpl pylons/templates/minimal_project/README.txt_tmpl pylons/templates/minimal_project/development.ini_tmpl pylons/templates/minimal_project/ez_setup.py pylons/templates/minimal_project/setup.cfg_tmpl pylons/templates/minimal_project/setup.py_tmpl pylons/templates/minimal_project/test.ini_tmpl pylons/templates/minimal_project/+package+/__init__.py_tmpl pylons/templates/minimal_project/+package+/helpers.py_tmpl pylons/templates/minimal_project/+package+/routing.py_tmpl pylons/templates/minimal_project/+package+/wsgiapp.py_tmpl pylons/templates/minimal_project/+package+/config/deployment.ini_tmpl_tmpl pylons/templates/minimal_project/+package+/controllers/__init__.py_tmpl pylons/templates/minimal_project/+package+/public/bg.png pylons/templates/minimal_project/+package+/public/favicon.ico pylons/templates/minimal_project/+package+/public/index.html_tmpl pylons/templates/minimal_project/+package+/public/pylons-logo.gif pylons/templates/minimal_project/+package+/templates/.distutils_placeholder pylons/templates/minimal_project/+package+/templates/__init__.py_tmpl pylons/templates/minimal_project/+package+/tests/__init__.py_tmpl test_files/__init__.py test_files/event_file.py test_files/sample_controllers/__init__.py test_files/sample_controllers/controllers/__init__.py test_files/sample_controllers/controllers/goodbye.py test_files/sample_controllers/controllers/hello.py test_files/sample_controllers/controllers/i18nc.py tests/__init__.py tests/__init__.pyc tests/conftest.py tests/conftest.pyc tests/__pycache__/__init__.cpython-34.pyc tests/__pycache__/conftest.cpython-34.pyc tests/test_units/__init__.py tests/test_units/__init__.pyc tests/test_units/test_basic_app.py tests/test_units/test_basic_app.pyc tests/test_units/test_controller.py tests/test_units/test_controller.pyc tests/test_units/test_decorator_authenticate_form.py tests/test_units/test_decorator_authenticate_form.pyc tests/test_units/test_decorator_cache.py tests/test_units/test_decorator_cache.pyc tests/test_units/test_decorator_https.py tests/test_units/test_decorator_https.pyc tests/test_units/test_decorator_jsonify.py tests/test_units/test_decorator_jsonify.pyc tests/test_units/test_decorator_validate.py tests/test_units/test_decorator_validate.pyc tests/test_units/test_helpers.py tests/test_units/test_helpers.pyc tests/test_units/test_i18n.py tests/test_units/test_i18n.pyc tests/test_units/test_jsonrpc.py tests/test_units/test_jsonrpc.pyc tests/test_units/test_middleware.py tests/test_units/test_middleware.pyc tests/test_units/test_templating.py tests/test_units/test_templating.pyc tests/test_units/test_xmlrpc.py tests/test_units/test_xmlrpc.pyc tests/test_units/__pycache__/__init__.cpython-34.pyc tests/test_units/cache/cache/container_dbm/f/f2/f246b96c6e5bc523da041adfca8ffd3affc89fbd.dbm tests/test_units/cache/cache/container_dbm_lock/2/22/22b5697111b9eaf491d2f96c851cd9286eb5426f.lock tests/test_units/cache/cache/container_dbm_lock/f/f2/f246b96c6e5bc523da041adfca8ffd3affc89fbd.lock tests/test_units/cache/container_dbm/d/d5/d5fdbd7d787be89ce138c47e2928108a32299635.dbm tests/test_units/cache/container_dbm_lock/7/78/78de1e289b688271826294912a5be42267dc17d9.lock tests/test_units/cache/container_dbm_lock/d/d5/d5fdbd7d787be89ce138c47e2928108a32299635.lock tests/test_webapps/__init__.py tests/test_webapps/__init__.pyc tests/test_webapps/test_make_project.py tests/test_webapps/test_make_project.pyc tests/test_webapps/__pycache__/__init__.cpython-34.pyc tests/test_webapps/__pycache__/test_make_project.cpython-34.pyc tests/test_webapps/filestotest/app_globals.py tests/test_webapps/filestotest/base_with_xmlrpc.py tests/test_webapps/filestotest/cache_controller.py tests/test_webapps/filestotest/controller_sample.py tests/test_webapps/filestotest/controller_sqlatest.py tests/test_webapps/filestotest/controller_xmlrpc.py tests/test_webapps/filestotest/development.ini tests/test_webapps/filestotest/development_sqlatesting.ini tests/test_webapps/filestotest/environment_def_engine.py tests/test_webapps/filestotest/environment_def_sqlamodel.py tests/test_webapps/filestotest/functional_controller_cache_decorator.py tests/test_webapps/filestotest/functional_controller_xmlrpc.py tests/test_webapps/filestotest/functional_sample_controller_i18n.py tests/test_webapps/filestotest/functional_sample_controller_jinja2.py tests/test_webapps/filestotest/functional_sample_controller_mako.py tests/test_webapps/filestotest/functional_sample_controller_sample1.py tests/test_webapps/filestotest/functional_sample_controller_sample2.py tests/test_webapps/filestotest/functional_sample_controller_sample3.py tests/test_webapps/filestotest/functional_sample_controller_sample4.py tests/test_webapps/filestotest/functional_sample_controller_sqlatesting.py tests/test_webapps/filestotest/helpers_sample.py tests/test_webapps/filestotest/messages.ja.mo tests/test_webapps/filestotest/messages.ja.po tests/test_webapps/filestotest/messages.pot tests/test_webapps/filestotest/middleware_mako.py tests/test_webapps/filestotest/model__init__.py tests/test_webapps/filestotest/rest_routing.py tests/test_webapps/filestotest/test_mako.html tests/test_webapps/filestotest/test_sqlalchemy.html tests/test_webapps/filestotest/testgenshi.html tests/test_webapps/filestotest/testjinja2.html tests/test_webapps/filestotest/tests__init__.py tests/test_webapps/filestotest/websetup.pyPylons-1.0.2/Pylons.egg-info/PKG-INFO0000644000175000017500000000714212553621447016420 0ustar benben00000000000000Metadata-Version: 1.1 Name: Pylons Version: 1.0.2 Summary: Pylons Web Framework Home-page: http://www.pylonshq.com/ Author: Ben Bangert, Philip Jenvey, James Gardner Author-email: ben@groovie.org, pjenvey@underboss.org License: BSD Description: Pylons ====== The Pylons web framework is designed for building web applications and sites in an easy and concise manner. They can range from as small as a single Python module, to a substantial directory layout for larger and more complex web applications. Pylons comes with project templates that help boot-strap a new web application project, or you can start from scratch and set things up exactly as desired. Example `Hello World` --------------------- .. from paste.httpserver import serve from pylons import Configurator, Response class Hello(object): def __init__(self, request): self.request = request def index(self): return Response(body="Hello World!") if __name__ == '__main__': config = Configurator() config.begin() config.add_handler('home', '/', handler=Hello, action='index') config.end() serve(config.make_wsgi_app(), host='0.0.0.0') Core Features ------------- * A framework to make writing web applications in Python easy * Utilizes a minimalist, component-based philosophy that makes it easy to expand on * Harness existing knowledge about Python * Extensible application design * Fast and efficient, an incredibly small per-request call-stack providing top performance * Uses existing and well tested Python packages Current Status -------------- Pylons 1.0 series is stable and production ready. The Pylons Project now maintains the Pyramid web framework for future development. Pylons 1.0 users should strongly consider using it for their next project. Download and Installation ------------------------- Pylons can be installed with `Easy Install `_ by typing:: > easy_install Pylons Dependant packages are automatically installed from the `Pylons download page `_ . Development Version ------------------- Pylons development uses the Mercuial distributed version control system (DVCS) with BitBucket hosting the main repository here: `Pylons Bitbucket repository `_ Keywords: web wsgi lightweight framework sqlalchemy formencode mako templates Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Framework :: Pylons Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 :: Only Classifier: Topic :: Internet :: WWW/HTTP Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Internet :: WWW/HTTP :: WSGI Classifier: Topic :: Software Development :: Libraries :: Python Modules Pylons-1.0.2/MANIFEST.in0000644000175000017500000000035612451647626014107 0ustar benben00000000000000recursive-include pylons/templates * recursive-include pylons/media * recursive-include tests * include CHANGELOG include LICENSE include UPGRADING recursive-exclude tests/test_units/session * global-exclude .DS_Store *.hgignore *.hgtags Pylons-1.0.2/tests/0000755000175000017500000000000012553621453013500 5ustar benben00000000000000Pylons-1.0.2/tests/__pycache__/0000755000175000017500000000000012553621453015710 5ustar benben00000000000000Pylons-1.0.2/tests/__pycache__/conftest.cpython-34.pyc0000644000175000017500000000111612460016451022151 0ustar benben00000000000000 OT@sddlZddlZddlZddlZejjeZejjeZejj eejj deejjeZej j eej jdsejjeddZejjerejeqndS)NZ PASTE_TESTINGZ test_webappsoutput)sysosshutil pkg_resourcespathdirname__file__herebaseappendinsert working_set add_entryenvirongetjoinZ output_direxistsrmtreerr5/home/ben/Programming/Python/pylons/tests/conftest.pys    Pylons-1.0.2/tests/__pycache__/__init__.cpython-34.pyc0000644000175000017500000000021012460016451022055 0ustar benben00000000000000 OT@sdS)Nrrr5/home/ben/Programming/Python/pylons/tests/__init__.pysPylons-1.0.2/tests/__init__.py0000644000175000017500000000000212451647626015610 0ustar benben00000000000000# Pylons-1.0.2/tests/test_webapps/0000755000175000017500000000000012553621453016200 5ustar benben00000000000000Pylons-1.0.2/tests/test_webapps/filestotest/0000755000175000017500000000000012553621453020545 5ustar benben00000000000000Pylons-1.0.2/tests/test_webapps/filestotest/controller_xmlrpc.py0000644000175000017500000000105212451647626024674 0ustar benben00000000000000from projectname.lib.base import * from pylons.controllers import XMLRPCController class XmlrpcController(XMLRPCController): def userstatus(self): return 'basic string' userstatus.signature = [ ['string'] ] def docs(self): "This method has a docstring" return dict(mess='a little somethin', a=1, b=[1,2,3], c=('all','the')) docs.signature = [ ['struct'] ] def uni(self): "This method has a docstring" return dict(mess=u'A unicode string, oh boy') docs.signature = [ ['struct'] ] Pylons-1.0.2/tests/test_webapps/filestotest/environment_def_sqlamodel.py0000644000175000017500000000444512451647626026360 0ustar benben00000000000000"""Pylons environment configuration""" import os from mako.lookup import TemplateLookup from genshi.template import TemplateLoader from jinja2 import ChoiceLoader, Environment, FileSystemLoader from pylons.configuration import PylonsConfig from pylons.error import handle_mako_error from sqlalchemy import engine_from_config import projectname.lib.app_globals as app_globals import projectname.lib.helpers from projectname.config.routing import make_map from projectname.model import init_model def load_environment(global_conf, app_conf): """Configure the Pylons environment via the ``pylons.config`` object """ config = PylonsConfig() # Pylons paths root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) paths = dict(root=root, controllers=os.path.join(root, 'controllers'), static_files=os.path.join(root, 'public'), templates=[os.path.join(root, 'templates')]) # Initialize config with the basic options config.init_app(global_conf, app_conf, package='projectname', paths=paths) config['routes.map'] = make_map(config) config['pylons.app_globals'] = app_globals.Globals(config) config['pylons.h'] = projectname.lib.helpers # Setup cache object as early as possible import pylons pylons.cache._push_object(config['pylons.app_globals'].cache) # Create the Mako TemplateLookup, with the default auto-escaping config['pylons.app_globals'].mako_lookup = TemplateLookup( directories=paths['templates'], error_handler=handle_mako_error, module_directory=os.path.join(app_conf['cache_dir'], 'templates'), input_encoding='utf-8', default_filters=['escape'], imports=['from webhelpers.html import escape']) # Create the Genshi TemplateLoader config['pylons.app_globals'].genshi_loader = TemplateLoader( paths['templates'], auto_reload=True) # Create the Jinja2 Environment config['pylons.app_globals'].jinja2_env = Environment(loader=ChoiceLoader( [FileSystemLoader(path) for path in paths['templates']])) # CONFIGURATION OPTIONS HERE (note: all config options will override # any Pylons config options) engine = engine_from_config(config, 'sqlalchemy.') init_model(engine) return config Pylons-1.0.2/tests/test_webapps/filestotest/helpers_sample.py0000644000175000017500000000024212451647626024127 0ustar benben00000000000000"""Helper functions Consists of functions to typically be used within templates, but also available to Controllers. This module is available to both as 'h'. """ Pylons-1.0.2/tests/test_webapps/filestotest/development_sqlatesting.ini0000644000175000017500000000307212451647626026217 0ustar benben00000000000000[DEFAULT] debug = true email_to = you@yourdomain.com smtp_server = localhost error_email_from = paste@exceptions.com [server:main] use = egg:Paste#http host = 127.0.0.1 port = 5000 [app:main] use = egg:projectname cache_dir = %(here)s/data beaker.session.key = projectname beaker.session.secret = somesecret # If you'd like to fine-tune the individual locations of the cache data dirs # for Myghty, the Cache data, or the Session saves, un-comment the desired # settings here: #beaker.cache_data_dir = %(here)s/data/cache #beaker.session_data_dir = %(here)s/data/sessions # If you are using SQLAlchemy you will need to specify a # dburi. You can do this with a line similar to the # one below but adjusted for your database connection # according to the SQLAlchemy documentation. The %(here)s # part is replaced with the current directory which is # useful when using sqlite on UNIX based platforms. # For Windows you should look at the SQLAlchemy # documentation for a special syntax to use because the # path returned by %(here)s contains a : character. # SQLAlchemy database URL sqlalchemy.url = sqlite:///%(here)s/development.db sqlalchemy.echo = True # Do not set debug to true or uncomment the line below # on a production environment otherwise in the event of # an error occurring the visitor will be presented with # interactive debugging tools and these could be used to # execute malicious code. # For development purposes debug should be set to true # to enable the debugging code but be sure to set it back # to false before releasing your application. #set debug = false Pylons-1.0.2/tests/test_webapps/filestotest/testgenshi.html0000644000175000017500000000057412451647626023625 0ustar benben00000000000000 Hello from Genshi

Hello from Genshi

You visited the URL ${request.url} at ${datetime.datetime.now()}

${c.test}

Pylons-1.0.2/tests/test_webapps/filestotest/messages.ja.po0000644000175000017500000000167112451647626023321 0ustar benben00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2007-02-05 12:36+0900\n" "PO-Revision-Date: 2007-02-05 13:06+0900\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" #: controller_sample.py:7 msgid "basic index page" msgstr "根本インデクスページ" #: controller_sample.py:59 #, python-format msgid "Could not set language to \"%(lang)s\"" msgstr "「%(lang)s」に言語設定が変更できません" #: controller_sample.py:63 #, python-format msgid "Set language to \"%(lang)s\"" msgstr "言語設定を「%(lang)s」に変更しました"Pylons-1.0.2/tests/test_webapps/filestotest/test_mako.html0000644000175000017500000000014112451647626023424 0ustar benben00000000000000<% from datetime import datetime mytime = datetime.now() %> Hi everyone! The time is ${mytime} Pylons-1.0.2/tests/test_webapps/filestotest/base_with_xmlrpc.py0000644000175000017500000000162212451647626024461 0ustar benben00000000000000from pylons import tmpl_context as c, app_globals, cache, request, session from pylons.controllers import WSGIController, XMLRPCController from pylons.controllers.util import abort, etag_cache, redirect from pylons.decorators import jsonify, validate from pylons.templating import render_mako as render from pylons.i18n import N_, _, ungettext import projectname.model as model import projectname.lib.helpers as h class BaseController(WSGIController): def __call__(self, environ, start_response): # Insert any code to be run per request here. The Routes match # is under environ['pylons.routes_dict'] should you want to check # the action or route vars here return WSGIController.__call__(self, environ, start_response) # Include the '_' function in the public names __all__ = [__name for __name in locals().keys() if not __name.startswith('_') \ or __name == '_'] Pylons-1.0.2/tests/test_webapps/filestotest/environment_def_engine.py0000644000175000017500000000420212451647626025633 0ustar benben00000000000000"""Pylons environment configuration""" import os from mako.lookup import TemplateLookup from genshi.template import TemplateLoader from jinja2 import ChoiceLoader, Environment, FileSystemLoader from pylons.configuration import PylonsConfig from pylons.error import handle_mako_error import projectname.lib.app_globals as app_globals import projectname.lib.helpers from projectname.config.routing import make_map def load_environment(global_conf, app_conf): """Configure the Pylons environment via the ``pylons.config`` object """ config = PylonsConfig() # Pylons paths root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) paths = dict(root=root, controllers=os.path.join(root, 'controllers'), static_files=os.path.join(root, 'public'), templates=[os.path.join(root, 'templates')]) # Initialize config with the basic options config.init_app(global_conf, app_conf, package='projectname', paths=paths) config['routes.map'] = make_map(config) config['pylons.app_globals'] = app_globals.Globals(config) config['pylons.h'] = projectname.lib.helpers # Setup cache object as early as possible import pylons pylons.cache._push_object(config['pylons.app_globals'].cache) # Create the Mako TemplateLookup, with the default auto-escaping config['pylons.app_globals'].mako_lookup = TemplateLookup( directories=paths['templates'], error_handler=handle_mako_error, module_directory=os.path.join(app_conf['cache_dir'], 'templates'), input_encoding='utf-8', default_filters=['escape'], imports=['from webhelpers.html import escape']) # Create the Genshi TemplateLoader config['pylons.app_globals'].genshi_loader = TemplateLoader( paths['templates'], auto_reload=True) # Create the Jinja2 Environment config['pylons.app_globals'].jinja2_env = Environment(loader=ChoiceLoader( [FileSystemLoader(path) for path in paths['templates']])) # CONFIGURATION OPTIONS HERE (note: all config options will override # any Pylons config options) return config Pylons-1.0.2/tests/test_webapps/filestotest/functional_sample_controller_sample1.py0000644000175000017500000000412512451647626030520 0ustar benben00000000000000import pylons from projectname.tests import * class TestSampleController(TestController): def test_conf_with_app_globals(self): assert 'pylons.app_globals' in pylons.config assert hasattr(pylons.app_globals, 'cache') def test_root_index(self): response = self.app.get('/') assert 'Welcome' in response # Test response... def test_index(self): response = self.app.get(url(controller='sample', action='index')) assert 'basic index page' in response def test_session(self): response = self.app.get(url(controller='sample', action='session_increment')) assert response.session.has_key('counter') assert response.session['counter'] == 0 response = self.app.get(url(controller='sample', action='session_increment')) assert response.session['counter'] == 1 assert 'session incrementer' in response def test_global(self): response = self.app.get(url(controller='sample', action='globalup')) assert 'Hello' in response def test_global_persistence(self): response = self.app.get(url(controller='sample', action='global_store')) assert '0' in response response = self.app.get(url(controller='sample', action='global_store', id=2)) assert '2' in response response = self.app.get(url(controller='sample', action='global_store')) assert '2' in response response = self.app.get(url(controller='sample', action='global_store', id=3)) assert '5' in response response = self.app.get(url(controller='sample', action='global_store')) assert '5' in response def test_helper_urlfor(self): response = self.app.get(url(controller='sample', action='myself')) assert 'sample/myself' in response def test_params(self): response = self.app.get(url(controller='sample', action='myparams', extra='something', data=4)) assert 'extra' in response assert 'something' in response assert 'data' in response Pylons-1.0.2/tests/test_webapps/filestotest/functional_sample_controller_mako.py0000644000175000017500000000033712451647626030106 0ustar benben00000000000000from projectname.tests import * class TestMakoController(TestController): def test_mako(self): response = self.app.get(url(controller='sample', action='testmako')) assert 'Hello, 5+5 is 10' in response Pylons-1.0.2/tests/test_webapps/filestotest/websetup.py0000644000175000017500000000105112451647626022761 0ustar benben00000000000000"""Setup the projectname application""" import logging import pylons.test from projectname.config.environment import load_environment from projectname.model.meta import Session, Base from projectname.model import Foo from sqlalchemy import engine_from_config log = logging.getLogger(__name__) def setup_app(command, conf, vars): """Place any commands to setup projectname here""" config = load_environment(conf.global_conf, conf.local_conf) # Create the tables if they don't already exist Base.metadata.create_all(bind=Session.bind) Pylons-1.0.2/tests/test_webapps/filestotest/testjinja2.html0000644000175000017500000000043412451647626023520 0ustar benben00000000000000#import datetime Hello from Jinja2

Hello from Jinja2

You visited the URL {{ request.url }} at {{ c.now() }}

{{ c.test }}

Pylons-1.0.2/tests/test_webapps/filestotest/messages.ja.mo0000644000175000017500000000120012451647626023302 0ustar benben00000000000000<\p$q552.aCould not set language to "%(lang)s"Set language to "%(lang)s"basic index pageProject-Id-Version: PACKAGE VERSION Report-Msgid-Bugs-To: POT-Creation-Date: 2007-02-05 12:36+0900 PO-Revision-Date: 2007-02-05 13:06+0900 Last-Translator: FULL NAME Language-Team: LANGUAGE MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit 「%(lang)s」に言語設定が変更できません言語設定を「%(lang)s」に変更しました根本インデクスページPylons-1.0.2/tests/test_webapps/filestotest/controller_sample.py0000644000175000017500000000520512451647626024654 0ustar benben00000000000000import datetime from projectname.lib.base import * import projectname.lib.helpers as h from pylons import request, response, session, url from pylons import tmpl_context as c from pylons import app_globals from pylons.decorators import rest from pylons.i18n import _, get_lang, set_lang, LanguageError from pylons.templating import render_mako, render_genshi, render_jinja2 from pylons.controllers.util import abort, redirect class SampleController(BaseController): def index(self): return 'basic index page' def session_increment(self): session.setdefault('counter', -1) session['counter'] += 1 session.save() return 'session incrementer' def globalup(self): return app_globals.message def global_store(self, id=None): if id: app_globals.counter += int(id) return str(app_globals.counter) def myself(self): return request.url def myparams(self): return str(request.params) def testdefault(self): c.test = "This is in c var" return render_genshi('testgenshi.html') def test_template_caching(self): return render_mako('/test_mako.html', cache_expire='never') @rest.dispatch_on(GET='test_only_get') @rest.restrict('POST') def test_only_post(self): return 'It was a post!' @rest.restrict('GET') def test_only_get(self): return 'It was a get!' @rest.restrict('POST') @rest.dispatch_on(POST='test_only_post') def impossible(self): return 'This should never be shown' def testjinja2(self): c.test = "This is in c var" c.now = datetime.datetime.now return render_jinja2('testjinja2.html') def set_lang(self): return self._set_lang(_) def set_lang_pylonscontext(self, pylons): return self._set_lang(lambda *args: pylons.translator.ugettext(*args)) def _set_lang(self, gettext): lang = request.GET['lang'] try: set_lang(lang) except (LanguageError, IOError), e: resp_unicode = gettext('Could not set language to "%(lang)s"') % {'lang': lang} else: session['lang'] = lang session.save() resp_unicode = gettext('Set language to "%(lang)s"') % {'lang': lang} return resp_unicode def i18n_index(self): locale_list = request.languages set_lang(request.languages) return unicode(_('basic index page')) def no_lang(self): set_lang(None) response.write(_('No language')) set_lang([]) response.write(_('No languages')) return '' Pylons-1.0.2/tests/test_webapps/filestotest/tests__init__.py0000644000175000017500000000377012451647626023757 0ustar benben00000000000000"""Pylons application test package This package assumes the Pylons environment is already loaded, such as when this script is imported from the `nosetests --with-pylons=test.ini` command. This module initializes the application via ``websetup`` (`paster setup-app`) and provides the base testing objects. """ from unittest import TestCase from paste.deploy import loadapp from paste.script.appinstall import SetupCommand from pylons import url from routes.util import URLGenerator from webtest import TestApp import pylons.test __all__ = ['environ', 'url', 'TestController'] try: from sqlalchemy import engine_from_config from projectname.model.meta import Session, Base from projectname.model import Foo, init_model SQLAtesting = True except: SQLAtesting = False import os import pylons from pylons.i18n.translation import _get_translator from paste.deploy import appconfig from projectname.config.environment import load_environment here_dir = os.path.dirname(__file__) conf_dir = os.path.dirname(os.path.dirname(here_dir)) test_file = os.path.join(conf_dir, 'test.ini') conf = appconfig('config:' + test_file) config = load_environment(conf.global_conf, conf.local_conf) if SQLAtesting: engine = engine_from_config(config, 'sqlalchemy.') init_model(engine) # Invoke websetup with the current config file SetupCommand('setup-app').run([test_file]) environ = {} class TestController(TestCase): def __init__(self, *args, **kwargs): wsgiapp = loadapp('config:test.ini', relative_to=conf_dir) config = wsgiapp.config pylons.app_globals._push_object(config['pylons.app_globals']) pylons.config._push_object(config) # Initialize a translator for tests that utilize i18n translator = _get_translator(pylons.config.get('lang')) pylons.translator._push_object(translator) url._push_object(URLGenerator(config['routes.map'], environ)) self.app = TestApp(wsgiapp) TestCase.__init__(self, *args, **kwargs) Pylons-1.0.2/tests/test_webapps/filestotest/functional_sample_controller_jinja2.py0000755000175000017500000000042412451647626030334 0ustar benben00000000000000from projectname.tests import * class TestJinja2Controller(TestController): def test_jinja2(self): response = self.app.get(url(controller='sample', action='testjinja2')) assert 'Hello from Jinja2' in response assert 'This is in c var' in response Pylons-1.0.2/tests/test_webapps/filestotest/functional_sample_controller_sample2.py0000644000175000017500000000142312451647626030517 0ustar benben00000000000000from projectname.tests import * class TestSample2Controller(TestController): def test_session(self): response = self.app.get(url(controller='sample', action='session_increment')) assert response.session.has_key('counter') assert response.session['counter'] == 0 response = self.app.get(url(controller='sample', action='session_increment')) assert response.session['counter'] == 1 assert 'session incrementer' in response def test_genshi_default(self): self._test_genshi_default('testdefault') def _test_genshi_default(self, action): response = self.app.get(url(controller='sample', action=action)) assert 'Hello from Genshi' in response assert 'This is in c var' in response Pylons-1.0.2/tests/test_webapps/filestotest/functional_controller_cache_decorator.py0000755000175000017500000000352212451647626030725 0ustar benben00000000000000import time from projectname.tests import * class TestCacheController(TestController): def test_default_cache_decorator(self): response = self.app.get(url(controller='cache', action='test_default_cache_decorator')) assert 'Counter=1' in response response = self.app.get(url(controller='cache', action='test_default_cache_decorator')) assert 'Counter=1' in response response = self.app.get(url(controller='cache', action='test_get_cache_decorator', param="123")) assert 'Counter=2' in response response = self.app.get(url(controller='cache', action='test_get_cache_decorator', param="123")) assert 'Counter=2' in response response = self.app.get(url(controller='cache', action='test_expire_cache_decorator')) assert 'Counter=3' in response response = self.app.get(url(controller='cache', action='test_expire_cache_decorator')) assert 'Counter=3' in response time.sleep(8) response = self.app.get(url(controller='cache', action='test_expire_cache_decorator')) assert 'Counter=4' in response response = self.app.get(url(controller='cache', action='test_key_cache_decorator', id=1)) assert 'Counter=5' in response response = self.app.get(url(controller='cache', action='test_key_cache_decorator', id=2)) assert 'Counter=6' in response response = self.app.get(url(controller='cache', action='test_key_cache_decorator', id=1)) assert 'Counter=5' in response response = self.app.get(url(controller='cache', action='test_keyslist_cache_decorator', id=1, id2=2)) assert 'Counter=7' in response response = self.app.get(url(controller='cache', action='test_keyslist_cache_decorator', id=1, id2=2)) assert 'Counter=7' in response Pylons-1.0.2/tests/test_webapps/filestotest/functional_controller_xmlrpc.py0000644000175000017500000000265612451647626027131 0ustar benben00000000000000from projectname.tests import * from xmlrpclib import loads, dumps class TestXmlrpcController(TestController): xmlurl = None def xmlreq(self, method, args=None): if args is None: args = () ee = dict(CONTENT_TYPE='text/xml') data = dumps(args, methodname=method) response = self.app.post(self.xmlurl, params = data, extra_environ=ee) return loads(response.body)[0][0] def setUp(self): self.xmlurl = url(controller='xmlrpc', action='index') def test_index(self): response = self.xmlreq('userstatus') assert response == 'basic string' def test_structure(self): response = self.xmlreq('docs') assert dict(mess='a little somethin', a=1, b=[1,2,3], c=['all','the']) == response def test_methodhelp(self): response = self.xmlreq('system.methodHelp', ('docs',)) assert "This method has a docstring" in response def test_methodsignature(self): response = self.xmlreq('system.methodSignature', ('docs',)) assert [['struct']] == response def test_listmethods(self): response = self.xmlreq('system.listMethods') assert response == ['docs', 'system.listMethods', 'system.methodHelp', 'system.methodSignature', 'uni', 'userstatus'] def test_unicode(self): response = self.xmlreq('uni') assert 'A unicode string' in response['mess']Pylons-1.0.2/tests/test_webapps/filestotest/messages.pot0000644000175000017500000000146712451647626023117 0ustar benben00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2007-02-05 12:36+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: controller_sample.py:7 msgid "basic index page" msgstr "" #: controller_sample.py:59 #, python-format msgid "Could not set language to \"%(lang)s\"" msgstr "" #: controller_sample.py:63 #, python-format msgid "Set language to \"%(lang)s\"" msgstr "" Pylons-1.0.2/tests/test_webapps/filestotest/functional_sample_controller_sqlatesting.py0000644000175000017500000000165112451647626031515 0ustar benben00000000000000from projectname.tests import * try: from sqlalchemy.exceptions import IntegrityError except ImportError: from sqlalchemy.exc import IntegrityError from projectname.model.meta import Session, Base from projectname.model import Foo class TestSQLAlchemyController(TestController): def setUp(self): Base.metadata.create_all(bind=Session.bind) f = Foo(id = 1, bar = u"Wabbit") Session.add(f) Session.commit() assert f.bar == u"Wabbit" def tearDown(self): Base.metadata.drop_all(bind=Session.bind) def test_sqlalchemy(self): response = self.app.get(url(controller='sample', action='testsqlalchemy')) assert 'foos = [Foo:1]' in response # def test_exception(self): # me = Foo(id=3, bar='giuseppe') # me_again = Foo(id=3, bar='giuseppe') # self.assertRaises(IntegrityError, Session.commit) # Session.rollback() Pylons-1.0.2/tests/test_webapps/filestotest/middleware_mako.py0000644000175000017500000000456112451647626024260 0ustar benben00000000000000"""Pylons middleware initialization""" from beaker.middleware import SessionMiddleware from paste.cascade import Cascade from paste.registry import RegistryManager from paste.urlparser import StaticURLParser from paste.deploy.converters import asbool from pylons.middleware import ErrorHandler, StatusCodeRedirect from pylons.wsgiapp import PylonsApp from routes.middleware import RoutesMiddleware from projectname.config.environment import load_environment def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:] section of the Paste ini file (where defaults to main). """ # Configure the Pylons environment config = load_environment(global_conf, app_conf) # The Pylons WSGI app app = PylonsApp(config=config) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map'], singleton=False) app = SessionMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # Display error documents for 401, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app) else: app = StatusCodeRedirect(app, [400, 401, 403, 404, 500]) # Establish the Registry for this application app = RegistryManager(app) if asbool(static_files): # Serve static files static_app = StaticURLParser(config['pylons.paths']['static_files']) app = Cascade([static_app, app]) app.config = config return app Pylons-1.0.2/tests/test_webapps/filestotest/cache_controller.py0000755000175000017500000000176612451647626024451 0ustar benben00000000000000from pylons import app_globals from pylons.decorators.cache import beaker_cache from projectname.lib.base import BaseController class CacheController(BaseController): @beaker_cache(key=None) def test_default_cache_decorator(self): app_globals.counter += 1 return 'Counter=%s' % app_globals.counter @beaker_cache(key="param", query_args=True) def test_get_cache_decorator(self): app_globals.counter += 1 return 'Counter=%s' % app_globals.counter @beaker_cache(expire=4) def test_expire_cache_decorator(self): app_globals.counter += 1 return 'Counter=%s' % app_globals.counter @beaker_cache(key="id") def test_key_cache_decorator(self, id): app_globals.counter += 1 return 'Counter=%s, id=%s' % (app_globals.counter, id) @beaker_cache(key=["id", "id2"]) def test_keyslist_cache_decorator(self, id, id2="123"): app_globals.counter += 1 return 'Counter=%s, id=%s' % (app_globals.counter, id) Pylons-1.0.2/tests/test_webapps/filestotest/test_sqlalchemy.html0000644000175000017500000000002112451647626024634 0ustar benben00000000000000foos = ${c.foos} Pylons-1.0.2/tests/test_webapps/filestotest/model__init__.py0000644000175000017500000000071712451647626023713 0ustar benben00000000000000"""The application's model objects""" from sqlalchemy import types, Column from projectname.model.meta import Base, Session def init_model(engine): """Call me before using any of the tables or classes in the model""" Session.configure(bind=engine) class Foo(Base): __tablename__ = 'foo' id = Column(types.Integer, primary_key=True) bar = Column(types.String(255), nullable=False) def __repr__(self): return "Foo:%s" % self.id Pylons-1.0.2/tests/test_webapps/filestotest/app_globals.py0000644000175000017500000000115512451647626023413 0ustar benben00000000000000"""The application's Globals object""" from pylons import config from beaker.cache import CacheManager from beaker.util import parse_cache_config_options class Globals(object): """Globals acts as a container for objects available throughout the life of the application """ def __init__(self, config): """One instance of Globals is created during application initialization and is available during requests via the 'app_globals' variable """ self.cache = CacheManager(**parse_cache_config_options(config)) self.message = 'Hello' self.counter = 0 Pylons-1.0.2/tests/test_webapps/filestotest/functional_sample_controller_sample4.py0000644000175000017500000000133012451647626030516 0ustar benben00000000000000from projectname.tests import * class TestSample2Controller(TestController): def test_get(self): response = self.app.get(url(controller='sample', action='test_only_get')) assert 'It was a get' in response def test_redir_get(self): response = self.app.get(url(controller='sample', action='test_only_post')) assert 'It was a get' in response def test_post(self): response = self.app.post(url(controller='sample', action='test_only_post'), params={'id':4}) assert 'It was a post' in response def test_head(self): response = self.app._gen_request('HEAD', url(controller='sample', action='index')) assert '' == response.body Pylons-1.0.2/tests/test_webapps/filestotest/rest_routing.py0000644000175000017500000000206712451647626023657 0ustar benben00000000000000"""Routes configuration The more specific and detailed routes should be defined first so they may take precedent over the more generic routes. For more information refer to the routes manual at http://routes.groovie.org/docs/ """ from routes import Mapper def make_map(config): """Create, configure and return the routes Mapper""" map = Mapper(directory=config['pylons.paths']['controllers'], always_scan=config['debug']) map.minimization = False map.explicit = False # The ErrorController route (handles 404/500 error pages); it should # likely stay at the top, ensuring it can always be resolved map.connect('/error/{action}', controller='error') map.connect('/error/{action}/{id}', controller='error') # CUSTOM ROUTES HERE map.resource('restsample', 'restsamples') map.resource('restsample', 'restsamples', controller='mysubdir/restsamples', path_prefix='/mysubdir', name_prefix='mysubdir_') map.connect('/{controller}/{action}') map.connect('/{controller}/{action}/{id}') return map Pylons-1.0.2/tests/test_webapps/filestotest/controller_sqlatest.py0000644000175000017500000000345112451647626025234 0ustar benben00000000000000import datetime from projectname.lib.base import * try: import sqlalchemy as sa from projectname.model.meta import Session, Base from projectname.model import Foo SQLAtesting = True except: SQLAtesting = False import projectname.lib.helpers as h from pylons import request, response, session from pylons import tmpl_context as c from pylons import app_globals from pylons.decorators import rest from pylons.i18n import _, get_lang, set_lang, LanguageError from pylons.templating import render_mako, render_genshi, render_jinja2 from pylons.controllers.util import abort, redirect class SampleController(BaseController): def index(self): return 'basic index page' def testsqlalchemy(self): if SQLAtesting: c.foos = Session.query(Foo).all() return render_mako('test_sqlalchemy.html') pass def set_lang(self): return self._set_lang(_) def set_lang_pylonscontext(self, pylons): return self._set_lang(lambda *args: pylons.translator.ugettext(*args)) def _set_lang(self, gettext): lang = request.GET['lang'] try: set_lang(lang) except (LanguageError, IOError), e: resp_unicode = gettext('Could not set language to "%(lang)s"') % {'lang': lang} else: session['lang'] = lang session.save() resp_unicode = gettext('Set language to "%(lang)s"') % {'lang': lang} return resp_unicode def i18n_index(self): locale_list = request.languages set_lang(request.languages) return unicode(_('basic index page')) def no_lang(self): set_lang(None) response.write(_('No language')) set_lang([]) response.write(_('No languages')) return '' Pylons-1.0.2/tests/test_webapps/filestotest/functional_sample_controller_sample3.py0000644000175000017500000000122012451647626030513 0ustar benben00000000000000from projectname.tests import * class TestSample2Controller(TestController): def test_session(self): response = self.app.get(url(controller='sample', action='session_increment')) assert response.session.has_key('counter') assert response.session['counter'] == 0 response = self.app.get(url(controller='sample', action='session_increment')) assert response.session['counter'] == 1 assert 'session incrementer' in response def test_default(self): response = self.app.get(url(controller='sample', action='test_template_caching')) assert 'Hi everyone!' in response Pylons-1.0.2/tests/test_webapps/filestotest/development.ini0000644000175000017500000000304312451647626023577 0ustar benben00000000000000[DEFAULT] debug = true email_to = you@yourdomain.com smtp_server = localhost error_email_from = paste@exceptions.com [server:main] use = egg:Paste#http host = 127.0.0.1 port = 5000 [app:main] use = egg:projectname cache_dir = %(here)s/data beaker.session.key = projectname beaker.session.secret = somesecret # If you'd like to fine-tune the individual locations of the cache data dirs # for Myghty, the Cache data, or the Session saves, un-comment the desired # settings here: #beaker.cache_data_dir = %(here)s/data/cache #beaker.session_data_dir = %(here)s/data/sessions # If you are using SQLAlchemy you will need to specify a # dburi. You can do this with a line similar to the # one below but adjusted for your database connection # according to the SQLAlchemy documentation. The %(here)s # part is replaced with the current directory which is # useful when using sqlite on UNIX based platforms. # For Windows you should look at the SQLAlchemy # documentation for a special syntax to use because the # path returned by %(here)s contains a : character. # SQLAlchemy database URL #sqlalchemy.url = sqlite:///%(here)s/development.db # Do not set debug to true or uncomment the line below # on a production environment otherwise in the event of # an error occurring the visitor will be presented with # interactive debugging tools and these could be used to # execute malicious code. # For development purposes debug should be set to true # to enable the debugging code but be sure to set it back # to false before releasing your application. #set debug = false Pylons-1.0.2/tests/test_webapps/filestotest/functional_sample_controller_i18n.py0000644000175000017500000000224312451647626027734 0ustar benben00000000000000from projectname.tests import * class TestSampleController(TestController): def test_set_lang(self): self._test_set_lang('set_lang') def test_set_lang_pylonscontext(self): self._test_set_lang('set_lang_pylonscontext') def _test_set_lang(self, action): response = self.app.get(url(controller='sample', action=action, lang='ja')) assert u'\u8a00\u8a9e\u8a2d\u5b9a\u3092\u300cja\u300d\u306b\u5909\u66f4\u3057\u307e\u3057\u305f'.encode('utf-8') in response response = self.app.get(url(controller='sample', action=action, lang='fr')) assert 'Could not set language to "fr"' in response def test_detect_lang(self): response = self.app.get(url(controller='sample', action='i18n_index'), headers={ 'Accept-Language':'fr;q=0.6, en;q=0.1, ja;q=0.3'}) # expect japanese fallback for nonexistent french. assert u'\u6839\u672c\u30a4\u30f3\u30c7\u30af\u30b9\u30da\u30fc\u30b8'.encode('utf-8') in response def test_no_lang(self): response = self.app.get(url(controller='sample', action='no_lang')) assert 'No language' in response assert 'No languages' in response Pylons-1.0.2/tests/test_webapps/__pycache__/0000755000175000017500000000000012553621453020410 5ustar benben00000000000000Pylons-1.0.2/tests/test_webapps/__pycache__/test_make_project.cpython-34.pyc0000644000175000017500000003413112553620127026535 0ustar benben00000000000000 U#:@sVdZddlZddlZddlZddlZddlZddlmZddlm Z ej j dddkrenddl Z ddl Z yddlZdZWnek rd ZYnXejjd Zd Zx'd d ddgD]ZejeqWejjejjedjddZej jZdedd?Z5d@dAZ6dBdCZ7dDdEZ8dFdGZ9dHdIZ:dJdKZ;dLdMZ<dNdOZ=dPdQZ>dRdSZ?dTdUZ@dVdWZAdXdYZBdZd[ZCd\d]ZDdS)^z7Tests against full Pylons projects created from scratchN)SkipTest)TestFileEnvironmentZSKIP_INTEGRATEDFalse0TFjavaoutputZ PasteScriptZPasteZ PasteDeploypylonsZ filestotest\/trueZ PASTE_TESTING template_pathenvironcCs6tjdkr2|jjd r2|d7}n|S)Nwin32z.exe)sysplatformlowerendswith)scriptrK/home/ben/Programming/Python/pylons/tests/test_webapps/test_make_project.py_get_script_name,s% rcCstjtddddd}tjjddjdd }d }d |kr]d }n||d t_d|jksttjj ddS)NZsvnadmincreateZREPOSZ printresultFr r  z%20zfile://:zfile:///z/REPOS) testenvrunr base_pathreplacesvn_url files_createdAssertionErrorZ ignore_pathsappend)respathbaserrrsvn_repos_setup1s !  r%makocCsdddg}|r%|jdn|jdddd|d d |gtjtd |}d d dddg}x\|D]T}tjjd|}|s||jj kst n||j kst qW|sC|jtjjdd}|j d|j d|j d|j dd|ksCt ntjtt jddtjjtjdjddddttjjtjdjdddddtdtatjjdd d!tjtjdmysubdirz sample.pyr?r@ztest_mysubdir_sample.pyrA) r6rrr/r#r0rr r2)r"rrrmake_controller_subdirectoryns**rDcCstjtdd}tjjddd|jks@ttjjdddd|jksjtd |jkstdS) Nr(z& restcontroller restsample restsamplesr)r>zrestsamples.pyr?r@ztest_restsamples.pyrA) r6rrr/r#r0rr r2)r"rrrmake_restcontrollervs'*rEcCstjtdd}tjjdddd|jksCttjjdddd |jksmtd |jkstdS) Nr(z8 restcontroller mysubdir/restsample mysubdir/restsamplesr)r>rCzrestsamples.pyr?r@ztest_mysubdir_restsamples.pyrA) r6rrr/r#r0rr r2)r"rrr make_restcontroller_subdirectory~s**rFcCs=tjjrdtj_n|s*g}nx-|jD]\}}tj|d|q7Wx|D]}tj|qaWtjtdddddtj j t j dj d d }|r9tjtd d dd dtj j t j dj d d }x2|D]'}tj|j|js tq WndS)zGiven a dict of files, where the key is a filename in filestotest, the value is the destination in the new projects dir. emptyfiles is a list of files that should be created and empty.NZfrompath nosetestsz -dr+Tr*r'r r r(z routesF)rtestZ pylonsappZ iteritemsr6Z writefilerrr/r#r0rr*rrecompilesearchr2r )copydictZ emptyfilesmatch_routes_outputZoriginalnewfilefir"patternrrr _do_proj_tests"    '' rQcCstidd6dS)Nzdevelopment.ini)rQrrrr do_nosetestssrRcCs0idd6dd6dd6dd6}t|dS) Nzprojectname/lib/helpers.pyzhelpers_sample.pyz!projectname/controllers/sample.pyzcontroller_sample.pyzprojectname/lib/app_globals.pyzapp_globals.pyz+projectname/tests/functional/test_sample.pyz'functional_sample_controller_sample1.py)rQ)rLrrr do_knowntests  rScCs)idd6dd6dd6}t|dS)Nz)projectname/tests/functional/test_i18n.pyz$functional_sample_controller_i18n.pyz.projectname/i18n/ja/LC_MESSAGES/projectname.pozmessages.ja.poz.projectname/i18n/ja/LC_MESSAGES/projectname.mozmessages.ja.mo)rQ)rLrrr do_i18ntests  rTcCsztddddidd6dd6d d 6d d 6}id d 6dd6dd6}|j|ddg}t||dS)Nr8Zgenshir9Tzprojectname/lib/helpers.pyzhelpers_sample.pyzprojectname/lib/app_globals.pyzapp_globals.pyzprojectname/config/routing.pyzrest_routing.pyzdevelopment.iniz%projectname/templates/testgenshi.htmlztestgenshi.htmlz!projectname/config/environment.pyzenvironment_def_engine.pyz,projectname/tests/functional/test_sample2.pyz'functional_sample_controller_sample2.pyz!projectname/templates/__init__.pyz*projectname/tests/functional/test_cache.py)r=updaterQ)resetrLemptyrrr do_genshis    rXcCs)idd6dd6dd6}t|dS)Nz projectname/config/middleware.pyzmiddleware_two_engines.pyz$projectname/templates/test_mako.htmlztest_mako.htmlz,projectname/tests/functional/test_sample2.pyz'functional_sample_controller_sample3.py)rQ)rLrrrdo_two_enginess  rYcCstidd6dS)Nz,projectname/tests/functional/test_sample3.pyz'functional_sample_controller_sample4.py)rQrrrrdo_crazy_decoratorssrZcCstddddidd6dd6d d 6d d 6}id d 6dd6dd6dd6}|j|dddddg}t||dS)Nr8Zjinja2r9Tzprojectname/lib/helpers.pyzhelpers_sample.pyzprojectname/lib/app_globals.pyzapp_globals.pyzprojectname/config/routing.pyzrest_routing.pyzdevelopment.iniz!projectname/controllers/sample.pyzcontroller_sample.pyz%projectname/templates/testjinja2.htmlztestjinja2.htmlz!projectname/config/environment.pyzenvironment_def_engine.pyz+projectname/tests/functional/test_jinja2.pyz&functional_sample_controller_jinja2.pyz!projectname/templates/__init__.pyz+projectname/tests/functional/test_sample.pyz,projectname/tests/functional/test_sample2.pyz,projectname/tests/functional/test_sample3.pyz*projectname/tests/functional/test_cache.py)r=rUrQ)rVrLrWrrr do_jinja2s$    r[cCsHidd6dd6dd6dd6}d d d d d g}t||dS)Nz projectname/config/middleware.pyzmiddleware_mako.pyzprojectname/lib/app_globals.pyzapp_globals.pyz projectname/controllers/cache.pyzcache_controller.pyz*projectname/tests/functional/test_cache.pyz(functional_controller_cache_decorator.pyz)projectname/tests/functional/test_mako.pyz+projectname/tests/functional/test_jinja2.pyz+projectname/tests/functional/test_sample.pyz,projectname/tests/functional/test_sample2.pyz,projectname/tests/functional/test_sample3.py)rQ)rLrWrrrdo_cache_decorators  r\cCs?idd6dd6dd6dd6}d d g}t||dS) Nz projectname/config/middleware.pyzmiddleware_mako.pyzprojectname/lib/base.pyzbase_with_xmlrpc.pyz!projectname/controllers/xmlrpc.pyzcontroller_xmlrpc.pyz+projectname/tests/functional/test_xmlrpc.pyzfunctional_controller_xmlrpc.pyz*projectname/tests/functional/test_cache.pyz+projectname/tests/functional/test_jinja2.py)rQ)rLrWrrr do_xmlrpcs  r]cCsd|jkstd|jks*ttjtddtj}|jd}|jdd|jksyttt j j tj dj d d d d d tadS)NzTagging 0.5 versionzAuto-update of version stringssvnz$ co %s/ProjectName/tags/0.5 Proj-05 zProj-05/setup.pyz0.5zProj-05/setup.cfgzProj-05r r r,Fr )r2r rrrrrr3rr/r#r0rrr Ztagenv)r"r<rrrmake_tags  $r_cCstddddddidd6dd 6d d 6d d 6dd6dd6dd6dd6}idd6dd6dd6dd6}|j|ddd d!d"g}t||dS)#Nr8r&r9Tr:zprojectname/lib/helpers.pyzhelpers_sample.pyzprojectname/lib/app_globals.pyzapp_globals.pyzprojectname/config/routing.pyzrest_routing.pyzdevelopment.inizdevelopment_sqlatesting.inizprojectname/websetup.pyz websetup.pyzprojectname/model/__init__.pyzmodel__init__.pyz!projectname/config/environment.pyzenvironment_def_sqlamodel.pyzprojectname/tests/__init__.pyztests__init__.pyz!projectname/controllers/sample.pyzcontroller_sqlatest.pyz$projectname/templates/test_mako.htmlztest_mako.htmlz*projectname/templates/test_sqlalchemy.htmlztest_sqlalchemy.htmlz6projectname/tests/functional/test_sqlalchemyproject.pyz+functional_sample_controller_sqlatesting.pyz!projectname/templates/__init__.pyz+projectname/tests/functional/test_sample.pyz,projectname/tests/functional/test_sample2.pyz,projectname/tests/functional/test_sample3.pyz*projectname/tests/functional/test_cache.py)r=rUrQ)rVrLrWrrrdo_sqlaproject!s,    r`cCs tdS)N)r=rrrrtest_project_paster_createAsracCs tdS)N)rBrrrrtest_project_make_controllerDsrbcCs tdS)N)rDrrrr)test_project_make_controller_subdirectoryGsrccCs tdS)N)rRrrrrtest_project_do_nosetestsJsrdcCs tdS)N)rSrrrrtest_project_do_knowntestMsrecCs tdS)N)rTrrrrtest_project_do_i18ntestPsrfcCs tdS)N)rErrrr test_project_make_restcontrollerSsrgcCs tdS)N)rFrrrr-test_project_make_restcontroller_subdirectoryVsrhcCs1idd6dd6}ddg}t||dS)Nzprojectname/config/routing.pyzrest_routing.pyzdevelopment.inizRoute name +Methods +Pathzrestsamples +GET +/restsamples)rQ)rLrMrrrtest_project_do_rest_nosetestsYs   ricCs tdS)N)rZrrrr test_project_do_crazy_decoratorsesrjcCs tdS)N)r\rrrrtest_project_do_cache_decoratorhsrkcCs trtdntdS)Nz(Jython does not currently support Genshi) is_jythonrrXrrrrtest_project_do_genshi_defaultksrmcCs tdS)N)r[rrrrtest_project_do_jinja2psrncCs tdS)N)r]rrrrtest_project_do_xmlrpcssrocCstrtndS)N) SQLAtestingr`rrrrtest_project_do_sqlaprojectxs rqcCsqtjjtjjtt}tjj|d}tjjtjjtjjt}tj|dS)Nr')r/r#r0dirname__file__TEST_OUTPUT_DIRNAMEshutilrmtree)Z dir_to_cleanZcov_dirZmain_dirrrrteardown~s!*rw)E__doc__r/rrurI pkg_resourcesnoserZ paste.fixturerr r7rZ pylons.testZ sqlalchemysarp ImportErrorr startswithrlrtspecrequirer#r0rrrsrr copyr5rr6rr%r=rBrDrErFrQrRrSrTrXrYrZr[r\r]r_r`rarbrcrdrerfrgrhrirjrkrmrnrorqrwrrrrs~            - -   *    "                       Pylons-1.0.2/tests/test_webapps/__pycache__/__init__.cpython-34.pyc0000644000175000017500000000022512460016451024563 0ustar benben00000000000000 OT@sdS)NrrrB/home/ben/Programming/Python/pylons/tests/test_webapps/__init__.pysPylons-1.0.2/tests/test_webapps/__init__.py0000644000175000017500000000000012451647626020306 0ustar benben00000000000000Pylons-1.0.2/tests/test_webapps/test_make_project.py0000644000175000017500000003504312553617762022271 0ustar benben00000000000000"""Tests against full Pylons projects created from scratch""" import os import sys import shutil import re import pkg_resources from nose import SkipTest from paste.fixture import TestFileEnvironment if os.environ.get('SKIP_INTEGRATED', 'False') != '0': raise SkipTest() import pylons import pylons.test try: import sqlalchemy as sa SQLAtesting = True except ImportError: SQLAtesting = False # SQLAtesting = False is_jython = sys.platform.startswith('java') TEST_OUTPUT_DIRNAME = 'output' for spec in ['PasteScript', 'Paste', 'PasteDeploy', 'pylons']: pkg_resources.require(spec) template_path = os.path.join( os.path.dirname(__file__), 'filestotest').replace('\\','/') test_environ = os.environ.copy() test_environ['PASTE_TESTING'] = 'true' testenv = TestFileEnvironment( os.path.join(os.path.dirname(__file__), TEST_OUTPUT_DIRNAME).replace('\\','/'), template_path=template_path, environ=test_environ) projenv = None def _get_script_name(script): if sys.platform == 'win32' and not script.lower().endswith('.exe'): script += '.exe' return script def svn_repos_setup(): res = testenv.run(_get_script_name('svnadmin'), 'create', 'REPOS', printresult=False) path = testenv.base_path.replace('\\','/').replace(' ','%20') base = 'file://' if ':' in path: base = 'file:///' testenv.svn_url = base + path + '/REPOS' assert 'REPOS' in res.files_created testenv.ignore_paths.append('REPOS') def paster_create(template_engine='mako', overwrite=False, sqlatesting=False): global projenv paster_args = ['create', '--verbose', '--no-interactive'] if overwrite: paster_args.append('-f') paster_args.extend(['--template=pylons', 'ProjectName', 'version=0.1', 'sqlalchemy=%s' % sqlatesting, 'zip_safe=False', 'template_engine=%s' % template_engine]) res = testenv.run(_get_script_name('paster'), *paster_args) expect_fn = ['projectname', 'development.ini', 'setup.cfg', 'README.txt', 'setup.py'] for fn in expect_fn: fn = os.path.join('ProjectName', fn) if not overwrite: assert fn in res.files_created.keys() assert fn in res.stdout if not overwrite: setup = res.files_created[os.path.join('ProjectName','setup.py')] setup.mustcontain('0.1') setup.mustcontain('projectname.config.middleware:make_app') setup.mustcontain('main = pylons.util:PylonsInstaller') setup.mustcontain("include_package_data=True") assert '0.1' in setup testenv.run(_get_script_name(sys.executable)+' setup.py egg_info', cwd=os.path.join(testenv.cwd, 'ProjectName').replace('\\','/'), expect_stderr=True) #testenv.run(_get_script_name('svn'), 'commit', '-m', 'Created project', 'ProjectName') # A new environment with a new projenv = TestFileEnvironment( os.path.join(testenv.base_path, 'ProjectName').replace('\\','/'), start_clear=False, template_path=template_path, environ=test_environ) projenv.environ['PYTHONPATH'] = ( projenv.environ.get('PYTHONPATH', '') + ':' + projenv.base_path) def make_controller(): res = projenv.run(_get_script_name('paster')+' controller sample') assert os.path.join('projectname','controllers','sample.py') in res.files_created assert os.path.join('projectname','tests','functional','test_sample.py') in res.files_created #res = projenv.run(_get_script_name('svn')+' status') # Make sure all files are added to the repository: assert '?' not in res.stdout def make_controller_subdirectory(): res = projenv.run(_get_script_name('paster')+' controller mysubdir/sample') assert os.path.join('projectname','controllers', 'mysubdir', 'sample.py') in res.files_created assert os.path.join('projectname','tests','functional','test_mysubdir_sample.py') in res.files_created #res = projenv.run(_get_script_name('svn')+' status') # Make sure all files are added to the repository: assert '?' not in res.stdout def make_restcontroller(): res = projenv.run(_get_script_name('paster')+' restcontroller restsample restsamples') assert os.path.join('projectname','controllers','restsamples.py') in res.files_created assert os.path.join('projectname','tests','functional','test_restsamples.py') in res.files_created #res = projenv.run(_get_script_name('svn')+' status') # Make sure all files are added to the repository: assert '?' not in res.stdout def make_restcontroller_subdirectory(): res = projenv.run(_get_script_name('paster')+' restcontroller mysubdir/restsample mysubdir/restsamples') assert os.path.join('projectname','controllers','mysubdir', 'restsamples.py') in res.files_created assert os.path.join('projectname','tests','functional','test_mysubdir_restsamples.py') in res.files_created #res = projenv.run(_get_script_name('svn')+' status') # Make sure all files are added to the repository: assert '?' not in res.stdout def _do_proj_test(copydict, emptyfiles=None, match_routes_output=None): """Given a dict of files, where the key is a filename in filestotest, the value is the destination in the new projects dir. emptyfiles is a list of files that should be created and empty.""" if pylons.test.pylonsapp: pylons.test.pylonsapp = None if not emptyfiles: emptyfiles = [] for original, newfile in copydict.iteritems(): projenv.writefile(newfile, frompath=original) for fi in emptyfiles: projenv.writefile(fi) # here_dir = os.getcwd() # test_dir = os.path.join(testenv.cwd, 'ProjectName').replace('\\','/') # os.chdir(test_dir) # sys.path.append(test_dir) # nose.run(argv=['nosetests', '-d', test_dir]) # # sys.path.pop(-1) # os.chdir(here_dir) res = projenv.run(_get_script_name('nosetests')+' -d', expect_stderr=True, cwd=os.path.join(testenv.cwd, 'ProjectName').replace('\\','/')) if match_routes_output: res = projenv.run(_get_script_name('paster')+' routes', expect_stderr=False, cwd=os.path.join(testenv.cwd, 'ProjectName').replace('\\','/')) for pattern in match_routes_output: assert re.compile(pattern).search(res.stdout) def do_nosetests(): _do_proj_test({'development.ini':'development.ini'}) def do_knowntest(): copydict = { 'helpers_sample.py':'projectname/lib/helpers.py', 'controller_sample.py':'projectname/controllers/sample.py', 'app_globals.py':'projectname/lib/app_globals.py', 'functional_sample_controller_sample1.py':'projectname/tests/functional/test_sample.py', } _do_proj_test(copydict) def do_i18ntest(): copydict = { 'functional_sample_controller_i18n.py':'projectname/tests/functional/test_i18n.py', 'messages.ja.po':'projectname/i18n/ja/LC_MESSAGES/projectname.po', 'messages.ja.mo':'projectname/i18n/ja/LC_MESSAGES/projectname.mo', } _do_proj_test(copydict) def do_genshi(): paster_create(template_engine='genshi', overwrite=True) reset = { 'helpers_sample.py':'projectname/lib/helpers.py', 'app_globals.py':'projectname/lib/app_globals.py', 'rest_routing.py':'projectname/config/routing.py', 'development.ini':'development.ini', } copydict = { 'testgenshi.html':'projectname/templates/testgenshi.html', 'environment_def_engine.py':'projectname/config/environment.py', 'functional_sample_controller_sample2.py':'projectname/tests/functional/test_sample2.py' } copydict.update(reset) empty = ['projectname/templates/__init__.py', 'projectname/tests/functional/test_cache.py'] _do_proj_test(copydict, empty) def do_two_engines(): copydict = { 'middleware_two_engines.py':'projectname/config/middleware.py', 'test_mako.html':'projectname/templates/test_mako.html', 'functional_sample_controller_sample3.py':'projectname/tests/functional/test_sample2.py', } _do_proj_test(copydict) def do_crazy_decorators(): _do_proj_test({'functional_sample_controller_sample4.py':'projectname/tests/functional/test_sample3.py'}) def do_jinja2(): paster_create(template_engine='jinja2', overwrite=True) reset = { 'helpers_sample.py':'projectname/lib/helpers.py', 'app_globals.py':'projectname/lib/app_globals.py', 'rest_routing.py':'projectname/config/routing.py', 'development.ini':'development.ini', } copydict = { 'controller_sample.py':'projectname/controllers/sample.py', 'testjinja2.html':'projectname/templates/testjinja2.html', 'environment_def_engine.py':'projectname/config/environment.py', 'functional_sample_controller_jinja2.py':'projectname/tests/functional/test_jinja2.py', } copydict.update(reset) empty = [ 'projectname/templates/__init__.py', 'projectname/tests/functional/test_sample.py', 'projectname/tests/functional/test_sample2.py', 'projectname/tests/functional/test_sample3.py', 'projectname/tests/functional/test_cache.py' ] _do_proj_test(copydict, empty) def do_cache_decorator(): copydict = { 'middleware_mako.py':'projectname/config/middleware.py', 'app_globals.py':'projectname/lib/app_globals.py', 'cache_controller.py':'projectname/controllers/cache.py', 'functional_controller_cache_decorator.py':'projectname/tests/functional/test_cache.py', } empty = [ 'projectname/tests/functional/test_mako.py', 'projectname/tests/functional/test_jinja2.py', 'projectname/tests/functional/test_sample.py', 'projectname/tests/functional/test_sample2.py', 'projectname/tests/functional/test_sample3.py' ] _do_proj_test(copydict, empty) def do_xmlrpc(): copydict = { 'middleware_mako.py':'projectname/config/middleware.py', 'base_with_xmlrpc.py':'projectname/lib/base.py', 'controller_xmlrpc.py':'projectname/controllers/xmlrpc.py', 'functional_controller_xmlrpc.py':'projectname/tests/functional/test_xmlrpc.py' } empty = [ 'projectname/tests/functional/test_cache.py', 'projectname/tests/functional/test_jinja2.py', ] _do_proj_test(copydict, empty) def make_tag(): global tagenv #res = projenv.run(_get_script_name('svn')+' commit -m "updates"') # Space at the end needed so run() doesn't add \n causing svntag to complain #res = projenv.run(_get_script_name(sys.executable)+' setup.py svntag --version=0.5 ') # XXX Still fails => setuptools problem on win32? assert 'Tagging 0.5 version' in res.stdout assert 'Auto-update of version strings' in res.stdout res = testenv.run(_get_script_name('svn')+' co %s/ProjectName/tags/0.5 Proj-05 ' % testenv.svn_url) setup = res.files_created['Proj-05/setup.py'] setup.mustcontain('0.5') assert 'Proj-05/setup.cfg' not in res.files_created tagenv = TestFileEnvironment( os.path.join(testenv.base_path, 'Proj-05').replace('\\','/'), start_clear=False, template_path=template_path) def do_sqlaproject(): paster_create(template_engine='mako', overwrite=True, sqlatesting=True) reset = { 'helpers_sample.py':'projectname/lib/helpers.py', 'app_globals.py':'projectname/lib/app_globals.py', 'rest_routing.py':'projectname/config/routing.py', 'development_sqlatesting.ini':'development.ini', 'websetup.py':'projectname/websetup.py', 'model__init__.py':'projectname/model/__init__.py', 'environment_def_sqlamodel.py':'projectname/config/environment.py', 'tests__init__.py':'projectname/tests/__init__.py', } copydict = { 'controller_sqlatest.py':'projectname/controllers/sample.py', 'test_mako.html':'projectname/templates/test_mako.html', 'test_sqlalchemy.html':'projectname/templates/test_sqlalchemy.html', 'functional_sample_controller_sqlatesting.py':'projectname/tests/functional/test_sqlalchemyproject.py', } copydict.update(reset) empty = [ 'projectname/templates/__init__.py', 'projectname/tests/functional/test_sample.py', 'projectname/tests/functional/test_sample2.py', 'projectname/tests/functional/test_sample3.py', 'projectname/tests/functional/test_cache.py' ] _do_proj_test(copydict, empty) # res = projenv.run(_get_script_name('paster')+' setup-app development.ini', expect_stderr=True,) # assert '?' not in res.stdout # Unfortunately, these are ordered, so be careful def test_project_paster_create(): paster_create() def test_project_make_controller(): make_controller() def test_project_make_controller_subdirectory(): make_controller_subdirectory() def test_project_do_nosetests(): do_nosetests() def test_project_do_knowntest(): do_knowntest() def test_project_do_i18ntest(): do_i18ntest() def test_project_make_restcontroller(): make_restcontroller() def test_project_make_restcontroller_subdirectory(): make_restcontroller_subdirectory() def test_project_do_rest_nosetests(): copydict = { 'rest_routing.py':'projectname/config/routing.py', 'development.ini':'development.ini', } match_routes_output = [ 'Route name +Methods +Path', 'restsamples +GET +/restsamples' ] _do_proj_test(copydict, match_routes_output) # Tests with templating plugin dependencies def test_project_do_crazy_decorators(): do_crazy_decorators() def test_project_do_cache_decorator(): do_cache_decorator() def test_project_do_genshi_default(): if is_jython: raise SkipTest('Jython does not currently support Genshi') do_genshi() def test_project_do_jinja2(): do_jinja2() def test_project_do_xmlrpc(): do_xmlrpc() #def test_project_make_tag(): # make_tag() def test_project_do_sqlaproject(): if SQLAtesting: do_sqlaproject() else: pass def teardown(): dir_to_clean = os.path.join(os.path.dirname(__file__), TEST_OUTPUT_DIRNAME) cov_dir = os.path.join(dir_to_clean, 'ProjectName') main_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) # Scan and move the coverage files # for name in os.listdir(cov_dir): # if name.startswith('.coverage.'): # shutil.move(os.path.join(cov_dir, name), main_dir) # shutil.rmtree(dir_to_clean) Pylons-1.0.2/tests/test_webapps/test_make_project.pyc0000644000175000017500000004277712553620015022431 0ustar benben00000000000000 Uc@sdZddlZddlZddlZddlZddlZddlmZddlm Z ej j dddkrenddl Z ddl Z yddlZeZWnek reZnXejjdZd Zx'd d d d gD]ZejeqWejjejjedjddZej j Z!de!dd0Z?d1Z@d2ZAd3ZBd4ZCd5ZDd6ZEd7ZFd8ZGdS(9s7Tests against full Pylons projects created from scratchiN(tSkipTest(tTestFileEnvironmenttSKIP_INTEGRATEDtFalset0tjavatoutputt PasteScripttPastet PasteDeploytpylonst filestotests\t/ttruet PASTE_TESTINGt template_pathtenvironcCs6tjdkr2|jjd r2|d7}n|S(Ntwin32s.exe(tsystplatformtlowertendswith(tscript((sK/home/ben/Programming/Python/pylons/tests/test_webapps/test_make_project.pyt_get_script_name,s% cCstjtddddt}tjjddjdd}d }d |kr]d }n||d t_d|jksttj j ddS( NtsvnadmintcreatetREPOSt printresults\R t s%20sfile://t:sfile:///s/REPOS( ttestenvtrunRRt base_pathtreplacetsvn_urlt files_createdtAssertionErrort ignore_pathstappend(trestpathtbase((sK/home/ben/Programming/Python/pylons/tests/test_webapps/test_make_project.pytsvn_repos_setup1s !  tmakocCsdddg}|r%|jdn|jdddd|d d |gtjtd |}d d dddg}x\|D]T}tjjd|}|s||jj kst n||j kst qW|sC|jtjjdd}|j d|j d|j d|j dd|ksCt ntjtt jddtjjtjdjdddtttjjtjdjdddtdtdtatjjdddtjtjdR t pylons.testt sqlalchemytsaR;Rt ImportErrorRRt startswithRRtspectrequireR(R6RRR!RtcopyR<RRTR=RR*RFRKRMRNRORaRbRcRdRiRjRkRmRnRoRrRsRtRuRvRwRxRyRzR{R|R}R~RRRRR(((sK/home/ben/Programming/Python/pylons/tests/test_webapps/test_make_project.pyts             $ -   *    "                       Pylons-1.0.2/tests/test_webapps/__init__.pyc0000644000175000017500000000023112456572500020450 0ustar benben00000000000000 OTc@sdS(N((((sB/home/ben/Programming/Python/pylons/tests/test_webapps/__init__.pytsPylons-1.0.2/tests/conftest.pyc0000644000175000017500000000123412460016502016030 0ustar benben00000000000000 OTc@sddlZddlZddlZddlZejjeZejjeZejj eejj deejjeZej j eej jdsejjeddZejjerejeqndS(iNit PASTE_TESTINGt test_webappstoutput(tsystostshutilt pkg_resourcestpathtdirnamet__file__theretbasetappendtinsertt working_sett add_entrytenvirontgettjoint output_dirtexiststrmtree(((s5/home/ben/Programming/Python/pylons/tests/conftest.pyts    Pylons-1.0.2/tests/test_units/0000755000175000017500000000000012553621453015701 5ustar benben00000000000000Pylons-1.0.2/tests/test_units/test_controller.py0000644000175000017500000001521712456601140021474 0ustar benben00000000000000# -*- coding: utf-8 -*- from paste.fixture import TestApp from paste.registry import RegistryManager from webob.exc import status_map import pylons from pylons.controllers import WSGIController from pylons.testutil import SetupCacheGlobal, ControllerWrap from __init__ import TestWSGIController, TestMiddleware class BasicWSGIController(WSGIController): def __init__(self): self._pylons_log_debug = True def __before__(self): pylons.response.headers['Cache-Control'] = 'private' def __after__(self): pylons.response.set_cookie('big_message', 'goodbye') def index(self): return 'hello world' def yield_fun(self): def its(): x = 0 while x < 100: yield 'hi' x += 1 return its() def strme(self): return "hi there" def use_redirect(self): pylons.response.set_cookie('message', 'Hello World') exc = status_map[301] raise exc('/elsewhere') def use_customnotfound(self): exc = status_map[404] raise exc('Custom not found') def header_check(self): pylons.response.headers['Content-Type'] = 'text/plain' return "Hello all!" def nothing(self): return def params(self): items = pylons.request.params.mixed().items() items.sort() return str(items) def list(self): return ['from', ' a ', 'list'] class FilteredWSGIController(WSGIController): def __init__(self): self.before = 0 self.after = 0 def __before__(self): self.before += 1 def __after__(self): self.after += 1 action = pylons.request.environ['pylons.routes_dict'].get('action') if action in ('after_response', 'after_string_response'): pylons.response.write(' from __after__') def index(self): return 'hi all, before is %s' % self.before def after_response(self): return 'hi' def after_string_response(self): return 'hello' class TestBasicWSGI(TestWSGIController): def __init__(self, *args, **kargs): TestWSGIController.__init__(self, *args, **kargs) self.baseenviron = {} app = ControllerWrap(BasicWSGIController) app = self.sap = SetupCacheGlobal(app, self.baseenviron) app = TestMiddleware(app) app = RegistryManager(app) self.app = TestApp(app) def setUp(self): TestWSGIController.setUp(self) self.baseenviron.update(self.environ) def test_wsgi_call(self): resp = self.get_response() assert 'hello world' in resp def test_yield_wrapper(self): resp = self.get_response(action='yield_fun') assert 'hi' * 100 in resp def test_404(self): self.environ['paste.config']['global_conf']['debug'] = False self.environ['pylons.routes_dict']['action'] = 'notthere' resp = self.app.get('/', status=404) assert resp.status == 404 def test_404exception(self): self.environ['paste.config']['global_conf']['debug'] = False self.environ['pylons.routes_dict']['action'] = 'use_customnotfound' resp = self.app.get('/', status=404) assert 'pylons.controller.exception' in resp.environ exc = resp.environ['pylons.controller.exception'] assert exc.detail == 'Custom not found' assert resp.status == 404 def test_private_func(self): self.baseenviron['pylons.routes_dict']['action'] = '_private' resp = self.app.get('/', status=404) assert resp.status == 404 def test_strme_func(self): self.baseenviron['pylons.routes_dict']['action'] = 'strme' resp = self.app.get('/') assert "hi there" in resp def test_header_check(self): self.baseenviron['pylons.routes_dict']['action'] = 'header_check' resp = self.app.get('/') assert "Hello all!" in resp assert resp.response.headers['Content-Type'] == 'text/plain' assert resp.response.headers['Cache-Control'] == 'private' assert resp.header('Content-Type') == 'text/plain' def test_head(self): self.baseenviron['pylons.routes_dict']['action'] = 'header_check' resp = self.app._gen_request('HEAD', '/') assert '' == resp.body assert resp.header('Content-Type') == 'text/plain' def test_redirect(self): self.baseenviron['pylons.routes_dict']['action'] = 'use_redirect' resp = self.app.get('/', status=301) def test_nothing(self): self.baseenviron['pylons.routes_dict']['action'] = 'nothing' resp = self.app.get('/') assert '' == resp.body assert resp.response.headers['Cache-Control'] == 'private' def test_unicode_action(self): self.baseenviron['pylons.routes_dict']['action'] = u'ОбсуждениеКомпаний' resp = self.app.get('/', status=404) def test_params(self): self.baseenviron['pylons.routes_dict']['action'] = u'params' resp = self.app.get('/?foo=bar') assert "'foo', u'bar')]" in resp, str(resp) resp = self.app.post('/?foo=bar', params=dict(snafu='snafoo')) assert "'foo', u'bar')" in resp, str(resp) assert "'snafu', u'snafoo')]" in resp, str(resp) resp = self.app.put('/?foo=bar', params=dict(snafu='snafoo')) assert "'foo', u'bar')" in resp, str(resp) assert "'snafu', u'snafoo')]" in resp, str(resp) def test_list(self): self.baseenviron['pylons.routes_dict']['action'] = 'list' assert 'from a list' in self.app.get('/') class TestFilteredWSGI(TestWSGIController): def __init__(self, *args, **kargs): TestWSGIController.__init__(self, *args, **kargs) self.baseenviron = {} app = ControllerWrap(FilteredWSGIController) app = self.sap = SetupCacheGlobal(app, self.baseenviron) app = RegistryManager(app) self.app = TestApp(app) def setUp(self): TestWSGIController.setUp(self) self.baseenviron.update(self.environ) def test_before(self): resp = self.get_response(action='index') assert 'hi' in resp assert 'before is 1' in resp def test_after_response(self): resp = self.get_response(action='after_response') assert 'hi from __after__' in resp def test_after_string_response(self): resp = self.get_response(action='after_string_response') assert 'hello from __after__' in resp def test_start_response(self): self.baseenviron['pylons.routes_dict']['action'] = 'start_response' self.app.get('/', status=404) Pylons-1.0.2/tests/test_units/test_helpers.py0000644000175000017500000000277312451647626020774 0ustar benben00000000000000import warnings from unittest import TestCase from paste.fixture import TestApp from paste.httpexceptions import HTTPMovedPermanently from paste.registry import RegistryManager from __init__ import TestWSGIController def make_helperscontroller(): import pylons from pylons.controllers import WSGIController from pylons.controllers.util import etag_cache class HelpersController(WSGIController): def test_etag_cache(self): etag_cache('test') return "from etag_cache" return HelpersController class TestHelpers(TestWSGIController): def __init__(self, *args, **kargs): from pylons.testutil import ControllerWrap, SetupCacheGlobal HelpersController = make_helperscontroller() TestWSGIController.__init__(self, *args, **kargs) self.baseenviron = {} app = ControllerWrap(HelpersController) app = self.sap = SetupCacheGlobal(app, self.baseenviron) app = RegistryManager(app) self.app = TestApp(app) def setUp(self): TestWSGIController.setUp(self) self.baseenviron.update(self.environ) warnings.simplefilter('error', DeprecationWarning) def tearDown(self): warnings.simplefilter('always', DeprecationWarning) def test_return_etag_cache(self): self.baseenviron['pylons.routes_dict']['action'] = 'test_etag_cache' response = self.app.get('/') assert '"test"' == response.header('Etag') assert 'from etag_cache' in response Pylons-1.0.2/tests/test_units/test_jsonrpc.pyc0000644000175000017500000002556412456572500021147 0ustar benben00000000000000 OTc@snddlmZddlmZddljZddlZddlmZdZ defdYZ dS(i(tTestApp(tRegistryManagerN(tTestWSGIControllercs9ddlmmdffdY}|S(Ni(tJSONRPCControllert JSONRPCErrortBaseJSONRPCControllercseZdZdZfdZfdZfdZddZdfdZd fd Z d Z RS( cSs t|_dS(N(tTruet_pylons_log_debug(tself((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyt__init__scSs|S(N((Rtmessage((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pytechoscs)t|ts!ddndSdS(NisThat is not an integersgot an integer(t isinstancetint(Rtarg(R(sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyt int_arg_checkscsS(N((R(R(sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pytreturn_garbagescs>t|t r2t|t r2ddn||SdS(NisThat is not an integer(R R (Rtxty(R(sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pytsubtracts sDefault messagecSs|S(N((RR ((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pytv2_echo$siccs)t|ts!ddndSdS(NisThat is not an integersgot an integer(R R (RR(R(sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pytv2_int_arg_check'sics>t|t r2t|t r2ddn||SdS(s)Like subtract, but decrements by default.isThat is not an integerN(R R (RRR(R(sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyt v2_decrement-s cSsdS(Nsprivate method((R((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyt_private4s( t__name__t __module__R R RRRRRRR((RR(sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyR s   (tpylons.controllersRR(R((RRsD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pytmake_basejsonrpc s*tTestJSONRPCControllercBseZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZdZdZRS(cOsddlm}m}t}tj|||i|_i|jd<||}|||j}|_t|}t ||_ dS(Ni(tControllerWraptSetupCacheGlobalspylons.routes_dict( tpylons.testutilRRRRR t baseenvirontsapRRtapp(RtargstkwargsRRRR"((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyR <s     cCs@|jddd }tdddddd|ks<tdS( NR R#s hello, worldtjsonrpcs2.0tidttesttresult(s hello, world(tjsonreqtdicttAssertionError(Rtresponse((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyt test_echoHs c CsN|jddd }tdddddid d 6d d 6|ksJtdS(NRR#t1R%s2.0R&R'terroritcodesThat is not an integerR (R.(R)R*R+(RR,((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyttest_int_arg_checkNs   c CsH|jd}tdddddidd6d d 6|ksDtdS( NRR%s2.0R&R'R/iR0sInternal errorR (R)R*R+(RR,((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyttest_return_garbageUs   c CsH|jd}tdddddidd6d d 6|ksDtdS( NRR%s2.0R&R'R/iR0sMethod not foundR (R)R*R+(RR,((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyttest_private_method\s   cCs7|jddd}|jjddks3tdS(NR R#tfoos Content-Typesapplication/json(sfoo(R)R,theaderR+(RR,((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyttest_content_typecsc CsH|jd}tdddddidd6d d 6|ksDtdS( NR4R%s2.0R&R'R/iR0sMethod not foundR (R)R*R+(RR,((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyttest_missing_methodgs   c sJtjtdddddddd }jtjfd dS( NR%s2.0R&R'tmethodR R#R4csjjddtddS(Nt/t extra_environtCONTENT_LENGTHt(R"tpostR*((R(sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pytts(sfoo(tjsontdumpsR*t assertRaisestexctHTTPLengthRequired(Rtdata((RsD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyttest_no_content_lengthns   c sJtjtdddddddd }jtjfd dS( NR%s2.0R&R'R8R R#R4csjjddtddS(NR9R:R;t0(R"R=R*((R(sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyR>}s(sfoo(R?R@R*RARBRC(RRD((RsD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyttest_zero_content_lengthws   cCsF|jddddg}tddddd d|ksBtdS( NRR#iiR%s2.0R&R'R((R)R*R+(RR,((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyttest_positional_paramss c CsQ|jdddg}tdddddid d 6d d 6|ksMtdS( NRR#iR%s2.0R&R'R/iR0sInvalid paramsR (R)R*R+(RR,((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyttest_missing_positional_params   c CsT|jddddg}tddddd id d 6d d 6|ksPtdS(NRR#R.t2R%s2.0R&R'R/iR0sThat is not an integerR (R)R*R+(RR,((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyttest_wrong_param_types   cCsG|jddidd6}tddddd d|ksCtdS( NRR#s hello, worldR R%s2.0R&R'R((R)R*R+(RR,((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyt test_v2_echos cCs@|jddi}tdddddd|ks<tdS( NRR#R%s2.0R&R'R(sDefault message(R)R*R+(RR,((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyttest_v2_echo_defaults cCsA|jddidd6}tddddd d s=tdS( NRR#iRR%s2.0R&R'R(sgot an integer(R)R*R+(RR,((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyttest_v2_int_arg_check_valids cCs:|jddi}tdddddds6tdS( NRR#R%s2.0R&R'R(sgot an integer(R)R*R+(RR,((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyt.test_v2_int_arg_check_default_keyword_arguments c CsU|jddidd6}tddddd id d 6d d 6|ksQtdS(NRR#tabcRR%s2.0R&R'R/iR0sThat is not an integerR (R)R*R+(RR,((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyttest_v2_int_arg_checks   cCsN|jddidd6dd6}tddd d d d |ksJtdS( NRR#i2RidRR%s2.0R&R'R(i(R)R*R+(RR,((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyttest_v2_decrements# cCsG|jddidd6}tddddd d |ksCtdS( NRR#i2RR%s2.0R&R'R(i1(R)R*R+(RR,((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyt+test_v2_decrement_default_keywoard_arguments c CsN|jddi}tdddddidd 6d d 6|ksJtdS( NRR#R%s2.0R&R'R/iR0sInvalid paramsR (R)R*R+(RR,((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyt*test_v2_decrement_missing_keyword_arguments   (RRR R-R1R2R3R6R7RERGRHRIRKRLRMRNRORQRRRSRT(((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyR:s(                ( t paste.fixtureRtpaste.registryRt webob.excRBR?R RRR(((sD/home/ben/Programming/Python/pylons/tests/test_units/test_jsonrpc.pyts   0Pylons-1.0.2/tests/test_units/test_basic_app.pyc0000644000175000017500000002243012456572500021377 0ustar benben00000000000000 OTc@sddlZddlZddlZddlmZddlmZeeeedZ de fdYZ de fdYZ dS( iN(traises(t test_rootcKssddl}ddlj}ddlm}ddlm} m} ddlm } ddl m } ddl m } ddlm}ddlm}m}dd lm}dd lm}dd lm}td tjjtd dtjjtd d}|j}|j||dd d||d|dd}|j d|j ddd|j ddd||dR;R:Rturl(RR=R>R:((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pytsetUp>s  cCs>|jjdditd6}tjd|js:tdS(Ns /_test_varst extra_environspaste.testing_variabless^\d+$(R:tgettTruetretmatchtbodytAssertionError(Rtresp((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pyt test_testvarsFscCs1|jjddt}|jdks-tdS(Ns /test_funct expect_errorsi(R:RDREtstatusRI(RRJ((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pyttest_exception_resp_attachJscCs(|jjddt}ds$tdS(Ns /test_emptyRLt wontgethre(R:RDRERI(RRJ((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pyttest_no_contentNscCsJddlm}|tidt}|jd}|jsFtdS(Ni(R=R6s /hello/index(R?R=R;RERDRRI(RR=R:RJ((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pyt"test_middleware_cache_obj_instanceSscCsMddlm}|tidt}|jd}d|ksItdS(Ni(R=R7s /hello/indexs Hello World(R?R=R;RERDRI(RR=R:RJ((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pyttest_attribsafe_tmpl_contextYscCs8|jjdditd6}|jdks4tdS(Ns /hello/indexRCspaste.testing_variablessNothing here but a string(R:RDRERRI(RRJ((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pyttest_cache_obj_appglobals_scCs(|jjd}d|ks$tdS(Ns/goodbye/indexs Hello World(R:RDRI(RRJ((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pyttest_controller_name_overridecs( RRRBRKRNRt ExceptionRPRQRRRSRT(((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pyR<=s      tTestJsonifyDecoratorcBsneZdZdZdZeedZdZdZ dZ dZ dZ d Z RS( cCsdddlm}ddlm}ti}|j|_|||_||jdi|_dS(Ni(R=(R>s routes.map(R?R=R@R>R;RR:RA(RR=R>R:((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pyRBis   cCs(|jjd}d|ks$tdS(Ns /hello/indexs Hello World(R:RDRI(Rtresponse((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pyttest_basic_responseqscCs7ddl}ddlj}|j|jks3tdS(Ni(RRRRRI(RRR((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pyt test_configus cCsOddlm}|ttdd}|jdddditd 6dS( Ni(R=RREs /hello/oopsRMiRCspaste.throw_errors(R?R=R;R*RDR2(RR=R:((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pyt test_evalzscCs|jddS(Ntset_lang(t_test_set_lang(R((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pyt test_set_langscCs|jddS(Ntset_lang_pylonscontext(R\(R((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pyttest_set_lang_pylonscontextscCs|jj|jddd|dd}djd|ksEt|jj|jddd|dd}d |kstdS( NRti18nctactiontlangtjau,言語設定を「ja」に変更しましたsutf-8tchsCould not set language to "ch"(R:RDRAtencodeRI(RRaRW((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pyR\s**cCsP|jj|jdddddidd6}djd |ksLtdS( NRR`Rat i18n_indextheaderssfr;q=0.6, en;q=0.1, ja;q=0.3sAccept-Languageu根本インデクスページsutf-8(R:RDRAReRI(RRW((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pyttest_detect_langs$ cCsL|jj|jdddd}d|ks6td|ksHtdS(NRR`Ratno_langs No languages No languages(R:RDRARI(RRW((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pyt test_no_langs$cCsG|jj|jdddddidd6}d|ksCtdS( NRR`RatlangsRgsfr;q=0.6, en;q=0.1, ja;q=0.3sAccept-Languages['fr', 'ja', 'en-us'](R:RDRARI(RRW((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pyt test_langss$ (RRRBRXRYRRIRZR]R_R\RhRjRl(((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pyRVhs        ( R+RFtsysR"RRRRER2R;R1R<RV(((sF/home/ben/Programming/Python/pylons/tests/test_units/test_basic_app.pyts   2+Pylons-1.0.2/tests/test_units/__pycache__/0000755000175000017500000000000012553621453020111 5ustar benben00000000000000Pylons-1.0.2/tests/test_units/__pycache__/__init__.cpython-34.pyc0000644000175000017500000000667212460016451024300 0ustar benben00000000000000 OT @s%ddlZddlZddlZddlmZddlmZddlmZm Z ej j ej j e ZyejeWnYnXej j ej j e Zej j ej j eZej jedZej jeGdddeZGdd d eZdS) N)TestCase) quote_plus)loadsdumpsZ test_filesc@s(eZdZddZddZdS)TestMiddlewarecCs ||_dS)N)app)selfrr @/home/ben/Programming/Python/pylons/tests/test_units/__init__.py__init__szTestMiddleware.__init__cCs=d|kri|ds  zTestWSGIController.xmlreqc Cst|ts3t|ts3t|ts3ttdd}tjtddd|d|}|jjddt |d||_ }tj |j S) Nr,zapplication/jsonidtestr/r)r!r") isinstancelisttuplerAssertionErrorjsonrrr*rrrr.)rr/r0r1r2rr r r jsonreqGs zTestWSGIController.jsonreq) rrrrrr(r+r3r;r r r r r!s     r)r:ossysunittestrurllibr xmlrpclibrrpathdirnameabspath__file__Zdata_dirshutilrmtreeZcur_dirZ pylons_rootjoinZ test_rootappendobjectrrr r r r s    Pylons-1.0.2/tests/test_units/test_middleware.py0000644000175000017500000000366312451647626021446 0ustar benben00000000000000# -*- coding: utf-8 -*- from webtest import TestApp def simple_app(environ, start_response): start_response('200 OK', [('Content-type', 'text/plain')]) return ['Hello world!'] def simple_exception_app(environ, start_response): if environ['PATH_INFO'].startswith('/error/document'): start_response('200 OK', [('Content-type', 'text/plain')]) return ['Made it to the error'] else: start_response('404 Not Found', [('Content-type', 'text/plain')]) return ['No page found!'] def test_plain_wrap(): from pylons.middleware import StatusCodeRedirect app = TestApp(StatusCodeRedirect(simple_app)) res = app.get('/') assert res.status_int == 200 def test_status_intercept(): from pylons.middleware import StatusCodeRedirect app = TestApp(StatusCodeRedirect(simple_exception_app)) res = app.get('/', status=404) assert 'Made it to the error' in res def test_original_path(): from pylons.middleware import StatusCodeRedirect app = TestApp(StatusCodeRedirect(simple_exception_app)) res = app.get('/', status=404) if getattr(res, 'environ', None) is not None: # webob<1.2 assert res.environ['PATH_INFO'] == '/' def test_retains_response(): from pylons.middleware import StatusCodeRedirect app = TestApp(StatusCodeRedirect(simple_exception_app)) res = app.get('/', status=404) if getattr(res, 'environ', None) is not None: # webob<1.2 assert 'pylons.original_response' in res.environ assert 'No page found!' in res.environ['pylons.original_response'].body def test_retains_request(): from pylons.middleware import StatusCodeRedirect app = TestApp(StatusCodeRedirect(simple_exception_app)) res = app.get('/fredrick', status=404) if getattr(res, 'environ', None) is not None: # webob<1.2 assert 'pylons.original_request' in res.environ assert '/fredrick' == res.environ['pylons.original_request'].path_info Pylons-1.0.2/tests/test_units/__init__.py0000644000175000017500000000534412451647626020027 0ustar benben00000000000000import json import os import sys from unittest import TestCase from urllib import quote_plus from xmlrpclib import loads, dumps data_dir = os.path.dirname(os.path.abspath(__file__)) try: shutil.rmtree(data_dir) except: pass cur_dir = os.path.dirname(os.path.abspath(__file__)) pylons_root = os.path.dirname(os.path.dirname(cur_dir)) test_root = os.path.join(pylons_root, 'test_files') sys.path.append(test_root) class TestMiddleware(object): def __init__(self, app): self.app = app def __call__(self, environ, start_response): if 'paste.testing_variables' not in environ: environ['paste.testing_variables'] = {} testenv = environ['paste.testing_variables'] testenv['environ'] = environ return self.app(environ, start_response) class TestWSGIController(TestCase): def setUp(self): import pylons from pylons.util import ContextObj, PylonsContext c = ContextObj() py_obj = PylonsContext() py_obj.tmpl_context = c py_obj.request = py_obj.response = None self.environ = {'pylons.routes_dict':dict(action='index'), 'paste.config':dict(global_conf=dict(debug=True)), 'pylons.pylons':py_obj} pylons.tmpl_context._push_object(c) def tearDown(self): import pylons pylons.tmpl_context._pop_object() def get_response(self, **kargs): test_args = kargs.pop('test_args', {}) url = kargs.pop('_url', '/') self.environ['pylons.routes_dict'].update(kargs) return self.app.get(url, extra_environ=self.environ, **test_args) def post_response(self, **kargs): url = kargs.pop('_url', '/') self.environ['pylons.routes_dict'].update(kargs) return self.app.post(url, extra_environ=self.environ, params=kargs) def xmlreq(self, method, args=None): if args is None: args = () ee = dict(CONTENT_TYPE='text/xml') data = dumps(args, methodname=method) self.response = response = self.app.post('/', params = data, extra_environ=ee) return loads(response.body)[0][0] def jsonreq(self, method, args=()): assert(isinstance(args, list) or isinstance(args, tuple) or isinstance(args, dict)) ee = dict(CONTENT_TYPE='application/json') data = json.dumps(dict(id='test', method=method, params=args)) self.response = response = self.app.post('/', params=quote_plus(data), extra_environ=ee) return json.loads(response.body) Pylons-1.0.2/tests/test_units/test_decorator_jsonify.py0000644000175000017500000000316012451647626023044 0ustar benben00000000000000import warnings from paste.fixture import TestApp from paste.registry import RegistryManager from __init__ import TestWSGIController def make_cache_controller_app(): from pylons.testutil import ControllerWrap, SetupCacheGlobal from pylons.decorators import jsonify from pylons.controllers import WSGIController class CacheController(WSGIController): @jsonify def test_bad_json(self): return ["this is neat"] @jsonify def test_bad_json2(self): return ("this is neat",) @jsonify def test_good_json(self): return dict(fred=42) environ = {} app = ControllerWrap(CacheController) app = sap = SetupCacheGlobal(app, environ) app = RegistryManager(app) app = TestApp(app) return app, environ class TestJsonifyDecorator(TestWSGIController): def setUp(self): self.app, environ = make_cache_controller_app() TestWSGIController.setUp(self) environ.update(self.environ) warnings.simplefilter('error', Warning) def tearDown(self): warnings.simplefilter('always', Warning) def test_bad_json(self): for action in 'test_bad_json', 'test_bad_json2': try: response = self.get_response(action=action) except Warning, msg: assert 'JSON responses with Array envelopes are' in msg[0] def test_good_json(self): response = self.get_response(action='test_good_json') assert '{"fred": 42}' in response assert response.header('Content-Type') == 'application/json; charset=utf-8' Pylons-1.0.2/tests/test_units/test_middleware.pyc0000644000175000017500000000607112456572500021576 0ustar benben00000000000000 OTc@sSddlmZdZdZdZdZdZdZdZd S( i(tTestAppcCs|ddgdgS(Ns200 OKs Content-types text/plains Hello world!(s Content-types text/plain((tenvirontstart_response((sG/home/ben/Programming/Python/pylons/tests/test_units/test_middleware.pyt simple_appscCsE|djdr*|dd gdgS|dd gdgSdS( Nt PATH_INFOs/error/documents200 OKs Content-types text/plainsMade it to the errors 404 Not FoundsNo page found!(s Content-types text/plain(s Content-types text/plain(t startswith(RR((sG/home/ben/Programming/Python/pylons/tests/test_units/test_middleware.pytsimple_exception_apps cCsJddlm}t|t}|jd}|jdksFtdS(Ni(tStatusCodeRedirectt/i(tpylons.middlewareRRRtgett status_inttAssertionError(Rtapptres((sG/home/ben/Programming/Python/pylons/tests/test_units/test_middleware.pyttest_plain_wrapscCsMddlm}t|t}|jddd}d|ksItdS(Ni(RRtstatusisMade it to the error(R RRRR R (RR R((sG/home/ben/Programming/Python/pylons/tests/test_units/test_middleware.pyttest_status_interceptscCsoddlm}t|t}|jddd}t|dddk rk|jddksktndS(Ni(RRRiRR( R RRRR tgetattrtNoneRR (RR R((sG/home/ben/Programming/Python/pylons/tests/test_units/test_middleware.pyttest_original_paths cCsddlm}t|t}|jddd}t|dddk rd|jksdtd|jdj kstndS( Ni(RRRiRspylons.original_responsesNo page found!( R RRRR RRRR tbody(RR R((sG/home/ben/Programming/Python/pylons/tests/test_units/test_middleware.pyttest_retains_response#s cCsddlm}t|t}|jddd}t|dddk rd|jksdtd|jdj kstndS(Ni(Rs /fredrickRiRspylons.original_request( R RRRR RRRR t path_info(RR R((sG/home/ben/Programming/Python/pylons/tests/test_units/test_middleware.pyttest_retains_request+s N( twebtestRRRRRRRR(((sG/home/ben/Programming/Python/pylons/tests/test_units/test_middleware.pyts      Pylons-1.0.2/tests/test_units/test_helpers.pyc0000644000175000017500000000560412456572500021124 0ustar benben00000000000000 OTc@sddlZddlmZddlmZddlmZddlmZddl m Z dZ de fd YZ dS( iN(tTestCase(tTestApp(tHTTPMovedPermanently(tRegistryManager(tTestWSGIControllercsLddl}ddlm}ddlmd|ffdY}|S(Ni(tWSGIController(t etag_cachetHelpersControllercseZfdZRS(csddS(Nttestsfrom etag_cache((tself(R(sD/home/ben/Programming/Python/pylons/tests/test_units/test_helpers.pyttest_etag_caches (t__name__t __module__R ((R(sD/home/ben/Programming/Python/pylons/tests/test_units/test_helpers.pyRs(tpylonstpylons.controllersRtpylons.controllers.utilR(R RR((RsD/home/ben/Programming/Python/pylons/tests/test_units/test_helpers.pytmake_helperscontroller s  t TestHelperscBs,eZdZdZdZdZRS(cOsddlm}m}t}tj|||i|_||}|||j}|_t|}t ||_ dS(Ni(tControllerWraptSetupCacheGlobal( tpylons.testutilRRRRt__init__t baseenvirontsapRRtapp(R targstkargsRRRR((sD/home/ben/Programming/Python/pylons/tests/test_units/test_helpers.pyRs    cCs4tj||jj|jtjdtdS(Nterror(RtsetUpRtupdatetenvirontwarningst simplefiltertDeprecationWarning(R ((sD/home/ben/Programming/Python/pylons/tests/test_units/test_helpers.pyR"s cCstjdtdS(Ntalways(RR R!(R ((sD/home/ben/Programming/Python/pylons/tests/test_units/test_helpers.pyttearDown'scCsTd|jdd<|jjd}d|jdks>td|ksPtdS(NR spylons.routes_dicttactiont/s"test"tEtagsfrom etag_cache(RRtgettheadertAssertionError(R tresponse((sD/home/ben/Programming/Python/pylons/tests/test_units/test_helpers.pyttest_return_etag_cache*s(R R RRR#R+(((sD/home/ben/Programming/Python/pylons/tests/test_units/test_helpers.pyRs  ( RtunittestRt paste.fixtureRtpaste.httpexceptionsRtpaste.registryRRRRR(((sD/home/ben/Programming/Python/pylons/tests/test_units/test_helpers.pyts  Pylons-1.0.2/tests/test_units/test_i18n.pyc0000644000175000017500000000566112456572500020244 0ustar benben00000000000000 OTc@sgddlZddlZddlmZddlmZdadZgZ de fdYZ dS(iN(tTestApp(t test_rootcCs|ddl}ddlm}tjjtd}ii|d6d6dd6atjj t|j j |ddtdS(Ni(t_get_translatortsample_controllerstroots pylons.pathsspylons.packaget pylons_config( tpylonstpylons.i18n.translationRtostpathtjoinRt lang_setuptsystappendt translatort _push_objecttNone(RRR((sA/home/ben/Programming/Python/pylons/tests/test_units/test_i18n.pytsetup_py_trans s  tTestI18NcBs#eZdZdZdZRS(cCs tdS(N(R(tself((sA/home/ben/Programming/Python/pylons/tests/test_units/test_i18n.pytsetUpscCsddlm}d}||}|d}|d}t|t|ks[ttjdt|t|kstdS(Ni(tlazifycSsd|ttfS(Ns%s%s(tlentglob_set(tst((sA/home/ben/Programming/Python/pylons/tests/test_units/test_i18n.pytshow_strstfredt1(RRtstrtAssertionErrorRR (RRRt lazy_show_strtresult1tresult2((sA/home/ben/Programming/Python/pylons/tests/test_units/test_i18n.pyt test_lazifys     csddl}ddlmm}m}|ddtffdY}|jdkskt|ddtdt }|j j ||jd kst|d dtdt }|j j ||jd kstdkstdS( Ni(t_tN_tset_langtHellotBarcseZfdZRS(cs|_dS(N(t local_foo(R(R"tfoo(sA/home/ben/Programming/Python/pylons/tests/test_units/test_i18n.pyt__init__.s(t__name__t __module__R)((R"R((sA/home/ben/Programming/Python/pylons/tests/test_units/test_i18n.pyR&-stfrt set_environRtBonjourtesu¡Hola!( RRR"R#R$tobjectR'RtFalseR RR(RRR#R$R&tt((R"R(sA/home/ben/Programming/Python/pylons/tests/test_units/test_i18n.pyt test_noop(s  (R*R+RR!R3(((sA/home/ben/Programming/Python/pylons/tests/test_units/test_i18n.pyRs  ( RR t paste.fixtureRR)RRR RRR0R(((sA/home/ben/Programming/Python/pylons/tests/test_units/test_i18n.pyts   Pylons-1.0.2/tests/test_units/test_controller.pyc0000644000175000017500000003140312456601147021641 0ustar benben00000000000000 `Tc@sddlmZddlmZddlmZddlZddlmZddl m Z m Z ddl m Z mZdefd YZd efd YZd e fd YZde fdYZdS(i(tTestApp(tRegistryManager(t status_mapN(tWSGIController(tSetupCacheGlobaltControllerWrap(tTestWSGIControllertTestMiddlewaretBasicWSGIControllercBsteZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z RS( cCs t|_dS(N(tTruet_pylons_log_debug(tself((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyt__init__ scCsdtjjdeZdZdZdZdZdZdZRS(cCsd|_d|_dS(Ni(tbeforetafter(R ((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyR =s cCs|jd7_dS(Ni(R-(R ((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyRAscCsK|jd7_tjjdjd}|dkrGtjjdndS(Nispylons.routes_dicttactiontafter_responsetafter_string_responses from __after__(safter_responsesafter_string_response(R.RR"tenvirontgetRtwrite(R R/((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyRDs cCs d|jS(Nshi all, before is %s(R-(R ((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyRJscCsdS(NR((R ((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyR0MscCsdS(Nthello((R ((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyR1Ps(R*R+R RRRR0R1(((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyR,<s      t TestBasicWSGIcBseZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZRS(cOsltj|||i|_tt}t||j}|_t|}t|}t ||_ dS(N( RR t baseenvironRRRtsapRRRtapp(R targstkargsR9((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyR Ts    cCs$tj||jj|jdS(N(RtsetUpR7tupdateR2(R ((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyR<]s cCs"|j}d|kstdS(Ns hello world(t get_responsetAssertionError(R tresp((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyttest_wsgi_callas cCs,|jdd}dd|ks(tdS(NR/RRid(R>R?(R R@((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyttest_yield_wrapperescCsWt|jdddtdS(Nt_privatespylons.routes_dictR/RFRGi(R7R9R3RGR?(R R@((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyttest_private_funcxscCs9d|jdd<|jjd}d|ks5tdS(NRspylons.routes_dictR/RFshi there(R7R9R3R?(R R@((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyttest_strme_func}scCsd|jdd<|jjd}d|ks5t|jjddksQt|jjdd ksmt|jddkstdS( NR spylons.routes_dictR/RFs Hello all!s Content-Types text/plains Cache-ControlR (R7R9R3R?RRtheader(R R@((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyttest_header_checks cCsZd|jdd<|jjdd}d|jks;t|jddksVtdS( NR spylons.routes_dictR/tHEADRFts Content-Types text/plain(R7R9t _gen_requesttbodyR?RO(R R@((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyt test_headscCs-d|jdd<|jjddd}dS(NRspylons.routes_dictR/RFRGi-(R7R9R3(R R@((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyt test_redirectscCsXd|jdd<|jjd}d|jks8t|jjddksTtdS(NR!spylons.routes_dictR/RFRRs Cache-ControlR (R7R9R3RTR?RR(R R@((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyt test_nothingscCs-d|jdd<|jjddd}dS(NuHОбсуждениеКомпанийspylons.routes_dictR/RFRGi(R7R9R3(R R@((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyttest_unicode_actionscCsd|jdd<|jjd}d|ksAtt||jjddtdd}d |kstt|d |kstt||jjddtdd}d |kstt|d |kstt|dS( Nuparamsspylons.routes_dictR/s /?foo=bars'foo', u'bar')]R#tsnafutsnafoos'foo', u'bar')s'snafu', u'snafoo')](R7R9R3R?R'tposttdicttput(R R@((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyt test_paramss!!cCs3d|jddeZdZdZdZdZdZdZRS(cOs`tj|||i|_tt}t||j}|_t|}t||_ dS(N( RR R7RR,RR8RRR9(R R:R;R9((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyR s    cCs$tj||jj|jdS(N(RR<R7R=R2(R ((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyR<s cCs:|jdd}d|ks$td|ks6tdS(NR/RRs before is 1(R>R?(R R@((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyt test_beforescCs(|jdd}d|ks$tdS(NR/R0shi from __after__(R>R?(R R@((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyttest_after_responsescCs(|jdd}d|ks$tdS(NR/R1shello from __after__(R>R?(R R@((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyttest_after_string_responsescCs+d|jdd<|jjddddS(Ntstart_responsespylons.routes_dictR/RFRGi(R7R9R3(R ((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyttest_start_responses(R*R+R R<RaRbRcRe(((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyR`s      (t paste.fixtureRtpaste.registryRt webob.excRRtpylons.controllersRtpylons.testutilRRR RRRR,R6R`(((sG/home/ben/Programming/Python/pylons/tests/test_units/test_controller.pyts 0ZPylons-1.0.2/tests/test_units/test_xmlrpc.pyc0000644000175000017500000002646012456572500020772 0ustar benben00000000000000 OTc@snddlmZddlmZddljZddlZddlmZdZ defdYZ dS(i(tTestApp(tRegistryManagerN(tTestWSGIControllercCs*ddlm}d|fdY}|S(Ni(tXMLRPCControllertBaseXMLRPCControllercBseZdZdZdZdgge_dZdgge_dZdgge_dZddgge_d Z d Z ddgge _d Z d Z RS( cSs t|_dS(N(tTruet_pylons_log_debug(tself((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyt__init__ stbarcSsdS(Ns basic string((R((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyt userstatusststringc Ss(tddddddddgdd S( sThis method has a docstringtmesssa little somethintaitbiitctalltthe(sallsthe(tdict(R((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pytdocsststructcSs tddS(sThis method has a docstringR uA unicode string, oh boy(R(R((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pytuniscSs't|tstjddSdSdS(NisInteger requireds received int(t isinstancetintt xmlrpclibtFault(Rtarg((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyt intargcheck sRcSsdS(Nsnot much((R((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pytnosig'scSsdS(sThis method has a docstringsTransform okay((RR((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pytstructured_methodname*scSsdS(s>This function has multiple lines in itshi all((R((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pytlongdoc/scSsdS(Nsprivate method((R((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyt_private5s( t__name__t __module__RtfooR t signatureRRRRRRR(((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyR s        (tpylons.controllersR(RR((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pytmake_basexmlrpc s+tTestXMLRPCControllercBseZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZdZdZdZdZdZdZdZRS(cOsddlm}m}t}tj|||i|_i|jd<||}|||j}|_t|}t ||_ dS(Ni(tControllerWraptSetupCacheGlobalspylons.routes_dict( tpylons.testutilR'R(R%RRt baseenvirontsapRRtapp(RtargstkargsR'R(RR,((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyR:s     cCs%|jd}|dks!tdS(NR s basic string(txmlreqtAssertionError(Rtresponse((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyt test_indexFsc CsO|jd}tddddddddgd d d g|ksKtdS( NRR sa little somethinR iRiiRRR(R/RR0(RR1((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyttest_structureJscCs(|jdd}d|ks$tdS(Nssystem.methodHelpRsThis method has a docstring(sdocs(R/R0(RR1((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyttest_methodhelpNscCs(|jdd}d|ks$tdS(Nssystem.methodHelpsstructured.methodnamesThis method has a docstring(sstructured.methodname(R/R0(RR1((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyt*test_methodhelp_with_structured_methodnameRscCs.|jdd}dgg|ks*tdS(Nssystem.methodSignatureRR(sdocs(R/R0(RR1((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyttest_methodsignatureVscCs1|jdd}ddgg|ks-tdS(Nssystem.methodSignaturesstructured.methodnameR (sstructured.methodname(R/R0(RR1((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyt/test_methodsignature_with_structured_methodnameZsc CsC|jd}|ddddddddd d g ks?tdS( Nssystem.listMethodsRRRRsstructured.methodnamessystem.methodHelpssystem.methodSignatureRR (R/R0(RR1((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyttest_listmethods^scCs)|jd}d|dks%tdS(NRsA unicode stringR (R/R0(RR1((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyt test_unicodebscCsGtjddd}|jjdd|dtdd|_}dS( Nt methodnameu$ОбсуждениеКомпанийt/tparamst extra_environt CONTENT_TYPEstext/xml((RtdumpsR,tpostRR1(RtdataR1((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyttest_unicode_methodfscs5tjddd}jtjfddS(NR:u$ОбсуждениеКомпанийcsjjddtddS(NR;R=tCONTENT_LENGTHt(R,R@R((R(sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pytls((RR?t assertRaisestexctHTTPLengthRequired(RRA((RsC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyttest_no_lengthjscs5tjddd}jtjfddS(NR:u$ОбсуждениеКомпанийcsjjddtddS(NR;R=RCt4194314(R,R@R((R(sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyREps((RR?RFRGtHTTPRequestEntityTooLarge(RRA((RsC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyt test_too_bignscCs|jtj|jddS(Nssystem.methodHelp(RFRRR/(R((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyt test_badargsrscCs|jtj|jddS(Nssystem.methodHelp(RFRRR/(R((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyt test_badarityuscCs |jtj|jdddS(NRg)@(g)@(RFRRR/(R((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyttest_bad_paramvalyscCs|jtj|jddS(Nt doesntexist(RFRRR/(R((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyttest_missingmethod|scCs(|jdd}|dks$tdS(Nssystem.methodSignatureRRD(snosig(R/R0(RR1((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyttest_nosignaturescCs |jtj|jdddS(Nssystem.methodSignatureu$ОбсуждениеКомпаний(u$ОбсуждениеКомпаний(RFRRR/(R((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyttest_nosignature_unicodescCs(|jdd}|dks$tdS(Nssystem.methodHelpRRD(snosig(R/R0(RR1((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyt test_nodocsscCs |jtj|jdddS(Nssystem.methodHelpu$ОбсуждениеКомпаний(u$ОбсуждениеКомпаний(RFRRR/(R((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyttest_nodocs_unicodescCs(|jdd}d|ks$tdS(Nssystem.methodHelpRs&This function has multiple lines in it(slongdoc(R/R0(RR1((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyttest_multilinedocscCs4|jdd}|jjddks0tdS(Nssystem.methodHelpRs Content-Typestext/xml(slongdoc(R/R1theaderR0(RR1((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyttest_contenttypescCs|jtj|jddS(Ntstart_response(RFRRR/(R((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyttest_start_responsescCs|jtj|jddS(NR(RFRRR/(R((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyttest_private_funcscCs|jtj|jddS(NR"(RFRRR/(R((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyttest_vars(R R!RR2R3R4R5R6R7R8R9RBRIRLRMRNRORQRRRSRTRURVRXRZR[R\(((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyR&9s2                       ( t paste.fixtureRtpaste.registryRt webob.excRGRRRR%R&(((sC/home/ben/Programming/Python/pylons/tests/test_units/test_xmlrpc.pyts   /Pylons-1.0.2/tests/test_units/test_decorator_jsonify.pyc0000644000175000017500000000652512456572500023210 0ustar benben00000000000000 OTc@s_ddlZddlmZddlmZddlmZdZdefdYZdS(iN(tTestApp(tRegistryManager(tTestWSGIControllercsddlm}m}ddlmddlm}d|ffdY}i}||}|||}}t|}t|}||fS(Ni(tControllerWraptSetupCacheGlobal(tjsonify(tWSGIControllertCacheControllercs5eZdZdZdZRS(cSsdgS(Ns this is neat((tself((sN/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_jsonify.pyt test_bad_jsonscSsdS(Ns this is neat(s this is neat((R((sN/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_jsonify.pyttest_bad_json2scSs tddS(Ntfredi*(tdict(R((sN/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_jsonify.pyttest_good_jsons(t__name__t __module__R R R ((R(sN/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_jsonify.pyR s( tpylons.testutilRRtpylons.decoratorsRtpylons.controllersRRR(RRRRtenvirontapptsap((RsN/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_jsonify.pytmake_cache_controller_apps   tTestJsonifyDecoratorcBs,eZdZdZdZdZRS(cCsCt\|_}tj||j|jtjdtdS(Nterror( RRRtsetUptupdateRtwarningst simplefiltertWarning(RR((sN/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_jsonify.pyR$s cCstjdtdS(Ntalways(RRR(R((sN/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_jsonify.pyttearDown*scCsWxPdD]H}y|jd|}Wqtk rN}d|dksOtqXqWdS(NR R tactions'JSON responses with Array envelopes arei(s test_bad_jsonstest_bad_json2(t get_responseRtAssertionError(RR tresponsetmsg((sN/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_jsonify.pyR -s  cCsC|jdd}d|ks$t|jddks?tdS(NR R s {"fred": 42}s Content-Typesapplication/json; charset=utf-8(R!R"theader(RR#((sN/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_jsonify.pyR 4s(RRRRR R (((sN/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_jsonify.pyR#s   ( Rt paste.fixtureRtpaste.registryRt__init__RRR(((sN/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_jsonify.pyts  Pylons-1.0.2/tests/test_units/test_xmlrpc.py0000644000175000017500000001377012451647626020636 0ustar benben00000000000000# -*- coding: utf-8 -*- from paste.fixture import TestApp from paste.registry import RegistryManager import webob.exc as exc import xmlrpclib from __init__ import TestWSGIController def make_basexmlrpc(): from pylons.controllers import XMLRPCController class BaseXMLRPCController(XMLRPCController): def __init__(self): self._pylons_log_debug = True foo = 'bar' def userstatus(self): return 'basic string' userstatus.signature = [ ['string'] ] def docs(self): "This method has a docstring" return dict(mess='a little somethin', a=1, b=[1,2,3], c=('all','the')) docs.signature = [ ['struct'] ] def uni(self): "This method has a docstring" return dict(mess=u'A unicode string, oh boy') uni.signature = [ ['struct'] ] def intargcheck(self, arg): if not isinstance(arg, int): return xmlrpclib.Fault(0, 'Integer required') else: return "received int" intargcheck.signature = [ ['string', 'int'] ] def nosig(self): return 'not much' def structured_methodname(self, arg): "This method has a docstring" return 'Transform okay' structured_methodname.signature = [ ['string', 'string'] ] def longdoc(self): """This function has multiple lines in it""" return "hi all" def _private(self): return 'private method' return BaseXMLRPCController class TestXMLRPCController(TestWSGIController): def __init__(self, *args, **kargs): from pylons.testutil import ControllerWrap, SetupCacheGlobal BaseXMLRPCController = make_basexmlrpc() TestWSGIController.__init__(self, *args, **kargs) self.baseenviron = {} self.baseenviron['pylons.routes_dict'] = {} app = ControllerWrap(BaseXMLRPCController) app = self.sap = SetupCacheGlobal(app, self.baseenviron) app = RegistryManager(app) self.app = TestApp(app) def test_index(self): response = self.xmlreq('userstatus') assert response == 'basic string' def test_structure(self): response = self.xmlreq('docs') assert dict(mess='a little somethin', a=1, b=[1,2,3], c=['all','the']) == response def test_methodhelp(self): response = self.xmlreq('system.methodHelp', ('docs',)) assert "This method has a docstring" in response def test_methodhelp_with_structured_methodname(self): response = self.xmlreq('system.methodHelp', ('structured.methodname',)) assert "This method has a docstring" in response def test_methodsignature(self): response = self.xmlreq('system.methodSignature', ('docs',)) assert [['struct']] == response def test_methodsignature_with_structured_methodname(self): response = self.xmlreq('system.methodSignature', ('structured.methodname',)) assert [['string', 'string']] == response def test_listmethods(self): response = self.xmlreq('system.listMethods') assert response == ['docs', 'intargcheck', 'longdoc', 'nosig', 'structured.methodname', 'system.listMethods', 'system.methodHelp', 'system.methodSignature', 'uni', 'userstatus'] def test_unicode(self): response = self.xmlreq('uni') assert 'A unicode string' in response['mess'] def test_unicode_method(self): data = xmlrpclib.dumps((), methodname=u'ОбсуждениеКомпаний') self.response = response = self.app.post('/', params=data, extra_environ=dict(CONTENT_TYPE='text/xml')) def test_no_length(self): data = xmlrpclib.dumps((), methodname=u'ОбсуждениеКомпаний') self.assertRaises(exc.HTTPLengthRequired, lambda: self.app.post('/', extra_environ=dict(CONTENT_LENGTH=''))) def test_too_big(self): data = xmlrpclib.dumps((), methodname=u'ОбсуждениеКомпаний') self.assertRaises(exc.HTTPRequestEntityTooLarge, lambda: self.app.post('/', extra_environ=dict(CONTENT_LENGTH='4194314'))) def test_badargs(self): self.assertRaises(xmlrpclib.Fault, self.xmlreq, 'system.methodHelp') def test_badarity(self): self.assertRaises(xmlrpclib.Fault, self.xmlreq, 'system.methodHelp') # Unsure whether this is actually picked up by xmlrpclib, but what the hey def test_bad_paramval(self): self.assertRaises(xmlrpclib.Fault, self.xmlreq, 'intargcheck', (12.5,)) def test_missingmethod(self): self.assertRaises(xmlrpclib.Fault, self.xmlreq, 'doesntexist') def test_nosignature(self): response = self.xmlreq('system.methodSignature', ('nosig',)) assert response == '' def test_nosignature_unicode(self): self.assertRaises(xmlrpclib.Fault, self.xmlreq, 'system.methodSignature', (u'ОбсуждениеКомпаний',)) def test_nodocs(self): response = self.xmlreq('system.methodHelp', ('nosig',)) assert response == '' def test_nodocs_unicode(self): self.assertRaises(xmlrpclib.Fault, self.xmlreq, 'system.methodHelp', (u'ОбсуждениеКомпаний',)) def test_multilinedoc(self): response = self.xmlreq('system.methodHelp', ('longdoc',)) assert 'This function\nhas multiple lines\nin it' in response def test_contenttype(self): response = self.xmlreq('system.methodHelp', ('longdoc',)) assert self.response.header('Content-Type') == 'text/xml' def test_start_response(self): self.assertRaises(xmlrpclib.Fault, self.xmlreq, 'start_response') def test_private_func(self): self.assertRaises(xmlrpclib.Fault, self.xmlreq, '_private') def test_var(self): self.assertRaises(xmlrpclib.Fault, self.xmlreq, 'foo') Pylons-1.0.2/tests/test_units/test_decorator_authenticate_form.py0000644000175000017500000000713112451647626025066 0ustar benben00000000000000# -*- coding: utf-8 -*- import logging import logging.handlers import os from beaker.middleware import SessionMiddleware from paste.fixture import TestApp from paste.registry import RegistryManager from routes import request_config from __init__ import data_dir, TestWSGIController session_dir = os.path.join(data_dir, 'session') try: import shutil shutil.rmtree(session_dir) except: pass # Eat the logging handler messages my_logger = logging.getLogger() my_logger.setLevel(logging.INFO) # Add the log message handler to the logger class NullHandler(logging.Handler): def emit(self, record): pass my_logger.addHandler(NullHandler()) def make_protected(): from pylons.controllers import WSGIController from pylons.decorators.secure import authenticate_form from webhelpers.pylonslib import secure_form from pylons import request class ProtectedController(WSGIController): def form(self): request_config().environ = request.environ return secure_form.authentication_token() @authenticate_form def protected(self): request_config().environ = request.environ return 'Authenticated' return ProtectedController class TestAuthenticateFormDecorator(TestWSGIController): def setUp(self): from pylons.testutil import ControllerWrap, SetupCacheGlobal ProtectedController = make_protected() TestWSGIController.setUp(self) app = ControllerWrap(ProtectedController) app = SetupCacheGlobal(app, self.environ, setup_session=True) app = SessionMiddleware(app, {}, data_dir=session_dir) app = RegistryManager(app) self.app = TestApp(app) def test_unauthenticated(self): from pylons.decorators.secure import csrf_detected_message self.environ['pylons.routes_dict']['action'] = 'protected' response = self.app.post('/protected', extra_environ=self.environ, expect_errors=True) assert response.status == 403 assert csrf_detected_message in response def test_authenticated(self): from webhelpers.pylonslib import secure_form self.environ['pylons.routes_dict']['action'] = 'form' response = self.app.get('/form', extra_environ=self.environ) token = response.body self.environ['pylons.routes_dict']['action'] = 'protected' response = self.app.post('/protected', params={secure_form.token_key: token}, extra_environ=self.environ, expect_errors=True) assert 'Authenticated' in response self.environ['pylons.routes_dict']['action'] = 'protected' response = self.app.put('/protected', params={secure_form.token_key: token}, extra_environ=self.environ, expect_errors=True) assert 'Authenticated' in response # GET with token_key in query string response = self.app.get('/protected', params={secure_form.token_key: token}, extra_environ=self.environ, expect_errors=True) assert 'Authenticated' in response # POST with token_key in query string response = self.app.post('/protected?' + secure_form.token_key + '=' + token, extra_environ=self.environ, expect_errors=True) assert 'Authenticated' in response Pylons-1.0.2/tests/test_units/test_decorator_cache.pyc0000644000175000017500000003133612456572500022570 0ustar benben00000000000000 OTc@sddlZddlZddlZddlmZddlmZddlmZddl m Z m Z iZ dadZejje dZyejeWnnXde fd YZd e fd YZdS( iN(tTestApp(tRegistryManager(tCacheMiddleware(tdata_dirtTestWSGIControllercsddlddlmmddlm}m}ddlm}m }d|ffdY|}||t dt }a t |idt}t|}t|}|}||t dt}t|}t|}||fS( Ni(t beaker_cachetcreate_cache_key(tWSGIControllertXMLRPCController(tSetupCacheGlobaltControllerWraptCacheControllercseZdddefdZddfdZfdZefdZddddfdZdd d efd Z d efd Z d dfdZ d dfdZ ddfdZ dddgdfdZfdZfdZddfdZd edZRS( tkeytinvalidate_on_startupcs jjd7_djjS(Nis Counter=%s(t app_globalstcounter(tself(tpylons(sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyt'test_default_cache_decorator_invalidatescs jjd7_djjS(Nis Counter=%s(RR(R(R(sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyttest_default_cache_decoratorscs+fd}dd|}|S(Ncs jjd7_djjS(Nis Counter=%s(RR((R(sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pytfunc#sR (tNone(RR(RR(sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyt!test_default_cache_decorator_func"scs[dj_fd}|r9dd|}ndddt|}|S(Nics jjd7_djjS(Nis Counter=%s(RR((R(sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyR+sR tcache_response(tresponset status_intRtFalse(Rtuse_cache_statusR(RR(sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyttest_response_cache_func)s  ttypetdbmcs jjd7_djjS(Nis Counter=%s(RR(R(R(sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyttest_dbm_cache_decorator4stparamt query_argscs jjd7_djjS(Nis Counter=%s(RR(R(R(sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyttest_get_cache_decorator9scs jjd7_djjS(Nis Counter=%s(RR(R(R(sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyttest_get_cache_default>stexpireics jjd7_djjS(Nis Counter=%s(RR(R(R(sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyttest_expire_cache_decoratorCscs jjd7_djjS(Nis Counter=%s(RR(R(R(sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyttest_expire_dbm_cache_decoratorHstidcs&jjd7_djj|fS(NisCounter=%s, id=%s(RR(RR'(R(sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyttest_key_cache_decoratorMstid2t123cs&jjd7_djj|fS(NisCounter=%s, id=%s(RR(RR'R)(R(sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyttest_keyslist_cache_decoratorRscs8j\}}jj|}|j|dS(N(Rtcachet get_cachet remove_value(RtnsR tc(R RR(sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyttest_invalidate_cacheWscs>j\}}jj|dd}|j|dS(NRR(RR,R-R.(RR/R R0(R RR(sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyttest_invalidate_dbm_cache\st cache_headerss content-typescontent-lengths x-powered-bycs>djjds(t assertRaisest Exception(R((RsL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyt test_no_caches(R8R9RFRM(((sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyREs tTestCacheDecoratorcBsPeZdZdZdZdZdZdZdZdZRS(cCs9t\}}||_tj|tj|jdS(N(RDRBRRFR?RG(RRBRC((sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyRFs  cCsdtj_|jdd|jdd}d|jdksGtd|ksYt|jdd}d|ks}tdS(NiRHRs text/htmls content-types Counter=1(R@tgRRIR4tAssertionError(RR((sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyRs c Csndtj_|jdd|jdd}d|jdksGtd|ksYt|jdd}d|ks}t|jddd d }d |kst|jddd d }d |kst|jdd }d |kst|jdd }d |ksttjd|jdd }d|ksJt|jdddd}d|kstt|jdddd}d|kst|jdddd}d|kst|jdddddd}d|kst|jdddddd}d|ks(t|jddd d}d|ksRt|jddd d}d|ks|t|jddd d }d|kst|jdd}d|jdkstd|kst|jdd}d|kst|jdddt}d|ks1t|jdddt d t d!d"}d|ksjtdS(#NiRHR1Rs text/htmls content-types Counter=1R"t_urls /?param=123s Counter=2R%s Counter=3is Counter=4R(R'is Counter=5s Counter=6R+R)s Counter=7R#s /?param=1243s Counter=8s Counter=9Rs Counter=10RRt test_argststatusi( R@RORRIR4RPR5tsleepR:Rtdict(RR((sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyRsX  cCs!dtj_|jdd|jdd}d|ks@t|jdd}d|ksdt|jdd|jdd}d|kstdtj_|jdd}d|kst|jdd}d|ksttjd|jdd}d|kstdS( NiRHR2Rs Counter=1s Counter=2R&i(R@RORRIRPR5RT(RR((sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyRs"   cCsddlm}m}|tj}|d|jdfksDt|jdd}|jdd}d|kszt|jdd}d|kst|jdd}|jdd}d|kstdS( Ni(RRs%s.TestCacheDecoratorRRHR1s Counter=1s Counter=2(R<RRRNRR9RPRI(RRRR R((sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyttest_cache_keyscCs_|jdddd}tjd|jdddd}t|t|ks[tdS(NRHR7RQs/test_cache_key_dupe?id=1g?s/test_cache_key_dupe?id=2&id=1(RIR5RTtstrRP(RRt response2((sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyR7s    cCs|jdd}|jddks+t|jddksDtd|jksYt|j}tjd|jdd}|j|kst|jddkst|jddkstd|jkstdS( NRHR6s content-typesapplication/specials x-powered-byRsx-dont-includei(RIR4RPtbodyR5RT(RRtoutput((sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_cache.pyR6s  cCs~ddl}dtj_d|jd<|jdd}d|ksIt|jdd}d|ksmtd |jds    k Pylons-1.0.2/tests/test_units/test_jsonrpc.py0000644000175000017500000001571212451647626021005 0ustar benben00000000000000# -*- coding: utf-8 -*- from paste.fixture import TestApp from paste.registry import RegistryManager import webob.exc as exc import json from __init__ import TestWSGIController def make_basejsonrpc(): from pylons.controllers import JSONRPCController, JSONRPCError class BaseJSONRPCController(JSONRPCController): def __init__(self): self._pylons_log_debug = True def echo(self, message): return message def int_arg_check(self, arg): if not isinstance(arg, int): raise JSONRPCError(1, 'That is not an integer') else: return 'got an integer' def return_garbage(self): return JSONRPCController def subtract(self, x, y): if not isinstance(x, int) and not isinstance(y, int): raise JSONRPCError(1, 'That is not an integer') else: return x - y def v2_echo(self, message='Default message'): return message def v2_int_arg_check(self, arg=99): if not isinstance(arg, int): raise JSONRPCError(1, 'That is not an integer') else: return 'got an integer' def v2_decrement(self, x, y=1): """Like subtract, but decrements by default.""" if not isinstance(x, int) and not isinstance(y, int): raise JSONRPCError(1, 'That is not an integer') else: return x - y def _private(self): return 'private method' return BaseJSONRPCController class TestJSONRPCController(TestWSGIController): def __init__(self, *args, **kwargs): from pylons.testutil import ControllerWrap, SetupCacheGlobal BaseJSONRPCController = make_basejsonrpc() TestWSGIController.__init__(self, *args, **kwargs) self.baseenviron = {} self.baseenviron['pylons.routes_dict'] = {} app = ControllerWrap(BaseJSONRPCController) app = self.sap = SetupCacheGlobal(app, self.baseenviron) app = RegistryManager(app) self.app = TestApp(app) def test_echo(self): response = self.jsonreq('echo', args=('hello, world',)) assert dict(jsonrpc='2.0', id='test', result='hello, world') == response def test_int_arg_check(self): response = self.jsonreq('int_arg_check', args=('1',)) assert dict(jsonrpc='2.0', id='test', error={'code': 1, 'message': 'That is not an integer'}) == response def test_return_garbage(self): response = self.jsonreq('return_garbage') assert dict(jsonrpc='2.0', id='test', error={'code': -32603, 'message': "Internal error"}) == response def test_private_method(self): response = self.jsonreq('_private') assert dict(jsonrpc='2.0', id='test', error={'code': -32601, 'message': "Method not found"}) == response def test_content_type(self): response = self.jsonreq('echo', args=('foo',)) assert self.response.header('Content-Type') == 'application/json' def test_missing_method(self): response = self.jsonreq('foo') assert dict(jsonrpc='2.0', id='test', error={'code': -32601, 'message': "Method not found"}) == response def test_no_content_length(self): data = json.dumps(dict(jsonrpc='2.0', id='test', method='echo', args=('foo',))) self.assertRaises(exc.HTTPLengthRequired, lambda: self.app.post('/', extra_environ=\ dict(CONTENT_LENGTH=''))) def test_zero_content_length(self): data = json.dumps(dict(jsonrpc='2.0', id='test', method='echo', args=('foo',))) self.assertRaises(exc.HTTPLengthRequired, lambda: self.app.post('/', extra_environ=\ dict(CONTENT_LENGTH='0'))) def test_positional_params(self): response = self.jsonreq('subtract', args=[4, 2]) assert dict(jsonrpc='2.0', id='test', result=2) == response def test_missing_positional_param(self): response = self.jsonreq('subtract', args=[1]) assert dict(jsonrpc='2.0', id='test', error={'code': -32602, 'message': "Invalid params"}) == response def test_wrong_param_type(self): response = self.jsonreq('subtract', args=['1', '2']) assert dict(jsonrpc='2.0', id='test', error={'code': 1, 'message': "That is not an integer"}) == response def test_v2_echo(self): response = self.jsonreq('v2_echo', args={'message': 'hello, world'}) assert dict(jsonrpc='2.0', id='test', result='hello, world') == response def test_v2_echo_default(self): response = self.jsonreq('v2_echo', args={}) assert dict(jsonrpc='2.0', id='test', result='Default message') == response def test_v2_int_arg_check_valid(self): response = self.jsonreq('v2_int_arg_check', args={'arg': 5}) assert dict(jsonrpc='2.0', id='test', result='got an integer') def test_v2_int_arg_check_default_keyword_argument(self): response = self.jsonreq('v2_int_arg_check', args={}) assert dict(jsonrpc='2.0', id='test', result='got an integer') def test_v2_int_arg_check(self): response = self.jsonreq('v2_int_arg_check', args={'arg': 'abc'}) assert dict(jsonrpc='2.0', id='test', error={'code': 1, 'message': "That is not an integer"}) == response def test_v2_decrement(self): response = self.jsonreq('v2_decrement', args={'x': 50, 'y': 100}) assert dict(jsonrpc='2.0', id='test', result=-50) == response def test_v2_decrement_default_keywoard_argument(self): response = self.jsonreq('v2_decrement', args={'x': 50}) assert dict(jsonrpc='2.0', id='test', result=49) == response def test_v2_decrement_missing_keyword_argument(self): response = self.jsonreq('v2_decrement', args={}) assert dict(jsonrpc='2.0', id='test', error={'code': -32602, 'message': "Invalid params"}) == response Pylons-1.0.2/tests/test_units/test_decorator_validate.pyc0000644000175000017500000001641612456614356023326 0ustar benben00000000000000 Tc@sddlZddlmZddlmZddlmZddlmZdZ dej fdYZ d ej fd YZ d Z d efd YZdS(iN(t html_quote(tTestApp(tRegistryManager(tTestWSGIControllercCsdt|S(Ns,

%s

(R(terror((sO/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_validate.pytcustom_error_formatter st NetworkFormcBs)eZeZeZejjdeZRS(t not_empty( t__name__t __module__tTruetallow_extra_fieldstfilter_extra_fieldst formencodet validatorstURLt new_network(((sO/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_validate.pyR st HelloFormcBs eZejejjZRS((RR R tForEachRtIntthello(((sO/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_validate.pyRscs@ddlmddlm}d|ffdY}|S(Ni(tvalidate(tWSGIControllertValidatingControllerc seZdZdedddZdZdededddZdededdd e d Z dedd d Z RS( cSsdS(Ns9
Network
((tself((sO/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_validate.pyRstschematformRcSsd|jjdS(NsYour network is: %sR(t form_resulttget(R((sO/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_validate.pytnetwork+scSsdS(Ns
Hello Bad Hello! 
((R((sO/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_validate.pyt view_hello/st post_onlyRcSs t|jS(N(tstrR(R((sO/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_validate.pyRCstauto_error_formattercSs t|jS(N(R R(R((sO/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_validate.pyt hello_customGst hello_recursecSs2|ddkr|jSd|jjdSdS(NtREQUEST_METHODtGETsYour network is: %sR(RRR(Rtenviron((sO/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_validate.pyR#Ls ( RR RRRRRtFalseRRR"R#((R(sO/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_validate.pyRs  '(tpylons.decoratorsRtpylons.controllersR(RR((RsO/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_validate.pytmake_validating_controllers9tTestValidateDecoratorcBsGeZdZdZdZdZdZdZdZRS(cCscddlm}m}t}tj|||||j}t|}t||_ dS(Ni(tControllerWraptSetupCacheGlobal( tpylons.testutilR,R-R*RtsetUpR&RRtapp(RR,R-RR0((sO/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_validate.pyR/Vs     cCs.|jdddd}d|ks*tdS(NtactionRRshttp://pylonshq.com/s%Your network is: http://pylonshq.com/(t post_responsetAssertionError(Rtresponse((sO/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_validate.pyttest_network_validated`s cCs@|jdddd}d|ks*td|ks<tdS(NR1RRsРосси́яs#You must provide a full domain name(R2R3(RR4((sO/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_validate.pyt(test_network_failed_validation_non_asciiescCs.|jdddd}d|ks*tdS(NR1R#Rshttp://pylonshq.com/s%Your network is: http://pylonshq.com/(R2R3(RR4((sO/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_validate.pyttest_recurse_validatedjs cCsBd|jdd<|jjdd|j}d|ks>tdS(NRspylons.routes_dictR1s/hello?hello=1&hello=2&hello=3t extra_environs'hello': [1, 2, 3](R&R0tpostR3(RR4((sO/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_validate.pyt test_helloos cCsTd|jdd<|jjdd|j}d|ks>td|ksPtdS(NRspylons.routes_dictR1s/hello?hello=1&hello=2&hello=hiR8sBad Hello! s.[None, None, u'Please enter an integer value'](R&R0R9R3(RR4((sO/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_validate.pyttest_hello_failedus  cCsfd|jdd<|jjdd|j}d|ks>td|ksPtd|ksbtdS( NR"spylons.routes_dictR1s&/hello_custom?hello=1&hello=2&hello=hiR8sBad Hello! s.[None, None, u'Please enter an integer value']sW

[None, None, u'Please enter an integer value']

(R&R0R9R3(RR4((sO/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_validate.pyttest_hello_custom_failed|s ( RR R/R5R6R7R:R;R<(((sO/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_validate.pyR+Us     (R tformencode.htmlfillRt paste.fixtureRtpaste.registryRt__init__RRtSchemaRRR*R+(((sO/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_validate.pyts   @Pylons-1.0.2/tests/test_units/test_decorator_https.py0000644000175000017500000000653412451647626022535 0ustar benben00000000000000from paste.fixture import TestApp from paste.registry import RegistryManager from routes.middleware import RoutesMiddleware from __init__ import TestWSGIController def make_httpscontroller(): from pylons import request, url from pylons.controllers import WSGIController from pylons.decorators.secure import https class HttpsController(WSGIController): @https('/pylons') def index(self): return 'index page' @https(lambda: url(controller='auth', action='login')) def login2(self): return 'login2 page' @https(lambda: request.url) def secure(self): return 'secure page' @https() def get(self): return 'get page' return HttpsController class TestHttpsDecorator(TestWSGIController): def setUp(self): from pylons.testutil import ControllerWrap, SetupCacheGlobal HttpsController = make_httpscontroller() TestWSGIController.setUp(self) from routes import Mapper map = Mapper() map.connect('/:action') map.connect('/:action/:id') map.connect('/:controller/:action/:id') map.connect('/:controller/:action') app = ControllerWrap(HttpsController) app = SetupCacheGlobal(app, self.environ, setup_cache=False) app = RoutesMiddleware(app, map) app = RegistryManager(app) self.app = TestApp(app) def test_https_explicit_path(self): self.environ['pylons.routes_dict']['action'] = 'index' response = self.app.get('/index', status=302) assert response.header_dict.get('location') == \ 'https://localhost/pylons' self.environ['wsgi.url_scheme'] = 'https' response = self.app.get('/index', status=200) assert 'location' not in response.header_dict assert 'index page' in response def test_https_disallows_post(self): self.environ['pylons.routes_dict']['action'] = 'index' response = self.app.post('/index', status=405) def test_https_callable(self): self.environ['pylons.routes_dict']['action'] = 'login2' response = self.app.get('/login2', status=302) assert response.header_dict.get('location') == \ 'https://localhost/auth/login' self.environ['wsgi.url_scheme'] = 'https' response = self.app.get('/login2', status=200) assert 'location' not in response.header_dict assert 'login2 page' in response def test_https_callable_current(self): self.environ['pylons.routes_dict']['action'] = 'secure' response = self.app.get('/secure', status=302) assert response.header_dict.get('location') == \ 'https://localhost/secure' self.environ['wsgi.url_scheme'] = 'https' response = self.app.get('/secure', status=200) assert 'location' not in response.header_dict assert 'secure page' in response def test_https_redirect_to_self(self): self.environ['pylons.routes_dict']['action'] = 'get' response = self.app.get('/get', status=302) assert response.header_dict.get('location') == \ 'https://localhost/get' self.environ['wsgi.url_scheme'] = 'https' response = self.app.get('/get', status=200) assert 'location' not in response.header_dict assert 'get page' in response Pylons-1.0.2/tests/test_units/test_decorator_https.pyc0000644000175000017500000001306212456572500022663 0ustar benben00000000000000 OTc@scddlmZddlmZddlmZddlmZdZdefdYZ dS( i(tTestApp(tRegistryManager(tRoutesMiddleware(tTestWSGIControllercs\ddlmmddlm}ddlmd|ffdY}|S(Ni(trequestturl(tWSGIController(thttpstHttpsControllercskeZddZfddZfddZdZRS(s/pylonscSsdS(Ns index page((tself((sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_https.pytindexscsddddS(Nt controllertauthtactiontlogin(((R(sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_https.pytscSsdS(Ns login2 page((R ((sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_https.pytlogin2scsjS(N(R((R(sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_https.pyRscSsdS(Ns secure page((R ((sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_https.pytsecurescSsdS(Nsget page((R ((sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_https.pytgets(t__name__t __module__R RRR((RRR(sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_https.pyR s(tpylonsRRtpylons.controllersRtpylons.decorators.secureR(RR((RRRsL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_https.pytmake_httpscontrollers "tTestHttpsDecoratorcBs>eZdZdZdZdZdZdZRS(cCsddlm}m}t}tj|ddlm}|}|jd|jd|jd|jd||}|||j dt }t ||}t |}t ||_dS( Ni(tControllerWraptSetupCacheGlobal(tMappers/:actions /:action/:ids/:controller/:action/:ids/:controller/:actiont setup_cache(tpylons.testutilRRRRtsetUptroutesRtconnecttenvirontFalseRRRtapp(R RRRRtmapR$((sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_https.pyR!s         cCsd|jdd<|jjddd}|jjddksGtd |jd <|jjddd }d|jkstd |kstdS( NR spylons.routes_dictR s/indextstatusi.tlocationshttps://localhost/pylonsRswsgi.url_schemeis index page(R"R$Rt header_dicttAssertionError(R tresponse((sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_https.pyttest_https_explicit_path1s cCs-d|jdd<|jjddd}dS(NR spylons.routes_dictR s/indexR&i(R"R$tpost(R R*((sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_https.pyttest_https_disallows_post=scCsd|jdd<|jjddd}|jjddksGtd |jd <|jjddd }d|jkstd |kstdS( NRspylons.routes_dictR s/login2R&i.R'shttps://localhost/auth/loginRswsgi.url_schemeis login2 page(R"R$RR(R)(R R*((sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_https.pyttest_https_callableAs cCsd|jdd<|jjddd}|jjddksGtd |jd <|jjddd }d|jkstd |kstdS( NRspylons.routes_dictR s/secureR&i.R'shttps://localhost/secureRswsgi.url_schemeis secure page(R"R$RR(R)(R R*((sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_https.pyttest_https_callable_currentMs cCsd|jdd<|jjddd}|jjddksGtd |jd <|jjddd }d|jkstd |kstdS( NRspylons.routes_dictR s/getR&i.R'shttps://localhost/getRswsgi.url_schemeisget page(R"R$RR(R)(R R*((sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_https.pyttest_https_redirect_to_selfYs (RRRR+R-R.R/R0(((sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_https.pyR s    N( t paste.fixtureRtpaste.registryRtroutes.middlewareRt__init__RRR(((sL/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_https.pyts  Pylons-1.0.2/tests/test_units/test_decorator_cache.py0000644000175000017500000002655412451647626022442 0ustar benben00000000000000import os import shutil import time from webtest import TestApp from paste.registry import RegistryManager from beaker.middleware import CacheMiddleware from __init__ import data_dir, TestWSGIController environ = {} sap = None def make_cache_controller(): global sap import pylons from pylons.decorators.cache import beaker_cache, create_cache_key from pylons.controllers import WSGIController, XMLRPCController from pylons.testutil import SetupCacheGlobal, ControllerWrap class CacheController(WSGIController): @beaker_cache(key=None, invalidate_on_startup=True) def test_default_cache_decorator_invalidate(self): pylons.app_globals.counter += 1 return 'Counter=%s' % pylons.app_globals.counter @beaker_cache(key=None) def test_default_cache_decorator(self): pylons.app_globals.counter += 1 return 'Counter=%s' % pylons.app_globals.counter def test_default_cache_decorator_func(self): def func(): pylons.app_globals.counter += 1 return 'Counter=%s' % pylons.app_globals.counter func = beaker_cache(key=None)(func) return func() def test_response_cache_func(self, use_cache_status=True): pylons.response.status_int = 404 def func(): pylons.app_globals.counter += 1 return 'Counter=%s' % pylons.app_globals.counter if use_cache_status: func = beaker_cache(key=None)(func) else: func = beaker_cache(key=None, cache_response=False)(func) return func() @beaker_cache(key=None, type='dbm') def test_dbm_cache_decorator(self): pylons.app_globals.counter += 1 return 'Counter=%s' % pylons.app_globals.counter @beaker_cache(key="param", query_args=True) def test_get_cache_decorator(self): pylons.app_globals.counter += 1 return 'Counter=%s' % pylons.app_globals.counter @beaker_cache(query_args=True) def test_get_cache_default(self): pylons.app_globals.counter += 1 return 'Counter=%s' % pylons.app_globals.counter @beaker_cache(expire=1) def test_expire_cache_decorator(self): pylons.app_globals.counter += 1 return 'Counter=%s' % pylons.app_globals.counter @beaker_cache(expire=1) def test_expire_dbm_cache_decorator(self): pylons.app_globals.counter += 1 return 'Counter=%s' % pylons.app_globals.counter @beaker_cache(key="id") def test_key_cache_decorator(self, id): pylons.app_globals.counter += 1 return 'Counter=%s, id=%s' % (pylons.app_globals.counter, id) @beaker_cache(key=["id", "id2"]) def test_keyslist_cache_decorator(self, id, id2="123"): pylons.app_globals.counter += 1 return 'Counter=%s, id=%s' % (pylons.app_globals.counter, id) def test_invalidate_cache(self): ns, key = create_cache_key(CacheController.test_default_cache_decorator) c = pylons.cache.get_cache(ns) c.remove_value(key) def test_invalidate_dbm_cache(self): ns, key = create_cache_key(CacheController.test_dbm_cache_decorator) c = pylons.cache.get_cache(ns, type='dbm') c.remove_value(key) @beaker_cache(cache_headers=('content-type','content-length', 'x-powered-by')) def test_header_cache(self): pylons.response.headers['Content-Type'] = 'application/special' pylons.response.headers['x-powered-by'] = 'pylons' pylons.response.headers['x-dont-include'] = 'should not be included' return "Hello folks, time is %s" % time.time() @beaker_cache(query_args=True) def test_cache_key_dupe(self): return "Hello folks, time is %s" % time.time() app = ControllerWrap(CacheController) app = sap = SetupCacheGlobal(app, environ, setup_cache=True) app = CacheMiddleware(app, {}, data_dir=cache_dir) app = RegistryManager(app) app = TestApp(app) # This one is missing cache middleware and the cache object to miss on purpsoe bad_app = ControllerWrap(CacheController) bad_app = SetupCacheGlobal(bad_app, environ, setup_cache=False) bad_app = RegistryManager(bad_app) bad_app = TestApp(bad_app) return app, bad_app cache_dir = os.path.join(data_dir, 'cache') try: shutil.rmtree(cache_dir) except: pass class TestBadCacheDecorator(TestWSGIController): def setUp(self): app, bad_app = make_cache_controller() self.app = bad_app TestWSGIController.setUp(self) environ.update(self.environ) def test_no_cache(self): self.assertRaises(Exception, lambda: self.get_response(action='test_default_cache_decorator')) class TestCacheDecorator(TestWSGIController): def setUp(self): app, bad_app = make_cache_controller() self.app = app TestWSGIController.setUp(self) environ.update(self.environ) def test_default_cache_decorator(self): sap.g.counter = 0 self.get_response(action='test_default_cache_decorator_invalidate') response = self.get_response(action='test_default_cache_decorator_invalidate') assert 'text/html' in response.headers['content-type'] assert 'Counter=1' in response response = self.get_response(action='test_default_cache_decorator_invalidate') assert 'Counter=1' in response def test_default_cache_decorator(self): sap.g.counter = 0 self.get_response(action='test_invalidate_cache') response = self.get_response(action='test_default_cache_decorator') assert 'text/html' in response.headers['content-type'] assert 'Counter=1' in response response = self.get_response(action='test_default_cache_decorator') assert 'Counter=1' in response response = self.get_response(action='test_get_cache_decorator', _url='/?param=123') assert 'Counter=2' in response response = self.get_response(action='test_get_cache_decorator', _url="/?param=123") assert 'Counter=2' in response response = self.get_response(action='test_expire_cache_decorator') assert 'Counter=3' in response response = self.get_response(action='test_expire_cache_decorator') assert 'Counter=3' in response time.sleep(2) response = self.get_response(action='test_expire_cache_decorator') assert 'Counter=4' in response response = self.get_response(action='test_key_cache_decorator', id=1) assert 'Counter=5' in response response = self.get_response(action='test_key_cache_decorator', id=2) assert 'Counter=6' in response response = self.get_response(action='test_key_cache_decorator', id=1) assert 'Counter=5' in response response = self.get_response(action='test_keyslist_cache_decorator', id=1, id2=2) assert 'Counter=7' in response response = self.get_response(action='test_keyslist_cache_decorator', id=1, id2=2) assert 'Counter=7' in response response = self.get_response(action='test_get_cache_default', _url='/?param=1243') assert 'Counter=8' in response response = self.get_response(action='test_get_cache_default', _url="/?param=1243") assert 'Counter=8' in response response = self.get_response(action='test_get_cache_default', _url="/?param=123") assert 'Counter=9' in response response = self.get_response(action='test_default_cache_decorator_func') assert 'text/html' in response.headers['content-type'] assert 'Counter=10' in response response = self.get_response(action='test_default_cache_decorator_func') assert 'Counter=10' in response response = self.get_response(action='test_response_cache_func', use_cache_status=True) assert 'Counter=10' in response response = self.get_response(action='test_response_cache_func', use_cache_status=False, test_args=dict(status=404)) assert 'Counter=10' in response def test_dbm_cache_decorator(self): sap.g.counter = 0 self.get_response(action="test_invalidate_dbm_cache") response = self.get_response(action="test_dbm_cache_decorator") assert "Counter=1" in response response = self.get_response(action="test_dbm_cache_decorator") assert "Counter=1" in response self.get_response(action="test_invalidate_dbm_cache") response = self.get_response(action="test_dbm_cache_decorator") assert "Counter=2" in response sap.g.counter = 0 response = self.get_response(action="test_expire_dbm_cache_decorator") assert "Counter=1" in response response = self.get_response(action="test_expire_dbm_cache_decorator") assert "Counter=1" in response time.sleep(2) response = self.get_response(action="test_expire_dbm_cache_decorator") assert "Counter=2" in response def test_cache_key(self): from pylons.decorators.cache import beaker_cache, create_cache_key key = create_cache_key(TestCacheDecorator.test_default_cache_decorator) assert key == ('%s.TestCacheDecorator' % self.__module__, 'test_default_cache_decorator') response = self.get_response(action='test_invalidate_cache') response = self.get_response(action='test_default_cache_decorator') assert 'Counter=1' in response response = self.get_response(action='test_default_cache_decorator') assert 'Counter=1' in response response = self.get_response(action='test_invalidate_cache') response = self.get_response(action='test_default_cache_decorator') assert 'Counter=2' in response def test_cache_key_dupe(self): response = self.get_response(action='test_cache_key_dupe', _url='/test_cache_key_dupe?id=1') time.sleep(0.1) response2 = self.get_response(action='test_cache_key_dupe', _url='/test_cache_key_dupe?id=2&id=1') assert str(response) != str(response2) def test_header_cache(self): response = self.get_response(action='test_header_cache') assert response.headers['content-type'] == 'application/special' assert response.headers['x-powered-by'] == 'pylons' assert 'x-dont-include' not in response.headers output = response.body time.sleep(1) response = self.get_response(action='test_header_cache') assert response.body == output assert response.headers['content-type'] == 'application/special' assert response.headers['x-powered-by'] == 'pylons' assert 'x-dont-include' not in response.headers def test_nocache(self): import pylons sap.g.counter = 0 pylons.config['cache_enabled'] = 'False' response = self.get_response(action='test_default_cache_decorator') assert 'Counter=1' in response response = self.get_response(action='test_default_cache_decorator') assert 'Counter=2' in response pylons.config['cache_enabled'] = 'True' Pylons-1.0.2/tests/test_units/test_templating.py0000644000175000017500000000543612451647626021475 0ustar benben00000000000000import os import re import sys from beaker.cache import CacheManager from beaker.middleware import SessionMiddleware, CacheMiddleware from mako.lookup import TemplateLookup from nose.tools import raises from paste.fixture import TestApp from paste.registry import RegistryManager from paste.deploy.converters import asbool from routes import Mapper from routes.middleware import RoutesMiddleware from nose.tools import raises from __init__ import test_root def make_app(global_conf, full_stack=True, static_files=True, include_cache_middleware=False, attribsafe=False, **app_conf): import pylons import pylons.configuration as configuration from pylons import url from pylons.decorators import jsonify from pylons.middleware import ErrorHandler, StatusCodeRedirect from pylons.error import handle_mako_error from pylons.wsgiapp import PylonsApp root = os.path.dirname(os.path.abspath(__file__)) paths = dict(root=os.path.join(test_root, 'sample_controllers'), controllers=os.path.join(test_root, 'sample_controllers', 'controllers'), templates=os.path.join(test_root, 'sample_controllers', 'templates')) sys.path.append(test_root) config = configuration.PylonsConfig() config.init_app(global_conf, app_conf, package='sample_controllers', paths=paths) map = Mapper(directory=config['pylons.paths']['controllers']) map.connect('/{controller}/{action}') config['routes.map'] = map class AppGlobals(object): pass config['pylons.app_globals'] = AppGlobals() config['pylons.app_globals'].mako_lookup = TemplateLookup( directories=paths['templates'], imports=['from markupsafe import escape'] ) if attribsafe: config['pylons.strict_tmpl_context'] = False app = PylonsApp(config=config) app = RoutesMiddleware(app, config['routes.map'], singleton=False) if include_cache_middleware: app = CacheMiddleware(app, config) app = SessionMiddleware(app, config) if asbool(full_stack): app = ErrorHandler(app, global_conf, **config['pylons.errorware']) if asbool(config['debug']): app = StatusCodeRedirect(app) else: app = StatusCodeRedirect(app, [401, 403, 404, 500]) app = RegistryManager(app) app.config = config return app class TestTemplatingApp(object): def setUp(self): self.app = TestApp(make_app({'cache_dir': os.path.join(os.path.dirname(__file__), 'cache')}, include_cache_middleware=True)) def test_testvars(self): resp = self.app.get('/hello/intro_template') assert 'Hi there 6' in resp def test_template_cache(self): resp = self.app.get('/hello/time_template') resp2 = self.app.get('/hello/time_template') assert resp.body == resp2.body Pylons-1.0.2/tests/test_units/test_decorator_validate.py0000644000175000017500000001127612456607612023157 0ustar benben00000000000000# -*- coding: utf-8 -*- import formencode from formencode.htmlfill import html_quote from paste.fixture import TestApp from paste.registry import RegistryManager from __init__ import TestWSGIController def custom_error_formatter(error): return '

%s

\n' % html_quote(error) class NetworkForm(formencode.Schema): allow_extra_fields = True filter_extra_fields = True new_network = formencode.validators.URL(not_empty=True) class HelloForm(formencode.Schema): hello = formencode.ForEach(formencode.validators.Int()) def make_validating_controller(): from pylons.decorators import validate from pylons.controllers import WSGIController class ValidatingController(WSGIController): def new_network(self): return """
Network
""" @validate(schema=NetworkForm, form='new_network') def network(self): return 'Your network is: %s' % self.form_result.get('new_network') def view_hello(self): return """
Hello Bad Hello! 
""" @validate(schema=HelloForm(), post_only=False, form='view_hello') def hello(self): return str(self.form_result) @validate(schema=HelloForm(), post_only=False, form='view_hello', auto_error_formatter=custom_error_formatter) def hello_custom(self): return str(self.form_result) @validate(schema=NetworkForm, form='hello_recurse') def hello_recurse(self, environ): if environ['REQUEST_METHOD'] == 'GET': return self.new_network() else: return 'Your network is: %s' % self.form_result.get('new_network') return ValidatingController class TestValidateDecorator(TestWSGIController): def setUp(self): from pylons.testutil import ControllerWrap, SetupCacheGlobal ValidatingController = make_validating_controller() TestWSGIController.setUp(self) app = SetupCacheGlobal(ControllerWrap(ValidatingController), self.environ) app = RegistryManager(app) self.app = TestApp(app) def test_network_validated(self): response = self.post_response(action='network', new_network='http://pylonshq.com/') assert 'Your network is: http://pylonshq.com/' in response def test_network_failed_validation_non_ascii(self): response = self.post_response(action='network', new_network='Росси́я') assert 'You must provide a full domain name' in response assert 'Росси́я' in response def test_recurse_validated(self): response = self.post_response(action='hello_recurse', new_network='http://pylonshq.com/') assert 'Your network is: http://pylonshq.com/' in response def test_hello(self): self.environ['pylons.routes_dict']['action'] = 'hello' response = self.app.post('/hello?hello=1&hello=2&hello=3', extra_environ=self.environ) assert "'hello': [1, 2, 3]" in response def test_hello_failed(self): self.environ['pylons.routes_dict']['action'] = 'hello' response = self.app.post('/hello?hello=1&hello=2&hello=hi', extra_environ=self.environ) assert 'Bad Hello! ' in response assert "[None, None, u'Please enter an integer value']" in response def test_hello_custom_failed(self): self.environ['pylons.routes_dict']['action'] = 'hello_custom' response = \ self.app.post('/hello_custom?hello=1&hello=2&hello=hi', extra_environ=self.environ) assert 'Bad Hello! ' in response assert "[None, None, u'Please enter an integer value']" in response assert ("""

[None, None, u'Please enter """ """an integer value']

""") in response Pylons-1.0.2/tests/test_units/test_i18n.py0000644000175000017500000000311412451647626020077 0ustar benben00000000000000# -*- coding: utf-8 -*- import os import sys from paste.fixture import TestApp from __init__ import test_root lang_setup = None def setup_py_trans(): global lang_setup import pylons from pylons.i18n.translation import _get_translator root = os.path.join(test_root, 'sample_controllers') lang_setup = {'pylons.paths': {'root': root}, 'pylons.package': 'sample_controllers'} sys.path.append(test_root) pylons.translator._push_object(_get_translator(None, pylons_config=lang_setup)) glob_set = [] class TestI18N(object): def setUp(self): setup_py_trans() def test_lazify(self): from pylons.i18n.translation import lazify def show_str(st): return '%s%s' % (st, len(glob_set)) lazy_show_str = lazify(show_str) result1 = lazy_show_str('fred') result2 = show_str('fred') assert str(result1) == str(result2) glob_set.append('1') assert str(result1) != str(result2) def test_noop(self): import pylons from pylons.i18n.translation import _, N_, set_lang foo = N_('Hello') class Bar(object): def __init__(self): self.local_foo = _(foo) assert Bar().local_foo == 'Hello' t = set_lang('fr', set_environ=False, pylons_config=lang_setup) pylons.translator._push_object(t) assert Bar().local_foo == 'Bonjour' t = set_lang('es', set_environ=False, pylons_config=lang_setup) pylons.translator._push_object(t) assert Bar().local_foo == u'¡Hola!' assert foo == 'Hello' Pylons-1.0.2/tests/test_units/test_basic_app.py0000644000175000017500000001335412451647626021250 0ustar benben00000000000000import os import re import sys from nose.tools import raises from __init__ import test_root def make_app(global_conf, full_stack=True, static_files=True, include_cache_middleware=False, attribsafe=False, **app_conf): import pylons import pylons.configuration as configuration from beaker.cache import CacheManager from beaker.middleware import SessionMiddleware, CacheMiddleware from nose.tools import raises from paste.registry import RegistryManager from paste.deploy.converters import asbool from pylons.decorators import jsonify from pylons.middleware import ErrorHandler, StatusCodeRedirect from pylons.wsgiapp import PylonsApp from routes import Mapper from routes.middleware import RoutesMiddleware paths = dict(root=os.path.join(test_root, 'sample_controllers'), controllers=os.path.join(test_root, 'sample_controllers', 'controllers')) config = configuration.pylons_config config.init_app(global_conf, app_conf, package='sample_controllers', paths=paths) map = Mapper(directory=config['pylons.paths']['controllers']) map.connect('/{controller}/{action}') map.connect('/test_func', controller='sample_controllers.controllers.hello:special_controller') map.connect('/test_empty', controller='sample_controllers.controllers.hello:empty_wsgi') config['routes.map'] = map class AppGlobals(object): def __init__(self): self.cache = 'Nothing here but a string' config['pylons.app_globals'] = AppGlobals() if attribsafe: config['pylons.strict_tmpl_context'] = False app = PylonsApp(config=config) app = RoutesMiddleware(app, config['routes.map'], singleton=False) if include_cache_middleware: app = CacheMiddleware(app, config) app = SessionMiddleware(app, config) if asbool(full_stack): app = ErrorHandler(app, global_conf, **config['pylons.errorware']) if asbool(config['debug']): app = StatusCodeRedirect(app) else: app = StatusCodeRedirect(app, [401, 403, 404, 500]) app = RegistryManager(app) app.config = config return app class TestWsgiApp(object): def setUp(self): from paste.fixture import TestApp from routes.util import URLGenerator app = make_app({}) self.app = TestApp(app) self.url = URLGenerator(app.config['routes.map'], {}) def test_testvars(self): resp = self.app.get('/_test_vars', extra_environ={'paste.testing_variables': True}) assert re.match(r'^\d+$', resp.body) def test_exception_resp_attach(self): resp = self.app.get('/test_func', expect_errors=True) assert resp.status == 404 @raises(Exception) def test_no_content(self): resp = self.app.get('/test_empty', expect_errors=True) assert 'wontgethre' def test_middleware_cache_obj_instance(self): from paste.fixture import TestApp app = TestApp(make_app({}, include_cache_middleware=True)) resp = app.get('/hello/index') assert resp.cache def test_attribsafe_tmpl_context(self): from paste.fixture import TestApp app = TestApp(make_app({}, attribsafe=True)) resp = app.get('/hello/index') assert 'Hello World' in resp def test_cache_obj_appglobals(self): resp = self.app.get('/hello/index', extra_environ={'paste.testing_variables': True}) assert resp.cache == 'Nothing here but a string' def test_controller_name_override(self): resp = self.app.get('/goodbye/index') assert 'Hello World' in resp class TestJsonifyDecorator(object): def setUp(self): from paste.fixture import TestApp from routes.util import URLGenerator app = make_app({}) self.config = app.config self.app = TestApp(app) self.url = URLGenerator(app.config['routes.map'], {}) def test_basic_response(self): response = self.app.get('/hello/index') assert 'Hello World' in response def test_config(self): import pylons import pylons.configuration as configuration assert pylons.config == configuration.config @raises(AssertionError) def test_eval(self): from paste.fixture import TestApp app = TestApp(make_app(dict(debug='True'))) app.get('/hello/oops', status=500, extra_environ={'paste.throw_errors': False}) def test_set_lang(self): self._test_set_lang('set_lang') def test_set_lang_pylonscontext(self): self._test_set_lang('set_lang_pylonscontext') def _test_set_lang(self, action): response = self.app.get(self.url(controller='i18nc', action=action, lang='ja')) assert u'\u8a00\u8a9e\u8a2d\u5b9a\u3092\u300cja\u300d\u306b\u5909\u66f4\u3057\u307e\u3057\u305f'.encode('utf-8') in response response = self.app.get(self.url(controller='i18nc', action=action, lang='ch')) assert 'Could not set language to "ch"' in response def test_detect_lang(self): response = self.app.get(self.url(controller='i18nc', action='i18n_index'), headers={ 'Accept-Language':'fr;q=0.6, en;q=0.1, ja;q=0.3'}) # expect japanese fallback for nonexistent french. assert u'\u6839\u672c\u30a4\u30f3\u30c7\u30af\u30b9\u30da\u30fc\u30b8'.encode('utf-8') in response def test_no_lang(self): response = self.app.get(self.url(controller='i18nc', action='no_lang')) assert 'No language' in response assert 'No languages' in response def test_langs(self): response = self.app.get(self.url(controller='i18nc', action='langs'), headers={ 'Accept-Language':'fr;q=0.6, en;q=0.1, ja;q=0.3'}) assert "['fr', 'ja', 'en-us']" in response Pylons-1.0.2/tests/test_units/test_decorator_authenticate_form.pyc0000644000175000017500000001111112456572500025213 0ustar benben00000000000000 OTc@sddlZddlZddlZddlmZddlmZddlmZddl m Z ddl m Z m Z ejje dZyddlZejeWnnXejZejejdejfd YZejed Zd e fd YZdS( iN(tSessionMiddleware(tTestApp(tRegistryManager(trequest_config(tdata_dirtTestWSGIControllertsessiont NullHandlercBseZdZRS(cCsdS(N((tselftrecord((sX/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_authenticate_form.pytemits(t__name__t __module__R (((sX/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_authenticate_form.pyRscsfddlm}ddlmddlmddlmd|ffdY}|S(Ni(tWSGIController(tauthenticate_form(t secure_form(trequesttProtectedControllercs/eZfdZfdZRS(csjt_jS(N(tenvironRtauthentication_token(R(RR(sX/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_authenticate_form.pytform'scsjt_dS(Nt Authenticated(RR(R(R(sX/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_authenticate_form.pyt protected+s(R R RR((RRR(sX/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_authenticate_form.pyR&s(tpylons.controllersR tpylons.decorators.secureRtwebhelpers.pylonslibRtpylonsR(R R((RRRsX/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_authenticate_form.pytmake_protected s " tTestAuthenticateFormDecoratorcBs#eZdZdZdZRS(cCsddlm}m}t}tj|||}|||jdt}t|idt }t |}t ||_ dS(Ni(tControllerWraptSetupCacheGlobalt setup_sessionR( tpylons.testutilRRRRtsetUpRtTrueRt session_dirRRtapp(RRRRR$((sX/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_authenticate_form.pyR!3s    cCsmddlm}d|jdd<|jjdd|jdt}|jd ksWt||ksitdS( Ni(tcsrf_detected_messageRspylons.routes_dicttactions /protectedt extra_environt expect_errorsi(RR%RR$tpostR"tstatustAssertionError(RR%tresponse((sX/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_authenticate_form.pyttest_unauthenticated=s  cCsvddlm}d|jdd<|jjdd|j}|j}d|jdd<|jjd d i||j6d|jd t}d |kst d|jdd<|jj d d i||j6d|jd t}d |kst |jjd d i||j6d|jd t}d |ks0t |jjd |jd|d|jd t}d |ksrt dS(Ni(RRspylons.routes_dictR&s/formR'Rs /protectedtparamsR(Rs /protected?t=( RRRR$tgettbodyR)t token_keyR"R+tput(RRR,ttoken((sX/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_authenticate_form.pyttest_authenticatedFs2         (R R R!R-R5(((sX/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_authenticate_form.pyR2s (tloggingtlogging.handlerstostbeaker.middlewareRt paste.fixtureRtpaste.registryRtroutesRt__init__RRtpathtjoinR#tshutiltrmtreet getLoggert my_loggertsetLeveltINFOtHandlerRt addHandlerRR(((sX/home/ben/Programming/Python/pylons/tests/test_units/test_decorator_authenticate_form.pyts&      Pylons-1.0.2/tests/test_units/cache/0000755000175000017500000000000012553621453016744 5ustar benben00000000000000Pylons-1.0.2/tests/test_units/cache/container_dbm/0000755000175000017500000000000012553621453021550 5ustar benben00000000000000Pylons-1.0.2/tests/test_units/cache/container_dbm/d/0000755000175000017500000000000012553621453021773 5ustar benben00000000000000Pylons-1.0.2/tests/test_units/cache/container_dbm/d/d5/0000755000175000017500000000000012553621453022303 5ustar benben00000000000000Pylons-1.0.2/tests/test_units/cache/container_dbm/d/d5/d5fdbd7d787be89ce138c47e2928108a32299635.dbm0000644000175000017500000003000012553620453030315 0ustar benben00000000000000a ^dэh^ ^dэh^(F1437540651.2323329 N(dp1 S'content' p2 S'Counter=2' p3 sS'status' p4 S'200 OK' p5 sS'cookies' p6 NsS'headers' p7 (lp8 (S'Content-Type' p9 S'text/html; charset=utf-8' tp10 a(S'Content-Length' p11 S'0' tp12 a(S'Pragma' p13 S'no-cache' p14 tp15 a(S'Cache-Control' p16 g14 tp17 astp18 .test_dbm_cache_decoratorPylons-1.0.2/tests/test_units/cache/container_dbm_lock/0000755000175000017500000000000012553621453022560 5ustar benben00000000000000Pylons-1.0.2/tests/test_units/cache/container_dbm_lock/7/0000755000175000017500000000000012553621453022726 5ustar benben00000000000000Pylons-1.0.2/tests/test_units/cache/container_dbm_lock/7/78/0000755000175000017500000000000012553621453023164 5ustar benben00000000000000././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000Pylons-1.0.2/tests/test_units/cache/container_dbm_lock/7/78/78de1e289b688271826294912a5be42267dc17d9.lockPylons-1.0.2/tests/test_units/cache/container_dbm_lock/7/78/78de1e289b688271826294912a5be42267dc17d90000755000175000017500000000000012553620453030212 0ustar benben00000000000000Pylons-1.0.2/tests/test_units/cache/container_dbm_lock/d/0000755000175000017500000000000012553621453023003 5ustar benben00000000000000Pylons-1.0.2/tests/test_units/cache/container_dbm_lock/d/d5/0000755000175000017500000000000012553621453023313 5ustar benben00000000000000././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000Pylons-1.0.2/tests/test_units/cache/container_dbm_lock/d/d5/d5fdbd7d787be89ce138c47e2928108a32299635.lockPylons-1.0.2/tests/test_units/cache/container_dbm_lock/d/d5/d5fdbd7d787be89ce138c47e2928108a322996350000755000175000017500000000000012553620453030564 0ustar benben00000000000000Pylons-1.0.2/tests/test_units/cache/cache/0000755000175000017500000000000012553621453020007 5ustar benben00000000000000Pylons-1.0.2/tests/test_units/cache/cache/container_dbm/0000755000175000017500000000000012553621453022613 5ustar benben00000000000000Pylons-1.0.2/tests/test_units/cache/cache/container_dbm/f/0000755000175000017500000000000012553621453023040 5ustar benben00000000000000Pylons-1.0.2/tests/test_units/cache/cache/container_dbm/f/f2/0000755000175000017500000000000012553621453023347 5ustar benben00000000000000././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000Pylons-1.0.2/tests/test_units/cache/cache/container_dbm/f/f2/f246b96c6e5bc523da041adfca8ffd3affc89fbd.dbmPylons-1.0.2/tests/test_units/cache/cache/container_dbm/f/f2/f246b96c6e5bc523da041adfca8ffd3affc89fb0000644000175000017500000003000012553620460031361 0ustar benben00000000000000a %"/Ntэh^C C%"/Ntэh^(F1437540656.3073189 I20 ccopy_reg _reconstructor p1 (cwebhelpers.html.builder literal p2 c__builtin__ unicode p3 V\u000aHello, the time is 2015-07-21 21:50:56.307068\u000a tRp4 tp5 .fredPylons-1.0.2/tests/test_units/cache/cache/container_dbm_lock/0000755000175000017500000000000012553621453023623 5ustar benben00000000000000Pylons-1.0.2/tests/test_units/cache/cache/container_dbm_lock/2/0000755000175000017500000000000012553621453023764 5ustar benben00000000000000Pylons-1.0.2/tests/test_units/cache/cache/container_dbm_lock/2/22/0000755000175000017500000000000012553621453024207 5ustar benben00000000000000././@LongLink0000000000000000000000000000016000000000000011212 Lustar 00000000000000Pylons-1.0.2/tests/test_units/cache/cache/container_dbm_lock/2/22/22b5697111b9eaf491d2f96c851cd9286eb5426f.lockPylons-1.0.2/tests/test_units/cache/cache/container_dbm_lock/2/22/22b5697111b9eaf491d2f96c851cd9286e0000755000175000017500000000000012553620460030611 0ustar benben00000000000000Pylons-1.0.2/tests/test_units/cache/cache/container_dbm_lock/f/0000755000175000017500000000000012553621453024050 5ustar benben00000000000000Pylons-1.0.2/tests/test_units/cache/cache/container_dbm_lock/f/f2/0000755000175000017500000000000012553621453024357 5ustar benben00000000000000././@LongLink0000000000000000000000000000016000000000000011212 Lustar 00000000000000Pylons-1.0.2/tests/test_units/cache/cache/container_dbm_lock/f/f2/f246b96c6e5bc523da041adfca8ffd3affc89fbd.lockPylons-1.0.2/tests/test_units/cache/cache/container_dbm_lock/f/f2/f246b96c6e5bc523da041adfca8ffd3aff0000755000175000017500000000000012553620460031535 0ustar benben00000000000000Pylons-1.0.2/tests/test_units/__init__.pyc0000644000175000017500000001017712456572500020163 0ustar benben00000000000000 OTc@s$ddlZddlZddlZddlmZddlmZddlmZm Z ej j ej j e ZyejeWnnXej j ej j e Zej j ej j eZej jedZej jedefdYZdefd YZdS( iN(tTestCase(t quote_plus(tloadstdumpst test_filestTestMiddlewarecBseZdZdZRS(cCs ||_dS(N(tapp(tselfR((s@/home/ben/Programming/Python/pylons/tests/test_units/__init__.pyt__init__scCs=d|kri|ds  c Cst|ts3t|ts3t|ts3ttdd}tjtddd|d|}|jjddt |d||_ }tj |j S( NR1sapplication/jsontidttestR4R.R&R'( t isinstancetlistttupleRtAssertionErrortjsonRRR/RRRR3(RR4R5R6R7R((s@/home/ben/Programming/Python/pylons/tests/test_units/__init__.pytjsonreqGs N(( R RR!R#R-R0RR8R@(((s@/home/ben/Programming/Python/pylons/tests/test_units/__init__.pyR!s     (R?tostsystunittestRturllibRt xmlrpclibRRtpathtdirnametabspatht__file__tdata_dirtshutiltrmtreetcur_dirt pylons_roottjoint test_roottappendtobjectRR(((s@/home/ben/Programming/Python/pylons/tests/test_units/__init__.pyts    Pylons-1.0.2/tests/test_units/test_templating.pyc0000644000175000017500000001001712456572500021620 0ustar benben00000000000000 OTc@s ddlZddlZddlZddlmZddlmZmZddlm Z ddl m Z ddl m Z ddlmZddlmZdd lmZdd lmZddl m Z dd lmZeeeed Zd efdYZdS(iN(t CacheManager(tSessionMiddlewaretCacheMiddleware(tTemplateLookup(traises(tTestApp(tRegistryManager(tasbool(tMapper(tRoutesMiddleware(t test_rootc Kscddl}ddlj}ddlm}ddlm} ddlm} m} ddl m } ddl m } t jjt jjt}tdt jjtdd t jjtdd d t jjtdd }tjjt|j}|j||d dd |td |dd }|jd||dR'R(R-R)R+tTrueR=(tself((sG/home/ben/Programming/Python/pylons/tests/test_units/test_templating.pytsetUpEscCs(|jjd}d|ks$tdS(Ns/hello/intro_templates Hi there 6(R=tgettAssertionError(RCtresp((sG/home/ben/Programming/Python/pylons/tests/test_units/test_templating.pyt test_testvarsHscCs@|jjd}|jjd}|j|jks<tdS(Ns/hello/time_template(R=REtbodyRF(RCRGtresp2((sG/home/ben/Programming/Python/pylons/tests/test_units/test_templating.pyttest_template_cacheLs(RRRDRHRK(((sG/home/ben/Programming/Python/pylons/tests/test_units/test_templating.pyR?Ds  (R'treR.t beaker.cacheRtbeaker.middlewareRRt mako.lookupRt nose.toolsRt paste.fixtureRtpaste.registryRtpaste.deploy.convertersRtroutesRtroutes.middlewareR t__init__R RBR5R>R3R?(((sG/home/ben/Programming/Python/pylons/tests/test_units/test_templating.pyts   0Pylons-1.0.2/tests/conftest.py0000644000175000017500000000064012451647626015706 0ustar benben00000000000000import sys import os import shutil import pkg_resources here = os.path.dirname(__file__) base = os.path.dirname(here) sys.path.append(here) sys.path.insert(0, base) here = os.path.dirname(__file__) pkg_resources.working_set.add_entry(base) if not os.environ.get('PASTE_TESTING'): output_dir = os.path.join(here, 'test_webapps', 'output') if os.path.exists(output_dir): shutil.rmtree(output_dir) Pylons-1.0.2/tests/__init__.pyc0000644000175000017500000000021412456572500015751 0ustar benben00000000000000 OTc@sdS(N((((s5/home/ben/Programming/Python/pylons/tests/__init__.pytsPylons-1.0.2/LICENSE0000644000175000017500000000543312451650053013343 0ustar benben00000000000000Copyright (c) 2005-2015 Ben Bangert, James Gardner, Philip Jenvey and contributors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. The name of the author or contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 THE AUTHOR OR CONTRIBUTORS 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. ------------------------------------------------------------------------------- ALL TEMPLATES GENERATED ARE COVERED UNDER THE FOLLOWING LICENSE: Copyright (c) 2005-2015 Ben Bangert, James Gardner, Philip Jenvey and contributors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following condition is met: The name of the author or contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 THE AUTHOR OR CONTRIBUTORS 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. Pylons-1.0.2/UPGRADING0000644000175000017500000000354412451647626013616 0ustar benben00000000000000Upgrading your Pylons Project ============================= Pylons projects should be updated using the paster command create. In addition to creating new projects, paster create when run over an existing project will provide several ways to update the project template to the latest version. Using this tool properly can make upgrading a fairly minor task. For the purpose of this document, the project being upgraded will be called 'demoapp' and all commands will use that name. Running paster create to upgrade -------------------------------- You'll first need to cd to the directory *above* your projects main directory. The main directory is the one that contains your setup.py, setup.cfg, and development.ini files. .. code:: bash /home/joe/demoapp $ cd .. /home/joe $ Then run paster create on the project directory: .. code:: bash /home/joe $ paster create demoapp -t pylons paster will prompt you on how to handle conflicts and updates to the existing project files. The options let you (hit the key in the parens to perform the operation): (d)iff them, and show you the changes between your projects file and the one that has changed in Pylons (b)ackup the file, and copy the new version into its place. The old one will end in .bak (y)es to overwrite the existing file with the new one. *Not recommended* since you will then have no way to see your existing one, unless you have seen the diff first and know there is no changes you're losing. (n)o to overwrite, and just keep your existing file. Also safe if you know that nothing has changed. It's recommended when upgrading your project that you always look at the diff first to see whats changed. Then either overwrite your existing one if you are not going to lose changes you want, or backup yours and write the new one in. You can then manually compare and add your changes back in. Pylons-1.0.2/CHANGELOG0000644000175000017500000012145712553621417013562 0ustar benben00000000000000Pylons Changelog ================ 1.0.2 (July 21, 2015) * In the event of a NilAccept for the language, request.languages() would throw an AttributeError exception. Fixes #24. * Encode Location HTTP header in redirect responses in UTF-8. Per RFC 3987. Refers to #15. * Remove "Post Traceback" as it was a possible XSS vector with prior versions of WebError, and the PylonsHQ site is no longer in existence to support them. 1.0.1 (August 13th, 2012) * No changes since RC1. 1.0.1RC1 (December 12, 2011) * WARNING: pylons.lib.decorators has had two functions removed: ``determine_response_charset`` and ``encode_formencode_errors``. * Updated dependencies to latest versions of Paste, PasteDeploy, and compatibility for the latest WebOb 1.2 betas. * authenticate_form allows for GET. Patch by Domen Kožar. * jsonify now properly sets charset to utf-8. * Add ability for jsonify to handle objects with a __json__ attribute using custom JSONEncoder class similar to TG2. Patch by Bob Farrell. * Added ability for __before__ to reference a callable function. Patch contributed by mverdone. * Pulled in JSON-RPC support from agentultra's pylons fork. * Apply patch for proper pylons.__version__ under Windows. Contributed by Christoph Zwerschke. * Utilize MarkupSafe for faster HTML escaping. * Fix signed cookies by using standard base64 alphabet, and prevent timing attacks on signature comparison. * Added setup of app_globals and config to Pylons config.init_app to ensure as long as the Pylons application is loaded, the app_globals and config will be appropriately initialized. * Documentation updates. 1.0 (May 27, 2010) * Minor tweak to allow proper importing of pylons. 1.0RC1 (March 1, 2010) * Switched to using Routes 1.12 with support for no longer using the odd routes singleton. * Removed pylons.middleware.StaticJavascripts, this is not used anymore. * Added more unit tests. 1.0b1 (February 5, 2010) * Removed CacheMiddleware. cache object is now setup as an attribute on the app_globals object for use where needed. * WARNING: config only supports dict access * WARNING: Method arguments no longer assigned to 'tmpl_context' by default. * WARNING: Changed default to strict_tmpl_context. * WARNING: Removed legacy pylons.c and pylons.g globals. * WARNING: Removed legacy pylons.database module. * WARNING: Removed legacy pylons.config module. * WARNING: Removed Buffet options, setup, and legacy render/render_response function from pylons.templating. This also means config no longer accepts the add_template_engine option. * WARNING: Removed legacy redirect_to function. * WARNING: @https decorator no longer accepts url_for-like arguments. * Add a "paster routes" command. This prints the mapper, which from Routes 1.12 onwards gives sensibly formatted output. * Fix unit tests on Windows * Prepare for Routes 1.12, ensure tests don't assume implicit routing 0.10 (May 27, 2010) * Fix legacy warning replacement. 0.10RC1 (March 1, 2010) * No changes to Pylons core since b1. 0.10b1 (February 5, 2010) * redirect_to is now deprecated, use redirect(url(*args, **kwargs)) instead. * url_for like args to the https decorator are now deprecated, pass it a url or a callable returning a url instead. * Changed 1.0 deprecated pylons.c, pylons.g, pylons.buffet instances to throw deprecation warnings. * Fixed etag_cache matching when the If-None-Match header contains a comma separated list of etags. Fixes #557. Thanks magicbronson. * Added tests for restcontroller with sub-directory, and fixed generated unit tests. Patches supplied by Michael van Tellingen, fixes #571. * Retain the original controller exception when thrown under environ['pylons.controller.exception'] for use in the error controller. * Fixed bug with unit tests running the app load twice during testing. Fixes #620. * Updated project templates to use actual config instance, rather than the StackedObjectProxy classes. * Changed PylonsConfig to be dict subclass, rather than DispatchingConfig subclass. 0.9.7 (February 23, 2009) * WARNING: A new option is available to determine whether or not an actions arguments should be automatically attached to 'c'. To turn off this implicit behavior in environment.py: config['pylons.c_attach_args'] = False This is set to True by default. * WARNING: Fixed a minor security hole in the default Pylons error page that could result in an XSS security hole. * WARNING: Fixed a security hole in the default project template to use the StaticURLParser to ensure arbitrary files can't be sent. * WARNING: Refactored PylonsApp to remove legacy PylonsApp, moved session/cache and routes middleware into the project template. This will require projects to be updated to include those 3 middleware in the projects middleware.py. * Added redirect, preferred over redirect_to. Takes an explicit url instead of url_for like arguments * Changed to using WebTest instead of paste.fixture for app testing. * Added render_mako_def to render def blocks within a mako template. * Changes to cache_decorator and cached_template to support Beaker API changes in version 1.1. 1.0.3 is still supported. * Fix HEAD requests causing an Exception as if no content was returned by the controller. Fixes #507. Thanks mvtellingen, Petr Kobalicek. * Fix a crash when returning the result of ``etag_cache`` in a controller. Fixes #508. * "response" flag has been removed from pylons.decorators.cache.beaker_cache, as it sends all headers along unconditionally including cookies; additionally, the flag was taking effect in all cases previously so prior versions of beaker_cache are not secure. In its place, a new option "cache_headers" is provided, which is a tuple of specific header names to be cached. It defaults to ('content-type','content-length'). * "invalidate_on_startup" flag added to beaker_cache, which provides a "starttime" to the cache such that when the application is started or restarted, the cache entry is invalidated. * Updating host to use 127.0.0.1 for development binding. * Added option to specify the controller name with a __controller__ variable in the controller's module. This name will be used for the controller class rather than the default naming scheme. * setup.py egg_info now restores projects' paster_plugins.txt, allowing paster shell to work again after the egg-info directory was lost. fixes #282. Thanks sevkin. * The paste_deploy_config.ini_tmpl template is now located at package/config/deployment.ini_tmpl for new projects. * Project's default test fixtures no longer hardcode test.ini; the ini file used can now be specified via the nosetests --with-pylons argument (defaults to test.ini in setup.cfg). fixes #400. * @validate now defaults to translating FormEncode error messages via Pylons' gettext catalog, then falls back to FormEncode's. fixes #296. Thanks Max Ischenko. * Fixed SQLAlchemy logging not working in paster shell. Fixes #363. Thanks Christoph Haas. * Added optionally engine initialization, to prevent Buffet from loading if there's no 'buffet.template_engines' in the config. * Updated minimal template to work with Tempita and other new templating changes. * Fixed websetup to parse location config file properly when the section isn't 'main'. Fixes #399. * Added default Mako filter of escape for all template rendering. * Fixed template for Session.remove inclusion when using SA. Fixed render_genshi to properly use fragment/format options. Thanks Antonin Enfrun. * Remove template engine from load_environment call. * Removing template controller from projects. Fixes #383. * Added signed_cookie method to WebOb Request/Response sub-classes. * Updated project template to setup appropriate template loader and controller template to doc how to import render. * Added documentation for render functions in pylons.templating. * Adding specific render functions that don't require Buffet. * Added forward controller.util function for forwarding the request to WSGI apps. Fixes #355. * Added default input encoding for Mako to utf-8. Suggested in #348. * Fixed paster controller to raise an error if the controller for it already exists. Fixes #279. * Added __init__.py to template dir in project template if the template engine is genshi or kid. Fixes #353. * Fixed jsonify to use application/json as its the proper mime-type and now used all over the net. * Fixed minimal template not replacing variables properly. Fixes #377. * Fixed @validate decorator to no longer catch exceptions should they be raised in the action that is supposed to display a form. Fixes #374. * Fixed paster shell command to no longer search for egg_info dir. Allows usage of paster shell with installed packages. Suggested by Gavin Carothers. * Added mimetype function and MIMETypes class for registering mimetypes. * WARNING: Usage of pylons.Response is now deprecated. Please use pylons.response instead. * Removed use of WSGIRequest/WSGIResponse and replaced with WebOb subclasses that implement methods to make it backwards compatible with the Paste wsgiwrappers. * Fixed missing import in template controller. * Deprecated function uses string substitution to avoid Nonetype error when Python optimization is on. Fixes #334. * E-tag cache no longer returns Content-Type in the headers. Fixes #323. * XMLRPCController now properly includes the Content-Length of the response. Fixes #310, thanks Nicholas. * Added SQLAlchemy option to template, which adds SQLAlchemy setup to the project template. * Switched project templating to use Tempita. * Updated abort/redirect_to to use appropriate Response object when WebOb is used. * Updated so that 404's properly return as Response objects when WebOb is in use instead of WSGIResponse. * Added beaker_cache option to avoid caching/restoring global Response values that were present during the first cache operation. * Adding StatusCodeRedirect to handle internal redirects based on the status code returned by the app. This replaces the use of ErrorDocuments in projects. * Refactored error exceptions to use WebError. * WSGIController now uses the environ references to response, request, and the c object for higher performance. * Added optional use of WebOb instead of paste.wsgiwrapper objects. * Fixed bug with beaker_cache defaulting to dbm rather than the beaker cache app-wide default. * The --with-pylons nose plugin no longer requires a project to have been registered with setuptools to work. * The config object is now included in the template namespace. * StaticJavascripts now accepts keyword arguments for StaticURLParser. Suggested by Marcin Kasperski. * Fix pylons.database.AutoConnectHub's doInTransaction not automatically connecting when necessary. Fixes #327. 0.9.6.1 (September 27th, 2007) * Fixed validate decorator to resume pre-0.9.6 behavior of only validating POST requests by default. Added option to validate during GET as well and a recursion avoidance check to prevent validate from running more than once. * WARNING: Fixed a security hole allowing private controller methods (those beginning with an underscore) to be accessed from the outside. Found by Tomasz Nazar. * Added nose plugin '--with-pylons=test.ini' option to load the Pylons app before scanning for unit tests. This enables Pylons apps to be unit tested with doc tests. * PylonsBaseWSGIApp now caches controller lookup and the effective logging level for a little better performance. 0.9.6 (September 8th, 2007) * Updated requirements for newer WebHelpers for SQLAlchemy 0.4 compatibility. Fixes #300. * Fixed pylons.templating to not pull session objects if there are none in use for the request. Thanks Bob Ippolito. * Catch UnicodeEncodeErrors when finding the Controller action method and fail gracefully. Thanks max. Fixes #298. * Allow passing of a state keyword to the validate decorator for the to_python methods. Fixes #297. * paster shell now configures logging from the config file, like paster serve and setup-app. This can be disabled via the -q option. Thanks Yannick Gingras. 0.9.6rc3 (August 18, 2007) * Fixed controllers.core to allow responses of None (empty bodies). Logs a message indicating the response was empty. * pylons.helpers has been moved to pylons.controllers.util, to differentiate between controller utility functions and projects' helpers modules. * Fixed non-basestring/generator/WSGIResponse objects returned from Controllers not being set as the response content. Thanks Alex Conrad. * development.ini now configures the app's Logger level to DEBUG by default. Thanks Christoph Haas 0.9.6rc2 (August 2, 2007) * Projects now include a MANIFEST.in file: it directs distutils to recursively include all files in the project's public/ and templates/ dir. This fixes these dirs not being included in dists unless they were checked into an RCS recognized by setuptools. This is at the expense of dists now globbing all files in those dirs (even those not checked into your RCS). Thanks Christoph Haas. * Fixed the validate decorator not setting c.form_errors in certain circumstances. Thanks max. Fixes #286. * email_to lines commented out in development.ini and test.ini files to avoid emails being sent to a non-existent address by mistake. If an error occurs it is logged but no email is sent unless email_to is specified. * [paste.app_factory] entry points changed to point to the actual make_app() function to make it simpler for someone to work out how Pylons works (tests updated accordingly too). * All use of the ez_setup module is now tested by an ImportError to make Pylons compatible with Buildout. Note: Tags and releases should be made using an svn export and an svn add to ensure a real copy of the ez_setup module is included and not just an svn:external so that the module is tied to time of the release. * More full-featured README.txt included. * Updated beaker_cache to cache global response cookies/status/headers. Fixes #280. * Fixed missing abort name import in restrict rest decorator. Fixes #281. * Added cheetah as a supported template language for template_engine option. * Fixed public/ and templates/ directories not being created with paster create. 0.9.6rc1 (July 15, 2007) * Fixed cookie header addition to use add instead of append. Thanks to anonymous patcher. Fixes #268, again. * Added ability to pass _code option to specify the status code type for redirect_to. * Fixed redirect_to to not copy all headers into redirect for old _response usage. Fixes #268. * WARNING: By default, the Pylons request object now returns unicode parameter (pylons.GET/POST/params) values (and assumes those parameters were sent to Pylons as utf-8). Unicode parameters can cause major problems if your application is not setup to handle unicode. To disable unicode parameters (0.9.5 default behavior), add the following to your load_environment function (0.9.6 syntax): config['request_options']['charset'] = None or, if still using the deprecated pre-0.9.6 pylons.config syntax, add: request_settings = pylons.config.request_defaults.copy() request_settings['charset'] = None return pylons.config.Config(tmpl_options, map, paths, request_settings=request_settings) * WARNING: Template names beginning with a / (or the OS's path separator) will now result in the name not having the separator's replaced with '.'s for the template engine. This shouldn't affect most projects as they usually assume a dot notation will be used with dot notation template engines (Kid, Genshi, etc.). This change allows template engines that can take filename paths to function properly. Fixes #233. * WARNING: The pylons.util.get_prefix(environ) function is deprecated. Please use: environ.get('SCRIPT_NAME', '') instead (the get_prefix function is used in the default ErrorController). Fixes #243. * WARNING: The paths dictionary's 'root_path' has moved to the less redundant 'root'. * Fixed the Error Documents/EvalException css referencing non-existent images. Thanks Shannon -jj Behrens. Fixes #238. * Added ability to pass _code option to specify the status code type for redirect_to. * Fixed redirect_to to not copy all headers into redirect for old _response usage. Fixes #268. * Added logging statements throughout Pylons code, added logging setup to default template. Fixes #98. * Refactored global response to be setup in wsgiapp along with the other globals. Updated WSGIController to copy in global response headers and cookies into a WSGI app's output. * Added global pylons.response object. Thanks Shannon -jj Behrens and Damjan Georgievski. Fixes #268 and #201. * Updated default project template files for new configuration layout. Options to handle config now just in environment.py, and middleware.py handling just middleware. Fixes #203. * Removing mako tests, as its now the default. Default test changed from Myghty to Mako. * Changing default templating to mako. * Added the https decorator. It requires an action to be loaded via https. Patch by ido. Fixes #241. * Added upgrade instructions, and posted a copy on the wiki. Fixes #230. * Added deprecation warnings for usage of the Pylons Controller class, all controllers should inherit from WSGIController instead. Fixes #239. * Removed deprecated attach_locals function from Controller class. * Added an authenticate_form decorator for use with WebHelpers' secure_form_tag functions for preventing CSRF attacks. Original patch by David Turner. Fixes #157. * Fix Buffet's include_pylons_variables not being upheld. Thanks Jonathan LaCour. * The validate decorator now accepts extra keyword arguments (**htmlfill_kwargs) to pass along to formencode's htmlfill.render function. * Removed POST-only restriction on validate decorator, now handles GET requests. No form arg required during a GET request, which will run the current action with c.form_errors set to the errors. Fixes #246. * Added PylonsConfig, which gets accessed as pylons.config dict. Contains all the merged ini options, in addition to the Config options such as 'routes.map', 'pylons.paths', 'buffet.template_options', etc. Check the pylons.config docs on PylonsConfig for dict keys populated by it. * Split up resolution stages in wsgiapp, so that controller lookup is a separate function making it easier to subclass. PylonsApp now takes a base_wsgi_app argument which is then used for the BaseWSGIApp instead of the one from wsgiapp.py. * Added mako template render tests. * Added storage of the action func used to handle a call, for later code that might need a reference to the action that originally handled the request. Fixes #253. * Updated config object to optionally take a single merged conf dict, updated project templates to pass around the single merged conf dict. * Changed project template to use new Beaker session keys. * Changed default routing for raw template matching to not unicode decode the route argument. Fixes #242. * Catch any exceptions raised by template engine entry points and emit a warning instead of crashing. Thanks markbradley. Fixes #249 * Fixed the validate decorator not working with formencode's CompoundValidators when variable_decode=False. Fixes #209. * Fixed the validate decorator failing with a KeyError when no value is specified to validate against for separate validators (as opposed to a schema). Reported by Graham Stratton. * Fixed paster shell not merging app_conf and global_conf into the main CONFIG dict namespace. Original patch by David Smith. Fixes #244. * Added logging to decorators. Refs #98. * Fixed paster restcontroller to test for lib.base and only add that import statement when its present. This fixes the restcontroller template when used with minimal Pylons project templates. Fixes #237. * Fixed the EvalException debugger showing broken links and buttons when the app's ErrorController was broken (such as when BaseController's __before__ raises an exception). Suggested by Ian Bicking. Fixes #228. * paster create now accepts a 'template_engine' option to setup the new project's default template engine. E.g. to create a new project that uses Genshi by default, use: paster create --template=pylons mygenshiproj template_engine=genshi Suggested by Ian Bicking. Fixes #141. * Fixed the validate decorator triggering the following error with FormEncode>=0.7 and non-ascii rendered form content: UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 10: ordinal not in range(128) the form was passed in as an encoded string, but some data or error messages were unicode strings; the form should be passed in as a unicode string Reported by Christoph Haas. * HTTPExceptions are now converted to Response objects (for __after__), making the httpexceptions middleware no longer required. * Added Warning to jsonify to warn about cross-site attacks when returning a list as the outer-most element to jsonify. Fixes #232. * Fixed beaker_cache decorator to take optional keyword arguments intended for the backend cache container (such as url for memcached). * Fixed paster controller assuming the minimal template was in use when the lib.base module existed but raised an exception. * Fixed bug in XMLRPC Controller not setting proper Content-Type. Fixes #236. * Added the '-d' ('--disable-ipython') option to paster shell for disabling IPython. * Allow creation of controllers named 'setup' via paster controller. Reported by Matt Good. * Added support for generic arguments to SQLAlchemy's create_engine of the form sqlalchemy.* from the PasteDeploy config file. 0.9.5 (Apr 11th, 2007) * Fixed a Python 2.3 incompatibility with paster shell, causing the Exception: File "Pylons-0.9.5-py2.3.egg/pylons/commands.py", line 357, in command locs.update([(name, getattr(base, name)) for name in base_public]) AttributeError: keys * Fixed paster shell breaking for projects where the base package was not the first package listed in top_level.txt. Patch from Alberto Valverde. Fixes #229. * Fixed doc references to config['app_conf']. Fixes #116. * Changed `get_engine_conf` to properly evaluate sqlalchemy echo statement when its 'debug'. Fixes #226. * make_session and create_engine now accept keyword arguments to pass to SQLAlchemy's create_engine. * make_session now accepts the keyword argument 'session_kwargs' to pass to SQLAlchemy's create_session. * Fixed _inspect_call to call function with keyword arguments instead of list args. Corrects issue with action defaults that caused the value for the latter args to be in the wrong spots. Spotted by Topher. Fixes #223. * Added the allow_none option (passed to xmlrpc.dumps) to XMLRPCController. Suggested by Jaroslaw Zabiello. * Updated XMLRPC Controller with patch for name lookup and additional unit tests for the patch. Fixes #216. * Updated docs for validate decorator to more clearly illustrate what the post_only args apply to. Fixes #221. * Added ability to return strings in the WSGIController. Fixes #218. * Added lazy i18n translation functions. Patch from David Smith. Fixes #181. * Added fix for XMLRPCController system.methodHelp function and unit test. Patch and unit test submitted by Graham Higgins. * Fixed bug in validate decorator with new UnicodeMultiDict response content not properly retaining form content as unicode for formencode's htmlfill. * Fixed bug in XMLRPC Controller with xmlrpclib Faults not being properly transformed into a WSGI response within the controller. * WARNING: Pylons now requires the decorator module: it no longer packages it as pylons.decorator. Code relying on the pylons.decorator.decorator function will trigger a deprecation warning and should be changed to use decorator.decorator. * WARNING: pylons.h was deprecated for using projects' lib.helpers module directly in 0.9.3. pylons.h is now formally deprecated (emits DeprecationWarnings). Projects still accessing pylons.h must change the following import: from pylons import h to: import MYPROJ.lib.helpers as h * pylons.jsonify and pylons.Controller references have been deprecated (they are misplaced references). They continue to be available at pylons.decorators.jsonify and pylons.controllers.Controller, as they always have been. * Updated templating Buffet to recognize format parameter and properly pass it to the template engine. * Updated LICENSE for new year and to indicate license covering templates generated. Fixes #188. * Interactive debugger now supports Mako. After r1780 if you are using a custom theme you will need to change '%(myghty_data)s' to '%(template_data)s' in your template. If you are using JavaScript the tab id is now "template_data". * Fixed bug in WSGIController with private function attempts not returning a valid WSGI response. * Added full unit test coverage of cache decorator. * Adding messages binary file, enabling i18n unit tests. Updating pylons.i18n to import LanguageError. Fixes #193. * Adding i18n tests, not active yet as they're waiting on a binary file from a patch. Refs #193. * Updated tests so that they now work with nose, removing py.test requirement. * Switching config setup to load keys into main config dict with app_conf and global_conf keys set for any code looking for those keys. Fixes #116. * PylonsInstaller is now the default paste.app_install entry point for new projects: this makes Cheetah no longer required for the paster make-config command. (Thanks Alexander Schremmer, Ian Bicking) * Added custom redirect_to function in pylons.helpers that will take an optional _response arg to pull headers and cookies out for preservation during a redirect. Fixes #136. * Changed config.Config.__init__ to take all options as keyword args so unused args can be skipped. Fixes #162. * The request object can now automatically decode GET/POST/params vars to unicode, when its charset attribute is set. * Added a new request_settings keyword arg to Config's constructor. Allows setting the default charset and errors values of of the request object. * Deprecated Config constructor's default_charset keyword arg. Use Config's response_settings keyword arg instead. * Fixed paster controller to test for lib.base and only add that import statement when its present. This fixes the controller template when used with minimal Pylons project templates. Fixes #140 and fixes #139. * Fixed the paster shell error: KeyError: 'pylons.routes_dict' when calling app.get and app.post. * Fixed paster shell not working on projects with names containing hyphens. * Fixed the config directive 'sqlalchemy.echo' set to False being interpreted as True. Patch by Alex Conrad. * Fixed paster shell not restoring CONFIG['global_conf']. 0.9.4.1 (Jan. 5th, 2007) * Added restcontroller command that generates a RESTful controller template and provides the appropriate map.resource command to add. Suggested by Matthew Scott. * Fixed SQLObject pylons.database.PackageHub error: exceptions.NameError: global name 'CONFIG' is not defined * Fixed pylons.database.session_context not working outside of requests (such as in websetup.py). * Updated template options config to take template options for multiple engines for less binding to Myghty. * Fixed paster shell incorrectly importing the the tuple (model,) as the model object. 0.9.4 (Dec. 29th, 2006) * WARNING: Removed the lang_extract and lang_compile commands. They used pygettext.py and its associated msgfmt.py, which lacked the ability to extract ngettext style function calls and had issues with unicode strings. The new I18NToolBox project aims to provide this functionality (and more) via the gettext command line utilities. http://i18ntoolbox.ufsoft.org * All Pylons special objects are now available within paster shell (not just h and g). * WARNING: Myghty's allow_globals config var has changed, causing the following when running pre-compiled templates: Error(TypeError): do_run_component() takes exactly 13 non-keyword arguments (5 given) Delete the compiled Myghty templates directory (specified by cache_dir or myghty_data_dir in the config file) to resolve the error. * Changed i18n functions in templates to use proxy objects so that using set_lang in a template works right. Fixes #153. * Now allowing any template plugin to overwrite global PYLONS_VARS (such as c, g), not just pylonsmyghty. * Adding SQLAlchemy support to the database.py file. Saves the session engine to g to maintain it during the apps lifetime. Uses SessionContext plugin for management of the current session. * Updated config object so that init_app can take an optional template engine argument to declare the default template engine. * Updated Myghty plugin to use extra_vars_func when passed in. * Fixed Buffet to use extra_vars_func properly. * Fixed the validate decorator when there are validation errors and variable_decode=True: now passing the original params to htmlfill.render instead of the varable_decode'd version. Patch by FlimFlamMan. * Added ungettext function for use with pluralized i18n, and the N_ function (gettext_noop) to mark global strings for translation. Added ungettext, N_ and translator objects to be globals for templates. Refs #126. * WARNING: The localization function '_' now uses ugettext (returns unicode strings) instead of gettext. To preserve the old behavior, append the following line to your project's lib.base and lib.helpers imports: from pylons.helpers import gettext as _ * Pylons special objects are now available within the interactive debugger (deprecating _attach_locals). * Added setup-app run before unit tests run so that webapp has proper setup tasks handled. Fixes #113. * Added paste.deploy.CONFIG setup to middleware.py, websetup.py and testing files in the Pylons project templates. Closes #112. * Added security policy doc to index for use as Pylons security policy. Closes #91. * Improved the repr() of the c context object to show attributes. * Set environ['paste.testing_variables'] whenever that key is available, not just in testing mode. * Added capability to have an action be a generator function. * Added introspection capability to XMLRPCController and signature checking. * Updated Controller to use additional arg lookup scheme so that the source of the function args for _inspect_call can be easily overridden. * Updated RPCController, renamed to XMLRPCController. XMLRPCController now functions properly and will automatically return proper xmlrpc responses. * Added test configuration ini file to default template. Closes #114. * Fixed problem with pylons.database.PackageHub.__get__ raising errors other than AttributeError when the database isn't configured. Added new UnconfiguredConnectionError exception, instead of just KeyError or TypeError (depending on what part of the configuration failed). * Fixed default g init, since bare object has no init method. Reported by Ian Bicking. * Fixed issue with SQLObject method override having wrong name. Reported by climbus with patch. Fixes #133. * Moved log function to pylons.helpers and translation functions to pylons.i18n. using pylons.util purely for Pylons internal util functions. * WARNING: Removed 0.8.x legacy code and backwards compatibility functions. * PylonsApp now has option to not use Routes middleware, default resolving uses new wsgi.org routing_args spec. * Refactored routes dispatching to use new Routes middleware. * Fixed paster shell command to properly acquire mapper object without relying on the template being configured in a specific manner. * Added keyword argument pool_connection to pylons.database.PackageHub; if set to false then SQLObject connections won't use pooled database connections (a new connection will be opened for each request). 0.9.3 (Nov 1st, 2006) * Updated project template to support full_stack option to make it easier to use Pylons apps within larger WSGI stacks. * Added deprecation warnings to legacy objects and for 1.0 functionality that will change. * Added cache decorator and Cheetah template functional tests. Patch and unit tests provided by Climbus. * Fixed readline support in the stock interactive console paster shell. Reported by Alex Conrad. * A controller's __after__ method will now be called after actions invoke redirect_to (or raise any HTTPException). Reported by David Turner. * Fixed config to use myghty_data_dir instead of cache_dir setting if its set as well. Reported by Shannon -jj Behrens. * Added traceback hiding so that more of the traceback relating to Pylons code is removed from the default traceback making it easier to focus on the code in an app that actually caused the problem. Closes #119. * Added ability to use '_' translation method directly from templates and in the controller without having to use it under h._. * Added 's' and 'l' Myghty escaping flags to default project templates. Suggested by Jamie Wilkinson. Closes #110. * Fixed SCGI bug with QUERY_STRING test when WSGI states it doesn't have to exist. Reported by Riklaunim. * Added pylons_minimal template, prone to fine-tuning. * Added option for PylonsApp to take a globals object to avoid checking a hardcoded path for a Globals object. * Removed old Helpers legacy object entirely, replaced pylons.h with proper StackedObjectProxy. Cleaned up PylonsApp and PylonsBaseApp to accept a helpers reference so that Pylons can be ignorant of where the helpers came from. * Fixed bug with lang app_conf option being set improperly. Reported by Laurent. * Fixed pylons.h to work proper with new and old-style helper imports. * Fixed render functions always passing disable_unicode=False to Myghty. 0.9.2 (Sept. 7th, 2006) * Fixed problem with dashes in controller names, resolves #107. * Updated default ini file to use localhost from address. Refs #104. * Updated default development.ini to use a single cache_dir setting which is the base dir that cache files, session files, and template caching will be saved in. Config object now looks to cache_dir setting properly for Myghty templates. Fixes #104. * Updated default template controller to provide better example of directly serving Myghty templates. * Fixed legacy (0.8) controller methods' **ARGS (also m.request_args and pylons.params) to be of the expected mixed dictionary instead of MultiDict. * Fixed _attach_locals not attaching g and cache objects. * Added g object to the shell. Works as long as the Pylons app can respond to a path of '/'. The pylons.g variable will also be setup properly for use in the shell. * Myghty template options are now passed properly to the template creation, and allow_globals now works to add Myghty template globals. * Re-organized helpers, switched Helpers class to use static methods to reduce code duplication. * Helpers cleanup: - Old-style Helper object uses StackedObjectProxy just like the new scheme, thus avoiding possible WSGI stack issues. - New project templates use new-style Helpers scheme. - Updated wsgiapp to utilize new Helpers cleanup style. The 'h' object is now friendlier to use, and maps directly to a projects lib.helpers file. No more wacky Helpers object proxying to it. - Added translator global to __init__.py for use with new Helpers cleanup. - Copied Helpers function methods directly into util so they can be used stand-alone. - Deprecated h.lang (for h.set_lang/h.get_lang) * Moved the 'default_charset' option from PylonsApp's constructor to Config's. * Added 'error' controller route to the top of the Pylons template to avoid the common issue people discover when removing the generic default route. * Changing validate decorator to have variable_decode option, which will also run formencode's variable_decode function over the form input. * Switched to using Context obj classes instead of RequestLocal which is being phased out. * Added an 'encode_variables' option to the validate decorator. * Switched all current_obj calls to _current_obj to avoid triggering deprecation warnings. * Added is_xhr to Request object in Paste. * Bumping up dependency to latest Paste. * Switching back to prior controller import check, throwing a more detailed error with a suggest fix should the user really want a URL with that name in it. (refs #67) * Fixes bug with prior fix for #67. Wasn't properly testing the full package name to include the current project which would incorrectly restrict valid controller names (refs #67). * Fixed '_method_' checking to test in a more efficient manner. * Added deprecation warning for legacy mode activation. Not necessary to update multiple files, as all of legacy mode is enabled via the Legacy WSGI app. Fixes #89. * Fixed controller command to check controller name and refuse to create controllers that have name clashes with existing modules that could be imported. Reported (with patch) by Chuck Adams. Fixes #67. * Added capability for 'c' object to throw an exception when an attribute is used that doesn't exist. Closes #84. * Fix for endless error document call when an error document controller wants to throw a error that the error_mapper catches. 0.9.1 (August 11th, 2006) * Fixed __all__ export typo in templating.py. Added example of render with a template. * Fixed issue with set_lang not using proper CONFIG var. * Minor tweaks to update docs in pylons.helpers and move remaining legacy code into legacy module. Updated wsgiapp to refer to new locations of legacy compatibility objects. * The interactive debugger's 'full traceback' link is now only displayed when the full traceback differs from the regular (includes hidden frames). * Providing an optional text version of exception tracebacks and the associated extra data within the interactive debugger. * The 'Debug at: http://hostname/_debug/view/XXXXX' URLs now display the interactive debugger properly skinned. * Fixed issue in PasteScript with new controller sub-directories lacking a __init__.py file. This fixes an import error when using the controller. PasteScript dependency updated to fixed version. Reported by Artur Lew. * Removed lowercasing of the module name during resolver import. * Removed [full] recommendation from docs. 0.9 (July 28th, 2006) * config file option 'debug' now defaults to false when undefined * Removed the components directory from the template * Updated paste.errordocuments support * Fix for multi-word controller names such that front_page / FrontPageController can be used as a controller name. Patch contributed by Timo Mihaljov. * Cleaned up imports in wsgiapp and new project to better reflect where things really come from. * Removed unnecessary myghty usage from wsgiapp for url unescaping, now uses urllib as the myghty function did. * Removing 'response' to import, sticking with Response as its more consistent with the fact that Response is a class/factory and not an instance like request, and the other lower-case objects. * Added redirect_to under pylons.helpers, and added import from helpers directly into lib/base.py for use in controllers. * Consolidated legacy objects into legacy module. * Adding abort method that raises the appropriate exception for the status code. * Removing form_fill, obsolete by the validate decorator. * Relocated 'params' object to only take effect in legacy mode. * Updated Pylons template to use WSGIController as the new default Controller. * Altered the wsgi dispatch to examine the controller, and instantiate it if it's just a class. Otherwise, if the controller is a subclass of Controller but not of WSGIController, it assumes its an older Controller class that may return a WSGIResponse, and calls it appropriately. * Dispatch now fixes up environ to move 'path_info' Route var into the WSGI PATH_INFO, and the rest is pushed into SCRIPT_NAME. This is for use with other WSGI apps under controller mount points. * Added WSGIController which takes a normal WSGI interface call and returns the appropriate WSGI response. * Added automatic copying of Route variables declared in an action's function definition to the 'c' object. * WebHelpers' .js files are now automatically published under the '/javascripts/' URL path. Individual WebHelpers' .js files can be overridden by other .js files inside the project's 'public/javascripts' directory * Added exception toss when a template engine doesn't exist. * Added alias option to Buffet to support aliasing more template engines to other engine names * Buffet enhancements to support caching of any template with any template engine * All render commands processed through Buffet * Backwards compatibility 'm' object for use with legacy projects * Added use of Beaker middleware for session and caching functionality * Fixed error traceback and updated template to use proper error images and stylesheets. 0.8.2 (**dev**) * Fixed default controller to allow for actions with - in them. The - will be replaced with an underscore, while the original action name in the mapper dict is unchanged. Patch by Thomas Sidwick. 0.8.1 (May 10th, 2006) * Added REST decorators and re-arranged decorator layout to support more styles of decorators for future expansion. * Fixed dependency requirement bug that had Pylons locked to simplejson 1.1 even though a newer version was out. Pylons-1.0.2/PKG-INFO0000644000175000017500000000714212553621453013437 0ustar benben00000000000000Metadata-Version: 1.1 Name: Pylons Version: 1.0.2 Summary: Pylons Web Framework Home-page: http://www.pylonshq.com/ Author: Ben Bangert, Philip Jenvey, James Gardner Author-email: ben@groovie.org, pjenvey@underboss.org License: BSD Description: Pylons ====== The Pylons web framework is designed for building web applications and sites in an easy and concise manner. They can range from as small as a single Python module, to a substantial directory layout for larger and more complex web applications. Pylons comes with project templates that help boot-strap a new web application project, or you can start from scratch and set things up exactly as desired. Example `Hello World` --------------------- .. from paste.httpserver import serve from pylons import Configurator, Response class Hello(object): def __init__(self, request): self.request = request def index(self): return Response(body="Hello World!") if __name__ == '__main__': config = Configurator() config.begin() config.add_handler('home', '/', handler=Hello, action='index') config.end() serve(config.make_wsgi_app(), host='0.0.0.0') Core Features ------------- * A framework to make writing web applications in Python easy * Utilizes a minimalist, component-based philosophy that makes it easy to expand on * Harness existing knowledge about Python * Extensible application design * Fast and efficient, an incredibly small per-request call-stack providing top performance * Uses existing and well tested Python packages Current Status -------------- Pylons 1.0 series is stable and production ready. The Pylons Project now maintains the Pyramid web framework for future development. Pylons 1.0 users should strongly consider using it for their next project. Download and Installation ------------------------- Pylons can be installed with `Easy Install `_ by typing:: > easy_install Pylons Dependant packages are automatically installed from the `Pylons download page `_ . Development Version ------------------- Pylons development uses the Mercuial distributed version control system (DVCS) with BitBucket hosting the main repository here: `Pylons Bitbucket repository `_ Keywords: web wsgi lightweight framework sqlalchemy formencode mako templates Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Framework :: Pylons Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 :: Only Classifier: Topic :: Internet :: WWW/HTTP Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Internet :: WWW/HTTP :: WSGI Classifier: Topic :: Software Development :: Libraries :: Python Modules Pylons-1.0.2/test_files/0000755000175000017500000000000012553621453014477 5ustar benben00000000000000Pylons-1.0.2/test_files/sample_controllers/0000755000175000017500000000000012553621453020406 5ustar benben00000000000000Pylons-1.0.2/test_files/sample_controllers/controllers/0000755000175000017500000000000012553621453022754 5ustar benben00000000000000Pylons-1.0.2/test_files/sample_controllers/controllers/hello.py0000644000175000017500000000166312451647626024446 0ustar benben00000000000000import logging from pylons import request, response, session, tmpl_context as c, url from pylons.controllers import WSGIController from pylons.controllers.util import abort, redirect from pylons.templating import render_mako from webob import Response from webob.exc import HTTPNotFound log = logging.getLogger(__name__) class HelloController(WSGIController): def __init__(self): self._pylons_log_debug = True def index(self): return 'Hello World' def oops(self): raise Exception('oops') def abort(self): abort(404) def intro_template(self): return render_mako('/hello.html') def time_template(self): return render_mako('/time.html', cache_key='fred', cache_expire=20) def special_controller(environ, start_response): return HTTPNotFound() def empty_wsgi(environ, start_response): return def a_view(request): return Response('A View') Pylons-1.0.2/test_files/sample_controllers/controllers/__init__.py0000644000175000017500000000000212451647626025064 0ustar benben00000000000000# Pylons-1.0.2/test_files/sample_controllers/controllers/i18nc.py0000644000175000017500000000263612451647626024266 0ustar benben00000000000000import datetime from pylons import request, response, session, url from pylons import tmpl_context as c from pylons import app_globals from pylons.i18n import _, get_lang, set_lang, LanguageError from pylons.controllers import WSGIController from pylons.controllers.util import abort, redirect class I18NcController(WSGIController): def set_lang(self): return self._set_lang(_) def set_lang_pylonscontext(self, pylons): return self._set_lang(lambda *args: pylons.translator.ugettext(*args)) def _set_lang(self, gettext): lang = request.GET['lang'] try: set_lang(lang) except (LanguageError, IOError), e: resp_unicode = gettext('Could not set language to "%(lang)s"') % {'lang': lang} else: session['lang'] = lang session.save() resp_unicode = gettext('Set language to "%(lang)s"') % {'lang': lang} return resp_unicode def i18n_index(self): obj = request._current_obj() locale_list = request.languages set_lang(request.languages) return unicode(_('basic index page')) def no_lang(self): set_lang(None) response.write(_('No language')) set_lang([]) response.write(_('No languages')) return '' def langs(self): locale_list = request.languages set_lang(request.languages) return str(get_lang()) Pylons-1.0.2/test_files/sample_controllers/controllers/goodbye.py0000644000175000017500000000071012451647626024763 0ustar benben00000000000000import logging from pylons import request, response, session, tmpl_context as c, url from pylons.controllers import WSGIController from pylons.controllers.util import abort, redirect from webob import Response from webob.exc import HTTPNotFound log = logging.getLogger(__name__) class Smithy(WSGIController): def __init__(self): self._pylons_log_debug = True def index(self): return 'Hello World' __controller__ = 'Smithy' Pylons-1.0.2/test_files/sample_controllers/__init__.py0000644000175000017500000000000212451647626022516 0ustar benben00000000000000# Pylons-1.0.2/test_files/__init__.py0000644000175000017500000000000012451647626016605 0ustar benben00000000000000Pylons-1.0.2/test_files/event_file.py0000644000175000017500000000033112451647626017175 0ustar benben00000000000000from pylons.events import NewRequest, NewResponse, subscriber @subscriber(NewRequest) def add_reggy(event): event.request.reg = True @subscriber(NewResponse) def add_respy(event): event.response.reg = True Pylons-1.0.2/README.rst0000644000175000017500000000277012456612060014027 0ustar benben00000000000000Pylons ++++++ .. image:: https://secure.travis-ci.org/Pylons/pylons.png?branch=master :alt: Build Status :target: https://secure.travis-ci.org/Pylons/pylons Pylons is a rapid web application development framework. .. note:: Pylons has merged with repoze.bfg, and is now in maintenance-only mode. It's highly recommended that new projects start with the new merged web framework, `pyramid `_. `Read the complete Pylons web framework documentation `_ Install ======= `Read the online Installation instructions `_. If you want to install from source you can run the following command: .. code-block :: bash $ python setup.py install This will display a message and download setuptools if the module is not already installed. It will then install Pylons and all its dependencies. You may need root privileges to install setuptools. Testing ======= To test the source distribution run the following command: .. code-block :: bash $ python setup.py test This will install additional dependencies needed for the tests. As above, you may need root privileges. Documentation ============= Generating documentation requires Sphinx: .. code-block :: bash $ easy_install Sphinx Then to build the documentation use the commands: .. code-block :: bash $ cd pylons/docs/ $ make html