Skip to content

Commit 73beed4

Browse files
committed
updating unit tests and implementing a bunch of things
1 parent 727ebd4 commit 73beed4

File tree

6 files changed

+52
-27
lines changed

6 files changed

+52
-27
lines changed

.vscode/launch.json

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,11 @@
1010
"request": "launch",
1111
"program": "${file}",
1212
"env": {
13-
"PYTHONPATH": "${workspaceFolder}/../../lib/commons"
13+
"PYTHONPATH": "${workspaceFolder}/src"
1414
},
1515
"console": "integratedTerminal",
1616
"envFile": "${workspaceFolder}/.env",
1717
"justMyCode": true
18-
},
19-
{
20-
// You need to enable QGIS VSCode debugger plugin
21-
// Before this will work
22-
"name": "QGIS Debug",
23-
"type": "debugpy",
24-
"request": "attach",
25-
"port": 5678,
26-
"host": "localhost",
27-
},
18+
}
2819
]
2920
}

RSXML-RiverscapesXML.code-workspace

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,13 @@
1010
"[python]": {
1111
"editor.tabSize": 4,
1212
"editor.formatOnSave": true,
13+
"editor.codeActionsOnSave": {
14+
"source.fixAll": "explicit",
15+
"source.organizeImports": "explicit"
16+
}
1317
},
14-
"autopep8.args": [
15-
"--max-line-length=240",
16-
],
17-
"pylint.args": [
18-
"--extension-pkg-whitelist=pygeoprocessing",
19-
"--disable=C0301,C0114,C0103,W0719,W0718",
20-
"--max-line-length=240"
18+
"python.analysis.extraPaths": [
19+
"./src"
2120
],
2221
"python.terminal.activateEnvironment": true,
2322
"python.testing.pytestEnabled": true,

examples/project_01_basic.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def main(filepath: str):
4545
bounding_box=BoundingBox(-22, -21, 114, 116),
4646
filepath="project_bounds.json",
4747
),
48-
meta_data=MetaData(values=[Meta("Test", "Test Value")]),
48+
meta_data=MetaData(values=[Meta("Test", "Test Value"), Meta("LockedMeta", "Locked Value", locked=True)]),
4949
realizations=[
5050
Realization(
5151
xml_id="test",
@@ -63,6 +63,7 @@ def main(filepath: str):
6363
ds_type=GeoPackageDatasetTypes.RASTER,
6464
summary="This is a input dataset",
6565
description="This is a input dataset",
66+
url="https://example.com/dataset",
6667
)
6768
],
6869
intermediates=[

noxfile.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
11
import nox
22

3+
# This file defines the automation tasks for the project using Nox.
4+
# Nox is a command-line tool that automates testing in multiple Python environments.
5+
# To run all sessions: uv run nox
6+
# To run a specific session: uv run nox -s lint
7+
38

49
@nox.session(python=["3.10", "3.11", "3.12"])
510
def tests(session):
11+
"""
12+
Run the test suite using pytest.
13+
This session installs the package in editable mode with dev dependencies
14+
and runs the tests across the specified Python versions.
15+
"""
616
session.install(".[dev]")
717
session.run("pytest")
818

919

1020
@nox.session
1121
def lint(session):
22+
"""
23+
Run linting checks using ruff.
24+
Ruff is a fast Python linter and code formatter.
25+
"""
1226
session.install("ruff")
1327
session.run("ruff", "check", ".")

src/rsxml/project_xml/Dataset.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class Dataset(RSObj):
6262
path: str
6363
ds_type: str
6464
ext_ref: str
65+
url: str
6566

6667
def __init__(
6768
self,
@@ -75,6 +76,7 @@ def __init__(
7576
description: str = None,
7677
citation: str = None,
7778
meta_data: MetaData = None,
79+
url: str = None,
7880
) -> None:
7981
"""
8082
Initializes a Dataset instance.
@@ -89,6 +91,7 @@ def __init__(
8991
description (str, optional): A detailed description of the dataset. Defaults to None.
9092
citation (str, optional): The citation information for the dataset. Defaults to None.
9193
meta_data (MetaData, optional): The metadata associated with the dataset. Defaults to None.
94+
url (str, optional): The URL for the dataset. Defaults to None.
9295
9396
Returns:
9497
None
@@ -109,7 +112,8 @@ def __init__(
109112
summary="A summary of the dataset",
110113
description="A detailed description of the dataset",
111114
citation="Citation information",
112-
meta_data=MetaData(...))
115+
meta_data=MetaData(...),
116+
url="https://example.com/dataset")
113117
"""
114118

115119
super().__init__(
@@ -135,6 +139,7 @@ def __init__(
135139
self.ds_type = ds_type.strip() if ds_type else None
136140
self.ds_type_attr = ds_type_attr.strip() if ds_type_attr else None
137141
self.ext_ref = ext_ref.strip() if ext_ref else None
142+
self.url = url.strip() if url else None
138143

139144
def __eq__(self, other: RSObj) -> bool:
140145
if not isinstance(other, Dataset):
@@ -143,7 +148,12 @@ def __eq__(self, other: RSObj) -> bool:
143148
if not super(Dataset, self).__eq__(other):
144149
return False
145150

146-
return self.path == other.path and self.ds_type == other.ds_type and self.ext_ref == other.ext_ref
151+
return (
152+
self.path == other.path
153+
and self.ds_type == other.ds_type
154+
and self.ext_ref == other.ext_ref
155+
and self.url == other.url
156+
)
147157

148158
@staticmethod
149159
def from_xml(xml_node: ET.Element) -> Dataset:
@@ -169,6 +179,7 @@ def from_xml(xml_node: ET.Element) -> Dataset:
169179
description=rsobj.description,
170180
citation=rsobj.citation,
171181
meta_data=rsobj.meta_data,
182+
url=xml_node.find("URL").text if xml_node.find("URL") is not None else None,
172183
)
173184
return dataset
174185

@@ -188,6 +199,8 @@ def to_xml(self) -> ET.Element:
188199
xml_node.set("type", self.ds_type_attr)
189200

190201
ET.SubElement(xml_node, "Path").text = self.path
202+
if self.url:
203+
ET.SubElement(xml_node, "URL").text = self.url
191204
return xml_node
192205

193206

src/rsxml/project_xml/MetaData.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class Meta(NamedTuple):
4444
value: MetaValue
4545
type: str = None # optional
4646
ext: str = None # optional
47+
locked: bool = False # optional
4748

4849

4950
class MetaData:
@@ -113,7 +114,7 @@ def _validate_ext_type(self, ext: str) -> None:
113114
if ext not in EXT_TYPES:
114115
raise ValueError(f"Invalid ext type {ext}. Valid types are {EXT_TYPES}")
115116

116-
def add_meta(self, name: str, value, meta_type: str = None, ext: str = None) -> None:
117+
def add_meta(self, name: str, value, meta_type: str = None, ext: str = None, locked: bool = False) -> None:
117118
"""
118119
Add a metadata item to the collection.
119120
The name must be unique and cannot be empty.
@@ -131,7 +132,7 @@ def add_meta(self, name: str, value, meta_type: str = None, ext: str = None) ->
131132
if ext is not None:
132133
self._validate_ext_type(ext)
133134

134-
self._values.append(Meta(name, value, meta_type, ext))
135+
self._values.append(Meta(name, value, meta_type, ext, locked))
135136

136137
def find_meta(self, name: str) -> Meta:
137138
"""
@@ -181,6 +182,7 @@ def from_xml(xml_node: ET.Element) -> MetaData:
181182
meta.text.strip() if meta.text else "",
182183
meta.get("type"),
183184
meta.get("ext"),
185+
meta.get("locked") == "true",
184186
)
185187
return meta_data
186188

@@ -201,10 +203,15 @@ def to_xml(self) -> ET.Element:
201203
"name": meta.name,
202204
},
203205
)
204-
if meta.type is not None:
205-
meta_node.set("type", meta.type)
206-
if meta.ext is not None:
207-
meta_node.set("ext", meta.ext)
206+
# Metric tags do not support type or ext attributes
207+
if self.inner_tag != "Metric":
208+
if meta.type is not None:
209+
meta_node.set("type", meta.type)
210+
if meta.ext is not None:
211+
meta_node.set("ext", meta.ext)
212+
213+
if meta.locked:
214+
meta_node.set("locked", "true")
208215

209216
meta_node.text = str(meta.value)
210217
meta_data.append(meta_node)

0 commit comments

Comments
 (0)