From 2fa4f4222d5d7b7bf212ba016b618a9b90b69276 Mon Sep 17 00:00:00 2001 From: Manuel Martinez Date: Sun, 25 Feb 2024 12:58:01 -0800 Subject: [PATCH 1/7] feat: onboard hatch --- .bumpversion.cfg | 8 ---- pyproject.toml | 81 ++++++++++++++++++++++++------------ src/stochatreat/__about__.py | 2 +- src/stochatreat/__init__.py | 13 ------ 4 files changed, 56 insertions(+), 48 deletions(-) delete mode 100644 .bumpversion.cfg diff --git a/.bumpversion.cfg b/.bumpversion.cfg deleted file mode 100644 index 34cda0e..0000000 --- a/.bumpversion.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[bumpversion] -current_version = 0.0.16 -commit = False -tag = True - -[bumpversion:file:pyproject.toml] -search = version = "{current_version}" -replace = version = "{new_version}" diff --git a/pyproject.toml b/pyproject.toml index 0194a62..1c350d7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,10 @@ [build-system] -requires = ["setuptools"] -build-backend = "setuptools.build_meta" +requires = ["hatchling"] +build-backend = "hatchling.build" [project] name = "stochatreat" -version = "0.0.16" +dynamic = ["version"] description = 'Stratified random assignment using pandas' readme = "README.md" requires-python = ">=3.8" @@ -23,6 +23,7 @@ classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Operating System :: OS Independent", @@ -30,41 +31,69 @@ classifiers = [ ] dependencies = ["pandas"] -[project.optional-dependencies] -dev = ["black", "build", "bump2version", "mypy", "ruff", "pytest", "pytest-cov"] - [project.urls] Documentation = "https://github.com/manmartgarc/stochatreat/blob/main/README.md" Issues = "https://github.com/manmartgarc/stochatreat/issues" Source = "https://github.com/manmartgarc/stochatreat/" -[tool.setuptools.packages.find] -where = ["src"] -exclude = ["tests"] -namespaces = false +[tool.hatch.version] +path = "src/stochatreat/__about__.py" + +[tool.hatch.envs.default] +dependencies = [ + "pytest", + "coverage[toml]>=6.5", +] +[tool.hatch.envs.default.scripts] +test = "pytest {args:tests}" +test-cov = "coverage run -m pytest {args:tests}" +cov-report = [ + "- coverage combine", + "coverage report", +] +cov = [ + "test-cov", + "cov-report" +] + +[[tool.hatch.envs.all.matrix]] +python = ["3.8", "3.9", "3.10", "3.11", "3.12"] + +[tool.hatch.envs.types] +dependencies = ["mypy>=1.0.0"] +[tool.hatch.envs.types.scripts] +check = "mypy --install-types --non-interactive {args:src/stochatreat tests}" + +[tool.coverage.run] +source_pkgs = ["stochatreat", "tests"] +branch = true +parallel = true +omit = [ + "src/stochatreat/__about__.py", +] + +[tool.coverage.paths] +stochatreat = ["src/stochatreat", "*/stochatreat/src/stochatreat"] +tests = ["tests", "*/stochatreat/tests"] -[tool.setuptools.package-data] -stochatreat = ["py.typed"] +[tool.coverage.report] +exclude_lines = [ + "no cov", + "if __name__ == .__main__.:", + "if TYPE_CHEKCING" +] -[tool.black] +[tool.ruff] line-length = 79 +[tool.ruff.lint] +ignore = [ + "TRY003" +] + [tool.mypy] -python_version = 3.8 -files = ["src", "tests"] check_untyped_defs = true show_error_codes = true pretty = true ignore_missing_imports = true -[tool.ruff] -line-length = 79 -target-version = "py38" - -[tool.pytest.ini_options] -addopts = [ - "--cov=stochatreat", - "--cov-branch", - "--cov-report=term-missing", - "--durations=5", -] diff --git a/src/stochatreat/__about__.py b/src/stochatreat/__about__.py index 311f216..d62d967 100644 --- a/src/stochatreat/__about__.py +++ b/src/stochatreat/__about__.py @@ -1 +1 @@ -__version__ = "0.0.14" +__version__ = "0.0.16" diff --git a/src/stochatreat/__init__.py b/src/stochatreat/__init__.py index d230bef..e69de29 100644 --- a/src/stochatreat/__init__.py +++ b/src/stochatreat/__init__.py @@ -1,13 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created on Wed Jul 10 12:16:55 2019 - -=============================================================================== -@author: Manuel Martinez -@project: stochatreat -=============================================================================== -""" -from stochatreat.stochatreat import stochatreat # noqa: F401 - -__version__ = "0.0.14" -__author__ = "Manuel Martinez" From c5039328654c2bfd2601614eb826a3f055204e71 Mon Sep 17 00:00:00 2001 From: Manuel Martinez Date: Sun, 25 Feb 2024 12:58:16 -0800 Subject: [PATCH 2/7] refactor: linting/formatting with hatch --- src/stochatreat/stochatreat.py | 73 +++++++++---------- src/stochatreat/utils.py | 13 ++-- tests/__init__.py | 0 ...treat_assignment.py => test_assignment.py} | 42 +++++------ tests/{test_stochatreat_io.py => test_io.py} | 52 ++++++------- 5 files changed, 82 insertions(+), 98 deletions(-) create mode 100644 tests/__init__.py rename tests/{test_stochatreat_assignment.py => test_assignment.py} (94%) rename tests/{test_stochatreat_io.py => test_io.py} (91%) diff --git a/src/stochatreat/stochatreat.py b/src/stochatreat/stochatreat.py index e7586f0..d1066c3 100644 --- a/src/stochatreat/stochatreat.py +++ b/src/stochatreat/stochatreat.py @@ -1,31 +1,27 @@ -# -*- coding: utf-8 -*- """ -Created on Thursday, 8th November 2018 2:34:47 pm -=============================================================================== -@filename: stochatreat.py -@author: Manuel Martinez (manmartgarc@gmail.com) -@project: stochatreat -@purpose: Define a function that assign treatments over an arbitrary - number of strata. -=============================================================================== + """ -from typing import List, Optional +from __future__ import annotations + +from typing import Literal import numpy as np import pandas as pd from stochatreat.utils import get_lcm_prob_denominators +MIN_ROW_N = 2 + def stochatreat( data: pd.DataFrame, - stratum_cols: List[str], + stratum_cols: list[str], treats: int, - probs: Optional[List[float]] = None, + probs: list[float] | None = None, random_state: int = 42, - idx_col: Optional[str] = None, - size: Optional[int] = None, - misfit_strategy: str = "stratum", + idx_col: str | None = None, + size: int | None = None, + misfit_strategy: Literal["stratum", "global"] = "stratum", ) -> pd.DataFrame: """ Takes a dataframe and an arbitrary number of treatments over an @@ -71,7 +67,7 @@ def stochatreat( treats=2, # including control idx_col='myid', # unique id column random_state=42) # seed for rng - >>> data = data.merge(treats, how='left', on='myid') + >>> data = data.merge(treats, how="left", on="myid") Multiple strata: >>> treats = stochatreat(data=data, @@ -80,10 +76,9 @@ def stochatreat( probs=[1/3, 2/3], idx_col='myid', random_state=42) - >>> data = data.merge(treats, how='left', on='myid') + >>> data = data.merge(treats, how="left", on="myid") """ - # pylint: disable=invalid-name - R = np.random.RandomState(random_state) + rand = np.random.RandomState(random_state) # ========================================================================= # do checks @@ -99,44 +94,50 @@ def stochatreat( elif probs is not None: probs_np = np.array(probs) if probs_np.sum() != 1: - raise ValueError("The probabilities must add up to 1") - - assertmsg = "length of treatments and probs must be the same" - assert len(treatment_ids) == len(probs_np), assertmsg + error_msg = "The probabilities must add up to 1" + raise ValueError(error_msg) + if len(probs_np) != len(treatment_ids): + error_msg = ( + "The number of probabilities must match the number of " + "treatments" + ) + raise ValueError(error_msg) # check if dataframe is empty if data.empty: - raise ValueError("Make sure that your dataframe is not empty.") + error_msg = "Make sure that your dataframe is not empty." + raise ValueError(error_msg) # check length of data - if len(data) < 2: - raise ValueError("Make sure your data has enough observations.") + if len(data) < MIN_ROW_N: + error_msg = "Your dataframe at least needs to have 2 rows." + raise ValueError(error_msg) # if idx_col parameter was not defined. if idx_col is None: data = data.rename_axis("index", axis="index").reset_index() idx_col = "index" elif not isinstance(idx_col, str): - raise TypeError("idx_col has to be a string.") + error_msg = "idx_col has to be a string." + raise TypeError(error_msg) # retrieve type to check and re-assign in the end idx_col_type = data[idx_col].dtype # check for unique identifiers if data[idx_col].duplicated(keep=False).sum() > 0: - raise ValueError("Values in idx_col are not unique.") + error_msg = "The values in idx_col are not unique." + raise ValueError(error_msg) # if size is larger than sample universe if size is not None and size > len(data): - raise ValueError("Size argument is larger than the sample universe.") + error_msg = "Size argument is larger than the sample universe." + raise ValueError(error_msg) # deal with multiple strata if isinstance(stratum_cols, str): stratum_cols = [stratum_cols] - if misfit_strategy not in ("stratum", "global"): - raise ValueError("the strategy must be one of 'stratum' or 'global'") - # sort data - useful to preserve correspondence between `idx_col` and # assignments data = data.sort_values(by=idx_col) @@ -145,7 +146,7 @@ def stochatreat( data["stratum_id"] = data.groupby(stratum_cols).ngroup() # keep only ids and concatenated strata - data = data[[idx_col] + ["stratum_id"]].copy() + data = data[[idx_col, "stratum_id"]].copy() # apply weights to each stratum if sampling is wanted if size is not None: @@ -164,8 +165,6 @@ def stochatreat( data = data.droplevel(level="stratum_id") - assert sum(reduced_sizes) == len(data) - # Treatment assignment proceeds in two stages within each stratum: # 1. In as far as units can be neatly divided in the proportions given by # prob they are so divided. @@ -235,7 +234,7 @@ def stochatreat( # generate random permutations without loop by generating large number of # random values and sorting row (meaning one permutation) wise permutations = np.argsort( - R.rand(len(data) // lcm_prob_denominators, lcm_prob_denominators), + rand.rand(len(data) // lcm_prob_denominators, lcm_prob_denominators), axis=1, ) # lookup treatment name for permutations. This works because we flatten @@ -248,6 +247,4 @@ def stochatreat( data["treat"] = data["treat"].astype(np.int64) - assert data["treat"].isnull().sum() == 0 - return data diff --git a/src/stochatreat/utils.py b/src/stochatreat/utils.py index b1ce817..cd8ee64 100644 --- a/src/stochatreat/utils.py +++ b/src/stochatreat/utils.py @@ -2,7 +2,9 @@ from fractions import Fraction from typing import Iterable -if sum(sys.version_info[:2]) < 12: +LCM_VERSION = 9 + +if sys.version_info.minor < LCM_VERSION: from functools import reduce from math import gcd # type: ignore @@ -17,12 +19,11 @@ def lcm(*args): from math import lcm # type: ignore -def get_lcm_prob_denominators(probs: Iterable[float]): +def get_lcm_prob_denominators(probs: Iterable[float]) -> int: """ Helper function to compute the LCM of the denominators of the probabilities """ - prob_denominators = [ + prob_denominators = ( Fraction(prob).limit_denominator().denominator for prob in probs - ] - lcm_prob_denominators = lcm(*prob_denominators) - return lcm_prob_denominators + ) + return lcm(*prob_denominators) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_stochatreat_assignment.py b/tests/test_assignment.py similarity index 94% rename from tests/test_stochatreat_assignment.py rename to tests/test_assignment.py index 80b4ecf..e079b2f 100644 --- a/tests/test_stochatreat_assignment.py +++ b/tests/test_assignment.py @@ -1,6 +1,7 @@ import numpy as np import pandas as pd import pytest + from stochatreat.stochatreat import stochatreat from stochatreat.utils import get_lcm_prob_denominators @@ -11,18 +12,16 @@ @pytest.fixture(params=[10_000, 100_000]) def df(request): - N = request.param - df = pd.DataFrame( + n = request.param + return pd.DataFrame( data={ - "id": np.arange(N), - "dummy": [1] * N, - "stratum1": np.random.randint(1, 100, size=N), - "stratum2": np.random.randint(0, 2, size=N), + "id": np.arange(n), + "dummy": [1] * n, + "stratum1": np.random.randint(1, 100, size=n), + "stratum2": np.random.randint(0, 2, size=n), } ) - return df - # a set of treatment assignment probabilities to throw at many tests standard_probs = [ @@ -46,19 +45,17 @@ def df(request): # no misfits @pytest.fixture def df_no_misfits(): - N = 1_000 + n = 1_000 stratum_size = 10 - df = pd.DataFrame( + return pd.DataFrame( data={ - "id": np.arange(N), + "id": np.arange(n), "stratum": np.repeat( - np.arange(N / stratum_size), repeats=stratum_size + np.arange(n / stratum_size), repeats=stratum_size ), } ) - return df - probs_no_misfits = [ [0.1, 0.9], @@ -147,11 +144,11 @@ def test_stochatreat_only_misfits(probs): of units is sufficiently large -- relies on the Law of Large Numbers, not deterministic """ - N = 10_000 + n = 10_000 df = pd.DataFrame( data={ - "id": np.arange(N), - "stratum": np.arange(N), + "id": np.arange(n), + "stratum": np.arange(n), } ) treats = stochatreat( @@ -190,12 +187,10 @@ def get_within_strata_counts(treats): .reset_index() ) - counts = pd.merge( + return pd.merge( treatment_counts, stratum_counts, on="stratum_id", how="left" ) - return counts - def compute_count_diff(treats, probs): """ @@ -324,9 +319,10 @@ def test_stochatreat_stratum_ids(df, misfit_strategy, stratum_cols): if misfit_strategy == "global": # depending on whether there are misfits - assert (n_unique_stratum_ids == n_unique_strata) or ( - n_unique_stratum_ids - 1 == n_unique_strata - ) + assert n_unique_strata in { + n_unique_stratum_ids, + n_unique_stratum_ids - 1, + } else: assert n_unique_stratum_ids == n_unique_strata diff --git a/tests/test_stochatreat_io.py b/tests/test_io.py similarity index 91% rename from tests/test_stochatreat_io.py rename to tests/test_io.py index dea112d..176d49d 100644 --- a/tests/test_stochatreat_io.py +++ b/tests/test_io.py @@ -1,6 +1,7 @@ import numpy as np import pandas as pd import pytest + from stochatreat.stochatreat import stochatreat @@ -9,7 +10,7 @@ def correct_params(): """ A set of valid parameters that can be passed to stochatreat() """ - params = { + return { "probs": [0.1, 0.9], "treat": 2, "data": pd.DataFrame( @@ -17,7 +18,6 @@ def correct_params(): ), "idx_col": "id", } - return params def test_input_invalid_probs(correct_params): @@ -25,7 +25,7 @@ def test_input_invalid_probs(correct_params): Tests that the function rejects probabilities that don't add up to one """ probs_not_sum_to_one = [0.1, 0.2] - with pytest.raises(Exception): + with pytest.raises(ValueError, match="The probabilities must add up to 1"): stochatreat( data=correct_params["data"], stratum_cols=["stratum"], @@ -41,7 +41,12 @@ def test_input_more_treats_than_probs(correct_params): different sizes """ treat_too_large = 3 - with pytest.raises(Exception): + with pytest.raises( + ValueError, + match=( + "The number of probabilities must match the number of treatments" + ), + ): stochatreat( data=correct_params["data"], stratum_cols=["stratum"], @@ -56,7 +61,9 @@ def test_input_empty_data(correct_params): Tests that the function raises an error when an empty dataframe is passed """ empty_data = pd.DataFrame() - with pytest.raises(ValueError): + with pytest.raises( + ValueError, match="Make sure that your dataframe is not empty." + ): stochatreat( data=empty_data, stratum_cols=["stratum"], @@ -72,7 +79,7 @@ def test_input_idx_col_str(correct_params): string or None """ idx_col_not_str = 0 - with pytest.raises(TypeError): + with pytest.raises(TypeError, match="idx_col has to be a string."): stochatreat( data=correct_params["data"], stratum_cols=["stratum"], @@ -87,7 +94,9 @@ def test_input_invalid_size(correct_params): Tests that the function rejects a sampling size larger than the data count """ size_bigger_than_sampling_universe_size = 101 - with pytest.raises(ValueError): + with pytest.raises( + ValueError, match="Size argument is larger than the sample universe." + ): stochatreat( data=correct_params["data"], stratum_cols=["stratum"], @@ -106,7 +115,9 @@ def test_input_idx_col_unique(correct_params): data_with_idx_col_with_duplicates = pd.DataFrame( data={"id": 1, "stratum": np.arange(100)} ) - with pytest.raises(ValueError): + with pytest.raises( + ValueError, match="The values in idx_col are not unique." + ): stochatreat( data=data_with_idx_col_with_duplicates, stratum_cols=["stratum"], @@ -116,23 +127,6 @@ def test_input_idx_col_unique(correct_params): ) -def test_input_invalid_strategy(correct_params): - """ - Tests that the function raises an error if an invalid strategy string is - passed - """ - unknown_strategy = "unknown" - with pytest.raises(ValueError): - stochatreat( - data=correct_params["data"], - stratum_cols=["stratum"], - treats=correct_params["treat"], - idx_col=correct_params["idx_col"], - probs=correct_params["probs"], - misfit_strategy=unknown_strategy, - ) - - @pytest.fixture def treatments_dict(): """fixture of stochatreat() output to test output format""" @@ -152,15 +146,13 @@ def treatments_dict(): random_state=42, ) - treatments_dict = { + return { "data": data, "idx_col": idx_col, "size": size, "treatments": treatments, } - return treatments_dict - def test_output_type(treatments_dict): """ @@ -259,7 +251,7 @@ def treatments_dict_rand_index(): random_state=42, ) - treatments_dict = { + return { "data": data, "stratum_cols": ["stratum"], "idx_col": idx_col, @@ -267,8 +259,6 @@ def treatments_dict_rand_index(): "n_treatments": treats, } - return treatments_dict - standard_probs = [ [0.1, 0.9], From f3cdb9ff46e85408ba95bd6824cac26e42243e83 Mon Sep 17 00:00:00 2001 From: Manuel Martinez Date: Sun, 25 Feb 2024 13:04:03 -0800 Subject: [PATCH 3/7] feat: use hatch on github actions --- .github/workflows/{test.yml => release.yml} | 22 ++++----- Makefile | 55 --------------------- README.md | 2 +- 3 files changed, 10 insertions(+), 69 deletions(-) rename .github/workflows/{test.yml => release.yml} (68%) delete mode 100644 Makefile diff --git a/.github/workflows/test.yml b/.github/workflows/release.yml similarity index 68% rename from .github/workflows/test.yml rename to .github/workflows/release.yml index 21b6d86..5d49581 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/release.yml @@ -1,7 +1,7 @@ # 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: test +name: Release CI on: push: @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v3 @@ -23,22 +23,18 @@ jobs: with: python-version: ${{ matrix.python-version }} cache: pip - - name: Install dependencies + - name: Install hatch run: | - python -m pip install --upgrade pip - pip install -e .[dev] - - name: Lint with Ruff + python -m pip install hatch + - name: Check lint and format run: | - make lint - - name: Check format with Black - run: | - make format + hatch fmt --check - name: Type-checking with Mypy run: | - make test/mypy - - name: Test with pytest + hatch run +py=${{ matrix.python-version }} types:check + - name: Run tests with pytest run: | - make test/pytest + hatch run +py=${{ matrix.python-version }} all:test - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v3 env: diff --git a/Makefile b/Makefile deleted file mode 100644 index c19d195..0000000 --- a/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -.DEFAULT_GOAL := all - -# taken from here: https://dwmkerr.com/makefile-help-command/ -.PHONY: help -help: # Show help for each of the Makefile recipes - @grep -E '^[a-zA-Z0-9 -]+:.*#' Makefile | sort | while read -r l; do printf "\033[1;32m$$(echo $$l | cut -f 1 -d':')\033[00m:$$(echo $$l | cut -f 2- -d'#')\n"; done - - -all: clean lint format test dist # Runs all recipes. - -clean: clean-build clean-pyc clean-test # Runs all clean recipes. - -clean-build: # Cleans all build files. - rm -fr build/ - rm -fr dist/ - rm -fr .eggs/ - find . -name '*.egg-info' -exec rm -fr {} + - find . -name '*.egg' -exec rm -f {} + - -clean-pyc: # Cleans all python cache files. - find . -name '*.pyc' -exec rm -f {} + - find . -name '*.pyo' -exec rm -f {} + - find . -name '*~' -exec rm -f {} + - find . -name '__pycache__' -exec rm -fr {} + - -clean-test: # Cleans all test files. - rm -fr .tox/ - rm -f .coverage - rm -fr htmlcov/ - rm -fr .pytest_cache - -dist: clean # Builds source and wheel package. - python -m build - ls -lth dist/ - -lint: lint/ruff # Runs all linting. - -lint/ruff: # Runs ruff linting. - ruff src tests - -release: dist # Releases a new version to PyPi. - twine upload dist/* - -format: format/black # Runs all format checks. - -format/black: # Runs black format checks. - black --check src tests - -test: test/mypy test/pytest # Runs all tests. - -test/pytest: # Runs pytest tests. - pytest - -test/mypy: # Runs mypy tests. - mypy \ No newline at end of file diff --git a/README.md b/README.md index 36af9d6..2bd6103 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ | | | |---|---| -|Build|[![Main Branch Tests](https://github.com/manmartgarc/stochatreat/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/manmartgarc/stochatreat/actions/workflows/test.yml) [![codecov](https://codecov.io/gh/manmartgarc/stochatreat/graph/badge.svg?token=llPoW2rWIN)](https://codecov.io/gh/manmartgarc/stochatreat) +|Build|[![Main Branch Tests](https://github.com/manmartgarc/stochatreat/actions/workflows/release.yml/badge.svg?branch=main)](https://github.com/manmartgarc/stochatreat/actions/workflows/test.yml) [![codecov](https://codecov.io/gh/manmartgarc/stochatreat/graph/badge.svg?token=llPoW2rWIN)](https://codecov.io/gh/manmartgarc/stochatreat) |PyPI| [![pypi](https://img.shields.io/pypi/v/stochatreat?logo=pypi)](https://pypi.org/project/stochatreat/) ![pypi-downloads](https://img.shields.io/pypi/dm/stochatreat?logo=pypi) |conda-forge| [![Conda](https://img.shields.io/conda/v/conda-forge/stochatreat?logo=conda-forge)](https://anaconda.org/conda-forge/stochatreat) ![conda-downloads](https://img.shields.io/conda/dn/conda-forge/stochatreat?logo=conda-forge) |Meta| [![linting - Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) [![code format - Black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![types - Mypy](https://img.shields.io/badge/types-Mypy-blue.svg)](https://github.com/python/mypy) [![License - MIT](https://img.shields.io/badge/license-MIT-9400d3.svg)](https://spdx.org/licenses/) From bfd021227c2adcba73a304e876d51c8db80f5ae5 Mon Sep 17 00:00:00 2001 From: Manuel Martinez Date: Sun, 25 Feb 2024 13:05:51 -0800 Subject: [PATCH 4/7] fix: mypy type checking --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5d49581..f0f3446 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,7 +31,7 @@ jobs: hatch fmt --check - name: Type-checking with Mypy run: | - hatch run +py=${{ matrix.python-version }} types:check + hatch run types:check - name: Run tests with pytest run: | hatch run +py=${{ matrix.python-version }} all:test From fa87fe8becb6dc7b26fdf26b42906af27462fbcc Mon Sep 17 00:00:00 2001 From: Manuel Martinez Date: Sun, 25 Feb 2024 13:14:22 -0800 Subject: [PATCH 5/7] docs: update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2bd6103..9a5b7c5 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ |Build|[![Main Branch Tests](https://github.com/manmartgarc/stochatreat/actions/workflows/release.yml/badge.svg?branch=main)](https://github.com/manmartgarc/stochatreat/actions/workflows/test.yml) [![codecov](https://codecov.io/gh/manmartgarc/stochatreat/graph/badge.svg?token=llPoW2rWIN)](https://codecov.io/gh/manmartgarc/stochatreat) |PyPI| [![pypi](https://img.shields.io/pypi/v/stochatreat?logo=pypi)](https://pypi.org/project/stochatreat/) ![pypi-downloads](https://img.shields.io/pypi/dm/stochatreat?logo=pypi) |conda-forge| [![Conda](https://img.shields.io/conda/v/conda-forge/stochatreat?logo=conda-forge)](https://anaconda.org/conda-forge/stochatreat) ![conda-downloads](https://img.shields.io/conda/dn/conda-forge/stochatreat?logo=conda-forge) -|Meta| [![linting - Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) [![code format - Black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![types - Mypy](https://img.shields.io/badge/types-Mypy-blue.svg)](https://github.com/python/mypy) [![License - MIT](https://img.shields.io/badge/license-MIT-9400d3.svg)](https://spdx.org/licenses/) +|Meta| [![Hatch project](https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5.svg)](https://github.com/pypa/hatch) [![linting - Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) [![types - Mypy](https://img.shields.io/badge/types-Mypy-blue.svg)](https://github.com/python/mypy) [![License - MIT](https://img.shields.io/badge/license-MIT-9400d3.svg)](https://spdx.org/licenses/) --- From 8505c1cb1f1c6bb81f13224c9f83956eb2fad863 Mon Sep 17 00:00:00 2001 From: Manuel Martinez Date: Sun, 25 Feb 2024 13:16:09 -0800 Subject: [PATCH 6/7] chore: bump version --- src/stochatreat/__about__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stochatreat/__about__.py b/src/stochatreat/__about__.py index d62d967..1f658a4 100644 --- a/src/stochatreat/__about__.py +++ b/src/stochatreat/__about__.py @@ -1 +1 @@ -__version__ = "0.0.16" +__version__ = "0.0.17" From 87876e02242bec9ca60cb9cd2afdab9b16c855df Mon Sep 17 00:00:00 2001 From: Manuel Martinez Date: Sun, 25 Feb 2024 13:23:08 -0800 Subject: [PATCH 7/7] docs: update contributing --- .github/CONTRIBUTING.md | 44 ++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 41ec91e..47ab2b1 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -20,28 +20,31 @@ ## Setting up development environment -You can install the development environment, i.e. all the dependencies required to run all tests and checks that are run when you submit a PR, by running. There are two main ways of doing this, one is to do it without cloning the repository, and the other is to clone the repository and then install the dependencies. +You can install the development environment, i.e. all the dependencies required to run all tests and checks that are run when you submit a PR, by following these steps: + +1. [Install](https://hatch.pypa.io/1.9/install/#installation) `hatch`. +2. Clone the repository: + ```bash + git clone https://github.com/manmartgarc/stochatreat + cd stochatreat + ``` +3. Confirm `hatch` picked up the project: + ```bash + hatch status + ``` -### Without cloning the repository - -```bash -pip install "stochatreat[dev] @ git+https://github.com/manmartgarc/stochatreat" -``` +## Tests -### Cloning the repository +To run tests in the default environment: ```bash -git clone https://github.com/manmartgarc/stochatreat -cd stochatreat -pip install -e .[dev] +hatch run default:test ``` -## Tests - -To run tests run: +To run tests in all environments: ```bash -make test +hatch run all:test ``` ## Format @@ -49,17 +52,22 @@ make test When submitting a PR, the CI will run `make format` and also `make lint` to check the format of the code. You can run this locally by running: ```bash -make format lint +hatch fmt ``` ## Release -- Run `bump2version` to update the version number in the `setup.py` file and create a new tag: +- Run `hatch` to update the version number file and create a new tag: ```bash - bump2version [major|minor|patch] + hatch version [major|minor|patch] ``` - Commit the changes and push them to your fork. +- Tag the new version: + ```bash + git tag -a v0.0.0 -m "v0.0.0" + git push origin v0.0.0 + ``` - Submit a PR. -- Once the PR is merged, run `make release` to create a new release in GitHub. +- Once the PR is merged, run `hatch publish` to create a new release in PyPI.