antelope-interface 0.2.4__tar.gz → 0.2.6__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 (39) hide show
  1. {antelope_interface-0.2.4/src/antelope_interface.egg-info → antelope_interface-0.2.6}/PKG-INFO +1 -1
  2. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/pyproject.toml +1 -1
  3. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/setup.py +6 -0
  4. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/__init__.py +4 -0
  5. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/exchanges_from_spreadsheet.py +5 -0
  6. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/interfaces/abstract_query.py +2 -1
  7. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/interfaces/ibackground.py +3 -4
  8. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/interfaces/ibasic.py +13 -0
  9. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/interfaces/iexchange.py +14 -0
  10. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/interfaces/iforeground.py +33 -0
  11. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/models/__init__.py +21 -14
  12. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/refs/catalog_ref.py +12 -3
  13. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/refs/process_ref.py +8 -1
  14. {antelope_interface-0.2.4 → antelope_interface-0.2.6/src/antelope_interface.egg-info}/PKG-INFO +1 -1
  15. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/LICENSE +0 -0
  16. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/MANIFEST.in +0 -0
  17. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/README.md +0 -0
  18. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/setup.cfg +0 -0
  19. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/flows/__init__.py +0 -0
  20. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/flows/flow.py +0 -0
  21. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/flows/flow_interface.py +0 -0
  22. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/flows/openlca_locales.json +0 -0
  23. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/interfaces/__init__.py +0 -0
  24. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/interfaces/iconfigure.py +0 -0
  25. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/interfaces/iindex.py +0 -0
  26. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/interfaces/iquantity.py +0 -0
  27. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/models/auth.py +0 -0
  28. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/refs/__init__.py +0 -0
  29. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/refs/base.py +0 -0
  30. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/refs/exchange_ref.py +0 -0
  31. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/refs/flow_ref.py +0 -0
  32. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/refs/quantity_ref.py +0 -0
  33. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/refs/tests/__init__.py +0 -0
  34. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/refs/tests/test_flows.py +0 -0
  35. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope/xdb_tokens.py +0 -0
  36. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope_interface.egg-info/SOURCES.txt +0 -0
  37. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope_interface.egg-info/dependency_links.txt +0 -0
  38. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope_interface.egg-info/requires.txt +0 -0
  39. {antelope_interface-0.2.4 → antelope_interface-0.2.6}/src/antelope_interface.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: antelope_interface
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: A common interface for accessing LCA data
5
5
  Author-email: Brandon Kuczenski <bkuczenski@ucsb.edu>
6
6
  License: BSD-3-Clause
@@ -22,7 +22,7 @@ classifiers = [
22
22
  "Topic :: Scientific/Engineering"
23
23
  ]
24
24
  dependencies = ["synonym_dict >= 0.2.4", "pydantic >= 2.5.0"]
25
- version = "0.2.4"
25
+ version = "0.2.6"
26
26
 
27
27
  [tool.setuptools.packages.find]
28
28
  where = ["src"]
@@ -5,6 +5,12 @@ setup()
5
5
 
6
6
  """
7
7
  Version History:
8
+ 0.2.6 2024/05/29 - split_subfragment and fragments_with_flow into fg interface
9
+ contrib_lcia is an exchange method
10
+ un-resolved CatalogRefs can now return their replacement, if provided a query at instantiation
11
+
12
+ 0.2.5 2024/05/06 - bg_lcia() becomes a basic interface route; sys_lcia() is the fully-featured background route
13
+
8
14
  0.2.4 2024/04/17 - split out BasicInterface from AbstractQuery.
9
15
  abandon setup.py except for this changelog.
10
16
  Redesign ExteriorFlow to have maybe a little bit more logic
@@ -105,6 +105,10 @@ class LcQuery(BasicQuery, BackgroundInterface, ConfigureInterface):
105
105
  pass
106
106
 
107
107
 
108
+ class FgQuery(LcQuery, ForegroundInterface):
109
+ pass
110
+
111
+
108
112
  '''
109
113
  Utilities
110
114
 
@@ -1,11 +1,15 @@
1
1
  """
2
2
  This module provides a routine that generates a list of exchange refs from a properly formatted spreadsheet
