diracx-cli 0.0.1a16__py3-none-any.whl → 0.0.1a18__py3-none-any.whl

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.
@@ -4,7 +4,7 @@ from typing import Annotated, Optional
4
4
  import git
5
5
  import typer
6
6
  import yaml
7
- from pydantic import parse_obj_as
7
+ from pydantic import TypeAdapter
8
8
 
9
9
  from diracx.core.config import ConfigSource, ConfigSourceUrl
10
10
  from diracx.core.config.schema import (
@@ -25,13 +25,11 @@ app.add_typer(legacy.app, name="legacy")
25
25
 
26
26
 
27
27
  @app.command()
28
- def generate_cs(
29
- config_repo: str,
30
- ):
31
- """Generate a minimal DiracX configuration repository"""
32
- # TODO: The use of parse_obj_as should be moved in to typer itself
33
- config_repo = parse_obj_as(ConfigSourceUrl, config_repo)
34
- if config_repo.scheme != "git+file":
28
+ def generate_cs(config_repo: str):
29
+ """Generate a minimal DiracX configuration repository."""
30
+ # TODO: The use of TypeAdapter should be moved in to typer itself
31
+ config_repo = TypeAdapter(ConfigSourceUrl).validate_python(config_repo)
32
+ if config_repo.scheme != "git+file" or config_repo.path is None:
35
33
  raise NotImplementedError("Only git+file:// URLs are supported")
36
34
  repo_path = Path(config_repo.path)
37
35
  if repo_path.exists() and list(repo_path.iterdir()):
@@ -60,10 +58,11 @@ def add_vo(
60
58
  idp_url: Annotated[str, typer.Option()],
61
59
  idp_client_id: Annotated[str, typer.Option()],
62
60
  ):
63
- """Add a registry entry (vo) to an existing configuration repository"""
64
-
65
- # TODO: The use of parse_obj_as should be moved in to typer itself
66
- config_repo = parse_obj_as(ConfigSourceUrl, config_repo)
61
+ """Add a registry entry (vo) to an existing configuration repository."""
62
+ # TODO: The use of TypeAdapter should be moved in to typer itself
63
+ config_repo = TypeAdapter(ConfigSourceUrl).validate_python(config_repo)
64
+ if config_repo.scheme != "git+file" or config_repo.path is None:
65
+ raise NotImplementedError("Only git+file:// URLs are supported")
67
66
  repo_path = Path(config_repo.path)
68
67
 
69
68
  # A VO should at least contain a default group
@@ -102,10 +101,11 @@ def add_group(
102
101
  group: Annotated[str, typer.Option()],
103
102
  properties: list[str] = ["NormalUser"],
104
103
  ):
105
- """Add a group to an existing vo in the configuration repository"""
106
-
107
- # TODO: The use of parse_obj_as should be moved in to typer itself
108
- config_repo = parse_obj_as(ConfigSourceUrl, config_repo)
104
+ """Add a group to an existing vo in the configuration repository."""
105
+ # TODO: The use of TypeAdapter should be moved in to typer itself
106
+ config_repo = TypeAdapter(ConfigSourceUrl).validate_python(config_repo)
107
+ if config_repo.scheme != "git+file" or config_repo.path is None:
108
+ raise NotImplementedError("Only git+file:// URLs are supported")
109
109
  repo_path = Path(config_repo.path)
110
110
 
111
111
  new_group = GroupConfig(Properties=set(properties), Quota=None, Users=set())
@@ -137,10 +137,11 @@ def add_user(
137
137
  sub: Annotated[str, typer.Option()],
138
138
  preferred_username: Annotated[str, typer.Option()],
139
139
  ):
140
- """Add a user to an existing vo and group"""
141
-
142
- # TODO: The use of parse_obj_as should be moved in to typer itself
143
- config_repo = parse_obj_as(ConfigSourceUrl, config_repo)
140
+ """Add a user to an existing vo and group."""
141
+ # TODO: The use of TypeAdapter should be moved in to typer itself
142
+ config_repo = TypeAdapter(ConfigSourceUrl).validate_python(config_repo)
143
+ if config_repo.scheme != "git+file" or config_repo.path is None:
144
+ raise NotImplementedError("Only git+file:// URLs are supported")
144
145
 
145
146
  repo_path = Path(config_repo.path)
146
147
 
@@ -180,10 +181,12 @@ def add_user(
180
181
 
181
182
 
182
183
  def update_config_and_commit(repo_path: Path, config: Config, message: str):
183
- """Update the yaml file in the repo and commit it"""
184
+ """Update the yaml file in the repo and commit it."""
184
185
  repo = git.Repo(repo_path)
185
186
  yaml_path = repo_path / "default.yml"
186
187
  typer.echo(f"Writing back configuration to {yaml_path}", err=True)
187
- yaml_path.write_text(yaml.safe_dump(config.dict(exclude_unset=True)))
188
+ yaml_path.write_text(
189
+ yaml.safe_dump(config.model_dump(exclude_unset=True, mode="json"))
190
+ )
188
191
  repo.index.add([yaml_path.relative_to(repo_path)])
189
192
  repo.index.commit(message)
@@ -53,7 +53,7 @@ class ConversionConfig(BaseModel):
53
53
 
54
54
  @app.command()
55
55
  def cs_sync(old_file: Path, new_file: Path):
56
- """Load the old CS and convert it to the new YAML format"""
56
+ """Load the old CS and convert it to the new YAML format."""
57
57
  if not os.environ.get("DIRAC_COMPAT_ENABLE_CS_CONVERSION"):
58
58
  raise RuntimeError(
59
59
  "DIRAC_COMPAT_ENABLE_CS_CONVERSION must be set for the conversion to be possible"
@@ -79,14 +79,15 @@ def cs_sync(old_file: Path, new_file: Path):
79
79
 
80
80
  _apply_fixes(raw)
81
81
 
82
- config = Config.parse_obj(raw)
83
- new_file.write_text(yaml.safe_dump(config.dict(exclude_unset=True)))
82
+ config = Config.model_validate(raw)
83
+ new_file.write_text(
84
+ yaml.safe_dump(config.model_dump(exclude_unset=True, mode="json"))
85
+ )
84
86
 
85
87
 
86
88
  def _apply_fixes(raw):
87
- """Modify raw in place to make any layout changes between the old and new structure"""
88
-
89
- conv_config = ConversionConfig.parse_obj(raw["DiracX"]["CsSync"])
89
+ """Modify raw in place to make any layout changes between the old and new structure."""
90
+ conv_config = ConversionConfig.model_validate(raw["DiracX"]["CsSync"])
90
91
 
91
92
  raw.pop("DiracX", None)
92
93
  # Remove dips specific parts from the CS
@@ -119,7 +120,7 @@ def _apply_fixes(raw):
119
120
 
120
121
  for vo, vo_meta in conv_config.VOs.items():
121
122
  raw["Registry"][vo] = {
122
- "IdP": vo_meta.IdP,
123
+ "IdP": vo_meta.IdP.model_dump(),
123
124
  "DefaultGroup": vo_meta.DefaultGroup,
124
125
  "Users": {},
125
126
  "Groups": {},
@@ -182,15 +183,15 @@ def generate_helm_values(
182
183
  ),
183
184
  output_file: Path = Option(help="Where to dump the yam file"),
184
185
  ):
185
- """Generate an initial values.yaml to run a DiracX installation
186
- compatible with a DIRAC instance. The file is not complete, and needs
187
- manual editing"""
186
+ """Generate an initial values.yaml to run a DiracX installation.
188
187
 
188
+ The file generated is not complete, and needs manual editing.
189
+ """
189
190
  helm_values = {
190
191
  "developer": {"enabled": False},
191
- "init-cs": {"enabled": True},
192
- "init-secrets": {"enabled": True},
193
- "init-sql": {"enabled": False, "env": {}},
192
+ "initCs": {"enabled": True},
193
+ "initSecrets": {"enabled": True},
194
+ "initSql": {"enabled": False, "env": {}},
194
195
  "cert-manager": {"enabled": False},
195
196
  "cert-manager-issuer": {"enabled": False},
196
197
  "minio": {"enabled": False},
diracx/cli/jobs.py CHANGED
@@ -20,6 +20,12 @@ from .utils import AsyncTyper
20
20
  app = AsyncTyper()
21
21
 
22
22
 
23
+ available_operators = (
24
+ f"Scalar operators: {', '.join([op.value for op in ScalarSearchOperator])}. "
25
+ f"Vector operators: {', '.join([op.value for op in VectorSearchOperator])}."
26
+ )
27
+
28
+
23
29
  def parse_condition(value: str) -> SearchSpec:
24
30
  parameter, operator, rest = value.split(" ", 2)
25
31
  if operator in set(ScalarSearchOperator):
@@ -51,15 +57,18 @@ async def search(
51
57
  "Owner",
52
58
  "LastUpdateTime",
53
59
  ],
54
- condition: Annotated[list[SearchSpec], Option(parser=parse_condition)] = [],
60
+ condition: Annotated[
61
+ list[str], Option(help=f'Example: "JobID eq 1000". {available_operators}')
62
+ ] = [],
55
63
  all: bool = False,
56
64
  page: int = 1,
57
65
  per_page: int = 10,
58
66
  ):
67
+ search_specs = [parse_condition(cond) for cond in condition]
59
68
  async with DiracClient() as api:
60
69
  jobs, content_range = await api.jobs.search(
61
70
  parameters=None if all else parameter,
62
- search=condition if condition else None,
71
+ search=search_specs if search_specs else None,
63
72
  page=page,
64
73
  per_page=per_page,
65
74
  cls=lambda _, jobs, headers: (
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: diracx-cli
3
- Version: 0.0.1a16
3
+ Version: 0.0.1a18
4
4
  Summary: TODO
5
5
  License: GPL-3.0-only
6
6
  Classifier: Intended Audience :: Science/Research
@@ -8,7 +8,7 @@ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: Topic :: Scientific/Engineering
10
10
  Classifier: Topic :: System :: Distributed Computing
11
- Requires-Python: >=3.10
11
+ Requires-Python: >=3.11
12
12
  Description-Content-Type: text/markdown
13
13
  Requires-Dist: diraccfg
14
14
  Requires-Dist: diracx-api
@@ -20,7 +20,7 @@ Requires-Dist: rich
20
20
  Requires-Dist: typer
21
21
  Requires-Dist: pyyaml
22
22
  Provides-Extra: testing
23
- Requires-Dist: diracx-testing ; extra == 'testing'
23
+ Requires-Dist: diracx-testing; extra == "testing"
24
24
  Provides-Extra: types
25
- Requires-Dist: types-PyYAML ; extra == 'types'
25
+ Requires-Dist: types-PyYAML; extra == "types"
26
26
 
@@ -0,0 +1,13 @@
1
+ diracx/cli/__init__.py,sha256=HI6-8S6JFU4hjX7DHy9c4jwUp7PVKwCxflcJCqqtu3M,4059
2
+ diracx/cli/__main__.py,sha256=SM9tEc-fiW7cDHTKQRwgKobe5FfijHLYiAWfWaIM_zg,56
3
+ diracx/cli/config.py,sha256=r5Lq_SN-1t3IzGAeS57ZzS-ukLhP6PMnmTXNld2pZXU,818
4
+ diracx/cli/jobs.py,sha256=rv3sa6Cz32y2wvKR7yV7mT719VOMm8qZ1nZFviNF98E,4721
5
+ diracx/cli/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ diracx/cli/utils.py,sha256=NwhMMHwveKOdW2aoSqpnLnfOKhPnjmPPLpX69naPAzc,855
7
+ diracx/cli/internal/__init__.py,sha256=DCKzknHUEvo7PYiatZis15-gkxhga5WU4cyVZ6LCkmA,6578
8
+ diracx/cli/internal/legacy.py,sha256=bhq8vfHoL0fZGhtye0EqMsucwepOYpQkj3UGe-rHNhY,10882
9
+ diracx_cli-0.0.1a18.dist-info/METADATA,sha256=9ucMoiWh8Zqf0OmnhyjxI4AcTOFVQjX0MfLF2ppAZlU,790
10
+ diracx_cli-0.0.1a18.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
11
+ diracx_cli-0.0.1a18.dist-info/entry_points.txt,sha256=pKKS950WHHoO6teZZXkWztX2XZFZSH6uh9BKY1PA-jg,41
12
+ diracx_cli-0.0.1a18.dist-info/top_level.txt,sha256=vJx10tdRlBX3rF2Psgk5jlwVGZNcL3m_7iQWwgPXt-U,7
13
+ diracx_cli-0.0.1a18.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (75.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,13 +0,0 @@
1
- diracx/cli/__init__.py,sha256=HI6-8S6JFU4hjX7DHy9c4jwUp7PVKwCxflcJCqqtu3M,4059
2
- diracx/cli/__main__.py,sha256=SM9tEc-fiW7cDHTKQRwgKobe5FfijHLYiAWfWaIM_zg,56
3
- diracx/cli/config.py,sha256=r5Lq_SN-1t3IzGAeS57ZzS-ukLhP6PMnmTXNld2pZXU,818
4
- diracx/cli/jobs.py,sha256=H1aQGFjaVLG2BShZO0cU3103QiuD1DR81cpm7drQ5Fs,4419
5
- diracx/cli/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- diracx/cli/utils.py,sha256=NwhMMHwveKOdW2aoSqpnLnfOKhPnjmPPLpX69naPAzc,855
7
- diracx/cli/internal/__init__.py,sha256=17PDFFNhppYPPq6KPmMxnOG3N6sP3apewpk8VjjHTYY,6041
8
- diracx/cli/internal/legacy.py,sha256=qiO73vIh2LPM6jma6G2RcLINwX6ZP5i1rhYBVMMYOuE,10849
9
- diracx_cli-0.0.1a16.dist-info/METADATA,sha256=T-3BwwSBhj85cqTxaHIkyC3bS9VATqkIxGkdZ2Ae09w,792
10
- diracx_cli-0.0.1a16.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
11
- diracx_cli-0.0.1a16.dist-info/entry_points.txt,sha256=pKKS950WHHoO6teZZXkWztX2XZFZSH6uh9BKY1PA-jg,41
12
- diracx_cli-0.0.1a16.dist-info/top_level.txt,sha256=vJx10tdRlBX3rF2Psgk5jlwVGZNcL3m_7iQWwgPXt-U,7
13
- diracx_cli-0.0.1a16.dist-info/RECORD,,