Skip to content

Commit de71e7e

Browse files
committed
docs: about writing custom objects
1 parent a9157c4 commit de71e7e

File tree

4 files changed

+93
-20
lines changed

4 files changed

+93
-20
lines changed

docs/reference/Dataclasses.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,10 @@ valid.
4242

4343
::: osmium.osm.Box
4444
::: osmium.osm.Location
45+
46+
## Mutable OSM objects
47+
48+
::: osmium.osm.mutable.OSMObject
49+
::: osmium.osm.mutable.Node
50+
::: osmium.osm.mutable.Way
51+
::: osmium.osm.mutable.Relation

docs/user_manual/06-Writing-Data.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,59 @@ You can also write data that is not based on OSM input data at all. The write
6969
functions will accept any Python object that mimics the attributes of a
7070
node, way or relation.
7171

72+
Here is a simple example that writes out four random points:
73+
74+
!!! example
75+
``` python
76+
from random import uniform
77+
78+
class RandomNode:
79+
def __init__(self, name, id):
80+
self.id = id
81+
self.location = (uniform(-180, 180), uniform(-90, 90))
82+
self.tags = {'name': name}
83+
84+
with osmium.SimpleWriter('points.opl') as writer:
85+
for i in range(4):
86+
writer.add_node(RandomNode(f"Random {i}", i))
87+
```
88+
89+
The following table gives an overview over the recognised attributes and
90+
acceptable types. If an attribute is missing, then pyosmium will choose a
91+
suitable default or leave the attribute out completely from the output if
92+
that is possible.
93+
94+
| attribute | types |
95+
|-----------|----------------------------|
96+
| id | `int` |
97+
| version | `int` (positive non-zero value) |
98+
| visible | `bool` |
99+
| changeset | `int` (positive non-zero value) |
100+
| timestamp | `str` or `datetime` (will be translated to UTC first) |
101+
| uid | `int` |
102+
| tags | [osmium.osm.TagList][], a dict-like object or a list of tuples, where each tuple contains a (key, value) string pair |
103+
| user | `str` |
104+
| location | _(node only)_ [osmium.osm.Location][] or a tuple of lon/lat coordinates |
105+
| nodes | _(way only)_ [osmium.osm.NodeRefList][] or a list consisting of either [osmium.osm.NodeRef][]s or simple node ids |
106+
| members | _(relation only)_ [osmium.osm.RelationMemberList][] or a list consisting of either [osmium.osm.RelationMember][]s or tuples of `(type, id, role)`. The member type must be a single character 'n', 'w' or 'r'. |
107+
108+
The `osmium.osm.mutable` module offers pure Python-object versions of `Node`,
109+
`Way` and `Relation` to make the creation of custom objects easier. Any of
110+
the allowable attributes may be set in the constructor. This makes the
111+
example for writing random points a bit shorter:
112+
113+
!!! example
114+
``` python
115+
from random import uniform
116+
117+
with osmium.SimpleWriter('points.opl') as writer:
118+
for i in range(4):
119+
writer.add_node(osmium.osm.mutable.Node(
120+
id=i, location = (uniform(-180, 180), uniform(-90, 90)),
121+
tags={'name': f"Random {i}"}))
122+
```
123+
124+
72125
## Writer types
73126

74127
pyosmium implements three different writer classes: the basic

src/osmium/osm/mutable.py

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,23 @@
1919
Sequence[Union[osmium.osm.RelationMember, Tuple[str, int, str]]]]
2020

2121
class OSMObject:
22-
"""Mutable version of ``osmium.osm.OSMObject``. It exposes the following
23-
attributes ``id``, ``version``, ``visible``, ``changeset``, ``timestamp``,
24-
``uid`` and ``tags``. Timestamps may be strings or datetime objects.
25-
Tags can be an osmium.osm.TagList, a dict-like object
26-
or a list of tuples, where each tuple contains a (key value) string pair.
27-
28-
If the ``base`` parameter is given in the constructor, then the object
29-
will be initialised first from the attributes of this base object.
22+
""" Mutable version of [osmium.osm.OSMObject][].
3023
"""
3124

3225
def __init__(self, base: Optional['OSMObjectLike'] = None,
3326
id: Optional[int] = None, version: Optional[int] = None,
3427
visible: Optional[bool] = None, changeset: Optional[int] = None,
3528
timestamp: Optional[datetime] = None, uid: Optional[int] = None,
3629
tags: Optional['TagSequence'] = None, user: Optional[str] = None) -> None:
30+
""" Initialise an object with the following optional
31+
attributes: `id`, `version`, `visible`, `changeset`, `timestamp`,
32+
`uid` and `tags`. Timestamps may be strings or datetime objects.
33+
Tags can be an osmium.osm.TagList, a dict-like object
34+
or a list of tuples, where each tuple contains a (key value) string pair.
35+
36+
If the `base` parameter is given in the constructor, then the object
37+
will be initialised first from the attributes of this base object.
38+
"""
3739
if base is None:
3840
self.id = id
3941
self.version = version
@@ -55,14 +57,18 @@ def __init__(self, base: Optional['OSMObjectLike'] = None,
5557

5658

5759
class Node(OSMObject):
58-
"""The mutable version of ``osmium.osm.Node``. It inherits all attributes
59-
from osmium.osm.mutable.OSMObject and adds a `location` attribute. This
60-
may either be an `osmium.osm.Location` or a tuple of lon/lat coordinates.
60+
""" The mutable version of [osmium.osm.Node][].
6161
"""
6262

6363
def __init__(self, base: Optional[Union['Node', 'osmium.osm.Node']] = None,
6464
location: Optional['LocationLike'] = None,
6565
**attrs: Any) -> None:
66+
""" Initialise a node with all optional attributes
67+
from osmium.osm.mutable.OSMObject as well as a `location` attribute.
68+
This may either be an [osmium.osm.Location][] or a tuple of
69+
lon/lat coordinates.
70+
71+
"""
6672
OSMObject.__init__(self, base=base, **attrs)
6773
if base is None:
6874
self.location = location
@@ -71,30 +77,35 @@ def __init__(self, base: Optional[Union['Node', 'osmium.osm.Node']] = None,
7177

7278

7379
class Way(OSMObject):
74-
"""The mutable version of ``osmium.osm.Way``. It inherits all attributes
75-
from osmium.osm.mutable.OSMObject and adds a `nodes` attribute. This may
76-
either be and ``osmium.osm.NodeList`` or a list consisting of
77-
``osmium.osm.NodeRef`` or simple node ids.
80+
""" The mutable version of [osmium.osm.Way][].
7881
"""
7982

8083
def __init__(self, base: Optional[Union['Way', 'osmium.osm.Way']] = None,
8184
nodes: Optional['NodeSequence'] = None, **attrs: Any) -> None:
85+
""" Initialise a way with all optional attributes
86+
from osmium.osm.mutable.OSMObject as well as a `nodes` attribute.
87+
This may either be an [osmium.osm.NodeRefList][] or a list
88+
consisting of [osmium.osm.NodeRef][] or simple node ids.
89+
"""
8290
OSMObject.__init__(self, base=base, **attrs)
8391
if base is None:
8492
self.nodes = nodes
8593
else:
8694
self.nodes = nodes if nodes is not None else base.nodes
8795

8896
class Relation(OSMObject):
89-
"""The mutable version of ``osmium.osm.Relation``. It inherits all attributes
90-
from osmium.osm.mutable.OSMObject and adds a `members` attribute. This
91-
may either be an ``osmium.osm.RelationMemberList`` or a list consisting
92-
of ``osmium.osm.RelationMember`` or tuples of (type, id, role). The
93-
member type should be a single character 'n', 'w' or 'r'.
97+
""" The mutable version of [osmium.osm.Relation][].
9498
"""
9599

96100
def __init__(self, base: Optional[Union['Relation', 'osmium.osm.Relation']] = None,
97101
members: Optional['MemberSequence'] = None, **attrs: Any) -> None:
102+
""" Initialise a relation with all optional attributes
103+
from osmium.osm.mutable.OSMObject as well as a `members` attribute.
104+
This may either be an [osmium.osm.RelationMemberList][] or
105+
a list consisting of [osmium.osm.RelationMember][] or
106+
tuples of (type, id, role). The
107+
member type must be a single character 'n', 'w' or 'r'.
108+
"""
98109
OSMObject.__init__(self, base=base, **attrs)
99110
if base is None:
100111
self.members = members

test/test_writer.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
# Copyright (C) 2022 Sarah Hoffmann.
66
from contextlib import contextmanager
77
from collections import OrderedDict
8+
from datetime import datetime, timezone, timedelta
89
import uuid
910

1011
import pytest
@@ -54,6 +55,7 @@ def __init__(self, **params):
5455
(O(uid=987), '0 v0 dV c0 t i987 u T'),
5556
(O(timestamp='2012-04-14T20:58:35Z'), '0 v0 dV c0 t2012-04-14T20:58:35Z i0 u T'),
5657
(O(timestamp=mkdate(2009, 4, 14, 20, 58, 35)), '0 v0 dV c0 t2009-04-14T20:58:35Z i0 u T'),
58+
(O(timestamp=datetime(2009, 4, 14, 20, 58, 35, tzinfo=timezone(timedelta(hours=1)))), '0 v0 dV c0 t2009-04-14T19:58:35Z i0 u T'),
5759
(O(timestamp='1970-01-01T00:00:01Z'), '0 v0 dV c0 t1970-01-01T00:00:01Z i0 u T')
5860
])
5961
class TestWriteAttributes:

0 commit comments

Comments
 (0)