From e8b7940f472cdd0038a316ca5796dabc4043281b Mon Sep 17 00:00:00 2001 From: Austin Hartzheim Date: Sat, 23 May 2015 04:20:24 +0000 Subject: [PATCH 01/20] Added support for SSL to API calls. The OsmApi class can now use SSL for API calls by using the https:// prefix for OsmApi's `api` parameter. The default value is now "https://wwww.openstreetmap.org". The prefix remains optional. Also, support has been added for using http:// as a prefix. --- osmapi/OsmApi.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osmapi/OsmApi.py b/osmapi/OsmApi.py index 74affbb..61858ae 100644 --- a/osmapi/OsmApi.py +++ b/osmapi/OsmApi.py @@ -95,7 +95,7 @@ def __init__( passwordfile=None, appid="", created_by="osmapi/"+__version__, - api="www.openstreetmap.org", + api="https://www.openstreetmap.org", changesetauto=False, changesetautotags={}, changesetautosize=500, @@ -1773,7 +1773,12 @@ def _http(self, cmd, path, auth, send): # noqa self._conn = self._get_http_connection() def _get_http_connection(self): - return httplib.HTTPConnection(self._api, 80) + if self._api.lower().startswith('https://'): + return httplib.HTTPSConnection(self._api[8:], 443) + elif self._api.lower().startswith('http://'): + return httplib.HTTPConnection(self._api[7:], 80) + else: + return httplib.HTTPConnection(self._api, 80) def _sleep(self): time.sleep(5) From a7900811ee68b775cceaa399e820c9e5b5ce713d Mon Sep 17 00:00:00 2001 From: Austin Hartzheim Date: Sat, 23 May 2015 04:53:13 +0000 Subject: [PATCH 02/20] Attempt to fix Travis CI error. Moved the location of an import line. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index dd70272..19dbba4 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import codecs +from distutils.core import setup version = __import__('osmapi').__version__ @@ -13,7 +14,6 @@ except (IOError, ImportError): description = 'Python wrapper for the OSM API' -from distutils.core import setup setup( name='osmapi', packages=['osmapi'], From 58185041a13a7a7f5cfed91173c220d01c9c4811 Mon Sep 17 00:00:00 2001 From: Austin Hartzheim Date: Sat, 23 May 2015 05:06:12 +0000 Subject: [PATCH 03/20] Moved __version__ import in OsmApi.py above any function declarations. --- osmapi/OsmApi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osmapi/OsmApi.py b/osmapi/OsmApi.py index 61858ae..d72223d 100644 --- a/osmapi/OsmApi.py +++ b/osmapi/OsmApi.py @@ -39,12 +39,12 @@ import urllib from datetime import datetime +from osmapi import __version__ + # Python 3.x if getattr(urllib, 'urlencode', None) is None: urllib.urlencode = urllib.parse.urlencode -from osmapi import __version__ - class UsernamePasswordMissingError(Exception): """ From 2a3d10886296865f4b5932d70618661374cfdc36 Mon Sep 17 00:00:00 2001 From: Austin Hartzheim Date: Sat, 23 May 2015 05:12:16 +0000 Subject: [PATCH 04/20] Run Travis builds for Python 3.4. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index f4beaa1..568e8d6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ python: - '2.7' - '3.2' - '3.3' +- '3.4' before_install: - sudo apt-get update -qq From 22c51c562730477755e1e0cee9796a9682964971 Mon Sep 17 00:00:00 2001 From: Stefan Oderbolz Date: Sun, 24 May 2015 12:26:37 +0200 Subject: [PATCH 05/20] First draft of the contributing guidelines --- CONTRIBUTING.md | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..417d655 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,56 @@ +# Contributing + +If you want to participate in this project, please follow this guidline. + +Fork and clone this repository: + +```bash +git clone git@github.com:your-username/osmapi.git +``` + +Install the dependencies using `pip`: + +```bash +pip install -r requirements.txt +pip install -r test-requirements.txt +``` + +Make sure the tests pass: + +```bash +nosetests --verbose +``` + +You can even run the tests on different versions of Python with `tox`: + +```bash +tox +``` + +To ensure a good quality of the code use `flake8` to check the code style: + +```bash +flake8 --install-hook +``` + +To create a pull request make sure + +1. You choose the `develop` branch as a target for new/changed functionality, `master` should only be targeted for urgent bugfixes. +2. While it's not strictly required, it's highly recommended to create a new branch in your branch for each pull request. +3. Push to your fork and [submit a pull request][pr]. +4. Check if the [build ran successfully][ci] and try to improve your code if not. + +At this point you're waiting for my review. +I might suggest some changes or improvements or alternatives. + +Some things that will increase the chance that your pull request is accepted: + +* Write tests. +* Follow the Python style guide ([PEP-8][pep8]). +* Write a [good commit message][commit]. + +[ci]: https://travis-ci.org/metaodi/osmapi +[pr]: https://github.com/metaodi/osmapi/compare/ +[pep8]: https://www.python.org/dev/peps/pep-0008/ +[style]: https://github.com/thoughtbot/guides/tree/master/style +[commit]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html From 6120596b33191b9be37fd5e4e2ff07bed3f63fac Mon Sep 17 00:00:00 2001 From: Stefan Oderbolz Date: Sun, 24 May 2015 12:33:03 +0200 Subject: [PATCH 06/20] Update links, add branching model info --- CONTRIBUTING.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 417d655..17759c1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -33,10 +33,10 @@ To ensure a good quality of the code use `flake8` to check the code style: flake8 --install-hook ``` -To create a pull request make sure +## Create a pull request -1. You choose the `develop` branch as a target for new/changed functionality, `master` should only be targeted for urgent bugfixes. -2. While it's not strictly required, it's highly recommended to create a new branch in your branch for each pull request. +1. Choose the `develop` branch as a target for new/changed functionality, `master` should only be targeted for urgent bugfixes. +2. While it's not strictly required, it's highly recommended to create a new branch on your fork for each pull request. I follow a simplified [git branching model of nvie][branch]. 3. Push to your fork and [submit a pull request][pr]. 4. Check if the [build ran successfully][ci] and try to improve your code if not. @@ -49,8 +49,8 @@ Some things that will increase the chance that your pull request is accepted: * Follow the Python style guide ([PEP-8][pep8]). * Write a [good commit message][commit]. -[ci]: https://travis-ci.org/metaodi/osmapi +[branch]: http://nvie.com/posts/a-successful-git-branching-model/ [pr]: https://github.com/metaodi/osmapi/compare/ +[ci]: https://travis-ci.org/metaodi/osmapi [pep8]: https://www.python.org/dev/peps/pep-0008/ -[style]: https://github.com/thoughtbot/guides/tree/master/style [commit]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html From d9823fcc76a6cdad4cc68ad138cc5bbbf810a764 Mon Sep 17 00:00:00 2001 From: Stefan Oderbolz Date: Sun, 24 May 2015 16:25:22 +0200 Subject: [PATCH 07/20] Remove explanation of the branching model --- CONTRIBUTING.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 17759c1..9031492 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,7 +36,7 @@ flake8 --install-hook ## Create a pull request 1. Choose the `develop` branch as a target for new/changed functionality, `master` should only be targeted for urgent bugfixes. -2. While it's not strictly required, it's highly recommended to create a new branch on your fork for each pull request. I follow a simplified [git branching model of nvie][branch]. +2. While it's not strictly required, it's highly recommended to create a new branch on your fork for each pull request. 3. Push to your fork and [submit a pull request][pr]. 4. Check if the [build ran successfully][ci] and try to improve your code if not. @@ -49,7 +49,6 @@ Some things that will increase the chance that your pull request is accepted: * Follow the Python style guide ([PEP-8][pep8]). * Write a [good commit message][commit]. -[branch]: http://nvie.com/posts/a-successful-git-branching-model/ [pr]: https://github.com/metaodi/osmapi/compare/ [ci]: https://travis-ci.org/metaodi/osmapi [pep8]: https://www.python.org/dev/peps/pep-0008/ From 9a1432ee5c9aef049d7c07f4055da9cb775ee208 Mon Sep 17 00:00:00 2001 From: Stefan Oderbolz Date: Sat, 3 Jan 2015 19:04:34 +0100 Subject: [PATCH 08/20] Introduce some more exceptions --- osmapi/OsmApi.py | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/osmapi/OsmApi.py b/osmapi/OsmApi.py index d72223d..b479566 100644 --- a/osmapi/OsmApi.py +++ b/osmapi/OsmApi.py @@ -53,6 +53,29 @@ class UsernamePasswordMissingError(Exception): pass +class NoChangesetOpenError(Exception): + """ + Error when an operation requires an open changeset, but currently + no changeset _is_ open + """ + pass + + +class ChangesetAlreadyOpenError(Exception): + """ + Error when a user tries to open a changeset when there is already + an open changeset + """ + pass + + +class OsmTypeAlreadyExists(Exception): + """ + Error when a user tries to create an object that already exsits + """ + pass + + class ApiError(Exception): """ Error class, is thrown when an API request fails @@ -76,10 +99,18 @@ def __str__(self): class AlreadySubscribedApiError(ApiError): + """ + Error when a user tries to subscribe to a changeset + that she is already subscribed to + """ pass class NotSubscribedApiError(ApiError): + """ + Error when user tries to unsubscribe from a changeset + that he is not subscribed to + """ pass @@ -1063,7 +1094,7 @@ def ChangesetUpdate(self, ChangesetTags={}): Updates current changeset with `ChangesetTags`. """ if not self._CurrentChangesetId: - raise Exception("No changeset currently opened") + raise NoChangesetOpenError("No changeset currently opened") if "created_by" not in ChangesetTags: ChangesetTags["created_by"] = self._created_by self._put( @@ -1081,7 +1112,7 @@ def ChangesetCreate(self, ChangesetTags={}): Returns `ChangesetId` """ if self._CurrentChangesetId: - raise Exception("Changeset already opened") + raise ChangesetAlreadyOpenError("Changeset already opened") if "created_by" not in ChangesetTags: ChangesetTags["created_by"] = self._created_by result = self._put( @@ -1098,7 +1129,7 @@ def ChangesetClose(self): Returns `ChangesetId`. """ if not self._CurrentChangesetId: - raise Exception("No changeset currently opened") + raise NoChangesetOpenError("No changeset currently opened") self._put( "/api/0.6/changeset/"+str(self._CurrentChangesetId)+"/close", "" @@ -1642,7 +1673,7 @@ def _do(self, action, OsmType, OsmData): def _do_manu(self, action, OsmType, OsmData): if not self._CurrentChangesetId: - raise Exception( + raise NoChangesetOpenError( "You need to open a changeset before uploading data" ) if "timestamp" in OsmData: @@ -1650,7 +1681,7 @@ def _do_manu(self, action, OsmType, OsmData): OsmData["changeset"] = self._CurrentChangesetId if action == "create": if OsmData.get("id", -1) > 0: - raise Exception("This "+OsmType+" already exists") + raise OsmTypeAlreadyExists("This "+OsmType+" already exists") result = self._put( "/api/0.6/" + OsmType + "/create", self._XmlBuild(OsmType, OsmData) From 8260a20f6e2ade205dcf64f33da5d1cd7e2873f6 Mon Sep 17 00:00:00 2001 From: Stefan Oderbolz Date: Mon, 5 Jan 2015 01:16:24 +0100 Subject: [PATCH 09/20] Add test for passwordfile --- tests/fixtures/passwordfile.txt | 1 + tests/helper_tests.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 tests/fixtures/passwordfile.txt diff --git a/tests/fixtures/passwordfile.txt b/tests/fixtures/passwordfile.txt new file mode 100644 index 0000000..708dc2e --- /dev/null +++ b/tests/fixtures/passwordfile.txt @@ -0,0 +1 @@ +testosm:testpass diff --git a/tests/helper_tests.py b/tests/helper_tests.py index cfc528b..cb9286a 100644 --- a/tests/helper_tests.py +++ b/tests/helper_tests.py @@ -3,6 +3,14 @@ from . import osmapi_tests import osmapi import mock +import os + +__location__ = os.path.realpath( + os.path.join( + os.getcwd(), + os.path.dirname(__file__) + ) +) class TestOsmApiHelper(osmapi_tests.TestOsmApi): @@ -23,6 +31,16 @@ def setupMock(self, status=200): self.api._username = 'testuser' self.api._password = 'testpassword' + def test_passwordfile(self): + path = os.path.join( + __location__, + 'fixtures', + 'passwordfile.txt' + ) + my_api = osmapi.OsmApi(passwordfile=path) + self.assertEquals('testosm', my_api._username) + self.assertEquals('testpass', my_api._password) + def test_http_request_get(self): response = self.api._http_request( 'GET', From 7088dd4322bbb630207fe2c55791323857788e08 Mon Sep 17 00:00:00 2001 From: Stefan Oderbolz Date: Sun, 24 May 2015 16:56:06 +0200 Subject: [PATCH 10/20] Run Python 3.4 tests with tox --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 310e84e..ccb6940 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py26,py27,py32,py33 +envlist = py26,py27,py32,py33,py34 [testenv] commands=nosetests --verbose deps = From 2a3f13a6990f6905710491ab7ad7a4ce6005df0e Mon Sep 17 00:00:00 2001 From: Stefan Oderbolz Date: Sun, 24 May 2015 17:38:54 +0200 Subject: [PATCH 11/20] Add new error superclass OsmApiError --- osmapi/OsmApi.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/osmapi/OsmApi.py b/osmapi/OsmApi.py index b479566..2d16ae8 100644 --- a/osmapi/OsmApi.py +++ b/osmapi/OsmApi.py @@ -46,14 +46,26 @@ urllib.urlencode = urllib.parse.urlencode -class UsernamePasswordMissingError(Exception): +class OsmApiError(Exception): + """ + General OsmApi error class to provide a superclass for all other errors + """ + + +class MaximumRetryLimitReachedError(OsmApiError): + """ + Error when the maximum amount of retries is reached and we have to give up + """ + + +class UsernamePasswordMissingError(OsmApiError): """ Error when username or password is missing for an authenticated request """ pass -class NoChangesetOpenError(Exception): +class NoChangesetOpenError(OsmApiError): """ Error when an operation requires an open changeset, but currently no changeset _is_ open @@ -61,7 +73,7 @@ class NoChangesetOpenError(Exception): pass -class ChangesetAlreadyOpenError(Exception): +class ChangesetAlreadyOpenError(OsmApiError): """ Error when a user tries to open a changeset when there is already an open changeset @@ -69,14 +81,14 @@ class ChangesetAlreadyOpenError(Exception): pass -class OsmTypeAlreadyExists(Exception): +class OsmTypeAlreadyExistsError(OsmApiError): """ Error when a user tries to create an object that already exsits """ pass -class ApiError(Exception): +class ApiError(OsmApiError): """ Error class, is thrown when an API request fails """ @@ -1681,7 +1693,9 @@ def _do_manu(self, action, OsmType, OsmData): OsmData["changeset"] = self._CurrentChangesetId if action == "create": if OsmData.get("id", -1) > 0: - raise OsmTypeAlreadyExists("This "+OsmType+" already exists") + raise OsmTypeAlreadyExistsError( + "This "+OsmType+" already exists" + ) result = self._put( "/api/0.6/" + OsmType + "/create", self._XmlBuild(OsmType, OsmData) From ef98f5ac5f32358e025caa15be5eab3e9191d160 Mon Sep 17 00:00:00 2001 From: Stefan Oderbolz Date: Sun, 24 May 2015 17:39:25 +0200 Subject: [PATCH 12/20] Add tests for new error classes --- tests/changeset_tests.py | 12 ++++++------ tests/node_tests.py | 30 ++++++++++++++++++++++++++---- tests/relation_tests.py | 32 ++++++++++++++++++++++++++++++++ tests/way_tests.py | 22 ++++++++++++++++++++++ 4 files changed, 86 insertions(+), 10 deletions(-) diff --git a/tests/changeset_tests.py b/tests/changeset_tests.py index 7024a23..deb0b33 100644 --- a/tests/changeset_tests.py +++ b/tests/changeset_tests.py @@ -1,7 +1,7 @@ from __future__ import (unicode_literals, absolute_import) from nose.tools import * # noqa from . import osmapi_tests -from osmapi import AlreadySubscribedApiError, NotSubscribedApiError +import osmapi import mock import xmltodict import datetime @@ -148,7 +148,7 @@ def test_ChangesetUpdate_wo_changeset(self): self._conn_mock() with self.assertRaisesRegexp( - Exception, + osmapi.NoChangesetOpenError, 'No changeset currently opened'): self.api.ChangesetUpdate( { @@ -221,7 +221,7 @@ def test_ChangesetCreate_with_open_changeset(self): ) with self.assertRaisesRegexp( - Exception, + osmapi.ChangesetAlreadyOpenError, 'Changeset already opened'): self.api.ChangesetCreate( { @@ -248,7 +248,7 @@ def test_ChangesetClose_with_no_changeset(self): self._conn_mock() with self.assertRaisesRegexp( - Exception, + osmapi.NoChangesetOpenError, 'No changeset currently opened'): self.api.ChangesetClose() @@ -652,7 +652,7 @@ def test_ChangesetSubscribe(self): def test_ChangesetSubscribeWhenAlreadySubscribed(self): self._conn_mock(auth=True, status=409) - with self.assertRaises(AlreadySubscribedApiError) as cm: + with self.assertRaises(osmapi.AlreadySubscribedApiError) as cm: self.api.ChangesetSubscribe(52924) self.assertEquals(cm.exception.status, 409) @@ -690,7 +690,7 @@ def test_ChangesetUnsubscribe(self): def test_ChangesetUnsubscribeWhenNotSubscribed(self): self._conn_mock(auth=True, status=404) - with self.assertRaises(NotSubscribedApiError) as cm: + with self.assertRaises(osmapi.NotSubscribedApiError) as cm: self.api.ChangesetUnsubscribe(52924) self.assertEquals(cm.exception.status, 404) diff --git a/tests/node_tests.py b/tests/node_tests.py index b435c70..a87a888 100644 --- a/tests/node_tests.py +++ b/tests/node_tests.py @@ -1,7 +1,7 @@ from __future__ import (unicode_literals, absolute_import) from nose.tools import * # noqa from . import osmapi_tests -from osmapi import OsmApi, UsernamePasswordMissingError +import osmapi import mock import datetime @@ -59,7 +59,7 @@ def test_NodeGet_with_version(self): def test_NodeCreate_changesetauto(self): # setup mock - self.api = OsmApi( + self.api = osmapi.OsmApi( api="api06.dev.openstreetmap.org", changesetauto=True ) @@ -124,10 +124,32 @@ def test_NodeCreate_wo_changeset(self): } with self.assertRaisesRegexp( - Exception, + osmapi.NoChangesetOpenError, 'need to open a changeset'): self.api.NodeCreate(test_node) + def test_NodeCreate_existing_node(self): + # setup mock + self.api.ChangesetCreate = mock.Mock( + return_value=1111 + ) + self.api._CurrentChangesetId = 1111 + + test_node = { + 'id': 123, + 'lat': 47.287, + 'lon': 8.765, + 'tag': { + 'amenity': 'place_of_worship', + 'religion': 'pastafarian' + } + } + + with self.assertRaisesRegexp( + osmapi.OsmTypeAlreadyExistsError, + 'This node already exists'): + self.api.NodeCreate(test_node) + def test_NodeCreate_wo_auth(self): self._conn_mock() @@ -146,7 +168,7 @@ def test_NodeCreate_wo_auth(self): } with self.assertRaisesRegexp( - UsernamePasswordMissingError, + osmapi.UsernamePasswordMissingError, 'Username/Password missing'): self.api.NodeCreate(test_node) diff --git a/tests/relation_tests.py b/tests/relation_tests.py index 82b85ad..7d5c839 100644 --- a/tests/relation_tests.py +++ b/tests/relation_tests.py @@ -1,6 +1,7 @@ from __future__ import (unicode_literals, absolute_import) from nose.tools import * # noqa from . import osmapi_tests +import osmapi import mock import datetime @@ -140,6 +141,37 @@ def test_RelationCreate(self): self.assertEquals(result['member'], test_relation['member']) self.assertEquals(result['tag'], test_relation['tag']) + def test_RelationCreate_existing_node(self): + # setup mock + self.api.ChangesetCreate = mock.Mock( + return_value=1111 + ) + self.api._CurrentChangesetId = 1111 + + test_relation = { + 'id': 456, + 'tag': { + 'type': 'test', + }, + 'member': [ + { + 'ref': 6908, + 'role': 'outer', + 'type': 'way' + }, + { + 'ref': 6352, + 'role': 'point', + 'type': 'node' + }, + ] + } + + with self.assertRaisesRegexp( + osmapi.OsmTypeAlreadyExistsError, + 'This relation already exists'): + self.api.RelationCreate(test_relation) + def test_RelationUpdate(self): self._conn_mock(auth=True) diff --git a/tests/way_tests.py b/tests/way_tests.py index 233d249..d5f50bc 100644 --- a/tests/way_tests.py +++ b/tests/way_tests.py @@ -1,6 +1,7 @@ from __future__ import (unicode_literals, absolute_import) from nose.tools import * # noqa from . import osmapi_tests +import osmapi import mock import datetime @@ -104,6 +105,27 @@ def test_WayCreate(self): self.assertEquals(result['nd'], test_way['nd']) self.assertEquals(result['tag'], test_way['tag']) + def test_WayCreate_existing_node(self): + # setup mock + self.api.ChangesetCreate = mock.Mock( + return_value=1111 + ) + self.api._CurrentChangesetId = 1111 + + test_way = { + 'id': 456, + 'nd': [11949, 11950], + 'tag': { + 'highway': 'unclassified', + 'name': 'Osmapi Street' + } + } + + with self.assertRaisesRegexp( + osmapi.OsmTypeAlreadyExistsError, + 'This way already exists'): + self.api.WayCreate(test_way) + def test_WayUpdate(self): self._conn_mock(auth=True) From 70eaefc10b413ee895928c1eeac1b05f5220d1f4 Mon Sep 17 00:00:00 2001 From: Stefan Oderbolz Date: Sun, 24 May 2015 18:29:48 +0200 Subject: [PATCH 13/20] Add test for MaximumRetryLimitReachedError --- osmapi/OsmApi.py | 14 ++++++++++---- tests/node_tests.py | 23 +++++++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/osmapi/OsmApi.py b/osmapi/OsmApi.py index 2d16ae8..79d68d7 100644 --- a/osmapi/OsmApi.py +++ b/osmapi/OsmApi.py @@ -130,6 +130,7 @@ class OsmApi: """ Main class of osmapi, instanciate this class to use osmapi """ + MAX_RETRY_LIMIT = 5 def __init__( self, @@ -1803,16 +1804,21 @@ def _http(self, cmd, path, auth, send): # noqa return self._http_request(cmd, path, auth, send) except ApiError as e: if e.status >= 500: - if i == 5: + if i == self.MAX_RETRY_LIMIT: raise if i != 1: self._sleep() self._conn = self._get_http_connection() else: raise - except Exception: - if i == 5: - raise + except Exception as e: + print(e) + if i == self.MAX_RETRY_LIMIT: + if isinstance(e, OsmApiError): + raise + raise MaximumRetryLimitReachedError( + "Give up after %s retries" % i + ) if i != 1: self._sleep() self._conn = self._get_http_connection() diff --git a/tests/node_tests.py b/tests/node_tests.py index a87a888..8fa1c12 100644 --- a/tests/node_tests.py +++ b/tests/node_tests.py @@ -172,6 +172,29 @@ def test_NodeCreate_wo_auth(self): 'Username/Password missing'): self.api.NodeCreate(test_node) + def test_NodeCreate_with_exception(self): + self._conn_mock(auth=True) + self.api._http_request = mock.Mock(side_effect=Exception) + + # 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.assertRaisesRegexp( + osmapi.MaximumRetryLimitReachedError, + 'Give up after 5 retries'): + self.api.NodeCreate(test_node) + def test_NodeUpdate(self): self._conn_mock(auth=True) From 9c75e82b096047872d7b0237413afec2ff44a973 Mon Sep 17 00:00:00 2001 From: Stefan Oderbolz Date: Mon, 25 May 2015 17:53:08 +0200 Subject: [PATCH 14/20] Add Pygments as a dependency to enable syntax highlighting of pdoc --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 1842bac..4565b99 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ pypandoc==0.7.0 Unidecode==0.04.14 pdoc==0.3.1 +Pygments==1.6 From 77cc5ebc6624b91bf9f984350030b11f16f334e5 Mon Sep 17 00:00:00 2001 From: Stefan Oderbolz Date: Mon, 25 May 2015 22:11:10 +0200 Subject: [PATCH 15/20] Add comment which Error might be raised where --- osmapi/OsmApi.py | 137 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/osmapi/OsmApi.py b/osmapi/OsmApi.py index 79d68d7..90ec672 100644 --- a/osmapi/OsmApi.py +++ b/osmapi/OsmApi.py @@ -348,6 +348,15 @@ def NodeCreate(self, NodeData): 'uid': id of user of last change, 'visible': True|False } + + If no authentication information are provided, + `osmapi.UsernamePasswordMissingError` is raised. + + If there is no open changeset, + `osmapi.NoChangesetOpenError` is raised. + + If the supplied information contain an existing node, + `osmapi.OsmTypeAlreadyExistsError` is raised. """ return self._do("create", "node", NodeData) @@ -378,6 +387,15 @@ def NodeUpdate(self, NodeData): 'uid': id of user of last change, 'visible': True|False } + + If no authentication information are provided, + `osmapi.UsernamePasswordMissingError` is raised. + + If there is no open changeset, + `osmapi.NoChangesetOpenError` is raised. + + If there is already an open changeset, + `osmapi.ChangesetAlreadyOpenError` is raised. """ return self._do("modify", "node", NodeData) @@ -408,6 +426,15 @@ def NodeDelete(self, NodeData): 'uid': id of user of last change, 'visible': True|False } + + If no authentication information are provided, + `osmapi.UsernamePasswordMissingError` is raised. + + If there is no open changeset, + `osmapi.NoChangesetOpenError` is raised. + + If there is already an open changeset, + `osmapi.ChangesetAlreadyOpenError` is raised. """ return self._do("delete", "node", NodeData) @@ -592,6 +619,18 @@ def WayCreate(self, WayData): 'uid': id of user of last change, 'visible': True|False } + + If no authentication information are provided, + `osmapi.UsernamePasswordMissingError` is raised. + + If the supplied information contain an existing node, + `osmapi.OsmTypeAlreadyExistsError` is raised. + + If there is no open changeset, + `osmapi.NoChangesetOpenError` is raised. + + If there is already an open changeset, + `osmapi.ChangesetAlreadyOpenError` is raised. """ return self._do("create", "way", WayData) @@ -620,6 +659,15 @@ def WayUpdate(self, WayData): 'uid': id of user of last change, 'visible': True|False } + + If no authentication information are provided, + `osmapi.UsernamePasswordMissingError` is raised. + + If there is no open changeset, + `osmapi.NoChangesetOpenError` is raised. + + If there is already an open changeset, + `osmapi.ChangesetAlreadyOpenError` is raised. """ return self._do("modify", "way", WayData) @@ -648,6 +696,15 @@ def WayDelete(self, WayData): 'uid': id of user of last change, 'visible': True|False } + + If no authentication information are provided, + `osmapi.UsernamePasswordMissingError` is raised. + + If there is no open changeset, + `osmapi.NoChangesetOpenError` is raised. + + If there is already an open changeset, + `osmapi.ChangesetAlreadyOpenError` is raised. """ return self._do("delete", "way", WayData) @@ -835,6 +892,18 @@ def RelationCreate(self, RelationData): 'uid': id of user that made the last change, 'visible': True|False } + + If no authentication information are provided, + `osmapi.UsernamePasswordMissingError` is raised. + + If the supplied information contain an existing node, + `osmapi.OsmTypeAlreadyExistsError` is raised. + + If there is no open changeset, + `osmapi.NoChangesetOpenError` is raised. + + If there is already an open changeset, + `osmapi.ChangesetAlreadyOpenError` is raised. """ return self._do("create", "relation", RelationData) @@ -872,6 +941,15 @@ def RelationUpdate(self, RelationData): 'uid': id of user that made the last change, 'visible': True|False } + + If no authentication information are provided, + `osmapi.UsernamePasswordMissingError` is raised. + + If there is no open changeset, + `osmapi.NoChangesetOpenError` is raised. + + If there is already an open changeset, + `osmapi.ChangesetAlreadyOpenError` is raised. """ return self._do("modify", "relation", RelationData) @@ -909,6 +987,15 @@ def RelationDelete(self, RelationData): 'uid': id of user that made the last change, 'visible': True|False } + + If no authentication information are provided, + `osmapi.UsernamePasswordMissingError` is raised. + + If there is no open changeset, + `osmapi.NoChangesetOpenError` is raised. + + If there is already an open changeset, + `osmapi.ChangesetAlreadyOpenError` is raised. """ return self._do("delete", "relation", RelationData) @@ -1105,6 +1192,12 @@ def ChangesetGet(self, ChangesetId, include_discussion=False): def ChangesetUpdate(self, ChangesetTags={}): """ Updates current changeset with `ChangesetTags`. + + If no authentication information are provided, + `osmapi.UsernamePasswordMissingError` is raised. + + If there is no open changeset, + `osmapi.NoChangesetOpenError` is raised. """ if not self._CurrentChangesetId: raise NoChangesetOpenError("No changeset currently opened") @@ -1123,6 +1216,12 @@ def ChangesetCreate(self, ChangesetTags={}): If `ChangesetTags` are given, this tags are applied (key/value). Returns `ChangesetId` + + If no authentication information are provided, + `osmapi.UsernamePasswordMissingError` is raised. + + If there is already an open changeset, + `osmapi.ChangesetAlreadyOpenError` is raised. """ if self._CurrentChangesetId: raise ChangesetAlreadyOpenError("Changeset already opened") @@ -1140,6 +1239,12 @@ def ChangesetClose(self): Closes current changeset. Returns `ChangesetId`. + + If no authentication information are provided, + `osmapi.UsernamePasswordMissingError` is raised. + + If there is no open changeset, + `osmapi.NoChangesetOpenError` is raised. """ if not self._CurrentChangesetId: raise NoChangesetOpenError("No changeset currently opened") @@ -1163,6 +1268,9 @@ def ChangesetUpload(self, ChangesData): } Returns list with updated ids. + + If no authentication information are provided, + `osmapi.UsernamePasswordMissingError` is raised. """ data = "" data += "\n" @@ -1301,6 +1409,9 @@ def ChangesetComment(self, ChangesetId, comment): 'uid': id of user that created this changeset, } + + If no authentication information are provided, + `osmapi.UsernamePasswordMissingError` is raised. """ params = urllib.urlencode({'text': comment}) data = self._post( @@ -1335,6 +1446,9 @@ def ChangesetSubscribe(self, ChangesetId): 'user': username of user that created this changeset, 'uid': id of user that created this changeset, } + + If no authentication information are provided, + `osmapi.UsernamePasswordMissingError` is raised. """ try: data = self._post( @@ -1374,6 +1488,9 @@ def ChangesetUnsubscribe(self, ChangesetId): 'user': username of user that created this changeset, 'uid': id of user that created this changeset, } + + If no authentication information are provided, + `osmapi.UsernamePasswordMissingError` is raised. """ try: data = self._post( @@ -1466,6 +1583,7 @@ def NoteGet(self, id): def NoteCreate(self, NoteData): """ Creates a note. + Returns updated NoteData (without timestamp). """ uri = "/api/0.6/notes" @@ -1475,6 +1593,7 @@ def NoteCreate(self, NoteData): def NoteComment(self, NoteId, comment): """ Adds a new comment to a note. + Returns the updated note. """ path = "/api/0.6/notes/%s/comment" % NoteId @@ -1483,7 +1602,11 @@ def NoteComment(self, NoteId, comment): def NoteClose(self, NoteId, comment): """ Closes a note. + Returns the updated note. + + If no authentication information are provided, + `osmapi.UsernamePasswordMissingError` is raised. """ path = "/api/0.6/notes/%s/close" % NoteId return self._NoteAction(path, comment, optionalAuth=False) @@ -1491,7 +1614,11 @@ def NoteClose(self, NoteId, comment): def NoteReopen(self, NoteId, comment): """ Reopens a note. + Returns the updated note. + + If no authentication information are provided, + `osmapi.UsernamePasswordMissingError` is raised. """ path = "/api/0.6/notes/%s/reopen" % NoteId return self._NoteAction(path, comment, optionalAuth=False) @@ -1520,6 +1647,7 @@ def NotesSearch(self, query, limit=100, closed=7): def _NoteAction(self, path, comment=None, optionalAuth=True): """ Performs an action on a Note with a comment + Return the updated note """ uri = path @@ -1723,6 +1851,15 @@ def _do_manu(self, action, OsmType, OsmData): def flush(self): """ Force the changes to be uploaded to OSM and the changeset to be closed + + If no authentication information are provided, + `osmapi.UsernamePasswordMissingError` is raised. + + If there is no open changeset, + `osmapi.NoChangesetOpenError` is raised. + + If there is already an open changeset, + `osmapi.ChangesetAlreadyOpenError` is raised. """ return self._changesetautoflush(True) From dcf559ea9d170e5293064d84b5cc8bf06050d962 Mon Sep 17 00:00:00 2001 From: Stefan Oderbolz Date: Tue, 26 May 2015 01:09:56 +0200 Subject: [PATCH 16/20] Remove magic numbers from SSL condition --- osmapi/OsmApi.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/osmapi/OsmApi.py b/osmapi/OsmApi.py index d72223d..5a5f346 100644 --- a/osmapi/OsmApi.py +++ b/osmapi/OsmApi.py @@ -114,9 +114,12 @@ def __init__( If this is omitted "osmapi" is used. It is possible to configure the URL to connect to using the `api` - parameter. By default this is the production API of OpenStreetMap, - for testing purposes, one might prefer the official test instance at - "api06.dev.openstreetmap.org". + parameter. By default this is the SSL version of the production API + of OpenStreetMap, for testing purposes, one might prefer the official + test instance at "api06.dev.openstreetmap.org" or any other valid + OSM-API. To use an encrypted connection (HTTPS) simply add 'https://' + in front of the hostname of the `api` parameter (e.g. + https://api.openstreetmap.com). There are several options to control the changeset behaviour. By default, a programmer has to take care to open and close a changeset @@ -1773,10 +1776,12 @@ def _http(self, cmd, path, auth, send): # noqa self._conn = self._get_http_connection() def _get_http_connection(self): - if self._api.lower().startswith('https://'): - return httplib.HTTPSConnection(self._api[8:], 443) - elif self._api.lower().startswith('http://'): - return httplib.HTTPConnection(self._api[7:], 80) + https_str = 'https://' + http_str = 'http://' + if self._api.lower().startswith(https_str): + return httplib.HTTPSConnection(self._api[len(https_str):], 443) + elif self._api.lower().startswith(http_str): + return httplib.HTTPConnection(self._api[len(http_str):], 80) else: return httplib.HTTPConnection(self._api, 80) From 7c5ed50df210059ed33f6a9733bf3f438f842c8b Mon Sep 17 00:00:00 2001 From: Stefan Oderbolz Date: Tue, 26 May 2015 01:11:36 +0200 Subject: [PATCH 17/20] Print full path when debugging --- osmapi/OsmApi.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/osmapi/OsmApi.py b/osmapi/OsmApi.py index 5a5f346..df96619 100644 --- a/osmapi/OsmApi.py +++ b/osmapi/OsmApi.py @@ -1704,12 +1704,9 @@ def _changesetautoflush(self, force=False): def _http_request(self, cmd, path, auth, send): # noqa if self._debug: - path2 = path - if len(path2) > 50: - path2 = path2[:50]+"[...]" error_msg = ( "%s %s %s" - % (time.strftime("%Y-%m-%d %H:%M:%S"), cmd, path2) + % (time.strftime("%Y-%m-%d %H:%M:%S"), cmd, path) ) print(error_msg, file=sys.stderr) self._conn.putrequest(cmd, path) @@ -1748,7 +1745,7 @@ def _http_request(self, cmd, path, auth, send): # noqa if self._debug: error_msg = ( "%s %s %s" - % (time.strftime("%Y-%m-%d %H:%M:%S"), cmd, path2) + % (time.strftime("%Y-%m-%d %H:%M:%S"), cmd, path) ) print(error_msg, file=sys.stderr) return response.read() From 69e81d0b27f8e76987bd4dfb7dfab337396f10c7 Mon Sep 17 00:00:00 2001 From: Stefan Oderbolz Date: Tue, 26 May 2015 01:35:55 +0200 Subject: [PATCH 18/20] Add changelog entries for all merges --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02d3060..7407692 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. This project follows [Semantic Versioning](http://semver.org/). ## [Unreleased][unreleased] +### Added +- SSL support for the API calls (thanks [Austin Hartzheim](http://austinhartzheim.me/)!) +- Run tests on Python 3.4 as well +- A bunch of new *Error classes (see below) +- Dependency to 'Pygments' to enable syntax highlighting for [online documentation](http://osmapi.divshot.io) +- [Contributing guidelines](https://github.com/metaodi/osmapi/blob/master/CONTRIBUTING.md) + +### Changed +- Changed generic `Exception` with more specific ones, so a client can catch those and react accordingly (no BC-break!) ## 0.5.0 - 2015-01-03 ### Changed From eab753fffe35a770cec13f67ebc975d47f13fc5a Mon Sep 17 00:00:00 2001 From: Stefan Oderbolz Date: Tue, 26 May 2015 01:58:41 +0200 Subject: [PATCH 19/20] Fix broken links to error classes --- osmapi/OsmApi.py | 94 ++++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/osmapi/OsmApi.py b/osmapi/OsmApi.py index 067a08d..8ca5c57 100644 --- a/osmapi/OsmApi.py +++ b/osmapi/OsmApi.py @@ -130,7 +130,9 @@ class OsmApi: """ Main class of osmapi, instanciate this class to use osmapi """ + MAX_RETRY_LIMIT = 5 + """Maximum retries if a call to the remote API fails (default: 5)""" def __init__( self, @@ -353,13 +355,13 @@ def NodeCreate(self, NodeData): } If no authentication information are provided, - `osmapi.UsernamePasswordMissingError` is raised. + `OsmApi.UsernamePasswordMissingError` is raised. If there is no open changeset, - `osmapi.NoChangesetOpenError` is raised. + `OsmApi.NoChangesetOpenError` is raised. If the supplied information contain an existing node, - `osmapi.OsmTypeAlreadyExistsError` is raised. + `OsmApi.OsmTypeAlreadyExistsError` is raised. """ return self._do("create", "node", NodeData) @@ -392,13 +394,13 @@ def NodeUpdate(self, NodeData): } If no authentication information are provided, - `osmapi.UsernamePasswordMissingError` is raised. + `OsmApi.UsernamePasswordMissingError` is raised. If there is no open changeset, - `osmapi.NoChangesetOpenError` is raised. + `OsmApi.NoChangesetOpenError` is raised. If there is already an open changeset, - `osmapi.ChangesetAlreadyOpenError` is raised. + `OsmApi.ChangesetAlreadyOpenError` is raised. """ return self._do("modify", "node", NodeData) @@ -431,13 +433,13 @@ def NodeDelete(self, NodeData): } If no authentication information are provided, - `osmapi.UsernamePasswordMissingError` is raised. + `OsmApi.UsernamePasswordMissingError` is raised. If there is no open changeset, - `osmapi.NoChangesetOpenError` is raised. + `OsmApi.NoChangesetOpenError` is raised. If there is already an open changeset, - `osmapi.ChangesetAlreadyOpenError` is raised. + `OsmApi.ChangesetAlreadyOpenError` is raised. """ return self._do("delete", "node", NodeData) @@ -624,16 +626,16 @@ def WayCreate(self, WayData): } If no authentication information are provided, - `osmapi.UsernamePasswordMissingError` is raised. + `OsmApi.UsernamePasswordMissingError` is raised. If the supplied information contain an existing node, - `osmapi.OsmTypeAlreadyExistsError` is raised. + `OsmApi.OsmTypeAlreadyExistsError` is raised. If there is no open changeset, - `osmapi.NoChangesetOpenError` is raised. + `OsmApi.NoChangesetOpenError` is raised. If there is already an open changeset, - `osmapi.ChangesetAlreadyOpenError` is raised. + `OsmApi.ChangesetAlreadyOpenError` is raised. """ return self._do("create", "way", WayData) @@ -664,13 +666,13 @@ def WayUpdate(self, WayData): } If no authentication information are provided, - `osmapi.UsernamePasswordMissingError` is raised. + `OsmApi.UsernamePasswordMissingError` is raised. If there is no open changeset, - `osmapi.NoChangesetOpenError` is raised. + `OsmApi.NoChangesetOpenError` is raised. If there is already an open changeset, - `osmapi.ChangesetAlreadyOpenError` is raised. + `OsmApi.ChangesetAlreadyOpenError` is raised. """ return self._do("modify", "way", WayData) @@ -701,13 +703,13 @@ def WayDelete(self, WayData): } If no authentication information are provided, - `osmapi.UsernamePasswordMissingError` is raised. + `OsmApi.UsernamePasswordMissingError` is raised. If there is no open changeset, - `osmapi.NoChangesetOpenError` is raised. + `OsmApi.NoChangesetOpenError` is raised. If there is already an open changeset, - `osmapi.ChangesetAlreadyOpenError` is raised. + `OsmApi.ChangesetAlreadyOpenError` is raised. """ return self._do("delete", "way", WayData) @@ -897,16 +899,16 @@ def RelationCreate(self, RelationData): } If no authentication information are provided, - `osmapi.UsernamePasswordMissingError` is raised. + `OsmApi.UsernamePasswordMissingError` is raised. If the supplied information contain an existing node, - `osmapi.OsmTypeAlreadyExistsError` is raised. + `OsmApi.OsmTypeAlreadyExistsError` is raised. If there is no open changeset, - `osmapi.NoChangesetOpenError` is raised. + `OsmApi.NoChangesetOpenError` is raised. If there is already an open changeset, - `osmapi.ChangesetAlreadyOpenError` is raised. + `OsmApi.ChangesetAlreadyOpenError` is raised. """ return self._do("create", "relation", RelationData) @@ -946,13 +948,13 @@ def RelationUpdate(self, RelationData): } If no authentication information are provided, - `osmapi.UsernamePasswordMissingError` is raised. + `OsmApi.UsernamePasswordMissingError` is raised. If there is no open changeset, - `osmapi.NoChangesetOpenError` is raised. + `OsmApi.NoChangesetOpenError` is raised. If there is already an open changeset, - `osmapi.ChangesetAlreadyOpenError` is raised. + `OsmApi.ChangesetAlreadyOpenError` is raised. """ return self._do("modify", "relation", RelationData) @@ -992,13 +994,13 @@ def RelationDelete(self, RelationData): } If no authentication information are provided, - `osmapi.UsernamePasswordMissingError` is raised. + `OsmApi.UsernamePasswordMissingError` is raised. If there is no open changeset, - `osmapi.NoChangesetOpenError` is raised. + `OsmApi.NoChangesetOpenError` is raised. If there is already an open changeset, - `osmapi.ChangesetAlreadyOpenError` is raised. + `OsmApi.ChangesetAlreadyOpenError` is raised. """ return self._do("delete", "relation", RelationData) @@ -1086,7 +1088,7 @@ def RelationFullRecur(self, RelationId): This function is useful for relations containing other relations. - If you don't need all levels, use `osmapi.OsmApi.RelationFull` + If you don't need all levels, use `OsmApi.RelationFull` instead, which return only 2 levels. """ data = [] @@ -1121,7 +1123,7 @@ def RelationFull(self, RelationId): The `RelationId` is a unique identifier for a way. - If you need all levels, use `osmapi.OsmApi.RelationFullRecur`. + If you need all levels, use `OsmApi.RelationFullRecur`. """ uri = "/api/0.6/relation/"+str(RelationId)+"/full" data = self._get(uri) @@ -1197,10 +1199,10 @@ def ChangesetUpdate(self, ChangesetTags={}): Updates current changeset with `ChangesetTags`. If no authentication information are provided, - `osmapi.UsernamePasswordMissingError` is raised. + `OsmApi.UsernamePasswordMissingError` is raised. If there is no open changeset, - `osmapi.NoChangesetOpenError` is raised. + `OsmApi.NoChangesetOpenError` is raised. """ if not self._CurrentChangesetId: raise NoChangesetOpenError("No changeset currently opened") @@ -1221,10 +1223,10 @@ def ChangesetCreate(self, ChangesetTags={}): Returns `ChangesetId` If no authentication information are provided, - `osmapi.UsernamePasswordMissingError` is raised. + `OsmApi.UsernamePasswordMissingError` is raised. If there is already an open changeset, - `osmapi.ChangesetAlreadyOpenError` is raised. + `OsmApi.ChangesetAlreadyOpenError` is raised. """ if self._CurrentChangesetId: raise ChangesetAlreadyOpenError("Changeset already opened") @@ -1244,10 +1246,10 @@ def ChangesetClose(self): Returns `ChangesetId`. If no authentication information are provided, - `osmapi.UsernamePasswordMissingError` is raised. + `OsmApi.UsernamePasswordMissingError` is raised. If there is no open changeset, - `osmapi.NoChangesetOpenError` is raised. + `OsmApi.NoChangesetOpenError` is raised. """ if not self._CurrentChangesetId: raise NoChangesetOpenError("No changeset currently opened") @@ -1273,7 +1275,7 @@ def ChangesetUpload(self, ChangesData): Returns list with updated ids. If no authentication information are provided, - `osmapi.UsernamePasswordMissingError` is raised. + `OsmApi.UsernamePasswordMissingError` is raised. """ data = "" data += "\n" @@ -1414,7 +1416,7 @@ def ChangesetComment(self, ChangesetId, comment): If no authentication information are provided, - `osmapi.UsernamePasswordMissingError` is raised. + `OsmApi.UsernamePasswordMissingError` is raised. """ params = urllib.urlencode({'text': comment}) data = self._post( @@ -1451,7 +1453,7 @@ def ChangesetSubscribe(self, ChangesetId): } If no authentication information are provided, - `osmapi.UsernamePasswordMissingError` is raised. + `OsmApi.UsernamePasswordMissingError` is raised. """ try: data = self._post( @@ -1493,7 +1495,7 @@ def ChangesetUnsubscribe(self, ChangesetId): } If no authentication information are provided, - `osmapi.UsernamePasswordMissingError` is raised. + `OsmApi.UsernamePasswordMissingError` is raised. """ try: data = self._post( @@ -1609,7 +1611,7 @@ def NoteClose(self, NoteId, comment): Returns the updated note. If no authentication information are provided, - `osmapi.UsernamePasswordMissingError` is raised. + `OsmApi.UsernamePasswordMissingError` is raised. """ path = "/api/0.6/notes/%s/close" % NoteId return self._NoteAction(path, comment, optionalAuth=False) @@ -1621,7 +1623,7 @@ def NoteReopen(self, NoteId, comment): Returns the updated note. If no authentication information are provided, - `osmapi.UsernamePasswordMissingError` is raised. + `OsmApi.UsernamePasswordMissingError` is raised. """ path = "/api/0.6/notes/%s/reopen" % NoteId return self._NoteAction(path, comment, optionalAuth=False) @@ -1856,13 +1858,13 @@ def flush(self): Force the changes to be uploaded to OSM and the changeset to be closed If no authentication information are provided, - `osmapi.UsernamePasswordMissingError` is raised. + `OsmApi.UsernamePasswordMissingError` is raised. If there is no open changeset, - `osmapi.NoChangesetOpenError` is raised. + `OsmApi.NoChangesetOpenError` is raised. If there is already an open changeset, - `osmapi.ChangesetAlreadyOpenError` is raised. + `OsmApi.ChangesetAlreadyOpenError` is raised. """ return self._changesetautoflush(True) From d846f037b6fe28dc072596b5b729ee7736a0c736 Mon Sep 17 00:00:00 2001 From: Stefan Oderbolz Date: Tue, 26 May 2015 02:11:06 +0200 Subject: [PATCH 20/20] Release 0.6.0 --- CHANGELOG.md | 2 ++ osmapi/__init__.py | 2 +- tests/changeset_tests.py | 18 +++++++++--------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7407692..b07258f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project follows [Semantic Versioning](http://semver.org/). ## [Unreleased][unreleased] + +## 0.6.0 - 2015-05-26 ### Added - SSL support for the API calls (thanks [Austin Hartzheim](http://austinhartzheim.me/)!) - Run tests on Python 3.4 as well diff --git a/osmapi/__init__.py b/osmapi/__init__.py index ddb4e18..ff2f8cf 100644 --- a/osmapi/__init__.py +++ b/osmapi/__init__.py @@ -1,5 +1,5 @@ from __future__ import (absolute_import, print_function, unicode_literals) -__version__ = '0.5.0' +__version__ = '0.6.0' from .OsmApi import * # noqa diff --git a/tests/changeset_tests.py b/tests/changeset_tests.py index deb0b33..f191e68 100644 --- a/tests/changeset_tests.py +++ b/tests/changeset_tests.py @@ -100,10 +100,10 @@ def test_ChangesetUpdate(self): xmltosorteddict(sendargs[0]), xmltosorteddict( b'\n' - b'\n' + b'\n' b' \n' b' \n' - b' \n' + b' \n' b' \n' b'\n' ) @@ -134,7 +134,7 @@ def test_ChangesetUpdate_with_created_by(self): xmltosorteddict(sendargs[0]), xmltosorteddict( b'\n' - b'\n' + b'\n' b' \n' b' \n' b' \n' @@ -173,10 +173,10 @@ def test_ChangesetCreate(self): xmltosorteddict(sendargs[0]), xmltosorteddict( b'\n' - b'\n' + b'\n' b' \n' b' \n' - b' \n' + b' \n' b' \n' b'\n' ) @@ -201,7 +201,7 @@ def test_ChangesetCreate_with_created_by(self): xmltosorteddict(sendargs[0]), xmltosorteddict( b'\n' - b'\n' + b'\n' b' \n' b' \n' b' \n' @@ -286,7 +286,7 @@ def test_ChangesetUpload_create_node(self): xmltosorteddict(sendargs[0]), xmltosorteddict( b'\n' - b'\n' + b'\n' b'\n' b' \n' @@ -360,7 +360,7 @@ def test_ChangesetUpload_modify_way(self): xmltosorteddict(sendargs[0]), xmltosorteddict( b'\n' - b'\n' + b'\n' b'\n' b' \n' @@ -444,7 +444,7 @@ def test_ChangesetUpload_delete_relation(self): xmltosorteddict(sendargs[0]), xmltosorteddict( b'\n' - b'\n' + b'\n' b'\n' b' \n'