Skip to content

Commit 6eda346

Browse files
committed
Added a data migration to fix recent slides names containing underscores.
- Legacy-Id: 13997
1 parent 0fc216b commit 6eda346

1 file changed

Lines changed: 201 additions & 0 deletions

File tree

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.10.7 on 2017-07-23 08:27
3+
from __future__ import unicode_literals, print_function
4+
5+
import os
6+
import copy
7+
import sys
8+
9+
from django.conf import settings
10+
from django.db import migrations
11+
from django.core.exceptions import ObjectDoesNotExist
12+
13+
import debug # pyflakes:ignore
14+
15+
def get_materials_path(meeting):
16+
return os.path.join(settings.AGENDA_PATH,meeting.number)
17+
18+
def get_file_path(self):
19+
if not hasattr(self, '_cached_file_path'):
20+
if self.type_id == "draft":
21+
if self.is_dochistory():
22+
self._cached_file_path = settings.INTERNET_ALL_DRAFTS_ARCHIVE_DIR
23+
else:
24+
if self.get_state_slug() == "rfc":
25+
self._cached_file_path = settings.RFC_PATH
26+
else:
27+
draft_state = self.get_state('draft')
28+
if draft_state and draft_state.slug == 'active':
29+
self._cached_file_path = settings.INTERNET_DRAFT_PATH
30+
else:
31+
self._cached_file_path = settings.INTERNET_ALL_DRAFTS_ARCHIVE_DIR
32+
elif self.type_id in ("agenda", "minutes", "slides", "bluesheets"):
33+
doc = self.doc if isinstance(self, DocHistory) else self
34+
if doc.session_set.exists():
35+
meeting = doc.session_set.first().meeting
36+
self._cached_file_path = os.path.join(get_materials_path(meeting), self.type_id) + "/"
37+
else:
38+
self._cached_file_path = ""
39+
elif self.type_id == "charter":
40+
self._cached_file_path = settings.CHARTER_PATH
41+
elif self.type_id == "conflrev":
42+
self._cached_file_path = settings.CONFLICT_REVIEW_PATH
43+
elif self.type_id == "statchg":
44+
self._cached_file_path = settings.STATUS_CHANGE_PATH
45+
else:
46+
self._cached_file_path = settings.DOCUMENT_PATH_PATTERN.format(doc=self)
47+
return self._cached_file_path
48+
49+
def get_base_name(self):
50+
if not hasattr(self, '_cached_base_name'):
51+
if self.type_id == 'draft':
52+
if self.is_dochistory():
53+
self._cached_base_name = "%s-%s.txt" % (self.doc.name, self.rev)
54+
else:
55+
if self.get_state_slug() == 'rfc':
56+
self._cached_base_name = "%s.txt" % self.canonical_name()
57+
else:
58+
self._cached_base_name = "%s-%s.txt" % (self.name, self.rev)
59+
elif self.type_id in ["slides", "agenda", "minutes", "bluesheets", ]:
60+
if self.external_url:
61+
# we need to remove the extension for the globbing below to work
62+
self._cached_base_name = self.external_url
63+
else:
64+
self._cached_base_name = "%s.txt" % self.canonical_name() # meeting materials are unversioned at the moment
65+
elif self.type_id == 'review':
66+
self._cached_base_name = "%s.txt" % self.name
67+
else:
68+
if self.rev:
69+
self._cached_base_name = "%s-%s.txt" % (self.canonical_name(), self.rev)
70+
else:
71+
self._cached_base_name = "%s.txt" % (self.canonical_name(), )
72+
return self._cached_base_name
73+
74+
75+
def get_file_name(self):
76+
if not hasattr(self, '_cached_file_name'):
77+
self._cached_file_name = os.path.join(self.get_file_path(), self.get_base_name())
78+
return self._cached_file_name
79+
80+
def get_state_slug(self, state_type=None):
81+
"""Get state of type, or default if not specified, returning
82+
the slug of the state or None. This frees the caller of having
83+
to check against None before accessing the slug for a
84+
comparison."""
85+
s = self.get_state(state_type)
86+
if s:
87+
return s.slug
88+
else:
89+
return None
90+
91+
def get_state(self, state_type=None):
92+
"""Get state of type, or default state for document type if
93+
not specified. Uses a local cache to speed multiple state
94+
reads up."""
95+
if self.pk == None: # states is many-to-many so not in database implies no state
96+
return None
97+
98+
if state_type == None:
99+
state_type = self.type_id
100+
101+
if not hasattr(self, "state_cache") or self.state_cache == None:
102+
self.state_cache = {}
103+
for s in self.states.all():
104+
self.state_cache[s.type_id] = s
105+
106+
return self.state_cache.get(state_type, None)
107+
108+
def canonical_name(self):
109+
if not hasattr(self, '_canonical_name'):
110+
name = self.name
111+
if self.type_id == "draft" and self.get_state_slug() == "rfc":
112+
a = self.docalias_set.filter(name__startswith="rfc").first()
113+
if a:
114+
name = a.name
115+
elif self.type_id == "charter":
116+
from ietf.doc.utils_charter import charter_name_for_group # Imported locally to avoid circular imports
117+
try:
118+
name = charter_name_for_group(self.chartered_group)
119+
except ObjectDoesNotExist:
120+
pass
121+
self._canonical_name = name
122+
return self._canonical_name
123+
124+
def move_related_objects(source, target, file, verbose=False):
125+
'''Find all related objects and migrate'''
126+
related_objects = [ f for f in source._meta.get_fields()
127+
if (f.one_to_many or f.one_to_one)
128+
and f.auto_created and not f.concrete ]
129+
for related_object in related_objects:
130+
accessor = related_object.get_accessor_name()
131+
field_name = related_object.field.name
132+
try:
133+
queryset = getattr(source, accessor).all()
134+
if verbose:
135+
print("Merging {}:{}".format(accessor,queryset.count()),file=file)
136+
kwargs = { field_name:target }
137+
queryset.update(**kwargs)
138+
except Exception as e:
139+
print(str(e))
140+
141+
def fix_exturl(d):
142+
filename = d.get_file_name()
143+
new = filename.replace('_', '-')
144+
if os.path.exists(filename):
145+
os.rename(filename, new)
146+
elif not os.path.exists(new):
147+
print(" ** Neither old (%s) or new (%s) filename found" % (filename, new))
148+
d.external_url = d.external_url.replace('_', '-')
149+
150+
def forwards(apps, schema_editor):
151+
global Document, DocHistory, DocAlias
152+
Document = apps.get_model('doc', 'Document')
153+
DocHistory = apps.get_model('doc', 'DocHistory')
154+
DocAlias = apps.get_model('doc', 'DocAlias')
155+
#
156+
Document.get_file_name = get_file_name
157+
Document.get_base_name = get_base_name
158+
Document.get_file_path = get_file_path
159+
Document.get_state_slug = get_state_slug
160+
Document.get_state = get_state
161+
Document.canonical_name = canonical_name
162+
#
163+
DocHistory.get_file_name = get_file_name
164+
DocHistory.get_base_name = get_base_name
165+
DocHistory.get_file_path = get_file_path
166+
DocHistory.get_state_slug = get_state_slug
167+
DocHistory.get_state = get_state
168+
DocHistory.canonical_name = canonical_name
169+
170+
171+
print("")
172+
for doc in Document.objects.filter(name__contains='_').filter(name__startswith='slides'):
173+
for hdoc in DocHistory.objects.filter(name=doc.name):
174+
hdoc.name = hdoc.name.replace('_', '-')
175+
fix_exturl(hdoc)
176+
hdoc.save()
177+
old_doc = copy.deepcopy(doc)
178+
doc.name = doc.name.replace('_', '-')
179+
fix_exturl(doc)
180+
doc.save()
181+
for old_alias in old_doc.docalias_set.all():
182+
aname = old_alias.name.replace('_', '-')
183+
print("New alias %s" % aname)
184+
alias = DocAlias.objects.create(name=aname, document=doc)
185+
move_related_objects(old_alias, alias, sys.stdout, verbose=True)
186+
old_alias.delete()
187+
move_related_objects(old_doc, doc, sys.stdout, verbose=False)
188+
old_doc.delete()
189+
190+
def backwards(apps, schema_editor):
191+
pass
192+
193+
class Migration(migrations.Migration):
194+
195+
dependencies = [
196+
('meeting', '0055_old_id_cutoffs'),
197+
]
198+
199+
operations = [
200+
migrations.RunPython(forwards, backwards),
201+
]

0 commit comments

Comments
 (0)