Completed
Push — master ( b244b2...c54284 )
by Roy
59s
created

pyspider.database._connect_database()   F

Complexity

Conditions 33

Size

Total Lines 108

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 33
dl 0
loc 108
rs 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like pyspider.database._connect_database() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
#!/usr/bin/env python
2
# -*- encoding: utf-8 -*-
3
# vim: set et sw=4 ts=4 sts=4 ff=unix fenc=utf8:
4
# Author: Binux<[email protected]>
5
#         http://binux.me
6
# Created on 2014-10-08 15:04:08
7
8
try:
9
    from urllib import parse as urlparse
10
except ImportError:
11
    import urlparse
12
13
14
def connect_database(url):
15
    """
16
    create database object by url
17
18
    mysql:
19
        mysql+type://user:passwd@host:port/database
20
    sqlite:
21
        # relative path
22
        sqlite+type:///path/to/database.db
23
        # absolute path
24
        sqlite+type:////path/to/database.db
25
        # memory database
26
        sqlite+type://
27
    mongodb:
28
        mongodb+type://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
29
        more: http://docs.mongodb.org/manual/reference/connection-string/
30
    sqlalchemy:
31
        sqlalchemy+postgresql+type://user:passwd@host:port/database
32
        sqlalchemy+mysql+mysqlconnector+type://user:passwd@host:port/database
33
        more: http://docs.sqlalchemy.org/en/rel_0_9/core/engines.html
34
    redis:
35
        redis+taskdb://host:port/db
36
    local:
37
        local+projectdb://filepath,filepath
38
39
    type:
40
        taskdb
41
        projectdb
42
        resultdb
43
44
    """
45
    db = _connect_database(url)
46
    db.copy = lambda: _connect_database(url)
47
    return db
48
49
50
def _connect_database(url):  # NOQA
51
    parsed = urlparse.urlparse(url)
52
53
    scheme = parsed.scheme.split('+')
54
    if len(scheme) == 1:
55
        raise Exception('wrong scheme format: %s' % parsed.scheme)
56
    else:
57
        engine, dbtype = scheme[0], scheme[-1]
58
        other_scheme = "+".join(scheme[1:-1])
59
60
    if dbtype not in ('taskdb', 'projectdb', 'resultdb'):
61
        raise LookupError('unknown database type: %s, '
62
                          'type should be one of ["taskdb", "projectdb", "resultdb"]', dbtype)
63
64
    if engine == 'mysql':
65
        parames = {}
66
        if parsed.username:
67
            parames['user'] = parsed.username
68
        if parsed.password:
69
            parames['passwd'] = parsed.password
70
        if parsed.hostname:
71
            parames['host'] = parsed.hostname
72
        if parsed.port:
73
            parames['port'] = parsed.port
74
        if parsed.path.strip('/'):
75
            parames['database'] = parsed.path.strip('/')
76
77
        if dbtype == 'taskdb':
78
            from .mysql.taskdb import TaskDB
79
            return TaskDB(**parames)
80
        elif dbtype == 'projectdb':
81
            from .mysql.projectdb import ProjectDB
82
            return ProjectDB(**parames)
83
        elif dbtype == 'resultdb':
84
            from .mysql.resultdb import ResultDB
85
            return ResultDB(**parames)
86
        else:
87
            raise LookupError
88
    elif engine == 'sqlite':
89
        if parsed.path.startswith('//'):
90
            path = '/' + parsed.path.strip('/')
91
        elif parsed.path.startswith('/'):
92
            path = './' + parsed.path.strip('/')
93
        elif not parsed.path:
94
            path = ':memory:'
95
        else:
96
            raise Exception('error path: %s' % parsed.path)
97
98
        if dbtype == 'taskdb':
99
            from .sqlite.taskdb import TaskDB
100
            return TaskDB(path)
101
        elif dbtype == 'projectdb':
102
            from .sqlite.projectdb import ProjectDB
103
            return ProjectDB(path)
104
        elif dbtype == 'resultdb':
105
            from .sqlite.resultdb import ResultDB
106
            return ResultDB(path)
107
        else:
108
            raise LookupError
109
    elif engine == 'mongodb':
110
        url = url.replace(parsed.scheme, 'mongodb')
111
        parames = {}
112
        if parsed.path.strip('/'):
113
            parames['database'] = parsed.path.strip('/')
114
115
        if dbtype == 'taskdb':
116
            from .mongodb.taskdb import TaskDB
117
            return TaskDB(url, **parames)
118
        elif dbtype == 'projectdb':
119
            from .mongodb.projectdb import ProjectDB
120
            return ProjectDB(url, **parames)
121
        elif dbtype == 'resultdb':
122
            from .mongodb.resultdb import ResultDB
123
            return ResultDB(url, **parames)
124
        else:
125
            raise LookupError
126
    elif engine == 'sqlalchemy':
127
        if not other_scheme:
128
            raise Exception('wrong scheme format: %s' % parsed.scheme)
129
        url = url.replace(parsed.scheme, other_scheme)
130
131
        if dbtype == 'taskdb':
132
            from .sqlalchemy.taskdb import TaskDB
133
            return TaskDB(url)
134
        elif dbtype == 'projectdb':
135
            from .sqlalchemy.projectdb import ProjectDB
136
            return ProjectDB(url)
137
        elif dbtype == 'resultdb':
138
            from .sqlalchemy.resultdb import ResultDB
139
            return ResultDB(url)
140
        else:
141
            raise LookupError
142
    elif engine == 'redis':
143
        if dbtype == 'taskdb':
144
            from .redis.taskdb import TaskDB
145
            return TaskDB(parsed.hostname, parsed.port,
146
                          int(parsed.path.strip('/') or 0))
147
        else:
148
            raise LookupError('not supported dbtype: %s', dbtype)
149
    elif engine == 'local':
150
        scripts = url.split('//', 1)[1].split(',')
151
        if dbtype == 'projectdb':
152
            from .local.projectdb import ProjectDB
153
            return ProjectDB(scripts)
154
        else:
155
            raise LookupError('not supported dbtype: %s', dbtype)
156
    else:
157
        raise Exception('unknown engine: %s' % engine)
158