diff --git a/.gitignore b/.gitignore index 61c8bde7..8eaad1eb 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,5 @@ src/icalendar.egg-info/ !.gitignore venv /ical_fuzzer.pkg.spec +/src/icalendar/_version.py + diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..d777b1e1 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,198 @@ +# +# We use the pyproject.toml package specification. +# See https://packaging.python.org/en/latest/guides/section-build-and-publish/ +# See https://github.com/collective/icalendar/issues/686 +# See https://packaging.python.org/en/latest/specifications/pyproject-toml/#license +# + +# TODO: +# - plone developers email still in use for this? +# - setup.cfg +# - tox test dependencies +# - In the readme, link to these: +# "CONTRIBUTING.rst", +# "CHANGES.rst", +# "LICENSE.rst" +# - from setup.py: +# - license='BSD-2-Clause', +# - packages=setuptools.find_namespace_packages('src', exclude=["icalendar.fuzzing"]), +# - package_dir={'': 'src'}, +# - include_package_data=True, +# - zip_safe=False +# - test_suite='icalendar.tests' +# DONE: +# - ruff in tox +# - version.py +# - long_description_content_type="text/x-rst", + + +[build-system] +requires = ["hatchling", "hatch-vcs"] +build-backend = "hatchling.build" + +[project] +name = "icalendar" +license = { file = "LICENSE.rst", name = "BSD-2-Clause" } +# name = "BSD-2-Clause", # TODO: is this the right short key +keywords = [ + "calendar", + "calendaring", + "ical", + "icalendar", + "event", + "todo", + "journal", + "recurring", +] +authors = [ + { name="Plone Foundation", email="plone-developers@lists.sourceforge.net" }, +] +maintainers = [ + { name="Nicco Kunzmann", email="niccokunzmann@rambler.ru" }, + { name="Christian Geier" }, + { name="Jaca", email="vitouejj@gmail.com" }, +] +# These attributes are dynamically generated by hatch-vcs +dynamic = [ + "urls", + "version" +] +description = "iCalendar parser/generator" +readme = { file = "README.rst", content-type = "text/x-rst" } + +# +# When adjusting the Python Version, adjust also: +# - .github/workflows/tests.yml +# - the classifiers below +# - the documentation +# - the README file +# - dependencies for 3.8, Python 3.13 will come our October, too +# - tool.ruff.target-version +# +requires-python = ">=3.8" + +# see https://pypi.python.org/pypi?%3Aaction=list_classifiers +classifiers = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "License :: OSI Approved :: BSD License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3.8", + "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", +] + +dependencies = [ + "python-dateutil", + # install requirements depending on python version, TODO: Remove with Python 3.8 + # see https://www.python.org/dev/peps/pep-0508/#environment-markers + "backports.zoneinfo; python_version < '3.9'", + "tzdata" +] + +[project.optional-dependencies] +test = [ + "pytest", + "coverage", + "hypothesis", + "pytz", +] + +[project.scripts] +icalendar = "icalendar.cli:main" + +[tool.hatch.metadata.hooks.vcs.urls] +# This is a dynamic generation of [project.urls] +Homepage = "https://icalendar.readthedocs.io/" +Repository = "https://github.com/collective/icalendar/" +source_archive = "https://github.com/collective/icalendar/archive/{commit_hash}.zip" +Issues = "https://github.com/collective/icalendar/issues" +Documentation = "https://icalendar.readthedocs.io/" +Changelog = "https://icalendar.readthedocs.io/en/latest/changelog.html" + +[tool.hatch.version] +# This configuration allows us to use the version from the tags and dynamically generate +# version files. This speeds up the release process. +source = "vcs" + +[tool.hatch.version.raw-options] +# see https://github.com/ofek/hatch-vcs/issues/43#issuecomment-1553065222 +local_scheme = "no-local-version" + +[tool.hatch.build.hooks.vcs] +version-file = "src/icalendar/_version.py" + +[tool.hatch.metadata] +allow-direct-references = true + +[tool.ruff] +target-version = "py38" + +[tool.ruff.lint] +select = ["ALL"] +ignore = [ + "ANN", # flake8-annotations + "B020", # Loop control variable {name} overrides iterable it iterates + "C401", # Unnecessary generator (rewrite as a set comprehension) + "C901", # {name} is too complex ({complexity} > {max_complexity}) + "COM812", # Trailing comma missing + "D1", # Missing docstring + "D2", # docstrings stuffs + "D4", # docstrings stuffs + "EM10", # Exception string usage + "ERA001", # Found commented-out code + "FBT002", # Boolean default positional argument in function definition + "FIX", # TODO comments + "ISC001", # Implicitly concatenated string literals on one line (to avoid with formatter) + "N818", # Exception name {name} should be named with an Error suffix + "PLR091", # Too many things (complexity, arguments, branches, etc...) + "PLR2004", # Magic value used in comparison, consider replacing {value} with a constant variable + "RUF012", # Mutable class attributes should be annotated with typing.ClassVar + "RUF015", # Prefer next({iterable}) over single element slice + "S101", # Use of assert detected + "TD", # TODO comments + "TRY003", # Avoid specifying long messages outside the exception class + "S104", # Possible binding to all interfaces + "E722", # Do not use bare `except` + "RUF005", # Consider iterable unpacking instead of concatenation + "DTZ005", # `datetime.datetime.now()` called without a `tz` argument + "PERF401", # Use a list comprehension to create a transformed list + "ARG002", # Unused method argument: ... + "ARG001", # Unused function argument: ... +] +extend-safe-fixes = [ + "PT006", # Wrong type passed to first argument of @pytest.mark.parametrize; expected {expected_string} +] + +[tool.ruff.lint.per-file-ignores] +"src/icalendar/tests/*" = [ + "B011", # Do not assert False (python -O removes these calls), raise AssertionError() + "DTZ001", # datetime.datetime() called without a tzinfo argument + "E501", # Indentation is not a multiple of {indent_size} + "N802", # Function name {name} should be lowercase + "PT011", # pytest.raises({exception}) is too broad, set the match parameter or use a more specific exception + "PT012", # pytest.raises() block should contain a single simple statement + "PT015", # Assertion always fails, replace with pytest.fail() + "T201", # print found + "T203", # `pprint` found + "RUF001", # String contains ambiguous character +] + +[tool.pytest.ini_options] +# see https://docs.pytest.org/en/6.2.x/customize.html +minversion = "6.0" +# see https://docs.pytest.org/en/6.2.x/reference.html?highlight=testpaths#confval-testpaths +testpaths = [ + "src/icalendar/tests", +] +# see https://docs.pytest.org/en/6.2.x/reference.html?highlight=testpaths#confval-norecursedirs +norecursedirs = [ + "src/icalendar/tests/hypothesis", + "build", +] + diff --git a/setup.cfg b/setup.cfg.bak similarity index 100% rename from setup.cfg rename to setup.cfg.bak diff --git a/setup.py b/setup.py.bak similarity index 100% rename from setup.py rename to setup.py.bak diff --git a/src/icalendar/version.py b/src/icalendar/version.py new file mode 100644 index 00000000..23690077 --- /dev/null +++ b/src/icalendar/version.py @@ -0,0 +1,13 @@ +"""Version file as a stable interface for the generated _version.py file.""" +try: + from ._version import __version__, __version_tuple__, version, version_tuple +except ModuleNotFoundError: + __version__ = version = "0.0.0dev0" + __version_tuple__ = version_tuple = (0, 0, 0, "dev0") + +__all__ = [ + "__version__", + "version", + "__version_tuple__", + "version_tuple", +] diff --git a/tox.ini b/tox.ini index cb9ce787..96ebb8d3 100644 --- a/tox.ini +++ b/tox.ini @@ -8,10 +8,7 @@ envlist = py38,py39,py310,py311,312,pypy3,docs,nopytz [testenv] usedevelop=True deps = - pytest - coverage - hypothesis - pytz + -e .[test] commands = coverage run --branch --source=src/icalendar --omit=*/tests/hypothesis/* --omit=*/tests/fuzzed/* --module pytest [] coverage report @@ -45,3 +42,11 @@ changedir = docs allowlist_externals = make commands = make html + +[testenv:ruff] +# use tox -e ruff to format the code base +deps = ruff +skip_install = True +commands = + ruff format + ruff check --fix