Skip to content
Merged
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
17 changes: 17 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# DO NOT EDIT THIS FILE MANUALLY.
# Generated from maintainers.toml by scripts/sync_ownership.py.
# Update maintainers.toml, then rerun the sync script.

* charles.r.graham@usace.army.mil eric.v.novotny@usace.army.mil # Default owners for repository-wide files and shared cwms-cli behavior
/.github/CODEOWNERS charles.r.graham@usace.army.mil eric.v.novotny@usace.army.mil # Protect ownership rules themselves
/cwmscli/commands/csv2cwms/ charles.r.graham@usace.army.mil
/docs/cli/csv2cwms*.rst charles.r.graham@usace.army.mil
/cwmscli/commands/blob.py charles.r.graham@usace.army.mil
/docs/cli/blob.rst charles.r.graham@usace.army.mil
/cwmscli/utils/update.py charles.r.graham@usace.army.mil
/docs/cli/update.rst charles.r.graham@usace.army.mil
/cwmscli/load/ charles.r.graham@usace.army.mil eric.v.novotny@usace.army.mil
/docs/cli/load_*.rst charles.r.graham@usace.army.mil eric.v.novotny@usace.army.mil
/cwmscli/usgs/ eric.v.novotny@usace.army.mil
/cwmscli/commands/shef_critfile_import.py eric.v.novotny@usace.army.mil
/cwmscli/commands/commands_cwms.py charles.r.graham@usace.army.mil eric.v.novotny@usace.army.mil # Shared Click wrappers span commands owned by both maintainers
3 changes: 3 additions & 0 deletions .github/workflows/code-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,7 @@ jobs:
poetry config virtualenvs.create false
poetry install --no-interaction

- name: Verify generated ownership files
run: poetry run python scripts/sync_ownership.py --check

- uses: pre-commit/action@v3.0.1
8 changes: 8 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,23 @@ repos:
entry: poetry run black
language: system
types: [file, python]
exclude: ^cwmscli/_generated/ownership_data\.py$

- id: isort
name: isort
entry: poetry run isort
language: system
types: [file, python]
exclude: ^cwmscli/_generated/ownership_data\.py$

- id: yamlfix
name: yamlfix
entry: poetry run yamlfix
language: system
types: [file, yaml]

- id: ownership-sync
name: generated ownership files
entry: poetry run python scripts/sync_ownership.py --check
language: system
pass_filenames: false
8 changes: 8 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ Once you have the repository on your system you can proceed:
3. `python -m pip install -e .` - This adds cwms-cli and it's commands to your local path allowing you to live develop cwms-cli as a package and test the CLI functions on your system.
4. Run `cwms-cli` to confirm everything installed!

## Ownership Metadata

Ownership metadata is centralized in [maintainers.toml](/maintainers.toml).

- Run `python scripts/sync_ownership.py` after editing `maintainers.toml` to regenerate `.github/CODEOWNERS` and synced package authors in [pyproject.toml](/pyproject.toml).
- Run `python scripts/sync_ownership.py --check` to verify the generated ownership files are current.
- The local `pre-commit` hook will check this if you installed it, but GitHub Actions is the enforcement point for contributors who do not have hooks installed.

## Running Tests

To run tests you can run: `poetry run pytest`
Expand Down
1 change: 1 addition & 0 deletions cwmscli/_generated/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Generated files used at runtime and in docs.
57 changes: 57 additions & 0 deletions cwmscli/_generated/ownership_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# DO NOT EDIT THIS FILE MANUALLY.
# Generated from maintainers.toml by scripts/sync_ownership.py.

