forked from edward/owl-map
Update
This commit is contained in:
parent
9f8ccf95f1
commit
733ca3aa8f
4 changed files with 366 additions and 231 deletions
100
matcher/utils.py
100
matcher/utils.py
|
|
@ -1,97 +1,114 @@
|
|||
from flask import current_app, request
|
||||
from itertools import islice
|
||||
import os.path
|
||||
import json
|
||||
import math
|
||||
import user_agents
|
||||
import os.path
|
||||
import re
|
||||
import typing
|
||||
from datetime import date
|
||||
from itertools import islice
|
||||
from typing import Any, cast
|
||||
|
||||
import flask
|
||||
import user_agents
|
||||
from num2words import num2words
|
||||
|
||||
metres_per_mile = 1609.344
|
||||
feet_per_metre = 3.28084
|
||||
feet_per_mile = 5280
|
||||
|
||||
T = typing.TypeVar("T")
|
||||
|
||||
def chunk(it, size):
|
||||
|
||||
def chunk(it: typing.Iterable[T], size: int) -> typing.Iterator[tuple[T, ...]]:
|
||||
"""Split an iterable into chunks of the given size."""
|
||||
it = iter(it)
|
||||
return iter(lambda: tuple(islice(it, size)), ())
|
||||
|
||||
|
||||
def flatten(l):
|
||||
return [item for sublist in l for item in sublist]
|
||||
def flatten(top_list: list[list[T]]) -> list[T]:
|
||||
"""Flatten a list."""
|
||||
return [item for sub_list in top_list for item in sub_list]
|
||||
|
||||
|
||||
def drop_start(s, start):
|
||||
def drop_start(s: str, start: str) -> str:
|
||||
"""Remove string prefix, otherwise throw an error."""
|
||||
assert s.startswith(start)
|
||||
return s[len(start) :]
|
||||
|
||||
|
||||
def remove_start(s, start):
|
||||
def remove_start(s: str, start: str) -> str:
|
||||
"""Remove a string prefix, if present."""
|
||||
return s[len(start) :] if s.startswith(start) else s
|
||||
|
||||
|
||||
def normalize_url(url):
|
||||
def normalize_url(url: str) -> str:
|
||||
"""Standardize URLs to help in comparison."""
|
||||
for start in "http://", "https://", "www.":
|
||||
url = remove_start(url, start)
|
||||
return url.rstrip("/")
|
||||
|
||||
|
||||
def contains_digit(s):
|
||||
def contains_digit(s: str) -> bool:
|
||||
"""Check if string contains a digit."""
|
||||
return any(c.isdigit() for c in s)
|
||||
|
||||
|
||||
def cache_dir():
|
||||
return current_app.config["CACHE_DIR"]
|
||||
def cache_dir() -> str:
|
||||
"""Get cache dir location."""
|
||||
d: str = flask.current_app.config["CACHE_DIR"]
|
||||
return d
|
||||
|
||||
|
||||
def cache_filename(filename):
|
||||
def cache_filename(filename: str) -> str:
|
||||
"""Get absolute path for cache file."""
|
||||
return os.path.join(cache_dir(), filename)
|
||||
|
||||
|
||||
def load_from_cache(filename):
|
||||
def load_from_cache(filename: str) -> Any:
|
||||
"""Load JSON data from cache."""
|
||||
return json.load(open(cache_filename(filename)))
|
||||
|
||||
|
||||
def get_radius(default=1000):
|
||||
arg_radius = request.args.get("radius")
|
||||
def get_radius(default: int = 1000) -> int | None:
|
||||
"""Get radius request argument with default."""
|
||||
arg_radius = flask.request.args.get("radius")
|
||||
return int(arg_radius) if arg_radius and arg_radius.isdigit() else default
|
||||
|
||||
|
||||
def get_int_arg(name):
|
||||
if name in request.args and request.args[name].isdigit():
|
||||
return int(request.args[name])
|
||||
def get_int_arg(name: str) -> int | None:
|
||||
"""Get an request arg and convert to integer."""
|
||||
v = flask.request.args.get(name)
|
||||
return int(v) if v and v.isdigit() else None
|
||||
|
||||
|
||||
def calc_chunk_size(area_in_sq_km, size=22):
|
||||
def calc_chunk_size(area_in_sq_km: float, size: int = 22) -> int:
|
||||
"""Work out the size of a chunk."""
|
||||
side = math.sqrt(area_in_sq_km)
|
||||
return max(1, math.ceil(side / size))
|
||||
|
||||
|
||||
def file_missing_or_empty(filename):
|
||||
def file_missing_or_empty(filename: str) -> bool:
|
||||
"""Check if a file is missing or empty."""
|
||||
return os.path.exists(filename) or os.stat(filename).st_size == 0
|
||||
|
||||
|
||||
def is_bot():
|
||||
""" Is the current request from a web robot? """
|
||||
ua = request.headers.get("User-Agent")
|
||||
return ua and user_agents.parse(ua).is_bot
|
||||
def is_bot() -> bool:
|
||||
"""Is the current request from a web robot."""
|
||||
ua = flask.request.headers.get("User-Agent")
|
||||
return bool(ua and user_agents.parse(ua).is_bot)
|
||||
|
||||
|
||||
def log_location():
|
||||
return current_app.config["LOG_DIR"]
|
||||
def log_location() -> str:
|
||||
"""Get log location from Flask config."""
|
||||
return cast(str, flask.current_app.config["LOG_DIR"])
|
||||
|
||||
|
||||
def good_location():
|
||||
return os.path.join(log_location(), "complete")
|
||||
|
||||
|
||||
def capfirst(value):
|
||||
""" Uppercase first letter of string, leave rest as is. """
|
||||
def capfirst(value: str) -> str:
|
||||
"""Uppercase first letter of string, leave rest as is."""
|
||||
return value[0].upper() + value[1:] if value else value
|
||||
|
||||
|
||||
def any_upper(value):
|
||||
def any_upper(value: str) -> bool:
|
||||
"""Check if string contains any uppercase characters."""
|
||||
return any(c.isupper() for c in value)
|
||||
|
||||
|
||||
|
|
@ -102,7 +119,8 @@ def find_log_file(place):
|
|||
return f.path
|
||||
|
||||
|
||||
def get_free_space(config):
|
||||
def get_free_space(config: flask.config.Config) -> int:
|
||||
"""Return the amount of available free space."""
|
||||
s = os.statvfs(config["FREE_SPACE_PATH"])
|
||||
return s.f_bsize * s.f_bavail
|
||||
|
||||
|
|
@ -132,12 +150,12 @@ def display_distance(units, dist):
|
|||
return f"{dist / 1000:,.2f} km"
|
||||
|
||||
|
||||
re_range = re.compile(r"\b(\d+) ?(?:to|-) ?(\d+)\b", re.I)
|
||||
re_number_list = re.compile(r"\b([\d, ]+) (?:and|&) (\d+)\b", re.I)
|
||||
re_number = re.compile(r"^(?:No\.?|Number)? ?(\d+)\b")
|
||||
def is_in_range(address_range: str, address: str) -> bool:
|
||||
"""Check if an address is within a range."""
|
||||
re_range = re.compile(r"\b(\d+) ?(?:to|-) ?(\d+)\b", re.I)
|
||||
re_number_list = re.compile(r"\b([\d, ]+) (?:and|&) (\d+)\b", re.I)
|
||||
re_number = re.compile(r"^(?:No\.?|Number)? ?(\d+)\b")
|
||||
|
||||
|
||||
def is_in_range(address_range, address):
|
||||
m_number = re_number.match(address)
|
||||
if not m_number:
|
||||
return False
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue