Changeset - 28a4bb11bb6f
[Not reviewed]
beta
0 9 0
Marcin Kuzminski - 15 years ago 2010-12-11 03:41:27
marcin@python-works.com
dbmigrations:
added first working upgrade script
fixed wrong versions
fixed template path
8 files changed with 43 insertions and 25 deletions:
0 comments (0 inline, 0 general)
rhodecode/__init__.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.__init__
 
    ~~~~~~~~~~~~~~~~~~
 

	
 
    RhodeCode, a web based repository management based on pylons
 
    versioning implementation: http://semver.org/
 

	
 
    :created_on: Apr 9, 2010
 
    :author: marcink
 
    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
 
    :license: GPLv3, see COPYING for more details.
 
"""
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 

	
 

	
 
VERSION = (1, 1, 0, 'beta')
 
__version__ = '.'.join((str(each) for each in VERSION[:4]))
 
__dbversion__ = 1 #defines current db version for migrations
 
__dbversion__ = 2 #defines current db version for migrations
 

	
 
from rhodecode.lib.utils import get_current_revision
 
_rev = get_current_revision()
 

	
 
if len(VERSION) > 3 and _rev:
 
    __version__ += ' [rev:%s]' % _rev[0]
 

	
 
def get_version():
 
    """Returns shorter version (digit parts only) as string."""
 

	
 
    return '.'.join((str(each) for each in VERSION[:3]))
 

	
 
BACKENDS = {
 
    'hg': 'Mercurial repository',
 
   #'git': 'Git repository',
 
}
rhodecode/lib/dbmigrate/__init__.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.lib.dbmigrate.__init__
 
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
    
 
    Database migration modules
 
    
 
    :created_on: Dec 11, 2010
 
    :author: marcink
 
    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
 
    :license: GPLv3, see COPYING for more details.
 
"""
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 

	
 
import logging
 
from sqlalchemy import engine_from_config
 

	
 
from rhodecode import __dbversion__
 
from rhodecode.lib.dbmigrate.migrate.versioning import api
 
from rhodecode.lib.dbmigrate.migrate.exceptions import \
 
    DatabaseNotControlledError
 
from rhodecode.lib.utils import BasePasterCommand, Command, add_cache
 

	
 
log = logging.getLogger(__name__)
 

	
 
class UpgradeDb(BasePasterCommand):
 
    """Command used for paster to upgrade our database to newer version
 
    """
 

	
 
    max_args = 1
 
    min_args = 1
 

	
 
    usage = "CONFIG_FILE"
 
    summary = "Upgrades current db to newer version given configuration file"
 
    group_name = "RhodeCode"
 

	
 
    parser = Command.standard_parser(verbose=True)
 

	
 
    def command(self):
 
        from pylons import config
 

	
 
        add_cache(config)
 
        #engine = engine_from_config(config, 'sqlalchemy.db1.')
 
        #rint engine
 

	
 
        from rhodecode.lib.dbmigrate.migrate.versioning import api
 
        path = 'rhodecode/lib/dbmigrate'
 
        #engine = engine_from_config(config, 'sqlalchemy.db1.')
 

	
 
        repository_path = 'rhodecode/lib/dbmigrate'
 
        db_uri = config['sqlalchemy.db1.url']
 

	
 
        try:
 
            curr_version = api.db_version(config['sqlalchemy.db1.url'], path)
 
            curr_version = api.db_version(db_uri, repository_path)
 
            msg = ('Found current database under version'
 
                 ' control with version %s' % curr_version)
 

	
 
        except (RuntimeError, DatabaseNotControlledError), e:
 
            curr_version = 0
 
            curr_version = 1
 
            msg = ('Current database is not under version control setting'
 
                   ' as version %s' % curr_version)
 
            api.version_control(db_uri, repository_path, curr_version)
 

	
 

	
 
        print msg
 
        #now we have our dbversion we can do upgrade
 

	
 
        msg = 'attempting to do database upgrade to version %s' % __dbversion__
 
        print msg
 
        api.upgrade(db_uri, repository_path, __dbversion__)
 

	
 
    def update_parser(self):
 
        self.parser.add_option('--sql',
 
                      action='store_true',
 
                      dest='just_sql',
 
                      help="Prints upgrade sql for further investigation",
 
                      default=False)
rhodecode/lib/dbmigrate/migrate/versioning/api.py
Show inline comments
 
"""
 
   This module provides an external API to the versioning system.
 

	
 
   .. versionchanged:: 0.6.0
 
    :func:`migrate.versioning.api.test` and schema diff functions
 
    changed order of positional arguments so all accept `url` and `repository`
 
    as first arguments.
 

	
 
   .. versionchanged:: 0.5.4
 
    ``--preview_sql`` displays source file when using SQL scripts.
 
    If Python script is used, it runs the action with mocked engine and
 
    returns captured SQL statements.
 

	
 
   .. versionchanged:: 0.5.4
 
    Deprecated ``--echo`` parameter in favour of new
 
    :func:`migrate.versioning.util.construct_engine` behavior.
 
"""
 

	
 
# Dear migrate developers,
 
#
 
# please do not comment this module using sphinx syntax because its
 
# docstrings are presented as user help and most users cannot
 
# interpret sphinx annotated ReStructuredText.
 
#
 
# Thanks,
 
# Jan Dittberner
 

	
 
import sys
 
import inspect
 
import logging
 

	
 
from rhodecode.lib.dbmigrate.migrate import exceptions
 
from rhodecode.lib.dbmigrate.migrate.versioning import (repository, schema, version,
 
    script as script_) # command name conflict
 
from rhodecode.lib.dbmigrate.migrate.versioning import repository, schema, version, \
 
    script as script_ # command name conflict
 
from rhodecode.lib.dbmigrate.migrate.versioning.util import catch_known_errors, with_engine
 

	
 

	
 
