Skip to content

pycopanlpjml compatibility#204

Open
jnnsbrr wants to merge 27 commits into
masterfrom
copanlpjml_docs
Open

pycopanlpjml compatibility#204
jnnsbrr wants to merge 27 commits into
masterfrom
copanlpjml_docs

Conversation

@jnnsbrr

@jnnsbrr jnnsbrr commented Feb 6, 2026

Copy link
Copy Markdown
Collaborator
  • add black and flake8 compatibility
  • add basic unit tests for data_model and model_components
  • add compatibility with pycopanlpjml region approach for inseeds

@codecov

codecov Bot commented Feb 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 60.68966% with 285 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (master@952ae16). Learn more about missing BASE report.

Files with missing lines Patch % Lines
pycopancore/runners/runner.py 0.00% 67 Missing ⚠️
pycopancore/model_components/base/model_logics.py 36.36% 35 Missing ⚠️
pycopancore/private/_trajectory_dictionary.py 0.00% 31 Missing ⚠️
pycopancore/private/_expressions.py 18.91% 30 Missing ⚠️
pycopancore/private/_mixin.py 42.85% 16 Missing ⚠️
pycopancore/data_model/variable.py 67.44% 14 Missing ⚠️
...model_components/base/implementation/individual.py 35.00% 13 Missing ⚠️
pycopancore/data_model/dimensional_quantity.py 36.84% 12 Missing ⚠️
...core/model_components/base/implementation/group.py 20.00% 12 Missing ⚠️
...ncore/model_components/base/implementation/cell.py 42.85% 8 Missing ⚠️
... and 15 more
Additional details and impacted files
@@            Coverage Diff            @@
##             master     #204   +/-   ##
=========================================
  Coverage          ?   53.55%           
=========================================
  Files             ?       74           
  Lines             ?     3262           
  Branches          ?        0           
=========================================
  Hits              ?     1747           
  Misses            ?     1515           
  Partials          ?        0           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR modernizes the repository’s Python tooling (Black/flake8/pytest + CI), reformats many modules and templates accordingly, and adds an initial pytest suite intended to validate core data_model and model_components behavior.

Changes:

  • Add pytest-based unit tests and a test configuration (tests/, pytest.ini, pyproject.toml).
  • Introduce Black + flake8 configuration and apply broad formatting/cleanup across code, templates, studies, and docs.
  • Add/adjust CI workflows for checks and releases, plus RTD + flake8 config files.

Reviewed changes

Copilot reviewed 112 out of 114 changed files in this pull request and generated 48 comments.

