Skip to content

Commit

Permalink
clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
mvexel committed May 25, 2024
1 parent 809ef35 commit 654fb6f
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 67 deletions.
30 changes: 8 additions & 22 deletions src/osmdiff/augmenteddiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,21 @@

from .osm import OSMObject

from osmdiff.settings import OVERPASS_URL, DEBUG
from osmdiff.util import get_logger
from osmdiff.settings import DEFAULT_OVERPASS_URL


class AugmentedDiff(object):
base_url = OVERPASS_URL
"""
Class to represent an Augmented Diff object.
"""

base_url = DEFAULT_OVERPASS_URL
minlon = None
minlat = None
maxlon = None
maxlat = None
timestamp = None
remarks = []

def __init__(
self,
Expand Down Expand Up @@ -47,18 +51,14 @@ def __init__(

def get_state(self):
"""Get the current state from the OSM API"""
logger = get_logger()
state_url = urljoin(self.base_url, "augmented_diff_status")
if DEBUG:
logger.log(10, f"getting state from {state_url}")
response = requests.get(state_url, timeout=5)
if response.status_code != 200:
return False
self.sequence_number = int(response.text)
return True

def _build_adiff_url(self):
logger = get_logger()
url = "{base}/augmented_diff?id={sequence_number}".format(
base=self.base_url, sequence_number=self.sequence_number
)
Expand All @@ -69,18 +69,13 @@ def _build_adiff_url(self):
maxlon=self.maxlon,
maxlat=self.maxlat,
)
if DEBUG:
logger.log(10, url)
return url

def _build_action(self, elem):
logger = get_logger()
if elem.attrib["type"] == "create":
for child in elem:
e = OSMObject.from_xml(child)
self.__getattribute__("create").append(e)
if DEBUG:
logger.log(10, elem.attrib["type"], e)
else:
new = elem.find("new")
old = elem.find("old")
Expand All @@ -90,18 +85,14 @@ def _build_action(self, elem):
osm_obj_old = OSMObject.from_xml(child)
for child in new:
osm_obj_new = OSMObject.from_xml(child)
if DEBUG:
logger.log(
10, f"{elem.attrib['type']}: old {osm_obj_old} , new {osm_obj_new}"
)
self.__getattribute__(elem.attrib["type"]).append(
{"old": osm_obj_old, "new": osm_obj_new}
)

def _parse_stream(self, stream):
for event, elem in cElementTree.iterparse(stream):
if elem.tag == "remark":
raise Exception("Augmented Diff API returned an error:", elem.text)
self.remarks.append(elem.text)
if elem.tag == "meta":
timestamp = dateutil.parser.parse(elem.attrib.get("osm_base"))
self.timestamp = timestamp
Expand All @@ -112,21 +103,16 @@ def retrieve(self, clear_cache=False, timeout=30) -> int:
"""
Retrieve the Augmented diff corresponding to the sequence_number.
"""
logger = get_logger()
if not self.sequence_number:
raise Exception("invalid sequence number")
if clear_cache:
self.create, self.modify, self.delete = ([], [], [])
url = self._build_adiff_url()
if DEBUG:
logger.log(10, "retrieving...")
try:
r = requests.get(url, stream=True, timeout=timeout)
if r.status_code != 200:
return r.status_code
r.raw.decode_content = True
if DEBUG:
logger.log(10, "parsing...")
self._parse_stream(r.raw)
return r.status_code
except ConnectionError:
Expand Down
74 changes: 46 additions & 28 deletions src/osmdiff/osmchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,26 @@
import requests

from osmdiff.osm import OSMObject
from osmdiff.settings import REPLICATION_URL, DEBUG
from osmdiff.util import get_logger
from osmdiff.settings import DEFAULT_REPLICATION_URL


class OSMChange(object):
"""
Class to represent an OSMChange object.
:param url: URL of the OSM replication server
:type url: str
:param frequency: frequency of the replication diff
:type frequency: str
:param file: path to the XML file
:type file: str
:param sequence_number: sequence number of the diff
:type sequence_number: int
"""

def __init__(
self,
url=REPLICATION_URL,
url=DEFAULT_REPLICATION_URL,
frequency="minute",
file=None,
sequence_number=None,
Expand All @@ -29,22 +41,22 @@ def __init__(
self._frequency = frequency
self._sequence_number = sequence_number

def get_state(self):
logger = get_logger()
def get_state(self) -> bool:
"""
Get the current state from the OSM API.
"""
# FIXME this should really not return a boolean
"""Get the current state from the OSM API"""
state_url = urljoin(self.base_url, self._frequency, "state.txt")
response = requests.get(state_url, timeout=5)
if response.status_code != 200:
return False
for line in response.text.split("\n"):
if DEBUG:
logger.log(10, line)
if line.startswith("sequenceNumber"):
self._sequence_number = int(line[15:])
return True

def _build_sequence_url(self):
logger = get_logger()
def _build_sequence_url(self) -> str:
seqno = str(self._sequence_number).zfill(9)
url = urljoin(
self.base_url,
Expand All @@ -53,32 +65,29 @@ def _build_sequence_url(self):
seqno[3:6],
"{}{}".format(seqno[6:], ".osc.gz"),
)
if DEBUG:
logger.log(10, url)
return url

def _parse_xml(self, xml):
logger = get_logger()
def _parse_xml(self, xml) -> None:
for event, elem in xml:
if elem.tag in ("create", "modify", "delete"):
self._build_action(elem)
if DEBUG:
logger.log(10, elem.tag)

def _build_action(self, elem):
logger = get_logger()
def _build_action(self, elem) -> None:
for thing in elem:
o = OSMObject.from_xml(thing)
self.__getattribute__(elem.tag).append(o)
if DEBUG:
logger.log(10, o)
logger.log(10, o.attribs)
logger.log(10, o.tags)
logger.log(10, o.bounds)

def retrieve(self, clear_cache=False, timeout=30) -> int:
"""
Retrieve the OSM diff corresponding to the OSMChange sequence_number.
:param clear_cache: clear the cache
:type clear_cache: bool
:param timeout: request timeout
:type timeout: int
:return: HTTP status code
:rtype: int
"""
if not self._sequence_number:
raise Exception("invalid sequence number")
Expand All @@ -97,7 +106,7 @@ def retrieve(self, clear_cache=False, timeout=30) -> int:
return 0

@classmethod
def from_xml(cls, xml):
def from_xml(cls, xml) -> "OSMChange":
"""
Initialize OSMChange object from an XML object.
Expand All @@ -107,33 +116,42 @@ def from_xml(cls, xml):
:param path: path to the XML file
:type path: str
:return: OSMChange object
:rtype: OSMChange
"""
new_osmchange_obj = cls()
new_osmchange_obj._parse_xml(xml)
return new_osmchange_obj

@classmethod
def from_xml_file(cls, path):
def from_xml_file(cls, path) -> "OSMChange":
"""
Initialize OSMChange object from an XML file.
:param path: path to the XML file
:type path: str
:return: OSMChange object
:rtype: OSMChange
"""
with open(path, "r") as fh:
xml = ElementTree.iterparse(fh, events=("start", "end"))
return cls.from_xml(xml)

def sequence_number(self):
def sequence_number(self) -> int:
"""
Get the sequence number of the OSMChange object.
"""
return self._sequence_number

def set_sequence_number(self, sn):
def set_sequence_number(self, sn) -> None:
"""
Set the sequence number of the OSMChange object.
:param sn: sequence number
:type sn: int
"""
self._sequence_number = int(sn)

sequence_number = property(sequence_number, set_sequence_number)
Expand Down
5 changes: 2 additions & 3 deletions src/osmdiff/settings.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
DEBUG = False # Set to True to enable debug output
OVERPASS_URL = "http://overpass-api.de/api" # URL for Overpass API
REPLICATION_URL = (
DEFAULT_OVERPASS_URL = "http://overpass-api.de/api" # URL for Overpass API
DEFAULT_REPLICATION_URL = (
"https://planet.openstreetmap.org/replication" # URL for OSM replication API
)
14 changes: 0 additions & 14 deletions src/osmdiff/util.py

This file was deleted.

0 comments on commit 654fb6f

Please sign in to comment.