cwms-cli 0.7.2__tar.gz → 0.7.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/PKG-INFO +3 -2
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/commands_cwms.py +13 -9
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/shef/import_infile.py +61 -3
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/users.py +1 -1
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/load/timeseries/timeseries_ids.py +1 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/pyproject.toml +13 -4
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/LICENSE +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/README.md +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/__init__.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/__main__.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/_generated/__init__.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/_generated/ownership_data.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/callbacks/__init__.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/blob.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/clob.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/.gitignore +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/README.md +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/__init__.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/__main__.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/config.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/doclinks.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/examples/complete_config.json +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/parser.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/tests/__init__.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/tests/data/.gitignore +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/tests/data/expected_brok_output.json +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/tests/data/sample_brok.csv +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/tests/data/sample_config.json +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/tests/skip_test_integration_pipeline.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/tests/test_dateutils.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/tests/test_expressions.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/tests/test_fileio.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/tests/test_main.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/transform.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/utils/__init__.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/utils/dateutils.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/utils/expression.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/utils/fileio.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/utils/logging.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/writer.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/shef/__init__.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/shef/import_critfile.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/shef/shef_parameters.csv +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/load/README.md +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/load/__init__.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/load/__main__.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/load/location/location.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/load/location/location_ids.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/load/location/location_ids_bygroup.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/load/root.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/load/timeseries/timeseries.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/load/timeseries/timeseries_data.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/ownership.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/requirements.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/usgs/__init__.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/usgs/__main__.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/usgs/getUSGS_ratings_cda.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/usgs/getusgs_cda.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/usgs/getusgs_measurements_cda.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/usgs/rating_ini_file_import.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/utils/__init__.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/utils/auth.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/utils/callback_success.html +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/utils/click_help.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/utils/colors.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/utils/deps.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/utils/friendly_errors.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/utils/intervals.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/utils/io.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/utils/links.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/utils/logging/__init__.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/utils/logging/formatters.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/utils/ssl_errors.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/utils/update.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/utils/version.py +0 -0
- {cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/utils/version_cli.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cwms-cli
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.4
|
|
4
4
|
Summary: Command line utilities for Corps Water Management Systems (CWMS) python scripts. This is a collection of shared scripts across the enterprise Water Management Enterprise System (WMES) teams.
|
|
5
5
|
License: LICENSE
|
|
6
6
|
License-File: LICENSE
|
|
@@ -18,7 +18,8 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.14
|
|
19
19
|
Requires-Dist: click (>=8.1.8,<9.0.0)
|
|
20
20
|
Requires-Dist: colorama (>=0.4.6,<0.5.0)
|
|
21
|
-
Requires-Dist: requests (>=2.
|
|
21
|
+
Requires-Dist: requests (>=2.32.0,<3.0.0) ; python_version == "3.9"
|
|
22
|
+
Requires-Dist: requests (>=2.33.0,<3.0.0) ; python_version >= "3.10"
|
|
22
23
|
Project-URL: Repository, https://github.com/HydrologicEngineeringCenter/cwms-cli
|
|
23
24
|
Description-Content-Type: text/markdown
|
|
24
25
|
|
|
@@ -283,7 +283,15 @@ def shef_import_crit(filename, office, api_root, api_key, api_key_loc, dry_run):
|
|
|
283
283
|
# ================================================================================
|
|
284
284
|
@shef_group.command(
|
|
285
285
|
"import_infile",
|
|
286
|
-
help=
|
|
286
|
+
help=(
|
|
287
|
+
"Import a legacy exportShef .in configuration file into a CWMS "
|
|
288
|
+
"timeseries group (default category 'SHEF Export'). Each entry "
|
|
289
|
+
"becomes a group member whose alias-id encodes the SHEF location, "
|
|
290
|
+
"PE code, send code, duration, and (optionally) units. "
|
|
291
|
+
"If the bulk save fails, each TSID is validated via "
|
|
292
|
+
"get_timeseries_identifier; missing TSIDs are logged and skipped, "
|
|
293
|
+
"and the save is retried with the surviving entries."
|
|
294
|
+
),
|
|
287
295
|
)
|
|
288
296
|
@click.option(
|
|
289
297
|
"-f",
|
|
@@ -484,15 +492,13 @@ def update_cli_cmd(target_version: Optional[str], pre: bool, yes: bool) -> None:
|
|
|
484
492
|
@click.group(
|
|
485
493
|
"blob",
|
|
486
494
|
help="Manage CWMS Blobs (upload, download, delete, update, list)",
|
|
487
|
-
epilog=textwrap.dedent(
|
|
488
|
-
"""
|
|
495
|
+
epilog=textwrap.dedent("""
|
|
489
496
|
Example Usage:\n
|
|
490
497
|
- Store a PDF/image as a CWMS blob with optional description\n
|
|
491
498
|
- Download a blob by id to your local filesystem\n
|
|
492
499
|
- Update a blob's name/description/mime-type\n
|
|
493
500
|
- Bulk list blobs for an office
|
|
494
|
-
"""
|
|
495
|
-
),
|
|
501
|
+
"""),
|
|
496
502
|
)
|
|
497
503
|
def blob_group():
|
|
498
504
|
pass
|
|
@@ -700,14 +706,12 @@ def list_cmd(**kwargs):
|
|
|
700
706
|
@click.group(
|
|
701
707
|
"clob",
|
|
702
708
|
help="Manage CWMS Clobs (upload, download, delete, update, list)",
|
|
703
|
-
epilog=textwrap.dedent(
|
|
704
|
-
"""
|
|
709
|
+
epilog=textwrap.dedent("""
|
|
705
710
|
Example Usage:\n
|
|
706
711
|
- Download a clob by id to your local filesystem\n
|
|
707
712
|
- Update a clob's name/description/mime-type\n
|
|
708
713
|
- Bulk list clobs for an office
|
|
709
|
-
"""
|
|
710
|
-
),
|
|
714
|
+
"""),
|
|
711
715
|
)
|
|
712
716
|
@requires(reqs.cwms)
|
|
713
717
|
def clob_group():
|
|
@@ -588,13 +588,32 @@ def build_group_json(
|
|
|
588
588
|
# ---------------------------------------------------------------------------
|
|
589
589
|
|
|
590
590
|
|
|
591
|
-
def
|
|
591
|
+
def _filter_existing_tsids(
|
|
592
|
+
entries: list[dict],
|
|
593
|
+
office_id: str,
|
|
594
|
+
) -> list[dict]:
|
|
595
|
+
"""Probe each TSID via cwms.get_timeseries_identifier and drop missing ones."""
|
|
596
|
+
valid: list[dict] = []
|
|
597
|
+
for e in entries:
|
|
598
|
+
try:
|
|
599
|
+
cwms.get_timeseries_identifier(ts_id=e["tsid"], office_id=office_id)
|
|
600
|
+
valid.append(e)
|
|
601
|
+
except Exception as exc:
|
|
602
|
+
log.warning(
|
|
603
|
+
"Skipping missing TSID '%s' (%s)",
|
|
604
|
+
e["tsid"],
|
|
605
|
+
type(exc).__name__,
|
|
606
|
+
)
|
|
607
|
+
return valid
|
|
608
|
+
|
|
609
|
+
|
|
610
|
+
def _save(
|
|
592
611
|
group_json: dict,
|
|
593
612
|
group_id: str,
|
|
594
613
|
office_id: str,
|
|
595
614
|
fail_if_exists: bool,
|
|
596
615
|
) -> None:
|
|
597
|
-
"""
|
|
616
|
+
"""Single store/update attempt with no validation fallback."""
|
|
598
617
|
try:
|
|
599
618
|
cwms.store_timeseries_groups(group_json, fail_if_exists=fail_if_exists)
|
|
600
619
|
log.info("SUCCESS — group stored via store_timeseries_groups.")
|
|
@@ -606,7 +625,6 @@ def store_group(
|
|
|
606
625
|
exc,
|
|
607
626
|
)
|
|
608
627
|
|
|
609
|
-
# Fallback: update, replacing all assigned timeseries
|
|
610
628
|
cwms.update_timeseries_groups(
|
|
611
629
|
data=group_json,
|
|
612
630
|
group_id=group_id,
|
|
@@ -616,6 +634,44 @@ def store_group(
|
|
|
616
634
|
log.info("SUCCESS — group updated via update_timeseries_groups.")
|
|
617
635
|
|
|
618
636
|
|
|
637
|
+
def store_group(
|
|
638
|
+
group_json: dict,
|
|
639
|
+
group_id: str,
|
|
640
|
+
office_id: str,
|
|
641
|
+
fail_if_exists: bool,
|
|
642
|
+
entries: Optional[list[dict]] = None,
|
|
643
|
+
category_id: str = DEFAULT_CATEGORY,
|
|
644
|
+
) -> None:
|
|
645
|
+
"""POST (create) or PATCH (update) the timeseries group in CWMS.
|
|
646
|
+
|
|
647
|
+
On failure, validate each TSID individually, drop any that don't exist in
|
|
648
|
+
CWMS, and retry the save with the surviving entries.
|
|
649
|
+
"""
|
|
650
|
+
try:
|
|
651
|
+
_save(group_json, group_id, office_id, fail_if_exists)
|
|
652
|
+
return
|
|
653
|
+
except Exception as exc:
|
|
654
|
+
if entries is None:
|
|
655
|
+
raise
|
|
656
|
+
log.warning(
|
|
657
|
+
"Group save failed (%s: %s) — validating each TSID and retrying ...",
|
|
658
|
+
type(exc).__name__,
|
|
659
|
+
exc,
|
|
660
|
+
)
|
|
661
|
+
|
|
662
|
+
valid = _filter_existing_tsids(entries, office_id)
|
|
663
|
+
if not valid:
|
|
664
|
+
log.error("No valid TSIDs remain after validation — nothing to store.")
|
|
665
|
+
return
|
|
666
|
+
if len(valid) == len(entries):
|
|
667
|
+
log.error("All TSIDs validated but save still failed; re-raising.")
|
|
668
|
+
raise
|
|
669
|
+
|
|
670
|
+
log.info("Retrying save with %d/%d valid TSIDs.", len(valid), len(entries))
|
|
671
|
+
retry_json = build_group_json(valid, group_id, office_id, category_id)
|
|
672
|
+
_save(retry_json, group_id, office_id, fail_if_exists=False)
|
|
673
|
+
|
|
674
|
+
|
|
619
675
|
# ---------------------------------------------------------------------------
|
|
620
676
|
# Importable function for CLI integration
|
|
621
677
|
# ---------------------------------------------------------------------------
|
|
@@ -713,6 +769,8 @@ def import_shef_infile(
|
|
|
713
769
|
group_id=group_name,
|
|
714
770
|
office_id=office_id,
|
|
715
771
|
fail_if_exists=fail_if_exists,
|
|
772
|
+
entries=entries,
|
|
773
|
+
category_id=category_id,
|
|
716
774
|
)
|
|
717
775
|
|
|
718
776
|
log.info(
|
|
@@ -126,7 +126,7 @@ def _existing_user_name(users: list[dict], user_name: str) -> Optional[str]:
|
|
|
126
126
|
|
|
127
127
|
|
|
128
128
|
def _split_roles(
|
|
129
|
-
raw_roles: Optional[Union[tuple[str, ...], list[str]]] = None
|
|
129
|
+
raw_roles: Optional[Union[tuple[str, ...], list[str]]] = None,
|
|
130
130
|
) -> list[str]:
|
|
131
131
|
if not raw_roles:
|
|
132
132
|
return []
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name = "cwms-cli"
|
|
3
3
|
repository = "https://github.com/HydrologicEngineeringCenter/cwms-cli"
|
|
4
4
|
|
|
5
|
-
version = "0.7.
|
|
5
|
+
version = "0.7.4"
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
packages = [
|
|
@@ -20,17 +20,26 @@ authors = ["Eric Novotny <eric.v.novotny@usace.army.mil>", "Charles Graham <char
|
|
|
20
20
|
[tool.poetry.dependencies]
|
|
21
21
|
python = "^3.9"
|
|
22
22
|
click = "^8.1.8"
|
|
23
|
-
requests =
|
|
23
|
+
requests = [
|
|
24
|
+
{ version = "^2.33.0", python = ">=3.10" },
|
|
25
|
+
{ version = "^2.32.0", python = ">=3.9,<3.10" },
|
|
26
|
+
]
|
|
24
27
|
hecdss = { version = ">=0.1.24", optional = true } # Via https://github.com/HydrologicEngineeringCenter/hec-python-library/blob/main/hec/shared.py#L9-10
|
|
25
28
|
cwms-python = { version = ">=1.0.7", optional = true}
|
|
26
29
|
colorama = "^0.4.6"
|
|
27
30
|
|
|
28
31
|
[tool.poetry.group.dev.dependencies]
|
|
29
|
-
black =
|
|
32
|
+
black = [
|
|
33
|
+
{ version = "^26.3.1", python = ">=3.10" },
|
|
34
|
+
{ version = "^24.2.0", python = ">=3.9,<3.10" },
|
|
35
|
+
]
|
|
30
36
|
isort = "^5.13.2"
|
|
31
37
|
mypy = "^1.9.0"
|
|
32
38
|
pre-commit = "^3.6.2"
|
|
33
|
-
pytest =
|
|
39
|
+
pytest = [
|
|
40
|
+
{ version = "^9.0.3", python = ">=3.10" },
|
|
41
|
+
{ version = "^8.3.5", python = ">=3.9,<3.10" },
|
|
42
|
+
]
|
|
34
43
|
#pytest-cov = "^4.1.0"
|
|
35
44
|
#pandas-stubs = "^2.2.1.240316"
|
|
36
45
|
yamlfix = "^1.16.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/tests/data/expected_brok_output.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cwms_cli-0.7.2 → cwms_cli-0.7.4}/cwmscli/commands/csv2cwms/tests/skip_test_integration_pipeline.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|