Skip to content

Commit

Permalink
Merge pull request #36 from MathiasStokholm/release/0.2.0
Browse files Browse the repository at this point in the history
Release 0.2.0
  • Loading branch information
MathiasStokholm authored Apr 11, 2023
2 parents d17fd52 + 95f0b0f commit a0a6392
Show file tree
Hide file tree
Showing 12 changed files with 37 additions and 22 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- ubuntu-20.04
- macos-latest
- windows-latest
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10.0"]
python-version: ["3.7", "3.8", "3.9", "3.10.0", "3.11.2"]
runs-on: ${{ matrix.os }}

steps:
Expand All @@ -32,13 +32,13 @@ jobs:
pip install -r dev-requirements.txt
- name: Lint with flake8
run: |
python labfile.py brew lint
python labfile.py brew --progress=none lint
- name: Test with pytest and generate coverage
run: |
python labfile.py brew coverage
python labfile.py brew --progress=none coverage
- name: Type check with mypy
run: |
python labfile.py brew type_check
python labfile.py brew --progress=none type_check
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
with:
Expand Down
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,28 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.2.0] - 2023-04-10
### Added
- Added `rich` as a runtime dependency
- Added fancy progress output mode that shows a summary of the execution at the bottom of the console using [Rich](https://rich.readthedocs.io/).
- Added support for Python 3.11

### Changed
- Rewrote parallel execution to only run bound functions in parallel, but use asyncio for the main execution logic
- Bumped `mypy` version to `1.2.0` (only used for development)
- Bumped `coverage` version to `6.4.2` (only used for development)

### Fixed
- Fixed a bug where a deadlock could occur when evaluating a number of `ForeachRecipes` with the same number of jobs
- Fixed a bug where a certain graph configuration could prevent parallelization from happening correctly
- Fixed a regression where all cached recipe outputs would always be loaded during execution, regardless of whether they
were needed to produce the requested output.

### Removed
- Dropped support for Python 3.6


## [0.1.0] - 2023-03-07
### Added
- Added `networkx` as a runtime dependency
Expand Down Expand Up @@ -168,7 +177,8 @@ from cache
### Added
- Initial release

[Unreleased]: https://github.com/MathiasStokholm/alkymi/compare/v0.1.0...HEAD
[Unreleased]: https://github.com/MathiasStokholm/alkymi/compare/v0.2.0...HEAD
[0.1.0]: https://github.com/MathiasStokholm/alkymi/compare/v0.1.0...v0.2.0
[0.1.0]: https://github.com/MathiasStokholm/alkymi/compare/v0.0.7...v0.1.0
[0.0.7]: https://github.com/MathiasStokholm/alkymi/compare/v0.0.6...v0.0.7
[0.0.6]: https://github.com/MathiasStokholm/alkymi/compare/v0.0.5...v0.0.6
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
[![pypi](https://img.shields.io/pypi/v/alkymi.svg)](https://pypi.org/project/alkymi)
[![versions](https://img.shields.io/pypi/pyversions/alkymi.svg)](https://pypi.org/project/alkymi)

Alkymi is a pure Python (3.6+) library for describing and executing tasks and pipelines with built-in caching and
Alkymi is a pure Python (3.7+) library for describing and executing tasks and pipelines with built-in caching and
conditional evaluation based on checksums.

Alkymi is easy to install, simple to use, and has very few dependencies outside of Python's standard library. The code
Expand Down
8 changes: 5 additions & 3 deletions alkymi/lab.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,14 @@ def register_arg(self, arg: Arg) -> None:
self._args[arg.name] = arg

def brew(self, target_recipe: Union[Recipe, str], *, jobs=1,
progress_type: ProgressType = ProgressType.Fancy) -> Any:
progress_type: Optional[ProgressType] = ProgressType.Fancy) -> Any:
"""
Brew (evaluate) a target recipe defined by its reference or name, and return the results
:param target_recipe: The recipe to evaluate, as a reference ot by name
:param jobs: The number of jobs to use for evaluating this recipe in parallel, defaults to 1 (no parallelism),
zero or negative values will cause alkymi to use the system's default number of jobs
:param progress_type: The method to use for showing progress
:param progress_type: The method to use for showing progress, if None will default to setting in alkymi's config
:return: The output of the evaluated recipe
"""

Expand Down Expand Up @@ -198,6 +198,8 @@ def open(self, args: Optional[List[str]] = None, stream: TextIO = sys.stdout) ->
help='Recipe(s) to brew')
brew_parser.add_argument("-j", "--jobs", type=int, default=1,
help="Use N jobs to evaluate the recipe, more than 1 job will parallelize evaluation")
brew_parser.add_argument("--progress", type=ProgressType, default=ProgressType.Fancy,
choices=list(ProgressType), help="The type of progress indication to use")
self._add_user_args_(brew_parser)

parsed_args = parser.parse_args(args)
Expand All @@ -221,7 +223,7 @@ def open(self, args: Optional[List[str]] = None, stream: TextIO = sys.stdout) ->
self.print_status()
elif parsed_args.subparser_name == 'brew':
for recipe in parsed_args.recipe:
self.brew(recipe, jobs=parsed_args.jobs)
self.brew(recipe, jobs=parsed_args.jobs, progress_type=parsed_args.progress)
else:
# No recognized command provided - print help
parser.print_help(file=stream)
4 changes: 2 additions & 2 deletions alkymi/serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ def value(self) -> T:
pass


class OutputWithValue(Output):
class OutputWithValue(Output[T]):
"""
An Output that is guaranteed to have an in-memory value - all outputs start out as this before being cached
"""
Expand All @@ -285,7 +285,7 @@ def value(self) -> T:
return self._value


class CachedOutput(Output):
class CachedOutput(Output[T]):
"""
An Output that has been cached - may or may not have it's associated value in-memory
"""
Expand Down
7 changes: 5 additions & 2 deletions alkymi/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@ class ProgressType(enum.Enum):
"""
Supported ways of showing progress
"""
NoProgress = 0 # Just run functions and log execution to alkymi's log
Fancy = 1 # Show progress indicators during recipe evaluation
NoProgress = "none" # Just run functions and log execution to alkymi's log
Fancy = "fancy" # Show progress indicators during recipe evaluation

def __str__(self):
return self.value


@enum.unique
Expand Down
2 changes: 1 addition & 1 deletion alkymi/version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Define the alkymi version as a tuple and a string
VERSION = (0, 1, 0)
VERSION = (0, 2, 0)
__version__ = ".".join(str(c) for c in VERSION)
4 changes: 2 additions & 2 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
-r requirements.txt
pytest==7.0.0
mypy==0.942
mypy==1.2.0
flake8==4.0.1
sphinx==4.3.0
sphinx_rtd_theme==1.0.0
markupsafe<2.1.0
m2r2==0.3.2
coverage==6.2
coverage==6.4.2
wheel==0.37.1
twine==3.2.0
2 changes: 1 addition & 1 deletion labfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def test(test_files: List[Path]) -> None:
# Run pytest in a separate thread to avoid asyncio recursion issues
from concurrent.futures import ThreadPoolExecutor
with ThreadPoolExecutor(max_workers=1) as executor:
result = executor.submit(pytest.main, args=test_files).result()
result = executor.submit(pytest.main, args=[str(f) for f in test_files]).result()
if result != pytest.ExitCode.OK:
exit(1)

Expand Down
2 changes: 1 addition & 1 deletion mypy.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[mypy]
python_version = 3.6
python_version = 3.7
warn_unused_configs = True

[mypy-numpy]
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@
"Natural Language :: English",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Intended Audience :: Developers",
"Intended Audience :: Information Technology",
"Intended Audience :: Science/Research",
Expand All @@ -45,7 +45,7 @@
"Tracker": "https://github.com/MathiasStokholm/alkymi/issues",
"Documentation": "https://alkymi.readthedocs.io/en/latest/",
},
python_requires=">=3.6",
python_requires=">=3.7",
install_requires=[
"networkx>=2.0",
"rich>=10.7"
Expand Down
4 changes: 2 additions & 2 deletions tests/test_foreach.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,11 +192,11 @@ def files_with_values(val: int) -> Path:
return f

# Initial evaluation should create all files
files: List[Path] = files_with_values.brew()
files = files_with_values.brew()
assert all([file.is_file() for file in files])

# If one of output files is deleted, a subsequent brew() should recreate it
files[0].unlink()
assert files_with_values.status() == Status.OutputsInvalid
files: List[Path] = files_with_values.brew()
files = files_with_values.brew()
assert all([file.is_file() for file in files])

0 comments on commit a0a6392

Please sign in to comment.