Show a summary per file
File Description
tests/test_working_functionality.py New “known working” smoke tests
tests/test_data_model.py New unit tests for data_model
tests/test_basic_functionality.py New basic import/functionality tests
tests/conftest.py New shared pytest fixtures
templates/studies/plot_trajectory.py Black/PEP8-style formatting
templates/studies/SOME_STUDY.py Black/PEP8-style formatting
templates/models/SOME_MODEL.py Template formatting cleanup
templates/model_components/SOME_COMPONENT/model.py Template import formatting + class decl cleanup
templates/model_components/SOME_COMPONENT/interface.py Template formatting + comment wrapping
templates/model_components/SOME_COMPONENT/implementation/world.py Template formatting cleanup
templates/model_components/SOME_COMPONENT/implementation/social_system.py Template formatting cleanup
templates/model_components/SOME_COMPONENT/implementation/metabolism.py Template formatting cleanup
templates/model_components/SOME_COMPONENT/implementation/individual.py Template formatting cleanup
templates/model_components/SOME_COMPONENT/implementation/environment.py Template formatting cleanup
templates/model_components/SOME_COMPONENT/implementation/culture.py Template formatting cleanup
templates/model_components/SOME_COMPONENT/implementation/cell.py Template formatting cleanup
templates/model_components/SOME_COMPONENT/implementation/init.py Template formatting cleanup
studies/seven_dwarfs/run_seven_dwarfs.py Formatting + minor style normalization
studies/esd_description_paper_example/run_esd_example.py Formatting + line wrapping
studies/esd_description_paper_example/plot_figure5.py Formatting + line wrapping
scripts/update_citation.py Removed release helper script
scripts/release.sh Removed release helper script
pytest.ini Simplified pytest configuration
pyproject.toml Add Black/flake8/pytest config + dev deps changes
pycopancore/util/seeding.py Formatting cleanup
pycopancore/util/functions.py Remove unused imports + formatting
pycopancore/util/init.py Formatting + safer exception handling
pycopancore/runners/hooks.py Formatting + minor robustness tweaks
pycopancore/runners/init.py Switch to docstring + add __all__
pycopancore/process_types/step.py Formatting cleanup
pycopancore/process_types/implicit.py Formatting cleanup
pycopancore/process_types/explicit.py Formatting cleanup
pycopancore/process_types/event.py Formatting cleanup
pycopancore/process_types/init.py Reorder imports + add __all__
pycopancore/process_types/ODE.py Formatting cleanup
pycopancore/private/_trajectory_dictionary.py Formatting + clearer imports
pycopancore/private/_mixin.py Change metaclass attribute handling + formatting
pycopancore/private/_abstract_runner.py Minor formatting
pycopancore/private/_abstract_process_taxon_mixin.py Formatting + clearer assertions
pycopancore/private/_abstract_process.py Minor formatting
pycopancore/private/_abstract_entity_mixin.py Formatting + quote normalization
pycopancore/private/init.py Replace empty docstring
pycopancore/models/seven_dwarfs.py Formatting + class declaration cleanup
pycopancore/models/base_only.py Minor formatting
pycopancore/models/_testing/generic_imitation/simple.py Formatting + config dict normalization
pycopancore/models/_testing/generic_imitation/other_component.py Formatting + class declaration cleanup
pycopancore/models/_testing/generic_imitation/like_example1.py Formatting + import normalization
pycopancore/model_components/seven_dwarfs/model.py Rename interface alias + import formatting
pycopancore/model_components/seven_dwarfs/interface.py Formatting + remove unused import
pycopancore/model_components/seven_dwarfs/implementation/world.py Formatting cleanup
pycopancore/model_components/seven_dwarfs/implementation/social_system.py Formatting + cleanup unused imports
pycopancore/model_components/seven_dwarfs/implementation/individual.py Formatting + cleanup unused imports
pycopancore/model_components/seven_dwarfs/implementation/group.py Formatting + rename interface alias
pycopancore/model_components/seven_dwarfs/implementation/culture.py Formatting cleanup
pycopancore/model_components/seven_dwarfs/implementation/cell.py Formatting + cleanup unused imports
pycopancore/model_components/seven_dwarfs/implementation/init.py Export ordering + add __all__
pycopancore/model_components/seven_dwarfs/init.py Formatting + add __all__
pycopancore/model_components/base/model.py Import normalization + interface aliasing
pycopancore/model_components/base/implementation/world.py Refactor imports + process list change
pycopancore/model_components/base/implementation/social_system.py Formatting + refactor variable names
pycopancore/model_components/base/implementation/metabolism.py Formatting + interface aliasing
pycopancore/model_components/base/implementation/individual.py Add network registration handling + formatting
pycopancore/model_components/base/implementation/group.py Add network registration handling + formatting
pycopancore/model_components/base/implementation/environment.py Formatting + import normalization
pycopancore/model_components/base/implementation/culture.py Formatting + import normalization
pycopancore/model_components/base/implementation/cell.py Remove/alter social_systems caching logic
pycopancore/model_components/base/implementation/init.py Export ordering + add __all__
pycopancore/model_components/base/init.py Wildcard export + add __all__
pycopancore/model_components/abstract/world.py Formatting + import normalization
pycopancore/model_components/abstract/social_system.py Formatting + import normalization
pycopancore/model_components/abstract/model.py Formatting cleanup
pycopancore/model_components/abstract/metabolism.py Formatting + import normalization
pycopancore/model_components/abstract/individual.py Formatting + import normalization
pycopancore/model_components/abstract/group.py Formatting + import normalization
pycopancore/model_components/abstract/environment.py Formatting + import normalization
pycopancore/model_components/abstract/culture.py Formatting + import normalization
pycopancore/model_components/abstract/cell.py Formatting + import normalization
pycopancore/model_components/abstract/init.py Export ordering + add __all__
pycopancore/data_model/unit.py Formatting + import normalization
pycopancore/data_model/set_variable.py Formatting + docstring wrapping
pycopancore/data_model/reference_variable.py Formatting + docstring wrapping
pycopancore/data_model/ordered_set.py Exception handling cleanup + formatting
pycopancore/data_model/master_data_model/world.py Formatting + import normalization
pycopancore/data_model/master_data_model/social_system.py Formatting + wrap Variable declarations
pycopancore/data_model/master_data_model/individual.py Formatting cleanup
pycopancore/data_model/master_data_model/group.py Formatting + comment cleanup
pycopancore/data_model/master_data_model/dimensions_and_units.py Formatting + wrap long docstrings
pycopancore/data_model/master_data_model/culture.py Formatting + wrap long Variable docs
pycopancore/data_model/master_data_model/cell.py Formatting + import normalization
pycopancore/data_model/master_data_model/init.py Rework exports of units/dimensions
pycopancore/data_model/dimensional_quantity.py Formatting + safer asserts
pycopancore/data_model/dimension.py Formatting + wrap long expressions
pycopancore/data_model/init.py Reformat module docstring + adjust exports
pycopancore/init.py Change fallback version + export base classes
docs/introduction.rst Update install/testing instructions
README.md Expand documentation + add badges/sections
CONTRIBUTING.md Rewrite contributor/release instructions
CITATION.cff Update version and release date
.readthedocs.yml Add Read the Docs configuration
.gitignore Ignore generated _version.py
.github/workflows/release.yml Add release workflow (build/test/lint/publish)
.github/workflows/check.yml Enable tests/black/flake8 in CI
.flake8 Add flake8 configuration file
Comments suppressed due to low confidence (5)

