diff mbox series

[RFC] Add a setup.py so Patchwork can be pip-installed

Message ID 20200428213613.280483-1-jcline@redhat.com
State New
Headers show
Series [RFC] Add a setup.py so Patchwork can be pip-installed | expand

Commit Message

Jeremy Cline April 28, 2020, 9:36 p.m. UTC
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.

Signed-off-by: Jeremy Cline <jcline@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

Comments

Stephen Finucane May 7, 2020, 1:29 p.m. UTC | #1
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@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",
> +)
Jeremy Cline May 7, 2020, 2:42 p.m. UTC | #2
Hi Stephen,

On Thu, May 07, 2020 at 02:29:30PM +0100, Stephen Finucane wrote:
> 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?
> 

No worries about the delay, thanks for taking a look.

What I'm doing is a bit odd, I suppose, but perhaps explaining what I'm
up to will make things clearer. We've got some people who like
developing via email, and some people who want to use GitLab, so I
decided to just bridge the two so patches and reviews end up as emails
and merge requests regardless of where they're submitted. Of course,
parsing and tracking the email is a big job, but Patchwork has already
done all the hard work so...

I created another Django application that depends on Patchwork, adds a
few new URLs, and includes a few event handlers on the Patchwork
database models. So even though it's not really the intention of
Patchwork, I'm using it a bit like a library and being able to express
the dependency in my own Python package is handy.

One of the great things about Django apps are their reusability (even if
you never imagined anyone would do something so silly) and bundling them
up in Python packages makes it much easier to extend. It also, I think,
simplifies your installation documentation because instead of having
people untar the release and potentially mess with their Python path it
becomes a simple "pip install".

I am using this in addition to an Ansible role so it's not a *huge*
deal, it's just a bit awkward.

Thanks,
Jeremy
Daniel Axtens May 8, 2020, 6:26 a.m. UTC | #3
Jeremy Cline <jcline@redhat.com> writes:

> Hi Stephen,
>
> On Thu, May 07, 2020 at 02:29:30PM +0100, Stephen Finucane wrote:
>> 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.

I'm not generally opposed to having a setup.py, but the moving around of
files worries me a little bit; I'd want to check to see it doesn't break
anyone using a webserver to serve the static files directly without
going through Django. It probably does! - I just want to check and be
sure before we merge it.

>> > 
>> > 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?
>> 
>
> No worries about the delay, thanks for taking a look.
>
> What I'm doing is a bit odd, I suppose, but perhaps explaining what I'm
> up to will make things clearer. We've got some people who like
> developing via email, and some people who want to use GitLab, so I
> decided to just bridge the two so patches and reviews end up as emails
> and merge requests regardless of where they're submitted. Of course,
> parsing and tracking the email is a big job, but Patchwork has already
> done all the hard work so...
>
> I created another Django application that depends on Patchwork, adds a
> few new URLs, and includes a few event handlers on the Patchwork
> database models. So even though it's not really the intention of
> Patchwork, I'm using it a bit like a library and being able to express
> the dependency in my own Python package is handy.
>

Nifty.

-- d

> One of the great things about Django apps are their reusability (even if
> you never imagined anyone would do something so silly) and bundling them
> up in Python packages makes it much easier to extend. It also, I think,
> simplifies your installation documentation because instead of having
> people untar the release and potentially mess with their Python path it
> becomes a simple "pip install".
>
> I am using this in addition to an Ansible role so it's not a *huge*
> deal, it's just a bit awkward.
>
> Thanks,
> Jeremy
>
> _______________________________________________
> Patchwork mailing list
> Patchwork@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/patchwork
Daniel Axtens May 8, 2020, 6:27 a.m. UTC | #4
Daniel Axtens <dja@axtens.net> writes:

> Jeremy Cline <jcline@redhat.com> writes:
>
>> Hi Stephen,
>>
>> On Thu, May 07, 2020 at 02:29:30PM +0100, Stephen Finucane wrote:
>>> 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.
>
> I'm not generally opposed to having a setup.py, but the moving around of
> files worries me a little bit; I'd want to check to see it doesn't break
> anyone using a webserver to serve the static files directly without
> going through Django. It probably does! - I just want to check and be

* s/It probably does!/It probably doesn't break anything!/

>>> > 
>>> > 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?
>>> 
>>
>> No worries about the delay, thanks for taking a look.
>>
>> What I'm doing is a bit odd, I suppose, but perhaps explaining what I'm
>> up to will make things clearer. We've got some people who like
>> developing via email, and some people who want to use GitLab, so I
>> decided to just bridge the two so patches and reviews end up as emails
>> and merge requests regardless of where they're submitted. Of course,
>> parsing and tracking the email is a big job, but Patchwork has already
>> done all the hard work so...
>>
>> I created another Django application that depends on Patchwork, adds a
>> few new URLs, and includes a few event handlers on the Patchwork
>> database models. So even though it's not really the intention of
>> Patchwork, I'm using it a bit like a library and being able to express
>> the dependency in my own Python package is handy.
>>
>
> Nifty.
>
> -- d
>
>> One of the great things about Django apps are their reusability (even if
>> you never imagined anyone would do something so silly) and bundling them
>> up in Python packages makes it much easier to extend. It also, I think,
>> simplifies your installation documentation because instead of having
>> people untar the release and potentially mess with their Python path it
>> becomes a simple "pip install".
>>
>> I am using this in addition to an Ansible role so it's not a *huge*
>> deal, it's just a bit awkward.
>>
>> Thanks,
>> Jeremy
>>
>> _______________________________________________
>> Patchwork mailing list
>> Patchwork@lists.ozlabs.org
>> https://lists.ozlabs.org/listinfo/patchwork
diff mbox series

Patch

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",
+)