Skip to content

Commit c38aeaa

Browse files
authored
Merge pull request #76 from elementary-data/simplify_requirements
Added extras requires to setup.py and fixed inter modules dependencies
2 parents 269444d + 2c75a0f commit c38aeaa

File tree

13 files changed

+73
-523
lines changed

13 files changed

+73
-523
lines changed

cli/cli.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,18 @@ def list_commands(self, ctx):
2525
def get_command(self, ctx, name):
2626
ns = {}
2727
fn = os.path.join(root_folder, name, 'cli.py')
28-
with open(fn) as f:
29-
code = compile(f.read(), fn, 'exec')
30-
eval(code, ns, ns)
28+
try:
29+
with open(fn) as f:
30+
code = compile(f.read(), fn, 'exec')
31+
eval(code, ns, ns)
32+
except Exception:
33+
return None
3134
return ns[name]
3235

3336
def format_help(self, ctx, formatter):
3437
try:
3538
config = Config(config_dir=os.path.join(expanduser('~'), '.edr'),
36-
profiles_dir=os.path.join(expanduser('~'), '.dbt'),
37-
profile_name='elementary')
39+
profiles_dir=os.path.join(expanduser('~'), '.dbt'))
3840
anonymous_tracking = AnonymousTracking(config)
3941
track_cli_help(anonymous_tracking)
4042
except Exception:

config/config.py

Lines changed: 1 addition & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
import os
2-
import csv
32
from typing import Union
4-
import glob
5-
6-
from exceptions.exceptions import ConfigError
7-
from utils.dbt import get_model_paths_from_dbt_project, get_target_database_name, \
8-
extract_credentials_and_data_from_profiles
93
from utils.ordered_yaml import OrderedYaml
104

115
ordered_yaml = OrderedYaml()
@@ -17,12 +11,9 @@ class Config(object):
1711
WORKFLOWS = 'workflows'
1812
CONFIG_FILE_NAME = 'config.yml'
1913

20-
def __init__(self, config_dir: str, profiles_dir: str, profile_name: str) -> None:
14+
def __init__(self, config_dir: str, profiles_dir: str) -> None:
2115
self.config_dir = config_dir
2216
self.profiles_dir = profiles_dir
23-
self.profile_name = profile_name
24-
self.credentials, self.profiles_data = extract_credentials_and_data_from_profiles(profiles_dir,
25-
profile_name)
2617
self.config_dict = self._load_configuration()
2718

2819
def _load_configuration(self) -> dict:
@@ -35,14 +26,6 @@ def _load_configuration(self) -> dict:
3526

3627
return ordered_yaml.load(config_file_path)
3728

38-
@property
39-
def query_history_source(self):
40-
return self.profiles_data.get('query_history_source')
41-
42-
@property
43-
def platform(self):
44-
return self.profiles_data.get('type', 'unknown')
45-
4629
@property
4730
def anonymous_tracking_enabled(self) -> bool:
4831
return self.config_dict.get('anonymous_usage_tracking', True)
@@ -70,106 +53,3 @@ def target_dir(self) -> str:
7053
return os.getcwd()
7154
return target_path
7255

