getting file size for all dict files to be downloaded. coming to be 400mb or so.
[worddb.git] / libs / dmigrations / migration_state.py
blob66c0ae0682d5f6c433add355e54501b5533fce97
1 from django.db import connection
2 from exceptions import *
3 import re
5 def _execute(*sql):
6 cursor = connection.cursor()
7 cursor.execute(*sql)
8 return cursor
10 def _execute_in_transaction(*sql):
11 cursor = connection.cursor()
12 cursor.execute("BEGIN")
13 cursor.execute(*sql)
14 cursor.execute("COMMIT")
16 def table_present(table_name):
17 cursor = _execute("SHOW TABLES LIKE %s", [table_name])
18 return bool(cursor.fetchone())
20 def _up(migrations):
21 return [(m, 'up') for m in migrations]
23 def _down(migrations):
24 return [(m, 'down') for m in migrations]
26 class MigrationState(object):
28 def __init__(self, dev=None, migration_db=None):
29 self.migration_db = migration_db
30 self.dev = dev
32 def migration_table_present(self):
33 return table_present('dmigrations')
35 def log(self, action, migration_name, status='success'):
36 from migration_log import log_action
37 log_action(action, migration_name, status)
39 def applied_but_not_in_db(self):
40 migrations_in_db = set(self.migration_db.list())
41 applied_migrations = [
42 m[0] for m in _execute(
43 "SELECT migration FROM dmigrations"
44 ).fetchall()
46 return self.migration_db.sort_migrations(
47 [m for m in applied_migrations if m not in migrations_in_db]
50 def apply(self, name):
51 try:
52 migration = self.migration_db.load_migration_object(name)
53 migration.up()
54 self.mark_as_applied(name, log=False)
55 self.log('apply', name)
56 except Exception, e:
57 self.log('apply', name, str(e))
58 raise
60 def unapply(self, name):
61 try:
62 migration = self.migration_db.load_migration_object(name)
63 migration.down()
64 self.mark_as_unapplied(name, log=False)
65 self.log('unapply', name)
66 except Exception, e:
67 self.log('unapply', name, str(e))
68 raise
70 def mark_as_applied(self, name, log=True):
71 if not self.is_applied(name):
72 _execute_in_transaction(
73 "INSERT INTO dmigrations (migration) VALUES (%s)", [name]
75 if log:
76 self.log('mark_as_applied', name)
78 def mark_as_unapplied(self, name, log=True):
79 if self.is_applied(name):
80 _execute_in_transaction(
81 "DELETE FROM dmigrations WHERE migration = %s", [name]
83 if log:
84 self.log('mark_as_unapplied', name)
86 def is_applied(self, name):
87 cursor = _execute(
88 "SELECT * FROM dmigrations WHERE migration = %s", [name]
90 return bool(cursor.fetchone())
92 def all_migrations_applied(self):
93 cursor = _execute("SELECT migration FROM dmigrations")
94 return self.migration_db.sort_migrations(
95 [row[0] for row in cursor.fetchall()]
98 def create_migration_table(self):
99 create_new = """
100 CREATE TABLE `dmigrations` (
101 `id` int(11) NOT NULL auto_increment,
102 `migration` VARCHAR(255) NOT NULL,
103 PRIMARY KEY (`id`)
104 ) ENGINE=InnoDB DEFAULT CHARSET=utf8
106 _execute_in_transaction(create_new)
108 def init(self):
109 "Create the dmigration table, if necessary"
110 if not self.migration_table_present():
111 self.create_migration_table()
112 from migration_log import init as log_init
113 log_init()
115 def resolve_name(self, name):
117 Resolve user-friendly migration name to real full migration name.
118 So both "5" and "005_foo" become "005_foo.py" etc.
120 Raises exception if ambiguous, returns None if not found.
122 name = str(name)
123 if re.search('^\d+$', name):
124 name = self.migration_db.find_unique_migration_by_number(
125 int(name)
127 return name
129 def force_resolve_name(self, name):
131 Resolve name or raise an exception if not possible.
133 Raises exception if ambiguous or not found.
135 resolved_name = self.resolve_name(name)
136 if resolved_name not in self.migration_db.list():
137 raise NoSuchMigrationError(name)
138 return resolved_name
140 def list_considering_dev(self):
142 Return list of migrations considering value of dev flag.
144 return [
145 m for m in self.migration_db.list()
146 if self.dev or not self.migration_db.is_dev_migration(m)
149 def plan_to(self, point):
151 Point can be a migration name or a number.
152 Number can resolve to an unique migration name,
153 or to a point between migrations,
154 but it cannot resolve to an ambiguous migration.
156 Return plan to migrate to such point.
158 migrations = self.list_considering_dev()
159 point = str(point)
160 if point in migrations:
161 i = migrations.index(point) + 1
162 elif re.search(r'^\d+$', point):
163 point = int(point)
164 # NOTE: It only checks that the point is not a duplicate
165 self.migration_db.find_unique_migration_by_number(point)
166 i = 0
167 while i < len(migrations) and \
168 self.migration_db.migration_number(migrations[i]) <= point:
169 i += 1
170 else:
171 raise NoSuchMigrationError(point)
173 return _down(
174 self.applied_only(reversed(migrations[i:]))
175 ) + _up(
176 self.unapplied_only(migrations[:i])
179 def applied_only(self, migrations):
180 return [m for m in migrations if self.is_applied(m)]
182 def unapplied_only(self, migrations):
183 return [m for m in migrations if not self.is_applied(m)]
185 def plan(self, action, *args):
186 if action in ['all', 'up', 'down'] and len(args) > 0:
187 raise Exception(u"Too many arguments")
189 if action in ['upto', 'downto', 'to'] and len(args) != 1:
190 raise Exception(u"Action %s requires exactly 1 argument" % action)
192 if action == 'apply':
193 return _up(self.unapplied_only(
194 [self.force_resolve_name(arg) for arg in args]
197 if action == 'unapply':
198 return _down(self.applied_only(
199 [self.force_resolve_name(arg) for arg in args]
202 if action == 'all':
203 return _up(self.unapplied_only(self.list_considering_dev()))
205 if action == 'up':
206 return _up(self.unapplied_only(self.list_considering_dev()))[:1]
208 if action == 'down':
209 return _down(reversed(
210 self.applied_only(self.list_considering_dev())
211 ))[:1]
213 if action == 'to':
214 return self.plan_to(*args)
216 if action == 'downto':
217 return [(m,a) for (m,a) in self.plan_to(*args) if a == 'down']
219 if action == 'upto':
220 return [(m,a) for (m,a) in self.plan_to(*args) if a == 'up']
222 raise Exception(
223 u"Unknown action %s" % " ".join([action] + list(args))