cmsdials 1.1.0__tar.gz → 1.3.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.
Files changed (44) hide show
  1. {cmsdials-1.1.0 → cmsdials-1.3.0}/PKG-INFO +12 -6
  2. {cmsdials-1.1.0 → cmsdials-1.3.0}/README.md +11 -5
  3. cmsdials-1.3.0/cmsdials/clients/file_index/client.py +27 -0
  4. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/clients/file_index/models.py +1 -1
  5. cmsdials-1.3.0/cmsdials/clients/h1d/client.py +27 -0
  6. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/clients/h1d/models.py +0 -1
  7. cmsdials-1.3.0/cmsdials/clients/h2d/client.py +27 -0
  8. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/clients/h2d/models.py +0 -1
  9. cmsdials-1.3.0/cmsdials/clients/oms_proxy/client.py +46 -0
  10. cmsdials-1.3.0/cmsdials/clients/oms_proxy/models.py +14 -0
  11. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/cmsdials.py +2 -0
  12. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/filters.py +3 -0
  13. cmsdials-1.3.0/cmsdials/utils/__init__.py +0 -0
  14. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/utils/api_client.py +8 -7
  15. {cmsdials-1.1.0 → cmsdials-1.3.0}/pyproject.toml +1 -1
  16. cmsdials-1.1.0/cmsdials/clients/file_index/client.py +0 -9
  17. cmsdials-1.1.0/cmsdials/clients/h1d/client.py +0 -9
  18. cmsdials-1.1.0/cmsdials/clients/h2d/client.py +0 -9
  19. {cmsdials-1.1.0 → cmsdials-1.3.0}/LICENSE +0 -0
  20. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/__init__.py +0 -0
  21. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/auth/__init__.py +0 -0
  22. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/auth/_base.py +0 -0
  23. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/auth/bearer.py +0 -0
  24. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/auth/client.py +0 -0
  25. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/auth/exceptions.py +0 -0
  26. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/auth/models.py +0 -0
  27. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/auth/secret_key.py +0 -0
  28. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/clients/__init__.py +0 -0
  29. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/clients/file_index/__init__.py +0 -0
  30. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/clients/h1d/__init__.py +0 -0
  31. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/clients/h2d/__init__.py +0 -0
  32. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/clients/lumisection/__init__.py +0 -0
  33. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/clients/lumisection/client.py +0 -0
  34. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/clients/lumisection/models.py +0 -0
  35. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/clients/mes/__init__.py +0 -0
  36. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/clients/mes/client.py +0 -0
  37. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/clients/mes/models.py +0 -0
  38. {cmsdials-1.1.0/cmsdials/clients/run → cmsdials-1.3.0/cmsdials/clients/oms_proxy}/__init__.py +0 -0
  39. {cmsdials-1.1.0/cmsdials/utils → cmsdials-1.3.0/cmsdials/clients/run}/__init__.py +0 -0
  40. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/clients/run/client.py +0 -0
  41. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/clients/run/models.py +0 -0
  42. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/utils/_json.py +0 -0
  43. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/utils/base_model.py +0 -0
  44. {cmsdials-1.1.0 → cmsdials-1.3.0}/cmsdials/utils/logger.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cmsdials
3
- Version: 1.1.0
3
+ Version: 1.3.0
4
4
  Summary: The Python api client interface to DIALS service
5
5
  Home-page: https://github.com/cms-DQM/dials-py
6
6
  Author: Gabriel Moreira
@@ -107,11 +107,11 @@ This package interacts with DIALS api endpoints using underlying classes in `Dia
107
107
  ### Retrieving a specific object using `get`
108
108
 
109
109
  ```python