OWNERSHIP_DATA = {
"commands": {
"cwms-cli blob": [
{
"email": "charles.r.graham@usace.army.mil",
"name": "Charles Graham"
}
],
"cwms-cli csv2cwms": [
{
"email": "charles.r.graham@usace.army.mil",
"name": "Charles Graham"
}
],
"cwms-cli load": [
{
"email": "charles.r.graham@usace.army.mil",
"name": "Charles Graham"
},
{
"email": "eric.v.novotny@usace.army.mil",
"name": "Eric Novotny"
}
],
"cwms-cli shefcritimport": [
{
"email": "eric.v.novotny@usace.army.mil",
"name": "Eric Novotny"
}
],
"cwms-cli update": [
{
"email": "charles.r.graham@usace.army.mil",
"name": "Charles Graham"
}
],
"cwms-cli usgs": [
{
"email": "eric.v.novotny@usace.army.mil",
"name": "Eric Novotny"
}
]
},
"default": [
{
"email": "charles.r.graham@usace.army.mil",
"name": "Charles Graham"
},
{
"email": "eric.v.novotny@usace.army.mil",
"name": "Eric Novotny"
}
]
}
26 changes: 26 additions & 0 deletions cwmscli/ownership.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from __future__ import annotations

from cwmscli._generated.ownership_data import OWNERSHIP_DATA


def _command_candidates(command_path: str) -> list[str]:
parts = command_path.split()
candidates = [" ".join(parts[:i]) for i in range(len(parts), 0, -1)]
return [candidate for candidate in candidates if candidate]


def get_command_maintainers(command_path: str) -> list[dict[str, str]]:
commands = OWNERSHIP_DATA["commands"]
for candidate in _command_candidates(command_path):
if candidate in commands:
return commands[candidate]
return OWNERSHIP_DATA["default"]


def get_core_maintainer_emails() -> set[str]:
return {person["email"] for person in OWNERSHIP_DATA["default"]}


def format_command_maintainers(command_path: str) -> str:
maintainers = get_command_maintainers(command_path)
return ", ".join(person["name"] for person in maintainers)
34 changes: 34 additions & 0 deletions cwmscli/utils/click_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import click

from cwmscli.ownership import get_command_maintainers, get_core_maintainer_emails
from cwmscli.utils import colors
from cwmscli.utils.version import get_cwms_cli_version

Expand Down Expand Up @@ -57,6 +58,32 @@ def _render_docs_line(ctx: click.Context) -> Optional[str]:
return f"Docs: {colors.c(docs_url, 'blue', bright=True)}"


def _command_path(ctx: click.Context) -> str:
names: list[str] = []
cur: Optional[click.Context] = ctx
while cur is not None:
name = (cur.info_name or getattr(cur.command, "name", None) or "").strip()
if name:
if cur.parent is None:
name = "cwms-cli"
names.append(name)
cur = cur.parent
names.reverse()
return " ".join(names)


def _render_maintainers_line(ctx: click.Context) -> str:
command_path = _command_path(ctx)
core_emails = get_core_maintainer_emails()
rendered = []
for person in get_command_maintainers(command_path):
name = person["name"]
if person["email"] in core_emails:
name = colors.c(name, "blue", bright=True)
rendered.append(name)
return f"Maintainers: {', '.join(rendered)}"


def _inject_help_header(help_text: str, ctx: click.Context) -> str:
lines = help_text.splitlines()
if not lines:
Expand All @@ -68,14 +95,21 @@ def _inject_help_header(help_text: str, ctx: click.Context) -> str:

version_line = _render_version_line(ctx)
docs_line = _render_docs_line(ctx)
maintainers_line = _render_maintainers_line(ctx)
if lines[0].startswith("Usage:"):
lines.insert(1, version_line)
if docs_line is not None:
lines.insert(2, docs_line)
lines.insert(3, maintainers_line)
else:
lines.insert(2, maintainers_line)
else:
lines.insert(0, version_line)
if docs_line is not None:
lines.insert(1, docs_line)
lines.insert(2, maintainers_line)
else:
lines.insert(1, maintainers_line)
return "\n".join(lines)


Expand Down
3 changes: 3 additions & 0 deletions docs/_generated/maintainers/blob.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.. note::

Maintainers: Charles Graham
3 changes: 3 additions & 0 deletions docs/_generated/maintainers/cli.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.. note::

Maintainers: Charles Graham, Eric Novotny
3 changes: 3 additions & 0 deletions docs/_generated/maintainers/csv2cwms.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.. note::

Maintainers: Charles Graham
3 changes: 3 additions & 0 deletions docs/_generated/maintainers/load_location_ids_all.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.. note::

