Mercurial > kallithea
comparison rhodecode/lib/dbmigrate/migrate/versioning/util/__init__.py @ 833:9753e0907827 beta
added dbmigrate package, added model changes
moved out upgrade db command to that package
author | Marcin Kuzminski <marcin@python-works.com> |
---|---|
date | Sat, 11 Dec 2010 01:54:12 +0100 |
parents | |
children | 08d2dcd71666 |
comparison
equal
deleted
inserted
replaced
832:634596f81cfd | 833:9753e0907827 |
---|---|
1 #!/usr/bin/env python | |
2 # -*- coding: utf-8 -*- | |
3 """.. currentmodule:: migrate.versioning.util""" | |
4 | |
5 import warnings | |
6 import logging | |
7 from decorator import decorator | |
8 from pkg_resources import EntryPoint | |
9 | |
10 from sqlalchemy import create_engine | |
11 from sqlalchemy.engine import Engine | |
12 from sqlalchemy.pool import StaticPool | |
13 | |
14 from migrate import exceptions | |
15 from migrate.versioning.util.keyedinstance import KeyedInstance | |
16 from migrate.versioning.util.importpath import import_path | |
17 | |
18 | |
19 log = logging.getLogger(__name__) | |
20 | |
21 def load_model(dotted_name): | |
22 """Import module and use module-level variable". | |
23 | |
24 :param dotted_name: path to model in form of string: ``some.python.module:Class`` | |
25 | |
26 .. versionchanged:: 0.5.4 | |
27 | |
28 """ | |
29 if isinstance(dotted_name, basestring): | |
30 if ':' not in dotted_name: | |
31 # backwards compatibility | |
32 warnings.warn('model should be in form of module.model:User ' | |
33 'and not module.model.User', exceptions.MigrateDeprecationWarning) | |
34 dotted_name = ':'.join(dotted_name.rsplit('.', 1)) | |
35 return EntryPoint.parse('x=%s' % dotted_name).load(False) | |
36 else: | |
37 # Assume it's already loaded. | |
38 return dotted_name | |
39 | |
40 def asbool(obj): | |
41 """Do everything to use object as bool""" | |
42 if isinstance(obj, basestring): | |
43 obj = obj.strip().lower() | |
44 if obj in ['true', 'yes', 'on', 'y', 't', '1']: | |
45 return True | |
46 elif obj in ['false', 'no', 'off', 'n', 'f', '0']: | |
47 return False | |
48 else: | |
49 raise ValueError("String is not true/false: %r" % obj) | |
50 if obj in (True, False): | |
51 return bool(obj) | |
52 else: | |
53 raise ValueError("String is not true/false: %r" % obj) | |
54 | |
55 def guess_obj_type(obj): | |
56 """Do everything to guess object type from string | |
57 | |
58 Tries to convert to `int`, `bool` and finally returns if not succeded. | |
59 | |
60 .. versionadded: 0.5.4 | |
61 """ | |
62 | |
63 result = None | |
64 | |
65 try: | |
66 result = int(obj) | |
67 except: | |
68 pass | |
69 | |
70 if result is None: | |
71 try: | |
72 result = asbool(obj) | |
73 except: | |
74 pass | |
75 | |
76 if result is not None: | |
77 return result | |
78 else: | |
79 return obj | |
80 | |
81 @decorator | |
82 def catch_known_errors(f, *a, **kw): | |
83 """Decorator that catches known api errors | |
84 | |
85 .. versionadded: 0.5.4 | |
86 """ | |
87 | |
88 try: | |
89 return f(*a, **kw) | |
90 except exceptions.PathFoundError, e: | |
91 raise exceptions.KnownError("The path %s already exists" % e.args[0]) | |
92 | |
93 def construct_engine(engine, **opts): | |
94 """.. versionadded:: 0.5.4 | |
95 | |
96 Constructs and returns SQLAlchemy engine. | |
97 | |
98 Currently, there are 2 ways to pass create_engine options to :mod:`migrate.versioning.api` functions: | |
99 | |
100 :param engine: connection string or a existing engine | |
101 :param engine_dict: python dictionary of options to pass to `create_engine` | |
102 :param engine_arg_*: keyword parameters to pass to `create_engine` (evaluated with :func:`migrate.versioning.util.guess_obj_type`) | |
103 :type engine_dict: dict | |
104 :type engine: string or Engine instance | |
105 :type engine_arg_*: string | |
106 :returns: SQLAlchemy Engine | |
107 | |
108 .. note:: | |
109 | |
110 keyword parameters override ``engine_dict`` values. | |
111 | |
112 """ | |
113 if isinstance(engine, Engine): | |
114 return engine | |
115 elif not isinstance(engine, basestring): | |
116 raise ValueError("you need to pass either an existing engine or a database uri") | |
117 | |
118 # get options for create_engine | |
119 if opts.get('engine_dict') and isinstance(opts['engine_dict'], dict): | |
120 kwargs = opts['engine_dict'] | |
121 else: | |
122 kwargs = dict() | |
123 | |
124 # DEPRECATED: handle echo the old way | |
125 echo = asbool(opts.get('echo', False)) | |
126 if echo: | |
127 warnings.warn('echo=True parameter is deprecated, pass ' | |
128 'engine_arg_echo=True or engine_dict={"echo": True}', | |
129 exceptions.MigrateDeprecationWarning) | |
130 kwargs['echo'] = echo | |
131 | |
132 # parse keyword arguments | |
133 for key, value in opts.iteritems(): | |
134 if key.startswith('engine_arg_'): | |
135 kwargs[key[11:]] = guess_obj_type(value) | |
136 | |
137 log.debug('Constructing engine') | |
138 # TODO: return create_engine(engine, poolclass=StaticPool, **kwargs) | |
139 # seems like 0.5.x branch does not work with engine.dispose and staticpool | |
140 return create_engine(engine, **kwargs) | |
141 | |
142 @decorator | |
143 def with_engine(f, *a, **kw): | |
144 """Decorator for :mod:`migrate.versioning.api` functions | |
145 to safely close resources after function usage. | |
146 | |
147 Passes engine parameters to :func:`construct_engine` and | |
148 resulting parameter is available as kw['engine']. | |
149 | |
150 Engine is disposed after wrapped function is executed. | |
151 | |
152 .. versionadded: 0.6.0 | |
153 """ | |
154 url = a[0] | |
155 engine = construct_engine(url, **kw) | |
156 | |
157 try: | |
158 kw['engine'] = engine | |
159 return f(*a, **kw) | |
160 finally: | |
161 if isinstance(engine, Engine): | |
162 log.debug('Disposing SQLAlchemy engine %s', engine) | |
163 engine.dispose() | |
164 | |
165 | |
166 class Memoize: | |
167 """Memoize(fn) - an instance which acts like fn but memoizes its arguments | |
168 Will only work on functions with non-mutable arguments | |
169 | |
170 ActiveState Code 52201 | |
171 """ | |
172 def __init__(self, fn): | |
173 self.fn = fn | |
174 self.memo = {} | |
175 | |
176 def __call__(self, *args): | |
177 if not self.memo.has_key(args): | |
178 self.memo[args] = self.fn(*args) | |
179 return self.memo[args] |