diff --git a/README.md b/README.md index 6c9126f..84ac9b7 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ Plus Code to iOS-Shortcuts-like shareable text - [API Reference](#api-reference) - [surplus.surplus()](#surplussurplus) - [surplus.parse_query()](#surplusparse_query) + - [surplus.handle_query()](#surplushandle_query) - [surplus.Localcode](#surpluslocalcode) - [surplus.Latlong](#surpluslatlong) - [Developing](#developing) @@ -44,16 +45,19 @@ pip install git+https://github.com/markjoshwel/surplus ### Command-line Interface ```text -usage: surplus [-h] [-d] query +usage: surplus [-h] [-d] query [query ...] Plus Code to iOS-Shortcuts-like shareable text 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: -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 @@ -76,9 +80,12 @@ pluscode to shareable text conversion function - arguments - `query: str | surplus.Localcode | surplus.Latlong` - str - normal longcode (6PH58QMF+FX) - surplus.Localcode - shortcode with locality (8QMF+FX Singapore) - surplus.Latlong - latlong + - str + normal longcode (6PH58QMF+FX) + - [`surplus.Localcode`](#surpluslocalcode) + shortcode with locality (8QMF+FX Singapore) + - [`surplus.Latlong`](#surpluslatlong) + latlong - `reverser: typing.Callable = geopy.geocoders.Nominatim(user_agent="surplus").reverser` latlong to location function, accesses a dict from .raw attribute of return object @@ -97,22 +104,22 @@ pluscode to shareable text conversion function - returns `tuple[bool, str]` - `(True, )` - conversion was successful, str is resultant text + conversion succeeded, second element is the resultant string - `(False, )` - conversion failed, str is error message + conversion failed, second element is an error message string --- #### `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: ```python def parse_query( query: str, debug: bool = False - ) -> tuple[bool, str | Localcode | Latlong]: + ) -> tuple[Literal[True], str | Localcode | Latlong] | tuple[Literal[False], str]: ``` - arguments: @@ -120,12 +127,43 @@ function that parses a string Plus Code, local code or latlong into a str, surpl - `query: str` 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, )` - conversion was successful, second element is result + - `(True, )` + conversion succeeded, second element is resultant Plus code string, [`surplus.Localcode`](#surpluslocalcode) or [`surplus.Latlong`](#surpluslatlong) - `(False, )` - 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, )` + conversion succeeded, second element is a [`surplus.Latlong`](#surpluslatlong) + - `(False, )` + conversion failed, second element is an error message string --- @@ -136,9 +174,9 @@ function that parses a string Plus Code, local code or latlong into a str, surpl - parameters: - `code: str` - Plus Code - e.g.: "8QMF+FX" + Plus Code - e.g.: `"8QMF+FX"` - `locality: str` - e.g.: "Singapore" + e.g.: `"Singapore"` --- @@ -162,9 +200,9 @@ method that calculates full-length Plus Code using locality - returns: - `(True, )` - conversion was successful, str is resultant Plus Code + conversion succeeded, second element is the resultant Plus Code string - `(False, )` - conversion failed, str is error message + conversion failed, second element is an error message string --- diff --git a/surplus.py b/surplus.py index 8c50459..654b6a6 100644 --- a/surplus.py +++ b/surplus.py @@ -32,7 +32,7 @@ For more information, please refer to from argparse import ArgumentParser from collections import OrderedDict 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.geocoders import Nominatim # type: ignore @@ -131,49 +131,17 @@ def surplus( (True, ) - conversion was successful, str is resultant text (False, ) - conversion failed, str is error message """ - lat: float = 0.0 - lon: float = 0.0 + _latlong = handle_query(query=query, debug=debug) - if isinstance(query, Latlong): - lat, lon = query.lat, query.long + if _latlong[0] is False: + assert isinstance(_latlong[1], str) + return False, _latlong[1] - 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, - "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") + assert isinstance(_latlong[1], Latlong) + latlong = _latlong[1] try: - _reversed: Location | None = reverser(f"{lat}, {lon}") + _reversed: Location | None = reverser(f"{latlong.lat}, {latlong.long}") if _reversed is None: raise Exception(f"reverser function returned None") @@ -183,7 +151,7 @@ def surplus( except Exception as reverr: return ( False, - f"error while reversing latlong ({lat},{lon}): {reverr.__class__.__name__} - {reverr}", + f"error while reversing latlong ({Latlong}): {reverr.__class__.__name__} - {reverr}", ) if debug: @@ -251,7 +219,7 @@ def surplus( def parse_query( 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, surplus.Localcode or surplus.Latlong respectively @@ -268,7 +236,7 @@ def parse_query( def _word_match( 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 @@ -332,6 +300,66 @@ def parse_query( 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, ) - 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: parser = ArgumentParser( prog="surplus",