diff --git a/ietf/meeting/migrations/0056_fix-slide-name-slugs.py b/ietf/meeting/migrations/0056_fix-slide-name-slugs.py new file mode 100644 index 000000000..e287a5f5a --- /dev/null +++ b/ietf/meeting/migrations/0056_fix-slide-name-slugs.py @@ -0,0 +1,201 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-07-23 08:27 +from __future__ import unicode_literals, print_function + +import os +import copy +import sys + +from django.conf import settings +from django.db import migrations +from django.core.exceptions import ObjectDoesNotExist + +import debug # pyflakes:ignore + +def get_materials_path(meeting): + return os.path.join(settings.AGENDA_PATH,meeting.number) + +def get_file_path(self): + if not hasattr(self, '_cached_file_path'): + if self.type_id == "draft": + if self.is_dochistory(): + self._cached_file_path = settings.INTERNET_ALL_DRAFTS_ARCHIVE_DIR + else: + if self.get_state_slug() == "rfc": + self._cached_file_path = settings.RFC_PATH + else: + draft_state = self.get_state('draft') + if draft_state and draft_state.slug == 'active': + self._cached_file_path = settings.INTERNET_DRAFT_PATH + else: + self._cached_file_path = settings.INTERNET_ALL_DRAFTS_ARCHIVE_DIR + elif self.type_id in ("agenda", "minutes", "slides", "bluesheets"): + doc = self.doc if isinstance(self, DocHistory) else self + if doc.session_set.exists(): + meeting = doc.session_set.first().meeting + self._cached_file_path = os.path.join(get_materials_path(meeting), self.type_id) + "/" + else: + self._cached_file_path = "" + elif self.type_id == "charter": + self._cached_file_path = settings.CHARTER_PATH + elif self.type_id == "conflrev": + self._cached_file_path = settings.CONFLICT_REVIEW_PATH + elif self.type_id == "statchg": + self._cached_file_path = settings.STATUS_CHANGE_PATH + else: + self._cached_file_path = settings.DOCUMENT_PATH_PATTERN.format(doc=self) + return self._cached_file_path + +def get_base_name(self): + if not hasattr(self, '_cached_base_name'): + if self.type_id == 'draft': + if self.is_dochistory(): + self._cached_base_name = "%s-%s.txt" % (self.doc.name, self.rev) + else: + if self.get_state_slug() == 'rfc': + self._cached_base_name = "%s.txt" % self.canonical_name() + else: + self._cached_base_name = "%s-%s.txt" % (self.name, self.rev) + elif self.type_id in ["slides", "agenda", "minutes", "bluesheets", ]: + if self.external_url: + # we need to remove the extension for the globbing below to work + self._cached_base_name = self.external_url + else: + self._cached_base_name = "%s.txt" % self.canonical_name() # meeting materials are unversioned at the moment + elif self.type_id == 'review': + self._cached_base_name = "%s.txt" % self.name + else: + if self.rev: + self._cached_base_name = "%s-%s.txt" % (self.canonical_name(), self.rev) + else: + self._cached_base_name = "%s.txt" % (self.canonical_name(), ) + return self._cached_base_name + + +def get_file_name(self): + if not hasattr(self, '_cached_file_name'): + self._cached_file_name = os.path.join(self.get_file_path(), self.get_base_name()) + return self._cached_file_name + +def get_state_slug(self, state_type=None): + """Get state of type, or default if not specified, returning + the slug of the state or None. This frees the caller of having + to check against None before accessing the slug for a + comparison.""" + s = self.get_state(state_type) + if s: + return s.slug + else: + return None + +def get_state(self, state_type=None): + """Get state of type, or default state for document type if + not specified. Uses a local cache to speed multiple state + reads up.""" + if self.pk == None: # states is many-to-many so not in database implies no state + return None + + if state_type == None: + state_type = self.type_id + + if not hasattr(self, "state_cache") or self.state_cache == None: + self.state_cache = {} + for s in self.states.all(): + self.state_cache[s.type_id] = s + + return self.state_cache.get(state_type, None) + +def canonical_name(self): + if not hasattr(self, '_canonical_name'): + name = self.name + if self.type_id == "draft" and self.get_state_slug() == "rfc": + a = self.docalias_set.filter(name__startswith="rfc").first() + if a: + name = a.name + elif self.type_id == "charter": + from ietf.doc.utils_charter import charter_name_for_group # Imported locally to avoid circular imports + try: + name = charter_name_for_group(self.chartered_group) + except ObjectDoesNotExist: + pass + self._canonical_name = name + return self._canonical_name + +def move_related_objects(source, target, file, verbose=False): + '''Find all related objects and migrate''' + related_objects = [ f for f in source._meta.get_fields() + if (f.one_to_many or f.one_to_one) + and f.auto_created and not f.concrete ] + for related_object in related_objects: + accessor = related_object.get_accessor_name() + field_name = related_object.field.name + try: + queryset = getattr(source, accessor).all() + if verbose: + print("Merging {}:{}".format(accessor,queryset.count()),file=file) + kwargs = { field_name:target } + queryset.update(**kwargs) + except Exception as e: + print(str(e)) + +def fix_exturl(d): + filename = d.get_file_name() + new = filename.replace('_', '-') + if os.path.exists(filename): + os.rename(filename, new) + elif not os.path.exists(new): + print(" ** Neither old (%s) or new (%s) filename found" % (filename, new)) + d.external_url = d.external_url.replace('_', '-') + +def forwards(apps, schema_editor): + global Document, DocHistory, DocAlias + Document = apps.get_model('doc', 'Document') + DocHistory = apps.get_model('doc', 'DocHistory') + DocAlias = apps.get_model('doc', 'DocAlias') + # + Document.get_file_name = get_file_name + Document.get_base_name = get_base_name + Document.get_file_path = get_file_path + Document.get_state_slug = get_state_slug + Document.get_state = get_state + Document.canonical_name = canonical_name + # + DocHistory.get_file_name = get_file_name + DocHistory.get_base_name = get_base_name + DocHistory.get_file_path = get_file_path + DocHistory.get_state_slug = get_state_slug + DocHistory.get_state = get_state + DocHistory.canonical_name = canonical_name + + + print("") + for doc in Document.objects.filter(name__contains='_').filter(name__startswith='slides'): + for hdoc in DocHistory.objects.filter(name=doc.name): + hdoc.name = hdoc.name.replace('_', '-') + fix_exturl(hdoc) + hdoc.save() + old_doc = copy.deepcopy(doc) + doc.name = doc.name.replace('_', '-') + fix_exturl(doc) + doc.save() + for old_alias in old_doc.docalias_set.all(): + aname = old_alias.name.replace('_', '-') + print("New alias %s" % aname) + alias = DocAlias.objects.create(name=aname, document=doc) + move_related_objects(old_alias, alias, sys.stdout, verbose=True) + old_alias.delete() + move_related_objects(old_doc, doc, sys.stdout, verbose=False) + old_doc.delete() + +def backwards(apps, schema_editor): + pass + +class Migration(migrations.Migration): + + dependencies = [ + ('meeting', '0055_old_id_cutoffs'), + ] + + operations = [ + migrations.RunPython(forwards, backwards), + ]