Skip to content

Commit

Permalink
Merge pull request #389 from cleder/develop
Browse files Browse the repository at this point in the history
1.0.0 final
  • Loading branch information
cleder authored Nov 19, 2024
2 parents ceb46b3 + e7d5dd7 commit 12bf959
Show file tree
Hide file tree
Showing 14 changed files with 297 additions and 106 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ repos:
hooks:
- id: absolufy-imports
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 'v0.7.3'
rev: 'v0.7.4'
hooks:
- id: ruff
- id: ruff-format
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ Optional

.. code-block:: bash
pip install --pre "fastkml[lxml]"
pip install "fastkml[lxml]"
Limitations
===========
Expand Down
Binary file added docs/co2growth.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 16 additions & 6 deletions docs/create_kml_files.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ Read a shapefile and build a 3D KML visualization.

This example shows how to read a shapefile and build a 3D KML visualization from it.

.. image:: co2-per-capita-2020.jpg
:alt: CO2 emissions per capita in 2020
:align: center
:width: 800px
:target: https://ion.cesium.com/stories/viewer/?id=a3cf93bb-bbb8-488b-8643-09c037ec12b8

(click on the image to see the KML visualization in Cesium Ion)

You will need to install `pyshp <https://pypi.org/project/pyshp/>`_ (``pip install pyshp``).

For this example we will use the
Expand Down Expand Up @@ -108,12 +116,6 @@ Finally, we create the KML object and write it to a file:
The resulting KML file can be opened in Google Earth or any other KML viewer.

.. image:: co2-per-capita-2020.jpg
:alt: CO2 emissions per capita in 2020
:align: center
:width: 800px
:target: https://ion.cesium.com/stories/viewer/?id=a3cf93bb-bbb8-488b-8643-09c037ec12b8


Build an animated over time KML visualization
----------------------------------------------
Expand All @@ -122,6 +124,14 @@ This example shows how to build an animated KML visualization over time.
We will use the same data as in the previous example, but this time we will
create a KML file that shows the CO2 emissions accumulating from 1995 to 2022.

.. image:: co2growth.gif
:alt: CO2 emissions per capita growth
:align: center
:width: 800px
:target: https://ion.cesium.com/stories/viewer/?id=602c8c64-72aa-4c57-8a01-752b6fbc62d0

(click on the image to see the full visualization in Cesium Ion)

First we import the necessary modules:

.. code-block:: pycon
Expand Down
96 changes: 57 additions & 39 deletions docs/fastkml.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,76 @@ Reference Guide

.. automodule:: fastkml

fastkml.kml
------------------

fastkml.about
--------------------

.. automodule:: fastkml.about
.. automodule:: fastkml.kml
:members:
:undoc-members:
:show-inheritance:

fastkml.atom

fastkml.base
-------------------

.. automodule:: fastkml.atom
.. automodule:: fastkml.base
:members:
:undoc-members:
:show-inheritance:

fastkml.base
.. autoclass:: fastkml.base._XMLObject
:members: etree_element, _get_kwargs, to_string, from_string, validate, __init__
:undoc-members:
:show-inheritance:

fastkml.registry
-----------------------

.. automodule:: fastkml.registry
:members:
:undoc-members:
:show-inheritance:

.. autoclass:: fastkml.registry::Registry
:members: register, get
:undoc-members:
:show-inheritance:

fastkml.kml\_base
------------------------

.. automodule:: fastkml.kml_base
:members:
:undoc-members:
:show-inheritance:

.. autoclass:: fastkml.kml_base::_BaseObject
:members: __init__
:undoc-members:
:show-inheritance:

fastkml.helpers
----------------------

.. automodule:: fastkml.helpers
:members:
:undoc-members:
:show-inheritance:

fastkml.about
--------------------

.. automodule:: fastkml.about
:members:
:undoc-members:
:show-inheritance:

.. autodata:: __version__

fastkml.atom
-------------------

.. automodule:: fastkml.base
.. automodule:: fastkml.atom
:members:
:undoc-members:
:show-inheritance:
Expand Down Expand Up @@ -93,30 +142,6 @@ fastkml.gx
:undoc-members:
:show-inheritance:

fastkml.helpers
----------------------

.. automodule:: fastkml.helpers
:members:
:undoc-members:
:show-inheritance:

fastkml.kml
------------------

.. automodule:: fastkml.kml
:members:
:undoc-members:
:show-inheritance:

fastkml.kml\_base
------------------------

.. automodule:: fastkml.kml_base
:members:
:undoc-members:
:show-inheritance:

fastkml.links
--------------------

Expand All @@ -141,13 +166,6 @@ fastkml.overlays
:undoc-members:
:show-inheritance:

fastkml.registry
-----------------------

.. automodule:: fastkml.registry
:members:
:undoc-members:
:show-inheritance:

fastkml.styles
---------------------
Expand Down
3 changes: 2 additions & 1 deletion fastkml/about.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
The only purpose of this module is to provide a version number for the package.
"""

__version__ = "1.0.0rc2"
__version__ = "1.0.0"
"""Fastkml version number."""

__all__ = ["__version__"]
54 changes: 53 additions & 1 deletion fastkml/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,22 @@
# 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."""
"""
Abstract XML base class.
The purpose of ``_XMLObject`` is to serve as a base class for KML objects in fastkml.
Its main functions are:
- Provide a common interface for XML serialization and deserialization.
- Handle namespace management for KML elements.
- Manage attribute storage and retrieval for derived classes.
- Provide the ``etree_element()`` method for converting objects to XML Elements.
- Facilitate integration with the registry system for flexible XML mapping.
By inheriting from ``_XMLObject``, KML classes gain these capabilities, ensuring
consistent handling of XML operations across the library.
"""

