synmax-api-python-client 4.15.0__py3-none-any.whl → 4.16.1__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.
synmax/openapi/client.py CHANGED
@@ -10,7 +10,7 @@ import importlib
10
10
  from itertools import islice
11
11
  import pandas as pd
12
12
 
13
- from synmax.openapi.utils import change_signature, get_annotation, get_body_model, get_param_model
13
+ from synmax.openapi.utils import change_signature, get_annotation, get_body_model, get_param_model, PARAM_MODEL_SUFFIX, BODY_MODEL_SUFFIX
14
14
 
15
15
  class OpenAPIClient:
16
16
  def __init__(self,
@@ -100,16 +100,15 @@ class OpenAPIClient:
100
100
 
101
101
  def _create_request_function(self, method: str, full_url: str, param_model: Optional[Type[BaseModel]], body_model: Optional[Type[BaseModel]]):
102
102
  def request_func(self, **kwargs) -> Result:
103
+ param_dict = None
104
+ if param_model:
105
+ data = param_model(**kwargs).model_dump(mode='json')
106
+ param_dict = {k: v for k, v in data.dict().items() if v is not None}
107
+ body_dict = None
108
+ if body_model:
109
+ data = body_model(**kwargs).model_dump(mode='json')
110
+ body_dict = {k: v for k, v in data.items() if v is not None}
103
111
  def generator() -> Iterator[Dict[str, Any]]:
104
- param_dict = None
105
- if param_model:
106
- data = param_model(**kwargs).model_dump(mode='json')
107
- param_dict = {k: v for k, v in data.dict().items() if v is not None}
108
- body_dict = None
109
- if body_model:
110
- data = body_model(**kwargs).model_dump(mode='json')
111
-
112
- body_dict = {k: v for k, v in data.items() if v is not None}
113
112
  self._logger.info(f"Making request to {full_url}")
114
113
  retry_count = 0
115
114
  can_retry = True
synmax/openapi/utils.py CHANGED
@@ -1,8 +1,15 @@
1
1
  import inspect
2
- from pydantic import BaseModel, create_model, Extra
2
+ from pydantic import BaseModel, create_model, Extra, ValidationError
3
3
  from typing import Any, Dict, Optional, Type, Union, Literal
4
4
  from datetime import date
5
5
 
6
+ import traceback
7
+ import types
8
+ import typing
9
+
10
+ BODY_MODEL_SUFFIX = "BodyModel"
11
+ PARAM_MODEL_SUFFIX = "ParamsModel"
12
+
6
13
 
7
14
  def change_signature(func, signature: inspect.Signature):
8
15
  """
@@ -14,7 +21,105 @@ def change_signature(func, signature: inspect.Signature):
14
21
  def wrapped(*args, **kwargs):
15
22
  bound_arguments = inspect.signature(func).bind(*args, **kwargs)
16
23
  bound_arguments.apply_defaults()
17
- return func(*bound_arguments.args, **bound_arguments.kwargs)
24
+ try:
25
+ return func(*bound_arguments.args, **bound_arguments.kwargs)
26
+ except ValidationError as pydanticerror:
27
+ # strip user-irrelevant library guts from the error
28
+ tb = discard_traceback_frames(pydanticerror.__traceback__, 5)
29
+
30
+ # intercept familiar pydantic errors; replace them with user friendly ones
31
+ pretty = []
32
+ funcname = pydanticerror.title
33
+ funcname = funcname.removesuffix(BODY_MODEL_SUFFIX)
34
+ funcname = funcname.removesuffix(PARAM_MODEL_SUFFIX)
35
+ model = pydanticerror.model
36
+ fields = model.model_fields
37
+
38
+ errors_dict = {}
39
+ for e in pydanticerror.errors():
40
+ key = e['loc'][0]
41
+ if key not in errors_dict:
42
+ errors_dict[key] = []
43
+ errors_dict[key].append(e)
44
+
45
+ pretty = []
46
+ for param,errors in errors_dict.items():
47
+ # case: spurious param
48
+ if param not in fields:
49
+ pe = f"{funcname}:\n unexpected parameter '{param}'"
50
+ pretty.append(pe)
51
+ continue
52
+
53
+ annotation = fields[param].annotation
54
+ # handle unions as follows:
55
+ # if any arm of the union shallowly matches, its "the" relevant arm
56
+ # if no arm shallowly matches and there is one simple branch, its that one
57
+ # otherwise, we keep the whole union i guess
58
+ num_simple = 0
59
+ paramtype = None
60
+ if typing.get_origin(annotation) == typing.Union:
61
+ for e in errors:
62
+ if len(e['loc']) == 2:
63
+ input_value = e['input']
64
+ args = list(typing.get_args(annotation))
65
+ for arg in args:
66
+ shallow = typing.get_origin(arg)
67
+ if shallow is not None:
68
+ if isinstance(input_value, shallow):
69
+ paramtype = arg
70
+ break
71
+ else:
72
+ num_simple += 1
73
+ simple = arg
74
+ if isinstance(input_value, arg):
75
+ paramtype = arg
76
+ break
77
+ if paramtype is None:
78
+ if num_simple == 1:
79
+ paramtype = simple
80
+ else:
81
+ paramtype = annotation
82
+ else:
83
+ paramtype = annotation
84
+
85
+ if paramtype in [date, str, int, bool, float]:
86
+ input = errors[0]['input']
87
+ pe = f"{funcname}:\n '{param}' is expecting type '{paramtype.__name__}'"
88
+ pe += f"\n Got '{input}'"
89
+ pretty.append(pe)
90
+ continue
91
+ if typing.get_origin(paramtype) is list:
92
+ bad_inputs = []
93
+ not_list = False
94
+ arg = typing.get_args(paramtype)[0]
95
+ is_enum_list = typing.get_origin(arg) is typing.Literal
96
+ expecting = str(paramtype)
97
+ if is_enum_list:
98
+ expecting = "list[enum]"
99
+ pe = f"{funcname}:\n '{param}' is expecting type '{expecting}'"
100
+ if is_enum_list:
101
+ enumvals = typing.get_args(arg)
102
+ pe += f"\n Accepted enum values are: {', '.join(enumvals)}"
103
+ for e in errors:
104
+ if len(e['loc']) == 3: # error in a list element (path depth 3)
105
+ bad_inputs.append(str(e['input']))
106
+ if len(e['loc']) == 2: # not giving a list where a list expected
107
+ not_list = True
108
+ if not_list:
109
+ pe += f"\n Got '{e['input']}'"
110
+ pretty.append(pe)
111
+ continue
112
+ if len(bad_inputs > 0):
113
+ pe += f"\n Got '{', '.join(bad_inputs)}'"
114
+ pretty.append(pe)
115
+ continue
116
+ # if there's an error our prettifier recognized, just print that
117
+ # otherwise, fall back to the raw pydantic error
118
+ if len(pretty) == 0:
119
+ raise pydanticerror.with_traceback(tb)
120
+ else:
121
+ raise ParamError(pretty).with_traceback(tb) from None
122
+
18
123
  sig = inspect.signature(func)
19
124
  new_params = [
20
125
  inspect.Parameter(
@@ -54,7 +159,7 @@ def get_param_model(parameters: list, operation_id: str) -> Optional[Type[BaseMo
54
159
  schema = param.get("schema", {"type": "string"})
55
160
  required = param.get("required", False)
56
161
  param_fields[name] = (map_openapi_type(schema, name), ... if required else None)
57
- return create_model(f"{operation_id}Params", **param_fields) if param_fields else None
162
+ return create_model_with_error_metadata(f"{operation_id}{PARAM_MODEL_SUFFIX}", **param_fields) if param_fields else None
58
163
 
59
164
 
60
165
  def get_body_model(request_body: dict, operation_id: str) -> Optional[Type[BaseModel]]:
@@ -69,7 +174,7 @@ def get_body_model(request_body: dict, operation_id: str) -> Optional[Type[BaseM
69
174
  body_fields[key] = (map_openapi_type(value, key), ... if is_required else None)
70
175
  if schema.get("additionalProperties") is False:
71
176
  body_extra = Extra.forbid
72
- return create_model(f"{operation_id}Body", **body_fields, __config__=type("Config", (), {"extra": body_extra})) if body_fields else None
177
+ return create_model_with_error_metadata(f"{operation_id}{BODY_MODEL_SUFFIX}", **body_fields, __config__=type("Config", (), {"extra": body_extra})) if body_fields else None
73
178
 
74
179
 
75
180
  def map_openapi_type(schema: Dict[str, Any], name: str) -> Type:
@@ -99,3 +204,59 @@ def map_openapi_type(schema: Dict[str, Any], name: str) -> Type:
99
204
 
100
205
  return type_map.get(schema.get("type"), Any)
101
206
 
207
+
208
+ def discard_traceback_frames(tb, discard):
209
+ frames = []
210
+ while tb:
211
+ frames.append(tb)
212
+ tb = tb.tb_next
213
+ keep = max(0, len(frames) - discard)
214
+ frames = frames[:keep]
215
+ head = None
216
+ current = None
217
+ for frame in frames:
218
+ new_tb = types.TracebackType(
219
+ tb_next=None,
220
+ tb_frame=frame.tb_frame,
221
+ tb_lasti=frame.tb_lasti,
222
+ tb_lineno=frame.tb_lineno
223
+ )
224
+ if head is None:
225
+ head = new_tb
226
+ current = head
227
+ else:
228
+ current.tb_next = new_tb
229
+ current = new_tb
230
+ return head
231
+
232
+
233
+ class ParamError(ValueError):
234
+ def __init__(self, lines):
235
+ self.lines = lines
236
+
237
+ def __str__(self):
238
+ out = ''
239
+ for line in self.lines:
240
+ out += "\n" + line
241
+ return out
242
+
243
+ def __repr__(self):
244
+ return f'ParamError(lines={self.lines!r})'
245
+
246
+
247
+ def create_model_with_error_metadata(name, **params):
248
+ base_model = create_model(name, **params)
249
+ def __init__(self, *args, **kwargs):
250
+ try:
251
+ super(base_model, self).__init__(*args, **kwargs)
252
+ except ValidationError as e:
253
+ e.model = base_model
254
+ raise e
255
+ enriched_model = type(
256
+ name,
257
+ (base_model,),
258
+ {'__init__': __init__}
259
+ )
260
+ return enriched_model
261
+
262
+
@@ -197,12 +197,34 @@ paths:
197
197
  content:
198
198
  application/json:
199
199
  schema: { $ref: '#/components/schemas/ErrorResponse' }
200
+
201
+ /infrastructure_watch_extended:
202
+ get:
203
+ operationId: routes.v2.infrastructure_watch_extended.get
204
+ x-method-name: infrastructure_watch_extended
205
+ summary: Get infrastructure watch extended data (Middle East conflict)
206
+ security: [ApiKeyAuth: [vulcan_infrastructure_watch_extended]]
207
+ responses:
208
+ '200':
209
+ description: Infrastructure watch extended data
210
+ content:
211
+ application/json:
212
+ schema:
213
+ type: array
214
+ items:
215
+ $ref: '#/components/schemas/InfrastructureWatchExtendedResponse'
216
+ '500':
217
+ description: Internal Server Error - Database error
218
+ content:
219
+ application/json:
220
+ schema: { $ref: '#/components/schemas/ErrorResponse' }
221
+
200
222
  /beta/query_datalinks:
201
223
  post:
202
224
  x-method-name: beta_query_datalinks
203
225
  security: [ApiKeyAuth: [hyperion]]
204
226
  summary: Execute SQL queries against SynMax datalinks
205
- description: Execute T-SQL queries directly against SynMax's 5 datalinks (19 tables). Returns query results as structured data.
227
+ description: Execute T-SQL queries directly against SynMax's datalinks. Returns query results as structured data.
206
228
  requestBody:
207
229
  required: true
208
230
  content:
@@ -215,7 +237,7 @@ paths:
215
237
  query:
216
238
  type: string
217
239
  description: SQL query to execute. Tables must use {linkid}_{table} format. Use ANSI SQL (LIMIT not TOP).
218
- example: "SELECT * FROM 1005_v_pipeline_flow WHERE gas_day >= '2024-01-01' LIMIT 100"
240
+ example: "SELECT * FROM v_pipeline_flow WHERE gas_day >= '2024-01-01' LIMIT 100"
219
241
  session_id:
220
242
  type: string
221
243
  description: Optional session ID for logging/tracking. Auto-generated if not provided.
@@ -479,6 +501,11 @@ components:
479
501
  description: ISO date on which the record was created
480
502
  example: "2023-01-01T12:00:00Z"
481
503
  nullable: true
504
+ btm_generation:
505
+ type: boolean
506
+ description: Indicates if the data center has behind-the-meter generation
507
+ example: true
508
+ nullable: true
482
509
  required:
483
510
  - synmax_id
484
511
 
@@ -662,6 +689,11 @@ components:
662
689
  example: "4/14/2025"
663
690
  description: Date of the latest available satellite image
664
691
  nullable: true
692
+ county:
693
+ type: string
694
+ example: "Fayette"
695
+ description: Plant county - Provided by EIA
696
+ nullable: true
665
697
  latitude:
666
698
  type: number
667
699
  format: float
@@ -1379,6 +1411,100 @@ components:
1379
1411
  example: "2025-11-17"
1380
1412
  description: ISO date on which the record was last modified
1381
1413
  nullable: true
1414
+
1415
+ InfrastructureWatchExtendedResponse:
1416
+ type: object
1417
+ properties:
1418
+ site_id:
1419
+ type: string
1420
+ format: uuid
1421
+ example: "f47ac10b-58cc-4372-a567-0e02b2c3d479"
1422
+ description: Unique UUID identifying the infrastructure site.
1423
+ nullable: false
1424
+ site_name:
1425
+ type: string
1426
+ example: "South Pars"
1427
+ description: Name of the tracked infrastructure site.
1428
+ nullable: false
1429
+ vulcan_assessment:
1430
+ type: string
1431
+ example: "visual change"
1432
+ description: The latest visual or operational assessment of the site (e.g., no change, visual change).
1433
+ nullable: false
1434
+ vulcan_assessment_datetime:
1435
+ type: string
1436
+ format: date-time
1437
+ example: "2026-03-05T20:00:00Z"
1438
+ description: ISO-8601 timestamp of when the assessment was conducted.
1439
+ nullable: false
1440
+ additional_notes:
1441
+ type: string
1442
+ example: "site fires and scarring detected near LNG trains"
1443
+ description: Additional context or observations regarding the assessment.
1444
+ nullable: true
1445
+ country:
1446
+ type: string
1447
+ example: "Iran"
1448
+ description: Country where the infrastructure is located.
1449
+ nullable: false
1450
+ country_code:
1451
+ type: string
1452
+ example: "IR"
1453
+ description: ISO country code of the location.
1454
+ nullable: false
1455
+ technology:
1456
+ type: string
1457
+ example: "Oil/Gas Processing"
1458
+ description: The primary industry or technology type of the site.
1459
+ nullable: true
1460
+ capacity:
1461
+ type: number
1462
+ format: float
1463
+ example: 730.0
1464
+ description: Operational capacity of the infrastructure.
1465
+ nullable: true
1466
+ capacity_unit:
1467
+ type: string
1468
+ example: "MMcm/d"
1469
+ description: Unit of measurement for the capacity.
1470
+ nullable: true
1471
+ latitude:
1472
+ type: number
1473
+ format: double
1474
+ example: 27.508
1475
+ description: Latitude of the site in decimal degrees.
1476
+ nullable: false
1477
+ longitude:
1478
+ type: number
1479
+ format: double
1480
+ example: 52.575
1481
+ description: Longitude of the site in decimal degrees.
1482
+ nullable: false
1483
+ location_wkt:
1484
+ type: string
1485
+ example: "POINT(52.575 27.508)"
1486
+ description: Well-Known Text (WKT) spatial representation of the site coordinates (Longitude Latitude).
1487
+ nullable: false
1488
+ image_benchmark_datetime:
1489
+ type: string
1490
+ format: date-time
1491
+ example: "2026-03-05T21:00:00Z"
1492
+ description: ISO-8601 timestamp of the baseline image used for comparison.
1493
+ nullable: true
1494
+ image_acquisition_datetime:
1495
+ type: string
1496
+ format: date-time
1497
+ example: "2026-03-05T20:00:00Z"
1498
+ description: ISO-8601 timestamp of when the newest satellite image was acquired.
1499
+ nullable: true
1500
+ image_source:
1501
+ type: string
1502
+ example: "Planet"
1503
+ description: Provider of the satellite imagery.
1504
+ nullable: true
1505
+ image_resolution:
1506
+ type: string
1507
+ example: "10m"
1382
1508
 
1383
1509
  ErrorResponse:
1384
1510
  type: object
@@ -23,6 +23,9 @@ class VulcanApiClient:
23
23
  def iir_data(self) -> Result:
24
24
  """Get IIR data"""
25
25
  ...
26
+ def infrastructure_watch_extended(self) -> Result:
27
+ """Get infrastructure watch extended data (Middle East conflict)"""
28
+ ...
26
29
  def beta_query_datalinks(self,query: str,session_id: str = ...) -> Result:
27
30
  """Execute SQL queries against SynMax datalinks"""
28
31
  ...
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: synmax-api-python-client
3
- Version: 4.15.0
3
+ Version: 4.16.1
4
4
  Summary: Synmax API client
5
5
  Home-page: https://github.com/SynMaxDev/synmax-api-python-client.git
6
6
  Author: SynMax Inc.
@@ -13,14 +13,23 @@ Requires-Dist: aioretry>=6.3.1
13
13
  Requires-Dist: packaging>=24.2
14
14
  Requires-Dist: pandas>=2.0.3
15
15
  Requires-Dist: pydantic>=2.10.6
16
- Requires-Dist: pydantic-core<2.32.0,>=2.27.2
16
+ Requires-Dist: pydantic_core<2.32.0,>=2.27.2
17
17
  Requires-Dist: requests>=2.32.3
18
18
  Requires-Dist: tenacity>=9.0.0
19
19
  Requires-Dist: tqdm>=4.67.1
20
20
  Requires-Dist: urllib3>=2.3.0
21
21
  Requires-Dist: prance>=25.4.8.0
22
- Requires-Dist: openapi-spec-validator>=0.7.1
22
+ Requires-Dist: openapi_spec_validator>=0.7.1
23
23
  Requires-Dist: httpx>=0.28.1
24
+ Dynamic: author
25
+ Dynamic: author-email
26
+ Dynamic: description
27
+ Dynamic: description-content-type
28
+ Dynamic: home-page
29
+ Dynamic: license-file
30
+ Dynamic: requires-dist
31
+ Dynamic: requires-python
32
+ Dynamic: summary
24
33
 
25
34
  # SynMax API Python Client
26
35
 
@@ -17,33 +17,27 @@ synmax/hyperion/v4/__init__.py,sha256=VpXU-_FP836dXUDcUFYr-0y0-ZrSM8aCtGE97Z2qbS
17
17
  synmax/hyperion/v4/hyperion_client.py,sha256=mhYL3QiOoD2viCI60grLMFvGdHx8iD8IF05NWC6-HS0,868
18
18
  synmax/hyperion/v4/hyperion_client.pyi,sha256=yNgEmWzZWKPeQ4Y-ilfBOr8e_lMD4GIMwWe3UCHu438,12039
19
19
  synmax/hyperion/v4/openapi.yaml,sha256=RU4mACjWtL3yNwN5tEyZHYcJ37-pg7F3Y84UyBDfveE,100266
20
- synmax/hyperion/v4/start_hyperion_client.py,sha256=0Cs6qgy8yYuhrVhSVZqa7TKKR9PHFkEomA26MTQUJlU,2495
21
20
  synmax/leviaton/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- synmax/leviaton/start_leviaton_client.py,sha256=XrgEHoYTsLgwyuBWkHxsCzeEGoj4C40RuDVD_0QZ_ks,4101
23
- synmax/leviaton/start_leviaton_client2.py,sha256=JdN0FJV67yqjptxw769CjRqgFdzqIdCvmpNclmnErzg,3107
24
21
  synmax/leviaton/v1/__init__.py,sha256=UgUccQqpTDS0qB20AyHb1ZCdoJvgjeWK1ZbEg2b2I6Y,93
25
22
  synmax/leviaton/v1/leviaton_client.py,sha256=rdASXkfD8V5ChNJMAUk2ZiptK-bgJpcBkdH812ih5jk,917
26
23
  synmax/leviaton/v1/leviaton_client.pyi,sha256=XwDR89SwF-Gc7YlGKxei0g0Z4e75qmFM5KzzmvMIHxo,14070
27
24
  synmax/leviaton/v1/openapi.yaml,sha256=0H4fJaVEfiDInHpY2yV03c5kZ4Bb_j_UiuMvO2Um03c,143378
28
25
  synmax/openapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
- synmax/openapi/client.py,sha256=WC14WowLxt6hFOdA6WAKAYU9Uet7tXmQGbkkyIQf9eo,8698
30
- synmax/openapi/utils.py,sha256=q6PsmUT0D58_AdOCM0ZNw1CrveiYVF4IQN4J6ticZ4Q,3689
26
+ synmax/openapi/client.py,sha256=lwENevbQmapCLktpcPgEpsqwYOATGLWDSwkpOs_3-LY,8684
27
+ synmax/openapi/utils.py,sha256=UyNm2UJ1s3YuLnd0Cq5lWbC92OWUhguyRYyOqlFB4rk,9789
31
28
  synmax/theia/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
29
  synmax/vulcan/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
- synmax/vulcan/start_vulcan_python_client.py,sha256=cx4DQyrNpIR6UyzOdEFreZWVLCwHE1Z1II5dfN6SPMg,746
34
30
  synmax/vulcan/v2/__init__.py,sha256=AGMAxDs93mZ_9zF1fFAufUsu9w9Ep94lO1vbLGbD-LU,81
35
- synmax/vulcan/v2/openapi.yaml,sha256=AkSc97bLX9hdR3OSSJqH_hF1TDCP7oghUk1uTsSmPNo,48866
36
- synmax/vulcan/v2/start_vulcan_client.py,sha256=XWHXzwCu6gK33Pw0FKfGjwXiEadg-G6VQI5UsqBlVHc,1002
37
- synmax/vulcan/v2/start_vulcan_client2.py,sha256=z59_ZLZ3NX7nO-50cEx7bqeuzYRj-pA4WEMlLf304qs,1833
31
+ synmax/vulcan/v2/openapi.yaml,sha256=NzIGFtgqH5fd7ekSjXoTl6aQAkt2Fjk2kDaqDj-0z9M,53272
38
32
  synmax/vulcan/v2/vulcan_client.py,sha256=aeCaISqNyJ0bezbvCcxVgdGmUPp2Lv0SFqDbFCt9TXQ,879
39
- synmax/vulcan/v2/vulcan_client.pyi,sha256=N8hgva9k2xdIikxnaZwsAPNb_S_ve_UVgpxfrHl7Od4,1120
33
+ synmax/vulcan/v2/vulcan_client.pyi,sha256=PwWS5qexlEWzwF3oK0N7_mgCP1ne8PFSwrlWyCd5b00,1263
34
+ synmax_api_python_client-4.16.1.dist-info/licenses/LICENSE,sha256=vKvn9cDVfJhNepCuIXLWaHnnUoDPX26KD-iWb7NAZ4M,44
40
35
  test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
36
  test/test_api_client.py,sha256=HFWCu_xBgqQXc9p6k6YmP2gVrdCFwuhoDVqlxpN1Yoc,4713
42
37
  test/test_hyperion_client.py,sha256=aCb4bMBXWofa82MInXoU9tJ5wWsg5sBRv7B_CHvkrcg,1380
43
38
  test/test_hyperion_e2e.py,sha256=BPhZH7eVQZSsFcvPdonKjmLahnfsLy37Z2DHp0LGeHc,6247
44
39
  test/test_hyperion_helpers.py,sha256=R0G7oqKaoz6jLRACODJ1Cf2gA0gaMPQhOZRjKp4a6-s,2006
45
- synmax_api_python_client-4.15.0.dist-info/LICENSE,sha256=vKvn9cDVfJhNepCuIXLWaHnnUoDPX26KD-iWb7NAZ4M,44
46
- synmax_api_python_client-4.15.0.dist-info/METADATA,sha256=nVpwzpTVF2G3zEFUaCMaZHf4NnTtDiaKdBc21HW3rEA,4994
47
- synmax_api_python_client-4.15.0.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
48
- synmax_api_python_client-4.15.0.dist-info/top_level.txt,sha256=SAjmDfHlJzUmjoGCT1SnS4qGSLN_ZF-p58UN1yW5kB0,17
49
- synmax_api_python_client-4.15.0.dist-info/RECORD,,
40
+ synmax_api_python_client-4.16.1.dist-info/METADATA,sha256=vkM0VHFRBA6soiZDcZSq-XyppOIUq-78ZGXfg4LfTxE,5193
41
+ synmax_api_python_client-4.16.1.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
42
+ synmax_api_python_client-4.16.1.dist-info/top_level.txt,sha256=SAjmDfHlJzUmjoGCT1SnS4qGSLN_ZF-p58UN1yW5kB0,17
43
+ synmax_api_python_client-4.16.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.45.1)
2
+ Generator: setuptools (79.0.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,27 +0,0 @@
1
- # from synmax.hyperion.v4.hyperion_client import HyperionApiClient
2
-
3
- # access_token = "eyJwcm9qZWN0X2lkIjogIlN5bm1heCBjb21tZXJjaWFsIEFQSSIsICJwcml2YXRlX2tleSI6ICIwQndzX0ExMFpkdVQyaWlNLS1lbXh3Mk5BNUkxa09kdFNVai04RjVvNzU4IiwgImNsaWVudF9pZCI6ICJGZWxpeCBLZXkiLCAidHlwZSI6ICJvbmVfeWVhcl9saWNlbnNlZF9jdXN0b21lciIsICJzdGFydF9kYXRlIjogIjAzLzE5LzIwMjQiLCAiZW5kX2RhdGUiOiAiMDMvMTkvMjAyNSIsICJ0cmlhbF9saWNlbnNlIjogZmFsc2UsICJpc3N1ZV9kYXRldGltZSI6ICIxOS0wMy0yMDI0IDE0OjI0OjA4IiwgImFkbWluX3VzZXIiOiBmYWxzZSwgInVzZXJfcm9sZXMiOiBbImh5cGVyaW9uIiwgInZ1bGNhbiJdfQ=="
4
-
5
- # client = HyperionApiClient(access_token=access_token)
6
-
7
- # res = client.wells(response_fields=["county", "date_completion", "date_first_production", "date_permit", "date_spud", "depth_measured", "depth_tvd", "horizontal_length", "lat_bottomhole", "lon_bottomhole", "lat_surface", "lon_surface", "operator", "region_natgas", "state_code", "sub_region_natgas", "well_id", "wellbore_type", "wellpad_id", "produced_formation", "produced_basin"], date_first_production_min="2023-01-31", date_first_production_max="2024-09-01")
8
- # # res = client.daily_production()
9
- # df = res.df()
10
- # print(df)
11
-
12
- # from synmax.hyperion.v4 import HyperionApiClient
13
-
14
- from synmax.hyperion.v4 import HyperionApiClient
15
-
16
- SYNMAX_ACCESS_TOKEN = "eyJwcm9qZWN0X2lkIjogIlN5bm1heCBjb21tZXJjaWFsIEFQSSIsICJwcml2YXRlX2tleSI6ICIwQndzX0ExMFpkdVQyaWlNLS1lbXh3Mk5BNUkxa09kdFNVai04RjVvNzU4IiwgImNsaWVudF9pZCI6ICJGZWxpeCBLZXkiLCAidHlwZSI6ICJvbmVfeWVhcl9saWNlbnNlZF9jdXN0b21lciIsICJzdGFydF9kYXRlIjogIjAzLzE5LzIwMjQiLCAiZW5kX2RhdGUiOiAiMDMvMTkvMjAyNSIsICJ0cmlhbF9saWNlbnNlIjogZmFsc2UsICJpc3N1ZV9kYXRldGltZSI6ICIxOS0wMy0yMDI0IDE0OjI0OjA4IiwgImFkbWluX3VzZXIiOiBmYWxzZSwgInVzZXJfcm9sZXMiOiBbImh5cGVyaW9uIiwgInZ1bGNhbiJdfQ=="
17
- hyperion_api_client = HyperionApiClient(access_token=SYNMAX_ACCESS_TOKEN)
18
- hyperion_api_client._write_stub()
19
-
20
- # wells_resp = hyperion_api_client.wells(response_fields=["county", "date_completion", "date_first_production", "date_permit", "date_spud", "depth_measured", "depth_tvd", "horizontal_length", "lat_bottomhole", "lon_bottomhole", "lat_surface", "lon_surface", "operator", "region_natgas", "state_code", "sub_region_natgas", "well_id", "wellbore_type", "wellpad_id", "produced_formation", "produced_basin"], date_first_production_min="2023-01-31", date_first_production_max="2024-09-01")
21
- results = hyperion_api_client.fetch_tils_expanded()
22
- results_df = results.df()
23
- results_df.head()
24
- print(results_df)
25
- # wells_df = wells_resp.df()
26
- # wells_df.head()
27
- # print(wells_df)
@@ -1,105 +0,0 @@
1
- from synmax.leviaton.v1.leviaton_client import LeviatonApiClient
2
- import requests
3
- headers={'x-api-key': '36b5ee11-c0c8-4af2-a1d1-ffdd5447597b', "Accept": "application/json"}
4
- key = '36b5ee11-c0c8-4af2-a1d1-ffdd5447597b'
5
- # client = LeviatonApiClient(access_token=headers['x-api-key'])
6
- import json
7
-
8
- # claims = {
9
- # "claims": [
10
- # {"claim_name": "leviaton_volume_flows", "claim_json": {"name": "leviaton_countries", "type": "api", "filters": {}}},
11
- # {"claim_name": "leviaton_terminals", "claim_json": {"name": "leviaton_terminals", "type": "api", "filters": {}}},
12
- # {"claim_name": "leviaton_transactions", "claim_json": {"name": "leviaton_transactions", "type": "api", "filters": {}}},
13
- # {"claim_name": "leviaton_vessels", "claim_json": {"name": "leviaton_volume_flows", "type": "api", "filters": {}}},
14
- # ]
15
- # }
16
- # url = f"https://leviaton.api.synmax.com/v1/openapi.yaml"
17
- # url = "http://127.0.0.1:8080/v1/openapi.yaml"
18
- # client = LeviatonApiClient(access_token=key)
19
-
20
- # response = requests.get(url, headers=headers, verify=False)
21
- # response.raise_for_status()
22
-
23
- # with open(client._spec, "wb") as f:
24
- # f.write(response.content)
25
- # client._write_stub()
26
-
27
- # payload = {
28
- # "destination_polygons": [
29
- # [
30
- # [-125.0, 24.5],
31
- # [-125.0, 49.5],
32
- # [-66.9, 49.5],
33
- # [-66.9, 24.5],
34
- # [-125.0, 24.5]
35
- # ],
36
- # [
37
- # [122.9, 24.0],
38
- # [122.9, 45.5],
39
- # [146.0, 45.5],
40
- # [146.0, 24.0],
41
- # [122.9, 24.0]
42
- # ]
43
- # ],
44
- # "from_timestamp": "2025-05-11T12:55:47.957167",
45
- # "to_timestamp": "2025-05-21T12:55:47.957167",
46
-
47
- # }
48
- # results = client.volume_flows_history(transaction_type='loading')
49
- # # results = client.volume_flows(**payload)
50
- # print(results.df())
51
-
52
- # res = client.transactions(destination_country_codes=["US"])
53
- # print(res.df())
54
-
55
- # for result in results:
56
- # print(result)
57
-
58
- # breakpoint()
59
-
60
- # from synmax.leviaton.v1.leviaton_client import LeviatonApiClient
61
-
62
- # API Key - Replace with your actual API key
63
- # api_key = "36b5ee11-c0c8-4af2-a1d1-ffdd5447597b"
64
-
65
- # Initialize the client
66
- # client = LeviatonApiClient(access_token=key)
67
- # client._write_stub()
68
-
69
- # Fetch transactions for USA terminals
70
- # result = client.vessels_history(from_timestamp="2025-01-01T00:00:00Z", to_timestamp="2025-01-22T00:00:00Z")
71
-
72
- # Fetch transactions from specific terminals
73
- # result = client.transactions_history(
74
- # destination_terminals=["LNG Canada", "Altamira", "Freeport", "Corpus Christi"]
75
- # )
76
-
77
- # result = client.terminals(countries=["USA"])
78
- # result = client.transactions()
79
- # result = client.vessels()
80
- # result = client.vessels_details()
81
- # result = client.volume_flows_history(transaction_type='loading')
82
- # result = client.volume_flows(transaction_type='loading')
83
- # result = client.countries()
84
- # result = client.transactions_details()
85
- # result = client.transactions_forecast()
86
- # result = client.transactions_forecast_details()
87
- # result = client.transactions_forecast_history()
88
- # result = client.transactions_forecast_history_details()
89
- # result = client.vessels_history()
90
-
91
-
92
- # print(result.df())for record in result:
93
- # print(record)
94
- access_token = "eyJwcm9qZWN0X2lkIjogIlN5bm1heCBjb21tZXJjaWFsIEFQSSIsICJwcml2YXRlX2tleSI6ICI5V2lYYUZqdXl1ZkdERXBRSUFhWWd6NG4wZlZLajktVjJocHRaM0RoSWdVIiwgImNsaWVudF9pZCI6ICJzeWRuZWVfZHRpbCIsICJ0eXBlIjogImxvbmdfdGVybV9saWNlbnNlZF9jdXN0b21lciIsICJzdGFydF9kYXRlIjogIjA5LzEyLzIwMjUiLCAiZW5kX2RhdGUiOiAiMTIvMzEvOTk5OSIsICJ0cmlhbF9saWNlbnNlIjogZmFsc2UsICJpc3N1ZV9kYXRldGltZSI6ICIxMi0wOS0yMDI1IDE5OjI5OjQ1IiwgImFkbWluX3VzZXIiOiBmYWxzZSwgInVzZXJfcm9sZXMiOiBbImR0aWxfZXhwYW5zaW9uIiwgImh5cGVyaW9uIiwgInZ1bGNhbiJdfQ=="
95
-
96
- from synmax.leviaton.v1 import LeviatonApiClient
97
- LeviatonApiClient._write_stub()
98
- leviaton_client = LeviatonApiClient(access_token=access_token)
99
-
100
- # Method name:
101
-
102
- result =leviaton_client.transactions_history(loading_origin_terminals=["Corpus Christi"], from_timestamp="2025-07-15T22:43:41.371622+00:00", to_timestamp="2025-07-27T22:43:41.371622+00:00")
103
-
104
- for record in result:
105
- print(record)
@@ -1,81 +0,0 @@
1
- from synmax.leviaton.v1.leviaton_client import LeviatonApiClient
2
-
3
-
4
- # API Key - Replace with your actual API key
5
- api_key = "36b5ee11-c0c8-4af2-a1d1-ffdd5447597b"
6
-
7
- # Initialize the client
8
- client = LeviatonApiClient(access_token=api_key)
9
-
10
- # Fetch transactions for USA terminals
11
- # print('starting')
12
- # result = client.transac
13
-
14
- # print(result.df())
15
-
16
- import os
17
- import unittest
18
- from synmax.leviaton.v1.leviaton_client import LeviatonApiClient
19
- import json
20
-
21
- class TestLeviatonApiMethods(unittest.TestCase):
22
- @classmethod
23
- def setUpClass(cls):
24
- api_key = "36b5ee11-c0c8-4af2-a1d1-ffdd5447597b"
25
- # x_auth_data = json.dumps({"claims": [{"claim_name":"leviaton_countries","claim_json":{"name":"leviaton_countries","type":"api","filters":{}}},{"claim_name":"leviaton_terminals","claim_json":{"name":"leviaton_terminals","type":"api","filters":{}}},{"claim_name":"leviaton_transactions","claim_json":{"name":"leviaton_transactions","type":"api","filters":{}}},{"claim_name":"leviaton_vessels","claim_json":{"name":"leviaton_vessels","type":"api","filters":{}}},{"claim_name":"leviaton_volume_flows","claim_json":{"name":"leviaton_volume_flows","type":"api","filters":{}}}]})
26
- cls.client = LeviatonApiClient(access_token=api_key)
27
-
28
- def test_all_api_methods(self):
29
- api_methods = [
30
- "countries",
31
- "healthcheck",
32
- "terminals",
33
- "vessels",
34
- # "vessels_history",
35
- "vessels_details",
36
- "volume_flows",
37
- "volume_flows/history",
38
- "transactions",
39
- "transactions_details",
40
- "transactions_forecast",
41
- "transactions_forecast_details",
42
- "transactions_forecast_history",
43
- "transactions_forecast_history_details",
44
- "transactions_history",
45
- ]
46
-
47
- for method_name in api_methods:
48
- with self.subTest(method=method_name):
49
- print(f"Testing {method_name}...")
50
- method = getattr(self.client, method_name, None)
51
- self.assertIsNotNone(method, f"Method '{method_name}' not found on client")
52
-
53
- try:
54
- result = method()
55
- df = result.df()
56
- self.assertIsNotNone(df, f"{method_name} returned None")
57
- self.assertFalse(df.empty, f"{method_name} returned an empty dataframe")
58
- except Exception as e:
59
- self.fail(f"{method_name} raised an exception: {e}")
60
-
61
- if __name__ == "__main__":
62
- unittest.main()
63
-
64
-
65
- # from synmax.leviaton.v1.leviaton_client import LeviatonApiClient
66
-
67
- # # API Key - Replace with your actual API key
68
- # api_key = "36b5ee11-c0c8-4af2-a1d1-ffdd5447597b"
69
-
70
- # # Initialize the client
71
- # client = LeviatonApiClient(access_token=api_key)
72
-
73
- # # Fetch transactions for USA terminals
74
- # result = client.transactions_history(destination_country_codes=["US"])
75
-
76
- # # Fetch transactions from specific terminals
77
- # result = client.transactions_history(
78
- # destination_terminals=["LNG Canada", "Altamira", "Freeport", "Corpus Christi"]
79
- # )
80
-
81
- # print(result.df())
@@ -1,14 +0,0 @@
1
-
2
-
3
-
4
- from synmax.vulcan.v2 import VulcanApiClient
5
-
6
- SYNMAX_ACCESS_TOKEN = "eyJwcm9qZWN0X2lkIjogIlN5bm1heCBjb21tZXJjaWFsIEFQSSIsICJwcml2YXRlX2tleSI6ICIwQndzX0ExMFpkdVQyaWlNLS1lbXh3Mk5BNUkxa09kdFNVai04RjVvNzU4IiwgImNsaWVudF9pZCI6ICJGZWxpeCBLZXkiLCAidHlwZSI6ICJvbmVfeWVhcl9saWNlbnNlZF9jdXN0b21lciIsICJzdGFydF9kYXRlIjogIjAzLzE5LzIwMjQiLCAiZW5kX2RhdGUiOiAiMDMvMTkvMjAyNSIsICJ0cmlhbF9saWNlbnNlIjogZmFsc2UsICJpc3N1ZV9kYXRldGltZSI6ICIxOS0wMy0yMDI0IDE0OjI0OjA4IiwgImFkbWluX3VzZXIiOiBmYWxzZSwgInVzZXJfcm9sZXMiOiBbImh5cGVyaW9uIiwgInZ1bGNhbiJdfQ=="
7
- vulcan_api_client = VulcanApiClient(access_token=SYNMAX_ACCESS_TOKEN)
8
- vulcan_api_client._write_stub()
9
-
10
- # wells_resp = vulcan_api_client.iir_data()
11
-
12
- # wells_df = wells_resp.df()
13
- # wells_df.head()
14
- # print(wells_df)
@@ -1,27 +0,0 @@
1
- from synmax.vulcan.v2.vulcan_client import VulcanApiClient
2
- import json
3
-
4
- VulcanApiClient._write_stub()
5
- # access_token = os.environ.get("ACCESS_TOKEN")
6
-
7
- claims_dict = {
8
- "claims": [
9
- {"claim_name": "vulcan_datacenters", "claim_json": {"name": "vulcan_datacenters", "type": "api", "filters": {}}},
10
- {"claim_name": "vulcan_underconstruction", "claim_json": {"name": "vulcan_underconstruction", "type": "api", "filters": {}}},
11
- {"claim_name": "vulcan_lng_projects", "claim_json": {"name": "vulcan_lng_projects", "type": "api", "filters": {}}},
12
- {"claim_name": "vulcan_metadata_history", "claim_json": {"name": "vulcan_metadata_history", "type": "api", "filters": {}}},
13
- {"claim_name": "vulcan_project_rankings", "claim_json": {"name": "vulcan_project_rankings", "type": "api", "filters": {}}},
14
- ]
15
- }
16
-
17
- client = VulcanApiClient(access_token='PSq8zWS3FgHnVGcE2Yz4ZNOBk4SRpUPI')
18
-
19
-
20
- payload = {}
21
-
22
- got = client.lng_projects()
23
- df = got.df()
24
- print(df)
25
-
26
- print(got)
27
- breakpoint()
@@ -1,43 +0,0 @@
1
- # result = client.transac
2
-
3
- # print(result.df())
4
-
5
- import os
6
- import unittest
7
- from synmax.vulcan.v2.vulcan_client import VulcanApiClient
8
- import json
9
-
10
- class TestVulcanApiMethods(unittest.TestCase):
11
- @classmethod
12
- def setUpClass(cls):
13
- api_key = "PSq8zWS3FgHnVGcE2Yz4ZNOBk4SRpUPI"
14
- x_auth_data = json.dumps({"claims": [{"claim_name":"vulcan_datacenters","claim_json":{"name":"vulcan_datacenters","type":"api","filters":{}}},{"claim_name":"vulcan_underconstruction","claim_json":{"name":"vulcan_underconstruction","type":"api","filters":{}}},{"claim_name":"vulcan_lng_projects","claim_json":{"name":"vulcan_lng_projects","type":"api","filters":{}}},{"claim_name":"vulcan_project_rankings","claim_json":{"name":"vulcan_project_rankings","type":"api","filters":{}}}]})
15
- cls.client = VulcanApiClient(access_token=api_key)
16
-
17
- def test_all_api_methods(self):
18
- api_methods = [
19
- "health",
20
- "datacenters",
21
- "underconstruction",
22
- "lng_projects",
23
- "project_rankings",
24
- "iir_data"
25
- ]
26
-
27
- for method_name in api_methods:
28
- with self.subTest(method=method_name):
29
- print(f"Testing {method_name}...")
30
- method = getattr(self.client, method_name, None)
31
- self.assertIsNotNone(method, f"Method '{method_name}' not found on client")
32
-
33
- try:
34
- result = method()
35
- df = result.df()
36
- print(df)
37
- self.assertIsNotNone(df, f"{method_name} returned None")
38
- self.assertFalse(df.empty, f"{method_name} returned an empty dataframe")
39
- except Exception as e:
40
- self.fail(f"{method_name} raised an exception: {e}")
41
-
42
- if __name__ == "__main__":
43
- unittest.main()