Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ on:
branches: [ main ]

jobs:
test:
code-tests:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.9", "3.10", "3.11", "3.12"]
python-version: ["3.10", "3.12"]

steps:
- uses: actions/checkout@v4
Expand All @@ -28,10 +28,15 @@ jobs:
- name: Install dependencies
run: uv sync --dev

- name: Run tests with coverage
run: uv run pytest -v --cov=src --cov-report=term --cov-report=xml
- name: Run tests with coverage (as defined in pyproject.toml)
run: uv run pytest

lint:
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}

code-quality:
runs-on: ubuntu-latest

steps:
Expand All @@ -44,6 +49,9 @@ jobs:

- name: Install dependencies
run: uv sync --dev

- name: Run ruff linting
run: uv run ruff check src tests

- name: Run mypy type checking
run: uv run mypy src tests --show-error-codes --show-error-context
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
- name: Smoke test (wheel)
run: |
WHEEL=$(ls dist/*.whl)
uv run --isolated --no-project -p 3.12 --with "$WHEEL" python -c "from chemformula import ChemFormula; print('Import successful'); water=ChemFormula('H2O'); print('Formula Weight:', water.formula_weight, 'g/mol')"
uv run --isolated --no-project -p 3.13 --with "$WHEEL" python -c "from chemformula import ChemFormula; print('Import successful'); water=ChemFormula('H2O'); print('Formula Weight:', water.formula_weight, 'g/mol')"

- name: Publish to PyPI
run: uv publish --trusted-publishing always
224 changes: 134 additions & 90 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion examples/example1.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
print(f" {stringElementSymbol:<2}: {floatElementFraction * 100:>5.2f} %")

print("\n--- Is Uranophane Radioactive and Charged? ---")
print(f" Yes, {uranophane.name} is radioactive.") if uranophane.radioactive else print(f" No, {uranophane.name} is not radioactive.") # noqa: E501
print(f" Yes, {uranophane.name} is radioactive.") if uranophane.is_radioactive else print(f" No, {uranophane.name} is not radioactive.") # noqa: E501
print(f" Yes, {uranophane.name} is charged.") if uranophane.charged else print(f" No, {uranophane.name} is not charged.")

print("\n--- Accessing Single Elements through FormulaObject.Element['Element_Symbol'] ---")
Expand Down
2 changes: 1 addition & 1 deletion examples/example2.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
print(f" {stringElementSymbol:<2}: {floatElementFraction * 100:>5.2f} %")

print("\n--- Is L-(+)-Muscarine Radioactive and Charged? ---")
print(f" Yes, {muscarine.name} is radioactive.") if muscarine.radioactive else print(f" No, {muscarine.name} is not radioactive.") # noqa: E501
print(f" Yes, {muscarine.name} is radioactive.") if muscarine.is_radioactive else print(f" No, {muscarine.name} is not radioactive.") # noqa: E501
print(f" Yes, {muscarine.name} is charged.") if muscarine.charged else print(f" No, {muscarine.name} is not charged.")

print("\n--- Accessing Single Elements through FormulaObject.Element['Element_Symbol'] ---")
Expand Down
18 changes: 18 additions & 0 deletions examples/example5.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import chemformula.config
from chemformula import ChemFormula

chemformula.config.AllowHydrogenIsotopes = True # Enable usage of hydrogen isotopes like Deuterium ("D") and Tritium ("T")

water = ChemFormula("H2O")
heavy_water = ChemFormula("D2O")

print("\n--- Isotopes in ChemFormula Objects ---")
print(f" Yes, {water.unicode} contains specific isotopes.") if water.contains_isotopes else print(f" No, {water.unicode} contains no specific isotopes.") # noqa: E501
print(f" Yes, {heavy_water.unicode} contains specific isotopes.\n") if heavy_water.contains_isotopes else print(f" No, {heavy_water.unicode} contains no specific isotopes.\n") # noqa: E501

# OUTPUT:
#
# --- Isotopes in ChemFormula Objects ---
# No, H₂O contains no specific isotopes.
# Yes, D₂O contains specific isotopes.
#
4 changes: 2 additions & 2 deletions examples/example_general.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
print(f" {stringElementSymbol:<2}: {floatElementFraction * 100:>5.2f} %")

print(f"\n--- {uranophane.name} and {muscarine.name} ---")
print(f" Yes, {uranophane.name} is radioactive.") if uranophane.radioactive else print(f" No, {uranophane.name} is not radioactive.") # noqa: E501
print(f" Yes, {uranophane.name} is radioactive.") if uranophane.is_radioactive else print(f" No, {uranophane.name} is not radioactive.") # noqa: E501
print(f" Yes, {uranophane.name} is charged.") if uranophane.charged else print(f" No, {uranophane.name} is not charged.")
print(f" Yes, {muscarine.name} is radioactive.") if muscarine.radioactive else print(f" No, {muscarine.name} is not radioactive.") # noqa: E501
print(f" Yes, {muscarine.name} is radioactive.") if muscarine.is_radioactive else print(f" No, {muscarine.name} is not radioactive.") # noqa: E501
print(f" Yes, {muscarine.name} is charged.") if muscarine.charged else print(f" No, {muscarine.name} is not charged.")

print('\n--- Accessing Single Elements through FormulaObject.Element["Element_Symbol"] ---')
Expand Down
25 changes: 16 additions & 9 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "chemformula"
version = "1.4.1"
version = "1.5.0"
description = "ChemFormula is a Python class for working with chemical formulas. It allows parsing chemical formulas, generating formatted output strings and calculating formula weights."
readme = "README.md"
authors = [
Expand All @@ -9,12 +9,14 @@ authors = [
maintainers = [
{name = "Axel Müller", email = "molshape@gmx.net"},
]
requires-python = ">=3.9"
requires-python = ">=3.10"
dependencies = [
"casregnum",
"casregnum>=1.1.2",
]
classifiers = [
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Operating System :: OS Independent",
"License :: OSI Approved :: MIT License",
"Topic :: Scientific/Engineering :: Chemistry",
Expand All @@ -34,11 +36,12 @@ build-backend = "hatchling.build"

[tool.uv]
dev-dependencies = [
"pytest",
"pytest-sugar",
"pytest-cov",
"ruff",
"twine",
"mypy>=1.18.1",
"pytest>=8.4.1",
"pytest-cov>=7.0.0",
"pytest-sugar>=1.1.1",
"ruff>=0.13.0",
"twine>=6.2.0",
]

[tool.pytest.ini_options]
Expand All @@ -50,6 +53,10 @@ addopts = [
"--strict-markers",
"--strict-config",
"--verbose",
"--cov=src",
"--cov-branch",
"--cov-report=term",
"--cov-report=xml",
]

[tool.ruff]
Expand Down
6 changes: 6 additions & 0 deletions src/chemformula/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
__all__ = ["ChemFormula"]
from .chemformula import ChemFormula

try:
from importlib.metadata import version
__version__ = version("chemformula")
except ImportError: # pragma: no cover
__version__ = "unknown" # pragma: no cover
Loading
Loading