import logging
from typing import Any
Expand Down Expand Up @@ -127,6 +142,18 @@ def etree_element(
"""
Return the KML Object as an Element.
This method essentially converts the Python object to its XML representation,
using the registry to determine how each attribute should be serialized.
- Create an XML Element with the object's tag name and namespace.
- Iterate through registered attributes for the object's class.
For each attribute:
- Call the corresponding set_element function. This function adds the
attribute to the Element as a sub-element or attribute.
- Handle different data types and nested objects.
- Apply precision and verbosity settings if specified.
- Return the complete Element tree representing the object.
Parameters
----------
precision : Optional[int], default=None
Expand Down Expand Up @@ -280,6 +307,31 @@ def _get_kwargs(
"""
Get the keyword arguments for the class constructor.
A class method used for XML deserialization. Its main purposes are:
- Extract attribute values from an XML element.
- Convert these values into appropriate Python types.
- Prepare a dictionary of keyword arguments for object initialization.
- It is called during the parsing process to populate object attributes from XML
data. The method uses the registry and helper functions to handle different
attribute types and nested objects.
Subclasses may override this method to add custom deserialization logic for
specific KML elements, although this should be rare. Prefer registration over
a custom ``_get_kwargs`` implementation to ensure consistent handling of KML:
- Consistency: Ensures uniform handling across all KML elements.
- Maintainability: Centralizes parsing logic, making updates easier.
- Declarative approach: Simplifies code by moving logic to configuration.
- Reusability: Allows sharing of parsing logic across different classes.
- Separation of concerns: Keeps parsing logic separate from class definitions.
- Extensibility: Makes it easier to add new attributes or change parsing
behavior.
- Reduced duplication: Avoids repeating similar parsing code in multiple
classes.
- Easier testing: Allows testing of parsing logic independently of class
implementations.
Parameters
----------
ns : str
Expand Down
77 changes: 47 additions & 30 deletions fastkml/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,22 @@
from enum import Enum
from enum import unique

__all__ = [
"AltitudeMode",
"ColorMode",
"DataType",
"DateTimeResolution",
"DisplayMode",
"GridOrigin",
"PairKey",
"RefreshMode",
"RelaxedEnum",
"Shape",
"Units",
"Verbosity",
"ViewRefreshMode",
]

logger = logging.getLogger(__name__)


Expand All @@ -40,14 +56,15 @@ class RelaxedEnum(Enum):
Usage:
To use this enum, simply subclass `RelaxedEnum` and define your enum values.
Example:
-------
class MyEnum(RelaxedEnum):
VALUE1 = "value1"
VALUE2 = "value2"
Example::
class AltitudeMode(RelaxedEnum):
clamp_to_ground = "clampToGround"
relative_to_ground = "relativeToGround"
absolute = "absolute"
my_value = MyEnum("VALUE1") # Case-insensitive match
print(my_value) # Output: MyEnum.VALUE1
my_value = AltitudeMode("CLAMPTOGROUND") # Case-insensitive match
print(my_value) # Output: AltitudeMode.clamp_to_ground
The subclass must define all values as strings.
Expand Down Expand Up @@ -102,33 +119,33 @@ class AltitudeMode(RelaxedEnum):
Possible values are
- clampToGround - (default) Indicates to ignore an altitude specification
(for example, in the <coordinates> tag).
(for example, in the <coordinates> tag).
- relativeToGround - Sets the altitude of the element relative to the actual
ground elevation of a particular location.
For example, if the ground elevation of a location is exactly at sea level
and the altitude for a point is set to 9 meters,
then the elevation for the icon of a point placemark elevation is 9 meters
with this mode.
However, if the same coordinate is set over a location where the ground
elevation is 10 meters above sea level, then the elevation of the coordinate
is 19 meters.
A typical use of this mode is for placing telephone poles or a ski lift.
ground elevation of a particular location.
For example, if the ground elevation of a location is exactly at sea level
and the altitude for a point is set to 9 meters,
then the elevation for the icon of a point placemark elevation is 9 meters
with this mode.
However, if the same coordinate is set over a location where the ground
elevation is 10 meters above sea level, then the elevation of the coordinate
is 19 meters.
A typical use of this mode is for placing telephone poles or a ski lift.
- absolute - Sets the altitude of the coordinate relative to sea level,
regardless of the actual elevation of the terrain beneath the element.
For example, if you set the altitude of a coordinate to 10 meters with an
absolute altitude mode, the icon of a point placemark will appear to be at
ground level if the terrain beneath is also 10 meters above sea level.
If the terrain is 3 meters above sea level, the placemark will appear elevated
above the terrain by 7 meters.
A typical use of this mode is for aircraft placement.
regardless of the actual elevation of the terrain beneath the element.
For example, if you set the altitude of a coordinate to 10 meters with an
absolute altitude mode, the icon of a point placemark will appear to be at
ground level if the terrain beneath is also 10 meters above sea level.
If the terrain is 3 meters above sea level, the placemark will appear elevated
above the terrain by 7 meters.
A typical use of this mode is for aircraft placement.
- relativeToSeaFloor - Interprets the altitude as a value in meters above the
sea floor.
If the point is above land rather than sea, the altitude will be interpreted
as being above the ground.
sea floor.
If the point is above land rather than sea, the altitude will be interpreted
as being above the ground.
- clampToSeaFloor - The altitude specification is ignored, and the point will be
positioned on the sea floor.
If the point is on land rather than at sea, the point will be positioned on
the ground.
positioned on the sea floor.
If the point is on land rather than at sea, the point will be positioned on
the ground.
The Values relativeToSeaFloor and clampToSeaFloor are not part of the KML definition
but of the <gx:altitudeMode> a KML extension in the Google extension namespace,
Expand Down
Loading

0 comments on commit 12bf959

Please sign in to comment.