opendataframework 0.0.2__tar.gz → 0.0.3__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.
- {opendataframework-0.0.2 → opendataframework-0.0.3}/PKG-INFO +1 -1
- {opendataframework-0.0.2 → opendataframework-0.0.3}/pyproject.toml +1 -1
- {opendataframework-0.0.2 → opendataframework-0.0.3}/setup.py +10 -2
- opendataframework-0.0.3/src/opendataframework/README.md +43 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/__init__.py +1 -1
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/__main__.py +470 -12
- opendataframework-0.0.3/src/opendataframework/docs/index.md +1 -0
- opendataframework-0.0.3/src/opendataframework/docs/mkdocs.yml +56 -0
- opendataframework-0.0.3/src/opendataframework/docs/requirements.txt +1 -0
- opendataframework-0.0.3/src/opendataframework/docs/stylesheets/extra.css +8 -0
- opendataframework-0.0.3/src/opendataframework/github/workflows/ci.yaml +21 -0
- opendataframework-0.0.3/src/opendataframework/hooks/.pre-commit-config.yaml +29 -0
- opendataframework-0.0.3/src/opendataframework/hooks/requirements.txt +1 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/setup.sh +2 -0
- opendataframework-0.0.3/src/opendataframework/tests/__init__.py +1 -0
- opendataframework-0.0.3/src/opendataframework/tests/requirements.txt +2 -0
- opendataframework-0.0.3/src/opendataframework/tests/test_example.py +6 -0
- opendataframework-0.0.3/src/opendataframework/utility/nginx/Dockerfile +5 -0
- opendataframework-0.0.3/src/opendataframework/utility/nginx/docker-compose.yaml +14 -0
- opendataframework-0.0.3/src/opendataframework/utility/nginx/nginx.conf +6 -0
- opendataframework-0.0.3/src/opendataframework/utility/nginx/static/images/logo.svg +7 -0
- opendataframework-0.0.3/src/opendataframework/utility/nginx/static/index.html +39 -0
- opendataframework-0.0.2/src/opendataframework/README.md +0 -28
- opendataframework-0.0.2/src/opendataframework/analytics/build.sh +0 -2
- opendataframework-0.0.2/src/opendataframework/analytics/start.sh +0 -2
- opendataframework-0.0.2/src/opendataframework/analytics/stop.sh +0 -2
- opendataframework-0.0.2/src/opendataframework/api/build.sh +0 -2
- opendataframework-0.0.2/src/opendataframework/api/start.sh +0 -2
- opendataframework-0.0.2/src/opendataframework/api/stop.sh +0 -2
- opendataframework-0.0.2/src/opendataframework/build.sh +0 -1
- opendataframework-0.0.2/src/opendataframework/env.sh +0 -11
- opendataframework-0.0.2/src/opendataframework/main.sh +0 -42
- opendataframework-0.0.2/src/opendataframework/start.sh +0 -1
- opendataframework-0.0.2/src/opendataframework/stop.sh +0 -1
- opendataframework-0.0.2/src/opendataframework/storage/build.sh +0 -2
- opendataframework-0.0.2/src/opendataframework/storage/start.sh +0 -2
- opendataframework-0.0.2/src/opendataframework/storage/stop.sh +0 -2
- opendataframework-0.0.2/src/opendataframework/utility/build.sh +0 -2
- opendataframework-0.0.2/src/opendataframework/utility/start.sh +0 -2
- opendataframework-0.0.2/src/opendataframework/utility/stop.sh +0 -2
- {opendataframework-0.0.2 → opendataframework-0.0.3}/LICENSE +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/README.md +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/analytics/setup.sh +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/analytics/superset/.env +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/analytics/superset/Dockerfile +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/analytics/superset/database/postgres/create.sh +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/analytics/superset/database/postgres/setup.sh +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/analytics/superset/docker-compose.yaml +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/analytics/superset/setup.sh +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/api/api-postgres/.env +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/api/api-postgres/Dockerfile +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/api/api-postgres/app/__init__.py +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/api/api-postgres/app/config.py +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/api/api-postgres/app/crud.py +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/api/api-postgres/app/database.py +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/api/api-postgres/app/dependencies.py +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/api/api-postgres/app/main.py +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/api/api-postgres/app/models.py +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/api/api-postgres/app/router.py +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/api/api-postgres/docker-compose.yaml +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/api/api-postgres/poetry.lock +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/api/api-postgres/pyproject.toml +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/api/ingest.py +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/api/requirements.txt +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/api/setup.sh +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/devcontainers/R/.devcontainer/.Rprofile +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/devcontainers/R/.devcontainer/Dockerfile +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/devcontainers/R/.devcontainer/devcontainer.json +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/devcontainers/python/.devcontainer/Dockerfile +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/devcontainers/python/.devcontainer/devcontainer.json +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/docker-compose.yaml +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/expectations.py +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/layouts/research/.vscode/extensions.json +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/layouts/research/code/build/.gitkeep +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/layouts/research/code/check/.gitkeep +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/layouts/research/code/learn/.gitkeep +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/layouts/research/code/share/.gitkeep +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/layouts/research/data/derived/.gitkeep +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/layouts/research/data/raw/.gitkeep +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/layouts/research/libraries/.gitkeep +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/layouts/research/logs/.gitkeep +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/layouts/research/models/.gitkeep +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/layouts/research/output/figures/.gitkeep +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/layouts/research/output/tables/.gitkeep +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/layouts/research/paper/.gitkeep +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/requirements.txt +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/storage/postgres/.env +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/storage/postgres/Dockerfile +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/storage/postgres/docker-compose.yaml +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/storage/postgres/setup.sh +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/storage/setup.sh +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/utility/setup.sh +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/utility/texlive/Dockerfile +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/utility/texlive/docker-compose.yaml +0 -0
- {opendataframework-0.0.2 → opendataframework-0.0.3}/src/opendataframework/utility/texlive/mnt/.gitkeep +0 -0
|
@@ -7,7 +7,8 @@ package_dir = \
|
|
|
7
7
|
packages = \
|
|
8
8
|
['opendataframework',
|
|
9
9
|
'opendataframework.api',
|
|
10
|
-
'opendataframework.api.api-postgres.app'
|
|
10
|
+
'opendataframework.api.api-postgres.app',
|
|
11
|
+
'opendataframework.tests']
|
|
11
12
|
|
|
12
13
|
package_data = \
|
|
13
14
|
{'': ['*'],
|
|
@@ -16,6 +17,10 @@ package_data = \
|
|
|
16
17
|
'analytics/superset/database/postgres/*',
|
|
17
18
|
'devcontainers/R/.devcontainer/*',
|
|
18
19
|
'devcontainers/python/.devcontainer/*',
|
|
20
|
+
'docs/*',
|
|
21
|
+
'docs/stylesheets/*',
|
|
22
|
+
'github/workflows/*',
|
|
23
|
+
'hooks/*',
|
|
19
24
|
'layouts/research/.vscode/*',
|
|
20
25
|
'layouts/research/code/build/*',
|
|
21
26
|
'layouts/research/code/check/*',
|
|
@@ -32,6 +37,9 @@ package_data = \
|
|
|
32
37
|
'storage/*',
|
|
33
38
|
'storage/postgres/*',
|
|
34
39
|
'utility/*',
|
|
40
|
+
'utility/nginx/*',
|
|
41
|
+
'utility/nginx/static/*',
|
|
42
|
+
'utility/nginx/static/images/*',
|
|
35
43
|
'utility/texlive/*',
|
|
36
44
|
'utility/texlive/mnt/*'],
|
|
37
45
|
'opendataframework.api': ['api-postgres/*']}
|
|
@@ -44,7 +52,7 @@ entry_points = \
|
|
|
44
52
|
|
|
45
53
|
setup_kwargs = {
|
|
46
54
|
'name': 'opendataframework',
|
|
47
|
-
'version': '0.0.
|
|
55
|
+
'version': '0.0.3',
|
|
48
56
|
'description': 'Open Data Framework is an open source, full stack data framework.',
|
|
49
57
|
'long_description': '# Open Data Framework\nOpen source, full stack data framework.\n',
|
|
50
58
|
'author': 'mykytapavlov',
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# project_name
|
|
2
|
+
|
|
3
|
+
### Build platform
|
|
4
|
+
Command builds platform's images.
|
|
5
|
+
|
|
6
|
+
```sh
|
|
7
|
+
opendataframework build
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
### Start platform
|
|
11
|
+
Command starts platform's containers.
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
opendataframework start
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Setup platform
|
|
18
|
+
Command setup platform's containers.
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
opendataframework setup
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Install dependencies
|
|
25
|
+
Command creates `myproject/.venv/` and installs dependencies from `requirements.txt`.
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
opendataframework install
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Docs
|
|
32
|
+
Command starts mkdocs server.
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
opendataframework docs
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Test
|
|
39
|
+
Command runs tests.
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
opendataframework test
|
|
43
|
+
```
|
|
@@ -5,8 +5,11 @@ import json
|
|
|
5
5
|
import os
|
|
6
6
|
import re
|
|
7
7
|
import shutil
|
|
8
|
+
import stat
|
|
9
|
+
import subprocess
|
|
8
10
|
import traceback
|
|
9
11
|
import uuid
|
|
12
|
+
import venv
|
|
10
13
|
from datetime import datetime
|
|
11
14
|
from pathlib import Path
|
|
12
15
|
|
|
@@ -106,6 +109,7 @@ class Component:
|
|
|
106
109
|
POSTGRES: str = "postgres"
|
|
107
110
|
|
|
108
111
|
# UTILITY
|
|
112
|
+
NGINX = "nginx"
|
|
109
113
|
TEXLIVE = "texlive"
|
|
110
114
|
|
|
111
115
|
|
|
@@ -121,7 +125,7 @@ COMPONENTS = {
|
|
|
121
125
|
Layer.DEVCONTAINERS: [Component.PYTHON, Component.R],
|
|
122
126
|
Layer.API: [Component.API_POSTGRES],
|
|
123
127
|
Layer.STORAGE: [Component.POSTGRES],
|
|
124
|
-
Layer.UTILITY: [Component.TEXLIVE],
|
|
128
|
+
Layer.UTILITY: [Component.NGINX, Component.TEXLIVE],
|
|
125
129
|
}
|
|
126
130
|
|
|
127
131
|
DEPENDENCIES = {
|
|
@@ -140,6 +144,7 @@ DESCRIPTIONS = {
|
|
|
140
144
|
# STORAGE
|
|
141
145
|
Component.POSTGRES: "Advanced Relational Database",
|
|
142
146
|
# UTILITY
|
|
147
|
+
Component.NGINX: "HTTP and reverse proxy server",
|
|
143
148
|
Component.TEXLIVE: "TeX Live is intended to be a straightforward way to get up and running with the TeX document production system", # noqa
|
|
144
149
|
}
|
|
145
150
|
|
|
@@ -151,6 +156,8 @@ PORTS = {
|
|
|
151
156
|
Component.API_POSTGRES: "8000",
|
|
152
157
|
# STORAGE
|
|
153
158
|
Component.POSTGRES: "5432",
|
|
159
|
+
# UTILITY
|
|
160
|
+
Component.NGINX: "80",
|
|
154
161
|
}
|
|
155
162
|
|
|
156
163
|
|
|
@@ -211,6 +218,14 @@ LAYOUTS = {Layout.CUSTOM, Layout.RESEARCH}
|
|
|
211
218
|
PROFILES = {Profile.CUSTOM, Profile.RESEARCH}
|
|
212
219
|
|
|
213
220
|
|
|
221
|
+
BADGES = {
|
|
222
|
+
Layer.ANALYTICS: "badge badge-info gap-2",
|
|
223
|
+
Layer.API: "badge badge-accent gap-2",
|
|
224
|
+
Layer.STORAGE: "badge badge-warning gap-2",
|
|
225
|
+
Layer.UTILITY: "badge badge-secondary gap-2",
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
|
|
214
229
|
class Field:
|
|
215
230
|
"""Field."""
|
|
216
231
|
|
|
@@ -690,6 +705,109 @@ class Project:
|
|
|
690
705
|
|
|
691
706
|
rprint(f"{self.name}: {self.layout} layout[green] created[/green]")
|
|
692
707
|
|
|
708
|
+
def add_docs(self):
|
|
709
|
+
"""Add project docs."""
|
|
710
|
+
from_path = os.path.join(SRC_PATH, "docs")
|
|
711
|
+
if not os.path.exists(from_path):
|
|
712
|
+
raise ValueError(f"{from_path} does not exist")
|
|
713
|
+
|
|
714
|
+
to_path = os.path.join(self.path, "docs")
|
|
715
|
+
if os.path.exists(to_path):
|
|
716
|
+
raise ValueError(f"{to_path} already exists")
|
|
717
|
+
|
|
718
|
+
shutil.copytree(
|
|
719
|
+
from_path,
|
|
720
|
+
to_path,
|
|
721
|
+
ignore=shutil.ignore_patterns(
|
|
722
|
+
*IGNORE_PATTERNS, *("mkdocs.yml", "requirements.txt")
|
|
723
|
+
),
|
|
724
|
+
)
|
|
725
|
+
|
|
726
|
+
if os.path.exists(os.path.join(self.path, "requirements.txt")):
|
|
727
|
+
with open(os.path.join(from_path, "requirements.txt"), "r") as file:
|
|
728
|
+
src_file_data = file.read()
|
|
729
|
+
with open(os.path.join(self.path, "requirements.txt"), "a") as file:
|
|
730
|
+
file.write(src_file_data)
|
|
731
|
+
else:
|
|
732
|
+
self.copy(from_path, self.path, "requirements.txt")
|
|
733
|
+
|
|
734
|
+
self.copy(from_path, self.path, "mkdocs.yml")
|
|
735
|
+
self.replace(
|
|
736
|
+
os.path.join(self.path, "docs", "index.md"), PROJECT_NAME, self.name
|
|
737
|
+
)
|
|
738
|
+
self.replace(os.path.join(self.path, "mkdocs.yml"), PROJECT_NAME, self.name)
|
|
739
|
+
|
|
740
|
+
rprint(f"{self.name}: docs[green] created[/green]")
|
|
741
|
+
|
|
742
|
+
def add_hooks(self):
|
|
743
|
+
"""Add project pre-commit hooks."""
|
|
744
|
+
from_path = os.path.join(SRC_PATH, "hooks")
|
|
745
|
+
if not os.path.exists(from_path):
|
|
746
|
+
raise ValueError(f"{from_path} does not exist")
|
|
747
|
+
|
|
748
|
+
if os.path.exists(os.path.join(self.path, ".pre-commit-config.yaml")):
|
|
749
|
+
raise ValueError(
|
|
750
|
+
f'{os.path.join(self.path, ".pre-commit-config.yaml")} already exists'
|
|
751
|
+
)
|
|
752
|
+
|
|
753
|
+
self.copy(from_path, self.path, ".pre-commit-config.yaml")
|
|
754
|
+
|
|
755
|
+
if os.path.exists(os.path.join(self.path, "requirements.txt")):
|
|
756
|
+
with open(os.path.join(from_path, "requirements.txt"), "r") as file:
|
|
757
|
+
src_file_data = file.read()
|
|
758
|
+
with open(os.path.join(self.path, "requirements.txt"), "a") as file:
|
|
759
|
+
file.write(src_file_data)
|
|
760
|
+
else:
|
|
761
|
+
self.copy(from_path, self.path, "requirements.txt")
|
|
762
|
+
|
|
763
|
+
rprint(f"{self.name}: .pre-commit-config.yaml[green] created[/green]")
|
|
764
|
+
|
|
765
|
+
def add_workflows(self):
|
|
766
|
+
"""Add github workflows (github pages ci for docs)."""
|
|
767
|
+
from_path = os.path.join(SRC_PATH, "github")
|
|
768
|
+
if not os.path.exists(from_path):
|
|
769
|
+
raise ValueError(f"{from_path} does not exist")
|
|
770
|
+
|
|
771
|
+
to_path = os.path.join(self.path, ".github")
|
|
772
|
+
if os.path.exists(to_path):
|
|
773
|
+
raise ValueError(f"{to_path} already exists")
|
|
774
|
+
|
|
775
|
+
shutil.copytree(
|
|
776
|
+
from_path,
|
|
777
|
+
to_path,
|
|
778
|
+
ignore=shutil.ignore_patterns(
|
|
779
|
+
*IGNORE_PATTERNS,
|
|
780
|
+
),
|
|
781
|
+
)
|
|
782
|
+
|
|
783
|
+
rprint(f"{self.name}: github workflows[green] created[/green]")
|
|
784
|
+
|
|
785
|
+
def add_tests(self):
|
|
786
|
+
"""Add project tests."""
|
|
787
|
+
from_path = os.path.join(SRC_PATH, "tests")
|
|
788
|
+
if not os.path.exists(from_path):
|
|
789
|
+
raise ValueError(f"{from_path} does not exist")
|
|
790
|
+
|
|
791
|
+
to_path = os.path.join(self.path, "tests")
|
|
792
|
+
if os.path.exists(to_path):
|
|
793
|
+
raise ValueError(f"{to_path} already exists")
|
|
794
|
+
|
|
795
|
+
shutil.copytree(
|
|
796
|
+
from_path,
|
|
797
|
+
to_path,
|
|
798
|
+
ignore=shutil.ignore_patterns(*IGNORE_PATTERNS, *("requirements.txt",)),
|
|
799
|
+
)
|
|
800
|
+
|
|
801
|
+
if os.path.exists(os.path.join(self.path, "requirements.txt")):
|
|
802
|
+
with open(os.path.join(from_path, "requirements.txt"), "r") as file:
|
|
803
|
+
src_file_data = file.read()
|
|
804
|
+
with open(os.path.join(self.path, "requirements.txt"), "a") as file:
|
|
805
|
+
file.write(src_file_data)
|
|
806
|
+
else:
|
|
807
|
+
self.copy(from_path, self.path, "requirements.txt")
|
|
808
|
+
|
|
809
|
+
rprint(f"{self.name}: tests[green] created[/green]")
|
|
810
|
+
|
|
693
811
|
def init(self):
|
|
694
812
|
"""Handler for `init` CLI command."""
|
|
695
813
|
rprint()
|
|
@@ -804,10 +922,24 @@ class Project:
|
|
|
804
922
|
rprint(f"{json.dumps(self.settings, indent=JSON_INDENT)}")
|
|
805
923
|
rprint()
|
|
806
924
|
|
|
807
|
-
def create(
|
|
925
|
+
def create(
|
|
926
|
+
self,
|
|
927
|
+
docs: bool = True,
|
|
928
|
+
hooks: bool = True,
|
|
929
|
+
workflows: bool = False,
|
|
930
|
+
tests: bool = True,
|
|
931
|
+
):
|
|
808
932
|
"""Handler for `create` CLI command."""
|
|
809
933
|
self.from_json()
|
|
810
934
|
self.add_layout()
|
|
935
|
+
if docs:
|
|
936
|
+
self.add_docs()
|
|
937
|
+
if hooks:
|
|
938
|
+
self.add_hooks()
|
|
939
|
+
if workflows:
|
|
940
|
+
self.add_workflows()
|
|
941
|
+
if tests:
|
|
942
|
+
self.add_tests()
|
|
811
943
|
|
|
812
944
|
layers = [
|
|
813
945
|
Analytics(project=self),
|
|
@@ -890,7 +1022,7 @@ class Project:
|
|
|
890
1022
|
if not os.path.exists(to_path):
|
|
891
1023
|
raise ValueError(f"{to_path} does not exist")
|
|
892
1024
|
|
|
893
|
-
scripts = ["
|
|
1025
|
+
scripts = ["setup.sh", "requirements.txt"]
|
|
894
1026
|
|
|
895
1027
|
for file_name in scripts:
|
|
896
1028
|
if file_name == "requirements.txt":
|
|
@@ -905,14 +1037,10 @@ class Project:
|
|
|
905
1037
|
self.copy(from_path, to_path, file_name)
|
|
906
1038
|
|
|
907
1039
|
self.copy(from_path, to_path, "docker-compose.yaml")
|
|
908
|
-
|
|
909
|
-
self.copy(from_path, self.path, "env.sh")
|
|
910
1040
|
self.copy(from_path, self.path, "expectations.py")
|
|
911
|
-
self.copy(from_path, self.path, "main.sh")
|
|
912
1041
|
self.copy(from_path, self.path, "README.md")
|
|
913
1042
|
|
|
914
1043
|
self.replace(os.path.join(self.path, "README.md"), f"{PROJECT_NAME}", self.name)
|
|
915
|
-
self.replace(os.path.join(self.path, "main.sh"), f"{PROJECT_NAME}", self.name)
|
|
916
1044
|
|
|
917
1045
|
for layer in COMPONENTS:
|
|
918
1046
|
if layer is Layer.DEVCONTAINERS:
|
|
@@ -944,11 +1072,20 @@ class Project:
|
|
|
944
1072
|
if lines and layer == Layer.STORAGE and file_name == "setup.sh":
|
|
945
1073
|
# put storage setup logic on top of setup.sh
|
|
946
1074
|
with open(f"{to_path}/{file_name}", "r") as file:
|
|
947
|
-
current_file_data = file.
|
|
948
|
-
|
|
1075
|
+
current_file_data = file.readlines()
|
|
1076
|
+
# keep shebang on top of the file
|
|
1077
|
+
header, current_file_data = (
|
|
1078
|
+
current_file_data[:3],
|
|
1079
|
+
current_file_data[3:],
|
|
1080
|
+
)
|
|
1081
|
+
header = [line for line in header if line != "\n"]
|
|
1082
|
+
header = "".join([*header])
|
|
1083
|
+
current_file_data = "".join([*current_file_data])
|
|
949
1084
|
with open(f"{to_path}/{file_name}", "w") as file:
|
|
950
1085
|
file.write(
|
|
951
|
-
"\n".join(
|
|
1086
|
+
"\n".join(
|
|
1087
|
+
[header, src_file_data, *lines, current_file_data]
|
|
1088
|
+
)
|
|
952
1089
|
)
|
|
953
1090
|
|
|
954
1091
|
else:
|
|
@@ -1398,6 +1535,113 @@ class Utility:
|
|
|
1398
1535
|
"""Create Utility layer instance."""
|
|
1399
1536
|
self.project = project
|
|
1400
1537
|
|
|
1538
|
+
def nginx(self):
|
|
1539
|
+
"""Configure Analytics `NGINX` component."""
|
|
1540
|
+
from_path = os.path.join(SRC_PATH, Layer.UTILITY, Component.NGINX)
|
|
1541
|
+
if not os.path.exists(from_path):
|
|
1542
|
+
raise ValueError(f"{from_path} does not exist")
|
|
1543
|
+
|
|
1544
|
+
to_path = os.path.join(
|
|
1545
|
+
self.project.path, PLATFORM_FOLDER, Layer.UTILITY, Component.NGINX
|
|
1546
|
+
)
|
|
1547
|
+
if os.path.exists(to_path):
|
|
1548
|
+
raise ValueError(f"{to_path} already exists")
|
|
1549
|
+
|
|
1550
|
+
entities = self.project.settings.get("entities", {})
|
|
1551
|
+
|
|
1552
|
+
for plural_name, settings in entities.items():
|
|
1553
|
+
components = settings["layers"].get(Layer.UTILITY, {})
|
|
1554
|
+
if Component.NGINX not in components:
|
|
1555
|
+
continue
|
|
1556
|
+
|
|
1557
|
+
if os.path.exists(to_path):
|
|
1558
|
+
raise ValueError(f"{to_path} already exists")
|
|
1559
|
+
|
|
1560
|
+
shutil.copytree(
|
|
1561
|
+
from_path,
|
|
1562
|
+
to_path,
|
|
1563
|
+
ignore=shutil.ignore_patterns(*IGNORE_PATTERNS),
|
|
1564
|
+
)
|
|
1565
|
+
|
|
1566
|
+
break
|
|
1567
|
+
|
|
1568
|
+
if not os.path.exists(to_path):
|
|
1569
|
+
return
|
|
1570
|
+
|
|
1571
|
+
Project.replace(
|
|
1572
|
+
os.path.join(to_path, "docker-compose.yaml"),
|
|
1573
|
+
PROJECT_NAME,
|
|
1574
|
+
self.project.settings["project"],
|
|
1575
|
+
)
|
|
1576
|
+
|
|
1577
|
+
ports = self.project.settings.get("ports", {})
|
|
1578
|
+
|
|
1579
|
+
Project.replace(
|
|
1580
|
+
os.path.join(to_path, "docker-compose.yaml"),
|
|
1581
|
+
f"{PORTS[Component.NGINX]}:",
|
|
1582
|
+
f"{ports[Component.NGINX]}:",
|
|
1583
|
+
)
|
|
1584
|
+
|
|
1585
|
+
host = "http://localhost"
|
|
1586
|
+
target_path = os.path.join(to_path, "static", "index.html")
|
|
1587
|
+
|
|
1588
|
+
Project.replace(target_path, PROJECT_NAME, self.project.settings["project"])
|
|
1589
|
+
|
|
1590
|
+
with open(target_path, "r") as file:
|
|
1591
|
+
filedata = file.read()
|
|
1592
|
+
|
|
1593
|
+
header = filedata.split("<tbody>")[0]
|
|
1594
|
+
template, _ = filedata.split("<tbody>")[1].split("</tbody>")
|
|
1595
|
+
footer = filedata.split("</tbody>")[1]
|
|
1596
|
+
|
|
1597
|
+
lines = [header]
|
|
1598
|
+
|
|
1599
|
+
for component, port in ports.items():
|
|
1600
|
+
layer = None
|
|
1601
|
+
for current_layer, components in COMPONENTS.items():
|
|
1602
|
+
if component in components:
|
|
1603
|
+
layer = current_layer
|
|
1604
|
+
break
|
|
1605
|
+
if not layer:
|
|
1606
|
+
continue
|
|
1607
|
+
|
|
1608
|
+
tr = template.replace(
|
|
1609
|
+
'class="badge badge-info gap-2">layer_name',
|
|
1610
|
+
f'class="{BADGES[layer]}">{layer}',
|
|
1611
|
+
)
|
|
1612
|
+
tr = tr.replace("component_name", f"{component}")
|
|
1613
|
+
tr = tr.replace("http://host:port/", f"{host}:{port}/")
|
|
1614
|
+
lines.append(tr)
|
|
1615
|
+
|
|
1616
|
+
entities = self.project.settings.get("entities", {})
|
|
1617
|
+
|
|
1618
|
+
for plural_name, settings in entities.items():
|
|
1619
|
+
layers = settings.get("layers", {})
|
|
1620
|
+
|
|
1621
|
+
if Component.NGINX not in layers.get(Layer.UTILITY, {}):
|
|
1622
|
+
continue
|
|
1623
|
+
|
|
1624
|
+
for layer, components in layers.items():
|
|
1625
|
+
for component in components:
|
|
1626
|
+
port = components[component].get("port")
|
|
1627
|
+
if not port:
|
|
1628
|
+
continue
|
|
1629
|
+
|
|
1630
|
+
tr = template.replace(
|
|
1631
|
+
'class="badge badge-info gap-2">layer_name',
|
|
1632
|
+
f'class="{BADGES[layer]}">{layer}',
|
|
1633
|
+
)
|
|
1634
|
+
tr = tr.replace("component_name", f"{component} | {plural_name}")
|
|
1635
|
+
tr = tr.replace("http://host:port/", f"{host}:{port}/")
|
|
1636
|
+
lines.append(tr)
|
|
1637
|
+
|
|
1638
|
+
lines.append(footer)
|
|
1639
|
+
filedata = "\n".join(lines)
|
|
1640
|
+
with open(target_path, "w") as file:
|
|
1641
|
+
file.write(filedata)
|
|
1642
|
+
|
|
1643
|
+
rprint(f"{to_path}[green] created[/green]")
|
|
1644
|
+
|
|
1401
1645
|
def texlive(self):
|
|
1402
1646
|
"""Configure Analytics `TEXLIVE` component."""
|
|
1403
1647
|
from_path = os.path.join(SRC_PATH, Layer.UTILITY, Component.TEXLIVE)
|
|
@@ -1447,6 +1691,7 @@ class Utility:
|
|
|
1447
1691
|
|
|
1448
1692
|
def __call__(self):
|
|
1449
1693
|
"""Call layer."""
|
|
1694
|
+
self.nginx()
|
|
1450
1695
|
self.texlive()
|
|
1451
1696
|
|
|
1452
1697
|
|
|
@@ -1507,15 +1752,228 @@ def init(
|
|
|
1507
1752
|
|
|
1508
1753
|
|
|
1509
1754
|
@app.command()
|
|
1510
|
-
def create(
|
|
1755
|
+
def create(
|
|
1756
|
+
project: str,
|
|
1757
|
+
path: str = "",
|
|
1758
|
+
docs: bool = True,
|
|
1759
|
+
hooks: bool = True,
|
|
1760
|
+
workflows: bool = False,
|
|
1761
|
+
tests: bool = True,
|
|
1762
|
+
):
|
|
1511
1763
|
"""Create PROJECT structure based on settings.json, optionally with a --path."""
|
|
1512
1764
|
try:
|
|
1513
1765
|
project = Project(name=project, path=path)
|
|
1514
|
-
project.create()
|
|
1766
|
+
project.create(docs=docs, hooks=hooks, workflows=workflows, tests=tests)
|
|
1515
1767
|
except Exception:
|
|
1516
1768
|
rprint(f"[bold red] {traceback.format_exc()} [/bold red]")
|
|
1517
1769
|
|
|
1518
1770
|
|
|
1771
|
+
@app.command()
|
|
1772
|
+
def install(project: str = "", path: str = ""):
|
|
1773
|
+
"""Install dependencies into .venv from requirements.txt under cwd/path."""
|
|
1774
|
+
try:
|
|
1775
|
+
if path and not os.path.exists(path):
|
|
1776
|
+
raise ValueError(f"{path} does not exists")
|
|
1777
|
+
elif not path:
|
|
1778
|
+
path = os.getcwd()
|
|
1779
|
+
path = os.path.join(path, project)
|
|
1780
|
+
venv_path = os.path.join(path, ".venv")
|
|
1781
|
+
if os.path.exists(venv_path):
|
|
1782
|
+
raise ValueError(f"{venv_path} already exists")
|
|
1783
|
+
|
|
1784
|
+
requirements_path = os.path.join(path, "requirements.txt")
|
|
1785
|
+
if not os.path.exists(requirements_path):
|
|
1786
|
+
raise ValueError(f"{requirements_path} not exists")
|
|
1787
|
+
|
|
1788
|
+
venv.create(venv_path, with_pip=True)
|
|
1789
|
+
subprocess.run(["bin/pip", "install", "-r", requirements_path], cwd=venv_path)
|
|
1790
|
+
except Exception as e:
|
|
1791
|
+
rprint(f"[bold red] {e} [/bold red]")
|
|
1792
|
+
|
|
1793
|
+
|
|
1794
|
+
@app.command()
|
|
1795
|
+
def build(project: str = "", path: str = ""):
|
|
1796
|
+
"""Run `docker compose --profile {layer} build`."""
|
|
1797
|
+
try:
|
|
1798
|
+
if path and not os.path.exists(path):
|
|
1799
|
+
raise ValueError(f"{path} does not exists")
|
|
1800
|
+
elif not path:
|
|
1801
|
+
path = os.getcwd()
|
|
1802
|
+
path = os.path.join(path, project, "platform")
|
|
1803
|
+
|
|
1804
|
+
compose_path = os.path.join(path, "docker-compose.yaml")
|
|
1805
|
+
if not os.path.exists(compose_path):
|
|
1806
|
+
raise ValueError(f"{compose_path} not exists")
|
|
1807
|
+
|
|
1808
|
+
for layer in COMPONENTS:
|
|
1809
|
+
subprocess.run(
|
|
1810
|
+
["docker", "compose", "--profile", f"{layer}", "build"], cwd=path
|
|
1811
|
+
)
|
|
1812
|
+
|
|
1813
|
+
except Exception as e:
|
|
1814
|
+
rprint(f"[bold red] {e} [/bold red]")
|
|
1815
|
+
|
|
1816
|
+
|
|
1817
|
+
@app.command()
|
|
1818
|
+
def start(project: str = "", path: str = ""):
|
|
1819
|
+
"""Run `docker compose --profile {layer} up -d`."""
|
|
1820
|
+
try:
|
|
1821
|
+
if path and not os.path.exists(path):
|
|
1822
|
+
raise ValueError(f"{path} does not exists")
|
|
1823
|
+
elif not path:
|
|
1824
|
+
path = os.getcwd()
|
|
1825
|
+
path = os.path.join(path, project, "platform")
|
|
1826
|
+
|
|
1827
|
+
compose_path = os.path.join(path, "docker-compose.yaml")
|
|
1828
|
+
if not os.path.exists(compose_path):
|
|
1829
|
+
raise ValueError(f"{compose_path} not exists")
|
|
1830
|
+
|
|
1831
|
+
for layer in COMPONENTS:
|
|
1832
|
+
subprocess.run(
|
|
1833
|
+
["docker", "compose", "--profile", f"{layer}", "up", "-d"], cwd=path
|
|
1834
|
+
)
|
|
1835
|
+
|
|
1836
|
+
except Exception as e:
|
|
1837
|
+
rprint(f"[bold red] {e} [/bold red]")
|
|
1838
|
+
|
|
1839
|
+
|
|
1840
|
+
@app.command()
|
|
1841
|
+
def stop(project: str = "", path: str = ""):
|
|
1842
|
+
"""Run `docker compose --profile {layer} stop`."""
|
|
1843
|
+
try:
|
|
1844
|
+
if path and not os.path.exists(path):
|
|
1845
|
+
raise ValueError(f"{path} does not exists")
|
|
1846
|
+
elif not path:
|
|
1847
|
+
path = os.getcwd()
|
|
1848
|
+
path = os.path.join(path, project, "platform")
|
|
1849
|
+
|
|
1850
|
+
compose_path = os.path.join(path, "docker-compose.yaml")
|
|
1851
|
+
if not os.path.exists(compose_path):
|
|
1852
|
+
raise ValueError(f"{compose_path} not exists")
|
|
1853
|
+
|
|
1854
|
+
for layer in COMPONENTS:
|
|
1855
|
+
subprocess.run(
|
|
1856
|
+
["docker", "compose", "--profile", f"{layer}", "stop"], cwd=path
|
|
1857
|
+
)
|
|
1858
|
+
|
|
1859
|
+
except Exception as e:
|
|
1860
|
+
rprint(f"[bold red] {e} [/bold red]")
|
|
1861
|
+
|
|
1862
|
+
|
|
1863
|
+
@app.command()
|
|
1864
|
+
def status(project: str = "", path: str = ""):
|
|
1865
|
+
"""Run `docker compose ps`."""
|
|
1866
|
+
try:
|
|
1867
|
+
if path and not os.path.exists(path):
|
|
1868
|
+
raise ValueError(f"{path} does not exists")
|
|
1869
|
+
elif not path:
|
|
1870
|
+
path = os.getcwd()
|
|
1871
|
+
path = os.path.join(path, project, "platform")
|
|
1872
|
+
|
|
1873
|
+
compose_path = os.path.join(path, "docker-compose.yaml")
|
|
1874
|
+
if not os.path.exists(compose_path):
|
|
1875
|
+
raise ValueError(f"{compose_path} not exists")
|
|
1876
|
+
|
|
1877
|
+
subprocess.run(["docker", "compose", "ps", "--all"], cwd=path)
|
|
1878
|
+
|
|
1879
|
+
except Exception as e:
|
|
1880
|
+
rprint(f"[bold red] {e} [/bold red]")
|
|
1881
|
+
|
|
1882
|
+
|
|
1883
|
+
@app.command()
|
|
1884
|
+
def setup(project: str = "", path: str = ""):
|
|
1885
|
+
"""Run `platform/setup.sh`."""
|
|
1886
|
+
try:
|
|
1887
|
+
if path and not os.path.exists(path):
|
|
1888
|
+
raise ValueError(f"{path} does not exists")
|
|
1889
|
+
elif not path:
|
|
1890
|
+
path = os.getcwd()
|
|
1891
|
+
path = os.path.join(path, project, "platform")
|
|
1892
|
+
|
|
1893
|
+
setup_path = os.path.join(path, "setup.sh")
|
|
1894
|
+
if not os.path.exists(setup_path):
|
|
1895
|
+
raise ValueError(f"{setup_path} not exists")
|
|
1896
|
+
|
|
1897
|
+
os.chmod(setup_path, os.stat(setup_path).st_mode | stat.S_IEXEC)
|
|
1898
|
+
subprocess.run(["./setup.sh"], cwd=path)
|
|
1899
|
+
|
|
1900
|
+
except Exception as e:
|
|
1901
|
+
rprint(f"[bold red] {e} [/bold red]")
|
|
1902
|
+
|
|
1903
|
+
|
|
1904
|
+
@app.command()
|
|
1905
|
+
def check(project: str = "", path: str = ""):
|
|
1906
|
+
"""Run `pre-commit run --all-files`."""
|
|
1907
|
+
try:
|
|
1908
|
+
if path and not os.path.exists(path):
|
|
1909
|
+
raise ValueError(f"{path} does not exist")
|
|
1910
|
+
elif not path:
|
|
1911
|
+
path = os.getcwd()
|
|
1912
|
+
path = os.path.join(path, project)
|
|
1913
|
+
venv_path = os.path.join(path, ".venv")
|
|
1914
|
+
if not os.path.exists(venv_path):
|
|
1915
|
+
raise ValueError(f"{venv_path} does not exist")
|
|
1916
|
+
|
|
1917
|
+
pre_commit_path = os.path.join(path, ".pre-commit-config.yaml")
|
|
1918
|
+
if not os.path.exists(pre_commit_path):
|
|
1919
|
+
raise ValueError(f"{pre_commit_path} does not exist")
|
|
1920
|
+
|
|
1921
|
+
subprocess.run([".venv/bin/pre-commit", "run", "--all-files"], cwd=path)
|
|
1922
|
+
except Exception as e:
|
|
1923
|
+
rprint(f"[bold red] {e} [/bold red]")
|
|
1924
|
+
|
|
1925
|
+
|
|
1926
|
+
@app.command()
|
|
1927
|
+
def docs(project: str = "", path: str = ""):
|
|
1928
|
+
"""Run `mkdocs serve`."""
|
|
1929
|
+
try:
|
|
1930
|
+
if path and not os.path.exists(path):
|
|
1931
|
+
raise ValueError(f"{path} does not exist")
|
|
1932
|
+
elif not path:
|
|
1933
|
+
path = os.getcwd()
|
|
1934
|
+
path = os.path.join(path, project)
|
|
1935
|
+
venv_path = os.path.join(path, ".venv")
|
|
1936
|
+
if not os.path.exists(venv_path):
|
|
1937
|
+
raise ValueError(f"{venv_path} does not exist")
|
|
1938
|
+
|
|
1939
|
+
docs_path = os.path.join(path, "mkdocs.yml")
|
|
1940
|
+
if not os.path.exists(docs_path):
|
|
1941
|
+
raise ValueError(f"{docs_path} does not exist")
|
|
1942
|
+
|
|
1943
|
+
subprocess.run([".venv/bin/mkdocs", "serve"], cwd=path)
|
|
1944
|
+
except Exception as e:
|
|
1945
|
+
rprint(f"[bold red] {e} [/bold red]")
|
|
1946
|
+
|
|
1947
|
+
|
|
1948
|
+
@app.command()
|
|
1949
|
+
def test(project: str = "", path: str = "", cov: str = ""):
|
|
1950
|
+
"""Run `pytest --cov={cov} tests`."""
|
|
1951
|
+
try:
|
|
1952
|
+
if path and not os.path.exists(path):
|
|
1953
|
+
raise ValueError(f"{path} does not exist")
|
|
1954
|
+
elif not path:
|
|
1955
|
+
path = os.getcwd()
|
|
1956
|
+
path = os.path.join(path, project)
|
|
1957
|
+
venv_path = os.path.join(path, ".venv")
|
|
1958
|
+
if not os.path.exists(venv_path):
|
|
1959
|
+
raise ValueError(f"{venv_path} does not exist")
|
|
1960
|
+
|
|
1961
|
+
test_path = os.path.join(path, "tests")
|
|
1962
|
+
if not os.path.exists(test_path):
|
|
1963
|
+
raise ValueError(f"{test_path} does not exist")
|
|
1964
|
+
|
|
1965
|
+
if cov:
|
|
1966
|
+
cov_path = os.path.join(path, cov)
|
|
1967
|
+
if not os.path.exists(cov_path):
|
|
1968
|
+
raise ValueError(f"{cov_path} does not exist")
|
|
1969
|
+
|
|
1970
|
+
subprocess.run([".venv/bin/pytest", f"--cov={cov}", "tests"], cwd=path)
|
|
1971
|
+
else:
|
|
1972
|
+
subprocess.run([".venv/bin/pytest", "tests"], cwd=path)
|
|
1973
|
+
except Exception as e:
|
|
1974
|
+
rprint(f"[bold red] {e} [/bold red]")
|
|
1975
|
+
|
|
1976
|
+
|
|
1519
1977
|
def main():
|
|
1520
1978
|
"""Main function which starts the app."""
|
|
1521
1979
|
rprint(colorized_logo())
|