Ver código fonte

Using Pythons abstract base class to define abstract classes and methods.

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@56879 15284696-431f-4ddb-bdfa-cd5b030d7da7
Soeren Gebbert 12 anos atrás
pai
commit
72e2a154dd

+ 29 - 30
lib/python/temporal/abstract_dataset.py

@@ -11,15 +11,6 @@ Usage:
 
 
 >>> import grass.temporal as tgis
 >>> import grass.temporal as tgis
 >>> ad = AbstractDataset()
 >>> ad = AbstractDataset()
->>> ad.reset(ident="soil@PERMANENT")
-Traceback (most recent call last):
-  File "/usr/lib/python2.7/doctest.py", line 1289, in __run
-    compileflags, 1) in test.globs
-  File "<doctest __main__[2]>", line 1, in <module>
-    ad.reset(ident="soil@PERMANENT")
-  File "AbstractDataset.py", line 53, in reset
-    raise ImplementationError("This method must be implemented in the subclasses")
-ImplementationError: 'This method must be implemented in the subclasses'
 
 
 @endcode
 @endcode
 
 
@@ -32,6 +23,7 @@ for details.
 """
 """
 import uuid
 import uuid
 import copy
 import copy
+from abc import ABCMeta, abstractmethod
 from temporal_extent import *
 from temporal_extent import *
 from spatial_extent import *
 from spatial_extent import *
 from metadata import *
 from metadata import *
@@ -53,6 +45,9 @@ class ImplementationError(Exception):
 class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetConnector):
 class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetConnector):
     """!This is the base class for all datasets 
     """!This is the base class for all datasets 
        (raster, vector, raster3d, strds, stvds, str3ds)"""
        (raster, vector, raster3d, strds, stvds, str3ds)"""
+    
+    __metaclass__ = ABCMeta
+    
     def __init__(self):
     def __init__(self):
         SpatialTopologyDatasetConnector.__init__(self)
         SpatialTopologyDatasetConnector.__init__(self)
         TemporalTopologyDatasetConnector.__init__(self)
         TemporalTopologyDatasetConnector.__init__(self)
@@ -140,13 +135,26 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
         if self.is_spatial_topology_build():
         if self.is_spatial_topology_build():
             self.print_spatial_topology_shell_info()
             self.print_spatial_topology_shell_info()
             
             
+    @abstractmethod
     def reset(self, ident):
     def reset(self, ident):
         """!Reset the internal structure and set the identifier
         """!Reset the internal structure and set the identifier
-
+        
+            This method creates the dataset specific internal objects
+            that store the base information, the spatial and temporal extent
+            and the metadata. It must be implemented in the dataset
+            specific subclasses. This is the code for the 
+            vector dataset:
+            
+            self.base = VectorBase(ident=ident)
+            self.absolute_time = VectorAbsoluteTime(ident=ident)
+            self.relative_time = VectorRelativeTime(ident=ident)
+            self.spatial_extent = VectorSpatialExtent(ident=ident)
+            self.metadata = VectorMetadata(ident=ident)
+        
            @param ident The identifier of the dataset that  "name@mapset" or in case of vector maps "name:layer@mapset"
            @param ident The identifier of the dataset that  "name@mapset" or in case of vector maps "name:layer@mapset"
         """
         """
-        raise ImplementationError("This method must be implemented in the subclasses")
 
 
+    @abstractmethod
     def get_type(self):
     def get_type(self):
         """!Return the type of this class as string
         """!Return the type of this class as string
            
            
@@ -154,24 +162,24 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
            
            
            @return "vect", "rast", "rast3d", "stvds", "strds" or "str3ds"
            @return "vect", "rast", "rast3d", "stvds", "strds" or "str3ds"
         """
         """
-        raise ImplementationError("This method must be implemented in the subclasses")
 
 
+    @abstractmethod
     def get_new_instance(self, ident):
     def get_new_instance(self, ident):
         """!Return a new instance with the type of this class
         """!Return a new instance with the type of this class
 
 
            @param ident The identifier of the new dataset instance
            @param ident The identifier of the new dataset instance
            @return A new instance with the type of this object
            @return A new instance with the type of this object
         """
         """
-        raise ImplementationError("This method must be implemented in the subclasses")
 
 
+    @abstractmethod
     def spatial_overlapping(self, dataset):
     def spatial_overlapping(self, dataset):
         """!Return True if the spatial extents overlap
         """!Return True if the spatial extents overlap
         
         
            @param dataset The abstract dataset to check spatial overlapping
            @param dataset The abstract dataset to check spatial overlapping
            @return True if self and the provided dataset spatial overlap
            @return True if self and the provided dataset spatial overlap
         """
         """
-        raise ImplementationError("This method must be implemented in the subclasses")
 
 
+    @abstractmethod
     def spatial_intersection(self, dataset):
     def spatial_intersection(self, dataset):
         """!Return the spatial intersection as spatial_extent 
         """!Return the spatial intersection as spatial_extent 
            object or None in case no intersection was found.
            object or None in case no intersection was found.
@@ -179,8 +187,8 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
            @param dataset The abstract dataset to intersect with
            @param dataset The abstract dataset to intersect with
            @return The intersection spatial extent
            @return The intersection spatial extent
         """
         """
-        raise ImplementationError("This method must be implemented in the subclasses")
 
 
+    @abstractmethod
     def spatial_union(self, dataset):
     def spatial_union(self, dataset):
         """!Return the spatial union as spatial_extent 
         """!Return the spatial union as spatial_extent 
            object or None in case the extents does not overlap or meet.
            object or None in case the extents does not overlap or meet.
@@ -188,16 +196,16 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
            @param dataset The abstract dataset to create a union with
            @param dataset The abstract dataset to create a union with
            @return The union spatial extent
            @return The union spatial extent
         """
         """
-        raise ImplementationError("This method must be implemented in the subclasses")
     
     
+    @abstractmethod
     def spatial_disjoint_union(self, dataset):
     def spatial_disjoint_union(self, dataset):
         """!Return the spatial union as spatial_extent object.
         """!Return the spatial union as spatial_extent object.
        
        
            @param dataset The abstract dataset to create a union with
            @param dataset The abstract dataset to create a union with
            @return The union spatial extent
            @return The union spatial extent
         """
         """
-        raise ImplementationError("This method must be implemented in the subclasses")
     
     
+    @abstractmethod
     def spatial_relation(self, dataset):
     def spatial_relation(self, dataset):
         """!Return the spatial relationship between self and dataset
         """!Return the spatial relationship between self and dataset
         
         
@@ -205,21 +213,20 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
            @return The spatial relationship as string
            @return The spatial relationship as string
         """
         """
 
 
-        raise ImplementationError("This method must be implemented in the subclasses")
-
+    @abstractmethod
     def print_info(self):
     def print_info(self):
         """!Print information about this class in human readable style"""
         """!Print information about this class in human readable style"""
-        raise ImplementationError("This method must be implemented in the subclasses")
 
 
+    @abstractmethod
     def print_shell_info(self):
     def print_shell_info(self):
         """!Print information about this class in shell style"""
         """!Print information about this class in shell style"""
-        raise ImplementationError("This method must be implemented in the subclasses")
 
 
+    @abstractmethod
     def print_self(self):
     def print_self(self):
         """!Print the content of the internal structure to stdout"""
         """!Print the content of the internal structure to stdout"""
-        raise ImplementationError("This method must be implemented in the subclasses")
 
 
     def set_id(self, ident):
     def set_id(self, ident):
+        """!Set the identifier of the dataset"""
         self.base.set_id(ident)
         self.base.set_id(ident)
         self.temporal_extent.set_id(ident)
         self.temporal_extent.set_id(ident)
         self.spatial_extent.set_id(ident)
         self.spatial_extent.set_id(ident)
