From 727b9a5fa74b63e54ed22a9b31ef9228801f14d6 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sun, 25 Mar 2012 13:48:13 -0500 Subject: [PATCH] save point (see note) Added 'db' command, tweaked pyramid scaffold a bit (added 'initialize' command there), removed migrate 'schema' repository in preparation for alembic. --- edbob/commands.py | 97 ++++++++++++++++- edbob/db/extensions.py | 101 ++++++++++-------- edbob/db/schema/README | 4 - edbob/db/schema/__init__.py | 0 edbob/db/schema/manage.py | 5 - edbob/db/schema/migrate.cfg | 25 ----- edbob/db/schema/versions/__init__.py | 0 .../edbob/+package+/__init__.py_tmpl | 3 +- .../edbob/+package+/commands.py_tmpl | 22 ++-- .../scaffolds/edbob/+package+/db.py_tmpl | 4 +- .../edbob/+package+/subscribers.py_tmpl | 21 ++++ .../edbob/+package+/templates/base.mako_tmpl | 4 + .../edbob/+package+/templates/home.mako_tmpl | 6 +- edbob/pyramid/scaffolds/edbob/CHANGES.txt | 1 + edbob/pyramid/scaffolds/edbob/README.txt_tmpl | 15 ++- edbob/pyramid/scaffolds/edbob/setup.py_tmpl | 4 +- edbob/pyramid/static/css/edbob.css | 6 ++ edbob/pyramid/templates/edbob/base.mako | 7 +- edbob/time.py | 2 +- setup.py | 87 ++++++++------- 20 files changed, 270 insertions(+), 144 deletions(-) delete mode 100644 edbob/db/schema/README delete mode 100644 edbob/db/schema/__init__.py delete mode 100644 edbob/db/schema/manage.py delete mode 100644 edbob/db/schema/migrate.cfg delete mode 100644 edbob/db/schema/versions/__init__.py create mode 100644 edbob/pyramid/scaffolds/edbob/+package+/subscribers.py_tmpl diff --git a/edbob/commands.py b/edbob/commands.py index 3821d9c..adacff3 100644 --- a/edbob/commands.py +++ b/edbob/commands.py @@ -37,6 +37,20 @@ import edbob from edbob.util import requires_impl +class ArgumentParser(argparse.ArgumentParser): + """ + Customized version of ``argparse.ArgumentParser``, which overrides some of + the argument parsing logic. This is necessary for the application's + primary command (:class:`Command` class); but is not used with + :class:`Subcommand` derivatives. + """ + + def parse_args(self, args=None, namespace=None): + args, argv = self.parse_known_args(args, namespace) + args.argv = argv + return args + + class Command(edbob.Object): """ The primary command for the application. @@ -107,7 +121,7 @@ Try '%(name)s help ' for more help.""" % self accordingly (or displays help text). """ - parser = argparse.ArgumentParser( + parser = ArgumentParser( prog=self.name, description=self.description, add_help=False, @@ -167,7 +181,7 @@ Try '%(name)s help ' for more help.""" % self # And finally, do something of real value... cmd = self.subcommands[cmd](parent=self) - cmd._run(*args.command) + cmd._run(*(args.command + args.argv)) class Subcommand(edbob.Object): @@ -231,14 +245,91 @@ class Subcommand(edbob.Object): pass +class DatabaseCommand(Subcommand): + """ + Provides tools for managing an ``edbob`` database; called as ``edbob db``. + + This command requires additional arguments; see ``edbob help db`` for more + information. + """ + + name = 'db' + description = "Tools for managing edbob databases" + + def add_parser_args(self, parser): + parser.add_argument('-D', '--database', metavar='URL', + help="Database engine (default is edbob.db.engine)") + parser.add_argument('command', choices=['upgrade', 'extensions', 'activate', 'deactivate'], + help="Command to execute against database") + + def run(self, args): + if args.database: + from sqlalchemy import create_engine + from sqlalchemy.exc import ArgumentError + try: + engine = create_engine(args.database) + except ArgumentError, err: + print err + return + else: + from edbob.db import engine + if not engine: + print >> sys.stderr, "Database not configured; please change that or specify -D URL" + return + + if args.command == 'upgrade': + print 'got upgrade ..' + + +# class ExtensionsCommand(RattailCommand): +# """ +# Displays the currently-installed (available) extensions, and whether or not +# each has been activated within the configured database. Called as +# ``rattail extensions``. +# """ + +# short_description = "Displays available extensions and their statuses" + +# def __call__(self, options, **args): +# from sqlalchemy.exc import OperationalError +# from rattail import engine +# from rattail.db.util import core_schema_installed +# from rattail.db.ext import get_available_extensions, extension_active + +# try: +# engine.connect() +# except OperationalError, e: +# print >> sys.stderr, "Cannot connect to database:" +# print >> sys.stderr, engine.url +# print >> sys.stderr, e[0].strip() +# return + +# if not core_schema_installed(): +# print >> sys.stderr, "Database lacks core schema:" +# print >> sys.stderr, engine.url +# return + +# extensions = get_available_extensions() +# print '' +# print ' %-25s %-10s' % ("Extension", "Active?") +# print '-' * 35 +# for name in sorted(extensions): +# active = 'Y' if extension_active(name) else 'N' +# print ' %-28s %s' % (name, active) +# print '' +# print "Use 'rattail {activate|deactivate} EXTENSION' to change." + + class ShellCommand(Subcommand): """ Launches a Python shell (of your choice) with ``edbob`` pre-loaded; called as ``edbob shell``. - You can configure the shell within ``edbob.conf`` (otherwise ``python`` is + You can define the shell within your config file (otherwise ``python`` is assumed):: + .. highlight:: ini + [edbob] shell.python = ipython """ diff --git a/edbob/db/extensions.py b/edbob/db/extensions.py index cc27b63..801fa75 100644 --- a/edbob/db/extensions.py +++ b/edbob/db/extensions.py @@ -32,7 +32,7 @@ import logging import sqlalchemy.exc # from sqlalchemy.orm import clear_mappers -# import migrate.versioning.api +import migrate.versioning.api # from migrate.versioning.schema import ControlledSchema # import rattail @@ -48,7 +48,11 @@ import edbob.db from edbob.db import exceptions from edbob.db import Session from edbob.db.classes import ActiveExtension -from edbob.db.util import get_database_version +from edbob.db.util import ( + get_database_version, + get_repository_path, + get_repository_version, + ) from edbob.util import requires_impl @@ -144,35 +148,35 @@ class Extension(edbob.Object): pass -# def activate_extension(extension, engine=None): -# """ -# Activates the :class:`RattailExtension` instance represented by -# ``extension`` (which can be the actual instance, or the extension's name) -# by installing its schema and registering it within the database, and -# immediately applies it to the current ORM API. +def activate_extension(extension, engine=None): + """ + Activates the :class:`Extension` instance represented by ``extension`` + (which can be the actual instance, or the extension's name) by installing + its schema and registering it within the database, and immediately applies + it to the current ORM/API. -# If ``engine`` is not provided, then ``rattail.engine`` is assumed. -# """ + If ``engine`` is not provided, then :attr:`edbob.db.engine` is assumed. + """ -# if engine is None: -# engine = rattail.engine + if engine is None: + engine = edbob.db.engine -# if not isinstance(extension, RattailExtension): -# extension = get_extension(extension) + if not isinstance(extension, Extension): + extension = get_extension(extension) -# log.info("Activating extension: %s" % extension.name) -# install_extension_schema(extension, engine) + log.info("Activating extension: %s" % extension.name) + install_extension_schema(extension, engine) -# session = Session(bind=engine) -# if not session.query(ActiveExtension).get(extension.name): -# session.add(ActiveExtension(name=extension.name)) -# session.commit() -# session.close() + session = Session(bind=engine) + if not session.query(ActiveExtension).get(extension.name): + session.add(ActiveExtension(name=extension.name)) + session.commit() + session.close() -# merge_extension_metadata(extension) -# extension.extend_classes() -# extension.extend_mappers(rattail.metadata) -# _active_extensions[extension.name] = extension + merge_extension_metadata(extension) + extension.extend_classes() + extension.extend_mappers(rattail.metadata) + active_extensions[extension.name] = extension # def deactivate_extension(extension, engine=None): @@ -217,7 +221,10 @@ def extend_framework(): found will be used to extend the ORM/API in-place. """ + # Do we even have an engine? engine = edbob.db.engine + if not engine: + return # Check primary database connection. try: @@ -304,32 +311,34 @@ def get_extension(name): raise exceptions.ExtensionNotFound(name) -# def install_extension_schema(extension, engine=None): -# """ -# Installs an extension's schema to the database and adds version control for -# it. -# """ +def install_extension_schema(extension, engine=None): + """ + Installs an extension's schema to the database and adds version control for + it. ``extension`` must be a valid :class:`Extension` instance. -# if engine is None: -# engine = rattail.engine + If ``engine`` is not provided, :attr:`edbob.db.engine` is assumed. + """ -# # Extensionls aren't required to provide metadata... -# ext_meta = extension.get_metadata() -# if not ext_meta: -# return + if engine is None: + engine = edbob.db.engine -# # ...but if they do they must also provide a SQLAlchemy-Migrate repository! -# assert extension.schema, "Extension does not implement 'schema': %s" % extension.name + # Extensions aren't required to provide metadata... + ext_meta = extension.get_metadata() + if not ext_meta: + return + + # ...but if they do they must also provide a SQLAlchemy-Migrate repository. + assert extension.schema, "Extension does not implement 'schema': %s" % extension.name -# meta = rattail.metadata -# for table in meta.sorted_tables: -# table.tometadata(ext_meta) -# for table in ext_meta.sorted_tables: -# if table.name not in meta.tables: -# table.create(bind=engine, checkfirst=True) + meta = edbob.db.metadata + for table in meta.sorted_tables: + table.tometadata(ext_meta) + for table in ext_meta.sorted_tables: + if table.name not in meta.tables: + table.create(bind=engine, checkfirst=True) -# migrate.versioning.api.version_control( -# str(engine.url), get_repository_path(extension), get_repository_version(extension)) + migrate.versioning.api.version_control( + str(engine.url), get_repository_path(extension), get_repository_version(extension)) def merge_extension_metadata(ext): diff --git a/edbob/db/schema/README b/edbob/db/schema/README deleted file mode 100644 index 6218f8c..0000000 --- a/edbob/db/schema/README +++ /dev/null @@ -1,4 +0,0 @@ -This is a database migration repository. - -More information at -http://code.google.com/p/sqlalchemy-migrate/ diff --git a/edbob/db/schema/__init__.py b/edbob/db/schema/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/edbob/db/schema/manage.py b/edbob/db/schema/manage.py deleted file mode 100644 index c3209f2..0000000 --- a/edbob/db/schema/manage.py +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env python -from migrate.versioning.shell import main - -if __name__ == '__main__': - main(debug='False') diff --git a/edbob/db/schema/migrate.cfg b/edbob/db/schema/migrate.cfg deleted file mode 100644 index 46e9c87..0000000 --- a/edbob/db/schema/migrate.cfg +++ /dev/null @@ -1,25 +0,0 @@ -[db_settings] -# Used to identify which repository this database is versioned under. -# You can use the name of your project. -repository_id=edbob - -# The name of the database table used to track the schema version. -# This name shouldn't already be used by your project. -# If this is changed once a database is under version control, you'll need to -# change the table name in each database too. -version_table=migrate_version - -# When committing a change script, Migrate will attempt to generate the -# sql for all supported databases; normally, if one of them fails - probably -# because you don't have that database installed - it is ignored and the -# commit continues, perhaps ending successfully. -# Databases in this list MUST compile successfully during a commit, or the -# entire commit will fail. List the databases your application will actually -# be using to ensure your updates to that database work properly. -# This must be a list; example: ['postgres','sqlite'] -required_dbs=[] - -# When creating new change scripts, Migrate will stamp the new script with -# a version number. By default this is latest_version + 1. You can set this -# to 'true' to tell Migrate to use the UTC timestamp instead. -use_timestamp_numbering=False diff --git a/edbob/db/schema/versions/__init__.py b/edbob/db/schema/versions/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/edbob/pyramid/scaffolds/edbob/+package+/__init__.py_tmpl b/edbob/pyramid/scaffolds/edbob/+package+/__init__.py_tmpl index d2f0770..a2153a7 100644 --- a/edbob/pyramid/scaffolds/edbob/+package+/__init__.py_tmpl +++ b/edbob/pyramid/scaffolds/edbob/+package+/__init__.py_tmpl @@ -12,7 +12,6 @@ from pyramid.config import Configurator import edbob from {{package}}._version import __version__ -from {{package}}.db import DBSession def main(global_config, **settings): @@ -37,6 +36,7 @@ def main(global_config, **settings): # Configure Pyramid config = Configurator(settings=settings) config.include('edbob.pyramid') + config.include('{{package}}.subscribers') config.scan() # Configure Beaker @@ -49,7 +49,6 @@ def main(global_config, **settings): edbob.init('{{package}}', os.path.abspath(settings['edbob.config'])) # Add static views - config.add_static_view('favicon.ico', 'static/favicon.ico') # config.add_static_view('css', 'static/css', cache_max_age=3600) # config.add_static_view('img', 'static/img', cache_max_age=3600) # config.add_static_view('js', 'static/js', cache_max_age=3600) diff --git a/edbob/pyramid/scaffolds/edbob/+package+/commands.py_tmpl b/edbob/pyramid/scaffolds/edbob/+package+/commands.py_tmpl index c708acf..7bd2341 100644 --- a/edbob/pyramid/scaffolds/edbob/+package+/commands.py_tmpl +++ b/edbob/pyramid/scaffolds/edbob/+package+/commands.py_tmpl @@ -23,34 +23,39 @@ class Command(commands.Command): long_description = '' -class InitDatabaseCommand(commands.Subcommand): +class InitCommand(commands.Subcommand): """ - Initializes the database. This is meant to be leveraged as part of setting - up the application. The database used by this command will be determined - by config, for example:: + Initializes the database; called as ``{{package}} initialize``. This is + meant to be leveraged as part of setting up the application. The database + used by this command will be determined by config, for example:: - .. highlight:: ini + .. highlight:: ini [edbob.db] sqlalchemy.url = postgresql://user:pass@localhost/{{package}} """ - name = 'init-db' + name = 'initialize' description = "Initialize the database" def run(self, args): from edbob.db import engine from edbob.db.util import install_core_schema from edbob.db.exceptions import CoreSchemaAlreadyInstalled + from edbob.db.extensions import activate_extension # Install core schema to database. try: install_core_schema(engine) except CoreSchemaAlreadyInstalled, err: - print err + print '%s:' % err + print ' %s' % engine.url return # Activate any extensions you like here... + # activate_extension('shrubbery') + + # Okay, on to bootstrapping... from edbob.db import Session from edbob.db.classes import Role, User @@ -68,7 +73,8 @@ class InitDatabaseCommand(commands.Subcommand): session.commit() session.close() - print "Initialized database %s" % engine.url + print "Initialized database:" + print ' %s' % engine.url def main(*args): diff --git a/edbob/pyramid/scaffolds/edbob/+package+/db.py_tmpl b/edbob/pyramid/scaffolds/edbob/+package+/db.py_tmpl index 8ccec8f..6d7a1a3 100644 --- a/edbob/pyramid/scaffolds/edbob/+package+/db.py_tmpl +++ b/edbob/pyramid/scaffolds/edbob/+package+/db.py_tmpl @@ -8,4 +8,6 @@ from sqlalchemy.orm import scoped_session, sessionmaker from zope.sqlalchemy import ZopeTransactionExtension -DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension())) +__all__ = ['Session'] + +Session = scoped_session(sessionmaker(extension=ZopeTransactionExtension())) diff --git a/edbob/pyramid/scaffolds/edbob/+package+/subscribers.py_tmpl b/edbob/pyramid/scaffolds/edbob/+package+/subscribers.py_tmpl new file mode 100644 index 0000000..53829e6 --- /dev/null +++ b/edbob/pyramid/scaffolds/edbob/+package+/subscribers.py_tmpl @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +""" +``{{package}}.subscribers`` -- Pyramid Event Subscribers +""" + +import {{package}} + + +def before_render(event): + """ + Adds goodies to the global template renderer context. + """ + + renderer_globals = event + renderer_globals['{{package}}'] = {{package}} + + +def includeme(config): + config.add_subscriber('{{package}}.subscribers:before_render', + 'pyramid.events.BeforeRender') diff --git a/edbob/pyramid/scaffolds/edbob/+package+/templates/base.mako_tmpl b/edbob/pyramid/scaffolds/edbob/+package+/templates/base.mako_tmpl index 8afc611..0999fee 100644 --- a/edbob/pyramid/scaffolds/edbob/+package+/templates/base.mako_tmpl +++ b/edbob/pyramid/scaffolds/edbob/+package+/templates/base.mako_tmpl @@ -1,3 +1,7 @@ <%inherit file="edbob/base.mako" /> <%def name="global_title()">{{project}} +<%def name="footer()"> + {{project}} v${{{package}}.__version__} powered by + ${h.link_to("edbob", 'http://edbob.org/', target='_blank')} v${edbob.__version__} + ${parent.body()} diff --git a/edbob/pyramid/scaffolds/edbob/+package+/templates/home.mako_tmpl b/edbob/pyramid/scaffolds/edbob/+package+/templates/home.mako_tmpl index 4965fa8..dfcdb08 100644 --- a/edbob/pyramid/scaffolds/edbob/+package+/templates/home.mako_tmpl +++ b/edbob/pyramid/scaffolds/edbob/+package+/templates/home.mako_tmpl @@ -1,11 +1,11 @@ <%inherit file="base.mako" /> -