3
3
  """
4
+
4
5
  from .refs import CatalogRef, ExchangeRef
5
6
  from .interfaces import check_direction
6
7
 
7
8
 
8
9
  class ValueIsBalance(Exception):
10
+ """
11
+ Used to signal when an exchange is reached that is designated as a balance.
12
+ """
9
13
  pass
10
14
 
11
15
 
@@ -93,6 +97,7 @@ def exchanges_from_spreadsheet(sheetlike, term_dict=None, node=None, origin=None
93
97
  - row(0) returns a header list
94
98
  - row(1) is the process's reference flow
95
99
  - subsequent rows are dependent flows
100
+
96
101
  !TODO: support multiple references with is_ref or is_reference field
97
102
 
98
103
  "entries" in the row() return must be "cell-like":
@@ -15,7 +15,8 @@ class PrivateArchive(Exception):
15
15
 
16
16
 
17
17
  class AbstractQuery(object):
18
- """ Not-quite-abstract base class for executing queries
18
+ """
19
+ Not-quite-abstract base class for executing queries
19
20
 
20
21
  Query implementation must provide:
21
22
  - origin (property)
@@ -20,7 +20,6 @@ More plugins are yet imagined.
20
20
 
21
21
  from .abstract_query import AbstractQuery
22
22
  from ..refs import ExchangeRef
23
- from itertools import chain
24
23
 
25
24
 
26
25
  class BackgroundRequired(Exception):
@@ -136,7 +135,7 @@ class BackgroundInterface(AbstractQuery):
136
135
  process, ref_flow=ref_flow, **kwargs)
137
136
 
138
137
  def _make_sys_lci_exchange(self, x):
139
- return ExchangeRef(self.get(x.process), self.make_ref(x.flow), x.direction, value=x.value,
138
+ return ExchangeRef(self.make_ref(x.process), self.make_ref(x.flow), x.direction, value=x.value,
140
139
  termination=x.termination, comment='SYS LCI', is_reference=False)
141
140
 
142
141
  def sys_lci(self, demand, **kwargs):
@@ -160,7 +159,7 @@ class BackgroundInterface(AbstractQuery):
160
159
  for i in self._perform_query(_interface, 'sys_lci', BackgroundRequired, demand, **kwargs):
161
160
  yield self._make_sys_lci_exchange(i)
162
161
 
163
- def bg_lcia(self, process, query_qty, observed=None, ref_flow=None, **kwargs):
162
+ def sys_lcia(self, process, query_qty, observed=None, ref_flow=None, **kwargs):
164
163
  """
165
164
 
166
165
  :param process:
@@ -170,7 +169,7 @@ class BackgroundInterface(AbstractQuery):
170
169
  :param kwargs:
171
170
  :return:
172
171
  """
173
- return self._perform_query(_interface, 'bg_lcia', BackgroundRequired,
172
+ return self._perform_query(_interface, 'sys_lcia', BackgroundRequired,
174
173
  process, query_qty, observed=observed, ref_flow=ref_flow, **kwargs)
175
174
 
176
175
  '''
@@ -142,4 +142,17 @@ class BasicInterface(AbstractQuery):
142
142
  except TypeError:
143
143
  return False
144
144
 
145
+ def bg_lcia(self, process, query_qty=None, ref_flow=None, **kwargs):
146
+ """
147
+ Basic interface permits cumulative LCIA scores to be retrieved, but only if values=True
148
+
149
+ :param process:
150
+ :param query_qty: if omitted, a catalog may select a default LCIA method
151
+ :param ref_flow:
152
+ :param kwargs:
153
+ :return:
154
+ """
155
+ return self._perform_query('basic', 'bg_lcia', BasicRequired,
156
+ process, query_qty, ref_flow=ref_flow, **kwargs)
157
+
145
158
 
@@ -103,3 +103,17 @@ class ExchangeInterface(AbstractQuery):
103
103
  """
104
104
  return self._perform_query(_interface, 'exchange_relation', ExchangeRequired,
105
105
  process, ref_flow, exch_flow, direction, termination=termination, **kwargs)