pycopancore/init.py:21

  • pycopancore.__init__ no longer exposes master_data_model, but repository scripts/templates import it via from pycopancore import master_data_model as D (e.g. studies/esd_description_paper_example/run_esd_example.py). Re-export pycopancore.data_model.master_data_model (or provide a pycopancore/master_data_model.py shim) to avoid breaking those entry points.
from pycopancore.model_components.base import (
    Individual,
    Group,
    SocialSystem,
    Cell,
    World,
    Environment,
    Metabolism,
    Culture,
)

templates/model_components/SOME_COMPONENT/implementation/cell.py:56

  • This comment appears to contain commented-out code.
    templates/model_components/SOME_COMPONENT/implementation/individual.py:57
  • This comment appears to contain commented-out code.
    templates/model_components/SOME_COMPONENT/implementation/social_system.py:57
  • This comment appears to contain commented-out code.
    templates/model_components/SOME_COMPONENT/implementation/world.py:57
  • This comment appears to contain commented-out code.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pyproject.toml
Comment on lines +63 to +66
[tool.black]
line-length = 79
target-version = ['py37', 'py38', 'py39', 'py310']
exclude = "pycopancore/_version.py"

Copilot AI Feb 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[tool.black].target-version includes py37/py38 even though requires-python is >=3.9. This can unnecessarily restrict formatting decisions and is confusing for contributors; consider setting it to only the supported versions (e.g. ['py39', 'py310', 'py311', 'py312']).

Copilot uses AI. Check for mistakes.
Comment thread tests/conftest.py
Comment on lines +60 to +73
from pycopancore.data_model import Unit, Dimension

