diracx-client 0.0.1a19__py3-none-any.whl → 0.0.1a21__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,10 +9,12 @@ Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python
9
9
  from __future__ import annotations
10
10
 
11
11
  import abc
12
- import json
12
+ from importlib.metadata import PackageNotFoundError, distribution
13
13
  from types import TracebackType
14
14
  from pathlib import Path
15
- from typing import Any, List, Optional, Self
15
+
16
+ from typing import Any, List, Optional, cast
17
+
16
18
  from azure.core.credentials import AccessToken
17
19
  from azure.core.credentials_async import AsyncTokenCredential
18
20
  from azure.core.pipeline import PipelineRequest
@@ -23,8 +25,6 @@ from diracx.core.preferences import get_diracx_preferences, DiracxPreferences
23
25
  from ..utils import (
24
26
  get_openid_configuration,
25
27
  get_token,
26
- refresh_token,
27
- is_refresh_token_valid,
28
28
  )
29
29
 
30
30
  __all__: List[str] = [
@@ -55,20 +55,12 @@ class DiracTokenCredential(AsyncTokenCredential):
55
55
  tenant_id: Optional[str] = None,
56
56
  **kwargs: Any,
57
57
  ) -> AccessToken:
58
- """Refresh the access token using the refresh_token flow.
59
- :param str scopes: The type of access needed.
60
- :keyword str claims: Additional claims required in the token, such as those returned in a resource
61
- provider's claims challenge following an authorization failure.
62
- :keyword str tenant_id: Optional tenant to include in the token request.
63
- :rtype: AccessToken
64
- :return: An AccessToken instance containing the token string and its expiration time in Unix time.
65
- """
66
- return refresh_token(
58
+ return get_token(
67
59
  self.location,
60
+ kwargs.get("token"),
68
61
  self.token_endpoint,
69
62
  self.client_id,
70
- kwargs["refresh_token"],
71
- verify=self.verify,
63
+ self.verify,
72
64
  )
73
65
 
74
66
  async def close(self) -> None:
@@ -96,6 +88,9 @@ class DiracBearerTokenCredentialPolicy(AsyncBearerTokenCredentialPolicy):
96
88
  * It does not ensure that an access token is available.
97
89
  """
98
90
 
91
+ # Make mypy happy
92
+ _token: Optional[AccessToken] = None
93
+
99
94
  def __init__(
100
95
  self, credential: DiracTokenCredential, *scopes: str, **kwargs: Any
101
96
  ) -> None:
@@ -109,28 +104,19 @@ class DiracBearerTokenCredentialPolicy(AsyncBearerTokenCredentialPolicy):
109
104
  :type request: ~azure.core.pipeline.PipelineRequest
110
105
  :raises: :class:`~azure.core.exceptions.ServiceRequestError`
111
106
  """
112
- self._token: AccessToken | None
113
- self._credential: DiracTokenCredential
114
- credentials: dict[str, Any]
115
- try:
116
- self._token = get_token(self._credential.location, self._token)
117
- except RuntimeError:
118
- # If we are here, it means the credentials path does not exist
119
- # we suppose it is not needed to perform the request
107
+ # Make mypy happy
108
+ if not isinstance(self._credential, AsyncTokenCredential):
120
109
  return
121
110
 
122
- if not self._token:
123
- credentials = json.loads(self._credential.location.read_text())
124
- refresh_token = credentials["refresh_token"]
125
- if not is_refresh_token_valid(refresh_token):
126
- # If we are here, it means the refresh token is not valid anymore
127
- # we suppose it is not needed to perform the request
128
- return
129
- self._token = await self._credential.get_token(
130
- "", refresh_token=refresh_token
131
- )
111
+ self._token = await self._credential.get_token("", token=self._token)
112
+ if not self._token.token:
113
+ # If we are here, it means the token is not available
114
+ # we suppose it is not needed to perform the request
115
+ return
132
116
 
133
- request.http_request.headers["Authorization"] = f"Bearer {self._token.token}"
117
+ request.http_request.headers["Authorization"] = (
118
+ "Bearer " + cast(AccessToken, self._token).token
119
+ )
134
120
 
135
121
 
136
122
  class DiracClientMixin(metaclass=abc.ABCMeta):
@@ -156,6 +142,20 @@ class DiracClientMixin(metaclass=abc.ABCMeta):
156
142
  # Get .well-known configuration
157
143
  openid_configuration = get_openid_configuration(self._endpoint, verify=verify)
158
144
 
145
+ try:
146
+ self.client_version = distribution("diracx").version
147
+ except PackageNotFoundError:
148
+ try:
149
+ self.client_version = distribution("diracx-client").version
150
+ except PackageNotFoundError:
151
+ print("Error while getting client version")
152
+ self.client_version = "Unknown"
153
+
154
+ # Setting default headers
155
+ kwargs.setdefault("base_headers", {})[
156
+ "DiracX-Client-Version"
157
+ ] = self.client_version
158
+
159
159
  # Initialize Dirac with a Dirac-specific token credential policy
160
160
  # We need to ignore types here because mypy complains that we give
161
161
  # too many arguments to "object" constructor as this is a mixin
@@ -1,37 +1,128 @@
1
1
  from __future__ import annotations
2
2
 
3
- from datetime import datetime, timezone
3
+ from dataclasses import dataclass
4
+ from datetime import datetime, timedelta, timezone
5
+ from enum import Enum
6
+ import fcntl
4
7
  import json
8
+ import os
9
+ from diracx.core.utils import EXPIRES_GRACE_SECONDS, serialize_credentials
5
10
  import jwt
6
11
  import requests
7
12
 
13
+ from datetime import datetime, timezone
14
+ from importlib.metadata import PackageNotFoundError, distribution
8
15
 
9
16
  from pathlib import Path
10
- from typing import Any, Dict, List, Optional, cast, Self
17
+
18
+ from typing import Any, Dict, Optional, TextIO
11
19
  from urllib import parse
12
20
  from azure.core.credentials import AccessToken
13
21
  from azure.core.credentials import TokenCredential
14
22
  from azure.core.pipeline import PipelineRequest
15
23
  from azure.core.pipeline.policies import BearerTokenCredentialPolicy
16
24
 
17
- from ..generated.models import TokenResponse
18
- from diracx.core.models import TokenResponse as CoreTokenResponse
25
+ from diracx.core.models import TokenResponse
19
26
  from diracx.core.preferences import DiracxPreferences, get_diracx_preferences
20
27
 
21
- import sys
22
28
 
29
+ class TokenStatus(Enum):
30
+ VALID = "valid"
31
+ REFRESH = "refresh"
32
+ INVALID = "invalid"
23
33
 
24
- def refresh_token(
34
+
35
+ @dataclass
36
+ class TokenResult:
37
+ status: TokenStatus
38
+ access_token: Optional[AccessToken] = None
39
+ refresh_token: Optional[str] = None
40
+
41
+
42
+ def get_openid_configuration(
43
+ endpoint: str, *, verify: bool | str = True
44
+ ) -> Dict[str, str]:
45
+ """Get the openid configuration from the .well-known endpoint"""
46
+ response = requests.get(
47
+ url=parse.urljoin(endpoint, ".well-known/openid-configuration"),
48
+ verify=verify,
49
+ )
50
+ if not response.ok:
51
+ raise RuntimeError("Cannot fetch any information from the .well-known endpoint")
52
+ return response.json()
53
+
54
+
55
+ def get_token(
25
56
  location: Path,
57
+ token: AccessToken | None,
58
+ token_endpoint: str,
59
+ client_id: str,
60
+ verify: bool | str,
61
+ ) -> AccessToken:
62
+ """Get the access token if available and still valid."""
63
+ # Immediately return the token if it is available and still valid
64
+ if token and is_token_valid(token):
65
+ return token
66
+
67
+ if not location.exists():
68
+ # If we are here, it means the credentials path does not exist
69
+ # we suppose access token is not needed to perform the request
70
+ # we return an empty token to align with the expected return type
71
+ return AccessToken(token="", expires_on=0)
72
+
73
+ with open(location, "r+") as f:
74
+ # Acquire exclusive lock
75
+ fcntl.flock(f, fcntl.LOCK_EX)
76
+ try:
77
+ response = extract_token_from_credentials(f, token)
78
+ if response.status == TokenStatus.VALID and response.access_token:
79
+ # Lock is released in the finally block
80
+ return response.access_token
81
+
82
+ if response.status == TokenStatus.REFRESH and response.refresh_token:
83
+ # If we are here, it means the token needs to be refreshed
84
+ token_response = refresh_token(
85
+ token_endpoint,
86
+ client_id,
87
+ response.refresh_token,
88
+ verify=verify,
89
+ )
90
+
91
+ # Write the new credentials to the file
92
+ f.seek(0)
93
+ f.truncate()
94
+ f.write(serialize_credentials(token_response))
95
+ f.flush()
96
+ os.fsync(f.fileno())
97
+
98
+ # Get an AccessToken instance
99
+ return AccessToken(
100
+ token=token_response.access_token,
101
+ expires_on=int(
102
+ (
103
+ datetime.now(tz=timezone.utc)
104
+ + timedelta(
105
+ seconds=token_response.expires_in
106
+ - EXPIRES_GRACE_SECONDS
107
+ )
108
+ ).timestamp()
109
+ ),
110
+ )
111
+ # If we are here, it means the token is not available or not valid anymore
112
+ return AccessToken(token="", expires_on=0)
113
+ finally:
114
+ # Release the lock
115
+ fcntl.flock(f, fcntl.LOCK_UN)
116
+
117
+
118
+ def refresh_token(
26
119
  token_endpoint: str,
27
120
  client_id: str,
28
121
  refresh_token: str,
29
122
  *,
30
123
  verify: bool | str = True,
31
- ) -> AccessToken:
124
+ ) -> TokenResponse:
32
125
  """Refresh the access token using the refresh_token flow."""
33
- from diracx.core.utils import write_credentials
34
-
35
126
  response = requests.post(
36
127
  url=token_endpoint,
37
128
  data={
@@ -48,56 +139,49 @@ def refresh_token(
48
139
  )
49
140
 
50
141
  res = response.json()
51
- token_response = TokenResponse(
142
+ return TokenResponse(
52
143
  access_token=res["access_token"],
53
144
  expires_in=res["expires_in"],
54
145
  token_type=res.get("token_type"),
55
146
  refresh_token=res.get("refresh_token"),
56
147
  )
57
148
 
58
- write_credentials(cast(CoreTokenResponse, token_response), location=location)
59
- credentials = json.loads(location.read_text())
60
- return AccessToken(credentials.get("access_token"), credentials.get("expires_on"))
61
-
62
-
63
- def get_openid_configuration(
64
- endpoint: str, *, verify: bool | str = True
65
- ) -> Dict[str, str]:
66
- """Get the openid configuration from the .well-known endpoint"""
67
- response = requests.get(
68
- url=parse.urljoin(endpoint, ".well-known/openid-configuration"),
69
- verify=verify,
70
- )
71
- if not response.ok:
72
- raise RuntimeError("Cannot fetch any information from the .well-known endpoint")
73
- return response.json()
74
-
75
149
 
76
- def get_token(location: Path, token: AccessToken | None) -> AccessToken | None:
150
+ def extract_token_from_credentials(
151
+ token_file_descriptor: TextIO, token: AccessToken | None
152
+ ) -> TokenResult:
77
153
  """Get token if available and still valid."""
78
- # If the credentials path does not exist, raise an error
79
- if not location.exists():
80
- raise RuntimeError("credentials are not set")
81
-
82
- # Load the existing credentials
83
- if not token:
84
- credentials = json.loads(location.read_text())
154
+ # If we are here, it means the token is not available or not valid anymore
155
+ # We try to get it from the file
156
+ try:
157
+ credentials = json.load(token_file_descriptor)
158
+ except json.JSONDecodeError:
159
+ return TokenResult(TokenStatus.INVALID)
160
+
161
+ try:
85
162
  token = AccessToken(
86
- cast(str, credentials.get("access_token")),
87
- cast(int, credentials.get("expires_on")),
163
+ token=credentials["access_token"],
164
+ expires_on=credentials["expires_on"],
88
165
  )
166
+ refresh_token = credentials["refresh_token"]
167
+ except KeyError:
168
+ return TokenResult(TokenStatus.INVALID)
169
+
170
+ # We check the validity of the tokens
171
+ if is_token_valid(token):
172
+ return TokenResult(TokenStatus.VALID, access_token=token)
89
173
 
90
- # We check the validity of the token
91
- # If not valid, then return None to inform the caller that a new token
92
- # is needed
93
- if not is_token_valid(token):
94
- return None
174
+ if is_refresh_token_valid(refresh_token):
175
+ return TokenResult(TokenStatus.REFRESH, refresh_token=refresh_token)
95
176
 
96
- return token
177
+ # If we are here, it means the refresh token is not valid anymore
178
+ return TokenResult(TokenStatus.INVALID)
97
179
 
98
180
 
99
- def is_refresh_token_valid(refresh_token: str) -> bool:
181
+ def is_refresh_token_valid(refresh_token: str | None) -> bool:
100
182
  """Check if the refresh token is still valid."""
183
+ if not refresh_token:
184
+ return False
101
185
  # Decode the refresh token
102
186
  refresh_payload = jwt.decode(refresh_token, options={"verify_signature": False})
103
187
  if not refresh_payload or "exp" not in refresh_payload:
@@ -138,20 +222,12 @@ class DiracTokenCredential(TokenCredential):
138
222
  tenant_id: Optional[str] = None,
139
223
  **kwargs: Any,
140
224
  ) -> AccessToken:
141
- """Refresh the access token using the refresh_token flow.
142
- :param str scopes: The type of access needed.
143
- :keyword str claims: Additional claims required in the token, such as those returned in a resource
144
- provider's claims challenge following an authorization failure.
145
- :keyword str tenant_id: Optional tenant to include in the token request.
146
- :rtype: AccessToken
147
- :return: An AccessToken instance containing the token string and its expiration time in Unix time.
148
- """
149
- return refresh_token(
225
+ return get_token(
150
226
  self.location,
227
+ kwargs.get("token"),
151
228
  self.token_endpoint,
152
229
  self.client_id,
153
- kwargs["refresh_token"],
154
- verify=self.verify,
230
+ self.verify,
155
231
  )
156
232
 
157
233
 
@@ -162,40 +238,31 @@ class DiracBearerTokenCredentialPolicy(BearerTokenCredentialPolicy):
162
238
  * It does not ensure that an access token is available.
163
239
  """
164
240
 
241
+ # Make mypy happy
242
+ _token: Optional[AccessToken] = None
243
+
165
244
  def __init__(
166
245
  self, credential: DiracTokenCredential, *scopes: str, **kwargs: Any
167
246
  ) -> None:
168
247
  super().__init__(credential, *scopes, **kwargs)
169
248
 
170
- def on_request(
171
- self, request: PipelineRequest
172
- ) -> None: # pylint:disable=invalid-overridden-method
249
+ def on_request(self, request: PipelineRequest) -> None:
173
250
  """Authorization Bearer is optional here.
174
251
  :param request: The pipeline request object to be modified.
175
252
  :type request: ~azure.core.pipeline.PipelineRequest
176
253
  :raises: :class:`~azure.core.exceptions.ServiceRequestError`
177
254
  """
178
- self._token: AccessToken | None
179
- self._credential: DiracTokenCredential
180
- credentials: dict[str, Any]
255
+ # Make mypy happy
256
+ if not isinstance(self._credential, TokenCredential):
257
+ return
181
258
 
182
- try:
183
- self._token = get_token(self._credential.location, self._token)
184
- except RuntimeError:
185
- # If we are here, it means the credentials path does not exist
259
+ self._token = self._credential.get_token("", token=self._token)
260
+ if not self._token.token:
261
+ # If we are here, it means the token is not available
186
262
  # we suppose it is not needed to perform the request
187
263
  return
188
264
 
189
- if not self._token:
190
- credentials = json.loads(self._credential.location.read_text())
191
- refresh_token = credentials["refresh_token"]
192
- if not is_refresh_token_valid(refresh_token):
193
- # If we are here, it means the refresh token is not valid anymore
194
- # we suppose it is not needed to perform the request
195
- return
196
- self._token = self._credential.get_token("", refresh_token=refresh_token)
197
-
198
- request.http_request.headers["Authorization"] = f"Bearer {self._token.token}"
265
+ self._update_headers(request.http_request.headers, self._token.token)
199
266
 
200
267
 
201
268
  class DiracClientMixin:
@@ -221,6 +288,20 @@ class DiracClientMixin:
221
288
  # Get .well-known configuration
222
289
  openid_configuration = get_openid_configuration(self._endpoint, verify=verify)
223
290
 
291
+ try:
292
+ self.client_version = distribution("diracx").version
293
+ except PackageNotFoundError:
294
+ try:
295
+ self.client_version = distribution("diracx-client").version
296
+ except PackageNotFoundError:
297
+ print("Error while getting client version")
298
+ self.client_version = "Unknown"
299
+
300
+ # Setting default headers
301
+ kwargs.setdefault("base_headers", {})[
302
+ "DiracX-Client-Version"
303
+ ] = self.client_version
304
+
224
305
  # Initialize Dirac with a Dirac-specific token credential policy
225
306
  # We need to ignore types here because mypy complains that we give
226
307
  # too many arguments to "object" constructor as this is a mixin
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: diracx-client
3
- Version: 0.0.1a19
3
+ Version: 0.0.1a21
4
4
  Summary: TODO
5
5
  License: GPL-3.0-only
6
6
  Classifier: Intended Audience :: Science/Research
@@ -18,4 +18,3 @@ Provides-Extra: testing
18
18
  Requires-Dist: diracx-testing; extra == "testing"
19
19
  Provides-Extra: types
20
20
  Requires-Dist: types-requests; extra == "types"
21
-
@@ -0,0 +1,36 @@
1
+ diracx/client/__init__.py,sha256=aLo7lP4xwlCtxs7MKD55gr2oDLQyWEvRHZVHwj5Sl2c,165
2
+ diracx/client/aio.py,sha256=gqVCOxYYl-q6hrz6dbhiT8kXuYWZfQeIQLHAHF9liI4,37
3
+ diracx/client/extensions.py,sha256=igHJAXhgpYQq-Di1ZOX2b2okqgjQHTs9HL8mBTHb6ss,3385
4
+ diracx/client/models.py,sha256=ToGTZHywDTtn-uw1woTLxNAcSw1eRCx2A_kr67ix2Hw,163
5
+ diracx/client/py.typed,sha256=bWew9mHgMy8LqMu7RuqQXFXLBxh2CRx0dUbSx-3wE48,27
6
+ diracx/client/generated/__init__.py,sha256=nlsFCxdUj1egqs6PF6vmNpl8Dd4B5Q3ewsO0QdxqJNM,854
7
+ diracx/client/generated/_client.py,sha256=F8bgxclyyUdLUQ1Elob20q_kXrobov_IRT1KNn_YmdY,4831
8
+ diracx/client/generated/_configuration.py,sha256=-Edgj-iuZW5SXOcCdS7jiv6UFauzO0GItg2ZnLp_xpA,1936
9
+ diracx/client/generated/_patch.py,sha256=ZsuUeieEbKp0OjXJz2qAW-z6W0Xt8wwb38J-RvQxfNE,1328
10
+ diracx/client/generated/_serialization.py,sha256=xx1ZQCrGqaBTG6N7TNUFRw7FT09rzJhpl33o6M_Fi88,86947
11
+ diracx/client/generated/_vendor.py,sha256=7SFDHLgkg4kHcXdnQhP4AqRKTW3x0UCwRikNL2jLYJ0,1936
12
+ diracx/client/generated/py.typed,sha256=bWew9mHgMy8LqMu7RuqQXFXLBxh2CRx0dUbSx-3wE48,27
13
+ diracx/client/generated/aio/__init__.py,sha256=nlsFCxdUj1egqs6PF6vmNpl8Dd4B5Q3ewsO0QdxqJNM,854
14
+ diracx/client/generated/aio/_client.py,sha256=L422ZtLs9A5rw9opXWEOwko-ZCL3TrtZtdmkUR03Mfc,4952
15
+ diracx/client/generated/aio/_configuration.py,sha256=oAz-SEZeCR4r-Rr0kxL44w56lRG1Gdw7iCIAC57CZDw,1968
16
+ diracx/client/generated/aio/_patch.py,sha256=6FYNV6Yt0ttTc7A5EQui764Ujuzypkjpv47LVdccmD8,697
17
+ diracx/client/generated/aio/_vendor.py,sha256=7SFDHLgkg4kHcXdnQhP4AqRKTW3x0UCwRikNL2jLYJ0,1936
18
+ diracx/client/generated/aio/operations/__init__.py,sha256=IdqXuE4gwqoRuocKXVW4jJGe8UtHfe-8WhCwn-ApVek,1070
19
+ diracx/client/generated/aio/operations/_operations.py,sha256=sMeIr-uvDuvT9qoU8NEyG5genE86uwNBnCKuaYhtiU4,68092
20
+ diracx/client/generated/aio/operations/_patch.py,sha256=3oHjHqBF7DXruMSVUTRxW0Xpv_mY1WaB8iyo47YBTec,4229
21
+ diracx/client/generated/models/__init__.py,sha256=Gjlh_zYz0ZAFpB1gqFvz8CdEzlGkLQKx25uoUJ1X-Gg,2512
22
+ diracx/client/generated/models/_enums.py,sha256=TEJYnmO0ax5GNhTb-qvUADe3wfLw-ji375Xn7Sgc7Ks,1738
23
+ diracx/client/generated/models/_models.py,sha256=UD4bVPgZRZpfTlb7ug9jvJyRBeVdqYDFKffRiMkC3BE,36407
24
+ diracx/client/generated/models/_patch.py,sha256=uvLwKzjWO_t-VZ4aSuLhuJ05RVxAP9UJxZV3XDeGMnU,1497
25
+ diracx/client/generated/operations/__init__.py,sha256=IdqXuE4gwqoRuocKXVW4jJGe8UtHfe-8WhCwn-ApVek,1070
26
+ diracx/client/generated/operations/_operations.py,sha256=xXzbVb8T6pyAaanYLuXprN4IhcYzPn1P-UNg8jdwp0w,84601
27
+ diracx/client/generated/operations/_patch.py,sha256=FvemlcswH_zZkdyoGObyTwRnwTsYIZJa3seO66C2BQI,4202
28
+ diracx/client/patches/__init__.py,sha256=8mzMyg1Kd9lJH1K7DYJ6FgjkTJgPRJmF0sYmuFv5wcs,468
29
+ diracx/client/patches/utils.py,sha256=7VaGp7IoAMMfotW3N9BrMb7h59mHjfkGgwFnLnIdNEs,10733
30
+ diracx/client/patches/aio/__init__.py,sha256=qIy1qj8HzaZDEU2PCjEHjFbylwfYRAM0i90WEDs2WuQ,471
31
+ diracx/client/patches/aio/utils.py,sha256=Bno4DntLGWEB88UO9eaBtZjG8K3QAJNaT2RI-_mQWgc,5949
32
+ diracx_client-0.0.1a21.dist-info/METADATA,sha256=MW4VLlkv77G0H-E7Osf03iCInid4Bdqv1txHeoICKn8,676
33
+ diracx_client-0.0.1a21.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
34
+ diracx_client-0.0.1a21.dist-info/entry_points.txt,sha256=NP67B7z-VIy8vEG3ZYtOAyxZqLtrOAD5hh2pA2AFBKI,123
35
+ diracx_client-0.0.1a21.dist-info/top_level.txt,sha256=vJx10tdRlBX3rF2Psgk5jlwVGZNcL3m_7iQWwgPXt-U,7
36
+ diracx_client-0.0.1a21.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.1.0)
2
+ Generator: setuptools (75.6.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,36 +0,0 @@
1
- diracx/client/__init__.py,sha256=aLo7lP4xwlCtxs7MKD55gr2oDLQyWEvRHZVHwj5Sl2c,165
2
- diracx/client/aio.py,sha256=gqVCOxYYl-q6hrz6dbhiT8kXuYWZfQeIQLHAHF9liI4,37
3
- diracx/client/extensions.py,sha256=igHJAXhgpYQq-Di1ZOX2b2okqgjQHTs9HL8mBTHb6ss,3385
4
- diracx/client/models.py,sha256=ToGTZHywDTtn-uw1woTLxNAcSw1eRCx2A_kr67ix2Hw,163
5
- diracx/client/py.typed,sha256=bWew9mHgMy8LqMu7RuqQXFXLBxh2CRx0dUbSx-3wE48,27
6
- diracx/client/generated/__init__.py,sha256=B9QWqpEmloFGgHcz5Qr_JhZ1VWuue3bFqG8P8tNRnOo,699
7
- diracx/client/generated/_client.py,sha256=Ucb7XVfbGg3wwzyUzyXVM7vHyHpiVY_SI-hLIlrzM10,4831
8
- diracx/client/generated/_configuration.py,sha256=cV68TslcEaEz1UC9I1w0fD97B8Qd-qp4e9DdnN52RNo,1936
9
- diracx/client/generated/_patch.py,sha256=ZsuUeieEbKp0OjXJz2qAW-z6W0Xt8wwb38J-RvQxfNE,1328
10
- diracx/client/generated/_serialization.py,sha256=D2NDvU1N7HsRxZcro5RqQsjwzeVrW89OfQABp2m-RT8,86957
11
- diracx/client/generated/_vendor.py,sha256=G4uvSqVEkCV40TKFEGOXRzs4kjAx70wPBNPS8cdzSBg,1936
12
- diracx/client/generated/py.typed,sha256=bWew9mHgMy8LqMu7RuqQXFXLBxh2CRx0dUbSx-3wE48,27
13
- diracx/client/generated/aio/__init__.py,sha256=B9QWqpEmloFGgHcz5Qr_JhZ1VWuue3bFqG8P8tNRnOo,699
14
- diracx/client/generated/aio/_client.py,sha256=sT_kcTQdSmZctC-uVACv_KvtUQUANbYNorpz31tcGsc,4952
15
- diracx/client/generated/aio/_configuration.py,sha256=XLwTMklUFCJUPdY7nyx2YjLHyu23q6H0nPYgbQfsr48,1968
16
- diracx/client/generated/aio/_patch.py,sha256=6FYNV6Yt0ttTc7A5EQui764Ujuzypkjpv47LVdccmD8,697
17
- diracx/client/generated/aio/_vendor.py,sha256=G4uvSqVEkCV40TKFEGOXRzs4kjAx70wPBNPS8cdzSBg,1936
18
- diracx/client/generated/aio/operations/__init__.py,sha256=GHpFQ9Xm5etewGThBTvKhKms0KHnhp2_vuNkb6na8a0,868
19
- diracx/client/generated/aio/operations/_operations.py,sha256=5h5c7NFGLOi53yxgC4ZPO4joSNysax4O4hxpDnNGNPE,99551
20
- diracx/client/generated/aio/operations/_patch.py,sha256=3oHjHqBF7DXruMSVUTRxW0Xpv_mY1WaB8iyo47YBTec,4229
21
- diracx/client/generated/models/__init__.py,sha256=1W96tTA46xJpxwVE73kswpIkUwuKZAVxKdr7mdUgykw,3110
22
- diracx/client/generated/models/_enums.py,sha256=xhX35Xy2EkLB1gX5TyOSFTV0pw9iAgR98UenK5yKB2o,2389
23
- diracx/client/generated/models/_models.py,sha256=WJoQCHRJ0rXehIr0gUwNNfKXp9uIifKb8smXmH0IQoE,39799
24
- diracx/client/generated/models/_patch.py,sha256=uvLwKzjWO_t-VZ4aSuLhuJ05RVxAP9UJxZV3XDeGMnU,1497
25
- diracx/client/generated/operations/__init__.py,sha256=GHpFQ9Xm5etewGThBTvKhKms0KHnhp2_vuNkb6na8a0,868
26
- diracx/client/generated/operations/_operations.py,sha256=jv07HbP9JF0DF56eyu7FYYjW4DSB1GxjMDHVRkM1LvY,124482
27
- diracx/client/generated/operations/_patch.py,sha256=FvemlcswH_zZkdyoGObyTwRnwTsYIZJa3seO66C2BQI,4202
28
- diracx/client/patches/__init__.py,sha256=8mzMyg1Kd9lJH1K7DYJ6FgjkTJgPRJmF0sYmuFv5wcs,468
29
- diracx/client/patches/utils.py,sha256=srbqBTsnNUKajHAP4aT3hR29P6rmJlsojIiJdMBW9wo,8403
30
- diracx/client/patches/aio/__init__.py,sha256=qIy1qj8HzaZDEU2PCjEHjFbylwfYRAM0i90WEDs2WuQ,471
31
- diracx/client/patches/aio/utils.py,sha256=d_OvqJuzJUfmeSmfmDD3J6CArVW3M9BZg9fnslzltKQ,6412
32
- diracx_client-0.0.1a19.dist-info/METADATA,sha256=7gHtve3zQW3j57bJyUOVYOoTykIkwGtjpVyi39uK5wg,677
33
- diracx_client-0.0.1a19.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
34
- diracx_client-0.0.1a19.dist-info/entry_points.txt,sha256=NP67B7z-VIy8vEG3ZYtOAyxZqLtrOAD5hh2pA2AFBKI,123
35
- diracx_client-0.0.1a19.dist-info/top_level.txt,sha256=vJx10tdRlBX3rF2Psgk5jlwVGZNcL3m_7iQWwgPXt-U,7
36
- diracx_client-0.0.1a19.dist-info/RECORD,,