flask-nginx 0.8.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flask_nginx-0.8.0/.gitignore +133 -0
- flask_nginx-0.8.0/PKG-INFO +133 -0
- flask_nginx-0.8.0/README.md +122 -0
- flask_nginx-0.8.0/flask_nginx/__init__.py +0 -0
- flask_nginx-0.8.0/flask_nginx/__main__.py +19 -0
- flask_nginx-0.8.0/flask_nginx/cli.py +111 -0
- flask_nginx-0.8.0/flask_nginx/config.py +90 -0
- flask_nginx-0.8.0/flask_nginx/core.py +177 -0
- flask_nginx-0.8.0/flask_nginx/irds.py +182 -0
- flask_nginx-0.8.0/flask_nginx/logo.py +47 -0
- flask_nginx-0.8.0/flask_nginx/mailer.py +53 -0
- flask_nginx-0.8.0/flask_nginx/mysql.py +498 -0
- flask_nginx-0.8.0/flask_nginx/py.typed +0 -0
- flask_nginx-0.8.0/flask_nginx/remote.py +20 -0
- flask_nginx-0.8.0/flask_nginx/restartd.py +60 -0
- flask_nginx-0.8.0/flask_nginx/rsync.py +34 -0
- flask_nginx-0.8.0/flask_nginx/systemd/__init__.py +0 -0
- flask_nginx-0.8.0/flask_nginx/systemd/cli.py +10 -0
- flask_nginx-0.8.0/flask_nginx/systemd/nginx.py +645 -0
- flask_nginx-0.8.0/flask_nginx/systemd/supervisor.py +259 -0
- flask_nginx-0.8.0/flask_nginx/systemd/systemd.py +556 -0
- flask_nginx-0.8.0/flask_nginx/systemd/utils.py +289 -0
- flask_nginx-0.8.0/flask_nginx/templates/celery.service +28 -0
- flask_nginx-0.8.0/flask_nginx/templates/nginx-app.conf +15 -0
- flask_nginx-0.8.0/flask_nginx/templates/nginx-test.conf +40 -0
- flask_nginx-0.8.0/flask_nginx/templates/nginx-upstream.conf +71 -0
- flask_nginx-0.8.0/flask_nginx/templates/nginx.conf +67 -0
- flask_nginx-0.8.0/flask_nginx/templates/secure-tunnel.service +15 -0
- flask_nginx-0.8.0/flask_nginx/templates/ssl.conf +25 -0
- flask_nginx-0.8.0/flask_nginx/templates/supervisord.ini +18 -0
- flask_nginx-0.8.0/flask_nginx/templates/systemd.mount +16 -0
- flask_nginx-0.8.0/flask_nginx/templates/systemd.service +39 -0
- flask_nginx-0.8.0/flask_nginx/templating.py +119 -0
- flask_nginx-0.8.0/flask_nginx/url.py +90 -0
- flask_nginx-0.8.0/flask_nginx/utils.py +185 -0
- flask_nginx-0.8.0/flask_nginx/watch.py +239 -0
- flask_nginx-0.8.0/pyproject.toml +24 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
pip-wheel-metadata/
|
|
24
|
+
share/python-wheels/
|
|
25
|
+
*.egg-info/
|
|
26
|
+
.installed.cfg
|
|
27
|
+
*.egg
|
|
28
|
+
MANIFEST
|
|
29
|
+
|
|
30
|
+
# PyInstaller
|
|
31
|
+
# Usually these files are written by a python script from a template
|
|
32
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
33
|
+
*.manifest
|
|
34
|
+
*.spec
|
|
35
|
+
|
|
36
|
+
# Installer logs
|
|
37
|
+
pip-log.txt
|
|
38
|
+
pip-delete-this-directory.txt
|
|
39
|
+
|
|
40
|
+
# Unit test / coverage reports
|
|
41
|
+
htmlcov/
|
|
42
|
+
.tox/
|
|
43
|
+
.nox/
|
|
44
|
+
.coverage
|
|
45
|
+
.coverage.*
|
|
46
|
+
.cache
|
|
47
|
+
nosetests.xml
|
|
48
|
+
coverage.xml
|
|
49
|
+
*.cover
|
|
50
|
+
*.py,cover
|
|
51
|
+
.hypothesis/
|
|
52
|
+
.pytest_cache/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
target/
|
|
76
|
+
|
|
77
|
+
# Jupyter Notebook
|
|
78
|
+
.ipynb_checkpoints
|
|
79
|
+
|
|
80
|
+
# IPython
|
|
81
|
+
profile_default/
|
|
82
|
+
ipython_config.py
|
|
83
|
+
|
|
84
|
+
# pyenv
|
|
85
|
+
.python-version
|
|
86
|
+
|
|
87
|
+
# pipenv
|
|
88
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
89
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
90
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
91
|
+
# install all needed dependencies.
|
|
92
|
+
#Pipfile.lock
|
|
93
|
+
|
|
94
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
|
95
|
+
__pypackages__/
|
|
96
|
+
|
|
97
|
+
# Celery stuff
|
|
98
|
+
celerybeat-schedule
|
|
99
|
+
celerybeat.pid
|
|
100
|
+
|
|
101
|
+
# SageMath parsed files
|
|
102
|
+
*.sage.py
|
|
103
|
+
|
|
104
|
+
# Environments
|
|
105
|
+
.env
|
|
106
|
+
.venv
|
|
107
|
+
env/
|
|
108
|
+
venv/
|
|
109
|
+
ENV/
|
|
110
|
+
env.bak/
|
|
111
|
+
venv.bak/
|
|
112
|
+
|
|
113
|
+
# Spyder project settings
|
|
114
|
+
.spyderproject
|
|
115
|
+
.spyproject
|
|
116
|
+
|
|
117
|
+
# Rope project settings
|
|
118
|
+
.ropeproject
|
|
119
|
+
|
|
120
|
+
# mkdocs documentation
|
|
121
|
+
/site
|
|
122
|
+
|
|
123
|
+
# mypy
|
|
124
|
+
.mypy_cache/
|
|
125
|
+
.dmypy.json
|
|
126
|
+
dmypy.json
|
|
127
|
+
|
|
128
|
+
# Pyre type checker
|
|
129
|
+
.pyre/
|
|
130
|
+
footprint.egg-info
|
|
131
|
+
app/node_modules
|
|
132
|
+
|
|
133
|
+
.vscode/
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: flask-nginx
|
|
3
|
+
Version: 0.8.0
|
|
4
|
+
Summary: install flask websites into nginx
|
|
5
|
+
Author-email: arabidopsis <ian.castleden@uwa.edu.au>
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Requires-Dist: flask>=2.0
|
|
8
|
+
Provides-Extra: psutil
|
|
9
|
+
Requires-Dist: psutil>=5.4; extra == 'psutil'
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# footprint 👣
|
|
13
|
+
|
|
14
|
+
I use this to generate config files for my flask apps. Currently systemd and nginx.
|
|
15
|
+
It only depends on Flask (which should alread be in the virtualenv).
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
export FLASK_APP=your_package.wsgi
|
|
19
|
+
footprint config nginx www.example.com > example.conf
|
|
20
|
+
footprint config nginx-install example.conf
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# install in ~/.config/systemd/user
|
|
25
|
+
export FLASK_APP=your_package.wsgi
|
|
26
|
+
footprint config systemd --user > example.service
|
|
27
|
+
footprint config systemd-install --user example.service
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
will install nginx and systemd files that will statically serve you 'static' assets and
|
|
31
|
+
run the Flask app with gunicorn.
|
|
32
|
+
|
|
33
|
+
Mostly I've found that confectioning these files by hand are highly error prone. These
|
|
34
|
+
commands will at least get the absolute pathnames correct :)
|
|
35
|
+
|
|
36
|
+
Install with:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
python -m pip install flask-nginx
|
|
40
|
+
python -m pip install -U git+https://github.com/arabidopsis/footprint.git
|
|
41
|
+
# or
|
|
42
|
+
# git clone https://github.com/arabidopsis/footprint.git
|
|
43
|
+
# cd footprint
|
|
44
|
+
# python -m pip install [--editable] .
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
or add to your `pyproject.toml` file
|
|
48
|
+
|
|
49
|
+
```toml
|
|
50
|
+
footprint = { git = "https://github.com/arabidopsis/footprint.git", branch="main" }
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Once installed you can upgrade with:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
footprint update
|
|
57
|
+
# or
|
|
58
|
+
uv pip install -U $(footprint repo)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
If `footprint` finds a `pyproject.toml` file in the current directory
|
|
62
|
+
if will try to load `[tool.footprint]` values into its global configuration object.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
footprint mysql --host=mysql://{user}:{pw}@{src}/{db} dump /var/www/websites/{repo}/instance/sql
|
|
66
|
+
# rsync the entire repo
|
|
67
|
+
footprint rsync {src}:/var/www/websites/{repo} {tgt}
|
|
68
|
+
footprint mysql --host=mysql://{user}:{pw}@{src}/{db} load /var/www/websites/{repo}/instance/sql/{db}.sql.gz
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## `nginx`, `systemd` and all that
|
|
72
|
+
|
|
73
|
+
Note that these configuration generating functions are
|
|
74
|
+
not infallible. Please examine the generated configure files
|
|
75
|
+
_carefully_! They are mainly useful for getting the directory
|
|
76
|
+
names correct etc. So if you move your repo then you will
|
|
77
|
+
have to regenerate and reinstall the files.
|
|
78
|
+
|
|
79
|
+
- [Nginx Docs](https://docs.nginx.com/nginx/). [Also](https://nginx.org/en/docs/) and [Proxy](https://nginx.org/en/docs/http/ngx_http_proxy_module.html)
|
|
80
|
+
|
|
81
|
+
Test an nginx config with e.g.:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
website=~/Sites/websites/ppr
|
|
85
|
+
export FLASK_APP=ppr.wsgi
|
|
86
|
+
footprint config nginx --app-dir=$website example.org | footprint config nginx-run --app-dir=$website -
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
This will run nginx at the terminal listening on port 2048 and run the backend
|
|
90
|
+
website.
|
|
91
|
+
|
|
92
|
+
To install a website:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
footprint config nginx --app-dir=$website example.org -o website.conf
|
|
96
|
+
footprint config systemd [--user] --app-dir=$website -o website.service
|
|
97
|
+
# nginx requires sudo (default) or su
|
|
98
|
+
footprint config nginx-install website.conf
|
|
99
|
+
# if you can install into ~/.config/systemd/user
|
|
100
|
+
footprint config systemd-install [--user] website.service
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
You can test _this_ locally by editing `/etc/hosts` and adding a line:
|
|
104
|
+
|
|
105
|
+
`127.0.0.1 example.org`
|
|
106
|
+
|
|
107
|
+
to the file.
|
|
108
|
+
|
|
109
|
+
**REMEMBER**: Unix file permissions mean that you should edit `/etc/nginx/nginx.conf`
|
|
110
|
+
and change `user www-data;` to `user {you};` Or (recursively) change the owner on
|
|
111
|
+
all the repo directories to `www-data`.
|
|
112
|
+
|
|
113
|
+
If you install as "user" (i.e. `footprint config systemd --user ...`) then
|
|
114
|
+
**to ensure that the user systemd starts at boot time use**: `sudo loginctl enable-linger <user>`
|
|
115
|
+
|
|
116
|
+
See [here](https://nts.strzibny.name/systemd-user-services/):
|
|
117
|
+
|
|
118
|
+
> But what’s the real reason for having user services?
|
|
119
|
+
> To answer that, we have to realize when the enabled service starts and stops.
|
|
120
|
+
> If we enable a user service, it starts on user login, and runs as long as there is a
|
|
121
|
+
> session open for that user. Once the last session dies, the service stops.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
See [digitalocean.com here](https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-gunicorn-and-nginx-on-ubuntu-20-04) for a tutorial about serving flask from nginx.
|
|
126
|
+
|
|
127
|
+
Uninstall with `footprint config nginx-uninstall website.conf` and `footprint config systemd-uninstall [--user] website.service`
|
|
128
|
+
|
|
129
|
+
### `.flaskenv`
|
|
130
|
+
|
|
131
|
+
If a `.flaskenv` is found in the repo directory then nginx and systemd will
|
|
132
|
+
read paramters from that file. The keywords should be _uppercase_ version of
|
|
133
|
+
the known parameters. Unknown parameters will be ignored.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# footprint 👣
|
|
2
|
+
|
|
3
|
+
I use this to generate config files for my flask apps. Currently systemd and nginx.
|
|
4
|
+
It only depends on Flask (which should alread be in the virtualenv).
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
export FLASK_APP=your_package.wsgi
|
|
8
|
+
footprint config nginx www.example.com > example.conf
|
|
9
|
+
footprint config nginx-install example.conf
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# install in ~/.config/systemd/user
|
|
14
|
+
export FLASK_APP=your_package.wsgi
|
|
15
|
+
footprint config systemd --user > example.service
|
|
16
|
+
footprint config systemd-install --user example.service
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
will install nginx and systemd files that will statically serve you 'static' assets and
|
|
20
|
+
run the Flask app with gunicorn.
|
|
21
|
+
|
|
22
|
+
Mostly I've found that confectioning these files by hand are highly error prone. These
|
|
23
|
+
commands will at least get the absolute pathnames correct :)
|
|
24
|
+
|
|
25
|
+
Install with:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
python -m pip install flask-nginx
|
|
29
|
+
python -m pip install -U git+https://github.com/arabidopsis/footprint.git
|
|
30
|
+
# or
|
|
31
|
+
# git clone https://github.com/arabidopsis/footprint.git
|
|
32
|
+
# cd footprint
|
|
33
|
+
# python -m pip install [--editable] .
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
or add to your `pyproject.toml` file
|
|
37
|
+
|
|
38
|
+
```toml
|
|
39
|
+
footprint = { git = "https://github.com/arabidopsis/footprint.git", branch="main" }
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Once installed you can upgrade with:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
footprint update
|
|
46
|
+
# or
|
|
47
|
+
uv pip install -U $(footprint repo)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
If `footprint` finds a `pyproject.toml` file in the current directory
|
|
51
|
+
if will try to load `[tool.footprint]` values into its global configuration object.
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
footprint mysql --host=mysql://{user}:{pw}@{src}/{db} dump /var/www/websites/{repo}/instance/sql
|
|
55
|
+
# rsync the entire repo
|
|
56
|
+
footprint rsync {src}:/var/www/websites/{repo} {tgt}
|
|
57
|
+
footprint mysql --host=mysql://{user}:{pw}@{src}/{db} load /var/www/websites/{repo}/instance/sql/{db}.sql.gz
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## `nginx`, `systemd` and all that
|
|
61
|
+
|
|
62
|
+
Note that these configuration generating functions are
|
|
63
|
+
not infallible. Please examine the generated configure files
|
|
64
|
+
_carefully_! They are mainly useful for getting the directory
|
|
65
|
+
names correct etc. So if you move your repo then you will
|
|
66
|
+
have to regenerate and reinstall the files.
|
|
67
|
+
|
|
68
|
+
- [Nginx Docs](https://docs.nginx.com/nginx/). [Also](https://nginx.org/en/docs/) and [Proxy](https://nginx.org/en/docs/http/ngx_http_proxy_module.html)
|
|
69
|
+
|
|
70
|
+
Test an nginx config with e.g.:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
website=~/Sites/websites/ppr
|
|
74
|
+
export FLASK_APP=ppr.wsgi
|
|
75
|
+
footprint config nginx --app-dir=$website example.org | footprint config nginx-run --app-dir=$website -
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
This will run nginx at the terminal listening on port 2048 and run the backend
|
|
79
|
+
website.
|
|
80
|
+
|
|
81
|
+
To install a website:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
footprint config nginx --app-dir=$website example.org -o website.conf
|
|
85
|
+
footprint config systemd [--user] --app-dir=$website -o website.service
|
|
86
|
+
# nginx requires sudo (default) or su
|
|
87
|
+
footprint config nginx-install website.conf
|
|
88
|
+
# if you can install into ~/.config/systemd/user
|
|
89
|
+
footprint config systemd-install [--user] website.service
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
You can test _this_ locally by editing `/etc/hosts` and adding a line:
|
|
93
|
+
|
|
94
|
+
`127.0.0.1 example.org`
|
|
95
|
+
|
|
96
|
+
to the file.
|
|
97
|
+
|
|
98
|
+
**REMEMBER**: Unix file permissions mean that you should edit `/etc/nginx/nginx.conf`
|
|
99
|
+
and change `user www-data;` to `user {you};` Or (recursively) change the owner on
|
|
100
|
+
all the repo directories to `www-data`.
|
|
101
|
+
|
|
102
|
+
If you install as "user" (i.e. `footprint config systemd --user ...`) then
|
|
103
|
+
**to ensure that the user systemd starts at boot time use**: `sudo loginctl enable-linger <user>`
|
|
104
|
+
|
|
105
|
+
See [here](https://nts.strzibny.name/systemd-user-services/):
|
|
106
|
+
|
|
107
|
+
> But what’s the real reason for having user services?
|
|
108
|
+
> To answer that, we have to realize when the enabled service starts and stops.
|
|
109
|
+
> If we enable a user service, it starts on user login, and runs as long as there is a
|
|
110
|
+
> session open for that user. Once the last session dies, the service stops.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
See [digitalocean.com here](https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-gunicorn-and-nginx-on-ubuntu-20-04) for a tutorial about serving flask from nginx.
|
|
115
|
+
|
|
116
|
+
Uninstall with `footprint config nginx-uninstall website.conf` and `footprint config systemd-uninstall [--user] website.service`
|
|
117
|
+
|
|
118
|
+
### `.flaskenv`
|
|
119
|
+
|
|
120
|
+
If a `.flaskenv` is found in the repo directory then nginx and systemd will
|
|
121
|
+
read paramters from that file. The keywords should be _uppercase_ version of
|
|
122
|
+
the known parameters. Unknown parameters will be ignored.
|
|
File without changes
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# pylint: disable=unused-import
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from . import irds # noqa:
|
|
5
|
+
from . import mailer # noqa:
|
|
6
|
+
from . import mysql # noqa:
|
|
7
|
+
from . import remote # noqa:
|
|
8
|
+
from . import restartd # noqa:
|
|
9
|
+
from . import rsync # noqa:
|
|
10
|
+
from . import watch # noqa:
|
|
11
|
+
from .cli import cli
|
|
12
|
+
from .systemd import nginx # noqa:
|
|
13
|
+
from .systemd import supervisor # noqa:
|
|
14
|
+
from .systemd import systemd # noqa:
|
|
15
|
+
|
|
16
|
+
# from . import logo # noqa:
|
|
17
|
+
|
|
18
|
+
if __name__ == "__main__":
|
|
19
|
+
cli.main(prog_name="footprint")
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import subprocess
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@click.group(
|
|
9
|
+
# cls=DYMGroup,
|
|
10
|
+
epilog=click.style("Commands to manage websites\n", fg="magenta"),
|
|
11
|
+
)
|
|
12
|
+
@click.version_option()
|
|
13
|
+
def cli() -> None:
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@cli.command()
|
|
18
|
+
def update() -> None:
|
|
19
|
+
"""Update this package"""
|
|
20
|
+
import sys
|
|
21
|
+
|
|
22
|
+
from .config import REPO
|
|
23
|
+
|
|
24
|
+
ret = subprocess.call([sys.executable, "-m", "pip", "install", "-U", REPO])
|
|
25
|
+
if ret:
|
|
26
|
+
click.secho(f"can't install {REPO}", fg="red")
|
|
27
|
+
raise click.Abort()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@cli.command()
|
|
31
|
+
def repo() -> None:
|
|
32
|
+
"""show git repository"""
|
|
33
|
+
|
|
34
|
+
from .config import REPO
|
|
35
|
+
|
|
36
|
+
click.echo(REPO)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@cli.command()
|
|
40
|
+
def config_show() -> None:
|
|
41
|
+
"""Show configuration"""
|
|
42
|
+
from dataclasses import fields
|
|
43
|
+
from .config import get_config
|
|
44
|
+
|
|
45
|
+
Config = get_config()
|
|
46
|
+
|
|
47
|
+
n = max(len(f.name) for f in fields(Config))
|
|
48
|
+
|
|
49
|
+
for f in fields(Config):
|
|
50
|
+
k = f.name
|
|
51
|
+
v = getattr(Config, f.name)
|
|
52
|
+
click.echo(f"{k:<{n}}: {v}")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@cli.command()
|
|
56
|
+
@click.option("-a", "--append", is_flag=True, help="append to file")
|
|
57
|
+
@click.argument("filename")
|
|
58
|
+
def config_dump(filename: str, append: bool) -> None:
|
|
59
|
+
"""Dump configuration"""
|
|
60
|
+
from .utils import require_mod
|
|
61
|
+
from .config import dump_to_file
|
|
62
|
+
|
|
63
|
+
require_mod("toml")
|
|
64
|
+
|
|
65
|
+
if not dump_to_file(filename, append):
|
|
66
|
+
click.secho("can't dump configuration!", fg="red", err=True)
|
|
67
|
+
raise click.Abort()
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
# @cli.command()
|
|
71
|
+
# @click.option("-p", "--with-python", is_flag=True)
|
|
72
|
+
# @click.option("-c", "--compile", "use_pip_compile", is_flag=True)
|
|
73
|
+
# @click.argument("project_dir", required=False)
|
|
74
|
+
def poetry_to_reqs(
|
|
75
|
+
project_dir: str,
|
|
76
|
+
with_python: bool,
|
|
77
|
+
use_pip_compile: bool = True,
|
|
78
|
+
) -> None:
|
|
79
|
+
"""Generate a requirements.txt file from pyproject.toml [**may require toml**]"""
|
|
80
|
+
import os
|
|
81
|
+
from contextlib import suppress
|
|
82
|
+
from .utils import toml_load
|
|
83
|
+
|
|
84
|
+
pyproject = "pyproject.toml"
|
|
85
|
+
if project_dir:
|
|
86
|
+
pyproject = os.path.join(project_dir, pyproject)
|
|
87
|
+
if not os.path.isfile(pyproject):
|
|
88
|
+
raise click.BadArgumentUsage("no pyproject.toml file!")
|
|
89
|
+
|
|
90
|
+
def fix(req: str) -> str:
|
|
91
|
+
if req.startswith("^"):
|
|
92
|
+
return f">={req[1:]}"
|
|
93
|
+
return req
|
|
94
|
+
|
|
95
|
+
reqs = "\n".join(
|
|
96
|
+
f"{k}{fix(v)}"
|
|
97
|
+
for k, v in sorted(
|
|
98
|
+
toml_load(pyproject)["tool"]["poetry"]["dependencies"].items(),
|
|
99
|
+
)
|
|
100
|
+
if with_python or k != "python" and isinstance(v, str)
|
|
101
|
+
)
|
|
102
|
+
if use_pip_compile:
|
|
103
|
+
try:
|
|
104
|
+
with open("requirements.in", "w", encoding="utf-8") as fp:
|
|
105
|
+
click.echo(reqs, file=fp)
|
|
106
|
+
subprocess.check_call(["pip-compile"])
|
|
107
|
+
finally:
|
|
108
|
+
with suppress(OSError):
|
|
109
|
+
os.remove("requirements.in")
|
|
110
|
+
else:
|
|
111
|
+
click.echo(reqs)
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from dataclasses import asdict
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from dataclasses import field
|
|
7
|
+
from dataclasses import fields
|
|
8
|
+
from dataclasses import replace
|
|
9
|
+
from typing import IO
|
|
10
|
+
|
|
11
|
+
from .utils import toml_load
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
REPO = "git+https://github.com/arabidopsis/footprint.git"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class Config:
|
|
19
|
+
mailhost: str = "uwa-edu-au.mail.protection.outlook.com"
|
|
20
|
+
# mailhost: str = "antivirus.uwa.edu.au"
|
|
21
|
+
datastore: str = "//drive.irds.uwa.edu.au/sci-ms-001"
|
|
22
|
+
# directories that *might* be in the static directory
|
|
23
|
+
static_dir: str = (
|
|
24
|
+
r"img|images|js|css|media|docs|tutorials|notebooks|downloads|\.well-known"
|
|
25
|
+
)
|
|
26
|
+
# basic files that have urls such as /robots.txt /favicon.ico etc.
|
|
27
|
+
static_files: str = (
|
|
28
|
+
r"robots\.txt|crossdomain\.xml|favicon\.ico|browserconfig\.xml|humans\.txt"
|
|
29
|
+
)
|
|
30
|
+
# exclude these filenames/directories from static consideration
|
|
31
|
+
exclude: list[str] = field(default_factory=lambda: ["__pycache__"])
|
|
32
|
+
# directory to put config files: (Ubuntu, RHEL8)
|
|
33
|
+
nginx_dirs: list[str] = field(
|
|
34
|
+
default_factory=lambda: ["/etc/nginx/sites-enabled", "/etc/nginx/conf.d"],
|
|
35
|
+
)
|
|
36
|
+
arg_color: str = "yellow" # use "none" for no color
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
XConfig: Config | None = None
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def get_config() -> Config:
|
|
43
|
+
global XConfig
|
|
44
|
+
if XConfig is None:
|
|
45
|
+
XConfig = _init_config(Config())
|
|
46
|
+
return XConfig
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _init_config(config: Config, application_dir: str = ".") -> Config:
|
|
50
|
+
project = os.path.join(application_dir, "pyproject.toml")
|
|
51
|
+
if os.path.isfile(project):
|
|
52
|
+
try:
|
|
53
|
+
d = toml_load(project)
|
|
54
|
+
if "tool" not in d:
|
|
55
|
+
return config
|
|
56
|
+
cfg = d["tool"].get("footprint")
|
|
57
|
+
if cfg is None:
|
|
58
|
+
return config
|
|
59
|
+
data = {}
|
|
60
|
+
for f in fields(config):
|
|
61
|
+
if f.name in cfg:
|
|
62
|
+
data[f.name] = cfg[f.name]
|
|
63
|
+
|
|
64
|
+
if data:
|
|
65
|
+
config = replace(config, **data)
|
|
66
|
+
|
|
67
|
+
except ImportError:
|
|
68
|
+
pass
|
|
69
|
+
except Exception:
|
|
70
|
+
import click
|
|
71
|
+
|
|
72
|
+
click.secho(f'can\'t load "{project}"', fg="red", bold=True, err=True)
|
|
73
|
+
return config
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def dump_toml(config: Config, out: IO[str]) -> bool:
|
|
77
|
+
try:
|
|
78
|
+
import toml # type: ignore
|
|
79
|
+
|
|
80
|
+
d = dict(tool=dict(footprint=asdict(config)))
|
|
81
|
+
toml.dump(d, out)
|
|
82
|
+
return True
|
|
83
|
+
except Exception:
|
|
84
|
+
return False
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def dump_to_file(filename: str, append: bool) -> bool:
|
|
88
|
+
config = get_config()
|
|
89
|
+
with open(filename, "a" if append else "w", encoding="utf-8") as fp:
|
|
90
|
+
return dump_toml(config, fp)
|