106
+
107
+ def contrib_lcia(self, process, quantity=None, ref_flow=None, **kwargs):
108
+ """
109
+ exchange interface provides the ability to perform a contribution analysis of a process's LCIA scores.
110
+ In core, this is accomplished with ephemeral fragments.
111
+
112
+ :param process:
113
+ :param quantity: if omitted, a catalog may select a default LCIA method
114
+ :param ref_flow:
115
+ :param kwargs:
116
+ :return:
117
+ """
118
+ return self._perform_query(_interface, 'contrib_lcia', ExchangeRequired,
119
+ process, quantity, ref_flow, **kwargs)
@@ -95,6 +95,39 @@ class ForegroundInterface(AbstractQuery):
95
95
  """
96
96
  return self.make_ref(self._perform_query(_interface, 'child_flows', ForegroundRequired, fragment, **kwargs))
97
97
 
98
+ def fragments_with_flow(self, flow, direction=None,**kwargs):
99
+ """
100
+ Generates fragments made with the specified flow, optionally filtering by direction, reference status, and
101
+ background status. For all three filters, the default None is to generate all fragments.
102
+ :param flow:
103
+ :param direction: [None | 'Input' | 'Output']
104
+ :param kwargs:
105
+ :return:
106
+ """
107
+ return self._perform_query(_interface, 'fragments_with_flow', ForegroundRequired,
108
+ flow, direction=direction, **kwargs)
109
+
110
+ def split_subfragment(self, fragment, replacement=None, **kwargs):
111
+ """
112
+ Given a non-reference fragment, split it off into a new reference fragment, and create a surrogate child
113
+ that terminates to it.
114
+
115
+ without replacement:
116
+ Old: ...parent-->fragment
117
+ New: ...parent-->surrogate#fragment; (fragment)
118
+
119
+ with replacement:
120
+ Old: ...parent-->fragment; (replacement)
121
+ New: ...parent-->surrogate#replacement; (fragment); (replacement)
122
+
123
+ :param fragment:
124
+ :param replacement:
125
+ :param kwargs:
126
+ :return:
127
+ """
128
+ return self._perform_query(_interface, 'split_subfragment', ForegroundRequired,
129
+ fragment, replacement=replacement, **kwargs)
130
+
98
131
  def anchors(self, fragment, **kwargs):
99
132
  """
100
133
  List observed anchors for a fragment
@@ -275,8 +275,8 @@ class DirectedFlow(ResponseModel):
275
275
  return self.flow.flowable
276
276
 
277
277
  @classmethod
278
- def from_exchange(cls, obj):
279
- return cls(flow=FlowSpec.from_exchange(obj), direction=obj.direction)
278
+ def from_observed(cls, obj):
279
+ return cls(flow=FlowSpec.from_flow(obj.flow), direction=obj.direction)
280
280
 
281
281
 
282
282
  class ExteriorFlow(DirectedFlow):
@@ -287,6 +287,10 @@ class ExteriorFlow(DirectedFlow):
287
287
  """
288
288
  context: List[str]
289
289
 
290
+ @property
291
+ def termination(self):
292
+ return self.context
293
+
290
294
  @classmethod
291
295
  def from_background(cls, flow, direction, context):
292
296
  if hasattr(context, 'entity_type'):
@@ -301,7 +305,7 @@ class ExteriorFlow(DirectedFlow):
301
305
  return cls(flow=FlowSpec.from_flow(flow), direction=direction, context=cx)
302
306
 
303
307
  @classmethod
304
- def from_exchange(cls, obj):
308
+ def from_exterior(cls, obj):
305
309
  if obj.type == 'context':
306
310
  context = obj.termination.as_list()
307
311
  elif obj.type == 'cutoff':
@@ -313,7 +317,7 @@ class ExteriorFlow(DirectedFlow):
313
317
 
314
318
  class Exchange(ResponseModel):
315
319
  """
316
- Do we need to add locale??
320
+ Do we need to add locale?? no it's in the flow entity
317
321
  """
318
322
  origin: str
319
323
  process: str
@@ -333,7 +337,8 @@ class Exchange(ResponseModel):
333
337
  term = x.termination
334
338
  cx = None
335
339
  return cls(origin=x.process.origin, process=x.process.external_ref, flow=FlowEntity.from_flow(x.flow),
336
- direction=x.direction, termination=term, context=cx, type=x.type, comment=x.comment, str=str(x), **kwargs)
340
+ direction=x.direction, termination=term, context=cx, type=x.type, comment=x.comment, str=str(x),
341
+ **kwargs)
337
342
 
338
343
 
339
344
  class ReferenceExchange(Exchange):
@@ -341,17 +346,18 @@ class ReferenceExchange(Exchange):
341
346
  termination: None
342
347
 
343
348
  @classmethod
344
- def from_exchange(cls, x):
349
+ def from_exchange(cls, x, **kwargs):
345
350
  if x.termination is not None:
346
351
  cx = list(x.termination)
347
352
  else:
348
353
  cx = None
349
354
  return cls(origin=x.process.origin, process=x.process.external_ref, flow=FlowEntity.from_flow(x.flow),
350
- direction=x.direction, termination=None, context=cx, type=x.type, comment=x.comment, str=str(x))
355
+ direction=x.direction, termination=None, context=cx, type=x.type, comment=x.comment, str=str(x),
356
+ **kwargs)
351
357
 
352
358
 
353
359
  class ReferenceValue(ReferenceExchange):
354
- value: float
360
+ value: float = 0.0
355
361
 
356
362
  @classmethod
357
363
  def from_rx(cls, x):
@@ -429,10 +435,11 @@ def generate_pydantic_inventory(xs, mode=None, values=False, ref_flow=None):
429
435
 
430
436
  :param xs: iterable of exchanges
431
437
  :param mode: [None] whether to filter the exchanges by type. could be one of:
432
- None: generate all exchanges
433
- 'interior'
434
- 'exterior'
435
- 'cutoff'
438
+ - None: generate all exchanges
439
+ - 'interior'
440
+ - 'exterior'
441
+ - 'cutoff'
442
+
436
443
  :param values: (bool) [False] whether to include exchange values.
437
444
  :param ref_flow: (ignored if values=False) the reference flow with which the exchange value was computed. If None,
438
445
  this implies the exchange reports un-allocated exchange values
@@ -604,13 +611,13 @@ class SummaryLciaScore(AggregatedLciaScore):
604
611
 
605
612
 
606
613
  class LciaDetail(ResponseModel):
607
- exchange: Optional[DirectedFlow]
614
+ exchange: Optional[ExteriorFlow]
608
615
  factor: QuantityConversion
609
616
  result: float
610
617
 
611
618
  @classmethod
612
619
  def from_detailed_lcia_result(cls, d):
613
- return cls(exchange=DirectedFlow.from_exchange(d.exchange),
620
+ return cls(exchange=ExteriorFlow.from_exterior(d.exchange),
614
621
  factor=QuantityConversion.from_qrresult(d.factor),
615
622
  result=d.result)
616
623
 
@@ -3,7 +3,7 @@ The main import.
3
3
  """