dim = Dimension("length")
return Unit("m", "meter", dim)


@pytest.fixture
def sample_dimensional_quantity():
"""Create a sample DimensionalQuantity instance for testing."""
from pycopancore.data_model import DimensionalQuantity, Unit, Dimension

dim = Dimension("length")
unit = Unit("m", "meter", dim)
return DimensionalQuantity(5.0, unit)

Copilot AI Feb 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unit.__init__ makes parameters after desc keyword-only (* in signature), so Unit("m", "meter", dim) will raise TypeError. Pass dimension=dim (and similarly update the unit construction in sample_dimensional_quantity).

Copilot uses AI. Check for mistakes.
Comment on lines 237 to 246
@groups.setter
def groups(self, g):
"""Set the World the SocialSystem is part of."""
if self._groups is not None:
self._groups._social_system.remove(self)
assert isinstance(g, I.Culture), "groups must be of taxon type Group"
assert isinstance(
g, Interface.Culture
), "groups must be of taxon type Group"
g._worlds.add(self)
self._culture = g

Copilot AI Feb 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SocialSystem.groups setter is internally inconsistent: it asserts g is a Culture, mutates g._worlds, and assigns self._culture, even though this is the setter for groups. This will corrupt state when used. The setter should accept a collection of Group instances (or be removed if groups are managed elsewhere), and it must not write to _culture/_worlds.

Copilot uses AI. Check for mistakes.
if: steps.version.outputs.should_release == 'false'
run: |
echo "Skipping release - no version tag found"
exit 0

Copilot AI Feb 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The release workflow doesn’t actually stop when no version tag is detected: should_release is only ever set to false and the “Check if release should proceed” step exits 0 without preventing later steps (so the job continues and can attempt a PyPI upload with empty/incorrect outputs). Make the entire job (or all subsequent steps) conditional on a positive signal (e.g., trigger on push tags v*, or set should_release=true on success and add if: steps.version.outputs.should_release == 'true' to the rest / use a job-level if).

Suggested change
exit 0
exit 1

Copilot uses AI. Check for mistakes.
Comment thread CITATION.cff Outdated
title: 'pycopancore: Reference implementation of the copan:CORE World-Earth modelling framework'
version: 0.8.6
date-released: '2025-09-22'
version: 0.9.1

Copilot AI Feb 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Package version information is inconsistent across the repo: CITATION.cff is bumped to 0.9.1, but pycopancore.__init__ falls back to 0.8.3 and pyproject.toml’s hatch fallback_version is also 0.8.3. Align these so that a source checkout without VCS metadata reports the same version that you intend to release/cite.

Suggested change
version: 0.9.1
version: 0.8.3

Copilot uses AI. Check for mistakes.
sw.Model,
base.Model):

class Model(sd.Model, sw.Model, base.Model):

Copilot AI Feb 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Base classes have conflicting values for attribute 'requires': List and List.

Copilot uses AI. Check for mistakes.
class Cell(sd.Cell,
sw.Cell,
base.Cell):
class Cell(sd.Cell, sw.Cell, base.Cell):

Copilot AI Feb 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class does not call Cell.init during initialization. (The class lacks an init method to ensure every base class init is called.)

Copilot uses AI. Check for mistakes.
sw.Model,
base.Model):

class Model(sd.Model, sw.Model, base.Model):

Copilot AI Feb 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class does not call ModelLogics.init during initialization. (The class lacks an init method to ensure every base class init is called.)

Copilot uses AI. Check for mistakes.
# base[np.where((base == 0)*(exponent < 0))] = 1e-10
except:
# base[np.where((base == 0)*(exponent < 0))] = 1e-10
except Exception:

Copilot AI Feb 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This statement is unreachable.

Copilot uses AI. Check for mistakes.

# load data:
traj = load(open(filename,"rb"))
traj = load(open(filename, "rb"))

Copilot AI Feb 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File is opened but is not closed.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants