prisma-api 0.4.2__tar.gz → 0.4.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: prisma_api
3
- Version: 0.4.2
3
+ Version: 0.4.4
4
4
  Summary: A package for interacting with PrISMa Platform APIs. PrISMa is a holistic system for numerical synthesis and assessment of Metal-Organic Frameworks and their applications, for Direct Air Capture of CO2. For more information, see: https://prisma.hw.ac.uk.
5
5
  Author-email: RCCS-CaptureTeam <team@prisma-platform.org>
6
6
  License: GNUv3
@@ -181,6 +181,7 @@ Module-level helpers exported from the package:
181
181
  - `prisma_api.update_dev_mode`
182
182
  - `prisma_api.update_dev_host_port`
183
183
  - `prisma_api.locate_config`
184
+ - `prisma_api.PrismaUpsertError`, `prisma_api.PrismaRowErrorWarning`, `prisma_api.PrismaUnknownFieldsWarning`, `prisma_api.PrismaNewStructureWarning`
184
185
 
185
186
  ## v2 wrapper list
186
187
 
@@ -266,6 +267,24 @@ All methods below are available on `api.v2`.
266
267
  - `get_carbon_zeopp_experimental(mof=None, limit=500, offset=0)`
267
268
  - `get_carbon_zeopp_experimental_item(item_id)`
268
269
 
270
+ ### AutoPrism tables
271
+
272
+ - `get_computation_runs(workflow_id=None, step=None, status=None, limit=500, offset=0)` / `get_computation_run(run_id)`
273
+ - `upsert_computation_runs(payload, timeout=None, raise_on_error=False)`
274
+ - `get_adsorption_singlepoint(...)` / `get_adsorption_singlepoint_item(row_id)` / `upsert_adsorption_singlepoint(payload, meta_provenance=None, repo_dir=None, timeout=None, raise_on_error=False, check_ids=True)`
275
+ - `get_heat_capacity(...)` / `get_heat_capacity_item(row_id)` / `upsert_heat_capacity(payload, meta_provenance=None, repo_dir=None, timeout=None, raise_on_error=False, check_ids=True)`
276
+ - `get_isotherm_h2(...)` / `get_isotherm_h2_item(row_id)` / `upsert_isotherm_h2(payload, meta_provenance=None, repo_dir=None, timeout=None, raise_on_error=False, check_ids=True)` — H2 only
277
+ - `get_adsorption_isotherm(structure=None, isotherm_id=None, component=None, temperature_K=None, pressure_bar=None, limit=500, offset=0, md5=None)` / `get_adsorption_isotherm_item(row_id)` / `upsert_adsorption_isotherm(payload, meta_provenance=None, repo_dir=None, timeout=None, raise_on_error=False, check_ids=True)` — every gas except H2; needs prisma_cloud **>= 0.6.16** (older servers return 404)
278
+ - `get_mofchecker(...)` / `get_mofchecker_item(row_id)` / `upsert_mofchecker(payload, meta_provenance=None, repo_dir=None, timeout=None, raise_on_error=False, check_ids=True)`
279
+ - `get_zeopp_metrics(...)` / `get_zeopp_metrics_item(row_id)` / `upsert_zeopp_metrics(payload, meta_provenance=None, repo_dir=None, timeout=None, raise_on_error=False, check_ids=True)`
280
+ - `get_autoprism_collection(...)` / `upsert_autoprism_collection(payload, meta_provenance=None, repo_dir=None, timeout=None, raise_on_error=False, check_ids=True)`
281
+
282
+ Rejected rows (HTTP 207, or 400 when nothing is stored) raise
283
+ `PrismaUpsertError` with `raise_on_error=True`, else emit
284
+ `PrismaRowErrorWarning`. Ignored payload fields and newly created MOF records
285
+ emit `PrismaUnknownFieldsWarning` / `PrismaNewStructureWarning`. See
286
+ [API_REFERENCE_V2.md](API_REFERENCE_V2.md#autoprism-tables).
287
+
269
288
  ### TEA, LCA, cases, and scenarios
270
289
 
271
290
  - `get_output_kpis(scenario_id=None, mof=None, good_structure=None, limit=500, offset=0)`
@@ -373,7 +392,8 @@ pytest tests/ -v --cov=prisma_api --cov-report=term-missing
373
392
 
374
393
  ## Additional documentation
375
394
 
376
- - [API_REFERENCE.md](API_REFERENCE.md)
395
+ - [API_REFERENCE_V1.md](API_REFERENCE_V1.md)
396
+ - [API_REFERENCE_V2.md](API_REFERENCE_V2.md)
377
397
  - [DEVELOPMENT_SUMMARY.md](DEVELOPMENT_SUMMARY.md)
378
398
  - [User Guide.md](User%20Guide.md)
379
399
 
@@ -381,4 +401,5 @@ pytest tests/ -v --cov=prisma_api --cov-report=term-missing
381
401
 
382
402
  - Production v2 base URL: `https://prisma-platform.org/api/v2`
383
403
  - Authentication header: `X-API-Key`
384
- - Local development routing is controlled through config and `api.update_dev_mode(True)`
404
+ - Local development routing is selected with `prisma_api.init(local_dev=True)`; the default targets production
405
+ - 0.4.4: the `adsorption-isotherm` endpoints and the 400/notice handling need prisma_cloud >= 0.6.16
@@ -161,6 +161,7 @@ Module-level helpers exported from the package:
161
161
  - `prisma_api.update_dev_mode`
162
162
  - `prisma_api.update_dev_host_port`
163
163
  - `prisma_api.locate_config`
164
+ - `prisma_api.PrismaUpsertError`, `prisma_api.PrismaRowErrorWarning`, `prisma_api.PrismaUnknownFieldsWarning`, `prisma_api.PrismaNewStructureWarning`
164
165
 
165
166
  ## v2 wrapper list
166
167
 
@@ -246,6 +247,24 @@ All methods below are available on `api.v2`.
246
247
  - `get_carbon_zeopp_experimental(mof=None, limit=500, offset=0)`
247
248
  - `get_carbon_zeopp_experimental_item(item_id)`
248
249
 
250
+ ### AutoPrism tables
251
+
252
+ - `get_computation_runs(workflow_id=None, step=None, status=None, limit=500, offset=0)` / `get_computation_run(run_id)`
253
+ - `upsert_computation_runs(payload, timeout=None, raise_on_error=False)`
254
+ - `get_adsorption_singlepoint(...)` / `get_adsorption_singlepoint_item(row_id)` / `upsert_adsorption_singlepoint(payload, meta_provenance=None, repo_dir=None, timeout=None, raise_on_error=False, check_ids=True)`
255
+ - `get_heat_capacity(...)` / `get_heat_capacity_item(row_id)` / `upsert_heat_capacity(payload, meta_provenance=None, repo_dir=None, timeout=None, raise_on_error=False, check_ids=True)`
256
+ - `get_isotherm_h2(...)` / `get_isotherm_h2_item(row_id)` / `upsert_isotherm_h2(payload, meta_provenance=None, repo_dir=None, timeout=None, raise_on_error=False, check_ids=True)` — H2 only
257
+ - `get_adsorption_isotherm(structure=None, isotherm_id=None, component=None, temperature_K=None, pressure_bar=None, limit=500, offset=0, md5=None)` / `get_adsorption_isotherm_item(row_id)` / `upsert_adsorption_isotherm(payload, meta_provenance=None, repo_dir=None, timeout=None, raise_on_error=False, check_ids=True)` — every gas except H2; needs prisma_cloud **>= 0.6.16** (older servers return 404)
258
+ - `get_mofchecker(...)` / `get_mofchecker_item(row_id)` / `upsert_mofchecker(payload, meta_provenance=None, repo_dir=None, timeout=None, raise_on_error=False, check_ids=True)`
259
+ - `get_zeopp_metrics(...)` / `get_zeopp_metrics_item(row_id)` / `upsert_zeopp_metrics(payload, meta_provenance=None, repo_dir=None, timeout=None, raise_on_error=False, check_ids=True)`
260
+ - `get_autoprism_collection(...)` / `upsert_autoprism_collection(payload, meta_provenance=None, repo_dir=None, timeout=None, raise_on_error=False, check_ids=True)`
261
+
262
+ Rejected rows (HTTP 207, or 400 when nothing is stored) raise
263
+ `PrismaUpsertError` with `raise_on_error=True`, else emit
264
+ `PrismaRowErrorWarning`. Ignored payload fields and newly created MOF records
265
+ emit `PrismaUnknownFieldsWarning` / `PrismaNewStructureWarning`. See
266
+ [API_REFERENCE_V2.md](API_REFERENCE_V2.md#autoprism-tables).
267
+
249
268
  ### TEA, LCA, cases, and scenarios
250
269
 
251
270
  - `get_output_kpis(scenario_id=None, mof=None, good_structure=None, limit=500, offset=0)`
@@ -353,7 +372,8 @@ pytest tests/ -v --cov=prisma_api --cov-report=term-missing
353
372
 
354
373
  ## Additional documentation
355
374
 
356
- - [API_REFERENCE.md](API_REFERENCE.md)
375
+ - [API_REFERENCE_V1.md](API_REFERENCE_V1.md)
376
+ - [API_REFERENCE_V2.md](API_REFERENCE_V2.md)
357
377
  - [DEVELOPMENT_SUMMARY.md](DEVELOPMENT_SUMMARY.md)
358
378
  - [User Guide.md](User%20Guide.md)
359
379
 
@@ -361,4 +381,5 @@ pytest tests/ -v --cov=prisma_api --cov-report=term-missing
361
381
 
362
382
  - Production v2 base URL: `https://prisma-platform.org/api/v2`
363
383
  - Authentication header: `X-API-Key`
364
- - Local development routing is controlled through config and `api.update_dev_mode(True)`
384
+ - Local development routing is selected with `prisma_api.init(local_dev=True)`; the default targets production
385
+ - 0.4.4: the `adsorption-isotherm` endpoints and the 400/notice handling need prisma_cloud >= 0.6.16
@@ -0,0 +1,13 @@
1
+ from importlib.metadata import PackageNotFoundError, version as _version
2
+
3
+ try:
4
+ __version__ = _version("prisma_api")
5
+ except PackageNotFoundError: # running from a source tree without installing
6
+ __version__ = "0+unknown"
7
+
8
+
9
+ from prisma_api.prisma_api import prisma_api as init # Main prisma_api class for initialisation
10
+ from prisma_api.prisma_api_v2 import PrismaAPIv2 # v2 API client (also accessible as api.v2)
11
+ from prisma_api.prisma_api_v2 import (PrismaUpsertError, PrismaRowErrorWarning, # upsert failure signals
12
+ PrismaUnknownFieldsWarning, PrismaNewStructureWarning)
13
+ from prisma_api.config import update_dev_mode, update_dev_host_port, locate_config # Config utility functions
@@ -1,3 +1,5 @@
1
+ import os
2
+ import sys
1
3
  from pathlib import Path
2
4
  import pandas as pd
3
5
  import yaml
@@ -54,6 +56,12 @@ def create_config_file(api_key: str = None):
54
56
  raise ImportError("PyYAML is required. Install with: pip install pyyaml")
55
57
 
56
58
  if not api_key:
59
+ if not sys.stdin or not sys.stdin.isatty():
60
+ raise RuntimeError(
61
+ f"No PrISMa config file at {get_config_path()} and no API key in the "
62
+ f"environment. Set {', '.join(ENV_VARS)} (at least PRISMA_API_KEY), "
63
+ "or run interactively once to create the config file."
64
+ )
57
65
  val = input("Enter your PrISMa API key: ").strip()
58
66
  api_key = val
59
67
 
@@ -67,10 +75,40 @@ def create_config_file(api_key: str = None):
67
75
  yaml.safe_dump(cfg, f, sort_keys=False)
68
76
  return cfg
69
77
 
78
+ # Environment variables read when no config file exists (or use_config_file=False)
79
+ ENV_VARS = ("PRISMA_API_KEY", "PRISMA_API_DEV_API_KEY", "PRISMA_API_DEV_HOST_PORT")
80
+
81
+
82
+ def config_from_env():
83
+ """
84
+ Build a config dict from PRISMA_API_* environment variables.
85
+
86
+ Returns None if none of them is set.
87
+ """
88
+ if not any(os.getenv(name) for name in ENV_VARS):
89
+ return None
90
+ prod_key = os.getenv("PRISMA_API_KEY", "")
91
+ return {
92
+ "api_key": prod_key,
93
+ "dev_api_key": os.getenv("PRISMA_API_DEV_API_KEY", prod_key),
94
+ "dev_host_port": os.getenv("PRISMA_API_DEV_HOST_PORT", "8000"),
95
+ }
96
+
97
+
70
98
  # Get or create config - intended use by initialisation of main prisma_api class
71
99
  def get_or_create_config():
72
- """Return existing config or create it interactively if missing."""
100
+ """
101
+ Return the config, in order of preference:
102
+
103
+ 1. config.yaml, if it exists;
104
+ 2. PRISMA_API_* environment variables (nothing is written to disk);
105
+ 3. an interactive prompt, which creates config.yaml. Without a terminal
106
+ (e.g. CI) this raises instead of blocking on input().
107
+ """
73
108
  cfg = load_config()
109
+ if cfg is not None:
110
+ return cfg
111
+ cfg = config_from_env()
74
112
  if cfg is not None:
75
113
  return cfg
76
114
  return create_config_file()
@@ -25,11 +25,15 @@ def _safe_nan_check(x):
25
25
  # prisma_api main class
26
26
  class prisma_api():
27
27
 
28
- def __init__(self, use_config_file=True, local_dev: bool = False):
28
+ def __init__(self, use_config_file=True, local_dev: bool = False,
29
+ upload_timeout: int = 120):
29
30
 
30
31
  # Initialise `prisma_api` object with api_key location
31
32
  self.verbose = False
32
33
  # Initialise `prisma_api` object with api_key location
34
+ # use_config_file=True: config.yaml, else PRISMA_API_* env vars, else
35
+ # an interactive prompt (raises instead when there is no terminal).
36
+ # use_config_file=False: env vars only.
33
37
  if use_config_file:
34
38
  cfg = get_or_create_config()
35
39
  prod_key = cfg.get('api_key', '')
@@ -40,7 +44,9 @@ class prisma_api():
40
44
  dev_key = os.getenv('PRISMA_API_DEV_API_KEY', prod_key)
41
45
  dev_host_port = os.getenv('PRISMA_API_DEV_HOST_PORT', '8000')
42
46
 
43
- # local_dev now controls target DB explicitly at init time.
47
+ # local_dev controls the target DB at init time:
48
+ # local_dev=False (default) -> PRODUCTION (prisma-platform.org)
49
+ # local_dev=True -> local dev server on localhost:<dev_host_port>
44
50
  self.dev = bool(local_dev)
45
51
  self.dev_host_port = dev_host_port
46
52
  self.key = dev_key if self.dev else prod_key
@@ -50,8 +56,13 @@ class prisma_api():
50
56
  dev=self.dev,
51
57
  dev_host_port=getattr(self, 'dev_host_port', ''),
52
58
  return_format=getattr(self, '_return_format', 'json'),
59
+ upload_timeout=upload_timeout,
53
60
  )
54
61
 
62
+ # Make the target explicit so test uploads don't go to production by mistake.
63
+ target = "LOCAL DEV" if self.dev else "PRODUCTION"
64
+ print(f"prisma_api: connected to {target} API at {self.v2._base_url()}")
65
+
55
66
  def set_return_format(self, fmt: str) -> None:
56
67
  """
57
68
  Set the output format for all v2 list endpoints.