surplus 2.0.0 (#19)
This commit is contained in:
commit
dd49301b09
10
.github/workflows/checks.yml
vendored
10
.github/workflows/checks.yml
vendored
|
@ -3,6 +3,8 @@ name: qc
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
|
paths:
|
||||||
|
- '**.py'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
analyse:
|
analyse:
|
||||||
|
@ -17,18 +19,18 @@ jobs:
|
||||||
- name: install dependencies
|
- name: install dependencies
|
||||||
run: devbox run poetry install
|
run: devbox run poetry install
|
||||||
|
|
||||||
- name: buil wheel
|
- name: build wheel
|
||||||
id: build
|
id: build
|
||||||
run: devbox run poetry build
|
run: devbox run poetry build
|
||||||
|
|
||||||
- name: analyse with mypy
|
- name: analyse with mypy
|
||||||
run: devbox run poetry run mypy surplus.py test.py
|
run: devbox run poetry run mypy **/*.py
|
||||||
|
|
||||||
- name: check for black formatting compliance
|
- name: check for black formatting compliance
|
||||||
run: devbox run poetry run "black --check surplus.py test.py"
|
run: devbox run poetry run "black --check **/*.py"
|
||||||
|
|
||||||
- name: analyse isort compliance
|
- name: analyse isort compliance
|
||||||
run: devbox run poetry run "isort --check surplus.py test.py"
|
run: devbox run poetry run "isort --check **/*.py"
|
||||||
|
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
3
.github/workflows/publish-slsa3.yml
vendored
3
.github/workflows/publish-slsa3.yml
vendored
|
@ -27,6 +27,9 @@ jobs:
|
||||||
id: build
|
id: build
|
||||||
run: devbox run poetry build
|
run: devbox run poetry build
|
||||||
|
|
||||||
|
- name: duplicate non-versioned wheel
|
||||||
|
run: cp dist/surplus-*.whl dist/surplus-py3-none-any.whl
|
||||||
|
|
||||||
- name: generate provenance subjects
|
- name: generate provenance subjects
|
||||||
id: hash
|
id: hash
|
||||||
run: |
|
run: |
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
{
|
{
|
||||||
"packages": [
|
"packages": [
|
||||||
"python311",
|
"python311",
|
||||||
|
"python311Packages.ipykernel",
|
||||||
"poetry"
|
"poetry"
|
||||||
],
|
],
|
||||||
"shell": {
|
"shell": {
|
||||||
"init_hook": "poetry shell"
|
"init_hook": [
|
||||||
|
"poetry env use $(which python)",
|
||||||
|
"poetry shell"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"commit": "f80ac848e3d6f0c12c52758c0f25c10c97ca3b62"
|
"commit": "f80ac848e3d6f0c12c52758c0f25c10c97ca3b62"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
"python311": {
|
"python311": {
|
||||||
"plugin_version": "0.0.1",
|
"plugin_version": "0.0.1",
|
||||||
"resolved": "github:NixOS/nixpkgs/f80ac848e3d6f0c12c52758c0f25c10c97ca3b62#python311"
|
"resolved": "github:NixOS/nixpkgs/f80ac848e3d6f0c12c52758c0f25c10c97ca3b62#python311"
|
||||||
|
},
|
||||||
|
"python311Packages.ipykernel": {
|
||||||
|
"resolved": "github:NixOS/nixpkgs/f80ac848e3d6f0c12c52758c0f25c10c97ca3b62#python311Packages.ipykernel"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
373
playground.ipynb
Normal file
373
playground.ipynb
Normal file
|
@ -0,0 +1,373 @@
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# surplus 2.0.0 playground notebook\n",
|
||||||
|
"\n",
|
||||||
|
"wrangling with environments for devbox users using codium/vs code:\n",
|
||||||
|
"\n",
|
||||||
|
"```text\n",
|
||||||
|
"$ devbox shell # enter devbox env\n",
|
||||||
|
"(surplus-py3.11) (devbox) $ exit # leave poetry env\n",
|
||||||
|
"(devbox) $ codium . # open ide\n",
|
||||||
|
"```"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"OUTPUT_LINE_X_KEYS: Final[tuple[str, ...]] = (\"region\",\"county\",\"state\",\"state_district\",\"country\",\"continent\",)\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# converting nominatim keys to OUTPUT_LINE_X_KEYS format\n",
|
||||||
|
"\n",
|
||||||
|
"keys = \"\"\"\n",
|
||||||
|
"region, county, state, state_district, country, continent\n",
|
||||||
|
"\"\"\"\n",
|
||||||
|
"\n",
|
||||||
|
"split_keys = [f'\"{key.strip()}\"' for key in keys.strip().split(\",\")]\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"OUTPUT_LINE_X_KEYS: Final[tuple[str, ...]] = ({','.join(split_keys)},)\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from surplus import PlusCodeQuery, LocalCodeQuery, LatlongQuery, StringQuery\n",
|
||||||
|
"from surplus import Latlong, Result\n",
|
||||||
|
"from surplus import default_geocoder, default_reverser"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Generic Result NamedTuple"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"True\tNone \t3\n",
|
||||||
|
"False\tZeroDivisionError('division by zero') \tdivision by zero (ZeroDivisionError)\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ename": "ZeroDivisionError",
|
||||||
|
"evalue": "division by zero",
|
||||||
|
"output_type": "error",
|
||||||
|
"traceback": [
|
||||||
|
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
||||||
|
"\u001b[0;31mZeroDivisionError\u001b[0m Traceback (most recent call last)",
|
||||||
|
"\u001b[1;32m/home/m/works/surplus/playground.ipynb Cell 5\u001b[0m in \u001b[0;36m<cell line: 0>\u001b[0;34m()\u001b[0m\n\u001b[1;32m <a href='vscode-notebook-cell://wsl%2Balpine/home/m/works/surplus/playground.ipynb#W4sdnNjb2RlLXJlbW90ZQ%3D%3D?line=7'>8</a>\u001b[0m \u001b[39mprint\u001b[39m(\u001b[39m\"\u001b[39m\u001b[39m{}\u001b[39;00m\u001b[39m\\t\u001b[39;00m\u001b[39m{:<40}\u001b[39;00m\u001b[39m\\t\u001b[39;00m\u001b[39m{}\u001b[39;00m\u001b[39m\"\u001b[39m\u001b[39m.\u001b[39mformat(\u001b[39mbool\u001b[39m(nom_result), \u001b[39mrepr\u001b[39m(nom_result\u001b[39m.\u001b[39merror), nom_result\u001b[39m.\u001b[39mget()))\n\u001b[1;32m <a href='vscode-notebook-cell://wsl%2Balpine/home/m/works/surplus/playground.ipynb#W4sdnNjb2RlLXJlbW90ZQ%3D%3D?line=8'>9</a>\u001b[0m \u001b[39mprint\u001b[39m(\n\u001b[1;32m <a href='vscode-notebook-cell://wsl%2Balpine/home/m/works/surplus/playground.ipynb#W4sdnNjb2RlLXJlbW90ZQ%3D%3D?line=9'>10</a>\u001b[0m \u001b[39m\"\u001b[39m\u001b[39m{}\u001b[39;00m\u001b[39m\\t\u001b[39;00m\u001b[39m{:<40}\u001b[39;00m\u001b[39m\\t\u001b[39;00m\u001b[39m{}\u001b[39;00m\u001b[39m\"\u001b[39m\u001b[39m.\u001b[39mformat(\n\u001b[1;32m <a href='vscode-notebook-cell://wsl%2Balpine/home/m/works/surplus/playground.ipynb#W4sdnNjb2RlLXJlbW90ZQ%3D%3D?line=10'>11</a>\u001b[0m \u001b[39mbool\u001b[39m(exc_result), \u001b[39mrepr\u001b[39m(exc_result\u001b[39m.\u001b[39merror), exc_result\u001b[39m.\u001b[39mcry(string\u001b[39m=\u001b[39m\u001b[39mTrue\u001b[39;00m)\n\u001b[1;32m <a href='vscode-notebook-cell://wsl%2Balpine/home/m/works/surplus/playground.ipynb#W4sdnNjb2RlLXJlbW90ZQ%3D%3D?line=11'>12</a>\u001b[0m )\n\u001b[1;32m <a href='vscode-notebook-cell://wsl%2Balpine/home/m/works/surplus/playground.ipynb#W4sdnNjb2RlLXJlbW90ZQ%3D%3D?line=12'>13</a>\u001b[0m )\n\u001b[0;32m---> <a href='vscode-notebook-cell://wsl%2Balpine/home/m/works/surplus/playground.ipynb#W4sdnNjb2RlLXJlbW90ZQ%3D%3D?line=13'>14</a>\u001b[0m \u001b[39mprint\u001b[39m(\u001b[39m\"\u001b[39m\u001b[39m{}\u001b[39;00m\u001b[39m\\t\u001b[39;00m\u001b[39m{:<40}\u001b[39;00m\u001b[39m\\t\u001b[39;00m\u001b[39m{}\u001b[39;00m\u001b[39m\"\u001b[39m\u001b[39m.\u001b[39mformat(\u001b[39mbool\u001b[39m(exc_result), \u001b[39mrepr\u001b[39m(exc_result\u001b[39m.\u001b[39merror), exc_result\u001b[39m.\u001b[39;49mget()))\n",
|
||||||
|
"File \u001b[0;32m~/works/surplus/surplus.py:247\u001b[0m, in \u001b[0;36mResult.get\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 245\u001b[0m \u001b[39m\"\"\"method that returns self.value if Result is non-erroneous else raises error\"\"\"\u001b[39;00m\n\u001b[1;32m 246\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39misinstance\u001b[39m(\u001b[39mself\u001b[39m\u001b[39m.\u001b[39merror, \u001b[39mBaseException\u001b[39;00m):\n\u001b[0;32m--> 247\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39merror\n\u001b[1;32m 248\u001b[0m \u001b[39mreturn\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mvalue\n",
|
||||||
|
"\u001b[1;32m/home/m/works/surplus/playground.ipynb Cell 5\u001b[0m in \u001b[0;36m<cell line: 0>\u001b[0;34m()\u001b[0m\n\u001b[1;32m <a href='vscode-notebook-cell://wsl%2Balpine/home/m/works/surplus/playground.ipynb#W4sdnNjb2RlLXJlbW90ZQ%3D%3D?line=0'>1</a>\u001b[0m nom_result \u001b[39m=\u001b[39m Result[\u001b[39mint\u001b[39m](\u001b[39m3\u001b[39m)\n\u001b[1;32m <a href='vscode-notebook-cell://wsl%2Balpine/home/m/works/surplus/playground.ipynb#W4sdnNjb2RlLXJlbW90ZQ%3D%3D?line=2'>3</a>\u001b[0m \u001b[39mtry\u001b[39;00m:\n\u001b[0;32m----> <a href='vscode-notebook-cell://wsl%2Balpine/home/m/works/surplus/playground.ipynb#W4sdnNjb2RlLXJlbW90ZQ%3D%3D?line=3'>4</a>\u001b[0m \u001b[39m1\u001b[39;49m \u001b[39m/\u001b[39;49m \u001b[39m0\u001b[39;49m\n\u001b[1;32m <a href='vscode-notebook-cell://wsl%2Balpine/home/m/works/surplus/playground.ipynb#W4sdnNjb2RlLXJlbW90ZQ%3D%3D?line=4'>5</a>\u001b[0m \u001b[39mexcept\u001b[39;00m \u001b[39mException\u001b[39;00m \u001b[39mas\u001b[39;00m exc:\n\u001b[1;32m <a href='vscode-notebook-cell://wsl%2Balpine/home/m/works/surplus/playground.ipynb#W4sdnNjb2RlLXJlbW90ZQ%3D%3D?line=5'>6</a>\u001b[0m exc_result \u001b[39m=\u001b[39m Result[\u001b[39mint\u001b[39m](\u001b[39m-\u001b[39m\u001b[39m1\u001b[39m, error\u001b[39m=\u001b[39mexc)\n",
|
||||||
|
"\u001b[0;31mZeroDivisionError\u001b[0m: division by zero"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"nom_result = Result[int](3)\n",
|
||||||
|
"\n",
|
||||||
|
"try:\n",
|
||||||
|
" 1 / 0\n",
|
||||||
|
"except Exception as exc:\n",
|
||||||
|
" exc_result = Result[int](-1, error=exc)\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"{}\\t{:<40}\\t{}\".format(bool(nom_result), repr(nom_result.error), nom_result.get()))\n",
|
||||||
|
"print(\n",
|
||||||
|
" \"{}\\t{:<40}\\t{}\".format(\n",
|
||||||
|
" bool(exc_result), repr(exc_result.error), exc_result.cry(string=True)\n",
|
||||||
|
" )\n",
|
||||||
|
")\n",
|
||||||
|
"print(\"{}\\t{:<40}\\t{}\".format(bool(exc_result), repr(exc_result.error), exc_result.get()))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Query Types"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"Result(value=Latlong(latitude=1.3336875, longitude=103.7746875), error=None)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 3,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"PlusCodeQuery(code=\"6PH58QMF+FV\").to_lat_long_coord(geocoder=default_geocoder)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"Result(value=Latlong(latitude=1.3336875, longitude=103.7746875), error=None)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 4,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"plus_code = LocalCodeQuery(code=\"8QMF+FV\", locality=\"Singapore\").to_full_plus_code(\n",
|
||||||
|
" geocoder=default_geocoder\n",
|
||||||
|
")\n",
|
||||||
|
"\n",
|
||||||
|
"PlusCodeQuery(code=plus_code.get()).to_lat_long_coord(geocoder=default_geocoder)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 5,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"Result(value=Latlong(latitude=1.3336875, longitude=103.7746875), error=None)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 5,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"LocalCodeQuery(code=\"8QMF+FV\", locality=\"Singapore\").to_lat_long_coord(\n",
|
||||||
|
" geocoder=default_geocoder\n",
|
||||||
|
")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 6,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"Result(value=Latlong(latitude=1.33318835, longitude=103.77461234638255), error=None)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 6,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"LatlongQuery(\n",
|
||||||
|
" latlong=Latlong(latitude=1.33318835, longitude=103.77461234638255)\n",
|
||||||
|
").to_lat_long_coord(geocoder=default_geocoder)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 7,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"Result(value=Latlong(latitude=1.33318835, longitude=103.77461234638255), error=None)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 7,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"StringQuery(query=\"Ngee Ann Polytechnic\").to_lat_long_coord(geocoder=default_geocoder)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## return dictionary of `reverser` function\n",
|
||||||
|
"\n",
|
||||||
|
"all the necessary keys (see `SHAREABLE_TEXT_LINE_*` constants) should be at the top-level of the dictionary.\n",
|
||||||
|
"these keys will be casted into strings for safety guarantee when shareable text lines are being generated.\n",
|
||||||
|
"\n",
|
||||||
|
"while not necessary, consider keeping the original response dict under the \"raw\" key.\n",
|
||||||
|
"helps with debugging using `-d/--debug`!"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"reverser_return = {\n",
|
||||||
|
" \"amenity\": \"Ngee Ann Polytechnic\",\n",
|
||||||
|
" \"house_number\": \"535\",\n",
|
||||||
|
" \"road\": \"Clementi Road\",\n",
|
||||||
|
" \"suburb\": \"Bukit Timah\",\n",
|
||||||
|
" \"city\": \"Singapore\",\n",
|
||||||
|
" \"county\": \"Northwest\",\n",
|
||||||
|
" \"ISO3166-2-lvl6\": \"SG-03\",\n",
|
||||||
|
" \"postcode\": \"599489\",\n",
|
||||||
|
" \"country\": \"Singapore\",\n",
|
||||||
|
" \"country_code\": \"sg\",\n",
|
||||||
|
" \"raw\": {\n",
|
||||||
|
" \"place_id\": 297946059,\n",
|
||||||
|
" \"licence\": \"Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright\",\n",
|
||||||
|
" \"osm_type\": \"relation\",\n",
|
||||||
|
" \"osm_id\": 2535118,\n",
|
||||||
|
" \"lat\": \"1.33318835\",\n",
|
||||||
|
" \"lon\": \"103.77461234638255\",\n",
|
||||||
|
" \"class\": \"amenity\",\n",
|
||||||
|
" \"type\": \"university\",\n",
|
||||||
|
" \"place_rank\": 30,\n",
|
||||||
|
" \"importance\": 0.34662169301918117,\n",
|
||||||
|
" \"addresstype\": \"amenity\",\n",
|
||||||
|
" \"name\": \"Ngee Ann Polytechnic\",\n",
|
||||||
|
" \"display_name\": \"Ngee Ann Polytechnic, 535, Clementi Road, Bukit Timah, Singapore, Northwest, 599489, Singapore\",\n",
|
||||||
|
" \"address\": {\n",
|
||||||
|
" \"amenity\": \"Ngee Ann Polytechnic\",\n",
|
||||||
|
" \"house_number\": \"535\",\n",
|
||||||
|
" \"road\": \"Clementi Road\",\n",
|
||||||
|
" \"suburb\": \"Bukit Timah\",\n",
|
||||||
|
" \"city\": \"Singapore\",\n",
|
||||||
|
" \"county\": \"Northwest\",\n",
|
||||||
|
" \"ISO3166-2-lvl6\": \"SG-03\",\n",
|
||||||
|
" \"postcode\": \"599489\",\n",
|
||||||
|
" \"country\": \"Singapore\",\n",
|
||||||
|
" \"country_code\": \"sg\",\n",
|
||||||
|
" },\n",
|
||||||
|
" \"boundingbox\": [\"1.3289692\", \"1.3372184\", \"103.7701481\", \"103.7783945\"],\n",
|
||||||
|
" },\n",
|
||||||
|
" \"latitude\": 1.33318835,\n",
|
||||||
|
" \"longitude\": 103.77461234638255,\n",
|
||||||
|
"}"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 7,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"{'ISO3166-2-lvl6': 'SG-03',\n",
|
||||||
|
" 'amenity': 'Ngee Ann Polytechnic',\n",
|
||||||
|
" 'city': 'Singapore',\n",
|
||||||
|
" 'country': 'Singapore',\n",
|
||||||
|
" 'country_code': 'sg',\n",
|
||||||
|
" 'county': 'Northwest',\n",
|
||||||
|
" 'house_number': '535',\n",
|
||||||
|
" 'latitude': 1.33318835,\n",
|
||||||
|
" 'longitude': 103.77461234638255,\n",
|
||||||
|
" 'postcode': '599489',\n",
|
||||||
|
" 'raw': {'address': {'ISO3166-2-lvl6': 'SG-03',\n",
|
||||||
|
" 'amenity': 'Ngee Ann Polytechnic',\n",
|
||||||
|
" 'city': 'Singapore',\n",
|
||||||
|
" 'country': 'Singapore',\n",
|
||||||
|
" 'country_code': 'sg',\n",
|
||||||
|
" 'county': 'Northwest',\n",
|
||||||
|
" 'house_number': '535',\n",
|
||||||
|
" 'postcode': '599489',\n",
|
||||||
|
" 'road': 'Clementi Road',\n",
|
||||||
|
" 'suburb': 'Bukit Timah'},\n",
|
||||||
|
" 'addresstype': 'amenity',\n",
|
||||||
|
" 'boundingbox': ['1.3289692',\n",
|
||||||
|
" '1.3372184',\n",
|
||||||
|
" '103.7701481',\n",
|
||||||
|
" '103.7783945'],\n",
|
||||||
|
" 'class': 'amenity',\n",
|
||||||
|
" 'display_name': 'Ngee Ann Polytechnic, 535, Clementi Road, Bukit '\n",
|
||||||
|
" 'Timah, Singapore, Northwest, 599489, Singapore',\n",
|
||||||
|
" 'importance': 0.34662169301918117,\n",
|
||||||
|
" 'lat': '1.33318835',\n",
|
||||||
|
" 'licence': 'Data © OpenStreetMap contributors, ODbL 1.0. '\n",
|
||||||
|
" 'http://osm.org/copyright',\n",
|
||||||
|
" 'lon': '103.77461234638255',\n",
|
||||||
|
" 'name': 'Ngee Ann Polytechnic',\n",
|
||||||
|
" 'osm_id': 2535118,\n",
|
||||||
|
" 'osm_type': 'relation',\n",
|
||||||
|
" 'place_id': 297946059,\n",
|
||||||
|
" 'place_rank': 30,\n",
|
||||||
|
" 'type': 'university'},\n",
|
||||||
|
" 'road': 'Clementi Road',\n",
|
||||||
|
" 'suburb': 'Bukit Timah'}\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"import pprint\n",
|
||||||
|
"\n",
|
||||||
|
"latlong = LocalCodeQuery(code=\"8QMF+FV\", locality=\"Singapore\").to_lat_long_coord(\n",
|
||||||
|
" default_geocoder\n",
|
||||||
|
")\n",
|
||||||
|
"if not latlong:\n",
|
||||||
|
" latlong.cry()\n",
|
||||||
|
"\n",
|
||||||
|
"else:\n",
|
||||||
|
" location = default_reverser(latlong.get())\n",
|
||||||
|
" pprint.pprint(location)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.11.1"
|
||||||
|
},
|
||||||
|
"orig_nbformat": 4
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 2
|
||||||
|
}
|
466
poetry.lock
generated
466
poetry.lock
generated
|
@ -1,47 +1,87 @@
|
||||||
# This file is automatically @generated by Poetry and should not be changed by hand.
|
# This file is automatically @generated by Poetry and should not be changed by hand.
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "appnope"
|
||||||
|
version = "0.1.3"
|
||||||
|
description = "Disable App Nap on macOS >= 10.9"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"},
|
||||||
|
{file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "asttokens"
|
||||||
|
version = "2.3.0"
|
||||||
|
description = "Annotate AST trees with source code positions"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "asttokens-2.3.0-py2.py3-none-any.whl", hash = "sha256:bef1a51bc256d349e9f94e7e40e44b705ed1162f55294220dd561d24583d9877"},
|
||||||
|
{file = "asttokens-2.3.0.tar.gz", hash = "sha256:2552a88626aaa7f0f299f871479fc755bd4e7c11e89078965e928fb7bb9a6afe"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
six = ">=1.12.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
test = ["astroid", "pytest"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "backcall"
|
||||||
|
version = "0.2.0"
|
||||||
|
description = "Specifications for callback functions passed in to an API"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"},
|
||||||
|
{file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "black"
|
name = "black"
|
||||||
version = "23.3.0"
|
version = "23.7.0"
|
||||||
description = "The uncompromising code formatter."
|
description = "The uncompromising code formatter."
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"},
|
{file = "black-23.7.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587"},
|
||||||
{file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"},
|
{file = "black-23.7.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f"},
|
||||||
{file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"},
|
{file = "black-23.7.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be"},
|
||||||
{file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"},
|
{file = "black-23.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc"},
|
||||||
{file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"},
|
{file = "black-23.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"},
|
||||||
{file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"},
|
{file = "black-23.7.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2"},
|
||||||
{file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"},
|
{file = "black-23.7.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd"},
|
||||||
{file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"},
|
{file = "black-23.7.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a"},
|
||||||
{file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"},
|
{file = "black-23.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926"},
|
||||||
{file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"},
|
{file = "black-23.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad"},
|
||||||
{file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"},
|
{file = "black-23.7.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f"},
|
||||||
{file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"},
|
{file = "black-23.7.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3"},
|
||||||
{file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"},
|
{file = "black-23.7.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6"},
|
||||||
{file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"},
|
{file = "black-23.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a"},
|
||||||
{file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"},
|
{file = "black-23.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320"},
|
||||||
{file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"},
|
{file = "black-23.7.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9"},
|
||||||
{file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"},
|
{file = "black-23.7.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3"},
|
||||||
{file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"},
|
{file = "black-23.7.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087"},
|
||||||
{file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"},
|
{file = "black-23.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91"},
|
||||||
{file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"},
|
{file = "black-23.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491"},
|
||||||
{file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"},
|
{file = "black-23.7.0-py3-none-any.whl", hash = "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96"},
|
||||||
{file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"},
|
{file = "black-23.7.0.tar.gz", hash = "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb"},
|
||||||
{file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"},
|
|
||||||
{file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"},
|
|
||||||
{file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
click = ">=8.0.0"
|
click = ">=8.0.0"
|
||||||
|
ipython = {version = ">=7.8.0", optional = true, markers = "extra == \"jupyter\""}
|
||||||
mypy-extensions = ">=0.4.3"
|
mypy-extensions = ">=0.4.3"
|
||||||
packaging = ">=22.0"
|
packaging = ">=22.0"
|
||||||
pathspec = ">=0.9.0"
|
pathspec = ">=0.9.0"
|
||||||
platformdirs = ">=2"
|
platformdirs = ">=2"
|
||||||
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
|
tokenize-rt = {version = ">=3.2.0", optional = true, markers = "extra == \"jupyter\""}
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
colorama = ["colorama (>=0.4.3)"]
|
colorama = ["colorama (>=0.4.3)"]
|
||||||
|
@ -51,14 +91,14 @@ uvloop = ["uvloop (>=0.15.2)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "click"
|
name = "click"
|
||||||
version = "8.1.3"
|
version = "8.1.7"
|
||||||
description = "Composable command line interface toolkit"
|
description = "Composable command line interface toolkit"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
|
{file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
|
||||||
{file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
|
{file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
@ -76,6 +116,33 @@ files = [
|
||||||
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "decorator"
|
||||||
|
version = "5.1.1"
|
||||||
|
description = "Decorators for Humans"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.5"
|
||||||
|
files = [
|
||||||
|
{file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"},
|
||||||
|
{file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "executing"
|
||||||
|
version = "1.2.0"
|
||||||
|
description = "Get the currently executing AST node of a frame, and other information"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "executing-1.2.0-py2.py3-none-any.whl", hash = "sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc"},
|
||||||
|
{file = "executing-1.2.0.tar.gz", hash = "sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
tests = ["asttokens", "littleutils", "pytest", "rich"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "geographiclib"
|
name = "geographiclib"
|
||||||
version = "2.0"
|
version = "2.0"
|
||||||
|
@ -90,14 +157,14 @@ files = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "geopy"
|
name = "geopy"
|
||||||
version = "2.3.0"
|
version = "2.4.0"
|
||||||
description = "Python Geocoding Toolbox"
|
description = "Python Geocoding Toolbox"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "geopy-2.3.0-py3-none-any.whl", hash = "sha256:4a29a16d41d8e56ba8e07310802a1cbdf098eeb6069cc3d6d3068fc770629ffc"},
|
{file = "geopy-2.4.0-py3-none-any.whl", hash = "sha256:d2639a46d0ce4c091e9688b750ba94348a14b898a1e55c68f4b4a07e7d1afa20"},
|
||||||
{file = "geopy-2.3.0.tar.gz", hash = "sha256:228cd53b6eef699b2289d1172e462a90d5057779a10388a7366291812601187f"},
|
{file = "geopy-2.4.0.tar.gz", hash = "sha256:a59392bf17adb486b25dbdd71fbed27733bdf24a2dac588047a619de56695e36"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
@ -112,6 +179,45 @@ dev-test = ["coverage", "pytest (>=3.10)", "pytest-asyncio (>=0.17)", "sphinx (<
|
||||||
requests = ["requests (>=2.16.2)", "urllib3 (>=1.24.2)"]
|
requests = ["requests (>=2.16.2)", "urllib3 (>=1.24.2)"]
|
||||||
timezone = ["pytz"]
|
timezone = ["pytz"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ipython"
|
||||||
|
version = "8.15.0"
|
||||||
|
description = "IPython: Productive Interactive Computing"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
files = [
|
||||||
|
{file = "ipython-8.15.0-py3-none-any.whl", hash = "sha256:45a2c3a529296870a97b7de34eda4a31bee16bc7bf954e07d39abe49caf8f887"},
|
||||||
|
{file = "ipython-8.15.0.tar.gz", hash = "sha256:2baeb5be6949eeebf532150f81746f8333e2ccce02de1c7eedde3f23ed5e9f1e"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
appnope = {version = "*", markers = "sys_platform == \"darwin\""}
|
||||||
|
backcall = "*"
|
||||||
|
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
||||||
|
decorator = "*"
|
||||||
|
jedi = ">=0.16"
|
||||||
|
matplotlib-inline = "*"
|
||||||
|
pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""}
|
||||||
|
pickleshare = "*"
|
||||||
|
prompt-toolkit = ">=3.0.30,<3.0.37 || >3.0.37,<3.1.0"
|
||||||
|
pygments = ">=2.4.0"
|
||||||
|
stack-data = "*"
|
||||||
|
traitlets = ">=5"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.21)", "pandas", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"]
|
||||||
|
black = ["black"]
|
||||||
|
doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"]
|
||||||
|
kernel = ["ipykernel"]
|
||||||
|
nbconvert = ["nbconvert"]
|
||||||
|
nbformat = ["nbformat"]
|
||||||
|
notebook = ["ipywidgets", "notebook"]
|
||||||
|
parallel = ["ipyparallel"]
|
||||||
|
qtconsole = ["qtconsole"]
|
||||||
|
test = ["pytest (<7.1)", "pytest-asyncio", "testpath"]
|
||||||
|
test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pandas", "pytest (<7.1)", "pytest-asyncio", "testpath", "trio"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "isort"
|
name = "isort"
|
||||||
version = "5.12.0"
|
version = "5.12.0"
|
||||||
|
@ -130,51 +236,85 @@ pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"
|
||||||
plugins = ["setuptools"]
|
plugins = ["setuptools"]
|
||||||
requirements-deprecated-finder = ["pip-api", "pipreqs"]
|
requirements-deprecated-finder = ["pip-api", "pipreqs"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jedi"
|
||||||
|
version = "0.19.0"
|
||||||
|
description = "An autocompletion tool for Python that can be used for text editors."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
files = [
|
||||||
|
{file = "jedi-0.19.0-py2.py3-none-any.whl", hash = "sha256:cb8ce23fbccff0025e9386b5cf85e892f94c9b822378f8da49970471335ac64e"},
|
||||||
|
{file = "jedi-0.19.0.tar.gz", hash = "sha256:bcf9894f1753969cbac8022a8c2eaee06bfa3724e4192470aaffe7eb6272b0c4"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
parso = ">=0.8.3,<0.9.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"]
|
||||||
|
qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"]
|
||||||
|
testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matplotlib-inline"
|
||||||
|
version = "0.1.6"
|
||||||
|
description = "Inline Matplotlib backend for Jupyter"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.5"
|
||||||
|
files = [
|
||||||
|
{file = "matplotlib-inline-0.1.6.tar.gz", hash = "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304"},
|
||||||
|
{file = "matplotlib_inline-0.1.6-py3-none-any.whl", hash = "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
traitlets = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mypy"
|
name = "mypy"
|
||||||
version = "1.3.0"
|
version = "1.5.1"
|
||||||
description = "Optional static typing for Python"
|
description = "Optional static typing for Python"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "mypy-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c1eb485cea53f4f5284e5baf92902cd0088b24984f4209e25981cc359d64448d"},
|
{file = "mypy-1.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f33592ddf9655a4894aef22d134de7393e95fcbdc2d15c1ab65828eee5c66c70"},
|
||||||
{file = "mypy-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c99c3ecf223cf2952638da9cd82793d8f3c0c5fa8b6ae2b2d9ed1e1ff51ba85"},
|
{file = "mypy-1.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:258b22210a4a258ccd077426c7a181d789d1121aca6db73a83f79372f5569ae0"},
|
||||||
{file = "mypy-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:550a8b3a19bb6589679a7c3c31f64312e7ff482a816c96e0cecec9ad3a7564dd"},
|
{file = "mypy-1.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9ec1f695f0c25986e6f7f8778e5ce61659063268836a38c951200c57479cc12"},
|
||||||
{file = "mypy-1.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cbc07246253b9e3d7d74c9ff948cd0fd7a71afcc2b77c7f0a59c26e9395cb152"},
|
{file = "mypy-1.5.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:abed92d9c8f08643c7d831300b739562b0a6c9fcb028d211134fc9ab20ccad5d"},
|
||||||
{file = "mypy-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:a22435632710a4fcf8acf86cbd0d69f68ac389a3892cb23fbad176d1cddaf228"},
|
{file = "mypy-1.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:a156e6390944c265eb56afa67c74c0636f10283429171018446b732f1a05af25"},
|
||||||
{file = "mypy-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6e33bb8b2613614a33dff70565f4c803f889ebd2f859466e42b46e1df76018dd"},
|
{file = "mypy-1.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6ac9c21bfe7bc9f7f1b6fae441746e6a106e48fc9de530dea29e8cd37a2c0cc4"},
|
||||||
{file = "mypy-1.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d23370d2a6b7a71dc65d1266f9a34e4cde9e8e21511322415db4b26f46f6b8c"},
|
{file = "mypy-1.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51cb1323064b1099e177098cb939eab2da42fea5d818d40113957ec954fc85f4"},
|
||||||
{file = "mypy-1.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:658fe7b674769a0770d4b26cb4d6f005e88a442fe82446f020be8e5f5efb2fae"},
|
{file = "mypy-1.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:596fae69f2bfcb7305808c75c00f81fe2829b6236eadda536f00610ac5ec2243"},
|
||||||
{file = "mypy-1.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6e42d29e324cdda61daaec2336c42512e59c7c375340bd202efa1fe0f7b8f8ca"},
|
{file = "mypy-1.5.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:32cb59609b0534f0bd67faebb6e022fe534bdb0e2ecab4290d683d248be1b275"},
|
||||||
{file = "mypy-1.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:d0b6c62206e04061e27009481cb0ec966f7d6172b5b936f3ead3d74f29fe3dcf"},
|
{file = "mypy-1.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:159aa9acb16086b79bbb0016145034a1a05360626046a929f84579ce1666b315"},
|
||||||
{file = "mypy-1.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:76ec771e2342f1b558c36d49900dfe81d140361dd0d2df6cd71b3db1be155409"},
|
{file = "mypy-1.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f6b0e77db9ff4fda74de7df13f30016a0a663928d669c9f2c057048ba44f09bb"},
|
||||||
{file = "mypy-1.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebc95f8386314272bbc817026f8ce8f4f0d2ef7ae44f947c4664efac9adec929"},
|
{file = "mypy-1.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:26f71b535dfc158a71264e6dc805a9f8d2e60b67215ca0bfa26e2e1aa4d4d373"},
|
||||||
{file = "mypy-1.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:faff86aa10c1aa4a10e1a301de160f3d8fc8703b88c7e98de46b531ff1276a9a"},
|
{file = "mypy-1.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fc3a600f749b1008cc75e02b6fb3d4db8dbcca2d733030fe7a3b3502902f161"},
|
||||||
{file = "mypy-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:8c5979d0deb27e0f4479bee18ea0f83732a893e81b78e62e2dda3e7e518c92ee"},
|
{file = "mypy-1.5.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:26fb32e4d4afa205b24bf645eddfbb36a1e17e995c5c99d6d00edb24b693406a"},
|
||||||
{file = "mypy-1.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c5d2cc54175bab47011b09688b418db71403aefad07cbcd62d44010543fc143f"},
|
{file = "mypy-1.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:82cb6193de9bbb3844bab4c7cf80e6227d5225cc7625b068a06d005d861ad5f1"},
|
||||||
{file = "mypy-1.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:87df44954c31d86df96c8bd6e80dfcd773473e877ac6176a8e29898bfb3501cb"},
|
{file = "mypy-1.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4a465ea2ca12804d5b34bb056be3a29dc47aea5973b892d0417c6a10a40b2d65"},
|
||||||
{file = "mypy-1.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:473117e310febe632ddf10e745a355714e771ffe534f06db40702775056614c4"},
|
{file = "mypy-1.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9fece120dbb041771a63eb95e4896791386fe287fefb2837258925b8326d6160"},
|
||||||
{file = "mypy-1.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:74bc9b6e0e79808bf8678d7678b2ae3736ea72d56eede3820bd3849823e7f305"},
|
{file = "mypy-1.5.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d28ddc3e3dfeab553e743e532fb95b4e6afad51d4706dd22f28e1e5e664828d2"},
|
||||||
{file = "mypy-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:44797d031a41516fcf5cbfa652265bb994e53e51994c1bd649ffcd0c3a7eccbf"},
|
{file = "mypy-1.5.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:57b10c56016adce71fba6bc6e9fd45d8083f74361f629390c556738565af8eeb"},
|
||||||
{file = "mypy-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ddae0f39ca146972ff6bb4399f3b2943884a774b8771ea0a8f50e971f5ea5ba8"},
|
{file = "mypy-1.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:ff0cedc84184115202475bbb46dd99f8dcb87fe24d5d0ddfc0fe6b8575c88d2f"},
|
||||||
{file = "mypy-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c4c42c60a8103ead4c1c060ac3cdd3ff01e18fddce6f1016e08939647a0e703"},
|
{file = "mypy-1.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8f772942d372c8cbac575be99f9cc9d9fb3bd95c8bc2de6c01411e2c84ebca8a"},
|
||||||
{file = "mypy-1.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e86c2c6852f62f8f2b24cb7a613ebe8e0c7dc1402c61d36a609174f63e0ff017"},
|
{file = "mypy-1.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5d627124700b92b6bbaa99f27cbe615c8ea7b3402960f6372ea7d65faf376c14"},
|
||||||
{file = "mypy-1.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f9dca1e257d4cc129517779226753dbefb4f2266c4eaad610fc15c6a7e14283e"},
|
{file = "mypy-1.5.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:361da43c4f5a96173220eb53340ace68cda81845cd88218f8862dfb0adc8cddb"},
|
||||||
{file = "mypy-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:95d8d31a7713510685b05fbb18d6ac287a56c8f6554d88c19e73f724a445448a"},
|
{file = "mypy-1.5.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:330857f9507c24de5c5724235e66858f8364a0693894342485e543f5b07c8693"},
|
||||||
{file = "mypy-1.3.0-py3-none-any.whl", hash = "sha256:a8763e72d5d9574d45ce5881962bc8e9046bf7b375b0abf031f3e6811732a897"},
|
{file = "mypy-1.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:c543214ffdd422623e9fedd0869166c2f16affe4ba37463975043ef7d2ea8770"},
|
||||||
{file = "mypy-1.3.0.tar.gz", hash = "sha256:e1f4d16e296f5135624b34e8fb741eb0eadedca90862405b1f1fde2040b9bd11"},
|
{file = "mypy-1.5.1-py3-none-any.whl", hash = "sha256:f757063a83970d67c444f6e01d9550a7402322af3557ce7630d3c957386fa8f5"},
|
||||||
|
{file = "mypy-1.5.1.tar.gz", hash = "sha256:b031b9601f1060bf1281feab89697324726ba0c0bae9d7cd7ab4b690940f0b92"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
mypy-extensions = ">=1.0.0"
|
mypy-extensions = ">=1.0.0"
|
||||||
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
|
typing-extensions = ">=4.1.0"
|
||||||
typing-extensions = ">=3.10"
|
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
dmypy = ["psutil (>=4.0)"]
|
dmypy = ["psutil (>=4.0)"]
|
||||||
install-types = ["pip"]
|
install-types = ["pip"]
|
||||||
python2 = ["typed-ast (>=1.4.0,<2)"]
|
|
||||||
reports = ["lxml"]
|
reports = ["lxml"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -201,33 +341,76 @@ files = [
|
||||||
{file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
|
{file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parso"
|
||||||
|
version = "0.8.3"
|
||||||
|
description = "A Python Parser"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
files = [
|
||||||
|
{file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"},
|
||||||
|
{file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
|
||||||
|
testing = ["docopt", "pytest (<6.0.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pathspec"
|
name = "pathspec"
|
||||||
version = "0.11.1"
|
version = "0.11.2"
|
||||||
description = "Utility library for gitignore style pattern matching of file paths."
|
description = "Utility library for gitignore style pattern matching of file paths."
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"},
|
{file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"},
|
||||||
{file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"},
|
{file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pexpect"
|
||||||
|
version = "4.8.0"
|
||||||
|
description = "Pexpect allows easy control of interactive console applications."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"},
|
||||||
|
{file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
ptyprocess = ">=0.5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pickleshare"
|
||||||
|
version = "0.7.5"
|
||||||
|
description = "Tiny 'shelve'-like database with concurrency support"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"},
|
||||||
|
{file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "platformdirs"
|
name = "platformdirs"
|
||||||
version = "3.5.1"
|
version = "3.10.0"
|
||||||
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "platformdirs-3.5.1-py3-none-any.whl", hash = "sha256:e2378146f1964972c03c085bb5662ae80b2b8c06226c54b2ff4aa9483e8a13a5"},
|
{file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"},
|
||||||
{file = "platformdirs-3.5.1.tar.gz", hash = "sha256:412dae91f52a6f84830f39a8078cecd0e866cb72294a5c66808e74d5e88d251f"},
|
{file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.2.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
|
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"]
|
||||||
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
|
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pluscodes"
|
name = "pluscodes"
|
||||||
|
@ -244,30 +427,147 @@ files = [
|
||||||
dev = ["black (==22.3.0)", "build (==0.8.0)", "coverage (==6.4)", "isort (==5.8.0)", "pylintv (==2.15.0)", "pytest (==7.1.1)", "pytest-cov (==3.0.0)", "twine (==4.0.1)"]
|
dev = ["black (==22.3.0)", "build (==0.8.0)", "coverage (==6.4)", "isort (==5.8.0)", "pylintv (==2.15.0)", "pytest (==7.1.1)", "pytest-cov (==3.0.0)", "twine (==4.0.1)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tomli"
|
name = "prompt-toolkit"
|
||||||
version = "2.0.1"
|
version = "3.0.39"
|
||||||
description = "A lil' TOML parser"
|
description = "Library for building powerful interactive command lines in Python"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7.0"
|
||||||
|
files = [
|
||||||
|
{file = "prompt_toolkit-3.0.39-py3-none-any.whl", hash = "sha256:9dffbe1d8acf91e3de75f3b544e4842382fc06c6babe903ac9acb74dc6e08d88"},
|
||||||
|
{file = "prompt_toolkit-3.0.39.tar.gz", hash = "sha256:04505ade687dc26dc4284b1ad19a83be2f2afe83e7a828ace0c72f3a1df72aac"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
wcwidth = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ptyprocess"
|
||||||
|
version = "0.7.0"
|
||||||
|
description = "Run a subprocess in a pseudo terminal"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"},
|
||||||
|
{file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pure-eval"
|
||||||
|
version = "0.2.2"
|
||||||
|
description = "Safely evaluate AST nodes without side effects"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"},
|
||||||
|
{file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
tests = ["pytest"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pygments"
|
||||||
|
version = "2.16.1"
|
||||||
|
description = "Pygments is a syntax highlighting package written in Python."
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
|
{file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"},
|
||||||
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
|
{file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
plugins = ["importlib-metadata"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "six"
|
||||||
|
version = "1.16.0"
|
||||||
|
description = "Python 2 and 3 compatibility utilities"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||||
|
files = [
|
||||||
|
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||||
|
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stack-data"
|
||||||
|
version = "0.6.2"
|
||||||
|
description = "Extract data from python stack frames and tracebacks for informative displays"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "stack_data-0.6.2-py3-none-any.whl", hash = "sha256:cbb2a53eb64e5785878201a97ed7c7b94883f48b87bfb0bbe8b623c74679e4a8"},
|
||||||
|
{file = "stack_data-0.6.2.tar.gz", hash = "sha256:32d2dd0376772d01b6cb9fc996f3c8b57a357089dec328ed4b6553d037eaf815"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
asttokens = ">=2.1.0"
|
||||||
|
executing = ">=1.2.0"
|
||||||
|
pure-eval = "*"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokenize-rt"
|
||||||
|
version = "5.2.0"
|
||||||
|
description = "A wrapper around the stdlib `tokenize` which roundtrips."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "tokenize_rt-5.2.0-py2.py3-none-any.whl", hash = "sha256:b79d41a65cfec71285433511b50271b05da3584a1da144a0752e9c621a285289"},
|
||||||
|
{file = "tokenize_rt-5.2.0.tar.gz", hash = "sha256:9fe80f8a5c1edad2d3ede0f37481cc0cc1538a2f442c9c2f9e4feacd2792d054"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "traitlets"
|
||||||
|
version = "5.9.0"
|
||||||
|
description = "Traitlets Python configuration system"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "traitlets-5.9.0-py3-none-any.whl", hash = "sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8"},
|
||||||
|
{file = "traitlets-5.9.0.tar.gz", hash = "sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"]
|
||||||
|
test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typing-extensions"
|
name = "typing-extensions"
|
||||||
version = "4.6.3"
|
version = "4.7.1"
|
||||||
description = "Backported and Experimental Type Hints for Python 3.7+"
|
description = "Backported and Experimental Type Hints for Python 3.7+"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "typing_extensions-4.6.3-py3-none-any.whl", hash = "sha256:88a4153d8505aabbb4e13aacb7c486c2b4a33ca3b3f807914a9b4c844c471c26"},
|
{file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"},
|
||||||
{file = "typing_extensions-4.6.3.tar.gz", hash = "sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5"},
|
{file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wcwidth"
|
||||||
|
version = "0.2.6"
|
||||||
|
description = "Measures the displayed width of unicode strings in a terminal"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"},
|
||||||
|
{file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.10"
|
python-versions = "^3.11"
|
||||||
content-hash = "9837c2f9210fa01e5287a85b36c2c95030cc6be0e4ecffa7fc2a5285970b41d3"
|
content-hash = "f9270d7fb45c708e923f4afe041b26f77becb8e4adfcd517742e67f6b8f9d6b9"
|
||||||
|
|
|
@ -1,26 +1,37 @@
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "surplus"
|
name = "surplus"
|
||||||
version = "1.1.3"
|
version = "2.0.0"
|
||||||
description = "Plus Code to iOS-Shortcuts-like shareable text"
|
description = "Python script to convert Google Maps Plus Codes to iOS Shortcuts-like shareable text."
|
||||||
authors = ["Mark Joshwel <mark@joshwel.co>"]
|
authors = ["Mark Joshwel <mark@joshwel.co>"]
|
||||||
license = "Unlicence"
|
license = "Unlicense"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
include = ["surplus.py"]
|
repository = "https://github.com/markjoshwel/surplus"
|
||||||
|
keywords = ["pluscodes", "openlocationcode"]
|
||||||
|
packages = [
|
||||||
|
{include = "surplus"}
|
||||||
|
]
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.10"
|
python = "^3.11"
|
||||||
pluscodes = "^2022.1.3"
|
pluscodes = "^2022.1.3"
|
||||||
geopy = "^2.3.0"
|
geopy = "^2.3.0"
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
[tool.poetry.group.dev.dependencies]
|
||||||
black = "^23.3.0"
|
black = {extras = ["jupyter"], version = "^23.7.0"}
|
||||||
mypy = "^1.3.0"
|
mypy = "^1.5.1"
|
||||||
isort = "^5.12.0"
|
isort = "^5.12.0"
|
||||||
|
|
||||||
[tool.poetry.scripts]
|
[tool.poetry.scripts]
|
||||||
surplus = 'surplus:cli'
|
surplus = 'surplus:cli'
|
||||||
"s+" = 'surplus:cli'
|
"s+" = 'surplus:cli'
|
||||||
|
|
||||||
|
[tool.black]
|
||||||
|
line-length = 90
|
||||||
|
|
||||||
|
[tool.isort]
|
||||||
|
line_length = 90
|
||||||
|
profile = "black"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core"]
|
requires = ["poetry-core"]
|
||||||
build-backend = "poetry.core.masonry.api"
|
build-backend = "poetry.core.masonry.api"
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
geographiclib==2.0 ; python_version >= "3.10" and python_version < "4.0" \
|
geographiclib==2.0 ; python_version >= "3.11" and python_version < "4.0" \
|
||||||
--hash=sha256:6b7225248e45ff7edcee32becc4e0a1504c606ac5ee163a5656d482e0cd38734 \
|
--hash=sha256:6b7225248e45ff7edcee32becc4e0a1504c606ac5ee163a5656d482e0cd38734 \
|
||||||
--hash=sha256:f7f41c85dc3e1c2d3d935ec86660dc3b2c848c83e17f9a9e51ba9d5146a15859
|
--hash=sha256:f7f41c85dc3e1c2d3d935ec86660dc3b2c848c83e17f9a9e51ba9d5146a15859
|
||||||
geopy==2.3.0 ; python_version >= "3.10" and python_version < "4.0" \
|
geopy==2.4.0 ; python_version >= "3.11" and python_version < "4.0" \
|
||||||
--hash=sha256:228cd53b6eef699b2289d1172e462a90d5057779a10388a7366291812601187f \
|
--hash=sha256:a59392bf17adb486b25dbdd71fbed27733bdf24a2dac588047a619de56695e36 \
|
||||||
--hash=sha256:4a29a16d41d8e56ba8e07310802a1cbdf098eeb6069cc3d6d3068fc770629ffc
|
--hash=sha256:d2639a46d0ce4c091e9688b750ba94348a14b898a1e55c68f4b4a07e7d1afa20
|
||||||
pluscodes==2022.1.3 ; python_version >= "3.10" and python_version < "4.0" \
|
pluscodes==2022.1.3 ; python_version >= "3.11" and python_version < "4.0" \
|
||||||
--hash=sha256:50625f472f8d4e8822e005180c2eb41bf09e45e429f362d3cded346f1169dae8
|
--hash=sha256:50625f472f8d4e8822e005180c2eb41bf09e45e429f362d3cded346f1169dae8
|
||||||
|
|
480
surplus.py
480
surplus.py
|
@ -1,480 +0,0 @@
|
||||||
"""
|
|
||||||
surplus: Plus Code to iOS-Shortcuts-like shareable text
|
|
||||||
-------------------------------------------------------
|
|
||||||
by mark <mark@joshwel.co> and contributors
|
|
||||||
|
|
||||||
This is free and unencumbered software released into the public domain.
|
|
||||||
|
|
||||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
||||||
distribute this software, either in source code form or as a compiled
|
|
||||||
binary, for any purpose, commercial or non-commercial, and by any
|
|
||||||
means.
|
|
||||||
|
|
||||||
In jurisdictions that recognize copyright laws, the author or authors
|
|
||||||
of this software dedicate any and all copyright interest in the
|
|
||||||
software to the public domain. We make this dedication for the benefit
|
|
||||||
of the public at large and to the detriment of our heirs and
|
|
||||||
successors. We intend this dedication to be an overt act of
|
|
||||||
relinquishment in perpetuity of all present and future rights to this
|
|
||||||
software under copyright law.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
||||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
||||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||||
OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
For more information, please refer to <http://unlicense.org/>
|
|
||||||
"""
|
|
||||||
|
|
||||||
from argparse import ArgumentParser
|
|
||||||
from collections import OrderedDict
|
|
||||||
from sys import stderr
|
|
||||||
from typing import Any, Callable, Final, Literal, NamedTuple
|
|
||||||
|
|
||||||
from geopy import Location # type: ignore
|
|
||||||
from geopy.geocoders import Nominatim # type: ignore
|
|
||||||
from pluscodes import PlusCode # type: ignore
|
|
||||||
from pluscodes.openlocationcode import recoverNearest # type: ignore
|
|
||||||
from pluscodes.validator import Validator # type: ignore
|
|
||||||
|
|
||||||
VERSION: Final[tuple[int, int, int]] = (1, 1, 3)
|
|
||||||
|
|
||||||
|
|
||||||
class Localcode(NamedTuple):
|
|
||||||
"""
|
|
||||||
typing.NamedTuple representing short Plus Code with locality
|
|
||||||
|
|
||||||
code: str
|
|
||||||
Plus Code - e.g.: "8QMF+FX"
|
|
||||||
locality: str
|
|
||||||
e.g.: "Singapore"
|
|
||||||
"""
|
|
||||||
|
|
||||||
code: str
|
|
||||||
locality: str
|
|
||||||
|
|
||||||
def full_length(
|
|
||||||
self, geocoder: Callable = Nominatim(user_agent="surplus").geocode
|
|
||||||
) -> tuple[bool, str]:
|
|
||||||
"""
|
|
||||||
method that calculates full-length Plus Code using locality
|
|
||||||
|
|
||||||
geocoder: typing.Callable = geopy.geocoders.Nominatim(user_agent="surplus").geocode
|
|
||||||
place/locality to location function, accesses .longitude and .latitude if
|
|
||||||
returned object is not None
|
|
||||||
|
|
||||||
returns tuple[bool, str]
|
|
||||||
(True, <str>) - conversion was successful, str is resultant Plus Code
|
|
||||||
(False, <str>) - conversion failed, str is error message
|
|
||||||
"""
|
|
||||||
location: Location | None = geocoder(self.locality)
|
|
||||||
lat: float = 0.0
|
|
||||||
lon: float = 0.0
|
|
||||||
|
|
||||||
if location is None:
|
|
||||||
return False, f"no coordinates found for '{self.locality}'"
|
|
||||||
|
|
||||||
recv_pcode = recoverNearest(
|
|
||||||
code=self.code,
|
|
||||||
referenceLongitude=location.longitude,
|
|
||||||
referenceLatitude=location.latitude,
|
|
||||||
)
|
|
||||||
|
|
||||||
return True, recv_pcode
|
|
||||||
|
|
||||||
|
|
||||||
class Latlong(NamedTuple):
|
|
||||||
"""
|
|
||||||
typing.NamedTuple representing a pair of latitude and longitude coordinates
|
|
||||||
|
|
||||||
lat: float
|
|
||||||
latitudinal coordinate
|
|
||||||
long: float
|
|
||||||
longitudinal coordinate
|
|
||||||
"""
|
|
||||||
|
|
||||||
lat: float
|
|
||||||
long: float
|
|
||||||
|
|
||||||
|
|
||||||
def surplus(
|
|
||||||
query: str | Localcode | Latlong,
|
|
||||||
reverser: Callable = Nominatim(user_agent="surplus").reverse,
|
|
||||||
debug: bool = False,
|
|
||||||
) -> tuple[bool, str]:
|
|
||||||
"""
|
|
||||||
pluscode to shareable text conversion function
|
|
||||||
|
|
||||||
query: str | surplus.Localcode | surplus.Latlong
|
|
||||||
str - normal longcode (6PH58QMF+FX)
|
|
||||||
surplus.Localcode - shortcode with locality (8QMF+FX Singapore)
|
|
||||||
surplus.Latlong - latlong
|
|
||||||
|
|
||||||
reverser: typing.Callable = geopy.geocoders.Nominatim(user_agent="surplus").reverser
|
|
||||||
latlong to data function, accesses a dict from .raw attribute of return object
|
|
||||||
function should be able to take a string with two floats and return a
|
|
||||||
geopy.Location-like object (None checking is done)
|
|
||||||
|
|
||||||
# code used by surplus
|
|
||||||
location: dict[str, Any] = reverser(f"{lat}, {lon}").raw
|
|
||||||
|
|
||||||
dict should be similar to nominatim raw dicts, see
|
|
||||||
<https://nominatim.org/release-docs/latest/api/Output/#addressdetails>
|
|
||||||
|
|
||||||
debug: bool = False
|
|
||||||
prints lat, long and reverser response dict to stderr
|
|
||||||
|
|
||||||
returns tuple[bool, str]
|
|
||||||
(True, <str>) - conversion was successful, str is resultant text
|
|
||||||
(False, <str>) - conversion failed, str is error message
|
|
||||||
"""
|
|
||||||
|
|
||||||
def _unique(l: list[str]) -> list[str]:
|
|
||||||
"""(internal function) returns a in-order unique list from list"""
|
|
||||||
unique: OrderedDict = OrderedDict()
|
|
||||||
for line in l:
|
|
||||||
unique.update({line: None})
|
|
||||||
return list(unique.keys())
|
|
||||||
|
|
||||||
def _generate_text(address: dict[str, str], debug: bool = False) -> list[str]:
|
|
||||||
"""(internal function) separation of concern function for text generation"""
|
|
||||||
|
|
||||||
text: list[str] = []
|
|
||||||
seen_names: list[str] = []
|
|
||||||
|
|
||||||
text.append(
|
|
||||||
("0\t" if debug else "")
|
|
||||||
+ ", ".join(
|
|
||||||
seen_names := [
|
|
||||||
d
|
|
||||||
for d in _unique(
|
|
||||||
[
|
|
||||||
address.get(detail, "")
|
|
||||||
for detail in (
|
|
||||||
"emergency, historic, military, natural, landuse, place, "
|
|
||||||
"railway, man_made, aerialway, boundary, amenity, aeroway, "
|
|
||||||
"club, craft, leisure, office, mountain_pass, shop, "
|
|
||||||
"tourism, bridge, tunnel, waterway"
|
|
||||||
).split(", ")
|
|
||||||
]
|
|
||||||
)
|
|
||||||
if d != ""
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if address.get("building") != address.get("house_number"):
|
|
||||||
seen_names += [address.get("building", "")]
|
|
||||||
text.append(("1\t" if debug else "") + address.get("building", ""))
|
|
||||||
|
|
||||||
seen_names += [address.get("highway", "")]
|
|
||||||
text.append(("2\t" if debug else "") + address.get("highway", ""))
|
|
||||||
|
|
||||||
seen_names += [address.get("house_name", "")]
|
|
||||||
text.append(
|
|
||||||
("3\t" if debug else "")
|
|
||||||
+ (
|
|
||||||
address.get("house_number", "")
|
|
||||||
+ (" " + address.get("house_name", "")).strip()
|
|
||||||
+ " "
|
|
||||||
+ address.get("road", "")
|
|
||||||
).strip()
|
|
||||||
)
|
|
||||||
|
|
||||||
if debug:
|
|
||||||
stderr.write(f"debug: {seen_names=}\n")
|
|
||||||
|
|
||||||
text.append("4\t" if debug else "")
|
|
||||||
basket: list[str] = []
|
|
||||||
for d in _unique(
|
|
||||||
[
|
|
||||||
address.get(detail, "")
|
|
||||||
for detail in (
|
|
||||||
"residential, neighbourhood, allotments, quarter, "
|
|
||||||
"city_district, district, borough, suburb, subdivision, "
|
|
||||||
"municipality, city, town, village"
|
|
||||||
).split(", ")
|
|
||||||
]
|
|
||||||
):
|
|
||||||
if all(
|
|
||||||
_dvtm4 := [
|
|
||||||
d != "",
|
|
||||||
d not in address.get("road", ""),
|
|
||||||
d
|
|
||||||
not in [
|
|
||||||
address.get(detail, "")
|
|
||||||
for detail in (
|
|
||||||
"region, state, state_district, county, "
|
|
||||||
"state, country, continent"
|
|
||||||
).split(", ")
|
|
||||||
],
|
|
||||||
any(
|
|
||||||
_dvcm4 := [
|
|
||||||
True if (d not in sn) else False for sn in seen_names
|
|
||||||
]
|
|
||||||
),
|
|
||||||
]
|
|
||||||
):
|
|
||||||
basket.append(d)
|
|
||||||
|
|
||||||
if debug:
|
|
||||||
stderr.write(f"debug: {d=}\t{_dvtm4=}\t{_dvcm4=}\n")
|
|
||||||
|
|
||||||
text[-1] += ", ".join(basket)
|
|
||||||
|
|
||||||
text.append(("5\t" if debug else "") + address.get("postcode", ""))
|
|
||||||
|
|
||||||
text.append(
|
|
||||||
("6\t" if debug else "")
|
|
||||||
+ ", ".join(
|
|
||||||
[
|
|
||||||
d
|
|
||||||
for d in _unique(
|
|
||||||
[
|
|
||||||
address.get(detail, "")
|
|
||||||
for detail in (
|
|
||||||
"region, county, state, state_district, "
|
|
||||||
"country, continent"
|
|
||||||
).split(", ")
|
|
||||||
]
|
|
||||||
)
|
|
||||||
if d != ""
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
return [d for d in _unique(text) if all([d != None, d != ""])]
|
|
||||||
|
|
||||||
_latlong = handle_query(query=query, debug=debug)
|
|
||||||
|
|
||||||
if _latlong[0] is False:
|
|
||||||
assert isinstance(_latlong[1], str)
|
|
||||||
return False, _latlong[1]
|
|
||||||
|
|
||||||
assert isinstance(_latlong[1], Latlong)
|
|
||||||
latlong = _latlong[1]
|
|
||||||
|
|
||||||
try:
|
|
||||||
_reversed: Location | None = reverser(f"{latlong.lat}, {latlong.long}")
|
|
||||||
|
|
||||||
if _reversed is None:
|
|
||||||
raise Exception(f"reverser function returned None")
|
|
||||||
|
|
||||||
location: dict[str, Any] = _reversed.raw
|
|
||||||
|
|
||||||
except Exception as reverr:
|
|
||||||
return (
|
|
||||||
False,
|
|
||||||
f"error while reversing latlong ({Latlong}): {reverr.__class__.__name__} - {reverr}",
|
|
||||||
)
|
|
||||||
|
|
||||||
if debug:
|
|
||||||
stderr.write(f"debug: {location=}\n")
|
|
||||||
return True, "\n".join(
|
|
||||||
_generate_text(address=location.get("address", {}), debug=debug)
|
|
||||||
+ _generate_text(address=location.get("address", {}))
|
|
||||||
)
|
|
||||||
|
|
||||||
return True, "\n".join(_generate_text(address=location.get("address", {})))
|
|
||||||
|
|
||||||
|
|
||||||
def parse_query(
|
|
||||||
query: str, debug: bool = False
|
|
||||||
) -> 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
|
|
||||||
|
|
||||||
query: str
|
|
||||||
string Plus Code, local code or latlong
|
|
||||||
debug: bool = False
|
|
||||||
prints query parsing information to stderr
|
|
||||||
|
|
||||||
returns tuple[bool, str | Localcode | Latlong]
|
|
||||||
(True, <str | Localcode | Latlong>) - conversion was successful, second element is result
|
|
||||||
(False, <str>) - conversion failed, str is error message
|
|
||||||
"""
|
|
||||||
|
|
||||||
def _word_match(
|
|
||||||
oquery: str, squery: list[str]
|
|
||||||
) -> tuple[Literal[True], str | Localcode | Latlong] | tuple[Literal[False], str]:
|
|
||||||
"""
|
|
||||||
internal helper code reuse function
|
|
||||||
|
|
||||||
looks through each 'word' and attempts to match to a Plus Code
|
|
||||||
if found, remove from original query and strip of whitespace and commas
|
|
||||||
use resulting stripped query as locality
|
|
||||||
"""
|
|
||||||
|
|
||||||
pcode: str = ""
|
|
||||||
|
|
||||||
for word in squery:
|
|
||||||
if Validator().is_valid(word):
|
|
||||||
pcode = word
|
|
||||||
|
|
||||||
if Validator().is_full(word):
|
|
||||||
return True, word
|
|
||||||
|
|
||||||
if pcode != "": # found a pluscode
|
|
||||||
locality = oquery.replace(pcode, "")
|
|
||||||
locality = locality.strip().strip(",").strip()
|
|
||||||
|
|
||||||
if debug:
|
|
||||||
stderr.write(f"debug: {pcode=}, {locality=}\n")
|
|
||||||
|
|
||||||
return True, Localcode(code=pcode, locality=locality)
|
|
||||||
|
|
||||||
return False, "unable to find a pluscode/match to a format"
|
|
||||||
|
|
||||||
squery = [word.strip(",").strip() for word in query.split()]
|
|
||||||
|
|
||||||
if debug:
|
|
||||||
stderr.write(f"debug: {squery=}\n")
|
|
||||||
|
|
||||||
match squery:
|
|
||||||
# attempt to match to conjoined latlong ('lat,long')
|
|
||||||
case [a]:
|
|
||||||
try:
|
|
||||||
plat, plong = a.split(",")
|
|
||||||
lat = float(plat)
|
|
||||||
long = float(plong)
|
|
||||||
|
|
||||||
except ValueError:
|
|
||||||
return _word_match(oquery=query, squery=squery)
|
|
||||||
|
|
||||||
else:
|
|
||||||
return True, Latlong(lat=lat, long=long)
|
|
||||||
|
|
||||||
# attempt to match to latlong ('lat, long')
|
|
||||||
case [a, b]:
|
|
||||||
try:
|
|
||||||
lat = float(a)
|
|
||||||
long = float(b)
|
|
||||||
|
|
||||||
except ValueError:
|
|
||||||
return _word_match(oquery=query, squery=squery)
|
|
||||||
|
|
||||||
else:
|
|
||||||
return True, Latlong(lat=lat, long=long)
|
|
||||||
|
|
||||||
case _:
|
|
||||||
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:
|
|
||||||
parser = ArgumentParser(
|
|
||||||
prog="surplus",
|
|
||||||
description=__doc__[__doc__.find(":") + 2 : __doc__.find("\n", 1)],
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"query",
|
|
||||||
type=str,
|
|
||||||
help="full-length Plus Code (6PH58QMF+FX), local code (8QMF+FX Singapore), or latlong (1.3336875, 103.7749375)",
|
|
||||||
nargs="*",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"-d",
|
|
||||||
"--debug",
|
|
||||||
action="store_true",
|
|
||||||
default=False,
|
|
||||||
help="prints lat, long and reverser response dict to stderr",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"-v",
|
|
||||||
"--version",
|
|
||||||
action="store_true",
|
|
||||||
default=False,
|
|
||||||
help="prints version information to stderr and exits",
|
|
||||||
)
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
stderr.write(
|
|
||||||
f"surplus version {'.'.join([str(v) for v in VERSION])}"
|
|
||||||
+ (f", debug mode" if args.debug else "")
|
|
||||||
+ "\n"
|
|
||||||
)
|
|
||||||
|
|
||||||
if args.version:
|
|
||||||
exit()
|
|
||||||
|
|
||||||
if args.debug:
|
|
||||||
stderr.write("debug: args.query='" + " ".join(args.query) + "'\n")
|
|
||||||
|
|
||||||
query = parse_query(" ".join(args.query), debug=args.debug)
|
|
||||||
if not query[0]:
|
|
||||||
stderr.write(f"{query[-1]}\n")
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
result: tuple[bool, str] = surplus(query[-1], debug=args.debug)
|
|
||||||
if not result[0]:
|
|
||||||
stderr.write(f"{result[-1]}\n")
|
|
||||||
exit(2)
|
|
||||||
|
|
||||||
print(result[-1])
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
cli()
|
|
69
surplus/__init__.py
Normal file
69
surplus/__init__.py
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
"""
|
||||||
|
surplus: Google Maps Plus Code to iOS Shortcuts-like shareable text
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
by mark <mark@joshwel.co> and contributors
|
||||||
|
|
||||||
|
This is free and unencumbered software released into the public domain.
|
||||||
|
|
||||||
|
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
distribute this software, either in source code form or as a compiled
|
||||||
|
binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
means.
|
||||||
|
|
||||||
|
In jurisdictions that recognize copyright laws, the author or authors
|
||||||
|
of this software dedicate any and all copyright interest in the
|
||||||
|
software to the public domain. We make this dedication for the benefit
|
||||||
|
of the public at large and to the detriment of our heirs and
|
||||||
|
successors. We intend this dedication to be an overt act of
|
||||||
|
relinquishment in perpetuity of all present and future rights to this
|
||||||
|
software under copyright law.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
For more information, please refer to <http://unlicense.org/>
|
||||||
|
"""
|
||||||
|
|
||||||
|
# surplus was and would've been a single-file module, but typing is in the way :(
|
||||||
|
# https://github.com/python/typing/issues/1333
|
||||||
|
|
||||||
|
from .surplus import (
|
||||||
|
EMPTY_LATLONG,
|
||||||
|
SHAREABLE_TEXT_LINE_0_KEYS,
|
||||||
|
SHAREABLE_TEXT_LINE_1_KEYS,
|
||||||
|
SHAREABLE_TEXT_LINE_2_KEYS,
|
||||||
|
SHAREABLE_TEXT_LINE_3_KEYS,
|
||||||
|
SHAREABLE_TEXT_LINE_4_KEYS,
|
||||||
|
SHAREABLE_TEXT_LINE_5_KEYS,
|
||||||
|
SHAREABLE_TEXT_LINE_6_KEYS,
|
||||||
|
SHAREABLE_TEXT_NAMES,
|
||||||
|
USER_AGENT,
|
||||||
|
VERSION,
|
||||||
|
Behaviour,
|
||||||
|
ConversionResultTypeEnum,
|
||||||
|
EmptyQueryError,
|
||||||
|
IncompletePlusCodeError,
|
||||||
|
Latlong,
|
||||||
|
LatlongParseError,
|
||||||
|
LatlongQuery,
|
||||||
|
LocalCodeQuery,
|
||||||
|
NoSuitableLocationError,
|
||||||
|
PlusCodeNotFoundError,
|
||||||
|
PlusCodeQuery,
|
||||||
|
Query,
|
||||||
|
ResultType,
|
||||||
|
StringQuery,
|
||||||
|
SurplusException,
|
||||||
|
UnavailableFeatureError,
|
||||||
|
cli,
|
||||||
|
default_geocoder,
|
||||||
|
default_reverser,
|
||||||
|
handle_args,
|
||||||
|
parse_query,
|
||||||
|
surplus,
|
||||||
|
)
|
0
surplus/py.typed
Normal file
0
surplus/py.typed
Normal file
1096
surplus/surplus.py
Normal file
1096
surplus/surplus.py
Normal file
File diff suppressed because it is too large
Load diff
145
test.py
145
test.py
|
@ -1,3 +1,5 @@
|
||||||
|
# type: ignore
|
||||||
|
|
||||||
"""
|
"""
|
||||||
surplus test runner
|
surplus test runner
|
||||||
-------------------
|
-------------------
|
||||||
|
@ -29,6 +31,7 @@ OTHER DEALINGS IN THE SOFTWARE.
|
||||||
For more information, please refer to <http://unlicense.org/>
|
For more information, please refer to <http://unlicense.org/>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from io import StringIO
|
||||||
from sys import stderr
|
from sys import stderr
|
||||||
from textwrap import indent
|
from textwrap import indent
|
||||||
from traceback import format_exception
|
from traceback import format_exception
|
||||||
|
@ -37,52 +40,80 @@ from typing import Final, NamedTuple
|
||||||
import surplus
|
import surplus
|
||||||
|
|
||||||
INDENT: Final[int] = 3
|
INDENT: Final[int] = 3
|
||||||
|
MINIMUM_PASS_RATE: Final[float] = 0.7 # because results can be flaky
|
||||||
|
|
||||||
|
|
||||||
class ContinuityTest(NamedTuple):
|
class ContinuityTest(NamedTuple):
|
||||||
query: str
|
query: str
|
||||||
expected: str
|
expected: list[str]
|
||||||
|
|
||||||
|
|
||||||
class TestFailure(NamedTuple):
|
class TestFailure(NamedTuple):
|
||||||
test: ContinuityTest
|
test: ContinuityTest
|
||||||
exception: Exception
|
exception: Exception
|
||||||
output: str
|
output: str
|
||||||
|
stderr: StringIO
|
||||||
|
|
||||||
|
|
||||||
tests: list[ContinuityTest] = [
|
tests: list[ContinuityTest] = [
|
||||||
ContinuityTest(
|
ContinuityTest(
|
||||||
query="8RPQ+JW Singapore",
|
query="8R3M+F8 Singapore",
|
||||||
expected=(
|
expected=("Wisma Atria\n" "435 Orchard Road\n" "238877\n" "Central, Singapore"),
|
||||||
"Caldecott Stn Exit 4\n" "Toa Payoh Link\n" "298106\n" "Central, Singapore"
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
ContinuityTest(
|
ContinuityTest(
|
||||||
query="9R3J+R9 Singapore",
|
query="9R3J+R9 Singapore",
|
||||||
expected=(
|
expected=[
|
||||||
"Thomson Plaza\n"
|
(
|
||||||
"301 Upper Thomson Road\n"
|
"Thomson Plaza\n"
|
||||||
"Sin Ming, Bishan\n"
|
"301 Upper Thomson Road\n"
|
||||||
"574408\n"
|
"Sin Ming, Bishan\n"
|
||||||
"Central, Singapore"
|
"574408\n"
|
||||||
),
|
"Central, Singapore"
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
ContinuityTest(
|
ContinuityTest(
|
||||||
query="3RQ3+HW3 Pemping, Batam City, Riau Islands, Indonesia",
|
query="3RQ3+HW3 Pemping, Batam City, Riau Islands, Indonesia",
|
||||||
expected=("Batam\n" "Kepulauan Riau, Indonesia"),
|
expected=[
|
||||||
|
("Batam\n" "Kepulauan Riau, Indonesia"),
|
||||||
|
("Batam\n" "Sumatera, Kepulauan Riau, Indonesia"),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
# ContinuityTest(
|
|
||||||
# query="CQPP+QM9 Singapore",
|
|
||||||
# expected=(
|
|
||||||
# "Woodlands Integrated Transport Hub\n" "738343\n" "Northwest, Singapore"
|
|
||||||
# ),
|
|
||||||
# ),
|
|
||||||
ContinuityTest(
|
ContinuityTest(
|
||||||
query="8RRX+75Q Singapore",
|
query="St Lucia, Queensland, Australia G227+XF",
|
||||||
|
expected=[
|
||||||
|
(
|
||||||
|
"The University of Queensland\n"
|
||||||
|
"Macquarie Street\n"
|
||||||
|
"St Lucia, Greater Brisbane\n"
|
||||||
|
"4072\n"
|
||||||
|
"Queensland, Australia"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"The University of Queensland\n"
|
||||||
|
"Eleanor Schonell Bridge\n"
|
||||||
|
"St Lucia, Greater Brisbane, Dutton Park\n"
|
||||||
|
"4072\n"
|
||||||
|
"Queensland, Australia"
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
ContinuityTest(
|
||||||
|
query="Ngee Ann Polytechnic, Singapore",
|
||||||
expected=(
|
expected=(
|
||||||
"Braddell Station/Blk 106\n"
|
"Ngee Ann Polytechnic\n"
|
||||||
"Lorong 1 Toa Payoh\n"
|
"535 Clementi Road\n"
|
||||||
"319758\n"
|
"Bukit Timah\n"
|
||||||
|
"599489\n"
|
||||||
|
"Northwest, Singapore"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ContinuityTest(
|
||||||
|
query="1.3521, 103.8198",
|
||||||
|
expected=(
|
||||||
|
"MacRitchie Nature Trail\n"
|
||||||
|
"Central Water Catchment\n"
|
||||||
|
"574325\n"
|
||||||
"Central, Singapore"
|
"Central, Singapore"
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -106,29 +137,33 @@ def main() -> int:
|
||||||
|
|
||||||
for idx, test in enumerate(tests, start=1):
|
for idx, test in enumerate(tests, start=1):
|
||||||
print(f"[{idx}/{len(tests)}] {test.query}")
|
print(f"[{idx}/{len(tests)}] {test.query}")
|
||||||
|
|
||||||
|
test_stderr = StringIO()
|
||||||
|
|
||||||
output: str = ""
|
output: str = ""
|
||||||
|
behaviour = surplus.Behaviour(test.query, stderr=test_stderr, debug=True)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
query = surplus.parse_query(query=test.query)
|
query = surplus.parse_query(behaviour)
|
||||||
|
|
||||||
if query[0] is False:
|
if not query:
|
||||||
raise QueryParseFailure(f"test query parse result returned False")
|
raise QueryParseFailure(query.cry())
|
||||||
|
|
||||||
result = surplus.surplus(query=query[1])
|
result = surplus.surplus(query.get(), behaviour)
|
||||||
|
|
||||||
if result[0] is False:
|
if not result:
|
||||||
raise SurplusFailure(result[1])
|
raise SurplusFailure(result.cry())
|
||||||
|
|
||||||
output = result[1]
|
output = result.get()
|
||||||
|
|
||||||
print(indent(text=output, prefix=INDENT * " "))
|
if output not in test.expected:
|
||||||
|
raise ContinuityFailure("did not match any expected outputs")
|
||||||
if output != test.expected:
|
|
||||||
raise ContinuityFailure(f"test did not match output")
|
|
||||||
|
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
failures.append(TestFailure(test=test, exception=exc, output=output))
|
failures.append(
|
||||||
stderr.write(indent(text="(fail)", prefix=INDENT * " ") + "\n")
|
TestFailure(test=test, exception=exc, output=output, stderr=test_stderr)
|
||||||
|
)
|
||||||
|
stderr.write(indent(text="(fail)", prefix=INDENT * " ") + "\n\n")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
stderr.write(indent(text="(pass)", prefix=INDENT * " ") + "\n\n")
|
stderr.write(indent(text="(pass)", prefix=INDENT * " ") + "\n\n")
|
||||||
|
@ -143,17 +178,39 @@ def main() -> int:
|
||||||
indent("\n".join(format_exception(fail.exception)), prefix=INDENT * " ")
|
indent("\n".join(format_exception(fail.exception)), prefix=INDENT * " ")
|
||||||
+ "\n"
|
+ "\n"
|
||||||
)
|
)
|
||||||
+ (indent(text="Expected:", prefix=INDENT * " ") + "\n")
|
+ (indent(text="Expected:", prefix=INDENT * " "))
|
||||||
+ (indent(text=repr(fail.test.expected), prefix=(2 * INDENT) * " ") + "\n")
|
|
||||||
+ (indent(text=fail.test.expected, prefix=(2 * INDENT) * " ") + "\n\n")
|
|
||||||
+ (indent(text="Actual:", prefix=INDENT * " ") + "\n")
|
|
||||||
+ (indent(text=repr(fail.output), prefix=(2 * INDENT) * " ") + "\n")
|
|
||||||
+ (indent(text=fail.output, prefix=(2 * INDENT) * " "))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
print(f"\ncomplete: {len(tests) - len(failures)} passed, {len(failures)} failed")
|
for expected_output in fail.test.expected:
|
||||||
|
print(
|
||||||
|
indent(text=repr(expected_output), prefix=(2 * INDENT) * " ")
|
||||||
|
+ "\n"
|
||||||
|
+ (indent(text=expected_output, prefix=(2 * INDENT) * " ") + "\n")
|
||||||
|
)
|
||||||
|
|
||||||
return len(failures)
|
print(
|
||||||
|
indent(text="Actual:", prefix=INDENT * " ")
|
||||||
|
+ "\n"
|
||||||
|
+ (indent(text=repr(fail.output), prefix=(2 * INDENT) * " ") + "\n")
|
||||||
|
+ (indent(text=fail.output, prefix=(2 * INDENT) * " ") + "\n\n")
|
||||||
|
+ (indent(text="stderr:", prefix=INDENT * " ") + "\n")
|
||||||
|
+ (indent(text=fail.stderr.getvalue(), prefix=(2 * INDENT) * " "))
|
||||||
|
)
|
||||||
|
|
||||||
|
passes = len(tests) - len(failures)
|
||||||
|
pass_rate = passes / len(tests)
|
||||||
|
|
||||||
|
print(
|
||||||
|
f"complete: {passes} passed, {len(failures)} failed "
|
||||||
|
f"({pass_rate * 100:.0f}%/{MINIMUM_PASS_RATE * 100:.0f}%)"
|
||||||
|
)
|
||||||
|
|
||||||
|
if pass_rate < MINIMUM_PASS_RATE:
|
||||||
|
print("continuity pass rate is under minimum, test suite failed ;<")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
print("continuity tests passed :>")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
Loading…
Reference in a new issue