log = logging.getLogger(__name__)
 
command_desc = {
 
    'help': 'displays help on a given command',
 
    'create': 'create an empty repository at the specified path',
 
    'script': 'create an empty change Python script',
 
    'script_sql': 'create empty change SQL scripts for given database',
 
    'version': 'display the latest version available in a repository',
 
    'db_version': 'show the current version of the repository under version control',
 
    'source': 'display the Python code for a particular version in this repository',
 
    'version_control': 'mark a database as under this repository\'s version control',
 
    'upgrade': 'upgrade a database to a later version',
 
    'downgrade': 'downgrade a database to an earlier version',
 
    'drop_version_control': 'removes version control from a database',
 
    'manage': 'creates a Python script that runs Migrate with a set of default values',
 
    'test': 'performs the upgrade and downgrade command on the given database',
 
    'compare_model_to_db': 'compare MetaData against the current database state',
 
    'create_model': 'dump the current database as a Python model to stdout',
 
    'make_update_script_for_model': 'create a script changing the old MetaData to the new (current) MetaData',
 
    'update_db_from_model': 'modify the database to match the structure of the current MetaData',
 
}
 
__all__ = command_desc.keys()
 

	
 
Repository = repository.Repository
 
ControlledSchema = schema.ControlledSchema
 
VerNum = version.VerNum
 
PythonScript = script_.PythonScript
 
SqlScript = script_.SqlScript
 

	
 

	
 
# deprecated
 
def help(cmd=None, **opts):
 
    """%prog help COMMAND
 

	
 
    Displays help on a given command.
 
    """
 
    if cmd is None:
 
        raise exceptions.UsageError(None)
 
    try:
 
        func = globals()[cmd]
 
    except:
 
        raise exceptions.UsageError(
 
            "'%s' isn't a valid command. Try 'help COMMAND'" % cmd)
 
    ret = func.__doc__
 
    if sys.argv[0]:
 
        ret = ret.replace('%prog', sys.argv[0])
 
    return ret
 

	
 
@catch_known_errors
 
def create(repository, name, **opts):
 
    """%prog create REPOSITORY_PATH NAME [--table=TABLE]
 

	
 
    Create an empty repository at the specified path.
 

	
 
    You can specify the version_table to be used; by default, it is
 
    'migrate_version'.  This table is created in all version-controlled
 
    databases.
 
    """
 
    repo_path = Repository.create(repository, name, **opts)
 

	
 

	
 
@catch_known_errors
 
def script(description, repository, **opts):
 
    """%prog script DESCRIPTION REPOSITORY_PATH
 

	
 
    Create an empty change script using the next unused version number
 
    appended with the given description.
 

	
 
    For instance, manage.py script "Add initial tables" creates:
 
    repository/versions/001_Add_initial_tables.py
 
    """
 
    repo = Repository(repository)
 
    repo.create_script(description, **opts)
 

	
 

	
 
@catch_known_errors
 
def script_sql(database, repository, **opts):
 
    """%prog script_sql DATABASE REPOSITORY_PATH
 

	
 
    Create empty change SQL scripts for given DATABASE, where DATABASE
 
    is either specific ('postgres', 'mysql', 'oracle', 'sqlite', etc.)
 
    or generic ('default').
 

	
 
    For instance, manage.py script_sql postgres creates:
 
    repository/versions/001_postgres_upgrade.sql and
 
    repository/versions/001_postgres_postgres.sql
 
    """
 
    repo = Repository(repository)
 
    repo.create_script_sql(database, **opts)
 

	
 

	
 
def version(repository, **opts):
 
    """%prog version REPOSITORY_PATH
 

	
 
    Display the latest version available in a repository.
 
    """
 
    repo = Repository(repository)
 
    return repo.latest
 

	
 

	
 
@with_engine
 
def db_version(url, repository, **opts):
 
    """%prog db_version URL REPOSITORY_PATH
 

	
 
    Show the current version of the repository with the given
 
    connection string, under version control of the specified
 
    repository.
 

	
 
    The url should be any valid SQLAlchemy connection string.
 
    """
 
    engine = opts.pop('engine')
 
    schema = ControlledSchema(engine, repository)
 
    return schema.version
 

	
 

	
 
def source(version, dest=None, repository=None, **opts):
 
    """%prog source VERSION [DESTINATION] --repository=REPOSITORY_PATH
 

	
 
    Display the Python code for a particular version in this
 
    repository.  Save it to the file at DESTINATION or, if omitted,
 
    send to stdout.
 
    """
 
    if repository is None:
 
        raise exceptions.UsageError("A repository must be specified")
 
    repo = Repository(repository)
 
    ret = repo.version(version).script().source()
 
    if dest is not None:
 
        dest = open(dest, 'w')
 
        dest.write(ret)
 
        dest.close()
 
        ret = None
 
    return ret
 

	
 

	
 
def upgrade(url, repository, version=None, **opts):
 
    """%prog upgrade URL REPOSITORY_PATH [VERSION] [--preview_py|--preview_sql]
 

	
 
    Upgrade a database to a later version.
 

	
 
    This runs the upgrade() function defined in your change scripts.
 

	
 
    By default, the database is updated to the latest available
 
    version. You may specify a version instead, if you wish.
 

	
 
    You may preview the Python or SQL code to be executed, rather than
 
    actually executing it, using the appropriate 'preview' option.
 
    """
 
    err = "Cannot upgrade a database of version %s to version %s. "\
 
        "Try 'downgrade' instead."
 
    return _migrate(url, repository, version, upgrade=True, err=err, **opts)
 

	
 

	
 
def downgrade(url, repository, version, **opts):
 
    """%prog downgrade URL REPOSITORY_PATH VERSION [--preview_py|--preview_sql]
 

	
 
    Downgrade a database to an earlier version.
 

	
 
    This is the reverse of upgrade; this runs the downgrade() function
 
    defined in your change scripts.
 

	
 
    You may preview the Python or SQL code to be executed, rather than
 
    actually executing it, using the appropriate 'preview' option.
 
    """
 
    err = "Cannot downgrade a database of version %s to version %s. "\
 
        "Try 'upgrade' instead."
 
    return _migrate(url, repository, version, upgrade=False, err=err, **opts)
 

	
 
@with_engine
 
def test(url, repository, **opts):
 
    """%prog test URL REPOSITORY_PATH [VERSION]
 

	
 
    Performs the upgrade and downgrade option on the given
 
    database. This is not a real test and may leave the database in a
 
    bad state. You should therefore better run the test on a copy of
 
    your database.
 
    """
 
    engine = opts.pop('engine')
 
    repos = Repository(repository)
 
    script = repos.version(None).script()
 

	
 
    # Upgrade
 
    log.info("Upgrading...")
 
    script.run(engine, 1)
 
    log.info("done")
 

	
 
    log.info("Downgrading...")
 
    script.run(engine, -1)
 
    log.info("done")
 
    log.info("Success")
 

	
 

	
 
@with_engine
 
def version_control(url, repository, version=None, **opts):
 
    """%prog version_control URL REPOSITORY_PATH [VERSION]
 

	
 
    Mark a database as under this repository's version control.
 

	
 
    Once a database is under version control, schema changes should
 
    only be done via change scripts in this repository.
 

	
 
    This creates the table version_table in the database.
 

	
 
    The url should be any valid SQLAlchemy connection string.
 

	
 
    By default, the database begins at version 0 and is assumed to be
 
    empty.  If the database is not empty, you may specify a version at
 
    which to begin instead. No attempt is made to verify this
 
    version's correctness - the database schema is expected to be
 
    identical to what it would be if the database were created from
 
    scratch.
 
    """
 
    engine = opts.pop('engine')
 
    ControlledSchema.create(engine, repository, version)
 

	
 

	
 
@with_engine
 
def drop_version_control(url, repository, **opts):
 
    """%prog drop_version_control URL REPOSITORY_PATH
 

	
 
    Removes version control from a database.
 
    """
 
    engine = opts.pop('engine')
 
    schema = ControlledSchema(engine, repository)
 
    schema.drop()
 

	
 

	
 
def manage(file, **opts):
 
    """%prog manage FILENAME [VARIABLES...]
 

	
 
    Creates a script that runs Migrate with a set of default values.
 

	
 
    For example::
 

	
 
        %prog manage manage.py --repository=/path/to/repository \
 
--url=sqlite:///project.db
 

	
 
    would create the script manage.py. The following two commands
 
    would then have exactly the same results::
 

	
 
        python manage.py version
 
        %prog version --repository=/path/to/repository
 
    """
 
    Repository.create_manage_file(file, **opts)
 

	
 

	
 
@with_engine
 
def compare_model_to_db(url, repository, model, **opts):
 
    """%prog compare_model_to_db URL REPOSITORY_PATH MODEL
 

	
 
    Compare the current model (assumed to be a module level variable
 
    of type sqlalchemy.MetaData) against the current database.
 

	
 
    NOTE: This is EXPERIMENTAL.
 
    """  # TODO: get rid of EXPERIMENTAL label
 
    engine = opts.pop('engine')
 
    return ControlledSchema.compare_model_to_db(engine, model, repository)
 

	
 

	
 
@with_engine
 
def create_model(url, repository, **opts):
 
    """%prog create_model URL REPOSITORY_PATH [DECLERATIVE=True]
 

	
 
    Dump the current database as a Python model to stdout.
 

	
 
    NOTE: This is EXPERIMENTAL.
 
    """  # TODO: get rid of EXPERIMENTAL label
 
    engine = opts.pop('engine')
 
    declarative = opts.get('declarative', False)
 
    return ControlledSchema.create_model(engine, repository, declarative)
 

	
 

	
 
@catch_known_errors
 
@with_engine
 
def make_update_script_for_model(url, repository, oldmodel, model, **opts):
 
    """%prog make_update_script_for_model URL OLDMODEL MODEL REPOSITORY_PATH
 

	
 
    Create a script changing the old Python model to the new (current)
 
    Python model, sending to stdout.
 

	
 
    NOTE: This is EXPERIMENTAL.
 
    """  # TODO: get rid of EXPERIMENTAL label
 
    engine = opts.pop('engine')
 
    return PythonScript.make_update_script_for_model(
 
        engine, oldmodel, model, repository, **opts)
 

	
 

	
 
@with_engine
 
def update_db_from_model(url, repository, model, **opts):
 
    """%prog update_db_from_model URL REPOSITORY_PATH MODEL
 

	
 
    Modify the database to match the structure of the current Python
 
    model. This also sets the db_version number to the latest in the
 
    repository.
 

	
 
    NOTE: This is EXPERIMENTAL.
 
    """  # TODO: get rid of EXPERIMENTAL label
 
    engine = opts.pop('engine')
 
    schema = ControlledSchema(engine, repository)
 
    schema.update_db_from_model(model)
 

	
 
@with_engine
 
def _migrate(url, repository, version, upgrade, err, **opts):
 
    engine = opts.pop('engine')
 
    url = str(engine.url)
 
    schema = ControlledSchema(engine, repository)
 
    version = _migrate_version(schema, version, upgrade, err)
 

	
 
    changeset = schema.changeset(version)
 
    for ver, change in changeset:
 
        nextver = ver + changeset.step
 
        log.info('%s -> %s... ', ver, nextver)
 

	
 
        if opts.get('preview_sql'):
 
            if isinstance(change, PythonScript):
 
                log.info(change.preview_sql(url, changeset.step, **opts))
 
            elif isinstance(change, SqlScript):
 
                log.info(change.source())
 

	
 
        elif opts.get('preview_py'):
 
            if not isinstance(change, PythonScript):
 
                raise exceptions.UsageError("Python source can be only displayed"
 
                    " for python migration files")
 
            source_ver = max(ver, nextver)
 
            module = schema.repository.version(source_ver).script().module
 
            funcname = upgrade and "upgrade" or "downgrade"
 
            func = getattr(module, funcname)
 
            log.info(inspect.getsource(func))
 
        else:
 
            schema.runchange(ver, change, changeset.step)
 
            log.info('done')
 

	
 

	
 
def _migrate_version(schema, version, upgrade, err):
 
    if version is None:
 
        return version
 
    # Version is specified: ensure we're upgrading in the right direction
 
    # (current version < target version for upgrading; reverse for down)
 
    version = VerNum(version)
 
    cur = schema.version
 
    if upgrade is not None:
 
        if upgrade:
 
            direction = cur <= version
 
        else:
 
            direction = cur >= version
 
        if not direction:
 
            raise exceptions.KnownError(err % (cur, version))
 
    return version
rhodecode/lib/dbmigrate/migrate/versioning/script/sql.py
Show inline comments
 
#!/usr/bin/env python
 
# -*- coding: utf-8 -*-
 
import logging
 
import shutil
 

	
 
from rhodecode.lib.dbmigrate.migrate.versioning.script import base
 
from rhodecode.lib.dbmigrate.migrate.versioning.template import Template
 

	
 

	
 
log = logging.getLogger(__name__)
 

	
 
class SqlScript(base.BaseScript):
 
    """A file containing plain SQL statements."""
 

	
 
    @classmethod
 
    def create(cls, path, **opts):
 
        """Create an empty migration script at specified path
 
        
 
        :returns: :class:`SqlScript instance <migrate.versioning.script.sql.SqlScript>`"""
 
        cls.require_notfound(path)
 

	
 
        src = Template(opts.pop('templates_path', None)).get_sql_script(theme=opts.pop('templates_theme', None))
 
        shutil.copy(src, path)
 
        return cls(path)
 

	
 
    # TODO: why is step parameter even here?
 
    def run(self, engine, step=None, executemany=True):
 
        """Runs SQL script through raw dbapi execute call"""
 
        text = self.source()
 
        # Don't rely on SA's autocommit here
 
        # (SA uses .startswith to check if a commit is needed. What if script
 
        # starts with a comment?)
 
        conn = engine.connect()
 
        try:
 
            trans = conn.begin()
 
            try:
 
                # HACK: SQLite doesn't allow multiple statements through
 
                # its execute() method, but it provides executescript() instead
 
                dbapi = conn.engine.raw_connection()
 
                if executemany and getattr(dbapi, 'executescript', None):
 
                    dbapi.executescript(text)
 
                else:
 
                    conn.execute(text)
 
                trans.commit()
 
            except:
 
                trans.rollback()
 
                raise
 
        finally:
 
            conn.close()
rhodecode/lib/dbmigrate/migrate/versioning/template.py
Show inline comments
 
#!/usr/bin/env python
 
# -*- coding: utf-8 -*-
 

	
 
import os
 
import shutil
 
import sys
 

	
 
from pkg_resources import resource_filename
 

	
 
from rhodecode.lib.dbmigrate.migrate.versioning.config import *
 
from rhodecode.lib.dbmigrate.migrate.versioning import pathed
 

	
 

	
 
class Collection(pathed.Pathed):
 
    """A collection of templates of a specific type"""
 
    _mask = None
 

	
 
    def get_path(self, file):
 
        return os.path.join(self.path, str(file))
 

	
 

	
 
class RepositoryCollection(Collection):
 
    _mask = '%s'
 

	
 
class ScriptCollection(Collection):
 
    _mask = '%s.py_tmpl'
 

	
 
class ManageCollection(Collection):
 
    _mask = '%s.py_tmpl'
 

	
 
class SQLScriptCollection(Collection):
 
    _mask = '%s.py_tmpl'
 

	
 
class Template(pathed.Pathed):
 
    """Finds the paths/packages of various Migrate templates.
 
    
 
    :param path: Templates are loaded from rhodecode.lib.dbmigrate.migrate package
 
    if `path` is not provided.
 
    """
 
    pkg = 'migrate.versioning.templates'
 
    pkg = 'rhodecode.lib.dbmigrate.migrate.versioning.templates'
 
    _manage = 'manage.py_tmpl'
 

	
 
    def __new__(cls, path=None):
 
        if path is None:
 
            path = cls._find_path(cls.pkg)
 
        return super(Template, cls).__new__(cls, path)
 

	
 
    def __init__(self, path=None):
 
        if path is None:
 
            path = Template._find_path(self.pkg)
 
        super(Template, self).__init__(path)
 
        self.repository = RepositoryCollection(os.path.join(path, 'repository'))
 
        self.script = ScriptCollection(os.path.join(path, 'script'))
 
        self.manage = ManageCollection(os.path.join(path, 'manage'))
 
        self.sql_script = SQLScriptCollection(os.path.join(path, 'sql_script'))
 

	
 
    @classmethod
 
    def _find_path(cls, pkg):
 
        """Returns absolute path to dotted python package."""
 
        tmp_pkg = pkg.rsplit('.', 1)
 

	
 
        if len(tmp_pkg) != 1:
 
            return resource_filename(tmp_pkg[0], tmp_pkg[1])
 
        else:
 
            return resource_filename(tmp_pkg[0], '')
 

	
 
    def _get_item(self, collection, theme=None):
 
        """Locates and returns collection.
 
        
 
        :param collection: name of collection to locate
 
        :param type_: type of subfolder in collection (defaults to "_default")
 
        :returns: (package, source)
 
        :rtype: str, str
 
        """
 
        item = getattr(self, collection)
 
        theme_mask = getattr(item, '_mask')
 
        theme = theme_mask % (theme or 'default')
 
        return item.get_path(theme)
 

	
 
    def get_repository(self, *a, **kw):
 
        """Calls self._get_item('repository', *a, **kw)"""
 
        return self._get_item('repository', *a, **kw)
 
    
 
    def get_script(self, *a, **kw):
 
        """Calls self._get_item('script', *a, **kw)"""
 
        return self._get_item('script', *a, **kw)
 

	
 
    def get_sql_script(self, *a, **kw):
 
        """Calls self._get_item('sql_script', *a, **kw)"""
 
        return self._get_item('sql_script', *a, **kw)
 

	
 
    def get_manage(self, *a, **kw):
 
        """Calls self._get_item('manage', *a, **kw)"""
 
        return self._get_item('manage', *a, **kw)
rhodecode/lib/dbmigrate/versions/001_initial_release.py
Show inline comments
 
from migrate import *
 

	
 
#==============================================================================
 
# DB INITIAL MODEL
 
#==============================================================================
 
import logging
 
import datetime
 

	
 
from sqlalchemy import *
 
from sqlalchemy.exc import DatabaseError
 
from sqlalchemy.orm import relation, backref, class_mapper
 
from sqlalchemy.orm.session import Session
 
from rhodecode.model.meta import Base
 

	
 
from rhodecode.model.meta import Base
 
from rhodecode.lib.dbmigrate.migrate import *
 

	
 
log = logging.getLogger(__name__)
 

	
 
class BaseModel(object):
 

	
 
    @classmethod
 
    def _get_keys(cls):
 
        """return column names for this model """
 
        return class_mapper(cls).c.keys()
 

	
 
    def get_dict(self):
 
        """return dict with keys and values corresponding 
 
        to this model data """
 

	
 
        d = {}
 
        for k in self._get_keys():
 
            d[k] = getattr(self, k)
 
        return d
 

	
 
    def get_appstruct(self):
 
        """return list with keys and values tupples corresponding 
 
        to this model data """
 

	
 
        l = []
 
        for k in self._get_keys():
 
            l.append((k, getattr(self, k),))
 
        return l
 

	
 
    def populate_obj(self, populate_dict):
 
        """populate model with data from given populate_dict"""
 

	
 
        for k in self._get_keys():
 
            if k in populate_dict:
 
                setattr(self, k, populate_dict[k])
 

	
 