73-
@staticmethod
74-
def _find_schema_yml_files_in_dbt_project(dbt_project_models_path: str) -> list:
75-
return glob.glob(os.path.join(dbt_project_models_path, '*.yml'), recursive=True)
76-
77-
def _get_sources_from_all_dbt_projects(self) -> list:
78-
config_dict = self._load_configuration()
79-
dbt_projects = config_dict.get('dbt_projects', [])
80-
sources = []
81-
for dbt_project_path in dbt_projects:
82-
try:
83-
dbt_project_target_database = get_target_database_name(self.profiles_dir, dbt_project_path)
84-
model_paths = get_model_paths_from_dbt_project(dbt_project_path)
85-
for model_path in model_paths:
86-
dbt_project_models_path = os.path.join(dbt_project_path, model_path)
87-
schema_yml_files = self._find_schema_yml_files_in_dbt_project(dbt_project_models_path)
88-
for schema_yml_file in schema_yml_files:
89-
schema_dict = ordered_yaml.load(schema_yml_file)
90-
schema_sources = schema_dict.get('sources')
91-
if schema_sources is not None:
92-
dbt_project_sources = {'sources': schema_sources,
93-
'dbt_project_target_database': dbt_project_target_database}
94-
sources.append(dbt_project_sources)
95-
except FileNotFoundError as exc:
96-
raise ConfigError(f'No such file - {exc.filename}, please configure a valid dbt project path')
97-
return sources
98-
99-
@staticmethod
100-
def _alert_on_schema_changes(source_dict: dict) -> Union[bool, None]:
101-
metadata = source_dict.get('meta', {})
102-
edr_config = metadata.get('edr', {})
103-
alert_on_schema_changes = edr_config.get('schema_changes')
104-
105-
# Normalize alert_on_schema_changes to handle both booleans and strings
106-
alert_on_schema_changes_str = str(alert_on_schema_changes).lower()
107-
if alert_on_schema_changes_str == 'false':
108-
return False
109-
elif alert_on_schema_changes_str == 'true':
110-
return True
111-
else:
112-
return None
113-
114-
def monitoring_configuration_in_dbt_sources_to_csv(self, target_csv_path: str) -> int:
115-
row_count = 0
116-
with open(target_csv_path, 'w') as target_csv:
117-
target_csv_writer = csv.DictWriter(target_csv, fieldnames=['database_name',
118-
'schema_name',
119-
'table_name',
120-
'column_name',
121-
'alert_on_schema_changes'])
122-
target_csv_writer.writeheader()
123-
124-
all_configured_sources = self._get_sources_from_all_dbt_projects()
125-
for sources_dict in all_configured_sources:
126-
sources = sources_dict.get('sources', [])
127-
target_database = sources_dict.get('dbt_project_target_database')
128-
for source in sources:
129-
source_db = source.get('database', target_database)
130-
if source_db is None:
131-
continue
132-
133-
schema_name = source.get('schema', source.get('name'))
134-
if schema_name is None:
135-
continue
136-
137-
alert_on_schema_changes = self._alert_on_schema_changes(source)
138-
if alert_on_schema_changes is not None:
139-
target_csv_writer.writerow({'database_name': source_db,
140-
'schema_name': schema_name,
141-
'table_name': None,
142-
'column_name': None,
143-
'alert_on_schema_changes': alert_on_schema_changes})
144-
row_count += 1
145-
146-
source_tables = source.get('tables', [])
147-
for source_table in source_tables:
148-
table_name = source_table.get('identifier', source_table.get('name'))
149-
if table_name is None:
150-
continue
151-
152-
alert_on_schema_changes = self._alert_on_schema_changes(source_table)
153-
if alert_on_schema_changes is not None:
154-
target_csv_writer.writerow({'database_name': source_db,
155-
'schema_name': schema_name,
156-
'table_name': table_name,
157-
'column_name': None,
158-
'alert_on_schema_changes': alert_on_schema_changes})
159-
row_count += 1
160-
161-
source_columns = source_table.get('columns', [])
162-
for source_column in source_columns:
163-
column_name = source_column.get('name')
164-
if column_name is None:
165-
continue
166-
167-
alert_on_schema_changes = self._alert_on_schema_changes(source_column)
168-
if alert_on_schema_changes is not None:
169-
target_csv_writer.writerow({'database_name': source_db,
170-
'schema_name': schema_name,
171-
'table_name': table_name,
172-
'column_name': column_name,
173-
'alert_on_schema_changes': alert_on_schema_changes})
174-
row_count += 1
175-
return row_count

lineage/cli.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import os
33
from os.path import expanduser
44

