opendataframework 0.0.3__tar.gz → 0.0.4__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.3 → opendataframework-0.0.4}/PKG-INFO +1 -1
- {opendataframework-0.0.3 → opendataframework-0.0.4}/pyproject.toml +1 -1
- {opendataframework-0.0.3 → opendataframework-0.0.4}/setup.py +3 -2
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/__init__.py +1 -1
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/__main__.py +161 -2
- opendataframework-0.0.4/src/opendataframework/api/inference/.env +7 -0
- opendataframework-0.0.4/src/opendataframework/api/inference/Dockerfile +16 -0
- opendataframework-0.0.4/src/opendataframework/api/inference/app/__init__.py +11 -0
- opendataframework-0.0.4/src/opendataframework/api/inference/app/config.py +14 -0
- opendataframework-0.0.4/src/opendataframework/api/inference/app/crud.py +14 -0
- opendataframework-0.0.4/src/opendataframework/api/inference/app/dependencies.py +19 -0
- opendataframework-0.0.4/src/opendataframework/api/inference/app/main.py +39 -0
- opendataframework-0.0.4/src/opendataframework/api/inference/app/models.py +20 -0
- opendataframework-0.0.4/src/opendataframework/api/inference/app/router.py +18 -0
- opendataframework-0.0.4/src/opendataframework/api/inference/docker-compose.yaml +16 -0
- opendataframework-0.0.4/src/opendataframework/api/inference/pyproject.toml +20 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/LICENSE +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/README.md +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/README.md +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/analytics/setup.sh +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/analytics/superset/.env +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/analytics/superset/Dockerfile +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/analytics/superset/database/postgres/create.sh +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/analytics/superset/database/postgres/setup.sh +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/analytics/superset/docker-compose.yaml +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/analytics/superset/setup.sh +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/api/api-postgres/.env +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/api/api-postgres/Dockerfile +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/api/api-postgres/app/__init__.py +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/api/api-postgres/app/config.py +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/api/api-postgres/app/crud.py +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/api/api-postgres/app/database.py +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/api/api-postgres/app/dependencies.py +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/api/api-postgres/app/main.py +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/api/api-postgres/app/models.py +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/api/api-postgres/app/router.py +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/api/api-postgres/docker-compose.yaml +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/api/api-postgres/poetry.lock +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/api/api-postgres/pyproject.toml +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/api/ingest.py +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/api/requirements.txt +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/api/setup.sh +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/devcontainers/R/.devcontainer/.Rprofile +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/devcontainers/R/.devcontainer/Dockerfile +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/devcontainers/R/.devcontainer/devcontainer.json +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/devcontainers/python/.devcontainer/Dockerfile +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/devcontainers/python/.devcontainer/devcontainer.json +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/docker-compose.yaml +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/docs/index.md +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/docs/mkdocs.yml +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/docs/requirements.txt +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/docs/stylesheets/extra.css +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/expectations.py +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/github/workflows/ci.yaml +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/hooks/.pre-commit-config.yaml +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/hooks/requirements.txt +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/layouts/research/.vscode/extensions.json +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/layouts/research/code/build/.gitkeep +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/layouts/research/code/check/.gitkeep +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/layouts/research/code/learn/.gitkeep +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/layouts/research/code/share/.gitkeep +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/layouts/research/data/derived/.gitkeep +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/layouts/research/data/raw/.gitkeep +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/layouts/research/libraries/.gitkeep +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/layouts/research/logs/.gitkeep +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/layouts/research/models/.gitkeep +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/layouts/research/output/figures/.gitkeep +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/layouts/research/output/tables/.gitkeep +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/layouts/research/paper/.gitkeep +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/requirements.txt +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/setup.sh +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/storage/postgres/.env +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/storage/postgres/Dockerfile +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/storage/postgres/docker-compose.yaml +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/storage/postgres/setup.sh +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/storage/setup.sh +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/tests/__init__.py +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/tests/requirements.txt +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/tests/test_example.py +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/utility/nginx/Dockerfile +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/utility/nginx/docker-compose.yaml +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/utility/nginx/nginx.conf +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/utility/nginx/static/images/logo.svg +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/utility/nginx/static/index.html +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/utility/setup.sh +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/utility/texlive/Dockerfile +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/utility/texlive/docker-compose.yaml +0 -0
- {opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/utility/texlive/mnt/.gitkeep +0 -0
|
@@ -8,6 +8,7 @@ packages = \
|
|
|
8
8
|
['opendataframework',
|
|
9
9
|
'opendataframework.api',
|
|
10
10
|
'opendataframework.api.api-postgres.app',
|
|
11
|
+
'opendataframework.api.inference.app',
|
|
11
12
|
'opendataframework.tests']
|
|
12
13
|
|
|
13
14
|
package_data = \
|
|
@@ -42,7 +43,7 @@ package_data = \
|
|
|
42
43
|
'utility/nginx/static/images/*',
|
|
43
44
|
'utility/texlive/*',
|
|
44
45
|
'utility/texlive/mnt/*'],
|
|
45
|
-
'opendataframework.api': ['api-postgres/*']}
|
|
46
|
+
'opendataframework.api': ['api-postgres/*', 'inference/*']}
|
|
46
47
|
|
|
47
48
|
install_requires = \
|
|
48
49
|
['typer>=0.12.3,<0.13.0']
|
|
@@ -52,7 +53,7 @@ entry_points = \
|
|
|
52
53
|
|
|
53
54
|
setup_kwargs = {
|
|
54
55
|
'name': 'opendataframework',
|
|
55
|
-
'version': '0.0.
|
|
56
|
+
'version': '0.0.4',
|
|
56
57
|
'description': 'Open Data Framework is an open source, full stack data framework.',
|
|
57
58
|
'long_description': '# Open Data Framework\nOpen source, full stack data framework.\n',
|
|
58
59
|
'author': 'mykytapavlov',
|
|
@@ -100,6 +100,7 @@ class Component:
|
|
|
100
100
|
|
|
101
101
|
# API
|
|
102
102
|
API_POSTGRES: str = "api-postgres"
|
|
103
|
+
INFERENCE: str = "inference"
|
|
103
104
|
|
|
104
105
|
# DEVCONTAINERS
|
|
105
106
|
PYTHON: str = "python"
|
|
@@ -123,7 +124,7 @@ FILE_FORMATS = {
|
|
|
123
124
|
COMPONENTS = {
|
|
124
125
|
Layer.ANALYTICS: [Component.SUPERSET],
|
|
125
126
|
Layer.DEVCONTAINERS: [Component.PYTHON, Component.R],
|
|
126
|
-
Layer.API: [Component.API_POSTGRES],
|
|
127
|
+
Layer.API: [Component.API_POSTGRES, Component.INFERENCE],
|
|
127
128
|
Layer.STORAGE: [Component.POSTGRES],
|
|
128
129
|
Layer.UTILITY: [Component.NGINX, Component.TEXLIVE],
|
|
129
130
|
}
|
|
@@ -154,6 +155,7 @@ PORTS = {
|
|
|
154
155
|
Component.SUPERSET: "8088",
|
|
155
156
|
# API
|
|
156
157
|
Component.API_POSTGRES: "8000",
|
|
158
|
+
Component.INFERENCE: "8000",
|
|
157
159
|
# STORAGE
|
|
158
160
|
Component.POSTGRES: "5432",
|
|
159
161
|
# UTILITY
|
|
@@ -431,16 +433,20 @@ class Entity:
|
|
|
431
433
|
class Project:
|
|
432
434
|
"""Project."""
|
|
433
435
|
|
|
434
|
-
def __init__(self, name: str, path: str = "", data: str = ""):
|
|
436
|
+
def __init__(self, name: str, path: str = "", data: str = "", models: str = ""):
|
|
435
437
|
"""Create project instance."""
|
|
436
438
|
self._name = None
|
|
437
439
|
self._path = None
|
|
438
440
|
self._profile = Profile.CUSTOM
|
|
439
441
|
self._layout = Layout.CUSTOM
|
|
442
|
+
self._models = None
|
|
443
|
+
|
|
440
444
|
if data:
|
|
441
445
|
self._data = os.path.join(os.getcwd(), data)
|
|
442
446
|
else:
|
|
443
447
|
self._data = os.path.join(os.getcwd(), "data")
|
|
448
|
+
if models:
|
|
449
|
+
self._models = os.path.join(os.getcwd(), models)
|
|
444
450
|
|
|
445
451
|
self._settings = {
|
|
446
452
|
"opendataframework": __version__,
|
|
@@ -505,6 +511,34 @@ class Project:
|
|
|
505
511
|
|
|
506
512
|
self._path = path
|
|
507
513
|
|
|
514
|
+
if not self._models:
|
|
515
|
+
models = os.path.join(os.getcwd(), "models")
|
|
516
|
+
if not os.path.exists(models):
|
|
517
|
+
return
|
|
518
|
+
self._models = models
|
|
519
|
+
|
|
520
|
+
models_path = os.path.join(path, "models")
|
|
521
|
+
if not os.path.exists(models_path):
|
|
522
|
+
os.mkdir(models_path)
|
|
523
|
+
rprint(f"{models_path}[green] created[/green]")
|
|
524
|
+
|
|
525
|
+
for folder in os.listdir(self._models):
|
|
526
|
+
source_path = os.path.join(self._models, folder)
|
|
527
|
+
if os.path.isdir(source_path):
|
|
528
|
+
dest_path = os.path.join(models_path, folder)
|
|
529
|
+
if not os.path.exists(dest_path):
|
|
530
|
+
os.mkdir(dest_path)
|
|
531
|
+
|
|
532
|
+
for file_name in os.listdir(source_path):
|
|
533
|
+
supported = [
|
|
534
|
+
file_name.endswith(".pkl"),
|
|
535
|
+
file_name.strip().lower() == "requirements.txt",
|
|
536
|
+
]
|
|
537
|
+
if not any(supported):
|
|
538
|
+
continue
|
|
539
|
+
self.copy(source_path, dest_path, file_name)
|
|
540
|
+
rprint(f"{file_name}[green] copied to [/green]{dest_path}")
|
|
541
|
+
|
|
508
542
|
@property
|
|
509
543
|
def settings(self) -> dict:
|
|
510
544
|
"""Get project settings."""
|
|
@@ -1340,9 +1374,134 @@ class API:
|
|
|
1340
1374
|
|
|
1341
1375
|
rprint(f"{to_path}[green] created[/green]")
|
|
1342
1376
|
|
|
1377
|
+
def inference(self):
|
|
1378
|
+
"""Configure API `INFERENCE` component."""
|
|
1379
|
+
from_path = os.path.join(SRC_PATH, Layer.API, Component.INFERENCE)
|
|
1380
|
+
if not os.path.exists(from_path):
|
|
1381
|
+
raise ValueError(f"{from_path} does not exist")
|
|
1382
|
+
|
|
1383
|
+
entities = self.project.settings.get("entities", {})
|
|
1384
|
+
|
|
1385
|
+
for plural_name, settings in entities.items():
|
|
1386
|
+
components = settings["layers"].get(Layer.API, {})
|
|
1387
|
+
if Component.INFERENCE not in components:
|
|
1388
|
+
continue
|
|
1389
|
+
|
|
1390
|
+
to_path = os.path.join(
|
|
1391
|
+
self.project.path,
|
|
1392
|
+
PLATFORM_FOLDER,
|
|
1393
|
+
Layer.API,
|
|
1394
|
+
Component.INFERENCE,
|
|
1395
|
+
plural_name,
|
|
1396
|
+
)
|
|
1397
|
+
if os.path.exists(to_path):
|
|
1398
|
+
raise ValueError(f"{to_path} already exists")
|
|
1399
|
+
|
|
1400
|
+
shutil.copytree(
|
|
1401
|
+
from_path,
|
|
1402
|
+
to_path,
|
|
1403
|
+
ignore=shutil.ignore_patterns(
|
|
1404
|
+
*IGNORE_PATTERNS,
|
|
1405
|
+
),
|
|
1406
|
+
)
|
|
1407
|
+
|
|
1408
|
+
model_path = os.path.join(self.project.path, "models", plural_name)
|
|
1409
|
+
if not os.path.exists(os.path.join(model_path, "model.pkl")):
|
|
1410
|
+
raise ValueError(f"{model_path} does not exist")
|
|
1411
|
+
|
|
1412
|
+
Project.copy(model_path, os.path.join(to_path, "app"), "model.pkl")
|
|
1413
|
+
|
|
1414
|
+
if os.path.exists(os.path.join(model_path, "requirements.txt")):
|
|
1415
|
+
with open(os.path.join(model_path, "requirements.txt"), "r") as file:
|
|
1416
|
+
filedata = file.read()
|
|
1417
|
+
new_filedata = []
|
|
1418
|
+
for line in filedata.split("\n"):
|
|
1419
|
+
if not line:
|
|
1420
|
+
continue
|
|
1421
|
+
packet, version = line.split("==")
|
|
1422
|
+
new_line = f'{packet} = "{version}"'
|
|
1423
|
+
new_filedata.append(new_line)
|
|
1424
|
+
filedata = "\n".join(new_filedata)
|
|
1425
|
+
|
|
1426
|
+
Project.replace(
|
|
1427
|
+
os.path.join(to_path, "pyproject.toml"),
|
|
1428
|
+
"# dependencies",
|
|
1429
|
+
filedata,
|
|
1430
|
+
)
|
|
1431
|
+
|
|
1432
|
+
hostname = self.project.settings["project"].replace("_", "-")
|
|
1433
|
+
|
|
1434
|
+
Project.replace(
|
|
1435
|
+
os.path.join(to_path, "docker-compose.yaml"),
|
|
1436
|
+
f"hostname: {PROJECT_NAME}-{Component.INFERENCE}",
|
|
1437
|
+
f"hostname: {hostname}-{Component.INFERENCE}",
|
|
1438
|
+
)
|
|
1439
|
+
|
|
1440
|
+
Project.replace(
|
|
1441
|
+
os.path.join(to_path, "docker-compose.yaml"),
|
|
1442
|
+
f"{PROJECT_NAME}",
|
|
1443
|
+
self.project.settings["project"],
|
|
1444
|
+
)
|
|
1445
|
+
|
|
1446
|
+
Project.replace(
|
|
1447
|
+
os.path.join(to_path, "docker-compose.yaml"), "entity", plural_name
|
|
1448
|
+
)
|
|
1449
|
+
|
|
1450
|
+
port = components[Component.INFERENCE]["port"]
|
|
1451
|
+
Project.replace(
|
|
1452
|
+
os.path.join(to_path, "docker-compose.yaml"),
|
|
1453
|
+
f"{PORTS[Component.INFERENCE]}:",
|
|
1454
|
+
f"{port}:",
|
|
1455
|
+
)
|
|
1456
|
+
|
|
1457
|
+
# model
|
|
1458
|
+
model_path = os.path.join(to_path, "app", "models.py")
|
|
1459
|
+
new_text = "# fields"
|
|
1460
|
+
|
|
1461
|
+
for field_name, field_type in settings["fields"].items():
|
|
1462
|
+
if field_name in Field.RESERVED_FIELDS:
|
|
1463
|
+
raise ValueError(
|
|
1464
|
+
f"Field names `{self.RESERVED_FIELDS}` are reserved"
|
|
1465
|
+
)
|
|
1466
|
+
if "datetime" in field_type:
|
|
1467
|
+
# TODO: format validator
|
|
1468
|
+
field_type = "datetime"
|
|
1469
|
+
|
|
1470
|
+
new_text += f"\n {field_name}: {field_type}"
|
|
1471
|
+
|
|
1472
|
+
Project.replace(model_path, "# extra fields", new_text)
|
|
1473
|
+
Project.replace(model_path, "entities", plural_name)
|
|
1474
|
+
Project.replace(model_path, "Entity", settings["name"].capitalize())
|
|
1475
|
+
|
|
1476
|
+
# crud
|
|
1477
|
+
crud_path = os.path.join(to_path, "app", "crud.py")
|
|
1478
|
+
Project.replace(crud_path, "entity", settings["name"])
|
|
1479
|
+
Project.replace(crud_path, "entities", plural_name)
|
|
1480
|
+
Project.replace(crud_path, "Entity", settings["name"].capitalize())
|
|
1481
|
+
|
|
1482
|
+
# router
|
|
1483
|
+
router_path = os.path.join(to_path, "app", "router.py")
|
|
1484
|
+
Project.replace(router_path, "entity", settings["name"])
|
|
1485
|
+
Project.replace(router_path, "entities", plural_name)
|
|
1486
|
+
Project.replace(router_path, "Entity", settings["name"].capitalize())
|
|
1487
|
+
|
|
1488
|
+
# env
|
|
1489
|
+
env_path = os.path.join(to_path, ".env")
|
|
1490
|
+
Project.replace(
|
|
1491
|
+
env_path, f"{PROJECT_NAME}", self.project.settings["project"]
|
|
1492
|
+
)
|
|
1493
|
+
Project.replace(env_path, "description", settings["description"])
|
|
1494
|
+
|
|
1495
|
+
# main
|
|
1496
|
+
main_path = os.path.join(to_path, "app", "main.py")
|
|
1497
|
+
Project.replace(main_path, "entity", settings["name"])
|
|
1498
|
+
|
|
1499
|
+
rprint(f"{to_path}[green] created[/green]")
|
|
1500
|
+
|
|
1343
1501
|
def __call__(self):
|
|
1344
1502
|
"""Call layer."""
|
|
1345
1503
|
self.api_postgres()
|
|
1504
|
+
self.inference()
|
|
1346
1505
|
|
|
1347
1506
|
|
|
1348
1507
|
class Devcontainers:
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
FROM python:3.11.2
|
|
2
|
+
WORKDIR /api
|
|
3
|
+
|
|
4
|
+
COPY .env pyproject.toml ./
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
ARG poetry_version=1.3.2
|
|
8
|
+
RUN pip install poetry==${poetry_version}
|
|
9
|
+
RUN poetry config virtualenvs.create false
|
|
10
|
+
RUN poetry install
|
|
11
|
+
|
|
12
|
+
COPY app/ app/
|
|
13
|
+
|
|
14
|
+
EXPOSE 8000
|
|
15
|
+
|
|
16
|
+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""CRUD module."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
from app.models import Entity
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def predict(entity: Entity, inference: Any) -> float:
|
|
11
|
+
"""Predict."""
|
|
12
|
+
data = pd.DataFrame(entity.dict(), index=[0])
|
|
13
|
+
predictions = inference.predict(data)
|
|
14
|
+
return predictions[0]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Dependencies module."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import pickle
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
MODEL_PATH = os.path.join(Path(__file__).parent, "model.pkl")
|
|
8
|
+
INFERENCE_MODEL = None
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_inference():
|
|
12
|
+
"""Get inference model."""
|
|
13
|
+
global INFERENCE_MODEL
|
|
14
|
+
|
|
15
|
+
if INFERENCE_MODEL is None:
|
|
16
|
+
with open(MODEL_PATH, "rb") as file:
|
|
17
|
+
INFERENCE_MODEL = pickle.load(file) # nosec
|
|
18
|
+
|
|
19
|
+
yield INFERENCE_MODEL
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Main module."""
|
|
2
|
+
|
|
3
|
+
from fastapi import FastAPI
|
|
4
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
5
|
+
|
|
6
|
+
from app import settings
|
|
7
|
+
from app.models import HealthCheck
|
|
8
|
+
from app.router import inference_router
|
|
9
|
+
|
|
10
|
+
app = FastAPI(
|
|
11
|
+
title=settings.project_name,
|
|
12
|
+
version=settings.version,
|
|
13
|
+
openapi_url=f"{settings.api_v1_prefix}/openapi.json",
|
|
14
|
+
debug=settings.debug,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
origins = ["http://localhost:8080"]
|
|
19
|
+
|
|
20
|
+
app.add_middleware(
|
|
21
|
+
CORSMiddleware,
|
|
22
|
+
allow_origins=origins,
|
|
23
|
+
allow_credentials=True,
|
|
24
|
+
allow_methods=["*"],
|
|
25
|
+
allow_headers=["*"],
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@app.get("/", response_model=HealthCheck, tags=["status"])
|
|
30
|
+
async def health_check():
|
|
31
|
+
"""Health check."""
|
|
32
|
+
return {
|
|
33
|
+
"name": settings.project_name,
|
|
34
|
+
"version": settings.version,
|
|
35
|
+
"description": settings.description,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
app.include_router(inference_router, prefix=settings.api_v1_prefix)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Models module."""
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
from sqlmodel import SQLModel
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class HealthCheck(BaseModel):
|
|
8
|
+
"""Health check model."""
|
|
9
|
+
|
|
10
|
+
name: str
|
|
11
|
+
version: str
|
|
12
|
+
description: str
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Entity(SQLModel):
|
|
16
|
+
"""Entity model."""
|
|
17
|
+
|
|
18
|
+
__tablename__ = "entities"
|
|
19
|
+
|
|
20
|
+
# extra fields
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Router module."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from fastapi import APIRouter, Depends, status
|
|
6
|
+
|
|
7
|
+
from app.crud import predict
|
|
8
|
+
from app.dependencies import get_inference
|
|
9
|
+
from app.models import Entity
|
|
10
|
+
|
|
11
|
+
inference_router = APIRouter(prefix="/inference", tags=["inference"])
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@inference_router.post("/", status_code=status.HTTP_200_OK)
|
|
15
|
+
def get_prediction(entity: Entity, inference: Any = Depends(get_inference)) -> float:
|
|
16
|
+
"""Create prediction."""
|
|
17
|
+
prediction = predict(entity, inference)
|
|
18
|
+
return prediction
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
version: "3.9"
|
|
2
|
+
services:
|
|
3
|
+
project_name_entity:
|
|
4
|
+
profiles: ["api"]
|
|
5
|
+
image: project_name:entity
|
|
6
|
+
container_name: project_name_entity
|
|
7
|
+
hostname: project_name-entity
|
|
8
|
+
build:
|
|
9
|
+
context: ./api/inference/entity
|
|
10
|
+
args:
|
|
11
|
+
poetry_version: "1.3.2"
|
|
12
|
+
ports:
|
|
13
|
+
- 8000:8000
|
|
14
|
+
networks:
|
|
15
|
+
- project_name_default
|
|
16
|
+
restart: always
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "api"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = ""
|
|
5
|
+
authors = [""]
|
|
6
|
+
license = "MIT"
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
|
|
9
|
+
[tool.poetry.dependencies]
|
|
10
|
+
python = "^3.11"
|
|
11
|
+
fastapi = "^0.92.0"
|
|
12
|
+
sqlmodel = "^0.0.8"
|
|
13
|
+
python-dotenv = "^0.21.1"
|
|
14
|
+
uvicorn = "^0.20.0"
|
|
15
|
+
pandas = "^2.2.3"
|
|
16
|
+
# dependencies
|
|
17
|
+
|
|
18
|
+
[build-system]
|
|
19
|
+
requires = ["poetry-core"]
|
|
20
|
+
build-backend = "poetry.core.masonry.api"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/analytics/setup.sh
RENAMED
|
File without changes
|
{opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/analytics/superset/.env
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/api/api-postgres/.env
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/api/requirements.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/docker-compose.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/docs/requirements.txt
RENAMED
|
File without changes
|
{opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/docs/stylesheets/extra.css
RENAMED
|
File without changes
|
|
File without changes
|
{opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/github/workflows/ci.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/hooks/requirements.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/storage/postgres/.env
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/storage/postgres/setup.sh
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/tests/requirements.txt
RENAMED
|
File without changes
|
{opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/tests/test_example.py
RENAMED
|
File without changes
|
{opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/utility/nginx/Dockerfile
RENAMED
|
File without changes
|
|
File without changes
|
{opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/utility/nginx/nginx.conf
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opendataframework-0.0.3 → opendataframework-0.0.4}/src/opendataframework/utility/texlive/Dockerfile
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|