Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: add from_dict method to construct configuration from dictionary #15

Merged
merged 19 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
701ef66
feat: add separate callback module
NucciTheBoss Aug 26, 2024
41c043e
chore(deps): update tox.ini to use new ruff command syntax
NucciTheBoss Aug 26, 2024
4a67164
chore(deps): update pyproject.toml to use new ruff syntax
NucciTheBoss Aug 26, 2024
8e58a9d
feat: simplify base editor implementation
NucciTheBoss Aug 26, 2024
1189f85
refactor: have config editors use explicitly declared methods rather …
NucciTheBoss Aug 26, 2024
2863e1e
feat!: add `from_*` methods for flexible creation of data models
NucciTheBoss Aug 26, 2024
43992ca
feat: add `BaseError` and `ModelError` for more granular exceptions
NucciTheBoss Aug 26, 2024
a28785f
tests: update unit tests for slurmconfig editor
NucciTheBoss Aug 26, 2024
4afd843
chore(deps): remove renovate
NucciTheBoss Aug 26, 2024
6df3071
chore(lint): use explicit re-exports in module __init__.py
NucciTheBoss Aug 26, 2024
72797ff
docs: slurm.conf -> slurmdbd.conf in function docstrings
NucciTheBoss Aug 26, 2024
8b6f6b5
refactor: use debug logging level instead of warning for ignored comm…
NucciTheBoss Aug 26, 2024
1eb6d94
docs: update README to match other Charmed HPC projects
NucciTheBoss Aug 26, 2024
82d9ed4
fix: use f-string to generate error message if config file is not found
NucciTheBoss Aug 26, 2024
b19f9de
feat: version bump and pypi metadata update
NucciTheBoss Aug 26, 2024
87e6fb2
refactor: make `clean` less Go-ish
NucciTheBoss Aug 26, 2024
703303f
refactor: use more clear naming for configuration option sets
NucciTheBoss Aug 26, 2024
67a1bdc
refactor: add type annotation to `generate_descriptors(...)` func
NucciTheBoss Aug 26, 2024
7a09a69
fix: use correct type annotations for SlurmConfig constructor
NucciTheBoss Aug 26, 2024
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
10 changes: 5 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ target-version = ["py38"]
# Linting tools configuration
[tool.ruff]
line-length = 99
extend-exclude = ["__pycache__", "*.egg_info"]

[tool.ruff.lint]
select = ["E", "W", "F", "C", "N", "D", "I001"]
extend-ignore = [
"D203",
Expand All @@ -80,9 +83,6 @@ extend-ignore = [
"D409",
"D413",
]
ignore = ["E501", "D105", "D107"]
extend-exclude = ["__pycache__", "*.egg_info", "__init__.py"]
ignore = ["E501", "D107"]
per-file-ignores = {"tests/*" = ["D100","D101","D102","D103","D104"]}

[tool.ruff.mccabe]
max-complexity = 15
mccabe = { "max-complexity" = 15 }
6 changes: 0 additions & 6 deletions renovate.json

This file was deleted.

4 changes: 2 additions & 2 deletions slurmutils/editors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@

"""Editors for Slurm workload manager configuration files."""

from . import slurmconfig
from . import slurmdbdconfig
from . import slurmconfig as slurmconfig
from . import slurmdbdconfig as slurmdbdconfig
229 changes: 0 additions & 229 deletions slurmutils/editors/_editor.py

This file was deleted.

131 changes: 131 additions & 0 deletions slurmutils/editors/editor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Copyright 2024 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License version 3 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""Base methods for Slurm workload manager configuration file editors."""

import logging
import shlex
from functools import wraps
from os import path
from typing import Any, Dict, List, Tuple

from ..exceptions import EditorError

_logger = logging.getLogger("slurmutils")


def _is_comment(line: str) -> bool:
"""Check if line is a comment."""
return line.startswith("#")


def _contains_comment(line: str) -> bool:
"""Check if line contains an inline comment."""
return "#" in line


def _slice_comment(line: str) -> str:
"""Slice inline comment off of line."""
return line.split("#", maxsplit=1)[0]


def clean(line: str) -> Tuple[str, bool]:
"""Clean line before further processing.

Returns:
Returns the cleaned line and False if it should be ignored.
If True, then the processors should ignore the line.
NucciTheBoss marked this conversation as resolved.
Show resolved Hide resolved
"""
if _is_comment(line):
return "", True

return (_slice_comment(line) if _contains_comment(line) else line).strip(), False
NucciTheBoss marked this conversation as resolved.
Show resolved Hide resolved


def parse_line(options, line: str) -> Dict[str, Any]:
"""Parse configuration line.

Args:
options: Available options for line.
line: Configuration line to parse.
"""
data = {}
opts = shlex.split(line) # Use `shlex.split(...)` to preserve quotation strings.
for opt in opts:
k, v = opt.split("=", maxsplit=1)
if not hasattr(options, k):
raise EditorError(
(
f"unable to parse configuration option {k}. "
+ f"valid configuration options are {[option.name for option in options]}"
)
)

parse = getattr(options, k).parser
data[k] = parse(v) if parse else v

return data


def marshall_content(options, line: Dict[str, Any]) -> List[str]:
"""Marshall data model content back into configuration line.

Args:
options: Available options for line.
line: Data model to marshall into line.
"""
result = []
for k, v in line.items():
if not hasattr(options, k):
raise EditorError(
(
f"unable to marshall configuration option {k}. "
+ f"valid configuration options are {[option.name for option in options]}"
)
)

marshall = getattr(options, k).marshaller
result.append(f"{k}={marshall(v) if marshall else v}")

return result


def loader(func):
"""Wrap function that loads configuration data from file."""

@wraps(func)
def wrapper(*args, **kwargs):
fin = args[0]
if not path.exists(fin):
raise FileNotFoundError("could not locate %s", fin)

_logger.debug("reading contents of %s", fin)
return func(*args, **kwargs)

return wrapper


def dumper(func):
"""Wrap function that dumps configuration data to file."""

@wraps(func)
def wrapper(*args, **kwargs):
fout = args[1]
if path.exists(fout):
_logger.debug("overwriting current contents of %s", fout)

_logger.debug("updating contents of %s", fout)
return func(*args, **kwargs)

return wrapper
Loading