source: subversion/applications/utils/import/bulkupload/set-changeset-tag.py @ 20882

Last change on this file since 20882 was 19989, checked in by balrog-kun, 10 years ago

Set the executable bits on the executables. (this directory still needs a clean-up)

  • Property svn:executable set to *
File size: 7.4 KB
Line 
1#! /usr/bin/python2
2# vim: fileencoding=utf-8 encoding=utf-8 et sw=4
3
4# Copyright (C) 2009 Jacek Konieczny <jajcus@jajcus.net>
5# Copyright (C) 2009 Andrzej Zaborowski <balrogg@gmail.com>
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20
21"""
22Set a tag on an open changeset
23"""
24
25__version__ = "$Revision: 21 $"
26
27import os
28import subprocess
29import sys
30import traceback
31import codecs
32import locale
33
34import httplib
35
36import xml.etree.cElementTree as ElementTree
37import urlparse
38
39import locale, codecs
40try:
41    locale.setlocale(locale.LC_ALL, "en_US.UTF-8")
42    encoding = locale.getlocale()[1]
43    sys.stdout = codecs.getwriter(encoding)(sys.stdout, errors = "replace")
44    sys.stderr = codecs.getwriter(encoding)(sys.stderr, errors = "replace")
45except locale.Error:
46    pass
47
48class HTTPError(Exception):
49    pass
50
51class OSM_API(object):
52    url = 'http://api.openstreetmap.org/'
53    def __init__(self, username = None, password = None):
54        if username and password:
55            self.username = username
56            self.password = password
57        else:
58            self.username = ""
59            self.password = ""
60        self.changeset = None
61        self.tags = {}
62        self.progress_msg = None
63
64    def __del__(self):
65        #if self.changeset is not None:
66        #    self.close_changeset()
67        pass
68
69    def msg(self, mesg):
70        sys.stderr.write(u"\r%s…                        " % (self.progress_msg))
71        sys.stderr.write(u"\r%s%s" % (self.progress_msg, mesg))
72        sys.stderr.flush()
73
74    def request(self, conn, method, url, body, headers, progress):
75        if progress:
76            self.msg(u"making request")
77            conn.putrequest(method, url)
78            self.msg(u"sending headers")
79            if body:
80                conn.putheader('Content-Length', str(len(body)))
81            for hdr, value in headers.iteritems():
82                conn.putheader(hdr, value)
83            self.msg(u"end of headers")
84            conn.endheaders()
85            self.msg(u" 0%")
86            if body:
87                start = 0
88                size = len(body)
89                chunk = size / 100
90                if chunk < 16384:
91                    chunk = 16384
92                while start < size:
93                    end = min(size, start + chunk)
94                    conn.send(body[start:end])
95                    start = end
96                    self.msg(u"%2i%%" % (start * 100 / size))
97        else:
98            self.msg(u" ")
99            conn.request(method, url, body, headers)
100
101    def _run_request(self, method, url, body = None, progress = 0, content_type = "text/xml"):
102        url = urlparse.urljoin(self.url, url)
103        purl = urlparse.urlparse(url)
104        if purl.scheme != "http":
105            raise ValueError, "Unsupported url scheme: %r" % (purl.scheme,)
106        if ":" in purl.netloc:
107            host, port = purl.netloc.split(":", 1)
108            port = int(port)
109        else:
110            host = purl.netloc
111            port = None
112        url = purl.path
113        if purl.query:
114            url += "?" + query
115        headers = {}
116        if body:
117            headers["Content-Type"] = content_type
118
119        try_no_auth = 0
120
121        if not try_no_auth and not self.username:
122            raise HTTPError, "Need a username"
123
124        try:
125            self.msg(u"connecting")
126            conn = httplib.HTTPConnection(host, port)
127#            conn.set_debuglevel(10)
128
129            if try_no_auth:
130                self.request(conn, method, url, body, headers, progress)
131                self.msg(u"waiting for status")
132                response = conn.getresponse()
133
134            if not try_no_auth or (response.status == httplib.UNAUTHORIZED and
135                    self.username):
136                if try_no_auth:
137                    conn.close()
138                    self.msg(u"re-connecting")
139                    conn = httplib.HTTPConnection(host, port)
140#                    conn.set_debuglevel(10)
141
142                creds = self.username + ":" + self.password
143                headers["Authorization"] = "Basic " + \
144                        creds.encode("base64").strip()
145                self.request(conn, method, url, body, headers, progress)
146                self.msg(u"waiting for status")
147                response = conn.getresponse()
148
149            if response.status == httplib.OK:
150                self.msg(u"reading response")
151                sys.stderr.flush()
152                response_body = response.read()
153            else:
154                raise HTTPError, "%02i: %s (%s)" % (response.status,
155                        response.reason, response.read())
156        finally:
157            conn.close()
158        return response_body
159
160    def get_changeset_tags(self):
161        if self.changeset is None:
162            raise RuntimeError, "Changeset not opened"
163        self.progress_msg = u"Getting changeset tags"
164        self.msg(u"")
165        reply = self._run_request("GET", "/api/0.6/changeset/" +
166                str(self.changeset), None)
167        root = ElementTree.XML(reply)
168        if root.tag != "osm" or root[0].tag != "changeset":
169            print >>sys.stderr, u"API returned unexpected XML!"
170            sys.exit(1)
171
172        for element in root[0]:
173            if element.tag == "tag" and "k" in element.attrib and \
174                    "v" in element.attrib:
175                self.tags[element.attrib["k"]] = element.attrib["v"]
176
177        self.msg(u"done.")
178        print >>sys.stderr, u""
179
180    def set_changeset_tags(self):
181        self.progress_msg = u"Setting new changeset tags"
182        self.msg(u"")
183
184        root = ElementTree.Element("osm")
185        tree = ElementTree.ElementTree(root)
186        element = ElementTree.SubElement(root, "changeset")
187        for key in self.tags:
188            ElementTree.SubElement(element, "tag",
189                    { "k": key, "v": self.tags[key] })
190
191        self._run_request("PUT", "/api/0.6/changeset/" +
192                str(self.changeset), ElementTree.tostring(root, "utf-8"))
193
194        self.msg(u"done, too.")
195        print >>sys.stderr, u""
196
197try:
198    this_dir = os.path.dirname(__file__)
199    try:
200        version = int(subprocess.Popen(["svnversion", this_dir], stdout = subprocess.PIPE).communicate()[0].strip())
201    except:
202        version = 1
203    if len(sys.argv) < 3 or (len(sys.argv) & 2):
204        print >>sys.stderr, u"Synopsis:"
205        print >>sys.stderr, u"    %s <changeset> <key> <value> [...]"
206        sys.exit(1)
207
208    login = raw_input("OSM login: ")
209    if not login:
210        sys.exit(1)
211    password = raw_input("OSM password: ")
212    if not password:
213        sys.exit(1)
214
215    api = OSM_API(login, password)
216    api.changeset = int(sys.argv[1])
217
218    api.get_changeset_tags()
219    api.tags.update(zip(sys.argv[2::2], sys.argv[3::2]))
220    api.set_changeset_tags()
221except HTTPError, err:
222    print >>sys.stderr, err
223    sys.exit(1)
224except Exception,err:
225    print >>sys.stderr, repr(err)
226    traceback.print_exc(file=sys.stderr)
227    sys.exit(1)
Note: See TracBrowser for help on using the repository browser.