cmsdials 1.8.0__tar.gz → 2.0.0__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.
- cmsdials-2.0.0/.gitlab-ci.yml +74 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/PKG-INFO +2 -1
- {cmsdials-1.8.0 → cmsdials-2.0.0}/README.md +1 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/_version.py +16 -3
- cmsdials-2.0.0/cmsdials/clients/mes/client.py +17 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/ml_bad_lumisection/client.py +13 -7
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/ml_bad_lumisection/models.py +1 -3
- cmsdials-2.0.0/cmsdials/clients/ml_models_index/models.py +47 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/run/models.py +1 -0
- cmsdials-2.0.0/cmsdials/clients/workspace/client.py +49 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/cmsdials.py +2 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials.egg-info/PKG-INFO +2 -1
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials.egg-info/SOURCES.txt +3 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/pyproject.toml +2 -2
- cmsdials-2.0.0/tests/integration/env.py +15 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/tests/integration/test_auth_client.py +6 -9
- {cmsdials-1.8.0 → cmsdials-2.0.0}/tests/integration/test_file_index_client.py +12 -9
- {cmsdials-1.8.0 → cmsdials-2.0.0}/tests/integration/test_h1d_client.py +34 -9
- {cmsdials-1.8.0 → cmsdials-2.0.0}/tests/integration/test_h2d_client.py +34 -9
- {cmsdials-1.8.0 → cmsdials-2.0.0}/tests/integration/test_lumisection_client.py +13 -9
- cmsdials-2.0.0/tests/integration/test_mes_client.py +31 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/tests/integration/test_oms_proxy_client.py +9 -8
- {cmsdials-1.8.0 → cmsdials-2.0.0}/tests/integration/test_resume.py +8 -7
- {cmsdials-1.8.0 → cmsdials-2.0.0}/tests/integration/test_run_client.py +12 -9
- cmsdials-2.0.0/tests/integration/utils.py +9 -0
- cmsdials-2.0.0/tests/unit/__init__.py +0 -0
- cmsdials-1.8.0/.gitlab-ci.yml +0 -115
- cmsdials-1.8.0/cmsdials/clients/mes/client.py +0 -36
- cmsdials-1.8.0/cmsdials/clients/ml_models_index/models.py +0 -26
- cmsdials-1.8.0/tests/integration/test_mes_client.py +0 -49
- cmsdials-1.8.0/tests/integration/utils.py +0 -15
- {cmsdials-1.8.0 → cmsdials-2.0.0}/.coveragerc +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/.editorconfig +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/.gitignore +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/.mailmap +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/.pre-commit-config.yaml +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/.tool-versions +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/LICENSE +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/__init__.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/auth/__init__.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/auth/_base.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/auth/bearer.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/auth/client.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/auth/exceptions.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/auth/models.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/auth/secret_key.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/__init__.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/dataset_index/__init__.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/dataset_index/client.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/dataset_index/models.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/file_index/__init__.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/file_index/client.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/file_index/models.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/h1d/__init__.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/h1d/client.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/h1d/models.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/h2d/__init__.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/h2d/client.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/h2d/models.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/lumisection/__init__.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/lumisection/client.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/lumisection/models.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/mes/__init__.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/mes/models.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/ml_bad_lumisection/__init__.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/ml_models_index/__init__.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/ml_models_index/client.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/oms_proxy/__init__.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/oms_proxy/client.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/oms_proxy/models.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/run/__init__.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/clients/run/client.py +0 -0
- {cmsdials-1.8.0/cmsdials/utils → cmsdials-2.0.0/cmsdials/clients/workspace}/__init__.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/filters.py +0 -0
- {cmsdials-1.8.0/tests/integration → cmsdials-2.0.0/cmsdials/utils}/__init__.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/utils/_json.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/utils/api_client.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/utils/base_model.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials/utils/logger.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials.egg-info/dependency_links.txt +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials.egg-info/requires.txt +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/cmsdials.egg-info/top_level.txt +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/mypy.ini +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/pytest.ini +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/ruff.toml +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/setup.cfg +0 -0
- {cmsdials-1.8.0/tests/unit → cmsdials-2.0.0/tests/integration}/__init__.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/tests/unit/test_base_api_client.py +0 -0
- {cmsdials-1.8.0 → cmsdials-2.0.0}/tox.ini +0 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
include:
|
|
2
|
+
- project: "cms-ppd/technical-support/ci-templates"
|
|
3
|
+
ref: release/v1
|
|
4
|
+
file:
|
|
5
|
+
- "templates/python/uv_build.yml"
|
|
6
|
+
- "templates/python/uv_publish.yml"
|
|
7
|
+
- "templates/gitlab/create_release.yml"
|
|
8
|
+
|
|
9
|
+
stages:
|
|
10
|
+
- test
|
|
11
|
+
- build
|
|
12
|
+
- publish
|
|
13
|
+
- create_release
|
|
14
|
+
|
|
15
|
+
###########
|
|
16
|
+
# Run tests
|
|
17
|
+
###########
|
|
18
|
+
|
|
19
|
+
test_matrix:
|
|
20
|
+
stage: test
|
|
21
|
+
parallel:
|
|
22
|
+
matrix:
|
|
23
|
+
- PYTHON_VERSION: ["3.9", "3.10", "3.11", "3.12"]
|
|
24
|
+
image: registry.cern.ch/docker.io/library/python:$PYTHON_VERSION
|
|
25
|
+
before_script:
|
|
26
|
+
- python -m pip install --upgrade pip
|
|
27
|
+
- pip install uv
|
|
28
|
+
- uv sync --all-groups --extra pandas --extra tqdm
|
|
29
|
+
script:
|
|
30
|
+
- uv run ruff format --check cmsdials tests
|
|
31
|
+
- uv run ruff check cmsdials tests
|
|
32
|
+
- uv run mypy cmsdials tests
|
|
33
|
+
- uv run pytest tests
|
|
34
|
+
coverage: "/TOTAL.+ ([0-9]{1,3}%)/"
|
|
35
|
+
artifacts:
|
|
36
|
+
reports:
|
|
37
|
+
coverage_report:
|
|
38
|
+
coverage_format: cobertura
|
|
39
|
+
path: coverage.xml
|
|
40
|
+
variables:
|
|
41
|
+
SECRET_KEY: "$SECRET_KEY"
|
|
42
|
+
|
|
43
|
+
###############
|
|
44
|
+
# Build package
|
|
45
|
+
###############
|
|
46
|
+
|
|
47
|
+
build:
|
|
48
|
+
extends: .uv_build
|
|
49
|
+
variables:
|
|
50
|
+
UV_SYNC_FLAGS: "--all-groups --extra pandas --extra tqdm"
|
|
51
|
+
needs:
|
|
52
|
+
- test_matrix
|
|
53
|
+
|
|
54
|
+
#################
|
|
55
|
+
# Publish to PyPI
|
|
56
|
+
#################
|
|
57
|
+
|
|
58
|
+
publish:
|
|
59
|
+
extends: .uv_publish
|
|
60
|
+
rules:
|
|
61
|
+
- if: $CI_COMMIT_TAG
|
|
62
|
+
needs:
|
|
63
|
+
- build
|
|
64
|
+
|
|
65
|
+
##########################
|
|
66
|
+
# Create release in GitLab
|
|
67
|
+
##########################
|
|
68
|
+
|
|
69
|
+
create_release:
|
|
70
|
+
extends: .create_gitlab_release
|
|
71
|
+
rules:
|
|
72
|
+
- if: $CI_COMMIT_TAG
|
|
73
|
+
needs:
|
|
74
|
+
- publish
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cmsdials
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: The Python api client interface to DIALS service
|
|
5
5
|
Author-email: Gabriel Moreira <gabriel.moreira@cern.ch>
|
|
6
6
|
Project-URL: Repository, https://gitlab.cern.ch/cms-dqmdc/libraries/dials-py
|
|
@@ -372,6 +372,7 @@ Do not worry. The GitLab CI is configured to automatically publish the package o
|
|
|
372
372
|
|
|
373
373
|
> [!NOTE]
|
|
374
374
|
> For this to work the CI/CD variables named `UV_PUBLISH_TOKEN`, `GITLAB_TOKEN` should be registered in gitlab. The `UV_PUBLISH_TOKEN` is a api token access of CMSDQM organization and the `GITLAB_TOKEN` is a Project Access Token with api read/write rights, which is needed to read merge requests using the `glab-cli`.
|
|
375
|
+
> https://gitlab.cern.ch/cms-dqmdc/libraries/dials-py/-/settings/access_tokens
|
|
375
376
|
|
|
376
377
|
#### Manual
|
|
377
378
|
|
|
@@ -349,6 +349,7 @@ Do not worry. The GitLab CI is configured to automatically publish the package o
|
|
|
349
349
|
|
|
350
350
|
> [!NOTE]
|
|
351
351
|
> For this to work the CI/CD variables named `UV_PUBLISH_TOKEN`, `GITLAB_TOKEN` should be registered in gitlab. The `UV_PUBLISH_TOKEN` is a api token access of CMSDQM organization and the `GITLAB_TOKEN` is a Project Access Token with api read/write rights, which is needed to read merge requests using the `glab-cli`.
|
|
352
|
+
> https://gitlab.cern.ch/cms-dqmdc/libraries/dials-py/-/settings/access_tokens
|
|
352
353
|
|
|
353
354
|
#### Manual
|
|
354
355
|
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
# file generated by setuptools-scm
|
|
2
2
|
# don't change, don't track in version control
|
|
3
3
|
|
|
4
|
-
__all__ = [
|
|
4
|
+
__all__ = [
|
|
5
|
+
"__version__",
|
|
6
|
+
"__version_tuple__",
|
|
7
|
+
"version",
|
|
8
|
+
"version_tuple",
|
|
9
|
+
"__commit_id__",
|
|
10
|
+
"commit_id",
|
|
11
|
+
]
|
|
5
12
|
|
|
6
13
|
TYPE_CHECKING = False
|
|
7
14
|
if TYPE_CHECKING:
|
|
@@ -9,13 +16,19 @@ if TYPE_CHECKING:
|
|
|
9
16
|
from typing import Union
|
|
10
17
|
|
|
11
18
|
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
+
COMMIT_ID = Union[str, None]
|
|
12
20
|
else:
|
|
13
21
|
VERSION_TUPLE = object
|
|
22
|
+
COMMIT_ID = object
|
|
14
23
|
|
|
15
24
|
version: str
|
|
16
25
|
__version__: str
|
|
17
26
|
__version_tuple__: VERSION_TUPLE
|
|
18
27
|
version_tuple: VERSION_TUPLE
|
|
28
|
+
commit_id: COMMIT_ID
|
|
29
|
+
__commit_id__: COMMIT_ID
|
|
19
30
|
|
|
20
|
-
__version__ = version = '
|
|
21
|
-
__version_tuple__ = version_tuple = (
|
|
31
|
+
__version__ = version = '2.0.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (2, 0, 0)
|
|
33
|
+
|
|
34
|
+
__commit_id__ = commit_id = 'g68ff6a70a'
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from ...utils.api_client import BaseAuthorizedNonPaginatedAPIClient
|
|
2
|
+
from .models import MEFilters, MonitoringElement
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class MonitoringElementClient(
|
|
6
|
+
BaseAuthorizedNonPaginatedAPIClient[
|
|
7
|
+
MonitoringElement,
|
|
8
|
+
MEFilters,
|
|
9
|
+
]
|
|
10
|
+
):
|
|
11
|
+
data_model = MonitoringElement
|
|
12
|
+
filter_class = MEFilters
|
|
13
|
+
lookup_url = "mes/"
|
|
14
|
+
|
|
15
|
+
def get(self, id: int, **kwargs): # noqa: A002
|
|
16
|
+
edp = f"{id}/"
|
|
17
|
+
return super()._get(edp, **kwargs)
|
|
@@ -18,18 +18,24 @@ class MLBadLumisectionClient(
|
|
|
18
18
|
edp = f"{model_id}/{dataset_id}/{run_number}/{ls_number}/{me_id}/"
|
|
19
19
|
return super()._get(edp, **kwargs)
|
|
20
20
|
|
|
21
|
-
def
|
|
22
|
-
|
|
21
|
+
def __json_params_builder(
|
|
22
|
+
self, model_id__in: list[int], dataset_id__in: list[int], run_number__in: list[int], **kwargs
|
|
23
|
+
):
|
|
23
24
|
midin = ",".join(str(v) for v in model_id__in)
|
|
24
25
|
didin = ",".join(str(v) for v in dataset_id__in)
|
|
25
26
|
ridin = ",".join(str(v) for v in run_number__in)
|
|
26
|
-
|
|
27
|
+
return {"model_id__in": midin, "dataset_id__in": didin, "run_number__in": ridin}
|
|
28
|
+
|
|
29
|
+
def cert_json(self, model_id__in: list[int], dataset_id__in: list[int], run_number__in: list[int], **kwargs):
|
|
30
|
+
edp = "cert-json/"
|
|
31
|
+
params = self.__json_params_builder(
|
|
32
|
+
model_id__in=model_id__in, dataset_id__in=dataset_id__in, run_number__in=run_number__in
|
|
33
|
+
)
|
|
27
34
|
return super()._get(edp, params=params, return_raw_json=True, **kwargs)
|
|
28
35
|
|
|
29
36
|
def golden_json(self, model_id__in: list[int], dataset_id__in: list[int], run_number__in: list[int], **kwargs):
|
|
30
37
|
edp = "golden-json/"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
params = {"model_id__in": midin, "dataset_id__in": didin, "run_number__in": ridin}
|
|
38
|
+
params = self.__json_params_builder(
|
|
39
|
+
model_id__in=model_id__in, dataset_id__in=dataset_id__in, run_number__in=run_number__in
|
|
40
|
+
)
|
|
35
41
|
return super()._get(edp, params=params, return_raw_json=True, **kwargs)
|
|
@@ -8,11 +8,9 @@ from ...utils.base_model import PaginatedBaseFilters, PaginatedBaseModel
|
|
|
8
8
|
class MLBadLumisection(BaseModel):
|
|
9
9
|
model_id: int
|
|
10
10
|
dataset_id: int
|
|
11
|
-
file_id: int
|
|
12
11
|
run_number: int
|
|
13
12
|
ls_number: int
|
|
14
|
-
|
|
15
|
-
mse: float
|
|
13
|
+
metric_value: float
|
|
16
14
|
|
|
17
15
|
|
|
18
16
|
class PaginatedMLBadLumisectionList(PaginatedBaseModel[MLBadLumisection]):
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel
|
|
5
|
+
|
|
6
|
+
from ...utils.base_model import PaginatedBaseFilters, PaginatedBaseModel
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class MLModelsIndex(BaseModel):
|
|
10
|
+
id: int
|
|
11
|
+
name: str
|
|
12
|
+
revision: int
|
|
13
|
+
ready: bool
|
|
14
|
+
active: bool
|
|
15
|
+
type: str
|
|
16
|
+
anomaly_threshold: Optional[float]
|
|
17
|
+
builtin_threshold: bool
|
|
18
|
+
description: str
|
|
19
|
+
flagging_key: Optional[str]
|
|
20
|
+
input_signature: list[dict]
|
|
21
|
+
metric_key: Optional[str]
|
|
22
|
+
output_signature: list[dict]
|
|
23
|
+
tags: Optional[list[dict]]
|
|
24
|
+
isvc_service_name: Optional[str]
|
|
25
|
+
isvc_yaml: Optional[str]
|
|
26
|
+
created_by: str
|
|
27
|
+
modified_by: str
|
|
28
|
+
created_at: datetime
|
|
29
|
+
modified_at: datetime
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class PaginatedMLModelsIndexList(PaginatedBaseModel[MLModelsIndex]):
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class MLModelsIndexFilters(PaginatedBaseFilters):
|
|
37
|
+
id: Optional[int] = None
|
|
38
|
+
id__in: Optional[list[int]] = None
|
|
39
|
+
name: Optional[str] = None
|
|
40
|
+
name__regex: Optional[str] = None
|
|
41
|
+
active: Optional[bool] = None
|
|
42
|
+
ready: Optional[bool] = None
|
|
43
|
+
type: Optional[str] = None
|
|
44
|
+
input_signature_contains_me: Optional[str] = None
|
|
45
|
+
input_signature_contains_me__regex: Optional[str] = None
|
|
46
|
+
tag_name: Optional[str] = None
|
|
47
|
+
tag_value: Optional[str] = None
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from requests.adapters import DEFAULT_RETRIES
|
|
2
|
+
from requests.exceptions import HTTPError
|
|
3
|
+
|
|
4
|
+
from ...auth._base import BaseCredentials
|
|
5
|
+
from ...utils.api_client import BaseAPIClient
|
|
6
|
+
from ...utils.logger import logger
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class WorkspaceClient(BaseAPIClient):
|
|
10
|
+
default_timeout = 30
|
|
11
|
+
lookup_url = "auth/"
|
|
12
|
+
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
creds: BaseCredentials,
|
|
16
|
+
*args: str,
|
|
17
|
+
**kwargs: str,
|
|
18
|
+
) -> None:
|
|
19
|
+
super().__init__(*args, **kwargs)
|
|
20
|
+
self.creds = creds
|
|
21
|
+
|
|
22
|
+
def _build_headers(self) -> dict:
|
|
23
|
+
base = {"Accept": "application/json", "User-Agent": self._build_user_agent()}
|
|
24
|
+
self.creds.before_request(base)
|
|
25
|
+
return base
|
|
26
|
+
|
|
27
|
+
def __get(self, endpoint: str, retries=DEFAULT_RETRIES):
|
|
28
|
+
headers = self._build_headers()
|
|
29
|
+
endpoint_url = self.api_url + self.lookup_url + endpoint
|
|
30
|
+
|
|
31
|
+
response = self._requests_get_retriable(
|
|
32
|
+
endpoint_url,
|
|
33
|
+
headers=headers,
|
|
34
|
+
timeout=self.default_timeout,
|
|
35
|
+
retries=retries,
|
|
36
|
+
)
|
|
37
|
+
try:
|
|
38
|
+
response.raise_for_status()
|
|
39
|
+
except HTTPError as err:
|
|
40
|
+
logger.info(f"Api raw response: {response.text}")
|
|
41
|
+
raise err
|
|
42
|
+
|
|
43
|
+
return response.json()
|
|
44
|
+
|
|
45
|
+
def list(self, retries=DEFAULT_RETRIES):
|
|
46
|
+
return self.__get("workspaces", retries=retries)
|
|
47
|
+
|
|
48
|
+
def my_workspace(self, retries=DEFAULT_RETRIES):
|
|
49
|
+
return self.__get("user-default-workspace", retries=retries)
|
|
@@ -11,6 +11,7 @@ from .clients.ml_bad_lumisection.client import MLBadLumisectionClient
|
|
|
11
11
|
from .clients.ml_models_index.client import MLModelsIndexClient
|
|
12
12
|
from .clients.oms_proxy.client import OMSProxyClient
|
|
13
13
|
from .clients.run.client import RunClient
|
|
14
|
+
from .clients.workspace.client import WorkspaceClient
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
class Dials:
|
|
@@ -25,3 +26,4 @@ class Dials:
|
|
|
25
26
|
self.oms = OMSProxyClient(creds, *args, **kwargs)
|
|
26
27
|
self.ml_bad_lumis = MLBadLumisectionClient(creds, workspace, *args, **kwargs)
|
|
27
28
|
self.ml_models_index = MLModelsIndexClient(creds, workspace, *args, **kwargs)
|
|
29
|
+
self.workspace = WorkspaceClient(creds, *args, **kwargs)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cmsdials
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: The Python api client interface to DIALS service
|
|
5
5
|
Author-email: Gabriel Moreira <gabriel.moreira@cern.ch>
|
|
6
6
|
Project-URL: Repository, https://gitlab.cern.ch/cms-dqmdc/libraries/dials-py
|
|
@@ -372,6 +372,7 @@ Do not worry. The GitLab CI is configured to automatically publish the package o
|
|
|
372
372
|
|
|
373
373
|
> [!NOTE]
|
|
374
374
|
> For this to work the CI/CD variables named `UV_PUBLISH_TOKEN`, `GITLAB_TOKEN` should be registered in gitlab. The `UV_PUBLISH_TOKEN` is a api token access of CMSDQM organization and the `GITLAB_TOKEN` is a Project Access Token with api read/write rights, which is needed to read merge requests using the `glab-cli`.
|
|
375
|
+
> https://gitlab.cern.ch/cms-dqmdc/libraries/dials-py/-/settings/access_tokens
|
|
375
376
|
|
|
376
377
|
#### Manual
|
|
377
378
|
|
|
@@ -59,12 +59,15 @@ cmsdials/clients/oms_proxy/models.py
|
|
|
59
59
|
cmsdials/clients/run/__init__.py
|
|
60
60
|
cmsdials/clients/run/client.py
|
|
61
61
|
cmsdials/clients/run/models.py
|
|
62
|
+
cmsdials/clients/workspace/__init__.py
|
|
63
|
+
cmsdials/clients/workspace/client.py
|
|
62
64
|
cmsdials/utils/__init__.py
|
|
63
65
|
cmsdials/utils/_json.py
|
|
64
66
|
cmsdials/utils/api_client.py
|
|
65
67
|
cmsdials/utils/base_model.py
|
|
66
68
|
cmsdials/utils/logger.py
|
|
67
69
|
tests/integration/__init__.py
|
|
70
|
+
tests/integration/env.py
|
|
68
71
|
tests/integration/test_auth_client.py
|
|
69
72
|
tests/integration/test_file_index_client.py
|
|
70
73
|
tests/integration/test_h1d_client.py
|
|
@@ -38,10 +38,10 @@ Repository = "https://gitlab.cern.ch/cms-dqmdc/libraries/dials-py"
|
|
|
38
38
|
|
|
39
39
|
[dependency-groups]
|
|
40
40
|
lint = [
|
|
41
|
-
"mypy
|
|
41
|
+
"mypy==1.15.0",
|
|
42
42
|
"pandas-stubs>=2.2.2.240807",
|
|
43
43
|
"pre-commit>=4.2.0",
|
|
44
|
-
"ruff
|
|
44
|
+
"ruff==0.11.4",
|
|
45
45
|
"types-requests>=2.31.0.6",
|
|
46
46
|
"types-tqdm>=4.67.0.20250516",
|
|
47
47
|
]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
SECRET_KEY = os.getenv("SECRET_KEY")
|
|
5
|
+
if not SECRET_KEY:
|
|
6
|
+
raise OSError("SECRET_KEY environment variable is not set.")
|
|
7
|
+
|
|
8
|
+
BASE_URL = os.getenv("BASE_URL", "https://dev-cmsdials-api.web.cern.ch/")
|
|
9
|
+
TEST_WORKSPACE = os.getenv("TEST_WORKSPACE", "global")
|
|
10
|
+
TEST_DATASET_ID = int(os.getenv("TEST_DATASET_ID", 15310647)) # /ZeroBias/Run2025B-PromptReco-v1/DQMIO
|
|
11
|
+
TEST_FILE_ID = int(
|
|
12
|
+
os.getenv("TEST_FILE_ID", 22961052797)
|
|
13
|
+
) # /store/data/Run2025B/ZeroBias/DQMIO/PromptReco-v1/000/392/158/00000/DC769215-780F-4D7D-B0B7-E66F731E3FC0.root
|
|
14
|
+
TEST_RUN_NUMBER = int(os.getenv("TEST_RUN_NUMBER", 392158))
|
|
15
|
+
TEST_LS_NUMBER = int(os.getenv("TEST_LS_NUMBER", 10))
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import os
|
|
2
1
|
from datetime import datetime, timedelta
|
|
3
2
|
from typing import Union
|
|
4
3
|
|
|
@@ -10,21 +9,19 @@ from cmsdials.auth.bearer import Credentials as BearerCredentials
|
|
|
10
9
|
from cmsdials.auth.client import AuthClient
|
|
11
10
|
from cmsdials.auth.models import Token
|
|
12
11
|
from cmsdials.auth.secret_key import Credentials as SecretKeyCredentials
|
|
13
|
-
from cmsdials.clients.h1d.models import LumisectionHistogram1D
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
BASE_URL = os.getenv("BASE_URL")
|
|
13
|
+
from .env import BASE_URL, SECRET_KEY, TEST_WORKSPACE
|
|
17
14
|
|
|
18
15
|
|
|
19
16
|
def __setup_dials_from_creds_and_test(creds: Union[SecretKeyCredentials, BearerCredentials]) -> None:
|
|
20
|
-
dials = Dials(creds, base_url=BASE_URL)
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
dials = Dials(creds, workspace=TEST_WORKSPACE, base_url=BASE_URL)
|
|
18
|
+
# just test if we can access the workspace endpoints
|
|
19
|
+
dials.workspace.my_workspace()
|
|
20
|
+
dials.workspace.list()
|
|
23
21
|
|
|
24
22
|
|
|
25
23
|
def test_secret_key_success() -> None:
|
|
26
|
-
|
|
27
|
-
creds = SecretKeyCredentials(token=secret_key)
|
|
24
|
+
creds = SecretKeyCredentials(token=SECRET_KEY)
|
|
28
25
|
__setup_dials_from_creds_and_test(creds)
|
|
29
26
|
|
|
30
27
|
|
|
@@ -4,44 +4,47 @@ from urllib3.util import Retry
|
|
|
4
4
|
from cmsdials.clients.file_index.models import FileIndex, PaginatedFileIndexList
|
|
5
5
|
from cmsdials.filters import FileIndexFilters
|
|
6
6
|
|
|
7
|
-
from .
|
|
7
|
+
from .env import TEST_DATASET_ID, TEST_FILE_ID
|
|
8
|
+
from .utils import setup_dials_object
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
def test_get_file_index() -> None:
|
|
11
|
-
dials = setup_dials_object(
|
|
12
|
-
data = dials.file_index.get(dataset_id=
|
|
12
|
+
dials = setup_dials_object()
|
|
13
|
+
data = dials.file_index.get(dataset_id=TEST_DATASET_ID, file_id=TEST_FILE_ID)
|
|
13
14
|
assert isinstance(data, FileIndex)
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
def test_list_file_index() -> None:
|
|
17
|
-
dials = setup_dials_object(
|
|
18
|
+
dials = setup_dials_object()
|
|
18
19
|
data = dials.file_index.list()
|
|
19
20
|
assert isinstance(data, PaginatedFileIndexList)
|
|
20
21
|
assert isinstance(data.to_pandas(), pd.DataFrame)
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
def test_list_all_file_index() -> None:
|
|
24
|
-
dials = setup_dials_object(
|
|
25
|
+
dials = setup_dials_object()
|
|
25
26
|
data = dials.file_index.list_all(FileIndexFilters(), max_pages=5)
|
|
26
27
|
assert isinstance(data, PaginatedFileIndexList)
|
|
27
28
|
assert isinstance(data.to_pandas(), pd.DataFrame)
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
def test_get_file_index_with_retries() -> None:
|
|
31
|
-
dials = setup_dials_object(
|
|
32
|
-
data = dials.file_index.get(
|
|
32
|
+
dials = setup_dials_object()
|
|
33
|
+
data = dials.file_index.get(
|
|
34
|
+
dataset_id=TEST_DATASET_ID, file_id=TEST_FILE_ID, retries=Retry(total=3, backoff_factor=0.1)
|
|
35
|
+
)
|
|
33
36
|
assert isinstance(data, FileIndex)
|
|
34
37
|
|
|
35
38
|
|
|
36
39
|
def test_list_file_index_with_retries() -> None:
|
|
37
|
-
dials = setup_dials_object(
|
|
40
|
+
dials = setup_dials_object()
|
|
38
41
|
data = dials.file_index.list(retries=Retry(total=3, backoff_factor=0.1))
|
|
39
42
|
assert isinstance(data, PaginatedFileIndexList)
|
|
40
43
|
assert isinstance(data.to_pandas(), pd.DataFrame)
|
|
41
44
|
|
|
42
45
|
|
|
43
46
|
def test_list_all_file_index_with_retries() -> None:
|
|
44
|
-
dials = setup_dials_object(
|
|
47
|
+
dials = setup_dials_object()
|
|
45
48
|
data = dials.file_index.list_all(FileIndexFilters(), max_pages=5, retries=Retry(total=3, backoff_factor=0.1))
|
|
46
49
|
assert isinstance(data, PaginatedFileIndexList)
|
|
47
50
|
assert isinstance(data.to_pandas(), pd.DataFrame)
|
|
@@ -4,46 +4,71 @@ from urllib3.util import Retry
|
|
|
4
4
|
from cmsdials.clients.h1d.models import LumisectionHistogram1D, PaginatedLumisectionHistogram1DList
|
|
5
5
|
from cmsdials.filters import LumisectionHistogram1DFilters
|
|
6
6
|
|
|
7
|
-
from .
|
|
7
|
+
from .env import TEST_DATASET_ID, TEST_LS_NUMBER, TEST_RUN_NUMBER
|
|
8
|
+
from .utils import setup_dials_object
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
def test_get_h1d() -> None:
|
|
11
|
-
dials = setup_dials_object(
|
|
12
|
-
|
|
12
|
+
dials = setup_dials_object()
|
|
13
|
+
|
|
14
|
+
# Fetch any valid monitoring element ID with dimension 1 from the MEs endpoint
|
|
15
|
+
data = dials.mes.list()
|
|
16
|
+
me_id = None
|
|
17
|
+
for me in data:
|
|
18
|
+
if me.dim == 1:
|
|
19
|
+
me_id = me.me_id
|
|
20
|
+
break
|
|
21
|
+
assert me_id is not None, "No 1D Monitoring Element found in MEs endpoint"
|
|
22
|
+
|
|
23
|
+
data = dials.h1d.get(dataset_id=TEST_DATASET_ID, run_number=TEST_RUN_NUMBER, ls_number=TEST_LS_NUMBER, me_id=me_id)
|
|
13
24
|
assert isinstance(data, LumisectionHistogram1D)
|
|
14
25
|
|
|
15
26
|
|
|
16
27
|
def test_list_h1d() -> None:
|
|
17
|
-
dials = setup_dials_object(
|
|
28
|
+
dials = setup_dials_object()
|
|
18
29
|
data = dials.h1d.list()
|
|
19
30
|
assert isinstance(data, PaginatedLumisectionHistogram1DList)
|
|
20
31
|
assert isinstance(data.to_pandas(), pd.DataFrame)
|
|
21
32
|
|
|
22
33
|
|
|
23
34
|
def test_list_all_h1d() -> None:
|
|
24
|
-
dials = setup_dials_object(
|
|
35
|
+
dials = setup_dials_object()
|
|
25
36
|
data = dials.h1d.list_all(LumisectionHistogram1DFilters(), max_pages=5)
|
|
26
37
|
assert isinstance(data, PaginatedLumisectionHistogram1DList)
|
|
27
38
|
assert isinstance(data.to_pandas(), pd.DataFrame)
|
|
28
39
|
|
|
29
40
|
|
|
30
41
|
def test_get_h1d_with_retries() -> None:
|
|
31
|
-
dials = setup_dials_object(
|
|
42
|
+
dials = setup_dials_object()
|
|
43
|
+
|
|
44
|
+
# Fetch any valid monitoring element ID with dimension 1 from the MEs endpoint
|
|
45
|
+
data = dials.mes.list()
|
|
46
|
+
me_id = None
|
|
47
|
+
for me in data:
|
|
48
|
+
if me.dim == 1:
|
|
49
|
+
me_id = me.me_id
|
|
50
|
+
break
|
|
51
|
+
assert me_id is not None, "No 1D Monitoring Element found in MEs endpoint"
|
|
52
|
+
|
|
32
53
|
data = dials.h1d.get(
|
|
33
|
-
dataset_id=
|
|
54
|
+
dataset_id=TEST_DATASET_ID,
|
|
55
|
+
run_number=TEST_RUN_NUMBER,
|
|
56
|
+
ls_number=TEST_LS_NUMBER,
|
|
57
|
+
me_id=me_id,
|
|
58
|
+
retries=Retry(total=3, backoff_factor=0.1),
|
|
34
59
|
)
|
|
35
60
|
assert isinstance(data, LumisectionHistogram1D)
|
|
36
61
|
|
|
37
62
|
|
|
38
63
|
def test_list_h1d_with_retries() -> None:
|
|
39
|
-
dials = setup_dials_object(
|
|
64
|
+
dials = setup_dials_object()
|
|
40
65
|
data = dials.h1d.list(retries=Retry(total=3, backoff_factor=0.1))
|
|
41
66
|
assert isinstance(data, PaginatedLumisectionHistogram1DList)
|
|
42
67
|
assert isinstance(data.to_pandas(), pd.DataFrame)
|
|
43
68
|
|
|
44
69
|
|
|
45
70
|
def test_list_all_h1d_with_retries() -> None:
|
|
46
|
-
dials = setup_dials_object(
|
|
71
|
+
dials = setup_dials_object()
|
|
47
72
|
data = dials.h1d.list_all(LumisectionHistogram1DFilters(), max_pages=5, retries=Retry(total=5, backoff_factor=0.1))
|
|
48
73
|
assert isinstance(data, PaginatedLumisectionHistogram1DList)
|
|
49
74
|
assert isinstance(data.to_pandas(), pd.DataFrame)
|
|
@@ -4,46 +4,71 @@ from urllib3.util import Retry
|
|
|
4
4
|
from cmsdials.clients.h2d.models import LumisectionHistogram2D, PaginatedLumisectionHistogram2DList
|
|
5
5
|
from cmsdials.filters import LumisectionHistogram2DFilters
|
|
6
6
|
|
|
7
|
-
from .
|
|
7
|
+
from .env import TEST_DATASET_ID, TEST_LS_NUMBER, TEST_RUN_NUMBER
|
|
8
|
+
from .utils import setup_dials_object
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
def test_get_h2d() -> None:
|
|
11
|
-
dials = setup_dials_object(
|
|
12
|
-
|
|
12
|
+
dials = setup_dials_object()
|
|
13
|
+
|
|
14
|
+
# Fetch any valid monitoring element ID with dimension 2 from the MEs endpoint
|
|
15
|
+
data = dials.mes.list()
|
|
16
|
+
me_id = None
|
|
17
|
+
for me in data:
|
|
18
|
+
if me.dim == 2:
|
|
19
|
+
me_id = me.me_id
|
|
20
|
+
break
|
|
21
|
+
assert me_id is not None, "No 2D Monitoring Element found in MEs endpoint"
|
|
22
|
+
|
|
23
|
+
data = dials.h2d.get(dataset_id=TEST_DATASET_ID, run_number=TEST_RUN_NUMBER, ls_number=TEST_LS_NUMBER, me_id=me_id)
|
|
13
24
|
assert isinstance(data, LumisectionHistogram2D)
|
|
14
25
|
|
|
15
26
|
|
|
16
27
|
def test_list_h2d() -> None:
|
|
17
|
-
dials = setup_dials_object(
|
|
28
|
+
dials = setup_dials_object()
|
|
18
29
|
data = dials.h2d.list()
|
|
19
30
|
assert isinstance(data, PaginatedLumisectionHistogram2DList)
|
|
20
31
|
assert isinstance(data.to_pandas(), pd.DataFrame)
|
|
21
32
|
|
|
22
33
|
|
|
23
34
|
def test_list_all_h2d() -> None:
|
|
24
|
-
dials = setup_dials_object(
|
|
35
|
+
dials = setup_dials_object()
|
|
25
36
|
data = dials.h2d.list_all(LumisectionHistogram2DFilters(), max_pages=5)
|
|
26
37
|
assert isinstance(data, PaginatedLumisectionHistogram2DList)
|
|
27
38
|
assert isinstance(data.to_pandas(), pd.DataFrame)
|
|
28
39
|
|
|
29
40
|
|
|
30
41
|
def test_get_h2d_with_retries() -> None:
|
|
31
|
-
dials = setup_dials_object(
|
|
42
|
+
dials = setup_dials_object()
|
|
43
|
+
|
|
44
|
+
# Fetch any valid monitoring element ID with dimension 2 from the MEs endpoint
|
|
45
|
+
data = dials.mes.list()
|
|
46
|
+
me_id = None
|
|
47
|
+
for me in data:
|
|
48
|
+
if me.dim == 2:
|
|
49
|
+
me_id = me.me_id
|
|
50
|
+
break
|
|
51
|
+
assert me_id is not None, "No 2D Monitoring Element found in MEs endpoint"
|
|
52
|
+
|
|
32
53
|
data = dials.h2d.get(
|
|
33
|
-
dataset_id=
|
|
54
|
+
dataset_id=TEST_DATASET_ID,
|
|
55
|
+
run_number=TEST_RUN_NUMBER,
|
|
56
|
+
ls_number=TEST_LS_NUMBER,
|
|
57
|
+
me_id=me_id,
|
|
58
|
+
retries=Retry(total=3, backoff_factor=0.1),
|
|
34
59
|
)
|
|
35
60
|
assert isinstance(data, LumisectionHistogram2D)
|
|
36
61
|
|
|
37
62
|
|
|
38
63
|
def test_list_h2d_with_retries() -> None:
|
|
39
|
-
dials = setup_dials_object(
|
|
64
|
+
dials = setup_dials_object()
|
|
40
65
|
data = dials.h2d.list(retries=Retry(total=3, backoff_factor=0.1))
|
|
41
66
|
assert isinstance(data, PaginatedLumisectionHistogram2DList)
|
|
42
67
|
assert isinstance(data.to_pandas(), pd.DataFrame)
|
|
43
68
|
|
|
44
69
|
|
|
45
70
|
def test_list_all_h2d_with_retries() -> None:
|
|
46
|
-
dials = setup_dials_object(
|
|
71
|
+
dials = setup_dials_object()
|
|
47
72
|
data = dials.h2d.list_all(LumisectionHistogram2DFilters(), max_pages=5, retries=Retry(total=5, backoff_factor=0.1))
|
|
48
73
|
assert isinstance(data, PaginatedLumisectionHistogram2DList)
|
|
49
74
|
assert isinstance(data.to_pandas(), pd.DataFrame)
|