@@ -456,14 +463,6 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
             dbif.close()
             dbif.close()
         return statement
         return statement
 
 
-    def set_time_to_absolute(self):
-        """!Set the temporal type to absolute"""
-        self.base.set_ttype("absolute")
-
-    def set_time_to_relative(self):
-        """!Set the temporal type to relative"""
-        self.base.set_ttype("relative")
-
     def is_time_absolute(self):
     def is_time_absolute(self):
         """!Return True in case the temporal type is absolute
         """!Return True in case the temporal type is absolute
         
         

+ 28 - 23
lib/python/temporal/abstract_map_dataset.py

@@ -5,11 +5,6 @@
 
 
 Temporal GIS related functions to be used in temporal GIS Python library package.
 Temporal GIS related functions to be used in temporal GIS Python library package.
 
 
-Usage:
-
->>> import grass.temporal as tgis
->>> amd = tgis.AbstractMapDataset()
-
 (C) 2008-2011 by the GRASS Development Team
 (C) 2008-2011 by the GRASS Development Team
 This program is free software under the GNU General Public
 This program is free software under the GNU General Public
 License (>=v2). Read the file COPYING that comes with GRASS
 License (>=v2). Read the file COPYING that comes with GRASS
@@ -41,9 +36,13 @@ class AbstractMapDataset(AbstractDataset):
         - Abstract methods that must be implemented in the map specific
         - Abstract methods that must be implemented in the map specific
           subclasses
           subclasses
     """
     """
+    
+    __metaclass__ = ABCMeta
+    
     def __init__(self):
     def __init__(self):
         AbstractDataset.__init__(self)
         AbstractDataset.__init__(self)
 
 
+    @abstractmethod
     def get_new_stds_instance(self, ident):
     def get_new_stds_instance(self, ident):
         """!Return a new space time dataset instance that store maps with the
         """!Return a new space time dataset instance that store maps with the
            type of this map object (rast, rast3d or vect)
            type of this map object (rast, rast3d or vect)
@@ -51,9 +50,8 @@ class AbstractMapDataset(AbstractDataset):
            @param ident The identifier of the space time dataset
            @param ident The identifier of the space time dataset
            @return The new space time dataset instance
            @return The new space time dataset instance
         """
         """
-        raise ImplementationError(
-            "This method must be implemented in the subclasses")
 
 
+    @abstractmethod
     def get_stds_register(self):
     def get_stds_register(self):
         """!Return the space time dataset register table name
         """!Return the space time dataset register table name
 
 
@@ -63,9 +61,8 @@ class AbstractMapDataset(AbstractDataset):
 
 
             @return The name of the stds register table
             @return The name of the stds register table
         """
         """
-        raise ImplementationError(
-            "This method must be implemented in the subclasses")
 
 
+    @abstractmethod
     def set_stds_register(self, name):
     def set_stds_register(self, name):
         """!Set the space time dataset register table name.
         """!Set the space time dataset register table name.
 
 
@@ -74,8 +71,6 @@ class AbstractMapDataset(AbstractDataset):
 
 
            @param name The name of the register table
            @param name The name of the register table
         """
         """
-        raise ImplementationError(
-            "This method must be implemented in the subclasses")
 
 
     def check_resolution_with_current_region(self):
     def check_resolution_with_current_region(self):
         """!Check if the raster or voxel resolution is
         """!Check if the raster or voxel resolution is
@@ -94,48 +89,42 @@ class AbstractMapDataset(AbstractDataset):
         raise ImplementationError(
         raise ImplementationError(
             "This method must be implemented in the subclasses")
             "This method must be implemented in the subclasses")
 
 
+    @abstractmethod
     def has_grass_timestamp(self):
     def has_grass_timestamp(self):
         """!Check if a grass file based time stamp exists for this map.
         """!Check if a grass file based time stamp exists for this map.
             @return True is the grass file based time stamped exists for this
             @return True is the grass file based time stamped exists for this
                     map
                     map
         """
         """
