Skip to content

Commit

Permalink
Post 1.2.1 release (#77)
Browse files Browse the repository at this point in the history
* improve 3d visualisation
* update base model init
* add version bump + publish to CI
* refactor model to use trampoline dispatch
* Bump requests from 2.28.2 to 2.31.0 in /examples
* custom timelines
* doc updates
* add docker release
* make seeder optional
  • Loading branch information
virgesmith authored May 29, 2023
1 parent e2afc44 commit 2d09162
Show file tree
Hide file tree
Showing 86 changed files with 853 additions and 721 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: PyPI
name: Build and test

on:
push:
branches: [ main ]
tags: '**'
pull_request:
branches: [ main ]
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

name: Python coverage
name: Code coverage

on:
push:
Expand Down
59 changes: 59 additions & 0 deletions .github/workflows/pypi-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: PyPI release

on:
push:
branches: main

jobs:
bump-version:
name: Bump package version
if: "!contains(github.event.head_commit.message, 'Bump version')"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
persist-credentials: false
- name: current_version
run: echo "current_version=$(grep __version__ neworder/__init__.py | cut -d ' ' -d'"' -f2)" >> $GITHUB_ENV
- name: bump2version-action
uses: FragileTech/[email protected]
with:
current_version: "${{ env.current_version }}"
files: neworder/__init__.py
commit_name: Version autobump
commit_email: [email protected]
login: virgesmith
token: "${{ secrets.REPO_PAT }}"
# part defaults to patch
part: minor
- name: Create dist
run: |
pip install pybind11 numpy
python setup.py sdist
- name: Publish
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
repository-url: https://upload.pypi.org/legacy/
- name: new_version
run: echo "new_version=$(grep __version__ neworder/__init__.py | cut -d ' ' -d'"' -f2)" >> $GITHUB_ENV

- name: Log in to Docker Hub
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PAT }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Build and push Docker images
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
with:
context: .
file: ./Dockerfile
push: true
tags: |
${{ secrets.DOCKER_USER }}/neworder:${{ env.new_version }}
${{ secrets.DOCKER_USER }}/neworder:latest
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ examples/people_multi/data
*.egg-info/
junk
dist/*
stubs/

test-coverage/
.env
# osmnx cache
cache/
cache/

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
[![DOI](https://zenodo.org/badge/111997710.svg)](https://zenodo.org/badge/latestdoi/111997710)
[![status](https://joss.theoj.org/papers/4b7cc8402819ff48fc7403c0e9a265e9/status.svg)](https://joss.theoj.org/papers/4b7cc8402819ff48fc7403c0e9a265e9)

[![PyPI build](https://github.com/virgesmith/neworder/actions/workflows/pip-package.yml/badge.svg)]()
[![Conda build](https://github.com/virgesmith/neworder/actions/workflows/conda.yml/badge.svg)](https://github.com/virgesmith/neworder/actions/workflows/conda.yml)
[![Build and test](https://github.com/virgesmith/neworder/actions/workflows/build-test.yml/badge.svg)](https://github.com/virgesmith/neworder/actions/workflows/build-test.yml)
[![Conda](https://github.com/virgesmith/neworder/actions/workflows/conda.yml/badge.svg)](https://github.com/virgesmith/neworder/actions/workflows/conda.yml)
[![codecov](https://codecov.io/gh/virgesmith/neworder/branch/main/graph/badge.svg?token=g5mDOcjGTD)](https://codecov.io/gh/virgesmith/neworder)
[![Documentation Status](https://readthedocs.org/projects/neworder/badge/?version=latest)](https://neworder.readthedocs.io/en/latest/?badge=latest)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/2f3d4cbf0d174b07b527c64b700db77f)](https://www.codacy.com/app/virgesmith/neworder?utm_source=github.com&utm_medium=referral&utm_content=virgesmith/neworder&utm_campaign=Badge_Grade)
Expand Down
9 changes: 9 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
coverage:
status:
project:
default:
target: 90%
threshold: 1% # leeway
patch:
default:
target: 80%
46 changes: 46 additions & 0 deletions docs/custom_timeline.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import neworder


class AsymptoticTimeline(neworder.Timeline):
def __init__(self) -> None:
super().__init__()
self.t = 1.0

@property
def start(self) -> float:
return 0.0

@property
def end(self) -> float:
return 1.0

@property
def nsteps(self) -> int:
return -1

@property
def time(self) -> float:
return 1.0 - self.t

@property
def dt(self) -> float:
return self.t / 2

def _next(self) -> None:
self.t /= 2

@property
def at_end(self) -> bool:
return False


class Model(neworder.Model):
def __init__(self) -> None:
super().__init__(AsymptoticTimeline())

def step(self) -> None:
neworder.log(f"{self.timeline.index}: {self.timeline.time}")
if self.timeline.time > 0.99:
self.halt()

neworder.run(Model())
41 changes: 28 additions & 13 deletions docs/developer.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,21 +136,36 @@ The C++ module needs to be built with instrumentation (the `--coverage` flag) an

The script from [codecov.io](https://codecov.io/gh/virgesmith/neworder/) uses `gcov` to process the output and upload it. NB it's important to ensure that the `gcc` and `gcov` versions are consistent otherwise it will crash (the ubuntu 20.04 appveyor image defaults to gcc-7 and gcov-9).

## Generating type stubs

Type stubs can be generated for the C++ module using `pybind11-stubgen`, although manual modifications are needed for the output (e.g. docstrings for overloaded functions are misplaced, numpy types need to be fixed).

```sh
pybind11-stubgen _neworder_core
```

It may also be necessary to regenerate type stubs for the submodules, e.g.

```sh
pybind11-stubgen _neworder_core.time
mv stubs/_neworder_core/time-stubs/__init__.pyi neworder/time.pyi
```

## Release Checklist

Merge branches/PRs into **main** and fix any CI issues (builds, tests, major code standards) before commencing.
Development should happen on a release branch (NOT on main). Any commit to main triggers a workflow that automatically bumps the version, tags the code, builds a package, publishes it to PyPI, then builds a docker image containing the examples and pushes this to docker hub.

If necessary, use `test.pypi.org` to upload a release candidate, which can then be installed to a model implementation for testing "in the wild".
!!! warning "Automatic version bumping"
By default the patch version is bumped but this can be changed to minor or major as necessary in `.github/workflows/pypi-release.yml`. Once a specific version has been published, it cannot be modified (only deleted), so if in doubt modify the action to publish a release candidate to `test.pypi.org`.

1. Create some release notes based on commit comments since previous release, e.g.: `git log 0.2.1..HEAD --oneline`
2. Bump `__version__` in `neworder/__init__.py`
3. Clean, rebuild, test, regenerate examples and code docs: `scripts/code_doc.sh`
4. Commit changes
5. Tag, e.g.: `git tag -a 0.3.0 -m"release v0.3.0"`
6. Push, including tag e.g.: `git push --atomic origin main 0.3.0`
7. Check tagged CI builds and docker image are ok
8. Package and upload to PyPI: `scripts/package.sh`
9. Update and check conda feedstock (if this doesn't happen automatically, see instructions [here](https://github.com/conda-forge/neworder-feedstock))
10. Install pypi/conda-forge/docker releases in a fresh environment and ensure all is well. If not, fix and go back to 2.
11. Create release on github, using the tag and the release notes from above
12. Check zenodo for new DOI and ensure documentation references it.
1. Regenerate type stubs (see above) as necessary
1. Clean, rebuild, run tests, check type annotations.
1. Commit changes to release branch
1. Ensure all checks passing and merge to `main`
1. Update and/or check:
- conda feedstock (if this doesn't happen automatically, see instructions [here](https://github.com/conda-forge/neworder-feedstock))
- docker image
1. Install pypi/conda-forge/docker releases in a fresh environment and ensure all is well. If not, fix in a patch release.
1. Create release on github, using the tag and the release notes from above
1. Check zenodo for new DOI and ensure documentation references it.
12 changes: 6 additions & 6 deletions docs/examples/hello-world.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,33 +30,33 @@ The input data for this model are just:

Firstly we create our model class, subclassing `neworder.Model`:

{{ include_snippet("./examples/hello-world/model.py", "class") }}
{{ include_snippet("./examples/hello_world/model.py", "class") }}

and provide a constructor that initialises the base class and a DataFrame containing the population:

{{ include_snippet("./examples/hello-world/model.py", "constructor") }}
{{ include_snippet("./examples/hello_world/model.py", "constructor") }}

!!! note "Unique Indexing"
The `neworder.df.unique_index()` provides a mechanism to guarantee unique indices for DataFrames, even for parallel runs. This allows individuals to be exchanged and tracked between processes without conflicting indices.

The `step` method randomly samples new values for the "talkative" attribute, using the `neworder.MonteCarlo.hazard` method

{{ include_snippet("./examples/hello-world/model.py", "step") }}
{{ include_snippet("./examples/hello_world/model.py", "step") }}

and at the end of the timeline the `finalise` method prints greetings from the talkative individuals using the `neworder.log` function, which is preferred to plain `print` statements as the output is annotated with useful context for debugging.

{{ include_snippet("./examples/hello-world/model.py", "finalise") }}
{{ include_snippet("./examples/hello_world/model.py", "finalise") }}

## Execution

The model is run by simply constructing an instance of our model and passing it to the `run` method:

{{ include_snippet("./examples/hello-world/model.py", "script") }}
{{ include_snippet("./examples/hello_world/model.py", "script") }}

From the command line, run the model:

```bash
python examples/hello-world/model.py
python examples/hello_world/model.py
```

which should result in something like
Expand Down
4 changes: 2 additions & 2 deletions docs/examples/markov-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ The model takes about 45s to run (depending on platform). Changing `MarkovChain.

## Input

{{ include_snippet("./examples/markov-chain/model.py") }}
{{ include_snippet("./examples/markov_chain/model.py") }}

## Implementation

{{ include_snippet("./examples/markov-chain/markov_chain.py") }}
{{ include_snippet("./examples/markov_chain/markov_chain.py") }}

## Output

Expand Down
21 changes: 0 additions & 21 deletions docs/examples/n-body.md

This file was deleted.

Binary file removed docs/examples/neworder-1.1.0-examples-src.tgz
Binary file not shown.
Binary file removed docs/examples/neworder-1.1.0-examples-src.zip
Binary file not shown.
Binary file removed docs/examples/neworder-1.1.1-examples-src.tgz
Binary file not shown.
Binary file removed docs/examples/neworder-1.1.1-examples-src.zip
Binary file not shown.
Binary file removed docs/examples/neworder-1.2.0-examples-src.tgz
Binary file not shown.
Binary file removed docs/examples/neworder-1.2.0-examples-src.zip
Binary file not shown.
Binary file removed docs/examples/neworder-1.2.1-examples-src.tgz
Binary file not shown.
Binary file removed docs/examples/neworder-1.2.1-examples-src.zip
Binary file not shown.
11 changes: 4 additions & 7 deletions docs/examples/src.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
!!! note "Examples Source Code"
Source code for all the examples can be downloaded using one of the the links below:
The code for all the examples can be obtained by either:

**[neworder-1.2.1-examples-src.tgz](./neworder-1.2.1-examples-src.tgz)** | **[neworder-1.2.1-examples-src.zip](./neworder-1.2.1-examples-src.zip)**
- pulling the docker image `virgesmith/neworder:latest` (more [here](/#docker)), or
- downloading the source code from the `neworder` [releases](https://github.com/virgesmith/neworder/releases) page

The contained file `requirements.txt` lists the package dependencies of the examples, which can be installed using e.g.:

```sh
pip install -r requirements.txt
```
If using the latter option, navigate to the `examples` subdirectory in the archive and install the dependencies required for the examples: `pip install -r requirements.txt`
10 changes: 0 additions & 10 deletions docs/examples/src.md_template

This file was deleted.

4 changes: 2 additions & 2 deletions docs/examples/wolf-sheep.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ An extension to the original model adds natural selection: new agents inherit th

Here's the implementation:

{{ include_snippet("./examples/wolf-sheep/wolf_sheep.py") }}
{{ include_snippet("./examples/wolf_sheep/wolf_sheep.py") }}

Which is run like so:

{{ include_snippet("./examples/wolf-sheep/model.py") }}
{{ include_snippet("./examples/wolf_sheep/model.py") }}

## Outputs

Expand Down
Loading

0 comments on commit 2d09162

Please sign in to comment.