[Git][debian-gis-team/python-osmapi][upstream] New upstream version 4.3.0+ds
Bas Couwenberg (@sebastic)
gitlab at salsa.debian.org
Tue Jan 21 14:29:18 GMT 2025
Bas Couwenberg pushed to branch upstream at Debian GIS Project / python-osmapi
Commits:
5bb1c0b6 by Bas Couwenberg at 2025-01-21T15:23:18+01:00
New upstream version 4.3.0+ds
- - - - -
13 changed files:
- .github/workflows/build.yml
- CHANGELOG.md
- README.md
- + examples/error_handling.py
- + examples/log_output.py
- examples/write_to_osm.py
- osmapi/OsmApi.py
- osmapi/__init__.py
- osmapi/errors.py
- osmapi/http.py
- osmapi/parser.py
- tests/changeset_test.py
- tests/fixtures/test_NoteCreate_wo_auth.xml
Changes:
=====================================
.github/workflows/build.yml
=====================================
@@ -2,7 +2,7 @@ name: Test osmapi package
on:
pull_request:
push:
- branches: [master, develop]
+ branches: [main, develop]
jobs:
test:
runs-on: ubuntu-latest
=====================================
CHANGELOG.md
=====================================
@@ -4,6 +4,16 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
## [Unreleased]
+## [4.3.0] - 2025-01-21
+### Added
+- New `ConnectionApiError` when a connection or network error occurs (see issue #176, thanks [Mateusz Konieczny](https://github.com/matkoniecz))
+-
+### Changed
+- Use the pattern `raise XYError from e` to explicitly add the original exceptions as the cause for a new (wrapped) exception.
+
+### Removed
+- Remove u string prefix (see PR #180, thanks [Boris Verkhovskiy](https://github.com/verhovsky))
+
## [4.2.0] - 2024-08-08
### Added
- Add a new `timeout` parameter to `OsmApi` which allows to set a timeout in seconds (default is 30s) for the API requests (see issue #170, thanks [Mateusz Konieczny](https://github.com/matkoniecz))
@@ -357,7 +367,8 @@ Miroslav Šedivý
- `Fixed` for any bug fixes.
- `Security` to invite users to upgrade in case of vulnerabilities.
-[Unreleased]: https://github.com/metaodi/osmapi/compare/v4.2.0...HEAD
+[Unreleased]: https://github.com/metaodi/osmapi/compare/v4.3.0...HEAD
+[4.3.0]: https://github.com/metaodi/osmapi/compare/v4.2.0...v4.3.0
[4.2.0]: https://github.com/metaodi/osmapi/compare/v4.1.0...v4.2.0
[4.1.0]: https://github.com/metaodi/osmapi/compare/v4.0.0...v4.1.0
[4.0.0]: https://github.com/metaodi/osmapi/compare/v3.1.0...v4.0.0
=====================================
README.md
=====================================
@@ -3,7 +3,7 @@ osmapi
[![Build osmapi](https://github.com/metaodi/osmapi/actions/workflows/build.yml/badge.svg)](https://github.com/metaodi/osmapi/actions/workflows/build.yml)
[![Version](https://img.shields.io/pypi/v/osmapi.svg)](https://pypi.python.org/pypi/osmapi/)
-[![License](https://img.shields.io/pypi/l/osmapi.svg)](https://github.com/metaodi/osmapi/blob/master/LICENSE.txt)
+[![License](https://img.shields.io/pypi/l/osmapi.svg)](https://github.com/metaodi/osmapi/blob/develop/LICENSE.txt)
[![Coverage](https://img.shields.io/coveralls/metaodi/osmapi/develop.svg)](https://coveralls.io/r/metaodi/osmapi?branch=develop)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit)
@@ -26,7 +26,7 @@ The build the documentation locally, you can use
make docs
This project uses GitHub Pages to publish its documentation.
-To update the online documentation, you need to re-generate the documentation with the above command and update the `master` branch of this repository.
+To update the online documentation, you need to re-generate the documentation with the above command and update the `main` branch of this repository.
## Examples
@@ -40,32 +40,21 @@ Check the [examples directory](https://github.com/metaodi/osmapi/tree/develop/ex
>>> import osmapi
>>> api = osmapi.OsmApi()
>>> print(api.NodeGet(123))
-{u'changeset': 532907, u'uid': 14298,
-u'timestamp': u'2007-09-29T09:19:17Z',
-u'lon': 10.790009299999999, u'visible': True,
-u'version': 1, u'user': u'Mede',
-u'lat': 59.9503044, u'tag': {}, u'id': 123}
+{'changeset': 532907, 'uid': 14298,
+'timestamp': '2007-09-29T09:19:17Z',
+'lon': 10.790009299999999, 'visible': True,
+'version': 1, 'user': 'Mede',
+'lat': 59.9503044, 'tag': {}, 'id': 123}
```
-### Constructor
-
-```python
-import osmapi
-api = osmapi.OsmApi(api="https://api06.dev.openstreetmap.org", username = "you", password = "***")
-api = osmapi.OsmApi(username = "you", passwordfile = "/etc/mypasswords")
-api = osmapi.OsmApi(passwordfile = "/etc/mypasswords") # if only the passwordfile is specified, the credentials on the first line of the file will be used
-```
-
-Note: Each line in the password file should have the format _user:password_
-
### Write to OpenStreetMap
```python
>>> import osmapi
->>> api = osmapi.OsmApi(api="https://api06.dev.openstreetmap.org", username = u"metaodi", password = u"*******")
->>> api.ChangesetCreate({u"comment": u"My first test"})
->>> print(api.NodeCreate({u"lon":1, u"lat":1, u"tag": {}}))
-{u'changeset': 532907, u'lon': 1, u'version': 1, u'lat': 1, u'tag': {}, u'id': 164684}
+>>> api = osmapi.OsmApi(api="https://api06.dev.openstreetmap.org", username = "metaodi", password = "*******")
+>>> api.ChangesetCreate({"comment": "My first test"})
+>>> print(api.NodeCreate({"lon":1, "lat":1, "tag": {}}))
+{'changeset': 532907, 'lon': 1, 'version': 1, 'lat': 1, 'tag': {}, 'id': 164684}
>>> api.ChangesetClose()
```
@@ -107,6 +96,24 @@ with api.Changeset({"comment": "My first test"}) as changeset_id:
An alternative way using the `requests-oauthlib` library can be found
[in the examples](https://github.com/metaodi/osmapi/blob/develop/examples/oauth2.py).
+
+### User agent / credit for application
+
+To credit the application that supplies changes to OSM, an `appid` can be provided.
+This is a string identifying the application.
+If this is omitted "osmapi" is used.
+
+```python
+api = osmapi.OsmApi(
+ api="https://api06.dev.openstreetmap.org",
+ appid="MyOSM Script"
+)
+```
+
+ If then changesets are made using this osmapi instance, they get a tag `created_by` with the following content: `MyOSM Script (osmapi/<version>)`
+
+ [Example changeset of `Kort` using osmapi](https://www.openstreetmap.org/changeset/55197785)
+
## Note about imports / automated edits
Scripted imports and automated edits should only be carried out by those with experience and understanding of the way the OpenStreetMap community creates maps, and only with careful **planning** and **consultation** with the local community.
@@ -140,8 +147,8 @@ To create a new release, follow these steps (please respect [Semantic Versioning
1. Adapt the version number in `osmapi/__init__.py`
1. Update the CHANGELOG with the version
1. Re-build the documentation (`make docs`)
-1. Create a pull request to merge develop into master (make sure the tests pass!)
-1. Create a [new release/tag on GitHub](https://github.com/metaodi/osmapi/releases) (on the master branch)
+1. Create a [pull request to merge develop into main](https://github.com/metaodi/osmapi/compare/main...develop) (make sure the tests pass!)
+1. Create a [new release/tag on GitHub](https://github.com/metaodi/osmapi/releases) (on the main branch)
1. The [publication on PyPI](https://pypi.python.org/pypi/osmapi) happens via [GitHub Actions](https://github.com/metaodi/osmapi/actions/workflows/publish_python.yml) on every tagged commit
## Attribution
=====================================
examples/error_handling.py
=====================================
@@ -0,0 +1,144 @@
+from dotenv import load_dotenv, find_dotenv
+from oauthcli import OpenStreetMapDevAuth
+from oauthlib.oauth2.rfc6749.errors import OAuth2Error
+import logging
+import os
+import osmapi
+import requests
+import subprocess
+import sys
+import urllib3
+
+
+load_dotenv(find_dotenv())
+
+# logging setup
+log = logging.getLogger(__name__)
+loglevel = logging.DEBUG
+logging.basicConfig(
+ format="%(asctime)s %(name)s %(levelname)-8s %(message)s",
+ level=loglevel,
+ datefmt="%Y-%m-%d %H:%M:%S",
+)
+logging.captureWarnings(True)
+
+# shut up DEBUG messages of specific loggers
+logging.getLogger(osmapi.dom.__name__).setLevel(logging.INFO)
+logging.getLogger(urllib3.__name__).setLevel(logging.INFO)
+
+
+def clear_screen():
+ # check and make call for specific operating system
+ _ = subprocess.call("clear" if os.name == "posix" else "cls")
+
+
+# The error handling with osmapi is very easy, simply catch the
+# exception for the specific case you want to handle.
+# - All osmapi excepctions are child classes of osmapi.OsmApiError
+# - Errors that result from the communication with the OSM server osmapi.ApiError
+# - There are a number of subclasses to differantiate the different errors
+# - catch more specific errors first, then use more general error classes
+
+# Upload data to OSM without a changeset
+log.debug("Try to write data to OSM without a changeset")
+api = osmapi.OsmApi(api="https://api06.dev.openstreetmap.org")
+try:
+ node1 = api.NodeCreate({"lon": 1, "lat": 1, "tag": {}})
+except osmapi.NoChangesetOpenError as e:
+ log.exception(e)
+ log.debug("There is no open changeset")
+input("Press Enter to continue...")
+clear_screen()
+
+
+# wrong server: ConnectionError
+log.debug("Connect to wrong server...")
+api = osmapi.OsmApi(api="https://invalid.server.name")
+try:
+ api.ChangesetGet(123)
+except osmapi.ConnectionApiError as e:
+ log.exception(e)
+ log.debug("Error connecting to server")
+input("Press Enter to continue...")
+clear_screen()
+
+
+# changeset not found: ElementNotFoundApiError
+log.debug("Request non-existent changeset id...")
+api = osmapi.OsmApi(api="https://api06.dev.openstreetmap.org")
+try:
+ api.ChangesetGet(111111111111)
+except osmapi.ElementNotFoundApiError as e:
+ log.exception(e)
+ log.debug("Changeset not found")
+input("Press Enter to continue...")
+clear_screen()
+
+
+# unauthorized request
+log.debug("Try to add data with wrong authorization")
+try:
+ s = requests.Session()
+ s.auth = ("user", "pass")
+ api = osmapi.OsmApi(api="https://api06.dev.openstreetmap.org", session=s)
+ with api.Changeset({"comment": "My first test"}) as changeset_id:
+ node1 = api.NodeCreate({"lon": 1, "lat": 1, "tag": {}})
+except osmapi.UnauthorizedApiError as e:
+ log.exception(e)
+ log.debug("Unauthorized to make this request")
+input("Press Enter to continue...")
+clear_screen()
+
+# request without auhorization
+log.debug("Try to add data without authorization")
+try:
+ api = osmapi.OsmApi(api="https://api06.dev.openstreetmap.org")
+ with api.Changeset({"comment": "My first test"}) as changeset_id:
+ node1 = api.NodeCreate({"lon": 1, "lat": 1, "tag": {}})
+except osmapi.UsernamePasswordMissingError as e:
+ log.exception(e)
+ log.debug("Username/Password or authorization missing")
+input("Press Enter to continue...")
+clear_screen()
+
+
+# a more or less complete "real-life" example
+client_id = os.getenv("OSM_OAUTH_CLIENT_ID")
+client_secret = os.getenv("OSM_OAUTH_CLIENT_SECRET")
+
+try:
+ auth = OpenStreetMapDevAuth(
+ client_id, client_secret, ["write_api", "write_notes"]
+ ).auth_code()
+except OAuth2Error as e:
+ log.exception(e)
+ log.debug("An OAuth2 error occured")
+ sys.exit(1)
+
+try:
+ api = osmapi.OsmApi(api="https://api06.dev.openstreetmap.org", session=auth.session)
+ with api.Changeset({"comment": "My first test"}) as changeset_id:
+ log.debug(f"Part of Changeset {changeset_id}")
+ node1 = api.NodeCreate({"lon": 1, "lat": 1, "tag": {}})
+ log.debug(node1)
+
+ # get all the info from the closed changeset
+ changeset = api.ChangesetGet(changeset_id)
+ log.debug(changeset)
+ exit_code = 0
+except osmapi.ConnectionApiError as e:
+ log.debug(f"Connection error: {str(e)}")
+ exit_code = 1
+ # display error for user, try again?
+except osmapi.ElementNotFoundApiError as e:
+ log.debug(f"Changeset not found: {str(e)}")
+ exit_code = 1
+except osmapi.ApiError as e:
+ log.debug(f"Error on the API side: {str(e)}")
+ exit_code = 1
+except osmapi.OsmApiError as e:
+ log.debug(f"Some other error: {str(e)}")
+ exit_code = 1
+finally:
+ log.debug(f"Exit code: {exit_code}")
+ sys.exit(exit_code)
=====================================
examples/log_output.py
=====================================
@@ -0,0 +1,23 @@
+import osmapi
+import logging
+from pprint import pformat
+import urllib3
+
+log = logging.getLogger(__name__)
+
+loglevel = logging.DEBUG
+logging.basicConfig(
+ format="%(asctime)s %(name)s %(levelname)-8s %(message)s",
+ level=loglevel,
+ datefmt="%Y-%m-%d %H:%M:%S",
+)
+logging.captureWarnings(True)
+
+# shut up DEBUG messages of specific loggers
+logging.getLogger(osmapi.dom.__name__).setLevel(logging.INFO)
+logging.getLogger(urllib3.__name__).setLevel(logging.INFO)
+
+
+api = osmapi.OsmApi(api="https://api06.dev.openstreetmap.org")
+node1 = api.NodeGet("1111")
+log.debug(pformat(node1))
=====================================
examples/write_to_osm.py
=====================================
@@ -1,14 +1,21 @@
+# install cli-oauth2 for requests: pip install cli-oauth2
+from oauthcli import OpenStreetMapDevAuth
import osmapi
from dotenv import load_dotenv, find_dotenv
import os
load_dotenv(find_dotenv())
-user = os.getenv("OSM_USER")
-pw = os.getenv("OSM_PASS")
-api = osmapi.OsmApi(
- api="https://api06.dev.openstreetmap.org", username=user, password=pw
-)
+# load secrets for OAuth
+client_id = os.getenv("OSM_OAUTH_CLIENT_ID")
+client_secret = os.getenv("OSM_OAUTH_CLIENT_SECRET")
+
+auth = OpenStreetMapDevAuth(
+ client_id, client_secret, ["write_api", "write_notes"]
+).auth_code()
+
+
+api = osmapi.OsmApi(api="https://api06.dev.openstreetmap.org", session=auth.session)
with api.Changeset({"comment": "My first test"}) as changeset_id:
print(f"Part of Changeset {changeset_id}")
node1 = api.NodeCreate({"lon": 1, "lat": 1, "tag": {}})
=====================================
osmapi/OsmApi.py
=====================================
@@ -1183,7 +1183,7 @@ class OsmApi:
with osmapi.Changeset({"comment": "Import script XYZ"}) as changeset_id:
print(f"Part of changeset {changeset_id}")
- api.NodeCreate({u"lon":1, u"lat":1, u"tag": {}})
+ api.NodeCreate({"lon":1, "lat":1, "tag": {}})
If `ChangesetTags` are given, this tags are applied (key/value).
@@ -1265,7 +1265,9 @@ class OsmApi:
)
except errors.ApiError as e:
if e.status == 409:
- raise errors.ChangesetClosedApiError(e.status, e.reason, e.payload)
+ raise errors.ChangesetClosedApiError(
+ e.status, e.reason, e.payload
+ ) from e
else:
raise
return self._CurrentChangesetId
@@ -1332,7 +1334,9 @@ class OsmApi:
self._CurrentChangesetId = 0
except errors.ApiError as e:
if e.status == 409:
- raise errors.ChangesetClosedApiError(e.status, e.reason, e.payload)
+ raise errors.ChangesetClosedApiError(
+ e.status, e.reason, e.payload
+ ) from e
else:
raise
return CurrentChangesetId
@@ -1376,7 +1380,9 @@ class OsmApi:
if e.status == 409 and re.search(
r"The changeset .* was closed at .*", e.payload
):
- raise errors.ChangesetClosedApiError(e.status, e.reason, e.payload)
+ raise errors.ChangesetClosedApiError(
+ e.status, e.reason, e.payload
+ ) from e
else:
raise
try:
@@ -1386,7 +1392,7 @@ class OsmApi:
except (xml.parsers.expat.ExpatError, IndexError) as e:
raise errors.XmlResponseInvalidError(
f"The XML response from the OSM API is invalid: {e!r}"
- )
+ ) from e
for change in ChangesData:
if change["action"] == "delete":
@@ -1509,7 +1515,9 @@ class OsmApi:
)
except errors.ApiError as e:
if e.status == 409:
- raise errors.ChangesetClosedApiError(e.status, e.reason, e.payload)
+ raise errors.ChangesetClosedApiError(
+ e.status, e.reason, e.payload
+ ) from e
else:
raise
changeset = dom.OsmResponseToDom(data, tag="changeset", single=True)
@@ -1548,7 +1556,9 @@ class OsmApi:
)
except errors.ApiError as e:
if e.status == 409:
- raise errors.AlreadySubscribedApiError(e.status, e.reason, e.payload)
+ raise errors.AlreadySubscribedApiError(
+ e.status, e.reason, e.payload
+ ) from e
else:
raise
changeset = dom.OsmResponseToDom(data, tag="changeset", single=True)
@@ -1586,7 +1596,7 @@ class OsmApi:
f"/api/0.6/changeset/{ChangesetId}/unsubscribe", None, forceAuth=True
)
except errors.ElementNotFoundApiError as e:
- raise errors.NotSubscribedApiError(e.status, e.reason, e.payload)
+ raise errors.NotSubscribedApiError(e.status, e.reason, e.payload) from e
changeset = dom.OsmResponseToDom(data, tag="changeset", single=True)
return dom.DomParseChangeset(changeset)
@@ -1767,7 +1777,9 @@ class OsmApi:
result = self._session._post(uri, None, optionalAuth=optionalAuth)
except errors.ApiError as e:
if e.status == 409:
- raise errors.NoteAlreadyClosedApiError(e.status, e.reason, e.payload)
+ raise errors.NoteAlreadyClosedApiError(
+ e.status, e.reason, e.payload
+ ) from e
else:
raise
@@ -1844,13 +1856,17 @@ class OsmApi:
if e.status == 409 and re.search(
r"The changeset .* was closed at .*", e.payload
):
- raise errors.ChangesetClosedApiError(e.status, e.reason, e.payload)
+ raise errors.ChangesetClosedApiError(
+ e.status, e.reason, e.payload
+ ) from e
elif e.status == 409:
- raise errors.VersionMismatchApiError(e.status, e.reason, e.payload)
+ raise errors.VersionMismatchApiError(
+ e.status, e.reason, e.payload
+ ) from e
elif e.status == 412:
raise errors.PreconditionFailedApiError(
e.status, e.reason, e.payload
- )
+ ) from e
else:
raise
OsmData["id"] = int(result.strip())
@@ -1867,13 +1883,17 @@ class OsmApi:
if e.status == 409 and re.search(
r"The changeset .* was closed at .*", e.payload
):
- raise errors.ChangesetClosedApiError(e.status, e.reason, e.payload)
+ raise errors.ChangesetClosedApiError(
+ e.status, e.reason, e.payload
+ ) from e
elif e.status == 409:
- raise errors.VersionMismatchApiError(e.status, e.reason, e.payload)
+ raise errors.VersionMismatchApiError(
+ e.status, e.reason, e.payload
+ ) from e
elif e.status == 412:
raise errors.PreconditionFailedApiError(
e.status, e.reason, e.payload
- )
+ ) from e
else:
raise
OsmData["version"] = int(result.strip())
@@ -1888,13 +1908,17 @@ class OsmApi:
if e.status == 409 and re.search(
r"The changeset .* was closed at .*", e.payload
):
- raise errors.ChangesetClosedApiError(e.status, e.reason, e.payload)
+ raise errors.ChangesetClosedApiError(
+ e.status, e.reason, e.payload
+ ) from e
elif e.status == 409:
- raise errors.VersionMismatchApiError(e.status, e.reason, e.payload)
+ raise errors.VersionMismatchApiError(
+ e.status, e.reason, e.payload
+ ) from e
elif e.status == 412:
raise errors.PreconditionFailedApiError(
e.status, e.reason, e.payload
- )
+ ) from e
else:
raise
OsmData["version"] = int(result.strip())
=====================================
osmapi/__init__.py
=====================================
@@ -1,4 +1,4 @@
-__version__ = "4.2.0"
+__version__ = "4.3.0"
from .OsmApi import * # noqa
from .errors import * # noqa
=====================================
osmapi/errors.py
=====================================
@@ -150,3 +150,10 @@ class TimeoutApiError(ApiError):
"""
Error if the http request ran into a timeout
"""
+
+
+class ConnectionApiError(ApiError):
+ """
+ Error if there was a network error (e.g. DNS failure, refused connection)
+ while connecting to the remote server.
+ """
=====================================
osmapi/http.py
=====================================
@@ -73,12 +73,14 @@ class OsmApiSession:
response = self._session.request(
method, path, data=send, timeout=self._timeout
)
- except requests.exceptions.Timeout:
+ except requests.exceptions.Timeout as e:
raise errors.TimeoutApiError(
0, f"Request timed out (timeout={self._timeout})", ""
- )
+ ) from e
+ except requests.exceptions.ConnectionError as e:
+ raise errors.ConnectionApiError(0, f"Connection error: {str(e)}", "") from e
except requests.exceptions.RequestException as e:
- raise errors.ApiError(0, str(e), "")
+ raise errors.ApiError(0, str(e), "") from e
if response.status_code != 200:
payload = response.content.strip()
@@ -119,6 +121,8 @@ class OsmApiSession:
else:
logger.exception("ApiError Exception occured")
raise
+ except errors.UsernamePasswordMissingError:
+ raise
except Exception as e:
logger.exception("General exception occured")
if i == self.MAX_RETRY_LIMIT:
@@ -126,7 +130,7 @@ class OsmApiSession:
raise
raise errors.MaximumRetryLimitReachedError(
f"Give up after {i} retries"
- )
+ ) from e
if i != 1:
self._sleep()
self._session = self._get_http_session()
=====================================
osmapi/parser.py
=====================================
@@ -23,7 +23,7 @@ def ParseOsm(data):
except (xml.parsers.expat.ExpatError, IndexError) as e:
raise errors.XmlResponseInvalidError(
f"The XML response from the OSM API is invalid: {e!r}"
- )
+ ) from e
result = []
for elem in data.childNodes:
@@ -55,7 +55,7 @@ def ParseOsc(data):
except (xml.parsers.expat.ExpatError, IndexError) as e:
raise errors.XmlResponseInvalidError(
f"The XML response from the OSM API is invalid: {e!r}"
- )
+ ) from e
result = []
for action in data.childNodes:
=====================================
tests/changeset_test.py
=====================================
@@ -63,6 +63,23 @@ def test_ChangesetGet(api, add_response):
assert result == test_changeset
+def test_ChangesetGet_with_connection_error(api, add_response):
+ # Setup mock
+ add_response(
+ GET,
+ "/changeset/123",
+ body=requests.exceptions.ConnectionError("Connection aborted."),
+ ),
+
+ # Call
+ with pytest.raises(osmapi.ConnectionApiError) as execinfo:
+ api.ChangesetGet(123)
+ assert (
+ str(execinfo.value)
+ == "Request failed: 0 - Connection error: Connection aborted. - "
+ )
+
+
def test_ChangesetGet_with_timeout(api, add_response):
# Setup mock
add_response(GET, "/changeset/123", body=requests.exceptions.Timeout())
@@ -87,10 +104,10 @@ def test_ChangesetUpdate(auth_api, add_response):
result = auth_api.ChangesetUpdate({"test": "foobar"})
changeset_xml = xmltosorteddict(
b'<?xml version="1.0" encoding="UTF-8"?>\n'
- b'<osm version="0.6" generator="osmapi/4.2.0">\n'
+ b'<osm version="0.6" generator="osmapi/4.3.0">\n'
b' <changeset visible="true">\n'
b' <tag k="test" v="foobar"/>\n'
- b' <tag k="created_by" v="osmapi/4.2.0"/>\n'
+ b' <tag k="created_by" v="osmapi/4.3.0"/>\n'
b" </changeset>\n"
b"</osm>\n"
)
@@ -110,7 +127,7 @@ def test_ChangesetUpdate_with_created_by(auth_api, add_response):
result = auth_api.ChangesetUpdate({"test": "foobar", "created_by": "MyTestOSMApp"})
changeset_xml = xmltosorteddict(
b'<?xml version="1.0" encoding="UTF-8"?>\n'
- b'<osm version="0.6" generator="osmapi/4.2.0">\n'
+ b'<osm version="0.6" generator="osmapi/4.3.0">\n'
b' <changeset visible="true">\n'
b' <tag k="test" v="foobar"/>\n'
b' <tag k="created_by" v="MyTestOSMApp"/>\n'
@@ -134,10 +151,10 @@ def test_ChangesetCreate(auth_api, add_response):
changeset_xml = xmltosorteddict(
b'<?xml version="1.0" encoding="UTF-8"?>\n'
- b'<osm version="0.6" generator="osmapi/4.2.0">\n'
+ b'<osm version="0.6" generator="osmapi/4.3.0">\n'
b' <changeset visible="true">\n'
b' <tag k="foobar" v="A new test changeset"/>\n'
- b' <tag k="created_by" v="osmapi/4.2.0"/>\n'
+ b' <tag k="created_by" v="osmapi/4.3.0"/>\n'
b" </changeset>\n"
b"</osm>\n"
)
@@ -157,7 +174,7 @@ def test_ChangesetCreate_with_created_by(auth_api, add_response):
changeset_xml = xmltosorteddict(
b'<?xml version="1.0" encoding="UTF-8"?>\n'
- b'<osm version="0.6" generator="osmapi/4.2.0">\n'
+ b'<osm version="0.6" generator="osmapi/4.3.0">\n'
b' <changeset visible="true">\n'
b' <tag k="foobar" v="A new test changeset"/>\n'
b' <tag k="created_by" v="CoolTestApp"/>\n'
@@ -237,7 +254,7 @@ def test_ChangesetUpload_create_node(auth_api, add_response):
upload_xml = xmltosorteddict(
b'<?xml version="1.0" encoding="UTF-8"?>\n'
- b'<osmChange version="0.6" generator="osmapi/4.2.0">\n'
+ b'<osmChange version="0.6" generator="osmapi/4.3.0">\n'
b"<create>\n"
b' <node lat="47.123" lon="8.555" visible="true" '
b'changeset="4444">\n'
@@ -309,7 +326,7 @@ def test_ChangesetUpload_modify_way(auth_api, add_response):
upload_xml = xmltosorteddict(
b'<?xml version="1.0" encoding="UTF-8"?>\n'
- b'<osmChange version="0.6" generator="osmapi/4.2.0">\n'
+ b'<osmChange version="0.6" generator="osmapi/4.3.0">\n'
b"<modify>\n"
b' <way id="4294967296" version="2" visible="true" '
b'changeset="4444">\n'
@@ -382,7 +399,7 @@ def test_ChangesetUpload_delete_relation(auth_api, add_response):
upload_xml = xmltosorteddict(
b'<?xml version="1.0" encoding="UTF-8"?>\n'
- b'<osmChange version="0.6" generator="osmapi/4.2.0">\n'
+ b'<osmChange version="0.6" generator="osmapi/4.3.0">\n'
b"<delete>\n"
b' <relation id="676" version="2" visible="true" '
b'changeset="4444">\n'
=====================================
tests/fixtures/test_NoteCreate_wo_auth.xml
=====================================
@@ -18,15 +18,15 @@
</note>
</osm>
-{u'comments': [{u'action': u'opened',
- u'date': u'2014-10-03 16:09:12 UTC',
- u'html': u'<p>This is an unauthenticated test</p>',
- u'text': u'This is an unauthenticated test',
- u'uid': None,
- u'user': None}],
- u'date_closed': None,
- u'date_created': u'2014-10-03 16:09:11 UTC',
- u'id': u'824',
- u'lat': 47.123,
- u'lon': 8.432,
- u'status': u'open'}
+{'comments': [{'action': 'opened',
+ 'date': '2014-10-03 16:09:12 UTC',
+ 'html': '<p>This is an unauthenticated test</p>',
+ 'text': 'This is an unauthenticated test',
+ 'uid': None,
+ 'user': None}],
+ 'date_closed': None,
+ 'date_created': '2014-10-03 16:09:11 UTC',
+ 'id': '824',
+ 'lat': 47.123,
+ 'lon': 8.432,
+ 'status': 'open'}
View it on GitLab: https://salsa.debian.org/debian-gis-team/python-osmapi/-/commit/5bb1c0b6f23967d1c5fe6ca47e53b1021c8ade64
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/python-osmapi/-/commit/5bb1c0b6f23967d1c5fe6ca47e53b1021c8ade64
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20250121/7f72df59/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list