Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions pyvolca/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,47 @@ instead of walking the raw exchanges list.
| `all_products` | `list[Activity]` | — |
| `exchanges` | `list[Union[TechnosphereExchange, BiosphereExchange, WasteExchange]]` | — |

#### Properties

##### `allocation_percent`

This process's own allocation share (0..100), or ``None``.

A multi-output process splits the parent activity's burden across its
co-products; every :attr:`all_products` entry carries its share. This
returns the share of *this* process — the entry whose ``process_id``
matches — and ``None`` for single-output processes.

##### `inputs`

Every input exchange — technosphere inputs and biosphere resources.

Equivalent to filtering :attr:`exchanges` by ``e.is_input``. Mixed
kinds: callers needing only one variant should use
:attr:`technosphere_inputs` or filter manually.

##### `is_allocated`

True iff the activity splits its burden across several co-products.

Reads the structured ``allocation_percent`` the engine sets on each
:attr:`all_products` entry (authoritative), not the description text.

##### `outputs`

Every output exchange — products and biosphere emissions.

Includes the reference product, coproducts (in allocated
activities), and all biosphere emissions.

##### `technosphere_inputs`

Only the technosphere inputs (ingredients from other activities).

Excludes biosphere inputs (resource extractions) and waste
outputs. The common case when answering "what does this activity
consume from upstream?".

### `ActivityDiff`

Result of ``compare_activities``.
Expand All @@ -910,6 +951,12 @@ One matched or unmatched flow in an activity comparison.
| `right` | `float \| None` | — |
| `unit` | `str \| None` | — |

#### Properties

##### `delta`

right - left (0 if one side is missing).

### `AggregateGroup`

One bucket inside an AggregateResult.
Expand Down Expand Up @@ -953,6 +1000,22 @@ An exchange with the environment (resource extraction or emission).
| `is_biosphere` | `bool` | True |
| `is_waste` | `bool` | False |

#### Properties

##### `is_input`

True for resource extractions (``direction`` is ``RESOURCE``).

Biosphere inputs are resource extractions; outputs are emissions
to the environment.

##### `is_reference`

Always False — biosphere exchanges cannot be reference flows.

The reference flow defines the functional unit and is always a
technosphere product (see :class:`TechnosphereExchange.is_reference`).

### `CharacterizationFactor`

One characterization factor matched against a database biosphere flow.
Expand Down Expand Up @@ -990,6 +1053,12 @@ the slice is incomplete.
| `shown` | `int` | — |
| `factors` | `list[CharacterizationFactor]` | list() |

#### Properties

##### `has_more`

True when the server truncated below ``matches``.

### `ClassificationFilter`

Filter a supply-chain/consumers query by a classification (system, value, mode).
Expand Down Expand Up @@ -1161,6 +1230,12 @@ response of :meth:`Client.get_flow_mapping`.
| `matched_flows` | `int` | — |
| `flows` | `list[FlowMappingEntry]` | list() |

#### Properties

##### `coverage_pct`

Matched fraction expressed as 0..100. Returns 0 when total is 0.

### `FlowMappingEntry`

One DB biosphere flow and the CF (if any) assigned to it.
Expand Down Expand Up @@ -1407,6 +1482,12 @@ materialise eagerly if you prefer.
| `_fetched` | `list[~T]` | list() |
| `_exhausted` | `bool` | False |

#### Properties

##### `page_size`

Server-applied limit (page size for further fetches).

### `ServerVersion`

Server build metadata returned by :meth:`Client.get_version`.
Expand Down Expand Up @@ -1462,6 +1543,16 @@ lengths by hand.
| `entries` | `list[SupplyChainEntry]` | list() |
| `edges` | `list[SupplyChainEdge]` | list() |

#### Properties

##### `has_more`

True when the server truncated ``entries`` below ``filtered_activities``.

Surfacing this lets callers detect silent truncation: if you passed
``limit=100`` and ``filtered_activities`` is 500, downstream LCA work
would be wrong without flagging the gap.

### `SupplyChainEdge`

A consumer→supplier link in the supply chain.
Expand Down Expand Up @@ -1519,6 +1610,22 @@ producing activity's classifications describe the product taxonomy.
| `is_biosphere` | `bool` | False |
| `is_waste` | `bool` | False |

