From ea880cb3f50dead9c6027955c6c69c21e8a5a785 Mon Sep 17 00:00:00 2001 From: Stefan Oderbolz Date: Sat, 23 Mar 2024 11:17:41 +0100 Subject: [PATCH 1/3] Add type hint setup --- .pre-commit-config.yaml | 18 ++++++++++++++++- osmapi/OsmApi.py | 13 ++++++++----- osmapi/types.py | 43 +++++++++++++++++++++++++++++++++++++++++ setup.py | 6 ++---- test-requirements.txt | 1 + 5 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 osmapi/types.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 95e9d24..1956613 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,4 +8,20 @@ repos: rev: 6.0.0 hooks: - id: flake8 - + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: no-commit-to-branch + - id: check-merge-conflict + - id: check-symlinks + - id: mixed-line-ending + args: ['--fix=no'] + - id: check-ast + - id: check-builtin-literals + - id: check-case-conflict + - id: check-docstring-first + - repo: https://github.com/asottile/pyupgrade + rev: v3.9.0 + hooks: + - id: pyupgrade + args: [--py38-plus] diff --git a/osmapi/OsmApi.py b/osmapi/OsmApi.py index 1b301ac..efe3b70 100644 --- a/osmapi/OsmApi.py +++ b/osmapi/OsmApi.py @@ -25,6 +25,8 @@ """ +from typing import Union +from typing_extensions import Self import xml.dom.minidom import xml.parsers.expat import urllib.parse @@ -37,6 +39,7 @@ from . import errors from . import http from . import parser +from . import types from . import xmlbuilder @@ -61,7 +64,7 @@ def __init__( changesetautosize=500, changesetautomulti=1, session=None, - ): + ) -> None: """ Initialized the OsmApi object. @@ -151,13 +154,13 @@ def __init__( self._api, self._created_by, auth=auth, session=self.http_session ) - def __enter__(self): + def __enter__(self) -> Self: self._session = http.OsmApiSession( self._api, self._created_by, session=self.http_session ) return self - def __exit__(self, *args): + def __exit__(self, *args) -> None: self.close() def close(self): @@ -174,7 +177,7 @@ def close(self): # Capabilities # ################################################## - def Capabilities(self): + def Capabilities(self) -> types.CapabilitiesDict: """ Returns the API capabilities as a dict: @@ -229,7 +232,7 @@ def Capabilities(self): # Node # ################################################## - def NodeGet(self, NodeId, NodeVersion=-1): + def NodeGet(self, NodeId: Union[str, int], NodeVersion: int = -1): """ Returns node with `NodeId` as a dict: diff --git a/osmapi/types.py b/osmapi/types.py new file mode 100644 index 0000000..51e69eb --- /dev/null +++ b/osmapi/types.py @@ -0,0 +1,43 @@ +from typing import Literal, TypedDict + +# from typing import List, Optional, Dict + + +class MaxDict(TypedDict): + maximum: int + + +class MinDict(TypedDict): + minimum: int + + +class MinMaxDict(MaxDict, MinDict): + pass + + +class ChangesetsDict(TypedDict): + maximum_elements: int + + +class StatusDict(TypedDict): + api: Literal["online", "readonly", "offline"] + database: Literal["online", "readonly", "offline"] + gpx: Literal["online", "readonly", "offline"] + + +class TimeoutDict(TypedDict): + seconds: int + + +class TracepointsDict(TypedDict): + per_page: int + + +class CapabilitiesDict(TypedDict): + area: MaxDict + changesets: ChangesetsDict + status: StatusDict + timeout: TimeoutDict + tracepoints: TracepointsDict + version: MinMaxDict + waynodes: MaxDict diff --git a/setup.py b/setup.py index dc02672..1d9d377 100644 --- a/setup.py +++ b/setup.py @@ -1,10 +1,8 @@ -# -*- coding: utf-8 -*- - from codecs import open from setuptools import setup, find_packages import re -with open("osmapi/__init__.py", "r") as fd: +with open("osmapi/__init__.py") as fd: version = re.search( r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]', fd.read(), re.MULTILINE ).group(1) @@ -12,7 +10,7 @@ if not version: raise RuntimeError("Cannot find version information") -with open("README.md", "r", encoding="utf-8") as f: +with open("README.md", encoding="utf-8") as f: long_description = f.read() setup( diff --git a/test-requirements.txt b/test-requirements.txt index ea0c3ff..776c272 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -7,3 +7,4 @@ responses coverage black pre-commit +mypy From 18a9a8beced8b33d6f6a4ced7439152d99eb7b11 Mon Sep 17 00:00:00 2001 From: Stefan Oderbolz Date: Thu, 28 Mar 2024 11:16:57 +0100 Subject: [PATCH 2/3] Temp commit --- .pre-commit-config.yaml | 8 ++++++++ .vscode/settings.json | 6 ++++++ Makefile | 1 + osmapi/OsmApi.py | 6 +++--- osmapi/types.py | 33 +++++++++++++++++++++++++++++++-- setup.cfg | 6 ++++++ 6 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1956613..23ce38c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,3 +25,11 @@ repos: hooks: - id: pyupgrade args: [--py38-plus] + - repo: local + hooks: + - id: mypy + name: mypy + entry: mypy + language: python + pass_filenames: false + files: '.*\.py$' diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..154b205 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "[python]": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "charliermarsh.ruff" + } + } \ No newline at end of file diff --git a/Makefile b/Makefile index 2d2965d..92ce967 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,7 @@ format: ## Format source code (black codestyle) lint: ## Linting of source code python -m black --check --diff osmapi examples tests *.py python -m flake8 --statistics --show-source . + python -m mypy --strict test: ## Run tests (run in UTF-8 mode in Windows) python -Xutf8 -m pytest --cov=osmapi tests/ diff --git a/osmapi/OsmApi.py b/osmapi/OsmApi.py index efe3b70..c3e80fc 100644 --- a/osmapi/OsmApi.py +++ b/osmapi/OsmApi.py @@ -25,7 +25,7 @@ """ -from typing import Union +from typing import Union, List from typing_extensions import Self import xml.dom.minidom import xml.parsers.expat @@ -53,7 +53,7 @@ class OsmApi: def __init__( self, - username=None, + username: str | None = None, password=None, passwordfile=None, appid="", @@ -131,7 +131,7 @@ def __init__( self._changesetautomulti = changesetautomulti self._changesetautocpt = 0 # data to upload for auto group - self._changesetautodata = [] + self._changesetautodata: List[types.ChangesetDataDict] = [] # Get API self._api = api.strip("/") diff --git a/osmapi/types.py b/osmapi/types.py index 51e69eb..51def26 100644 --- a/osmapi/types.py +++ b/osmapi/types.py @@ -1,6 +1,9 @@ -from typing import Literal, TypedDict +from typing import Literal, TypedDict, List, Dict -# from typing import List, Optional, Dict +# from typing import Literal, List, Optional, TypedDict, Dict + +id_type = int +OsmType = Literal["node", "way", "relation"] class MaxDict(TypedDict): @@ -41,3 +44,29 @@ class CapabilitiesDict(TypedDict): tracepoints: TracepointsDict version: MinMaxDict waynodes: MaxDict + + +class RelationMemberDict(TypedDict): + ref: id_type + role: str # TODO: how many roles are there? + type: OsmType + + +class RealtionData(TypedDict): + id: id_type + member: List[RelationMemberDict] + tag: Dict + changeset: id_type + version: int + user: str + uid: id_type + visible: bool + + +OsmData = RealtionData + + +class ChangesetDataDict(TypedDict): + action: Literal["delete", "", ""] + type: OsmType + data: OsmData diff --git a/setup.cfg b/setup.cfg index 5b235b2..d0a8ae4 100644 --- a/setup.cfg +++ b/setup.cfg @@ -10,3 +10,9 @@ disable_noqa = False # adaptions for black max-line-length = 88 extend-ignore = E203 + +[mypy] +ignore_missing_imports = True +install_types = on +non_interactive = on +files = osmapi/*.py \ No newline at end of file From 92e46ae6df0b62a20fab4466972b9f51036f1d72 Mon Sep 17 00:00:00 2001 From: Stefan Oderbolz Date: Thu, 8 Aug 2024 07:46:49 +0200 Subject: [PATCH 3/3] Temp commit --- osmapi/OsmApi.py | 22 +++++++++++----------- osmapi/types.py | 19 ++++++++++++++++++- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/osmapi/OsmApi.py b/osmapi/OsmApi.py index c3e80fc..b7f9fd8 100644 --- a/osmapi/OsmApi.py +++ b/osmapi/OsmApi.py @@ -52,18 +52,18 @@ class OsmApi: """ def __init__( - self, + self: Self, username: str | None = None, - password=None, - passwordfile=None, - appid="", - created_by=f"osmapi/{__version__}", - api="https://www.openstreetmap.org", - changesetauto=False, - changesetautotags={}, - changesetautosize=500, - changesetautomulti=1, - session=None, + password: str | None = None, + passwordfile: str | None = None, + appid: str = "", + created_by: str = f"osmapi/{__version__}", + api: str = "https://www.openstreetmap.org", + changesetauto: bool = False, + changesetautotags: dict = {}, + changesetautosize: int = 500, + changesetautomulti: int = 1, + session: types.SessionLike | None = None, ) -> None: """ Initialized the OsmApi object. diff --git a/osmapi/types.py b/osmapi/types.py index 51def26..b351c33 100644 --- a/osmapi/types.py +++ b/osmapi/types.py @@ -1,4 +1,4 @@ -from typing import Literal, TypedDict, List, Dict +from typing import Literal, TypedDict, List, Dict, Any, Protocol # from typing import Literal, List, Optional, TypedDict, Dict @@ -70,3 +70,20 @@ class ChangesetDataDict(TypedDict): action: Literal["delete", "", ""] type: OsmType data: OsmData + + +class ChangesetTagsDict(TypedDict): + str: str + + +class HttpResponse: + status_code: int + content: str + reason: str + + +class SessionLike(Protocol): + auth: Any + headers: dict + + def request(method: str, path: str, data: dict) -> HttpResponse: ...