Skip to content

Commit

Permalink
new build system (#243)
Browse files Browse the repository at this point in the history
For my current PR #240 I'm adding `hypothesis` as a test dependency to allow generation of random input strings to better test parsing and escaping logic (see e44e4b3). I also changed how we load the grammar file, to make the package zip safe again (see 3cafe53). While working on how these could be integrated into our testsuite, I found out that `setup.py test` is deprecated ([1](pytest-dev/pytest#5534) [2](https://tox.readthedocs.io/en/latest/example/basic.html#integration-with-setup-py-test-command)). The recommendation was to use `tox` to test the generated package directly using `pytest` instead of relying on `setup.py` to test the sources. Additionally, there's a designated successor to `setup.py` and `setup.cfg` (in which we probably accumulated a few outdated definitions), the build-system independent `pyproject.toml`. Additionally, there are newer tools like `pipenv`, `flit` and `poetry` to help with the whole build and publishing process. As I was not quite happy with how the whole development process of ics.py was set up, I wanted to give them a shot. Collecting some opinion around the internet, it seemed that `flit` was mostly targeted at very simple low-configuration projects and the development of `pipenv` somehow stagnated, while `poetry` seemed to be a well suited solution.

So this PR contains my attempt at migrating to `poetry`, with all ics.py sources moved according to the new recommended format.
It's mostly the config files in the root directory that changed, but I also removed the `dev` directory as it should no longer be needed. Next to all files from the `./ics/` directory remain unchanged and are simply moved to `./src/ics/`. I didn't copy the tests over yet, as I plan to rewrite most of them in my other branch.
The first of the two main configuration files is now `pyproject.toml`, where all meta-information on the project and how it can be installed (i.e. dependencies) and built are stored (without the need to actually execute the file and have some specific setuptools lying around). The second is `tox.ini`, where all testing related functionality is configured. A third file `.bumpversion.cfg` is from a small tool that helps with updating the version number in all places when doing a new release. The `poetry.lock` file optionally stores the dependency versions against which we want to develop, which is independent from the versions the library pulls in as dependency itself, where we are pretty liberal, and the versions we test against, which is always the latest releases. All library sourcecode now resides within a `src` folder, which is recommended as it prevents you from accidentally having the sources in your PATH when you want to test the final package.

The root directory now looks very clean and all those files have their specific purpose. If you want to configure how testing is done, you find all information in [`tox.ini`](https://github.com/N-Coder/ics.py-poetry/blob/master/tox.ini). If you want to run the tests (i.e. pytest, doctest, flake8, mypy and check that the docs build), simply run `tox` - you don't have to worry about which versions in which venvs are installed and whether you're directly testing against the sources or against a built package, tox handles all that for you. This not only comes in very handy when running the tests manually, but should also ensure that [CI](https://github.com/N-Coder/ics.py-poetry/blob/master/.github/workflows/pythonpackage.yml) does exactly the same. On a side note, we're now again publishing [coverage data](https://codecov.io/gh/N-Coder/ics.py-poetry).

If you just want to run the tests and don't need to fiddle around with the development version of ics in an interactive shell, that's all you need. For the fiddling part, just run [`poetry install`](https://python-poetry.org/docs/cli/#install) and you will have a turnkey development environment set up. Use `poetry shell` or `poetry run` to easily access the venv poetry set up for you. Publishing is now also very simple: just call `poetry publish --build` and the tool will take care of the rest. This made it very easy to make some releases on the [testing pypi instance](https://test.pypi.org/project/ics/#history).

The third and last tool you might want is `bumpversion`, if you are making new releases. But there is no need anymore to handle any venvs yourself or to install all ics.py dependencies globally. To summarize, if you want to hit the ground running and publish a new release on a newly set-up machine, the following should suffice:

```bash
git clone https://github.com/N-Coder/ics.py-poetry.git && cd ics.py-poetry
pip install tox poetry bumpversion --user
tox # make sure all the test run
bumpversion --verbose release # 0.8.0-dev -> 0.8.0 (release)
poetry build # build the package
tox --recreate # ensure that the version numbers are consistent
# check changelog and amend if necessary
git push && git push --tags
poetry publish # publish to pypi
bumpversion --verbose minor # 0.8.0 (release) -> 0.9.0-dev
git push && git push --tags
```

You can try that out if you want -- except for the publishing part maybe. Also note that `bumpversion` directly makes a commit with the new version if you don't pass `--no-commit` or `--dry-run`, but that's no problem as you can easily amend any changes you want to make, e.g. to the changelog.

The above information on developing, testing and publishing can now also be found in the docs (see CONTRIBUTING.rst). As these changes are partially based upon #240 but are also quite fundamental, I wanted to collect feedback first before including the changes into #240. The only other thing #240 is still lacking is more testing (only few files already have close to 100% coverage), and I'd prefer to provide that using `tox` in this new environment. So that's also some kind of cyclic dependency.

Sorry for the (now superfluous) issue I opened before. So @C4ptainCrunch (and maybe also @aureooms and @tomschr), what's your opinion on this?

* migrate repo structure to poetry

* fix src path for pytest

* add doc skeleton

* implement handling of attachments

* import project files

* set version

* fix sphinx build with poetry

* don't use poetry within tox

see python-poetry/poetry#1941 (comment)

* fix timezone tests

* change coveralls action

* try codecov

* bugfixes

* add bumpversion

* separate src inspection (flake8+mypy src/) from package testing (pytest tests/) to fix PATH problems

* bugfixes

* Merge branch 'master' into new-parser-impl

* remove old files

* add dev and publish instructions

* checker happiness

`noqa` and `type: ignore` are now only used for actual bugs in the checkers
unfortunately, current pyflakes dislikes `type: ignore[something]`, so we can't ignore specific mypy bugs until pyflakes 2.2 is in flakes8

* more checker happiness

* Apply suggestions from code review

Co-Authored-By: Tom Schraitle <tomschr@users.noreply.github.com>

* use gitignore directly from github instead of gitignore.io

* Apply suggestions from code review to tox.ini

* fix tox.ini

* add pypy support

Mostly by moving/splitting test dependencies to different sections in
tox.ini as mypy and pypy don't work well together and it is sufficient
to run mypy checks on CPython.

* update developing documentation

* fix non-ASCII whitespace handling

* update test/dev dependencies
  • Loading branch information
N-Coder committed May 16, 2020
1 parent 52ef1f1 commit c8f05cb
Show file tree
Hide file tree
Showing 88 changed files with 108,893 additions and 21,913 deletions.
23 changes: 23 additions & 0 deletions .bumpversion.cfg
@@ -0,0 +1,23 @@
[bumpversion]
current_version = 0.8.0-dev
commit = True
tag = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)-?(?P<release>dev)?
serialize =
{major}.{minor}.{patch}-{release}
{major}.{minor}.{patch}

[bumpversion:file:pyproject.toml]

[bumpversion:file:src/ics/__init__.py]

[bumpversion:file:doc/event.rst]

[bumpversion:file:README.rst]

[bumpversion:part:release]
values =
dev
release
optional_value = release

2 changes: 0 additions & 2 deletions .coveragerc

This file was deleted.

20 changes: 10 additions & 10 deletions .github/workflows/pythonpackage.yml
Expand Up @@ -17,13 +17,13 @@ jobs:
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools
pip install -r requirements.txt -r dev/requirements-test.txt
- name: Static checking with mypy
run: |
mypy ics
- name: Run pytest
run: |
python setup.py test
- name: Report timezone information
run: python -c "import time; print((time.timezone, time.altzone, time.daylight, time.tzname, time.time()))"
- name: Install tox
run: python -m pip install --upgrade tox tox-gh-actions
- name: Run tox
run: tox
- name: Publish coverage
run:
rm -rf ./.mypy_cache/;
bash <(curl https://codecov.io/bash)
171 changes: 134 additions & 37 deletions .gitignore
@@ -1,45 +1,142 @@
# Compiled python modules.
*.pyc
/.idea
/venv
/.venv

# Setuptools distribution folder.
dist/
build/
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# Python egg metadata, regenerated from source files by setuptools.
/*.egg-info
/*.egg
# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Virtualenvs
ve
ve3

bin
include
lib
local
venv
venv3
/bin
/include/
/lib/

# doc builds
doc/_build/*

#tests
.cache/
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
htmlcov
.pytest_cache
/.pytest_cache/
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# IDE settings
/.idea/
# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# pffff
.idea
pip-selfcheck.json
/pip-selfcheck.json
share
# Cython debug symbols
cython_debug/
122 changes: 118 additions & 4 deletions CONTRIBUTING.rst
Expand Up @@ -16,8 +16,8 @@ How to submit an issue

Please include the following in your bug reports:

* the version of ics.py you are using; run ``pip freeze | grep ics``
* the version of Python ``python -v``
* the version of ics.py you are using; run :command:`pip freeze | grep ics`
* the version of Python :command:`python -v`
* the OS you are using

Please also include a (preferably minimal) example of the code or
Expand All @@ -33,6 +33,76 @@ you are solving it. This might save you a lot of time if the maintainers
are already working on it or have a specific idea on how the problem should
be solved.

Setting up the Development Environment
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

There are three Python tools required to develop, test, and release ics.py:

* `poetry <https://python-poetry.org/>`_ for managing virtualenvs, dependencies, building, and publishing the package.
* `tox <https://tox.readthedocs.io/>`_ for running the testsuite and building the documentation.
* `bump2version <https://pypi.org/project/bump2version/>`_ to help with making a release.

Their respective configuration files are :file:`pyproject.toml`, :file:`tox.ini` and :file:`.bumpversion.cfg`.
Install the tools via pip:

.. code-block:: bash
$ pip install tox poetry bump2version --user
.. note::
If you want to develop using multiple different Python versions, you might want to consider the
`poetry installer <https://python-poetry.org/docs/#installation>`_.

Poetry will automatically manage a virtualenv that you can use for developing.
By default, it will be located centrally in your home directory (e.g. in :file:`/home/user/.cache/pypoetry/virtualenvs/`).
To make poetry use a :file:`./.venv/` directory within the ics.py folder, use the following config:

.. code-block:: bash
$ poetry config virtualenvs.in-project true
Now you are ready to setup your development environment using the following command:

.. code-block:: bash
$ poetry install
This will create a new virtualenv and install the dependencies for using ics.py.
Furthermore, the current source of the ics.py package will be available similar to running :command:`./setup.py develop`.
To access the virtualenv, use :command:`poetry run python` or :command:`poetry shell`.
The :file:`poetry.lock` file locks the versions of dependencies in the development environment set up by poetry. This ensures that such an environment is the same for everyone.
The file :file:`poetry.lock` is only read by poetry and not included in any distributions. These restrictions don't apply when running :command:`pip install ics`.
As tox manages its own environments and doesn't read the lock file, it installs the latest versions of dependencies for testing.
More details on the poetry side can be found in the `poetry documentation <https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control>`_.

If you made some changes and now want to lint your code, run the testsuite, or build the documentation, run tox.
You don't have to worry about which versions in which venvs are installed and whether you're directly testing against the sources or against a built package, tox handles all that for you:

.. code-block:: bash
$ tox
To run a single task and not the whole testsuite, use the ``-e`` flag:

.. code-block:: bash
$ tox -e docs
To get a list of all available tasks, run :command:`tox -av`.

.. note::
If you want to run any tasks of tox manually, make sure you have all the dependencies of the task listed in :file:`tox.ini`.
For testing with pytest, this can be done through poetry by installing the ``test`` extra: :command:`poetry install -E test`.
Alternatively, you can also let tox `set up <https://tox.readthedocs.io/en/latest/example/devenv.html#creating-development-environments-using-the-devenv-option>`_ your development environment or re-use one of its test environments:

.. code-block:: bash
$ tox -e py38
$ source .tox/py38/bin/activate
(py38) $ pytest
This also works without having poetry installed.

If you are fixing a bug
^^^^^^^^^^^^^^^^^^^^^^^

Expand All @@ -55,8 +125,8 @@ We will ask you to provide:
Last thing
^^^^^^^^^^

* Please add yourself to ``AUTHORS.rst``
* and state your changes in ``CHANGELOG.rst``.
* Please add yourself to :file:`AUTHORS.rst`
* and state your changes in :file:`CHANGELOG.rst`.

.. note::
Your PR will most likely be squashed in a single commit, authored
Expand All @@ -66,3 +136,47 @@ Last thing

The title of your PR will become the commit message, please craft it
with care.

How to make a new release
-------------------------

If you want to publish a new release, use the following steps

.. code-block:: bash
# Grab the sources and install the dev tools
git clone https://github.com/C4ptainCrunch/ics.py.git && cd ics.py
pip install tox poetry bump2version --user
# Make sure all the test run
tox && echo "Ready to make a new release" \
|| echo "Please fix all the tests first"
# Bump the version and make a "0.8.0-dev -> 0.8.0 (release)" commit
bump2version --verbose release
# Build the package
poetry build
# Ensure that the version numbers are consistent
tox --recreate
# Check changelog and amend if necessary
vi CHANGELOG.rst && git commit -i CHANGELOG.rst --amend
# Publish to GitHub
git push && git push --tags
# Publish to PyPi
poetry publish
# Bump the version again to start development of next version
bump2version --verbose minor # 0.8.0 (release) -> 0.9.0-dev
# Start new changelog
vi CHANGELOG.rst && git commit -i CHANGELOG.rst --amend
# Publish to GitHub
git push && git push --tags
Please note that bump2version directly makes a commit with the new version if you don't
pass ``--no-commit`` or ``--dry-run``,
but that's no problem as you can easily amend any changes you want to make.
Further things to check:

* Check GitHub and PyPi release pages for obvious errors
* Build documentation for the tag v{version} on rtfd.org
* Set the default rtfd version to {version}
11 changes: 0 additions & 11 deletions MANIFEST.in

This file was deleted.

4 changes: 2 additions & 2 deletions README.rst
@@ -1,5 +1,5 @@
Ics.py : iCalendar for Humans
=============================
ics.py `0.8.0-dev` : iCalendar for Humans
=========================================

`Original repository <https://github.com/C4ptainCrunch/ics.py>`_ (GitHub) -
`Bugtracker and issues <https://github.com/C4ptainCrunch/ics.py/issues>`_ (GitHub) -
Expand Down

0 comments on commit c8f05cb

Please sign in to comment.