[Git][debian-gis-team/python-osmapi][upstream] New upstream version 4.1.0+ds
Bas Couwenberg (@sebastic)
gitlab at salsa.debian.org
Tue Mar 19 17:43:56 GMT 2024
Bas Couwenberg pushed to branch upstream at Debian GIS Project / python-osmapi
Commits:
7603908e by Bas Couwenberg at 2024-03-19T18:33:43+01:00
New upstream version 4.1.0+ds
- - - - -
20 changed files:
- .gitignore
- CHANGELOG.md
- Makefile
- README.md
- + examples/oauth2.py
- + examples/oauth2_backend.py
- osmapi/__init__.py
- osmapi/errors.py
- osmapi/http.py
- requirements.txt
- setup.sh
- test-requirements.txt
- tests/changeset_test.py
- tests/fixtures/test_ChangesetDownloadContainingUnicode.xml
- + tests/fixtures/test_NodeCreate_with_session_auth.xml
- + tests/fixtures/test_NodeCreate_wo_auth.xml
- tests/node_test.py
- tests/notes_test.py
- tests/osmapi_test.py
- tests/way_test.py
Changes:
=====================================
.gitignore
=====================================
@@ -7,3 +7,4 @@ MANIFEST
.pycache/*
.pytest_cache/*
.env
+pyenv
=====================================
CHANGELOG.md
=====================================
@@ -4,6 +4,16 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
## [Unreleased]
+## [4.1.0] - 2024-03-19
+### Added
+- OAuth 2.0 example in README and in the `examples` directory
+
+### Changed
+- Check if a passed `session` is authenticated and use this instead of Username/Password, this enables OAuth 2.0 authentication
+
+### Removed
+- remove Python2 crumbs (see PR #159, thanks [Alexandre Detiste](https://github.com/a-detiste))
+
## [4.0.0] - 2023-07-15
### Added
- Add Python 3.11 to build
@@ -339,7 +349,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.0.0...HEAD
+[Unreleased]: https://github.com/metaodi/osmapi/compare/v4.1.0...HEAD
+[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
[3.1.0]: https://github.com/metaodi/osmapi/compare/v3.0.0...v3.1.0
[3.0.0]: https://github.com/metaodi/osmapi/compare/v2.0.2...v3.0.0
=====================================
Makefile
=====================================
@@ -10,6 +10,7 @@ deps: ## Install dependencies
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
python -m pip install -r test-requirements.txt
+ pre-commit install
docs: ## Generate documentation
python -m pdoc -o docs osmapi
@@ -21,8 +22,8 @@ lint: ## Linting of source code
python -m black --check --diff osmapi examples tests *.py
python -m flake8 --statistics --show-source .
-test: ## Run tests
- python -m pytest --cov=osmapi tests/
+test: ## Run tests (run in UTF-8 mode in Windows)
+ python -Xutf8 -m pytest --cov=osmapi tests/
help: SHELL := /bin/bash
help: ## Show help message
=====================================
README.md
=====================================
@@ -2,10 +2,12 @@ osmapi
======
[![Build osmapi](https://github.com/metaodi/osmapi/actions/workflows/build.yml/badge.svg)](https://github.com/metaodi/osmapi/actions/workflows/build.yml)
-[![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)
[![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)
+[![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)
+
Python wrapper for the OSM API (requires Python >= 3.8)
@@ -30,6 +32,8 @@ To update the online documentation, you need to re-generate the documentation wi
To test this library, please create an account on the [development server of OpenStreetMap (https://api06.dev.openstreetmap.org)](https://api06.dev.openstreetmap.org).
+Check the [examples directory](https://github.com/metaodi/osmapi/tree/develop/examples) to find more example code.
+
### Read from OpenStreetMap
```python
@@ -65,22 +69,81 @@ Note: Each line in the password file should have the format _user:password_
>>> api.ChangesetClose()
```
-## Note
+### OAuth authentication
+
+Username/Password authentication will be deprecated in 2024 (see [official OWG announcemnt](https://www.openstreetmap.org/user/pnorman/diary/401157) for details).
+In order to use this library in the future, you'll need to use OAuth 2.0.
+
+To use OAuth 2.0, you must register an application with an OpenStreetMap account, either on the [development server](https://master.apis.dev.openstreetmap.org/oauth2/applications) or on the [production server](https://www.openstreetmap.org/oauth2/applications).
+Once this registration is done, you'll get a `client_id` and a `client_secret` that you can use to authenticate users.
+
+Example code using [`requests-oauth2client`](https://pypi.org/project/requests-oauth2client/):
+
+```python
+from requests_oauth2client import OAuth2Client, OAuth2AuthorizationCodeAuth
+import requests
+import webbrowser
+import osmapi
+import os
+
+client_id = "<client_id>"
+client_secret = "<client_secret>"
+
+# special value for redirect_uri for non-web applications
+redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
+
+authorization_base_url = "https://master.apis.dev.openstreetmap.org/oauth2/authorize"
+token_url = "https://master.apis.dev.openstreetmap.org/oauth2/token"
+
+oauth2client = OAuth2Client(
+ token_endpoint=token_url,
+ authorization_endpoint=authorization_base_url,
+ redirect_uri=redirect_uri,
+ client_id=client_id,
+ client_secret=client_secret,
+ code_challenge_method=None,
+)
+
+# open OSM website to authrorize user using the write_api and write_notes scope
+scope = ["write_api", "write_notes"]
+az_request = oauth2client.authorization_request(scope=scope)
+print(f"Authorize user using this URL: {az_request.uri}")
+webbrowser.open(az_request.uri)
+
+# create a new requests session using the OAuth authorization
+auth_code = input("Paste the authorization code here: ")
+auth = OAuth2AuthorizationCodeAuth(
+ oauth2client,
+ auth_code,
+ redirect_uri=redirect_uri,
+)
+oauth_session = requests.Session()
+oauth_session.auth = auth
+
+# use the custom session
+api = osmapi.OsmApi(
+ api="https://api06.dev.openstreetmap.org",
+ session=oauth_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": {}})
+ print(node1)
+```
+
+## 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.
See the [Import/Guidelines](http://wiki.openstreetmap.org/wiki/Import/Guidelines) and [Automated Edits/Code of Conduct](http://wiki.openstreetmap.org/wiki/Automated_Edits/Code_of_Conduct) for more information.
-### Development
+## Development
If you want to help with the development of `osmapi`, you should clone this repository and install the requirements:
- pip install -r requirements.txt
- pip install -r test-requirements.txt
+ make deps
-After that, it is recommended to install the pre-commit-hooks (flake8, black):
-
- pre-commit install
+Better yet use the provided [`setup.sh`](https://github.com/metaodi/osmapi/blob/develop/setup.sh) script to create a virtual env and install this package in it.
You can lint the source code using this command:
@@ -90,8 +153,6 @@ And if you want to reformat the files (using the black code style) simply run:
make format
-### Tests
-
To run the tests use the following command:
make test
=====================================
examples/oauth2.py
=====================================
@@ -0,0 +1,52 @@
+# install oauthlib for requests: pip install requests-oauth2client
+from requests_oauth2client import OAuth2Client, OAuth2AuthorizationCodeAuth
+import requests
+import webbrowser
+import osmapi
+from dotenv import load_dotenv, find_dotenv
+import os
+
+load_dotenv(find_dotenv())
+
+# Credentials you get from registering a new application
+# register here: https://master.apis.dev.openstreetmap.org/oauth2/applications
+# or on production: https://www.openstreetmap.org/oauth2/applications
+client_id = os.getenv("OSM_OAUTH_CLIENT_ID")
+client_secret = os.getenv("OSM_OAUTH_CLIENT_SECRET")
+
+# special value for redirect_uri for non-web applications
+redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
+
+authorization_base_url = "https://master.apis.dev.openstreetmap.org/oauth2/authorize"
+token_url = "https://master.apis.dev.openstreetmap.org/oauth2/token"
+
+oauth2client = OAuth2Client(
+ token_endpoint=token_url,
+ authorization_endpoint=authorization_base_url,
+ redirect_uri=redirect_uri,
+ auth=(client_id, client_secret),
+ code_challenge_method=None,
+)
+
+# open OSM website to authrorize user using the write_api and write_notes scope
+scope = ["write_api", "write_notes"]
+az_request = oauth2client.authorization_request(scope=scope)
+print(f"Authorize user using this URL: {az_request.uri}")
+webbrowser.open(az_request.uri)
+
+# create a new requests session using the OAuth authorization
+auth_code = input("Paste the authorization code here: ")
+auth = OAuth2AuthorizationCodeAuth(
+ oauth2client,
+ auth_code,
+ redirect_uri=redirect_uri,
+)
+oauth_session = requests.Session()
+oauth_session.auth = auth
+
+# use the custom session
+api = osmapi.OsmApi(api="https://api06.dev.openstreetmap.org", session=oauth_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": {}})
+ print(node1)
=====================================
examples/oauth2_backend.py
=====================================
@@ -0,0 +1,118 @@
+# This script shows how to authenticate with OAuth2 with a backend application
+# The token is saved to disk in $HOME/.osmapi/token.json
+# It can be reused until it's revoked or expired.
+
+# install oauthlib for requests: pip install oauthlib requests-oauthlib
+from requests_oauthlib import OAuth2Session
+import json
+import webbrowser
+import osmapi
+from dotenv import load_dotenv, find_dotenv
+import os
+import sys
+
+load_dotenv(find_dotenv())
+
+# Credentials you get from registering a new application
+# register here: https://master.apis.dev.openstreetmap.org/oauth2/applications
+# or on production: https://www.openstreetmap.org/oauth2/applications
+client_id = os.getenv("OSM_OAUTH_CLIENT_ID")
+client_secret = os.getenv("OSM_OAUTH_CLIENT_SECRET")
+
+# special value for redirect_uri for non-web applications
+redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
+
+authorization_base_url = "https://master.apis.dev.openstreetmap.org/oauth2/authorize"
+token_url = "https://master.apis.dev.openstreetmap.org/oauth2/token"
+scope = ["write_api", "write_notes"]
+
+
+def get_osmapi_path():
+ base_dir = ""
+
+ if os.getenv("HOME"):
+ base_dir = os.getenv("HOME")
+ elif os.getenv("HOMEDRIVE") and os.getenv("HOMEPATH"):
+ base_dir = os.path.join(os.getenv("HOMEDRIVE"), os.getenv("HOMEPATH"))
+ elif os.getenv("USERPROFILE"):
+ base_dir = os.getenv("USERPROFILE")
+
+ if not base_dir:
+ print(
+ "Unable to find home directory (check env vars HOME, HOMEDRIVE, HOMEPATH and USERPROFILE)", # noqa
+ file=sys.stderr,
+ )
+ raise Exception("Home directory not found")
+
+ return os.path.join(base_dir, ".osmapi")
+
+
+def token_saver(token):
+ osmapi_path = get_osmapi_path()
+ token_path = os.path.join(osmapi_path, "token.json")
+
+ with open(token_path, "w") as f:
+ print(f"Saving token {token} to {token_path}")
+ f.write(json.dumps(token))
+
+
+def token_loader():
+ osmapi_path = get_osmapi_path()
+ token_path = os.path.join(osmapi_path, "token.json")
+
+ with open(token_path, "r") as f:
+ token = json.loads(f.read())
+ print(f"Loaded token {token} from {token_path}")
+ return token
+
+
+def save_and_get_access_token(client_id, client_secret, redirect_uri, scope):
+ oauth = OAuth2Session(
+ client_id=client_id,
+ redirect_uri=redirect_uri,
+ scope=scope,
+ )
+
+ login_url, _ = oauth.authorization_url(authorization_base_url)
+
+ print(f"Authorize user using this URL: {login_url}")
+ webbrowser.open(login_url)
+
+ authorization_code = input("Paste the authorization code here: ")
+
+ token = oauth.fetch_token(
+ token_url=token_url,
+ client_secret=client_secret,
+ code=authorization_code,
+ )
+
+ token_saver(token)
+ return token
+
+
+def make_osm_change(oauth_session):
+ api = osmapi.OsmApi(
+ api="https://api06.dev.openstreetmap.org", session=oauth_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": {}})
+ print(node1)
+
+
+# load a previously saved token
+try:
+ token = token_loader()
+except FileNotFoundError:
+ print("Token not found, get a new one...")
+ token = save_and_get_access_token(client_id, client_secret, redirect_uri, scope)
+
+# test the token
+try:
+ oauth_session = OAuth2Session(client_id, token=token)
+ make_osm_change(oauth_session)
+except osmapi.errors.UnauthorizedApiError:
+ print("Token expired, let's create a new one")
+ token = save_and_get_access_token(client_id, client_secret, redirect_uri, scope)
+ oauth_session = OAuth2Session(client_id, token=token)
+ make_osm_change(oauth_session)
=====================================
osmapi/__init__.py
=====================================
@@ -1,4 +1,4 @@
-__version__ = "4.0.0"
+__version__ = "4.1.0"
from .OsmApi import * # noqa
from .errors import * # noqa
=====================================
osmapi/errors.py
=====================================
@@ -69,6 +69,15 @@ class ApiError(OsmApiError):
return f"Request failed: {self.status} - {self.reason} - {self.payload}"
+class UnauthorizedApiError(ApiError):
+ """
+ Error when the API returned an Unauthorized error,
+ e.g. when the provided OAuth token is expired
+ """
+
+ pass
+
+
class AlreadySubscribedApiError(ApiError):
"""
Error when a user tries to subscribe to a changeset
=====================================
osmapi/http.py
=====================================
@@ -17,7 +17,13 @@ class OsmApiSession:
def __init__(self, base_url, created_by, auth=None, session=None):
self._api = base_url
self._created_by = created_by
- self._auth = auth
+
+ try:
+ self._auth = auth
+ if not auth and session.auth:
+ self._auth = session.auth
+ except AttributeError:
+ pass
self._http_session = session
self._session = self._get_http_session()
@@ -65,6 +71,10 @@ class OsmApiSession:
response = self._session.request(method, path, data=send)
if response.status_code != 200:
payload = response.content.strip()
+ if response.status_code == 401:
+ raise errors.UnauthorizedApiError(
+ response.status_code, response.reason, payload
+ )
if response.status_code == 404:
raise errors.ElementNotFoundApiError(
response.status_code, response.reason, payload
=====================================
requirements.txt
=====================================
@@ -1,4 +1,4 @@
pdoc==8.0.1
-Pygments==2.10.0
+Pygments==2.15.0
requests==2.31.0
python-dotenv
=====================================
setup.sh
=====================================
@@ -3,7 +3,5 @@
[ ! -d pyenv ] && python -m venv pyenv
source pyenv/bin/activate
-pip install --upgrade pip
-pip install -r requirements.txt
-pip install -r test-requirements.txt
+make deps
pip install -e .
=====================================
test-requirements.txt
=====================================
@@ -1,5 +1,4 @@
flake8
-mock
virtualenv
xmltodict
pytest
=====================================
tests/changeset_test.py
=====================================
@@ -75,10 +75,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.0.0">\n'
+ b'<osm version="0.6" generator="osmapi/4.1.0">\n'
b' <changeset visible="true">\n'
b' <tag k="test" v="foobar"/>\n'
- b' <tag k="created_by" v="osmapi/4.0.0"/>\n'
+ b' <tag k="created_by" v="osmapi/4.1.0"/>\n'
b" </changeset>\n"
b"</osm>\n"
)
@@ -98,7 +98,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.0.0">\n'
+ b'<osm version="0.6" generator="osmapi/4.1.0">\n'
b' <changeset visible="true">\n'
b' <tag k="test" v="foobar"/>\n'
b' <tag k="created_by" v="MyTestOSMApp"/>\n'
@@ -122,10 +122,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.0.0">\n'
+ b'<osm version="0.6" generator="osmapi/4.1.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.0.0"/>\n'
+ b' <tag k="created_by" v="osmapi/4.1.0"/>\n'
b" </changeset>\n"
b"</osm>\n"
)
@@ -145,7 +145,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.0.0">\n'
+ b'<osm version="0.6" generator="osmapi/4.1.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'
@@ -218,7 +218,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.0.0">\n'
+ b'<osmChange version="0.6" generator="osmapi/4.1.0">\n'
b"<create>\n"
b' <node lat="47.123" lon="8.555" visible="true" '
b'changeset="4444">\n'
@@ -283,7 +283,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.0.0">\n'
+ b'<osmChange version="0.6" generator="osmapi/4.1.0">\n'
b"<modify>\n"
b' <way id="4294967296" version="2" visible="true" '
b'changeset="4444">\n'
@@ -354,7 +354,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.0.0">\n'
+ b'<osmChange version="0.6" generator="osmapi/4.1.0">\n'
b"<delete>\n"
b' <relation id="676" version="2" visible="true" '
b'changeset="4444">\n'
@@ -490,8 +490,8 @@ def test_ChangesetDownloadContainingUnicode(api, add_response):
"tag": {
"highway": "service",
# UTF-8 encoded 'LATIN SMALL LETTER O WITH STROKE'
- # Aka. 0xf8 in latin-1/ISO 8859-1
- "name": b"S\xc3\xb8nderskovvej".decode("utf-8"),
+ # Aka. 0xf8 in latin-1/ISO 8859-1 Emoji: 😀
+ "name": b"S\xc3\xb8nderskovvej".decode("utf-8") + " \U0001f600",
"service": "driveway",
},
"timestamp": datetime.datetime(2016, 2, 23, 16, 55, 35),
=====================================
tests/fixtures/test_ChangesetDownloadContainingUnicode.xml
=====================================
@@ -10,7 +10,7 @@
<nd ref="4022271567"/>
<nd ref="4022271565"/>
<tag k="highway" v="service"/>
- <tag k="name" v="Sønderskovvej"/>
+ <tag k="name" v="Sønderskovvej 😀"/>
<tag k="service" v="driveway"/>
</way>
</create>
=====================================
tests/fixtures/test_NodeCreate_with_session_auth.xml
=====================================
@@ -0,0 +1 @@
+3322
=====================================
tests/fixtures/test_NodeCreate_wo_auth.xml
=====================================
@@ -0,0 +1 @@
+123
=====================================
tests/node_test.py
=====================================
@@ -2,6 +2,7 @@ from . import osmapi_test
import osmapi
from unittest import mock
import datetime
+from requests.auth import HTTPBasicAuth
class TestOsmApiNode(osmapi_test.TestOsmApi):
@@ -158,6 +159,41 @@ class TestOsmApiNode(osmapi_test.TestOsmApi):
):
self.api.NodeCreate(test_node)
+ def test_NodeCreate_unauthorized(self):
+ self._session_mock(auth=True, status=401)
+
+ # setup mock
+ self.api.ChangesetCreate = mock.Mock(return_value=1111)
+ self.api._CurrentChangesetId = 1111
+ test_node = {
+ "lat": 47.287,
+ "lon": 8.765,
+ "tag": {"amenity": "place_of_worship", "religion": "pastafarian"},
+ }
+
+ with self.assertRaises(osmapi.UnauthorizedApiError):
+ self.api.NodeCreate(test_node)
+
+ def test_NodeCreate_with_session_auth(self):
+ self._session_mock()
+ self.session_mock.auth = HTTPBasicAuth("user", "pass")
+
+ api = osmapi.OsmApi(api=self.api_base, session=self.session_mock)
+
+ # setup mock
+ api.ChangesetCreate = mock.Mock(return_value=1111)
+ api._CurrentChangesetId = 1111
+ test_node = {
+ "lat": 47.287,
+ "lon": 8.765,
+ "tag": {"amenity": "place_of_worship", "religion": "pastafarian"},
+ }
+
+ cs = api.ChangesetCreate({"comment": "This is a test dataset"})
+ self.assertEqual(cs, 1111)
+ result = api.NodeCreate(test_node)
+ self.assertEqual(result["id"], 3322)
+
def test_NodeCreate_with_exception(self):
self._session_mock(auth=True)
self.api._session._http_request = mock.Mock(side_effect=Exception)
=====================================
tests/notes_test.py
=====================================
@@ -1,11 +1,7 @@
from . import osmapi_test
from datetime import datetime
import osmapi
-
-try:
- import urlparse
-except ImportError:
- from urllib import parse as urlparse
+from urllib import parse as urlparse
class TestOsmApiNotes(osmapi_test.TestOsmApi):
=====================================
tests/osmapi_test.py
=====================================
@@ -2,6 +2,7 @@ from osmapi import OsmApi
from unittest import mock
import os
import unittest
+import codecs
__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
@@ -26,6 +27,7 @@ class TestOsmApi(unittest.TestCase):
self.session_mock = mock.Mock()
self.session_mock.request = mock.Mock(return_value=response_mock)
+ self.session_mock.auth = None
if auth:
self.api = OsmApi(
@@ -48,7 +50,7 @@ class TestOsmApi(unittest.TestCase):
for filename in filenames:
path = os.path.join(__location__, "fixtures", filename)
try:
- with open(path) as file:
+ with codecs.open(path, "r", "utf-8") as file:
return_values.append(file.read())
except Exception:
pass
=====================================
tests/way_test.py
=====================================
@@ -1,7 +1,6 @@
-from __future__ import unicode_literals, absolute_import
from . import osmapi_test
import osmapi
-import mock
+from unittest import mock
import datetime
View it on GitLab: https://salsa.debian.org/debian-gis-team/python-osmapi/-/commit/7603908e57fd5d1c0ef1ff71b3ce837b04ab7527
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/python-osmapi/-/commit/7603908e57fd5d1c0ef1ff71b3ce837b04ab7527
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/20240319/11bee845/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list