110
- dials.file_index.get(id=3386119397)
111
- dials.h1d.get(id=1)
112
- dials.h2d.get(id=1)
113
- dials.lumi.get(dataset_id=14677060, run_number=367094, ls_number=1)
114
- dials.run.get(dataset_id=14677060, run_number=367094)
110
+ dials.file_index.get(dataset_id=14677060, file_id=3393809397)
111
+ dials.h1d.get(dataset_id=14677060, run_number=367112, ls_number=10, me_id=1)
112
+ dials.h1d.get(dataset_id=14677060, run_number=367112, ls_number=10, me_id=96)
113
+ dials.lumi.get(dataset_id=14677060, run_number=367112, ls_number=10)
114
+ dials.run.get(dataset_id=14677060, run_number=367112)
115
115
  ```
116
116
 
117
117
  ### Retrieving a list of objects per page using `list`
@@ -230,3 +230,9 @@ SECRET_KEY=... pytest tests
230
230
 
231
231
  The secret key is an api client enabled secret key and can be obtained from the applications portal, any api client secret key whitelisted in DIALS can be used. The interactive authentication flow should be tested manually, an example for this can be found in [this line](/tests/integration/test_auth_client.py#L33).
232
232
 
233
+ If testing against a local version of DIALS you need to specify the BASE_URL:
234
+
235
+ ```bash
236
+ SECRET_KEY=... BASE_URl=http://localhost:8000 pytest tests
237
+ ```
238
+
@@ -80,11 +80,11 @@ This package interacts with DIALS api endpoints using underlying classes in `Dia
80
80
  ### Retrieving a specific object using `get`
81
81
 
82
82
  ```python
83
- dials.file_index.get(id=3386119397)
84
- dials.h1d.get(id=1)
85
- dials.h2d.get(id=1)
86
- dials.lumi.get(dataset_id=14677060, run_number=367094, ls_number=1)
87
- dials.run.get(dataset_id=14677060, run_number=367094)
83
+ dials.file_index.get(dataset_id=14677060, file_id=3393809397)
84
+ dials.h1d.get(dataset_id=14677060, run_number=367112, ls_number=10, me_id=1)
85
+ dials.h1d.get(dataset_id=14677060, run_number=367112, ls_number=10, me_id=96)
86
+ dials.lumi.get(dataset_id=14677060, run_number=367112, ls_number=10)
87
+ dials.run.get(dataset_id=14677060, run_number=367112)
88
88
  ```
89
89
 
90
90
  ### Retrieving a list of objects per page using `list`
