tg.devtools-2.0.2/0000755000076500007650000000000011240527554021050 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/0000755000076500007650000000000011240527554022707 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/.___init__.py0000644000076500007650000000027011113340245025221 0ustar markramm-christensenmarkramm-christensenMac OS X  2ATTRC  com.macromates.caretxR<[k0?'3/«tg.devtools-2.0.2/devtools/__init__.py0000644000076500007650000000000011113340245024773 0ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/commands/0000755000076500007650000000000011240527554024510 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/commands/__init__.py0000644000076500007650000000000011113340241026570 0ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/commands/._migration.py0000644000076500007650000000027311113340241027253 0ustar markramm-christensenmarkramm-christensenMac OS X  2ATTRC{##com.macromates.caret{ column = 61; line = 10; }tg.devtools-2.0.2/devtools/commands/migration.py0000644000076500007650000000366211113340241027043 0ustar markramm-christensenmarkramm-christensen""" TurboGears migration paster migrate command integrate sqlalchemy-migrate into TurboGears 2. To start a migration, run command:: $ paster migrate create And migrate command will create a 'migration' directory for you. With migrate command you don't need use 'manage.py' in 'migration' directory anymore. Then you could bind the database with migration with command:: $ paster migrate version_control Usage: .. parsed-literal:: paster migrate help paster migrate create paster migrate vc|version_control paster migrate dbv|db_version paster migrate v|version paster migrate manage [script.py] paster migrate test [script.py] paster migrate ci|commit [script.py] paster migrate up|upgrade [--version] paster migrate downgrade [--version] .. container:: paster-usage --version database's version number check http://code.google.com/p/sqlalchemy-migrate/wiki/MigrateVersioning for detail. """ from paste.script import command import os import ConfigParser from migrate.versioning.shell import main class MigrateCommand(command.Command): """Sqlalchemy migration""" max_args = 3 min_args = 1 summary = __doc__.splitlines()[0] usage = '\n' + __doc__ group_name = "TurboGears2" parser = command.Command.standard_parser(verbose=True) def command(self): ini = 'development.ini' sect = 'app:main' option = 'sqlalchemy.url' # get sqlalchemy.url config in app:mains curdir = os.getcwd() conf = ConfigParser.ConfigParser() conf.read(os.path.join(curdir, ini)) self.name = "migration" try: self.dburi = conf.get(sect, option, vars={'here':curdir}) except: print "you shold set sqlalchemy.url in development.ini first" print "The repository is '%s'\nThe url is '%s'"%(self.name, self.dburi) main(argv=self.args, url=self.dburi,repository=self.name, name=self.name) tg.devtools-2.0.2/devtools/commands/quickstart.py0000644000076500007650000002105011153607757027261 0ustar markramm-christensenmarkramm-christensen"""Quickstart command to generate a new project. TurboGears 2 uses Paste to create and deploy projects as well as create new controllers and their tests. Quickstart takes the files from turbogears.pastetemplates and processes them to produce a new, ready-to-run project. Create a new project named helloworld with this command:: $ paster quickstart helloworld You can use TurboGears2, Pylons, and WebHelper paster commands within the project, as well as any paster commands that are provided by a plugin, or you create yourself. Usage: .. parsed-literal:: paster quickstart [--version][-h|--help] [-p *PACKAGE*][--dry-run][-t|--templates *TEMPLATES*] [-s|--sqlalchemy][-o|--sqlobject][-a|--auth][-g|--geo] .. container:: paster-usage --version how program's version number and exit -h, --help show this help message and exit -p PACKAGE, --package=PACKAGE package name for the code --dry-run dry run (don't actually do anything) -t TEMPLATES, --templates=TEMPLATES user specific templates -s, --sqlalchemy use SQLAlchemy as ORM -a, --auth provide authentication and authorization support -g, --geo add GIS support """ import pkg_resources import re import optparse from paste.script import command from paste.script import create_distro import os import stat import sys beginning_letter = re.compile(r"^[^a-z]*") valid_only = re.compile(r"[^a-z0-9_]") class QuickstartCommand(command.Command): """Create a new TurboGears 2 project. Create a new Turbogears project with this command. Example usage:: $ paster quickstart yourproject or start project with authentication and authorization support:: $ paster quickstart -a yourproject """ version = pkg_resources.get_distribution('turbogears2').version max_args = 3 min_args = 0 summary = __doc__.splitlines()[0] usage = '\n' + __doc__ group_name = "TurboGears2" name = None auth = None geo = False package = None svn_repository = None sqlalchemy = False sqlobject = False templates = "turbogears2" dry_run = False no_input = False parser = command.Command.standard_parser(quiet=True) parser = optparse.OptionParser( usage="%prog quickstart [options] [project name]", version="%prog " + version) parser.add_option("-a", "--auth", help='add authentication and authorization support', action="store_true", dest="auth") parser.add_option("-g", "--geo", help="add GIS support", action="store_true", dest="geo") parser.add_option("-p", "--package", help="package name for the code", dest="package") parser.add_option("-r", "--svn-repository", metavar="REPOS", help="create project in given SVN repository", dest="svn_repository", default=svn_repository) parser.add_option("-s", "--sqlalchemy", help="use SQLAlchemy as ORM", action="store_true", dest="sqlalchemy", default=True) parser.add_option("-t", "--templates", help="user specific templates", dest="templates", default=templates) parser.add_option("--dry-run", help="dry run (don't actually do anything)", action="store_true", dest="dry_run") parser.add_option("--noinput", help="no input (don't ask any questions)", action="store_true", dest="no_input") def command(self): """Quickstarts the new project.""" self.__dict__.update(self.options.__dict__) if not True in [self.sqlalchemy, self.sqlobject]: self.sqlalchemy = True if self.args: self.name = self.args[0] while not self.name: self.name = raw_input("Enter project name: ") package = self.name.lower() package = beginning_letter.sub("", package) package = valid_only.sub("", package) if package and self.no_input: self.package = package else: self.package = None while not self.package: self.package = raw_input( "Enter package name [%s]: " % package).strip() or package if not self.no_input: while self.auth is None: self.auth = raw_input( "Do you need authentication and authorization" " in this project? [yes] ") self.auth = dict(y=True, n=False).get( self.auth.lstrip()[:1].lower() or 'y') if self.auth is None: print "Please enter y(es) or n(o)." if self.auth: if self.sqlalchemy: self.auth = "sqlalchemy" else: print ('You can only use authentication and authorization' ' in a new project if you use SQLAlchemy. Please check' ' the repoze.what documentation to learn how to implement' ' authentication/authorization with other sources.') return # TODO: As far as I know, SQLObject has never been supported in # TG2 # self.auth = "sqlobject" else: self.auth = None self.name = pkg_resources.safe_name(self.name) env = pkg_resources.Environment() if self.name.lower() in env: print 'The name "%s" is already in use by' % self.name, for dist in env[self.name]: print dist return import imp try: if imp.find_module(self.package): print 'The package name "%s" is already in use' % self.package return except ImportError: pass if os.path.exists(self.name): print 'A directory called "%s" already exists. Exiting.' % self.name return command = create_distro.CreateDistroCommand("create") cmd_args = [] for template in self.templates.split(): cmd_args.append("--template=%s" % template) if self.svn_repository: cmd_args.append("--svn-repository=%s" % self.svn_repository) if self.dry_run: cmd_args.append("--simulate") cmd_args.append("-q") cmd_args.append(self.name) cmd_args.append("sqlalchemy=%s" % self.sqlalchemy) cmd_args.append("sqlobject=%s" % self.sqlobject) cmd_args.append("auth=%s" % self.auth) cmd_args.append("geo=%s" % self.geo) cmd_args.append("package=%s" % self.package) cmd_args.append("tgversion=%s" % self.version) # set the exact ORM-version for the proper requirements # it's extracted from our own requirements, so looking # them up must be in sync (there must be the extras_require named # sqlobject/sqlalchemy) """if self.sqlobject: sqlobjectversion = str(get_requirement('sqlobject')) cmd_args.append("sqlobjectversion=%s" % sqlobjectversion) if self.sqlalchemy: sqlalchemyversion = str(get_requirement('sqlalchemy')) cmd_args.append("sqlalchemyversion=%s" % sqlalchemyversion) """ command.run(cmd_args) if not self.dry_run: os.chdir(self.name) if self.sqlobject: # Create the SQLObject history directory only when needed. # With paste.script it's only possible to skip files, but # not directories. So we are handling this manually. sodir = '%s/sqlobject-history' % self.package if not os.path.exists(sodir): os.mkdir(sodir) try: if not os.path.exists(os.path.join(os.path.dirname( os.path.abspath(sodir)), '.svn')): raise OSError command.run_command('svn', 'add', sodir) except OSError: pass startscript = "start-%s.py" % self.package if os.path.exists(startscript): oldmode = os.stat(startscript).st_mode os.chmod(startscript, oldmode | stat.S_IXUSR) sys.argv = ["setup.py", "egg_info"] import imp imp.load_module("setup", *imp.find_module("setup", ["."])) # dirty hack to allow "empty" dirs for base, path, files in os.walk("./"): for file in files: if file == "empty": os.remove(os.path.join(base, file)) tg.devtools-2.0.2/devtools/pastetemplate.py0000644000076500007650000000325011150150764026124 0ustar markramm-christensenmarkramm-christensen"""Definitions for TurboGears quickstart templates""" from paste.script import templates from tempita import paste_script_template_renderer class TurboGearsTemplate(templates.Template): """ TurboGears 2 default paste template class """ _template_dir = 'templates/turbogears' template_renderer = staticmethod(paste_script_template_renderer) summary = 'TurboGears 2.0 Standard Quickstart Template' egg_plugins = ['PasteScript', 'Pylons', 'TurboGears2', 'tg.devtools'] vars = [ templates.var('sqlalchemy', 'use SQLAlchemy as ORM', default=True), templates.var('auth', 'use authentication and authorization support', default="sqlalchemy"), templates.var('geo', 'Include GIS support (True/False)', default='False'), ] 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 template_engine = \ vars.setdefault('template_engine', 'genshi') if template_engine == 'mako': # Support a Babel extractor default for Mako vars['babel_templates_extractor'] = \ "('templates/**.mako', 'mako', None),\n%s#%s" % (' ' * 4, ' ' * 8) else: vars['babel_templates_extractor'] = '' if vars['geo'] == 'True': # Add tgext.geo as paster plugin vars['egg_plugins'].append('tgext.geo') tg.devtools-2.0.2/devtools/templates/0000755000076500007650000000000011240527554024705 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/templates/.___init__.py0000644000076500007650000000027211113340245027221 0ustar markramm-christensenmarkramm-christensenMac OS X  2ATTRC""com.macromates.caret{ column = 5; line = 13; }tg.devtools-2.0.2/devtools/templates/__init__.py0000644000076500007650000000557311113340245027015 0ustar markramm-christensenmarkramm-christensen""" Place to hold TurboGears built-in templates With 'paster quickstart' or 'paster create' command you can create a new TurboGears project which you can use as a basis for your own project. Let's take the command 'paster quickstart helloworld' for example. The generated directory structure is as follows:: - helloworld/ - helloworld/ - development.ini - setup.cfg - setup.py - test.ini The setup.py file is used to create a re-distributable Python package of your project called an egg. Eggs can be thought of as similar to .jar files in Java. The setup.cfg file contains extra information about your project. The sub 'helloworld' directory within the root 'helloworld' directory is where all your application specific code and files are placed. The sub directory looks like this:: - helloworld/ - config/ - controllers/ - lib/ - model/ - public/ - templates/ - tests/ - __init__.py - websetup.py The config directory contains the configuration options for your web application. The controllers directory is where your application controllers are written. Controllers are the core of your application where the decision is made on what data to load, and how to view it. The lib directory is where you can put code that is used between different controllers, third party code, or any other code that doesn't fit in well elsewhere. The models directory is for your model objects, if you're using an ORM this is where the classes for them should go. Objects defined in models/__init__.py will be loaded and present as model. YourObject inside your controllers. The database configuration string can be set in your development.ini file. The public directory is where you put all your HTML, images, Javascript, CSS and other static files. It is similar to the htdocs directory in Apache. The templates directory is where templates are stored. Templates contain a mixture of plain text and Python code and are used for creating HTML and other documents in a way that is easy for designers to tweak without them needing to see all the code that goes on behind the scenes. TurboGears 2 uses Genshi templates by default but also supports Mako, and jinja out of the box. Cheetah, Kid and any other template system you want can be easily used by writing a simple render function for them. The tests directory is where you can put controller and other tests. The controller testing functionality uses Nose and paste.fixture. The __init__.py file is present so that the helloworld directory can be used as a Python module within the egg. The websetup.py should contain any code that should be executed when an end user of your application runs the paster setup-app command described in Application Setup. If you're looking for where to put that should be run before your application is, this is the place. """ tg.devtools-2.0.2/devtools/templates/turbogears/0000755000076500007650000000000011240527554027062 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/templates/turbogears/+package+/0000755000076500007650000000000011240527554030603 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/templates/turbogears/+package+/__init__.py_tmpl0000644000076500007650000000006611153607760033753 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """The {{project}} package""" tg.devtools-2.0.2/devtools/templates/turbogears/+package+/config/0000755000076500007650000000000011240527554032050 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/templates/turbogears/+package+/config/__init__.py_tmpl0000644000076500007650000000003111153607757035216 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- tg.devtools-2.0.2/devtools/templates/turbogears/+package+/config/._app_cfg.py_tmpl0000644000076500007650000000027311237676730035303 0ustar markramm-christensenmarkramm-christensenMac OS X  2ATTRe.##com.macromates.caret{ column = 45; line = 52; }tg.devtools-2.0.2/devtools/templates/turbogears/+package+/config/app_cfg.py_tmpl0000644000076500007650000000477711237676730035103 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """ Global configuration file for TG2-specific settings in {{project}}. This file complements development/deployment.ini. Please note that **all the argument values are strings**. If you want to convert them into boolean, for example, you should use the :func:`paste.deploy.converters.asbool` function, as in:: from paste.deploy.converters import asbool setting = asbool(global_conf.get('the_setting')) """ from tg.configuration import AppConfig import {{package}} from {{package}} import model from {{package}}.lib import app_globals, helpers base_config = AppConfig() base_config.renderers = [] base_config.package = {{package}} #Set the default renderer {{if template_engine == 'mako'}} base_config.default_renderer = 'mako' base_config.renderers.append('mako') {{elif template_engine == 'jinja'}} base_config.default_renderer = 'jinja' base_config.renderers.append('jinja') {{elif template_engine == 'genshi'}} base_config.default_renderer = 'genshi' base_config.renderers.append('genshi') # if you want raw speed and have installed chameleon.genshi # you should try to use this renderer instead. # warning: for the moment chameleon does not handle i18n translations #base_config.renderers.append('chameleon_genshi') {{endif}} {{if sqlalchemy}} #Configure the base SQLALchemy Setup base_config.use_sqlalchemy = True base_config.model = {{package}}.model base_config.DBSession = {{package}}.model.DBSession {{endif}} {{if auth == "sqlalchemy"}} # YOU MUST CHANGE THIS VALUE IN PRODUCTION TO SECURE YOUR APP base_config.sa_auth.cookie_secret = "ChangeME" # Configure the authentication backend base_config.auth_backend = 'sqlalchemy' base_config.sa_auth.dbsession = model.DBSession # what is the class you want to use to search for users in the database base_config.sa_auth.user_class = model.User # what is the class you want to use to search for groups in the database base_config.sa_auth.group_class = model.Group # what is the class you want to use to search for permissions in the database base_config.sa_auth.permission_class = model.Permission # override this if you would like to provide a different who plugin for # managing login and logout of your application base_config.sa_auth.form_plugin = None # You may optionally define a page where you want users to be redirected to # on login: base_config.sa_auth.post_login_url = '/post_login' # You may optionally define a page where you want users to be redirected to # on logout: base_config.sa_auth.post_logout_url = '/post_logout' {{endif}} tg.devtools-2.0.2/devtools/templates/turbogears/+package+/config/deployment.ini_tmpl_tmpl0000644000076500007650000000534111173202655037021 0ustar markramm-christensenmarkramm-christensen# # {{project}} - TurboGears configuration # # The %(here)s variable will be replaced with the parent directory of this file # [DEFAULT] # WARGING == If debug is not set to false, you'll get the interactive # debugger on production, which is a huge security hole. debug = false 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 = 8080 [app:main] use = egg:{{project}} full_stack = 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}} # Specify the database for SQLAlchemy to use via # turbogears.database # %(here) may include a ':' character on Windows environments; this can # invalidate the URI when specifying a SQLite db via path name sqlalchemy.url = sqlite:///%(here)s/somedb.db sqlalchemy.echo = False {{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 # Add additional loggers, handlers, formatters here # Uses python's logging config file format # http://docs.python.org/lib/logging-config-fileformat.html [loggers] keys = root, {{package_logger}}{{if sqlalchemy}}, sqlalchemy{{endif}}{{if auth == "sqlalchemy"}}, auth{{endif}} [handlers] keys = console [formatters] keys = generic # If you create additional loggers, add them as a key to [loggers] [logger_root] level = INFO handlers = console [logger_{{package_logger}}] level = INFO handlers = qualname = {{package_logger}} {{if sqlalchemy}} [logger_sqlalchemy] level = WARN 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}} {{if auth == "sqlalchemy"}} # A logger for authentication, identification and authorization -- this is # repoze.who and repoze.what: [logger_auth] level = WARN handlers = qualname = auth {{endif}} # If you create additional handlers, add them as a key to [handlers] [handler_console] class = StreamHandler args = (sys.stderr,) level = NOTSET formatter = generic # If you create additional formatters, add them as a key to [formatters] [formatter_generic] format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s datefmt = %H:%M:%S tg.devtools-2.0.2/devtools/templates/turbogears/+package+/config/environment.py_tmpl0000644000076500007650000000041411153607757036030 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """WSGI environment setup for {{project}}.""" from {{package}}.config.app_cfg import base_config __all__ = ['load_environment'] #Use base_config to setup the environment loader function load_environment = base_config.make_load_environment() tg.devtools-2.0.2/devtools/templates/turbogears/+package+/config/middleware.py_tmpl0000644000076500007650000000243211160337245035571 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """WSGI middleware initialization for the {{project}} application.""" from {{package}}.config.app_cfg import base_config from {{package}}.config.environment import load_environment __all__ = ['make_app'] # Use base_config to setup the necessary PasteDeploy application factory. # make_base_app will wrap the TG2 app with all the middleware it needs. make_base_app = base_config.setup_tg_wsgi_app(load_environment) def make_app(global_conf, full_stack=True, **app_conf): """ Set {{project}} up with the settings found in the PasteDeploy configuration file used. :param global_conf: The global settings for {{project}} (those defined under the ``[DEFAULT]`` section). :type global_conf: dict :param full_stack: Should the whole TG2 stack be set up? :type full_stack: str or bool :return: The {{project}} application with all the relevant middleware loaded. This is the PasteDeploy factory for the {{project}} application. ``app_conf`` contains all the application-specific settings (those defined under ``[app:main]``. """ app = make_base_app(global_conf, full_stack=True, **app_conf) # Wrap your base TurboGears 2 application with custom middleware here return app tg.devtools-2.0.2/devtools/templates/turbogears/+package+/controllers/0000755000076500007650000000000011240527554033151 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/templates/turbogears/+package+/controllers/__init__.py_tmpl0000644000076500007650000000011311153607760036312 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """Controllers for the {{project}} application.""" tg.devtools-2.0.2/devtools/templates/turbogears/+package+/controllers/controller.template_tmpl0000644000076500007650000000124411153607760040127 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """Sample controller module""" # turbogears imports from tg import expose #from tg import redirect, validate, flash # third party imports #from pylons.i18n import ugettext as _ #from repoze.what import predicates # project specific imports from {{package}}.lib.base import BaseController #from {{package}}.model import DBSession, metadata class SampleController(BaseController): {{if auth == "sqlalchemy"}} #Uncomment this line if your controller requires an authenticated user #allow_only = authorize.not_anonymous() {{endif}} @expose('{{package}}.templates.index') def index(self): return dict(page='index') tg.devtools-2.0.2/devtools/templates/turbogears/+package+/controllers/error.py_tmpl0000644000076500007650000000202711160337245035706 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """Error controller""" from tg import request, expose __all__ = ['ErrorController'] class ErrorController(object): """ 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. """ @expose('{{package}}.templates.error') def document(self, *args, **kwargs): """Render the error document""" resp = request.environ.get('pylons.original_response') default_message = ("

We're sorry but we weren't able to process " " this request.

") values = dict(prefix=request.environ.get('SCRIPT_NAME', ''), code=request.params.get('code', resp.status_int), message=request.params.get('message', default_message)) return values tg.devtools-2.0.2/devtools/templates/turbogears/+package+/controllers/._root.py_tmpl0000644000076500007650000000027011166762000035750 0ustar markramm-christensenmarkramm-christensenMac OS X  2ATTRe?  com.macromates.caretxR<[k0?'3/«tg.devtools-2.0.2/devtools/templates/turbogears/+package+/controllers/root.py_tmpl0000644000076500007650000000664311166762000035545 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """Main Controller""" from tg import expose, flash, require, url, request, redirect from pylons.i18n import ugettext as _, lazy_ugettext as l_ {{if auth == "sqlalchemy"}} from catwalk.tg2 import Catwalk from repoze.what import predicates {{endif}} from {{package}}.lib.base import BaseController from {{package}}.model import DBSession, metadata from {{package}}.controllers.error import ErrorController {{if auth == "sqlalchemy"}} from {{package}} import model from {{package}}.controllers.secure import SecureController {{endif}} __all__ = ['RootController'] class RootController(BaseController): """ The root controller for the {{project}} application. All the other controllers and WSGI applications should be mounted on this controller. For example:: panel = ControlPanelController() another_app = AnotherWSGIApplication() Keep in mind that WSGI applications shouldn't be mounted directly: They must be wrapped around with :class:`tg.controllers.WSGIAppController`. """ {{if auth == "sqlalchemy"}} secc = SecureController() admin = Catwalk(model, DBSession) {{endif}} error = ErrorController() @expose('{{package}}.templates.index') def index(self): """Handle the front-page.""" return dict(page='index') @expose('{{package}}.templates.about') def about(self): """Handle the 'about' page.""" return dict(page='about') {{if auth == "sqlalchemy"}} @expose('{{package}}.templates.authentication') def auth(self): """Display some information about auth* on this application.""" return dict(page='auth') {{endif}} {{if auth == "sqlalchemy"}} @expose('{{package}}.templates.index') @require(predicates.has_permission('manage', msg=l_('Only for managers'))) def manage_permission_only(self, **kw): """Illustrate how a page for managers only works.""" return dict(page='managers stuff') @expose('{{package}}.templates.index') @require(predicates.is_user('editor', msg=l_('Only for the editor'))) def editor_user_only(self, **kw): """Illustrate how a page exclusive for the editor works.""" return dict(page='editor stuff') @expose('{{package}}.templates.login') def login(self, came_from=url('/')): """Start the user login.""" login_counter = request.environ['repoze.who.logins'] if login_counter > 0: flash(_('Wrong credentials'), 'warning') return dict(page='login', login_counter=str(login_counter), came_from=came_from) @expose() def post_login(self, came_from=url('/')): """ Redirect the user to the initially requested page on successful authentication or redirect her back to the login page if login failed. """ if not request.identity: login_counter = request.environ['repoze.who.logins'] + 1 redirect(url('/login', came_from=came_from, __logins=login_counter)) userid = request.identity['repoze.who.userid'] flash(_('Welcome back, %s!') % userid) redirect(came_from) @expose() def post_logout(self, came_from=url('/')): """ Redirect the user to the initially requested page on logout and say goodbye as well. """ flash(_('We hope to see you soon!')) redirect(came_from) {{endif}} tg.devtools-2.0.2/devtools/templates/turbogears/+package+/controllers/secure.py_tmpl0000644000076500007650000000244211160337245036044 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """Sample controller with all its actions protected.""" {{if auth == "sqlalchemy"}} from tg import expose, flash from pylons.i18n import ugettext as _, lazy_ugettext as l_ from repoze.what.predicates import has_permission #from dbsprockets.dbmechanic.frameworks.tg2 import DBMechanic #from dbsprockets.saprovider import SAProvider from {{package}}.lib.base import BaseController #from {{package}}.model import DBSession, metadata __all__ = ['SecureController'] class SecureController(BaseController): """Sample controller-wide authorization""" # The predicate that must be met for all the actions in this controller: allow_only = has_permission('manage', msg=l_('Only for people with the "manage" permission')) @expose('{{package}}.templates.index') def index(self): """Let the user know that's visiting a protected controller.""" flash(_("Secure Controller here")) return dict(page='index') @expose('{{package}}.templates.index') def some_where(self): """Let the user know that this action is protected too.""" return dict(page='some_where') {{else}} # This controller is only used when you activate auth. You can safely remove # this file from your project. {{endif}} tg.devtools-2.0.2/devtools/templates/turbogears/+package+/controllers/template.py_tmpl0000644000076500007650000000170111160337245036366 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """Fallback controller.""" from {{package}}.lib.base import BaseController __all__ = ['TemplateController'] class TemplateController(BaseController): """ The fallback controller for {{project}}. By default, the final controller tried to fulfill the request when no other routes match. It may be used to display a template when all else fails, e.g.:: def view(self, url): return render('/%s' % url) Or if you're using Mako and want to explicitly send a 404 (Not Found) response code when the requested template doesn't exist:: import mako.exceptions def view(self, url): try: return render('/%s' % url) except mako.exceptions.TopLevelLookupException: abort(404) """ def view(self, url): """Abort the request with a 404 HTTP status code.""" abort(404) tg.devtools-2.0.2/devtools/templates/turbogears/+package+/i18n/0000755000076500007650000000000011240527554031362 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/templates/turbogears/+package+/i18n/ru/0000755000076500007650000000000011240527554032010 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/templates/turbogears/+package+/i18n/ru/LC_MESSAGES/0000755000076500007650000000000011240527554033575 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/templates/turbogears/+package+/i18n/ru/LC_MESSAGES/+package+.po_tmpl0000644000076500007650000000154111113340241036674 0ustar markramm-christensenmarkramm-christensen# Russian translations for ${package}. # Copyright (C) 2008 ORGANIZATION # This file is distributed under the same license as the ${package} project. # FIRST AUTHOR , 2008. # msgid "" msgstr "" "Project-Id-Version: ${package} 0.0.0\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2008-01-13 14:00+0200\n" "PO-Revision-Date: 2008-01-13 14:00+0200\n" "Last-Translator: FULL NAME \n" "Language-Team: ru \n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.1\n" #: ${package}/controllers/root.py:13 msgid "Your application is now running" msgstr "Ваши приложение успешно запущено" tg.devtools-2.0.2/devtools/templates/turbogears/+package+/lib/0000755000076500007650000000000011240527554031351 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/templates/turbogears/+package+/lib/__init__.py_tmpl0000644000076500007650000000003111153607760034511 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- tg.devtools-2.0.2/devtools/templates/turbogears/+package+/lib/app_globals.py_tmpl0000644000076500007650000000064311157554563035254 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """The application's Globals object""" __all__ = ['Globals'] class Globals(object): """Container for objects available throughout the life of the application. One instance of Globals is created during application initialization and is available during requests via the 'app_globals' variable. """ def __init__(self): """Do nothing, by default.""" pass tg.devtools-2.0.2/devtools/templates/turbogears/+package+/lib/base.py_tmpl0000644000076500007650000000213611160337245033670 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """The base Controller API.""" from tg import TGController, tmpl_context from tg.render import render {{if auth == "sqlalchemy"}} from tg import request {{endif}} from pylons.i18n import _, ungettext, N_ from tw.api import WidgetBunch {{if sqlalchemy}} import {{package}}.model as model {{endif}} __all__ = ['Controller', 'BaseController'] class BaseController(TGController): """ Base class for the controllers in the application. Your web application should have one of these. The root of your application is used to compute URLs used by your app. """ def __call__(self, environ, start_response): """Invoke the Controller""" # TGController.__call__ dispatches to the Controller method # the request is routed to. This routing information is # available in environ['pylons.routes_dict'] {{if auth == "sqlalchemy"}} request.identity = request.environ.get('repoze.who.identity') tmpl_context.identity = request.identity {{endif}} return TGController.__call__(self, environ, start_response) tg.devtools-2.0.2/devtools/templates/turbogears/+package+/lib/helpers.py_tmpl0000644000076500007650000000020511157554563034425 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """WebHelpers used in {{project}}.""" from webhelpers import date, feedgenerator, html, number, misc, text tg.devtools-2.0.2/devtools/templates/turbogears/+package+/model/0000755000076500007650000000000011240527554031703 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/templates/turbogears/+package+/model/__init__.py_tmpl0000644000076500007650000000455011153607757035063 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- {{if sqlalchemy}} """The application's model objects""" from zope.sqlalchemy import ZopeTransactionExtension from sqlalchemy.orm import scoped_session, sessionmaker #from sqlalchemy import MetaData from sqlalchemy.ext.declarative import declarative_base # Global session manager: DBSession() returns the Thread-local # session object appropriate for the current web request. maker = sessionmaker(autoflush=True, autocommit=False, extension=ZopeTransactionExtension()) DBSession = scoped_session(maker) # Base class for all of our model classes: By default, the data model is # defined with SQLAlchemy's declarative extension, but if you need more # control, you can switch to the traditional method. DeclarativeBase = declarative_base() # There are two convenient ways for you to spare some typing. # You can have a query property on all your model classes by doing this: # DeclarativeBase.query = DBSession.query_property() # Or you can use a session-aware mapper as it was used in TurboGears 1: # DeclarativeBase = declarative_base(mapper=DBSession.mapper) # Global metadata. # The default metadata is the one from the declarative base. metadata = DeclarativeBase.metadata # If you have multiple databases with overlapping table names, you'll need a # metadata for each database. Feel free to rename 'metadata2'. #metadata2 = MetaData() ##### # Generally you will not want to define your table's mappers, and data objects # here in __init__ but will want to create modules them in the model directory # and import them at the bottom of this file. # ###### def init_model(engine): """Call me before using any of the tables or classes in the model.""" DBSession.configure(bind=engine) # If you are using reflection to introspect your database and create # table objects for you, your tables must be defined and mapped inside # the init_model function, so that the engine is available if you # use the model outside tg2, you need to make sure this is called before # you use the model. # # See the following example: #global t_reflected #t_reflected = Table("Reflected", metadata, # autoload=True, autoload_with=engine) #mapper(Reflected, t_reflected) {{endif}} # Import your model modules here. {{if auth == "sqlalchemy"}} from {{package}}.model.auth import User, Group, Permission {{endif}} tg.devtools-2.0.2/devtools/templates/turbogears/+package+/model/auth.py_tmpl0000644000076500007650000001531611160337245034255 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """ Auth* related model. This is where the models used by :mod:`repoze.who` and :mod:`repoze.what` are defined. It's perfectly fine to re-use this definition in the {{project}} application, though. """ {{if auth == "sqlalchemy"}} import os from datetime import datetime import sys try: from hashlib import sha1 except ImportError: sys.exit('ImportError: No module named hashlib\n' 'If you are on python2.4 this library is not part of python. ' 'Please install it. Example: easy_install hashlib') from sqlalchemy import Table, ForeignKey, Column from sqlalchemy.types import Unicode, Integer, DateTime from sqlalchemy.orm import relation, synonym from {{package}}.model import DeclarativeBase, metadata, DBSession __all__ = ['User', 'Group', 'Permission'] #{ Association tables # This is the association table for the many-to-many relationship between # groups and permissions. This is required by repoze.what. group_permission_table = Table('tg_group_permission', metadata, Column('group_id', Integer, ForeignKey('tg_group.group_id', onupdate="CASCADE", ondelete="CASCADE")), Column('permission_id', Integer, ForeignKey('tg_permission.permission_id', onupdate="CASCADE", ondelete="CASCADE")) ) # This is the association table for the many-to-many relationship between # groups and members - this is, the memberships. It's required by repoze.what. user_group_table = Table('tg_user_group', metadata, Column('user_id', Integer, ForeignKey('tg_user.user_id', onupdate="CASCADE", ondelete="CASCADE")), Column('group_id', Integer, ForeignKey('tg_group.group_id', onupdate="CASCADE", ondelete="CASCADE")) ) #{ The auth* model itself class Group(DeclarativeBase): """ Group definition for :mod:`repoze.what`. Only the ``group_name`` column is required by :mod:`repoze.what`. """ __tablename__ = 'tg_group' #{ Columns group_id = Column(Integer, autoincrement=True, primary_key=True) group_name = Column(Unicode(16), unique=True, nullable=False) display_name = Column(Unicode(255)) created = Column(DateTime, default=datetime.now) #{ Relations users = relation('User', secondary=user_group_table, backref='groups') #{ Special methods def __repr__(self): return '' % self.group_name def __unicode__(self): return self.group_name #} # The 'info' argument we're passing to the email_address and password columns # contain metadata that Rum (http://python-rum.org/) can use generate an # admin interface for your models. class User(DeclarativeBase): """ User definition. This is the user definition used by :mod:`repoze.who`, which requires at least the ``user_name`` column. """ __tablename__ = 'tg_user' #{ Columns user_id = Column(Integer, autoincrement=True, primary_key=True) user_name = Column(Unicode(16), unique=True, nullable=False) email_address = Column(Unicode(255), unique=True, nullable=False, info={'rum': {'field':'Email'{{end_braces}}) display_name = Column(Unicode(255)) _password = Column('password', Unicode(80), info={'rum': {'field':'Password'{{end_braces}}) created = Column(DateTime, default=datetime.now) #{ Special methods def __repr__(self): return '' % ( self.email_address, self.display_name) def __unicode__(self): return self.display_name or self.user_name #{ Getters and setters @property def permissions(self): """Return a set of strings for the permissions granted.""" perms = set() for g in self.groups: perms = perms | set(g.permissions) return perms @classmethod def by_email_address(cls, email): """Return the user object whose email address is ``email``.""" return DBSession.query(cls).filter(cls.email_address==email).first() @classmethod def by_user_name(cls, username): """Return the user object whose user name is ``username``.""" return DBSession.query(cls).filter(cls.user_name==username).first() def _set_password(self, password): """Hash ``password`` on the fly and store its hashed version.""" hashed_password = password if isinstance(password, unicode): password_8bit = password.encode('UTF-8') else: password_8bit = password salt = sha1() salt.update(os.urandom(60)) hash = sha1() hash.update(password_8bit + salt.hexdigest()) hashed_password = salt.hexdigest() + hash.hexdigest() # Make sure the hashed password is an UTF-8 object at the end of the # process because SQLAlchemy _wants_ a unicode object for Unicode # columns if not isinstance(hashed_password, unicode): hashed_password = hashed_password.decode('UTF-8') self._password = hashed_password def _get_password(self): """Return the hashed version of the password.""" return self._password password = synonym('_password', descriptor=property(_get_password, _set_password)) #} def validate_password(self, password): """ Check the password against existing credentials. :param password: the password that was provided by the user to try and authenticate. This is the clear text version that we will need to match against the hashed one in the database. :type password: unicode object. :return: Whether the password is valid. :rtype: bool """ hashed_pass = sha1() hashed_pass.update(password + self.password[:40]) return self.password[40:] == hashed_pass.hexdigest() class Permission(DeclarativeBase): """ Permission definition for :mod:`repoze.what`. Only the ``permission_name`` column is required by :mod:`repoze.what`. """ __tablename__ = 'tg_permission' #{ Columns permission_id = Column(Integer, autoincrement=True, primary_key=True) permission_name = Column(Unicode(16), unique=True, nullable=False) description = Column(Unicode(255)) #{ Relations groups = relation(Group, secondary=group_permission_table, backref='permissions') #{ Special methods def __repr__(self): return '' % self.permission_name def __unicode__(self): return self.permission_name #} #} {{endif}} tg.devtools-2.0.2/devtools/templates/turbogears/+package+/model/model.template_tmpl0000644000076500007650000000103011153607757035575 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """Sample model module.""" from sqlalchemy import * from sqlalchemy.orm import mapper, relation from sqlalchemy import Table, ForeignKey, Column from sqlalchemy.types import Integer, Unicode #from sqlalchemy.orm import relation, backref from {{package}}.model import DeclarativeBase, metadata, DBSession class SampleModel(DeclarativeBase): __tablename__ = 'sample_model' #{ Columns id = Column(Integer, primary_key=True) data = Column(Unicode(255), nullable=False) #} tg.devtools-2.0.2/devtools/templates/turbogears/+package+/public/0000755000076500007650000000000011240527554032061 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/templates/turbogears/+package+/public/css/0000755000076500007650000000000011240527554032651 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/templates/turbogears/+package+/public/css/style.css0000644000076500007650000001167211160337245034527 0ustar markramm-christensenmarkramm-christensenhtml { background: #555555 url('../images/pagebg.png') top left repeat-x; text-align: center; margin: 0; padding: 0; } body { text-align: left; width: 960px; margin: 0 auto; padding: 0; font-size: 12px; font-family:"Lucida Grande","Lucida Sans Unicode",geneva,verdana,sans-serif; } a { color: #286571; } #header { height: 132px; margin: 10px 10px 0 10px; background: url('../images/headerbg.png') top left no-repeat; } #header h1 { padding: 0; margin: 0; padding-top: 30px; padding-left: 180px; color: #fff; position: relative; font-size: 36px; } #header h1 .subtitle { font-size: 60%; position: absolute; left: 240px; top: 70px; } ul#mainmenu { margin: 0; padding: 0 10px; background: url('../images/menubg.png') top left no-repeat; height: 38px; } ul#mainmenu li { list-style-type: none; margin: 0; padding: 0; position: relative; display: inline; float: left; } ul#mainmenu li a { color: #fff; float: left; height: 31px; display: block; line-height: 30px; vertical-align: middle; padding: 0 10px; font-size: 12px; text-decoration: none; background: url('../images/menu-item-border.png') left top no-repeat; } ul#mainmenu li a:hover, ul#mainmenu li a.active { background: url('../images/menu-item-actibg.png') left top no-repeat; } ul#mainmenu li.first a { background: none; } ul#mainmenu li.first a:hover, ul#mainmenu li.first a.active { background: url('../images/menu-item-actibg-first.png') left top no-repeat; } ul#mainmenu li.loginlogout { float: right; right: 10px; } ul#mainmenu li.loginlogout a:hover { background: url('../images/menu-item-border.png') left top no-repeat; } #content { background: #fff url('../images/contentbg.png') left bottom no-repeat; margin : 0 10px 10px 10px; padding: 0 10px; overflow: hidden; } #content .currentpage { margin-top: 0; } /* Login form*/ #loginform { text-align: center; } form.loginfields { text-align: left; width: 270px; background: url('../images/loginbg.png') top left no-repeat; padding: 0; margin: 0 auto; border: 0; } form.loginfields h2 { font-size: 16px; float: left; padding: 0; margin: 5px; margin-top: 0; background: url('../images/loginheader-left.png') top left no-repeat; } * html form.loginfields h2 { margin-left: 3px; width: 80px; text-align: center; } form.loginfields h2 span { background: url('../images/loginheader-right.png') right top no-repeat; height: 30px; line-height: 30px; display: block; font-size: 100%; font-weight: normal; color: #fff; padding: 0 10px; } *+html form.loginfields h2 span { padding: 0 20px; } form.loginfields label { clear: left; float: left; margin-top: 5px; margin-left: 10px; width: 65px; line-height: 31px; vertical-align: middle; } form.loginfields input.text { float: left; margin-left: 10px; margin-top: 5px; width: 165px; height: 21px; padding: 5px; border: 0; background: url('../images/inputbg.png') top left no-repeat; color: #fff; } form.loginfields input#submit { background: url('../images/loginbottombg.png') bottom left no-repeat; width: 270px; height: 61px; border: 0; margin-top: 10px; color: #fff; padding: 10px 140px 20px 10px; } * html form.loginfields input#submit { clear: both; margin-left: -10px; } /* Sidebar */ .sidebar { border: 1px solid #cce; background-color: #eee; margin: 0.5em; margin-left: 1.5em; padding: 1em; float: right; width: 200px; font-size: 88%; } .sidebar h2 { margin-top: 0; color: black; } .sidebar ul { margin-left: 1.5em; padding-left: 0; } #sb_top { clear: right; } #sb_bottom { clear: right; } #getting_started { margin-left: 20px; } #getting_started_steps a { text-decoration: none; } #getting_started_steps a:hover { text-decoration: underline; } #getting_started_steps li { margin-bottom: 0.5em; } /* Other and footer */ #footer { background: #fff; padding: 10px; color:#888888; font-size:90%; } .flogo { float:left; margin-bottom:0px; padding-left:20px; padding-right:20px; padding-top:0px; } .foottext p { margin: 0; padding: 0; } .code { font-family:monospace; font-size:127%; } span.code { background:#EEEEEE none repeat scroll 0% 0%; font-weight:bold; } #flash, .notice { font-size:120%; font-weight:bolder; margin:0pt auto 0.5em; width:680px; } #flash div, .notice { padding:20px 15px 20px 65px; } #flash .ok { background:#d8ecd8 url(../images/ok.png) no-repeat scroll 10px center; } #flash .warning { background:#fff483 url(../images/warning.png) no-repeat scroll 10px center; } #flash .error { background:#f9c5c1 url(../images/error.png) no-repeat scroll 10px center; } #flash .alert, #flash .info { background:#EEEEFF url(../images/info.png) no-repeat scroll 10px center; } .notice { background:#EEEEFF url(../images/info.png) no-repeat scroll 10px center; } .fielderror { color:red; font-weight:bold; } div.clearingdiv { clear:both; } tg.devtools-2.0.2/devtools/templates/turbogears/+package+/public/favicon.ico0000644000076500007650000000212011113340244034161 0ustar markramm-christensenmarkramm-christensen9GIF89aM]]]Cqqq|||ӑan/-.ͣӴ򓓓̾ίuRƴZ0T%`ԇmbn01onniiiؐiV}QQQGGGC&ÛT*fff```sA.{-M"WWWSfAZ2wgc[Hp$>l1l:pPI򞾜jlqL̞沶䌍beiۅ=ߏ썐nqvwzľHuuvՂLMMSUYzCt6\_cxxx󅉏NPS]`d2.on:::QSWֶ˦PHfhmABBöƻ՝ISSSbcéssgggXXXZZ[ȿ|$##ͺ!Created with The GIMP,4a!y3PeHfD$ <͊HXMc ʁp0:Hctq wbE'Ę4iRx{oXBQUGZP#UR]  t-( ϗ.5Q:TPiŚ(ьlj16ls"@˹kexK#F 2>}\bD*$h5 碆1cb6q#U0$#_NH D蛬`-a@;F89tg.devtools-2.0.2/devtools/templates/turbogears/+package+/public/images/0000755000076500007650000000000011240527554033326 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/templates/turbogears/+package+/public/images/contentbg.png0000644000076500007650000000063011121106676036012 0ustar markramm-christensenmarkramm-christensenPNG  IHDR *sBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATx!3$x `="&h-I5x:*K^BO'7W|^(o1 CfmNoڶͬi;M4+O4un$Iu:s8$pH%IUU9S7sJ5INSʲ8qLY9Nn_mn6,<\׷$EQdf^g\fZe>X,msr\2 ÷?`FKIENDB`tg.devtools-2.0.2/devtools/templates/turbogears/+package+/public/images/error.png0000755000076500007650000000524511160337245035173 0ustar markramm-christensenmarkramm-christensenPNG  IHDR**[sBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org< "IDATXŘ{?ܻwa}JȻ*AUS+>GƤmQ_m_`5wҔTk‚# vDz ,.3_;ν{wAܙ3};ߌzu?&+D&Rܪ)JuAm' XaN}k"uV|z 㪪|9U芊`F]{92IǾn9LWնn;tc/bҊ (oJiUnmi'?pYeK1ގ• ==TϜŤٳioo{З,!ՉB&̈́)&-\DO%ILE?For|\ 3s&=Z4B H[ʈ̅Zku\Kns THU -b"ax+R H>KZES񏔬:A:OaJdH:6hƈR̘U8r=; ([`d֪՜0{j}7ٵQ';?>୩{hkerqxCdURwSev!L(c sLzq =Xa֊J55M;Q4ZK7&$ٹdT=LY|ElOOP)F@Fp15[U3}ۥ"GSW_E[S#\^35#+T(ȴdۨ޼zOKBFT:JJAGۚ9R4sgg~ )Xq;p ;'xٯā'iQdRcɃ7-@ J9gx<ĂA׊;lZ\ R+"8c)E`SWEqS.OB~XKZZWASxrk] J8.\ )vŰc:"B<߄aR:#8kK|G& ʗ =^S pHƞ:V!Pe*DJX &C]N؎ZR)&%<^OFvx !b P %Hj2{ ?/kɇU` \怳qdLO=̘s Ȼp'.< ;npAR`N87\jQ¼ipV@(4q+>/#\h]G Qa*AE+)71+|rԔu|8F&=* r|2PQd)gR vjnB>9(p #hOT`"XyuKW 7t7sW$wdK&AUjmR8.$D~u&9}tI]m9 B;n"fLqqQɻ42FexmݰlY!9C>)j(|᱊D~G ."px\:r(Ψe>k8N~)a$(e1C#T,Bi(^jvR8 S~)ԩn L?]RE P8’&$qq2dW3Dn4 .g cU.RWL'n)<)y eaC*uT Eu Vn3_n ex.2%G72Vp\Av@ _V0},F}__SR*Օh m- }WLP?ZQ5)vV\LzEWsiw^)8[MzT-R)ȌCT 'bp"DkIĪ" U 5 !PhF y;b'+Q}ۤ0-KRaSʁPMcHPkݟ3m2ah9>%9_>0O,8[<$3Me&(p3\$)2HdŰ'^ uRCש퓯L MZ89>ٷ< /"F!Aw0 Ѹ̙s2RU xD;Pkd4O5iPCgt"t<nYbXdw*9!_ ci2">ܑŠ<^?'uQ|.Q `cw PP>f%D&C3"~Q5ֈL?%# DJP!#3]-Dob2sr:qo^RJ0fvR ?=I"TWDJ *NIXT/JP1;3'Ax Gr'*w@څ'E΍l8eFLP1Ȓ(Q(y 2rّS$pDÐѾ\Dhs$DI#mHILL $s.1m- 7Z_sVJC-w+Di]FA BfW%]G`L1,.֕whnK(I/xL?u;a^,2xBFQzs8)"{G6yp֪v]Ԍ8Yܱc\X=r9(ǽt8_3xOܴ; -{Tdxq5ZJNXM ZDN\K>ZQ̗r$&EhaIiGtV&8L 0q&>S$q/2 VmnDu_kn9+Ek |c0Nd9 Иuȹ~*⎶3' !THxTb3 YuL$Ko6QU6ǪI+f<972ԓ)䍕mjR$q^T dR@yRQ/$\s1.J++*C94)%gD9.3uB{~zPq$ޕ$0$ūjT*VM\ceOoZ/8A[\&iD&w(TD#4<%ſ3u`lz<@bt{Mn6Tm!t^Bh>u%&J3p2Ձ'ׁ#͔w2UmM.)Pa1?&`,7o߇w^'.n4!ė+ MpGzp KݡR- -炖!$qZ{S$6Z%ҵ24*,KlZC~wp!vzi ecx/${|C$.Kd쐏 Wg@f@̒&rh^}({"Zbn ewF.E5i%)Ġ <'bsWf'|-soK`Vڛ*J&%QBW;|< \+ǮU5&[s0N; #" ;2S1cdABq PmA@xL -c)N#iq{ ,H cD#y!tsJq}850 PpѴHhY|RuebT+IX n\cL,Mח% Ji }$K̔l9JNK^>Ԑ8ڬī/$IA (*Z)@[vDG=\shW9$Ӵ2g$aPDƿ1~~8yI 84o޵I̍[2Ixρ\Z ,+!ȈV ?ڑ.!9TME% 鵔$эfAb`Hx$PK'$6N}%c@!7?B H礃mBcJc rq>> cpD܊B֯.W$7p٤lg/FS\v& pw3֯aq{]i;L_p㊳ar6+yn6g VQH0:ID 6k ſI.A!@;w,8G]AQ'hFf;.&6U[^D(ncu0P4s@u@$HTXhR|C"J@ N>NDM,UdyP|VOKD-` ><'1 #+P|^*nG02ǣfmdwNZ6>j8oI 7yi8~c [xi2Jq1\w,o?>{o:o) ކM:KvA=Y pZ#IAƨ(d*Yc5VHZA>pv>lrV\f=zKv,#%ѥ)gXSS6 &PPd#ofF*bY*kp|GLBOc2,c8]!B!3YL3IZG6J/war>_iKTRrd8Bt IDAT]򻡩y`(0I Z$B߫ڲxiݸtUk: 5csdVQծB̖‹(eKV~V7oN9߿|oxYW,nӈuǞYD] Z:ӥ1Fʒ)Vok/9 ?}tFZnϔ:[38Q02=,m9lA]}h*d o?W]4 b$r^GxD`w(>|0;_?ڎ۞8DLI6 Ҙ}SlE QgMYL -KXd6$7f\>%= wTө lqnOwz366#`zG~V 1},]rF/"WD+i> ^$B%`8Dc wOB;ZcP-M29z#r~AXgk0?f&К9 > xAܺoJs= Q|Ȟyb.][oދeBDh*/i6"|^jM;UxV|C]1=Dqc@*fI'sd+՘UzÓcjF`'C0B{2كsĠH'{P^ɫ.Znl1NRNͥsgs7ŗnً|!L՜5o:dzsi\pO u"gC]Ǖ?y7mYa/33s]<>117: }uiHFdD¦́E5?t嘱toY =WVx)")</sR>q\I  : y&A⥠vc˵dX3YCZkMF|ccFs~Tx$s>?S]2!ӹW/boÅ+*OD:!8'Jd \}*}ç9XA+³n/,}1`w 7[G=PfߌOLLiG+wELC0&ruR3n U*%p1!0%$C @$-zĐתa%m2߸!/EJ:A6MFXεQdu;a)YSP-tiER P:f }j|MR9}xH-q÷򳾯_` Na#Ck6XքfIe+q {)T&L0<U>}>6ߝdؗoT\Td"R5Q-eSC*S.խXH!Eyj73`!Lngn, plfbf>M{F;qz_~*1":sQc [yx8~NcX(+2ig*@B)|RFҽheR~ݤȗs!z̐'}In9.J!7!ԩ9LB'qc>S~Ct6|垭Ḟ6ڞ^֍v>rr^)Eٳ~tWV:iV&\<ЈLy8;o?w q>ЌlGzN\|"h݋Cq5p5Don^ܱ6 =,w4a\r,ͮ ]Fly2_< _%yBi]> ڂڌwo\cmnlbFL{&LVpP`}Fpa|mxk)6¹ŸgphzB,ڋyj^y\}h_i s69ڍhM? ):6!_Ht tLlpTl9'o 5SB0/;,%3QU'{B][û~1$RؕlO5mH Ӈ+~q/= iù-[]\(@k<.{>NZ^tmc'^ DNX4$xﳋv | +zБy9`ځI|2!ڔdzrdV={bƅYɏXf<ąz?$}ʹPc({w-f3D`i {2N))=k2bюO\r)a&h 4M).! L|kCػB t`fI)NjV@r^@UŲhX8t=*Pg,ۤ')J2$4W}~Ҩ QGOў|v(e(^;>iti3~gmceRWSI/lhoâh7 Ya#Rɦ÷/^EM:؝Ǖ?߶X<:Zq)O~0n޶_z47h+__I1@nڍ-/to݂OaL勄R9L(-7́Lۇq~W_k{Ԑkn$LM9Dn;acU41 5d~Z)Kchqh*9[ {sUztfn'Z<>v#vD"* m>?w|~|Mg>_ܿr `Vy/m(%ɐHkTۡ*oJ' l R7i!1.xX @/~: ',psThAKaMM:k(PƒPw(|ȵΔ?- CFam>e@K"2DlR.tirgi@L$ɶ4Xd;m|xϙGIuNGvrRG5n2ML#l“X&oҒǯ:OZNiYc b`Z{A 8@FDFnܲ^[ןF3ZmΣ#Z5]Y<:<8iqu[\{,Cn6Heb<5dE(L8>G [4dž4JXIqK6QnH1v|dV;@S?^0~ eNÝCGON F:B&'1ikkLBjS=Ls*-ǡ֌yM,l9T ` t@v.CK!٘ BaU ~P g!}N!H<pghHdNH޹)[&QeS1! i!J_2MxttKpIs<)%IkM Ƕ+1t2PEQTW?M?lݧv'[09/>wI¥-`|6td Wݸ#nڍo2`x[[P8rXh(qlsEj-nSg" t;{9|C3\x߾P:Gp`l2XߗbG^Am~GHu-A~xXk/Xck|`'N,Q32'1 k51 ǙW>El+|PqpoT4XG S2}:A.U&YC_B aeshQ}LaROs_?%PC>$` LBwÜ2PK?tIg-CŸRzƆO!P7 fqgDeq]Jz߼CJD0Ej֢C糓B D o9hX ֜+&TԩB}6Lӿ߬ޘ5k\@nڄ_?e:MO,r c-$3`py Spm>zFX jm!zs x!nޢ$hn+o=-)㷜Ku҇E36kkfЗ{ ԏ]܎SV0 ET(Aj1E>JΈ߈QJaR&ME6VI*RNlJuJH#V*F%3*Ii*ֶ4:M+ciysUZʺְD10KcK'䲂RC-bNrH{rCHoZK,ߐ2aC":sHX$sA1t~-ֶq쌆6&!ERr:0_xJ=* 8n=`:ߚt0!~MT)!lLO|\Ą ^ݍ90?'1Y-k>q R}@F)aScKיHHd;gTϴ{NӬ-޴ 1ҽK5Vc01+2QVH1Y>Ŷz0 H"b+K@sfOF:>6>1L/Xlf;"9R}05$B wQ쮂x%qN:G'JxmLמkm7ޭisVP\d >0O|^cD23Zz[pkOB:E:$ 3&Jؐ,W-W-g*'Xgo".bS r<OdQCNu*c ♶.["fzN[o1KcWD3YK]j)C> bѦE)`bjqLpH }cB^ Mc:v^N+2E[wįw6Jg]O[ȥ+m ȥ$ į=fEz/>i ^|R џu?|Pu$w%W<[kI. b4&]8e

,>ϭp||Ÿ`' ) QaOOɚU@bCΑKoR< IRu)X)ivlғdaCz "i b&_P-}Y,>!q1sPlh -sxr._zQT^J-м)kNXVK/ :3t6QrMQIP*r IUň I,U8EJ-(L5܁&'>5d[΅KS-EV`6/Xy?TLJwBO-i ptg%ig#1ZH#vPS(]݀BaPWЉflkb\7~}Ao.#.ׇ?\&'Bleǵ=n+Haf;~?xEkJGk׵swa)F }W`:ysLhax _(p֑q'$mv:\D˪(ݯh7_*naF#`-pX D5<5ٷN`*njLgJvi4ᑨ =]TLjaARJ Dţ(NIQɵ@iF eq}#8PM18P3 ~qhᢔk`ё1;G&ZJv\[neu,<<ahj$qaDMA*™0y #]w9#'n> t-?q|j ,'Dջ'jD׵7m{GZ@ y8api0>'&X4L =k%.,nM)Š NjfP[weA2vͻq!|S/cZcZqQ|AL#0'P),''f-8"HalؐRc¹Vs$40*5b@Iؼ%/W7TuGj΄Tdg N,]S> "YLM@fm+4ZP%#3?/Y`2 aPK@#PPwb`PlJU͸35|ZfBpr._LF6=!94S0 'KNz,,}U͍¨,oM㸮i+7cdj?}y8yI)މۇqgo|oh/, A~6ǴV̟klr]R;?4wG6]%#Fx)߭|OoI)h1KuO}*5oktҵm8 9j~~npUEjXN-rD?%S2()D8e?5!pEھ BՆ\wrSZja4F uz ' IDAT]&r)?4t$Ǧivil?8/t۪bQ/ϘҾܺe?013l; a"<%snfٖibI1x.]d $7^`Vy5DWR6<'Ma\k\!Ȅۈ(N">hֱɱ)[qc0QKlj$J^xIፇ2i`UEO<$I7I/&)άd:_x[x9r4fJ l9 +7o)I軫Qu3)F|=2}w؎OQLADKK&nճf\RQSQc3##CqL_+` e~{R拖?|s\Ɉn`jM1)f(Ozv%q8*L2Q  ((JMp`w+pFÝěheȇEaL`RB.nM`(<52TOˇ|bԡ݄µ4)A"3>-N4F~aW &uvI ]ݍO1/6-3$nt= 4No_^U+Zpn>0ZmMXkB:f3( lENՋs8ϒ&<.txɺ[vjE)P:JeJ5%c?p^\xrl~{jn#*UBKEfyL> i,yܹ0Z!kU||{vqAnĮCGbtȄLeT*mGںv05øG[/=geik8 _x`o3n M`h\ą-Fl#M,LIm;T%eMqQ5S[\e}H&g%!ȆOoT@\l$zZ} }j)gT2QUNp9ԑ1ÀPC &~O5FJ )!Aצ;X $baǔU7&<)mFqToߏ@41/ Hw!j*7ū8CC(=:/ݳ>hZiC3y,Qۀ]ZU+ ҭ;O (bx|lv48ex|(B_yd ]4מR/9۸F%@CnTE8mQ#"1O4[ׇ:cal*|dq2!۶!ρTk3W781 ,.]ـvcxw·^{&zsvatz"DDml)LĢF_R0B҆(>;-co݆$nL~|KoȟcN4z-dL``[.;o0azښb6@4۵u c6N9 B둟w,ҔI =EϢ{)q1.K ZKI:PLl-^1+IAz'`(ၡQ'j6b#f 虅̡Y\^ӊן(GYތ]|! 6(݀o)< S]XބKmt4<<ƑYI8{i72w b^2'ϝ5c Ә"ѣ<48 "R:E-Cdr$>t>|8sE7"\q7NJa1YS,. SEt>q#u sGnٕ9m~'zi]Ʊtymʚ7?^ w!O^v73oT"K|(Eg 4>pjGLPKkft#J-x-,!'Or;Vא8T`Yړh2>n;h ,"R z0 q#&K`&8¢z}긦T˝J5б+j%PzM PM\ɤNTCu1m ?|SE'qjNGl A͖]sEEE6|I"tunpp݉,[$z=UZf3r<<l84Kr !,wB9);@ n`VQSzQk?(kb>lwgu]5!oT2/inwcT$!|aO8y0Xў%G}6k où!ɢ צRu ߹g'^w |񞛇IZaѸ۬F4&N$lD Sr'BԱ _Vϡk_ dG:Ê2YmC7#e!8ԍ9 CBz16> fA\I76*0p:xT}èRLf%޻z$Z~̨IRRѠ APظD 9 ϙiʀfݜM ԗ1B529Qsx=ǶC=5(#!vpFj܁6 I@ \3yIKRkC!F%^)ErNNqʝKwce3a|vDDxˉ]أse>"e&{#ލPȃA,U=WjVk|UlHԇ;-`T7ҍ;~{XM9Vwek;}ӸvSޟKahrsT8Aҙ|psBQ(")}|L16<斢 LDx)9'`]{T]Be2Z;E%$:ٞ"bw_?$3EbӵwQySd|FTSC0PĀ'_iB>ݍչbHo܁f-x"_G,9cT^l~o9_}n?x 8' XXS*CF'„!T&ŀJ]VGs0V,"f $+9+g3VtaD`=g=&܁bRHS< :9)pP'~mD9`)?DvRrpԄNU׆,TXGDZw>RX3jdEq>qR1,גQ49Ŕ]KHs6a kE Y'l+YN9IJ Mo` PFɺe`l3G8c@g%!I8ֲGS[c+plu^e*彪0Lg hD 8`S HG: >#C)RDwfn˚(n/c#m  Sxyyyq<gqJgFJxmnIamNapFAohϟCSZ&߰wǝgVFנ2dw|Po5k2i;qņCxQb1>Ď\}Y2{v`ǡ DNE`I\dI<{,.8Z\d`"y}'/(׌҆O=0*m+q U6O2MN]pZoh06sL0$x(]Bu&$W;F4O/+0őIݰ@̕%AUubJÕP I`kO<)R+X\l'IeG.3wfkײA]0 gk|B[mHcڼ#$ B@IHLzF@NG뎛zf8uIk6"|vcW78P2%aq,*`C>r|ܣw8.m8óRs5m;vW#ŝSxъ9ge&)##v܍N G煋;ʏǗbtg,Nj݌ ',j|]wֱ9 3+\9띙=4Z{xrq3&fiv+Rʶ0L ׬mGA_Vl?m[5&!1\&=:|YT4ǩL+ۈNrhn7ԅ;fq)qkI';׿~?(KU/"}%9w, ,\I:Zgfc sp/بM *^)@(D)ͳI -qAjN9)cs9IZi+]bc1?f?3w3E")CDLLQJbʆCk}Ra92*jy$'LdQQȺ1t'GqRYztG3| U<̿CS۱U"ܹA8&UIj"wVXw6OmZ1[Rӊ ?TgOdv?sĜrb [Ʊo*o'5x&3ud^L hEiԜY[ #nkEWKsjkO׏<:oĈցL죫׏kklFazQKDKf޾ar &[[#6!5IþE'0( DKE[nW04f|NI-w-L›m3{0'gКޡ8~B&x$ AF#l=(܀;x[6+FR+p$Ad.08|bC5?Y5ԃ H'?1JdR:D}B7h0y5^GIۭ%"S!IfMI5^S}IhM@-:Y=y qܸ3yH3…=ݚi D-#soh7v4?4o?wOoD1ГCCkCծͥ˥q~w-{/ݻyH5$|3k^<Јeݓn6HYfMXL}'gHw6ƃX`M{ڻو5mGp6 Y̥qA9:p=zIA34Mav5gp¢RmXv6l.[݂&}߼k }`İ;F5en?P*3~29"%$igc>ouX[wONҵ\.wctWriֵG[AQRt.~$hA A(9a~ D"2*@wЇ1DSIf5t)i!D+], $ MFrZ\.nKFM֐X-azf#) /fڢ^-D]uǙǘ<@z?߱=OWFIsl?2cEb\ [VB>{VܷoQc ˋ_&mݏ\:xxl.458-x`?޴,J!jl]*1}EЭ/o˛qx}y윘d#aYSʹ@QăGA42@r3S~dӘ/=pngm o;o;f 79C3+`YK M)tfeݺin_aL~r%d2}!n[jx )x @Q~grf^DNDƖ;S~T5J}LPb!(A0Eu>T'זYPL#qC\?+I|dXqNf" miЖZoڃo> Bnk~W>lڋW; fX˒oy3bEG@("B(R"A#IB㱱=cƯO?ܯ{o߾}V~~Tծڏs 8ҙ{޵k׮ַx\зObK5u&~pWc\ݎ ;ƻ^̝gn\yT֪ ~}7N?鞻Cp/X4KxCL\JOwY# ÿkXjA{ Yw/k7b?5.|4%km$<O~~w]`O=X8mv>p>3[)j;OADH.ÿܤ@atL)Gq7%SpDEAL*)ٻXrlDr-:5H"Z#̾:(4y /|ZS`:kAE={3y}Y:yI*v;;ҭqU IDATI|:] Jyϧ.9C;߉٠CXT+ωFBE󖴦5~^y~?G/ .A7"cJq]6 -:~>w x̮(r( w |o)>ۧb,3_͠ lT% a)y<+ͩ~K[#h|#8"ML6\D>ewk?|=b_kPit{"~;`jNq;S|7jץřah>tPr?hBdyzoY*XۨINv׃P[>׹;r T{ +[ZP֗lPdU~=iQS1}Mkʾ7:$ .v!;a0a0{*ܶolW:AM@k;e,^@R}3kO>@9_N_>G;+K/Z?Nm'_xK]Wr&n1~C}E,e֣ySg?~L=|SÜRZ.oMqpO=nEP- |?O/o&dLHem^{/rԘд.[zcgKx7O|/`٨/3|]Ǐ|oxg@I.[5ө6JOY>Y27 A$H ۞=)E ; pN.s׃ğ#m'T]gY|nSnZI~_Sy5! OA_tRN'j&Yc {PW%]i ZtqL"EFF0Zb_\~j]G/2;MT{[xܦqia_xw M/CMc3s^|uc^BKאlJ,ZKX`d<3 ==hz>mdCsn21*7R&,`G3pÙk$;H./7@Ľ}ɂZola&}KTi?~ N.lsw0]e\fj"h7yq>I1U摧0jəsH.sN\|udLJ߇WZmdwk}=|i^J`#`\q$+ r6v7 Եw {x|!>y6&QL;yaYG%i&=<͎>Ͳ3')hi Rt 1T:1 |p!>}0"#m`Yj}ihEvlAmlk\i |~>w7zg/{u?|S;_~!xR?5JIҜ_͎sVQowglQ'H`YqH nn._9Xqc /<.Vw[ȍaҽLFAZӜ Z 57+iLƷRh@K$GĖUsn=Zwm8"u~"R_:H`zA67)%9^̠ܖ<GcѠEiIu'N'HV 1TVl$-?vQq\=GuOS7헆4G[5Hp/|{]4{܂"o~)~bɖccP"o^3]Jݒ1YL3XsM%- 6\69ж ODI&ΩyO0>~ rDO[AΈO܂WC"`{7 Mʲޫ Z$&gWҗEH[7 B.ֽw@a9Chx8u%@Iݮ/PM+ީ- 3PDƴI73$o;Vm)f=TzUؤCOG%XRB^;oz2WTvoGcxҮHP}zf+I n5~慛ٯNj x姠!+0>ڽH2 "9{1u - >cLt6r_k#B-B]$ 6mXёLm-e$Ѐ_œhO\Yr>eDwo\_ ;f0KsBܜ1WuecBRy V8#cSN\DEY˧3R5߱mZ3S7e Gq7$W2YjmZ82*gm;! (x^8y/&)Psb(󆴾7Od׹{3ȓÓqS džeO3OQ#O:b Z`p (},aJ%ܹ{1x <CdG@*ibnpE~hJwۺRߋN*v(P{[C,Q4CJs˞M&|vZ vj+b=7㳥{8b:~f)ÒBn?#Uѫe;}q2ĊG"V[ut|ǝz]KxYI3"%U*?%lIŻFJ@+`&ggm@ H8sy 7[S5(MBhD >#F;uVlbJjc%-y*]Bz&ic}#Tshݱ^<һT5X|oox'OxzXaïށL5NVY?<@2] Q SA=FƊ طG,kaxq Ԙ_@N9hHc QvVW 5ؚu5\G%xqA&K-P: |ᦊTy]vɳ |GI{9EΑu%qNNGrr =Mɯ-y!;jΓp#F5׆^9U-aåY };$n[>i;f(PMmPݪ]:[p!x5^,Of0֋j.!9Bv2eHg\U 奣=7>عu\]Ў" Km^w~J,PyJ0jx~T#xu晔Xxq pqFŵkx2 )[)F`oS W pVA us~*߀pok>Y/`$-ׄG!'&K)jV(*61qcS 5co:;={e[ Ȝ. --kե*8TVTǙ"9_ dUi2N NU=⒨svJ+FLCPNxy8o6Ɯյ M!j3 L@ҪKx> 'tC-%99Gc  ƬL]^p(݅%!-6fRGjI{提woqu/&;V@WJ)!0 ;<mhblR$ٚ_-<%d!ED`%8L>"[S~_A)$"@9 tG wy'E/$Rzġ~pB x^RX3GBɊMxdYe*mFRɏ=3E:,2xon-xHY{C-iI`EW}L3 + ȋ(m$D,s܀xl S`o!UAa~uѺa]|˭XZYإCNl~S@NkW~砜Z›[7AH1L0 @$nQ3Ue \W؉&%Kdp G '536lP"mQ)Z莓Dٵ GU?R561&a:wyzM :QmHA.yF]i.0m:ps̝:"DcM6ѫ: ' bV .4̳ܫDqq1 #E':` g KY&bI\a[t;. paHMc,4V!e•7L+B&if\ 2ZOP ƙaLi1GKK6hR4=5<8!gk :aP>MvhnWrV*<]ܫF]rX@zS"aPy9*>h2X45忨@` .^^V."(w<~VXْȢEw¼Xn&DkDPM7(u(ۼvc+'SW8bQ; t3Bc5Tinc7&! r,KJEh ɪѸDmBjU/v\0(,Ws.S)v IL(BG L $e$@@ߛ zt>1+mmd1r#C3 q4 /ň!c4j~ ;ϜMfx/Hro$K^Eb3IrBItrE/NҴ[jYv@ jP6C6vZ(D 2ɫ _:yxFu1fB"jv|Q 5eQV+q.!;!ST?f87dQk?pwbha65Fʥ+:#JqaDX>sF%S@NZ )v1^7VsKc3ڛjwV ęTHe^1;`@a#!gd쥌6aG<2l<޴p ƒY&8\jp~%(LQ3 >sep#EVbzxJp - g @m Quk296+,5Pp/nS #`#Hj3Õl+Qf YE:00(~*q"H!.Ȫ{x4h[2x2K sVvS Φ,Hx _QlP'(#=uOba(;C%yPn;w̭8m f._vLzXP6uBDփOX m" .M%Kka ro[j %dLם$>^U,1%-X%媈5駜GSh 9& Y7մ04#hS*BfR=Dy( &ae)n8I'x_joM&^yKTRyHm,JAü!ޘ?n<5>=zͺ'B 2Hk+Hwo;e(6H>,Våif*h׹*Ӹyqe`T+!Ls-~$&dNʥFb%9FőASpi߳bA[ 5v n4l@-R 2bK ˕yɅ]!7gΦLs2p~3*- 3,5.j\3Ewh.Lpn 5,L VY3PQ /=`,{Vq![(垫U(%H.Ϧj3m}T-\1:\ j]M։"Lq-gAV;jx t {ZG Bƞ.a16 W3 eڅ#￀TaK~xC8)姸P2'6nk KyrG"مK-\,FT{6tK\} ٰ&KV@ZM3w-6]Px@8"X~:ԉɈֿ7Qs-Ϛk H¦9u'I-)P܈j-!0LU!! 9:Kܙg06E059Xh a= 0ksU=Թ`Lt6%;>Pa&T"f<fR EPvR?eno(.Ú.D0VB946rt>&`G-DPoe,{}Y dHHs/"D—־Sʸxo#@Hg[0 uZ 8z5UFF%7N/~ 7^'&Gao/dՙ(;yVeU+VU{XyP=$ :WMtDg(ٝnO cFa]GsI'cwxAs>$m[u ǮԽ9MV9_ڦ *b\,r)GFv@ZJumy*%xr)5VD&DWnTUUrk)(B9D& "sBBKE1 HIԌ`PE]}MQ7-Rm۹T$fpN>l'&̴k$#9* q7dbX  xMx& ctg-Nq3E`1وKA',O9b'/fsyQ 8kU91"߻r fJ`ݽ<"GhenF ]Ez00dwW3cʺ׼fOeeRF 7\? 4M6xtb$qK8w(ԥCˑ8 *tS&S,%k%/TC'TT+C Y9;ތ2wBm0}JB"gėdbh+Wgm٩ $,__ W(b w*`ĭ0T.{ akZh8.W2Vr1UIIEEeRgKK(Ʊ]4]r Zjh=EZ8wȰ+ *AIE]$RlٲŲ)>S8$J\ز-)U,7J$6;A eaHЀ` e{ךZ2-Zd NYdWT]ZFNQ1= GEDDDDDD j>JteXdZ;+fe_ h"IS đhrل|l \/Ie^)^?C.I^S{41;&ee!;L# bIeZ |w3Ϫpmq>kf6m#xcDoSҾ~{]=ea8Vtֲr'$"""""r3MU"WoڵM<-;p}aVYIVaq/ne9{c""""""ydX8Qˁi h X8v r)rRigI32q N}n?mLufηl&9nfɄȥťcaq˘m~<~t>OIkɰ}~' /n\`e;yۺw2l$0/hz&RonkLѓ;AGw Au+ CMmIZ:fcyś$-?hDiQDDDDDR`YబKsIFy OxY*ϩ;{l>̫/_wü]\=O㟧 9{Kxe&uEDDDDD. e X/Avw,;>̜OMeB|6rg>GdLI3e1(c]fD3'ZiVtr4?`r=7*Vp[ft߽ʶ%?`փg<Nq Q[C44DZ,yS2R @A#n*ݬ iZI"; =<<==1=h2Yk;DHrg3јoh[ٙ,ac o m'_wrN?z/ay2O\V=N8,4Drkp;m&1q: dxoeϡ(?}GQմ,vEز/ƝޖGמSovq-e|,r2l'ܬ>`K~2&"""""2˲p$XKqۘ|m=}םFWL V6Ԍ\fOJ-+p?j"-\΁Kna]3sk͹fOeqHܬM=Կ66V,_KXҲppfX*[WIO󵭷bQ'"~aH׆kg-q&W;EL.nM2j/%Y ^,ԅk;DY9>4d?<6V~;?&0HT\1l\(8L* sX5HcK4?ݼ~73j?_f3mOeKn[x$vPl,c] ӠŜI^Nqy=V2'']tE݊@*œ -V;5a x ӲYe؁Yes|#O/ ]N"'M1}a7>_LZmH!I(1U"/5aϓ}i WAXX8Qa-tWxl82ek_"ۑ⛟`J"vP1.gi͹c-9eݶ ƺoqh+g09$aW b:eMv1+;=^g80 j 6*Wa?gm鱤ߓ^aiۢG8]o;u@䪙>>{SnZ_ϬzY﻾>7_XUߤ oA&f% 7\ q7,pͬ!~\9D>DDDDDD.0їa8 X1Ɲ^ɳm)Ȕj3jVfv&量)6zmڪTi}|5ȑ,&Y4d8,b:Ji4e1}e?τs+!}?XOOlέF)"""""rL1[uFOxU=/}GNiA~jQD+ͺ("""""2XeaumXj3[Ӯ'ɧJzu993c/,thPĤ0ׁ F^(ߑa#Q9k|N%5$Jjx o? 8d`?͸?3ͱW\YU$- ;y+9u hCW9-Tx%oQaFMٙ+:.n ֕#NE8~@.K-nL?be‰Dx3Z{6,_ʹ|Xfۚ\=͎1>OVXFlڵu""""""#!>DGz,X|QmxStWm~g+{X`cbrL 6D9Җ` 7$rsײvM{c|{UN" $v2,wƅfS^)yٴݸAe#O{krqc|w +@ܴS-$MGA8jr:yJ7EyN5FRd\0xc]&Mݳ2 _/ȼesp_˺z/Z- Dn"^sHTDDDDDq' U)xݶ 6H;j7!l֭|ǎSMVYt7Don4~} ^XmE|=Lkgn, ^[ÿyZ}Ecn1D VGqܷ^VN°W*X Sw=;E>WoN6ra⦍? #O_h'N]uI66k֕A*]|O+?{ل"u!v epCdm$ʧDDDDDD.Lkta2LrwᨉaPYbR[gQS᧿m+~-eq~c]r$|}90}9on,"""""r , [|8yⴙe8N>V{G˶`ZGZt&{(ʾ(y%©<2NtEDDDDD.U>kNjmKf7kkΥl{F5y+4,+kYE´,py9ga p;IޓD|-jht늈\,FCLÎs꣺_} 2Y8-?aڻSˌU0}9[ Fzh""""""eZ8Fg޿G WMwtܧםrι 6L]yi5USщ\x5簚i-eۻ6GT8Ωe/ 7&4X([xhڑq4aȅwHu=qmA5V5q6uqu늈ȥ%uhBqsꪢ؁n`iGN'm8 `Vn3r)XVkGnseEDDDDDFӲpeGBab;{zZF{+v26K YRH$བr^;2UeM0TDDDDDU鸦aڗ9L>,}Şа'J鍻XqWT:V""""""d  |8K sG>j:Ϲ$/re Ϗum%Lw1.{vۓLSb/E=q-yȘFll;?^ɴ69lv7tOXٔa|pْḫ^mo6->uA'"""""r%\H?fwO. D(Z˶Sg#'c9\L`K[=QDɬ"W@(~5y=l=c9==""""""gÁ5bE0-{Z$vx8cVcȯ<.Ic|a޹2I$!{lLw&# """""rϰ7#!ǟ{:]|kIsqL=s-vcx_WoW`D3&:2ayp Cfհ{B;X"W&ncbVװOX&eZw'r˕]Q1ZÔME=qO1?boatmI#l3k{yO!JW ukjm8;qt6+gkTeXOd,vu層Ȱ|ٍ͟5,} hjOdxmܹ4|P6;ђ)`Y$}$}0vF(=׈k3kK-X=nL]1awL_O(OJ77_u}"ݩjኈW⫮{xq\3ϗjv匟wX^r5Et&2;Ʋ<}|o}`'z]cp9Ͼ\a0m7?3:,虳PFU7cOb,;tu*H}{]j~Py8'r6;;@K}xq99a8uH.ZH gykL1@OФɸRICsGtL1,ߙU;)ӾkۭZ[lԜzܶ<^>TmDbcYv:Zn.wf;5xv'{2n[<7՛9,{fS+ЍJ=뱋\(kV}d4+mf%h2iHit̲ɯd:ci6SGc]s?3-E9>n{6I;(OnLѓ3+Ͳ3(nkRŵDx󖗰3u|9g9K12/K_Ƕwpw}~|+ngN zl;D-1íq~6&Uyy,(jeAQ+;:sy|Dk*7ƕvSȇBt&(u0EEd~\;"lI X1<Υ^K=?%=4 X-Fe IڱU/Z.?Ӷ4-z/[-l6f*?bU%j*l!T."""""r `ul}Jmռe?'7,mڹgy΀>>`_C} 1n3Wdr)=7ٴ'LO0ɭK63q\NXh{/`=eCf .ޓOAnۣ$`;Ӟ^??qLW|?77pYP2ic yH eٮu< ^>Tq~DDDDDDŨϰhZ^?2!90v<!GOqHkR)6vG~:o3IB}FV&yO}ɺ!v9$ ~|Jw]+77-Wߓu(3ױkhxt$&tqGATP*"""""煽ʥ NG3Γ!5t em `0mT&1g5[BneOE}(q ¸_|\7ϜI^ R}}ށl QY;IJ`L_ -{#C&U.~LM rVoٙvvf|y> AS{bUFgIvYVĴN0`Y u""""""IO/R8z̛ec/uѓOE8jb3 _9$߿xes3ӖBj90g09N|-{1 hH?o#5<+zN:)+Xh~M.`CSDDDDDL\TUOԜYցijKM#7X>#նݕ?d0ń.n\'Px3R6DiLPn37j[w8:3 4q ‚+RAmaޔ8W/شpo?Mck&'>໿袩=uo,*ΐI~6Z;Z5M7CIp; n^wBK^4;EDDDDDEw뉢{ylyﱹfÒv` s0lHظfN;}?x!iY륱%Ζ}ᾀ` 2`ղ; _B`8<^F7C{Ղ\;ܔg㽍AVnL-} KffR>DyxfeP.#ᰓ!Lߋ;8N?X=1Z:IgoS GM6hrﳑa㍵"1kag]ӴIũ|zj#tg56{W;{מrg~o\EMej}7p)F}S ˂ؐkM<`n¥W""""""g]|2{IGcnPs (ڹbLt?a B'@{cl1i籖sjf*@eI*)~v?ΝПݩkgԁc+㤾)@$f=IKg9zVv0֑δ{/,3K3>!=.sT¾;"쨋ܬ%Ǘ/f{]IR{DIxoSG}q bKo?_R_'lnxԘeYP0ϸ{Y ">e{ueXteWqs^njm4Tp(mI2>kx5nj*ܱ4Š8p؍A+T,vQ`縶wfeWDMe3Nr1me$p; Bs| sܳ<'z$f:h?}-s0cm|~Y3xÁCDDDDDL]rެ㣷m5GlݟޮsY>g d]<8y~}ODDDDD.O\DFmS>ϛ;;10l.NU1y l$P^`U;(z lO4iK+p"5:< <\`:a&5`Q^ I W?Oɘ[J1т $a\~. qѼ*xw.tfAǠϵuٿuY>6^y镉~J-t&i2-nLߗܑbl2yزcoN,!7bMh…]1g=捵vew1×>w,| 8y_8~DDDDDD.cmNa#Tޓj2|S_* ԥb}/X "/"K(6D_ۮ^݇RE.'z]S?硛]zUw3z<$I4![CYDDDDDT.=ko]~~1=ݴl^_tz + ^/ocCshjҗ '`,^V 6Nw{~y`2ve.9d@_p":""""""C3u,'Gp-$ \A_< Sx'UG GzG{޺# 4_jx3ze2f C<#2{ܚÌ!y:zt$mM 6M o6IoT~^[qgXKd%T2 Lm&U2^+wx i#c& ڿe؈Ua$ijIxC=W;dZw8z}%̡_ŤʅDDDDDDΖAX6!$=6+DFIxX79vײZvr{[߄7G ;eg%WM8:?i:x=H"kx*=vnʨ)Ϲ.Ȼj*Ό}""""""HE._R_̻0*yn}iX ?eX/ 2:w\joˉ`Gzrvgq4eYE ƱkI7+T8g'B H^Y๗O~ /E kyuMg ҙ5a2tVypb/_LV˂&4hMty\)Mm>du[aɭ$Yy;"L64'yk}G8ܚp|N/}F0nZ FzVDDDDDl9^zs&4j\O(I$]>BYu 2.?|y; 64懑cw z`)Xa*p^5*,ؾHN(P?n RjE$pnIOkr!q,"""""N{X/a} VzFtH_;v.Qɠ '&K8o40PzJǖN/Q qgLoh-eߴ_ׂ-5B#I991XpSѥ\hi7{!"""""#LڈȨ J*""""""2""""""2*9 jEDDDDDd8 rb' a=ᚥ`UDDDDDDĠuv`Xpz1juCbzkm4wɟߚS ]}=;gARlsn_\朴Soo,*dvS\@P!Cp)/Վu,3ܧx+X Xwn,՞hbNk?1=ju~2OSu~˯UddC%ŹcGNY,9xrQRҲ]ba/񃻏+)%5,*&{e/wW][{_>`WWu^S:+/~HJ?kiw/0=隻WRE\/& g8>o. O>,N@dQ)!V1-j:1ڋ-ya9P9 <2)u:֬Vz,ZU;Î,g'0gҡ};(~s[wnrcZN Y.- k{ X>V$g_Ć_=OJ 9MhuX+)ƂiD ؎܆خJ!Kٹe.h)h`MOA/XI/%7/U|CJK1-~`{!; :}l/-{) %$ k5nݫԃF}6Z Dۋbyx#}-u~`;MkI.EJK*;UV+u "iߘ;Ok"mD :MA&%ȤZ pgj6$R9zpRu\AZKZϤe Z+l"(d,\jNy|zP唖h)eTҨD+ &tQ$cr}B5 c%(Xf5piZ7xDq#$H*= \\Vyט4a_c"% zRW@YвƘR uMa]RN,l0T.tt`SX!`U[xIN x+JGRF͑J kzʤE jӗz54L@*R6cTFVA"R$ l~bds%,qtٞٗӭ1P.Ƈi-;2E%bH&)2?~}IID `<5G/·-xF(\hi,HP,|=z vkG@&-O+PR I`L%ӑRHeٝф[>"وV x5WOヨ)|gBZ8 Ik{LMmuWKNǏNO85B2QcTYeO[t 8ѱcG $nuJ2a8ԭ/&RISY<#MF`^bCuF &A'2seXs^:$ӆ C6R}!I~26`1%Qď&FZhφ'/Ie%?rA: Hs+ M@F Vtb*|IENDB`tg.devtools-2.0.2/devtools/templates/turbogears/+package+/public/images/inputbg.png0000644000076500007650000000070311123617233035476 0ustar markramm-christensenmarkramm-christensenPNG  IHDRwqVDsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<@IDATx=JQẁ(*Hc*m)lRuf \\"elJ^ *rY)6hoprF@"է&p 5ৃpsv_ >p՛M*Gey%Us2ܫ;4CL)pRu˜s!,B(SJugfrQEU~*< EUU!x,B+U!XTW.B(s~8fʔ8;I<C;4E[_ k+'peU$=u45'icJM kqXL+IENDB`tg.devtools-2.0.2/devtools/templates/turbogears/+package+/public/images/loginbg.png0000644000076500007650000000222311123617233035446 0ustar markramm-christensenmarkramm-christensenPNG  IHDREPsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATxnV@Cnl^u R.É,zi۶m1뺎mƺc>uc?itm\or2iyo_i۶mXey~/ XƷox{1!c| }Xe,1p||c2\cYmۇأ ÷*ܭ|c %_=crc<`6\@?#@&@v%w&    ;<98d1qppVe*^a1qpp 8gUddnd&   2L@&@&@fd& U2  Lm;~(ydddddO>fi:ǚ8L8L8L8L8d2٪0qpppOwSgVȄȄȄNGmUU?Vx222Up#EcSֱ9p8 p pVx2[ [EA& 2rfc&ʬ}-vol6B>#Xtb?vlu /WrslX#] omyC0S]JWy?wt w4MʸO-`Li'uiOq7>,2`},`<[#{z2ʤ8ƚFb| VpUp Bz}CY*mȸf޶`y!Ҵ@5cz5nƳy]CdbGtYۻ!SkϘAhF@&QQzp:P/^î}!v U q} ySY)gz JYU}(SWJGYhc zr k8wo8l@\1{Xk_ .PwIENDB`tg.devtools-2.0.2/devtools/templates/turbogears/+package+/public/images/loginheader-left.png0000644000076500007650000000051311123617233037236 0ustar markramm-christensenmarkramm-christensenPNG  IHDRz sBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATx1 @E@I`؊bL"8c!`^q x&M)HR\:,K@-!I]?F} Ym$lDM\OL*2 'q?jTnB{^PJC)aRJ ;v(%PJءC)aRJ ;v(%Da0M ;ܔ(a74|dgU-IENDB`tg.devtools-2.0.2/devtools/templates/turbogears/+package+/public/images/loginheader-right.png0000644000076500007650000000042211123617233037420 0ustar markramm-christensenmarkramm-christensenPNG  IHDRsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT(1 @`IVE@@I!7:wkdGXXQJ,=>^16KԺ%>}mL덪"v1û^,GcfN=Q;t]Brw\P!IENDB`tg.devtools-2.0.2/devtools/templates/turbogears/+package+/public/images/menu-item-actibg-first.png0000644000076500007650000000112111121106676040277 0ustar markramm-christensenmarkramm-christensenPNG  IHDRsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATx=nAwml$$~DTq$8(@ЁDGGE/Howg&p,ާvիf< p|I1N! h D@SDk =Og87CuG ʺ_\];LP ̴4܁ܝn2ٶ"g\t]QatxJ)ۮhc:)%0aSKTCRۮh`"1ZcR.DP(,mAq 3aƼMMpGpRB MbsSKY|QRKYxpDQ"M9~qY""_kfL&x=Tfoj, r.lpjVH)a^7>g8?&sFJ }݇x30s;fY8 ċIENDB`tg.devtools-2.0.2/devtools/templates/turbogears/+package+/public/images/menu-item-actibg.png0000644000076500007650000000052211121106676037156 0ustar markramm-christensenmarkramm-christensenPNG  IHDRc3sBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATxڱ0 CQ 2@ڴ"R$gm@o8”5qJ1TDxv7)ZgDfJCLe!P%Z-1P,lKvQ/Z.Z C>jŮ6.0f^#|(P(F W-hvтE=C5jm]aEEC1C b_LIENDB`tg.devtools-2.0.2/devtools/templates/turbogears/+package+/public/images/menu-item-border.png0000755000076500007650000000032111121106676037202 0ustar markramm-christensenmarkramm-christensenPNG  IHDR6jsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<NIDATA 1 5tQC P Ko2 \k!3{&{3d6s8FөnTcMHc4qCIENDB`tg.devtools-2.0.2/devtools/templates/turbogears/+package+/public/images/menubg.png0000644000076500007650000000312711121106676035310 0ustar markramm-christensenmarkramm-christensenPNG  IHDR& #sBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATx=oY羵x5ɈA`&Er@|>Z$fvHfn`v6=3O*u\/s\ì?m~+CsΒ}::*,c)93u !( cQk$#Ncts< K)bi8'g"kuuU7.^@*k$Rw- 9g$e]LC혡 p8ԇtxxK.ΚkKN9Q4SpMtIYS_Iҧ~+r@_9+}%!x pV裌>` @[[[e!-ͧG֕h{aRJ:88?響GO E-)%m}ժU|sJU5ПMRJI-Ч$ jթVJi7Ҋj&T5[sH,]Zbd`! C1ݮ6)%_FJxբ ia`ڟ$8ʭsYXX`̒SNn6*EcˮƾW E3KN?kST %Պp@K@e t= XZǦ@ONn+[ks Be; X9pY]E`czsNW^^Sp}nn+ .ɓ'_ڠo>A;oooŋ~ݮGUb9UڵkzzX. CBJ)) ={L^˗/G#%/!0Z+heeEUZZZRQA!3۞ cK ct]*{~'^8&nmmiggGW\ !hiiI!yNSsn,Y;ёBysG7nd0< r΍2i{9W}\sR~OouwA1Fڟ hk&zGߛTE-%Co&RJ_hfkGZoDJI9O%*p; L8mߞ3/ f6w+/~n0[=ʴβ}+kq]DH7"Ln;`e;}g-u'[On*&犴/Gx{ +sunqk A{~G2 YC&iՑrVerV]Y\v!HaG$:.0@pҐkɶ&6־1ʪTPEbmIu*7eo:5NbZ; zď 3munNCogJq*اSu3Q߀15ޤ8;5^'0$-KCDzi= b-8q>pl *ϾW*A T?ogsE -5 痛z CV%8}~3 _.IhJ:kx|J$MQ"Z|גFh`S!\]iOF}"j&6€eJ1bpb=Йʷ2 OP h:^uk4:WsZ#usF"(dȸAy˂%ya4 j=I9]U]1:TqRAX a8>UbxR_ioLIt)nI"DNa<FW@VS=2'g!P,*B!Ȅ'[Oپ3j2!!NѬ4O@ 0pJ4^GɃ?ęۦ.1N_h۸hXd vՊvj;)81@>E55C<:!{IX-aIENDB`tg.devtools-2.0.2/devtools/templates/turbogears/+package+/public/images/pagebg.png0000644000076500007650000000035311121106676035256 0ustar markramm-christensenmarkramm-christensenPNG  IHDR sBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<hIDATX퐱 0 GǒD!j& 9{zk5֮`fXy_c fZ|=̃kW03 `fXy6yIENDB`tg.devtools-2.0.2/devtools/templates/turbogears/+package+/public/images/star.png0000755000076500007650000000443411113340244035001 0ustar markramm-christensenmarkramm-christensenPNG  IHDR szzIDATXyU?{;83 0ȢUShS1.1nhc ƨI#؂TlZwM\H *# 007󖻝?ZIڗwo{~?aXB)S9V.FȱN> P`'-_d]6cC`9lkQ[W1cty:[Wgc DaH[%XVVҐX}ů)+}Taɼ{Ts.7Ӎ_lթm&6w1 wWh{_l*U,[ֽZDX;[V4B?>gWgq]*FBp^0Bcǫqc-?M̻=E!7λ+8 -]G uA0tT:d[WܷZHfW+9Z;+D j`Lm\ާ6-HZ#A2է?_pK`:̹rL~%pu 46MFX.sǮ(!UPW^pcʒ vP?/˖\㚭~9א/(<@EY%\-obli(-Iiejpή9i人)ĘR: 2{$ģwTMyԽ{@GG[pKzo3}VɜyZt{en+Yg uXV(ȁ7!A:UL^`q-P: p^>c2TXZcOMTV& OaxT% ,'ޣBX -(BZ4caLV JNԉ&$)F,H3 " ӱR~(tC@f'XFlZu,;l}Ɣt,vZ @C>zlL\:IDPP3 #n<}V_]LH@G~{(~ʔ8QҀ@vw/ڃ(j|$j0plc˓]>/'K]L(ذW*s ūfDt-cu4MqbC+>Đ$l_o~}610`%[ڳA A!=@_zҭl ލˠА'1}H[0}Hil=%tW&l Z~~_&REy+4،чśv-?7 0<`0M̶,(*AtGw6^r3b)2~͡g]XI㙈%iTs룭Z<_7JN<ƀS9%B a#LQLGXzR8\%s8ΟIӯM@P@`+4ԇ)R.SpgYm|eI i6O!(m,uJ 8i>RM)kgOCkxe|"qmNpm c7kʌ~ ڔCQ9 Cڷ&# 5T(1SZH(f0qb?Р4xQ<;" Jƭ )õԦ{4Rjs~t~GzW#xyRPiذ-=6XՐV. Q,,BsŌ@`0|i7h>/[ ecAK>ܓ {#2mIC?^iSٲ$K#4 s*^98nvB v |Nw:yʥk@}oSrq'ZwA1fiQ<I 6 `mgVSo 4t m%YV<H"d_u!mvU B%4C,Qˍrv׌׽>I+Ȍʠc.k옙? -TEJ CZ$ NnYWߺ?eWiy{#i8DZ-Mz,T umCRG7Y摤*IENDB`tg.devtools-2.0.2/devtools/templates/turbogears/+package+/public/images/strype2.png0000644000076500007650000000304511113340244035432 0ustar markramm-christensenmarkramm-christensenPNG  IHDR jsRGBbKGD pHYs  tIMEg?tEXtCommentCreated with GIMPWIDATh[Y#) 1u9ϖo>Hg#L@I`/ブ|k|7-<5n/b}oݧu G pָ/e/'^[\Fӏ?xe#%0Y/y˘>S#CVeЇ1M,+Ʒ͔O=BP+Xqq?u Ɗ W#\Np}8#]ߝm`PRLf0=7JZHZQ<!qM8l`å|!]4dXz@, T@ 1;(0`?`Eta*:!^exj"x^TsV\ꌥaql)`R hٕoj83LIB :kߕX` WRv Ĕ&H\¸ˌ5JD}$[ 7cˊ ps,$ "B믲==.~ѸJ^D rDz7"80CshHS? z}3Ux]P` Iz"e8WJfȏVHʒcvnS47]VFCm L([Bim1llr7?ݾ%lx-ם9~"nd>:}'{$kߖ_ySY[~>+@0ܦ݋UD m_tBa Eda/tzŗ9OpНmBPt*檕W(Ɏ}+ 2G=kN@>Rd!枧h!>d¢'v. %ӯb71X0해:J>yBZllIb`^& -#ھbJ2+Cͮ>IB/[*ZGƸ kChFJix#ѯZK,َ_^1WM1v%/*@b6 W <vi zE[=?v*$eLA![@`(50zYMR-NYVD[PHXVfVFy&LA^j;K `hE y `h@>`1 հ>Al7hHb'$$0Krić PFHu@PAIH"7W,fA;`h)#_UY*q'BrH# (;\E٘E\ ąxDEm;\32:KRK]K] ۈ h$ P3D~OVNZ霆`Wi*@Hbb,l "" L[RDRRdbg ZYU|B Aqq-!f&yI!!Iynnfy- fPO ԌP"'Kp]eo..YlL: `fWoL@A (ldfu ( 6 ln: deaQcDyRaDq B^ 'W3ǫoг*jBVYm6 J5! %^~acAVJ("Yr||rAr|Rrm|ArRRmmm\Rj*Жm9KԀgMUMU7U,{ ]h @96.6) V֐ocnや;)' RkkאUꎠ2CX5V5&-}x@8 H1# ,8P@ (k/P!+(("koꨐQ uYR\\jgoGv0١Β%0DA*a]1Ks^MA^^V^^^P J", Ѧ J`|Rĕ4 ))m{n\:X(ک *QHu1Y58@E+QugF' ֹKvAAWAVg/YSSdi0g 88[K@: Xr bh8 h u@ Rg1M^@lIENDB`tg.devtools-2.0.2/devtools/templates/turbogears/+package+/public/images/warning.png0000644000076500007650000000437611160337245035510 0ustar markramm-christensenmarkramm-christensenPNG  IHDR++]qsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<{IDATXřkos\֘ލm%$8;vH'8 *Zȥ}~ ~TM[E@RKU@BJpB|۹Y{^ڑ~fyٿZk*]B~ȧg_nJ$_dBJկRö憧s~l-Ũ8ITgSbۈh{J&]rv+Ykn|sY0m`f[Kc$clqj!pH?\e[GwR[u+tMյ䟩;,ڃj?qE0[~wNwKc$PcS$?H]r:ڨ솆k^p X z2׷=6{O~^XL|m[w- dZetCwޏG6;=% ?6d3%`(`%4*0hi3k|eM وo zZΆ ?.;0+IBX 6|6MNO c7vrۍ.+-1^!1%e@2ul8v5m+ݲyҦ u4*c7# L+ XV<Y-3I@KW4U7_~^j4qFj ڛ]XkLT (oẃ<5y7]iEՊG~]Reѫ@O׻I`Ջ ,̭khK`1eEF5-|p;|Ff7J_'O+glFo9B-:,:2U "_tYoN} 4;pWK*l5z*{;m4qH`MDqdDk׭籬SBk MGqy5Xkl1bnC[Ý%ѣ]zeE)j9zLV"(6xрz 4"vgoxhRYcY,~oG)9mѱ 2ޓ; *y>m:VGďw+.\ Emc#ҙ Jŋ\pF$y*A84^}/%uz@*9k>u^y)qOf!~_PKn?Cm̃x} 7pOJS&O tG}]XS?O'kڳ.9| >}'%(E ~{3|g4:ޫ^9"T:+V5^zb!ȿ_PS_*BR=xgIENDB`tg.devtools-2.0.2/devtools/templates/turbogears/+package+/templates/0000755000076500007650000000000011240527554032601 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/templates/turbogears/+package+/templates/__init__.py0000644000076500007650000000010511153607760034707 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """Templates package for the application.""" tg.devtools-2.0.2/devtools/templates/turbogears/+package+/templates/._about.html0000644000076500007650000000027411173202031035002 0ustar markramm-christensenmarkramm-christensenMac OS X  2ATTRaf$$com.macromates.caret{ column = 54; line = 106; }tg.devtools-2.0.2/devtools/templates/turbogears/+package+/templates/about.html0000644000076500007650000001726411173202031034574 0ustar markramm-christensenmarkramm-christensen Learning TurboGears 2.0: Quick guide to the Quickstart pages. ${sidebar_top()} ${sidebar_bottom()}

Architectural basics of a quickstart TG2 site.

The TG2 quickstart command produces this basic TG site. Here's how it works.

  1. Code my data model

    When you want a model for storing favorite links or wiki content, the /model folder in your site is ready to go.

    You can build a dynamic site without any data model at all. There still be a default data-model template for you if you didn't enable authentication and authorization in quickstart. If you enabled it, you got auth data-model made for you.

  2. Design my URL structure

    The "root.py" file under the /controllers folder has your URLs. When you called this url (about), the command went through the RootController class to the about() method.

    Those Python methods are responsible to create the dictionary of variables that will be used in your web views (template).

  3. Reuse the web page elements

    A web page viewed by user could be constructed by single or several reusable templates under /templates. Take 'about' page for example, each reusable templates generating a part of the page. We'll cover them in the order of where they are found, listed near the top of the about.html template

    header.html - The "header.html" template contains the HTML code to display the 'header': The blue gradient, TG2 logo, and some site text at the top of every page it is included on. When the "about.html" template is called, it includes this "header.html" template (and the others) with a <xi:include /> tag, part of the Genshi templating system. The "header.html" template is not a completely static HTML -- it also dynamically displays the current page name with a Genshi template method called "replace" with the code: <span py:replace="page"/>. It means replace this <span /> region with the contents found in the variable 'page' that has been sent in the dictionary to this "about.html" template, and is available through that namespace for use by this "header.html" template. That's how it changes in the header depending on what page you are visiting.

    sidebars.html - The sidebars (navigation areas on the right side of the page) are generated as two separate py:def blocks in the "sidebars.html" template. The py:def construct is best thought of as a "macro" code... a simple way to separate and reuse common code snippets. All it takes to include these on the "about.html" page template is to write

    $${sidebar_top()}
    $${sidebar_bottom()}

    in the page where they are wanted. CSS styling (in "/public/css/style.css") floats them off to the right side. You can remove a sidebar or add more of them, and the CSS will place them one atop the other.

    This is, of course, also exactly how the header and footer templates are also displayed in their proper places, but we'll cover that in the "master.html" template below.

    Oh, and in sidebar_top we've added a dynamic menu that shows the link to this page at the top when you're at the "index" page, and shows a link to the Home (index) page when you're here. Study the "sidebars.html" template to see how we used py:choose for that.

    footer.html - The "footer.html" block is simple, but also utilizes a special "replace" method to set the current YEAR in the footer copyright message. The code is: <span py:replace="now.strftime('%Y')"> and it uses the variable "now" that was passed in with the dictionary of variables. But because "now" is a datetime object, we can use the Python "strftime()" method with the "replace" call to say "Just Display The Year Here". Simple, elegant; we format the date display in the template (the View in the Model/View/Controller architecture) rather than formatting it in the Controller method and sending it to the template as a string variable.

    master.html - The "master.html" template is called last, by design. The "master.html" template controls the overall design of the page we're looking at, calling first the "header" py:def macro, then the putting everything from this "about.html" template into the "content" div, and then calling the "footer" macro at the end. Thus the "master.html" template provides the overall architecture for each page in this site.

    But why then shouldn't we call it first? Isn't it the most important? Perhaps, but that's precisely why we call it LAST. The "master.html" template needs to know where to find everything else, everything that it will use in py:def macros to build the page. So that means we call the other templates first, and then call "master.html".

    There's more to the "master.html" template... study it to see how the <title> tags and static JS and CSS files are brought into the page. Templating with Genshi is a powerful tool and we've only scratched the surface. There are also a few little CSS tricks hidden in these pages, like the use of a "clearingdiv" to make sure that your footer stays below the sidebars and always looks right. That's not TG2 at work, just CSS. You'll need all your skills to build a fine web app, but TG2 will make the hard parts easier so that you can concentrate more on good design and content rather than struggling with mechanics.

Good luck with TurboGears 2!

tg.devtools-2.0.2/devtools/templates/turbogears/+package+/templates/._authentication.html0000644000076500007650000000027411123617233036720 0ustar markramm-christensenmarkramm-christensenMac OS X  2ATTRRc$$com.macromates.caret{ column = 123; line = 62; }tg.devtools-2.0.2/devtools/templates/turbogears/+package+/templates/authentication.html0000644000076500007650000000553011123617233036503 0ustar markramm-christensenmarkramm-christensen Learning TurboGears 2.0: Quick guide to authentication. ${sidebar_top()} ${sidebar_bottom()}

Authentication & Authorization in a TG2 site.

If you have access to this page, this means you have enabled authentication and authorization in the quickstart to create your project.

The paster command will have created a few specific controllers for you. But before you go to play with those controllers you'll need to make sure your application has been properly bootstapped. This is dead easy, here is how to do this:

paster setup-app development.ini

inside your application's folder and you'll get a database setup (using the preferences you have set in your development.ini file). This database will also have been prepopulated with some default logins/passwords so that you can test the secured controllers and methods.

To change the comportement of this setup-app command you just need to edit the websetup.py file.

Now try to visiting the manage_permission_only URL. You will be challenged with a login/password form.

Only managers are authorized to visit this method. You will need to log-in using:

login: manager

password: managepass

Another protected resource is editor_user_only. This one is protected by a different set of permissions. You will need to be editor with a password of editpass to be able to access it.

The last kind of protected resource in this quickstarted app is a full so called secure controller. This controller is protected globally. Instead of having a @require decorator on each method, we have set an allow_only attribute at the class level. All the methods in this controller will require the same level of access. You need to be manager to access secc or secc/some_where.

tg.devtools-2.0.2/devtools/templates/turbogears/+package+/templates/debug.html0000644000076500007650000000122711113340244034543 0ustar markramm-christensenmarkramm-christensen Sample Template, for looking at template locals

All objects from locals():

${item}: ${repr(locals()['data'][item])}
tg.devtools-2.0.2/devtools/templates/turbogears/+package+/templates/._error.html0000644000076500007650000000027311141455264035035 0ustar markramm-christensenmarkramm-christensenMac OS X  2ATTR_##com.macromates.caret{ column = 26; line = 16; }tg.devtools-2.0.2/devtools/templates/turbogears/+package+/templates/error.html0000644000076500007650000000103711141455264034617 0ustar markramm-christensenmarkramm-christensen A ${code} Error has Occurred

Error ${code}

${XML(message)}
tg.devtools-2.0.2/devtools/templates/turbogears/+package+/templates/footer.html0000644000076500007650000000110011121106676034751 0ustar markramm-christensenmarkramm-christensen tg.devtools-2.0.2/devtools/templates/turbogears/+package+/templates/._header.html0000644000076500007650000000027011121106676035127 0ustar markramm-christensenmarkramm-christensenMac OS X  2ATTRO  com.macromates.caretxR<[k0?'3/«tg.devtools-2.0.2/devtools/templates/turbogears/+package+/templates/header.html0000644000076500007650000000044211121106676034713 0ustar markramm-christensenmarkramm-christensen tg.devtools-2.0.2/devtools/templates/turbogears/+package+/templates/._index.html0000644000076500007650000000027011123617233035004 0ustar markramm-christensenmarkramm-christensenMac OS X  2ATTRRc  com.macromates.caretxR<[k0?'3/«tg.devtools-2.0.2/devtools/templates/turbogears/+package+/templates/index.html0000644000076500007650000000267411123617233034601 0ustar markramm-christensenmarkramm-christensen Welcome to TurboGears 2.0, standing on the shoulders of giants, since 2007 ${sidebar_top()}

Presentation

TurboGears 2 is rapid web application development toolkit designed to make your life easier.

  1. Code your data model

    Design your data model, Create the database, and Add some bootstrap data.

  2. Design your URL architecture

    Decide your URLs, Program your controller methods, Design your templates, and place some static files (CSS and/or JavaScript).

  3. Distribute your app

    Test your source, Generate project documents, Build a distribution.

Thank you for choosing TurboGears.
tg.devtools-2.0.2/devtools/templates/turbogears/+package+/templates/._login.html0000644000076500007650000000027311141365077035016 0ustar markramm-christensenmarkramm-christensenMac OS X  2ATTR_J##com.macromates.caret{ column = 53; line = 15; }tg.devtools-2.0.2/devtools/templates/turbogears/+package+/templates/login.html0000644000076500007650000000171411141365077034602 0ustar markramm-christensenmarkramm-christensen Login Form

Login


tg.devtools-2.0.2/devtools/templates/turbogears/+package+/templates/._master.html0000644000076500007650000000027311173202133035165 0ustar markramm-christensenmarkramm-christensenMac OS X  2ATTR\3##com.macromates.caret{ column = 16; line = 39; }tg.devtools-2.0.2/devtools/templates/turbogears/+package+/templates/master.html0000644000076500007650000000416511173202133034754 0ustar markramm-christensenmarkramm-christensen Your title goes here ${header()}
Now Viewing:
${footer()}
tg.devtools-2.0.2/devtools/templates/turbogears/+package+/templates/._sidebars.html0000644000076500007650000000027211173176642035504 0ustar markramm-christensenmarkramm-christensenMac OS X  2ATTRZ""com.macromates.caret{ column = 8; line = 12; }tg.devtools-2.0.2/devtools/templates/turbogears/+package+/templates/sidebars.html0000644000076500007650000000421311173176642035266 0ustar markramm-christensenmarkramm-christensen tg.devtools-2.0.2/devtools/templates/turbogears/+package+/tests/0000755000076500007650000000000011240527554031745 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/templates/turbogears/+package+/tests/__init__.py_tmpl0000644000076500007650000000402511160337245035110 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """Unit and functional test suite for {{project}}.""" from os import path import sys from tg import config from paste.deploy import loadapp from paste.script.appinstall import SetupCommand from routes import url_for from webtest import TestApp from nose.tools import eq_ from {{package}} import model __all__ = ['setup_db', 'teardown_db', 'TestController', 'url_for'] def setup_db(): """Method used to build a database""" engine = config['pylons.app_globals'].sa_engine model.init_model(engine) model.metadata.create_all(engine) def teardown_db(): """Method used to destroy a database""" engine = config['pylons.app_globals'].sa_engine model.metadata.drop_all(engine) class TestController(object): """ Base functional test case for the controllers. The {{project}} application instance (``self.app``) set up in this test case (and descendants) has authentication disabled, so that developers can test the protected areas independently of the :mod:`repoze.who` plugins used initially. This way, authentication can be tested once and separately. Check {{package}}.tests.functional.test_authentication for the repoze.who integration tests. This is the officially supported way to test protected areas with repoze.who-testutil (http://code.gustavonarea.net/repoze.who-testutil/). """ application_under_test = 'main_without_authn' def setUp(self): """Method called by nose before running each test""" # Loading the application: conf_dir = config.here wsgiapp = loadapp('config:test.ini#%s' % self.application_under_test, relative_to=conf_dir) self.app = TestApp(wsgiapp) # Setting it up: test_file = path.join(conf_dir, 'test.ini') cmd = SetupCommand('setup-app') cmd.run([test_file]) def tearDown(self): """Method called by nose after running each test""" # Cleaning up the database: teardown_db() tg.devtools-2.0.2/devtools/templates/turbogears/+package+/tests/functional/0000755000076500007650000000000011240527554034107 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/templates/turbogears/+package+/tests/functional/__init__.py_tmpl0000644000076500007650000000013311153607757037260 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """Functional test suite for the controllers of the application."""././@LongLink0000000000000000000000000000014700000000000011710 Lustar rootwheeltg.devtools-2.0.2/devtools/templates/turbogears/+package+/tests/functional/test_authentication.py_tmpltg.devtools-2.0.2/devtools/templates/turbogears/+package+/tests/functional/test_authentication.py_tm0000644000076500007650000000675211153607757041260 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- {{if auth == "sqlalchemy"}} """ Integration tests for the :mod:`repoze.who`-powered authentication sub-system. As {{project}} grows and the authentication method changes, only these tests should be updated. """ from {{package}}.tests import TestController class TestAuthentication(TestController): """ Tests for the default authentication setup. By default in TurboGears 2, :mod:`repoze.who` is configured with the same plugins specified by repoze.what-quickstart (which are listed in http://code.gustavonarea.net/repoze.what-quickstart/#repoze.what.plugins.quickstart.setup_sql_auth). As the settings for those plugins change, or the plugins are replaced, these tests should be updated. """ application_under_test = 'main' def test_forced_login(self): """ Anonymous users must be redirected to the login form when authorization is denied. Next, upon successful login they should be redirected to the initially requested page. """ # Requesting a protected area resp = self.app.get('/secc/', status=302) assert resp.location.startswith('http://localhost/login') # Getting the login form: resp = resp.follow(status=200) form = resp.form # Submitting the login form: form['login'] = u'manager' form['password'] = 'managepass' post_login = form.submit(status=302) # Being redirected to the initially requested page: assert post_login.location.startswith('http://localhost/post_login') initial_page = post_login.follow(status=302) assert 'authtkt' in initial_page.request.cookies, \ "Session cookie wasn't defined: %s" % initial_page.request.cookies assert initial_page.location.startswith('http://localhost/secc/'), \ initial_page.location def test_voluntary_login(self): """Voluntary logins must work correctly""" # Going to the login form voluntarily: resp = self.app.get('/login', status=200) form = resp.form # Submitting the login form: form['login'] = u'manager' form['password'] = 'managepass' post_login = form.submit(status=302) # Being redirected to the home page: assert post_login.location.startswith('http://localhost/post_login') home_page = post_login.follow(status=302) assert 'authtkt' in home_page.request.cookies, \ 'Session cookie was not defined: %s' % home_page.request.cookies assert home_page.location == 'http://localhost/' def test_logout(self): """Logouts must work correctly""" # Logging in voluntarily the quick way: resp = self.app.get('/login_handler?login=manager&password=managepass', status=302) resp = resp.follow(status=302) assert 'authtkt' in resp.request.cookies, \ 'Session cookie was not defined: %s' % resp.request.cookies # Logging out: resp = self.app.get('/logout_handler', status=302) assert resp.location.startswith('http://localhost/post_logout') # Finally, redirected to the home page: home_page = resp.follow(status=302) assert home_page.request.cookies.get('authtkt') == '', \ 'Session cookie was not deleted: %s' % home_page.request.cookies assert home_page.location == 'http://localhost/', home_page.location {{endif}} tg.devtools-2.0.2/devtools/templates/turbogears/+package+/tests/functional/test_root.py_tmpl0000644000076500007650000000365311157554563037555 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """ Functional test suite for the root controller. This is an example of how functional tests can be written for controllers. As opposed to a unit-test, which test a small unit of functionality, functional tests exercise the whole application and its WSGI stack. Please read http://pythonpaste.org/webtest/ for more information. """ from nose.tools import assert_true from {{package}}.tests import TestController class TestRootController(TestController): def test_index(self): response = self.app.get('/') msg = 'TurboGears 2 is rapid web application development toolkit '\ 'designed to make your life easier.' # You can look for specific strings: assert_true(msg in response) # You can also access a BeautifulSoup'ed response in your tests # (First run $ easy_install BeautifulSoup # and then uncomment the next two lines) #links = response.html.findAll('a') #print links #assert_true(links, "Mummy, there are no links here!") {{if auth == 'sqlalchemy'}} def test_secc_with_manager(self): """Only the manager can access the secure controller""" # Note how authentication is forged: environ = {'REMOTE_USER': 'manager'} resp = self.app.get('/secc', extra_environ=environ, status=200) assert 'Secure Controller here' in resp.body, resp.body def test_secc_with_editor(self): """The editor shouldn't access the secure controller""" environ = {'REMOTE_USER': 'editor'} self.app.get('/secc', extra_environ=environ, status=403) # It's enough to know that authorization was denied with a 403 status def test_secc_with_anonymous(self): """Anonymous users must not access the secure controller""" self.app.get('/secc', status=401) # It's enough to know that authorization was denied with a 401 status {{endif}} tg.devtools-2.0.2/devtools/templates/turbogears/+package+/tests/models/0000755000076500007650000000000011240527554033230 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/templates/turbogears/+package+/tests/models/__init__.py_tmpl0000644000076500007650000000264611160337245036402 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """Unit test suite for the models of the application.""" from nose.tools import assert_equals from {{package}}.model import DBSession from {{package}}.tests import setup_db, teardown_db __all__ = ['ModelTest'] #Create an empty database before we start our tests for this module def setup(): """Function called by nose on module load""" setup_db() #Teardown that database def teardown(): """Function called by nose after all tests in this module ran""" teardown_db() class ModelTest(object): """Base unit test case for the models.""" klass = None attrs = {} def setup(self): try: new_attrs = {} new_attrs.update(self.attrs) new_attrs.update(self.do_get_dependencies()) self.obj = self.klass(**new_attrs) DBSession.add(self.obj) DBSession.flush() return self.obj except: DBSession.rollback() raise def tearDown(self): DBSession.rollback() def do_get_dependencies(self): """Use this method to pull in other objects that need to be created for this object to be build properly""" return {} def test_create_obj(self): pass def test_query_obj(self): obj = DBSession.query(self.klass).one() for key, value in self.attrs.iteritems(): assert_equals(getattr(obj, key), value) tg.devtools-2.0.2/devtools/templates/turbogears/+package+/tests/models/test_auth.py_tmpl0000644000076500007650000000300611153607757036644 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """Test suite for the TG app's models""" from nose.tools import eq_ from {{package}} import model from {{package}}.tests.models import ModelTest {{if auth == "sqlalchemy"}} class TestGroup(ModelTest): """Unit test case for the ``Group`` model.""" klass = model.Group attrs = dict( group_name = u"test_group", display_name = u"Test Group" ) class TestUser(ModelTest): """Unit test case for the ``User`` model.""" klass = model.User attrs = dict( user_name = u"ignucius", email_address = u"ignucius@example.org" ) def test_obj_creation_username(self): """The obj constructor must set the user name right""" eq_(self.obj.user_name, u"ignucius") def test_obj_creation_email(self): """The obj constructor must set the email right""" eq_(self.obj.email_address, u"ignucius@example.org") def test_no_permissions_by_default(self): """User objects should have no permission by default.""" eq_(len(self.obj.permissions), 0) def test_getting_by_email(self): """Users should be fetcheable by their email addresses""" him = model.User.by_email_address(u"ignucius@example.org") eq_(him, self.obj) class TestPermission(ModelTest): """Unit test case for the ``Permission`` model.""" klass = model.Permission attrs = dict( permission_name = u"test_permission", description = u"This is a test Description" ) {{endif}} tg.devtools-2.0.2/devtools/templates/turbogears/+package+/websetup.py_tmpl0000644000076500007650000000306511161536056034052 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- """Setup the {{project}} application""" import logging import transaction from tg import config from {{package}}.config.environment import load_environment __all__ = ['setup_app'] log = logging.getLogger(__name__) def setup_app(command, conf, vars): """Place any commands to setup {{package}} here""" load_environment(conf.global_conf, conf.local_conf) {{if sqlalchemy}} # Load the models from {{package}} import model print "Creating tables" model.metadata.create_all(bind=config['pylons.app_globals'].sa_engine) {{if auth == "sqlalchemy"}} manager = model.User() manager.user_name = u'manager' manager.display_name = u'Example manager' manager.email_address = u'manager@somedomain.com' manager.password = u'managepass' model.DBSession.add(manager) group = model.Group() group.group_name = u'managers' group.display_name = u'Managers Group' group.users.append(manager) model.DBSession.add(group) permission = model.Permission() permission.permission_name = u'manage' permission.description = u'This permission give an administrative right to the bearer' permission.groups.append(group) model.DBSession.add(permission) editor = model.User() editor.user_name = u'editor' editor.display_name = u'Example editor' editor.email_address = u'editor@somedomain.com' editor.password = u'editpass' model.DBSession.add(editor) model.DBSession.flush() {{endif}} transaction.commit() print "Successfully setup" {{endif}} tg.devtools-2.0.2/devtools/templates/turbogears/development.ini_tmpl0000644000076500007650000001053211150150764033135 0ustar markramm-christensenmarkramm-christensen# # {{project}} - Pylons development environment configuration # # The %(here)s variable will be replaced with the parent directory of this file # # This file is for deployment specific config options -- other configuration # that is always required for the app is done in the config directory, # and generally should not be modified by end users. [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 = 8080 [app:main] use = egg:{{project}} full_stack = true #lang = ru 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 # pick the form for your database # %(here) may include a ':' character on Windows environments; this can # invalidate the URI when specifying a SQLite db via path name {{if sqlalchemy}} # sqlalchemy.url=postgres://username:password@hostname:port/databasename # sqlalchemy.url=mysql://username:password@hostname:port/databasename # If you have sqlite, here's a simple default to get you started # in development sqlalchemy.url = sqlite:///%(here)s/devdata.db #echo shouldn't be used together with the logging module. sqlalchemy.echo = false sqlalchemy.echo_pool = false sqlalchemy.pool_recycle = 3600 {{endif}} # if you are using Mako and want to be able to reload # the mako template from disk during the development phase # you should say 'true' here # This option is only used for mako templating engine # WARNING: if you want to deploy your application using a zipped egg # (ie: if your application's setup.py defines zip-safe=True, then you # MUST put "false" for the production environment because there will # be no disk and real files to compare time with. # On the contrary if your application defines zip-safe=False and is # deployed in an unzipped manner, then you can leave this option to true templating.mako.reloadfromdisk = true # the compiled template dir is a directory that must be readable by your # webserver. It will be used to store the resulting templates once compiled # by the TemplateLookup system. # During development you generally don't need this option since paste's HTTP # server will have access to you development directories, but in production # you'll most certainly want to have apache or nginx to write in a directory # that does not contain any source code in any form for obvious security reasons. # #templating.mako.compiled_templates_dir = /some/dir/where/webserver/has/access # 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 # Add additional loggers, handlers, formatters here # Uses python's logging config file format # http://docs.python.org/lib/logging-config-fileformat.html [loggers] keys = root, {{package_logger}}{{if sqlalchemy}}, sqlalchemy{{endif}}{{if auth == "sqlalchemy"}}, auth{{endif}} [handlers] keys = console [formatters] keys = generic # If you create additional loggers, add them as a key to [loggers] [logger_root] level = INFO handlers = console [logger_{{package_logger}}] level = DEBUG handlers = qualname = {{package_logger}} {{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}} {{if auth == "sqlalchemy"}} # A logger for authentication, identification and authorization -- this is # repoze.who and repoze.what: [logger_auth] level = WARN handlers = qualname = auth {{endif}} # If you create additional handlers, add them as a key to [handlers] [handler_console] class = StreamHandler args = (sys.stderr,) level = NOTSET formatter = generic # If you create additional formatters, add them as a key to [formatters] [formatter_generic] format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s datefmt = %H:%M:%S tg.devtools-2.0.2/devtools/templates/turbogears/ez_setup/0000755000076500007650000000000011240527554030720 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/templates/turbogears/ez_setup/__init__.py0000755000076500007650000002137311113340245033027 0ustar markramm-christensenmarkramm-christensen#!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.6c7" 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', } import sys, os def _validate_md5(egg_name, data): if egg_name in md5_data: from md5 import md5 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. """ try: import setuptools 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) except ImportError: egg = download_setuptools(version, download_base, to_dir, download_delay) sys.path.insert(0, egg) import setuptools; setuptools.bootstrap_install_from = egg import pkg_resources try: pkg_resources.require("setuptools>="+version) except pkg_resources.VersionConflict, e: # XXX could we install in a subprocess here? 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.\n\n(Currently using %r)" ) % (version, e.args[0]) sys.exit(2) 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': # tell the user to uninstall obsolete version use_setuptools(version) 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 from md5 import md5 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:]) tg.devtools-2.0.2/devtools/templates/turbogears/ez_setup/README.txt0000755000076500007650000000114511113340245032407 0ustar markramm-christensenmarkramm-christensenThis directory exists so that Subversion-based projects can share a single copy of the ``ez_setup`` bootstrap module for ``setuptools``, and have it automatically updated in their projects when ``setuptools`` is updated. For your convenience, you may use the following svn:externals definition:: ez_setup svn://svn.eby-sarna.com/svnroot/ez_setup You can set this by executing this command in your project directory:: svn propedit svn:externals . And then adding the line shown above to the file that comes up for editing. Then, whenever you update your project, ``ez_setup`` will be updated as well. tg.devtools-2.0.2/devtools/templates/turbogears/._MANIFEST.in_tmpl0000644000076500007650000000027011141365077032070 0ustar markramm-christensenmarkramm-christensenMac OS X  2ATTR_Z  com.macromates.caretxR<[k0?'3/«tg.devtools-2.0.2/devtools/templates/turbogears/MANIFEST.in_tmpl0000644000076500007650000000023511141365077031654 0ustar markramm-christensenmarkramm-christensenrecursive-include {{package}}/public * include {{package}}/public/favicon.ico recursive-include {{package}}/i18n * recursive-include {{package}}/templates * tg.devtools-2.0.2/devtools/templates/turbogears/README.txt_tmpl0000644000076500007650000000127511113340245031606 0ustar markramm-christensenmarkramm-christensenThis 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 the setup.py script:: $ cd {{project}} $ python setup.py install Create the project database for any model classes defined:: $ paster setup-app development.ini Start the paste http server:: $ paster serve development.ini While developing you may want the server to reload after changes in package files (or its dependencies) are saved. This can be achieved easily by adding the --reload option:: $ paster serve --reload development.ini Then you are ready to go. tg.devtools-2.0.2/devtools/templates/turbogears/setup.cfg_tmpl0000644000076500007650000000115511150150764031734 0ustar markramm-christensenmarkramm-christensen[egg_info] tag_build = dev tag_svn_revision = true [easy_install] find_links = http://www.pylonshq.com/download/ [nosetests] with-pylons=test.ini # Babel configuration [compile_catalog] domain = {{package}} directory = {{package}}/i18n statistics = true [extract_messages] add_comments = TRANSLATORS: output_file = {{package}}/i18n/{{package}}.pot width = 80 keywords = l_ [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 tg.devtools-2.0.2/devtools/templates/turbogears/._setup.py_tmpl0000644000076500007650000000027211217042172032036 0ustar markramm-christensenmarkramm-christensenMac OS X  2ATTReC""com.macromates.caret{ column = 9; line = 19; }tg.devtools-2.0.2/devtools/templates/turbogears/setup.py_tmpl0000644000076500007650000000314011217042172031616 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- try: 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='0.1', description='', author='', author_email='', #url='', install_requires=[ "TurboGears2 >= 2.0b7", "Catwalk >= 2.0.2", "Babel >=0.9.4", #can be removed iif use_toscawidgets = False "toscawidgets >= 0.9.7.1", {{if sqlalchemy}} "zope.sqlalchemy >= 0.4 ", "repoze.tm2 >= 1.0a4", {{endif}} {{if auth == "sqlalchemy"}} "repoze.what-quickstart >= 1.0", {{endif}} {{if geo == "True"}} "tgext.geo", {{endif}} ], setup_requires=["PasteScript >= 1.7"], paster_plugins={{egg_plugins}}, packages=find_packages(exclude=['ez_setup']), include_package_data=True, test_suite='nose.collector', tests_require=['WebTest', 'BeautifulSoup'], package_data={'{{package}}': ['i18n/*/LC_MESSAGES/*.mo', 'templates/*/*', 'public/*/*']}, message_extractors={'{{package}}': [ ('**.py', 'python', None), ('templates/**.mako', 'mako', None), ('templates/**.html', 'genshi', None), {{babel_templates_extractor}}('public/**', 'ignore', None)]}, entry_points=""" [paste.app_factory] main = {{package}}.config.middleware:make_app [paste.app_install] main = pylons.util:PylonsInstaller """, ) tg.devtools-2.0.2/devtools/templates/turbogears/test.ini_tmpl0000644000076500007650000000121511153607760031576 0ustar markramm-christensenmarkramm-christensen# # {{project}} - TurboGears 2 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 = 0.0.0.0 port = 5000 [app:main] {{if auth == "sqlalchemy"}} sqlalchemy.url = sqlite:///:memory: {{endif}} use = config:development.ini [app:main_without_authn] use = main skip_authentication = True # Add additional test specific configuration options as necessary. tg.devtools-2.0.2/devtools/tests/0000755000076500007650000000000011240527554024051 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/devtools/tests/test_pastetemplate.py0000644000076500007650000000513211150150764030326 0ustar markramm-christensenmarkramm-christensenfrom devtools.pastetemplate import TurboGearsTemplate import os, shutil import pkg_resources from paste.deploy import loadapp from webtest import TestApp from paste.script.create_distro import CreateDistroCommand testDataPath = os.path.join( os.path.abspath(os.path.dirname(__file__)), 'data') class MochOptions(object): simulate = False overwrite = True templates = ['turbogears2',] output_dir = testDataPath list_templates = False list_variables = False config = None inspect_files = False svn_repository = False class TestQuickStart(object): def __init__(self,**options): self.app = None self.template_vars = { 'package': 'TGTest', 'project': 'tgtest', 'egg': 'tgtest', 'egg_plugins': ['PasteScript', 'Pylons', 'TurboGears2', 'tg.devtools'], 'sqlalchemy': True, 'sqlobject': False, 'elixir': False, 'auth': True, 'geo': False } def setUp(self): command = CreateDistroCommand('TGQuickStartUnitTest') command.verbose = False command.simulate = False command.options = MochOptions() command.interactive=False command.args=['TGTest',] proj_dir = os.path.join(testDataPath, 'TGTest') command.create_template( TurboGearsTemplate('TGTest'), proj_dir, self.template_vars) command.command() pkg_resources.working_set.add_entry(proj_dir) self.app = loadapp('config:development.ini', relative_to=proj_dir) self.app = TestApp(self.app) def tearDown(self): shutil.rmtree(testDataPath, ignore_errors=True) def test_index(self): resp = self.app.get('/') assert 'Now Viewing: index' in resp def test_login(self): resp = self.app.get('/login') assert '
' in resp def test_admin(self): resp = self.app.get('/admin/') print resp assert 'This is a fully-configurable administrative tool to help you administer your website.' in resp assert '
  • Groups
  • Users
  • Permissions
  • ' in resp #now we run the quickstarted project nosetests #FIXME, we need a better implementation import nose cls = TestQuickStart() cls.setUp() testspath = os.path.join(testDataPath,'TGTest','tgtest','tests') nose.main(argv=['-w',testspath],exit=False) cls.tearDown() tg.devtools-2.0.2/PKG-INFO0000644000076500007650000000036711240527554022153 0ustar markramm-christensenmarkramm-christensenMetadata-Version: 1.0 Name: tg.devtools Version: 2.0.2 Summary: UNKNOWN Home-page: www.turbogears.org Author: TurboGears Team 2008 Author-email: turbogears@groups.google.com License: MIT Description: UNKNOWN Keywords: turbogears Platform: UNKNOWN tg.devtools-2.0.2/scripts/0000755000076500007650000000000011240527554022537 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/scripts/_installer.py0000644000076500007650000000335011150656064025245 0ustar markramm-christensenmarkramm-christensenimport os import sys def extend_parser(parser): parser.add_option( '--trunk', dest='trunk', action='store_true', default=False, help='Install TurboGears in development mode, useful for when you want to contribute back patches (experimental, requires pip)') parser.add_option( '--requirements', dest='requirement_file', metavar='requirements.txt', default=None, help='URL or path to the pip requirement files to use') parser.add_option( '--pip', dest='use_pip', action='store_true', default=False, help='Use pip instead of easy_install (experimental)') def after_install(options, home_dir): if sys.platform == 'win32': bin = "Scripts" else: bin = "bin" pip = os.path.join(home_dir,bin,'pip') easy_install = os.path.join(home_dir,bin,'easy_install') if options.requirement_file: print "Sorry option not supported yet" return def execute(cmd,params): cmd = cmd + ' ' + params print "Running command...." print cmd subprocess.call(cmd.split()) print "Installing turbogears...." if options.use_pip: execute(easy_install,'pip') if options.trunk: execute(pip,'install -e svn+http://svn.turbogears.org/trunk') execute(pip,'install -e svn+http://svn.turbogears.org/projects/tg.devtools/trunk') else: execute(pip,'install -i http://www.turbogears.org/2.0/downloads/current/index tg.devtools') else:#use easy_install execute(easy_install,'-i http://www.turbogears.org/2.0/downloads/current/index tg.devtools') tg.devtools-2.0.2/scripts/._create-venv-script.py0000644000076500007650000000027011150150764027041 0ustar markramm-christensenmarkramm-christensenMac OS X  2ATTRa֠  com.macromates.caretxR<[k0?'3/«tg.devtools-2.0.2/scripts/create-venv-script.py0000644000076500007650000000127611150150764026633 0ustar markramm-christensenmarkramm-christensenimport os import virtualenv here = os.path.dirname(os.path.abspath(__file__)) base_dir = os.path.dirname(here) script_name = os.path.join(base_dir, 'tg2-bootstrap.py') extra_text = open(os.path.join(here,'_installer.py')).read() def main(): text = virtualenv.create_bootstrap_script(extra_text) if os.path.exists(script_name): f = open(script_name) cur_text = f.read() f.close() else: cur_text = '' print 'Updating %s' % script_name if cur_text == text: print 'No update' else: print 'Script changed; updating...' f = open(script_name, 'w') f.write(text) f.close() if __name__ == '__main__': main() tg.devtools-2.0.2/setup.cfg0000644000076500007650000000020111240527554022662 0ustar markramm-christensenmarkramm-christensen[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 [aliases] release = egg_info -RDb "" sdist bdist_egg register upload tg.devtools-2.0.2/._setup.py0000644000076500007650000000027311237676572023014 0ustar markramm-christensenmarkramm-christensenMac OS X  2ATTReD##com.macromates.caret{ column = 18; line = 25; }tg.devtools-2.0.2/setup.py0000644000076500007650000000346111237676572022601 0ustar markramm-christensenmarkramm-christensen# -*- coding: utf-8 -*- from setuptools import setup, find_packages import sys, os test_requirements = ['coverage', 'nose', 'repoze.tm2 >= 1.0a4', 'TurboKid >= 1.0.4', 'TurboJson >= 1.2.1', 'zope.sqlalchemy >= 0.4', 'SQLAlchemy >= 0.5', 'repoze.what-quickstart >= 1.0' ] install_requirements = [ 'TurboGears2 >= 2.0.2', 'sqlalchemy-migrate >= 0.5.1', 'SQLAlchemy >= 0.5', 'repoze.what-quickstart >= 1.0', 'repoze.who >= 1.0.10' ] setup( name='tg.devtools', version="2.0.2", description="", long_description="""""", classifiers=[], keywords='turbogears', author="TurboGears Team 2008", author_email="turbogears@groups.google.com", url="www.turbogears.org", license="MIT", packages=find_packages(exclude=['ez_setup', 'examples', 'tests']), include_package_data=True, zip_safe=False, install_requires = install_requirements, entry_points=''' [paste.global_paster_command] quickstart = devtools.commands.quickstart:QuickstartCommand [paste.paster_command] migrate = devtools.commands.migration:MigrateCommand [turbogears2.command] quickstart = devtools.commands.quickstart:QuickstartCommand migrate = devtools.commands.migration:MigrateCommand [paste.paster_create_template] turbogears2=devtools.pastetemplate:TurboGearsTemplate [turbogears2.template] turbogears2=devtools.pastetemplate:TurboGearsTemplate ''', test_suite='nose.collector', tests_require = test_requirements, ) tg.devtools-2.0.2/tg.devtools.egg-info/0000755000076500007650000000000011240527554025012 5ustar markramm-christensenmarkramm-christensentg.devtools-2.0.2/tg.devtools.egg-info/dependency_links.txt0000644000076500007650000000000111240527553031057 0ustar markramm-christensenmarkramm-christensen tg.devtools-2.0.2/tg.devtools.egg-info/entry_points.txt0000644000076500007650000000105411240527553030307 0ustar markramm-christensenmarkramm-christensen [paste.global_paster_command] quickstart = devtools.commands.quickstart:QuickstartCommand [paste.paster_command] migrate = devtools.commands.migration:MigrateCommand [turbogears2.command] quickstart = devtools.commands.quickstart:QuickstartCommand migrate = devtools.commands.migration:MigrateCommand [paste.paster_create_template] turbogears2=devtools.pastetemplate:TurboGearsTemplate [turbogears2.template] turbogears2=devtools.pastetemplate:TurboGearsTemplate tg.devtools-2.0.2/tg.devtools.egg-info/not-zip-safe0000644000076500007650000000000111166762032027237 0ustar markramm-christensenmarkramm-christensen tg.devtools-2.0.2/tg.devtools.egg-info/PKG-INFO0000644000076500007650000000036711240527553026114 0ustar markramm-christensenmarkramm-christensenMetadata-Version: 1.0 Name: tg.devtools Version: 2.0.2 Summary: UNKNOWN Home-page: www.turbogears.org Author: TurboGears Team 2008 Author-email: turbogears@groups.google.com License: MIT Description: UNKNOWN Keywords: turbogears Platform: UNKNOWN tg.devtools-2.0.2/tg.devtools.egg-info/requires.txt0000644000076500007650000000016511240527553027413 0ustar markramm-christensenmarkramm-christensenTurboGears2 >= 2.0.2 sqlalchemy-migrate >= 0.5.1 SQLAlchemy >= 0.5 repoze.what-quickstart >= 1.0 repoze.who >= 1.0.10tg.devtools-2.0.2/tg.devtools.egg-info/SOURCES.txt0000644000076500007650000001144211240527554026700 0ustar markramm-christensenmarkramm-christensensetup.cfg setup.py devtools/__init__.py devtools/pastetemplate.py devtools/commands/__init__.py devtools/commands/migration.py devtools/commands/quickstart.py devtools/templates/__init__.py devtools/templates/turbogears/MANIFEST.in_tmpl devtools/templates/turbogears/README.txt_tmpl devtools/templates/turbogears/development.ini_tmpl devtools/templates/turbogears/setup.cfg_tmpl devtools/templates/turbogears/setup.py_tmpl devtools/templates/turbogears/test.ini_tmpl devtools/templates/turbogears/+package+/__init__.py_tmpl devtools/templates/turbogears/+package+/websetup.py_tmpl devtools/templates/turbogears/+package+/config/__init__.py_tmpl devtools/templates/turbogears/+package+/config/app_cfg.py_tmpl devtools/templates/turbogears/+package+/config/deployment.ini_tmpl_tmpl devtools/templates/turbogears/+package+/config/environment.py_tmpl devtools/templates/turbogears/+package+/config/middleware.py_tmpl devtools/templates/turbogears/+package+/controllers/__init__.py_tmpl devtools/templates/turbogears/+package+/controllers/controller.template_tmpl devtools/templates/turbogears/+package+/controllers/error.py_tmpl devtools/templates/turbogears/+package+/controllers/root.py_tmpl devtools/templates/turbogears/+package+/controllers/secure.py_tmpl devtools/templates/turbogears/+package+/controllers/template.py_tmpl devtools/templates/turbogears/+package+/i18n/ru/LC_MESSAGES/+package+.po_tmpl devtools/templates/turbogears/+package+/lib/__init__.py_tmpl devtools/templates/turbogears/+package+/lib/app_globals.py_tmpl devtools/templates/turbogears/+package+/lib/base.py_tmpl devtools/templates/turbogears/+package+/lib/helpers.py_tmpl devtools/templates/turbogears/+package+/model/__init__.py_tmpl devtools/templates/turbogears/+package+/model/auth.py_tmpl devtools/templates/turbogears/+package+/model/model.template_tmpl devtools/templates/turbogears/+package+/public/favicon.ico devtools/templates/turbogears/+package+/public/css/style.css devtools/templates/turbogears/+package+/public/images/contentbg.png devtools/templates/turbogears/+package+/public/images/error.png devtools/templates/turbogears/+package+/public/images/header_inner2.png devtools/templates/turbogears/+package+/public/images/headerbg.png devtools/templates/turbogears/+package+/public/images/info.png devtools/templates/turbogears/+package+/public/images/inputbg.png devtools/templates/turbogears/+package+/public/images/loginbg.png devtools/templates/turbogears/+package+/public/images/loginbottombg.png devtools/templates/turbogears/+package+/public/images/loginheader-left.png devtools/templates/turbogears/+package+/public/images/loginheader-right.png devtools/templates/turbogears/+package+/public/images/menu-item-actibg-first.png devtools/templates/turbogears/+package+/public/images/menu-item-actibg.png devtools/templates/turbogears/+package+/public/images/menu-item-border.png devtools/templates/turbogears/+package+/public/images/menubg.png devtools/templates/turbogears/+package+/public/images/ok.png devtools/templates/turbogears/+package+/public/images/pagebg.png devtools/templates/turbogears/+package+/public/images/star.png devtools/templates/turbogears/+package+/public/images/strype2.png devtools/templates/turbogears/+package+/public/images/under_the_hood_blue.png devtools/templates/turbogears/+package+/public/images/warning.png devtools/templates/turbogears/+package+/templates/__init__.py devtools/templates/turbogears/+package+/templates/about.html devtools/templates/turbogears/+package+/templates/authentication.html devtools/templates/turbogears/+package+/templates/debug.html devtools/templates/turbogears/+package+/templates/error.html devtools/templates/turbogears/+package+/templates/footer.html devtools/templates/turbogears/+package+/templates/header.html devtools/templates/turbogears/+package+/templates/index.html devtools/templates/turbogears/+package+/templates/login.html devtools/templates/turbogears/+package+/templates/master.html devtools/templates/turbogears/+package+/templates/sidebars.html devtools/templates/turbogears/+package+/tests/__init__.py_tmpl devtools/templates/turbogears/+package+/tests/functional/__init__.py_tmpl devtools/templates/turbogears/+package+/tests/functional/test_authentication.py_tmpl devtools/templates/turbogears/+package+/tests/functional/test_root.py_tmpl devtools/templates/turbogears/+package+/tests/models/__init__.py_tmpl devtools/templates/turbogears/+package+/tests/models/test_auth.py_tmpl devtools/templates/turbogears/ez_setup/README.txt devtools/templates/turbogears/ez_setup/__init__.py devtools/tests/test_pastetemplate.py scripts/_installer.py scripts/create-venv-script.py tg.devtools.egg-info/PKG-INFO tg.devtools.egg-info/SOURCES.txt tg.devtools.egg-info/dependency_links.txt tg.devtools.egg-info/entry_points.txt tg.devtools.egg-info/not-zip-safe tg.devtools.egg-info/requires.txt tg.devtools.egg-info/top_level.txttg.devtools-2.0.2/tg.devtools.egg-info/top_level.txt0000644000076500007650000000001111240527553027533 0ustar markramm-christensenmarkramm-christensendevtools