5-
from config.config import Config
5+
from lineage.lineage_config import LineageConfig
66
from exceptions.exceptions import ConfigError
77
from lineage.query_history_factory import QueryHistoryFactory
88
from utils.package import get_package_version
@@ -164,7 +164,7 @@ def lineage(ctx, database: str, schema: str, table: str, open_browser: bool, ful
164164
if ctx.invoked_subcommand is not None:
165165
return
166166

167-
config = Config(config_dir, profiles_dir, profile_name)
167+
config = LineageConfig(config_dir, profiles_dir, profile_name)
168168
anonymous_tracking = AnonymousTracking(config)
169169
track_cli_start(anonymous_tracking, 'lineage', get_cli_lineage_properties(), ctx.command.name)
170170
execution_properties = dict()
@@ -244,7 +244,7 @@ def lineage(ctx, database: str, schema: str, table: str, open_browser: bool, ful
244244
@click.pass_context
245245
def generate(ctx, start_date: datetime, end_date: datetime, databases: str, config_dir: str,
246246
profiles_dir: str, profile_name: str):
247-
config = Config(config_dir, profiles_dir, profile_name)
247+
config = LineageConfig(config_dir, profiles_dir, profile_name)
248248
anonymous_tracking = AnonymousTracking(config)
249249
track_cli_start(anonymous_tracking, 'lineage', get_cli_lineage_generate_properties(), ctx.command.name)
250250

lineage/lineage_config.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from utils.dbt import extract_credentials_and_data_from_profiles
2+
from config.config import Config
3+
4+
5+
class LineageConfig(Config):
6+
def __init__(self, config_dir: str, profiles_dir: str, profile_name: str) -> None:
7+
super().__init__(config_dir, profiles_dir)
8+
self.profile_name = profile_name
9+
self.credentials, self.profiles_data = extract_credentials_and_data_from_profiles(profiles_dir,
10+
profile_name)
11+
12+
@property
13+
def query_history_source(self):
14+
return self.profiles_data.get('query_history_source')
15+
16+
@property
17+
def platform(self):
18+
return self.profiles_data.get('type', 'unknown')

monitor/cli.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
from utils.package import get_package_version
66
from tracking.anonymous_tracking import AnonymousTracking, track_cli_start, track_cli_exception, track_cli_end
7-
from utils.dbt import get_profile_name_from_dbt_project, is_dbt_installed
87
from utils.ordered_yaml import OrderedYaml
98
from config.config import Config
109
from monitor.data_monitoring import DataMonitoring
@@ -29,7 +28,6 @@ def get_cli_properties() -> dict:
2928
return {'reload_monitoring_configuration': reload_monitoring_configuration,
3029
'update_dbt_package': update_dbt_package,
3130
'full_refresh_dbt_package': full_refresh_dbt_package,
32-
'dbt_installed': is_dbt_installed(),
3331
'version': get_package_version()}
3432

3533

@@ -78,7 +76,7 @@ def get_cli_properties() -> dict:
7876
def monitor(ctx, days_back, slack_webhook, config_dir, profiles_dir, update_dbt_package, full_refresh_dbt_package):
7977
click.echo(f"Any feedback and suggestions are welcomed! join our community here - "
8078
f"https://bit.ly/slack-elementary\n")
81-
config = Config(config_dir, profiles_dir, get_profile_name_from_dbt_project(DataMonitoring.DBT_PROJECT_PATH))
79+
config = Config(config_dir, profiles_dir)
8280
anonymous_tracking = AnonymousTracking(config)
8381
track_cli_start(anonymous_tracking, 'monitor', get_cli_properties(), ctx.command.name)
8482
try:

scripts/validate_install.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,10 @@ python3 -m ensurepip --upgrade
66
python3 -m pip install --upgrade pip
77
python3 -m pip install elementary-data
88
python3 -c "import monitor"
9+
python3 -m pip install elementary-data[bigquery]
10+
python3 -m pip install elementary-data[snowflake]
11+
python3 -m pip install elementary-data[redshift]
12+
python3 -m pip install elementary-data[postgres]
13+
python3 -m pip install elementary-data[lineage]
14+
python3 -c "import lineage"
915
deactivate

setup.py

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,36 +23,40 @@
2323
"Snowflake, BigQuery, Redshift, data reliability, analytics engineering",
2424
long_description=README,
2525
install_requires=[
26-
'click>=8,<9',
26+
'click>=7.0,<9',
2727
'pyfiglet',
28-
'snowflake-connector-python[secure-local-storage]>=2.4.1,<2.8.0',
29-
'dbt-core>=0.20,<1.1.0',
30-
'dbt-postgres>=0.20,<1.1.0',
31-
'dbt-redshift>=0.20,<1.1.0',
32-
'dbt-snowflake>=0.20,<1.1.0',
33-
'dbt-bigquery>=0.20,<1.1.0',
34-
'networkx>=2.3,<3',
35-
'sqllineage==1.2.4',
36-
'pyvis>=0.1,<1',
37-
'sqlparse>=0.3.1,<0.5',
38-
'alive-progress<=2.3.1',
39-
'python-dateutil>=2.7.2,<3.0.0',
40-
'google-cloud-bigquery>=1.25.0,<3',
41-
'google-api-core>=1.16.0,<3',
42-
'requests>=2.7,<3.0.0',
28+
'dbt-core>=0.20,<2.0.0',
29+
'requests<3.0.0',
4330
'beautifulsoup4',
4431
'posthog',
45-
'sqlfluff<0.9.0',
4632
'ruamel.yaml',
47-
# Indirect
48-
'protobuf<4,>=3.13.0',
49-
'typing-extensions<3.11,>=3.7.4',
50-
'flask<1.1.1',
51-
'Jinja2>=2.10.1,<3',
52-
'tomli<2.0.0,>=0.2.6',
53-
'urllib3<1.26,>=1.20',
54-
'MarkupSafe==2.0.1'
33+
'alive-progress<=2.3.1'
5534
],
35+
extras_require={
36+
'snowflake': ['dbt-snowflake>=0.20,<2.0.0'],
37+
'bigquery': ['dbt-bigquery>=0.20,<2.0.0'],
38+
'redshift': ['dbt-redshift>=0.20,<2.0.0'],
39+
'postgres': ['dbt-postgres>=0.20,<2.0.0'],
40+
'lineage': ['snowflake-connector-python[secure-local-storage]>=2.4.1,<2.8.0',
41+
'click>=8,<9',
42+
'requests>=2.7,<3.0.0',
43+
'networkx>=2.3,<3',
44+
'sqllineage==1.2.4',
45+
'pyvis>=0.1,<1',
46+
'sqlparse>=0.3.1,<0.5',
47+
'sqlfluff<0.9.0',
48+
'google-cloud-bigquery>=1.25.0,<3',
49+
'google-api-core>=1.16.0,<3',
50+
'python-dateutil>=2.7.2,<3.0.0',
51+
# Indirect
52+
'protobuf<4,>=3.13.0',
53+
'typing-extensions<3.11,>=3.7.4',
54+
'flask<1.1.1',
55+
'Jinja2>=2.10.1,<3',
56+
'tomli<2.0.0,>=0.2.6',
57+
'urllib3<1.26,>=1.20',
58+
'MarkupSafe==2.0.1']
59+
},
5660
long_description_content_type="text/markdown",
5761
license='',
5862
url='https://github.com/elementary-data/elementary',

0 commit comments

Comments
 (0)