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
32 changes: 32 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: CI

on:
push:
branches:
- main
pull_request:
branches:
- main

permissions:
contents: read

jobs:
pre-commit:
name: Checks via pre-commit
runs-on: ubuntu-latest

steps:
- name: Check out repository
uses: actions/checkout@v7

- name: Install uv
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9
with:
enable-cache: true

- name: Install dependencies
run: uv sync --locked

- name: Run pre-commit
run: uv run pre-commit run --all-files
10 changes: 8 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ repos:
- id: end-of-file-fixer
- id: check-added-large-files

# Run tests, including doctests
# Project checks
- repo: local
hooks:
- id: copyright-header
Expand All @@ -22,11 +22,17 @@ repos:
types: [python]
always_run: true
pass_filenames: false
- id: mypy
name: mypy
entry: uv run mypy dcaf/
language: system
types: [python]
always_run: true
pass_filenames: false

# Linting and formatting
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.11.10
hooks:
- id: ruff-check
- id: ruff-format
args: [ --check ]
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2026 Battelle Energy Alliance, LLC
Copyright (c) 2026 Battelle Energy Alliance, LLC

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
8 changes: 7 additions & 1 deletion dcaf/finance/opex.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@
from datetime import date

from dcaf.finance.escalation import EscalationPolicy
from dcaf.shared.types import DayCountConvention, Period, ProFormaCategory, TaxTreatment, TimingConvention
from dcaf.shared.types import (
DayCountConvention,
Period,
ProFormaCategory,
TaxTreatment,
TimingConvention,
)
from dcaf.shared.validation import validate_finite
from dcaf.streams.cashflows import CashFlowStream

Expand Down
2 changes: 2 additions & 0 deletions dcaf/project/contracts.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# © 2026 Battelle Energy Alliance, LLC
# ALL RIGHTS RESERVED
"""Generation-linked contract terms for project-level revenue policies."""

from __future__ import annotations
Expand Down
2 changes: 2 additions & 0 deletions dcaf/project/policies.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# © 2026 Battelle Energy Alliance, LLC
# ALL RIGHTS RESERVED
"""Public protocol for generation-linked project cash-flow policies."""

from __future__ import annotations
Expand Down
3 changes: 1 addition & 2 deletions tests/unit/test_cashflow_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,7 @@ def test_from_recurring_annual_escalation_is_date_based():
)
expected_dates = [date(2026, 4, 4), date(2026, 5, 4), date(2026, 6, 4)]
expected_amounts = [
-200.0 * _annual_factor(date(2026, 3, 5), flow_date, 0.1)
for flow_date in expected_dates
-200.0 * _annual_factor(date(2026, 3, 5), flow_date, 0.1) for flow_date in expected_dates
]
for i, flow in enumerate(cf_stream.entries):
assert flow.date == expected_dates[i]
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ def test_from_capacity_rejects_capacity_factor_outside_unit_interval(capacity_fa
periods=1,
)


def test_from_capacity_supports_timing_conventions():
begin = GenerationStream.from_capacity(1.0, 1.0, date(2030, 1, 1), 1, timing="begin")
middle = GenerationStream.from_capacity(1.0, 1.0, date(2030, 1, 1), 1, timing="middle")
Expand Down
6 changes: 5 additions & 1 deletion tests/unit/test_generation_linked_policies.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# © 2026 Battelle Energy Alliance, LLC
# ALL RIGHTS RESERVED
from datetime import date
from math import inf, nan
from typing import cast
Expand Down Expand Up @@ -279,7 +281,9 @@ def test_generation_revenue_callable_receives_whole_project_settlement_context()
events: list[GenerationSettlementEvent] = []

def price(event: GenerationSettlementEvent) -> float:
events.append(event) # creates an external artifact that the `price` function was called for every generation event
events.append(
event
) # creates an external artifact that the `price` function was called for every generation event
return prices[event.date]

analysis = (
Expand Down