4
4
 
5
5
 
6
- from .base import BaseRef
6
+ from .base import BaseRef, InvalidQuery, NoCatalog
7
7
  from .flow_ref import FlowRef
8
8
  # from .fragment_ref import FragmentRef
9
9
  from .process_ref import ProcessRef
@@ -66,7 +66,7 @@ class CatalogRef(BaseRef):
66
66
  return QuantityRef(external_ref, query, **kwargs)
67
67
  # elif etype == 'fragment':
68
68
  # return FragmentRef(external_ref, query, reference_entity, **kwargs)
69
- return cls(query.origin, external_ref, entity_type=etype, **kwargs)
69
+ return cls(query.origin, external_ref, entity_type=etype, query=query, **kwargs)
70
70
 
71
71
  def __init__(self, origin, external_ref, entity_type=None, reference_entity=None, **kwargs):
72
72
  """
@@ -78,7 +78,7 @@ class CatalogRef(BaseRef):
78
78
  """
79
79
  super(CatalogRef, self).__init__(origin, external_ref, **kwargs)
80
80
 
81
- if 'Name' not in kwargs:
81
+ if 'Name' not in self._d:
82
82
  self['Name'] = self.link
83
83
 
84
84
  self._asgn_etype = entity_type
@@ -143,3 +143,12 @@ class CatalogRef(BaseRef):
143
143
 
144
144
  def cf(self, *args, **kwargs):
145
145
  return 0.0
146
+
147
+ def resolve(self):
148
+ if self.has_property('query'):
149
+ try:
150
+ return self['query'].get(self.external_ref)
151
+ except InvalidQuery:
152
+ return self
153
+ else:
154
+ raise NoCatalog(self.origin)
@@ -306,6 +306,10 @@ class ProcessRef(EntityRef):
306
306
  for i in lci:
307
307
  yield self._to_exch_ref(i, i.value)
308
308
 
309
+ def contrib_lcia(self, quantity=None, ref_flow=None, **kwargs):
310
+ ref_flow = self._use_ref_exch(ref_flow)
311
+ return self._query.contrib_lcia(self.external_ref, quantity, ref_flow=ref_flow, **kwargs)
312
+
309
313
  def bg_lcia(self, lcia_qty, observed=None, ref_flow=None, **kwargs):
310
314
  """
311
315
  :param lcia_qty: should be a quantity ref (or qty), not an external ID
@@ -315,4 +319,7 @@ class ProcessRef(EntityRef):
315
319
  :return:
316
320
  """
317
321
  ref_flow = self._use_ref_exch(ref_flow)
318
- return self._query.bg_lcia(self.external_ref, lcia_qty, observed=observed, ref_flow=ref_flow, **kwargs)
322
+ if observed:
323
+ return self._query.sys_lcia(self.external_ref, lcia_qty, observed=observed, ref_flow=ref_flow, **kwargs)
324
+ else:
325
+ return self._query.bg_lcia(self.external_ref, lcia_qty, ref_flow=ref_flow, **kwargs)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: antelope_interface
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: A common interface for accessing LCA data
5
5
  Author-email: Brandon Kuczenski <bkuczenski@ucsb.edu>
6
6
  License: BSD-3-Clause