diff options
38 files changed, 317 insertions, 344 deletions
@@ -16,6 +16,8 @@ /paste_local.ini /mediagoblin_local.ini /mediagoblin.db +/celery.db +/kombu.db /server-log.txt # Tests diff --git a/mediagoblin/app.py b/mediagoblin/app.py index 06627675..0a57c091 100644 --- a/mediagoblin/app.py +++ b/mediagoblin/app.py @@ -16,11 +16,12 @@ import os import urllib +import logging import routes from webob import Request, exc -from mediagoblin import routing, meddleware +from mediagoblin import routing, meddleware, __version__ from mediagoblin.tools import common, translate, template from mediagoblin.tools.response import render_404 from mediagoblin.tools import request as mg_request @@ -31,6 +32,9 @@ from mediagoblin.init import (get_jinja_loader, get_staticdirector, setup_storage, setup_beaker_cache) +_log = logging.getLogger(__name__) + + class MediaGoblinApp(object): """ WSGI application of MediaGoblin @@ -47,6 +51,7 @@ class MediaGoblinApp(object): (Note: setting 'celery_setup_elsewhere' also disables setting up celery.) """ + _log.info("GNU MediaGoblin %s main server starting", __version__) ############## # Setup config ############## @@ -179,6 +184,14 @@ class MediaGoblinApp(object): for m in self.meddleware[::-1]: m.process_response(request, response) + # Reset the sql session, so that the next request + # gets a fresh session + try: + self.db.reset_after_request() + except TypeError: + # We're still on mongo + pass + return response(environ, start_response) diff --git a/mediagoblin/config_spec.ini b/mediagoblin/config_spec.ini index 2b4ba2f9..10828536 100644 --- a/mediagoblin/config_spec.ini +++ b/mediagoblin/config_spec.ini @@ -79,46 +79,54 @@ lock_dir = string(default="%(here)s/user_dev/beaker/cache/lock") [celery] +# default result stuff +CELERY_RESULT_BACKEND = string(default="database") +CELERY_RESULT_DBURI = string(default="sqlite:///%(here)s/celery.db") + +# default kombu stuff +BROKER_TRANSPORT = string(default="sqlalchemy") +BROKER_HOST = string(default="sqlite:///%(here)s/kombu.db") + # known booleans -celery_result_persistent = boolean() -celery_create_missing_queues = boolean() -broker_use_ssl = boolean() -broker_connection_retry = boolean() -celery_always_eager = boolean() -celery_eager_propagates_exceptions = boolean() -celery_ignore_result = boolean() -celery_track_started = boolean() -celery_disable_rate_limits = boolean() -celery_acks_late = boolean() -celery_store_errors_even_if_ignored = boolean() -celery_send_task_error_emails = boolean() -celery_send_events = boolean() -celery_send_task_sent_event = boolean() -celeryd_log_color = boolean() -celery_redirect_stdouts = boolean() +CELERY_RESULT_PERSISTENT = boolean() +CELERY_CREATE_MISSING_QUEUES = boolean() +BROKER_USE_SSL = boolean() +BROKER_CONNECTION_RETRY = boolean() +CELERY_ALWAYS_EAGER = boolean() +CELERY_EAGER_PROPAGATES_EXCEPTIONS = boolean() +CELERY_IGNORE_RESULT = boolean() +CELERY_TRACK_STARTED = boolean() +CELERY_DISABLE_RATE_LIMITS = boolean() +CELERY_ACKS_LATE = boolean() +CELERY_STORE_ERRORS_EVEN_IF_IGNORED = boolean() +CELERY_SEND_TASK_ERROR_EMAILS = boolean() +CELERY_SEND_EVENTS = boolean() +CELERY_SEND_TASK_SENT_EVENT = boolean() +CELERYD_LOG_COLOR = boolean() +CELERY_REDIRECT_STDOUTS = boolean() # known ints -celeryd_concurrency = integer() -celeryd_prefetch_multiplier = integer() -celery_amqp_task_result_expires = integer() -celery_amqp_task_result_connection_max = integer() -redis_port = integer() -redis_db = integer() -broker_port = integer() -broker_connection_timeout = integer() -celery_broker_connection_max_retries = integer() -celery_task_result_expires = integer() -celery_max_cached_results = integer() -celery_default_rate_limit = integer() -celeryd_max_tasks_per_child = integer() -celeryd_task_time_limit = integer() -celeryd_task_soft_time_limit = integer() -mail_port = integer() -celerybeat_max_loop_interval = integer() +CELERYD_CONCURRENCY = integer() +CELERYD_PREFETCH_MULTIPLIER = integer() +CELERY_AMQP_TASK_RESULT_EXPIRES = integer() +CELERY_AMQP_TASK_RESULT_CONNECTION_MAX = integer() +REDIS_PORT = integer() +REDIS_DB = integer() +BROKER_PORT = integer() +BROKER_CONNECTION_TIMEOUT = integer() +CELERY_BROKER_CONNECTION_MAX_RETRIES = integer() +CELERY_TASK_RESULT_EXPIRES = integer() +CELERY_MAX_CACHED_RESULTS = integer() +CELERY_DEFAULT_RATE_LIMIT = integer() +CELERYD_MAX_TASKS_PER_CHILD = integer() +CELERYD_TASK_TIME_LIMIT = integer() +CELERYD_TASK_SOFT_TIME_LIMIT = integer() +MAIL_PORT = integer() +CELERYBEAT_MAX_LOOP_INTERVAL = integer() # known floats -celeryd_eta_scheduler_precision = float() +CELERYD_ETA_SCHEDULER_PRECISION = float() # known lists -celery_routes = string_list() -celery_imports = string_list() +CELERY_ROUTES = string_list() +CELERY_IMPORTS = string_list() diff --git a/mediagoblin/db/mongo/migrations.py b/mediagoblin/db/mongo/migrations.py index 59035f3b..c5766b0d 100644 --- a/mediagoblin/db/mongo/migrations.py +++ b/mediagoblin/db/mongo/migrations.py @@ -139,3 +139,17 @@ def remove_calculated_html(database): drop_table_field(database, 'users', 'bio_html') drop_table_field(database, 'media_entries', 'description_html') drop_table_field(database, 'media_comments', 'content_html') + +@RegisterMigration(10) +def convert_video_media_data(database): + """ + Move media_data["video"] directly into media_data + """ + collection = database['media_entries'] + target = collection.find( + {'media_data.video': {'$exists': True}}) + + for document in target: + assert len(document['media_data']) == 1 + document['media_data'] = document['media_data']['video'] + collection.save(document) diff --git a/mediagoblin/db/mongo/models.py b/mediagoblin/db/mongo/models.py index 57af137d..c86adbb6 100644 --- a/mediagoblin/db/mongo/models.py +++ b/mediagoblin/db/mongo/models.py @@ -25,6 +25,17 @@ from mediagoblin.tools.pagination import Pagination from mediagoblin.tools import url from mediagoblin.db.mixin import UserMixin, MediaEntryMixin, MediaCommentMixin + +class MongoPK(object): + """An alias for the _id primary key""" + def __get__(self, instance, cls): + return instance['_id'] + def __set__(self, instance, val): + instance['_id'] = val + def __delete__(self, instance): + del instance['_id'] + + ################### # Custom validators ################### @@ -87,6 +98,8 @@ class User(Document, UserMixin): 'status': u'needs_email_verification', 'is_admin': False} + id = MongoPK() + class MediaEntry(Document, MediaEntryMixin): """ @@ -205,6 +218,11 @@ class MediaEntry(Document, MediaEntryMixin): 'created': datetime.datetime.utcnow, 'state': u'unprocessed'} + id = MongoPK() + + def media_data_init(self, **kwargs): + self.media_data.update(kwargs) + def get_comments(self, ascending=False): if ascending: order = ASCENDING diff --git a/mediagoblin/db/sql/base.py b/mediagoblin/db/sql/base.py index 6ed24a03..838080b0 100644 --- a/mediagoblin/db/sql/base.py +++ b/mediagoblin/db/sql/base.py @@ -67,6 +67,10 @@ class GMGTableBase(object): def get(self, key): return getattr(self, key) + def setdefault(self, key, defaultvalue): + # The key *has* to exist on sql. + return getattr(self, key) + def save(self, validate=True): assert validate sess = object_session(self) @@ -75,6 +79,12 @@ class GMGTableBase(object): sess.add(self) sess.commit() + def delete(self): + sess = object_session(self) + assert sess is not None, "Not going to delete detached %r" % self + sess.delete(self) + sess.commit() + Base = declarative_base(cls=GMGTableBase) diff --git a/mediagoblin/db/sql/convert.py b/mediagoblin/db/sql/convert.py index 36d6fc7f..250c559b 100644 --- a/mediagoblin/db/sql/convert.py +++ b/mediagoblin/db/sql/convert.py @@ -19,7 +19,8 @@ from mediagoblin.init import setup_global_and_app_config, setup_database from mediagoblin.db.mongo.util import ObjectId from mediagoblin.db.sql.models import (Base, User, MediaEntry, MediaComment, - Tag, MediaTag, MediaFile) + Tag, MediaTag, MediaFile, MediaAttachmentFile) +from mediagoblin.media_types.video.models import VideoData from mediagoblin.db.sql.open import setup_connection_and_db_from_config as \ sql_connect from mediagoblin.db.mongo.open import setup_connection_and_db_from_config as \ @@ -49,7 +50,7 @@ def copy_reference_attr(entry, new_entry, ref_attr): def convert_users(mk_db): session = Session() - for entry in mk_db.User.find(): + for entry in mk_db.User.find().sort('created'): print entry.username new_entry = User() @@ -71,7 +72,7 @@ def convert_users(mk_db): def convert_media_entries(mk_db): session = Session() - for entry in mk_db.MediaEntry.find(): + for entry in mk_db.MediaEntry.find().sort('created'): print repr(entry.title) new_entry = MediaEntry() @@ -92,6 +93,15 @@ def convert_media_entries(mk_db): new_file.media_entry = new_entry.id Session.add(new_file) + for attachment in entry.attachment_files: + new_attach = MediaAttachmentFile( + name=attachment["name"], + filepath=attachment["filepath"], + created=attachment["created"] + ) + new_attach.media_entry = new_entry.id + Session.add(new_attach) + session.commit() session.close() @@ -100,7 +110,7 @@ def convert_media_tags(mk_db): session = Session() session.autoflush = False - for media in mk_db.MediaEntry.find(): + for media in mk_db.MediaEntry.find().sort('created'): print repr(media.title) for otag in media.tags: @@ -127,7 +137,7 @@ def convert_media_tags(mk_db): def convert_media_comments(mk_db): session = Session() - for entry in mk_db.MediaComment.find(): + for entry in mk_db.MediaComment.find().sort('created'): print repr(entry.content) new_entry = MediaComment() @@ -145,8 +155,8 @@ def convert_media_comments(mk_db): session.close() -def main(): - global_config, app_config = setup_global_and_app_config("mediagoblin.ini") +def run_conversion(config_name): + global_config, app_config = setup_global_and_app_config(config_name) sql_conn, sql_db = sql_connect(app_config) mk_conn, mk_db = mongo_connect(app_config) @@ -164,4 +174,4 @@ def main(): if __name__ == '__main__': - main() + run_conversion("mediagoblin.ini") diff --git a/mediagoblin/db/sql/models.py b/mediagoblin/db/sql/models.py index 699dbf33..dbc9ca05 100644 --- a/mediagoblin/db/sql/models.py +++ b/mediagoblin/db/sql/models.py @@ -118,6 +118,15 @@ class MediaEntry(Base, MediaEntryMixin): creator=lambda k, v: MediaFile(name=k, file_path=v) ) + attachment_files_helper = relationship("MediaAttachmentFile", + cascade="all, delete-orphan", + order_by="MediaAttachmentFile.created" + ) + attachment_files = association_proxy("attachment_files_helper", "dict_view", + creator=lambda v: MediaAttachmentFile( + name=v["name"], filepath=v["filepath"]) + ) + tags_helper = relationship("MediaTag", cascade="all, delete-orphan" ) @@ -127,7 +136,6 @@ class MediaEntry(Base, MediaEntryMixin): ## TODO # media_data - # attachment_files # fail_error _id = SimpleFieldAlias("id") @@ -159,6 +167,15 @@ class MediaEntry(Base, MediaEntryMixin): if media is not None: return media.url_for_self(urlgen) + @property + def media_data(self): + # TODO: Replace with proper code to read the correct table + return {} + + def media_data_init(self, **kwargs): + # TODO: Implement this + pass + class MediaFile(Base): """ @@ -177,6 +194,23 @@ class MediaFile(Base): return "<MediaFile %s: %r>" % (self.name, self.file_path) +class MediaAttachmentFile(Base): + __tablename__ = "core__attachment_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.now) + + @property + def dict_view(self): + """A dict like view on this object""" + return DictReadAttrProxy(self) + + class Tag(Base): __tablename__ = "tags" diff --git a/mediagoblin/db/sql/open.py b/mediagoblin/db/sql/open.py index 1bfc5538..a8677bcb 100644 --- a/mediagoblin/db/sql/open.py +++ b/mediagoblin/db/sql/open.py @@ -36,6 +36,7 @@ class DatabaseMaster(object): Session.flush() def reset_after_request(self): + Session.rollback() Session.remove() diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py index 3df36e8e..d21ef03a 100644 --- a/mediagoblin/edit/views.py +++ b/mediagoblin/edit/views.py @@ -120,7 +120,7 @@ def edit_attachments(request, media): finally: request.POST['attachment_file'].file.close() - media['attachment_files'].append(dict( + media.attachment_files.append(dict( name=request.POST['attachment_name'] \ or request.POST['attachment_file'].filename, filepath=attachment_public_filepath, diff --git a/mediagoblin/gmg_commands/__init__.py b/mediagoblin/gmg_commands/__init__.py index d804376b..054e2616 100644 --- a/mediagoblin/gmg_commands/__init__.py +++ b/mediagoblin/gmg_commands/__init__.py @@ -57,6 +57,10 @@ SUBCOMMAND_MAP = { 'setup': 'mediagoblin.gmg_commands.dbupdate:dbupdate_parse_setup', 'func': 'mediagoblin.gmg_commands.dbupdate:dbupdate', 'help': 'Set up or update the SQL database'}, + 'convert_mongo_to_sql': { + 'setup': 'mediagoblin.gmg_commands.mongosql:mongosql_parser_setup', + 'func': 'mediagoblin.gmg_commands.mongosql:mongosql', + 'help': 'Convert Mongo DB data to SQL DB data'}, } diff --git a/mediagoblin/gmg_commands/mongosql.py b/mediagoblin/gmg_commands/mongosql.py new file mode 100644 index 00000000..a25263e2 --- /dev/null +++ b/mediagoblin/gmg_commands/mongosql.py @@ -0,0 +1,25 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from mediagoblin.db.sql.convert import run_conversion + + +def mongosql_parser_setup(subparser): + pass + + +def mongosql(args): + run_conversion(args.conf_file) diff --git a/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po index b5832fe4..7c64c09f 100644 --- a/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2012-02-09 09:30-0600\n" +"POT-Creation-Date: 2012-02-26 15:51-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -37,51 +37,51 @@ msgstr "" msgid "Sorry, registration is disabled on this instance." msgstr "" -#: mediagoblin/auth/views.py:73 +#: mediagoblin/auth/views.py:75 msgid "Sorry, a user with that name already exists." msgstr "" -#: mediagoblin/auth/views.py:77 +#: mediagoblin/auth/views.py:79 msgid "Sorry, a user with that email address already exists." msgstr "" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:182 msgid "" "Your email address has been verified. You may now login, edit your " "profile, and submit images!" msgstr "" -#: mediagoblin/auth/views.py:186 +#: mediagoblin/auth/views.py:188 msgid "The verification key or user id is incorrect" msgstr "" -#: mediagoblin/auth/views.py:204 +#: mediagoblin/auth/views.py:206 msgid "You must be logged in so we know who to send the email to!" msgstr "" -#: mediagoblin/auth/views.py:212 +#: mediagoblin/auth/views.py:214 msgid "You've already verified your email address!" msgstr "" -#: mediagoblin/auth/views.py:225 +#: mediagoblin/auth/views.py:227 msgid "Resent your verification email." msgstr "" -#: mediagoblin/auth/views.py:260 +#: mediagoblin/auth/views.py:262 msgid "An email has been sent with instructions on how to change your password." msgstr "" -#: mediagoblin/auth/views.py:270 +#: mediagoblin/auth/views.py:272 msgid "" "Could not send password recovery email as your username is inactive or " "your account's email address has not been verified." msgstr "" -#: mediagoblin/auth/views.py:282 +#: mediagoblin/auth/views.py:284 msgid "Couldn't find someone with that username or email." msgstr "" -#: mediagoblin/auth/views.py:330 +#: mediagoblin/auth/views.py:332 msgid "You can now log in using your new password." msgstr "" @@ -152,23 +152,23 @@ msgstr "" msgid "An entry with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:92 +#: mediagoblin/edit/views.py:89 msgid "You are editing another user's media. Proceed with caution." msgstr "" -#: mediagoblin/edit/views.py:162 +#: mediagoblin/edit/views.py:159 msgid "You are editing a user's profile. Proceed with caution." msgstr "" -#: mediagoblin/edit/views.py:180 +#: mediagoblin/edit/views.py:175 msgid "Profile changes saved" msgstr "" -#: mediagoblin/edit/views.py:206 +#: mediagoblin/edit/views.py:201 msgid "Wrong password" msgstr "" -#: mediagoblin/edit/views.py:222 +#: mediagoblin/edit/views.py:217 msgid "Account settings saved" msgstr "" @@ -188,7 +188,7 @@ msgstr "" msgid "You must provide a file." msgstr "" -#: mediagoblin/submit/views.py:158 +#: mediagoblin/submit/views.py:156 msgid "Woohoo! Submitted!" msgstr "" @@ -623,23 +623,23 @@ msgstr "" msgid "I am sure I want to delete this" msgstr "" -#: mediagoblin/user_pages/views.py:155 +#: mediagoblin/user_pages/views.py:153 msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:161 +#: mediagoblin/user_pages/views.py:159 msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:183 +#: mediagoblin/user_pages/views.py:181 msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:190 +#: mediagoblin/user_pages/views.py:188 msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:198 +#: mediagoblin/user_pages/views.py:196 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mo Binary files differindex 25ab5836..f5a660d9 100644 --- a/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po index 49626556..b3088b25 100644 --- a/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2012-01-29 13:47-0600\n" -"PO-Revision-Date: 2012-02-05 21:07+0000\n" +"POT-Creation-Date: 2012-02-09 09:30-0600\n" +"PO-Revision-Date: 2012-02-26 19:34+0000\n" "Last-Translator: aleksejrs <deletesoftware@yandex.ru>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" @@ -21,7 +21,7 @@ msgstr "" "Language: eo\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" -#: mediagoblin/processing.py:143 +#: mediagoblin/processing.py:153 msgid "Invalid file given for media type." msgstr "La provizita dosiero ne konformas al la informtipo." @@ -53,9 +53,7 @@ msgstr "Ni bedaŭras, sed konto kun tiu retpoŝtadreso jam ekzistas." msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" -msgstr "" -"Via retpoŝtadreso estas konfirmita. Vi povas nun ensaluti, redakti vian " -"profilon, kaj alŝuti bildojn!" +msgstr "Via retpoŝtadreso estas konfirmita. Vi povas nun ensaluti, redakti vian profilon, kaj alŝuti bildojn!" #: mediagoblin/auth/views.py:186 msgid "The verification key or user id is incorrect" @@ -82,9 +80,7 @@ msgstr "Senditas retletero kun instrukcio pri kiel ŝanĝi vian pasvorton." msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." -msgstr "" -"Ni ne povas sendi pasvortsavan retleteron, ĉar aŭ via konto estas neaktiva, " -"aŭ ĝia retpoŝtadreso ne estis konfirmita." +msgstr "Ni ne povas sendi pasvortsavan retleteron, ĉar aŭ via konto estas neaktiva, aŭ ĝia retpoŝtadreso ne estis konfirmita." #: mediagoblin/auth/views.py:282 msgid "Couldn't find someone with that username or email." @@ -108,10 +104,7 @@ msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." -msgstr "" -"Vi povas uzi por markado la lingvon\n" -" «<a href=\"http://daringfireball.net/projects/markdown/basics\">\n" -" Markdown</a>»." +msgstr "Vi povas uzi por markado la lingvon\n «<a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a>»." #: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 msgid "Tags" @@ -133,9 +126,7 @@ msgstr "La distingiga adresparto ne povas esti malplena" msgid "" "The title part of this media's address. You usually don't need to change " "this." -msgstr "" -"La dosiertitol-bazita parto de la dosieradreso. Ordinare ne necesas ĝin " -"ŝanĝi." +msgstr "La dosiertitol-bazita parto de la dosieradreso. Ordinare ne necesas ĝin ŝanĝi." #: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 msgid "License" @@ -221,9 +212,7 @@ msgstr "Verŝajne ĉe ĉi tiu adreso ne estas paĝo. Ni bedaŭras!" msgid "" "If you're sure the address is correct, maybe the page you're looking for has" " been moved or deleted." -msgstr "" -"Se vi estas certa, ke la adreso estas ĝusta, eble la serĉata de vi paĝo " -"estis movita aŭ forigita." +msgstr "Se vi estas certa, ke la adreso estas ĝusta, eble la serĉata de vi paĝo estis movita aŭ forigita." #: mediagoblin/templates/mediagoblin/base.html:46 msgid "MediaGoblin logo" @@ -252,9 +241,7 @@ msgstr "Ensaluti" msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" -msgstr "" -"Funkcias per <a href=\"http://mediagoblin.org\">MediaGoblin</a>, unu el la " -"<a href=\"http://gnu.org/\">projektoj de GNU</a>" +msgstr "Funkcias per <a href=\"http://mediagoblin.org\">MediaGoblin</a>, unu el la <a href=\"http://gnu.org/\">projektoj de GNU</a>" #: mediagoblin/templates/mediagoblin/root.html:24 msgid "Explore" @@ -268,18 +255,13 @@ msgstr "Saluton, kaj bonvenon al ĉi tiu MediaGoblina retpaĝaro!" msgid "" "This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " "extraordinarily great piece of media hosting software." -msgstr "" -"Ĉi tiu retpaĝaro funkcias per <a " -"href=\"http://mediagoblin.org\">MediaGoblin</a>, eksterordinare bonega " -"programaro por gastigado de aŭd‐vid‐dosieroj." +msgstr "Ĉi tiu retpaĝaro funkcias per <a href=\"http://mediagoblin.org\">MediaGoblin</a>, eksterordinare bonega programaro por gastigado de aŭd‐vid‐dosieroj." #: mediagoblin/templates/mediagoblin/root.html:29 msgid "" "To add your own media, place comments, save your favourites and more, you " "can log in with your MediaGoblin account." -msgstr "" -"Por aldoni viajn proprajn dosierojn, fari al vi liston de la plej plaĉaj, " -"ks, vi povas ensaluti je via MediaGoblina konto." +msgstr "Por aldoni viajn proprajn dosierojn, fari al vi liston de la plej plaĉaj, ks, vi povas ensaluti je via MediaGoblina konto." #: mediagoblin/templates/mediagoblin/root.html:31 msgid "Don't have one yet? It's easy!" @@ -291,10 +273,7 @@ msgid "" "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" " <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" -msgstr "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Kreu konton en ĉi tiu retejo</a>\n" -" aŭ\n" -" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">ekfunkciigu MediaGoblin’on en via propra servilo</a>" +msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Kreu konton en ĉi tiu retejo</a>\n aŭ\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">ekfunkciigu MediaGoblin’on en via propra servilo</a>" #: mediagoblin/templates/mediagoblin/root.html:40 msgid "Most recent media" @@ -328,14 +307,7 @@ msgid "" "\n" "If you think this is an error, just ignore this email and continue being\n" "a happy goblin!" -msgstr "" -"Saluton, %(username)s,\n" -"\n" -"por ŝanĝi vian pasvorton ĉe GNUa MediaGoblin, sekvu la jenan retadreson per via TTT-legilo:\n" -"\n" -"%(verification_url)s\n" -"\n" -"Se vi pensas, ke ĉi tiu retletero estas sendita erare, simple ignoru ĝin kaj plu restu feliĉa koboldo!" +msgstr "Saluton, %(username)s,\n\npor ŝanĝi vian pasvorton ĉe GNUa MediaGoblin, sekvu la jenan retadreson per via TTT-legilo:\n\n%(verification_url)s\n\nSe vi pensas, ke ĉi tiu retletero estas sendita erare, simple ignoru ĝin kaj plu restu feliĉa koboldo!" #: mediagoblin/templates/mediagoblin/auth/login.html:30 msgid "Logging in failed!" @@ -370,12 +342,7 @@ msgid "" "your web browser:\n" "\n" "%(verification_url)s" -msgstr "" -"Sal %(username)s,\n" -"\n" -"por aktivigi vian GNU MediaGoblin konton, malfermu la sekvantan URLon en via retumilo:\n" -"\n" -"%(verification_url)s" +msgstr "Sal %(username)s,\n\npor aktivigi vian GNU MediaGoblin konton, malfermu la sekvantan URLon en via retumilo:\n\n%(verification_url)s" #: mediagoblin/templates/mediagoblin/edit/edit.html:29 #, python-format @@ -419,20 +386,14 @@ msgid "" "Sorry, this video will not work because \n" "\t your web browser does not support HTML5 \n" "\t video." -msgstr "" -"Bedaŭrinde ĉi tiu filmo ne spekteblas, ĉar\n" -"<span class=\"whitespace other\" title=\"Tab\">»</span> via TTT-legilo ne subtenas montradon\n" -"<span class=\"whitespace other\" title=\"Tab\">»</span> de filmoj laŭ HTML5." +msgstr "Bedaŭrinde ĉi tiu filmo ne spekteblas, ĉar\n<span class=\"whitespace other\" title=\"Tab\">»</span> via TTT-legilo ne subtenas montradon\n<span class=\"whitespace other\" title=\"Tab\">»</span> de filmoj laŭ HTML5." #: mediagoblin/templates/mediagoblin/media_displays/video.html:36 msgid "" "You can get a modern web browser that \n" "\t can play this video at <a href=\"http://getfirefox.com\">\n" "\t http://getfirefox.com</a>!" -msgstr "" -"Vi povas akiri modernan TTT-legilon,\n" -"<span class=\"whitespace other\" title=\"Tab\">»</span> kapablan montri ĉi tiun filmon, ĉe <a href=\"http://getfirefox.com\">\n" -"<span class=\"whitespace other\" title=\"Tab\">»</span> http://getfirefox.com</a>!" +msgstr "Vi povas akiri modernan TTT-legilon,\n<span class=\"whitespace other\" title=\"Tab\">»</span> kapablan montri ĉi tiun filmon, ĉe <a href=\"http://getfirefox.com\">\n<span class=\"whitespace other\" title=\"Tab\">»</span> http://getfirefox.com</a>!" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Add your media" @@ -488,9 +449,7 @@ msgid "" "You can use <a " "href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" " formatting." -msgstr "" -"Vi povas uzi por markado la lingvon «<a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a>»." +msgstr "Vi povas uzi por markado la lingvon «<a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a>»." #: mediagoblin/templates/mediagoblin/user_pages/media.html:116 msgid "Add this comment" @@ -503,8 +462,7 @@ msgstr "je" #: mediagoblin/templates/mediagoblin/user_pages/media.html:153 #, python-format msgid "<p>❖ Browsing media by <a href=\"%(user_url)s\">%(username)s</a></p>" -msgstr "" -"<p>❖ Foliumado de dosieraro de <a href=\"%(user_url)s\">%(username)s</a></p>" +msgstr "<p>❖ Foliumado de dosieraro de <a href=\"%(user_url)s\">%(username)s</a></p>" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -522,9 +480,7 @@ msgstr "Kontrolejo pri dosierpreparado." #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:25 msgid "" "You can track the state of media being processed for your gallery here." -msgstr "" -"Ĉi tie vi povas informiĝi pri la stato de preparado de dosieroj por via " -"galerio." +msgstr "Ĉi tie vi povas informiĝi pri la stato de preparado de dosieroj por via galerio." #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:28 msgid "Media in-processing" @@ -560,8 +516,7 @@ msgstr "Preskaŭ finite! Restas nur validigi vian konton." #: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." -msgstr "" -"Post kelkaj momentoj devas veni retletero kun instrukcio pri kiel tion fari." +msgstr "Post kelkaj momentoj devas veni retletero kun instrukcio pri kiel tion fari." #: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" @@ -575,18 +530,14 @@ msgstr "Resendi kontrolmesaĝon" msgid "" "Someone has registered an account with this username, but it still has to be" " activated." -msgstr "" -"Iu registris konton kun tiu ĉi uzantonomo, sed ĝi devas ankoraŭ esti " -"aktivigita." +msgstr "Iu registris konton kun tiu ĉi uzantonomo, sed ĝi devas ankoraŭ esti aktivigita." #: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " "href=\"%(login_url)s\">log in</a> and resend it." -msgstr "" -"Se vi estas tiu sed vi perdis vian kontrolmesaĝon, vi povas <a " -"href=\"%(login_url)s\">ensaluti</a> kaj resendi ĝin." +msgstr "Se vi estas tiu sed vi perdis vian kontrolmesaĝon, vi povas <a href=\"%(login_url)s\">ensaluti</a> kaj resendi ĝin." #: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." @@ -614,8 +565,7 @@ msgstr "Rigardi ĉiujn dosierojn de %(username)s" msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." -msgstr "" -"Ĝuste ĉi tie aperos viaj dosieroj, sed vi ŝajne ankoraŭ nenion alŝutis." +msgstr "Ĝuste ĉi tie aperos viaj dosieroj, sed vi ŝajne ankoraŭ nenion alŝutis." #: mediagoblin/templates/mediagoblin/user_pages/user.html:163 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72 @@ -690,12 +640,8 @@ msgstr "Vi forigis la dosieron." #: mediagoblin/user_pages/views.py:190 msgid "The media was not deleted because you didn't check that you were sure." -msgstr "" -"La dosiero ne estis forigita, ĉar vi ne konfirmis vian certecon per la " -"markilo." +msgstr "La dosiero ne estis forigita, ĉar vi ne konfirmis vian certecon per la markilo." #: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Vi estas forigonta dosieron de alia uzanto. Estu singardema." - - diff --git a/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mo Binary files differindex dd7735fd..eb6cc942 100644 --- a/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po index d895f3bf..ea9d1dc3 100644 --- a/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2012-01-29 13:47-0600\n" -"PO-Revision-Date: 2012-02-05 21:04+0000\n" +"POT-Creation-Date: 2012-02-09 09:30-0600\n" +"PO-Revision-Date: 2012-02-26 19:33+0000\n" "Last-Translator: aleksejrs <deletesoftware@yandex.ru>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" @@ -19,7 +19,7 @@ msgstr "" "Language: ru\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" -#: mediagoblin/processing.py:143 +#: mediagoblin/processing.py:153 msgid "Invalid file given for media type." msgstr "Неправильный формат файла." @@ -45,17 +45,13 @@ msgstr "Извините, пользователь с этим именем уж #: mediagoblin/auth/views.py:77 msgid "Sorry, a user with that email address already exists." -msgstr "" -"Сожалеем, но на этот адрес электронной почты уже зарегистрирована другая " -"учётная запись." +msgstr "Сожалеем, но на этот адрес электронной почты уже зарегистрирована другая учётная запись." #: mediagoblin/auth/views.py:180 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" -msgstr "" -"Адрес вашей электронной потвержден. Вы теперь можете войти и начать " -"редактировать свой профиль и загружать новые изображения!" +msgstr "Адрес вашей электронной потвержден. Вы теперь можете войти и начать редактировать свой профиль и загружать новые изображения!" #: mediagoblin/auth/views.py:186 msgid "The verification key or user id is incorrect" @@ -82,15 +78,11 @@ msgstr "Вам отправлено электронное письмо с ин msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." -msgstr "" -"Мы не можем отправить сообщение для восстановления пароля, потому что ваша " -"учётная запись неактивна, либо указанный в ней адрес электронной почты не " -"был подтверждён." +msgstr "Мы не можем отправить сообщение для восстановления пароля, потому что ваша учётная запись неактивна, либо указанный в ней адрес электронной почты не был подтверждён." #: mediagoblin/auth/views.py:282 msgid "Couldn't find someone with that username or email." -msgstr "" -"Не найдено никого с таким именем пользователя или адресом электронной почты." +msgstr "Не найдено никого с таким именем пользователя или адресом электронной почты." #: mediagoblin/auth/views.py:330 msgid "You can now log in using your new password." @@ -110,10 +102,7 @@ msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." -msgstr "" -"Для разметки можете использовать язык\n" -" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" -" Markdown</a>." +msgstr "Для разметки можете использовать язык\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a>." #: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 msgid "Tags" @@ -135,9 +124,7 @@ msgstr "Отличительная часть адреса необходима" msgid "" "The title part of this media's address. You usually don't need to change " "this." -msgstr "" -"Часть адреса этого файла, производная от его названия. Её обычно не " -"требуется изменять." +msgstr "Часть адреса этого файла, производная от его названия. Её обычно не требуется изменять." #: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 msgid "License" @@ -157,9 +144,7 @@ msgstr "Старый пароль" #: mediagoblin/edit/forms.py:65 msgid "Enter your old password to prove you own this account." -msgstr "" -"Введите свой старый пароль в качестве доказательства, что это ваша учётная " -"запись." +msgstr "Введите свой старый пароль в качестве доказательства, что это ваша учётная запись." #: mediagoblin/edit/forms.py:68 msgid "New password" @@ -167,8 +152,7 @@ msgstr "Новый пароль" #: mediagoblin/edit/views.py:68 msgid "An entry with that slug already exists for this user." -msgstr "" -"У этого пользователя уже есть файл с такой отличительной частью адреса." +msgstr "У этого пользователя уже есть файл с такой отличительной частью адреса." #: mediagoblin/edit/views.py:92 msgid "You are editing another user's media. Proceed with caution." @@ -255,9 +239,7 @@ msgstr "Войти" msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" -msgstr "" -"Работает на <a href=\"http://mediagoblin.org\">MediaGoblin</a>, проекте <a " -"href=\"http://gnu.org/\">GNU</a>" +msgstr "Работает на <a href=\"http://mediagoblin.org\">MediaGoblin</a>, проекте <a href=\"http://gnu.org/\">GNU</a>" #: mediagoblin/templates/mediagoblin/root.html:24 msgid "Explore" @@ -271,18 +253,13 @@ msgstr "Привет! Добро пожаловать на наш MediaGoblin’ msgid "" "This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " "extraordinarily great piece of media hosting software." -msgstr "" -"Этот сайт работает на <a href=\"http://mediagoblin.org\">MediaGoblin</a>, " -"необыкновенно замечательном ПО для хостинга мультимедийных файлов." +msgstr "Этот сайт работает на <a href=\"http://mediagoblin.org\">MediaGoblin</a>, необыкновенно замечательном ПО для хостинга мультимедийных файлов." #: mediagoblin/templates/mediagoblin/root.html:29 msgid "" "To add your own media, place comments, save your favourites and more, you " "can log in with your MediaGoblin account." -msgstr "" -"Для добавления собственных файлов, комментирования, ведения списка любимых " -"файлов и т. п. вы можете представиться с помощью вашей MediaGoblin’овой " -"учётной записи." +msgstr "Для добавления собственных файлов, комментирования, ведения списка любимых файлов и т. п. вы можете представиться с помощью вашей MediaGoblin’овой учётной записи." #: mediagoblin/templates/mediagoblin/root.html:31 msgid "Don't have one yet? It's easy!" @@ -294,10 +271,7 @@ msgid "" "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" " <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" -msgstr "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Создайте учётную запись на этом сайте</a>\n" -" или\n" -" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">установите MediaGoblin на собственный сервер</a>" +msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Создайте учётную запись на этом сайте</a>\n или\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">установите MediaGoblin на собственный сервер</a>" #: mediagoblin/templates/mediagoblin/root.html:40 msgid "Most recent media" @@ -331,16 +305,7 @@ msgid "" "\n" "If you think this is an error, just ignore this email and continue being\n" "a happy goblin!" -msgstr "" -"Привет, %(username)s,\n" -"\n" -"чтобы сменить свой пароль от GNU MediaGoblin, откройте\n" -"следующий URL вашим веб‐браузером:\n" -"\n" -"%(verification_url)s\n" -"\n" -"Если вы думаете, что это какая‐то ошибка, то игнорируйте\n" -"это сообщение и продолжайте быть счастливым гоблином!" +msgstr "Привет, %(username)s,\n\nчтобы сменить свой пароль от GNU MediaGoblin, откройте\nследующий URL вашим веб‐браузером:\n\n%(verification_url)s\n\nЕсли вы думаете, что это какая‐то ошибка, то игнорируйте\nэто сообщение и продолжайте быть счастливым гоблином!" #: mediagoblin/templates/mediagoblin/auth/login.html:30 msgid "Logging in failed!" @@ -375,12 +340,7 @@ msgid "" "your web browser:\n" "\n" "%(verification_url)s" -msgstr "" -"Привет, %(username)s!\n" -"\n" -"Чтобы активировать свой аккаунт в GNU MediaGoblin, откройте в своём веб‐браузере следующую ссылку:\n" -"\n" -"%(verification_url)s" +msgstr "Привет, %(username)s!\n\nЧтобы активировать свой аккаунт в GNU MediaGoblin, откройте в своём веб‐браузере следующую ссылку:\n\n%(verification_url)s" #: mediagoblin/templates/mediagoblin/edit/edit.html:29 #, python-format @@ -424,20 +384,14 @@ msgid "" "Sorry, this video will not work because \n" "\t your web browser does not support HTML5 \n" "\t video." -msgstr "" -"Сожалеем, этот ролик не проиграется, ⏎\n" -"» потому что ваш браузер не поддерживает ⏎\n" -"» видео в соответствии со стандартом HTML5." +msgstr "Сожалеем, этот ролик не проиграется, ⏎\n» потому что ваш браузер не поддерживает ⏎\n» видео в соответствии со стандартом HTML5." #: mediagoblin/templates/mediagoblin/media_displays/video.html:36 msgid "" "You can get a modern web browser that \n" "\t can play this video at <a href=\"http://getfirefox.com\">\n" "\t http://getfirefox.com</a>!" -msgstr "" -"Вы можете скачать современный браузер,\n" -"<span class=\"whitespace other\" title=\"Tab\">»</span> способный воспроизводить это видео, с <a href=\"http://getfirefox.com\">\n" -"<span class=\"whitespace other\" title=\"Tab\">»</span> http://getfirefox.com</a>!" +msgstr "Вы можете скачать современный браузер,\n<span class=\"whitespace other\" title=\"Tab\">»</span> способный воспроизводить это видео, с <a href=\"http://getfirefox.com\">\n<span class=\"whitespace other\" title=\"Tab\">»</span> http://getfirefox.com</a>!" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Add your media" @@ -493,9 +447,7 @@ msgid "" "You can use <a " "href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" " formatting." -msgstr "" -"Для разметки можете использовать язык <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a>." +msgstr "Для разметки можете использовать язык <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a>." #: mediagoblin/templates/mediagoblin/user_pages/media.html:116 msgid "Add this comment" @@ -508,9 +460,7 @@ msgstr "в" #: mediagoblin/templates/mediagoblin/user_pages/media.html:153 #, python-format msgid "<p>❖ Browsing media by <a href=\"%(user_url)s\">%(username)s</a></p>" -msgstr "" -"<p>❖ Просмотр файлов пользователя <a " -"href=\"%(user_url)s\">%(username)s</a></p>" +msgstr "<p>❖ Просмотр файлов пользователя <a href=\"%(user_url)s\">%(username)s</a></p>" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -528,8 +478,7 @@ msgstr "Панель обработки файлов" #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:25 msgid "" "You can track the state of media being processed for your gallery here." -msgstr "" -"Вы можете следить за статусом обработки файлов для вашей галереи здесь." +msgstr "Вы можете следить за статусом обработки файлов для вашей галереи здесь." #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:28 msgid "Media in-processing" @@ -565,9 +514,7 @@ msgstr "Почти закончили! Теперь надо активиров #: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." -msgstr "" -"Через пару мгновений на адрес вашей электронной почты должно прийти " -"сообщение с дальнейшими инструкциями." +msgstr "Через пару мгновений на адрес вашей электронной почты должно прийти сообщение с дальнейшими инструкциями." #: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" @@ -575,8 +522,7 @@ msgstr "А если нет, то:" #: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" -msgstr "" -"Повторно отправить сообщение для подверждения адреса электронной почты" +msgstr "Повторно отправить сообщение для подверждения адреса электронной почты" #: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" @@ -589,9 +535,7 @@ msgstr "Кто‐то создал аккаунт с этим именем, но msgid "" "If you are that person but you've lost your verification email, you can <a " "href=\"%(login_url)s\">log in</a> and resend it." -msgstr "" -"Если это были вы, и если вы потеряли сообщение для подтверждения аккаунта, " -"то вы можете <a href=\"%(login_url)s\">войти</a> и отправить его повторно." +msgstr "Если это были вы, и если вы потеряли сообщение для подтверждения аккаунта, то вы можете <a href=\"%(login_url)s\">войти</a> и отправить его повторно." #: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." @@ -699,5 +643,3 @@ msgstr "Файл не удалён, так как вы не подтвердил #: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Вы на пороге удаления файла другого пользователя. Будьте осторожны." - - diff --git a/mediagoblin/init/celery/__init__.py b/mediagoblin/init/celery/__init__.py index fb958909..29ccd83a 100644 --- a/mediagoblin/init/celery/__init__.py +++ b/mediagoblin/init/celery/__init__.py @@ -47,30 +47,12 @@ def setup_celery_from_config(app_config, global_config, celery_settings = {} - # set up mongodb stuff - celery_settings['CELERY_RESULT_BACKEND'] = 'mongodb' - if 'BROKER_BACKEND' not in celery_settings: - celery_settings['BROKER_BACKEND'] = 'mongodb' - - celery_mongo_settings = {} - - if 'db_host' in app_config: - celery_mongo_settings['host'] = app_config['db_host'] - if celery_settings['BROKER_BACKEND'] == 'mongodb': - celery_settings['BROKER_HOST'] = app_config['db_host'] - if 'db_port' in app_config: - celery_mongo_settings['port'] = app_config['db_port'] - if celery_settings['BROKER_BACKEND'] == 'mongodb': - celery_settings['BROKER_PORT'] = app_config['db_port'] - celery_mongo_settings['database'] = app_config['db_name'] - - celery_settings['CELERY_MONGODB_BACKEND_SETTINGS'] = celery_mongo_settings - - # Add anything else + # Add all celery settings from config for key, value in celery_conf.iteritems(): - key = key.upper() celery_settings[key] = value + # TODO: use default result stuff here if it exists + # add mandatory celery imports celery_imports = celery_settings.setdefault('CELERY_IMPORTS', []) celery_imports.extend(MANDATORY_CELERY_IMPORTS) diff --git a/mediagoblin/media_types/video/models.py b/mediagoblin/media_types/video/models.py index 741c329b..709d7910 100644 --- a/mediagoblin/media_types/video/models.py +++ b/mediagoblin/media_types/video/models.py @@ -18,16 +18,17 @@ from mediagoblin.db.sql.models import Base from sqlalchemy import ( - Column, Integer, Unicode, UnicodeText, DateTime, Boolean, ForeignKey, - UniqueConstraint) + Column, Integer, SmallInteger, ForeignKey) class VideoData(Base): __tablename__ = "video_data" - id = Column(Integer, primary_key=True) - media_entry = Column( - Integer, ForeignKey('media_entries.id'), nullable=False) + # The primary key *and* reference to the main media_entry + media_entry = Column(Integer, ForeignKey('media_entries.id'), + primary_key=True) + width = Column(SmallInteger) + height = Column(SmallInteger) DATA_MODEL = VideoData diff --git a/mediagoblin/media_types/video/processing.py b/mediagoblin/media_types/video/processing.py index 9dc23c55..3a479802 100644 --- a/mediagoblin/media_types/video/processing.py +++ b/mediagoblin/media_types/video/processing.py @@ -77,9 +77,9 @@ def process_video(entry): entry.media_files['webm_640'] = medium_filepath # Save the width and height of the transcoded video - entry.media_data['video'] = { - u'width': transcoder.dst_data.videowidth, - u'height': transcoder.dst_data.videoheight} + entry.media_data_init( + width=transcoder.dst_data.videowidth, + height=transcoder.dst_data.videoheight) # Create a temporary file for the video thumbnail tmp_thumb = tempfile.NamedTemporaryFile() diff --git a/mediagoblin/processing.py b/mediagoblin/processing.py index 9e57380d..a07de869 100644 --- a/mediagoblin/processing.py +++ b/mediagoblin/processing.py @@ -114,6 +114,7 @@ def mark_entry_failed(entry_id, exc): u'fail_error': exc.exception_path, u'fail_metadata': exc.metadata}}) else: + _log.warn("No idea what happened here, but it failed: %r", exc) # Looks like no, so just mark it as failed and don't record a # failure_error (we'll assume it wasn't handled) and don't record # metadata (in fact overwrite it if somehow it had previous info diff --git a/mediagoblin/static/images/goblin.ico b/mediagoblin/static/images/goblin.ico Binary files differindex f2e7152f..ae5a1b12 100644 --- a/mediagoblin/static/images/goblin.ico +++ b/mediagoblin/static/images/goblin.ico diff --git a/mediagoblin/static/images/goblin.png b/mediagoblin/static/images/goblin.png Binary files differindex 0a3ad22e..672ed61a 100644 --- a/mediagoblin/static/images/goblin.png +++ b/mediagoblin/static/images/goblin.png diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py index 845400ca..1e145e9d 100644 --- a/mediagoblin/submit/views.py +++ b/mediagoblin/submit/views.py @@ -59,7 +59,7 @@ def submit_start(request): # create entry and save in database entry = request.db.MediaEntry() - entry['_id'] = ObjectId() + entry.id = ObjectId() entry.media_type = unicode(media_type) entry.title = ( unicode(request.POST['title']) @@ -78,11 +78,18 @@ def submit_start(request): # Generate a slug from the title entry.generate_slug() + # We generate this ourselves so we know what the taks id is for + # retrieval later. + + # (If we got it off the task's auto-generation, there'd be + # a risk of a race condition when we'd save after sending + # off the task) + task_id = unicode(uuid.uuid4()) # Now store generate the queueing related filename queue_filepath = request.app.queue_store.get_unique_filepath( ['media_entries', - unicode(entry._id), + task_id, secure_filename(filename)]) # queue appropriately @@ -95,14 +102,7 @@ def submit_start(request): # Add queued filename to the entry entry.queued_media_file = queue_filepath - # We generate this ourselves so we know what the taks id is for - # retrieval later. - - # (If we got it off the task's auto-generation, there'd be - # a risk of a race condition when we'd save after sending - # off the task) - task_id = unicode(uuid.uuid4()) - entry['queued_task_id'] = task_id + entry.queued_task_id = task_id # Save now so we have this data before kicking off processing entry.save(validate=True) diff --git a/mediagoblin/templates/mediagoblin/media_displays/video.html b/mediagoblin/templates/mediagoblin/media_displays/video.html index ec4338fa..acd570e7 100644 --- a/mediagoblin/templates/mediagoblin/media_displays/video.html +++ b/mediagoblin/templates/mediagoblin/media_displays/video.html @@ -21,8 +21,8 @@ {% block mediagoblin_media %} <div class="video-player" style="position: relative;"> <video class="video-js vjs-default-skin" - width="{{ media.media_data.video.width }}" - height="{{ media.media_data.video.height }}" + width="{{ media.media_data.width }}" + height="{{ media.media_data.height }}" controls="controls" preload="auto" data-setup=""> diff --git a/mediagoblin/tests/fake_carrot_conf_bad.ini b/mediagoblin/tests/fake_carrot_conf_bad.ini index 0c79b354..9d8cf518 100644 --- a/mediagoblin/tests/fake_carrot_conf_bad.ini +++ b/mediagoblin/tests/fake_carrot_conf_bad.ini @@ -11,4 +11,4 @@ encouragement_phrase = 586956856856 # shouldn't throw error blah_blah = "blah!" # shouldn't throw error either [celery] -eat_celery_with_carrots = pants # yeah that's def an error right there. +EAT_CELERY_WITH_CARROTS = pants # yeah that's def an error right there. diff --git a/mediagoblin/tests/fake_carrot_conf_good.ini b/mediagoblin/tests/fake_carrot_conf_good.ini index fed14d07..1377907b 100644 --- a/mediagoblin/tests/fake_carrot_conf_good.ini +++ b/mediagoblin/tests/fake_carrot_conf_good.ini @@ -10,4 +10,4 @@ encouragement_phrase = "I'd love it if you eat your carrots!" blah_blah = "blah!" [celery] -eat_celery_with_carrots = False +EAT_CELERY_WITH_CARROTS = False diff --git a/mediagoblin/tests/fake_celery_conf.ini b/mediagoblin/tests/fake_celery_conf.ini index 3e52ac3a..67b0cba6 100644 --- a/mediagoblin/tests/fake_celery_conf.ini +++ b/mediagoblin/tests/fake_celery_conf.ini @@ -1,9 +1,9 @@ -['mediagoblin'] +[mediagoblin] # I got nothin' in this file! -['celery'] -some_variable = floop -mail_port = 2000 -celeryd_eta_scheduler_precision = 1.3 -celery_result_persistent = true -celery_imports = foo.bar.baz, this.is.an.import +[celery] +SOME_VARIABLE = floop +MAIL_PORT = 2000 +CELERYD_ETA_SCHEDULER_PRECISION = 1.3 +CELERY_RESULT_PERSISTENT = true +CELERY_IMPORTS = foo.bar.baz, this.is.an.import diff --git a/mediagoblin/tests/fake_celery_conf_mgdb.ini b/mediagoblin/tests/fake_celery_conf_mgdb.ini deleted file mode 100644 index 52671c14..00000000 --- a/mediagoblin/tests/fake_celery_conf_mgdb.ini +++ /dev/null @@ -1,14 +0,0 @@ -['mediagoblin'] -db_host = mongodb.example.org -db_port = 8080 -db_name = captain_lollerskates - -['something'] -or = other - -['celery'] -some_variable = poolf -mail_port = 2020 -celeryd_eta_scheduler_precision = 3.1 -celery_result_persistent = false -celery_imports = baz.bar.foo, import.is.a.this diff --git a/mediagoblin/tests/fake_config_spec.ini b/mediagoblin/tests/fake_config_spec.ini index 9421ce36..43f2e236 100644 --- a/mediagoblin/tests/fake_config_spec.ini +++ b/mediagoblin/tests/fake_config_spec.ini @@ -7,4 +7,4 @@ num_carrots = integer(default=1) encouragement_phrase = string() [celery] -eat_celery_with_carrots = boolean(default=True)
\ No newline at end of file +EAT_CELERY_WITH_CARROTS = boolean(default=True)
\ No newline at end of file diff --git a/mediagoblin/tests/test_celery_setup.py b/mediagoblin/tests/test_celery_setup.py index c9c77821..fd600f56 100644 --- a/mediagoblin/tests/test_celery_setup.py +++ b/mediagoblin/tests/test_celery_setup.py @@ -22,8 +22,6 @@ from mediagoblin.init.config import read_mediagoblin_config TEST_CELERY_CONF_NOSPECIALDB = pkg_resources.resource_filename( 'mediagoblin.tests', 'fake_celery_conf.ini') -TEST_CELERY_CONF_MGSPECIALDB = pkg_resources.resource_filename( - 'mediagoblin.tests', 'fake_celery_conf_mgdb.ini') def test_setup_celery_from_config(): @@ -51,35 +49,12 @@ def test_setup_celery_from_config(): assert fake_celery_module.CELERY_RESULT_PERSISTENT is True assert fake_celery_module.CELERY_IMPORTS == [ 'foo.bar.baz', 'this.is.an.import', 'mediagoblin.processing'] - assert fake_celery_module.CELERY_MONGODB_BACKEND_SETTINGS == { - 'database': 'mediagoblin'} - assert fake_celery_module.CELERY_RESULT_BACKEND == 'mongodb' - assert fake_celery_module.BROKER_BACKEND == 'mongodb' - - _wipe_testmodule_clean(fake_celery_module) - - global_config, validation_result = read_mediagoblin_config( - TEST_CELERY_CONF_MGSPECIALDB) - app_config = global_config['mediagoblin'] - - celery_setup.setup_celery_from_config( - app_config, global_config, - 'mediagoblin.tests.fake_celery_module', set_environ=False) - - from mediagoblin.tests import fake_celery_module - assert fake_celery_module.SOME_VARIABLE == 'poolf' - assert fake_celery_module.MAIL_PORT == 2020 - assert isinstance(fake_celery_module.MAIL_PORT, int) - assert fake_celery_module.CELERYD_ETA_SCHEDULER_PRECISION == 3.1 - assert isinstance(fake_celery_module.CELERYD_ETA_SCHEDULER_PRECISION, float) - assert fake_celery_module.CELERY_RESULT_PERSISTENT is False - assert fake_celery_module.CELERY_IMPORTS == [ - 'baz.bar.foo', 'import.is.a.this', 'mediagoblin.processing'] - assert fake_celery_module.CELERY_MONGODB_BACKEND_SETTINGS == { - 'database': 'captain_lollerskates', - 'host': 'mongodb.example.org', - 'port': 8080} - assert fake_celery_module.CELERY_RESULT_BACKEND == 'mongodb' - assert fake_celery_module.BROKER_BACKEND == 'mongodb' - assert fake_celery_module.BROKER_HOST == 'mongodb.example.org' - assert fake_celery_module.BROKER_PORT == 8080 + assert fake_celery_module.CELERY_RESULT_BACKEND == 'database' + assert fake_celery_module.CELERY_RESULT_DBURI == ( + 'sqlite:///' + + pkg_resources.resource_filename('mediagoblin.tests', 'celery.db')) + + assert fake_celery_module.BROKER_TRANSPORT == 'sqlalchemy' + assert fake_celery_module.BROKER_HOST == ( + 'sqlite:///' + + pkg_resources.resource_filename('mediagoblin.tests', 'kombu.db')) diff --git a/mediagoblin/tests/test_config.py b/mediagoblin/tests/test_config.py index c596f6a6..7d8c65c1 100644 --- a/mediagoblin/tests/test_config.py +++ b/mediagoblin/tests/test_config.py @@ -37,7 +37,7 @@ def test_read_mediagoblin_config(): assert this_conf['carrotapp']['carrotcake'] == False assert this_conf['carrotapp']['num_carrots'] == 1 assert not this_conf['carrotapp'].has_key('encouragement_phrase') - assert this_conf['celery']['eat_celery_with_carrots'] == True + assert this_conf['celery']['EAT_CELERY_WITH_CARROTS'] == True # A good file this_conf, validation_results = config.read_mediagoblin_config( @@ -48,7 +48,7 @@ def test_read_mediagoblin_config(): assert this_conf['carrotapp']['encouragement_phrase'] == \ "I'd love it if you eat your carrots!" assert this_conf['carrotapp']['blah_blah'] == "blah!" - assert this_conf['celery']['eat_celery_with_carrots'] == False + assert this_conf['celery']['EAT_CELERY_WITH_CARROTS'] == False # A bad file this_conf, validation_results = config.read_mediagoblin_config( @@ -61,7 +61,7 @@ def test_read_mediagoblin_config(): assert this_conf['carrotapp']['encouragement_phrase'] == \ "586956856856" assert this_conf['carrotapp']['blah_blah'] == "blah!" - assert this_conf['celery']['eat_celery_with_carrots'] == "pants" + assert this_conf['celery']['EAT_CELERY_WITH_CARROTS'] == "pants" def test_generate_validation_report(): @@ -89,7 +89,7 @@ There were validation problems loading this config file: expected_warnings = [ 'carrotapp:carrotcake = the value "slobber" is of the wrong type.', 'carrotapp:num_carrots = the value "GROSS" is of the wrong type.', - 'celery:eat_celery_with_carrots = the value "pants" is of the wrong type.'] + 'celery:EAT_CELERY_WITH_CARROTS = the value "pants" is of the wrong type.'] warnings = report.splitlines()[2:] assert len(warnings) == 3 diff --git a/mediagoblin/tests/test_mgoblin_app.ini b/mediagoblin/tests/test_mgoblin_app.ini index c91ed92b..01bf0972 100644 --- a/mediagoblin/tests/test_mgoblin_app.ini +++ b/mediagoblin/tests/test_mgoblin_app.ini @@ -26,4 +26,4 @@ data_dir = %(here)s/test_user_dev/beaker/cache/data lock_dir = %(here)s/test_user_dev/beaker/cache/lock [celery] -celery_always_eager = true +CELERY_ALWAYS_EAGER = true diff --git a/mediagoblin/tests/test_paste.ini b/mediagoblin/tests/test_paste.ini index bd57994b..d7c18642 100644 --- a/mediagoblin/tests/test_paste.ini +++ b/mediagoblin/tests/test_paste.ini @@ -29,7 +29,7 @@ beaker.session.data_dir = %(here)s/test_user_dev/beaker/sessions/data beaker.session.lock_dir = %(here)s/test_user_dev/beaker/sessions/lock [celery] -celery_always_eager = true +CELERY_ALWAYS_EAGER = true [server:main] use = egg:Paste#http diff --git a/mediagoblin/tests/test_submission.py b/mediagoblin/tests/test_submission.py index 217926a4..2f11bdfb 100644 --- a/mediagoblin/tests/test_submission.py +++ b/mediagoblin/tests/test_submission.py @@ -140,7 +140,7 @@ class TestSubmission: context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/user_pages/user.html'] request = context['request'] media = request.db.MediaEntry.find({'title': 'Balanced Goblin'})[0] - assert_equal(media['tags'], + assert_equal(media.tags, [{'name': u'yin', 'slug': u'yin'}, {'name': u'yang', 'slug': u'yang'}]) @@ -255,7 +255,7 @@ class TestSubmission: {'title': 'Malicious Upload 2'}) assert_equal(entry.state, 'failed') assert_equal( - entry['fail_error'], + entry.fail_error, u'mediagoblin.processing:BadMediaFail') # Test non-supported file with .png extension @@ -275,5 +275,5 @@ class TestSubmission: {'title': 'Malicious Upload 3'}) assert_equal(entry.state, 'failed') assert_equal( - entry['fail_error'], + entry.fail_error, u'mediagoblin.processing:BadMediaFail') diff --git a/mediagoblin/tools/files.py b/mediagoblin/tools/files.py index b2f316b2..25c1a6e6 100644 --- a/mediagoblin/tools/files.py +++ b/mediagoblin/tools/files.py @@ -27,6 +27,6 @@ def delete_media_files(media): mg_globals.public_store.delete_file( listpath) - for attachment in media['attachment_files']: + for attachment in media.attachment_files: mg_globals.public_store.delete_file( attachment['filepath']) diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py index 05d07b1b..530dea64 100644 --- a/mediagoblin/user_pages/views.py +++ b/mediagoblin/user_pages/views.py @@ -142,11 +142,11 @@ def media_post_comment(request, media): assert request.method == 'POST' comment = request.db.MediaComment() - comment['media_entry'] = media._id - comment['author'] = request.user._id - comment['content'] = unicode(request.POST['comment_content']) + comment.media_entry = media.id + comment.author = request.user.id + comment.content = unicode(request.POST['comment_content']) - if not comment['content'].strip(): + if not comment.content.strip(): messages.add_message( request, messages.ERROR, @@ -64,6 +64,7 @@ setup( 'Markdown', 'sqlalchemy', 'sqlalchemy-migrate', + 'kombu-sqlalchemy', ## For now we're expecting that users will install this from ## their package managers. # 'lxml', |