| Conditions | 3 |
| Total Lines | 185 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 11 | ||
| Bugs | 0 | Features | 0 |
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:
If many parameters/temporary variables are present:
| 1 | # ~*~ coding: utf-8 ~*~ |
||
| 21 | This class holds all the SQLAlchemy classes and logic that make up |
||
| 22 | OSMAlchemy. It is contained in a separate class because it is a |
||
| 23 | template that can be modified as needed by users, e.g. by using a |
||
| 24 | different table prefix or a different declarative base. |
||
| 25 | """ |
||
| 26 | |||
| 27 | def __init__(self, base=None, prefix="osm_"): |
||
| 28 | """ Initialise the table definitions in the wrapper object |
||
| 29 | |||
| 30 | This function generates the OSM element classes as SQLAlchemy table |
||
| 31 | declaratives. If called without an argument, it uses a newly created |
||
| 32 | declarative base. |
||
| 33 | |||
| 34 | The base argument, if provided, can be either a declarative base or |
||
| 35 | a Flask-SQLAlchemy object. |
||
| 36 | """ |
||
| 37 | |||
| 38 | # Check what we got as declarative base |
||
| 39 | if base is None: |
||
| 40 | # Nothing, so create one |
||
| 41 | base = declarative_base() |
||
| 42 | elif hasattr(base, "Model"): |
||
| 43 | # Unwrap Flask-SQLAlchemy object if we got one |
||
| 44 | base = base.Model |
||
| 45 | |||
| 46 | class OSMElement(base): |
||
| 47 | """ Base class for all the conceptual OSM elements. """ |
||
| 48 | |||
| 49 | # Name of the table in the database, prefix provided by user |
||
| 50 | __tablename__ = prefix + "elements" |
||
| 51 | |||
| 52 | # The internal ID of the element, only for structural use |
||
| 53 | element_id = Column(Integer, primary_key=True) |
||
| 54 | |||
| 55 | # Track element modification for OSMAlchemy caching |
||
| 56 | osmalchemy_updated = Column(DateTime, default=datetime.datetime.now, |
||
| 57 | onupdate=datetime.datetime.now) |
||
| 58 | |||
| 59 | # The type of the element, used by SQLAlchemy for polymorphism |
||
| 60 | type = Column(String(256)) |
||
| 61 | |||
| 62 | # Tags belonging to the element |
||
| 63 | # Accessed as a dictionary like {'name': 'value', 'name2': 'value2',…} |
||
| 64 | # Uses proxying across several tables to OSMTag |
||
| 65 | tags = association_proxy(prefix+"elements_tags", "tag_value", |
||
| 66 | creator=lambda k, v: OSMElementsTags(tag_key=k, tag_value=v)) |
||
| 67 | |||
| 68 | # Metadata shared by all element types |
||
| 69 | version = Column(Integer) |
||
| 70 | changeset = Column(Integer) |
||
| 71 | user = Column(String) |
||
| 72 | uid = Column(Integer) |
||
| 73 | visible = Column(Bool) |
||
| 74 | timestamp = Column(DateTime) |
||
| 75 | |||
| 76 | # Configure polymorphism |
||
| 77 | __mapper_args__ = { |
||
| 78 | 'polymorphic_identity': prefix + 'elements', |
||
| 79 | 'polymorphic_on': type, |
||
| 80 | 'with_polymorphic': '*' |
||
| 81 | } |
||
| 82 | |||
| 83 | class OSMNode(OSMElement): |
||
| 84 | """ An OSM node element. |
||
| 85 | |||
| 86 | A node hast a latitude and longitude, which are non-optional, |
||
| 87 | and a list of zero or more tags. |
||
| 88 | """ |
||
| 89 | |||
| 90 | # Name of the table in the database, prefix provided by user |
||
| 91 | __tablename__ = prefix + "nodes" |
||
| 92 | |||
| 93 | # The internal ID of the element, only for structural use |
||
| 94 | # Synchronised with the id of the parent table OSMElement through polymorphism |
||
| 95 | element_id = Column(Integer, ForeignKey(prefix + 'elements.element_id'), |
||
| 96 | primary_key=True) |
||
| 97 | |||
| 98 | # ID of the node, not to be confused with the primary key from OSMElements |
||
| 99 | id = Column(Integer, unique=True) |
||
| 100 | |||
| 101 | # Geographical coordinates of the node |
||
| 102 | latitude = Column(Float, nullable=False) |
||
| 103 | longitude = Column(Float, nullable=False) |
||
| 104 | |||
| 105 | # Configure polymorphism with OSMElement |
||
| 106 | __mapper_args__ = { |
||
| 107 | 'polymorphic_identity': prefix + 'nodes', |
||
| 108 | } |
||
| 109 | |||
| 110 | def __init__(self, latitude=0.0, longitude=0.0, **kwargs): |
||
| 111 | """ Initialisation with two main positional arguments. |
||
| 112 | |||
| 113 | Shorthand for OSMNode(lat, lon). |
||
| 114 | """ |
||
| 115 | |||
| 116 | self.latitude = latitude |
||
| 117 | self.longitude = longitude |
||
| 118 | |||
| 119 | # Pass rest on to default constructor |
||
| 120 | OSMElement.__init__(self, **kwargs) |
||
| 121 | |||
| 122 | class OSMWaysNodes(base): |
||
| 123 | """ Secondary mapping table for ways and nodes """ |
||
| 124 | |||
| 125 | # Name of the table in the database, prefix provided by user |
||
| 126 | __tablename__ = prefix + "ways_nodes" |
||
| 127 | |||
| 128 | # Internal ID of the mapping, only for structural use |
||
| 129 | map_id = Column(Integer, primary_key=True) |
||
| 130 | |||
| 131 | # Foreign key columns for the connected way and node |
||
| 132 | way_id = Column(Integer, ForeignKey(prefix + 'ways.element_id')) |
||
| 133 | node_id = Column(Integer, ForeignKey(prefix + 'nodes.element_id')) |
||
| 134 | # Relationships for proxy access |
||
| 135 | way = relationship("OSMWay", foreign_keys=[way_id]) |
||
| 136 | node = relationship("OSMNode", foreign_keys=[node_id]) |
||
| 137 | |||
| 138 | # Index of the node in the way to maintain ordered list, structural use only |
||
| 139 | position = Column(Integer) |
||
| 140 | |||
| 141 | class OSMWay(OSMElement): |
||
| 142 | """ An OSM way element (also area). |
||
| 143 | |||
| 144 | Contains a list of two or more nodes and a list of zero or more |
||
| 145 | tags. |
||
| 146 | """ |
||
| 147 | |||
| 148 | # Name of the table in the database, prefix provided by user |
||
| 149 | __tablename__ = prefix + "ways" |
||
| 150 | |||
| 151 | # The internal ID of the element, only for structural use |
||
| 152 | # Synchronised with the id of the parent table OSMElement through polymorphism |
||
| 153 | element_id = Column(Integer, ForeignKey(prefix + 'elements.element_id'), |
||
| 154 | primary_key=True) |
||
| 155 | |||
| 156 | # ID of the way, not to be confused with the primary key from OSMElements |
||
| 157 | id = Column(Integer, unique=True) |
||
| 158 | |||
| 159 | # Relationship with all nodes in the way |
||
| 160 | # Uses association proxy and a collection class to maintain an ordered list, |
||
| 161 | # synchronised with the position field of OSMWaysNodes |
||
| 162 | _nodes = relationship('OSMWaysNodes', order_by="OSMWaysNodes.position", |
||
| 163 | collection_class=ordering_list("position")) |
||
| 164 | nodes = association_proxy("_nodes", "node", |
||
| 165 | creator=lambda _n: OSMWaysNodes(node=_n)) |
||
| 166 | |||
| 167 | # Configure polymorphism with OSMElement |
||
| 168 | __mapper_args__ = { |
||
| 169 | 'polymorphic_identity': prefix + 'ways', |
||
| 170 | } |
||
| 171 | |||
| 172 | class OSMElementsTags(base): |
||
| 173 | """ Secondary mapping table for elements and tags """ |
||
| 174 | |||
| 175 | # Name of the table in the database, prefix provided by user |
||
| 176 | __tablename__ = prefix + "elements_tags" |
||
| 177 | |||
| 178 | # Internal ID of the mapping, only for structural use |
||
| 179 | map_id = Column(Integer, primary_key=True) |
||
| 180 | |||
| 181 | # Foreign key columns for the element and tag of the mapping |
||
| 182 | element_id = Column(Integer, ForeignKey(prefix + 'elements.element_id')) |
||
| 183 | tag_id = Column(Integer, ForeignKey(prefix + 'tags.tag_id')) |
||
| 184 | |||
| 185 | # Relationship with all the tags mapped to the element |
||
| 186 | # The backref is the counter-part to the tags association proxy |
||
| 187 | # in OSMElement to form the dictionary |
||
| 188 | element = relationship("OSMElement", foreign_keys=[element_id], |
||
| 189 | backref=backref(prefix+"elements_tags", |
||
| 190 | collection_class=attribute_mapped_collection("tag_key"), |
||
| 191 | cascade="all, delete-orphan")) |
||
| 192 | |||
| 193 | # Relationship to the tag object and short-hand for its key and value |
||
| 194 | # for use in the association proxy |
||
| 195 | tag = relationship("OSMTag", foreign_keys=[tag_id]) |
||
| 196 | tag_key = association_proxy("tag", "key") |
||
| 197 | tag_value = association_proxy("tag", "value") |
||
| 198 | |||
| 199 | class OSMRelationsElements(base): |
||
| 200 | """ Secondary mapping table for relation members """ |
||
| 201 | |||
| 202 | # Name of the table in the database, prefix provided by user |
||
| 203 | __tablename__ = prefix + "relations_elements" |
||
| 204 | |||
| 205 | # Internal ID of the mapping, only for structural use |
||
| 206 | map_id = Column(Integer, primary_key=True) |
||
| 296 |