-        raise ImplementationError(
-            "This method must be implemented in the subclasses")
 
 
+    @abstractmethod
     def write_timestamp_to_grass(self):
     def write_timestamp_to_grass(self):
         """!Write the timestamp of this map into the map metadata
         """!Write the timestamp of this map into the map metadata
            in the grass file system based spatial database.
            in the grass file system based spatial database.
         """
         """
-        raise ImplementationError(
-            "This method must be implemented in the subclasses")
 
 
+    @abstractmethod
     def remove_timestamp_from_grass(self):
     def remove_timestamp_from_grass(self):
         """!Remove the timestamp from the grass file
         """!Remove the timestamp from the grass file
            system based spatial database
            system based spatial database
         """
         """
-        raise ImplementationError(
-            "This method must be implemented in the subclasses")
 
 
+    @abstractmethod
     def map_exists(self):
     def map_exists(self):
         """!Return True in case the map exists in the grass spatial database
         """!Return True in case the map exists in the grass spatial database
 
 
            @return True if map exists, False otherwise
            @return True if map exists, False otherwise
         """
         """
-        raise ImplementationError(
-            "This method must be implemented in the subclasses")
 
 
+    @abstractmethod
     def read_info(self):
     def read_info(self):
         """!Read the map info from the grass file system based database and
         """!Read the map info from the grass file system based database and
            store the content into a dictionary
            store the content into a dictionary
         """
         """
-        raise ImplementationError(
-            "This method must be implemented in the subclasses")
 
 
+    @abstractmethod
     def load(self):
     def load(self):
         """!Load the content of this object from the grass
         """!Load the content of this object from the grass
            file system based database"""
            file system based database"""
-        raise ImplementationError(
-            "This method must be implemented in the subclasses")
 
 
     def _convert_timestamp(self):
     def _convert_timestamp(self):
         """!Convert the valid time into a grass datetime library
         """!Convert the valid time into a grass datetime library
@@ -211,6 +200,14 @@ class AbstractMapDataset(AbstractDataset):
         """
         """
         return self.base.get_layer()
         return self.base.get_layer()
 
 
+
+    def print_self(self):
+        """!Print the content of the internal structure to stdout"""
+        self.base.print_self()
+        self.temporal_extent.print_self()
+        self.spatial_extent.print_self()
+        self.metadata.print_self()
+        
     def print_info(self):
     def print_info(self):
         """!Print information about this object in human readable style"""
         """!Print information about this object in human readable style"""
 
 
@@ -324,6 +321,14 @@ class AbstractMapDataset(AbstractDataset):
         self.write_timestamp_to_grass()
         self.write_timestamp_to_grass()
         return AbstractDataset.update_all(self, dbif, execute)
         return AbstractDataset.update_all(self, dbif, execute)
 
 
+    def set_time_to_absolute(self):
+        """!Set the temporal type to absolute"""
+        self.base.set_ttype("absolute")
+
+    def set_time_to_relative(self):
+        """!Set the temporal type to relative"""
+        self.base.set_ttype("relative")
+        
     def set_absolute_time(self, start_time, end_time=None, timezone=None):
     def set_absolute_time(self, start_time, end_time=None, timezone=None):
         """!Set the absolute time with start time and end time
         """!Set the absolute time with start time and end time
 
 

+ 18 - 18
lib/python/temporal/abstract_space_time_dataset.py

@@ -32,20 +32,14 @@ class AbstractSpaceTimeDataset(AbstractDataset):
        database, like the computation of the temporal and spatial extent as
        database, like the computation of the temporal and spatial extent as
        well as the collecting of metadata.
        well as the collecting of metadata.
     """
     """
+    
+    __metaclass__ = ABCMeta
+    
     def __init__(self, ident):
     def __init__(self, ident):
         AbstractDataset.__init__(self)
         AbstractDataset.__init__(self)
         self.reset(ident)
         self.reset(ident)
         self.map_counter = 0
         self.map_counter = 0
 
 
-    def get_new_map_instance(self, ident=None):
-        """!Return a new instance of a map which is associated
-           with the type of this object
-
-           @param ident The unique identifier of the new object
-        """
-        raise ImplementationError(
-            "This method must be implemented in the subclasses")
-
     def create_map_register_name(self):
     def create_map_register_name(self):
         """!Create the name of the map register table of this space time
         """!Create the name of the map register table of this space time
             dataset
             dataset
@@ -62,13 +56,21 @@ class AbstractSpaceTimeDataset(AbstractDataset):
                 self.base.get_mapset() + "_" + \
                 self.base.get_mapset() + "_" + \
                 self.get_new_map_instance(None).get_type() + "_register"
                 self.get_new_map_instance(None).get_type() + "_register"
 
 
+    @abstractmethod
+    def get_new_map_instance(self, ident=None):
+        """!Return a new instance of a map which is associated
+           with the type of this object
+
+           @param ident The unique identifier of the new object
+        """
+        
+    @abstractmethod
     def get_map_register(self):
     def get_map_register(self):
         """!Return the name of the map register table
         """!Return the name of the map register table
            @return The map register table name
            @return The map register table name
         """
         """
-        raise ImplementationError(
-            "This method must be implemented in the subclasses")
 
 
+    @abstractmethod
     def set_map_register(self, name):
     def set_map_register(self, name):
         """!Set the name of the map register table
         """!Set the name of the map register table
 
 
@@ -80,8 +82,6 @@ class AbstractSpaceTimeDataset(AbstractDataset):
 
 
            @param name The name of the register table
            @param name The name of the register table
         """
         """
-        raise ImplementationError(
-            "This method must be implemented in the subclasses")
 
 
     def print_self(self):
     def print_self(self):
         """!Print the content of the internal structure to stdout"""
         """!Print the content of the internal structure to stdout"""
@@ -124,7 +124,7 @@ class AbstractSpaceTimeDataset(AbstractDataset):
         """!Set the initial values of the space time dataset
         """!Set the initial values of the space time dataset
 
 
             In addition the command creation string is generated
             In addition the command creation string is generated
-            an inerted into the metadata object.
+            an inserted into the metadata object.
 
 
             This method only modifies this object and does not commit
             This method only modifies this object and does not commit
             the modifications to the temporal database.
             the modifications to the temporal database.
@@ -140,9 +140,9 @@ class AbstractSpaceTimeDataset(AbstractDataset):
         """
         """
 
 
         if temporal_type == "absolute":
         if temporal_type == "absolute":
-            self.set_time_to_absolute()
+            self.base.set_ttype("absolute")
         elif temporal_type == "relative":
         elif temporal_type == "relative":
-            self.set_time_to_relative()
+            self.base.set_ttype("relative")
         else:
         else:
             core.fatal(_("Unknown temporal type \"%s\"") % (temporal_type))
             core.fatal(_("Unknown temporal type \"%s\"") % (temporal_type))
 
 
@@ -262,9 +262,9 @@ class AbstractSpaceTimeDataset(AbstractDataset):
             core.fatal(_("Wrong granularity: \"%s\"") % str(granularity))
             core.fatal(_("Wrong granularity: \"%s\"") % str(granularity))
 
 
         if temporal_type == "absolute":
         if temporal_type == "absolute":
-            self.set_time_to_absolute()
+            self.base.set_ttype("absolute")
         elif temporal_type == "relative":
         elif temporal_type == "relative":
-            self.set_time_to_relative()
+            self.base.set_ttype("relative")
         else:
         else:
             core.fatal(_("Unknown temporal type \"%s\"") % (temporal_type))
             core.fatal(_("Unknown temporal type \"%s\"") % (temporal_type))