Skip to content

Commit c815eb8

Browse files
authored
✨♻️🐛 serviceslib[fastapi] and projects tables validation scripts (ITISFoundation#2550)
- New diagnostics script: in models-library/scripts a script to validate db projects table exported to a CSV - New extra for ``servicelib[fastapi]`` package with fastapi-only features (released as servicelib 1.1.0) - bug FIXES openapi.json in catalog service - bug FiXES pylint tests - cleanup pytest-simcore * scripts to run model validation against csv exported file * adds typer as tool * servicelib: adds fastapi extra * adds minimal to servicelib.fastapi extra * fixes makefile help warning * introduces [all] extras * adds tests for fastapi extra * catalog service: split reqs in base and packages * updates catalog OAS using new openapi generator * fixes call deprecated celery class. Detected by pylint * @GitHK review: doc * updates service-lib setup * fixes catalog setup * servicelib 1.0.0 → 1.1.0 * minor fix classifier field type * patches properly exclusive* field discrepancies between openapi and jsonschema * renamed job
1 parent 7162ba4 commit c815eb8

File tree

47 files changed

+922
-312
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+922
-312
lines changed

.github/workflows/ci-testing-deploy.yml

Lines changed: 4 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,7 @@ jobs:
747747
name: codeclimate-${{ github.job }}-coverage
748748
path: codeclimate.${{ github.job }}_coverage.json
749749

750+
750751
unit-test-service-library:
751752
timeout-minutes: 14 # if this timeout gets too small, then split the tests
752753
name: "[unit] service-library"
@@ -781,72 +782,15 @@ jobs:
781782
name: getting cached data
782783
with:
783784
path: ~/.cache/pip
784-
key: ${{ runner.os }}-pip-service-library-${{ hashFiles('packages/service-library/requirements/ci.txt') }}
785-
restore-keys: |
786-
${{ runner.os }}-pip-service-library-
787-
${{ runner.os }}-pip-
788-
${{ runner.os }}-
789-
- name: install
790-
run: ./ci/github/unit-testing/service-library.bash install
791-
- name: test
792-
run: ./ci/github/unit-testing/service-library.bash test
793-
- uses: codecov/[email protected]
794-
with:
795-
flags: unittests #optional
796-
- name: prepare codeclimate coverage file
797-
run: |
798-
curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-0.7.0-linux-amd64 > ./cc-test-reporter
799-
chmod +x ./cc-test-reporter && ./cc-test-reporter --version
800-
./cc-test-reporter format-coverage -t coverage.py -o codeclimate.${{ github.job }}_coverage.json coverage.xml
801-
- name: upload codeclimate coverage
802-
uses: actions/upload-artifact@v2
803-
with:
804-
name: codeclimate-${{ github.job }}-coverage
805-
path: codeclimate.${{ github.job }}_coverage.json
806-
807-
unit-test-service-library-aiohttp:
808-
timeout-minutes: 14 # if this timeout gets too small, then split the tests
809-
name: "[unit] service-library[aiohttp]"
810-
runs-on: ${{ matrix.os }}
811-
strategy:
812-
matrix:
813-
python: [3.8]
814-
os: [ubuntu-20.04]
815-
docker_buildx: [v0.5.1]
816-
docker_compose: [1.29.1]
817-
include:
818-
- docker_compose: 1.29.1
819-
docker_compose_sha: 8097769d32e34314125847333593c8edb0dfc4a5b350e4839bef8c2fe8d09de7
820-
fail-fast: false
821-
steps:
822-
- uses: actions/checkout@v2
823-
- name: setup docker buildx
824-
id: buildx
825-
uses: docker/setup-buildx-action@v1
826-
with:
827-
version: ${{ matrix.docker_buildx }}
828-
driver: docker
829-
- name: setup docker-compose
830-
run: sudo ./ci/github/helpers/setup_docker_compose.bash ${{ matrix.docker_compose }} ${{ matrix.docker_compose_sha }}
831-
- name: setup python environment
832-
uses: actions/setup-python@v2
833-
with:
834-
python-version: ${{ matrix.python }}
835-
- name: show system version
836-
run: ./ci/helpers/show_system_versions.bash
837-
- uses: actions/cache@v2
838-
name: getting cached data
839-
with:
840-
path: ~/.cache/pip
841-
key: ${{ runner.os }}-pip-service-library-${{ hashFiles('packages/service-library/requirements/ci[aiohttp].txt') }}
785+
key: ${{ runner.os }}-pip-service-library-${{ hashFiles('packages/service-library/requirements/ci[all].txt') }}
842786
restore-keys: |
843787
${{ runner.os }}-pip-service-library-
844788
${{ runner.os }}-pip-
845789
${{ runner.os }}-
846790
- name: install
847-
run: ./ci/github/unit-testing/service-library.bash install_aiohttp
791+
run: ./ci/github/unit-testing/service-library.bash install_all
848792
- name: test
849-
run: ./ci/github/unit-testing/service-library.bash test_aiohttp
793+
run: ./ci/github/unit-testing/service-library.bash test_all
850794
- uses: codecov/[email protected]
851795
with:
852796
flags: unittests #optional

ci/github/unit-testing/service-library.bash

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,16 @@ set -o nounset # abort on unbound variable
55
set -o pipefail # don't hide errors within pipes
66
IFS=$'\n\t'
77

8-
install() {
9-
bash ci/helpers/ensure_python_pip.bash
10-
pushd packages/service-library; pip3 install -r requirements/ci.txt; popd;
11-
pip list -v
12-
}
138

14-
install_aiohttp() {
9+
# NOTE: notice that the CI uses [all]
10+
# TODO: add STEPS where pip-sync individual extras and test separately
11+
install_all() {
1512
bash ci/helpers/ensure_python_pip.bash
16-
pushd packages/service-library; pip3 install -r requirements/ci[aiohttp].txt; popd;
13+
pushd packages/service-library; pip3 install -r "requirements/ci[all].txt"; popd;
1714
pip list -v
1815
}
1916

20-
test() {
21-
pytest --cov=servicelib --durations=10 --cov-append \
22-
--color=yes --cov-report=term-missing --cov-report=xml --cov-config=.coveragerc \
23-
-v -m "not travis" --ignore=packages/service-library/tests/aiohttp \
24-
packages/service-library/tests
25-
}
26-
27-
test_aiohttp() {
17+
test_all() {
2818
pytest --cov=servicelib --durations=10 --cov-append \
2919
--color=yes --cov-report=term-missing --cov-report=xml --cov-config=.coveragerc \
3020
-v -m "not travis" packages/service-library/tests

ci/helpers/requirements.in

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# Minimal packages for install_pylint.bash
22
#
3-
# NOTE: keep frozen since it caused errors in the past
4-
celery==4.4.7
5-
docker==4.3.1
6-
pyjwt==1.7.1
7-
aiohttp==3.7.4.post0
3+
# Installing these void e.g. E0611: No name 'UploadFile' in module 'fastapi' (no-name-in-module)
4+
#
5+
aiohttp
6+
celery
7+
docker
8+
fastapi
9+
pyjwt

ci/helpers/requirements.txt

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,56 @@
22
# This file is autogenerated by pip-compile with python 3.8
33
# To update, run:
44
#
5-
# pip-compile requirements.in
5+
# pip-compile
66
#
77
aiohttp==3.7.4.post0
88
# via -r requirements.in
9-
amqp==2.6.1
9+
amqp==5.0.6
1010
# via kombu
1111
async-timeout==3.0.1
1212
# via aiohttp
1313
attrs==21.2.0
1414
# via aiohttp
15-
billiard==3.6.3.0
15+
billiard==3.6.4.0
1616
# via celery
17-
celery==4.4.7
17+
celery==5.1.2
1818
# via -r requirements.in
1919
certifi==2020.6.20
2020
# via requests
2121
chardet==3.0.4
2222
# via
2323
# aiohttp
2424
# requests
25-
docker==4.3.1
25+
click==7.1.2
26+
# via
27+
# celery
28+
# click-didyoumean
29+
# click-plugins
30+
# click-repl
31+
click-didyoumean==0.0.3
32+
# via celery
33+
click-plugins==1.1.1
34+
# via celery
35+
click-repl==0.2.0
36+
# via celery
37+
docker==5.0.2
38+
# via -r requirements.in
39+
fastapi==0.68.1
2640
# via -r requirements.in
2741
idna==2.10
2842
# via
2943
# requests
3044
# yarl
31-
kombu==4.6.11
45+
kombu==5.1.0
3246
# via celery
3347
multidict==5.1.0
3448
# via
3549
# aiohttp
3650
# yarl
51+
prompt-toolkit==3.0.20
52+
# via click-repl
53+
pydantic==1.8.2
54+
# via fastapi
3755
pyjwt==1.7.1
3856
# via -r requirements.in
3957
pytz==2020.1
@@ -42,17 +60,27 @@ requests==2.24.0
4260
# via docker
4361
six==1.15.0
4462
# via
45-
# docker
63+
# click-repl
4664
# websocket-client
65+
starlette==0.14.2
66+
# via fastapi
4767
typing-extensions==3.10.0.2
48-
# via aiohttp
68+
# via
69+
# aiohttp
70+
# pydantic
4971
urllib3==1.25.10
5072
# via requests
51-
vine==1.3.0
73+
vine==5.0.0
5274
# via
5375
# amqp
5476
# celery
77+
# kombu
78+
wcwidth==0.2.5
79+
# via prompt-toolkit
5580
websocket-client==0.57.0
5681
# via docker
5782
yarl==1.6.3
5883
# via aiohttp
84+
85+
# The following packages are considered to be unsafe in a requirements file:
86+
# setuptools

packages/models-library/requirements/_tools.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@
33
--constraint _test.txt
44

55
--requirement ../../../requirements/devenv.txt
6+
7+
typer

packages/models-library/requirements/_tools.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ click==8.0.1
1616
# via
1717
# black
1818
# pip-tools
19+
# typer
1920
distlib==0.3.2
2021
# via virtualenv
2122
filelock==3.0.12
@@ -62,6 +63,8 @@ tomli==1.2.1
6263
# via
6364
# black
6465
# pep517
66+
typer==0.4.0
67+
# via -r requirements/_tools.in
6568
typing-extensions==3.10.0.2
6669
# via
6770
# -c requirements/_base.txt
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import csv
2+
import json
3+
from pathlib import Path
4+
5+
import typer
6+
from models_library.projects import ProjectAtDB
7+
from pydantic import Json, ValidationError, validator
8+
from pydantic.main import Extra
9+
10+
11+
class ProjectFromCsv(ProjectAtDB):
12+
class Config(ProjectAtDB.Config):
13+
extra = Extra.forbid
14+
15+
# TODO: missing in ProjectAtDB
16+
17+
access_rights: Json
18+
ui: Json
19+
classifiers: str # FIXME: this is ARRAY[sa.STRING]
20+
dev: Json
21+
quality: Json
22+
23+
hidden: bool
24+
25+
# NOTE: validators introduced to parse CSV
26+
27+
@validator("published", "hidden", pre=True, check_fields=False)
28+
@classmethod
29+
def empty_str_as_false(cls, v):
30+
# See booleans for >v1.0 https://pydantic-docs.helpmanual.io/usage/types/#booleans
31+
if isinstance(v, str) and v == "":
32+
return False
33+
return v
34+
35+
@validator("workbench", pre=True, check_fields=False)
36+
@classmethod
37+
def jsonstr_to_dict(cls, v):
38+
if isinstance(v, str):
39+
return json.loads(v)
40+
return v
41+
42+
43+
def validate_csv_exported_pg_project(
44+
csvpath: Path, verbose: int = typer.Option(0, "--verbose", "-v", count=True)
45+
):
46+
"""Validates a postgres (pg) projects table exported as a CSV file
47+
48+
49+
EXAMPLES
50+
$ for f in *.csv; do python validate-pg-projects.py -v $f >$f.log 2>&1 ; done
51+
52+
TIP: CSV file can be obtained directly from Adminer website
53+
"""
54+
typer.echo(f"Validating {csvpath} ...")
55+
56+
failed = []
57+
index = -1
58+
with csvpath.open(encoding="utf-8-sig") as fh:
59+
reader = csv.DictReader(fh)
60+
for index, row in enumerate(reader):
61+
pid = row.get("uuid", index + 1)
62+
63+
try:
64+
model = ProjectFromCsv.parse_obj(row)
65+
66+
if verbose > 1:
67+
typer.secho(f"{pid} OK", fg=typer.colors.GREEN)
68+
if verbose > 2:
69+
typer.echo(model.json(indent=2))
70+
except ValidationError as err:
71+
failed.append(pid)
72+
typer.secho(
73+
f"Invalid project {pid} (from {row['last_change_date']}", err=True
74+
)
75+
typer.secho(f" {err}", fg=typer.colors.RED, err=True)
76+
77+
if failed:
78+
typer.secho(
79+
f"Found {len(failed)}/{index+1} invalid projects",
80+
fg=typer.colors.RED,
81+
err=True,
82+
)
83+
84+
85+
if __name__ == "__main__":
86+
typer.run(validate_csv_exported_pg_project)

packages/models-library/tests/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ def package_dir():
2525

2626

2727
@pytest.fixture(scope="session")
28-
def json_diff_script(script_dir: Path) -> Path:
29-
json_diff_script = script_dir / "json-schema-diff.bash"
28+
def json_diff_script(osparc_simcore_scripts_dir: Path) -> Path:
29+
json_diff_script = osparc_simcore_scripts_dir / "json-schema-diff.bash"
3030
assert json_diff_script.exists()
3131
return json_diff_script
3232

packages/pytest-simcore/src/pytest_simcore/celery_service.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ def celery_service(celery_config: Dict, docker_stack: Dict) -> str:
4141
@tenacity.retry(**CeleryRetryPolicyUponInitialization().kwargs)
4242
def wait_till_celery_responsive(url: str) -> None:
4343
app = celery.Celery("tasks", broker=url)
44-
45-
status = celery.bin.celery.CeleryCommand.commands["status"]()
44+
status = celery.bin.celery.celery.commands["status"]()
4645
status.app = status.get_app()
4746
status.run() # raises celery.bin.base.Error if cannot run

0 commit comments

Comments
 (0)