Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
F
fastkml
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Aurélien Vermylen
fastkml
Commits
365ed6e5
Commit
365ed6e5
authored
Jul 17, 2014
by
Christian Ledermann
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #13 from IanLee1521/pep8
Pep8
parents
9eac7e71
d8d77db0
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
827 additions
and
642 deletions
+827
-642
.travis.yml
.travis.yml
+2
-1
docs/CONTRIBUTORS.txt
docs/CONTRIBUTORS.txt
+1
-1
docs/HISTORY.txt
docs/HISTORY.txt
+2
-0
fastkml/__init__.py
fastkml/__init__.py
+15
-15
fastkml/atom.py
fastkml/atom.py
+48
-47
fastkml/base.py
fastkml/base.py
+29
-23
fastkml/config.py
fastkml/config.py
+12
-12
fastkml/geometry.py
fastkml/geometry.py
+81
-61
fastkml/gx.py
fastkml/gx.py
+15
-18
fastkml/kml.py
fastkml/kml.py
+127
-92
fastkml/styles.py
fastkml/styles.py
+103
-101
fastkml/test_main.py
fastkml/test_main.py
+356
-241
requirements/test.txt
requirements/test.txt
+1
-0
setup.py
setup.py
+35
-30
No files found.
.travis.yml
View file @
365ed6e5
...
...
@@ -17,7 +17,8 @@ install:
# command to run tests, e.g. python setup.py test
script
:
coverage run --source=fastkml setup.py test
-
pep8 --exclude test_main.py fastkml
-
coverage run --source=fastkml setup.py test
after_success
:
coveralls
...
...
docs/CONTRIBUTORS.txt
View file @
365ed6e5
...
...
@@ -5,4 +5,4 @@ Contributors
- Jeremy Blalock
- Denis Krienbühl
- Egil Möller
- Ian Lee
- Ian Lee
<IanLee1521@gmail.com>
docs/HISTORY.txt
View file @
365ed6e5
...
...
@@ -6,6 +6,8 @@ Changelog
----------------
- test case additions and lxml warning [Ian Lee]
- pep8-ify source code (except test_main.py) [Ian Lee]
- pyflakes-ify source code (except __init__.py) [Ian Lee]
0.6 (2014/05/29)
----------------
...
...
fastkml/__init__.py
View file @
365ed6e5
# -*- coding: utf-8 -*-
#
Copyright (C) 2012 Christian Ledermann
#
#
This library is free software; you can redistribute it and/or
#
modify it under the terms of the GNU Lesser General Public
#
License as published by the Free Software Foundation; either
#
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,
#
but WITHOUT ANY WARRANTY; without even the implied warranty of
#
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#
Lesser General Public License for more details.
#
#
You should have received a copy of the GNU Lesser General Public
#
License along with this library; if not, write to the Free Software
#
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
# Copyright (C) 2012 Christian Ledermann
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# 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,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
#
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
from
.kml
import
KML
,
Document
,
Folder
,
Placemark
from
.kml
import
TimeSpan
,
TimeStamp
...
...
fastkml/atom.py
View file @
365ed6e5
# -*- coding: utf-8 -*-
#
Copyright (C) 2012 Christian Ledermann
#
#
This library is free software; you can redistribute it and/or
#
modify it under the terms of the GNU Lesser General Public
#
License as published by the Free Software Foundation; either
#
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,
#
but WITHOUT ANY WARRANTY; without even the implied warranty of
#
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#
Lesser General Public License for more details.
#
#
You should have received a copy of the GNU Lesser General Public
#
License along with this library; if not, write to the Free Software
#
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
# Copyright (C) 2012 Christian Ledermann
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# 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,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
#
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
"""
KML 2.2 supports new elements for including data about the author and
related website in your KML file. This information is displayed in geo
...
...
@@ -82,10 +82,11 @@ class Link(object):
length
=
None
# the length of the resource, in bytes
def
__init__
(
self
,
ns
=
None
,
href
=
None
,
rel
=
None
,
type
=
None
,
hreflang
=
None
,
title
=
None
,
length
=
None
):
if
ns
==
None
:
def
__init__
(
self
,
ns
=
None
,
href
=
None
,
rel
=
None
,
type
=
None
,
hreflang
=
None
,
title
=
None
,
length
=
None
):
if
ns
is
None
:
self
.
ns
=
NS
else
:
self
.
ns
=
ns
...
...
@@ -99,7 +100,6 @@ class Link(object):
def
from_string
(
self
,
xml_string
):
self
.
from_element
(
etree
.
XML
(
xml_string
))
def
from_element
(
self
,
element
):
if
self
.
ns
+
self
.
__name__
.
lower
()
!=
element
.
tag
:
raise
TypeError
...
...
@@ -120,7 +120,6 @@ class Link(object):
if
element
.
get
(
'length'
):
self
.
length
=
element
.
get
(
'length'
)
def
etree_element
(
self
):
element
=
etree
.
Element
(
self
.
ns
+
self
.
__name__
.
lower
())
if
self
.
href
:
...
...
@@ -142,11 +141,14 @@ class Link(object):
def
to_string
(
self
,
prettyprint
=
True
):
""" Return the ATOM Object as serialized xml """
if
LXML
and
prettyprint
:
return
etree
.
tostring
(
self
.
etree_element
(),
encoding
=
'utf-8'
,
pretty_print
=
True
).
decode
(
'UTF-8'
)
return
etree
.
tostring
(
self
.
etree_element
(),
encoding
=
'utf-8'
,
pretty_print
=
True
).
decode
(
'UTF-8'
)
else
:
return
etree
.
tostring
(
self
.
etree_element
(),
encoding
=
'utf-8'
).
decode
(
'UTF-8'
)
return
etree
.
tostring
(
self
.
etree_element
(),
encoding
=
'utf-8'
).
decode
(
'UTF-8'
)
class
_Person
(
object
):
...
...
@@ -159,16 +161,16 @@ class _Person(object):
ns
=
None
name
=
None
#conveys a human-readable name for the person.
#
conveys a human-readable name for the person.
uri
=
None
#contains a home page for the person.
#
contains a home page for the person.
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
):
if
ns
==
None
:
if
ns
is
None
:
self
.
ns
=
NS
else
:
self
.
ns
=
ns
...
...
@@ -176,27 +178,24 @@ class _Person(object):
self
.
uri
=
uri
self
.
email
=
email
def
etree_element
(
self
):
element
=
etree
.
Element
(
self
.
ns
+
self
.
__name__
.
lower
())
if
self
.
name
:
name
=
etree
.
SubElement
(
element
,
"%sname"
%
self
.
ns
)
name
=
etree
.
SubElement
(
element
,
"%sname"
%
self
.
ns
)
name
.
text
=
self
.
name
#else:
#
else:
# logger.critical('No Name for person defined')
# raise TypeError
if
self
.
uri
:
#XXX validate uri
uri
=
etree
.
SubElement
(
element
,
"%suri"
%
self
.
ns
)
#
XXX validate uri
uri
=
etree
.
SubElement
(
element
,
"%suri"
%
self
.
ns
)
uri
.
text
=
self
.
uri
if
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
return
element
def
from_string
(
self
,
xml_string
):
self
.
from_element
(
etree
.
XML
(
xml_string
))
...
...
@@ -204,13 +203,13 @@ class _Person(object):
if
self
.
ns
+
self
.
__name__
.
lower
()
!=
element
.
tag
:
raise
TypeError
else
:
name
=
element
.
find
(
'%sname'
%
self
.
ns
)
name
=
element
.
find
(
'%sname'
%
self
.
ns
)
if
name
is
not
None
:
self
.
name
=
name
.
text
uri
=
element
.
find
(
'%suri'
%
self
.
ns
)
uri
=
element
.
find
(
'%suri'
%
self
.
ns
)
if
uri
is
not
None
:
self
.
uri
=
uri
.
text
email
=
element
.
find
(
'%semail'
%
self
.
ns
)
email
=
element
.
find
(
'%semail'
%
self
.
ns
)
if
email
is
not
None
:
if
check_email
(
email
.
text
):
self
.
email
=
email
.
text
...
...
@@ -218,21 +217,23 @@ class _Person(object):
def
to_string
(
self
,
prettyprint
=
True
):
""" Return the ATOM Object as serialized xml """
if
LXML
and
prettyprint
:
return
etree
.
tostring
(
self
.
etree_element
(),
encoding
=
'utf-8'
,
pretty_print
=
True
).
decode
(
'UTF-8'
)
return
etree
.
tostring
(
self
.
etree_element
(),
encoding
=
'utf-8'
,
pretty_print
=
True
).
decode
(
'UTF-8'
)
else
:
return
etree
.
tostring
(
self
.
etree_element
(),
encoding
=
'utf-8'
).
decode
(
'UTF-8'
)
return
etree
.
tostring
(
self
.
etree_element
(),
encoding
=
'utf-8'
).
decode
(
'UTF-8'
)
class
Author
(
_Person
):
""" Names one author of the feed/entry. A feed/entry may have
multiple authors."""
__name__
=
"Author"
class
Contributor
(
_Person
):
""" Names one contributor to the feed/entry. A feed/entry may have
multiple contributor elements."""
__name__
=
"Contributor"
fastkml/base.py
View file @
365ed6e5
# -*- coding: utf-8 -*-
#
Copyright (C) 2012 Christian Ledermann
# Copyright (C) 2012 Christian Ledermann
#
#
This library is free software; you can redistribute it and/or
#
modify it under the terms of the GNU Lesser General Public
#
License as published by the Free Software Foundation; either
#
version 2.1 of the License, or (at your option) any later version.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# 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,
#
but WITHOUT ANY WARRANTY; without even the implied warranty of
#
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#
Lesser General Public License for more details.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
#
You should have received a copy of the GNU Lesser General Public
#
License along with this library; if not, write to the Free Software
#
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
#
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
""" abstract base classes"""
import
fastkml.config
as
config
from
fastkml.config
import
etree
class
_XMLObject
(
object
):
""" XML Baseclass"""
...
...
@@ -27,7 +28,7 @@ class _XMLObject(object):
ns
=
None
def
__init__
(
self
,
ns
=
None
):
if
ns
==
None
:
if
ns
is
None
:
self
.
ns
=
config
.
NS
else
:
self
.
ns
=
ns
...
...
@@ -36,12 +37,16 @@ class _XMLObject(object):
if
self
.
__name__
:
element
=
etree
.
Element
(
self
.
ns
+
self
.
__name__
)
else
:
raise
NotImplementedError
(
"Call of abstract base class, subclasses implement this!"
)
raise
NotImplementedError
(
"Call of abstract base class, subclasses implement this!"
)
return
element
def
from_element
(
self
,
element
):
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
):
self
.
from_element
(
etree
.
XML
(
xml_string
))
...
...
@@ -49,11 +54,15 @@ class _XMLObject(object):
def
to_string
(
self
,
prettyprint
=
True
):
""" Return the KML Object as serialized xml """
if
config
.
LXML
and
prettyprint
:
return
etree
.
tostring
(
self
.
etree_element
(),
encoding
=
'utf-8'
,
pretty_print
=
True
).
decode
(
'UTF-8'
)
return
etree
.
tostring
(
self
.
etree_element
(),
encoding
=
'utf-8'
,
pretty_print
=
True
).
decode
(
'UTF-8'
)
else
:
return
etree
.
tostring
(
self
.
etree_element
(),
encoding
=
'utf-8'
).
decode
(
'UTF-8'
)
return
etree
.
tostring
(
self
.
etree_element
(),
encoding
=
'utf-8'
).
decode
(
'UTF-8'
)
class
_BaseObject
(
_XMLObject
):
""" This is an abstract base class and cannot be used directly in a
...
...
@@ -68,7 +77,7 @@ class _BaseObject(_XMLObject):
def
__init__
(
self
,
ns
=
None
,
id
=
None
):
super
(
_BaseObject
,
self
).
__init__
(
ns
)
self
.
id
=
id
if
ns
==
None
:
if
ns
is
None
:
self
.
ns
=
config
.
NS
else
:
self
.
ns
=
ns
...
...
@@ -81,12 +90,9 @@ class _BaseObject(_XMLObject):
element
.
set
(
'targetId'
,
self
.
targetId
)
return
element
def
from_element
(
self
,
element
):
super
(
_BaseObject
,
self
).
from_element
(
element
)
if
element
.
get
(
'id'
):
self
.
id
=
element
.
get
(
'id'
)
if
element
.
get
(
'targetId'
):
self
.
targetId
=
element
.
get
(
'targetId'
)
fastkml/config.py
View file @
365ed6e5
# -*- coding: utf-8 -*-
#
Copyright (C) 2012 Christian Ledermann
# Copyright (C) 2012 Christian Ledermann
#
#
This library is free software; you can redistribute it and/or
#
modify it under the terms of the GNU Lesser General Public
#
License as published by the Free Software Foundation; either
#
version 2.1 of the License, or (at your option) any later version.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# 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,
#
but WITHOUT ANY WARRANTY; without even the implied warranty of
#
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#
Lesser General Public License for more details.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
#
You should have received a copy of the GNU Lesser General Public
#
License along with this library; if not, write to the Free Software
#
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
#
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
"""frequently used constants and abstract base classes"""
import
logging
...
...
fastkml/geometry.py
View file @
365ed6e5
# -*- coding: utf-8 -*-
#
Copyright (C) 2012 Christian Ledermann
# Copyright (C) 2012 Christian Ledermann
#
#
This library is free software; you can redistribute it and/or
#
modify it under the terms of the GNU Lesser General Public
#
License as published by the Free Software Foundation; either
#
version 2.1 of the License, or (at your option) any later version.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# 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,
#
but WITHOUT ANY WARRANTY; without even the implied warranty of
#
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#
Lesser General Public License for more details.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
#
You should have received a copy of the GNU Lesser General Public
#
License along with this library; if not, write to the Free Software
#
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
#
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
"""
Import the geometries from shapely if it is installed
or otherwise from Pygeoif
...
...
@@ -22,7 +22,7 @@ try:
from
shapely.geometry
import
Point
,
LineString
,
Polygon
from
shapely.geometry
import
MultiPoint
,
MultiLineString
,
MultiPolygon
from
shapely.geometry.polygon
import
LinearRing
#from shapely.geometry import GeometryCollection
#
from shapely.geometry import GeometryCollection
# Sean Gillies:
# I deliberately omitted a geometry collection constructor because
# there was almost no support in GEOS for operations on them. You
...
...
@@ -40,10 +40,7 @@ except ImportError:
from
pygeoif.geometry
import
GeometryCollection
from
pygeoif.geometry
import
as_shape
as
asShape
try
:
import
fastkml.config
as
config
except
ImportError
:
import
config
import
fastkml.config
as
config
from
.config
import
etree
...
...
@@ -63,9 +60,10 @@ class Geometry(_BaseObject):
tessellate
=
False
altitude_mode
=
None
def
__init__
(
self
,
ns
=
None
,
id
=
None
,
geometry
=
None
,
extrude
=
False
,
tessellate
=
False
,
altitude_mode
=
None
):
def
__init__
(
self
,
ns
=
None
,
id
=
None
,
geometry
=
None
,
extrude
=
False
,
tessellate
=
False
,
altitude_mode
=
None
):
"""
geometry: a geometry that implements the __geo_interface__ convention
...
...
@@ -115,9 +113,14 @@ class Geometry(_BaseObject):
self
.
tessellate
=
tessellate
self
.
altitude_mode
=
altitude_mode
if
geometry
:
if
isinstance
(
geometry
,
(
Point
,
LineString
,
Polygon
,
MultiPoint
,
MultiLineString
,
MultiPolygon
,
LinearRing
,
GeometryCollection
)):
if
isinstance
(
geometry
,
(
Point
,
LineString
,
Polygon
,
MultiPoint
,
MultiLineString
,
MultiPolygon
,
LinearRing
,
GeometryCollection
)
):
self
.
geometry
=
geometry
else
:
self
.
geometry
=
asShape
(
geometry
)
...
...
@@ -126,35 +129,43 @@ class Geometry(_BaseObject):
def
_set_altitude_mode
(
self
,
element
):
if
self
.
altitude_mode
:
assert
(
self
.
altitude_mode
in
[
'clampToGround'
,
#'relativeToSeaFloor', 'clampToSeaFloor',
'relativeToGround'
,
'absolute'
])
assert
(
self
.
altitude_mode
in
[
'clampToGround'
,
# 'relativeToSeaFloor', 'clampToSeaFloor',
'relativeToGround'
,
'absolute'
])
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
def
_set_extrude
(
self
,
element
):
if
self
.
extrude
and
self
.
altitude_mode
in
[
'relativeToGround'
,
#'relativeToSeaFloor',
'absolute'
]:
et_element
=
etree
.
SubElement
(
element
,
"%sextrude"
%
self
.
ns
)
if
self
.
extrude
and
self
.
altitude_mode
in
[
'relativeToGround'
,
# 'relativeToSeaFloor',
'absolute'
]:
et_element
=
etree
.
SubElement
(
element
,
"%sextrude"
%
self
.
ns
)
et_element
.
text
=
'1'
def
_etree_coordinates
(
self
,
coordinates
):
clampToGround
=
(
self
.
altitude_mode
==
'clampToGround'
)
or
(
self
.
altitude_mode
==
None
)
element
=
etree
.
Element
(
"%scoordinates"
%
self
.
ns
)
# clampToGround = (
# (self.altitude_mode == 'clampToGround')
# or (self.altitude_mode is None)
# )
element
=
etree
.
Element
(
"%scoordinates"
%
self
.
ns
)
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
)
else
:
tuples
=
(
'%f,%f'
%
tuple
(
c
)
for
c
in
coordinates
)
elif
len
(
coordinates
[
0
])
==
3
:
#if clampToGround:
#
if clampToGround:
# if the altitude is ignored anyway, we may as well
# ignore the z-value
# tuples = ('%f,%f' % tuple(c[:2]) for c in coordinates)
#else:
#
else:
tuples
=
(
'%f,%f,%f'
%
tuple
(
c
)
for
c
in
coordinates
)
else
:
raise
ValueError
(
"Invalid dimensions"
)
...
...
@@ -162,7 +173,7 @@ class Geometry(_BaseObject):
return
element
def
_etree_point
(
self
,
point
):
element
=
etree
.
Element
(
"%sPoint"
%
self
.
ns
)
element
=
etree
.
Element
(
"%sPoint"
%
self
.
ns
)
self
.
_set_extrude
(
element
)
self
.
_set_altitude_mode
(
element
)
coords
=
list
(
point
.
coords
)
...
...
@@ -170,24 +181,26 @@ class Geometry(_BaseObject):
return
element
def
_etree_linestring
(
self
,
linestring
):
element
=
etree
.
Element
(
"%sLineString"
%
self
.
ns
)
element
=
etree
.
Element
(
"%sLineString"
%
self
.
ns
)
self
.
_set_extrude
(
element
)
self
.
_set_altitude_mode
(
element
)
if
self
.
tessellate
and
self
.
altitude_mode
in
[
'clampToGround'
,
'clampToSeaFloor'
]:
ts_element
=
etree
.
SubElement
(
element
,
"%stessellate"
%
self
.
ns
)
if
self
.
tessellate
and
self
.
altitude_mode
in
[
'clampToGround'
,
'clampToSeaFloor'
]:
ts_element
=
etree
.
SubElement
(
element
,
"%stessellate"
%
self
.
ns
)
ts_element
.
text
=
'1'
coords
=
list
(
linestring
.
coords
)
element
.
append
(
self
.
_etree_coordinates
(
coords
))
return
element
def
_etree_linearring
(
self
,
linearring
):
element
=
etree
.
Element
(
"%sLinearRing"
%
self
.
ns
)
element
=
etree
.
Element
(
"%sLinearRing"
%
self
.
ns
)
self
.
_set_extrude
(
element
)
self
.
_set_altitude_mode
(
element
)
# tesseleation is ignored by polygon and tesselation together with
# 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']:
# element.set('tessellate', '1')
coords
=
list
(
linearring
.
coords
)
...
...
@@ -195,36 +208,40 @@ class Geometry(_BaseObject):
return
element
def
_etree_polygon
(
self
,
polygon
):
element
=
etree
.
Element
(
"%sPolygon"
%
self
.
ns
)
element
=
etree
.
Element
(
"%sPolygon"
%
self
.
ns
)
self
.
_set_extrude
(
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
))
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
))
return
element
def
_etree_multipoint
(
self
,
points
):
element
=
etree
.
Element
(
"%sMultiGeometry"
%
self
.
ns
)
element
=
etree
.
Element
(
"%sMultiGeometry"
%
self
.
ns
)
for
point
in
points
.
geoms
:
element
.
append
(
self
.
_etree_point
(
point
))
return
element
def
_etree_multilinestring
(
self
,
linestrings
):
element
=
etree
.
Element
(
"%sMultiGeometry"
%
self
.
ns
)
element
=
etree
.
Element
(
"%sMultiGeometry"
%
self
.
ns
)
for
linestring
in
linestrings
.
geoms
:
element
.
append
(
self
.
_etree_linestring
(
linestring
))
return
element
def
_etree_multipolygon
(
self
,
polygons
):
element
=
etree
.
Element
(
"%sMultiGeometry"
%
self
.
ns
)
element
=
etree
.
Element
(
"%sMultiGeometry"
%
self
.
ns
)
for
polygon
in
polygons
.
geoms
:
element
.
append
(
self
.
_etree_polygon
(
polygon
))
return
element
def
_etree_collection
(
self
,
features
):
element
=
etree
.
Element
(
"%sMultiGeometry"
%
self
.
ns
)
element
=
etree
.
Element
(
"%sMultiGeometry"
%
self
.
ns
)
for
feature
in
features
.
geoms
:
if
feature
.
geom_type
==
"Point"
:
element
.
append
(
self
.
_etree_point
(
feature
))
...
...
@@ -282,16 +299,17 @@ class Geometry(_BaseObject):
altitude_mode
=
element
.
find
(
'%saltitudeMode'
%
self
.
ns
)
if
altitude_mode
is
not
None
:
am
=
altitude_mode
.
text
.
strip
()
if
am
in
[
'clampToGround'
,
#'relativeToSeaFloor', 'clampToSeaFloor',
'relativeToGround'
,
'absolute'
]:
if
am
in
[
'clampToGround'
,
# 'relativeToSeaFloor', 'clampToSeaFloor',
'relativeToGround'
,
'absolute'
]:
self
.
altitude_mode
=
am
else
:
self
.
altitude_mode
=
None
else
:
self
.
altitude_mode
=
None
def
_get_coordinates
(
self
,
element
):
coordinates
=
element
.
find
(
'%scoordinates'
%
self
.
ns
)
if
coordinates
is
not
None
:
...
...
@@ -321,9 +339,9 @@ class Geometry(_BaseObject):
return
LineString
(
coords
)
if
element
.
tag
==
(
'%sPolygon'
%
self
.
ns
):
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
)
inner_boundaries
=
element
.
findall
(
'%sinnerBoundaryIs'
%
self
.
ns
)
inner_boundaries
=
element
.
findall
(
'%sinnerBoundaryIs'
%
self
.
ns
)
ibs
=
[]
for
inner_boundary
in
inner_boundaries
:
ibs
.
append
(
self
.
_get_linear_ring
(
inner_boundary
))
...
...
@@ -333,8 +351,6 @@ class Geometry(_BaseObject):
self
.
_get_geometry_spec
(
element
)
return
LinearRing
(
coords
)
def
_get_multigeometry
(
self
,
element
):
# MultiGeometry
geoms
=
[]
...
...
@@ -353,9 +369,13 @@ class Geometry(_BaseObject):
if
polygons
:
for
polygon
in
polygons
:
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
)
inner_boundaries
=
polygon
.
findall
(
'%sinnerBoundaryIs'
%
self
.
ns
)
inner_boundaries
=
polygon
.
findall
(
'%sinnerBoundaryIs'
%
self
.
ns
)
ibs
=
[]
for
inner_boundary
in
inner_boundaries
:
ibs
.
append
(
self
.
_get_linear_ring
(
inner_boundary
))
...
...
fastkml/gx.py
View file @
365ed6e5
# -*- coding: utf-8 -*-
#
Copyright (C) 2012 Christian Ledermann
# Copyright (C) 2012 Christian Ledermann
#
#
This library is free software; you can redistribute it and/or
#
modify it under the terms of the GNU Lesser General Public
#
License as published by the Free Software Foundation; either
#
version 2.1 of the License, or (at your option) any later version.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# 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,
#
but WITHOUT ANY WARRANTY; without even the implied warranty of
#
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#
Lesser General Public License for more details.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
#
You should have received a copy of the GNU Lesser General Public
#
License along with this library; if not, write to the Free Software
#
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
#
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
"""
With the launch of Google Earth 5.0, Google has provided extensions to KML
...
...
@@ -76,9 +76,6 @@ located at http://developers.google.com/kml/schema/kml22gx.xsd.
import
logging
logger
=
logging
.
getLogger
(
'fastkml.gx'
)
from
.config
import
etree
from
.config
import
GXNS
as
NS
from
.config
import
LXML
# from .config import etree
# from .config import GXNS as NS
# from .config import LXML
fastkml/kml.py
View file @
365ed6e5
# -*- coding: utf-8 -*-
#
Copyright (C) 2012 Christian Ledermann
# Copyright (C) 2012 Christian Ledermann
#
#
This library is free software; you can redistribute it and/or
#
modify it under the terms of the GNU Lesser General Public
#
License as published by the Free Software Foundation; either
#
version 2.1 of the License, or (at your option) any later version.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# 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,
#
but WITHOUT ANY WARRANTY; without even the implied warranty of
#
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#
Lesser General Public License for more details.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
#
You should have received a copy of the GNU Lesser General Public
#
License along with this library; if not, write to the Free Software
#
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
#
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
"""
KML is an open standard officially named the OpenGIS KML Encoding Standard
...
...
@@ -31,9 +31,9 @@ except ImportError:
import
urllib.parse
as
urlparse
import
warnings
from
.geometry
import
Point
,
LineString
,
Polygon
from
.geometry
import
MultiPoint
,
MultiLineString
,
MultiPolygon
from
.geometry
import
LinearRing
#
from .geometry import Point, LineString, Polygon
#
from .geometry import MultiPoint, MultiLineString, MultiPolygon
#
from .geometry import LinearRing
from
.geometry
import
Geometry
from
datetime
import
datetime
,
date
...
...
@@ -54,7 +54,7 @@ from .base import _BaseObject, _XMLObject
from
.styles
import
StyleUrl
,
Style
,
StyleMap
,
_StyleSelector
import
fastkml.atom
as
atom
import
fastkml.gx
as
gx
#
import fastkml.gx as gx
import
fastkml.config
as
config
try
:
...
...
@@ -76,7 +76,7 @@ class KML(object):
to be initialized with empty namespace as well in this case.
"""
self
.
_features
=
[]
self
.
_features
=
[]
if
ns
is
None
:
self
.
ns
=
config
.
NS
...
...
@@ -86,7 +86,10 @@ class KML(object):
def
from_string
(
self
,
xml_string
):
""" create a KML object from a xml string"""
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
:
element
=
etree
.
XML
(
xml_string
)
...
...
@@ -119,22 +122,27 @@ class KML(object):
root
.
set
(
'xmlns'
,
config
.
NS
[
1
:
-
1
])
else
:
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
:
root
=
etree
.
Element
(
'%skml'
%
self
.
ns
)
for
feature
in
self
.
features
():
root
.
append
(
feature
.
etree_element
())
return
root
def
to_string
(
self
,
prettyprint
=
False
):
""" Return the KML Object as serialized xml """
if
config
.
LXML
and
prettyprint
:
return
etree
.
tostring
(
self
.
etree_element
(),
encoding
=
'utf-8'
,
pretty_print
=
True
).
decode
(
'UTF-8'
)
return
etree
.
tostring
(
self
.
etree_element
(),
encoding
=
'utf-8'
,
pretty_print
=
True
).
decode
(
'UTF-8'
)
else
:
return
etree
.
tostring
(
self
.
etree_element
(),
encoding
=
'utf-8'
).
decode
(
'UTF-8'
)
return
etree
.
tostring
(
self
.
etree_element
(),
encoding
=
'utf-8'
).
decode
(
'UTF-8'
)
def
features
(
self
):
""" iterate over features """
...
...
@@ -143,7 +151,9 @@ class KML(object):
yield
feature
else
:
raise
TypeError
(
"Features must be instances of (Document, Folder, Placemark)"
)
"Features must be instances of "
"(Document, Folder, Placemark)"
)
def
append
(
self
,
kmlobj
):
""" append a feature """
...
...
@@ -151,7 +161,8 @@ class KML(object):
self
.
_features
.
append
(
kmlobj
)
else
:
raise
TypeError
(
"Features must be instances of (Document, Folder, Placemark)"
)
"Features must be instances of (Document, Folder, Placemark)"
)
class
_Feature
(
_BaseObject
):
"""
...
...
@@ -188,17 +199,17 @@ class _Feature(_BaseObject):
_atom_link
=
None
# 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
# standard street, city, state address, and/or as a postal code.
# You can use the <address> tag to specify the location of a point
# instead of using latitude and longitude coordinates.
#TODO phoneNumber = None
#
TODO phoneNumber = None
# A string value representing a telephone number.
# 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.maxLines or a string
#
...
...
@@ -213,7 +224,7 @@ class _Feature(_BaseObject):
# that specifies the maximum number of lines to display.
description
=
None
#User-supplied content that appears in the description balloon.
#
User-supplied content that appears in the description balloon.
_styleUrl
=
None
# URL of a <Style> or <StyleMap> defined in a Document.
...
...
@@ -240,11 +251,11 @@ class _Feature(_BaseObject):
_time_stamp
=
None
# 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
# the Region is active.
#TODO ExtendedData = None
#
TODO ExtendedData = None
# Allows you to add custom data to a KML file. This data can be
# (1) data that references an external XML schema,
# (2) untyped data/value pairs, or
...
...
@@ -257,11 +268,13 @@ class _Feature(_BaseObject):
# <Metadata> (deprecated in KML 2.2; use <ExtendedData> instead)
extended_data
=
None
def
__init__
(
self
,
ns
=
None
,
id
=
None
,
name
=
None
,
description
=
None
,
styles
=
None
,
styleUrl
=
None
,
extended_data
=
None
):
def
__init__
(
self
,
ns
=
None
,
id
=
None
,
name
=
None
,
description
=
None
,
styles
=
None
,
styleUrl
=
None
,
extended_data
=
None
):
super
(
_Feature
,
self
).
__init__
(
ns
,
id
)
self
.
name
=
name
self
.
description
=
description
self
.
name
=
name
self
.
description
=
description
self
.
styleUrl
=
styleUrl
self
.
_styles
=
[]
if
styles
:
...
...
@@ -297,7 +310,7 @@ class _Feature(_BaseObject):
@
timeStamp
.
setter
def
timeStamp
(
self
,
dt
):
if
dt
==
None
:
if
dt
is
None
:
self
.
_time_stamp
=
None
else
:
self
.
_time_stamp
=
TimeStamp
(
timestamp
=
dt
)
...
...
@@ -370,12 +383,11 @@ class _Feature(_BaseObject):
self
.
_atom_author
=
atom
.
Author
(
name
=
name
)
else
:
self
.
_atom_author
.
name
=
name
elif
name
==
None
:
elif
name
is
None
:
self
.
_atom_author
=
None
else
:
raise
TypeError
def
append_style
(
self
,
style
):
""" append a style to the feature """
if
isinstance
(
style
,
_StyleSelector
):
...
...
@@ -390,6 +402,7 @@ class _Feature(_BaseObject):
yield
style
else
:
raise
TypeError
@
property
def
snippet
(
self
):
if
self
.
_snippet
:
...
...
@@ -406,7 +419,10 @@ class _Feature(_BaseObject):
elif
isinstance
(
self
.
_snippet
,
basestring
):
return
self
.
_snippet
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
def
snippet
(
self
,
snip
=
None
):
...
...
@@ -421,27 +437,29 @@ class _Feature(_BaseObject):
elif
snip
is
None
:
self
.
_snippet
=
None
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
):
element
=
super
(
_Feature
,
self
).
etree_element
()
if
self
.
name
:
name
=
etree
.
SubElement
(
element
,
"%sname"
%
self
.
ns
)
name
=
etree
.
SubElement
(
element
,
"%sname"
%
self
.
ns
)
name
.
text
=
self
.
name
if
self
.
description
:
description
=
etree
.
SubElement
(
element
,
"%sdescription"
%
self
.
ns
)
description
=
etree
.
SubElement
(
element
,
"%sdescription"
%
self
.
ns
)
description
.
text
=
self
.
description
visibility
=
etree
.
SubElement
(
element
,
"%svisibility"
%
self
.
ns
)
visibility
=
etree
.
SubElement
(
element
,
"%svisibility"
%
self
.
ns
)
visibility
.
text
=
str
(
self
.
visibility
)
if
self
.
isopen
:
isopen
=
etree
.
SubElement
(
element
,
"%sopen"
%
self
.
ns
)
isopen
=
etree
.
SubElement
(
element
,
"%sopen"
%
self
.
ns
)
isopen
.
text
=
str
(
self
.
isopen
)
if
self
.
_styleUrl
is
not
None
:
element
.
append
(
self
.
_styleUrl
.
etree_element
())
for
style
in
self
.
styles
():
element
.
append
(
style
.
etree_element
())
if
self
.
snippet
:
snippet
=
etree
.
SubElement
(
element
,
"%sSnippet"
%
self
.
ns
)
snippet
=
etree
.
SubElement
(
element
,
"%sSnippet"
%
self
.
ns
)
if
isinstance
(
self
.
snippet
,
basestring
):
snippet
.
text
=
self
.
snippet
else
:
...
...
@@ -450,7 +468,9 @@ class _Feature(_BaseObject):
if
self
.
snippet
.
get
(
'maxLines'
):
snippet
.
set
(
'maxLines'
,
str
(
self
.
snippet
[
'maxLines'
]))
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
:
element
.
append
(
self
.
_time_span
.
etree_element
())
elif
self
.
_time_stamp
is
not
None
:
...
...
@@ -463,19 +483,18 @@ class _Feature(_BaseObject):
element
.
append
(
self
.
extended_data
.
etree_element
())
return
element
def
from_element
(
self
,
element
):
super
(
_Feature
,
self
).
from_element
(
element
)
name
=
element
.
find
(
'%sname'
%
self
.
ns
)
name
=
element
.
find
(
'%sname'
%
self
.
ns
)
if
name
is
not
None
:
self
.
name
=
name
.
text
description
=
element
.
find
(
'%sdescription'
%
self
.
ns
)
description
=
element
.
find
(
'%sdescription'
%
self
.
ns
)
if
description
is
not
None
:
self
.
description
=
description
.
text
visibility
=
element
.
find
(
'%svisibility'
%
self
.
ns
)
visibility
=
element
.
find
(
'%svisibility'
%
self
.
ns
)
if
visibility
is
not
None
:
self
.
visibility
=
int
(
visibility
.
text
)
isopen
=
element
.
find
(
'%sopen'
%
self
.
ns
)
isopen
=
element
.
find
(
'%sopen'
%
self
.
ns
)
if
isopen
is
not
None
:
self
.
isopen
=
int
(
isopen
.
text
)
styles
=
element
.
findall
(
'%sStyle'
%
self
.
ns
)
...
...
@@ -524,14 +543,12 @@ class _Feature(_BaseObject):
x
=
ExtendedData
(
self
.
ns
)
x
.
from_element
(
extended_data
)
self
.
extended_data
=
x
#else:
#
else:
# logger.warn(
# 'arbitrary or typed extended data is not yet supported'
# )
class
_Container
(
_Feature
):
"""
abstract element; do not create
...
...
@@ -544,10 +561,14 @@ class _Container(_Feature):
_features
=
[]
def
__init__
(
self
,
ns
=
None
,
id
=
None
,
name
=
None
,
description
=
None
,
styles
=
None
,
styleUrl
=
None
):
super
(
_Container
,
self
).
__init__
(
ns
,
id
,
name
,
description
,
styles
,
styleUrl
)
self
.
_features
=
[]
def
__init__
(
self
,
ns
=
None
,
id
=
None
,
name
=
None
,
description
=
None
,
styles
=
None
,
styleUrl
=
None
):
super
(
_Container
,
self
).
__init__
(
ns
,
id
,
name
,
description
,
styles
,
styleUrl
)
self
.
_features
=
[]
def
features
(
self
):
""" iterate over features """
...
...
@@ -564,18 +585,17 @@ class _Container(_Feature):
element
.
append
(
feature
.
etree_element
())
return
element
def
append
(
self
,
kmlobj
):
""" append a feature """
if
isinstance
(
kmlobj
,
(
Folder
,
Placemark
)):
self
.
_features
.
append
(
kmlobj
)
else
:
raise
TypeError
(
"Features must be instances of (Folder, Placemark)"
)
"Features must be instances of (Folder, Placemark)"
)
assert
(
kmlobj
!=
self
)
class
Document
(
_Container
):
"""
A Document is a container for features and styles. This element is
...
...
@@ -613,7 +633,7 @@ class Document(_Container):
self
.
append
(
feature
)
schemata
=
element
.
findall
(
'%sSchema'
%
self
.
ns
)
for
schema
in
schemata
:
s
=
Schema
(
self
.
ns
,
id
=
'default'
)
s
=
Schema
(
self
.
ns
,
id
=
'default'
)
s
.
from_element
(
schema
)
self
.
append_schema
(
s
)
...
...
@@ -651,6 +671,7 @@ class Folder(_Container):
feature
.
from_element
(
placemark
)
self
.
append
(
feature
)
class
Placemark
(
_Feature
):
"""
A Placemark is a Feature with associated Geometry.
...
...
@@ -715,6 +736,7 @@ class Placemark(_Feature):
logger
.
error
(
'Object does not have a geometry'
)
return
element
class
_TimePrimitive
(
_BaseObject
):
""" The dateTime is defined according to XML Schema time.
The value can be expressed as yyyy-mm-ddThh:mm:sszzzzzz, where T is
...
...
@@ -748,7 +770,6 @@ class _TimePrimitive(_BaseObject):
resolution
=
None
return
resolution
def
parse_str
(
self
,
datestr
):
resolution
=
'dateTime'
year
=
0
...
...
@@ -778,7 +799,6 @@ class _TimePrimitive(_BaseObject):
raise
ValueError
return
[
dt
,
resolution
]
def
date_to_string
(
self
,
dt
,
resolution
=
None
):
if
isinstance
(
dt
,
(
date
,
datetime
)):
resolution
=
self
.
get_resolution
(
dt
,
resolution
)
...
...
@@ -807,18 +827,17 @@ class TimeStamp(_TimePrimitive):
def
etree_element
(
self
):
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
)
return
element
def
from_element
(
self
,
element
):
super
(
TimeStamp
,
self
).
from_element
(
element
)
when
=
element
.
find
(
'%swhen'
%
self
.
ns
)
when
=
element
.
find
(
'%swhen'
%
self
.
ns
)
if
when
is
not
None
:
self
.
timestamp
=
self
.
parse_str
(
when
.
text
)
class
TimeSpan
(
_TimePrimitive
):
""" Represents an extent in time bounded by begin and end dateTimes.
"""
...
...
@@ -826,8 +845,10 @@ class TimeSpan(_TimePrimitive):
begin
=
None
end
=
None
def
__init__
(
self
,
ns
=
None
,
id
=
None
,
begin
=
None
,
begin_res
=
None
,
end
=
None
,
end_res
=
None
):
def
__init__
(
self
,
ns
=
None
,
id
=
None
,
begin
=
None
,
begin_res
=
None
,
end
=
None
,
end_res
=
None
):
super
(
TimeSpan
,
self
).
__init__
(
ns
,
id
)
if
begin
:
resolution
=
self
.
get_resolution
(
begin
,
begin_res
)
...
...
@@ -838,10 +859,10 @@ class TimeSpan(_TimePrimitive):
def
from_element
(
self
,
element
):
super
(
TimeSpan
,
self
).
from_element
(
element
)
begin
=
element
.
find
(
'%sbegin'
%
self
.
ns
)
begin
=
element
.
find
(
'%sbegin'
%
self
.
ns
)
if
begin
is
not
None
:
self
.
begin
=
self
.
parse_str
(
begin
.
text
)
end
=
element
.
find
(
'%send'
%
self
.
ns
)
end
=
element
.
find
(
'%send'
%
self
.
ns
)
if
end
is
not
None
:
self
.
end
=
self
.
parse_str
(
end
.
text
)
...
...
@@ -850,16 +871,16 @@ class TimeSpan(_TimePrimitive):
if
self
.
begin
is
not
None
:
text
=
self
.
date_to_string
(
*
self
.
begin
)
if
text
:
begin
=
etree
.
SubElement
(
element
,
"%sbegin"
%
self
.
ns
)
begin
=
etree
.
SubElement
(
element
,
"%sbegin"
%
self
.
ns
)
begin
.
text
=
text
if
self
.
end
is
not
None
:
text
=
self
.
date_to_string
(
*
self
.
end
)
if
text
:
end
=
etree
.
SubElement
(
element
,
"%send"
%
self
.
ns
)
end
=
etree
.
SubElement
(
element
,
"%send"
%
self
.
ns
)
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"
)
#TODO test if end > begin
#
TODO test if end > begin
return
element
...
...
@@ -890,9 +911,11 @@ class Schema(_BaseObject):
sfs
=
[]
for
simple_field
in
self
.
_simple_fields
:
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'
],
'displayName'
:
simple_field
.
get
(
'displayName'
)})
'displayName'
:
simple_field
.
get
(
'displayName'
)
})
return
tuple
(
sfs
)
@
simple_fields
.
setter
...
...
@@ -933,12 +956,17 @@ class Schema(_BaseObject):
the Google Earth user. Use the [CDATA] element to escape standard
HTML markup.
"""
allowed_types
=
[
'string'
,
'int'
,
'uint'
,
'short'
,
'ushort'
,
'float'
,
'double'
,
'bool'
]
allowed_types
=
[
'string'
,
'int'
,
'uint'
,
'short'
,
'ushort'
,
'float'
,
'double'
,
'bool'
]
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
:
#TODO explicit type conversion to check for the right type
#
TODO explicit type conversion to check for the right type
pass
self
.
_simple_fields
.
append
({
'type'
:
type
,
'name'
:
name
,
'displayName'
:
displayName
})
...
...
@@ -963,11 +991,11 @@ class Schema(_BaseObject):
if
self
.
name
:
element
.
set
(
'name'
,
self
.
name
)
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
(
'name'
,
simple_field
[
'name'
])
if
simple_field
.
get
(
'displayName'
):
dn
=
etree
.
SubElement
(
sf
,
"%sdisplayName"
%
self
.
ns
)
dn
=
etree
.
SubElement
(
sf
,
"%sdisplayName"
%
self
.
ns
)
dn
.
text
=
simple_field
[
'displayName'
]
return
element
...
...
@@ -1008,10 +1036,12 @@ class ExtendedData(_XMLObject):
class
UntypedExtendedData
(
ExtendedData
):
def
__init__
(
self
,
ns
=
None
,
elements
=
None
):
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
):
...
...
@@ -1044,10 +1074,17 @@ class Data(_XMLObject):
if
display_name
is
not
None
:
self
.
display_name
=
display_name
.
text
class
UntypedExtendedDataElement
(
Data
):
def
__init__
(
self
,
ns
=
None
,
name
=
None
,
value
=
None
,
display_name
=
None
):
super
(
UntypedExtendedDataElement
,
self
).
__init__
(
ns
,
name
,
value
,
display_name
)
warnings
.
warn
(
"UntypedExtendedDataElement is deprecated use Data instead"
,
DeprecationWarning
)
super
(
UntypedExtendedDataElement
,
self
).
__init__
(
ns
,
name
,
value
,
display_name
)
warnings
.
warn
(
"UntypedExtendedDataElement is deprecated use Data instead"
,
DeprecationWarning
)
class
SchemaData
(
_XMLObject
):
"""
...
...
@@ -1093,7 +1130,7 @@ class SchemaData(_XMLObject):
def
append_data
(
self
,
name
,
value
):
if
isinstance
(
name
,
basestring
)
and
name
:
self
.
_data
.
append
({
'name'
:
name
,
'value'
:
value
})
self
.
_data
.
append
({
'name'
:
name
,
'value'
:
value
})
else
:
raise
TypeError
(
'name must be a nonempty string'
)
...
...
@@ -1101,7 +1138,7 @@ class SchemaData(_XMLObject):
element
=
super
(
SchemaData
,
self
).
etree_element
()
element
.
set
(
'schemaUrl'
,
self
.
schema_url
)
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
.
text
=
data
[
'value'
]
return
element
...
...
@@ -1113,5 +1150,3 @@ class SchemaData(_XMLObject):
simple_data
=
element
.
findall
(
'%sSimpleData'
%
self
.
ns
)
for
sd
in
simple_data
:
self
.
append_data
(
sd
.
get
(
'name'
),
sd
.
text
)
fastkml/styles.py
View file @
365ed6e5
# -*- coding: utf-8 -*-
#
Copyright (C) 2012 Christian Ledermann
# Copyright (C) 2012 Christian Ledermann
#
#
This library is free software; you can redistribute it and/or
#
modify it under the terms of the GNU Lesser General Public
#
License as published by the Free Software Foundation; either
#
version 2.1 of the License, or (at your option) any later version.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# 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,
#
but WITHOUT ANY WARRANTY; without even the implied warranty of
#
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#
Lesser General Public License for more details.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
#
You should have received a copy of the GNU Lesser General Public
#
License along with this library; if not, write to the Free Software
#
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
#
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
"""
Once you've created features within Google Earth and examined the KML
code Google Earth generates, you'll notice how styles are an important
...
...
@@ -23,13 +23,10 @@ part of how your data is displayed.
import
logging
logger
=
logging
.
getLogger
(
'fastkml.styles'
)
import
fastkml.config
as
config
from
fastkml.config
import
etree
from
fastkml.base
import
_BaseObject
class
StyleUrl
(
_BaseObject
):
"""
URL of a <Style> or <StyleMap> defined in a Document. If the style
...
...
@@ -78,7 +75,7 @@ class Style(_StyleSelector):
__name__
=
"Style"
_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
)
self
.
_styles
=
[]
if
styles
:
...
...
@@ -100,27 +97,27 @@ class Style(_StyleSelector):
def
from_element
(
self
,
element
):
super
(
Style
,
self
).
from_element
(
element
)
style
=
element
.
find
(
'%sIconStyle'
%
self
.
ns
)
style
=
element
.
find
(
'%sIconStyle'
%
self
.
ns
)
if
style
is
not
None
:
thestyle
=
IconStyle
(
self
.
ns
)
thestyle
.
from_element
(
style
)
self
.
append_style
(
thestyle
)
style
=
element
.
find
(
'%sLineStyle'
%
self
.
ns
)
style
=
element
.
find
(
'%sLineStyle'
%
self
.
ns
)
if
style
is
not
None
:
thestyle
=
LineStyle
(
self
.
ns
)
thestyle
.
from_element
(
style
)
self
.
append_style
(
thestyle
)
style
=
element
.
find
(
'%sPolyStyle'
%
self
.
ns
)
style
=
element
.
find
(
'%sPolyStyle'
%
self
.
ns
)
if
style
is
not
None
:
thestyle
=
PolyStyle
(
self
.
ns
)
thestyle
.
from_element
(
style
)
self
.
append_style
(
thestyle
)
style
=
element
.
find
(
'%sLabelStyle'
%
self
.
ns
)
style
=
element
.
find
(
'%sLabelStyle'
%
self
.
ns
)
if
style
is
not
None
:
thestyle
=
LabelStyle
(
self
.
ns
)
thestyle
.
from_element
(
style
)
self
.
append_style
(
thestyle
)
style
=
element
.
find
(
'%sBalloonStyle'
%
self
.
ns
)
style
=
element
.
find
(
'%sBalloonStyle'
%
self
.
ns
)
if
style
is
not
None
:
thestyle
=
BalloonStyle
(
self
.
ns
)
thestyle
.
from_element
(
style
)
...
...
@@ -148,14 +145,13 @@ class StyleMap(_StyleSelector):
super
(
StyleMap
,
self
).
__init__
(
ns
,
id
)
pass
def
from_element
(
self
,
element
):
super
(
StyleMap
,
self
).
from_element
(
element
)
pairs
=
element
.
findall
(
'%sPair'
%
self
.
ns
)
pairs
=
element
.
findall
(
'%sPair'
%
self
.
ns
)
for
pair
in
pairs
:
key
=
pair
.
find
(
'%skey'
%
self
.
ns
)
style
=
pair
.
find
(
'%sStyle'
%
self
.
ns
)
style_url
=
pair
.
find
(
'%sstyleUrl'
%
self
.
ns
)
key
=
pair
.
find
(
'%skey'
%
self
.
ns
)
style
=
pair
.
find
(
'%sStyle'
%
self
.
ns
)
style_url
=
pair
.
find
(
'%sstyleUrl'
%
self
.
ns
)
if
key
.
text
==
"highlight"
:
if
style
is
not
None
:
highlight
=
Style
(
self
.
ns
)
...
...
@@ -179,20 +175,18 @@ class StyleMap(_StyleSelector):
else
:
raise
ValueError
def
etree_element
(
self
):
element
=
super
(
StyleMap
,
self
).
etree_element
()
if
self
.
normal
:
if
isinstance
(
self
.
normal
,
(
Style
,
StyleUrl
)):
pair
=
etree
.
SubElement
(
element
,
"%sPair"
%
self
.
ns
)
key
=
etree
.
SubElement
(
pair
,
"%skey"
%
self
.
ns
)
pair
=
etree
.
SubElement
(
element
,
"%sPair"
%
self
.
ns
)
key
=
etree
.
SubElement
(
pair
,
"%skey"
%
self
.
ns
)
key
.
text
=
'normal'
pair
.
append
(
self
.
normal
.
etree_element
())
if
self
.
highlight
:
if
isinstance
(
self
.
highlight
,
(
Style
,
StyleUrl
)):
pair
=
etree
.
SubElement
(
element
,
"%sPair"
%
self
.
ns
)
key
=
etree
.
SubElement
(
pair
,
"%skey"
%
self
.
ns
)
pair
=
etree
.
SubElement
(
element
,
"%sPair"
%
self
.
ns
)
key
=
etree
.
SubElement
(
pair
,
"%skey"
%
self
.
ns
)
key
.
text
=
'highlight'
pair
.
append
(
self
.
highlight
.
etree_element
())
return
element
...
...
@@ -224,27 +218,26 @@ class _ColorStyle(_BaseObject):
self
.
color
=
color
self
.
colorMode
=
colorMode
def
etree_element
(
self
):
element
=
super
(
_ColorStyle
,
self
).
etree_element
()
if
self
.
color
:
color
=
etree
.
SubElement
(
element
,
"%scolor"
%
self
.
ns
)
color
=
etree
.
SubElement
(
element
,
"%scolor"
%
self
.
ns
)
color
.
text
=
self
.
color
if
self
.
colorMode
:
colorMode
=
etree
.
SubElement
(
element
,
"%scolorMode"
%
self
.
ns
)
colorMode
=
etree
.
SubElement
(
element
,
"%scolorMode"
%
self
.
ns
)
colorMode
.
text
=
self
.
colorMode
return
element
def
from_element
(
self
,
element
):
super
(
_ColorStyle
,
self
).
from_element
(
element
)
colorMode
=
element
.
find
(
'%scolorMode'
%
self
.
ns
)
colorMode
=
element
.
find
(
'%scolorMode'
%
self
.
ns
)
if
colorMode
is
not
None
:
self
.
colorMode
=
colorMode
.
text
color
=
element
.
find
(
'%scolor'
%
self
.
ns
)
color
=
element
.
find
(
'%scolor'
%
self
.
ns
)
if
color
is
not
None
:
self
.
color
=
color
.
text
class
IconStyle
(
_ColorStyle
):
""" Specifies how icons for point Placemarks are drawn """
__name__
=
"IconStyle"
...
...
@@ -256,8 +249,10 @@ class IconStyle(_ColorStyle):
icon_href
=
None
# An HTTP address or a local file specification used to load an icon.
def
__init__
(
self
,
ns
=
None
,
id
=
None
,
color
=
None
,
colorMode
=
None
,
scale
=
1.0
,
heading
=
None
,
icon_href
=
None
):
def
__init__
(
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
)
self
.
scale
=
scale
self
.
heading
=
heading
...
...
@@ -266,33 +261,32 @@ class IconStyle(_ColorStyle):
def
etree_element
(
self
):
element
=
super
(
IconStyle
,
self
).
etree_element
()
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
)
if
self
.
heading
:
heading
=
etree
.
SubElement
(
element
,
"%sheading"
%
self
.
ns
)
heading
=
etree
.
SubElement
(
element
,
"%sheading"
%
self
.
ns
)
heading
.
text
=
str
(
self
.
heading
)
if
self
.
icon_href
:
icon
=
etree
.
SubElement
(
element
,
"%sIcon"
%
self
.
ns
)
href
=
etree
.
SubElement
(
icon
,
"%shref"
%
self
.
ns
)
icon
=
etree
.
SubElement
(
element
,
"%sIcon"
%
self
.
ns
)
href
=
etree
.
SubElement
(
icon
,
"%shref"
%
self
.
ns
)
href
.
text
=
self
.
icon_href
return
element
def
from_element
(
self
,
element
):
super
(
IconStyle
,
self
).
from_element
(
element
)
scale
=
element
.
find
(
'%sscale'
%
self
.
ns
)
scale
=
element
.
find
(
'%sscale'
%
self
.
ns
)
if
scale
is
not
None
:
self
.
scale
=
float
(
scale
.
text
)
heading
=
element
.
find
(
'%sheading'
%
self
.
ns
)
heading
=
element
.
find
(
'%sheading'
%
self
.
ns
)
if
heading
is
not
None
:
self
.
heading
=
float
(
heading
.
text
)
icon
=
element
.
find
(
'%sIcon'
%
self
.
ns
)
icon
=
element
.
find
(
'%sIcon'
%
self
.
ns
)
if
icon
is
not
None
:
href
=
icon
.
find
(
'%shref'
%
self
.
ns
)
href
=
icon
.
find
(
'%shref'
%
self
.
ns
)
if
href
is
not
None
:
self
.
icon_href
=
href
.
text
class
LineStyle
(
_ColorStyle
):
"""
Specifies the drawing style (color, color mode, and line width)
...
...
@@ -304,24 +298,26 @@ class LineStyle(_ColorStyle):
width
=
1.0
# Width of the line, in pixels.
def
__init__
(
self
,
ns
=
None
,
id
=
None
,
color
=
None
,
colorMode
=
None
,
width
=
1
):
def
__init__
(
self
,
ns
=
None
,
id
=
None
,
color
=
None
,
colorMode
=
None
,
width
=
1
):
super
(
LineStyle
,
self
).
__init__
(
ns
,
id
,
color
,
colorMode
)
self
.
width
=
width
def
etree_element
(
self
):
element
=
super
(
LineStyle
,
self
).
etree_element
()
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
)
return
element
def
from_element
(
self
,
element
):
super
(
LineStyle
,
self
).
from_element
(
element
)
width
=
element
.
find
(
'%swidth'
%
self
.
ns
)
width
=
element
.
find
(
'%swidth'
%
self
.
ns
)
if
width
is
not
None
:
self
.
width
=
float
(
width
.
text
)
class
PolyStyle
(
_ColorStyle
):
"""
Specifies the drawing style for all polygons, including polygon
...
...
@@ -335,8 +331,9 @@ class PolyStyle(_ColorStyle):
# Boolean value. Specifies whether to outline the polygon.
# Polygon outlines use the current LineStyle.
def
__init__
(
self
,
ns
=
None
,
id
=
None
,
color
=
None
,
colorMode
=
None
,
fill
=
1
,
outline
=
1
):
def
__init__
(
self
,
ns
=
None
,
id
=
None
,
color
=
None
,
colorMode
=
None
,
fill
=
1
,
outline
=
1
):
super
(
PolyStyle
,
self
).
__init__
(
ns
,
id
,
color
,
colorMode
)
self
.
fill
=
fill
self
.
outline
=
outline
...
...
@@ -344,19 +341,19 @@ class PolyStyle(_ColorStyle):
def
etree_element
(
self
):
element
=
super
(
PolyStyle
,
self
).
etree_element
()
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
)
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
)
return
element
def
from_element
(
self
,
element
):
super
(
PolyStyle
,
self
).
from_element
(
element
)
fill
=
element
.
find
(
'%sfill'
%
self
.
ns
)
fill
=
element
.
find
(
'%sfill'
%
self
.
ns
)
if
fill
is
not
None
:
self
.
fill
=
int
(
fill
.
text
)
outline
=
element
.
find
(
'%soutline'
%
self
.
ns
)
outline
=
element
.
find
(
'%soutline'
%
self
.
ns
)
if
outline
is
not
None
:
self
.
outline
=
int
(
outline
.
text
)
...
...
@@ -369,24 +366,26 @@ class LabelStyle(_ColorStyle):
scale
=
1.0
# Resizes the label.
def
__init__
(
self
,
ns
=
None
,
id
=
None
,
color
=
None
,
colorMode
=
None
,
scale
=
1.0
):
def
__init__
(
self
,
ns
=
None
,
id
=
None
,
color
=
None
,
colorMode
=
None
,
scale
=
1.0
):
super
(
LabelStyle
,
self
).
__init__
(
ns
,
id
,
color
,
colorMode
)
self
.
scale
=
scale
def
etree_element
(
self
):
element
=
super
(
LabelStyle
,
self
).
etree_element
()
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
)
return
element
def
from_element
(
self
,
element
):
super
(
LabelStyle
,
self
).
from_element
(
element
)
scale
=
element
.
find
(
'%sscale'
%
self
.
ns
)
scale
=
element
.
find
(
'%sscale'
%
self
.
ns
)
if
scale
is
not
None
:
self
.
scale
=
float
(
scale
.
text
)
class
BalloonStyle
(
_BaseObject
):
""" Specifies how the description balloon for placemarks is drawn.
The <bgColor>, if specified, is used as the background color of
...
...
@@ -395,15 +394,15 @@ class BalloonStyle(_BaseObject):
__name__
=
"BalloonStyle"
bgColor
=
None
#Background color of the balloon (optional). Color and opacity (alpha)
#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
#
Background color of the balloon (optional). Color and opacity (alpha)
#
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
# aabbggrr, where aa=alpha (00 to ff); bb=blue (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 example, if you want to apply a blue color with 50 percent
# 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).
# Note: The use of the <color> element within <BalloonStyle> has been
# deprecated. Use <bgColor> instead.
...
...
@@ -412,33 +411,36 @@ class BalloonStyle(_BaseObject):
# Foreground color for text. The default is black (ff000000).
text
=
None
#Text displayed in the balloon. If no text is specified, Google Earth
#draws the default balloon (with the Feature <name> in boldface,
#the Feature <description>, links for driving directions, a white
#background, and a tail that is attached to the point coordinates of
#the Feature, if specified).
#You can add entities to the <text> tag using the following format to
#refer to a child element of Feature: $[name], $[description], $[address],
#$[id], $[Snippet]. Google Earth looks in the current Feature for the
#corresponding string entity and substitutes that information in the balloon.
#To include To here - From here driving directions in the balloon,
#use the $[geDirections] tag. To prevent the driving directions links
#from appearing in a balloon, include the <text> element with some content,
#or with $[description] to substitute the basic Feature <description>.
#For example, in the following KML excerpt, $[name] and $[description]
#fields will be replaced by the <name> and <description> fields found
#in the Feature elements that use this BalloonStyle:
#<text>This is $[name], whose description is:<br/>$[description]</text>
# Text displayed in the balloon. If no text is specified, Google Earth
# draws the default balloon (with the Feature <name> in boldface,
# the Feature <description>, links for driving directions, a white
# background, and a tail that is attached to the point coordinates of
# the Feature, if specified).
# You can add entities to the <text> tag using the following format to
# refer to a child element of Feature: $[name], $[description], $[address],
# $[id], $[Snippet]. Google Earth looks in the current Feature for the
# corresponding string entity and substitutes that information in the
# balloon.
# To include To here - From here driving directions in the balloon,
# use the $[geDirections] tag. To prevent the driving directions links
# from appearing in a balloon, include the <text> element with some content
# or with $[description] to substitute the basic Feature <description>.
# For example, in the following KML excerpt, $[name] and $[description]
# fields will be replaced by the <name> and <description> fields found
# in the Feature elements that use this BalloonStyle:
# <text>This is $[name], whose description is:<br/>$[description]</text>
displayMode
=
None
#If <displayMode> is default, Google Earth uses the information supplied
#in <text> to create a balloon . If <displayMode> is hide, Google Earth
#does not display the balloon. In Google Earth, clicking the List View
#icon for a Placemark whose balloon's <displayMode> is hide causes
#Google Earth to fly to the Placemark.
def
__init__
(
self
,
ns
=
None
,
id
=
None
,
bgColor
=
None
,
textColor
=
None
,
text
=
None
,
displayMode
=
None
):
# If <displayMode> is default, Google Earth uses the information supplied
# in <text> to create a balloon . If <displayMode> is hide, Google Earth
# does not display the balloon. In Google Earth, clicking the List View
# icon for a Placemark whose balloon's <displayMode> is hide causes
# Google Earth to fly to the Placemark.
def
__init__
(
self
,
ns
=
None
,
id
=
None
,
bgColor
=
None
,
textColor
=
None
,
text
=
None
,
displayMode
=
None
):
super
(
BalloonStyle
,
self
).
__init__
(
ns
,
id
)
self
.
bgColor
=
bgColor
self
.
textColor
=
textColor
...
...
@@ -447,35 +449,35 @@ class BalloonStyle(_BaseObject):
def
from_element
(
self
,
element
):
super
(
BalloonStyle
,
self
).
from_element
(
element
)
bgColor
=
element
.
find
(
'%sbgColor'
%
self
.
ns
)
bgColor
=
element
.
find
(
'%sbgColor'
%
self
.
ns
)
if
bgColor
is
not
None
:
self
.
bgColor
=
bgColor
.
text
else
:
bgColor
=
element
.
find
(
'%scolor'
%
self
.
ns
)
bgColor
=
element
.
find
(
'%scolor'
%
self
.
ns
)
if
bgColor
is
not
None
:
self
.
bgColor
=
bgColor
.
text
textColor
=
element
.
find
(
'%stextColor'
%
self
.
ns
)
textColor
=
element
.
find
(
'%stextColor'
%
self
.
ns
)
if
textColor
is
not
None
:
self
.
textColor
=
textColor
.
text
text
=
element
.
find
(
'%stext'
%
self
.
ns
)
text
=
element
.
find
(
'%stext'
%
self
.
ns
)
if
text
is
not
None
:
self
.
text
=
text
.
text
displayMode
=
element
.
find
(
'%sdisplayMode'
%
self
.
ns
)
displayMode
=
element
.
find
(
'%sdisplayMode'
%
self
.
ns
)
if
displayMode
is
not
None
:
self
.
displayMode
=
displayMode
.
text
def
etree_element
(
self
):
element
=
super
(
BalloonStyle
,
self
).
etree_element
()
if
self
.
bgColor
is
not
None
:
elem
=
etree
.
SubElement
(
element
,
"%sbgColor"
%
self
.
ns
)
elem
=
etree
.
SubElement
(
element
,
"%sbgColor"
%
self
.
ns
)
elem
.
text
=
self
.
bgColor
if
self
.
textColor
is
not
None
:
elem
=
etree
.
SubElement
(
element
,
"%stextColor"
%
self
.
ns
)
elem
=
etree
.
SubElement
(
element
,
"%stextColor"
%
self
.
ns
)
elem
.
text
=
self
.
textColor
if
self
.
text
is
not
None
:
elem
=
etree
.
SubElement
(
element
,
"%stext"
%
self
.
ns
)
elem
=
etree
.
SubElement
(
element
,
"%stext"
%
self
.
ns
)
elem
.
text
=
self
.
text
if
self
.
displayMode
is
not
None
:
elem
=
etree
.
SubElement
(
element
,
"%sdisplayMode"
%
self
.
ns
)
elem
=
etree
.
SubElement
(
element
,
"%sdisplayMode"
%
self
.
ns
)
elem
.
text
=
self
.
displayMode
return
element
fastkml/test_main.py
View file @
365ed6e5
# -*- coding: utf-8 -*-
#
Copyright (C) 2012 Christian Ledermann
# Copyright (C) 2012 Christian Ledermann
#
#
This library is free software; you can redistribute it and/or
#
modify it under the terms of the GNU Lesser General Public
#
License as published by the Free Software Foundation; either
#
version 2.1 of the License, or (at your option) any later version.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# 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,
#
but WITHOUT ANY WARRANTY; without even the implied warranty of
#
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#
Lesser General Public License for more details.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
#
You should have received a copy of the GNU Lesser General Public
#
License along with this library; if not, write to the Free Software
#
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
#
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
import
unittest
...
...
@@ -23,7 +23,6 @@ from fastkml import base
from
fastkml
import
atom
from
fastkml
import
config
import
datetime
from
dateutil.tz
import
tzutc
,
tzoffset
...
...
@@ -33,7 +32,6 @@ from fastkml.geometry import Point, LineString, Polygon
from
fastkml.geometry
import
MultiPoint
,
MultiLineString
,
MultiPolygon
from
fastkml.geometry
import
LinearRing
,
GeometryCollection
from
fastkml.geometry
import
Geometry
from
fastkml.geometry
import
asShape
class
BaseClassesTestCase
(
unittest
.
TestCase
):
...
...
@@ -48,8 +46,8 @@ class BaseClassesTestCase(unittest.TestCase):
self
.
assertEqual
(
bo
.
__name__
,
None
)
bo
.
targetId
=
'target'
self
.
assertEqual
(
bo
.
targetId
,
'target'
)
bo
.
ns
=
''
bo
.
id
=
None
bo
.
ns
=
''
bo
.
id
=
None
self
.
assertEqual
(
bo
.
id
,
None
)
self
.
assertEqual
(
bo
.
ns
,
''
)
self
.
assertRaises
(
NotImplementedError
,
bo
.
etree_element
)
...
...
@@ -58,7 +56,7 @@ class BaseClassesTestCase(unittest.TestCase):
self
.
assertRaises
(
TypeError
,
bo
.
from_element
,
element
)
bo
.
__name__
=
'NotABaseObject'
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
.
ns
=
config
.
NS
bo
.
from_element
(
element
)
...
...
@@ -75,23 +73,22 @@ class BaseClassesTestCase(unittest.TestCase):
self
.
assertEqual
(
f
.
isopen
,
0
)
self
.
assertEqual
(
f
.
_atom_author
,
None
)
self
.
assertEqual
(
f
.
_atom_link
,
None
)
#self.assertEqual(f.address, None)
#self.assertEqual(f.phoneNumber, None)
#
self.assertEqual(f.address, None)
#
self.assertEqual(f.phoneNumber, None)
self
.
assertEqual
(
f
.
_snippet
,
None
)
self
.
assertEqual
(
f
.
description
,
None
)
self
.
assertEqual
(
f
.
_styleUrl
,
None
)
self
.
assertEqual
(
f
.
_styles
,
[])
self
.
assertEqual
(
f
.
_time_span
,
None
)
self
.
assertEqual
(
f
.
_time_stamp
,
None
)
#self.assertEqual(f.region, None)
#self.assertEqual(f.extended_data, None)
#
self.assertEqual(f.region, None)
#
self.assertEqual(f.extended_data, None)
f
.
__name__
=
'Feature'
f
.
styleUrl
=
'#default'
self
.
assertTrue
(
'Feature>'
in
str
(
f
.
to_string
()))
self
.
assertTrue
(
'#default'
in
str
(
f
.
to_string
()))
def
test_Container
(
self
):
f
=
kml
.
_Container
(
name
=
'A Container'
)
d
=
kml
.
Document
()
...
...
@@ -100,7 +97,6 @@ class BaseClassesTestCase(unittest.TestCase):
f
.
append
(
p
)
self
.
assertRaises
(
NotImplementedError
,
f
.
etree_element
)
def
test_TimePrimitive
(
self
):
pass
...
...
@@ -113,22 +109,29 @@ class BaseClassesTestCase(unittest.TestCase):
def
test_Person
(
self
):
pass
class
BuildKmlTestCase
(
unittest
.
TestCase
):
""" Build a simple KML File """
def
test_kml
(
self
):
""" kml file without contents """
k
=
kml
.
KML
()
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
0
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
0
)
if
config
.
LXML
:
self
.
assertEqual
(
str
(
k
.
to_string
())[:
43
],
'<kml xmlns="http://www.opengis.net/kml/2.2"/>'
[:
43
])
self
.
assertEqual
(
str
(
k
.
to_string
())[:
43
],
'<kml xmlns="http://www.opengis.net/kml/2.2"/>'
[:
43
]
)
else
:
if
hasattr
(
etree
,
'register_namespace'
):
self
.
assertEqual
(
str
(
k
.
to_string
())[:
51
],
'<kml:kml xmlns:kml="http://www.opengis.net/kml/2.2" />'
[:
51
])
self
.
assertEqual
(
str
(
k
.
to_string
())[:
51
],
'<kml:kml xmlns:kml="http://www.opengis.net/kml/2.2" />'
[:
51
]
)
else
:
self
.
assertEqual
(
str
(
k
.
to_string
())[:
51
],
'<ns0:kml xmlns:ns0="http://www.opengis.net/kml/2.2" />'
[:
51
])
self
.
assertEqual
(
str
(
k
.
to_string
())[:
51
],
'<ns0:kml xmlns:ns0="http://www.opengis.net/kml/2.2" />'
[:
51
]
)
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
())
...
...
@@ -144,14 +147,13 @@ class BuildKmlTestCase(unittest.TestCase):
k
.
append
(
f
)
f2
=
kml
.
Folder
(
ns
,
'id2'
,
'name2'
,
'description2'
)
k
.
append
(
f2
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
2
)
self
.
assertEqual
(
len
(
list
(
list
(
k
.
features
())[
0
].
features
())),
1
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
2
)
self
.
assertEqual
(
len
(
list
(
list
(
k
.
features
())[
0
].
features
())),
1
)
k2
=
kml
.
KML
()
s
=
k
.
to_string
()
k2
.
from_string
(
s
)
self
.
assertEqual
(
s
,
k2
.
to_string
())
def
test_placemark
(
self
):
ns
=
'{http://www.opengis.net/kml/2.2}'
k
=
kml
.
KML
(
ns
=
ns
)
...
...
@@ -161,7 +163,7 @@ class BuildKmlTestCase(unittest.TestCase):
p2
.
geometry
=
LineString
([(
0
,
0
,
0
),
(
1
,
1
,
1
)])
k
.
append
(
p
)
k
.
append
(
p2
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
2
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
2
)
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
(
prettyprint
=
True
))
self
.
assertEqual
(
k
.
to_string
(),
k2
.
to_string
())
...
...
@@ -170,15 +172,15 @@ class BuildKmlTestCase(unittest.TestCase):
ns
=
'{http://www.opengis.net/kml/2.2}'
self
.
assertRaises
(
ValueError
,
kml
.
Schema
,
ns
)
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'
)
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
][
'displayName'
],
'An Integer'
)
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
.
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'
))
fields
=
{
'type'
:
'int'
,
'name'
:
'Integer'
,
'displayName'
:
'An Integer'
}
s
.
simple_fields
=
fields
...
...
@@ -193,7 +195,6 @@ class BuildKmlTestCase(unittest.TestCase):
self
.
assertEqual
(
list
(
s
.
simple_fields
)[
1
][
'name'
],
'Integer'
)
self
.
assertEqual
(
list
(
s
.
simple_fields
)[
1
][
'displayName'
],
'An Integer'
)
def
test_schema_data
(
self
):
ns
=
'{http://www.opengis.net/kml/2.2}'
self
.
assertRaises
(
ValueError
,
kml
.
SchemaData
,
ns
)
...
...
@@ -211,7 +212,6 @@ class BuildKmlTestCase(unittest.TestCase):
self
.
assertEqual
(
sd
.
data
[
0
],
{
'value'
:
'Some new Text'
,
'name'
:
'text'
})
self
.
assertEqual
(
sd
.
data
[
1
],
{
'value'
:
2
,
'name'
:
'Integer'
})
def
test_untyped_extended_data
(
self
):
ns
=
'{http://www.opengis.net/kml/2.2}'
k
=
kml
.
KML
(
ns
=
ns
)
...
...
@@ -244,7 +244,6 @@ class BuildKmlTestCase(unittest.TestCase):
self
.
assertEqual
(
extended_data
.
elements
[
1
].
value
,
'blue skies'
)
self
.
assertEqual
(
extended_data
.
elements
[
1
].
display_name
,
'Weather'
)
def
test_untyped_extended_data_nested
(
self
):
ns
=
'{http://www.opengis.net/kml/2.2}'
k
=
kml
.
KML
(
ns
=
ns
)
...
...
@@ -274,7 +273,6 @@ class BuildKmlTestCase(unittest.TestCase):
self
.
assertEqual
(
folder_data
.
elements
[
0
].
name
,
'type'
)
self
.
assertEqual
(
folder_data
.
elements
[
0
].
value
,
'Folder'
)
def
test_document
(
self
):
k
=
kml
.
KML
()
ns
=
'{http://www.opengis.net/kml/2.2}'
...
...
@@ -287,21 +285,18 @@ class BuildKmlTestCase(unittest.TestCase):
f2
=
kml
.
Folder
(
ns
,
'id2'
,
'name2'
,
'description2'
)
d
.
append
(
f2
)
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 does not have a geometry!
#
p2 does not have a geometry!
f2
.
append
(
p
)
nf
.
append
(
p2
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertEqual
(
len
(
list
((
list
(
k
.
features
())[
0
].
features
()))),
2
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertEqual
(
len
(
list
((
list
(
k
.
features
())[
0
].
features
()))),
2
)
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
())
self
.
assertEqual
(
k
.
to_string
(),
k2
.
to_string
())
def
test_author
(
self
):
k
=
kml
.
KML
()
d
=
kml
.
Document
()
d
.
author
=
'Christian Ledermann'
self
.
assertTrue
(
'Christian Ledermann'
in
str
(
d
.
to_string
()))
...
...
@@ -316,8 +311,6 @@ class BuildKmlTestCase(unittest.TestCase):
d2
.
from_string
(
d
.
to_string
())
self
.
assertEqual
(
d
.
to_string
(),
d2
.
to_string
())
d
.
author
=
None
#print (d.to_string())
def
test_link
(
self
):
d
=
kml
.
Document
()
...
...
@@ -332,8 +325,8 @@ class BuildKmlTestCase(unittest.TestCase):
self
.
assertEqual
(
d
.
to_string
(),
d2
.
to_string
())
d
.
link
=
None
class
KmlFromStringTestCase
(
unittest
.
TestCase
):
class
KmlFromStringTestCase
(
unittest
.
TestCase
):
def
test_document
(
self
):
doc
=
"""<kml xmlns="http://www.opengis.net/kml/2.2">
<Document targetId="someTargetId">
...
...
@@ -362,16 +355,14 @@ class KmlFromStringTestCase( unittest.TestCase ):
</kml>"""
k
=
kml
.
KML
()
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertEqual
(
len
(
list
(
list
(
k
.
features
())[
0
].
features
())),
2
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertEqual
(
len
(
list
(
list
(
k
.
features
())[
0
].
features
())),
2
)
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
())
self
.
assertEqual
(
k
.
to_string
(),
k2
.
to_string
())
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>
<name>Folder.kml</name>
<open>1</open>
...
...
@@ -412,15 +403,14 @@ class KmlFromStringTestCase( unittest.TestCase ):
</kml>"""
k
=
kml
.
KML
()
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertEqual
(
len
(
list
(
list
(
k
.
features
())[
0
].
features
())),
3
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertEqual
(
len
(
list
(
list
(
k
.
features
())[
0
].
features
())),
3
)
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
())
self
.
assertEqual
(
k
.
to_string
(),
k2
.
to_string
())
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>
<name>Simple placemark</name>
<description>Attached to the ground. Intelligently places itself
...
...
@@ -432,15 +422,14 @@ class KmlFromStringTestCase( unittest.TestCase ):
</kml>"""
k
=
kml
.
KML
()
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"
)
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
())
self
.
assertEqual
(
k
.
to_string
(),
k2
.
to_string
())
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>
<name>Simple placemark</name>
<description></description>
...
...
@@ -489,23 +478,132 @@ class KmlFromStringTestCase( unittest.TestCase ):
self
.
assertEqual
(
sd
.
data
[
1
][
'value'
],
'347.45'
)
def
test_polygon
(
self
):
doc
=
"""<kml xmlns="http://www.opengis.net/kml/2.2">
<Placemark>
<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>
</Placemark> </kml>"""
doc
=
"""
<kml xmlns="http://www.opengis.net/kml/2.2">
<Placemark>
<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>
</Placemark>
</kml>"""
k
=
kml
.
KML
()
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
k
.
features
())[
0
].
geometry
,
Polygon
))
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
k
.
features
())[
0
].
geometry
,
Polygon
)
)
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
())
self
.
assertEqual
(
k
.
to_string
(),
k2
.
to_string
())
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">
<name>MultiPoint</name>
<styleUrl>#stylesel_9</styleUrl>
...
...
@@ -550,18 +648,17 @@ class KmlFromStringTestCase( unittest.TestCase ):
</Placemark></kml>"""
k
=
kml
.
KML
()
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
k
.
features
())[
0
].
geometry
,
MultiPoint
))
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
k
.
features
())[
0
].
geometry
,
MultiPoint
)
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())[
0
].
geometry
.
geoms
),
12
)
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
())
self
.
assertEqual
(
k
.
to_string
(),
k2
.
to_string
())
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>
<name>Dnipro (Dnieper)</name>
<MultiGeometry>
...
...
@@ -573,15 +670,15 @@ class KmlFromStringTestCase( unittest.TestCase ):
</Placemark> </kml>"""
k
=
kml
.
KML
()
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
k
.
features
())[
0
].
geometry
,
MultiLineString
))
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
k
.
features
())[
0
].
geometry
,
MultiLineString
)
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())[
0
].
geometry
.
geoms
),
4
)
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
())
self
.
assertEqual
(
k
.
to_string
(),
k2
.
to_string
())
def
test_multipolygon
(
self
):
doc
=
"""<kml xmlns="http://www.opengis.net/kml/2.2">
<Placemark>
...
...
@@ -590,9 +687,10 @@ class KmlFromStringTestCase( unittest.TestCase ):
</Placemark> </kml>"""
k
=
kml
.
KML
()
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
k
.
features
())[
0
].
geometry
,
MultiPolygon
))
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
k
.
features
())[
0
].
geometry
,
MultiPolygon
)
)
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
())
self
.
assertEqual
(
k
.
to_string
(),
k2
.
to_string
())
...
...
@@ -665,7 +763,6 @@ class KmlFromStringTestCase( unittest.TestCase ):
self
.
assertEqual
(
sd1
.
schema_url
,
'#TrailHeadTypeId'
)
self
.
assertEqual
(
sd
.
to_string
(),
sd1
.
to_string
())
def
test_snippet
(
self
):
doc
=
"""<kml xmlns="http://www.opengis.net/kml/2.2">
<Placemark>
...
...
@@ -690,8 +787,7 @@ class KmlFromStringTestCase( unittest.TestCase ):
self
.
assertRaises
(
TypeError
,
doc
.
from_string
,
'<xml></xml>'
)
class
StyleTestCase
(
unittest
.
TestCase
):
class
StyleTestCase
(
unittest
.
TestCase
):
def
test_styleurl
(
self
):
f
=
kml
.
Document
()
f
.
styleUrl
=
'#somestyle'
...
...
@@ -707,8 +803,8 @@ class StyleTestCase( unittest.TestCase ):
def
test_style
(
self
):
lstyle
=
styles
.
LineStyle
(
color
=
'red'
,
width
=
2.0
)
style
=
styles
.
Style
(
styles
=
[
lstyle
])
f
=
kml
.
Document
(
styles
=
[
style
])
style
=
styles
.
Style
(
styles
=
[
lstyle
])
f
=
kml
.
Document
(
styles
=
[
style
])
f2
=
kml
.
Document
()
f2
.
from_string
(
f
.
to_string
(
prettyprint
=
True
))
self
.
assertEqual
(
f
.
to_string
(),
f2
.
to_string
())
...
...
@@ -769,8 +865,7 @@ class StyleUsageTestCase(unittest.TestCase):
self
.
assertEqual
(
place
.
to_string
(),
place3
.
to_string
())
class
StyleFromStringTestCase
(
unittest
.
TestCase
):
class
StyleFromStringTestCase
(
unittest
.
TestCase
):
def
test_styleurl
(
self
):
doc
=
"""<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
...
...
@@ -781,13 +876,12 @@ class StyleFromStringTestCase( unittest.TestCase ):
</kml>"""
k
=
kml
.
KML
()
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'
)
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
())
self
.
assertEqual
(
k
.
to_string
(),
k2
.
to_string
())
def
test_balloonstyle
(
self
):
doc
=
"""<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
...
...
@@ -816,9 +910,10 @@ class StyleFromStringTestCase( unittest.TestCase ):
</kml>"""
k
=
kml
.
KML
()
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
],
styles
.
Style
))
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
],
styles
.
Style
)
)
style
=
list
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
].
styles
())[
0
]
self
.
assertTrue
(
isinstance
(
style
,
styles
.
BalloonStyle
))
self
.
assertEqual
(
style
.
bgColor
,
'ffffffbb'
)
...
...
@@ -844,9 +939,10 @@ class StyleFromStringTestCase( unittest.TestCase ):
</kml>"""
k
=
kml
.
KML
()
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
],
styles
.
Style
))
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
],
styles
.
Style
)
)
style
=
list
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
].
styles
())[
0
]
self
.
assertTrue
(
isinstance
(
style
,
styles
.
LabelStyle
))
self
.
assertEqual
(
style
.
color
,
'ff0000cc'
)
...
...
@@ -855,7 +951,6 @@ class StyleFromStringTestCase( unittest.TestCase ):
k2
.
from_string
(
k
.
to_string
())
self
.
assertEqual
(
k
.
to_string
(),
k2
.
to_string
())
def
test_iconstyle
(
self
):
doc
=
"""<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
...
...
@@ -874,9 +969,10 @@ class StyleFromStringTestCase( unittest.TestCase ):
</kml>"""
k
=
kml
.
KML
()
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
list
((
k
.
features
()))),
1
)
self
.
assertTrue
(
isinstance
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
],
styles
.
Style
))
self
.
assertEqual
(
len
(
list
((
k
.
features
()))),
1
)
self
.
assertTrue
(
isinstance
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
],
styles
.
Style
)
)
style
=
list
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
].
styles
())[
0
]
self
.
assertTrue
(
isinstance
(
style
,
styles
.
IconStyle
))
self
.
assertEqual
(
style
.
color
,
'ff00ff00'
)
...
...
@@ -888,9 +984,8 @@ class StyleFromStringTestCase( unittest.TestCase ):
k2
.
from_string
(
k
.
to_string
())
self
.
assertEqual
(
k
.
to_string
(),
k2
.
to_string
())
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>
<name>LineStyle.kml</name>
<open>1</open>
...
...
@@ -904,9 +999,10 @@ class StyleFromStringTestCase( unittest.TestCase ):
</kml>"""
k
=
kml
.
KML
()
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
],
styles
.
Style
))
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
],
styles
.
Style
)
)
style
=
list
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
].
styles
())[
0
]
self
.
assertTrue
(
isinstance
(
style
,
styles
.
LineStyle
))
self
.
assertEqual
(
style
.
color
,
'7f0000ff'
)
...
...
@@ -915,9 +1011,8 @@ class StyleFromStringTestCase( unittest.TestCase ):
k2
.
from_string
(
k
.
to_string
())
self
.
assertEqual
(
k
.
to_string
(),
k2
.
to_string
())
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>
<name>PolygonStyle.kml</name>
<open>1</open>
...
...
@@ -929,12 +1024,13 @@ class StyleFromStringTestCase( unittest.TestCase ):
</Style>
</Document>
</kml>"""
#XXX fill and outline
#
XXX fill and outline
k
=
kml
.
KML
()
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
],
styles
.
Style
))
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
],
styles
.
Style
)
)
style
=
list
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
].
styles
())[
0
]
self
.
assertTrue
(
isinstance
(
style
,
styles
.
PolyStyle
))
self
.
assertEqual
(
style
.
color
,
'ff0000cc'
)
...
...
@@ -943,9 +1039,8 @@ class StyleFromStringTestCase( unittest.TestCase ):
k2
.
from_string
(
k
.
to_string
())
self
.
assertEqual
(
k
.
to_string
(),
k2
.
to_string
())
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>
<!-- Begin Style Definitions -->
<Style id="myDefaultStyles">
...
...
@@ -974,9 +1069,10 @@ class StyleFromStringTestCase( unittest.TestCase ):
</kml>"""
k
=
kml
.
KML
()
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
],
styles
.
Style
))
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
],
styles
.
Style
)
)
style
=
list
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
].
styles
())
self
.
assertEqual
(
len
(
style
),
4
)
k2
=
kml
.
KML
()
...
...
@@ -984,7 +1080,7 @@ class StyleFromStringTestCase( unittest.TestCase ):
self
.
assertEqual
(
k
.
to_string
(),
k2
.
to_string
())
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>
<StyleMap id="styleMapExample">
<Pair>
...
...
@@ -1000,21 +1096,21 @@ class StyleFromStringTestCase( unittest.TestCase ):
</kml>"""
k
=
kml
.
KML
()
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
],
styles
.
StyleMap
))
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
],
styles
.
StyleMap
)
)
sm
=
list
(
list
(
list
(
k
.
features
())[
0
].
styles
()))[
0
]
self
.
assertTrue
(
isinstance
(
sm
.
normal
,
styles
.
StyleUrl
))
self
.
assertEqual
(
sm
.
normal
.
url
,
'#normalState'
)
self
.
assertTrue
(
isinstance
(
sm
.
highlight
,
styles
.
StyleUrl
))
self
.
assertEqual
(
sm
.
highlight
.
url
,
'#highlightState'
)
k2
=
kml
.
KML
()
ks
=
k
.
to_string
()
k2
.
from_string
(
k
.
to_string
())
self
.
assertEqual
(
k
.
to_string
(),
k2
.
to_string
())
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>
<StyleMap id="styleMapExample">
<Pair>
...
...
@@ -1043,9 +1139,10 @@ class StyleFromStringTestCase( unittest.TestCase ):
</kml>"""
k
=
kml
.
KML
()
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
],
styles
.
StyleMap
))
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertTrue
(
isinstance
(
list
(
list
(
k
.
features
())[
0
].
styles
())[
0
],
styles
.
StyleMap
)
)
sm
=
list
(
list
(
list
(
k
.
features
())[
0
].
styles
()))[
0
]
self
.
assertTrue
(
isinstance
(
sm
.
normal
,
styles
.
Style
))
self
.
assertEqual
(
len
(
list
(
sm
.
normal
.
styles
())),
1
)
...
...
@@ -1089,7 +1186,7 @@ class StyleFromStringTestCase( unittest.TestCase ):
</kml>"""
k
=
kml
.
KML
()
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
self
.
assertEqual
(
len
(
list
(
k
.
features
())),
1
)
document
=
list
(
k
.
features
())[
0
]
style
=
document
.
get_style_by_url
(
'http://localhost:8080/somepath#exampleStyleDocument'
)
self
.
assertTrue
(
isinstance
(
list
(
style
.
styles
())[
0
],
styles
.
LabelStyle
))
...
...
@@ -1099,8 +1196,7 @@ class StyleFromStringTestCase( unittest.TestCase ):
self
.
assertTrue
(
isinstance
(
style
,
styles
.
StyleMap
))
class
DateTimeTestCase
(
unittest
.
TestCase
):
class
DateTimeTestCase
(
unittest
.
TestCase
):
def
test_timestamp
(
self
):
now
=
datetime
.
datetime
.
now
()
...
...
@@ -1109,12 +1205,11 @@ class DateTimeTestCase( unittest.TestCase ):
self
.
assertTrue
(
'TimeStamp>'
in
str
(
ts
.
to_string
()))
self
.
assertTrue
(
'when>'
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
)
self
.
assertEqual
(
ts
.
timestamp
,
[
y2k
,
'date'
])
self
.
assertTrue
(
'2000-01-01'
in
str
(
ts
.
to_string
()))
def
test_timestamp_resolution
(
self
):
now
=
datetime
.
datetime
.
now
()
ts
=
kml
.
TimeStamp
(
timestamp
=
now
)
...
...
@@ -1133,10 +1228,9 @@ class DateTimeTestCase( unittest.TestCase ):
ts
.
timestamp
=
None
self
.
assertRaises
(
TypeError
,
ts
.
to_string
)
def
test_timespan
(
self
):
now
=
datetime
.
datetime
.
now
()
y2k
=
datetime
.
datetime
(
2000
,
1
,
1
)
y2k
=
datetime
.
datetime
(
2000
,
1
,
1
)
ts
=
kml
.
TimeSpan
(
end
=
now
,
begin
=
y2k
)
self
.
assertEqual
(
ts
.
end
,
[
now
,
'dateTime'
])
self
.
assertEqual
(
ts
.
begin
,
[
y2k
,
'dateTime'
])
...
...
@@ -1151,7 +1245,6 @@ class DateTimeTestCase( unittest.TestCase ):
ts
.
begin
=
None
self
.
assertRaises
(
ValueError
,
ts
.
to_string
)
def
test_feature_timestamp
(
self
):
now
=
datetime
.
datetime
.
now
()
f
=
kml
.
Document
()
...
...
@@ -1168,7 +1261,7 @@ class DateTimeTestCase( unittest.TestCase ):
def
test_feature_timespan
(
self
):
now
=
datetime
.
datetime
.
now
()
y2k
=
datetime
.
date
(
2000
,
1
,
1
)
y2k
=
datetime
.
date
(
2000
,
1
,
1
)
f
=
kml
.
Document
()
f
.
begin
=
y2k
f
.
end
=
now
...
...
@@ -1190,7 +1283,7 @@ class DateTimeTestCase( unittest.TestCase ):
def
test_feature_timespan_stamp
(
self
):
now
=
datetime
.
datetime
.
now
()
y2k
=
datetime
.
date
(
2000
,
1
,
1
)
y2k
=
datetime
.
date
(
2000
,
1
,
1
)
f
=
kml
.
Document
()
f
.
begin
=
y2k
f
.
end
=
now
...
...
@@ -1219,7 +1312,7 @@ class DateTimeTestCase( unittest.TestCase ):
self
.
assertTrue
(
'end>'
in
str
(
f
.
to_string
()))
self
.
assertFalse
(
'TimeStamp>'
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
)
f
.
_time_stamp
=
ts
# this raises an exception as only either timespan or timestamp
...
...
@@ -1228,55 +1321,55 @@ class DateTimeTestCase( unittest.TestCase ):
def
test_read_timestamp
(
self
):
ts
=
kml
.
TimeStamp
(
ns
=
''
)
doc
=
"""
doc
=
"""
<TimeStamp>
<when>1997</when>
</TimeStamp>
"""
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
))
doc
=
"""
doc
=
"""
<TimeStamp>
<when>1997-07</when>
</TimeStamp>
"""
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
))
doc
=
"""
doc
=
"""
<TimeStamp>
<when>199808</when>
</TimeStamp>
"""
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
))
doc
=
"""
doc
=
"""
<TimeStamp>
<when>1997-07-16</when>
</TimeStamp>
"""
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
))
#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.)
doc
=
"""
#
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.)
doc
=
"""
<TimeStamp>
<when>1997-07-16T07:30:15Z</when>
</TimeStamp>
"""
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
()))
doc
=
"""
doc
=
"""
<TimeStamp>
<when>1997-07-16T10:30:15+03:00</when>
</TimeStamp>
"""
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
,
10
,
30
,
15
,
tzinfo
=
tzoffset
(
None
,
10800
)))
def
test_read_timespan
(
self
):
...
...
@@ -1288,14 +1381,14 @@ class DateTimeTestCase( unittest.TestCase ):
</TimeSpan>
"""
ts
.
from_string
(
doc
)
self
.
assertEqual
(
ts
.
begin
[
1
],
'date'
)
self
.
assertEqual
(
ts
.
begin
[
1
],
'date'
)
self
.
assertEqual
(
ts
.
begin
[
0
],
datetime
.
datetime
(
1876
,
8
,
1
,
0
,
0
))
self
.
assertEqual
(
ts
.
end
[
1
],
'dateTime'
)
self
.
assertEqual
(
ts
.
end
[
1
],
'dateTime'
)
self
.
assertEqual
(
ts
.
end
[
0
],
datetime
.
datetime
(
1997
,
7
,
16
,
7
,
30
,
15
,
tzinfo
=
tzutc
()))
def
test_featurefromstring
(
self
):
d
=
kml
.
Document
(
ns
=
''
)
doc
=
"""<Document>
d
=
kml
.
Document
(
ns
=
''
)
doc
=
"""<Document>
<name>Document.kml</name>
<open>1</open>
<TimeStamp>
...
...
@@ -1309,9 +1402,7 @@ class DateTimeTestCase( unittest.TestCase ):
d
.
from_string
(
doc
)
class
AtomTestCase
(
unittest
.
TestCase
):
class
AtomTestCase
(
unittest
.
TestCase
):
def
test_author
(
self
):
a
=
atom
.
Author
(
name
=
"Christian Ledermann"
)
self
.
assertEqual
(
a
.
name
,
"Christian Ledermann"
)
...
...
@@ -1323,7 +1414,7 @@ class AtomTestCase( unittest.TestCase ):
self
.
assertTrue
(
'name>'
in
str
(
a
.
to_string
()))
self
.
assertTrue
(
'uri>'
in
str
(
a
.
to_string
()))
self
.
assertTrue
(
'email>'
in
str
(
a
.
to_string
()))
#print (a.to_string())
#
print (a.to_string())
a
.
email
=
'christian'
self
.
assertFalse
(
'email>'
in
str
(
a
.
to_string
()))
a2
=
atom
.
Author
()
...
...
@@ -1334,10 +1425,10 @@ class AtomTestCase( unittest.TestCase ):
l
=
atom
.
Link
(
href
=
"http://localhost/"
,
rel
=
"alternate"
)
self
.
assertEqual
(
l
.
href
,
"http://localhost/"
)
self
.
assertEqual
(
l
.
rel
,
"alternate"
)
l
.
title
=
"Title"
l
.
type
=
"text/html"
l
.
hreflang
=
'en'
l
.
length
=
"4096"
l
.
title
=
"Title"
l
.
type
=
"text/html"
l
.
hreflang
=
'en'
l
.
length
=
"4096"
self
.
assertTrue
(
'href="http://localhost/"'
in
str
(
l
.
to_string
()))
self
.
assertTrue
(
'rel="alternate"'
in
str
(
l
.
to_string
()))
self
.
assertTrue
(
'title="Title"'
in
str
(
l
.
to_string
()))
...
...
@@ -1352,12 +1443,12 @@ class AtomTestCase( unittest.TestCase ):
l
.
href
=
None
self
.
assertRaises
(
ValueError
,
l
.
to_string
)
class
SetGeometryTestCase
(
unittest
.
TestCase
):
class
SetGeometryTestCase
(
unittest
.
TestCase
):
def
test_altitude_mode
(
self
):
geom
=
Geometry
()
geom
.
geometry
=
Point
(
0
,
1
)
self
.
assertEqual
(
geom
.
altitude_mode
,
None
)
geom
=
Geometry
()
geom
.
geometry
=
Point
(
0
,
1
)
self
.
assertEqual
(
geom
.
altitude_mode
,
None
)
self
.
assertFalse
(
'altitudeMode'
in
str
(
geom
.
to_string
()))
geom
.
altitude_mode
=
'unknown'
self
.
assertRaises
(
AssertionError
,
geom
.
to_string
)
...
...
@@ -1373,12 +1464,12 @@ class SetGeometryTestCase( unittest.TestCase ):
self
.
assertTrue
(
'altitudeMode>absolute</'
in
str
(
geom
.
to_string
()))
def
test_extrude
(
self
):
geom
=
Geometry
()
self
.
assertEqual
(
geom
.
extrude
,
False
)
geom
.
geometry
=
Point
(
0
,
1
)
geom
.
extrude
=
False
geom
=
Geometry
()
self
.
assertEqual
(
geom
.
extrude
,
False
)
geom
.
geometry
=
Point
(
0
,
1
)
geom
.
extrude
=
False
self
.
assertFalse
(
'extrude'
in
str
(
geom
.
to_string
()))
geom
.
extrude
=
True
geom
.
extrude
=
True
geom
.
altitude_mode
=
'clampToGround'
self
.
assertFalse
(
'extrude'
in
str
(
geom
.
to_string
()))
geom
.
altitude_mode
=
'relativeToGround'
...
...
@@ -1387,9 +1478,9 @@ class SetGeometryTestCase( unittest.TestCase ):
self
.
assertTrue
(
'extrude>1</'
in
str
(
geom
.
to_string
()))
def
test_tesselate
(
self
):
geom
=
Geometry
()
self
.
assertEqual
(
geom
.
tessellate
,
False
)
geom
.
geometry
=
LineString
([(
0
,
0
),
(
1
,
1
)])
geom
=
Geometry
()
self
.
assertEqual
(
geom
.
tessellate
,
False
)
geom
.
geometry
=
LineString
([(
0
,
0
),
(
1
,
1
)])
self
.
assertFalse
(
'tessellate'
in
str
(
geom
.
to_string
()))
geom
.
altitude_mode
=
'clampToGround'
self
.
assertFalse
(
'tessellate'
in
str
(
geom
.
to_string
()))
...
...
@@ -1406,14 +1497,14 @@ class SetGeometryTestCase( unittest.TestCase ):
self
.
assertFalse
(
'tessellate'
in
str
(
geom
.
to_string
()))
geom
.
altitude_mode
=
'clampToGround'
self
.
assertTrue
(
'tessellate>1</'
in
str
(
geom
.
to_string
()))
#for geometries != LineString tesselate is ignored
geom
.
geometry
=
Point
(
0
,
1
)
#
for geometries != LineString tesselate is ignored
geom
.
geometry
=
Point
(
0
,
1
)
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
()))
def
testPoint
(
self
):
p
=
Point
(
0
,
1
)
p
=
Point
(
0
,
1
)
g
=
Geometry
(
geometry
=
p
)
self
.
assertEqual
(
g
.
geometry
,
p
)
g
=
Geometry
(
geometry
=
p
.
__geo_interface__
)
...
...
@@ -1422,7 +1513,7 @@ class SetGeometryTestCase( unittest.TestCase ):
self
.
assertTrue
(
'coordinates>0.000000,1.000000</'
in
str
(
g
.
to_string
()))
def
testLineString
(
self
):
l
=
LineString
([(
0
,
0
),
(
1
,
1
)])
l
=
LineString
([(
0
,
0
),
(
1
,
1
)])
g
=
Geometry
(
geometry
=
l
)
self
.
assertEqual
(
g
.
geometry
,
l
)
self
.
assertTrue
(
'LineString'
in
str
(
g
.
to_string
()))
...
...
@@ -1432,7 +1523,7 @@ class SetGeometryTestCase( unittest.TestCase ):
self
.
assertEqual
(
g
.
to_string
(),
g2
.
to_string
())
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
)
self
.
assertEqual
(
g
.
geometry
,
l
)
self
.
assertTrue
(
'LinearRing'
in
str
(
g
.
to_string
()))
...
...
@@ -1441,8 +1532,8 @@ class SetGeometryTestCase( unittest.TestCase ):
in
str
(
g
.
to_string
()))
def
testPolygon
(
self
):
#without holes
l
=
Polygon
([(
0
,
0
),
(
1
,
0
),
(
1
,
1
),
(
0
,
0
)])
#
without holes
l
=
Polygon
([(
0
,
0
),
(
1
,
0
),
(
1
,
1
),
(
0
,
0
)])
g
=
Geometry
(
geometry
=
l
)
self
.
assertEqual
(
g
.
geometry
,
l
)
self
.
assertTrue
(
'Polygon'
in
str
(
g
.
to_string
()))
...
...
@@ -1452,8 +1543,11 @@ class SetGeometryTestCase( unittest.TestCase ):
self
.
assertTrue
(
'coordinates>0.000000,0.000000 1.000000,0.000000 1.000000,1.000000 0.000000,0.000000</'
in
str
(
g
.
to_string
()))
#with holes
p
=
Polygon
([(
-
1
,
-
1
),
(
2
,
-
1
),
(
2
,
2
),
(
-
1
,
-
1
)],[[(
0
,
0
),
(
1
,
0
),
(
1
,
1
),
(
0
,
0
)]])
# with holes
p
=
Polygon
(
[(
-
1
,
-
1
),
(
2
,
-
1
),
(
2
,
2
),
(
-
1
,
-
1
)],
[[(
0
,
0
),
(
1
,
0
),
(
1
,
1
),
(
0
,
0
)]],
)
g
=
Geometry
(
geometry
=
p
)
self
.
assertEqual
(
g
.
geometry
,
p
)
self
.
assertTrue
(
'Polygon'
in
str
(
g
.
to_string
()))
...
...
@@ -1468,29 +1562,32 @@ class SetGeometryTestCase( unittest.TestCase ):
in
str
(
g
.
to_string
()))
def
testMultiPoint
(
self
):
p0
=
Point
(
0
,
1
)
p1
=
Point
(
1
,
1
)
g
=
Geometry
(
geometry
=
MultiPoint
([
p0
,
p1
]))
p0
=
Point
(
0
,
1
)
p1
=
Point
(
1
,
1
)
g
=
Geometry
(
geometry
=
MultiPoint
([
p0
,
p1
]))
self
.
assertTrue
(
'MultiGeometry'
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>1.000000,1.000000</'
in
str
(
g
.
to_string
()))
def
testMultiLineString
(
self
):
l0
=
LineString
([(
0
,
0
),
(
1
,
0
)])
l1
=
LineString
([(
0
,
1
),
(
1
,
1
)])
g
=
Geometry
(
geometry
=
MultiLineString
([
l0
,
l1
]))
l0
=
LineString
([(
0
,
0
),
(
1
,
0
)])
l1
=
LineString
([(
0
,
1
),
(
1
,
1
)])
g
=
Geometry
(
geometry
=
MultiLineString
([
l0
,
l1
]))
self
.
assertTrue
(
'MultiGeometry'
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,1.000000 1.000000,1.000000</'
in
str
(
g
.
to_string
()))
def
testMultiPolygon
(
self
):
#with holes
p0
=
Polygon
([(
-
1
,
-
1
),
(
2
,
-
1
),
(
2
,
2
),
(
-
1
,
-
1
)],[[(
0
,
0
),
(
1
,
0
),
(
1
,
1
),
(
0
,
0
)]])
#without holes
p1
=
Polygon
([(
3
,
0
),
(
4
,
0
),
(
4
,
1
),
(
3
,
0
)])
g
=
Geometry
(
geometry
=
MultiPolygon
([
p0
,
p1
]))
# with holes
p0
=
Polygon
(
[(
-
1
,
-
1
),
(
2
,
-
1
),
(
2
,
2
),
(
-
1
,
-
1
)],
[[(
0
,
0
),
(
1
,
0
),
(
1
,
1
),
(
0
,
0
)]]
)
# 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
(
'Polygon'
in
str
(
g
.
to_string
()))
self
.
assertTrue
(
'outerBoundaryIs'
in
str
(
g
.
to_string
()))
...
...
@@ -1507,16 +1604,16 @@ class SetGeometryTestCase( unittest.TestCase ):
in
str
(
g
.
to_string
()))
def
testGeometryCollection
(
self
):
po
=
Polygon
([(
3
,
0
),
(
4
,
0
),
(
4
,
1
),
(
3
,
0
)])
lr
=
LinearRing
([(
0
,
-
1
),
(
1
,
-
1
),
(
1
,
1
),
(
0
,
-
1
)])
ls
=
LineString
([(
0
,
0
),
(
1
,
1
)])
p
=
Point
(
0
,
1
)
geo_if
=
{
'type'
:
'GeometryCollection'
,
'geometries'
:
[
po
.
__geo_interface__
,
p
.
__geo_interface__
,
ls
.
__geo_interface__
,
lr
.
__geo_interface__
]}
g
=
Geometry
(
geometry
=
GeometryCollection
([
po
,
p
,
ls
,
lr
]))
#g1 = Geometry(geometry=as_shape(geo_if))
#self.assertEqual(g1.__geo_interface__, g.__geo_interface__)
po
=
Polygon
([(
3
,
0
),
(
4
,
0
),
(
4
,
1
),
(
3
,
0
)])
lr
=
LinearRing
([(
0
,
-
1
),
(
1
,
-
1
),
(
1
,
1
),
(
0
,
-
1
)])
ls
=
LineString
([(
0
,
0
),
(
1
,
1
)])
p
=
Point
(
0
,
1
)
#
geo_if = {'type': 'GeometryCollection', 'geometries': [
#
po.__geo_interface__, p.__geo_interface__,
# ls.__geo_interface__, lr.__geo_interface__
]}
g
=
Geometry
(
geometry
=
GeometryCollection
([
po
,
p
,
ls
,
lr
]))
#
g1 = Geometry(geometry=as_shape(geo_if))
#
self.assertEqual(g1.__geo_interface__, g.__geo_interface__)
self
.
assertTrue
(
'MultiGeometry'
in
str
(
g
.
to_string
()))
self
.
assertTrue
(
'Polygon'
in
str
(
g
.
to_string
()))
self
.
assertTrue
(
'outerBoundaryIs'
in
str
(
g
.
to_string
()))
...
...
@@ -1530,8 +1627,8 @@ class SetGeometryTestCase( unittest.TestCase ):
self
.
assertTrue
(
'Point'
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
):
doc
=
"""<kml:Point xmlns:kml="http://www.opengis.net/kml/2.2">
<kml:coordinates>0.000000,1.000000</kml:coordinates>
...
...
@@ -1568,8 +1665,10 @@ class GetGeometryTestCase( unittest.TestCase ):
</kml:Point>"""
g
=
Geometry
()
g
.
from_string
(
doc
)
self
.
assertEqual
(
g
.
geometry
.
__geo_interface__
,
{
'type'
:
'Point'
,
'coordinates'
:
(
0.0
,
1.0
)})
self
.
assertEqual
(
g
.
geometry
.
__geo_interface__
,
{
'type'
:
'Point'
,
'coordinates'
:
(
0.0
,
1.0
)}
)
def
testLineString
(
self
):
doc
=
"""<kml:LineString xmlns:kml="http://www.opengis.net/kml/2.2">
...
...
@@ -1577,8 +1676,10 @@ class GetGeometryTestCase( unittest.TestCase ):
</kml:LineString>"""
g
=
Geometry
()
g
.
from_string
(
doc
)
self
.
assertEqual
(
g
.
geometry
.
__geo_interface__
,
{
'type'
:
'LineString'
,
'coordinates'
:
((
0.0
,
0.0
),
(
1.0
,
1.0
))})
self
.
assertEqual
(
g
.
geometry
.
__geo_interface__
,
{
'type'
:
'LineString'
,
'coordinates'
:
((
0.0
,
0.0
),
(
1.0
,
1.0
))}
)
def
testLinearRing
(
self
):
doc
=
"""<kml:LinearRing xmlns:kml="http://www.opengis.net/kml/2.2">
...
...
@@ -1587,8 +1688,11 @@ class GetGeometryTestCase( unittest.TestCase ):
"""
g
=
Geometry
()
g
.
from_string
(
doc
)
self
.
assertEqual
(
g
.
geometry
.
__geo_interface__
,
{
'type'
:
'LinearRing'
,
'coordinates'
:
((
0.0
,
0.0
),
(
1.0
,
0.0
),
(
1.0
,
1.0
),
(
0.0
,
0.0
))})
self
.
assertEqual
(
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
):
doc
=
"""<kml:Polygon xmlns:kml="http://www.opengis.net/kml/2.2">
<kml:outerBoundaryIs>
...
...
@@ -1600,11 +1704,19 @@ class GetGeometryTestCase( unittest.TestCase ):
"""
g
=
Geometry
()
g
.
from_string
(
doc
)
self
.
assertEqual
(
g
.
geometry
.
__geo_interface__
,
{
'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">
self
.
assertEqual
(
g
.
geometry
.
__geo_interface__
,
{
'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">
<kml:outerBoundaryIs>
<kml:LinearRing>
<kml:coordinates>-1.000000,-1.000000 2.000000,-1.000000 2.000000,2.000000 -1.000000,-1.000000</kml:coordinates>
...
...
@@ -1618,11 +1730,16 @@ class GetGeometryTestCase( unittest.TestCase ):
</kml:Polygon>
"""
g
.
from_string
(
doc
)
self
.
assertEqual
(
g
.
geometry
.
__geo_interface__
,
{
'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
)))}
)
self
.
assertEqual
(
g
.
geometry
.
__geo_interface__
,
{
'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
):
doc
=
"""
...
...
@@ -1639,7 +1756,6 @@ class GetGeometryTestCase( unittest.TestCase ):
g
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
g
.
geometry
),
2
)
def
testMultiLineString
(
self
):
doc
=
"""
<kml:MultiGeometry xmlns:kml="http://www.opengis.net/kml/2.2">
...
...
@@ -1723,28 +1839,28 @@ class GetGeometryTestCase( unittest.TestCase ):
self
.
assertEqual
(
g
.
geometry
.
geom_type
,
'GeometryCollection'
)
class
Force3DTestCase
(
unittest
.
TestCase
):
class
Force3DTestCase
(
unittest
.
TestCase
):
def
test3d
(
self
):
ns
=
''
ns
=
''
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
.
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
#p3.altitudeMode = 'absolute'
#
p3.altitudeMode = 'absolute'
self
.
assertNotEqual
(
p2
.
to_string
(),
p3
.
to_string
())
config
.
FORCE3D
=
True
self
.
assertEqual
(
p2
.
to_string
(),
p3
.
to_string
())
#altitudeMode clampToGround indicates to ignore an altitude specification.
#p3.altitudeMode = 'clampToGround'
#self.assertEqual(p2.to_string(), p3.to_string())
#config.FORCE3D = False
#self.assertNotEqual(p2.to_string(), p3.to_string())
#
altitudeMode clampToGround indicates to ignore an altitude specification.
#
p3.altitudeMode = 'clampToGround'
#
self.assertEqual(p2.to_string(), p3.to_string())
#
config.FORCE3D = False
#
self.assertNotEqual(p2.to_string(), p3.to_string())
#Important: Set FORCE3D back to False!
#
Important: Set FORCE3D back to False!
config
.
FORCE3D
=
False
def
test_suite
():
suite
=
unittest
.
TestSuite
()
suite
.
addTest
(
unittest
.
makeSuite
(
BaseClassesTestCase
))
...
...
@@ -1761,4 +1877,3 @@ def test_suite():
if
__name__
==
'__main__'
:
unittest
.
main
()
requirements/test.txt
View file @
365ed6e5
-r common.txt
pytest
pep8
coveralls
setup.py
View file @
365ed6e5
from
setuptools
import
setup
,
find_packages
from
setuptools.command.test
import
test
as
TestCommand
import
sys
,
os
import
sys
import
os
class
PyTest
(
TestCommand
):
def
finalize_options
(
self
):
TestCommand
.
finalize_options
(
self
)
self
.
test_args
=
[]
self
.
test_suite
=
True
def
run_tests
(
self
):
#import here, cause outside the eggs aren't loaded
#
import here, cause outside the eggs aren't loaded
import
pytest
errno
=
pytest
.
main
(
self
.
test_args
)
sys
.
exit
(
errno
)
...
...
@@ -16,14 +19,16 @@ class PyTest(TestCommand):
version
=
'0.7'
setup
(
name
=
'fastkml'
,
version
=
version
,
description
=
"Fast KML processing in python"
,
long_description
=
open
(
"README.rst"
).
read
()
+
"
\
n
"
+
open
(
os
.
path
.
join
(
"docs"
,
"HISTORY.txt"
)).
read
()
+
"
\
n
"
+
open
(
os
.
path
.
join
(
"docs"
,
"TODO.txt"
)).
read
(),
classifiers
=
[
setup
(
name
=
'fastkml'
,
version
=
version
,
description
=
"Fast KML processing in python"
,
long_description
=
(
open
(
"README.rst"
).
read
()
+
"
\
n
"
+
open
(
os
.
path
.
join
(
"docs"
,
"HISTORY.txt"
)).
read
()
+
"
\
n
"
+
open
(
os
.
path
.
join
(
"docs"
,
"TODO.txt"
)).
read
()
),
classifiers
=
[
"Topic :: Scientific/Engineering :: GIS"
,
"Programming Language :: Python"
,
'Programming Language :: Python :: 2'
,
...
...
@@ -37,23 +42,23 @@ setup(name='fastkml',
'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)'
,
'Development Status :: 4 - Beta'
,
'Operating System :: OS Independent'
,
],
# Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
keywords
=
'GIS KML Google Maps OpenLayers'
,
author
=
'Christian Ledermann'
,
author_email
=
'christian.ledermann@gmail.com'
,
url
=
'https://github.com/cleder/fastkml'
,
license
=
'LGPL'
,
packages
=
find_packages
(
exclude
=
[
'ez_setup'
,
'examples'
,
'tests'
]),
include_package_data
=
True
,
zip_safe
=
False
,
tests_require
=
[
'pytest'
],
cmdclass
=
{
'test'
:
PyTest
},
install_requires
=
[
# -*- Extra requirements: -*-
'pygeoif'
,
'python-dateutil'
,
],
entry_points
=
"""
# -*- Entry points: -*-
"""
,
)
],
# Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
keywords
=
'GIS KML Google Maps OpenLayers'
,
author
=
'Christian Ledermann'
,
author_email
=
'christian.ledermann@gmail.com'
,
url
=
'https://github.com/cleder/fastkml'
,
license
=
'LGPL'
,
packages
=
find_packages
(
exclude
=
[
'ez_setup'
,
'examples'
,
'tests'
]),
include_package_data
=
True
,
zip_safe
=
False
,
tests_require
=
[
'pytest'
],
cmdclass
=
{
'test'
:
PyTest
},
install_requires
=
[
# -*- Extra requirements: -*-
'pygeoif'
,
'python-dateutil'
,
],
entry_points
=
"""
# -*- Entry points: -*-
"""
,
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment