use logging module for output, fixes #26

This commit is contained in:
iElectric
2009-07-08 23:57:15 +02:00
parent 67af81806d
commit 1c166845f8
16 changed files with 91 additions and 45 deletions

View File

@@ -1,6 +1,7 @@
0.5.5 0.5.5
----- -----
- use Python logging for output, can be shut down by passing ``logging=False`` to :func:`migrate.versioning.shell.main`
- `url` parameter can also be an :class:`Engine` instance (this usage is discouraged though sometimes necessary) - `url` parameter can also be an :class:`Engine` instance (this usage is discouraged though sometimes necessary)
- added support for SQLAlchemy 0.6 (missing oracle and firebird) by Michael Bayer - added support for SQLAlchemy 0.6 (missing oracle and firebird) by Michael Bayer
- alter, create, drop column / rename table / rename index constructs now accept `alter_metadata` parameter. If True, it will modify Column/Table objects according to changes. Otherwise, everything will be untouched. - alter, create, drop column / rename table / rename index constructs now accept `alter_metadata` parameter. If True, it will modify Column/Table objects according to changes. Otherwise, everything will be untouched.

View File

@@ -28,12 +28,14 @@
import sys import sys
import inspect import inspect
import warnings import warnings
import logging
from migrate.versioning import (exceptions, repository, schema, version, from migrate.versioning import (exceptions, repository, schema, version,
script as script_) # command name conflict script as script_) # command name conflict
from migrate.versioning.util import catch_known_errors, construct_engine from migrate.versioning.util import catch_known_errors, construct_engine
log = logging.getLogger(__name__)
__all__ = [ __all__ = [
'help', 'help',
'create', 'create',
@@ -211,14 +213,14 @@ def test(url, repository, **opts):
script = repos.version(None).script() script = repos.version(None).script()
# Upgrade # Upgrade
print "Upgrading...", log.info("Upgrading...")
script.run(engine, 1) script.run(engine, 1)
print "done" log.info("done")
print "Downgrading...", log.info("Downgrading...")
script.run(engine, -1) script.run(engine, -1)
print "done" log.info("done")
print "Success" log.info("Success")
def version_control(url, repository, version=None, **opts): def version_control(url, repository, version=None, **opts):
@@ -333,13 +335,13 @@ def _migrate(url, repository, version, upgrade, err, **opts):
changeset = schema.changeset(version) changeset = schema.changeset(version)
for ver, change in changeset: for ver, change in changeset:
nextver = ver + changeset.step nextver = ver + changeset.step
print '%s -> %s... ' % (ver, nextver) log.info('%s -> %s... ', ver, nextver)
if opts.get('preview_sql'): if opts.get('preview_sql'):
if isinstance(change, PythonScript): if isinstance(change, PythonScript):
print change.preview_sql(url, changeset.step, **opts) log.info(change.preview_sql(url, changeset.step, **opts))
elif isinstance(change, SqlScript): elif isinstance(change, SqlScript):
print change.source() log.info(change.source())
elif opts.get('preview_py'): elif opts.get('preview_py'):
if not isinstance(change, PythonScript): if not isinstance(change, PythonScript):
@@ -349,10 +351,10 @@ def _migrate(url, repository, version, upgrade, err, **opts):
module = schema.repository.version(source_ver).script().module module = schema.repository.version(source_ver).script().module
funcname = upgrade and "upgrade" or "downgrade" funcname = upgrade and "upgrade" or "downgrade"
func = getattr(module, funcname) func = getattr(module, funcname)
print inspect.getsource(func) log.info(inspect.getsource(func))
else: else:
schema.runchange(ver, change, changeset.step) schema.runchange(ver, change, changeset.step)
print 'done' log.info('done')
def _migrate_version(schema, version, upgrade, err): def _migrate_version(schema, version, upgrade, err):

View File

@@ -1,5 +1,13 @@
"""Things that should be imported by all migrate packages""" """Things that should be imported by all migrate packages"""
#__all__ = ['logging','log','databases','operations'] from sqlalchemy.util import OrderedDict
from logger import logging, log
from const import databases, operations
__all__ = ['databases', 'operations']
databases = ('sqlite', 'postgres', 'mysql', 'oracle', 'mssql', 'firebird')
# Map operation names to function names
operations = OrderedDict()
operations['upgrade'] = 'upgrade'
operations['downgrade'] = 'downgrade'

View File

@@ -1,11 +0,0 @@
from sqlalchemy.util import OrderedDict
__all__ = ['databases', 'operations']
databases = ('sqlite', 'postgres', 'mysql', 'oracle', 'mssql', 'firebird')
# Map operation names to function names
operations = OrderedDict()
operations['upgrade'] = 'upgrade'
operations['downgrade'] = 'downgrade'

View File

@@ -1,9 +0,0 @@
"""Manages logging (to stdout) for our versioning system.
"""
import logging
log=logging.getLogger('migrate.versioning')
log.setLevel(logging.WARNING)
log.addHandler(logging.StreamHandler())
__all__ = ['log','logging']

View File

@@ -7,11 +7,13 @@
""" """
import sys import sys
import logging
import migrate import migrate
import sqlalchemy import sqlalchemy
log = logging.getLogger(__name__)
HEADER = """ HEADER = """
## File autogenerated by genmodel.py ## File autogenerated by genmodel.py

View File

@@ -4,12 +4,15 @@
import os import os
import shutil import shutil
import logging
from migrate.versioning import exceptions from migrate.versioning import exceptions
from migrate.versioning.base import * from migrate.versioning.base import *
from migrate.versioning.util import KeyedInstance from migrate.versioning.util import KeyedInstance
log = logging.getLogger(__name__)
class Pathed(KeyedInstance): class Pathed(KeyedInstance):
""" """
A class associated with a path/directory tree. A class associated with a path/directory tree.
@@ -32,7 +35,7 @@ class Pathed(KeyedInstance):
"""Try to initialize this object's parent, if it has one""" """Try to initialize this object's parent, if it has one"""
parent_path = self.__class__._parent_path(path) parent_path = self.__class__._parent_path(path)
self.parent = self.__class__.parent(parent_path) self.parent = self.__class__.parent(parent_path)
log.info("Getting parent %r:%r" % (self.__class__.parent, parent_path)) log.debug("Getting parent %r:%r" % (self.__class__.parent, parent_path))
self.parent._init_child(path, self) self.parent._init_child(path, self)
def _init_child(self, child, path): def _init_child(self, child, path):

View File

@@ -4,6 +4,7 @@
import os import os
import shutil import shutil
import string import string
import logging
from pkg_resources import resource_string, resource_filename from pkg_resources import resource_string, resource_filename
from migrate.versioning import exceptions, script, version, pathed, cfgparse from migrate.versioning import exceptions, script, version, pathed, cfgparse
@@ -11,6 +12,8 @@ from migrate.versioning.template import template
from migrate.versioning.base import * from migrate.versioning.base import *
log = logging.getLogger(__name__)
class Changeset(dict): class Changeset(dict):
"""A collection of changes to be applied to a database. """A collection of changes to be applied to a database.
@@ -67,13 +70,13 @@ class Repository(pathed.Pathed):
_versions = 'versions' _versions = 'versions'
def __init__(self, path): def __init__(self, path):
log.info('Loading repository %s...' % path) log.debug('Loading repository %s...' % path)
self.verify(path) self.verify(path)
super(Repository, self).__init__(path) super(Repository, self).__init__(path)
self.config = cfgparse.Config(os.path.join(self.path, self._config)) self.config = cfgparse.Config(os.path.join(self.path, self._config))
self.versions = version.Collection(os.path.join(self.path, self.versions = version.Collection(os.path.join(self.path,
self._versions)) self._versions))
log.info('Repository %s loaded successfully' % path) log.debug('Repository %s loaded successfully' % path)
log.debug('Config: %r' % self.config.to_dict()) log.debug('Config: %r' % self.config.to_dict())
@classmethod @classmethod

View File

@@ -2,6 +2,7 @@
Database schema version management. Database schema version management.
""" """
import sys import sys
import logging
from sqlalchemy import (Table, Column, MetaData, String, Text, Integer, from sqlalchemy import (Table, Column, MetaData, String, Text, Integer,
create_engine) create_engine)
@@ -15,6 +16,8 @@ from migrate.versioning.util import load_model
from migrate.versioning.version import VerNum from migrate.versioning.version import VerNum
log = logging.getLogger(__name__)
class ControlledSchema(object): class ControlledSchema(object):
"""A database under version control""" """A database under version control"""

View File

@@ -1,9 +1,14 @@
""" """
Schema differencing support. Schema differencing support.
""" """
import logging
import sqlalchemy import sqlalchemy
from migrate.changeset import SQLA_06 from migrate.changeset import SQLA_06
log = logging.getLogger(__name__)
def getDiffOfModelAgainstDatabase(model, conn, excludeTables=None): def getDiffOfModelAgainstDatabase(model, conn, excludeTables=None):
""" """
Return differences of model against database. Return differences of model against database.

View File

@@ -1,10 +1,13 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import logging
from migrate.versioning.base import log, operations from migrate.versioning.base import operations
from migrate.versioning import pathed, exceptions from migrate.versioning import pathed, exceptions
log = logging.getLogger(__name__)
class BaseScript(pathed.Pathed): class BaseScript(pathed.Pathed):
"""Base class for other types of scripts. """Base class for other types of scripts.
All scripts have the following properties: All scripts have the following properties:
@@ -20,10 +23,10 @@ class BaseScript(pathed.Pathed):
""" # TODO: sphinxfy this and implement it correctly """ # TODO: sphinxfy this and implement it correctly
def __init__(self, path): def __init__(self, path):
log.info('Loading script %s...' % path) log.debug('Loading script %s...' % path)
self.verify(path) self.verify(path)
super(BaseScript, self).__init__(path) super(BaseScript, self).__init__(path)
log.info('Script %s loaded successfully' % path) log.debug('Script %s loaded successfully' % path)
@classmethod @classmethod
def verify(cls, path): def verify(cls, path):

View File

@@ -1,8 +1,9 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import warnings
import shutil import shutil
import warnings
import logging
from StringIO import StringIO from StringIO import StringIO
import migrate import migrate
@@ -12,6 +13,8 @@ from migrate.versioning.template import template
from migrate.versioning.script import base from migrate.versioning.script import base
from migrate.versioning.util import import_path, load_model, construct_engine from migrate.versioning.util import import_path, load_model, construct_engine
log = logging.getLogger(__name__)
__all__ = ['PythonScript'] __all__ = ['PythonScript']
class PythonScript(base.BaseScript): class PythonScript(base.BaseScript):

View File

@@ -1,9 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import logging
from migrate.versioning.script import base from migrate.versioning.script import base
log = logging.getLogger(__name__)
class SqlScript(base.BaseScript): class SqlScript(base.BaseScript):
"""A file containing plain SQL statements.""" """A file containing plain SQL statements."""

View File

@@ -2,10 +2,12 @@
import sys import sys
import inspect import inspect
import logging
from optparse import OptionParser, BadOptionError from optparse import OptionParser, BadOptionError
from migrate.versioning.base import *
from migrate.versioning import api, exceptions from migrate.versioning import api, exceptions
from migrate.versioning.base import *
from migrate.versioning.util import asbool
alias = dict( alias = dict(
@@ -50,10 +52,14 @@ class PassiveOptionParser(OptionParser):
del rargs[0] del rargs[0]
def main(argv=None, **kwargs): def main(argv=None, **kwargs):
"""kwargs are default options that can be overriden with passing """Shell interface to :mod:`migrate.versioning.api`.
--some_option to cmdline
"""
kwargs are default options that can be overriden with passing
--some_option as command line option
:param logging: Let migrate configure logging
:type logging: bool
"""
argv = argv or list(sys.argv[1:]) argv = argv or list(sys.argv[1:])
commands = list(api.__all__) commands = list(api.__all__)
commands.sort() commands.sort()
@@ -138,6 +144,17 @@ def main(argv=None, **kwargs):
# apply overrides # apply overrides
kwargs.update(override_kwargs) kwargs.update(override_kwargs)
# configure logging
if asbool(kwargs.pop('logging', True)):
logger = logging.getLogger()
logger.setLevel(logging.INFO)
formatter = logging.Formatter("%(message)s")
ch = logging.StreamHandler(sys.stdout)
ch.setFormatter(formatter)
logger.addHandler(ch)
log = logging.getLogger(__name__)
# check if all args are given # check if all args are given
try: try:
num_defaults = len(f_defaults) num_defaults = len(f_defaults)
@@ -153,7 +170,7 @@ def main(argv=None, **kwargs):
try: try:
ret = command_func(**kwargs) ret = command_func(**kwargs)
if ret is not None: if ret is not None:
print ret log.info(ret)
except (exceptions.UsageError, exceptions.KnownError), e: except (exceptions.UsageError, exceptions.KnownError), e:
parser.error(e.args[0]) parser.error(e.args[0])

View File

@@ -4,10 +4,13 @@
import os import os
import re import re
import shutil import shutil
import logging
from migrate.versioning import exceptions, pathed, script from migrate.versioning import exceptions, pathed, script
log = logging.getLogger(__name__)
class VerNum(object): class VerNum(object):
"""A version number that behaves like a string and int at the same time""" """A version number that behaves like a string and int at the same time"""

View File

@@ -31,6 +31,16 @@ class TestShellCommands(Shell):
self.assertTrue(result.stdout) self.assertTrue(result.stdout)
self.assertFalse(result.stderr) self.assertFalse(result.stderr)
def test_shutdown_logging(self):
"""Try to shutdown logging output"""
repos = self.tmp_repos()
result = self.env.run('migrate create %s repository_name' % repos)
result = self.env.run('migrate version %s --logging=False' % repos)
self.assertEqual(result.stdout, '')
# TODO: assert logging messages to 0
shell.main(['version', repos], logging=False)
def test_main(self): def test_main(self):
"""Test main() function""" """Test main() function"""
# TODO: test output? # TODO: test output?