-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add python implementation. Add python packaging. Add github workflows. TODO: Finalise the package naming ~ this is only going to test pypi at the moment, but is otherwise complete
- Loading branch information
Showing
18 changed files
with
866 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
name: Python 🐍 Build, Release, and Publish 📦 to PyPI and TestPyPI | ||
on: | ||
push: | ||
branches: | ||
- 'main' | ||
paths: | ||
- 'python/src/collatz/__version__.py' | ||
workflow_dispatch: # manual, rather than tag triggering | ||
jobs: | ||
build-n-publish: | ||
name: Build, Release, and publish Python 🐍 distributions 📦 to PyPI and TestPyPI | ||
runs-on: ubuntu-latest | ||
defaults: | ||
run: | ||
shell: bash | ||
working-directory: python | ||
steps: | ||
- name: 🏁 Checkout | ||
uses: actions/checkout@v3 | ||
- name: 🐍 Set up Python | ||
uses: actions/setup-python@v3 | ||
with: | ||
python-version: '3.10' | ||
- name: 🧱 Install build dependencies | ||
run: | | ||
make venv | ||
- name: 🎡 Build wheel and source | ||
run: | | ||
make build | ||
- name: 🦏 Release | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
run: >- | ||
export VER=$(cut -d \" -f 2 src/collatz/__version__.py) && | ||
gh release create | ||
python-v$VER | ||
"$(find dist | grep \\-none\\-any\\.whl)#Wheel" | ||
"$(find dist | grep \\.tar\\.gz)#Tarball" | ||
--generate-notes | ||
-t "Python: Version $VER" | ||
- name: 📦 Publish distribution to Test PyPI | ||
uses: pypa/gh-action-pypi-publish@master | ||
with: | ||
password: ${{ secrets.TEST_PYPI_API_TOKEN }} | ||
repository_url: https://test.pypi.org/legacy/ | ||
- name: 📦 Publish distribution to PyPI | ||
if: startsWith(github.ref, 'refs/tags') | ||
uses: pypa/gh-action-pypi-publish@master | ||
with: | ||
password: ${{ secrets.PYPI_API_TOKEN }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
name: Python 🐍 Tox 🦂 Pytest | ||
on: | ||
push: | ||
paths: | ||
- 'python/**' | ||
- '.github/workflows/python-*' | ||
pull_request: | ||
types: [opened, reopened] | ||
branches: | ||
- 'main' | ||
paths: | ||
- 'python/**' | ||
- '.github/workflows/python-*' | ||
jobs: | ||
tox-pytest: | ||
runs-on: '${{ matrix.os }}' | ||
defaults: | ||
run: | ||
working-directory: python | ||
strategy: | ||
matrix: | ||
python-version: ['3.6', '3.7', '3.8', '3.9', '3.10'] | ||
os: [ubuntu-latest, macOS-latest, windows-latest] | ||
steps: | ||
- name: 🏁 Checkout | ||
uses: actions/checkout@v3 | ||
- name: 🐍 Set up Python ${{ matrix.python-version }} | ||
uses: actions/setup-python@v3 | ||
with: | ||
python-version: ${{ matrix.python-version }} | ||
- name: 🍑 Install dependencies | ||
run: | | ||
python -m pip install --upgrade pip | ||
python -m pip install tox tox-gh-actions | ||
- name: 🦂 Test with tox | ||
run: tox |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[distutils] | ||
index-servers = | ||
pypi | ||
testpypi | ||
|
||
[pypi] | ||
username = __token__ | ||
password = <pypi-token> | ||
|
||
[testpypi] | ||
username = __token__ | ||
password = <test-pypi-token> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
graft tests | ||
global-exclude *.py[cod] | ||
prune */__pycache__/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# Virtual Environment | ||
VE=source .ve/bin/activate && | ||
.PHONY: venv clean clean_again test build upload_test upload | ||
SHELL:=/bin/bash | ||
|
||
# https://code.visualstudio.com/docs/python/environments | ||
# https://docs.python.org/3/library/venv.html < for pwsh execution policy. | ||
# Will need to `python -m venv .ve` from pwsh separately to create the | ||
# ~/.ve/Scripts/python.exe if this Makefile is run from WSL, which doesn't | ||
# populate the ~/.ve/Scripts folder, but is needed to run the venv as the | ||
# interpreter by an IDE on windows. Make sure to create it at a different | ||
# place to the .ve in ~/python/ as the venv is mutually exclusive between them. | ||
# Despite being in a venv pip install --upgrade pip still needs admin on windows | ||
venv: | ||
python3 -m venv .ve | ||
$(VE) pip install --upgrade pip | ||
$(VE) pip install --upgrade -r requirements-venv.txt | ||
|
||
clean clean_again: | ||
rm -rf src/*.egg-info/ | ||
rm -rf dist/ | ||
rm -rf */__pycache__/ | ||
rm -rf */*/__pycache__/ | ||
rm -rf .pytest_cache/ | ||
|
||
test: clean | ||
$(VE) pytest | ||
|
||
# build will automatically include an adjacent "LICENSE*" ~ but if it's | ||
# referenced as ../LICENSE in either manifest or [metadate]license_files then | ||
# it will result in being added outside the built wheel? So just shuffle it | ||
# around here and remove it after to always use the top level one. | ||
build: test clean_again | ||
cp ../LICENSE LICENSE | ||
$(VE) python3 -m build | ||
rm LICENSE | ||
$(VE) pip install --force-reinstall dist/*-none-any.whl | ||
|
||
# https://twine.readthedocs.io/en/stable/#twine-upload | ||
upload_test: build | ||
$(VE) twine upload --config-file ./.pypirc --repository testpypi dist/* | ||
|
||
upload: upload_test | ||
$(VE) twine upload --config-file ./.pypirc --repository pypi dist/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,93 @@ | ||
# Collatz: Python | ||
Functions related to the Collatz/Syracuse/3N+1 problem, implemented in Python | ||
## Package | ||
The [default Python package index](https://pypi.org/) ~ [search results for collatz](https://pypi.org/project/collatz/) (which appears to already be in unique use on PyPi) | ||
# [Collatz](https://github.com/Skenvy/Collatz): [Python](https://github.com/Skenvy/Collatz/tree/main/python) | ||
Functions related to [the Collatz/Syracuse/3N+1 problem](https://en.wikipedia.org/wiki/Collatz_conjecture), implemented in Python. | ||
## Getting Started | ||
To [install the latest](https://test.pypi.org/project/collatz-skenvy/); | ||
``` | ||
pip install -i https://test.pypi.org/simple/ collatz-skenvy | ||
``` | ||
### Developing | ||
#### The first time virtual env | ||
``` | ||
git clone https://github.com/Skenvy/Collatz.git | ||
cd Collatz/python | ||
make venv | ||
``` | ||
#### Iterative development | ||
`make build` will test and build the wheel and force reinstall it into the local venv, to test the built distribution | ||
## Usage | ||
Provides the basic functionality to interact with the Collatz conjecture. | ||
The parameterisation uses the same `(P,a,b)` notation as Conway's generalisations. | ||
Besides the function and reverse function, there is also functionality to retrieve the hailstone sequence, the "stopping time"/"total stopping time", or tree-graph. | ||
The only restriction placed on parameters is that both `P` and `a` can't be `0`. | ||
### collatz.function(~) | ||
`(n:int, P:int=2, a:int=3, b:int=1)` | ||
``` | ||
>>> import collatz | ||
>>> # The default "Collatz function" | ||
>>> collatz.function(5) | ||
16 | ||
>>> # Alternatively, you can parameterise the function. | ||
>>> collatz.function(5, P=7, a=5, b=17) | ||
42 | ||
``` | ||
### collatz.reverse_function(~) | ||
`(n:int, P:int=2, a:int=3, b:int=1)` | ||
``` | ||
>>> import collatz | ||
>>> # Get the list of values that return the input. | ||
>>> collatz.reverse_function(4) | ||
[1, 8] | ||
>>> # Alternatively, you can parameterise the reverse_function. | ||
>>> collatz.reverse_function(5, P=5, a=2, b=3) | ||
[1, 25] | ||
``` | ||
### collatz.hailstone_sequence(~) | ||
`(initial_value:int, P:int=2, a:int=3, b:int=1, max_total_stopping_time:int=1000, total_stopping_time:bool=True, verbose:bool=True)` | ||
``` | ||
>>> import collatz | ||
>>> # Get the sequence of values forming the hailstone from an initial value | ||
>>> collatz.hailstone_sequence(10) | ||
[10, 5, 16, 8, 4, 2, 1, ['TOTAL_STOPPING_TIME', 6]] | ||
>>> # Determines if it's in a cycle | ||
>>> collatz.hailstone_sequence(-56) | ||
[-56, -28, 'CYCLE_INIT', [-14, -7, -20, -10, -5], ['CYCLE_LENGTH', 5]] | ||
>>> # The verbose messages can be muted, although this might leave a sense of ambiguity for larger lists. | ||
>>> collatz.hailstone_sequence(-200, verbose=False) | ||
[-200, -100, -50, -25, -74, -37, -110, -55, -164, -82, -41, -122, -61, -182, -91, -272, -136, -68, -34, -17, -50] | ||
>>> # Although hailstones typically go to the "total stop" of 1, they can be set to terminate on the regular stop | ||
>>> collatz.hailstone_sequence(5, total_stopping_time=False) | ||
[5, 16, 8, 4, ['STOPPING_TIME', 3]] | ||
``` | ||
### collatz.stopping_time(~) | ||
`(initial_value:int, P:int=2, a:int=3, b:int=1, max_stopping_time:int=1000, total_stopping_time:bool=False)` | ||
``` | ||
>>> import collatz | ||
>>> # Reports the stopping time, the amount of iterations of the function to reach a value lower than the initial value. | ||
>>> collatz.stopping_time(5) | ||
3 | ||
>>> # Can be used to find the "total stopping time" as well, the amount of iterations to reach "1" | ||
>>> collatz.stopping_time(5, total_stopping_time=True) | ||
5 | ||
>>> # Although most cylces have a stopping time, by targetting the total stopping time, you can see if a value leads into a cycle by the 'inf' return | ||
>>> collatz.stopping_time(-17, total_stopping_time=True) | ||
inf | ||
>>> # Some cycles are small enough that starting on the lowest absolute value will still identify a cycle. | ||
>>> collatz.stopping_time(-1) | ||
inf | ||
>>> # If it overruns maximum stopping time, returns nothing. | ||
>>> collatz.stopping_time(5, max_stopping_time=-1) | ||
>>> # <None> | ||
``` | ||
### collatz.tree_graph(~) | ||
`(initial_value:int, max_orbit_distance:int, P:int=2, a:int=3, b:int=1)` | ||
``` | ||
>>> import collatz | ||
>>> # See the tree graph built by a reverse function traversal, to the depth specified by max_orbit_distance. | ||
>>> collatz.tree_graph(1, 3) | ||
{1: {2: {4: {'CYCLE_INIT': 1, 8: {}}}}} | ||
>>> collatz.tree_graph(1, 12) | ||
{1: {2: {4: {'CYCLE_INIT': 1, 8: {16: {5: {10: {3: {6: {12: {24: {48: {96: {}}}}}}, 20: {40: {13: {26: {52: {17: {}, 104: {}}}}, 80: {160: {53: {106: {}}, 320: {640: {}}}}}}}}, 32: {64: {21: {42: {84: {168: {336: {672: {}}}}}}, 128: {256: {85: {170: {340: {113: {}, 680: {}}}}, 512: {1024: {341: {682: {}}, 2048: {4096: {}}}}}}}}}}}}}} | ||
>>> # Can also be parameterised; | ||
>>> collatz.tree_graph(1, 2, P=5, a=2, b=3) | ||
{1: {-1: {-5: {}, -2: {}}, 5: {'CYCLE_INIT': 1, 25: {}}}} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,6 @@ | ||
# Devlog | ||
At the moment, a [python package already exists on pypi](https://pypi.org/project/collatz/), owned by [NGeorgescu](https://github.com/NGeorgescu/collatz), and there appear to be more recent uploads with more squashed names, such as {[simple-collatz](https://pypi.org/project/simple-collatz/)|[collatzconj](https://pypi.org/project/collatzconj/)|[lychrel](https://pypi.org/project/lychrel/)}. | ||
|
||
We can follow the [pypi packaging doc](https://packaging.python.org/en/latest/tutorials/packaging-projects/) for the recommended steps to start setting up, although it looks like the '~/src' directory is a new recommendation, which seems to have a non inconsequential effect on imports, and the current tutorial on python.org appears to have no follow up to default testing recommendations besides "make a test folder for later..", although `from src import <thing>` works fine. | ||
|
||
Because the overall project layout doesn't include the license in the python folder from which the build is run, might need to look into using [the manifest file](https://packaging.python.org/en/latest/guides/using-manifest-in/) to add it. Once we've [set up testing with pytest](https://docs.pytest.org/en/7.1.x/getting-started.html#get-started), will have a look at [the recommended github actions](https://packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/). Also worth double checking [the actual recommendation on aligning the readme with pypi's expectations for it](https://packaging.python.org/en/latest/guides/making-a-pypi-friendly-readme/). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
[build-system] | ||
requires = [ | ||
"setuptools>=42", | ||
"wheel" | ||
] | ||
build-backend = "setuptools.build_meta" | ||
[tool.pytest.ini_options] | ||
addopts = "-r a -v" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# https://packaging.python.org/en/latest/guides/making-a-pypi-friendly-readme/ | ||
|
||
# The version of build should be major version locked but minor version | ||
# permissive. The most recent verified working for `make build` is 0.7.0 | ||
build>=0.7.0,<1 | ||
# Twine in general, for uploading to pypi, with minimum version lock by the PyPi | ||
# friendly README doc above, although the current tip used is 3.8.0 | ||
twine>=1.11.0 | ||
# pytest breaks heavily between minor versions, so only allow patch drift. | ||
pytest>=7.1.0,<7.2 | ||
# Allow patch drift for tox as well. | ||
tox>=3.24.5,<3.25 | ||
# Other version mins specd by the PyPi friendly README doc. | ||
setuptools>=38.6.0 | ||
wheel>=0.31.0 |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
[metadata] | ||
name = collatz-skenvy | ||
author = Skenvy | ||
author_email = [email protected] | ||
description = Enabling experimenting with functions related to or involved in the Collatz conjecture. | ||
long_description = file: README.md | ||
long_description_content_type = text/markdown | ||
url = https://github.com/Skenvy/Collatz | ||
project_urls = | ||
Bug Tracker = https://github.com/Skenvy/Collatz/issues | ||
classifiers = | ||
Programming Language :: Python :: 3 | ||
License :: OSI Approved :: Apache Software License | ||
Operating System :: OS Independent | ||
|
||
[options] | ||
package_dir = | ||
= src | ||
packages = find: | ||
python_requires = >=3.6 | ||
|
||
[options.packages.find] | ||
where = src |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import setuptools | ||
# Because this is run via "build" and not "setup with args" it needs 'here' | ||
# added to the path manually to be able to find 'src' | ||
import sys, os | ||
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '.')) | ||
from src.collatz import __version__ | ||
|
||
|
||
setuptools.setup( | ||
version=__version__, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from .__version__ import __version__ | ||
from .parameterised import * | ||
from .parameterised import _ErrMsg | ||
from .parameterised import _CC | ||
from .parameterised import _KNOWN_CYCLES |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
__version__ = "0.1.2" |
Oops, something went wrong.