1.1.1
This commit is contained in:
commit
e61960dcfb
31
.github/workflows/check-quality.yml
vendored
Normal file
31
.github/workflows/check-quality.yml
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
name: qc (black/mypy/isort checks)
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyse:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: install devbox
|
||||||
|
uses: jetpack-io/devbox-install-action@v0.3.0
|
||||||
|
|
||||||
|
- name: install dependencies
|
||||||
|
run: devbox run poetry install
|
||||||
|
|
||||||
|
- name: install dependencies
|
||||||
|
id: build
|
||||||
|
run: devbox run poetry build
|
||||||
|
|
||||||
|
- name: analyse with mypy
|
||||||
|
run: devbox run poetry run mypy surplus.py
|
||||||
|
|
||||||
|
- name: check for black formatting compliance
|
||||||
|
run: devbox run poetry run "black --check surplus.py"
|
||||||
|
|
||||||
|
- name: analyse isort compliance
|
||||||
|
run: devbox run poetry run "isort --check surplus.py"
|
|
@ -1,6 +1,9 @@
|
||||||
name: release (slsa 3)
|
name: release with slsa 3 compliance
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
main
|
||||||
tags:
|
tags:
|
||||||
- '*'
|
- '*'
|
||||||
|
|
81
README.md
81
README.md
|
@ -8,6 +8,7 @@ Plus Code to iOS-Shortcuts-like shareable text
|
||||||
- [API Reference](#api-reference)
|
- [API Reference](#api-reference)
|
||||||
- [surplus.surplus()](#surplussurplus)
|
- [surplus.surplus()](#surplussurplus)
|
||||||
- [surplus.parse_query()](#surplusparse_query)
|
- [surplus.parse_query()](#surplusparse_query)
|
||||||
|
- [surplus.handle_query()](#surplushandle_query)
|
||||||
- [surplus.Localcode](#surpluslocalcode)
|
- [surplus.Localcode](#surpluslocalcode)
|
||||||
- [surplus.Latlong](#surpluslatlong)
|
- [surplus.Latlong](#surpluslatlong)
|
||||||
- [Developing](#developing)
|
- [Developing](#developing)
|
||||||
|
@ -16,11 +17,12 @@ Plus Code to iOS-Shortcuts-like shareable text
|
||||||
|
|
||||||
```text
|
```text
|
||||||
$ surplus 9R3J+R9 Singapore
|
$ surplus 9R3J+R9 Singapore
|
||||||
surplus version 1.1.0
|
surplus version 1.1.1
|
||||||
Thomson Plaza
|
Thomson Plaza
|
||||||
301 Upper Thomson Road, Bishan
|
301 Upper Thomson Road, Bishan
|
||||||
|
Sin Ming, Bishan
|
||||||
574408
|
574408
|
||||||
Singapore
|
Central, Singapore
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
@ -28,7 +30,7 @@ Singapore
|
||||||
>>> Localcode(code="8RPQ+JW", locality="Singapore").full_length()
|
>>> Localcode(code="8RPQ+JW", locality="Singapore").full_length()
|
||||||
(True, '6PH58RPQ+JW')
|
(True, '6PH58RPQ+JW')
|
||||||
>>> surplus("6PH58RPQ+JW")
|
>>> surplus("6PH58RPQ+JW")
|
||||||
(True, 'Caldecott Stn Exit 4\nToa Payoh Link\n298106\nSingapore')
|
(True, 'Caldecott Stn Exit 4\nToa Payoh Link\n298106\nCentral, Singapore')
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installing
|
## Installing
|
||||||
|
@ -44,16 +46,19 @@ pip install git+https://github.com/markjoshwel/surplus
|
||||||
### Command-line Interface
|
### Command-line Interface
|
||||||
|
|
||||||
```text
|
```text
|
||||||
usage: surplus [-h] [-d] query
|
usage: surplus [-h] [-d] query [query ...]
|
||||||
|
|
||||||
Plus Code to iOS-Shortcuts-like shareable text
|
Plus Code to iOS-Shortcuts-like shareable text
|
||||||
|
|
||||||
positional arguments:
|
positional arguments:
|
||||||
query full-length Plus Code (6PH58QMF+FX), local codes (8QMF+FX Singapore), or latlong (1.3336875, 103.7749375)
|
query full-length Plus Code (6PH58QMF+FX),
|
||||||
|
local code (8QMF+FX Singapore), or
|
||||||
|
latlong (1.3336875, 103.7749375)
|
||||||
|
|
||||||
options:
|
options:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
-d, --debug prints lat, long and reverser response dict to stderr
|
-d, --debug prints lat, long and reverser response
|
||||||
|
dict to stderr
|
||||||
```
|
```
|
||||||
|
|
||||||
### API Reference
|
### API Reference
|
||||||
|
@ -76,9 +81,12 @@ pluscode to shareable text conversion function
|
||||||
- arguments
|
- arguments
|
||||||
|
|
||||||
- `query: str | surplus.Localcode | surplus.Latlong`
|
- `query: str | surplus.Localcode | surplus.Latlong`
|
||||||
str - normal longcode (6PH58QMF+FX)
|
- str
|
||||||
surplus.Localcode - shortcode with locality (8QMF+FX Singapore)
|
normal longcode (6PH58QMF+FX)
|
||||||
surplus.Latlong - latlong
|
- [`surplus.Localcode`](#surpluslocalcode)
|
||||||
|
shortcode with locality (8QMF+FX Singapore)
|
||||||
|
- [`surplus.Latlong`](#surpluslatlong)
|
||||||
|
latlong
|
||||||
|
|
||||||
- `reverser: typing.Callable = geopy.geocoders.Nominatim(user_agent="surplus").reverser`
|
- `reverser: typing.Callable = geopy.geocoders.Nominatim(user_agent="surplus").reverser`
|
||||||
latlong to location function, accesses a dict from .raw attribute of return object
|
latlong to location function, accesses a dict from .raw attribute of return object
|
||||||
|
@ -97,22 +105,22 @@ pluscode to shareable text conversion function
|
||||||
- returns `tuple[bool, str]`
|
- returns `tuple[bool, str]`
|
||||||
|
|
||||||
- `(True, <str>)`
|
- `(True, <str>)`
|
||||||
conversion was successful, str is resultant text
|
conversion succeeded, second element is the resultant string
|
||||||
- `(False, <str>)`
|
- `(False, <str>)`
|
||||||
conversion failed, str is error message
|
conversion failed, second element is an error message string
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
#### `surplus.parse_query()`
|
#### `surplus.parse_query()`
|
||||||
|
|
||||||
function that parses a string Plus Code, local code or latlong into a str, surplus.Localcode or surplus.Latlong respectively
|
function that parses a string Plus Code, local code or latlong into a str, [`surplus.Localcode`](#surpluslocalcode) or [`surplus.Latlong`](#surpluslatlong) respectively
|
||||||
|
|
||||||
- signature:
|
- signature:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def parse_query(
|
def parse_query(
|
||||||
query: str, debug: bool = False
|
query: str, debug: bool = False
|
||||||
) -> tuple[bool, str | Localcode | Latlong]:
|
) -> tuple[Literal[True], str | Localcode | Latlong] | tuple[Literal[False], str]:
|
||||||
```
|
```
|
||||||
|
|
||||||
- arguments:
|
- arguments:
|
||||||
|
@ -120,12 +128,43 @@ function that parses a string Plus Code, local code or latlong into a str, surpl
|
||||||
- `query: str`
|
- `query: str`
|
||||||
string Plus Code, local code or latlong
|
string Plus Code, local code or latlong
|
||||||
|
|
||||||
- returns `tuple[bool, str | Localcode | Latlong]`
|
- returns `tuple[Literal[True], str | Localcode | Latlong] | tuple[Literal[False], str]`
|
||||||
|
|
||||||
- `(True, <str | Localcode | Latlong>)`
|
- `(True, <str | surplus.Localcode | surplus.Latlong>)`
|
||||||
conversion was successful, second element is result
|
conversion succeeded, second element is resultant Plus code string, [`surplus.Localcode`](#surpluslocalcode) or [`surplus.Latlong`](#surpluslatlong)
|
||||||
- `(False, <str>)`
|
- `(False, <str>)`
|
||||||
conversion failed, str is error message
|
conversion failed, second element is an error message string
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `surplus.handle_query()`
|
||||||
|
|
||||||
|
function that gets returns a [surplus.Latlong](#surpluslatlong) from a Plus Code string, [`surplus.Localcode`](#surpluslocalcode) or [`surplus.Latlong`](#surpluslatlong) object.
|
||||||
|
used after [`surplus.parse_query()`](#surplusparse_query).
|
||||||
|
|
||||||
|
- signature:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def handle_query(
|
||||||
|
query: str | Localcode | Latlong, debug: bool = False
|
||||||
|
) -> tuple[Literal[True], Latlong] | tuple[Literal[False], str]:
|
||||||
|
```
|
||||||
|
|
||||||
|
- arguments:
|
||||||
|
|
||||||
|
- `query: str | Localcode | Latlong`
|
||||||
|
- str
|
||||||
|
normal longcode (6PH58QMF+FX)
|
||||||
|
- [`surplus.Localcode`](#surpluslocalcode)
|
||||||
|
shortcode with locality (8QMF+FX Singapore)
|
||||||
|
- [`surplus.Latlong`](#surpluslatlong)
|
||||||
|
latlong
|
||||||
|
|
||||||
|
- returns `tuple[Literal[True], Latlong] | tuple[Literal[False], str]`
|
||||||
|
- `(True, <surplus.Latlong>)`
|
||||||
|
conversion succeeded, second element is a [`surplus.Latlong`](#surpluslatlong)
|
||||||
|
- `(False, <str>)`
|
||||||
|
conversion failed, second element is an error message string
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -136,9 +175,9 @@ function that parses a string Plus Code, local code or latlong into a str, surpl
|
||||||
- parameters:
|
- parameters:
|
||||||
|
|
||||||
- `code: str`
|
- `code: str`
|
||||||
Plus Code - e.g.: "8QMF+FX"
|
Plus Code - e.g.: `"8QMF+FX"`
|
||||||
- `locality: str`
|
- `locality: str`
|
||||||
e.g.: "Singapore"
|
e.g.: `"Singapore"`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -162,9 +201,9 @@ method that calculates full-length Plus Code using locality
|
||||||
- returns:
|
- returns:
|
||||||
|
|
||||||
- `(True, <str>)`
|
- `(True, <str>)`
|
||||||
conversion was successful, str is resultant Plus Code
|
conversion succeeded, second element is the resultant Plus Code string
|
||||||
- `(False, <str>)`
|
- `(False, <str>)`
|
||||||
conversion failed, str is error message
|
conversion failed, second element is an error message string
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "surplus"
|
name = "surplus"
|
||||||
version = "1.1.0"
|
version = "1.1.1"
|
||||||
description = "Plus Code to iOS-Shortcuts-like shareable text"
|
description = "Plus Code to iOS-Shortcuts-like shareable text"
|
||||||
authors = ["Mark Joshwel <mark@joshwel.co>"]
|
authors = ["Mark Joshwel <mark@joshwel.co>"]
|
||||||
license = "Unlicence"
|
license = "Unlicence"
|
||||||
|
|
269
surplus.py
269
surplus.py
|
@ -30,8 +30,9 @@ For more information, please refer to <http://unlicense.org/>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
|
from collections import OrderedDict
|
||||||
from sys import stderr
|
from sys import stderr
|
||||||
from typing import Any, Callable, Final, NamedTuple
|
from typing import Any, Callable, Final, Literal, NamedTuple
|
||||||
|
|
||||||
from geopy import Location # type: ignore
|
from geopy import Location # type: ignore
|
||||||
from geopy.geocoders import Nominatim # type: ignore
|
from geopy.geocoders import Nominatim # type: ignore
|
||||||
|
@ -39,7 +40,7 @@ from pluscodes import PlusCode # type: ignore
|
||||||
from pluscodes.openlocationcode import recoverNearest # type: ignore
|
from pluscodes.openlocationcode import recoverNearest # type: ignore
|
||||||
from pluscodes.validator import Validator # type: ignore
|
from pluscodes.validator import Validator # type: ignore
|
||||||
|
|
||||||
VERSION: Final[tuple[int, int, int]] = (1, 1, 0)
|
VERSION: Final[tuple[int, int, int]] = (1, 1, 1)
|
||||||
|
|
||||||
|
|
||||||
class Localcode(NamedTuple):
|
class Localcode(NamedTuple):
|
||||||
|
@ -130,49 +131,24 @@ def surplus(
|
||||||
(True, <str>) - conversion was successful, str is resultant text
|
(True, <str>) - conversion was successful, str is resultant text
|
||||||
(False, <str>) - conversion failed, str is error message
|
(False, <str>) - conversion failed, str is error message
|
||||||
"""
|
"""
|
||||||
lat: float = 0.0
|
|
||||||
lon: float = 0.0
|
|
||||||
|
|
||||||
if isinstance(query, Latlong):
|
def _unique(l: list[str]) -> list[str]:
|
||||||
lat, lon = query.lat, query.long
|
unique: OrderedDict = OrderedDict()
|
||||||
|
for line in l:
|
||||||
|
unique.update({line: None})
|
||||||
|
return list(unique.keys())
|
||||||
|
|
||||||
else: # instances: str | Localcode
|
_latlong = handle_query(query=query, debug=debug)
|
||||||
str_pcode: str = ""
|
|
||||||
|
|
||||||
if isinstance(query, Localcode):
|
if _latlong[0] is False:
|
||||||
result = query.full_length()
|
assert isinstance(_latlong[1], str)
|
||||||
|
return False, _latlong[1]
|
||||||
|
|
||||||
if not result[0]:
|
assert isinstance(_latlong[1], Latlong)
|
||||||
return False, result[1]
|
latlong = _latlong[1]
|
||||||
|
|
||||||
str_pcode = result[1]
|
|
||||||
|
|
||||||
else:
|
|
||||||
str_pcode = query
|
|
||||||
|
|
||||||
try:
|
|
||||||
pcode = PlusCode(str_pcode)
|
|
||||||
|
|
||||||
except KeyError:
|
|
||||||
return (
|
|
||||||
False,
|
|
||||||
"enter full-length Plus Code including area code, e.g.: 6PH58QMF+FX",
|
|
||||||
)
|
|
||||||
|
|
||||||
except Exception as pcderr:
|
|
||||||
return (
|
|
||||||
False,
|
|
||||||
f"error while decoding Plus Code: {pcderr.__class__.__name__} - {pcderr}",
|
|
||||||
)
|
|
||||||
|
|
||||||
lat = pcode.area.center().lat
|
|
||||||
lon = pcode.area.center().lon
|
|
||||||
|
|
||||||
if debug:
|
|
||||||
stderr.write(f"debug: {lat=}, {lon=}\n")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
_reversed: Location | None = reverser(f"{lat}, {lon}")
|
_reversed: Location | None = reverser(f"{latlong.lat}, {latlong.long}")
|
||||||
|
|
||||||
if _reversed is None:
|
if _reversed is None:
|
||||||
raise Exception(f"reverser function returned None")
|
raise Exception(f"reverser function returned None")
|
||||||
|
@ -182,71 +158,113 @@ def surplus(
|
||||||
except Exception as reverr:
|
except Exception as reverr:
|
||||||
return (
|
return (
|
||||||
False,
|
False,
|
||||||
f"error while reversing latlong ({lat},{lon}): {reverr.__class__.__name__} - {reverr}",
|
f"error while reversing latlong ({Latlong}): {reverr.__class__.__name__} - {reverr}",
|
||||||
)
|
)
|
||||||
|
|
||||||
if debug:
|
if debug:
|
||||||
stderr.write(f"debug: {location=}\n")
|
stderr.write(f"debug: {location=}\n")
|
||||||
|
|
||||||
data: list[str] = [
|
text: list[str] = _unique(
|
||||||
(
|
[
|
||||||
",".join(
|
(
|
||||||
[
|
", ".join(
|
||||||
location["address"].get(detail, "")
|
[
|
||||||
for detail in (
|
d
|
||||||
"emergency, historic, military, natural, landuse, place, railway,"
|
for d in _unique(
|
||||||
"man_made, aerialway, boundary, amenity, aeroway, club, craft,"
|
[
|
||||||
"leisure, office, mountain_pass, shop, tourism, bridge, tunnel, waterway"
|
location["address"].get(detail, None)
|
||||||
).split(", ")
|
for detail in (
|
||||||
]
|
"emergency, historic, military, natural, landuse, place, railway, "
|
||||||
)
|
"man_made, aerialway, boundary, amenity, aeroway, club, craft, "
|
||||||
).strip(","),
|
"leisure, office, mountain_pass, shop, tourism, bridge, tunnel, waterway"
|
||||||
# location["address"].get("leisure"),
|
).split(", ")
|
||||||
# location["address"].get("shop"),
|
]
|
||||||
# location["address"].get("railway"),
|
)
|
||||||
(
|
if d is not None
|
||||||
location["address"].get("building")
|
]
|
||||||
if (
|
)
|
||||||
|
).strip(", "),
|
||||||
|
(
|
||||||
location["address"].get("building")
|
location["address"].get("building")
|
||||||
!= location["address"].get("house_number")
|
if (
|
||||||
)
|
location["address"].get("building")
|
||||||
else None
|
!= location["address"].get("house_number")
|
||||||
),
|
)
|
||||||
location["address"].get("highway"),
|
else None
|
||||||
(
|
),
|
||||||
location["address"].get("house_number", "")
|
location["address"].get("highway"),
|
||||||
+ (" " + location["address"].get("house_name", "")).strip()
|
(
|
||||||
+ " "
|
location["address"].get("house_number", "")
|
||||||
+ location["address"].get("road", "")
|
+ (" " + location["address"].get("house_name", "")).strip()
|
||||||
+ (
|
+ " "
|
||||||
", " + location["address"].get("suburb", "")
|
+ location["address"].get("road", "")
|
||||||
# dont repeat if suburb is mentioned in the road itself
|
# + (
|
||||||
# 'Toa Payoh' in 'Lorong 1A Toa Payoh'
|
# ", " + location["address"].get("suburb", "")
|
||||||
if location["address"].get("suburb", "")
|
# # dont repeat if suburb is mentioned in the road itself
|
||||||
not in location["address"].get("road", "")
|
# # 'Toa Payoh' in 'Lorong 1A Toa Payoh'
|
||||||
else ""
|
# if location["address"].get("suburb", "")
|
||||||
)
|
# not in location["address"].get("road", "")
|
||||||
).strip(),
|
# else None
|
||||||
(
|
# )
|
||||||
",".join(
|
).strip(),
|
||||||
[
|
(
|
||||||
location["address"].get(detail, "")
|
", ".join(
|
||||||
for detail in (
|
[
|
||||||
"residential, neighbourhood, allotments, quarter"
|
d
|
||||||
).split(", ")
|
for d in _unique(
|
||||||
]
|
[
|
||||||
)
|
location["address"].get(detail, "")
|
||||||
).strip(","),
|
for detail in (
|
||||||
location["address"].get("postcode"),
|
"residential, neighbourhood, allotments, quarter, "
|
||||||
location["address"].get("country"),
|
"city_district, district, borough, suburb, subdivision, "
|
||||||
]
|
"municipality, city, town, village"
|
||||||
|
).split(", ")
|
||||||
|
]
|
||||||
|
)
|
||||||
|
if all(
|
||||||
|
[
|
||||||
|
d != "",
|
||||||
|
d not in location["address"].get("road", ""),
|
||||||
|
d
|
||||||
|
not in [
|
||||||
|
location["address"].get(detail, "")
|
||||||
|
for detail in (
|
||||||
|
"region, state, state_district, county, "
|
||||||
|
"state, country, continent"
|
||||||
|
).split(", ")
|
||||||
|
],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
).strip(","),
|
||||||
|
location["address"].get("postcode"),
|
||||||
|
(
|
||||||
|
", ".join(
|
||||||
|
[
|
||||||
|
d
|
||||||
|
for d in _unique(
|
||||||
|
[
|
||||||
|
location["address"].get(detail, None)
|
||||||
|
for detail in (
|
||||||
|
"region, state, state_district, county, "
|
||||||
|
"state, country, continent"
|
||||||
|
).split(", ")
|
||||||
|
]
|
||||||
|
)
|
||||||
|
if d is not None
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
return True, "\n".join([d for d in data if ((d != None) and d != "")])
|
return True, "\n".join([d for d in text if ((d != None) and d != "")])
|
||||||
|
|
||||||
|
|
||||||
def parse_query(
|
def parse_query(
|
||||||
query: str, debug: bool = False
|
query: str, debug: bool = False
|
||||||
) -> tuple[bool, str | Localcode | Latlong]:
|
) -> tuple[Literal[True], str | Localcode | Latlong] | tuple[Literal[False], str]:
|
||||||
"""
|
"""
|
||||||
function that parses a string Plus Code, local code or latlong into a str,
|
function that parses a string Plus Code, local code or latlong into a str,
|
||||||
surplus.Localcode or surplus.Latlong respectively
|
surplus.Localcode or surplus.Latlong respectively
|
||||||
|
@ -263,7 +281,7 @@ def parse_query(
|
||||||
|
|
||||||
def _word_match(
|
def _word_match(
|
||||||
oquery: str, squery: list[str]
|
oquery: str, squery: list[str]
|
||||||
) -> tuple[bool, str | Localcode | Latlong]:
|
) -> tuple[Literal[True], str | Localcode | Latlong] | tuple[Literal[False], str]:
|
||||||
"""
|
"""
|
||||||
internal helper code reuse function
|
internal helper code reuse function
|
||||||
|
|
||||||
|
@ -285,6 +303,9 @@ def parse_query(
|
||||||
locality = oquery.replace(pcode, "")
|
locality = oquery.replace(pcode, "")
|
||||||
locality = locality.strip().strip(",").strip()
|
locality = locality.strip().strip(",").strip()
|
||||||
|
|
||||||
|
if debug:
|
||||||
|
stderr.write(f"debug: {pcode=}, {locality=}\n")
|
||||||
|
|
||||||
return True, Localcode(code=pcode, locality=locality)
|
return True, Localcode(code=pcode, locality=locality)
|
||||||
|
|
||||||
return False, "unable to find a pluscode/match to a format"
|
return False, "unable to find a pluscode/match to a format"
|
||||||
|
@ -324,6 +345,66 @@ def parse_query(
|
||||||
return _word_match(oquery=query, squery=squery)
|
return _word_match(oquery=query, squery=squery)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_query(
|
||||||
|
query: str | Localcode | Latlong, debug: bool = False
|
||||||
|
) -> tuple[Literal[True], Latlong] | tuple[Literal[False], str]:
|
||||||
|
"""
|
||||||
|
function that gets returns a surplus.Latlong from a Plus Code string,
|
||||||
|
surplus.Localcode or surplus.Latlong object.
|
||||||
|
used after surplus.parse_query().
|
||||||
|
|
||||||
|
query: str | Localcode | Latlong
|
||||||
|
|
||||||
|
debug: bool = False
|
||||||
|
|
||||||
|
returns tuple[bool, str | Latlong]
|
||||||
|
(True, Latlong) - conversion was successful, second element is latlong
|
||||||
|
(False, <str>) - conversion failed, str is error message
|
||||||
|
"""
|
||||||
|
lat: float = 0.0
|
||||||
|
lon: float = 0.0
|
||||||
|
|
||||||
|
if isinstance(query, Latlong):
|
||||||
|
return True, query
|
||||||
|
|
||||||
|
else: # instances: str | Localcode
|
||||||
|
str_pcode: str = ""
|
||||||
|
|
||||||
|
if isinstance(query, Localcode):
|
||||||
|
result = query.full_length()
|
||||||
|
|
||||||
|
if not result[0]:
|
||||||
|
return False, result[1]
|
||||||
|
|
||||||
|
str_pcode = result[1]
|
||||||
|
|
||||||
|
else:
|
||||||
|
str_pcode = query
|
||||||
|
|
||||||
|
try:
|
||||||
|
pcode = PlusCode(str_pcode)
|
||||||
|
|
||||||
|
except KeyError:
|
||||||
|
return (
|
||||||
|
False,
|
||||||
|
"code given is not a full-length Plus Code (including area code), e.g.: 6PH58QMF+FX",
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as pcderr:
|
||||||
|
return (
|
||||||
|
False,
|
||||||
|
f"error while decoding Plus Code: {pcderr.__class__.__name__} - {pcderr}",
|
||||||
|
)
|
||||||
|
|
||||||
|
lat = pcode.area.center().lat
|
||||||
|
lon = pcode.area.center().lon
|
||||||
|
|
||||||
|
if debug:
|
||||||
|
stderr.write(f"debug: {lat=}, {lon=}\n")
|
||||||
|
|
||||||
|
return True, Latlong(lat=lat, long=lon)
|
||||||
|
|
||||||
|
|
||||||
def cli() -> None:
|
def cli() -> None:
|
||||||
parser = ArgumentParser(
|
parser = ArgumentParser(
|
||||||
prog="surplus",
|
prog="surplus",
|
||||||
|
|
Loading…
Reference in a new issue