Commit a35dd031 authored by Ian Lee's avatar Ian Lee

Applied PEP8 and Pyflakes style guidelines to fastkml source code using the

following style checkers:
* pep8 (version 1.5.7)
* pyflakes (version 0.7.3)
parent 9eac7e71
...@@ -17,6 +17,7 @@ install: ...@@ -17,6 +17,7 @@ install:
# command to run tests, e.g. python setup.py test # command to run tests, e.g. python setup.py test
script: script:
pep8 --exclude test_main.py fastkml
coverage run --source=fastkml setup.py test coverage run --source=fastkml setup.py test
after_success: after_success:
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2012 Christian Ledermann # Copyright (C) 2012 Christian Ledermann
#
# This library is free software; you can redistribute it and/or # This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public # modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either # License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version. # version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful, # This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details. # Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public # You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software # License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2012 Christian Ledermann # Copyright (C) 2012 Christian Ledermann
#
# This library is free software; you can redistribute it and/or # This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public # modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either # License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version. # version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful, # This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details. # Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public # You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software # License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
...@@ -82,10 +82,11 @@ class Link(object): ...@@ -82,10 +82,11 @@ class Link(object):
length = None length = None
# the length of the resource, in bytes # the length of the resource, in bytes
def __init__(
def __init__(self, ns=None, href=None, rel=None, type=None, self, ns=None, href=None, rel=None, type=None,
hreflang=None, title=None, length=None): hreflang=None, title=None, length=None
if ns == None: ):
if ns is None:
self.ns = NS self.ns = NS
else: else:
self.ns = ns self.ns = ns
...@@ -99,7 +100,6 @@ class Link(object): ...@@ -99,7 +100,6 @@ class Link(object):
def from_string(self, xml_string): def from_string(self, xml_string):
self.from_element(etree.XML(xml_string)) self.from_element(etree.XML(xml_string))
def from_element(self, element): def from_element(self, element):
if self.ns + self.__name__.lower() != element.tag: if self.ns + self.__name__.lower() != element.tag:
raise TypeError raise TypeError
...@@ -120,7 +120,6 @@ class Link(object): ...@@ -120,7 +120,6 @@ class Link(object):
if element.get('length'): if element.get('length'):
self.length = element.get('length') self.length = element.get('length')
def etree_element(self): def etree_element(self):
element = etree.Element(self.ns + self.__name__.lower()) element = etree.Element(self.ns + self.__name__.lower())
if self.href: if self.href:
...@@ -142,10 +141,13 @@ class Link(object): ...@@ -142,10 +141,13 @@ class Link(object):
def to_string(self, prettyprint=True): def to_string(self, prettyprint=True):
""" Return the ATOM Object as serialized xml """ """ Return the ATOM Object as serialized xml """
if LXML and prettyprint: if LXML and prettyprint:
return etree.tostring(self.etree_element(), encoding='utf-8', return etree.tostring(
self.etree_element(),
encoding='utf-8',
pretty_print=True).decode('UTF-8') pretty_print=True).decode('UTF-8')
else: else:
return etree.tostring(self.etree_element(), return etree.tostring(
self.etree_element(),
encoding='utf-8').decode('UTF-8') encoding='utf-8').decode('UTF-8')
...@@ -159,16 +161,16 @@ class _Person(object): ...@@ -159,16 +161,16 @@ class _Person(object):
ns = None ns = None
name = None name = None
#conveys a human-readable name for the person. # conveys a human-readable name for the person.
uri = None uri = None
#contains a home page for the person. # contains a home page for the person.
email = None email = None
#contains an email address for the person. # contains an email address for the person.
def __init__(self, ns=None, name=None, uri=None, email=None): def __init__(self, ns=None, name=None, uri=None, email=None):
if ns == None: if ns is None:
self.ns = NS self.ns = NS
else: else:
self.ns = ns self.ns = ns
...@@ -176,27 +178,24 @@ class _Person(object): ...@@ -176,27 +178,24 @@ class _Person(object):
self.uri = uri self.uri = uri
self.email = email self.email = email
def etree_element(self): def etree_element(self):
element = etree.Element(self.ns + self.__name__.lower()) element = etree.Element(self.ns + self.__name__.lower())
if self.name: if self.name:
name = etree.SubElement(element, "%sname" %self.ns) name = etree.SubElement(element, "%sname" % self.ns)
name.text = self.name name.text = self.name
#else: # else:
# logger.critical('No Name for person defined') # logger.critical('No Name for person defined')
# raise TypeError # raise TypeError
if self.uri: if self.uri:
#XXX validate uri # XXX validate uri
uri = etree.SubElement(element, "%suri" %self.ns) uri = etree.SubElement(element, "%suri" % self.ns)
uri.text = self.uri uri.text = self.uri
if self.email: if self.email:
if check_email(self.email): if check_email(self.email):
email = etree.SubElement(element, "%semail" %self.ns) email = etree.SubElement(element, "%semail" % self.ns)
email.text = self.email email.text = self.email
return element return element
def from_string(self, xml_string): def from_string(self, xml_string):
self.from_element(etree.XML(xml_string)) self.from_element(etree.XML(xml_string))
...@@ -204,13 +203,13 @@ class _Person(object): ...@@ -204,13 +203,13 @@ class _Person(object):
if self.ns + self.__name__.lower() != element.tag: if self.ns + self.__name__.lower() != element.tag:
raise TypeError raise TypeError
else: else:
name = element.find('%sname' %self.ns) name = element.find('%sname' % self.ns)
if name is not None: if name is not None:
self.name = name.text self.name = name.text
uri = element.find('%suri' %self.ns) uri = element.find('%suri' % self.ns)
if uri is not None: if uri is not None:
self.uri = uri.text self.uri = uri.text
email = element.find('%semail' %self.ns) email = element.find('%semail' % self.ns)
if email is not None: if email is not None:
if check_email(email.text): if check_email(email.text):
self.email = email.text self.email = email.text
...@@ -218,21 +217,23 @@ class _Person(object): ...@@ -218,21 +217,23 @@ class _Person(object):
def to_string(self, prettyprint=True): def to_string(self, prettyprint=True):
""" Return the ATOM Object as serialized xml """ """ Return the ATOM Object as serialized xml """
if LXML and prettyprint: if LXML and prettyprint:
return etree.tostring(self.etree_element(), encoding='utf-8', return etree.tostring(
self.etree_element(),
encoding='utf-8',
pretty_print=True).decode('UTF-8') pretty_print=True).decode('UTF-8')
else: else:
return etree.tostring(self.etree_element(), return etree.tostring(
self.etree_element(),
encoding='utf-8').decode('UTF-8') encoding='utf-8').decode('UTF-8')
class Author(_Person): class Author(_Person):
""" Names one author of the feed/entry. A feed/entry may have """ Names one author of the feed/entry. A feed/entry may have
multiple authors.""" multiple authors."""
__name__ = "Author" __name__ = "Author"
class Contributor(_Person): class Contributor(_Person):
""" Names one contributor to the feed/entry. A feed/entry may have """ Names one contributor to the feed/entry. A feed/entry may have
multiple contributor elements.""" multiple contributor elements."""
__name__ = "Contributor" __name__ = "Contributor"
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
import fastkml.config as config import fastkml.config as config
from fastkml.config import etree from fastkml.config import etree
class _XMLObject(object): class _XMLObject(object):
""" XML Baseclass""" """ XML Baseclass"""
...@@ -27,7 +28,7 @@ class _XMLObject(object): ...@@ -27,7 +28,7 @@ class _XMLObject(object):
ns = None ns = None
def __init__(self, ns=None): def __init__(self, ns=None):
if ns == None: if ns is None:
self.ns = config.NS self.ns = config.NS
else: else:
self.ns = ns self.ns = ns
...@@ -36,12 +37,16 @@ class _XMLObject(object): ...@@ -36,12 +37,16 @@ class _XMLObject(object):
if self.__name__: if self.__name__:
element = etree.Element(self.ns + self.__name__) element = etree.Element(self.ns + self.__name__)
else: else:
raise NotImplementedError("Call of abstract base class, subclasses implement this!") raise NotImplementedError(
"Call of abstract base class, subclasses implement this!"
)
return element return element
def from_element(self, element): def from_element(self, element):
if self.ns + self.__name__ != element.tag: if self.ns + self.__name__ != element.tag:
raise TypeError("Call of abstract base class, subclasses implement this!") raise TypeError(
"Call of abstract base class, subclasses implement this!"
)
def from_string(self, xml_string): def from_string(self, xml_string):
self.from_element(etree.XML(xml_string)) self.from_element(etree.XML(xml_string))
...@@ -49,12 +54,16 @@ class _XMLObject(object): ...@@ -49,12 +54,16 @@ class _XMLObject(object):
def to_string(self, prettyprint=True): def to_string(self, prettyprint=True):
""" Return the KML Object as serialized xml """ """ Return the KML Object as serialized xml """
if config.LXML and prettyprint: if config.LXML and prettyprint:
return etree.tostring(self.etree_element(), encoding='utf-8', return etree.tostring(
self.etree_element(),
encoding='utf-8',
pretty_print=True).decode('UTF-8') pretty_print=True).decode('UTF-8')
else: else:
return etree.tostring(self.etree_element(), return etree.tostring(
self.etree_element(),
encoding='utf-8').decode('UTF-8') encoding='utf-8').decode('UTF-8')
class _BaseObject(_XMLObject): class _BaseObject(_XMLObject):
""" This is an abstract base class and cannot be used directly in a """ This is an abstract base class and cannot be used directly in a
KML file. It provides the id attribute, which allows unique KML file. It provides the id attribute, which allows unique
...@@ -68,7 +77,7 @@ class _BaseObject(_XMLObject): ...@@ -68,7 +77,7 @@ class _BaseObject(_XMLObject):
def __init__(self, ns=None, id=None): def __init__(self, ns=None, id=None):
super(_BaseObject, self).__init__(ns) super(_BaseObject, self).__init__(ns)
self.id = id self.id = id
if ns == None: if ns is None:
self.ns = config.NS self.ns = config.NS
else: else:
self.ns = ns self.ns = ns
...@@ -81,12 +90,9 @@ class _BaseObject(_XMLObject): ...@@ -81,12 +90,9 @@ class _BaseObject(_XMLObject):
element.set('targetId', self.targetId) element.set('targetId', self.targetId)
return element return element
def from_element(self, element): def from_element(self, element):
super(_BaseObject, self).from_element(element) super(_BaseObject, self).from_element(element)
if element.get('id'): if element.get('id'):
self.id = element.get('id') self.id = element.get('id')
if element.get('targetId'): if element.get('targetId'):
self.targetId = element.get('targetId') self.targetId = element.get('targetId')
...@@ -22,7 +22,7 @@ try: ...@@ -22,7 +22,7 @@ try:
from shapely.geometry import Point, LineString, Polygon from shapely.geometry import Point, LineString, Polygon
from shapely.geometry import MultiPoint, MultiLineString, MultiPolygon from shapely.geometry import MultiPoint, MultiLineString, MultiPolygon
from shapely.geometry.polygon import LinearRing from shapely.geometry.polygon import LinearRing
#from shapely.geometry import GeometryCollection # from shapely.geometry import GeometryCollection
# Sean Gillies: # Sean Gillies:
# I deliberately omitted a geometry collection constructor because # I deliberately omitted a geometry collection constructor because
# there was almost no support in GEOS for operations on them. You # there was almost no support in GEOS for operations on them. You
...@@ -40,10 +40,7 @@ except ImportError: ...@@ -40,10 +40,7 @@ except ImportError:
from pygeoif.geometry import GeometryCollection from pygeoif.geometry import GeometryCollection
from pygeoif.geometry import as_shape as asShape from pygeoif.geometry import as_shape as asShape
try: import fastkml.config as config
import fastkml.config as config
except ImportError:
import config
from .config import etree from .config import etree
...@@ -63,9 +60,10 @@ class Geometry(_BaseObject): ...@@ -63,9 +60,10 @@ class Geometry(_BaseObject):
tessellate = False tessellate = False
altitude_mode = None altitude_mode = None
def __init__(
def __init__(self, ns=None, id=None, geometry=None, extrude=False, self, ns=None, id=None, geometry=None, extrude=False,
tessellate=False, altitude_mode=None): tessellate=False, altitude_mode=None
):
""" """
geometry: a geometry that implements the __geo_interface__ convention geometry: a geometry that implements the __geo_interface__ convention
...@@ -115,9 +113,14 @@ class Geometry(_BaseObject): ...@@ -115,9 +113,14 @@ class Geometry(_BaseObject):
self.tessellate = tessellate self.tessellate = tessellate
self.altitude_mode = altitude_mode self.altitude_mode = altitude_mode
if geometry: if geometry:
if isinstance(geometry, (Point, LineString, Polygon, if isinstance(
geometry,
(
Point, LineString, Polygon,
MultiPoint, MultiLineString, MultiPolygon, MultiPoint, MultiLineString, MultiPolygon,
LinearRing, GeometryCollection)): LinearRing, GeometryCollection
)
):
self.geometry = geometry self.geometry = geometry
else: else:
self.geometry = asShape(geometry) self.geometry = asShape(geometry)
...@@ -126,35 +129,43 @@ class Geometry(_BaseObject): ...@@ -126,35 +129,43 @@ class Geometry(_BaseObject):
def _set_altitude_mode(self, element): def _set_altitude_mode(self, element):
if self.altitude_mode: if self.altitude_mode:
assert(self.altitude_mode in ['clampToGround', assert(self.altitude_mode in [
#'relativeToSeaFloor', 'clampToSeaFloor', 'clampToGround',
'relativeToGround', 'absolute']) # 'relativeToSeaFloor', 'clampToSeaFloor',
'relativeToGround', 'absolute'
])
if self.altitude_mode != 'clampToGround': if self.altitude_mode != 'clampToGround':
am_element = etree.SubElement(element, "%saltitudeMode" %self.ns) am_element = etree.SubElement(
element, "%saltitudeMode" % self.ns
)
am_element.text = self.altitude_mode am_element.text = self.altitude_mode
def _set_extrude(self, element): def _set_extrude(self, element):
if self.extrude and self.altitude_mode in ['relativeToGround', if self.extrude and self.altitude_mode in [
#'relativeToSeaFloor', 'relativeToGround',
'absolute']: # 'relativeToSeaFloor',
et_element = etree.SubElement(element, "%sextrude" %self.ns) 'absolute'
]:
et_element = etree.SubElement(element, "%sextrude" % self.ns)
et_element.text = '1' et_element.text = '1'
def _etree_coordinates(self, coordinates): def _etree_coordinates(self, coordinates):
clampToGround = (self.altitude_mode == 'clampToGround') or (self.altitude_mode == None) # clampToGround = (
element = etree.Element("%scoordinates" %self.ns) # (self.altitude_mode == 'clampToGround')
# or (self.altitude_mode is None)
# )
element = etree.Element("%scoordinates" % self.ns)
if len(coordinates[0]) == 2: if len(coordinates[0]) == 2:
if config.FORCE3D: # and not clampToGround: if config.FORCE3D: # and not clampToGround:
tuples = ('%f,%f,0.000000' % tuple(c) for c in coordinates) tuples = ('%f,%f,0.000000' % tuple(c) for c in coordinates)
else: else:
tuples = ('%f,%f' % tuple(c) for c in coordinates) tuples = ('%f,%f' % tuple(c) for c in coordinates)
elif len(coordinates[0]) == 3: elif len(coordinates[0]) == 3:
#if clampToGround: # if clampToGround:
# if the altitude is ignored anyway, we may as well # if the altitude is ignored anyway, we may as well
# ignore the z-value # ignore the z-value
# tuples = ('%f,%f' % tuple(c[:2]) for c in coordinates) # tuples = ('%f,%f' % tuple(c[:2]) for c in coordinates)
#else: # else:
tuples = ('%f,%f,%f' % tuple(c) for c in coordinates) tuples = ('%f,%f,%f' % tuple(c) for c in coordinates)
else: else:
raise ValueError("Invalid dimensions") raise ValueError("Invalid dimensions")
...@@ -162,7 +173,7 @@ class Geometry(_BaseObject): ...@@ -162,7 +173,7 @@ class Geometry(_BaseObject):
return element return element
def _etree_point(self, point): def _etree_point(self, point):
element = etree.Element("%sPoint" %self.ns) element = etree.Element("%sPoint" % self.ns)
self._set_extrude(element) self._set_extrude(element)
self._set_altitude_mode(element) self._set_altitude_mode(element)
coords = list(point.coords) coords = list(point.coords)
...@@ -170,24 +181,26 @@ class Geometry(_BaseObject): ...@@ -170,24 +181,26 @@ class Geometry(_BaseObject):
return element return element
def _etree_linestring(self, linestring): def _etree_linestring(self, linestring):
element = etree.Element("%sLineString" %self.ns) element = etree.Element("%sLineString" % self.ns)
self._set_extrude(element) self._set_extrude(element)
self._set_altitude_mode(element) self._set_altitude_mode(element)
if self.tessellate and self.altitude_mode in ['clampToGround', if self.tessellate and self.altitude_mode in [
'clampToSeaFloor']: 'clampToGround',
ts_element = etree.SubElement(element, "%stessellate" %self.ns) 'clampToSeaFloor'
]:
ts_element = etree.SubElement(element, "%stessellate" % self.ns)
ts_element.text = '1' ts_element.text = '1'
coords = list(linestring.coords) coords = list(linestring.coords)
element.append(self._etree_coordinates(coords)) element.append(self._etree_coordinates(coords))
return element return element
def _etree_linearring(self, linearring): def _etree_linearring(self, linearring):
element = etree.Element("%sLinearRing" %self.ns) element = etree.Element("%sLinearRing" % self.ns)
self._set_extrude(element) self._set_extrude(element)
self._set_altitude_mode(element) self._set_altitude_mode(element)
# tesseleation is ignored by polygon and tesselation together with # tesseleation is ignored by polygon and tesselation together with
# LinearRing without a polygon very rare Edgecase -> ignore for now # LinearRing without a polygon very rare Edgecase -> ignore for now
#if self.tessellate and self.altitude_mode in ['clampToGround', # if self.tessellate and self.altitude_mode in ['clampToGround',
# 'clampToSeaFloor']: # 'clampToSeaFloor']:
# element.set('tessellate', '1') # element.set('tessellate', '1')
coords = list(linearring.coords) coords = list(linearring.coords)
...@@ -195,36 +208,40 @@ class Geometry(_BaseObject): ...@@ -195,36 +208,40 @@ class Geometry(_BaseObject):
return element return element
def _etree_polygon(self, polygon): def _etree_polygon(self, polygon):
element = etree.Element("%sPolygon" %self.ns) element = etree.Element("%sPolygon" % self.ns)
self._set_extrude(element) self._set_extrude(element)
self._set_altitude_mode(element) self._set_altitude_mode(element)
outer_boundary = etree.SubElement(element, "%souterBoundaryIs" %self.ns) outer_boundary = etree.SubElement(
element, "%souterBoundaryIs" % self.ns
)
outer_boundary.append(self._etree_linearring(polygon.exterior)) outer_boundary.append(self._etree_linearring(polygon.exterior))
for ib in polygon.interiors: for ib in polygon.interiors:
inner_boundary = etree.SubElement(element, "%sinnerBoundaryIs" %self.ns) inner_boundary = etree.SubElement(
element, "%sinnerBoundaryIs" % self.ns
)
inner_boundary.append(self._etree_linearring(ib)) inner_boundary.append(self._etree_linearring(ib))
return element return element
def _etree_multipoint(self, points): def _etree_multipoint(self, points):
element = etree.Element("%sMultiGeometry" %self.ns) element = etree.Element("%sMultiGeometry" % self.ns)
for point in points.geoms: for point in points.geoms:
element.append(self._etree_point(point)) element.append(self._etree_point(point))
return element return element
def _etree_multilinestring(self, linestrings): def _etree_multilinestring(self, linestrings):
element = etree.Element("%sMultiGeometry" %self.ns) element = etree.Element("%sMultiGeometry" % self.ns)
for linestring in linestrings.geoms: for linestring in linestrings.geoms:
element.append(self._etree_linestring(linestring)) element.append(self._etree_linestring(linestring))
return element return element
def _etree_multipolygon(self, polygons): def _etree_multipolygon(self, polygons):
element = etree.Element("%sMultiGeometry" %self.ns) element = etree.Element("%sMultiGeometry" % self.ns)
for polygon in polygons.geoms: for polygon in polygons.geoms:
element.append(self._etree_polygon(polygon)) element.append(self._etree_polygon(polygon))
return element return element
def _etree_collection(self, features): def _etree_collection(self, features):
element = etree.Element("%sMultiGeometry" %self.ns) element = etree.Element("%sMultiGeometry" % self.ns)
for feature in features.geoms: for feature in features.geoms:
if feature.geom_type == "Point": if feature.geom_type == "Point":
element.append(self._etree_point(feature)) element.append(self._etree_point(feature))
...@@ -282,16 +299,17 @@ class Geometry(_BaseObject): ...@@ -282,16 +299,17 @@ class Geometry(_BaseObject):
altitude_mode = element.find('%saltitudeMode' % self.ns) altitude_mode = element.find('%saltitudeMode' % self.ns)
if altitude_mode is not None: if altitude_mode is not None:
am = altitude_mode.text.strip() am = altitude_mode.text.strip()
if am in ['clampToGround', if am in [
#'relativeToSeaFloor', 'clampToSeaFloor', 'clampToGround',
'relativeToGround', 'absolute']: # 'relativeToSeaFloor', 'clampToSeaFloor',
'relativeToGround', 'absolute'
]:
self.altitude_mode = am self.altitude_mode = am
else: else:
self.altitude_mode = None self.altitude_mode = None
else: else:
self.altitude_mode = None self.altitude_mode = None
def _get_coordinates(self, element): def _get_coordinates(self, element):
coordinates = element.find('%scoordinates' % self.ns) coordinates = element.find('%scoordinates' % self.ns)
if coordinates is not None: if coordinates is not None:
...@@ -321,9 +339,9 @@ class Geometry(_BaseObject): ...@@ -321,9 +339,9 @@ class Geometry(_BaseObject):
return LineString(coords) return LineString(coords)
if element.tag == ('%sPolygon' % self.ns): if element.tag == ('%sPolygon' % self.ns):
self._get_geometry_spec(element) self._get_geometry_spec(element)
outer_boundary = element.find('%souterBoundaryIs' %self.ns) outer_boundary = element.find('%souterBoundaryIs' % self.ns)
ob = self._get_linear_ring(outer_boundary) ob = self._get_linear_ring(outer_boundary)
inner_boundaries = element.findall('%sinnerBoundaryIs' %self.ns) inner_boundaries = element.findall('%sinnerBoundaryIs' % self.ns)
ibs = [] ibs = []
for inner_boundary in inner_boundaries: for inner_boundary in inner_boundaries:
ibs.append(self._get_linear_ring(inner_boundary)) ibs.append(self._get_linear_ring(inner_boundary))
...@@ -333,8 +351,6 @@ class Geometry(_BaseObject): ...@@ -333,8 +351,6 @@ class Geometry(_BaseObject):
self._get_geometry_spec(element) self._get_geometry_spec(element)
return LinearRing(coords) return LinearRing(coords)
def _get_multigeometry(self, element): def _get_multigeometry(self, element):
# MultiGeometry # MultiGeometry
geoms = [] geoms = []
...@@ -353,9 +369,13 @@ class Geometry(_BaseObject): ...@@ -353,9 +369,13 @@ class Geometry(_BaseObject):
if polygons: if polygons:
for polygon in polygons: for polygon in polygons:
self._get_geometry_spec(polygon) self._get_geometry_spec(polygon)
outer_boundary = polygon.find('%souterBoundaryIs' %self.ns) outer_boundary = polygon.find(
'%souterBoundaryIs' % self.ns
)
ob = self._get_linear_ring(outer_boundary) ob = self._get_linear_ring(outer_boundary)
inner_boundaries = polygon.findall('%sinnerBoundaryIs' %self.ns) inner_boundaries = polygon.findall(
'%sinnerBoundaryIs' % self.ns
)
ibs = [] ibs = []
for inner_boundary in inner_boundaries: for inner_boundary in inner_boundaries:
ibs.append(self._get_linear_ring(inner_boundary)) ibs.append(self._get_linear_ring(inner_boundary))
......
...@@ -76,9 +76,6 @@ located at http://developers.google.com/kml/schema/kml22gx.xsd. ...@@ -76,9 +76,6 @@ located at http://developers.google.com/kml/schema/kml22gx.xsd.
import logging import logging
logger = logging.getLogger('fastkml.gx') logger = logging.getLogger('fastkml.gx')
from .config import etree # from .config import etree
from .config import GXNS as NS # from .config import GXNS as NS
from .config import LXML # from .config import LXML
...@@ -31,9 +31,9 @@ except ImportError: ...@@ -31,9 +31,9 @@ except ImportError:
import urllib.parse as urlparse import urllib.parse as urlparse
import warnings import warnings
from .geometry import Point, LineString, Polygon # from .geometry import Point, LineString, Polygon
from .geometry import MultiPoint, MultiLineString, MultiPolygon # from .geometry import MultiPoint, MultiLineString, MultiPolygon
from .geometry import LinearRing # from .geometry import LinearRing
from .geometry import Geometry from .geometry import Geometry
from datetime import datetime, date from datetime import datetime, date
...@@ -54,7 +54,7 @@ from .base import _BaseObject, _XMLObject ...@@ -54,7 +54,7 @@ from .base import _BaseObject, _XMLObject
from .styles import StyleUrl, Style, StyleMap, _StyleSelector from .styles import StyleUrl, Style, StyleMap, _StyleSelector
import fastkml.atom as atom import fastkml.atom as atom
import fastkml.gx as gx # import fastkml.gx as gx
import fastkml.config as config import fastkml.config as config
try: try:
...@@ -76,7 +76,7 @@ class KML(object): ...@@ -76,7 +76,7 @@ class KML(object):
to be initialized with empty namespace as well in this case. to be initialized with empty namespace as well in this case.
""" """
self._features =[] self._features = []
if ns is None: if ns is None:
self.ns = config.NS self.ns = config.NS
...@@ -86,7 +86,10 @@ class KML(object): ...@@ -86,7 +86,10 @@ class KML(object):
def from_string(self, xml_string): def from_string(self, xml_string):
""" create a KML object from a xml string""" """ create a KML object from a xml string"""
if config.LXML: if config.LXML:
element = etree.fromstring(xml_string, parser=etree.XMLParser(huge_tree=True)) element = etree.fromstring(
xml_string,
parser=etree.XMLParser(huge_tree=True)
)
else: else:
element = etree.XML(xml_string) element = etree.XML(xml_string)
...@@ -119,21 +122,26 @@ class KML(object): ...@@ -119,21 +122,26 @@ class KML(object):
root.set('xmlns', config.NS[1:-1]) root.set('xmlns', config.NS[1:-1])
else: else:
if config.LXML: if config.LXML:
root = etree.Element('%skml' % self.ns, nsmap={None:self.ns[1:-1]}) root = etree.Element(
'%skml' % self.ns,
nsmap={None: self.ns[1:-1]}
)
else: else:
root = etree.Element('%skml' % self.ns) root = etree.Element('%skml' % self.ns)
for feature in self.features(): for feature in self.features():
root.append(feature.etree_element()) root.append(feature.etree_element())
return root return root
def to_string(self, prettyprint=False): def to_string(self, prettyprint=False):
""" Return the KML Object as serialized xml """ """ Return the KML Object as serialized xml """
if config.LXML and prettyprint: if config.LXML and prettyprint:
return etree.tostring(self.etree_element(), encoding='utf-8', return etree.tostring(
self.etree_element(),
encoding='utf-8',
pretty_print=True).decode('UTF-8') pretty_print=True).decode('UTF-8')
else: else:
return etree.tostring(self.etree_element(), return etree.tostring(
self.etree_element(),
encoding='utf-8').decode('UTF-8') encoding='utf-8').decode('UTF-8')
def features(self): def features(self):
...@@ -143,7 +151,9 @@ class KML(object): ...@@ -143,7 +151,9 @@ class KML(object):
yield feature yield feature
else: else:
raise TypeError( raise TypeError(
"Features must be instances of (Document, Folder, Placemark)") "Features must be instances of "
"(Document, Folder, Placemark)"
)
def append(self, kmlobj): def append(self, kmlobj):
""" append a feature """ """ append a feature """
...@@ -153,6 +163,7 @@ class KML(object): ...@@ -153,6 +163,7 @@ class KML(object):
raise TypeError( raise TypeError(
"Features must be instances of (Document, Folder, Placemark)") "Features must be instances of (Document, Folder, Placemark)")
class _Feature(_BaseObject): class _Feature(_BaseObject):
""" """
abstract element; do not create abstract element; do not create
...@@ -188,17 +199,17 @@ class _Feature(_BaseObject): ...@@ -188,17 +199,17 @@ class _Feature(_BaseObject):
_atom_link = None _atom_link = None
# Specifies the URL of the website containing this KML or KMZ file. # Specifies the URL of the website containing this KML or KMZ file.
#TODO address = None # TODO address = None
# A string value representing an unstructured address written as a # A string value representing an unstructured address written as a
# standard street, city, state address, and/or as a postal code. # standard street, city, state address, and/or as a postal code.
# You can use the <address> tag to specify the location of a point # You can use the <address> tag to specify the location of a point
# instead of using latitude and longitude coordinates. # instead of using latitude and longitude coordinates.
#TODO phoneNumber = None # TODO phoneNumber = None
# A string value representing a telephone number. # A string value representing a telephone number.
# This element is used by Google Maps Mobile only. # This element is used by Google Maps Mobile only.
_snippet = None #XXX _snippet = None # XXX
# _snippet is eiter a tuple of a string Snippet.text and an integer # _snippet is eiter a tuple of a string Snippet.text and an integer
# Snippet.maxLines or a string # Snippet.maxLines or a string
# #
...@@ -213,7 +224,7 @@ class _Feature(_BaseObject): ...@@ -213,7 +224,7 @@ class _Feature(_BaseObject):
# that specifies the maximum number of lines to display. # that specifies the maximum number of lines to display.
description = None description = None
#User-supplied content that appears in the description balloon. # User-supplied content that appears in the description balloon.
_styleUrl = None _styleUrl = None
# URL of a <Style> or <StyleMap> defined in a Document. # URL of a <Style> or <StyleMap> defined in a Document.
...@@ -240,11 +251,11 @@ class _Feature(_BaseObject): ...@@ -240,11 +251,11 @@ class _Feature(_BaseObject):
_time_stamp = None _time_stamp = None
# Associates this Feature with a point in time. # Associates this Feature with a point in time.
#TODO Region = None # TODO Region = None
# Features and geometry associated with a Region are drawn only when # Features and geometry associated with a Region are drawn only when
# the Region is active. # the Region is active.
#TODO ExtendedData = None # TODO ExtendedData = None
# Allows you to add custom data to a KML file. This data can be # Allows you to add custom data to a KML file. This data can be
# (1) data that references an external XML schema, # (1) data that references an external XML schema,
# (2) untyped data/value pairs, or # (2) untyped data/value pairs, or
...@@ -257,11 +268,13 @@ class _Feature(_BaseObject): ...@@ -257,11 +268,13 @@ class _Feature(_BaseObject):
# <Metadata> (deprecated in KML 2.2; use <ExtendedData> instead) # <Metadata> (deprecated in KML 2.2; use <ExtendedData> instead)
extended_data = None extended_data = None
def __init__(self, ns=None, id=None, name=None, description=None, def __init__(
styles=None, styleUrl=None, extended_data=None): self, ns=None, id=None, name=None, description=None,
styles=None, styleUrl=None, extended_data=None
):
super(_Feature, self).__init__(ns, id) super(_Feature, self).__init__(ns, id)
self.name=name self.name = name
self.description=description self.description = description
self.styleUrl = styleUrl self.styleUrl = styleUrl
self._styles = [] self._styles = []
if styles: if styles:
...@@ -297,7 +310,7 @@ class _Feature(_BaseObject): ...@@ -297,7 +310,7 @@ class _Feature(_BaseObject):
@timeStamp.setter @timeStamp.setter
def timeStamp(self, dt): def timeStamp(self, dt):
if dt == None: if dt is None:
self._time_stamp = None self._time_stamp = None
else: else:
self._time_stamp = TimeStamp(timestamp=dt) self._time_stamp = TimeStamp(timestamp=dt)
...@@ -370,12 +383,11 @@ class _Feature(_BaseObject): ...@@ -370,12 +383,11 @@ class _Feature(_BaseObject):
self._atom_author = atom.Author(name=name) self._atom_author = atom.Author(name=name)
else: else:
self._atom_author.name = name self._atom_author.name = name
elif name == None: elif name is None:
self._atom_author = None self._atom_author = None
else: else:
raise TypeError raise TypeError
def append_style(self, style): def append_style(self, style):
""" append a style to the feature """ """ append a style to the feature """
if isinstance(style, _StyleSelector): if isinstance(style, _StyleSelector):
...@@ -390,6 +402,7 @@ class _Feature(_BaseObject): ...@@ -390,6 +402,7 @@ class _Feature(_BaseObject):
yield style yield style
else: else:
raise TypeError raise TypeError
@property @property
def snippet(self): def snippet(self):
if self._snippet: if self._snippet:
...@@ -406,7 +419,10 @@ class _Feature(_BaseObject): ...@@ -406,7 +419,10 @@ class _Feature(_BaseObject):
elif isinstance(self._snippet, basestring): elif isinstance(self._snippet, basestring):
return self._snippet return self._snippet
else: else:
raise ValueError("Snippet must be dict of {'text':t, 'maxLines':i} or string") raise ValueError(
"Snippet must be dict of "
"{'text':t, 'maxLines':i} or string"
)
@snippet.setter @snippet.setter
def snippet(self, snip=None): def snippet(self, snip=None):
...@@ -421,27 +437,29 @@ class _Feature(_BaseObject): ...@@ -421,27 +437,29 @@ class _Feature(_BaseObject):
elif snip is None: elif snip is None:
self._snippet = None self._snippet = None
else: else:
raise ValueError("Snippet must be dict of {'text':t, 'maxLines':i} or string") raise ValueError(
"Snippet must be dict of {'text':t, 'maxLines':i} or string"
)
def etree_element(self): def etree_element(self):
element = super(_Feature, self).etree_element() element = super(_Feature, self).etree_element()
if self.name: if self.name:
name = etree.SubElement(element, "%sname" %self.ns) name = etree.SubElement(element, "%sname" % self.ns)
name.text = self.name name.text = self.name
if self.description: if self.description:
description =etree.SubElement(element, "%sdescription" %self.ns) description = etree.SubElement(element, "%sdescription" % self.ns)
description.text = self.description description.text = self.description
visibility = etree.SubElement(element, "%svisibility" %self.ns) visibility = etree.SubElement(element, "%svisibility" % self.ns)
visibility.text = str(self.visibility) visibility.text = str(self.visibility)
if self.isopen: if self.isopen:
isopen = etree.SubElement(element, "%sopen" %self.ns) isopen = etree.SubElement(element, "%sopen" % self.ns)
isopen.text = str(self.isopen) isopen.text = str(self.isopen)
if self._styleUrl is not None: if self._styleUrl is not None:
element.append(self._styleUrl.etree_element()) element.append(self._styleUrl.etree_element())
for style in self.styles(): for style in self.styles():
element.append(style.etree_element()) element.append(style.etree_element())
if self.snippet: if self.snippet:
snippet = etree.SubElement(element, "%sSnippet" %self.ns) snippet = etree.SubElement(element, "%sSnippet" % self.ns)
if isinstance(self.snippet, basestring): if isinstance(self.snippet, basestring):
snippet.text = self.snippet snippet.text = self.snippet
else: else:
...@@ -450,7 +468,9 @@ class _Feature(_BaseObject): ...@@ -450,7 +468,9 @@ class _Feature(_BaseObject):
if self.snippet.get('maxLines'): if self.snippet.get('maxLines'):
snippet.set('maxLines', str(self.snippet['maxLines'])) snippet.set('maxLines', str(self.snippet['maxLines']))
if (self._time_span is not None) and (self._time_stamp is not None): if (self._time_span is not None) and (self._time_stamp is not None):
raise ValueError('Either Timestamp or Timespan can be defined, not both') raise ValueError(
'Either Timestamp or Timespan can be defined, not both'
)
elif self._time_span is not None: elif self._time_span is not None:
element.append(self._time_span.etree_element()) element.append(self._time_span.etree_element())
elif self._time_stamp is not None: elif self._time_stamp is not None:
...@@ -463,19 +483,18 @@ class _Feature(_BaseObject): ...@@ -463,19 +483,18 @@ class _Feature(_BaseObject):
element.append(self.extended_data.etree_element()) element.append(self.extended_data.etree_element())
return element return element
def from_element(self, element): def from_element(self, element):
super(_Feature, self).from_element(element) super(_Feature, self).from_element(element)
name = element.find('%sname' %self.ns) name = element.find('%sname' % self.ns)
if name is not None: if name is not None:
self.name = name.text self.name = name.text
description = element.find('%sdescription' %self.ns) description = element.find('%sdescription' % self.ns)
if description is not None: if description is not None:
self.description = description.text self.description = description.text
visibility = element.find('%svisibility' %self.ns) visibility = element.find('%svisibility' % self.ns)
if visibility is not None: if visibility is not None:
self.visibility = int(visibility.text) self.visibility = int(visibility.text)
isopen = element.find('%sopen' %self.ns) isopen = element.find('%sopen' % self.ns)
if isopen is not None: if isopen is not None:
self.isopen = int(isopen.text) self.isopen = int(isopen.text)
styles = element.findall('%sStyle' % self.ns) styles = element.findall('%sStyle' % self.ns)
...@@ -524,14 +543,12 @@ class _Feature(_BaseObject): ...@@ -524,14 +543,12 @@ class _Feature(_BaseObject):
x = ExtendedData(self.ns) x = ExtendedData(self.ns)
x.from_element(extended_data) x.from_element(extended_data)
self.extended_data = x self.extended_data = x
#else: # else:
# logger.warn( # logger.warn(
# 'arbitrary or typed extended data is not yet supported' # 'arbitrary or typed extended data is not yet supported'
# ) # )
class _Container(_Feature): class _Container(_Feature):
""" """
abstract element; do not create abstract element; do not create
...@@ -544,10 +561,14 @@ class _Container(_Feature): ...@@ -544,10 +561,14 @@ class _Container(_Feature):
_features = [] _features = []
def __init__(self, ns=None, id=None, name=None, description=None, def __init__(
styles=None, styleUrl=None): self, ns=None, id=None, name=None, description=None,
super(_Container, self).__init__(ns, id, name, description, styles, styleUrl) styles=None, styleUrl=None
self._features =[] ):
super(_Container, self).__init__(
ns, id, name, description, styles, styleUrl
)
self._features = []
def features(self): def features(self):
""" iterate over features """ """ iterate over features """
...@@ -564,18 +585,17 @@ class _Container(_Feature): ...@@ -564,18 +585,17 @@ class _Container(_Feature):
element.append(feature.etree_element()) element.append(feature.etree_element())
return element return element
def append(self, kmlobj): def append(self, kmlobj):
""" append a feature """ """ append a feature """
if isinstance(kmlobj, (Folder, Placemark)): if isinstance(kmlobj, (Folder, Placemark)):
self._features.append(kmlobj) self._features.append(kmlobj)
else: else:
raise TypeError( raise TypeError(
"Features must be instances of (Folder, Placemark)") "Features must be instances of (Folder, Placemark)"
)
assert(kmlobj != self) assert(kmlobj != self)
class Document(_Container): class Document(_Container):
""" """
A Document is a container for features and styles. This element is A Document is a container for features and styles. This element is
...@@ -613,7 +633,7 @@ class Document(_Container): ...@@ -613,7 +633,7 @@ class Document(_Container):
self.append(feature) self.append(feature)
schemata = element.findall('%sSchema' % self.ns) schemata = element.findall('%sSchema' % self.ns)
for schema in schemata: for schema in schemata:
s = Schema(self.ns, id = 'default') s = Schema(self.ns, id='default')
s.from_element(schema) s.from_element(schema)
self.append_schema(s) self.append_schema(s)
...@@ -651,6 +671,7 @@ class Folder(_Container): ...@@ -651,6 +671,7 @@ class Folder(_Container):
feature.from_element(placemark) feature.from_element(placemark)
self.append(feature) self.append(feature)
class Placemark(_Feature): class Placemark(_Feature):
""" """
A Placemark is a Feature with associated Geometry. A Placemark is a Feature with associated Geometry.
...@@ -715,6 +736,7 @@ class Placemark(_Feature): ...@@ -715,6 +736,7 @@ class Placemark(_Feature):
logger.error('Object does not have a geometry') logger.error('Object does not have a geometry')
return element return element
class _TimePrimitive(_BaseObject): class _TimePrimitive(_BaseObject):
""" The dateTime is defined according to XML Schema time. """ The dateTime is defined according to XML Schema time.
The value can be expressed as yyyy-mm-ddThh:mm:sszzzzzz, where T is The value can be expressed as yyyy-mm-ddThh:mm:sszzzzzz, where T is
...@@ -748,7 +770,6 @@ class _TimePrimitive(_BaseObject): ...@@ -748,7 +770,6 @@ class _TimePrimitive(_BaseObject):
resolution = None resolution = None
return resolution return resolution
def parse_str(self, datestr): def parse_str(self, datestr):
resolution = 'dateTime' resolution = 'dateTime'
year = 0 year = 0
...@@ -778,7 +799,6 @@ class _TimePrimitive(_BaseObject): ...@@ -778,7 +799,6 @@ class _TimePrimitive(_BaseObject):
raise ValueError raise ValueError
return [dt, resolution] return [dt, resolution]
def date_to_string(self, dt, resolution=None): def date_to_string(self, dt, resolution=None):
if isinstance(dt, (date, datetime)): if isinstance(dt, (date, datetime)):
resolution = self.get_resolution(dt, resolution) resolution = self.get_resolution(dt, resolution)
...@@ -807,18 +827,17 @@ class TimeStamp(_TimePrimitive): ...@@ -807,18 +827,17 @@ class TimeStamp(_TimePrimitive):
def etree_element(self): def etree_element(self):
element = super(TimeStamp, self).etree_element() element = super(TimeStamp, self).etree_element()
when = etree.SubElement(element, "%swhen" %self.ns) when = etree.SubElement(element, "%swhen" % self.ns)
when.text = self.date_to_string(*self.timestamp) when.text = self.date_to_string(*self.timestamp)
return element return element
def from_element(self, element): def from_element(self, element):
super(TimeStamp, self).from_element(element) super(TimeStamp, self).from_element(element)
when = element.find('%swhen' %self.ns) when = element.find('%swhen' % self.ns)
if when is not None: if when is not None:
self.timestamp = self.parse_str(when.text) self.timestamp = self.parse_str(when.text)
class TimeSpan(_TimePrimitive): class TimeSpan(_TimePrimitive):
""" Represents an extent in time bounded by begin and end dateTimes. """ Represents an extent in time bounded by begin and end dateTimes.
""" """
...@@ -826,8 +845,10 @@ class TimeSpan(_TimePrimitive): ...@@ -826,8 +845,10 @@ class TimeSpan(_TimePrimitive):
begin = None begin = None
end = None end = None
def __init__(self, ns=None, id=None, begin=None, begin_res=None, def __init__(
end=None, end_res=None): self, ns=None, id=None, begin=None, begin_res=None,
end=None, end_res=None
):
super(TimeSpan, self).__init__(ns, id) super(TimeSpan, self).__init__(ns, id)
if begin: if begin:
resolution = self.get_resolution(begin, begin_res) resolution = self.get_resolution(begin, begin_res)
...@@ -838,10 +859,10 @@ class TimeSpan(_TimePrimitive): ...@@ -838,10 +859,10 @@ class TimeSpan(_TimePrimitive):
def from_element(self, element): def from_element(self, element):
super(TimeSpan, self).from_element(element) super(TimeSpan, self).from_element(element)
begin = element.find('%sbegin' %self.ns) begin = element.find('%sbegin' % self.ns)
if begin is not None: if begin is not None:
self.begin = self.parse_str(begin.text) self.begin = self.parse_str(begin.text)
end = element.find('%send' %self.ns) end = element.find('%send' % self.ns)
if end is not None: if end is not None:
self.end = self.parse_str(end.text) self.end = self.parse_str(end.text)
...@@ -850,16 +871,16 @@ class TimeSpan(_TimePrimitive): ...@@ -850,16 +871,16 @@ class TimeSpan(_TimePrimitive):
if self.begin is not None: if self.begin is not None:
text = self.date_to_string(*self.begin) text = self.date_to_string(*self.begin)
if text: if text:
begin = etree.SubElement(element, "%sbegin" %self.ns) begin = etree.SubElement(element, "%sbegin" % self.ns)
begin.text = text begin.text = text
if self.end is not None: if self.end is not None:
text = self.date_to_string(*self.end) text = self.date_to_string(*self.end)
if text: if text:
end = etree.SubElement(element, "%send" %self.ns) end = etree.SubElement(element, "%send" % self.ns)
end.text = text end.text = text
if self.begin == self.end == None: if self.begin == self.end is None:
raise ValueError("Either begin, end or both must be set") raise ValueError("Either begin, end or both must be set")
#TODO test if end > begin # TODO test if end > begin
return element return element
...@@ -890,9 +911,11 @@ class Schema(_BaseObject): ...@@ -890,9 +911,11 @@ class Schema(_BaseObject):
sfs = [] sfs = []
for simple_field in self._simple_fields: for simple_field in self._simple_fields:
if simple_field.get('type') and simple_field.get('name'): if simple_field.get('type') and simple_field.get('name'):
sfs.append( {'type': simple_field['type'], sfs.append({
'type': simple_field['type'],
'name': simple_field['name'], 'name': simple_field['name'],
'displayName': simple_field.get('displayName')}) 'displayName': simple_field.get('displayName')
})
return tuple(sfs) return tuple(sfs)
@simple_fields.setter @simple_fields.setter
...@@ -933,12 +956,17 @@ class Schema(_BaseObject): ...@@ -933,12 +956,17 @@ class Schema(_BaseObject):
the Google Earth user. Use the [CDATA] element to escape standard the Google Earth user. Use the [CDATA] element to escape standard
HTML markup. HTML markup.
""" """
allowed_types= ['string', 'int', 'uint', 'short', 'ushort', allowed_types = [
'float', 'double', 'bool'] 'string', 'int', 'uint', 'short', 'ushort',
'float', 'double', 'bool'
]
if type not in allowed_types: if type not in allowed_types:
raise TypeError("type must be one of 'string', 'int', 'uint', 'short', 'ushort', 'float', 'double', 'bool'") raise TypeError(
"type must be one of ""'string', 'int', 'uint', 'short', "
"'ushort', 'float', 'double', 'bool'"
)
else: else:
#TODO explicit type conversion to check for the right type # TODO explicit type conversion to check for the right type
pass pass
self._simple_fields.append({'type': type, 'name': name, self._simple_fields.append({'type': type, 'name': name,
'displayName': displayName}) 'displayName': displayName})
...@@ -963,11 +991,11 @@ class Schema(_BaseObject): ...@@ -963,11 +991,11 @@ class Schema(_BaseObject):
if self.name: if self.name:
element.set('name', self.name) element.set('name', self.name)
for simple_field in self.simple_fields: for simple_field in self.simple_fields:
sf = etree.SubElement(element, "%sSimpleField" %self.ns) sf = etree.SubElement(element, "%sSimpleField" % self.ns)
sf.set('type', simple_field['type']) sf.set('type', simple_field['type'])
sf.set('name', simple_field['name']) sf.set('name', simple_field['name'])
if simple_field.get('displayName'): if simple_field.get('displayName'):
dn = etree.SubElement(sf, "%sdisplayName" %self.ns) dn = etree.SubElement(sf, "%sdisplayName" % self.ns)
dn.text = simple_field['displayName'] dn.text = simple_field['displayName']
return element return element
...@@ -1008,10 +1036,12 @@ class ExtendedData(_XMLObject): ...@@ -1008,10 +1036,12 @@ class ExtendedData(_XMLObject):
class UntypedExtendedData(ExtendedData): class UntypedExtendedData(ExtendedData):
def __init__(self, ns=None, elements=None): def __init__(self, ns=None, elements=None):
super(UntypedExtendedData, self).__init__(ns, elements) super(UntypedExtendedData, self).__init__(ns, elements)
warnings.warn("UntypedExtendedData is deprecated use ExtendedData instead", DeprecationWarning) warnings.warn(
"UntypedExtendedData is deprecated use ExtendedData instead",
DeprecationWarning
)
class Data(_XMLObject): class Data(_XMLObject):
...@@ -1044,10 +1074,17 @@ class Data(_XMLObject): ...@@ -1044,10 +1074,17 @@ class Data(_XMLObject):
if display_name is not None: if display_name is not None:
self.display_name = display_name.text self.display_name = display_name.text
class UntypedExtendedDataElement(Data): class UntypedExtendedDataElement(Data):
def __init__(self, ns=None, name=None, value=None, display_name=None): def __init__(self, ns=None, name=None, value=None, display_name=None):
super(UntypedExtendedDataElement, self).__init__(ns, name, value, display_name) super(UntypedExtendedDataElement, self).__init__(
warnings.warn("UntypedExtendedDataElement is deprecated use Data instead", DeprecationWarning) ns, name, value, display_name
)
warnings.warn(
"UntypedExtendedDataElement is deprecated use Data instead",
DeprecationWarning
)
class SchemaData(_XMLObject): class SchemaData(_XMLObject):
""" """
...@@ -1093,7 +1130,7 @@ class SchemaData(_XMLObject): ...@@ -1093,7 +1130,7 @@ class SchemaData(_XMLObject):
def append_data(self, name, value): def append_data(self, name, value):
if isinstance(name, basestring) and name: if isinstance(name, basestring) and name:
self._data.append({'name':name, 'value': value}) self._data.append({'name': name, 'value': value})
else: else:
raise TypeError('name must be a nonempty string') raise TypeError('name must be a nonempty string')
...@@ -1101,7 +1138,7 @@ class SchemaData(_XMLObject): ...@@ -1101,7 +1138,7 @@ class SchemaData(_XMLObject):
element = super(SchemaData, self).etree_element() element = super(SchemaData, self).etree_element()
element.set('schemaUrl', self.schema_url) element.set('schemaUrl', self.schema_url)
for data in self.data: for data in self.data:
sd = etree.SubElement(element, "%sSimpleData" %self.ns) sd = etree.SubElement(element, "%sSimpleData" % self.ns)
sd.set('name', data['name']) sd.set('name', data['name'])
sd.text = data['value'] sd.text = data['value']
return element return element
...@@ -1113,5 +1150,3 @@ class SchemaData(_XMLObject): ...@@ -1113,5 +1150,3 @@ class SchemaData(_XMLObject):
simple_data = element.findall('%sSimpleData' % self.ns) simple_data = element.findall('%sSimpleData' % self.ns)
for sd in simple_data: for sd in simple_data:
self.append_data(sd.get('name'), sd.text) self.append_data(sd.get('name'), sd.text)
...@@ -23,13 +23,10 @@ part of how your data is displayed. ...@@ -23,13 +23,10 @@ part of how your data is displayed.
import logging import logging
logger = logging.getLogger('fastkml.styles') logger = logging.getLogger('fastkml.styles')
import fastkml.config as config
from fastkml.config import etree from fastkml.config import etree
from fastkml.base import _BaseObject from fastkml.base import _BaseObject
class StyleUrl(_BaseObject): class StyleUrl(_BaseObject):
""" """
URL of a <Style> or <StyleMap> defined in a Document. If the style URL of a <Style> or <StyleMap> defined in a Document. If the style
...@@ -78,7 +75,7 @@ class Style(_StyleSelector): ...@@ -78,7 +75,7 @@ class Style(_StyleSelector):
__name__ = "Style" __name__ = "Style"
_styles = None _styles = None
def __init__(self, ns=None, id=None, styles = None): def __init__(self, ns=None, id=None, styles=None):
super(Style, self).__init__(ns, id) super(Style, self).__init__(ns, id)
self._styles = [] self._styles = []
if styles: if styles:
...@@ -100,27 +97,27 @@ class Style(_StyleSelector): ...@@ -100,27 +97,27 @@ class Style(_StyleSelector):
def from_element(self, element): def from_element(self, element):
super(Style, self).from_element(element) super(Style, self).from_element(element)
style = element.find('%sIconStyle' %self.ns) style = element.find('%sIconStyle' % self.ns)
if style is not None: if style is not None:
thestyle = IconStyle(self.ns) thestyle = IconStyle(self.ns)
thestyle.from_element(style) thestyle.from_element(style)
self.append_style(thestyle) self.append_style(thestyle)
style = element.find('%sLineStyle' %self.ns) style = element.find('%sLineStyle' % self.ns)
if style is not None: if style is not None:
thestyle = LineStyle(self.ns) thestyle = LineStyle(self.ns)
thestyle.from_element(style) thestyle.from_element(style)
self.append_style(thestyle) self.append_style(thestyle)
style = element.find('%sPolyStyle' %self.ns) style = element.find('%sPolyStyle' % self.ns)
if style is not None: if style is not None:
thestyle = PolyStyle(self.ns) thestyle = PolyStyle(self.ns)
thestyle.from_element(style) thestyle.from_element(style)
self.append_style(thestyle) self.append_style(thestyle)
style = element.find('%sLabelStyle' %self.ns) style = element.find('%sLabelStyle' % self.ns)
if style is not None: if style is not None:
thestyle = LabelStyle(self.ns) thestyle = LabelStyle(self.ns)
thestyle.from_element(style) thestyle.from_element(style)
self.append_style(thestyle) self.append_style(thestyle)
style = element.find('%sBalloonStyle' %self.ns) style = element.find('%sBalloonStyle' % self.ns)
if style is not None: if style is not None:
thestyle = BalloonStyle(self.ns) thestyle = BalloonStyle(self.ns)
thestyle.from_element(style) thestyle.from_element(style)
...@@ -148,14 +145,13 @@ class StyleMap(_StyleSelector): ...@@ -148,14 +145,13 @@ class StyleMap(_StyleSelector):
super(StyleMap, self).__init__(ns, id) super(StyleMap, self).__init__(ns, id)
pass pass
def from_element(self, element): def from_element(self, element):
super(StyleMap, self).from_element(element) super(StyleMap, self).from_element(element)
pairs = element.findall('%sPair' %self.ns) pairs = element.findall('%sPair' % self.ns)
for pair in pairs: for pair in pairs:
key = pair.find('%skey' %self.ns) key = pair.find('%skey' % self.ns)
style = pair.find('%sStyle' %self.ns) style = pair.find('%sStyle' % self.ns)
style_url = pair.find('%sstyleUrl' %self.ns) style_url = pair.find('%sstyleUrl' % self.ns)
if key.text == "highlight": if key.text == "highlight":
if style is not None: if style is not None:
highlight = Style(self.ns) highlight = Style(self.ns)
...@@ -179,20 +175,18 @@ class StyleMap(_StyleSelector): ...@@ -179,20 +175,18 @@ class StyleMap(_StyleSelector):
else: else:
raise ValueError raise ValueError
def etree_element(self): def etree_element(self):
element = super(StyleMap, self).etree_element() element = super(StyleMap, self).etree_element()
if self.normal: if self.normal:
if isinstance(self.normal, (Style, StyleUrl)): if isinstance(self.normal, (Style, StyleUrl)):
pair = etree.SubElement(element, "%sPair" %self.ns) pair = etree.SubElement(element, "%sPair" % self.ns)
key = etree.SubElement(pair, "%skey" %self.ns) key = etree.SubElement(pair, "%skey" % self.ns)
key.text = 'normal' key.text = 'normal'
pair.append(self.normal.etree_element()) pair.append(self.normal.etree_element())
if self.highlight: if self.highlight:
if isinstance(self.highlight, (Style, StyleUrl)): if isinstance(self.highlight, (Style, StyleUrl)):
pair = etree.SubElement(element, "%sPair" %self.ns) pair = etree.SubElement(element, "%sPair" % self.ns)
key = etree.SubElement(pair, "%skey" %self.ns) key = etree.SubElement(pair, "%skey" % self.ns)
key.text = 'highlight' key.text = 'highlight'
pair.append(self.highlight.etree_element()) pair.append(self.highlight.etree_element())
return element return element
...@@ -224,27 +218,26 @@ class _ColorStyle(_BaseObject): ...@@ -224,27 +218,26 @@ class _ColorStyle(_BaseObject):
self.color = color self.color = color
self.colorMode = colorMode self.colorMode = colorMode
def etree_element(self): def etree_element(self):
element = super(_ColorStyle, self).etree_element() element = super(_ColorStyle, self).etree_element()
if self.color: if self.color:
color = etree.SubElement(element, "%scolor" %self.ns) color = etree.SubElement(element, "%scolor" % self.ns)
color.text = self.color color.text = self.color
if self.colorMode: if self.colorMode:
colorMode = etree.SubElement(element, "%scolorMode" %self.ns) colorMode = etree.SubElement(element, "%scolorMode" % self.ns)
colorMode.text = self.colorMode colorMode.text = self.colorMode
return element return element
def from_element(self, element): def from_element(self, element):
super(_ColorStyle, self).from_element(element) super(_ColorStyle, self).from_element(element)
colorMode = element.find('%scolorMode' %self.ns) colorMode = element.find('%scolorMode' % self.ns)
if colorMode is not None: if colorMode is not None:
self.colorMode = colorMode.text self.colorMode = colorMode.text
color = element.find('%scolor' %self.ns) color = element.find('%scolor' % self.ns)
if color is not None: if color is not None:
self.color = color.text self.color = color.text
class IconStyle(_ColorStyle): class IconStyle(_ColorStyle):
""" Specifies how icons for point Placemarks are drawn """ """ Specifies how icons for point Placemarks are drawn """
__name__ = "IconStyle" __name__ = "IconStyle"
...@@ -256,8 +249,10 @@ class IconStyle(_ColorStyle): ...@@ -256,8 +249,10 @@ class IconStyle(_ColorStyle):
icon_href = None icon_href = None
# An HTTP address or a local file specification used to load an icon. # An HTTP address or a local file specification used to load an icon.
def __init__(self, ns=None, id=None, color=None, colorMode=None, def __init__(
scale=1.0, heading=None, icon_href=None): self, ns=None, id=None, color=None, colorMode=None, scale=1.0,
heading=None, icon_href=None
):
super(IconStyle, self).__init__(ns, id, color, colorMode) super(IconStyle, self).__init__(ns, id, color, colorMode)
self.scale = scale self.scale = scale
self.heading = heading self.heading = heading
...@@ -266,33 +261,32 @@ class IconStyle(_ColorStyle): ...@@ -266,33 +261,32 @@ class IconStyle(_ColorStyle):
def etree_element(self): def etree_element(self):
element = super(IconStyle, self).etree_element() element = super(IconStyle, self).etree_element()
if self.scale is not None: if self.scale is not None:
scale = etree.SubElement(element, "%sscale" %self.ns) scale = etree.SubElement(element, "%sscale" % self.ns)
scale.text = str(self.scale) scale.text = str(self.scale)
if self.heading: if self.heading:
heading = etree.SubElement(element, "%sheading" %self.ns) heading = etree.SubElement(element, "%sheading" % self.ns)
heading.text = str(self.heading) heading.text = str(self.heading)
if self.icon_href: if self.icon_href:
icon = etree.SubElement(element, "%sIcon" %self.ns) icon = etree.SubElement(element, "%sIcon" % self.ns)
href = etree.SubElement(icon, "%shref" %self.ns) href = etree.SubElement(icon, "%shref" % self.ns)
href.text = self.icon_href href.text = self.icon_href
return element return element
def from_element(self, element): def from_element(self, element):
super(IconStyle, self).from_element(element) super(IconStyle, self).from_element(element)
scale = element.find('%sscale' %self.ns) scale = element.find('%sscale' % self.ns)
if scale is not None: if scale is not None:
self.scale = float(scale.text) self.scale = float(scale.text)
heading = element.find('%sheading' %self.ns) heading = element.find('%sheading' % self.ns)
if heading is not None: if heading is not None:
self.heading = float(heading.text) self.heading = float(heading.text)
icon = element.find('%sIcon' %self.ns) icon = element.find('%sIcon' % self.ns)
if icon is not None: if icon is not None:
href = icon.find('%shref' %self.ns) href = icon.find('%shref' % self.ns)
if href is not None: if href is not None:
self.icon_href = href.text self.icon_href = href.text
class LineStyle(_ColorStyle): class LineStyle(_ColorStyle):
""" """
Specifies the drawing style (color, color mode, and line width) Specifies the drawing style (color, color mode, and line width)
...@@ -304,24 +298,26 @@ class LineStyle(_ColorStyle): ...@@ -304,24 +298,26 @@ class LineStyle(_ColorStyle):
width = 1.0 width = 1.0
# Width of the line, in pixels. # Width of the line, in pixels.
def __init__(self, ns=None, id=None, color=None, colorMode=None, def __init__(
width=1): self, ns=None, id=None, color=None, colorMode=None, width=1
):
super(LineStyle, self).__init__(ns, id, color, colorMode) super(LineStyle, self).__init__(ns, id, color, colorMode)
self.width = width self.width = width
def etree_element(self): def etree_element(self):
element = super(LineStyle, self).etree_element() element = super(LineStyle, self).etree_element()
if self.width is not None: if self.width is not None:
width = etree.SubElement(element, "%swidth" %self.ns) width = etree.SubElement(element, "%swidth" % self.ns)
width.text = str(self.width) width.text = str(self.width)
return element return element
def from_element(self, element): def from_element(self, element):
super(LineStyle, self).from_element(element) super(LineStyle, self).from_element(element)
width = element.find('%swidth' %self.ns) width = element.find('%swidth' % self.ns)
if width is not None: if width is not None:
self.width = float(width.text) self.width = float(width.text)
class PolyStyle(_ColorStyle): class PolyStyle(_ColorStyle):
""" """
Specifies the drawing style for all polygons, including polygon Specifies the drawing style for all polygons, including polygon
...@@ -335,8 +331,9 @@ class PolyStyle(_ColorStyle): ...@@ -335,8 +331,9 @@ class PolyStyle(_ColorStyle):
# Boolean value. Specifies whether to outline the polygon. # Boolean value. Specifies whether to outline the polygon.
# Polygon outlines use the current LineStyle. # Polygon outlines use the current LineStyle.
def __init__(self, ns=None, id=None, color=None, colorMode=None, def __init__(
fill=1, outline=1): self, ns=None, id=None, color=None, colorMode=None, fill=1, outline=1
):
super(PolyStyle, self).__init__(ns, id, color, colorMode) super(PolyStyle, self).__init__(ns, id, color, colorMode)
self.fill = fill self.fill = fill
self.outline = outline self.outline = outline
...@@ -344,19 +341,19 @@ class PolyStyle(_ColorStyle): ...@@ -344,19 +341,19 @@ class PolyStyle(_ColorStyle):
def etree_element(self): def etree_element(self):
element = super(PolyStyle, self).etree_element() element = super(PolyStyle, self).etree_element()
if self.fill is not None: if self.fill is not None:
fill = etree.SubElement(element, "%sfill" %self.ns) fill = etree.SubElement(element, "%sfill" % self.ns)
fill.text = str(self.fill) fill.text = str(self.fill)
if self.outline is not None: if self.outline is not None:
outline = etree.SubElement(element, "%soutline" %self.ns) outline = etree.SubElement(element, "%soutline" % self.ns)
outline.text = str(self.outline) outline.text = str(self.outline)
return element return element
def from_element(self, element): def from_element(self, element):
super(PolyStyle, self).from_element(element) super(PolyStyle, self).from_element(element)
fill = element.find('%sfill' %self.ns) fill = element.find('%sfill' % self.ns)
if fill is not None: if fill is not None:
self.fill = int(fill.text) self.fill = int(fill.text)
outline = element.find('%soutline' %self.ns) outline = element.find('%soutline' % self.ns)
if outline is not None: if outline is not None:
self.outline = int(outline.text) self.outline = int(outline.text)
...@@ -369,24 +366,26 @@ class LabelStyle(_ColorStyle): ...@@ -369,24 +366,26 @@ class LabelStyle(_ColorStyle):
scale = 1.0 scale = 1.0
# Resizes the label. # Resizes the label.
def __init__(self, ns=None, id=None, color=None, colorMode=None, def __init__(
scale=1.0): self, ns=None, id=None, color=None, colorMode=None, scale=1.0
):
super(LabelStyle, self).__init__(ns, id, color, colorMode) super(LabelStyle, self).__init__(ns, id, color, colorMode)
self.scale = scale self.scale = scale
def etree_element(self): def etree_element(self):
element = super(LabelStyle, self).etree_element() element = super(LabelStyle, self).etree_element()
if self.scale is not None: if self.scale is not None:
scale = etree.SubElement(element, "%sscale" %self.ns) scale = etree.SubElement(element, "%sscale" % self.ns)
scale.text = str(self.scale) scale.text = str(self.scale)
return element return element
def from_element(self, element): def from_element(self, element):
super(LabelStyle, self).from_element(element) super(LabelStyle, self).from_element(element)
scale = element.find('%sscale' %self.ns) scale = element.find('%sscale' % self.ns)
if scale is not None: if scale is not None:
self.scale = float(scale.text) self.scale = float(scale.text)
class BalloonStyle(_BaseObject): class BalloonStyle(_BaseObject):
""" Specifies how the description balloon for placemarks is drawn. """ Specifies how the description balloon for placemarks is drawn.
The <bgColor>, if specified, is used as the background color of The <bgColor>, if specified, is used as the background color of
...@@ -395,15 +394,15 @@ class BalloonStyle(_BaseObject): ...@@ -395,15 +394,15 @@ class BalloonStyle(_BaseObject):
__name__ = "BalloonStyle" __name__ = "BalloonStyle"
bgColor = None bgColor = None
#Background color of the balloon (optional). Color and opacity (alpha) # Background color of the balloon (optional). Color and opacity (alpha)
#values are expressed in hexadecimal notation. The range of values for # values are expressed in hexadecimal notation. The range of values for
#any one color is 0 to 255 (00 to ff). The order of expression is # any one color is 0 to 255 (00 to ff). The order of expression is
# aabbggrr, where aa=alpha (00 to ff); bb=blue (00 to ff); # aabbggrr, where aa=alpha (00 to ff); bb=blue (00 to ff);
# gg=green (00 to ff); rr=red (00 to ff). # gg=green (00 to ff); rr=red (00 to ff).
# For alpha, 00 is fully transparent and ff is fully opaque. # For alpha, 00 is fully transparent and ff is fully opaque.
# For example, if you want to apply a blue color with 50 percent # For example, if you want to apply a blue color with 50 percent
# opacity to an overlay, you would specify the following: # opacity to an overlay, you would specify the following:
#<bgColor>7fff0000</bgColor>, where alpha=0x7f, blue=0xff, green=0x00, # <bgColor>7fff0000</bgColor>, where alpha=0x7f, blue=0xff, green=0x00,
# and red=0x00. The default is opaque white (ffffffff). # and red=0x00. The default is opaque white (ffffffff).
# Note: The use of the <color> element within <BalloonStyle> has been # Note: The use of the <color> element within <BalloonStyle> has been
# deprecated. Use <bgColor> instead. # deprecated. Use <bgColor> instead.
...@@ -412,33 +411,36 @@ class BalloonStyle(_BaseObject): ...@@ -412,33 +411,36 @@ class BalloonStyle(_BaseObject):
# Foreground color for text. The default is black (ff000000). # Foreground color for text. The default is black (ff000000).
text = None text = None
#Text displayed in the balloon. If no text is specified, Google Earth # Text displayed in the balloon. If no text is specified, Google Earth
#draws the default balloon (with the Feature <name> in boldface, # draws the default balloon (with the Feature <name> in boldface,
#the Feature <description>, links for driving directions, a white # the Feature <description>, links for driving directions, a white
#background, and a tail that is attached to the point coordinates of # background, and a tail that is attached to the point coordinates of
#the Feature, if specified). # the Feature, if specified).
#You can add entities to the <text> tag using the following format to # You can add entities to the <text> tag using the following format to
#refer to a child element of Feature: $[name], $[description], $[address], # refer to a child element of Feature: $[name], $[description], $[address],
#$[id], $[Snippet]. Google Earth looks in the current Feature for the # $[id], $[Snippet]. Google Earth looks in the current Feature for the
#corresponding string entity and substitutes that information in the balloon. # corresponding string entity and substitutes that information in the
#To include To here - From here driving directions in the balloon, # balloon.
#use the $[geDirections] tag. To prevent the driving directions links # To include To here - From here driving directions in the balloon,
#from appearing in a balloon, include the <text> element with some content, # use the $[geDirections] tag. To prevent the driving directions links
#or with $[description] to substitute the basic Feature <description>. # from appearing in a balloon, include the <text> element with some content
#For example, in the following KML excerpt, $[name] and $[description] # or with $[description] to substitute the basic Feature <description>.
#fields will be replaced by the <name> and <description> fields found # For example, in the following KML excerpt, $[name] and $[description]
#in the Feature elements that use this BalloonStyle: # fields will be replaced by the <name> and <description> fields found
#<text>This is $[name], whose description is:<br/>$[description]</text> # in the Feature elements that use this BalloonStyle:
# <text>This is $[name], whose description is:<br/>$[description]</text>
displayMode = None displayMode = None
#If <displayMode> is default, Google Earth uses the information supplied # If <displayMode> is default, Google Earth uses the information supplied
#in <text> to create a balloon . If <displayMode> is hide, Google Earth # in <text> to create a balloon . If <displayMode> is hide, Google Earth
#does not display the balloon. In Google Earth, clicking the List View # does not display the balloon. In Google Earth, clicking the List View
#icon for a Placemark whose balloon's <displayMode> is hide causes # icon for a Placemark whose balloon's <displayMode> is hide causes
#Google Earth to fly to the Placemark. # Google Earth to fly to the Placemark.
def __init__(self, ns=None, id=None, bgColor=None, textColor=None, def __init__(
text=None, displayMode=None): self, ns=None, id=None, bgColor=None, textColor=None, text=None,
displayMode=None
):
super(BalloonStyle, self).__init__(ns, id) super(BalloonStyle, self).__init__(ns, id)
self.bgColor = bgColor self.bgColor = bgColor
self.textColor = textColor self.textColor = textColor
...@@ -447,35 +449,35 @@ class BalloonStyle(_BaseObject): ...@@ -447,35 +449,35 @@ class BalloonStyle(_BaseObject):
def from_element(self, element): def from_element(self, element):
super(BalloonStyle, self).from_element(element) super(BalloonStyle, self).from_element(element)
bgColor = element.find('%sbgColor' %self.ns) bgColor = element.find('%sbgColor' % self.ns)
if bgColor is not None: if bgColor is not None:
self.bgColor = bgColor.text self.bgColor = bgColor.text
else: else:
bgColor = element.find('%scolor' %self.ns) bgColor = element.find('%scolor' % self.ns)
if bgColor is not None: if bgColor is not None:
self.bgColor = bgColor.text self.bgColor = bgColor.text
textColor = element.find('%stextColor' %self.ns) textColor = element.find('%stextColor' % self.ns)
if textColor is not None: if textColor is not None:
self.textColor = textColor.text self.textColor = textColor.text
text = element.find('%stext' %self.ns) text = element.find('%stext' % self.ns)
if text is not None: if text is not None:
self.text = text.text self.text = text.text
displayMode = element.find('%sdisplayMode' %self.ns) displayMode = element.find('%sdisplayMode' % self.ns)
if displayMode is not None: if displayMode is not None:
self.displayMode = displayMode.text self.displayMode = displayMode.text
def etree_element(self): def etree_element(self):
element = super(BalloonStyle, self).etree_element() element = super(BalloonStyle, self).etree_element()
if self.bgColor is not None: if self.bgColor is not None:
elem = etree.SubElement(element, "%sbgColor" %self.ns) elem = etree.SubElement(element, "%sbgColor" % self.ns)
elem.text = self.bgColor elem.text = self.bgColor
if self.textColor is not None: if self.textColor is not None:
elem = etree.SubElement(element, "%stextColor" %self.ns) elem = etree.SubElement(element, "%stextColor" % self.ns)
elem.text = self.textColor elem.text = self.textColor
if self.text is not None: if self.text is not None:
elem = etree.SubElement(element, "%stext" %self.ns) elem = etree.SubElement(element, "%stext" % self.ns)
elem.text = self.text elem.text = self.text
if self.displayMode is not None: if self.displayMode is not None:
elem = etree.SubElement(element, "%sdisplayMode" %self.ns) elem = etree.SubElement(element, "%sdisplayMode" % self.ns)
elem.text = self.displayMode elem.text = self.displayMode
return element return element
...@@ -23,7 +23,6 @@ from fastkml import base ...@@ -23,7 +23,6 @@ from fastkml import base
from fastkml import atom from fastkml import atom
from fastkml import config from fastkml import config
import datetime import datetime
from dateutil.tz import tzutc, tzoffset from dateutil.tz import tzutc, tzoffset
...@@ -33,7 +32,6 @@ from fastkml.geometry import Point, LineString, Polygon ...@@ -33,7 +32,6 @@ from fastkml.geometry import Point, LineString, Polygon
from fastkml.geometry import MultiPoint, MultiLineString, MultiPolygon from fastkml.geometry import MultiPoint, MultiLineString, MultiPolygon
from fastkml.geometry import LinearRing, GeometryCollection from fastkml.geometry import LinearRing, GeometryCollection
from fastkml.geometry import Geometry from fastkml.geometry import Geometry
from fastkml.geometry import asShape
class BaseClassesTestCase(unittest.TestCase): class BaseClassesTestCase(unittest.TestCase):
...@@ -48,8 +46,8 @@ class BaseClassesTestCase(unittest.TestCase): ...@@ -48,8 +46,8 @@ class BaseClassesTestCase(unittest.TestCase):
self.assertEqual(bo.__name__, None) self.assertEqual(bo.__name__, None)
bo.targetId = 'target' bo.targetId = 'target'
self.assertEqual(bo.targetId, 'target') self.assertEqual(bo.targetId, 'target')
bo.ns ='' bo.ns = ''
bo.id =None bo.id = None
self.assertEqual(bo.id, None) self.assertEqual(bo.id, None)
self.assertEqual(bo.ns, '') self.assertEqual(bo.ns, '')
self.assertRaises(NotImplementedError, bo.etree_element) self.assertRaises(NotImplementedError, bo.etree_element)
...@@ -58,7 +56,7 @@ class BaseClassesTestCase(unittest.TestCase): ...@@ -58,7 +56,7 @@ class BaseClassesTestCase(unittest.TestCase):
self.assertRaises(TypeError, bo.from_element, element) self.assertRaises(TypeError, bo.from_element, element)
bo.__name__ = 'NotABaseObject' bo.__name__ = 'NotABaseObject'
self.assertRaises(TypeError, bo.from_element, element) self.assertRaises(TypeError, bo.from_element, element)
#Note that we can coax baseclasses not to throw errors # Note that we can coax baseclasses not to throw errors
bo.__name__ = 'Base' bo.__name__ = 'Base'
bo.ns = config.NS bo.ns = config.NS
bo.from_element(element) bo.from_element(element)
...@@ -75,23 +73,22 @@ class BaseClassesTestCase(unittest.TestCase): ...@@ -75,23 +73,22 @@ class BaseClassesTestCase(unittest.TestCase):
self.assertEqual(f.isopen, 0) self.assertEqual(f.isopen, 0)
self.assertEqual(f._atom_author, None) self.assertEqual(f._atom_author, None)
self.assertEqual(f._atom_link, None) self.assertEqual(f._atom_link, None)
#self.assertEqual(f.address, None) # self.assertEqual(f.address, None)
#self.assertEqual(f.phoneNumber, None) # self.assertEqual(f.phoneNumber, None)
self.assertEqual(f._snippet, None) self.assertEqual(f._snippet, None)
self.assertEqual(f.description, None) self.assertEqual(f.description, None)
self.assertEqual(f._styleUrl, None) self.assertEqual(f._styleUrl, None)
self.assertEqual(f._styles, []) self.assertEqual(f._styles, [])
self.assertEqual(f._time_span, None) self.assertEqual(f._time_span, None)
self.assertEqual(f._time_stamp, None) self.assertEqual(f._time_stamp, None)
#self.assertEqual(f.region, None) # self.assertEqual(f.region, None)
#self.assertEqual(f.extended_data, None) # self.assertEqual(f.extended_data, None)
f.__name__ = 'Feature' f.__name__ = 'Feature'
f.styleUrl = '#default' f.styleUrl = '#default'
self.assertTrue('Feature>' in str(f.to_string())) self.assertTrue('Feature>' in str(f.to_string()))
self.assertTrue('#default' in str(f.to_string())) self.assertTrue('#default' in str(f.to_string()))
def test_Container(self): def test_Container(self):
f = kml._Container(name='A Container') f = kml._Container(name='A Container')
d = kml.Document() d = kml.Document()
...@@ -100,7 +97,6 @@ class BaseClassesTestCase(unittest.TestCase): ...@@ -100,7 +97,6 @@ class BaseClassesTestCase(unittest.TestCase):
f.append(p) f.append(p)
self.assertRaises(NotImplementedError, f.etree_element) self.assertRaises(NotImplementedError, f.etree_element)
def test_TimePrimitive(self): def test_TimePrimitive(self):
pass pass
...@@ -113,22 +109,29 @@ class BaseClassesTestCase(unittest.TestCase): ...@@ -113,22 +109,29 @@ class BaseClassesTestCase(unittest.TestCase):
def test_Person(self): def test_Person(self):
pass pass
class BuildKmlTestCase(unittest.TestCase): class BuildKmlTestCase(unittest.TestCase):
""" Build a simple KML File """ """ Build a simple KML File """
def test_kml(self): def test_kml(self):
""" kml file without contents """ """ kml file without contents """
k = kml.KML() k = kml.KML()
self.assertEqual(len( list(k.features())),0) self.assertEqual(len(list(k.features())), 0)
if config.LXML: if config.LXML:
self.assertEqual( str(k.to_string())[:43], self.assertEqual(
'<kml xmlns="http://www.opengis.net/kml/2.2"/>'[:43]) str(k.to_string())[:43],
'<kml xmlns="http://www.opengis.net/kml/2.2"/>'[:43]
)
else: else:
if hasattr(etree, 'register_namespace'): if hasattr(etree, 'register_namespace'):
self.assertEqual(str(k.to_string())[:51], self.assertEqual(
'<kml:kml xmlns:kml="http://www.opengis.net/kml/2.2" />'[:51]) str(k.to_string())[:51],
'<kml:kml xmlns:kml="http://www.opengis.net/kml/2.2" />'[:51]
)
else: else:
self.assertEqual(str(k.to_string())[:51], self.assertEqual(
'<ns0:kml xmlns:ns0="http://www.opengis.net/kml/2.2" />'[:51]) str(k.to_string())[:51],
'<ns0:kml xmlns:ns0="http://www.opengis.net/kml/2.2" />'[:51]
)
k2 = kml.KML() k2 = kml.KML()
k2.from_string(k.to_string()) k2.from_string(k.to_string())
...@@ -144,14 +147,13 @@ class BuildKmlTestCase(unittest.TestCase): ...@@ -144,14 +147,13 @@ class BuildKmlTestCase(unittest.TestCase):
k.append(f) k.append(f)
f2 = kml.Folder(ns, 'id2', 'name2', 'description2') f2 = kml.Folder(ns, 'id2', 'name2', 'description2')
k.append(f2) k.append(f2)
self.assertEqual(len(list(k.features())),2) self.assertEqual(len(list(k.features())), 2)
self.assertEqual(len( list( list(k.features())[0].features())),1) self.assertEqual(len(list(list(k.features())[0].features())), 1)
k2 = kml.KML() k2 = kml.KML()
s = k.to_string() s = k.to_string()
k2.from_string(s) k2.from_string(s)
self.assertEqual(s, k2.to_string()) self.assertEqual(s, k2.to_string())
def test_placemark(self): def test_placemark(self):
ns = '{http://www.opengis.net/kml/2.2}' ns = '{http://www.opengis.net/kml/2.2}'
k = kml.KML(ns=ns) k = kml.KML(ns=ns)
...@@ -161,7 +163,7 @@ class BuildKmlTestCase(unittest.TestCase): ...@@ -161,7 +163,7 @@ class BuildKmlTestCase(unittest.TestCase):
p2.geometry = LineString([(0, 0, 0), (1, 1, 1)]) p2.geometry = LineString([(0, 0, 0), (1, 1, 1)])
k.append(p) k.append(p)
k.append(p2) k.append(p2)
self.assertEqual(len(list(k.features())),2) self.assertEqual(len(list(k.features())), 2)
k2 = kml.KML() k2 = kml.KML()
k2.from_string(k.to_string(prettyprint=True)) k2.from_string(k.to_string(prettyprint=True))
self.assertEqual(k.to_string(), k2.to_string()) self.assertEqual(k.to_string(), k2.to_string())
...@@ -170,15 +172,15 @@ class BuildKmlTestCase(unittest.TestCase): ...@@ -170,15 +172,15 @@ class BuildKmlTestCase(unittest.TestCase):
ns = '{http://www.opengis.net/kml/2.2}' ns = '{http://www.opengis.net/kml/2.2}'
self.assertRaises(ValueError, kml.Schema, ns) self.assertRaises(ValueError, kml.Schema, ns)
s = kml.Schema(ns, 'some_id') s = kml.Schema(ns, 'some_id')
self.assertEqual(len(list(s.simple_fields)),0) self.assertEqual(len(list(s.simple_fields)), 0)
s.append('int', 'Integer', 'An Integer') s.append('int', 'Integer', 'An Integer')
self.assertEqual(list(s.simple_fields)[0]['type'], 'int') self.assertEqual(list(s.simple_fields)[0]['type'], 'int')
self.assertEqual(list(s.simple_fields)[0]['name'], 'Integer') self.assertEqual(list(s.simple_fields)[0]['name'], 'Integer')
self.assertEqual(list(s.simple_fields)[0]['displayName'], 'An Integer') self.assertEqual(list(s.simple_fields)[0]['displayName'], 'An Integer')
s.simple_fields = None s.simple_fields = None
self.assertEqual(len(list(s.simple_fields)),0) self.assertEqual(len(list(s.simple_fields)), 0)
self.assertRaises(TypeError, s.append, ('none', 'Integer', 'An Integer')) self.assertRaises(TypeError, s.append, ('none', 'Integer', 'An Integer'))
self.assertRaises(TypeError, s.simple_fields, [('none', 'Integer', 'An Integer'),]) self.assertRaises(TypeError, s.simple_fields, [('none', 'Integer', 'An Integer')])
self.assertRaises(TypeError, s.simple_fields, ('int', 'Integer', 'An Integer')) self.assertRaises(TypeError, s.simple_fields, ('int', 'Integer', 'An Integer'))
fields = {'type': 'int', 'name': 'Integer', 'displayName': 'An Integer'} fields = {'type': 'int', 'name': 'Integer', 'displayName': 'An Integer'}
s.simple_fields = fields s.simple_fields = fields
...@@ -193,7 +195,6 @@ class BuildKmlTestCase(unittest.TestCase): ...@@ -193,7 +195,6 @@ class BuildKmlTestCase(unittest.TestCase):
self.assertEqual(list(s.simple_fields)[1]['name'], 'Integer') self.assertEqual(list(s.simple_fields)[1]['name'], 'Integer')
self.assertEqual(list(s.simple_fields)[1]['displayName'], 'An Integer') self.assertEqual(list(s.simple_fields)[1]['displayName'], 'An Integer')
def test_schema_data(self): def test_schema_data(self):
ns = '{http://www.opengis.net/kml/2.2}' ns = '{http://www.opengis.net/kml/2.2}'
self.assertRaises(ValueError, kml.SchemaData, ns) self.assertRaises(ValueError, kml.SchemaData, ns)
...@@ -211,7 +212,6 @@ class BuildKmlTestCase(unittest.TestCase): ...@@ -211,7 +212,6 @@ class BuildKmlTestCase(unittest.TestCase):
self.assertEqual(sd.data[0], {'value': 'Some new Text', 'name': 'text'}) self.assertEqual(sd.data[0], {'value': 'Some new Text', 'name': 'text'})
self.assertEqual(sd.data[1], {'value': 2, 'name': 'Integer'}) self.assertEqual(sd.data[1], {'value': 2, 'name': 'Integer'})
def test_untyped_extended_data(self): def test_untyped_extended_data(self):
ns = '{http://www.opengis.net/kml/2.2}' ns = '{http://www.opengis.net/kml/2.2}'
k = kml.KML(ns=ns) k = kml.KML(ns=ns)
...@@ -244,7 +244,6 @@ class BuildKmlTestCase(unittest.TestCase): ...@@ -244,7 +244,6 @@ class BuildKmlTestCase(unittest.TestCase):
self.assertEqual(extended_data.elements[1].value, 'blue skies') self.assertEqual(extended_data.elements[1].value, 'blue skies')
self.assertEqual(extended_data.elements[1].display_name, 'Weather') self.assertEqual(extended_data.elements[1].display_name, 'Weather')
def test_untyped_extended_data_nested(self): def test_untyped_extended_data_nested(self):
ns = '{http://www.opengis.net/kml/2.2}' ns = '{http://www.opengis.net/kml/2.2}'
k = kml.KML(ns=ns) k = kml.KML(ns=ns)
...@@ -274,7 +273,6 @@ class BuildKmlTestCase(unittest.TestCase): ...@@ -274,7 +273,6 @@ class BuildKmlTestCase(unittest.TestCase):
self.assertEqual(folder_data.elements[0].name, 'type') self.assertEqual(folder_data.elements[0].name, 'type')
self.assertEqual(folder_data.elements[0].value, 'Folder') self.assertEqual(folder_data.elements[0].value, 'Folder')
def test_document(self): def test_document(self):
k = kml.KML() k = kml.KML()
ns = '{http://www.opengis.net/kml/2.2}' ns = '{http://www.opengis.net/kml/2.2}'
...@@ -289,19 +287,16 @@ class BuildKmlTestCase(unittest.TestCase): ...@@ -289,19 +287,16 @@ class BuildKmlTestCase(unittest.TestCase):
p = kml.Placemark(ns, 'id', 'name', 'description') p = kml.Placemark(ns, 'id', 'name', 'description')
p.geometry = Polygon([(0, 0, 0), (1, 1, 0), (1, 0, 1)]) p.geometry = Polygon([(0, 0, 0), (1, 1, 0), (1, 0, 1)])
p2 = kml.Placemark(ns, 'id2', 'name2', 'description2') p2 = kml.Placemark(ns, 'id2', 'name2', 'description2')
#p2 does not have a geometry! # p2 does not have a geometry!
f2.append(p) f2.append(p)
nf.append(p2) nf.append(p2)
self.assertEqual(len(list(k.features())),1) self.assertEqual(len(list(k.features())), 1)
self.assertEqual(len(list((list(k.features())[0].features()))),2) self.assertEqual(len(list((list(k.features())[0].features()))), 2)
k2 = kml.KML() k2 = kml.KML()
k2.from_string(k.to_string()) k2.from_string(k.to_string())
self.assertEqual(k.to_string(), k2.to_string()) self.assertEqual(k.to_string(), k2.to_string())
def test_author(self): def test_author(self):
k = kml.KML()
d = kml.Document() d = kml.Document()
d.author = 'Christian Ledermann' d.author = 'Christian Ledermann'
self.assertTrue('Christian Ledermann' in str(d.to_string())) self.assertTrue('Christian Ledermann' in str(d.to_string()))
...@@ -316,8 +311,6 @@ class BuildKmlTestCase(unittest.TestCase): ...@@ -316,8 +311,6 @@ class BuildKmlTestCase(unittest.TestCase):
d2.from_string(d.to_string()) d2.from_string(d.to_string())
self.assertEqual(d.to_string(), d2.to_string()) self.assertEqual(d.to_string(), d2.to_string())
d.author = None d.author = None
#print (d.to_string())
def test_link(self): def test_link(self):
d = kml.Document() d = kml.Document()
...@@ -332,8 +325,8 @@ class BuildKmlTestCase(unittest.TestCase): ...@@ -332,8 +325,8 @@ class BuildKmlTestCase(unittest.TestCase):
self.assertEqual(d.to_string(), d2.to_string()) self.assertEqual(d.to_string(), d2.to_string())
d.link = None d.link = None
class KmlFromStringTestCase( unittest.TestCase ):
class KmlFromStringTestCase(unittest.TestCase):
def test_document(self): def test_document(self):
doc = """<kml xmlns="http://www.opengis.net/kml/2.2"> doc = """<kml xmlns="http://www.opengis.net/kml/2.2">
<Document targetId="someTargetId"> <Document targetId="someTargetId">
...@@ -362,16 +355,14 @@ class KmlFromStringTestCase( unittest.TestCase ): ...@@ -362,16 +355,14 @@ class KmlFromStringTestCase( unittest.TestCase ):
</kml>""" </kml>"""
k = kml.KML() k = kml.KML()
k.from_string(doc) k.from_string(doc)
self.assertEqual(len(list(k.features())),1) self.assertEqual(len(list(k.features())), 1)
self.assertEqual(len(list(list(k.features())[0].features())),2) self.assertEqual(len(list(list(k.features())[0].features())), 2)
k2 = kml.KML() k2 = kml.KML()
k2.from_string(k.to_string()) k2.from_string(k.to_string())
self.assertEqual(k.to_string(), k2.to_string()) self.assertEqual(k.to_string(), k2.to_string())
def test_folders(self): def test_folders(self):
doc="""<kml xmlns="http://www.opengis.net/kml/2.2"> doc = """<kml xmlns="http://www.opengis.net/kml/2.2">
<Folder> <Folder>
<name>Folder.kml</name> <name>Folder.kml</name>
<open>1</open> <open>1</open>
...@@ -412,15 +403,14 @@ class KmlFromStringTestCase( unittest.TestCase ): ...@@ -412,15 +403,14 @@ class KmlFromStringTestCase( unittest.TestCase ):
</kml>""" </kml>"""
k = kml.KML() k = kml.KML()
k.from_string(doc) k.from_string(doc)
self.assertEqual(len(list(k.features())),1) self.assertEqual(len(list(k.features())), 1)
self.assertEqual(len(list(list(k.features())[0].features())),3) self.assertEqual(len(list(list(k.features())[0].features())), 3)
k2 = kml.KML() k2 = kml.KML()
k2.from_string(k.to_string()) k2.from_string(k.to_string())
self.assertEqual(k.to_string(), k2.to_string()) self.assertEqual(k.to_string(), k2.to_string())
def test_placemark(self): def test_placemark(self):
doc="""<kml xmlns="http://www.opengis.net/kml/2.2"> doc = """<kml xmlns="http://www.opengis.net/kml/2.2">
<Placemark> <Placemark>
<name>Simple placemark</name> <name>Simple placemark</name>
<description>Attached to the ground. Intelligently places itself <description>Attached to the ground. Intelligently places itself
...@@ -432,15 +422,14 @@ class KmlFromStringTestCase( unittest.TestCase ): ...@@ -432,15 +422,14 @@ class KmlFromStringTestCase( unittest.TestCase ):
</kml>""" </kml>"""
k = kml.KML() k = kml.KML()
k.from_string(doc) k.from_string(doc)
self.assertEqual(len(list(k.features())),1) self.assertEqual(len(list(k.features())), 1)
self.assertEqual(list(k.features())[0].name, "Simple placemark") self.assertEqual(list(k.features())[0].name, "Simple placemark")
k2 = kml.KML() k2 = kml.KML()
k2.from_string(k.to_string()) k2.from_string(k.to_string())
self.assertEqual(k.to_string(), k2.to_string()) self.assertEqual(k.to_string(), k2.to_string())
def test_extended_data(self): def test_extended_data(self):
doc="""<kml xmlns="http://www.opengis.net/kml/2.2"> doc = """<kml xmlns="http://www.opengis.net/kml/2.2">
<Placemark> <Placemark>
<name>Simple placemark</name> <name>Simple placemark</name>
<description></description> <description></description>
...@@ -489,23 +478,132 @@ class KmlFromStringTestCase( unittest.TestCase ): ...@@ -489,23 +478,132 @@ class KmlFromStringTestCase( unittest.TestCase ):
self.assertEqual(sd.data[1]['value'], '347.45') self.assertEqual(sd.data[1]['value'], '347.45')
def test_polygon(self): def test_polygon(self):
doc= """<kml xmlns="http://www.opengis.net/kml/2.2"> doc = """
<kml xmlns="http://www.opengis.net/kml/2.2">
<Placemark> <Placemark>
<name>South Africa</name> <name>South Africa</name>
<Polygon><outerBoundaryIs><LinearRing><coordinates>31.521,-29.257,0 31.326,-29.402,0 30.902,-29.91,0 30.623,-30.424,0 30.056,-31.14,0 28.926,-32.172,0 28.22,-32.772,0 27.465,-33.227,0 26.419,-33.615,0 25.91,-33.667,0 25.781,-33.945,0 25.173,-33.797,0 24.678,-33.987,0 23.594,-33.794,0 22.988,-33.916,0 22.574,-33.864,0 21.543,-34.259,0 20.689,-34.417,0 20.071,-34.795,0 19.616,-34.819,0 19.193,-34.463,0 18.855,-34.444,0 18.425,-33.998,0 18.377,-34.137,0 18.244,-33.868,0 18.25,-33.281,0 17.925,-32.611,0 18.248,-32.429,0 18.222,-31.662,0 17.567,-30.726,0 17.064,-29.879,0 17.063,-29.876,0 16.345,-28.577,0 16.824,-28.082,0 17.219,-28.356,0 17.387,-28.784,0 17.836,-28.856,0 18.465,-29.045,0 19.002,-28.972,0 19.895,-28.461,0 19.896,-24.768,0 20.166,-24.918,0 20.759,-25.868,0 20.666,-26.477,0 20.89,-26.829,0 21.606,-26.727,0 22.106,-26.28,0 22.58,-25.979,0 22.824,-25.5,0 23.312,-25.269,0 23.734,-25.39,0 24.211,-25.67,0 25.025,-25.72,0 25.665,-25.487,0 25.766,-25.175,0 25.942,-24.696,0 26.486,-24.616,0 26.786,-24.241,0 27.119,-23.574,0 28.017,-22.828,0 29.432,-22.091,0 29.839,-22.102,0 30.323,-22.272,0 30.66,-22.152,0 31.191,-22.252,0 31.67,-23.659,0 31.931,-24.369,0 31.752,-25.484,0 31.838,-25.843,0 31.333,-25.66,0 31.044,-25.731,0 30.95,-26.023,0 30.677,-26.398,0 30.686,-26.744,0 31.283,-27.286,0 31.868,-27.178,0 32.072,-26.734,0 32.83,-26.742,0 32.58,-27.47,0 32.462,-28.301,0 32.203,-28.752,0 31.521,-29.257,0 </coordinates></LinearRing></outerBoundaryIs><innerBoundaryIs><LinearRing><coordinates>28.978,-28.956,0 28.542,-28.648,0 28.074,-28.851,0 27.533,-29.243,0 26.999,-29.876,0 27.749,-30.645,0 28.107,-30.546,0 28.291,-30.226,0 28.848,-30.07,0 29.018,-29.744,0 29.325,-29.257,0 28.978,-28.956,0 </coordinates></LinearRing></innerBoundaryIs></Polygon> <Polygon>
</Placemark> </kml>""" <outerBoundaryIs>
<LinearRing>
<coordinates>
31.521,-29.257,0
31.326,-29.402,0
30.902,-29.91,0
30.623,-30.424,0
30.056,-31.14,0
28.926,-32.172,0
28.22,-32.772,0
27.465,-33.227,0
26.419,-33.615,0
25.91,-33.667,0
25.781,-33.945,0
25.173,-33.797,0
24.678,-33.987,0
23.594,-33.794,0
22.988,-33.916,0
22.574,-33.864,0
21.543,-34.259,0
20.689,-34.417,0
20.071,-34.795,0
19.616,-34.819,0
19.193,-34.463,0
18.855,-34.444,0
18.425,-33.998,0
18.377,-34.137,0
18.244,-33.868,0
18.25,-33.281,0
17.925,-32.611,0
18.248,-32.429,0
18.222,-31.662,0
17.567,-30.726,0
17.064,-29.879,0
17.063,-29.876,0
16.345,-28.577,0
16.824,-28.082,0
17.219,-28.356,0
17.387,-28.784,0
17.836,-28.856,0
18.465,-29.045,0
19.002,-28.972,0
19.895,-28.461,0
19.896,-24.768,0
20.166,-24.918,0
20.759,-25.868,0
20.666,-26.477,0
20.89,-26.829,0
21.606,-26.727,0
22.106,-26.28,0
22.58,-25.979,0
22.824,-25.5,0
23.312,-25.269,0
23.734,-25.39,0
24.211,-25.67,0
25.025,-25.72,0
25.665,-25.487,0
25.766,-25.175,0
25.942,-24.696,0
26.486,-24.616,0
26.786,-24.241,0
27.119,-23.574,0
28.017,-22.828,0
29.432,-22.091,0
29.839,-22.102,0
30.323,-22.272,0
30.66,-22.152,0
31.191,-22.252,0
31.67,-23.659,0
31.931,-24.369,0
31.752,-25.484,0
31.838,-25.843,0
31.333,-25.66,0
31.044,-25.731,0
30.95,-26.023,0
30.677,-26.398,0
30.686,-26.744,0
31.283,-27.286,0
31.868,-27.178,0
32.072,-26.734,0
32.83,-26.742,0
32.58,-27.47,0
32.462,-28.301,0
32.203,-28.752,0
31.521,-29.257,0
</coordinates>
</LinearRing>
</outerBoundaryIs>
<innerBoundaryIs>
<LinearRing>
<coordinates>
28.978,-28.956,0
28.542,-28.648,0
28.074,-28.851,0
27.533,-29.243,0
26.999,-29.876,0
27.749,-30.645,0
28.107,-30.546,0
28.291,-30.226,0
28.848,-30.07,0
29.018,-29.744,0
29.325,-29.257,0
28.978,-28.956,0
</coordinates>
</LinearRing>
</innerBoundaryIs>
</Polygon>
</Placemark>
</kml>"""
k = kml.KML() k = kml.KML()
k.from_string(doc) k.from_string(doc)
self.assertEqual(len(list(k.features())),1) self.assertEqual(len(list(k.features())), 1)
self.assertTrue(isinstance( self.assertTrue(
list(k.features())[0].geometry, Polygon)) isinstance(list(k.features())[0].geometry, Polygon)
)
k2 = kml.KML() k2 = kml.KML()
k2.from_string(k.to_string()) k2.from_string(k.to_string())
self.assertEqual(k.to_string(), k2.to_string()) self.assertEqual(k.to_string(), k2.to_string())
def test_multipoints(self): def test_multipoints(self):
doc="""<kml xmlns="http://www.opengis.net/kml/2.2"> doc = """<kml xmlns="http://www.opengis.net/kml/2.2">
<Placemark id="feat_2"> <Placemark id="feat_2">
<name>MultiPoint</name> <name>MultiPoint</name>
<styleUrl>#stylesel_9</styleUrl> <styleUrl>#stylesel_9</styleUrl>
...@@ -550,18 +648,17 @@ class KmlFromStringTestCase( unittest.TestCase ): ...@@ -550,18 +648,17 @@ class KmlFromStringTestCase( unittest.TestCase ):
</Placemark></kml>""" </Placemark></kml>"""
k = kml.KML() k = kml.KML()
k.from_string(doc) k.from_string(doc)
self.assertEqual(len(list(k.features())),1) self.assertEqual(len(list(k.features())), 1)
self.assertTrue(isinstance( self.assertTrue(
list(k.features())[0].geometry, MultiPoint)) isinstance(list(k.features())[0].geometry, MultiPoint)
)
self.assertEqual(len(list(k.features())[0].geometry.geoms), 12) self.assertEqual(len(list(k.features())[0].geometry.geoms), 12)
k2 = kml.KML() k2 = kml.KML()
k2.from_string(k.to_string()) k2.from_string(k.to_string())
self.assertEqual(k.to_string(), k2.to_string()) self.assertEqual(k.to_string(), k2.to_string())
def test_multilinestrings(self): def test_multilinestrings(self):
doc="""<kml xmlns="http://www.opengis.net/kml/2.2"> doc = """<kml xmlns="http://www.opengis.net/kml/2.2">
<Placemark> <Placemark>
<name>Dnipro (Dnieper)</name> <name>Dnipro (Dnieper)</name>
<MultiGeometry> <MultiGeometry>
...@@ -573,15 +670,15 @@ class KmlFromStringTestCase( unittest.TestCase ): ...@@ -573,15 +670,15 @@ class KmlFromStringTestCase( unittest.TestCase ):
</Placemark> </kml>""" </Placemark> </kml>"""
k = kml.KML() k = kml.KML()
k.from_string(doc) k.from_string(doc)
self.assertEqual(len(list(k.features())),1) self.assertEqual(len(list(k.features())), 1)
self.assertTrue(isinstance( self.assertTrue(
list(k.features())[0].geometry, MultiLineString)) isinstance(list(k.features())[0].geometry, MultiLineString)
)
self.assertEqual(len(list(k.features())[0].geometry.geoms), 4) self.assertEqual(len(list(k.features())[0].geometry.geoms), 4)
k2 = kml.KML() k2 = kml.KML()
k2.from_string(k.to_string()) k2.from_string(k.to_string())
self.assertEqual(k.to_string(), k2.to_string()) self.assertEqual(k.to_string(), k2.to_string())
def test_multipolygon(self): def test_multipolygon(self):
doc = """<kml xmlns="http://www.opengis.net/kml/2.2"> doc = """<kml xmlns="http://www.opengis.net/kml/2.2">
<Placemark> <Placemark>
...@@ -590,9 +687,10 @@ class KmlFromStringTestCase( unittest.TestCase ): ...@@ -590,9 +687,10 @@ class KmlFromStringTestCase( unittest.TestCase ):
</Placemark> </kml>""" </Placemark> </kml>"""
k = kml.KML() k = kml.KML()
k.from_string(doc) k.from_string(doc)
self.assertEqual(len(list(k.features())),1) self.assertEqual(len(list(k.features())), 1)
self.assertTrue(isinstance( self.assertTrue(
list(k.features())[0].geometry, MultiPolygon)) isinstance(list(k.features())[0].geometry, MultiPolygon)
)
k2 = kml.KML() k2 = kml.KML()
k2.from_string(k.to_string()) k2.from_string(k.to_string())
self.assertEqual(k.to_string(), k2.to_string()) self.assertEqual(k.to_string(), k2.to_string())
...@@ -665,7 +763,6 @@ class KmlFromStringTestCase( unittest.TestCase ): ...@@ -665,7 +763,6 @@ class KmlFromStringTestCase( unittest.TestCase ):
self.assertEqual(sd1.schema_url, '#TrailHeadTypeId') self.assertEqual(sd1.schema_url, '#TrailHeadTypeId')
self.assertEqual(sd.to_string(), sd1.to_string()) self.assertEqual(sd.to_string(), sd1.to_string())
def test_snippet(self): def test_snippet(self):
doc = """<kml xmlns="http://www.opengis.net/kml/2.2"> doc = """<kml xmlns="http://www.opengis.net/kml/2.2">
<Placemark> <Placemark>
...@@ -690,8 +787,7 @@ class KmlFromStringTestCase( unittest.TestCase ): ...@@ -690,8 +787,7 @@ class KmlFromStringTestCase( unittest.TestCase ):
self.assertRaises(TypeError, doc.from_string, '<xml></xml>') self.assertRaises(TypeError, doc.from_string, '<xml></xml>')
class StyleTestCase( unittest.TestCase ): class StyleTestCase(unittest.TestCase):
def test_styleurl(self): def test_styleurl(self):
f = kml.Document() f = kml.Document()
f.styleUrl = '#somestyle' f.styleUrl = '#somestyle'
...@@ -707,8 +803,8 @@ class StyleTestCase( unittest.TestCase ): ...@@ -707,8 +803,8 @@ class StyleTestCase( unittest.TestCase ):
def test_style(self): def test_style(self):
lstyle = styles.LineStyle(color='red', width=2.0) lstyle = styles.LineStyle(color='red', width=2.0)
style = styles.Style(styles = [lstyle]) style = styles.Style(styles=[lstyle])
f = kml.Document(styles = [style]) f = kml.Document(styles=[style])
f2 = kml.Document() f2 = kml.Document()
f2.from_string(f.to_string(prettyprint=True)) f2.from_string(f.to_string(prettyprint=True))
self.assertEqual(f.to_string(), f2.to_string()) self.assertEqual(f.to_string(), f2.to_string())
...@@ -769,8 +865,7 @@ class StyleUsageTestCase(unittest.TestCase): ...@@ -769,8 +865,7 @@ class StyleUsageTestCase(unittest.TestCase):
self.assertEqual(place.to_string(), place3.to_string()) self.assertEqual(place.to_string(), place3.to_string())
class StyleFromStringTestCase( unittest.TestCase ): class StyleFromStringTestCase(unittest.TestCase):
def test_styleurl(self): def test_styleurl(self):
doc = """<kml xmlns="http://www.opengis.net/kml/2.2"> doc = """<kml xmlns="http://www.opengis.net/kml/2.2">
<Document> <Document>
...@@ -781,13 +876,12 @@ class StyleFromStringTestCase( unittest.TestCase ): ...@@ -781,13 +876,12 @@ class StyleFromStringTestCase( unittest.TestCase ):
</kml>""" </kml>"""
k = kml.KML() k = kml.KML()
k.from_string(doc) k.from_string(doc)
self.assertEqual(len(list(k.features())),1) self.assertEqual(len(list(k.features())), 1)
self.assertEqual(list(k.features())[0].styleUrl, '#default') self.assertEqual(list(k.features())[0].styleUrl, '#default')
k2 = kml.KML() k2 = kml.KML()
k2.from_string(k.to_string()) k2.from_string(k.to_string())
self.assertEqual(k.to_string(), k2.to_string()) self.assertEqual(k.to_string(), k2.to_string())
def test_balloonstyle(self): def test_balloonstyle(self):
doc = """<kml xmlns="http://www.opengis.net/kml/2.2"> doc = """<kml xmlns="http://www.opengis.net/kml/2.2">
<Document> <Document>
...@@ -816,9 +910,10 @@ class StyleFromStringTestCase( unittest.TestCase ): ...@@ -816,9 +910,10 @@ class StyleFromStringTestCase( unittest.TestCase ):
</kml>""" </kml>"""
k = kml.KML() k = kml.KML()
k.from_string(doc) k.from_string(doc)
self.assertEqual(len(list(k.features())),1) self.assertEqual(len(list(k.features())), 1)
self.assertTrue(isinstance( self.assertTrue(
list(list(k.features())[0].styles())[0], styles.Style)) isinstance(list(list(k.features())[0].styles())[0], styles.Style)
)
style = list(list(list(k.features())[0].styles())[0].styles())[0] style = list(list(list(k.features())[0].styles())[0].styles())[0]
self.assertTrue(isinstance(style, styles.BalloonStyle)) self.assertTrue(isinstance(style, styles.BalloonStyle))
self.assertEqual(style.bgColor, 'ffffffbb') self.assertEqual(style.bgColor, 'ffffffbb')
...@@ -844,9 +939,10 @@ class StyleFromStringTestCase( unittest.TestCase ): ...@@ -844,9 +939,10 @@ class StyleFromStringTestCase( unittest.TestCase ):
</kml>""" </kml>"""
k = kml.KML() k = kml.KML()
k.from_string(doc) k.from_string(doc)
self.assertEqual(len(list(k.features())),1) self.assertEqual(len(list(k.features())), 1)
self.assertTrue(isinstance( self.assertTrue(
list(list(k.features())[0].styles())[0], styles.Style)) isinstance(list(list(k.features())[0].styles())[0], styles.Style)
)
style = list(list(list(k.features())[0].styles())[0].styles())[0] style = list(list(list(k.features())[0].styles())[0].styles())[0]
self.assertTrue(isinstance(style, styles.LabelStyle)) self.assertTrue(isinstance(style, styles.LabelStyle))
self.assertEqual(style.color, 'ff0000cc') self.assertEqual(style.color, 'ff0000cc')
...@@ -855,7 +951,6 @@ class StyleFromStringTestCase( unittest.TestCase ): ...@@ -855,7 +951,6 @@ class StyleFromStringTestCase( unittest.TestCase ):
k2.from_string(k.to_string()) k2.from_string(k.to_string())
self.assertEqual(k.to_string(), k2.to_string()) self.assertEqual(k.to_string(), k2.to_string())
def test_iconstyle(self): def test_iconstyle(self):
doc = """<kml xmlns="http://www.opengis.net/kml/2.2"> doc = """<kml xmlns="http://www.opengis.net/kml/2.2">
<Document> <Document>
...@@ -874,9 +969,10 @@ class StyleFromStringTestCase( unittest.TestCase ): ...@@ -874,9 +969,10 @@ class StyleFromStringTestCase( unittest.TestCase ):
</kml>""" </kml>"""
k = kml.KML() k = kml.KML()
k.from_string(doc) k.from_string(doc)
self.assertEqual(len(list((k.features()))),1) self.assertEqual(len(list((k.features()))), 1)
self.assertTrue(isinstance( self.assertTrue(
list(list(k.features())[0].styles())[0], styles.Style)) isinstance(list(list(k.features())[0].styles())[0], styles.Style)
)
style = list(list(list(k.features())[0].styles())[0].styles())[0] style = list(list(list(k.features())[0].styles())[0].styles())[0]
self.assertTrue(isinstance(style, styles.IconStyle)) self.assertTrue(isinstance(style, styles.IconStyle))
self.assertEqual(style.color, 'ff00ff00') self.assertEqual(style.color, 'ff00ff00')
...@@ -888,9 +984,8 @@ class StyleFromStringTestCase( unittest.TestCase ): ...@@ -888,9 +984,8 @@ class StyleFromStringTestCase( unittest.TestCase ):
k2.from_string(k.to_string()) k2.from_string(k.to_string())
self.assertEqual(k.to_string(), k2.to_string()) self.assertEqual(k.to_string(), k2.to_string())
def test_linestyle(self): def test_linestyle(self):
doc="""<kml xmlns="http://www.opengis.net/kml/2.2"> doc = """<kml xmlns="http://www.opengis.net/kml/2.2">
<Document> <Document>
<name>LineStyle.kml</name> <name>LineStyle.kml</name>
<open>1</open> <open>1</open>
...@@ -904,9 +999,10 @@ class StyleFromStringTestCase( unittest.TestCase ): ...@@ -904,9 +999,10 @@ class StyleFromStringTestCase( unittest.TestCase ):
</kml>""" </kml>"""
k = kml.KML() k = kml.KML()
k.from_string(doc) k.from_string(doc)
self.assertEqual(len(list(k.features())),1) self.assertEqual(len(list(k.features())), 1)
self.assertTrue(isinstance( self.assertTrue(
list(list(k.features())[0].styles())[0], styles.Style)) isinstance(list(list(k.features())[0].styles())[0], styles.Style)
)
style = list(list(list(k.features())[0].styles())[0].styles())[0] style = list(list(list(k.features())[0].styles())[0].styles())[0]
self.assertTrue(isinstance(style, styles.LineStyle)) self.assertTrue(isinstance(style, styles.LineStyle))
self.assertEqual(style.color, '7f0000ff') self.assertEqual(style.color, '7f0000ff')
...@@ -915,9 +1011,8 @@ class StyleFromStringTestCase( unittest.TestCase ): ...@@ -915,9 +1011,8 @@ class StyleFromStringTestCase( unittest.TestCase ):
k2.from_string(k.to_string()) k2.from_string(k.to_string())
self.assertEqual(k.to_string(), k2.to_string()) self.assertEqual(k.to_string(), k2.to_string())
def test_polystyle(self): def test_polystyle(self):
doc="""<kml xmlns="http://www.opengis.net/kml/2.2"> doc = """<kml xmlns="http://www.opengis.net/kml/2.2">
<Document> <Document>
<name>PolygonStyle.kml</name> <name>PolygonStyle.kml</name>
<open>1</open> <open>1</open>
...@@ -929,12 +1024,13 @@ class StyleFromStringTestCase( unittest.TestCase ): ...@@ -929,12 +1024,13 @@ class StyleFromStringTestCase( unittest.TestCase ):
</Style> </Style>
</Document> </Document>
</kml>""" </kml>"""
#XXX fill and outline # XXX fill and outline
k = kml.KML() k = kml.KML()
k.from_string(doc) k.from_string(doc)
self.assertEqual(len(list(k.features())),1) self.assertEqual(len(list(k.features())), 1)
self.assertTrue(isinstance( self.assertTrue(
list(list(k.features())[0].styles())[0], styles.Style)) isinstance(list(list(k.features())[0].styles())[0], styles.Style)
)
style = list(list(list(k.features())[0].styles())[0].styles())[0] style = list(list(list(k.features())[0].styles())[0].styles())[0]
self.assertTrue(isinstance(style, styles.PolyStyle)) self.assertTrue(isinstance(style, styles.PolyStyle))
self.assertEqual(style.color, 'ff0000cc') self.assertEqual(style.color, 'ff0000cc')
...@@ -943,9 +1039,8 @@ class StyleFromStringTestCase( unittest.TestCase ): ...@@ -943,9 +1039,8 @@ class StyleFromStringTestCase( unittest.TestCase ):
k2.from_string(k.to_string()) k2.from_string(k.to_string())
self.assertEqual(k.to_string(), k2.to_string()) self.assertEqual(k.to_string(), k2.to_string())
def test_styles(self): def test_styles(self):
doc="""<kml xmlns="http://www.opengis.net/kml/2.2"> doc = """<kml xmlns="http://www.opengis.net/kml/2.2">
<Document> <Document>
<!-- Begin Style Definitions --> <!-- Begin Style Definitions -->
<Style id="myDefaultStyles"> <Style id="myDefaultStyles">
...@@ -974,9 +1069,10 @@ class StyleFromStringTestCase( unittest.TestCase ): ...@@ -974,9 +1069,10 @@ class StyleFromStringTestCase( unittest.TestCase ):
</kml>""" </kml>"""
k = kml.KML() k = kml.KML()
k.from_string(doc) k.from_string(doc)
self.assertEqual(len(list(k.features())),1) self.assertEqual(len(list(k.features())), 1)
self.assertTrue(isinstance( self.assertTrue(
list(list(k.features())[0].styles())[0], styles.Style)) isinstance(list(list(k.features())[0].styles())[0], styles.Style)
)
style = list(list(list(k.features())[0].styles())[0].styles()) style = list(list(list(k.features())[0].styles())[0].styles())
self.assertEqual(len(style), 4) self.assertEqual(len(style), 4)
k2 = kml.KML() k2 = kml.KML()
...@@ -984,7 +1080,7 @@ class StyleFromStringTestCase( unittest.TestCase ): ...@@ -984,7 +1080,7 @@ class StyleFromStringTestCase( unittest.TestCase ):
self.assertEqual(k.to_string(), k2.to_string()) self.assertEqual(k.to_string(), k2.to_string())
def test_stylemapurl(self): def test_stylemapurl(self):
doc= """<kml xmlns="http://www.opengis.net/kml/2.2"> doc = """<kml xmlns="http://www.opengis.net/kml/2.2">
<Document> <Document>
<StyleMap id="styleMapExample"> <StyleMap id="styleMapExample">
<Pair> <Pair>
...@@ -1000,21 +1096,21 @@ class StyleFromStringTestCase( unittest.TestCase ): ...@@ -1000,21 +1096,21 @@ class StyleFromStringTestCase( unittest.TestCase ):
</kml>""" </kml>"""
k = kml.KML() k = kml.KML()
k.from_string(doc) k.from_string(doc)
self.assertEqual(len(list(k.features())),1) self.assertEqual(len(list(k.features())), 1)
self.assertTrue(isinstance( self.assertTrue(
list(list(k.features())[0].styles())[0], styles.StyleMap)) isinstance(list(list(k.features())[0].styles())[0], styles.StyleMap)
)
sm = list(list(list(k.features())[0].styles()))[0] sm = list(list(list(k.features())[0].styles()))[0]
self.assertTrue(isinstance(sm.normal, styles.StyleUrl)) self.assertTrue(isinstance(sm.normal, styles.StyleUrl))
self.assertEqual(sm.normal.url, '#normalState') self.assertEqual(sm.normal.url, '#normalState')
self.assertTrue(isinstance(sm.highlight, styles.StyleUrl)) self.assertTrue(isinstance(sm.highlight, styles.StyleUrl))
self.assertEqual(sm.highlight.url, '#highlightState') self.assertEqual(sm.highlight.url, '#highlightState')
k2 = kml.KML() k2 = kml.KML()
ks = k.to_string()
k2.from_string(k.to_string()) k2.from_string(k.to_string())
self.assertEqual(k.to_string(), k2.to_string()) self.assertEqual(k.to_string(), k2.to_string())
def test_stylemapstyles(self): def test_stylemapstyles(self):
doc= """<kml xmlns="http://www.opengis.net/kml/2.2"> doc = """<kml xmlns="http://www.opengis.net/kml/2.2">
<Document> <Document>
<StyleMap id="styleMapExample"> <StyleMap id="styleMapExample">
<Pair> <Pair>
...@@ -1043,9 +1139,10 @@ class StyleFromStringTestCase( unittest.TestCase ): ...@@ -1043,9 +1139,10 @@ class StyleFromStringTestCase( unittest.TestCase ):
</kml>""" </kml>"""
k = kml.KML() k = kml.KML()
k.from_string(doc) k.from_string(doc)
self.assertEqual(len(list(k.features())),1) self.assertEqual(len(list(k.features())), 1)
self.assertTrue(isinstance( self.assertTrue(
list(list(k.features())[0].styles())[0], styles.StyleMap)) isinstance(list(list(k.features())[0].styles())[0], styles.StyleMap)
)
sm = list(list(list(k.features())[0].styles()))[0] sm = list(list(list(k.features())[0].styles()))[0]
self.assertTrue(isinstance(sm.normal, styles.Style)) self.assertTrue(isinstance(sm.normal, styles.Style))
self.assertEqual(len(list(sm.normal.styles())), 1) self.assertEqual(len(list(sm.normal.styles())), 1)
...@@ -1089,7 +1186,7 @@ class StyleFromStringTestCase( unittest.TestCase ): ...@@ -1089,7 +1186,7 @@ class StyleFromStringTestCase( unittest.TestCase ):
</kml>""" </kml>"""
k = kml.KML() k = kml.KML()
k.from_string(doc) k.from_string(doc)
self.assertEqual(len(list(k.features())),1) self.assertEqual(len(list(k.features())), 1)
document = list(k.features())[0] document = list(k.features())[0]
style = document.get_style_by_url('http://localhost:8080/somepath#exampleStyleDocument') style = document.get_style_by_url('http://localhost:8080/somepath#exampleStyleDocument')
self.assertTrue(isinstance(list(style.styles())[0], styles.LabelStyle)) self.assertTrue(isinstance(list(style.styles())[0], styles.LabelStyle))
...@@ -1099,8 +1196,7 @@ class StyleFromStringTestCase( unittest.TestCase ): ...@@ -1099,8 +1196,7 @@ class StyleFromStringTestCase( unittest.TestCase ):
self.assertTrue(isinstance(style, styles.StyleMap)) self.assertTrue(isinstance(style, styles.StyleMap))
class DateTimeTestCase(unittest.TestCase):
class DateTimeTestCase( unittest.TestCase ):
def test_timestamp(self): def test_timestamp(self):
now = datetime.datetime.now() now = datetime.datetime.now()
...@@ -1109,12 +1205,11 @@ class DateTimeTestCase( unittest.TestCase ): ...@@ -1109,12 +1205,11 @@ class DateTimeTestCase( unittest.TestCase ):
self.assertTrue('TimeStamp>' in str(ts.to_string())) self.assertTrue('TimeStamp>' in str(ts.to_string()))
self.assertTrue('when>' in str(ts.to_string())) self.assertTrue('when>' in str(ts.to_string()))
self.assertTrue(now.isoformat() in str(ts.to_string())) self.assertTrue(now.isoformat() in str(ts.to_string()))
y2k = datetime.date(2000,1,1) y2k = datetime.date(2000, 1, 1)
ts = kml.TimeStamp(timestamp=y2k) ts = kml.TimeStamp(timestamp=y2k)
self.assertEqual(ts.timestamp, [y2k, 'date']) self.assertEqual(ts.timestamp, [y2k, 'date'])
self.assertTrue('2000-01-01' in str(ts.to_string())) self.assertTrue('2000-01-01' in str(ts.to_string()))
def test_timestamp_resolution(self): def test_timestamp_resolution(self):
now = datetime.datetime.now() now = datetime.datetime.now()
ts = kml.TimeStamp(timestamp=now) ts = kml.TimeStamp(timestamp=now)
...@@ -1133,10 +1228,9 @@ class DateTimeTestCase( unittest.TestCase ): ...@@ -1133,10 +1228,9 @@ class DateTimeTestCase( unittest.TestCase ):
ts.timestamp = None ts.timestamp = None
self.assertRaises(TypeError, ts.to_string) self.assertRaises(TypeError, ts.to_string)
def test_timespan(self): def test_timespan(self):
now = datetime.datetime.now() now = datetime.datetime.now()
y2k = datetime.datetime(2000,1,1) y2k = datetime.datetime(2000, 1, 1)
ts = kml.TimeSpan(end=now, begin=y2k) ts = kml.TimeSpan(end=now, begin=y2k)
self.assertEqual(ts.end, [now, 'dateTime']) self.assertEqual(ts.end, [now, 'dateTime'])
self.assertEqual(ts.begin, [y2k, 'dateTime']) self.assertEqual(ts.begin, [y2k, 'dateTime'])
...@@ -1151,7 +1245,6 @@ class DateTimeTestCase( unittest.TestCase ): ...@@ -1151,7 +1245,6 @@ class DateTimeTestCase( unittest.TestCase ):
ts.begin = None ts.begin = None
self.assertRaises(ValueError, ts.to_string) self.assertRaises(ValueError, ts.to_string)
def test_feature_timestamp(self): def test_feature_timestamp(self):
now = datetime.datetime.now() now = datetime.datetime.now()
f = kml.Document() f = kml.Document()
...@@ -1168,7 +1261,7 @@ class DateTimeTestCase( unittest.TestCase ): ...@@ -1168,7 +1261,7 @@ class DateTimeTestCase( unittest.TestCase ):
def test_feature_timespan(self): def test_feature_timespan(self):
now = datetime.datetime.now() now = datetime.datetime.now()
y2k = datetime.date(2000,1,1) y2k = datetime.date(2000, 1, 1)
f = kml.Document() f = kml.Document()
f.begin = y2k f.begin = y2k
f.end = now f.end = now
...@@ -1190,7 +1283,7 @@ class DateTimeTestCase( unittest.TestCase ): ...@@ -1190,7 +1283,7 @@ class DateTimeTestCase( unittest.TestCase ):
def test_feature_timespan_stamp(self): def test_feature_timespan_stamp(self):
now = datetime.datetime.now() now = datetime.datetime.now()
y2k = datetime.date(2000,1,1) y2k = datetime.date(2000, 1, 1)
f = kml.Document() f = kml.Document()
f.begin = y2k f.begin = y2k
f.end = now f.end = now
...@@ -1219,7 +1312,7 @@ class DateTimeTestCase( unittest.TestCase ): ...@@ -1219,7 +1312,7 @@ class DateTimeTestCase( unittest.TestCase ):
self.assertTrue('end>' in str(f.to_string())) self.assertTrue('end>' in str(f.to_string()))
self.assertFalse('TimeStamp>' in str(f.to_string())) self.assertFalse('TimeStamp>' in str(f.to_string()))
self.assertFalse('when>' in str(f.to_string())) self.assertFalse('when>' in str(f.to_string()))
#We manipulate our Feature so it has timespan and stamp # We manipulate our Feature so it has timespan and stamp
ts = kml.TimeStamp(timestamp=now) ts = kml.TimeStamp(timestamp=now)
f._time_stamp = ts f._time_stamp = ts
# this raises an exception as only either timespan or timestamp # this raises an exception as only either timespan or timestamp
...@@ -1228,7 +1321,7 @@ class DateTimeTestCase( unittest.TestCase ): ...@@ -1228,7 +1321,7 @@ class DateTimeTestCase( unittest.TestCase ):
def test_read_timestamp(self): def test_read_timestamp(self):
ts = kml.TimeStamp(ns='') ts = kml.TimeStamp(ns='')
doc =""" doc = """
<TimeStamp> <TimeStamp>
<when>1997</when> <when>1997</when>
</TimeStamp> </TimeStamp>
...@@ -1236,7 +1329,7 @@ class DateTimeTestCase( unittest.TestCase ): ...@@ -1236,7 +1329,7 @@ class DateTimeTestCase( unittest.TestCase ):
ts.from_string(doc) ts.from_string(doc)
self.assertEqual(ts.timestamp[1], 'gYear') self.assertEqual(ts.timestamp[1], 'gYear')
self.assertEqual(ts.timestamp[0], datetime.datetime(1997, 1, 1, 0, 0)) self.assertEqual(ts.timestamp[0], datetime.datetime(1997, 1, 1, 0, 0))
doc =""" doc = """
<TimeStamp> <TimeStamp>
<when>1997-07</when> <when>1997-07</when>
</TimeStamp> </TimeStamp>
...@@ -1244,7 +1337,7 @@ class DateTimeTestCase( unittest.TestCase ): ...@@ -1244,7 +1337,7 @@ class DateTimeTestCase( unittest.TestCase ):
ts.from_string(doc) ts.from_string(doc)
self.assertEqual(ts.timestamp[1], 'gYearMonth') self.assertEqual(ts.timestamp[1], 'gYearMonth')
self.assertEqual(ts.timestamp[0], datetime.datetime(1997, 7, 1, 0, 0)) self.assertEqual(ts.timestamp[0], datetime.datetime(1997, 7, 1, 0, 0))
doc =""" doc = """
<TimeStamp> <TimeStamp>
<when>199808</when> <when>199808</when>
</TimeStamp> </TimeStamp>
...@@ -1252,7 +1345,7 @@ class DateTimeTestCase( unittest.TestCase ): ...@@ -1252,7 +1345,7 @@ class DateTimeTestCase( unittest.TestCase ):
ts.from_string(doc) ts.from_string(doc)
self.assertEqual(ts.timestamp[1], 'gYearMonth') self.assertEqual(ts.timestamp[1], 'gYearMonth')
self.assertEqual(ts.timestamp[0], datetime.datetime(1998, 8, 1, 0, 0)) self.assertEqual(ts.timestamp[0], datetime.datetime(1998, 8, 1, 0, 0))
doc =""" doc = """
<TimeStamp> <TimeStamp>
<when>1997-07-16</when> <when>1997-07-16</when>
</TimeStamp> </TimeStamp>
...@@ -1260,9 +1353,9 @@ class DateTimeTestCase( unittest.TestCase ): ...@@ -1260,9 +1353,9 @@ class DateTimeTestCase( unittest.TestCase ):
ts.from_string(doc) ts.from_string(doc)
self.assertEqual(ts.timestamp[1], 'date') self.assertEqual(ts.timestamp[1], 'date')
self.assertEqual(ts.timestamp[0], datetime.datetime(1997, 7, 16, 0, 0)) self.assertEqual(ts.timestamp[0], datetime.datetime(1997, 7, 16, 0, 0))
#dateTime (YYYY-MM-DDThh:mm:ssZ) # dateTime (YYYY-MM-DDThh:mm:ssZ)
#Here, T is the separator between the calendar and the hourly notation of time, and Z indicates UTC. (Seconds are required.) # Here, T is the separator between the calendar and the hourly notation of time, and Z indicates UTC. (Seconds are required.)
doc =""" doc = """
<TimeStamp> <TimeStamp>
<when>1997-07-16T07:30:15Z</when> <when>1997-07-16T07:30:15Z</when>
</TimeStamp> </TimeStamp>
...@@ -1270,7 +1363,7 @@ class DateTimeTestCase( unittest.TestCase ): ...@@ -1270,7 +1363,7 @@ class DateTimeTestCase( unittest.TestCase ):
ts.from_string(doc) ts.from_string(doc)
self.assertEqual(ts.timestamp[1], 'dateTime') self.assertEqual(ts.timestamp[1], 'dateTime')
self.assertEqual(ts.timestamp[0], datetime.datetime(1997, 7, 16, 7, 30, 15, tzinfo=tzutc())) self.assertEqual(ts.timestamp[0], datetime.datetime(1997, 7, 16, 7, 30, 15, tzinfo=tzutc()))
doc =""" doc = """
<TimeStamp> <TimeStamp>
<when>1997-07-16T10:30:15+03:00</when> <when>1997-07-16T10:30:15+03:00</when>
</TimeStamp> </TimeStamp>
...@@ -1294,8 +1387,8 @@ class DateTimeTestCase( unittest.TestCase ): ...@@ -1294,8 +1387,8 @@ class DateTimeTestCase( unittest.TestCase ):
self.assertEqual(ts.end[0], datetime.datetime(1997, 7, 16, 7, 30, 15, tzinfo=tzutc())) self.assertEqual(ts.end[0], datetime.datetime(1997, 7, 16, 7, 30, 15, tzinfo=tzutc()))
def test_featurefromstring(self): def test_featurefromstring(self):
d=kml.Document(ns='') d = kml.Document(ns='')
doc="""<Document> doc = """<Document>
<name>Document.kml</name> <name>Document.kml</name>
<open>1</open> <open>1</open>
<TimeStamp> <TimeStamp>
...@@ -1309,9 +1402,7 @@ class DateTimeTestCase( unittest.TestCase ): ...@@ -1309,9 +1402,7 @@ class DateTimeTestCase( unittest.TestCase ):
d.from_string(doc) d.from_string(doc)
class AtomTestCase(unittest.TestCase):
class AtomTestCase( unittest.TestCase ):
def test_author(self): def test_author(self):
a = atom.Author(name="Christian Ledermann") a = atom.Author(name="Christian Ledermann")
self.assertEqual(a.name, "Christian Ledermann") self.assertEqual(a.name, "Christian Ledermann")
...@@ -1323,7 +1414,7 @@ class AtomTestCase( unittest.TestCase ): ...@@ -1323,7 +1414,7 @@ class AtomTestCase( unittest.TestCase ):
self.assertTrue('name>' in str(a.to_string())) self.assertTrue('name>' in str(a.to_string()))
self.assertTrue('uri>' in str(a.to_string())) self.assertTrue('uri>' in str(a.to_string()))
self.assertTrue('email>' in str(a.to_string())) self.assertTrue('email>' in str(a.to_string()))
#print (a.to_string()) # print (a.to_string())
a.email = 'christian' a.email = 'christian'
self.assertFalse('email>' in str(a.to_string())) self.assertFalse('email>' in str(a.to_string()))
a2 = atom.Author() a2 = atom.Author()
...@@ -1334,10 +1425,10 @@ class AtomTestCase( unittest.TestCase ): ...@@ -1334,10 +1425,10 @@ class AtomTestCase( unittest.TestCase ):
l = atom.Link(href="http://localhost/", rel="alternate") l = atom.Link(href="http://localhost/", rel="alternate")
self.assertEqual(l.href, "http://localhost/") self.assertEqual(l.href, "http://localhost/")
self.assertEqual(l.rel, "alternate") self.assertEqual(l.rel, "alternate")
l.title="Title" l.title = "Title"
l.type="text/html" l.type = "text/html"
l.hreflang ='en' l.hreflang = 'en'
l.length="4096" l.length = "4096"
self.assertTrue('href="http://localhost/"' in str(l.to_string())) self.assertTrue('href="http://localhost/"' in str(l.to_string()))
self.assertTrue('rel="alternate"' in str(l.to_string())) self.assertTrue('rel="alternate"' in str(l.to_string()))
self.assertTrue('title="Title"' in str(l.to_string())) self.assertTrue('title="Title"' in str(l.to_string()))
...@@ -1352,12 +1443,12 @@ class AtomTestCase( unittest.TestCase ): ...@@ -1352,12 +1443,12 @@ class AtomTestCase( unittest.TestCase ):
l.href = None l.href = None
self.assertRaises(ValueError, l.to_string) self.assertRaises(ValueError, l.to_string)
class SetGeometryTestCase( unittest.TestCase ):
class SetGeometryTestCase(unittest.TestCase):
def test_altitude_mode(self): def test_altitude_mode(self):
geom=Geometry() geom = Geometry()
geom.geometry = Point(0,1) geom.geometry = Point(0, 1)
self.assertEqual(geom.altitude_mode , None) self.assertEqual(geom.altitude_mode, None)
self.assertFalse('altitudeMode' in str(geom.to_string())) self.assertFalse('altitudeMode' in str(geom.to_string()))
geom.altitude_mode = 'unknown' geom.altitude_mode = 'unknown'
self.assertRaises(AssertionError, geom.to_string) self.assertRaises(AssertionError, geom.to_string)
...@@ -1373,12 +1464,12 @@ class SetGeometryTestCase( unittest.TestCase ): ...@@ -1373,12 +1464,12 @@ class SetGeometryTestCase( unittest.TestCase ):
self.assertTrue('altitudeMode>absolute</' in str(geom.to_string())) self.assertTrue('altitudeMode>absolute</' in str(geom.to_string()))
def test_extrude(self): def test_extrude(self):
geom=Geometry() geom = Geometry()
self.assertEqual(geom.extrude , False) self.assertEqual(geom.extrude, False)
geom.geometry = Point(0,1) geom.geometry = Point(0, 1)
geom.extrude=False geom.extrude = False
self.assertFalse('extrude' in str(geom.to_string())) self.assertFalse('extrude' in str(geom.to_string()))
geom.extrude=True geom.extrude = True
geom.altitude_mode = 'clampToGround' geom.altitude_mode = 'clampToGround'
self.assertFalse('extrude' in str(geom.to_string())) self.assertFalse('extrude' in str(geom.to_string()))
geom.altitude_mode = 'relativeToGround' geom.altitude_mode = 'relativeToGround'
...@@ -1387,9 +1478,9 @@ class SetGeometryTestCase( unittest.TestCase ): ...@@ -1387,9 +1478,9 @@ class SetGeometryTestCase( unittest.TestCase ):
self.assertTrue('extrude>1</' in str(geom.to_string())) self.assertTrue('extrude>1</' in str(geom.to_string()))
def test_tesselate(self): def test_tesselate(self):
geom=Geometry() geom = Geometry()
self.assertEqual(geom.tessellate , False) self.assertEqual(geom.tessellate, False)
geom.geometry = LineString([(0,0), (1,1)]) geom.geometry = LineString([(0, 0), (1, 1)])
self.assertFalse('tessellate' in str(geom.to_string())) self.assertFalse('tessellate' in str(geom.to_string()))
geom.altitude_mode = 'clampToGround' geom.altitude_mode = 'clampToGround'
self.assertFalse('tessellate' in str(geom.to_string())) self.assertFalse('tessellate' in str(geom.to_string()))
...@@ -1406,14 +1497,14 @@ class SetGeometryTestCase( unittest.TestCase ): ...@@ -1406,14 +1497,14 @@ class SetGeometryTestCase( unittest.TestCase ):
self.assertFalse('tessellate' in str(geom.to_string())) self.assertFalse('tessellate' in str(geom.to_string()))
geom.altitude_mode = 'clampToGround' geom.altitude_mode = 'clampToGround'
self.assertTrue('tessellate>1</' in str(geom.to_string())) self.assertTrue('tessellate>1</' in str(geom.to_string()))
#for geometries != LineString tesselate is ignored # for geometries != LineString tesselate is ignored
geom.geometry = Point(0,1) geom.geometry = Point(0, 1)
self.assertFalse('tessellate' in str(geom.to_string())) self.assertFalse('tessellate' in str(geom.to_string()))
geom.geometry = Polygon([(0,0), (1,0), (1,1), (0,0)]) geom.geometry = Polygon([(0, 0), (1, 0), (1, 1), (0, 0)])
self.assertFalse('tessellate' in str(geom.to_string())) self.assertFalse('tessellate' in str(geom.to_string()))
def testPoint(self): def testPoint(self):
p = Point(0,1) p = Point(0, 1)
g = Geometry(geometry=p) g = Geometry(geometry=p)
self.assertEqual(g.geometry, p) self.assertEqual(g.geometry, p)
g = Geometry(geometry=p.__geo_interface__) g = Geometry(geometry=p.__geo_interface__)
...@@ -1422,7 +1513,7 @@ class SetGeometryTestCase( unittest.TestCase ): ...@@ -1422,7 +1513,7 @@ class SetGeometryTestCase( unittest.TestCase ):
self.assertTrue('coordinates>0.000000,1.000000</' in str(g.to_string())) self.assertTrue('coordinates>0.000000,1.000000</' in str(g.to_string()))
def testLineString(self): def testLineString(self):
l = LineString([(0,0), (1,1)]) l = LineString([(0, 0), (1, 1)])
g = Geometry(geometry=l) g = Geometry(geometry=l)
self.assertEqual(g.geometry, l) self.assertEqual(g.geometry, l)
self.assertTrue('LineString' in str(g.to_string())) self.assertTrue('LineString' in str(g.to_string()))
...@@ -1432,7 +1523,7 @@ class SetGeometryTestCase( unittest.TestCase ): ...@@ -1432,7 +1523,7 @@ class SetGeometryTestCase( unittest.TestCase ):
self.assertEqual(g.to_string(), g2.to_string()) self.assertEqual(g.to_string(), g2.to_string())
def testLinearRing(self): def testLinearRing(self):
l = LinearRing([(0,0), (1,0), (1,1), (0,0)]) l = LinearRing([(0, 0), (1, 0), (1, 1), (0, 0)])
g = Geometry(geometry=l) g = Geometry(geometry=l)
self.assertEqual(g.geometry, l) self.assertEqual(g.geometry, l)
self.assertTrue('LinearRing' in str(g.to_string())) self.assertTrue('LinearRing' in str(g.to_string()))
...@@ -1441,8 +1532,8 @@ class SetGeometryTestCase( unittest.TestCase ): ...@@ -1441,8 +1532,8 @@ class SetGeometryTestCase( unittest.TestCase ):
in str(g.to_string())) in str(g.to_string()))
def testPolygon(self): def testPolygon(self):
#without holes # without holes
l = Polygon([(0,0), (1,0), (1,1), (0,0)]) l = Polygon([(0, 0), (1, 0), (1, 1), (0, 0)])
g = Geometry(geometry=l) g = Geometry(geometry=l)
self.assertEqual(g.geometry, l) self.assertEqual(g.geometry, l)
self.assertTrue('Polygon' in str(g.to_string())) self.assertTrue('Polygon' in str(g.to_string()))
...@@ -1452,8 +1543,11 @@ class SetGeometryTestCase( unittest.TestCase ): ...@@ -1452,8 +1543,11 @@ class SetGeometryTestCase( unittest.TestCase ):
self.assertTrue( self.assertTrue(
'coordinates>0.000000,0.000000 1.000000,0.000000 1.000000,1.000000 0.000000,0.000000</' 'coordinates>0.000000,0.000000 1.000000,0.000000 1.000000,1.000000 0.000000,0.000000</'
in str(g.to_string())) in str(g.to_string()))
#with holes # with holes
p = Polygon([(-1,-1), (2,-1), (2,2), (-1,-1)],[[(0,0), (1,0), (1,1), (0,0)]]) p = Polygon(
[(-1, -1), (2, -1), (2, 2), (-1, -1)],
[[(0, 0), (1, 0), (1, 1), (0, 0)]],
)
g = Geometry(geometry=p) g = Geometry(geometry=p)
self.assertEqual(g.geometry, p) self.assertEqual(g.geometry, p)
self.assertTrue('Polygon' in str(g.to_string())) self.assertTrue('Polygon' in str(g.to_string()))
...@@ -1468,29 +1562,32 @@ class SetGeometryTestCase( unittest.TestCase ): ...@@ -1468,29 +1562,32 @@ class SetGeometryTestCase( unittest.TestCase ):
in str(g.to_string())) in str(g.to_string()))
def testMultiPoint(self): def testMultiPoint(self):
p0 = Point(0,1) p0 = Point(0, 1)
p1 = Point(1,1) p1 = Point(1, 1)
g = Geometry(geometry=MultiPoint([p0,p1])) g = Geometry(geometry=MultiPoint([p0, p1]))
self.assertTrue('MultiGeometry' in str(g.to_string())) self.assertTrue('MultiGeometry' in str(g.to_string()))
self.assertTrue('Point' in str(g.to_string())) self.assertTrue('Point' in str(g.to_string()))
self.assertTrue('coordinates>0.000000,1.000000</' in str(g.to_string())) self.assertTrue('coordinates>0.000000,1.000000</' in str(g.to_string()))
self.assertTrue('coordinates>1.000000,1.000000</' in str(g.to_string())) self.assertTrue('coordinates>1.000000,1.000000</' in str(g.to_string()))
def testMultiLineString(self): def testMultiLineString(self):
l0 = LineString([(0,0), (1,0)]) l0 = LineString([(0, 0), (1, 0)])
l1 = LineString([(0,1), (1,1)]) l1 = LineString([(0, 1), (1, 1)])
g = Geometry(geometry=MultiLineString([l0,l1])) g = Geometry(geometry=MultiLineString([l0, l1]))
self.assertTrue('MultiGeometry' in str(g.to_string())) self.assertTrue('MultiGeometry' in str(g.to_string()))
self.assertTrue('LineString' in str(g.to_string())) self.assertTrue('LineString' in str(g.to_string()))
self.assertTrue('coordinates>0.000000,0.000000 1.000000,0.000000</' in str(g.to_string())) self.assertTrue('coordinates>0.000000,0.000000 1.000000,0.000000</' in str(g.to_string()))
self.assertTrue('coordinates>0.000000,1.000000 1.000000,1.000000</' in str(g.to_string())) self.assertTrue('coordinates>0.000000,1.000000 1.000000,1.000000</' in str(g.to_string()))
def testMultiPolygon(self): def testMultiPolygon(self):
#with holes # with holes
p0 = Polygon([(-1,-1), (2,-1), (2,2), (-1,-1)],[[(0,0), (1,0), (1,1), (0,0)]]) p0 = Polygon(
#without holes [(-1, -1), (2, -1), (2, 2), (-1, -1)],
p1 = Polygon([(3,0), (4,0), (4,1), (3,0)]) [[(0, 0), (1, 0), (1, 1), (0, 0)]]
g = Geometry(geometry=MultiPolygon([p0,p1])) )
# without holes
p1 = Polygon([(3, 0), (4, 0), (4, 1), (3, 0)])
g = Geometry(geometry=MultiPolygon([p0, p1]))
self.assertTrue('MultiGeometry' in str(g.to_string())) self.assertTrue('MultiGeometry' in str(g.to_string()))
self.assertTrue('Polygon' in str(g.to_string())) self.assertTrue('Polygon' in str(g.to_string()))
self.assertTrue('outerBoundaryIs' in str(g.to_string())) self.assertTrue('outerBoundaryIs' in str(g.to_string()))
...@@ -1507,16 +1604,16 @@ class SetGeometryTestCase( unittest.TestCase ): ...@@ -1507,16 +1604,16 @@ class SetGeometryTestCase( unittest.TestCase ):
in str(g.to_string())) in str(g.to_string()))
def testGeometryCollection(self): def testGeometryCollection(self):
po = Polygon([(3,0), (4,0), (4,1), (3,0)]) po = Polygon([(3, 0), (4, 0), (4, 1), (3, 0)])
lr = LinearRing([(0,-1), (1,-1), (1,1), (0,-1)]) lr = LinearRing([(0, -1), (1, -1), (1, 1), (0, -1)])
ls = LineString([(0,0), (1,1)]) ls = LineString([(0, 0), (1, 1)])
p = Point(0,1) p = Point(0, 1)
geo_if = {'type': 'GeometryCollection', 'geometries': [ # geo_if = {'type': 'GeometryCollection', 'geometries': [
po.__geo_interface__, p.__geo_interface__, # po.__geo_interface__, p.__geo_interface__,
ls.__geo_interface__, lr.__geo_interface__ ]} # ls.__geo_interface__, lr.__geo_interface__]}
g = Geometry(geometry=GeometryCollection([po,p,ls,lr])) g = Geometry(geometry=GeometryCollection([po, p, ls, lr]))
#g1 = Geometry(geometry=as_shape(geo_if)) # g1 = Geometry(geometry=as_shape(geo_if))
#self.assertEqual(g1.__geo_interface__, g.__geo_interface__) # self.assertEqual(g1.__geo_interface__, g.__geo_interface__)
self.assertTrue('MultiGeometry' in str(g.to_string())) self.assertTrue('MultiGeometry' in str(g.to_string()))
self.assertTrue('Polygon' in str(g.to_string())) self.assertTrue('Polygon' in str(g.to_string()))
self.assertTrue('outerBoundaryIs' in str(g.to_string())) self.assertTrue('outerBoundaryIs' in str(g.to_string()))
...@@ -1530,8 +1627,8 @@ class SetGeometryTestCase( unittest.TestCase ): ...@@ -1530,8 +1627,8 @@ class SetGeometryTestCase( unittest.TestCase ):
self.assertTrue('Point' in str(g.to_string())) self.assertTrue('Point' in str(g.to_string()))
self.assertTrue('coordinates>0.000000,1.000000</' in str(g.to_string())) self.assertTrue('coordinates>0.000000,1.000000</' in str(g.to_string()))
class GetGeometryTestCase( unittest.TestCase ):
class GetGeometryTestCase(unittest.TestCase):
def test_altitude_mode(self): def test_altitude_mode(self):
doc = """<kml:Point xmlns:kml="http://www.opengis.net/kml/2.2"> doc = """<kml:Point xmlns:kml="http://www.opengis.net/kml/2.2">
<kml:coordinates>0.000000,1.000000</kml:coordinates> <kml:coordinates>0.000000,1.000000</kml:coordinates>
...@@ -1568,8 +1665,10 @@ class GetGeometryTestCase( unittest.TestCase ): ...@@ -1568,8 +1665,10 @@ class GetGeometryTestCase( unittest.TestCase ):
</kml:Point>""" </kml:Point>"""
g = Geometry() g = Geometry()
g.from_string(doc) g.from_string(doc)
self.assertEqual(g.geometry.__geo_interface__, self.assertEqual(
{'type': 'Point', 'coordinates': (0.0, 1.0)}) g.geometry.__geo_interface__,
{'type': 'Point', 'coordinates': (0.0, 1.0)}
)
def testLineString(self): def testLineString(self):
doc = """<kml:LineString xmlns:kml="http://www.opengis.net/kml/2.2"> doc = """<kml:LineString xmlns:kml="http://www.opengis.net/kml/2.2">
...@@ -1577,8 +1676,10 @@ class GetGeometryTestCase( unittest.TestCase ): ...@@ -1577,8 +1676,10 @@ class GetGeometryTestCase( unittest.TestCase ):
</kml:LineString>""" </kml:LineString>"""
g = Geometry() g = Geometry()
g.from_string(doc) g.from_string(doc)
self.assertEqual(g.geometry.__geo_interface__, self.assertEqual(
{'type': 'LineString', 'coordinates': ((0.0, 0.0), (1.0, 1.0))}) g.geometry.__geo_interface__,
{'type': 'LineString', 'coordinates': ((0.0, 0.0), (1.0, 1.0))}
)
def testLinearRing(self): def testLinearRing(self):
doc = """<kml:LinearRing xmlns:kml="http://www.opengis.net/kml/2.2"> doc = """<kml:LinearRing xmlns:kml="http://www.opengis.net/kml/2.2">
...@@ -1587,8 +1688,11 @@ class GetGeometryTestCase( unittest.TestCase ): ...@@ -1587,8 +1688,11 @@ class GetGeometryTestCase( unittest.TestCase ):
""" """
g = Geometry() g = Geometry()
g.from_string(doc) g.from_string(doc)
self.assertEqual(g.geometry.__geo_interface__, self.assertEqual(
{'type': 'LinearRing', 'coordinates': ((0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0))}) g.geometry.__geo_interface__,
{'type': 'LinearRing', 'coordinates': ((0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0))}
)
def testPolygon(self): def testPolygon(self):
doc = """<kml:Polygon xmlns:kml="http://www.opengis.net/kml/2.2"> doc = """<kml:Polygon xmlns:kml="http://www.opengis.net/kml/2.2">
<kml:outerBoundaryIs> <kml:outerBoundaryIs>
...@@ -1600,11 +1704,19 @@ class GetGeometryTestCase( unittest.TestCase ): ...@@ -1600,11 +1704,19 @@ class GetGeometryTestCase( unittest.TestCase ):
""" """
g = Geometry() g = Geometry()
g.from_string(doc) g.from_string(doc)
self.assertEqual(g.geometry.__geo_interface__, self.assertEqual(
{'type': 'Polygon', 'coordinates': g.geometry.__geo_interface__,
(((0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)),)} {
'type': 'Polygon',
'coordinates': ((
(0.0, 0.0),
(1.0, 0.0),
(1.0, 1.0),
(0.0, 0.0)
),)
}
) )
doc ="""<kml:Polygon xmlns:kml="http://www.opengis.net/kml/2.2"> doc = """<kml:Polygon xmlns:kml="http://www.opengis.net/kml/2.2">
<kml:outerBoundaryIs> <kml:outerBoundaryIs>
<kml:LinearRing> <kml:LinearRing>
<kml:coordinates>-1.000000,-1.000000 2.000000,-1.000000 2.000000,2.000000 -1.000000,-1.000000</kml:coordinates> <kml:coordinates>-1.000000,-1.000000 2.000000,-1.000000 2.000000,2.000000 -1.000000,-1.000000</kml:coordinates>
...@@ -1618,10 +1730,15 @@ class GetGeometryTestCase( unittest.TestCase ): ...@@ -1618,10 +1730,15 @@ class GetGeometryTestCase( unittest.TestCase ):
</kml:Polygon> </kml:Polygon>
""" """
g.from_string(doc) g.from_string(doc)
self.assertEqual(g.geometry.__geo_interface__, self.assertEqual(
{'type': 'Polygon', 'coordinates': g.geometry.__geo_interface__,
(((-1.0, -1.0), (2.0, -1.0), (2.0, 2.0), (-1.0, -1.0)), {
((0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)))} 'type': 'Polygon',
'coordinates': (
((-1.0, -1.0), (2.0, -1.0), (2.0, 2.0), (-1.0, -1.0)),
((0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)),
)
}
) )
def testMultiPoint(self): def testMultiPoint(self):
...@@ -1639,7 +1756,6 @@ class GetGeometryTestCase( unittest.TestCase ): ...@@ -1639,7 +1756,6 @@ class GetGeometryTestCase( unittest.TestCase ):
g.from_string(doc) g.from_string(doc)
self.assertEqual(len(g.geometry), 2) self.assertEqual(len(g.geometry), 2)
def testMultiLineString(self): def testMultiLineString(self):
doc = """ doc = """
<kml:MultiGeometry xmlns:kml="http://www.opengis.net/kml/2.2"> <kml:MultiGeometry xmlns:kml="http://www.opengis.net/kml/2.2">
...@@ -1723,28 +1839,28 @@ class GetGeometryTestCase( unittest.TestCase ): ...@@ -1723,28 +1839,28 @@ class GetGeometryTestCase( unittest.TestCase ):
self.assertEqual(g.geometry.geom_type, 'GeometryCollection') self.assertEqual(g.geometry.geom_type, 'GeometryCollection')
class Force3DTestCase( unittest.TestCase ): class Force3DTestCase(unittest.TestCase):
def test3d(self): def test3d(self):
ns ='' ns = ''
p2 = kml.Placemark(ns, 'id', 'name', 'description') p2 = kml.Placemark(ns, 'id', 'name', 'description')
p2.geometry = Polygon([(0, 0), (1, 1), (1, 0)]) p2.geometry = Polygon([(0, 0), (1, 1), (1, 0)])
p3 = kml.Placemark(ns, 'id', 'name', 'description') p3 = kml.Placemark(ns, 'id', 'name', 'description')
p3.geometry = Polygon([(0, 0, 0), (1, 1, 0), (1, 0, 0)]) p3.geometry = Polygon([(0, 0, 0), (1, 1, 0), (1, 0, 0)])
config.FORCE3D = False config.FORCE3D = False
#p3.altitudeMode = 'absolute' # p3.altitudeMode = 'absolute'
self.assertNotEqual(p2.to_string(), p3.to_string()) self.assertNotEqual(p2.to_string(), p3.to_string())
config.FORCE3D = True config.FORCE3D = True
self.assertEqual(p2.to_string(), p3.to_string()) self.assertEqual(p2.to_string(), p3.to_string())
#altitudeMode clampToGround indicates to ignore an altitude specification. # altitudeMode clampToGround indicates to ignore an altitude specification.
#p3.altitudeMode = 'clampToGround' # p3.altitudeMode = 'clampToGround'
#self.assertEqual(p2.to_string(), p3.to_string()) # self.assertEqual(p2.to_string(), p3.to_string())
#config.FORCE3D = False # config.FORCE3D = False
#self.assertNotEqual(p2.to_string(), p3.to_string()) # self.assertNotEqual(p2.to_string(), p3.to_string())
#Important: Set FORCE3D back to False! # Important: Set FORCE3D back to False!
config.FORCE3D = False config.FORCE3D = False
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(BaseClassesTestCase)) suite.addTest(unittest.makeSuite(BaseClassesTestCase))
...@@ -1761,4 +1877,3 @@ def test_suite(): ...@@ -1761,4 +1877,3 @@ def test_suite():
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
-r common.txt -r common.txt
pytest pytest
pep8
coveralls coveralls
from setuptools import setup, find_packages from setuptools import setup, find_packages
from setuptools.command.test import test as TestCommand from setuptools.command.test import test as TestCommand
import sys, os import sys
import os
class PyTest(TestCommand): class PyTest(TestCommand):
def finalize_options(self): def finalize_options(self):
TestCommand.finalize_options(self) TestCommand.finalize_options(self)
self.test_args = [] self.test_args = []
self.test_suite = True self.test_suite = True
def run_tests(self): def run_tests(self):
#import here, cause outside the eggs aren't loaded # import here, cause outside the eggs aren't loaded
import pytest import pytest
errno = pytest.main(self.test_args) errno = pytest.main(self.test_args)
sys.exit(errno) sys.exit(errno)
...@@ -16,13 +19,15 @@ class PyTest(TestCommand): ...@@ -16,13 +19,15 @@ class PyTest(TestCommand):
version = '0.7' version = '0.7'
setup(name='fastkml', setup(
name='fastkml',
version=version, version=version,
description="Fast KML processing in python", description="Fast KML processing in python",
long_description=open( long_description=(
"README.rst").read() + "\n" + open("README.rst").read() + "\n" +
open(os.path.join("docs", "HISTORY.txt")).read() + "\n" + open(os.path.join("docs", "HISTORY.txt")).read() + "\n" +
open(os.path.join("docs", "TODO.txt")).read(), open(os.path.join("docs", "TODO.txt")).read()
),
classifiers=[ classifiers=[
"Topic :: Scientific/Engineering :: GIS", "Topic :: Scientific/Engineering :: GIS",
"Programming Language :: Python", "Programming Language :: Python",
...@@ -56,4 +61,4 @@ setup(name='fastkml', ...@@ -56,4 +61,4 @@ setup(name='fastkml',
entry_points=""" entry_points="""
# -*- Entry points: -*- # -*- Entry points: -*-
""", """,
) )
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment