[RFC] Add a setup.py so Patchwork can be pip-installed
Stephen Finucane
stephen at that.guru
Thu May 7 23:29:30 AEST 2020
On Tue, 2020-04-28 at 17:36 -0400, Jeremy Cline wrote:
> Recently I needed to deploy Patchwork and I noticed it was missing a
> setup.py. This is a first draft at adding one and making Patchwork easy
> to install with pip.
>
> To do this, static files and templates are moved within the Python
> package. "htdocs" is renamed to "static" which is the default location
> Django searches for static files. The two templates directories have
> been merged - I'm not sure why there are two so this perhaps breaks
> something I'm not aware of.
>
> With this change you should be able to do something like:
>
> $ python3 setup.py sdist
> $ python3 -m venv ~/.virtualenvs/pw
> $ source ~/.virtualenvs/pw/bin/activate
> $ pip install dist/patchwork-3.0.0a1.tar.gz
> $ DJANGO_SETTINGS_MODULE=patchwork.settings.dev PW_TEST_DB_TYPE=sqlite \
> django-admin migrate
> $ DJANGO_SETTINGS_MODULE=patchwork.settings.dev PW_TEST_DB_TYPE=sqlite \
> django-admin runserver
>
> I poked around the web UI and everything seems to work as expected, but
> it's quite likely I've missed something. This change would obviously
> also require updating the installation documentation, but before I go
> any further I'd love some feedback on this. Is this something people are
> interested in?
>
> My motivation for this is that I've got a little Django app that runs
> alongside Patchwork and would prefer it to be a simple "pip install" to
> get everything set up.
Sorry for the delay getting to this /o\ I've considered doing this
myself for some time and the main reason I hadn't was because Patchwork
isn't really packaged as a library or something reusable - it's an
application (in the packaging sense of the word [1]). As such, I'm not
sure how much sense there would be in publishing Patchwork to PyPI and,
for me at least, a setup.py file only real makes sense in that context
[2].
With that said, you've suggested that this is beneficial for you at
least. Could you go into a little more on this? I'd have suspected an
Ansible playbook or production Docker container to be far more useful
because they'd include things like nginx/Apache setup, etc. Is that not
the case?
Cheers,
Stephen
[1] https://caremad.io/posts/2013/07/setup-vs-requirement/
[2] Yes, you have distutils commands, but there are almost always
alternatives you can use for this.
> Signed-off-by: Jeremy Cline <jcline at redhat.com>
> ---
> MANIFEST.in | 7 ++
> htdocs/js/jquery-1.10.1.min.js | 1 -
> htdocs/js/jquery.checkboxes-1.0.6.min.js | 1 -
> htdocs/js/jquery.stickytableheaders.min.js | 1 -
> htdocs/js/jquery.tablednd.js | 1 -
> patchwork/settings/base.py | 4 +-
> {htdocs => patchwork/static}/README.rst | 0
> .../static}/css/bootstrap.min.css | 0
> .../static}/css/selectize.bootstrap3.css | 0
> {htdocs => patchwork/static}/css/style.css | 0
> .../fonts/glyphicons-halflings-regular.eot | Bin
> .../fonts/glyphicons-halflings-regular.svg | 0
> .../fonts/glyphicons-halflings-regular.ttf | Bin
> .../fonts/glyphicons-halflings-regular.woff | Bin
> .../static}/js/bootstrap.min.js | 0
> {htdocs => patchwork/static}/js/bundle.js | 0
> .../static}/js/clipboard.min.js | 0
> patchwork/static/js/jquery-1.10.1.min.js | 1 +
> .../static/js/jquery.checkboxes-1.0.6.min.js | 1 +
> .../js/jquery.stickytableheaders.min.js | 1 +
> patchwork/static/js/jquery.tablednd.js | 1 +
> .../static}/js/selectize.min.js | 0
> {templates => patchwork/templates}/404.html | 0
> {templates => patchwork/templates}/base.html | 0
> .../registration/password_change_done.html | 0
> .../registration/password_change_form.html | 0
> .../registration/password_reset_complete.html | 0
> .../registration/password_reset_confirm.html | 0
> .../registration/password_reset_done.html | 0
> .../registration/password_reset_email.html | 0
> .../registration/password_reset_form.html | 0
> requirements-test.txt | 2 +-
> setup.py | 69 ++++++++++++++++++
> 33 files changed, 83 insertions(+), 7 deletions(-)
> create mode 100644 MANIFEST.in
> delete mode 120000 htdocs/js/jquery-1.10.1.min.js
> delete mode 120000 htdocs/js/jquery.checkboxes-1.0.6.min.js
> delete mode 120000 htdocs/js/jquery.stickytableheaders.min.js
> delete mode 120000 htdocs/js/jquery.tablednd.js
> rename {htdocs => patchwork/static}/README.rst (100%)
> rename {htdocs => patchwork/static}/css/bootstrap.min.css (100%)
> rename {htdocs => patchwork/static}/css/selectize.bootstrap3.css (100%)
> rename {htdocs => patchwork/static}/css/style.css (100%)
> rename {htdocs => patchwork/static}/fonts/glyphicons-halflings-regular.eot (100%)
> rename {htdocs => patchwork/static}/fonts/glyphicons-halflings-regular.svg (100%)
> rename {htdocs => patchwork/static}/fonts/glyphicons-halflings-regular.ttf (100%)
> rename {htdocs => patchwork/static}/fonts/glyphicons-halflings-regular.woff (100%)
> rename {htdocs => patchwork/static}/js/bootstrap.min.js (100%)
> rename {htdocs => patchwork/static}/js/bundle.js (100%)
> rename {htdocs => patchwork/static}/js/clipboard.min.js (100%)
> create mode 120000 patchwork/static/js/jquery-1.10.1.min.js
> create mode 120000 patchwork/static/js/jquery.checkboxes-1.0.6.min.js
> create mode 120000 patchwork/static/js/jquery.stickytableheaders.min.js
> create mode 120000 patchwork/static/js/jquery.tablednd.js
> rename {htdocs => patchwork/static}/js/selectize.min.js (100%)
> rename {templates => patchwork/templates}/404.html (100%)
> rename {templates => patchwork/templates}/base.html (100%)
> rename {templates => patchwork/templates}/registration/password_change_done.html (100%)
> rename {templates => patchwork/templates}/registration/password_change_form.html (100%)
> rename {templates => patchwork/templates}/registration/password_reset_complete.html (100%)
> rename {templates => patchwork/templates}/registration/password_reset_confirm.html (100%)
> rename {templates => patchwork/templates}/registration/password_reset_done.html (100%)
> rename {templates => patchwork/templates}/registration/password_reset_email.html (100%)
> rename {templates => patchwork/templates}/registration/password_reset_form.html (100%)
> create mode 100755 setup.py
>
> diff --git a/MANIFEST.in b/MANIFEST.in
> new file mode 100644
> index 0000000..8d20fbf
> --- /dev/null
> +++ b/MANIFEST.in
> @@ -0,0 +1,7 @@
> +include COPYING CONTRIBUTING.rst README.rst
> +include requirements-prod.txt requirements-test.txt
> +recursive-include patchwork/static *.js *.css *.png *.ico *.eot *.svg *.ttf *.woff *.woff2
> +recursive-include patchwork/templates *.html *.txt
> +recursive-include patchwork/fixtures *.xml
> +graft docs
> +prune docs/_build
> diff --git a/htdocs/js/jquery-1.10.1.min.js b/htdocs/js/jquery-1.10.1.min.js
> deleted file mode 120000
> index d48d893..0000000
> --- a/htdocs/js/jquery-1.10.1.min.js
> +++ /dev/null
> @@ -1 +0,0 @@
> -../../lib/packages/jquery/jquery-1.10.1.min.js
> \ No newline at end of file
> diff --git a/htdocs/js/jquery.checkboxes-1.0.6.min.js b/htdocs/js/jquery.checkboxes-1.0.6.min.js
> deleted file mode 120000
> index dfef5d4..0000000
> --- a/htdocs/js/jquery.checkboxes-1.0.6.min.js
> +++ /dev/null
> @@ -1 +0,0 @@
> -../../lib/packages/jquery/jquery.checkboxes-1.0.6.min.js
> \ No newline at end of file
> diff --git a/htdocs/js/jquery.stickytableheaders.min.js b/htdocs/js/jquery.stickytableheaders.min.js
> deleted file mode 120000
> index 0c22fa9..0000000
> --- a/htdocs/js/jquery.stickytableheaders.min.js
> +++ /dev/null
> @@ -1 +0,0 @@
> -../../lib/packages/jquery/jquery.stickytableheaders.min.js
> \ No newline at end of file
> diff --git a/htdocs/js/jquery.tablednd.js b/htdocs/js/jquery.tablednd.js
> deleted file mode 120000
> index ed51ba1..0000000
> --- a/htdocs/js/jquery.tablednd.js
> +++ /dev/null
> @@ -1 +0,0 @@
> -../../lib/packages/jquery/jquery.tablednd.js
> \ No newline at end of file
> diff --git a/patchwork/settings/base.py b/patchwork/settings/base.py
> index 001878a..e72d809 100644
> --- a/patchwork/settings/base.py
> +++ b/patchwork/settings/base.py
> @@ -5,7 +5,7 @@ Base settings for patchwork project.
> import os
>
> ROOT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)),
> - os.pardir, os.pardir)
> + os.pardir)
>
> #
> # Core settings
> @@ -97,7 +97,7 @@ SITE_ID = 1
> STATIC_URL = '/static/'
>
> STATICFILES_DIRS = [
> - os.path.join(ROOT_DIR, 'htdocs'),
> + os.path.join(ROOT_DIR, 'static'),
> ]
>
> #
> diff --git a/htdocs/README.rst b/patchwork/static/README.rst
> similarity index 100%
> rename from htdocs/README.rst
> rename to patchwork/static/README.rst
> diff --git a/htdocs/css/bootstrap.min.css b/patchwork/static/css/bootstrap.min.css
> similarity index 100%
> rename from htdocs/css/bootstrap.min.css
> rename to patchwork/static/css/bootstrap.min.css
> diff --git a/htdocs/css/selectize.bootstrap3.css b/patchwork/static/css/selectize.bootstrap3.css
> similarity index 100%
> rename from htdocs/css/selectize.bootstrap3.css
> rename to patchwork/static/css/selectize.bootstrap3.css
> diff --git a/htdocs/css/style.css b/patchwork/static/css/style.css
> similarity index 100%
> rename from htdocs/css/style.css
> rename to patchwork/static/css/style.css
> diff --git a/htdocs/fonts/glyphicons-halflings-regular.eot b/patchwork/static/fonts/glyphicons-halflings-regular.eot
> similarity index 100%
> rename from htdocs/fonts/glyphicons-halflings-regular.eot
> rename to patchwork/static/fonts/glyphicons-halflings-regular.eot
> diff --git a/htdocs/fonts/glyphicons-halflings-regular.svg b/patchwork/static/fonts/glyphicons-halflings-regular.svg
> similarity index 100%
> rename from htdocs/fonts/glyphicons-halflings-regular.svg
> rename to patchwork/static/fonts/glyphicons-halflings-regular.svg
> diff --git a/htdocs/fonts/glyphicons-halflings-regular.ttf b/patchwork/static/fonts/glyphicons-halflings-regular.ttf
> similarity index 100%
> rename from htdocs/fonts/glyphicons-halflings-regular.ttf
> rename to patchwork/static/fonts/glyphicons-halflings-regular.ttf
> diff --git a/htdocs/fonts/glyphicons-halflings-regular.woff b/patchwork/static/fonts/glyphicons-halflings-regular.woff
> similarity index 100%
> rename from htdocs/fonts/glyphicons-halflings-regular.woff
> rename to patchwork/static/fonts/glyphicons-halflings-regular.woff
> diff --git a/htdocs/js/bootstrap.min.js b/patchwork/static/js/bootstrap.min.js
> similarity index 100%
> rename from htdocs/js/bootstrap.min.js
> rename to patchwork/static/js/bootstrap.min.js
> diff --git a/htdocs/js/bundle.js b/patchwork/static/js/bundle.js
> similarity index 100%
> rename from htdocs/js/bundle.js
> rename to patchwork/static/js/bundle.js
> diff --git a/htdocs/js/clipboard.min.js b/patchwork/static/js/clipboard.min.js
> similarity index 100%
> rename from htdocs/js/clipboard.min.js
> rename to patchwork/static/js/clipboard.min.js
> diff --git a/patchwork/static/js/jquery-1.10.1.min.js b/patchwork/static/js/jquery-1.10.1.min.js
> new file mode 120000
> index 0000000..659cd57
> --- /dev/null
> +++ b/patchwork/static/js/jquery-1.10.1.min.js
> @@ -0,0 +1 @@
> +../../../lib/packages/jquery/jquery-1.10.1.min.js
> \ No newline at end of file
> diff --git a/patchwork/static/js/jquery.checkboxes-1.0.6.min.js b/patchwork/static/js/jquery.checkboxes-1.0.6.min.js
> new file mode 120000
> index 0000000..8b3452b
> --- /dev/null
> +++ b/patchwork/static/js/jquery.checkboxes-1.0.6.min.js
> @@ -0,0 +1 @@
> +../../../lib/packages/jquery/jquery.checkboxes-1.0.6.min.js
> \ No newline at end of file
> diff --git a/patchwork/static/js/jquery.stickytableheaders.min.js b/patchwork/static/js/jquery.stickytableheaders.min.js
> new file mode 120000
> index 0000000..7031ac1
> --- /dev/null
> +++ b/patchwork/static/js/jquery.stickytableheaders.min.js
> @@ -0,0 +1 @@
> +../../../lib/packages/jquery/jquery.stickytableheaders.min.js
> \ No newline at end of file
> diff --git a/patchwork/static/js/jquery.tablednd.js b/patchwork/static/js/jquery.tablednd.js
> new file mode 120000
> index 0000000..80574c4
> --- /dev/null
> +++ b/patchwork/static/js/jquery.tablednd.js
> @@ -0,0 +1 @@
> +../../../lib/packages/jquery/jquery.tablednd.js
> \ No newline at end of file
> diff --git a/htdocs/js/selectize.min.js b/patchwork/static/js/selectize.min.js
> similarity index 100%
> rename from htdocs/js/selectize.min.js
> rename to patchwork/static/js/selectize.min.js
> diff --git a/templates/404.html b/patchwork/templates/404.html
> similarity index 100%
> rename from templates/404.html
> rename to patchwork/templates/404.html
> diff --git a/templates/base.html b/patchwork/templates/base.html
> similarity index 100%
> rename from templates/base.html
> rename to patchwork/templates/base.html
> diff --git a/templates/registration/password_change_done.html b/patchwork/templates/registration/password_change_done.html
> similarity index 100%
> rename from templates/registration/password_change_done.html
> rename to patchwork/templates/registration/password_change_done.html
> diff --git a/templates/registration/password_change_form.html b/patchwork/templates/registration/password_change_form.html
> similarity index 100%
> rename from templates/registration/password_change_form.html
> rename to patchwork/templates/registration/password_change_form.html
> diff --git a/templates/registration/password_reset_complete.html b/patchwork/templates/registration/password_reset_complete.html
> similarity index 100%
> rename from templates/registration/password_reset_complete.html
> rename to patchwork/templates/registration/password_reset_complete.html
> diff --git a/templates/registration/password_reset_confirm.html b/patchwork/templates/registration/password_reset_confirm.html
> similarity index 100%
> rename from templates/registration/password_reset_confirm.html
> rename to patchwork/templates/registration/password_reset_confirm.html
> diff --git a/templates/registration/password_reset_done.html b/patchwork/templates/registration/password_reset_done.html
> similarity index 100%
> rename from templates/registration/password_reset_done.html
> rename to patchwork/templates/registration/password_reset_done.html
> diff --git a/templates/registration/password_reset_email.html b/patchwork/templates/registration/password_reset_email.html
> similarity index 100%
> rename from templates/registration/password_reset_email.html
> rename to patchwork/templates/registration/password_reset_email.html
> diff --git a/templates/registration/password_reset_form.html b/patchwork/templates/registration/password_reset_form.html
> similarity index 100%
> rename from templates/registration/password_reset_form.html
> rename to patchwork/templates/registration/password_reset_form.html
> diff --git a/requirements-test.txt b/requirements-test.txt
> index 5afe243..43af5ea 100644
> --- a/requirements-test.txt
> +++ b/requirements-test.txt
> @@ -2,4 +2,4 @@ mysqlclient~=1.4.4
> psycopg2-binary~=2.8.0
> sqlparse~=0.3.0
> python-dateutil~=2.8.0
> -https://github.com/p1c2u/openapi-core/archive/97ec8c796746f72ef3298fe92078b5f80e1f66f7.tar.gz
> +git+https://github.com/p1c2u/openapi-core.git@97ec8c796746f72ef3298fe92078b5f80e1f66f7 # openapi-core
> diff --git a/setup.py b/setup.py
> new file mode 100755
> index 0000000..0ea5fe4
> --- /dev/null
> +++ b/setup.py
> @@ -0,0 +1,69 @@
> +#!/usr/bin/env python
> +
> +import os
> +
> +from setuptools import setup, find_packages
> +
> +
> +here = os.path.abspath(os.path.dirname(__file__))
> +with open(os.path.join(here, "README.rst")) as fd:
> + README = fd.read()
> +
> +
> +def get_requirements(requirements_file="requirements-prod.txt"):
> + """Get the contents of a file listing the requirements.
> +
> + Args:
> + requirements_file (str): The path to the requirements file, relative
> + to this file.
> +
> + Returns:
> + list: the list of requirements, or an empty list if
> + ``requirements_file`` could not be opened or read.
> + """
> + with open(requirements_file) as fd:
> + lines = fd.readlines()
> + dependencies = []
> + for line in lines:
> + maybe_dep = line.strip()
> + if maybe_dep.startswith("#"):
> + # Skip pure comment lines
> + continue
> + if maybe_dep.startswith("git+"):
> + # VCS reference for dev purposes, expect a trailing comment
> + # with the normal requirement
> + __, __, maybe_dep = maybe_dep.rpartition("#")
> + else:
> + # Ignore any trailing comment
> + maybe_dep, __, __ = maybe_dep.partition("#")
> + # Remove any whitespace and assume non-empty results are dependencies
> + maybe_dep = maybe_dep.strip()
> + if maybe_dep:
> + dependencies.append(maybe_dep)
> + return dependencies
> +
> +
> +setup(
> + name="patchwork",
> + version="3.0.0a1",
> + description="A patch tracking system for community-based projects.",
> + long_description=README,
> + url="https://github.com/getpatchwork/patchwork/",
> + # Possible options are at https://pypi.python.org/pypi?%3Aaction=list_classifiers
> + classifiers=[
> + "Development Status :: 5 - Production/Stable",
> + "Framework :: Django",
> + "License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
> + "Programming Language :: Python :: 3",
> + "Programming Language :: Python :: 3.6",
> + "Programming Language :: Python :: 3.7",
> + "Programming Language :: Python :: 3.8",
> + ],
> + license="GPLv2",
> + packages=find_packages(),
> + include_package_data=True,
> + zip_safe=False,
> + install_requires=get_requirements(),
> + tests_require=get_requirements(requirements_file="requirements-test.txt"),
> + test_suite="patchwork.tests",
> +)
More information about the Patchwork
mailing list