class RhodeCodeSettings(Base, BaseModel):
 
    __tablename__ = 'rhodecode_settings'
 
    __table_args__ = (UniqueConstraint('app_settings_name'), {'useexisting':True})
 
    app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    app_settings_name = Column("app_settings_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    app_settings_value = Column("app_settings_value", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 

	
 
    def __init__(self, k, v):
 
        self.app_settings_name = k
 
        self.app_settings_value = v
 

	
 
    def __repr__(self):
 
        return "<RhodeCodeSetting('%s:%s')>" % (self.app_settings_name,
 
                                                self.app_settings_value)
 

	
 
class RhodeCodeUi(Base, BaseModel):
 
    __tablename__ = 'rhodecode_ui'
 
    __table_args__ = {'useexisting':True}
 
    ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    ui_section = Column("ui_section", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_key = Column("ui_key", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_value = Column("ui_value", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
 

	
 

	
 
class User(Base, BaseModel):
 
    __tablename__ = 'users'
 
    __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'useexisting':True})
 
    user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    username = Column("username", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    password = Column("password", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    active = Column("active", Boolean(), nullable=True, unique=None, default=None)
 
    admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
 
    name = Column("name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    lastname = Column("lastname", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    email = Column("email", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
 
    is_ldap = Column("is_ldap", Boolean(), nullable=False, unique=None, default=False)
 

	
 
    user_log = relation('UserLog', cascade='all')
 
    user_perms = relation('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
 

	
 
    repositories = relation('Repository')
 
    user_followers = relation('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
 

	
 
    @property
 
    def full_contact(self):
 
        return '%s %s <%s>' % (self.name, self.lastname, self.email)
 

	
 
    def __repr__(self):
 
        return "<User('id:%s:%s')>" % (self.user_id, self.username)
 

	
 
    def update_lastlogin(self):
 
        """Update user lastlogin"""
 

	
 
        try:
 
            session = Session.object_session(self)
 
            self.last_login = datetime.datetime.now()
 
            session.add(self)
 
            session.commit()
 
            log.debug('updated user %s lastlogin', self.username)
 
        except (DatabaseError,):
 
            session.rollback()
 

	
 

	
 
class UserLog(Base, BaseModel):
 
    __tablename__ = 'user_logs'
 
    __table_args__ = {'useexisting':True}
 
    user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
 
    repository_id = Column("repository_id", Integer(length=None, convert_unicode=False, assert_unicode=None), ForeignKey(u'repositories.repo_id'), nullable=False, unique=None, default=None)
 
    repository_name = Column("repository_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    user_ip = Column("user_ip", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    action = Column("action", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
 

	
 
    user = relation('User')
 
    repository = relation('Repository')
 

	
 
class Repository(Base, BaseModel):
 
    __tablename__ = 'repositories'
 
    __table_args__ = (UniqueConstraint('repo_name'), {'useexisting':True},)
 
    repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repo_name = Column("repo_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    repo_type = Column("repo_type", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
 
    user_id = Column("user_id", Integer(), ForeignKey(u'users.user_id'), nullable=False, unique=False, default=None)
 
    private = Column("private", Boolean(), nullable=True, unique=None, default=None)
 
    enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
 
    description = Column("description", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    fork_id = Column("fork_id", Integer(), ForeignKey(u'repositories.repo_id'), nullable=True, unique=False, default=None)
 

	
 
    user = relation('User')
 
    fork = relation('Repository', remote_side=repo_id)
 
    repo_to_perm = relation('RepoToPerm', cascade='all')
 
    stats = relation('Statistics', cascade='all', uselist=False)
 

	
 
    repo_followers = relation('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
 

	
 

	
 
    def __repr__(self):
 
        return "<Repository('%s:%s')>" % (self.repo_id, self.repo_name)
 

	
 
class Permission(Base, BaseModel):
 
    __tablename__ = 'permissions'
 
    __table_args__ = {'useexisting':True}
 
    permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    permission_name = Column("permission_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    permission_longname = Column("permission_longname", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 

	
 
    def __repr__(self):
 
        return "<Permission('%s:%s')>" % (self.permission_id, self.permission_name)
 

	
 
class RepoToPerm(Base, BaseModel):
 
    __tablename__ = 'repo_to_perm'
 
    __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'useexisting':True})
 
    repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey(u'permissions.permission_id'), nullable=False, unique=None, default=None)
 
    repository_id = Column("repository_id", Integer(), ForeignKey(u'repositories.repo_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relation('User')
 
    permission = relation('Permission')
 
    repository = relation('Repository')
 

	
 
class UserToPerm(Base, BaseModel):
 
    __tablename__ = 'user_to_perm'
 
    __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'useexisting':True})
 
    user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey(u'permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relation('User')
 
    permission = relation('Permission')
 

	
 
class Statistics(Base, BaseModel):
 
    __tablename__ = 'statistics'
 
    __table_args__ = (UniqueConstraint('repository_id'), {'useexisting':True})
 
    stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repository_id = Column("repository_id", Integer(), ForeignKey(u'repositories.repo_id'), nullable=False, unique=True, default=None)
 
    stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
 
    commit_activity = Column("commit_activity", LargeBinary(), nullable=False)#JSON data
 
    commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
 
    languages = Column("languages", LargeBinary(), nullable=False)#JSON data
 

	
 
    repository = relation('Repository', single_parent=True)
 

	
 
class UserFollowing(Base, BaseModel):
 
    __tablename__ = 'user_followings'
 
    __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
 
                      UniqueConstraint('user_id', 'follows_user_id')
 
                      , {'useexisting':True})
 

	
 
    user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
 
    follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey(u'repositories.repo_id'), nullable=True, unique=None, default=None)
 
    follows_user_id = Column("follows_user_id", Integer(), ForeignKey(u'users.user_id'), nullable=True, unique=None, default=None)
 

	
 
    user = relation('User', primaryjoin='User.user_id==UserFollowing.user_id')
 

	
 
    follows_user = relation('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
 
    follows_repository = relation('Repository')
 

	
 

	
 
class CacheInvalidation(Base, BaseModel):
 
    __tablename__ = 'cache_invalidation'
 
    __table_args__ = (UniqueConstraint('cache_key'), {'useexisting':True})
 
    cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    cache_key = Column("cache_key", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    cache_args = Column("cache_args", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
 

	
 

	
 
    def __init__(self, cache_key, cache_args=''):
 
        self.cache_key = cache_key
 
        self.cache_args = cache_args
 
        self.cache_active = False
 

	
 
    def __repr__(self):
 
        return "<CacheInvalidation('%s:%s')>" % (self.cache_id, self.cache_key)
 

	
 

	
 
def upgrade(migrate_engine):
 
    # Upgrade operations go here. Don't create your own engine; bind migrate_engine
 
    # to your metadata
 
    Base.metadata.create_all(bind=migrate_engine, checkfirst=False)
 

	
 
def downgrade(migrate_engine):
 
    # Operations to reverse the above upgrade go here.
 
    Base.metadata.drop_all(bind=migrate_engine, checkfirst=False)
rhodecode/lib/dbmigrate/versions/002_version_1_1_0.py
Show inline comments
 
from sqlalchemy import *
 
from sqlalchemy.orm import relation
 
import logging
 
import datetime
 

	
 
from migrate import *
 
from migrate.changeset import *
 
from rhodecode.model.meta import Base, BaseModel
 
from sqlalchemy import *
 
from sqlalchemy.exc import DatabaseError
 
from sqlalchemy.orm import relation, backref, class_mapper
 
from sqlalchemy.orm.session import Session
 
from rhodecode.model.meta import Base
 
from rhodecode.model.db import BaseModel
 

	
 
from rhodecode.lib.dbmigrate.migrate import *
 

	
 
log = logging.getLogger(__name__)
 

	
 
def upgrade(migrate_engine):
 
    """ Upgrade operations go here. 
 
    Don't create your own engine; bind migrate_engine to your metadata
 
    """
 

	
 
    #==========================================================================
 
    # Upgrade of `users` table
 
    #==========================================================================
 
    tblname = 'users'
 
    tbl = Table(tblname, MetaData(bind=migrate_engine), autoload=True,
 
                    autoload_with=migrate_engine)
 

	
 
    #ADD is_ldap column
 
    is_ldap = Column("is_ldap", Boolean(), nullable=False,
 
    is_ldap = Column("is_ldap", Boolean(), nullable=True,
 
                     unique=None, default=False)
 
    is_ldap.create(tbl)
 

	
 
    is_ldap.create(tbl, populate_default=True)
 
    is_ldap.alter(nullable=False)
 

	
 
    #==========================================================================
 
    # Upgrade of `user_logs` table
 
    #==========================================================================    
 

	
 
    tblname = 'users'
 
    tbl = Table(tblname, MetaData(bind=migrate_engine), autoload=True,
 
                    autoload_with=migrate_engine)
 

	
 
    #ADD revision column
 
    revision = Column('revision', TEXT(length=None, convert_unicode=False,
 
                                       assert_unicode=None),
 
                      nullable=True, unique=None, default=None)
 
    revision.create(tbl)
 

	
 

	
 

	
 
    #==========================================================================
 
    # Upgrade of `repositories` table
 
    #==========================================================================    
 
    tblname = 'users'
 
    tbl = Table(tblname, MetaData(bind=migrate_engine), autoload=True,
 
                    autoload_with=migrate_engine)
 

	
 
    #ADD repo_type column
 
    repo_type = Column("repo_type", String(length=None, convert_unicode=False,
 
                                           assert_unicode=None),
 
                       nullable=False, unique=False, default=None)
 
    repo_type.create(tbl)
 
                       nullable=True, unique=False, default='hg')
 

	
 
    repo_type.create(tbl, populate_default=True)
 
    repo_type.alter(nullable=False)
 

	
 
    #ADD statistics column
 
    enable_statistics = Column("statistics", Boolean(), nullable=True,
 
                               unique=None, default=True)
 
    enable_statistics.create(tbl)
 

	
 

	
 

	
 
    #==========================================================================
 
    # Add table `user_followings`
 
    #==========================================================================
 
    tblname = 'user_followings'
 

	
 
    class UserFollowing(Base, BaseModel):
 
        __tablename__ = 'user_followings'
 
        __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
 
                          UniqueConstraint('user_id', 'follows_user_id')
 
                          , {'useexisting':True})
 

	
 
        user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
        user_id = Column("user_id", Integer(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
 
        follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey(u'repositories.repo_id'), nullable=True, unique=None, default=None)
 
        follows_user_id = Column("follows_user_id", Integer(), ForeignKey(u'users.user_id'), nullable=True, unique=None, default=None)
 

	
 
        user = relation('User', primaryjoin='User.user_id==UserFollowing.user_id')
 

	
 
        follows_user = relation('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
 
        follows_repository = relation('Repository')
 

	
 
    Base.metadata.tables[tblname].create(migrate_engine)
 

	
 
    #==========================================================================
 
    # Add table `cache_invalidation`
 
    #==========================================================================
 
    tblname = 'cache_invalidation'
 

	
 
    class CacheInvalidation(Base, BaseModel):
 
        __tablename__ = 'cache_invalidation'
 
        __table_args__ = (UniqueConstraint('cache_key'), {'useexisting':True})
 
        cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
        cache_key = Column("cache_key", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
        cache_args = Column("cache_args", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
        cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
 

	
 

	
 
        def __init__(self, cache_key, cache_args=''):
 
            self.cache_key = cache_key
 
            self.cache_args = cache_args
 
            self.cache_active = False
 

	
 
        def __repr__(self):
 
            return "<CacheInvalidation('%s:%s')>" % (self.cache_id, self.cache_key)
 

	
 
    Base.metadata.tables[tblname].create(migrate_engine)
 

	
 
    return
 

	
 

	
 

	
 

	
 

	
 

	
 
def downgrade(migrate_engine):
 
    meta = MetaData()
 
    meta.bind = migrate_engine
 

	
 

	
rhodecode/model/db.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.model.db
 
    ~~~~~~~~~~~~~~~~~~
 
    
 
    Database Models for RhodeCode
 
    
 
    :created_on: Apr 08, 2010
 
    :author: marcink
 
    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
 
    :license: GPLv3, see COPYING for more details.
 
"""
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
import logging
 
import datetime
 

	
 
from sqlalchemy import *
 
from sqlalchemy.exc import DatabaseError
 
from sqlalchemy.orm import relation, backref, class_mapper
 
from sqlalchemy.orm.session import Session
 

	
 
from rhodecode.model.meta import Base
 

	
 
log = logging.getLogger(__name__)
 

	
 
class BaseModel(object):
 

	
 
    @classmethod
 
    def _get_keys(cls):
 
        """return column names for this model """
 
        return class_mapper(cls).c.keys()
 

	
 
    def get_dict(self):
 
        """return dict with keys and values corresponding 
 
        to this model data """
 

	
 
        d = {}
 
        for k in self._get_keys():
 
            d[k] = getattr(self, k)
 
        return d
 

	
 
    def get_appstruct(self):
 
        """return list with keys and values tupples corresponding 
 
        to this model data """
 

	
 
        l = []
 
        for k in self._get_keys():
 
            l.append((k, getattr(self, k),))
 
        return l
 

	
 
    def populate_obj(self, populate_dict):
 
        """populate model with data from given populate_dict"""
 

	
 
        for k in self._get_keys():
 
            if k in populate_dict:
 
                setattr(self, k, populate_dict[k])
 

	
 
class RhodeCodeSettings(Base, BaseModel):
 
    __tablename__ = 'rhodecode_settings'
 
    __table_args__ = (UniqueConstraint('app_settings_name'), {'useexisting':True})
 
    app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    app_settings_name = Column("app_settings_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    app_settings_value = Column("app_settings_value", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 

	
 
    def __init__(self, k, v):
 
        self.app_settings_name = k
 
        self.app_settings_value = v
 

	
 
    def __repr__(self):
 
        return "<RhodeCodeSetting('%s:%s')>" % (self.app_settings_name,
 
                                                self.app_settings_value)
 

	
 
class RhodeCodeUi(Base, BaseModel):
 
    __tablename__ = 'rhodecode_ui'
 
    __table_args__ = {'useexisting':True}
 
    ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    ui_section = Column("ui_section", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_key = Column("ui_key", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_value = Column("ui_value", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
 

	
 

	
 
class User(Base, BaseModel):
 
    __tablename__ = 'users'
 
    __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'useexisting':True})
 
    user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    username = Column("username", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    password = Column("password", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    active = Column("active", Boolean(), nullable=True, unique=None, default=None)
 
    admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
 
    name = Column("name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    lastname = Column("lastname", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    email = Column("email", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
 
    is_ldap = Column("is_ldap", Boolean(), nullable=False, unique=None, default=False)
 

	
 
    user_log = relation('UserLog', cascade='all')
 
    user_perms = relation('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
 

	
 
    repositories = relation('Repository')
 
    user_followers = relation('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
 

	
 
    @property
 
    def full_contact(self):
 
        return '%s %s <%s>' % (self.name, self.lastname, self.email)
 

	
 
    def __repr__(self):
 
        return "<User('id:%s:%s')>" % (self.user_id, self.username)
 

	
 
    def update_lastlogin(self):
 
        """Update user lastlogin"""
 

	
 
        try:
 
            session = Session.object_session(self)
 
            self.last_login = datetime.datetime.now()
 
            session.add(self)
 
            session.commit()
 
            log.debug('updated user %s lastlogin', self.username)
 
        except (DatabaseError,):
 
            session.rollback()
 

	
 

	
 
class UserLog(Base, BaseModel):
 
    __tablename__ = 'user_logs'
 
    __table_args__ = {'useexisting':True}
 
    user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
 
    repository_id = Column("repository_id", Integer(length=None, convert_unicode=False, assert_unicode=None), ForeignKey(u'repositories.repo_id'), nullable=False, unique=None, default=None)
 
    repository_name = Column("repository_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    user_ip = Column("user_ip", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    action = Column("action", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
 

	
 
    user = relation('User')
 
    repository = relation('Repository')
 

	
 
class Repository(Base, BaseModel):
 
    __tablename__ = 'repositories'
 
    __table_args__ = (UniqueConstraint('repo_name'), {'useexisting':True},)
 
    repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repo_name = Column("repo_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    repo_type = Column("repo_type", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
 
    repo_type = Column("repo_type", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default='hg')
 
    user_id = Column("user_id", Integer(), ForeignKey(u'users.user_id'), nullable=False, unique=False, default=None)
 
    private = Column("private", Boolean(), nullable=True, unique=None, default=None)
 
    enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
 
    description = Column("description", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    fork_id = Column("fork_id", Integer(), ForeignKey(u'repositories.repo_id'), nullable=True, unique=False, default=None)
 

	
 
    user = relation('User')
 
    fork = relation('Repository', remote_side=repo_id)
 
    repo_to_perm = relation('RepoToPerm', cascade='all')
 
    stats = relation('Statistics', cascade='all', uselist=False)
 

	
 
    repo_followers = relation('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
 

	
 

	
 
    def __repr__(self):
 
        return "<Repository('%s:%s')>" % (self.repo_id, self.repo_name)
 

	
 
class Permission(Base, BaseModel):
 
    __tablename__ = 'permissions'
 
    __table_args__ = {'useexisting':True}
 
    permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    permission_name = Column("permission_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    permission_longname = Column("permission_longname", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 

	
 
    def __repr__(self):
 
        return "<Permission('%s:%s')>" % (self.permission_id, self.permission_name)
 

	
 
class RepoToPerm(Base, BaseModel):
 
    __tablename__ = 'repo_to_perm'
 
    __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'useexisting':True})
 
    repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey(u'permissions.permission_id'), nullable=False, unique=None, default=None)
 
    repository_id = Column("repository_id", Integer(), ForeignKey(u'repositories.repo_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relation('User')
 
    permission = relation('Permission')
 
    repository = relation('Repository')
 

	
 
class UserToPerm(Base, BaseModel):
 
    __tablename__ = 'user_to_perm'
 
    __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'useexisting':True})
 
    user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey(u'permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relation('User')
 
    permission = relation('Permission')
 

	
 
class Statistics(Base, BaseModel):
 
    __tablename__ = 'statistics'
 
    __table_args__ = (UniqueConstraint('repository_id'), {'useexisting':True})
 
    stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repository_id = Column("repository_id", Integer(), ForeignKey(u'repositories.repo_id'), nullable=False, unique=True, default=None)
 
    stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
 
    commit_activity = Column("commit_activity", LargeBinary(), nullable=False)#JSON data
 
    commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
 
    languages = Column("languages", LargeBinary(), nullable=False)#JSON data
 

	
 
    repository = relation('Repository', single_parent=True)
 

	
 
class UserFollowing(Base, BaseModel):
 
    __tablename__ = 'user_followings'
 
    __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
 
                      UniqueConstraint('user_id', 'follows_user_id')
 
                      , {'useexisting':True})
 

	
 
    user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
 
    follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey(u'repositories.repo_id'), nullable=True, unique=None, default=None)
 
    follows_user_id = Column("follows_user_id", Integer(), ForeignKey(u'users.user_id'), nullable=True, unique=None, default=None)
 

	
 
    user = relation('User', primaryjoin='User.user_id==UserFollowing.user_id')
 

	
 
    follows_user = relation('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
 
    follows_repository = relation('Repository')
 

	
 

	
 
class CacheInvalidation(Base, BaseModel):
 
    __tablename__ = 'cache_invalidation'
 
    __table_args__ = (UniqueConstraint('cache_key'), {'useexisting':True})
 
    cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    cache_key = Column("cache_key", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    cache_args = Column("cache_args", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
 

	
 

	
 
    def __init__(self, cache_key, cache_args=''):
 
        self.cache_key = cache_key
 
        self.cache_args = cache_args
 
        self.cache_active = False
 

	
 
    def __repr__(self):
 
        return "<CacheInvalidation('%s:%s')>" % (self.cache_id, self.cache_key)
 

	
 
class DbMigrateVersion(Base, BaseModel):
 
    __tablename__ = 'db_migrate_version'
 
    __table_args__ = {'useexisting':True}
 
    repository_id = Column('repository_id', String(250), primary_key=True)
 
    repository_path = Column('repository_path', Text)
 
    version = Column('version', Integer)
 

	
0 comments (0 inline, 0 general)