Passed
Push — master ( da4639...75155f )
by Dominik
14:07
created

_query_compiling()   C

Complexity

Conditions 7

Size

Total Lines 45

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 7
Bugs 0 Features 0
Metric Value
cc 7
c 7
b 0
f 0
dl 0
loc 45
ccs 0
cts 22
cp 0
crap 56
rs 5.5
1
# ~*~ coding: utf-8 ~*~
2
#-
3
# OSMAlchemy - OpenStreetMap to SQLAlchemy bridge
4
# Copyright (c) 2016 Dominik George <[email protected]>
5
#
6
# Permission is hereby granted, free of charge, to any person obtaining a copy
7
# of this software and associated documentation files (the "Software"), to deal
8
# in the Software without restriction, including without limitation the rights
9
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
# copies of the Software, and to permit persons to whom the Software is
11
# furnished to do so, subject to the following conditions:
12
#
13
# The above copyright notice and this permission notice shall be included in all
14
# copies or substantial portions of the Software.
15
#
16
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
# SOFTWARE.
23
#
24
# Alternatively, you are free to use OSMAlchemy under Simplified BSD, The
25
# MirOS Licence, GPL-2+, LGPL-2.1+, AGPL-3+ or the same terms as Python
26
# itself.
27
28 1
""" Trigger code for live OSMAlchemy/Overpass integration. """
29
30 1
import datetime
0 ignored issues
show
Unused Code introduced by
The import datetime seems to be unused.
Loading history...
31 1
from sqlalchemy import inspect
0 ignored issues
show
Unused Code introduced by
Unused inspect imported from sqlalchemy
Loading history...
32 1
from sqlalchemy.event import listens_for
33 1
from sqlalchemy.orm import Query
34 1
from weakref import WeakSet
0 ignored issues
show
introduced by
standard import "from weakref import WeakSet" comes before "from sqlalchemy import inspect"
Loading history...
35
36 1
from .util.db import _import_osm_xml
37 1
from .util.online import _get_elements_by_query, _where_to_tree, _trees_to_overpassql
38
39 1
def _generate_triggers(osmalchemy, maxage=60*60*24):
0 ignored issues
show
Unused Code introduced by
The argument maxage seems to be unused.
Loading history...
40
    """ Generates the triggers for online functionality.
41
42
      osmalchemy - reference to the OSMAlchemy instance to be configured
43
      maxage - maximum age of objects before they are updated online, in seconds
44
    """
45
46
    _visited_queries = WeakSet()
47
48
    @listens_for(Query, "before_compile")
49
    def _query_compiling(query):
0 ignored issues
show
Unused Code introduced by
The variable _query_compiling seems to be unused.
Loading history...
50
        # Get the session associated with the query:
51
        session = query.session
52
53
        # Skip if the session was in a trigger before
54
        # Prevents recursion in import code
55
        if hasattr(session, "_osmalchemy_in_trigger"):
56
            return
57
58
        # Prevent recursion by skipping already-seen queries
59
        if query in _visited_queries:
60
            return
61
        else:
62
            _visited_queries.add(query)
63
64
        # Check whether this query affects our model
65
        affected_models = set([c["type"] for c in query.column_descriptions])
66
        our_models = set([osmalchemy.node, osmalchemy.way,  osmalchemy.relation,
0 ignored issues
show
Coding Style introduced by
Exactly one space required after comma
Loading history...
67
                          osmalchemy.element])
68
        if affected_models.isdisjoint(our_models):
69
            # None of our models is affected
70
            return
71
72
        # Check whether this query filters elements
73
        # Online update will only run on a specified set, not all data
74
        if query.whereclause is None:
75
            # No filters
76
            return
77
78
        # Analyse where clause looking for all looked-up fields
79
        trees = {}
80
        for target in our_models.intersection(affected_models):
81
            # Build expression trees first
82
            trees[target.__name__] = _where_to_tree(query.whereclause, target)
83
84
        # Compile to OverpassQL and run query
85
        query = _trees_to_overpassql(trees)
86
        print(query)
0 ignored issues
show
Unused Code Coding Style introduced by
Unnecessary parens after u'print' keyword
Loading history...
87
        xml = _get_elements_by_query(osmalchemy._overpass, query)
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like _overpass was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
88
89
        # Import data
90
        session._osmalchemy_in_trigger = True
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like _osmalchemy_in_trigger was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
91
        _import_osm_xml(osmalchemy, session, xml)
92
        del session._osmalchemy_in_trigger
93