Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions python/grass/temporal/abstract_map_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ def get_map_id(self):
"""
return self.base.get_map_id()

def get_readonly(self) -> bool:
"""Return True if this map is read-only (belongs to a foreign mapset)"""
return self.base.get_readonly()

@staticmethod
def split_name(name: str, layer=None, mapset=None):
"""Convenient method to split a map name into three potentially
Expand Down Expand Up @@ -356,7 +360,7 @@ def insert(self, dbif=None, execute: bool = True):
:return: The SQL insert statement in case execute=False, or an
empty string otherwise
"""
if get_enable_timestamp_write():
if get_enable_timestamp_write() and not self.get_readonly():
self.write_timestamp_to_grass()
return AbstractDataset.insert(self, dbif=dbif, execute=execute)

Expand All @@ -375,7 +379,7 @@ def update(self, dbif=None, execute: bool = True):
:return: The SQL insert statement in case execute=False, or an
empty string otherwise
"""
if get_enable_timestamp_write():
if get_enable_timestamp_write() and not self.get_readonly():
self.write_timestamp_to_grass()
return AbstractDataset.update(self, dbif, execute)

Expand All @@ -395,7 +399,7 @@ def update_all(self, dbif=None, execute: bool = True):
empty string otherwise

"""
if get_enable_timestamp_write():
if get_enable_timestamp_write() and not self.get_readonly():
self.write_timestamp_to_grass()
return AbstractDataset.update_all(self, dbif, execute)

Expand Down Expand Up @@ -534,7 +538,7 @@ def update_absolute_time(self, start_time, end_time=None, dbif=None) -> None:
if connection_state_changed:
dbif.close()

if get_enable_timestamp_write():
if get_enable_timestamp_write() and not self.get_readonly():
self.write_timestamp_to_grass()

def set_relative_time(self, start_time, end_time, unit) -> bool:
Expand Down Expand Up @@ -655,7 +659,7 @@ def update_relative_time(self, start_time, end_time, unit, dbif=None) -> None:
if connection_state_changed:
dbif.close()

if get_enable_timestamp_write():
if get_enable_timestamp_write() and not self.get_readonly():
self.write_timestamp_to_grass()

def set_temporal_extent(self, extent) -> None:
Expand Down
107 changes: 50 additions & 57 deletions python/grass/temporal/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,10 +256,11 @@ def __init__(self, table=None, ident=None) -> None:
self.ident = ident
self.msgr = get_tgis_message_interface()

if self.ident and self.ident.find("@") >= 0:
if self.ident and "@" in self.ident:
self.mapset = self.ident.split("@")[1]
else:
self.mapset = None
self._readonly = False

def get_table_name(self):
"""Return the name of the table in which the internal
Expand Down Expand Up @@ -631,12 +632,12 @@ class DatasetBase(SQLDatabaseInterface):
def __init__(
self,
table=None,
ident=None,
ident: str | None = None,
name: str | None = None,
mapset=None,
creator=None,
ctime=None,
ttype=None,
mapset: str | None = None,
creator: str | None = None,
ctime: datetime | None = None,
ttype: str | None = None,
) -> None:
"""Constructor

Expand All @@ -660,15 +661,17 @@ def __init__(

self.set_id(ident)
if ident is not None and name is None and mapset is None:
if ident.find("@") >= 0:
name, mapset = ident.split("@")
if name.find(":") >= 0:
name, layer = ident.split(":")
if "@" in ident:
name, mapset = ident.split("@", 1)
if ":" in name:
name, layer = name.split(":", 1)
self.set_name(name)
self.set_mapset(mapset)
self.set_creator(creator)
self.set_ctime(ctime)
self.set_ttype(ttype)
self._readonly = False
self.set_readonly()

def set_id(self, ident) -> None:
"""Convenient method to set the unique identifier (primary key)
Expand All @@ -682,14 +685,14 @@ def set_id(self, ident) -> None:
name = ""

if ident is not None:
if ident.find("@") >= 0:
name, mapset = ident.split("@")
if "@" in ident:
name, mapset = ident.split("@", 1)
self.set_mapset(mapset)
self.set_name(name)
else:
self.msgr.fatal(_("Wrong identifier, the mapset is missing"))
if name.find(":") >= 0:
name, layer = ident.split(":")
if ":" in name:
name, layer = name.split(":", 1)
self.set_layer(layer)
self.set_name(name)

Expand All @@ -706,6 +709,7 @@ def set_mapset(self, mapset) -> None:
:param mapset: The name of the mapset in which this dataset is stored
"""
self.D["mapset"] = mapset
self.set_readonly()

def set_layer(self, layer) -> None:
"""Convenient method to set the layer of the map (part of primary key)
Expand Down Expand Up @@ -745,84 +749,80 @@ def set_ttype(self, ttype) -> None:
else:
self.D["temporal_type"] = ttype

def get_id(self):
def get_id(self) -> str | None:
"""Convenient method to get the unique identifier (primary key)

:return: None if not found
"""
if "id" in self.D:
return self.D["id"]
return None
return self.D.get("id")

def get_map_id(self):
def get_map_id(self) -> str | None:
"""Convenient method to get the unique map identifier
without layer information

:return: The name of the vector map as "name@mapset"
or None in case the id was not set
"""
if self.id:
if self.id.find(":") >= 0:
if ":" in self.id:
# Remove the layer identifier from the id
return self.id.split("@")[0].split(":")[0] + "@" + self.id.split("@")[1]
return f"{self.id.split('@')[0].split(':')[0]}@{self.id.split('@')[1]}"
return self.id
return None

def get_layer(self):
def get_layer(self) -> str | None:
"""Convenient method to get the layer of the map (part of primary key)

Layer are currently supported for vector maps

:return: None if not found
"""
if "layer" in self.D:
return self.D["layer"]
return None
return self.D.get("layer")

