visivo 1.0.20__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.
- visivo-1.0.20/PKG-INFO +37 -0
- visivo-1.0.20/pyproject.toml +57 -0
- visivo-1.0.20/visivo/__init__.py +0 -0
- visivo-1.0.20/visivo/__main__.py +0 -0
- visivo-1.0.20/visivo/command_line.py +63 -0
- visivo-1.0.20/visivo/commands/__init__.py +0 -0
- visivo-1.0.20/visivo/commands/aggregate.py +19 -0
- visivo-1.0.20/visivo/commands/archive.py +24 -0
- visivo-1.0.20/visivo/commands/archive_phase.py +36 -0
- visivo-1.0.20/visivo/commands/compile.py +21 -0
- visivo-1.0.20/visivo/commands/compile_phase.py +67 -0
- visivo-1.0.20/visivo/commands/deploy.py +28 -0
- visivo-1.0.20/visivo/commands/deploy_phase.py +75 -0
- visivo-1.0.20/visivo/commands/dist.py +38 -0
- visivo-1.0.20/visivo/commands/dist_phase.py +37 -0
- visivo-1.0.20/visivo/commands/init.py +16 -0
- visivo-1.0.20/visivo/commands/init_phase.py +166 -0
- visivo-1.0.20/visivo/commands/options.py +124 -0
- visivo-1.0.20/visivo/commands/run.py +35 -0
- visivo-1.0.20/visivo/commands/run_phase.py +35 -0
- visivo-1.0.20/visivo/commands/serve.py +28 -0
- visivo-1.0.20/visivo/commands/serve_phase.py +90 -0
- visivo-1.0.20/visivo/commands/test.py +26 -0
- visivo-1.0.20/visivo/commands/test_phase.py +28 -0
- visivo-1.0.20/visivo/commands/utils.py +53 -0
- visivo-1.0.20/visivo/db/utils.py +0 -0
- visivo-1.0.20/visivo/discovery/__init__.py +0 -0
- visivo-1.0.20/visivo/discovery/discover.py +95 -0
- visivo-1.0.20/visivo/logging/__init__.py +0 -0
- visivo-1.0.20/visivo/logging/logger.py +56 -0
- visivo-1.0.20/visivo/logging/singleton.py +37 -0
- visivo-1.0.20/visivo/models/__init__.py +0 -0
- visivo-1.0.20/visivo/models/alert.py +155 -0
- visivo-1.0.20/visivo/models/base/base_model.py +73 -0
- visivo-1.0.20/visivo/models/base/named_model.py +23 -0
- visivo-1.0.20/visivo/models/base/parent_model.py +169 -0
- visivo-1.0.20/visivo/models/base/selector_model.py +26 -0
- visivo-1.0.20/visivo/models/chart.py +56 -0
- visivo-1.0.20/visivo/models/dashboard.py +109 -0
- visivo-1.0.20/visivo/models/defaults.py +42 -0
- visivo-1.0.20/visivo/models/include.py +21 -0
- visivo-1.0.20/visivo/models/item.py +72 -0
- visivo-1.0.20/visivo/models/models/__init__.py +0 -0
- visivo-1.0.20/visivo/models/models/csv_script_model.py +129 -0
- visivo-1.0.20/visivo/models/models/fields.py +47 -0
- visivo-1.0.20/visivo/models/models/local_merge_model.py +98 -0
- visivo-1.0.20/visivo/models/models/model.py +10 -0
- visivo-1.0.20/visivo/models/models/sql_model.py +42 -0
- visivo-1.0.20/visivo/models/project.py +201 -0
- visivo-1.0.20/visivo/models/row.py +32 -0
- visivo-1.0.20/visivo/models/selector.py +47 -0
- visivo-1.0.20/visivo/models/table.py +122 -0
- visivo-1.0.20/visivo/models/table_column_definition.py +34 -0
- visivo-1.0.20/visivo/models/targets/fields.py +41 -0
- visivo-1.0.20/visivo/models/targets/mysql_target.py +37 -0
- visivo-1.0.20/visivo/models/targets/postgresql_target.py +37 -0
- visivo-1.0.20/visivo/models/targets/snowflake_target.py +74 -0
- visivo-1.0.20/visivo/models/targets/sqlalchemy_target.py +52 -0
- visivo-1.0.20/visivo/models/targets/sqlite_target.py +63 -0
- visivo-1.0.20/visivo/models/targets/target.py +69 -0
- visivo-1.0.20/visivo/models/test.py +27 -0
- visivo-1.0.20/visivo/models/test_run.py +56 -0
- visivo-1.0.20/visivo/models/tokenized_trace.py +12 -0
- visivo-1.0.20/visivo/models/trace.py +217 -0
- visivo-1.0.20/visivo/models/trace_columns.py +135 -0
- visivo-1.0.20/visivo/models/trace_props.py +25997 -0
- visivo-1.0.20/visivo/parsers/__init__.py +0 -0
- visivo-1.0.20/visivo/parsers/core_parser.py +69 -0
- visivo-1.0.20/visivo/parsers/line_validation_error.py +61 -0
- visivo-1.0.20/visivo/parsers/mkdocs.py +76 -0
- visivo-1.0.20/visivo/parsers/mkdocs_utils/markdown.py +199 -0
- visivo-1.0.20/visivo/parsers/mkdocs_utils/nav_configuration_generator.py +233 -0
- visivo-1.0.20/visivo/parsers/parser_factory.py +11 -0
- visivo-1.0.20/visivo/parsers/schema_generator.py +12 -0
- visivo-1.0.20/visivo/parsers/serializer.py +63 -0
- visivo-1.0.20/visivo/parsers/yaml_ordered_dict.py +59 -0
- visivo-1.0.20/visivo/query/__init__.py +1 -0
- visivo-1.0.20/visivo/query/aggregator.py +14 -0
- visivo-1.0.20/visivo/query/dialect.py +100 -0
- visivo-1.0.20/visivo/query/jobs/__init__.py +1 -0
- visivo-1.0.20/visivo/query/jobs/job.py +90 -0
- visivo-1.0.20/visivo/query/jobs/run_csv_script_job.py +59 -0
- visivo-1.0.20/visivo/query/jobs/run_local_merge_job.py +65 -0
- visivo-1.0.20/visivo/query/jobs/run_trace_job.py +86 -0
- visivo-1.0.20/visivo/query/query_string_factory.py +17 -0
- visivo-1.0.20/visivo/query/query_writer.py +21 -0
- visivo-1.0.20/visivo/query/runner.py +138 -0
- visivo-1.0.20/visivo/query/statement_classifier.py +29 -0
- visivo-1.0.20/visivo/query/target_job_tracker.py +128 -0
- visivo-1.0.20/visivo/query/trace_tokenizer.py +136 -0
- visivo-1.0.20/visivo/src/plotly_config_meta.json +1 -0
- visivo-1.0.20/visivo/templates/__init__.py +0 -0
- visivo-1.0.20/visivo/templates/charts/dashboard.html +19 -0
- visivo-1.0.20/visivo/templates/charts/default_chart.txt +50 -0
- visivo-1.0.20/visivo/templates/charts/default_trace.txt +20 -0
- visivo-1.0.20/visivo/templates/queries/default_trace.sql +54 -0
- visivo-1.0.20/visivo/templates/render_yaml.py +135 -0
- visivo-1.0.20/visivo/testing/__init__.py +0 -0
- visivo-1.0.20/visivo/testing/runner.py +79 -0
- visivo-1.0.20/visivo/utils.py +108 -0
- visivo-1.0.20/visivo/viewer/about.txt +6 -0
- visivo-1.0.20/visivo/viewer/android-chrome-192x192.png +0 -0
- visivo-1.0.20/visivo/viewer/android-chrome-512x512.png +0 -0
- visivo-1.0.20/visivo/viewer/apple-touch-icon.png +0 -0
- visivo-1.0.20/visivo/viewer/asset-manifest.json +15 -0
- visivo-1.0.20/visivo/viewer/favicon-16x16.png +0 -0
- visivo-1.0.20/visivo/viewer/favicon-32x32.png +0 -0
- visivo-1.0.20/visivo/viewer/favicon.ico +0 -0
- visivo-1.0.20/visivo/viewer/index.html +1 -0
- visivo-1.0.20/visivo/viewer/manifest.json +25 -0
- visivo-1.0.20/visivo/viewer/robots.txt +3 -0
- visivo-1.0.20/visivo/viewer/site.webmanifest +1 -0
- visivo-1.0.20/visivo/viewer/static/css/main.5285427e.css +4 -0
- visivo-1.0.20/visivo/viewer/static/css/main.5285427e.css.map +1 -0
- visivo-1.0.20/visivo/viewer/static/js/488.72e7b0fa.chunk.js +2 -0
- visivo-1.0.20/visivo/viewer/static/js/488.72e7b0fa.chunk.js.map +1 -0
- visivo-1.0.20/visivo/viewer/static/js/main.5aa6f1f8.js +3 -0
- visivo-1.0.20/visivo/viewer/static/js/main.5aa6f1f8.js.LICENSE.txt +192 -0
- visivo-1.0.20/visivo/viewer/static/js/main.5aa6f1f8.js.map +1 -0
visivo-1.0.20/PKG-INFO
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: visivo
|
|
3
|
+
Version: 1.0.20
|
|
4
|
+
Summary:
|
|
5
|
+
Author: Visivo People
|
|
6
|
+
Requires-Python: >=3.10,<3.13
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Requires-Dist: Flask (>=2.2.3,<3.0.0)
|
|
12
|
+
Requires-Dist: Jinja2 (>=3.1.2,<4.0.0)
|
|
13
|
+
Requires-Dist: PyYAML (>=6.0,<7.0)
|
|
14
|
+
Requires-Dist: assertpy (>=1.1,<2.0)
|
|
15
|
+
Requires-Dist: click (>=8.1.3,<9.0.0)
|
|
16
|
+
Requires-Dist: deepmerge (>=1.1.0,<2.0.0)
|
|
17
|
+
Requires-Dist: gitpython (>=3.1.32,<4.0.0)
|
|
18
|
+
Requires-Dist: halo (>=0.0.31,<0.0.32)
|
|
19
|
+
Requires-Dist: livereload (>=2.6.3,<3.0.0)
|
|
20
|
+
Requires-Dist: matplotlib (>=3.7.1,<4.0.0)
|
|
21
|
+
Requires-Dist: mkdocs-autolinks-plugin (>=0.7.1,<0.8.0)
|
|
22
|
+
Requires-Dist: networkx (>=3.1,<4.0)
|
|
23
|
+
Requires-Dist: numpy (==1.26.0)
|
|
24
|
+
Requires-Dist: pandas (>=1.5.3,<2.0.0)
|
|
25
|
+
Requires-Dist: psycopg2-binary (>=2.9.5,<3.0.0)
|
|
26
|
+
Requires-Dist: pydantic (>=2.5.0)
|
|
27
|
+
Requires-Dist: pymysql (>=1.1.0,<2.0.0)
|
|
28
|
+
Requires-Dist: pytest-mock (>=3.14.0,<4.0.0)
|
|
29
|
+
Requires-Dist: python-dateutil (>=2.9.0.post0,<3.0.0)
|
|
30
|
+
Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
|
|
31
|
+
Requires-Dist: requests (>=2.28.2,<3.0.0)
|
|
32
|
+
Requires-Dist: snowflake-connector-python (>=3.7.0,<4.0.0)
|
|
33
|
+
Requires-Dist: sql-formatter (>=0.6.2,<0.7.0)
|
|
34
|
+
Requires-Dist: sqlalchemy (>=2.0.8,<3.0.0)
|
|
35
|
+
Requires-Dist: termcolor (>=2.4.0,<3.0.0)
|
|
36
|
+
Requires-Dist: tornado (<6.3)
|
|
37
|
+
Project-URL: Documentation, https://docs.visivo.io/
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "visivo"
|
|
3
|
+
version = "1.0.20"
|
|
4
|
+
description = ""
|
|
5
|
+
authors = ["Visivo People"]
|
|
6
|
+
documentation = "https://docs.visivo.io/"
|
|
7
|
+
|
|
8
|
+
[tool.poetry.scripts]
|
|
9
|
+
visivo = "visivo.command_line:safe_visivo"
|
|
10
|
+
|
|
11
|
+
[tool.poetry.dependencies]
|
|
12
|
+
python = " >=3.10,<3.13"
|
|
13
|
+
pydantic = ">=2.5.0"
|
|
14
|
+
requests = "^2.28.2"
|
|
15
|
+
Jinja2 = "^3.1.2"
|
|
16
|
+
PyYAML = "^6.0"
|
|
17
|
+
sql-formatter = "^0.6.2"
|
|
18
|
+
click = "^8.1.3"
|
|
19
|
+
pandas = "^1.5.3"
|
|
20
|
+
Flask = "^2.2.3"
|
|
21
|
+
livereload = "^2.6.3"
|
|
22
|
+
tornado = "< 6.3"
|
|
23
|
+
numpy = "=1.26.0"
|
|
24
|
+
psycopg2-binary = "^2.9.5"
|
|
25
|
+
sqlalchemy = "^2.0.8"
|
|
26
|
+
snowflake-connector-python = "^3.7.0"
|
|
27
|
+
python-dotenv = "^1.0.0"
|
|
28
|
+
networkx = "^3.1"
|
|
29
|
+
matplotlib = "^3.7.1"
|
|
30
|
+
deepmerge = "^1.1.0"
|
|
31
|
+
gitpython = "^3.1.32"
|
|
32
|
+
halo = "^0.0.31"
|
|
33
|
+
mkdocs-autolinks-plugin = "^0.7.1"
|
|
34
|
+
termcolor = "^2.4.0"
|
|
35
|
+
python-dateutil = "^2.9.0.post0"
|
|
36
|
+
pytest-mock = "^3.14.0"
|
|
37
|
+
pymysql = "^1.1.0"
|
|
38
|
+
assertpy = "^1.1"
|
|
39
|
+
|
|
40
|
+
[tool.poetry.group.dev.dependencies]
|
|
41
|
+
pytest = "^7.2.1"
|
|
42
|
+
factory-boy = "^3.2.1"
|
|
43
|
+
mkdocs = "^1.4.2"
|
|
44
|
+
mkdocs-click = "^0.8.0"
|
|
45
|
+
mkdocs-encryptcontent-plugin = "^2.4.5"
|
|
46
|
+
mkdocs-material = "^9.1.3"
|
|
47
|
+
mkdocs-spellcheck = {extras = ["all"], version = "^1.0.0"}
|
|
48
|
+
symspellpy = "^6.7.7"
|
|
49
|
+
codespell = "^2.2.4"
|
|
50
|
+
mkdocs-macros-plugin = "^0.7.0"
|
|
51
|
+
setuptools = "^67.7.2"
|
|
52
|
+
pytest-env = "^1.0.1"
|
|
53
|
+
requests-mock = "^1.11.0"
|
|
54
|
+
|
|
55
|
+
[build-system]
|
|
56
|
+
requires = ["poetry-core>=1.0.0"]
|
|
57
|
+
build-backend = "poetry.core.masonry.api"
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import click
|
|
2
|
+
import os
|
|
3
|
+
import importlib
|
|
4
|
+
from dotenv import load_dotenv
|
|
5
|
+
from pydantic import ValidationError
|
|
6
|
+
from visivo.logging.logger import Logger, TypeEnum
|
|
7
|
+
from visivo.parsers.line_validation_error import LineValidationError
|
|
8
|
+
|
|
9
|
+
from .commands.deploy import deploy
|
|
10
|
+
from .commands.serve import serve
|
|
11
|
+
from .commands.run import run
|
|
12
|
+
from .commands.dist import dist
|
|
13
|
+
from .commands.compile import compile
|
|
14
|
+
from .commands.init import init
|
|
15
|
+
from .commands.test import test
|
|
16
|
+
from .commands.aggregate import aggregate
|
|
17
|
+
from .commands.archive import archive
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@click.group()
|
|
21
|
+
@click.option("-e", "--env-file", default=".env")
|
|
22
|
+
@click.version_option(version=importlib.metadata.version("visivo"))
|
|
23
|
+
def visivo(env_file):
|
|
24
|
+
Logger.instance().set_type(TypeEnum.spinner)
|
|
25
|
+
load_env(env_file)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
visivo.add_command(init)
|
|
29
|
+
visivo.add_command(compile)
|
|
30
|
+
visivo.add_command(run)
|
|
31
|
+
visivo.add_command(serve)
|
|
32
|
+
visivo.add_command(deploy)
|
|
33
|
+
visivo.add_command(dist)
|
|
34
|
+
visivo.add_command(test)
|
|
35
|
+
visivo.add_command(aggregate)
|
|
36
|
+
visivo.add_command(archive)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def load_env(env_file):
|
|
40
|
+
if os.path.isfile(env_file):
|
|
41
|
+
Logger.instance().debug(f"Loading env file: {env_file}")
|
|
42
|
+
load_dotenv(env_file)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def safe_visivo():
|
|
46
|
+
try:
|
|
47
|
+
visivo(standalone_mode=False)
|
|
48
|
+
except (ValidationError, LineValidationError) as e:
|
|
49
|
+
Logger.instance().error(str(e))
|
|
50
|
+
exit(1)
|
|
51
|
+
except Exception as e:
|
|
52
|
+
if "STACKTRACE" in os.environ and os.environ["STACKTRACE"] == "true":
|
|
53
|
+
raise e
|
|
54
|
+
Logger.instance().error("An unexpected error has occurred")
|
|
55
|
+
Logger.instance().error(str(e))
|
|
56
|
+
Logger.instance().error(
|
|
57
|
+
"To print more error information add the 'STACKTRACE=true' environment variable."
|
|
58
|
+
)
|
|
59
|
+
exit(1)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
if __name__ == "__main__":
|
|
63
|
+
safe_visivo()
|
|
File without changes
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from visivo.query.aggregator import Aggregator
|
|
3
|
+
from .options import output_dir
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@click.command()
|
|
7
|
+
@output_dir
|
|
8
|
+
@click.option(
|
|
9
|
+
"-j", "--json-file", help="The file with the raw json results from the query"
|
|
10
|
+
)
|
|
11
|
+
def aggregate(output_dir, json_file):
|
|
12
|
+
from visivo.logging.logger import Logger
|
|
13
|
+
|
|
14
|
+
Logger.instance().debug("Aggregating")
|
|
15
|
+
|
|
16
|
+
from visivo.query.runner import Runner
|
|
17
|
+
|
|
18
|
+
Aggregator.aggregate(trace_dir=output_dir, json_file=json_file)
|
|
19
|
+
Logger.instance().success("Done")
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from .options import user_dir, stage, host
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@click.command()
|
|
6
|
+
@stage
|
|
7
|
+
@host
|
|
8
|
+
@user_dir
|
|
9
|
+
def archive(stage, host, user_dir):
|
|
10
|
+
"""
|
|
11
|
+
Archives a stage. You must specify a stage when deploying a project.
|
|
12
|
+
"""
|
|
13
|
+
from visivo.logging.logger import Logger
|
|
14
|
+
|
|
15
|
+
Logger.instance().debug("Archiving")
|
|
16
|
+
|
|
17
|
+
from visivo.commands.archive_phase import archive_phase
|
|
18
|
+
|
|
19
|
+
archive_phase(
|
|
20
|
+
user_dir=user_dir,
|
|
21
|
+
stage=stage,
|
|
22
|
+
host=host,
|
|
23
|
+
)
|
|
24
|
+
Logger.instance().success("Done")
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from visivo.logging.logger import Logger
|
|
2
|
+
import click
|
|
3
|
+
import requests
|
|
4
|
+
import json
|
|
5
|
+
from visivo.commands.utils import get_profile_file, get_profile_token
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def archive_phase(stage, host, user_dir):
|
|
9
|
+
profile_token = get_profile_token(get_profile_file(home_directory=user_dir))
|
|
10
|
+
|
|
11
|
+
json_headers = {
|
|
12
|
+
"content-type": "application/json",
|
|
13
|
+
"Authorization": f"Api-Key {profile_token}",
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
url = f"{host}/api/stages/?name={stage}"
|
|
17
|
+
response = requests.get(url, headers=json_headers)
|
|
18
|
+
if response.status_code == 401:
|
|
19
|
+
raise click.ClickException(f"Token not authorized for host: {host}")
|
|
20
|
+
if response.status_code == 404:
|
|
21
|
+
raise click.ClickException(f"404 error raised. Does your user have an account?")
|
|
22
|
+
|
|
23
|
+
if len(response.json()) == 0:
|
|
24
|
+
Logger.instance().debug(f"No stages with name {stage} found")
|
|
25
|
+
return
|
|
26
|
+
|
|
27
|
+
id = response.json()[0]["id"]
|
|
28
|
+
body = {
|
|
29
|
+
"archived": True,
|
|
30
|
+
}
|
|
31
|
+
url = f"{host}/api/stages/{id}/"
|
|
32
|
+
response = requests.put(url, data=json.dumps(body), headers=json_headers)
|
|
33
|
+
if response.status_code == 200:
|
|
34
|
+
Logger.instance().debug("Stage archived")
|
|
35
|
+
else:
|
|
36
|
+
raise click.ClickException(f"There was an unexpected error: {response.content}")
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from .options import output_dir, working_dir, target, name_filter
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@click.command()
|
|
6
|
+
@target
|
|
7
|
+
@working_dir
|
|
8
|
+
@output_dir
|
|
9
|
+
@name_filter
|
|
10
|
+
def compile(working_dir, output_dir, target, name_filter):
|
|
11
|
+
"""
|
|
12
|
+
Parses the files in your working directory, extracting visivo configurations and then using those configurations to build the trace queries and a project.json file in your target directory. Queries are not run on compile, just written.
|
|
13
|
+
"""
|
|
14
|
+
from visivo.logging.logger import Logger
|
|
15
|
+
|
|
16
|
+
Logger.instance().debug("Compiling")
|
|
17
|
+
|
|
18
|
+
from visivo.commands.compile_phase import compile_phase
|
|
19
|
+
|
|
20
|
+
compile_phase(default_target=target, working_dir=working_dir, output_dir=output_dir, name_filter=name_filter)
|
|
21
|
+
Logger.instance().success("Done")
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import click
|
|
2
|
+
import os
|
|
3
|
+
import yaml
|
|
4
|
+
from visivo.discovery.discover import Discover
|
|
5
|
+
from visivo.models.defaults import Defaults
|
|
6
|
+
from visivo.models.models.csv_script_model import CsvScriptModel
|
|
7
|
+
from visivo.models.targets.target import Target
|
|
8
|
+
from visivo.models.models.model import Model
|
|
9
|
+
from visivo.models.base.parent_model import ParentModel
|
|
10
|
+
from visivo.parsers.parser_factory import ParserFactory
|
|
11
|
+
from visivo.parsers.serializer import Serializer
|
|
12
|
+
from visivo.query.query_string_factory import QueryStringFactory
|
|
13
|
+
from visivo.query.trace_tokenizer import TraceTokenizer
|
|
14
|
+
from visivo.query.query_writer import QueryWriter
|
|
15
|
+
from visivo.logging.logger import Logger
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def compile_phase(
|
|
19
|
+
default_target: str, working_dir: str, output_dir: str, name_filter: str = None
|
|
20
|
+
):
|
|
21
|
+
Logger.instance().debug("Compiling project")
|
|
22
|
+
discover = Discover(working_directory=working_dir)
|
|
23
|
+
parser = ParserFactory().build(
|
|
24
|
+
project_file=discover.project_file, files=discover.files
|
|
25
|
+
)
|
|
26
|
+
project = None
|
|
27
|
+
try:
|
|
28
|
+
project = parser.parse()
|
|
29
|
+
if not project.defaults:
|
|
30
|
+
project.defaults = Defaults()
|
|
31
|
+
if default_target:
|
|
32
|
+
project.defaults.target_name = default_target
|
|
33
|
+
except yaml.YAMLError as e:
|
|
34
|
+
message = "\n"
|
|
35
|
+
if hasattr(e, "problem_mark"):
|
|
36
|
+
mark = e.problem_mark
|
|
37
|
+
message = f"\n Error position: line:{mark.line+1} column:{mark.column+1}\n"
|
|
38
|
+
raise click.ClickException(
|
|
39
|
+
f"There was an error parsing the yml file(s):{message} {e}"
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
os.makedirs(output_dir, exist_ok=True)
|
|
43
|
+
with open(f"{output_dir}/project.json", "w") as fp:
|
|
44
|
+
serializer = Serializer(project=project)
|
|
45
|
+
fp.write(serializer.dereference().model_dump_json(exclude_none=True))
|
|
46
|
+
|
|
47
|
+
dag = project.dag()
|
|
48
|
+
for trace in project.filter_traces(name_filter=name_filter):
|
|
49
|
+
model = ParentModel.all_descendants_of_type(
|
|
50
|
+
type=Model, dag=dag, from_node=trace
|
|
51
|
+
)[0]
|
|
52
|
+
if isinstance(model, CsvScriptModel):
|
|
53
|
+
target = model.get_sqlite_target(output_dir=output_dir)
|
|
54
|
+
else:
|
|
55
|
+
target = ParentModel.all_descendants_of_type(
|
|
56
|
+
type=Target, dag=dag, from_node=model
|
|
57
|
+
)[0]
|
|
58
|
+
tokenized_trace = TraceTokenizer(
|
|
59
|
+
trace=trace, model=model, target=target
|
|
60
|
+
).tokenize()
|
|
61
|
+
query_string = QueryStringFactory(tokenized_trace=tokenized_trace).build()
|
|
62
|
+
QueryWriter(
|
|
63
|
+
trace=trace, query_string=query_string, output_dir=output_dir
|
|
64
|
+
).write()
|
|
65
|
+
|
|
66
|
+
Logger.instance().debug("Project compiled")
|
|
67
|
+
return project
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from visivo.commands.options import output_dir, working_dir, user_dir, stage, host
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@click.command()
|
|
6
|
+
@working_dir
|
|
7
|
+
@output_dir
|
|
8
|
+
@stage
|
|
9
|
+
@host
|
|
10
|
+
@user_dir
|
|
11
|
+
def deploy(working_dir, user_dir, output_dir, stage, host):
|
|
12
|
+
"""
|
|
13
|
+
Sends the current version of your project, traces & data to app.visivo.io where it can be viewed by other users on your account. You must specify a stage when deploying a project. The stage allows multiple versions of your project to exist remotely. This is very useful for setting up different dev, CI and production environments.
|
|
14
|
+
"""
|
|
15
|
+
from visivo.logging.logger import Logger
|
|
16
|
+
|
|
17
|
+
Logger.instance().debug("Deploying")
|
|
18
|
+
|
|
19
|
+
from visivo.commands.deploy_phase import deploy_phase
|
|
20
|
+
|
|
21
|
+
url = deploy_phase(
|
|
22
|
+
user_dir=user_dir,
|
|
23
|
+
working_dir=working_dir,
|
|
24
|
+
output_dir=output_dir,
|
|
25
|
+
stage=stage,
|
|
26
|
+
host=host,
|
|
27
|
+
)
|
|
28
|
+
Logger.instance().success(f"Deployed to: '{host}{url}'")
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import click
|
|
2
|
+
import requests
|
|
3
|
+
import json
|
|
4
|
+
from visivo.commands.utils import get_profile_file, get_profile_token
|
|
5
|
+
from visivo.discovery.discover import Discover
|
|
6
|
+
from visivo.logging.logger import Logger
|
|
7
|
+
from visivo.parsers.serializer import Serializer
|
|
8
|
+
from visivo.parsers.parser_factory import ParserFactory
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def deploy_phase(working_dir, user_dir, output_dir, stage, host):
|
|
12
|
+
"""
|
|
13
|
+
Sends the current version of your project, traces & data to app.visivo.io where it can be viewed by other users on your account. You must specify a stage when deploying a project. The stage allows multiple versions of your project to exist remotely. This is very useful for setting up different dev, CI and production environments.
|
|
14
|
+
"""
|
|
15
|
+
profile_token = get_profile_token(get_profile_file(home_directory=user_dir))
|
|
16
|
+
|
|
17
|
+
discover = Discover(working_directory=working_dir, home_directory=user_dir)
|
|
18
|
+
parser = ParserFactory().build(
|
|
19
|
+
project_file=discover.project_file, files=discover.files
|
|
20
|
+
)
|
|
21
|
+
project = parser.parse()
|
|
22
|
+
serializer = Serializer(project=project)
|
|
23
|
+
project_json = json.loads(
|
|
24
|
+
serializer.dereference().model_dump_json(exclude_none=True)
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
body = {
|
|
28
|
+
"project_json": project_json,
|
|
29
|
+
"name": project_json["name"],
|
|
30
|
+
"cli_version": project_json["cli_version"],
|
|
31
|
+
"stage": stage,
|
|
32
|
+
}
|
|
33
|
+
json_headers = {
|
|
34
|
+
"content-type": "application/json",
|
|
35
|
+
"Authorization": f"Api-Key {profile_token}",
|
|
36
|
+
}
|
|
37
|
+
form_headers = {
|
|
38
|
+
"Authorization": f"Api-Key {profile_token}",
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
url = f"{host}/api/projects/"
|
|
42
|
+
response = requests.post(url, data=json.dumps(body), headers=json_headers)
|
|
43
|
+
if response.status_code == 401:
|
|
44
|
+
raise click.ClickException(f"Token not authorized for host: {host}")
|
|
45
|
+
if response.status_code == 404:
|
|
46
|
+
raise click.ClickException(f"404 error raised. Does your user have an account?")
|
|
47
|
+
if response.status_code == 201:
|
|
48
|
+
Logger.instance().debug("Project uploaded")
|
|
49
|
+
project_data = response.json()
|
|
50
|
+
project_id = project_data["id"]
|
|
51
|
+
project_url = project_data["url"]
|
|
52
|
+
|
|
53
|
+
for trace in project.trace_objs:
|
|
54
|
+
url = f"{host}/api/files/"
|
|
55
|
+
|
|
56
|
+
data_file = f"{output_dir}/{trace.name}/data.json"
|
|
57
|
+
files = {"file": open(data_file, "rb")}
|
|
58
|
+
response = requests.post(url, files=files, data={}, headers=form_headers)
|
|
59
|
+
if response.status_code != 201:
|
|
60
|
+
raise click.ClickException(f"Trace '{trace.name}' data not uploaded")
|
|
61
|
+
Logger.instance().debug(f"Trace '{trace.name}' data uploaded")
|
|
62
|
+
url = f"{host}/api/traces/"
|
|
63
|
+
body = {
|
|
64
|
+
"name": trace.name,
|
|
65
|
+
"project_id": project_id,
|
|
66
|
+
"data_file_id": response.json()["id"],
|
|
67
|
+
}
|
|
68
|
+
response = requests.post(url, data=json.dumps(body), headers=json_headers)
|
|
69
|
+
if response.status_code != 201:
|
|
70
|
+
Logger.instance().debug(response.json())
|
|
71
|
+
raise click.ClickException(f"Trace '{trace.name}' not created")
|
|
72
|
+
Logger.instance().debug(f"Trace '{trace.name}' created")
|
|
73
|
+
return project_url
|
|
74
|
+
else:
|
|
75
|
+
raise click.ClickException(f"There was an unexpected error: {response.content}")
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from visivo.commands.options import (
|
|
3
|
+
dist_dir,
|
|
4
|
+
name_filter,
|
|
5
|
+
output_dir,
|
|
6
|
+
target,
|
|
7
|
+
threads,
|
|
8
|
+
working_dir,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@click.command()
|
|
13
|
+
@target
|
|
14
|
+
@working_dir
|
|
15
|
+
@output_dir
|
|
16
|
+
@dist_dir
|
|
17
|
+
@name_filter
|
|
18
|
+
@threads
|
|
19
|
+
def dist(output_dir, working_dir, dist_dir, target, name_filter, threads):
|
|
20
|
+
"""
|
|
21
|
+
Creates a distributable version of this dashboard and stores it in a 'dist' folder.
|
|
22
|
+
This folder can be statically deployed to any web server, hosting service, or bucket storage.
|
|
23
|
+
"""
|
|
24
|
+
from visivo.logging.logger import Logger
|
|
25
|
+
|
|
26
|
+
Logger.instance().debug("Creating Dist")
|
|
27
|
+
|
|
28
|
+
from visivo.commands.dist_phase import dist_phase
|
|
29
|
+
|
|
30
|
+
dist_phase(
|
|
31
|
+
output_dir=output_dir,
|
|
32
|
+
working_dir=working_dir,
|
|
33
|
+
dist_dir=dist_dir,
|
|
34
|
+
default_target=target,
|
|
35
|
+
name_filter=name_filter,
|
|
36
|
+
threads=threads,
|
|
37
|
+
)
|
|
38
|
+
Logger.instance().success(f"Created dist folder")
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import pkg_resources
|
|
2
|
+
|
|
3
|
+
VIEWER_PATH = pkg_resources.resource_filename("visivo", "viewer/")
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def dist_phase(output_dir, working_dir, dist_dir, default_target, name_filter, threads):
|
|
7
|
+
from visivo.commands.run_phase import run_phase
|
|
8
|
+
import os
|
|
9
|
+
import json
|
|
10
|
+
import shutil
|
|
11
|
+
from glob import glob
|
|
12
|
+
|
|
13
|
+
run_phase(
|
|
14
|
+
output_dir=output_dir,
|
|
15
|
+
working_dir=working_dir,
|
|
16
|
+
default_target=default_target,
|
|
17
|
+
name_filter=name_filter,
|
|
18
|
+
threads=threads,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
os.makedirs(f"{dist_dir}/data", exist_ok=True)
|
|
22
|
+
with open(f"{output_dir}/project.json", "r") as f:
|
|
23
|
+
project_json = json.load(f)
|
|
24
|
+
with open(f"{dist_dir}/data/project.json", "w") as f:
|
|
25
|
+
f.write(json.dumps({"project_json": project_json}))
|
|
26
|
+
|
|
27
|
+
trace_dirs = glob(f"{output_dir}/*/", recursive=True)
|
|
28
|
+
for trace_dir in trace_dirs:
|
|
29
|
+
trace_name = os.path.basename(os.path.normpath(trace_dir))
|
|
30
|
+
if os.path.exists(f"{output_dir}/{trace_name}/data.json"):
|
|
31
|
+
os.makedirs(f"{dist_dir}/data/{trace_name}", exist_ok=True)
|
|
32
|
+
shutil.copyfile(
|
|
33
|
+
f"{output_dir}/{trace_name}/data.json",
|
|
34
|
+
f"{dist_dir}/data/{trace_name}/data.json",
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
shutil.copytree(VIEWER_PATH, dist_dir, dirs_exist_ok=True)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@click.command()
|
|
5
|
+
def init():
|
|
6
|
+
"""
|
|
7
|
+
Enables a quick set up by writing your target & api credentials to an env file.
|
|
8
|
+
"""
|
|
9
|
+
from visivo.logging.logger import Logger
|
|
10
|
+
|
|
11
|
+
Logger.instance().debug("Initializing")
|
|
12
|
+
|
|
13
|
+
from visivo.commands.init_phase import init_phase
|
|
14
|
+
|
|
15
|
+
init_phase()
|
|
16
|
+
Logger.instance().success("Done")
|