Skip to content

Introduce type annotations #211

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Sep 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions lib/osm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,17 @@ PYBIND11_MODULE(_osm, m) {
py::return_value_policy::reference_internal,
"Extend the box to include the given location. If the location "
"is invalid the box remains unchanged. If the box is invalid, it "
"will contain only the location after the operation.")
"will contain only the location after the operation. "
"Returns a reference to itself.")
.def("extend",
(osmium::Box& (osmium::Box::*)(osmium::Box const &))
&osmium::Box::extend,
py::arg("box"),
py::return_value_policy::reference_internal,
"Extend the box to include the given box. If the box to be added "
"is invalid the input box remains unchanged. If the input box is invalid, it "
"will become equal to the box that was added.")
"will become equal to the box that was added. "
"Returns a reference to itself.")
.def("valid", &osmium::Box::valid,
"Check if the box coordinates are defined and with the usual bounds.")
.def("size", &osmium::Box::size,
Expand Down
2 changes: 1 addition & 1 deletion lib/osmium.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ PYBIND11_MODULE(_osmium, m) {
"Apply a chain of handlers.");
m.def("apply", [](osmium::io::Reader &rd, NodeLocationHandler &h)
{ py::gil_scoped_release release; osmium::apply(rd, h); },
py::arg("reader"), py::arg("handler"),
py::arg("reader"), py::arg("node_handler"),
"Apply a chain of handlers.");
m.def("apply", [](osmium::io::Reader &rd, NodeLocationHandler &l,
BaseHandler &h)
Expand Down
3 changes: 3 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ def build_extension(self, ext):
ext_modules=[CMakeExtension('cmake_example')],
packages = ['osmium', 'osmium/osm', 'osmium/replication'],
package_dir = {'' : 'src'},
package_data = { 'osmium': ['py.typed', '*.pyi',
'replication/_replication.pyi',
'osm/_osm.pyi']},
python_requires = ">=3.6",
install_requires = ['requests'],
cmdclass=dict(build_ext=CMakeBuild, sdist=Pyosmium_sdist),
Expand Down
55 changes: 55 additions & 0 deletions src/osmium/_osmium.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from typing import overload, ByteString, Union
import os

import osmium.index
import osmium.io

StrPath = Union[str, 'os.PathLike[str]']

class InvalidLocationError(Exception): ...

class NodeLocationsForWays:
def __init__(self, locations: osmium.index.LocationTable) -> None: ...
def ignore_errors(self) -> None: ...

class BaseHandler: ...

class SimpleHandler(BaseHandler):
def __init__(self) -> None: ...
def apply_buffer(self, buffer: Union[ByteString, str], format: str, locations: bool = ..., idx: str = ...) -> None: ...
def apply_file(self, filename: StrPath, locations: bool = ..., idx: str = ...) -> None: ...

class MergeInputReader:
def __init__(self) -> None: ...
def add_buffer(self, buffer: Union[ByteString, str], format: str) -> int: ...
def add_file(self, file: str) -> int: ...
def apply(self, handler: BaseHandler, idx: str = ..., simplify: bool = ...) -> None: ...
def apply_to_reader(self, reader: osmium.io.Reader, writer: osmium.io.Writer, with_history: bool = ...) -> None: ...

class WriteHandler(BaseHandler):
@overload
def __init__(self, filename: str, bufsz: int, filetype: str) -> None: ...
@overload
def __init__(self, filename: str, bufsz: int) -> None: ...
@overload
def __init__(self, filename: str) -> None: ...
def close(self) -> None: ...

class SimpleWriter:
@overload
def __init__(self, filename: str, bufsz: int, header: osmium.io.Header) -> None: ...
@overload
def __init__(self, filename: str, bufsz: int) -> None: ...
@overload
def __init__(self, filename: str) -> None: ...
def add_node(self, node: object) -> None: ...
def add_relation(self, relation: object) -> None: ...
def add_way(self, way: object) -> None: ...
def close(self) -> None: ...

@overload
def apply(reader: osmium.io.Reader, handler: BaseHandler) -> None: ...
@overload
def apply(reader: osmium.io.Reader, node_handler: NodeLocationsForWays) -> None: ...
@overload
def apply(reader: osmium.io.Reader, node_handler: NodeLocationsForWays, handler: BaseHandler) -> None: ...
99 changes: 99 additions & 0 deletions src/osmium/geom.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
from typing import ClassVar

from typing import overload
import osmium.osm
ALL: use_nodes
BACKWARD: direction
FORWARD: direction
UNIQUE: use_nodes


class use_nodes:
ALL: ClassVar[use_nodes] = ...
UNIQUE: ClassVar[use_nodes] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...

class direction:
BACKWARD: ClassVar[direction] = ...
FORWARD: ClassVar[direction] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...

class Coordinates:
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, cx: float, cy: float) -> None: ...
@overload
def __init__(self, location: osmium.osm.Location) -> None: ...
def valid(self) -> bool: ...
@property
def x(self) -> float: ...
@property
def y(self) -> float: ...


class GeoJSONFactory:
def __init__(self) -> None: ...
@overload
def create_linestring(self, list: osmium.osm.WayNodeList, use_nodes: use_nodes = ..., direction: direction = ...) -> str: ...
@overload
def create_linestring(self, way: osmium.osm.Way, use_nodes: use_nodes = ..., direction: direction = ...) -> str: ...
def create_multipolygon(self, area: osmium.osm.Area) -> str: ...
@overload
def create_point(self, location: osmium.osm.Location) -> str: ...
@overload
def create_point(self, node: osmium.osm.Node) -> str: ...
@overload
def create_point(self, ref: osmium.osm.NodeRef) -> str: ...
@property
def epsg(self) -> int: ...
@property
def proj_string(self) -> str: ...

class WKBFactory:
def __init__(self) -> None: ...
@overload
def create_linestring(self, list: osmium.osm.WayNodeList, use_nodes: use_nodes = ..., direction: direction = ...) -> str: ...
@overload
def create_linestring(self, way: osmium.osm.Way, use_nodes: use_nodes = ..., direction: direction = ...) -> str: ...
def create_multipolygon(self, area: osmium.osm.Area) -> str: ...
@overload
def create_point(self, location: osmium.osm.Location) -> str: ...
@overload
def create_point(self, node: osmium.osm.Node) -> str: ...
@overload
def create_point(self, ref: osmium.osm.NodeRef) -> str: ...
@property
def epsg(self) -> int: ...
@property
def proj_string(self) -> str: ...

class WKTFactory:
def __init__(self) -> None: ...
@overload
def create_linestring(self, list: osmium.osm._osm.WayNodeList, use_nodes: use_nodes = ..., direction: direction = ...) -> str: ...
@overload
def create_linestring(self, way: osmium.osm._osm.Way, use_nodes: use_nodes = ..., direction: direction = ...) -> str: ...
def create_multipolygon(self, area: osmium.osm._osm.Area) -> str: ...
@overload
def create_point(self, location: osmium.osm._osm.Location) -> str: ...
@overload
def create_point(self, node: osmium.osm._osm.Node) -> str: ...
@overload
def create_point(self, ref: osmium.osm._osm.NodeRef) -> str: ...
@property
def epsg(self) -> int: ...
@property
def proj_string(self) -> str: ...

def haversine_distance(list: osmium.osm.WayNodeList) -> float: ...
def lonlat_to_mercator(coordinate: Coordinates) -> Coordinates: ...
def mercator_to_lonlat(coordinate: Coordinates) -> Coordinates: ...
23 changes: 17 additions & 6 deletions src/osmium/helper.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
from typing import Optional, Callable, TypeVar

from osmium._osmium import SimpleHandler
from osmium.osm import Node, Way, Relation, Area, Changeset

T = TypeVar('T')
HandlerFunc = Optional[Callable[[T], None]]


def make_simple_handler(node=None, way=None, relation=None, area=None, changeset=None):
def make_simple_handler(node: HandlerFunc[Node] = None,
way: HandlerFunc[Way] = None,
relation: HandlerFunc[Relation] = None,
area: HandlerFunc[Area] = None,
changeset: HandlerFunc[Changeset] = None) -> SimpleHandler:
""" Convenience function that creates a `SimpleHandler` from a set of
callback functions. Each of the parameters takes an optional callable
that must expect a single positional parameter with the object being
Expand All @@ -10,14 +21,14 @@ class __HandlerWithCallbacks(SimpleHandler):
pass

if node is not None:
__HandlerWithCallbacks.node = staticmethod(node)
setattr(__HandlerWithCallbacks, "node", staticmethod(node))
if way is not None:
__HandlerWithCallbacks.way = staticmethod(way)
setattr(__HandlerWithCallbacks, "way", staticmethod(way))
if relation is not None:
__HandlerWithCallbacks.relation = staticmethod(relation)
setattr(__HandlerWithCallbacks, "relation", staticmethod(relation))
if area is not None:
__HandlerWithCallbacks.area = staticmethod(area)
setattr(__HandlerWithCallbacks, "area", staticmethod(area))
if changeset is not None:
__HandlerWithCallbacks.changeset = staticmethod(changeset)
setattr(__HandlerWithCallbacks, "changeset", staticmethod(changeset))

return __HandlerWithCallbacks()
12 changes: 12 additions & 0 deletions src/osmium/index.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from typing import List

import osmium.osm

class LocationTable:
def clear(self) -> None: ...
def get(self, id: int) -> osmium.osm.Location: ...
def set(self, id: int, loc: osmium.osm.Location) -> None: ...
def used_memory(self) -> int: ...

def create_map(map_type: str) -> LocationTable: ...
def map_types() -> List[str]: ...
41 changes: 41 additions & 0 deletions src/osmium/io.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from typing import Any

from typing import overload

import osmium.osm

class File:
has_multiple_object_versions: bool
@overload
def __init__(self, filename: str) -> None: ...
@overload
def __init__(self, filename: str, format: str) -> None: ...
def parse_format(self, arg0: str) -> None: ...

class Header:
has_multiple_object_versions: bool
def __init__(self) -> None: ...
def add_box(self, box: osmium.osm.Box) -> Header: ...
def box(self) -> osmium.osm.Box: ...
def get(self, key: str, default: str = ...) -> str: ...
def set(self, key: str, value: str) -> None: ...

class Reader:
@overload
def __init__(self, filename: str) -> None: ...
@overload
def __init__(self, filename: str, types: osmium.osm.osm_entity_bits) -> None: ...
def close(self) -> None: ...
def eof(self) -> bool: ...
def header(self) -> Header: ...

class Writer:
@overload
def __init__(self, filename: str) -> None: ...
@overload
def __init__(self, ffile: File) -> None: ...
@overload
def __init__(self, filename: str, header: Header) -> None: ...
@overload
def __init__(self, ffile: File, header: Header) -> None: ...
def close(self) -> int: ...
41 changes: 11 additions & 30 deletions src/osmium/osm/__init__.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,24 @@
import osmium.osm.mutable
from typing import Any, Callable, Sequence

from osmium.osm.mutable import create_mutable_node, create_mutable_way, create_mutable_relation
from ._osm import *

def create_mutable_node(node, **args):
""" Create a mutable node replacing the properties given in the
named parameters. Note that this function only creates a shallow
copy which is still bound to the scope of the original object.
"""
return osmium.osm.mutable.Node(base=node, **args)

def create_mutable_way(way, **args):
""" Create a mutable way replacing the properties given in the
named parameters. Note that this function only creates a shallow
copy which is still bound to the scope of the original object.
"""
return osmium.osm.mutable.Way(base=way, **args)

def create_mutable_relation(rel, **args):
""" Create a mutable relation replacing the properties given in the
named parameters. Note that this function only creates a shallow
copy which is still bound to the scope of the original object.
"""
return osmium.osm.mutable.Relation(base=rel, **args)

Node.replace = create_mutable_node
Way.replace = create_mutable_way
Relation.replace = create_mutable_relation

def _make_repr(*attr_list):
setattr(Node, 'replace', create_mutable_node)
setattr(Way, 'replace', create_mutable_way)
setattr(Relation, 'replace', create_mutable_relation)

def _make_repr(*attrs: str) -> Callable[[object], str]:
fmt_string = 'osmium.osm.{0}('\
+ ', '.join([f'{x}={{1.{x}!r}}' for x in attr_list])\
+ ', '.join([f'{x}={{1.{x}!r}}' for x in attrs])\
+ ')'

return lambda o: fmt_string.format(o.__class__.__name__, o)

def _list_repr(obj):
def _list_repr(obj: Sequence[Any]) -> str:
return 'osmium.osm.{}([{}])'.format(obj.__class__.__name__,
', '.join(map(repr, obj)))

def _list_elipse(obj):
def _list_elipse(obj: Sequence[Any]) -> str:
objects = ','.join(map(str, obj))
if len(objects) > 50:
objects = objects[:47] + '...'
Expand Down
Loading