diff options
Diffstat (limited to 'mediagoblin/db')
-rw-r--r-- | mediagoblin/db/migration_tools.py | 5 | ||||
-rw-r--r-- | mediagoblin/db/migrations/alembic.ini | 56 | ||||
-rw-r--r-- | mediagoblin/db/migrations/versions/afd3d1da5e29_subtitle_plugin_initial_migration.py | 36 | ||||
-rw-r--r-- | mediagoblin/db/models.py | 38 |
4 files changed, 130 insertions, 5 deletions
diff --git a/mediagoblin/db/migration_tools.py b/mediagoblin/db/migration_tools.py index f4273fa0..852f35ee 100644 --- a/mediagoblin/db/migration_tools.py +++ b/mediagoblin/db/migration_tools.py @@ -365,9 +365,8 @@ def build_alembic_config(global_config, cmd_options, session): configuration. Initialize the database session appropriately as well. """ - root_dir = os.path.abspath(os.path.dirname(os.path.dirname( - os.path.dirname(__file__)))) - alembic_cfg_path = os.path.join(root_dir, 'alembic.ini') + alembic_dir = os.path.join(os.path.dirname(__file__), 'migrations') + alembic_cfg_path = os.path.join(alembic_dir, 'alembic.ini') cfg = Config(alembic_cfg_path, cmd_opts=cmd_options) cfg.attributes["session"] = session diff --git a/mediagoblin/db/migrations/alembic.ini b/mediagoblin/db/migrations/alembic.ini new file mode 100644 index 00000000..4f7fc115 --- /dev/null +++ b/mediagoblin/db/migrations/alembic.ini @@ -0,0 +1,56 @@ +# A generic, single database configuration. + +[alembic] +# path to migration scripts +script_location = %(here)s + +# template used to generate migration files +# file_template = %%(rev)s_%%(slug)s + +# max length of characters to apply to the +# "slug" field +#truncate_slug_length = 40 + +# set to 'true' to run the environment during +# the 'revision' command, regardless of autogenerate +# revision_environment = false + +# set to 'true' to allow .pyc and .pyo files without +# a source .py file to be detected as revisions in the +# versions/ directory +# sourceless = false + +# Logging configuration +[loggers] +keys = root,sqlalchemy,alembic + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = WARN +handlers = console +qualname = + +[logger_sqlalchemy] +level = WARN +handlers = +qualname = sqlalchemy.engine + +[logger_alembic] +level = INFO +handlers = +qualname = alembic + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(levelname)-5.5s [%(name)s] %(message)s +datefmt = %H:%M:%S diff --git a/mediagoblin/db/migrations/versions/afd3d1da5e29_subtitle_plugin_initial_migration.py b/mediagoblin/db/migrations/versions/afd3d1da5e29_subtitle_plugin_initial_migration.py new file mode 100644 index 00000000..565d4864 --- /dev/null +++ b/mediagoblin/db/migrations/versions/afd3d1da5e29_subtitle_plugin_initial_migration.py @@ -0,0 +1,36 @@ +"""Subtitle plugin initial migration + +Revision ID: afd3d1da5e29 +Revises: 228916769bd2 +Create Date: 2016-06-03 11:48:03.369079 + +""" + +# revision identifiers, used by Alembic. +revision = 'afd3d1da5e29' +down_revision = '228916769bd2' +branch_labels = ('subtitles_plugin',) +depends_on = None + +from alembic import op +import sqlalchemy as sa +from mediagoblin.db.extratypes import PathTupleWithSlashes + +def upgrade(): + ### commands auto generated by Alembic - please adjust! ### + op.create_table('core__subtitle_files', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('media_entry', sa.Integer(), nullable=False), + sa.Column('name', sa.Unicode(), nullable=False), + sa.Column('filepath', PathTupleWithSlashes(), nullable=True), + sa.Column('created', sa.DateTime(), nullable=False), + sa.ForeignKeyConstraint(['media_entry'], [u'core__media_entries.id'], ), + sa.PrimaryKeyConstraint('id') + ) + ### end Alembic commands ### + + +def downgrade(): + ### commands auto generated by Alembic - please adjust! ### + op.drop_table('core__subtitle_files') + ### end Alembic commands ### diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py index b2dcb6ad..0974676a 100644 --- a/mediagoblin/db/models.py +++ b/mediagoblin/db/models.py @@ -43,6 +43,7 @@ from mediagoblin.db.mixin import UserMixin, MediaEntryMixin, \ from mediagoblin.tools.files import delete_media_files from mediagoblin.tools.common import import_component from mediagoblin.tools.routing import extract_url_arguments +from mediagoblin.tools.text import convert_to_tag_list_of_dicts import six from six.moves.urllib.parse import urljoin @@ -574,6 +575,15 @@ class MediaEntry(Base, MediaEntryMixin, CommentingMixin): name=v["name"], filepath=v["filepath"]) ) + subtitle_files_helper = relationship("MediaSubtitleFile", + cascade="all, delete-orphan", + order_by="MediaSubtitleFile.created" + ) + subtitle_files = association_proxy("subtitle_files_helper", "dict_view", + creator=lambda v: MediaSubtitleFile( + name=v["name"], filepath=v["filepath"]) + ) + tags_helper = relationship("MediaTag", cascade="all, delete-orphan" # should be automatically deleted ) @@ -771,7 +781,6 @@ class MediaEntry(Base, MediaEntryMixin, CommentingMixin): "self": { "href": public_id, }, - } } @@ -787,6 +796,12 @@ class MediaEntry(Base, MediaEntryMixin, CommentingMixin): if self.location: context["location"] = self.get_location.serialize(request) + # Always show tags, even if empty list + if self.tags: + context["tags"] = [tag['name'] for tag in self.tags] + else: + context["tags"] = [] + if show_comments: comments = [ l.comment().serialize(request) for l in self.get_comments()] @@ -834,6 +849,9 @@ class MediaEntry(Base, MediaEntryMixin, CommentingMixin): if "location" in data: License.create(data["location"], self) + if "tags" in data: + self.tags = convert_to_tag_list_of_dicts(', '.join(data["tags"])) + return True class FileKeynames(Base): @@ -899,6 +917,22 @@ class MediaAttachmentFile(Base): """A dict like view on this object""" return DictReadAttrProxy(self) +class MediaSubtitleFile(Base): + __tablename__ = "core__subtitle_files" + + id = Column(Integer, primary_key=True) + media_entry = Column( + Integer, ForeignKey(MediaEntry.id), + nullable=False) + name = Column(Unicode, nullable=False) + filepath = Column(PathTupleWithSlashes) + created = Column(DateTime, nullable=False, default=datetime.datetime.utcnow) + + @property + def dict_view(self): + """A dict like view on this object""" + return DictReadAttrProxy(self) + class Tag(Base): __tablename__ = "core__tags" @@ -1610,7 +1644,7 @@ class Graveyard(Base): return context MODELS = [ LocalUser, RemoteUser, User, MediaEntry, Tag, MediaTag, Comment, TextComment, - Collection, CollectionItem, MediaFile, FileKeynames, MediaAttachmentFile, + Collection, CollectionItem, MediaFile, FileKeynames, MediaAttachmentFile, MediaSubtitleFile, ProcessingMetaData, Notification, Client, CommentSubscription, Report, UserBan, Privilege, PrivilegeUserAssociation, RequestToken, AccessToken, NonceTimestamp, Activity, Generator, Location, GenericModelReference, Graveyard] |