#### Properties

##### `is_input`

True for technosphere inputs (``role`` is ``INPUT`` or ``REFERENCE_INPUT``).

Lets callers split exchanges into inputs vs. outputs without
knowing the four-role taxonomy.

##### `is_reference`

True for reference roles (``REFERENCE_PRODUCT`` / ``REFERENCE_INPUT``).

The reference exchange is the one that defines the activity's
functional unit — the basis the LCA result is normalised to.

### `WasteExchange`

An exchange of a waste flow with a treatment activity.
Expand All @@ -1541,6 +1648,15 @@ product input. Orphan waste (no linked treatment) contributes zero impact
| `is_biosphere` | `bool` | False |
| `is_waste` | `bool` | True |

#### Properties

##### `is_reference`

Always False — waste flows never define an activity's functional unit.

Treatment activities have a ``ReferenceInput`` instead, exposed
via :class:`TechnosphereExchange`.

## Functions

### `compare_activities(client: Client, pid_left: str, pid_right: str, *, scope: str = 'direct', group_by: str = 'flow_id', is_input: bool | None = True, **aggregate_kwargs) -> ActivityDiff`
Expand Down
51 changes: 30 additions & 21 deletions pyvolca/scripts/gen_api_md.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,16 @@ def _public_members(cls: type) -> tuple[list[tuple[str, str, str]], list[tuple[s
return methods, properties


def _render_properties(properties: list[tuple[str, str]], buf: io.StringIO) -> None:
"""Append the Properties section — shared by class and dataclass rendering."""
if not properties:
return
buf.write("#### Properties\n\n")
for name, doc in properties:
buf.write(f"##### `{name}`\n\n")
buf.write((doc or "_(no docstring)_") + "\n\n")


def render_class(cls: type, buf: io.StringIO) -> None:
"""Render a class with its public methods.

Expand All @@ -173,11 +183,7 @@ def render_class(cls: type, buf: io.StringIO) -> None:
except (TypeError, ValueError):
pass
methods, properties = _public_members(cls)
if properties:
buf.write("#### Properties\n\n")
for name, doc in properties:
buf.write(f"##### `{name}`\n\n")
buf.write((doc or "_(no docstring)_") + "\n\n")
_render_properties(properties, buf)
if methods:
buf.write("#### Methods\n\n")
for name, sig_str, doc in methods:
Expand All @@ -191,22 +197,25 @@ def render_dataclass(cls: type, buf: io.StringIO) -> None:
if doc and not _is_autogenerated_dataclass_doc(cls, doc):
buf.write(doc + "\n\n")
fields = dataclasses.fields(cls)
if not fields:
return
buf.write("| Field | Type | Default |\n")
buf.write("|-------|------|---------|\n")
for f in fields:
# Escape pipes in type annotations (e.g. `str | None`) so they don't
# break markdown table cells.
type_str = _format_type(f.type).replace("|", "\\|")
if f.default is not dataclasses.MISSING:
default = repr(f.default)
elif f.default_factory is not dataclasses.MISSING: # type: ignore[misc]
default = f"{f.default_factory.__name__}()" # type: ignore[union-attr]
else:
default = "—"
buf.write(f"| `{f.name}` | `{type_str}` | {default} |\n")
buf.write("\n")
if fields:
buf.write("| Field | Type | Default |\n")
buf.write("|-------|------|---------|\n")
for f in fields:
# Escape pipes in type annotations (e.g. `str | None`) so they don't
# break markdown table cells.
type_str = _format_type(f.type).replace("|", "\\|")
if f.default is not dataclasses.MISSING:
default = repr(f.default)
elif f.default_factory is not dataclasses.MISSING: # type: ignore[misc]
default = f"{f.default_factory.__name__}()" # type: ignore[union-attr]
else:
default = "—"
buf.write(f"| `{f.name}` | `{type_str}` | {default} |\n")
buf.write("\n")
# Dataclasses carry computed @property members too (e.g.
# ``ActivityDetail.allocation_percent``); the field table alone hides them.
_, properties = _public_members(cls)
_render_properties(properties, buf)


def render_function(fn: object, buf: io.StringIO) -> None:
Expand Down
Loading