| # -*-*- encoding: utf-8 -*-*- |
| # |
| # This is gdata.photos.geo, implementing geological positioning in gdata structures |
| # |
| # $Id: __init__.py 81 2007-10-03 14:41:42Z havard.gulldahl $ |
| # |
| # Copyright 2007 Håvard Gulldahl |
| # Portions copyright 2007 Google Inc. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| """Picasa Web Albums uses the georss and gml namespaces for |
| elements defined in the GeoRSS and Geography Markup Language specifications. |
| |
| Specifically, Picasa Web Albums uses the following elements: |
| |
| georss:where |
| gml:Point |
| gml:pos |
| |
| http://code.google.com/apis/picasaweb/reference.html#georss_reference |
| |
| |
| Picasa Web Albums also accepts geographic-location data in two other formats: |
| W3C format and plain-GeoRSS (without GML) format. |
| """ |
| # |
| #Over the wire, the Picasa Web Albums only accepts and sends the |
| #elements mentioned above, but this module will let you seamlessly convert |
| #between the different formats (TODO 2007-10-18 hg) |
| |
| __author__ = u'havard@gulldahl.no'# (Håvard Gulldahl)' #BUG: api chokes on non-ascii chars in __author__ |
| __license__ = 'Apache License v2' |
| |
| |
| import atom |
| import gdata |
| |
| GEO_NAMESPACE = 'http://www.w3.org/2003/01/geo/wgs84_pos#' |
| GML_NAMESPACE = 'http://www.opengis.net/gml' |
| GEORSS_NAMESPACE = 'http://www.georss.org/georss' |
| |
| class GeoBaseElement(atom.AtomBase): |
| """Base class for elements. |
| |
| To add new elements, you only need to add the element tag name to self._tag |
| and the namespace to self._namespace |
| """ |
| |
| _tag = '' |
| _namespace = GML_NAMESPACE |
| _children = atom.AtomBase._children.copy() |
| _attributes = atom.AtomBase._attributes.copy() |
| |
| def __init__(self, name=None, extension_elements=None, |
| extension_attributes=None, text=None): |
| self.name = name |
| self.text = text |
| self.extension_elements = extension_elements or [] |
| self.extension_attributes = extension_attributes or {} |
| |
| class Pos(GeoBaseElement): |
| """(string) Specifies a latitude and longitude, separated by a space, |
| e.g. `35.669998 139.770004'""" |
| |
| _tag = 'pos' |
| def PosFromString(xml_string): |
| return atom.CreateClassFromXMLString(Pos, xml_string) |
| |
| class Point(GeoBaseElement): |
| """(container) Specifies a particular geographical point, by means of |
| a <gml:pos> element.""" |
| |
| _tag = 'Point' |
| _children = atom.AtomBase._children.copy() |
| _children['{%s}pos' % GML_NAMESPACE] = ('pos', Pos) |
| def __init__(self, pos=None, extension_elements=None, extension_attributes=None, text=None): |
| GeoBaseElement.__init__(self, extension_elements=extension_elements, |
| extension_attributes=extension_attributes, |
| text=text) |
| if pos is None: |
| pos = Pos() |
| self.pos=pos |
| def PointFromString(xml_string): |
| return atom.CreateClassFromXMLString(Point, xml_string) |
| |
| class Where(GeoBaseElement): |
| """(container) Specifies a geographical location or region. |
| A container element, containing a single <gml:Point> element. |
| (Not to be confused with <gd:where>.) |
| |
| Note that the (only) child attribute, .Point, is title-cased. |
| This reflects the names of elements in the xml stream |
| (principle of least surprise). |
| |
| As a convenience, you can get a tuple of (lat, lon) with Where.location(), |
| and set the same data with Where.setLocation( (lat, lon) ). |
| |
| Similarly, there are methods to set and get only latitude and longitude. |
| """ |
| |
| _tag = 'where' |
| _namespace = GEORSS_NAMESPACE |
| _children = atom.AtomBase._children.copy() |
| _children['{%s}Point' % GML_NAMESPACE] = ('Point', Point) |
| def __init__(self, point=None, extension_elements=None, extension_attributes=None, text=None): |
| GeoBaseElement.__init__(self, extension_elements=extension_elements, |
| extension_attributes=extension_attributes, |
| text=text) |
| if point is None: |
| point = Point() |
| self.Point=point |
| def location(self): |
| "(float, float) Return Where.Point.pos.text as a (lat,lon) tuple" |
| try: |
| return tuple([float(z) for z in self.Point.pos.text.split(' ')]) |
| except AttributeError: |
| return tuple() |
| def set_location(self, latlon): |
| """(bool) Set Where.Point.pos.text from a (lat,lon) tuple. |
| |
| Arguments: |
| lat (float): The latitude in degrees, from -90.0 to 90.0 |
| lon (float): The longitude in degrees, from -180.0 to 180.0 |
| |
| Returns True on success. |
| |
| """ |
| |
| assert(isinstance(latlon[0], float)) |
| assert(isinstance(latlon[1], float)) |
| try: |
| self.Point.pos.text = "%s %s" % (latlon[0], latlon[1]) |
| return True |
| except AttributeError: |
| return False |
| def latitude(self): |
| "(float) Get the latitude value of the geo-tag. See also .location()" |
| lat, lon = self.location() |
| return lat |
| |
| def longitude(self): |
| "(float) Get the longtitude value of the geo-tag. See also .location()" |
| lat, lon = self.location() |
| return lon |
| |
| longtitude = longitude |
| |
| def set_latitude(self, lat): |
| """(bool) Set the latitude value of the geo-tag. |
| |
| Args: |
| lat (float): The new latitude value |
| |
| See also .set_location() |
| """ |
| _lat, lon = self.location() |
| return self.set_location(lat, lon) |
| |
| def set_longitude(self, lon): |
| """(bool) Set the longtitude value of the geo-tag. |
| |
| Args: |
| lat (float): The new latitude value |
| |
| See also .set_location() |
| """ |
| lat, _lon = self.location() |
| return self.set_location(lat, lon) |
| |
| set_longtitude = set_longitude |
| |
| def WhereFromString(xml_string): |
| return atom.CreateClassFromXMLString(Where, xml_string) |
| |