diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 51e4fd4..b95768e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,12 @@ jobs: run: uv sync --dev - name: Run tests with coverage - run: uv run pytest -v --cov=src --cov-report=term --cov-report=xml + run: uv run pytest -v --cov=src --cov-branch --cov-report=term --cov-report=xml + + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} lint: runs-on: ubuntu-latest diff --git a/README.md b/README.md index 6d9a80c..75e0ccf 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ ![PyPI Version](https://img.shields.io/pypi/v/casregnum) ![CI](https://github.com/molshape/CASRegistryNumbers/actions/workflows/ci.yml/badge.svg) +[![codecov](https://codecov.io/github/molshape/CASRegistryNumbers/graph/badge.svg?token=5HZN6RX2XA)](https://codecov.io/github/molshape/CASRegistryNumbers) \ ![Python Versions](https://img.shields.io/pypi/pyversions/casregnum) ![License](https://img.shields.io/github/license/molshape/casregnum) \ ![GitHub stars](https://img.shields.io/github/stars/molshape/casregnum) @@ -10,7 +11,7 @@ Python class to manage, check and sort CAS Registry Numbers® (CAS RN®).
-Table of Content +Table of Contents 1. [Description](#description) 2. [How to install and uninstall?](#how-to-install-and-uninstall) @@ -23,17 +24,25 @@ Python class to manage, check and sort CAS Registry Numbers® (CAS RN®). **casregnum** is a Python class to manage, check, and sort CAS Registry Numbers® (CAS RN®) by the [Chemical Abstracts Service](https://www.cas.org/). Check their official [FAQ website](https://www.cas.org/support/documentation/chemical-substances/faqs) for more information on CAS numbers. -## How to install and uninstall? +## How to install and uninstall **casregnum** can be installed from the [Python Package Index (PyPI)](https://pypi.org/) repository by calling - pip install casregnum + pip install casregnum + +or + + uv add casregnum In order to uninstall **casregnum** from your local environment use - pip uninstall casregnum + pip uninstall casregnum + +or + + uv remove casregnum -## How to use? +## How to use **casregnum** provides the `CAS` class for creating a CAS Registry Number® instance: ```Python @@ -81,18 +90,15 @@ for i, isomer in enumerate(sorted(octanes), start=1): print() ``` -will generate the following output: - -``` -str: 58-08-2 -int: 58082 -check digit: 2 -58-08-2 == 58-08-2: True -58-08-2 > 58-08-2: False -79-33-4 > 10326-41-7: False -79-33-4 < 10326-41-7: True - 111-65-9, 540-84-1, 560-21-4, 563-16-6, 564-02-3, 565-75-3, - 583-48-2, 584-94-1, 589-43-5, 589-53-7, 589-81-1, 590-73-8, - 592-13-2, 592-27-8, 594-82-1, 609-26-7, 619-99-8, 1067-08-9, -``` - +This will generate the following output: + + str: 58-08-2 + int: 58082 + check digit: 2 + 58-08-2 == 58-08-2: True + 58-08-2 > 58-08-2: False + 79-33-4 > 10326-41-7: False + 79-33-4 < 10326-41-7: True + 111-65-9, 540-84-1, 560-21-4, 563-16-6, 564-02-3, 565-75-3, + 583-48-2, 584-94-1, 589-43-5, 589-53-7, 589-81-1, 590-73-8, + 592-13-2, 592-27-8, 594-82-1, 609-26-7, 619-99-8, 1067-08-9, diff --git a/pyproject.toml b/pyproject.toml index 6f00e43..4b38c5c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "casregnum" -version = "1.1.0" +version = "1.1.1" description = "Python class to manage, check and sort CAS Registry Numbers® (CAS RN®)" readme = "README.md" authors = [ diff --git a/src/casregnum/__init__.py b/src/casregnum/__init__.py index 124d291..381bf9f 100644 --- a/src/casregnum/__init__.py +++ b/src/casregnum/__init__.py @@ -4,5 +4,5 @@ try: from importlib.metadata import version __version__ = version("casregnum") -except ImportError: - __version__ = "unknown" +except ImportError: # pragma: no cover + __version__ = "unknown" # pragma: no cover diff --git a/src/casregnum/casregnum.py b/src/casregnum/casregnum.py index 59c77af..d182bc5 100644 --- a/src/casregnum/casregnum.py +++ b/src/casregnum/casregnum.py @@ -1,5 +1,3 @@ -import re - """ Class for CAS Registry Numbers® (CAS RN®) allows to manage, check and sort CAS Registry Numbers® @@ -8,6 +6,10 @@ and the calculation method to determine the check digit """ +from __future__ import annotations + +import re + class CAS: """ @@ -53,15 +55,15 @@ def __format__(self, format_spec) -> str: return f"{self.cas_string:{format_spec}}" # checks if two CAS Registry Numbers are equal - def __eq__(self, other: object) -> bool: + def __eq__(self, other: CAS) -> bool: if not isinstance(other, CAS): - return False + raise TypeError("Comparisons can only be made between CAS objects.") return self.cas_integer == other.cas_integer # checks if self.cas_integer < other.cas_integer - def __lt__(self, other: object) -> bool: + def __lt__(self, other: CAS) -> bool: if not isinstance(other, CAS): - return NotImplemented + raise TypeError("Comparisons can only be made between CAS objects.") return self.cas_integer < other.cas_integer # Returns CAS Registry Number @@ -70,7 +72,7 @@ def cas_string(self) -> str: """ Returns the CAS Registry Number as a formatted string (e.g. "58-08-2"). """ - return self.__cas_string + return self._cas_string # Sets CAS Registry Number # if the passed input value is a string, parse the string according to _____00-00-0 @@ -79,7 +81,7 @@ def cas_string(self) -> str: def cas_string(self, cas_rn: str) -> None: # convert (formatted) CAS string into integer if regex_cas := re.match(r"^(\d{2,7})\-(\d{2})-(\d{1})$", cas_rn): - self.cas_integer = self.__cas_integer = int( + self.cas_integer = self._cas_integer = int( regex_cas.group(1) + regex_cas.group(2) + regex_cas.group(3) ) # cas_rn is not following the notation rule for CAS numbers => ValueError @@ -87,7 +89,7 @@ def cas_string(self, cas_rn: str) -> None: raise ValueError( f"Invalid CAS number format for '{cas_rn}' (must follow the notation _____00-00-0)" ) - self.__cas_string = cas_rn + self._cas_string = cas_rn # Returns CAS Registry Number as an integer (without the hyphens) @property @@ -95,7 +97,7 @@ def cas_integer(self) -> int: """ Returns the CAS Registry Number as an integer (e.g. 58082). """ - return self.__cas_integer + return self._cas_integer @cas_integer.setter def cas_integer(self, cas_rn: int) -> None: @@ -106,7 +108,7 @@ def cas_integer(self, cas_rn: int) -> None: raise ValueError( f"Invalid CAS number '{cas_rn}' (must be an integer between 10004 and 9999999995)" ) - self.__cas_integer = cas_rn + self._cas_integer = cas_rn # Returns check digit of the CAS Registry Number @property @@ -114,7 +116,7 @@ def check_digit(self) -> int: """ Returns the check digit of the CAS Registry Number (e.g. 2 for "58-08-2"). """ - return self.__check_digit + return self._check_digit # Sets the CAS Registry Number check digit @check_digit.setter @@ -134,4 +136,4 @@ def check_digit(self, digit_to_test: int) -> None: f"Invalid CAS number '{self.cas_string}' " f"(found check digit '{digit_to_test}', but expected '{check_sum % 10}')" ) - self.__check_digit = int(digit_to_test) + self._check_digit = int(digit_to_test) diff --git a/test/test_functionality.py b/test/test_functionality.py index bdab1be..1680799 100644 --- a/test/test_functionality.py +++ b/test/test_functionality.py @@ -78,21 +78,31 @@ def test_for_sorting(octanes, octanes_sorted): # Tests for error handling -@pytest.mark.xfail(raises=TypeError) +def test_cas_equal_invalid(caffeine): + with pytest.raises(TypeError): + assert caffeine == "theine" + + +def test_cas_lesser_than_invalid(l_lacticacid): + with pytest.raises(TypeError): + assert l_lacticacid < "D-lactic acid" + + def test_cas_invalid_input(): - CAS(6417.5) + with pytest.raises(TypeError): + CAS(6417.5) -@pytest.mark.xfail(raises=ValueError) def test_cas_format_unreadable(): - CAS("64 - 17 - 5") + with pytest.raises(ValueError): + CAS("64 - 17 - 5") -@pytest.mark.xfail(raises=ValueError) def test_cas_range_error(): - CAS(100) + with pytest.raises(ValueError): + CAS(100) -@pytest.mark.xfail(raises=ValueError) def test_cas_check_digit_error(): - CAS("64-17-6") + with pytest.raises(ValueError): + CAS("64-17-6") diff --git a/uv.lock b/uv.lock index 7fce871..91ea413 100644 --- a/uv.lock +++ b/uv.lock @@ -13,7 +13,7 @@ wheels = [ [[package]] name = "casregnum" -version = "1.1.0" +version = "1.1.1" source = { editable = "." } [package.dev-dependencies]