diff --git a/.gitignore b/.gitignore index c19d45e..bcddaa5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.pyc *.db phyloplumber.egg-info + diff --git a/development.ini b/development.ini index bbe07c7..da320d3 100644 --- a/development.ini +++ b/development.ini @@ -10,6 +10,10 @@ debug = true smtp_server = localhost error_email_from = paste@localhost +top_internal_dir = /Users/mholder/Library/Application Support/phyloplumber +top_external_dir = /Users/mholder/Documents/phyloplumberExternal + + [server:main] use = egg:Paste#http host = 127.0.0.1 diff --git a/phyloplumber/lib/__init__.py b/phyloplumber/lib/__init__.py index e69de29..ca0008a 100644 --- a/phyloplumber/lib/__init__.py +++ b/phyloplumber/lib/__init__.py @@ -0,0 +1,36 @@ +import os +from pylons import config + +_INTERNAL_DIR = os.path.abspath(os.path.expandvars(os.path.expanduser(config.get('top_internal_dir', '~/internals_phyloplumber')))) +_EXTERNAL_DIR = os.path.abspath(os.path.expandvars(os.path.expanduser(config.get('top_external_dir', '~/phyloplumber')))) + + +_MISSING_SETTING_MSG = 'A %(setting)s setting is required in the initialization file used to start the server' + +def verify_dir(dir): + if os.path.exists(dir): + if os.path.isdir(dir): + return True + raise OSError("File %(f)s exists, so a directory cannot be created at that location" % {f : dir}) + os.makedirs(dir) + +def get_top_internal_dir(): + '''Returns the absolute path to the top directory for "internal" storage. + + Raises OSError if the directory does not exist and cannot be created. + ''' + if not _INTERNAL_DIR: + raise OSError(_MISSING_SETTING_MSG % {'setting' : 'top_internal_dir'}) + verify_dir(_INTERNAL_DIR) + return _INTERNAL_DIR + +def get_top_external_dir(): + '''Returns the absolute path to the top directory for "external" storage. + + Raises OSError if the directory does not exist and cannot be created. + ''' + if not _EXTERNAL_DIR: + raise OSError(_MISSING_SETTING_MSG % {'setting' : 'top_external_dir'}) + verify_dir(_EXTERNAL_DIR) + return _EXTERNAL_DIR + diff --git a/phyloplumber/model/__init__.py b/phyloplumber/model/__init__.py index 1c0a728..507996e 100644 --- a/phyloplumber/model/__init__.py +++ b/phyloplumber/model/__init__.py @@ -1,7 +1,69 @@ """The application's model objects""" -from phyloplumber.model.meta import Session, Base +import sqlalchemy as sa +from sqlalchemy import orm, schema +from sqlalchemy.ext.declarative import declarative_base +from phyloplumber.model import meta +def now(): + return datetime.datetime.now() def init_model(engine): """Call me before using any of the tables or classes in the model""" - Session.configure(bind=engine) + #meta.Session.configure(bind=engine) + sm = orm.sessionmaker(autoflush=True, autocommit=False, bind=engine) + meta.engine = engine + meta.Session = orm.scoped_session(sm) + meta.set_metadata(schema.MetaData(bind=engine)) + + + t_group = schema.Table("PhyloplumberGroup", meta.get_metadata(), + schema.Column('id', sa.types.Integer, + schema.Sequence('groupuser_seq_id', optional=True), primary_key=True), + sa.Column("name", sa.types.String, nullable=False), + ) + + t_user = schema.Table("PhyloplumberUser", meta.metadata, + schema.Column('id', sa.types.Integer, + schema.Sequence('groupuser_seq_id', optional=True), primary_key=True), + sa.Column("username", sa.types.String, nullable=False), + sa.Column("fullname", sa.types.String, nullable=False), + sa.Column("date_created", sa.types.DateTime, nullable=False), + sa.Column("email", sa.types.DateTime, nullable=False), + ) + + t_process = schema.Table("ExternalProcess", meta.metadata, + sa.Column("id", sa.types.String, nullable=False, primary_key=True), + sa.Column("parent_dirname", sa.types.String, nullable=False), + sa.Column("launch_timestamp", sa.types.DateTime, nullable=False), + sa.Column("invocation", sa.types.String, nullable=False), + sa.Column("label", sa.types.String, nullable=False), + sa.Column("status", sa.types.Integer, nullable=False), + sa.Column("service_name", sa.types.String, nullable=False), # this is the controller that launched the job + sa.Column("read_group", sa.types.Integer, schema.ForeignKey('PhyloplumberGroup.id')), + sa.Column("write_group", sa.types.Integer, schema.ForeignKey('PhyloplumberGroup.id')), + ) + + + + t_group_user = schema.Table('PhyloplumberGroupUser', meta.metadata, + schema.Column('id', sa.types.Integer, + schema.Sequence('groupuser_seq_id', optional=True), primary_key=True), + schema.Column('groupid', sa.types.Integer, schema.ForeignKey('PhyloplumberGroup.id')), + schema.Column('userid', sa.types.Integer, schema.ForeignKey('PhyloplumberUser.id')), + ) + + + class PhyloplumberGroup(object): + pass + class PhyloplumberUser(object): + pass + class PhyloplumberGroupUser(object): + pass + class ExternalProcess(object): + pass + + orm.mapper(PhyloplumberGroup, t_group) + orm.mapper(PhyloplumberUser, t_user) + orm.mapper(ExternalProcess, t_process) + orm.mapper(PhyloplumberGroupUser, t_group_user) + diff --git a/phyloplumber/model/meta.py b/phyloplumber/model/meta.py index 66e7e0d..4185d39 100644 --- a/phyloplumber/model/meta.py +++ b/phyloplumber/model/meta.py @@ -1,11 +1,24 @@ """SQLAlchemy Metadata and Session object""" from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import scoped_session, sessionmaker +from sqlalchemy import schema + __all__ = ['Base', 'Session'] # SQLAlchemy session manager. Updated by model.init_model() Session = scoped_session(sessionmaker()) -# The declarative Base -Base = declarative_base() +metadata = None +def get_metadata(): + global metadata + return metadata +def set_metadata(n): + global metadata + metadata = n + +# Assign the same metadata object we created earlier. +#Base = declarative_base(metadata=metadata) + + + diff --git a/phyloplumber/websetup.py b/phyloplumber/websetup.py index 8e37a74..ed47136 100644 --- a/phyloplumber/websetup.py +++ b/phyloplumber/websetup.py @@ -4,7 +4,7 @@ import pylons.test from phyloplumber.config.environment import load_environment -from phyloplumber.model.meta import Session, Base +from phyloplumber.model.meta import Session, get_metadata log = logging.getLogger(__name__) @@ -13,6 +13,6 @@ def setup_app(command, conf, vars): # Don't reload the app if it was loaded under the testing environment if not pylons.test.pylonsapp: load_environment(conf.global_conf, conf.local_conf) - + # Create the tables if they don't already exist - Base.metadata.create_all(bind=Session.bind) + get_metadata().create_all(bind=Session.bind) diff --git a/setup.cfg b/setup.cfg index a0e61b6..7469899 100644 --- a/setup.cfg +++ b/setup.cfg @@ -10,7 +10,6 @@ verbose = True verbosity = 2 with-pylons = test.ini detailed-errors = 1 -with-doctest = True # Babel configuration [compile_catalog]