[python-osmapi] 01/05: Imported Upstream version 0.6.0
Sebastiaan Couwenberg
sebastic at moszumanska.debian.org
Sat May 30 15:02:50 UTC 2015
This is an automated email from the git hooks/post-receive script.
sebastic pushed a commit to branch master
in repository python-osmapi.
commit 1f5d976f9e9f110460896d3ba24d75ffa539e7ee
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Sat May 30 16:25:35 2015 +0200
Imported Upstream version 0.6.0
---
.travis.yml | 1 +
CHANGELOG.md | 11 ++
CONTRIBUTING.md | 55 +++++++++
osmapi/OsmApi.py | 245 ++++++++++++++++++++++++++++++++++++----
osmapi/__init__.py | 2 +-
requirements.txt | 1 +
setup.py | 2 +-
tests/changeset_tests.py | 30 ++---
tests/fixtures/passwordfile.txt | 1 +
tests/helper_tests.py | 18 +++
tests/node_tests.py | 53 ++++++++-
tests/relation_tests.py | 32 ++++++
tests/way_tests.py | 22 ++++
tox.ini | 2 +-
14 files changed, 429 insertions(+), 46 deletions(-)
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
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 02d3060..b07258f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,17 @@ 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
+- 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
- BC-break: all dates are now parsed as datetime objects
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..9031492
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,55 @@
+# Contributing
+
+If you want to participate in this project, please follow this guidline.
+
+Fork and clone this repository:
+
+```bash
+git clone git at 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
+```
+
+## 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.
+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].
+
+[pr]: https://github.com/metaodi/osmapi/compare/
+[ci]: https://travis-ci.org/metaodi/osmapi
+[pep8]: https://www.python.org/dev/peps/pep-0008/
+[commit]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
diff --git a/osmapi/OsmApi.py b/osmapi/OsmApi.py
index 74affbb..8ca5c57 100644
--- a/osmapi/OsmApi.py
+++ b/osmapi/OsmApi.py
@@ -39,21 +39,56 @@ import sys
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 OsmApiError(Exception):
+ """
+ General OsmApi error class to provide a superclass for all other errors
+ """
-class UsernamePasswordMissingError(Exception):
+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 ApiError(Exception):
+class NoChangesetOpenError(OsmApiError):
+ """
+ Error when an operation requires an open changeset, but currently
+ no changeset _is_ open
+ """
+ pass
+
+
+class ChangesetAlreadyOpenError(OsmApiError):
+ """
+ Error when a user tries to open a changeset when there is already
+ an open changeset
+ """
+ pass
+
+
+class OsmTypeAlreadyExistsError(OsmApiError):
+ """
+ Error when a user tries to create an object that already exsits
+ """
+ pass
+
+
+class ApiError(OsmApiError):
"""
Error class, is thrown when an API request fails
"""
@@ -76,10 +111,18 @@ class ApiError(Exception):
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
@@ -88,6 +131,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,
username=None,
@@ -95,7 +141,7 @@ class OsmApi:
passwordfile=None,
appid="",
created_by="osmapi/"+__version__,
- api="www.openstreetmap.org",
+ api="https://www.openstreetmap.org",
changesetauto=False,
changesetautotags={},
changesetautosize=500,
@@ -114,9 +160,12 @@ class OsmApi:
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
@@ -304,6 +353,15 @@ class OsmApi:
'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)
@@ -334,6 +392,15 @@ class OsmApi:
'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)
@@ -364,6 +431,15 @@ class OsmApi:
'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)
@@ -548,6 +624,18 @@ class OsmApi:
'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)
@@ -576,6 +664,15 @@ class OsmApi:
'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)
@@ -604,6 +701,15 @@ class OsmApi:
'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)
@@ -791,6 +897,18 @@ class OsmApi:
'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)
@@ -828,6 +946,15 @@ class OsmApi:
'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)
@@ -865,6 +992,15 @@ class OsmApi:
'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)
@@ -952,7 +1088,7 @@ class OsmApi:
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 = []
@@ -987,7 +1123,7 @@ class OsmApi:
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)
@@ -1061,9 +1197,15 @@ class OsmApi:
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 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(
@@ -1079,9 +1221,15 @@ class OsmApi:
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 Exception("Changeset already opened")
+ raise ChangesetAlreadyOpenError("Changeset already opened")
if "created_by" not in ChangesetTags:
ChangesetTags["created_by"] = self._created_by
result = self._put(
@@ -1096,9 +1244,15 @@ class OsmApi:
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 Exception("No changeset currently opened")
+ raise NoChangesetOpenError("No changeset currently opened")
self._put(
"/api/0.6/changeset/"+str(self._CurrentChangesetId)+"/close",
""
@@ -1119,6 +1273,9 @@ class OsmApi:
}
Returns list with updated ids.
+
+ If no authentication information are provided,
+ `OsmApi.UsernamePasswordMissingError` is raised.
"""
data = ""
data += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
@@ -1257,6 +1414,9 @@ class OsmApi:
'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(
@@ -1291,6 +1451,9 @@ class OsmApi:
'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(
@@ -1330,6 +1493,9 @@ class OsmApi:
'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(
@@ -1422,6 +1588,7 @@ class OsmApi:
def NoteCreate(self, NoteData):
"""
Creates a note.
+
Returns updated NoteData (without timestamp).
"""
uri = "/api/0.6/notes"
@@ -1431,6 +1598,7 @@ class OsmApi:
def NoteComment(self, NoteId, comment):
"""
Adds a new comment to a note.
+
Returns the updated note.
"""
path = "/api/0.6/notes/%s/comment" % NoteId
@@ -1439,7 +1607,11 @@ class OsmApi:
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)
@@ -1447,7 +1619,11 @@ class OsmApi:
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)
@@ -1476,6 +1652,7 @@ class OsmApi:
def _NoteAction(self, path, comment=None, optionalAuth=True):
"""
Performs an action on a Note with a comment
+
Return the updated note
"""
uri = path
@@ -1642,7 +1819,7 @@ class OsmApi:
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 +1827,9 @@ class OsmApi:
OsmData["changeset"] = self._CurrentChangesetId
if action == "create":
if OsmData.get("id", -1) > 0:
- raise Exception("This "+OsmType+" already exists")
+ raise OsmTypeAlreadyExistsError(
+ "This "+OsmType+" already exists"
+ )
result = self._put(
"/api/0.6/" + OsmType + "/create",
self._XmlBuild(OsmType, OsmData)
@@ -1677,6 +1856,15 @@ class OsmApi:
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)
@@ -1701,12 +1889,9 @@ class OsmApi:
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)
@@ -1745,7 +1930,7 @@ class OsmApi:
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()
@@ -1758,22 +1943,34 @@ class OsmApi:
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()
def _get_http_connection(self):
- return httplib.HTTPConnection(self._api, 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)
def _sleep(self):
time.sleep(5)
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/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
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 @@ try:
except (IOError, ImportError):
description = 'Python wrapper for the OSM API'
-from distutils.core import setup
setup(
name='osmapi',
packages=['osmapi'],
diff --git a/tests/changeset_tests.py b/tests/changeset_tests.py
index 7024a23..f191e68 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
@@ -100,10 +100,10 @@ class TestOsmApiChangeset(osmapi_tests.TestOsmApi):
xmltosorteddict(sendargs[0]),
xmltosorteddict(
b'<?xml version="1.0" encoding="UTF-8"?>\n'
- b'<osm version="0.6" generator="osmapi/0.5.0">\n'
+ b'<osm version="0.6" generator="osmapi/0.6.0">\n'
b' <changeset visible="true">\n'
b' <tag k="test" v="foobar"/>\n'
- b' <tag k="created_by" v="osmapi/0.5.0"/>\n'
+ b' <tag k="created_by" v="osmapi/0.6.0"/>\n'
b' </changeset>\n'
b'</osm>\n'
)
@@ -134,7 +134,7 @@ class TestOsmApiChangeset(osmapi_tests.TestOsmApi):
xmltosorteddict(sendargs[0]),
xmltosorteddict(
b'<?xml version="1.0" encoding="UTF-8"?>\n'
- b'<osm version="0.6" generator="osmapi/0.5.0">\n'
+ b'<osm version="0.6" generator="osmapi/0.6.0">\n'
b' <changeset visible="true">\n'
b' <tag k="test" v="foobar"/>\n'
b' <tag k="created_by" v="MyTestOSMApp"/>\n'
@@ -148,7 +148,7 @@ class TestOsmApiChangeset(osmapi_tests.TestOsmApi):
self._conn_mock()
with self.assertRaisesRegexp(
- Exception,
+ osmapi.NoChangesetOpenError,
'No changeset currently opened'):
self.api.ChangesetUpdate(
{
@@ -173,10 +173,10 @@ class TestOsmApiChangeset(osmapi_tests.TestOsmApi):
xmltosorteddict(sendargs[0]),
xmltosorteddict(
b'<?xml version="1.0" encoding="UTF-8"?>\n'
- b'<osm version="0.6" generator="osmapi/0.5.0">\n'
+ b'<osm version="0.6" generator="osmapi/0.6.0">\n'
b' <changeset visible="true">\n'
b' <tag k="foobar" v="A new test changeset"/>\n'
- b' <tag k="created_by" v="osmapi/0.5.0"/>\n'
+ b' <tag k="created_by" v="osmapi/0.6.0"/>\n'
b' </changeset>\n'
b'</osm>\n'
)
@@ -201,7 +201,7 @@ class TestOsmApiChangeset(osmapi_tests.TestOsmApi):
xmltosorteddict(sendargs[0]),
xmltosorteddict(
b'<?xml version="1.0" encoding="UTF-8"?>\n'
- b'<osm version="0.6" generator="osmapi/0.5.0">\n'
+ b'<osm version="0.6" generator="osmapi/0.6.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'
@@ -221,7 +221,7 @@ class TestOsmApiChangeset(osmapi_tests.TestOsmApi):
)
with self.assertRaisesRegexp(
- Exception,
+ osmapi.ChangesetAlreadyOpenError,
'Changeset already opened'):
self.api.ChangesetCreate(
{
@@ -248,7 +248,7 @@ class TestOsmApiChangeset(osmapi_tests.TestOsmApi):
self._conn_mock()
with self.assertRaisesRegexp(
- Exception,
+ osmapi.NoChangesetOpenError,
'No changeset currently opened'):
self.api.ChangesetClose()
@@ -286,7 +286,7 @@ class TestOsmApiChangeset(osmapi_tests.TestOsmApi):
xmltosorteddict(sendargs[0]),
xmltosorteddict(
b'<?xml version="1.0" encoding="UTF-8"?>\n'
- b'<osmChange version="0.6" generator="osmapi/0.5.0">\n'
+ b'<osmChange version="0.6" generator="osmapi/0.6.0">\n'
b'<create>\n'
b' <node lat="47.123" lon="8.555" visible="true" '
b'changeset="4444">\n'
@@ -360,7 +360,7 @@ class TestOsmApiChangeset(osmapi_tests.TestOsmApi):
xmltosorteddict(sendargs[0]),
xmltosorteddict(
b'<?xml version="1.0" encoding="UTF-8"?>\n'
- b'<osmChange version="0.6" generator="osmapi/0.5.0">\n'
+ b'<osmChange version="0.6" generator="osmapi/0.6.0">\n'
b'<modify>\n'
b' <way id="4294967296" version="2" visible="true" '
b'changeset="4444">\n'
@@ -444,7 +444,7 @@ class TestOsmApiChangeset(osmapi_tests.TestOsmApi):
xmltosorteddict(sendargs[0]),
xmltosorteddict(
b'<?xml version="1.0" encoding="UTF-8"?>\n'
- b'<osmChange version="0.6" generator="osmapi/0.5.0">\n'
+ b'<osmChange version="0.6" generator="osmapi/0.6.0">\n'
b'<delete>\n'
b' <relation id="676" version="2" visible="true" '
b'changeset="4444">\n'
@@ -652,7 +652,7 @@ class TestOsmApiChangeset(osmapi_tests.TestOsmApi):
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 @@ class TestOsmApiChangeset(osmapi_tests.TestOsmApi):
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/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 nose.tools import * # noqa
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 @@ class TestOsmApiHelper(osmapi_tests.TestOsmApi):
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',
diff --git a/tests/node_tests.py b/tests/node_tests.py
index b435c70..8fa1c12 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 @@ class TestOsmApiNode(osmapi_tests.TestOsmApi):
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 @@ class TestOsmApiNode(osmapi_tests.TestOsmApi):
}
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,10 +168,33 @@ class TestOsmApiNode(osmapi_tests.TestOsmApi):
}
with self.assertRaisesRegexp(
- UsernamePasswordMissingError,
+ osmapi.UsernamePasswordMissingError,
'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)
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 @@ class TestOsmApiRelation(osmapi_tests.TestOsmApi):
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 @@ class TestOsmApiWay(osmapi_tests.TestOsmApi):
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)
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 =
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/python-osmapi.git
More information about the Pkg-grass-devel
mailing list