1 | #!/usr/bin/env python |
---|
2 | # -*- coding: utf-8 -*- |
---|
3 | |
---|
4 | import warnings |
---|
5 | from decorator import decorator |
---|
6 | from pkg_resources import EntryPoint |
---|
7 | |
---|
8 | from sqlalchemy import create_engine |
---|
9 | |
---|
10 | from migrate.versioning import exceptions |
---|
11 | from migrate.versioning.util.keyedinstance import KeyedInstance |
---|
12 | from migrate.versioning.util.importpath import import_path |
---|
13 | |
---|
14 | |
---|
15 | def load_model(dotted_name): |
---|
16 | """Import module and use module-level variable". |
---|
17 | |
---|
18 | :param dotted_name: path to model in form of string: ``some.python.module:Class`` |
---|
19 | |
---|
20 | .. versionchanged:: 0.5.4 |
---|
21 | |
---|
22 | """ |
---|
23 | if isinstance(dotted_name, basestring): |
---|
24 | if ':' not in dotted_name: |
---|
25 | # backwards compatibility |
---|
26 | warnings.warn('model should be in form of module.model:User ' |
---|
27 | 'and not module.model.User', DeprecationWarning) |
---|
28 | dotted_name = ':'.join(dotted_name.rsplit('.', 1)) |
---|
29 | return EntryPoint.parse('x=%s' % dotted_name).load(False) |
---|
30 | else: |
---|
31 | # Assume it's already loaded. |
---|
32 | return dotted_name |
---|
33 | |
---|
34 | def asbool(obj): |
---|
35 | """Do everything to use object as bool""" |
---|
36 | if isinstance(obj, (str, unicode)): |
---|
37 | obj = obj.strip().lower() |
---|
38 | if obj in ['true', 'yes', 'on', 'y', 't', '1']: |
---|
39 | return True |
---|
40 | elif obj in ['false', 'no', 'off', 'n', 'f', '0']: |
---|
41 | return False |
---|
42 | else: |
---|
43 | raise ValueError("String is not true/false: %r" % obj) |
---|
44 | if obj in (True, False): |
---|
45 | return bool(obj) |
---|
46 | else: |
---|
47 | raise ValueError("String is not true/false: %r" % obj) |
---|
48 | |
---|
49 | def guess_obj_type(obj): |
---|
50 | """Do everything to guess object type from string |
---|
51 | |
---|
52 | Tries to convert to `int`, `bool` and finally returns if not succeded. |
---|
53 | |
---|
54 | .. versionadded: 0.5.4 |
---|
55 | """ |
---|
56 | |
---|
57 | result = None |
---|
58 | |
---|
59 | try: |
---|
60 | result = int(obj) |
---|
61 | except: |
---|
62 | pass |
---|
63 | |
---|
64 | if result is None: |
---|
65 | try: |
---|
66 | result = asbool(obj) |
---|
67 | except: |
---|
68 | pass |
---|
69 | |
---|
70 | if result is not None: |
---|
71 | return result |
---|
72 | else: |
---|
73 | return obj |
---|
74 | |
---|
75 | @decorator |
---|
76 | def catch_known_errors(f, *a, **kw): |
---|
77 | """Decorator that catches known api errors |
---|
78 | |
---|
79 | .. versionadded: 0.5.4 |
---|
80 | """ |
---|
81 | |
---|
82 | try: |
---|
83 | f(*a, **kw) |
---|
84 | except exceptions.PathFoundError, e: |
---|
85 | raise exceptions.KnownError("The path %s already exists" % e.args[0]) |
---|
86 | |
---|
87 | def construct_engine(url, **opts): |
---|
88 | """.. versionadded:: 0.5.4 |
---|
89 | |
---|
90 | Constructs and returns SQLAlchemy engine. |
---|
91 | |
---|
92 | Currently, there are 2 ways to pass create_engine options to :mod:`migrate.versioning.api` functions: |
---|
93 | |
---|
94 | :param engine_dict: python dictionary of options to pass to `create_engine` |
---|
95 | :param engine_arg_*: keyword parameters to pass to `create_engine` (evaluated with :func:`migrate.versioning.util.guess_obj_type`) |
---|
96 | |
---|
97 | .. note:: |
---|
98 | |
---|
99 | keyword parameters override ``engine_dict`` values. |
---|
100 | |
---|
101 | """ |
---|
102 | |
---|
103 | # get options for create_engine |
---|
104 | if opts.get('engine_dict') and isinstance(opts['engine_dict'], dict): |
---|
105 | kwargs = opts['engine_dict'] |
---|
106 | else: |
---|
107 | kwargs = dict() |
---|
108 | |
---|
109 | # DEPRECATED: handle echo the old way |
---|
110 | echo = asbool(opts.get('echo', False)) |
---|
111 | if echo: |
---|
112 | warnings.warn('echo=True parameter is deprecated, pass ' |
---|
113 | 'engine_arg_echo=True or engine_dict={"echo": True}', |
---|
114 | DeprecationWarning) |
---|
115 | kwargs['echo'] = echo |
---|
116 | |
---|
117 | # parse keyword arguments |
---|
118 | for key, value in opts.iteritems(): |
---|
119 | if key.startswith('engine_arg_'): |
---|
120 | kwargs[key[11:]] = guess_obj_type(value) |
---|
121 | |
---|
122 | return create_engine(url, **kwargs) |
---|