@@ -202,3 +202,9 @@ SECRET_KEY=... pytest tests
202
202
  ```
203
203
 
204
204
  The secret key is an api client enabled secret key and can be obtained from the applications portal, any api client secret key whitelisted in DIALS can be used. The interactive authentication flow should be tested manually, an example for this can be found in [this line](/tests/integration/test_auth_client.py#L33).
205
+
206
+ If testing against a local version of DIALS you need to specify the BASE_URL:
207
+
208
+ ```bash
209
+ SECRET_KEY=... BASE_URl=http://localhost:8000 pytest tests
210
+ ```
@@ -0,0 +1,27 @@
1
+ import requests
2
+ from requests.exceptions import HTTPError
3
+
4
+ from ...utils.api_client import BaseAuthorizedAPIClient
5
+ from ...utils.logger import logger
6
+ from .models import FileIndex, FileIndexFilters, PaginatedFileIndexList
7
+
8
+
9
+ class FileIndexClient(BaseAuthorizedAPIClient):
10
+ data_model = FileIndex
11
+ pagination_model = PaginatedFileIndexList
12
+ filter_class = FileIndexFilters
13
+ lookup_url = "file-index/"
14
+
15
+ def get(self, dataset_id: int, file_id: int):
16
+ endpoint_url = f"{self.api_url}{self.lookup_url}{dataset_id}/{file_id}/"
17
+ headers = self._build_headers()
18
+ response = requests.get(endpoint_url, headers=headers, timeout=self.default_timeout)
19
+
20
+ try:
21
+ response.raise_for_status()
22
+ except HTTPError as err:
23
+ logger.info(f"Api raw response: {response.text}")
24
+ raise err
25
+
26
+ response = response.json()
27
+ return self.data_model(**response)
@@ -14,7 +14,7 @@ class FileIndex(BaseModel):
14
14
  creation_date: datetime
15
15
  last_modification_date: datetime
16
16
  logical_file_name: str
17
- status: str = Field(..., max_length=15)
17
+ status: str = Field(..., max_length=255)
18
18
  err_trace: Optional[str] = Field(..., max_length=5000)
19
19
 
20
20
 
@@ -0,0 +1,27 @@
1
+ import requests
2
+ from requests.exceptions import HTTPError
3
+
4
+ from ...utils.api_client import BaseAuthorizedAPIClient
5
+ from ...utils.logger import logger
6
+ from .models import LumisectionHistogram1D, LumisectionHistogram1DFilters, PaginatedLumisectionHistogram1DList
7
+
8
+
9
+ class LumisectionHistogram1DClient(BaseAuthorizedAPIClient):
10
+ data_model = LumisectionHistogram1D
11
+ pagination_model = PaginatedLumisectionHistogram1DList
12
+ filter_class = LumisectionHistogram1DFilters
13
+ lookup_url = "th1/"
14
+
15
+ def get(self, dataset_id: int, run_number: int, ls_number: int, me_id: int):
16
+ endpoint_url = f"{self.api_url}{self.lookup_url}{dataset_id}/{run_number}/{ls_number}/{me_id}/"
17
+ headers = self._build_headers()
18
+ response = requests.get(endpoint_url, headers=headers, timeout=self.default_timeout)
19
+
20
+ try:
21
+ response.raise_for_status()
22
+ except HTTPError as err:
23
+ logger.info(f"Api raw response: {response.text}")
24
+ raise err
25
+
26
+ response = response.json()
27
+ return self.data_model(**response)
@@ -6,7 +6,6 @@ from ...utils.base_model import OBaseModel, PaginatedBaseModel
6
6
 
7
7
 
8
8
  class LumisectionHistogram1D(BaseModel):
9
- hist_id: int
10
9
  dataset: str = Field(..., max_length=255)
11
10
  me: str = Field(..., max_length=255)
12
11
  dataset_id: int
@@ -0,0 +1,27 @@
1
+ import requests
2
+ from requests.exceptions import HTTPError
3
+
4
+ from ...utils.api_client import BaseAuthorizedAPIClient
5
+ from ...utils.logger import logger
6
+ from .models import LumisectionHistogram2D, LumisectionHistogram2DFilters, PaginatedLumisectionHistogram2DList
7
+
8
+
9
+ class LumisectionHistogram2DClient(BaseAuthorizedAPIClient):
10
+ data_model = LumisectionHistogram2D
11
+ pagination_model = PaginatedLumisectionHistogram2DList
12
+ filter_class = LumisectionHistogram2DFilters
13
+ lookup_url = "th2/"
14
+
15
+ def get(self, dataset_id: int, run_number: int, ls_number: int, me_id: int):
16
+ endpoint_url = f"{self.api_url}{self.lookup_url}{dataset_id}/{run_number}/{ls_number}/{me_id}/"
17
+ headers = self._build_headers()
18
+ response = requests.get(endpoint_url, headers=headers, timeout=self.default_timeout)
19
+
20
+ try:
21
+ response.raise_for_status()
22
+ except HTTPError as err:
23
+ logger.info(f"Api raw response: {response.text}")
24
+ raise err
25
+
26
+ response = response.json()
27
+ return self.data_model(**response)
@@ -6,7 +6,6 @@ from ...utils.base_model import OBaseModel, PaginatedBaseModel
6
6
 
7
7
 
8
8
  class LumisectionHistogram2D(BaseModel):
9
- hist_id: int
10
9
  dataset: str = Field(..., max_length=255)
11
10
  me: str = Field(..., max_length=255)
12
11
  dataset_id: int
@@ -0,0 +1,46 @@
1
+ from typing import Optional
2
+
3
+ import requests
4
+ from requests.exceptions import HTTPError
5
+
6
+ from ...auth._base import BaseCredentials
7
+ from ...utils.api_client import BaseAPIClient
8
+ from ...utils.logger import logger
9
+ from .models import OMSFilter, OMSPage
10
+
11
+
12
+ class OMSProxyClient(BaseAPIClient):
13
+ default_timeout = 30
14
+ lookup_url = "oms-proxy/"
15
+
16
+ def __init__(
17
+ self,
18
+ creds: BaseCredentials,
19
+ *args: str,
20
+ **kwargs: str,
21
+ ) -> None:
22
+ super().__init__(*args, **kwargs)
23
+ self.creds = creds
24
+
25
+ def _build_headers(self) -> dict:
26
+ base = {"accept": "application/json"}
27
+ self.creds.before_request(base)
28
+ return base
29
+
30
+ def query(self, endpoint: str, filters: list[OMSFilter], pages: Optional[list[OMSPage]] = None):
31
+ headers = self._build_headers()
32
+ endpoint_url = self.api_url + self.lookup_url
33
+
34
+ # Format filters
35
+ filters = {f"filter[{_filter.attribute_name}][{_filter.operator}]": _filter.value for _filter in filters}
36
+ pages = {f"page[{page.attribute_name}]": page.value for page in pages} if pages and len(pages) > 0 else {}
37
+ params = {"endpoint": endpoint, **filters, **pages}
38
+
39
+ response = requests.get(endpoint_url, headers=headers, params=params, timeout=self.default_timeout)
40
+ try:
41
+ response.raise_for_status()
42
+ except HTTPError as err:
43
+ logger.info(f"Api raw response: {response.text}")
44
+ raise err
45
+
46
+ return response.json()
@@ -0,0 +1,14 @@
1
+ from typing import Literal, Union
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class OMSFilter(BaseModel):
7
+ attribute_name: str
8
+ value: Union[str, int, float]
9
+ operator: Literal["EQ", "NEQ", "LT", "GT", "LE", "GE", "LIKE"]
10
+
11
+
12
+ class OMSPage(BaseModel):
13
+ attribute_name: str
14
+ value: int
@@ -6,6 +6,7 @@ from .clients.h1d.client import LumisectionHistogram1DClient
6
6
  from .clients.h2d.client import LumisectionHistogram2DClient
7
7
  from .clients.lumisection.client import LumisectionClient
8
8
  from .clients.mes.client import MonitoringElementClient
9
+ from .clients.oms_proxy.client import OMSProxyClient
9
10
  from .clients.run.client import RunClient
10
11
 
11
12
 
@@ -17,3 +18,4 @@ class Dials:
17
18
  self.lumi = LumisectionClient(creds, workspace, *args, **kwargs)
18
19
  self.run = RunClient(creds, workspace, *args, **kwargs)
19
20
  self.mes = MonitoringElementClient(creds, workspace, *args, **kwargs)
21
+ self.oms = OMSProxyClient(creds, *args, **kwargs)
@@ -3,6 +3,7 @@ from .clients.h1d.models import LumisectionHistogram1DFilters
3
3
  from .clients.h2d.models import LumisectionHistogram2DFilters
4
4
  from .clients.lumisection.models import LumisectionFilters
5
5
  from .clients.mes.models import MEFilters
6
+ from .clients.oms_proxy.models import OMSFilter, OMSPage
6
7
  from .clients.run.models import RunFilters
7
8
 
8
9
 
@@ -13,4 +14,6 @@ __all__ = [
13
14
  "LumisectionFilters",
14
15
  "RunFilters",
15
16
  "MEFilters",
17
+ "OMSFilter",
18
+ "OMSPage",
16
19
  ]
File without changes
@@ -10,7 +10,7 @@ from ..utils.logger import logger
10
10
 
11
11
 
12
12
  if importlib_util.find_spec("tqdm"):
13
- from tqdm import tqdm
13
+ from tqdm.auto import tqdm
14
14
 
15
15
  TQDM_INSTALLED = True
16
16
  else:
@@ -99,13 +99,14 @@ class BaseAuthorizedAPIClient(BaseAPIClient):
99
99
 
100
100
  raise ValueError("pagination model is None and response is not a list.")
101
101
 
102
- def __list_sync(self, filters, max_pages: Optional[int] = None):
102
+ def __list_sync(self, filters, max_pages: Optional[int] = None, enable_progress: bool = False):
103
103
  next_token = None
104
104
  results = []
105
105
  is_last_page = False
106
106
  total_pages = 0
107
+ use_tqdm = TQDM_INSTALLED and enable_progress
107
108
 
108
- if TQDM_INSTALLED:
109
+ if use_tqdm:
109
110
  progress = tqdm(desc="Progress", total=1)
110
111
 
111
112
  while is_last_page is False:
@@ -117,7 +118,7 @@ class BaseAuthorizedAPIClient(BaseAPIClient):
117
118
  next_token = parse_qs(urlparse(response.next).query).get("next_token") if response.next else None
118
119
  total_pages += 1
119
120
  max_pages_reached = max_pages and total_pages >= max_pages
120
- if TQDM_INSTALLED:
121
+ if use_tqdm:
121
122
  if is_last_page or max_pages_reached:
122
123
  progress.update()
123
124
  else:
@@ -126,7 +127,7 @@ class BaseAuthorizedAPIClient(BaseAPIClient):
126
127
  if max_pages_reached:
127
128
  break
128
129
 
129
- if TQDM_INSTALLED:
130
+ if use_tqdm:
130
131
  progress.close()
131
132
 
132
133
  return self.pagination_model(
@@ -135,7 +136,7 @@ class BaseAuthorizedAPIClient(BaseAPIClient):
135
136
  results=results, # No problem re-using last response count
136
137
  )
137
138
 
138
- def list_all(self, filters, max_pages: Optional[int] = None):
139
+ def list_all(self, filters, max_pages: Optional[int] = None, **kwargs):
139
140
  if self.pagination_model is None:
140
141
  return self.list(filters)
141
- return self.__list_sync(filters, max_pages)
142
+ return self.__list_sync(filters, max_pages, **kwargs)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "cmsdials"
3
- version = "1.1.0"
3
+ version = "1.3.0"
4
4
  description = "The Python api client interface to DIALS service"
5
5
  authors = ["Gabriel Moreira <gabrielmscampos@gmail.com>"]
6
6
  readme = "README.md"
@@ -1,9 +0,0 @@
1
- from ...utils.api_client import BaseAuthorizedAPIClient
2
- from .models import FileIndex, FileIndexFilters, PaginatedFileIndexList
3
-
4
-
5
- class FileIndexClient(BaseAuthorizedAPIClient):
6
- data_model = FileIndex
7
- pagination_model = PaginatedFileIndexList
8
- filter_class = FileIndexFilters
9
- lookup_url = "file-index/"
@@ -1,9 +0,0 @@
1
- from ...utils.api_client import BaseAuthorizedAPIClient
2
- from .models import LumisectionHistogram1D, LumisectionHistogram1DFilters, PaginatedLumisectionHistogram1DList
3
-
4
-
5
- class LumisectionHistogram1DClient(BaseAuthorizedAPIClient):
6
- data_model = LumisectionHistogram1D
7
- pagination_model = PaginatedLumisectionHistogram1DList
8
- filter_class = LumisectionHistogram1DFilters
9
- lookup_url = "th1/"
@@ -1,9 +0,0 @@
1
- from ...utils.api_client import BaseAuthorizedAPIClient
2
- from .models import LumisectionHistogram2D, LumisectionHistogram2DFilters, PaginatedLumisectionHistogram2DList
3
-
4
-
5
- class LumisectionHistogram2DClient(BaseAuthorizedAPIClient):
6
- data_model = LumisectionHistogram2D
7
- pagination_model = PaginatedLumisectionHistogram2DList
8
- filter_class = LumisectionHistogram2DFilters
9
- lookup_url = "th2/"
File without changes
File without changes