# -*-*- 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 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 element. (Not to be confused with .) 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)