diff --git a/.github/workflows/continuous_integration.yaml b/.github/workflows/continuous_integration.yaml new file mode 100644 index 0000000..4f82c52 --- /dev/null +++ b/.github/workflows/continuous_integration.yaml @@ -0,0 +1,33 @@ +name: Python CI + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + name: Checkout repository + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.10' + + - name: Install dependencies from pyproject.toml + run: | + pip install --upgrade pip + pip install . + + - name: Install development dependencies + run: | + pip install -r requirements-dev.txt + + - name: Run tests + run: | + pytest diff --git a/.github/workflows/python-publish.yaml b/.github/workflows/python-publish.yaml new file mode 100644 index 0000000..0d01815 --- /dev/null +++ b/.github/workflows/python-publish.yaml @@ -0,0 +1,41 @@ +# This workflow will upload a Python Package using Twine when a release is created +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Publish Python Package + +on: + release: + types: [published] + +permissions: + contents: read + +jobs: + deploy: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: '3.10' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build + - name: Build package + run: python -m build + - name: Publish package + uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 + with: + user: __token__ + password: ${{ secrets.PYPI_API_TOKEN }} + + diff --git a/pyproject.toml b/pyproject.toml index 756c1e3..ff08065 100755 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,10 @@ [project] name = "myfigure" -version = "0.0.1" +version = "1.0.0" authors = [ { name = "Matteo Pecchi"} ] -description = "the final plotting class" +description = "a class for standardized accessible plots" readme = "README.md" license = { text = "MIT" } classifiers = [ @@ -13,7 +13,7 @@ classifiers = [ "Operating System :: OS Independent", ] -requires-python = ">=3.8" +requires-python = ">=3.10" dependencies = [ "numpy>=1.21.2", diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..f93da71 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,2 @@ +pytest>=6.2 +pytest-cov diff --git a/tests/test_myfigure.py b/tests/test_myfigure.py old mode 100755 new mode 100644 index d0a9700..b72369f --- a/tests/test_myfigure.py +++ b/tests/test_myfigure.py @@ -1,111 +1,88 @@ -# %% -from __future__ import annotations -import matplotlib.pyplot as plt -import pytest -from myfigure.myfigure import MyFigure - - -def test_myfigure_initialization_with_defaults(): - # Test initialization with default values - fig = MyFigure() - assert isinstance(fig.broad_props, dict) - assert isinstance(fig.kwargs, dict) - assert "rows" in fig.kwargs and fig.kwargs["rows"] == 1 # Default value assumed to be 1 - assert "cols" in fig.kwargs and fig.kwargs["cols"] == 1 # Default value assumed to be 1 - assert isinstance(fig.fig, plt.Figure) # Check if fig is an instance of plt.Figure - assert len(fig.axs) == 1 # There should be one Axes object in the list - - -def test_myfigure_initialization_with_custom_values(): - # Test initialization with custom values - custom_kwargs = {"rows": 2, "cols": 3, "width": 10.0} - fig = MyFigure(**custom_kwargs) - for key, value in custom_kwargs.items(): - assert key in fig.kwargs and fig.kwargs[key] == value - - -def test_broadcast_value_prop(): - fig = MyFigure(rows=2, cols=2) # Assuming a 2x2 grid - # Broadcasting a single value - result = fig._broadcast_value_prop("test", "prop_name") - assert result == ["test", "test", "test", "test"] - - # Broadcasting a list of values - result = fig._broadcast_value_prop(["a", "b", "c", "d"], "prop_name") - assert result == ["a", "b", "c", "d"] - - # Broadcasting with incorrect list size - with pytest.raises(ValueError): - fig._broadcast_value_prop(["a", "b"], "prop_name") - - -def test_broadcast_list_prop(): - fig = MyFigure(rows=2, cols=1) # Assuming a 2x1 grid - # Broadcasting a list of lists - result = fig._broadcast_list_prop([[1, 2], [3, 4]], "prop_name") - assert result == [[1, 2], [3, 4]] - - # Broadcasting a list with incorrect inner list size - with pytest.raises(ValueError): - fig._broadcast_list_prop([[1, 2], [3]], "prop_name") - - -def test_broadcast_value_prop_single_axis(): - fig = MyFigure(rows=1, cols=1) # A single subplot - # Broadcasting a single value - result = fig._broadcast_value_prop("test", "prop_name") - assert result == ["test"] - - # Broadcasting a list of values (which should be just one value for a single subplot) - result = fig._broadcast_value_prop(["a"], "prop_name") - assert result == ["a"] - - # Broadcasting with incorrect list size should raise an error even for a single subplot - with pytest.raises(ValueError): - fig._broadcast_value_prop(["a", "b"], "prop_name") - - -def test_broadcast_list_prop_single_axis(): - fig = MyFigure(rows=1, cols=1) # A single subplot - # Broadcasting a list of lists (which should just be one list for a single subplot) - result = fig._broadcast_list_prop([[1, 2]], "prop_name") - assert result == [[1, 2]] - - # Broadcasting a list with incorrect inner list size should raise an error - with pytest.raises(ValueError): - fig._broadcast_list_prop([[1, 2], [3]], "prop_name") - - -def test_create_figure_single_axis(): - fig = MyFigure(rows=1, cols=1) - fig.create_figure() - assert isinstance(fig.fig, plt.Figure) - assert len(fig.axs) == 1 # Should have one Axes object in the list - assert isinstance(fig.axs[0], plt.Axes) - - -def test_create_figure_multiple_axes(): - rows, cols = 2, 3 - fig = MyFigure(rows=rows, cols=cols) - fig.create_figure() - assert isinstance(fig.fig, plt.Figure) - assert len(fig.axs) == rows * cols # Number of Axes should match rows * cols - for ax in fig.axs: - assert isinstance(ax, plt.Axes) - - -def test_invalid_rows_cols(): - # Testing invalid row and column inputs - with pytest.raises(ValueError): - MyFigure(rows=-1, cols=1) - with pytest.raises(ValueError): - MyFigure(rows=1, cols=0) - - -def test_invalid_kwargs(): - # Testing with an invalid keyword argument - with pytest.raises(ValueError): - MyFigure(invalid_arg=123) - - -# %% +# %% +from __future__ import annotations +import matplotlib.pyplot as plt +import pytest +from myfigure.myfigure import MyFigure + + +def test_myfigure_initialization_with_defaults(): + # Test initialization with default values + fig = MyFigure() + assert isinstance(fig.broad_props, dict) + assert isinstance(fig.kwargs, dict) + assert "rows" in fig.kwargs and fig.kwargs["rows"] == 1 # Default value assumed to be 1 + assert "cols" in fig.kwargs and fig.kwargs["cols"] == 1 # Default value assumed to be 1 + assert isinstance(fig.fig, plt.Figure) # Check if fig is an instance of plt.Figure + assert len(fig.axs) == 1 # There should be one Axes object in the list + + +def test_myfigure_initialization_with_custom_values(): + # Test initialization with custom values + custom_kwargs = {"rows": 2, "cols": 3, "width": 10.0} + fig = MyFigure(**custom_kwargs) + for key, value in custom_kwargs.items(): + assert key in fig.kwargs and fig.kwargs[key] == value + + +def test_broadcast_value_prop(): + fig = MyFigure(rows=2, cols=2, x_lab="test", y_lab=["a", "b", "c", "d"]) # Assuming a 2x2 grid + # Broadcasting a single value + result = fig.broad_props["x_lab"] + assert result == ["test", "test", "test", "test"] + + # Broadcasting a list of values + result = fig.broad_props["y_lab"] + assert result == ["a", "b", "c", "d"] + + # Broadcasting with incorrect list size + with pytest.raises(ValueError): + fig = MyFigure(rows=2, cols=2, y_lab=["a", "b"]) + + +def test_broadcast_list_prop(): + fig = MyFigure(rows=2, cols=1, x_lim=(0, 1), y_lim=[(0, 1), (2, 4)]) # Assuming a 2x1 grid + # Broadcasting a list of lists + result = fig.broad_props["x_lim"] + assert result == [(0, 1), (0, 1)] + + result = fig.broad_props["y_lim"] + assert result == [(0, 1), (2, 4)] + + # Broadcasting a list with incorrect inner list size + with pytest.raises(ValueError): + fig = MyFigure(rows=2, cols=1, y_lim=[(0, 1), (2, 4), (3, 5)]) + + +def test_create_figure_single_axis(): + fig = MyFigure(rows=1, cols=1) + fig.create_figure() + assert isinstance(fig.fig, plt.Figure) + assert len(fig.axs) == 1 # Should have one Axes object in the list + assert isinstance(fig.axs[0], plt.Axes) + + +def test_create_figure_multiple_axes(): + rows, cols = 2, 3 + fig = MyFigure(rows=rows, cols=cols) + fig.create_figure() + assert isinstance(fig.fig, plt.Figure) + assert len(fig.axs) == rows * cols # Number of Axes should match rows * cols + for ax in fig.axs: + assert isinstance(ax, plt.Axes) + + +def test_invalid_rows_cols(): + # Testing invalid row and column inputs + with pytest.raises(ValueError): + MyFigure(rows=-1, cols=1) + with pytest.raises(ValueError): + MyFigure(rows=1, cols=0) + + +def test_invalid_kwargs(): + # Testing with an invalid keyword argument + with pytest.raises(ValueError): + MyFigure(invalid_arg=123) + + +# %%