def get_name(self):
def get_name(self) -> str | None:
"""Get the name of the dataset

:return: None if not found
"""
if "name" in self.D:
return self.D["name"]
return None
return self.D.get("name")

def get_mapset(self):
def get_mapset(self) -> str | None:
"""Get the name of mapset of this dataset

:return: None if not found
"""
if "mapset" in self.D:
return self.D["mapset"]
return None
return self.D.get("mapset")

def get_creator(self):
def get_creator(self) -> str | None:
"""Get the creator of the dataset

:return: None if not found
"""
if "creator" in self.D:
return self.D["creator"]
return None
return self.D.get("creator")

def get_ctime(self):
def get_ctime(self) -> datetime | None:
"""Get the creation time of the dataset, datatype is datetime

:return: None if not found
"""
if "creation_time" in self.D:
return self.D["creation_time"]
return None
return self.D.get("creation_time")

def get_ttype(self):
def get_ttype(self) -> str | None:
"""Get the temporal type of the map

:return: None if not found
"""
if "temporal_type" in self.D:
return self.D["temporal_type"]
return None
return self.D.get("temporal_type")

def set_readonly(self) -> None:
"""Set the readonly flag for this object"""
self._readonly = bool(
self.get_mapset() and self.get_mapset() != get_current_mapset()
)

def get_readonly(self) -> bool:
"""Get the readonly flag for this object"""
return self._readonly

# Properties of this class
id = property(fget=get_id, fset=set_id)
Expand All @@ -832,6 +832,7 @@ def get_ttype(self):
ctime = property(fget=get_ctime, fset=set_ctime)
ttype = property(fget=get_ttype, fset=set_ttype)
creator = property(fget=get_creator, fset=set_creator)
readonly = property(fget=get_readonly)

def print_info(self) -> None:
"""Print information about this class in human readable style"""
Expand Down Expand Up @@ -1030,19 +1031,15 @@ def get_semantic_type(self):

:return: None if not found
"""
if "semantic_type" in self.D:
return self.D["semantic_type"]
return None
return self.D.get("semantic_type")

def get_mtime(self):
"""Get the modification time of the space time dataset, datatype is
datetime

:return: None if not found
"""
if "modification_time" in self.D:
return self.D["modification_time"]
return None
return self.D.get("modification_time")

semantic_type = property(fget=get_semantic_type, fset=set_semantic_type)

Expand Down Expand Up @@ -1202,19 +1199,15 @@ def get_id(self):

:return: None if not found
"""
if "id" in self.D:
return self.D["id"]
return None
return self.D.get("id")

def get_registered_stds(self):
"""Get the comma separated list of space time datasets ids
in which this map is registered

:return: None if not found
"""
if "registered_stds" in self.D:
return self.D["registered_stds"]
return None
return self.D.get("registered_stds")

# Properties of this class
id = property(fget=get_id, fset=set_id)
Expand Down
27 changes: 25 additions & 2 deletions python/grass/temporal/space_time_datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,9 @@ def write_timestamp_to_grass(self) -> bool:

:return: True if success, False on error
"""
if self.get_readonly():
return False

check = self.ciface.write_raster_timestamp(
self.get_name(), self.get_mapset(), self._convert_timestamp()
)
Expand Down Expand Up @@ -341,6 +344,9 @@ def remove_timestamp_from_grass(self) -> bool:

:return: True if success, False on error
"""
if self.get_readonly():
return False

check = self.ciface.remove_raster_timestamp(self.get_name(), self.get_mapset())

if check == -1:
Expand Down Expand Up @@ -376,10 +382,14 @@ def write_semantic_label_to_grass(self) -> bool:
"""Write the semantic label of this map into the map metadata in
the GRASS file system based spatial database.

Internally the libgis API functions are used for writing
Internally the libgis API functions are used for writing. Writing is
only possible if the map is in the current mapset (not read-only).

:return: True if success, False on error
"""
if self.get_readonly():
return False

check = self.ciface.write_raster_semantic_label(
self.get_name(), self.get_mapset(), self.metadata.get_semantic_label()
)
Expand Down Expand Up @@ -470,7 +480,8 @@ def set_semantic_label(self, semantic_label) -> None:
:param str semantic_label: semantic label (eg. S2_1)
"""
self.metadata.set_semantic_label(semantic_label)
self.write_semantic_label_to_grass()
if not self.get_readonly():
self.write_semantic_label_to_grass()


###############################################################################
Expand Down Expand Up @@ -745,6 +756,9 @@ def write_timestamp_to_grass(self) -> bool:

:return: True if success, False on error
"""
if self.get_readonly():
return False

check = self.ciface.write_raster3d_timestamp(
self.get_name(), self.get_mapset(), self._convert_timestamp()
)
Expand Down Expand Up @@ -774,6 +788,9 @@ def remove_timestamp_from_grass(self) -> bool:

:return: True if success, False on error
"""
if self.get_readonly():
return False

check = self.ciface.remove_raster3d_timestamp(
self.get_name(), self.get_mapset()
)
Expand Down Expand Up @@ -1084,6 +1101,9 @@ def write_timestamp_to_grass(self) -> bool:

Internally the libgis API functions are used for writing
"""
if self.get_readonly():
return False

check = self.ciface.write_vector_timestamp(
self.get_name(),
self.get_mapset(),
Expand Down Expand Up @@ -1113,6 +1133,9 @@ def remove_timestamp_from_grass(self) -> bool:

Internally the libgis API functions are used for removal
"""
if self.get_readonly():
return False

check = self.ciface.remove_vector_timestamp(self.get_name(), self.get_mapset())

if check == -1:
Expand Down
Loading
Loading