Maintainers: Charles Graham, Eric Novotny
3 changes: 3 additions & 0 deletions docs/_generated/maintainers/update.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.. note::

Maintainers: Charles Graham
2 changes: 2 additions & 0 deletions docs/cli.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
CLI reference
=============

.. include:: _generated/maintainers/cli.inc

See also
--------

Expand Down
2 changes: 2 additions & 0 deletions docs/cli/blob.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
Blob commands
=============

.. include:: ../_generated/maintainers/blob.inc

Use ``cwms-cli blob`` to upload, download, delete, update, and list CWMS blobs.

Quick reference
Expand Down
2 changes: 2 additions & 0 deletions docs/cli/csv2cwms.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
csv2cwms
========

.. include:: ../_generated/maintainers/csv2cwms.inc

Use ``cwms-cli csv2cwms`` to load CSV time series data into
`CWMS Data API (CDA) <https://cwms-data.usace.army.mil/cwms-data>`_ with a
user-defined JSON configuration file.
Expand Down
2 changes: 2 additions & 0 deletions docs/cli/load_location_ids_all.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
Load Location ids-all
=====================

.. include:: ../_generated/maintainers/load_location_ids_all.inc

Use ``cwms-cli load location ids-all`` to copy locations selected by the
source CDA catalog into a target CDA.

Expand Down
2 changes: 2 additions & 0 deletions docs/cli/update.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
Update command
==============

.. include:: ../_generated/maintainers/update.inc

Use ``cwms-cli update`` to update the installed ``cwms-cli`` package with pip.
By default it installs the latest available release, and you can optionally
target a specific version with ``--target-version``. After updating, use
Expand Down
83 changes: 83 additions & 0 deletions maintainers.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
[people.charles]
name = "Charles Graham"
email = "charles.r.graham@usace.army.mil"

[people.eric]
name = "Eric Novotny"
email = "eric.v.novotny@usace.army.mil"

[poetry]
authors = ["eric", "charles"]

[cli]
default = ["charles", "eric"]

[cli.commands]
"cwms-cli csv2cwms" = ["charles"]
"cwms-cli blob" = ["charles"]
"cwms-cli update" = ["charles"]
"cwms-cli load" = ["charles", "eric"]
"cwms-cli usgs" = ["eric"]
"cwms-cli shefcritimport" = ["eric"]

[docs.pages]
"cli" = "cwms-cli"
"blob" = "cwms-cli blob"
"csv2cwms" = "cwms-cli csv2cwms"
"update" = "cwms-cli update"
"load_location_ids_all" = "cwms-cli load"

[[codeowners.rule]]
pattern = "*"
owners = ["charles", "eric"]
comment = "Default owners for repository-wide files and shared cwms-cli behavior"

[[codeowners.rule]]
pattern = "/.github/CODEOWNERS"
owners = ["charles", "eric"]
comment = "Protect ownership rules themselves"

[[codeowners.rule]]
pattern = "/cwmscli/commands/csv2cwms/"
owners = ["charles"]

[[codeowners.rule]]
pattern = "/docs/cli/csv2cwms*.rst"
owners = ["charles"]

[[codeowners.rule]]
pattern = "/cwmscli/commands/blob.py"
owners = ["charles"]

[[codeowners.rule]]
pattern = "/docs/cli/blob.rst"
owners = ["charles"]

[[codeowners.rule]]
pattern = "/cwmscli/utils/update.py"
owners = ["charles"]

[[codeowners.rule]]
pattern = "/docs/cli/update.rst"
owners = ["charles"]

[[codeowners.rule]]
pattern = "/cwmscli/load/"
owners = ["charles", "eric"]

[[codeowners.rule]]
pattern = "/docs/cli/load_*.rst"
owners = ["charles", "eric"]

[[codeowners.rule]]
pattern = "/cwmscli/usgs/"
owners = ["eric"]

[[codeowners.rule]]
pattern = "/cwmscli/commands/shef_critfile_import.py"
owners = ["eric"]

[[codeowners.rule]]
pattern = "/cwmscli/commands/commands_cwms.py"
owners = ["charles", "eric"]
comment = "Shared Click wrappers span commands owned by both maintainers"
Loading
Loading