Welcome to {{project}} !

+

Welcome to {{project}}

You must choose, but choose wisely:


    -
  • links should...
  • -
  • ...go here
  • +
  • some...
  • +
  • ...links
diff --git a/edbob/pyramid/scaffolds/edbob/CHANGES.txt b/edbob/pyramid/scaffolds/edbob/CHANGES.txt index 93dae39..fbe7946 100644 --- a/edbob/pyramid/scaffolds/edbob/CHANGES.txt +++ b/edbob/pyramid/scaffolds/edbob/CHANGES.txt @@ -1,3 +1,4 @@ + 0.1a1 ----- diff --git a/edbob/pyramid/scaffolds/edbob/README.txt_tmpl b/edbob/pyramid/scaffolds/edbob/README.txt_tmpl index 7cfee7d..562ae0f 100644 --- a/edbob/pyramid/scaffolds/edbob/README.txt_tmpl +++ b/edbob/pyramid/scaffolds/edbob/README.txt_tmpl @@ -8,10 +8,15 @@ Welcome to the {{project}} project. Getting Started --------------- -- cd +{{project}} should install and run without issue on Linux and Windows:: -- $venv/bin/python setup.py develop +.. highlight:: sh -- $venv/bin/populate_{{package}} development.ini - -- $venv/bin/pserve --reload development.ini + $ virtualenv {{package}} + $ cd <{{package}}-src-dir> + $ python setup.py develop + $ cd + $ {{package}} make-app + $ cd + $ {{package}} -c development.ini initialize + $ pserve --reload development.ini diff --git a/edbob/pyramid/scaffolds/edbob/setup.py_tmpl b/edbob/pyramid/scaffolds/edbob/setup.py_tmpl index 7e0d007..197159d 100644 --- a/edbob/pyramid/scaffolds/edbob/setup.py_tmpl +++ b/edbob/pyramid/scaffolds/edbob/setup.py_tmpl @@ -76,6 +76,8 @@ setup( 'Framework :: Pylons', 'Operating System :: OS Independent', 'Programming Language :: Python', + 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', 'Topic :: Internet :: WWW/HTTP', 'Topic :: Internet :: WWW/HTTP :: WSGI :: Application', ], @@ -92,7 +94,7 @@ setup( {{package}} = {{package}}.commands:main [{{package}}.commands] -init-db = {{package}}.commands:InitDatabaseCommand +initialize = {{package}}.commands:InitCommand [paste.app_factory] main = {{package}}:main diff --git a/edbob/pyramid/static/css/edbob.css b/edbob/pyramid/static/css/edbob.css index 8fde0c6..032935a 100644 --- a/edbob/pyramid/static/css/edbob.css +++ b/edbob/pyramid/static/css/edbob.css @@ -95,6 +95,12 @@ ul.sub-menu li { margin-right: 15px; } +#footer { + clear: both; + margin-top: 40px; + text-align: center; +} + #body { padding-top: 15px; } diff --git a/edbob/pyramid/templates/edbob/base.mako b/edbob/pyramid/templates/edbob/base.mako index 9c02fc8..0f4aeee 100644 --- a/edbob/pyramid/templates/edbob/base.mako +++ b/edbob/pyramid/templates/edbob/base.mako @@ -1,6 +1,9 @@ <%def name="global_title()">edbob <%def name="title()"> <%def name="head_tags()"> +<%def name="footer()"> + powered by ${h.link_to('edbob', 'http://edbob.org', target='_blank')} v${edbob.__version__} + @@ -53,8 +56,8 @@ ${self.body()} - diff --git a/edbob/time.py b/edbob/time.py index d80dc85..c9b7d04 100644 --- a/edbob/time.py +++ b/edbob/time.py @@ -47,7 +47,7 @@ def init(config): tz = config.get('edbob.time', 'timezone') if tz: set_timezone(tz) - log.info("Set timezone to '%s'" % tz) + log.debug("Timezone set to '%s'" % tz) else: log.warning("No timezone configured; falling back to US/Central") set_timezone('US/Central') diff --git a/setup.py b/setup.py index 5c2a6e3..4e86304 100644 --- a/setup.py +++ b/setup.py @@ -30,6 +30,7 @@ except ImportError: use_setuptools() +import sys import os.path from setuptools import setup, find_packages @@ -39,6 +40,50 @@ execfile(os.path.join(here, 'edbob', '_version.py')) readme = open(os.path.join(here, 'README.txt')).read() +requires = [ + # + # Version numbers within comments below have specific meanings. + # Basically the 'low' value is a "soft low," and 'high' a "soft high." + # In other words: + # + # If either a 'low' or 'high' value exists, the primary point to be + # made about the value is that it represents the most current (stable) + # version available for the package (assuming typical public access + # methods) whenever this project was started and/or documented. + # Therefore: + # + # If a 'low' version is present, you should know that attempts to use + # versions of the package significantly older than the 'low' version + # may not yield happy results. (A "hard" high limit may or may not be + # indicated by a true version requirement.) + # + # Similarly, if a 'high' version is present, and especially if this + # project has laid dormant for a while, you may need to refactor a bit + # when attempting to support a more recent version of the package. (A + # "hard" low limit should be indicated by a true version requirement + # when a 'high' version is present.) + # + # In any case, developers and other users are encouraged to play + # outside the lines with regard to these soft limits. If bugs are + # encountered then they should be filed as such. + # + # package # low high + + 'progressbar', # 2.3 + 'pytz', # 2012b + ] + +if sys.version_info < (2, 7): + # Python < 2.7 has a standard library in need of supplementation. + + requires += [ + # + # package # low high + # + 'argparse', # 1.2.1 + ] + + setup( name = "edbob", version = __version__, @@ -65,54 +110,19 @@ setup( 'Topic :: Software Development :: Libraries :: Python Modules', ], - install_requires = [ - # - # Version numbers within comments below have specific meanings. - # Basically the 'low' value is a "soft low," and 'high' a "soft high." - # In other words: - # - # If either a 'low' or 'high' value exists, the primary point to be - # made about the value is that it represents the most current (stable) - # version available for the package (assuming typical public access - # methods) whenever this project was started and/or documented. - # Therefore: - # - # If a 'low' version is present, you should know that attempts to use - # versions of the package significantly older than the 'low' version - # may not yield happy results. (A "hard" high limit may or may not be - # indicated by a true version requirement.) - # - # Similarly, if a 'high' version is present, and especially if this - # project has laid dormant for a while, you may need to refactor a bit - # when attempting to support a more recent version of the package. (A - # "hard" low limit should be indicated by a true version requirement - # when a 'high' version is present.) - # - # In any case, developers and other users are encouraged to play - # outside the lines with regard to these soft limits. If bugs are - # encountered then they should be filed as such. - # - # package # low high - - 'progressbar', # 2.3 - 'pytz', # 2012b - - # If using Python < 2.7, you must install 'argparse' yourself... - # 'argparse', # 1.2.1 - ], + install_requires = requires, extras_require = { - # - # Same guidelines apply to the extra dependency versions. 'db': [ # # package # low high # + 'alembic', # 0.2.1 'decorator', # 3.3.2 'py-bcrypt', # 0.2 'SQLAlchemy', # 0.7.6 - 'sqlalchemy-migrate', # 0.7.2 + # 'sqlalchemy-migrate', # 0.7.2 'Tempita', # 0.5.1 ], @@ -150,6 +160,7 @@ edbobw = edbob.commands:main edbob = edbob.pyramid.scaffolds:Template [edbob.commands] +db = edbob.commands:DatabaseCommand shell = edbob.commands:ShellCommand uuid = edbob.commands:UuidCommand