mirror of
https://github.com/samsonjs/vdirsyncer.git
synced 2026-04-27 14:57:41 +00:00
Merge pull request #354 from untitaker/packaging-guidelines
Add packaging guidelines
This commit is contained in:
commit
88547294a7
9 changed files with 150 additions and 34 deletions
|
|
@ -3,6 +3,8 @@ include CHANGELOG.rst
|
||||||
include LICENSE
|
include LICENSE
|
||||||
include config.example
|
include config.example
|
||||||
include Makefile
|
include Makefile
|
||||||
|
include test-requirements.txt
|
||||||
|
include docs-requirements.txt
|
||||||
|
|
||||||
recursive-include docs *
|
recursive-include docs *
|
||||||
recursive-include tests *
|
recursive-include tests *
|
||||||
|
|
|
||||||
18
Makefile
18
Makefile
|
|
@ -1,11 +1,4 @@
|
||||||
# Packagers who want to run the testsuite against an installed vdirsyncer:
|
# See the documentation on how to run the tests.
|
||||||
#
|
|
||||||
# - Create a virtualenv
|
|
||||||
# - Somehow link your installation of vdirsyncer into the virtualenv, e.g. by
|
|
||||||
# using --system-site-packages when creating the virtualenv
|
|
||||||
# - Inside the virtualenv: `make install-test test`
|
|
||||||
#
|
|
||||||
# The `install-test` target requires internet access.
|
|
||||||
|
|
||||||
export DAV_SERVER := skip
|
export DAV_SERVER := skip
|
||||||
export REMOTESTORAGE_SERVER := skip
|
export REMOTESTORAGE_SERVER := skip
|
||||||
|
|
@ -13,6 +6,7 @@ export RADICALE_BACKEND := filesystem
|
||||||
export REQUIREMENTS := release
|
export REQUIREMENTS := release
|
||||||
export TESTSERVER_BASE := ./tests/storage/servers/
|
export TESTSERVER_BASE := ./tests/storage/servers/
|
||||||
export TRAVIS := false
|
export TRAVIS := false
|
||||||
|
export DETERMINISTIC_TESTS := false
|
||||||
|
|
||||||
install-servers:
|
install-servers:
|
||||||
set -ex; \
|
set -ex; \
|
||||||
|
|
@ -28,14 +22,12 @@ install-servers:
|
||||||
|
|
||||||
install-test: install-servers
|
install-test: install-servers
|
||||||
(python --version | grep -vq 'Python 3.3') || pip install enum34
|
(python --version | grep -vq 'Python 3.3') || pip install enum34
|
||||||
|
pip install -r test-requirements.txt
|
||||||
set -xe && if [ "$$REQUIREMENTS" = "devel" ]; then \
|
set -xe && if [ "$$REQUIREMENTS" = "devel" ]; then \
|
||||||
pip install -U --force-reinstall \
|
pip install -U --force-reinstall \
|
||||||
git+https://github.com/DRMacIver/hypothesis \
|
git+https://github.com/DRMacIver/hypothesis \
|
||||||
git+https://github.com/pytest-dev/pytest; \
|
git+https://github.com/pytest-dev/pytest; \
|
||||||
else \
|
|
||||||
pip install pytest hypothesis; \
|
|
||||||
fi
|
fi
|
||||||
pip install pytest-xprocess pytest-localserver pytest-subtesthack
|
|
||||||
[ $(TRAVIS) != "true" ] || pip install coverage codecov
|
[ $(TRAVIS) != "true" ] || pip install coverage codecov
|
||||||
|
|
||||||
test:
|
test:
|
||||||
|
|
@ -62,7 +54,7 @@ travis-conf:
|
||||||
python3 scripts/make_travisconf.py > .travis.yml
|
python3 scripts/make_travisconf.py > .travis.yml
|
||||||
|
|
||||||
install-docs:
|
install-docs:
|
||||||
pip install sphinx sphinx_rtd_theme
|
pip install -r docs-requirements.txt
|
||||||
|
|
||||||
docs:
|
docs:
|
||||||
cd docs && make html
|
cd docs && make html
|
||||||
|
|
@ -88,7 +80,7 @@ install-dev:
|
||||||
set -xe && if [ "$$REQUIREMENTS" = "devel" ]; then \
|
set -xe && if [ "$$REQUIREMENTS" = "devel" ]; then \
|
||||||
pip install -U --force-reinstall git+https://github.com/kennethreitz/requests; \
|
pip install -U --force-reinstall git+https://github.com/kennethreitz/requests; \
|
||||||
elif [ "$$REQUIREMENTS" = "minimal" ]; then \
|
elif [ "$$REQUIREMENTS" = "minimal" ]; then \
|
||||||
pip install -U --force-reinstall lxml==3.1 requests==2.4.1 requests_toolbelt==0.4.0 click==5.0; \
|
pip install -U --force-reinstall $$(python setup.py --quiet minimal_requirements); \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
.PHONY: docs
|
.PHONY: docs
|
||||||
|
|
|
||||||
2
docs-requirements.txt
Normal file
2
docs-requirements.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
sphinx
|
||||||
|
sphinx_rtd_theme
|
||||||
|
|
@ -29,6 +29,7 @@ Table of Contents
|
||||||
problems
|
problems
|
||||||
vdir
|
vdir
|
||||||
contributing
|
contributing
|
||||||
|
packaging
|
||||||
contact
|
contact
|
||||||
changelog
|
changelog
|
||||||
license
|
license
|
||||||
|
|
|
||||||
65
docs/packaging.rst
Normal file
65
docs/packaging.rst
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
====================
|
||||||
|
Packaging guidelines
|
||||||
|
====================
|
||||||
|
|
||||||
|
Thank you very much for packaging vdirsyncer! The following guidelines should
|
||||||
|
help you to avoid some common pitfalls.
|
||||||
|
|
||||||
|
While they are called guidelines and therefore theoretically not mandatory, if
|
||||||
|
you consider going a different direction, please first open an issue or contact
|
||||||
|
me otherwise instead of just going ahead. These guidelines exist for my own
|
||||||
|
convenience too.
|
||||||
|
|
||||||
|
Obtaining the source code
|
||||||
|
=========================
|
||||||
|
|
||||||
|
The main distribution channel is `PyPI
|
||||||
|
<https://pypi.python.org/pypi/vdirsyncer>`_, and source tarballs can be
|
||||||
|
obtained there. Do not use the ones from GitHub: Their tarballs contain useless
|
||||||
|
junk and are more of a distraction than anything else.
|
||||||
|
|
||||||
|
I give each release a tag in the git repo. If you want to get notified of new
|
||||||
|
releases, `GitHub's feed
|
||||||
|
<https://github.com/untitaker/vdirsyncer/releases.atom>`_ is a good way.
|
||||||
|
|
||||||
|
Dependency versions
|
||||||
|
===================
|
||||||
|
|
||||||
|
It is strongly discouraged to package vdirsyncer as a Python 2 application.
|
||||||
|
Future releases will only work on Python 3.3 and newer versions.
|
||||||
|
|
||||||
|
As with most Python packages, ``setup.py`` denotes the runtime dependencies of
|
||||||
|
vdirsyncer. It also contains lower-bound versions of each dependency. Older
|
||||||
|
versions will be rejected by the testsuite.
|
||||||
|
|
||||||
|
Testing
|
||||||
|
=======
|
||||||
|
|
||||||
|
Everything testing-related goes through the ``Makefile`` in the root of the
|
||||||
|
repository or PyPI package. Trying to e.g. run ``py.test`` directly will
|
||||||
|
require a lot of environment variables to be set (for configuration) and you
|
||||||
|
probably don't want to deal with that.
|
||||||
|
|
||||||
|
You can install the testing dependencies with ``make test-install``. You
|
||||||
|
probably don't want this since it will use pip to download the dependencies.
|
||||||
|
Alternatively you can find the testing dependencies in
|
||||||
|
``test-requirements.txt``, again with lower-bound version requirements.
|
||||||
|
|
||||||
|
You also have to have vdirsyncer fully installed at this point. Merely
|
||||||
|
``cd``-ing into the tarball will not be sufficient.
|
||||||
|
|
||||||
|
Running the tests happens with ``make test``.
|
||||||
|
|
||||||
|
Hypothesis will randomly generate test input. If you care about deterministic
|
||||||
|
tests, set the ``DETERMINISTIC_TESTS`` variable to ``"true"``::
|
||||||
|
|
||||||
|
make DETERMINISTIC_TESTS=true test
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
=============
|
||||||
|
|
||||||
|
You can find a list of dependencies in ``docs-requirements.txt``.
|
||||||
|
|
||||||
|
Change into the ``docs/`` directory and build whatever format you want. That
|
||||||
|
said, I only take care of the HTML docs' formatting -- other targets (such as
|
||||||
|
the generated manpage) may look like garbage.
|
||||||
65
setup.py
65
setup.py
|
|
@ -12,9 +12,48 @@ Vdirsyncer is a synchronization tool for vdir. See the README for more details.
|
||||||
|
|
||||||
import platform
|
import platform
|
||||||
|
|
||||||
from setuptools import find_packages, setup
|
from setuptools import Command, find_packages, setup
|
||||||
|
|
||||||
|
|
||||||
|
requirements = [
|
||||||
|
# https://github.com/mitsuhiko/click/issues/200
|
||||||
|
'click>=5.0',
|
||||||
|
'click-log>=0.1.3',
|
||||||
|
'click-threading>=0.1.2',
|
||||||
|
# https://github.com/kennethreitz/requests/issues/2930
|
||||||
|
'requests >=2.0.1, !=2.9.0',
|
||||||
|
'lxml >=3.1' + (
|
||||||
|
# See https://github.com/untitaker/vdirsyncer/issues/298
|
||||||
|
# We pin some LXML version that is known to work with PyPy
|
||||||
|
# I assume nobody actually uses PyPy with vdirsyncer, so this is
|
||||||
|
# moot
|
||||||
|
', <=3.4.4'
|
||||||
|
if platform.python_implementation() == 'PyPy'
|
||||||
|
else ''
|
||||||
|
),
|
||||||
|
# https://github.com/sigmavirus24/requests-toolbelt/pull/28
|
||||||
|
'requests_toolbelt >=0.3.0',
|
||||||
|
# https://github.com/untitaker/python-atomicwrites/commit/4d12f23227b6a944ab1d99c507a69fdbc7c9ed6d # noqa
|
||||||
|
'atomicwrites>=0.1.7'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class PrintRequirements(Command):
|
||||||
|
|
||||||
|
description = 'Prints minimal requirements'
|
||||||
|
|
||||||
|
user_options = []
|
||||||
|
|
||||||
|
def initialize_options(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def finalize_options(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
for requirement in requirements:
|
||||||
|
print(requirement.replace(">", "=").replace(" ", ""))
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='vdirsyncer',
|
name='vdirsyncer',
|
||||||
use_scm_version={
|
use_scm_version={
|
||||||
|
|
@ -32,27 +71,11 @@ setup(
|
||||||
entry_points={
|
entry_points={
|
||||||
'console_scripts': ['vdirsyncer = vdirsyncer.cli:main']
|
'console_scripts': ['vdirsyncer = vdirsyncer.cli:main']
|
||||||
},
|
},
|
||||||
install_requires=[
|
install_requires=requirements,
|
||||||
# https://github.com/mitsuhiko/click/issues/200
|
|
||||||
'click>=5.0',
|
|
||||||
'click-log',
|
|
||||||
'click-threading',
|
|
||||||
# https://github.com/kennethreitz/requests/issues/2930
|
|
||||||
'requests !=2.9.0',
|
|
||||||
'lxml >=3.1' + (
|
|
||||||
# See https://github.com/untitaker/vdirsyncer/issues/298
|
|
||||||
# We pin some LXML version that is known to work with PyPy
|
|
||||||
# I assume nobody actually uses PyPy with vdirsyncer, so this is
|
|
||||||
# moot
|
|
||||||
', <=3.4.4'
|
|
||||||
if platform.python_implementation() == 'PyPy'
|
|
||||||
else ''
|
|
||||||
),
|
|
||||||
# https://github.com/sigmavirus24/requests-toolbelt/pull/28
|
|
||||||
'requests_toolbelt >=0.5.0',
|
|
||||||
'atomicwrites'
|
|
||||||
],
|
|
||||||
extras_require={
|
extras_require={
|
||||||
'remotestorage': ['requests-oauthlib']
|
'remotestorage': ['requests-oauthlib']
|
||||||
|
},
|
||||||
|
cmdclass={
|
||||||
|
'minimal_requirements': PrintRequirements
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
5
test-requirements.txt
Normal file
5
test-requirements.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
hypothesis>=3
|
||||||
|
pytest
|
||||||
|
pytest-localserver
|
||||||
|
pytest-subtesthack
|
||||||
|
pytest-xprocess
|
||||||
|
|
@ -8,12 +8,22 @@ from click.testing import CliRunner
|
||||||
from hypothesis import example, given
|
from hypothesis import example, given
|
||||||
import hypothesis.strategies as st
|
import hypothesis.strategies as st
|
||||||
|
|
||||||
|
from pkg_resources import load_entry_point
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import vdirsyncer.cli as cli
|
import vdirsyncer.cli as cli
|
||||||
from vdirsyncer.utils.compat import PY2, to_native
|
from vdirsyncer.utils.compat import PY2, to_native
|
||||||
|
|
||||||
|
|
||||||
|
def test_entry_points(monkeypatch, capsys):
|
||||||
|
monkeypatch.setattr('sys.argv', ['--help'])
|
||||||
|
with pytest.raises(SystemExit) as excinfo:
|
||||||
|
load_entry_point('vdirsyncer', 'console_scripts', 'vdirsyncer')()
|
||||||
|
|
||||||
|
assert excinfo.value.code == 0
|
||||||
|
|
||||||
|
|
||||||
def test_simple_run(tmpdir, runner):
|
def test_simple_run(tmpdir, runner):
|
||||||
runner.write_with_general(dedent('''
|
runner.write_with_general(dedent('''
|
||||||
[pair my_pair]
|
[pair my_pair]
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,12 @@
|
||||||
General-purpose fixtures for vdirsyncer's testsuite.
|
General-purpose fixtures for vdirsyncer's testsuite.
|
||||||
'''
|
'''
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
import click_log
|
import click_log
|
||||||
|
|
||||||
|
from hypothesis import Verbosity, settings
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -27,3 +30,16 @@ except ImportError:
|
||||||
return lambda x: x()
|
return lambda x: x()
|
||||||
else:
|
else:
|
||||||
del pytest_benchmark
|
del pytest_benchmark
|
||||||
|
|
||||||
|
settings.register_profile("ci", settings(
|
||||||
|
max_examples=1000,
|
||||||
|
verbosity=Verbosity.verbose,
|
||||||
|
))
|
||||||
|
settings.register_profile("deterministic", settings(
|
||||||
|
derandomize=True,
|
||||||
|
))
|
||||||
|
|
||||||
|
if os.getenv('DETERMINISTIC_TESTS').lower == 'true':
|
||||||
|
settings.load_profile("deterministic")
|
||||||
|
elif os.getenv('TRAVIS').lower == 'true':
|
||||||
|
settings.load_profile("ci")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue