|
1 | | -import json |
2 | | -import os |
3 | | -import re |
4 | | -from pathlib import Path |
5 | | - |
6 | 1 | import click |
7 | | -from dotenv import load_dotenv |
8 | 2 |
|
9 | 3 | from datapilot import __version__ |
10 | 4 | from datapilot.core.knowledge.cli import cli as knowledge |
11 | 5 | from datapilot.core.mcp_utils.mcp import mcp |
12 | 6 | from datapilot.core.platforms.dbt.cli.cli import dbt |
13 | 7 |
|
14 | 8 |
|
15 | | -def load_config_from_file(): |
16 | | - """Load configuration from ~/.altimate/altimate.json if it exists.""" |
17 | | - config_path = Path.home() / ".altimate" / "altimate.json" |
18 | | - |
19 | | - if not config_path.exists(): |
20 | | - return {} |
21 | | - |
22 | | - try: |
23 | | - with config_path.open() as f: |
24 | | - config = json.load(f) |
25 | | - return config |
26 | | - except (OSError, json.JSONDecodeError) as e: |
27 | | - click.echo(f"Warning: Failed to load config from {config_path}: {e}", err=True) |
28 | | - return {} |
29 | | - |
30 | | - |
31 | | -def substitute_env_vars(value): |
32 | | - """Replace ${env:ENV_VARIABLE} patterns with actual environment variable values.""" |
33 | | - if not isinstance(value, str): |
34 | | - return value |
35 | | - |
36 | | - # Pattern to match ${env:VARIABLE_NAME} |
37 | | - pattern = r"\$\{env:([^}]+)\}" |
38 | | - |
39 | | - def replacer(match): |
40 | | - env_var = match.group(1) |
41 | | - return os.environ.get(env_var, match.group(0)) |
42 | | - |
43 | | - return re.sub(pattern, replacer, value) |
44 | | - |
45 | | - |
46 | | -def process_config(config): |
47 | | - """Process configuration dictionary to substitute environment variables.""" |
48 | | - processed = {} |
49 | | - for key, value in config.items(): |
50 | | - processed[key] = substitute_env_vars(value) |
51 | | - return processed |
52 | | - |
53 | | - |
54 | 9 | @click.group() |
55 | 10 | @click.version_option(version=__version__, prog_name="datapilot") |
56 | | -@click.option("--token", required=False, help="Your API token for authentication.", hide_input=True) |
57 | | -@click.option("--instance-name", required=False, help="Your tenant ID.") |
58 | | -@click.option("--backend-url", required=False, help="Altimate's Backend URL", default="https://api.myaltimate.com") |
59 | 11 | @click.pass_context |
60 | | -def datapilot(ctx, token, instance_name, backend_url): |
| 12 | +def datapilot(ctx): |
61 | 13 | """Altimate CLI for DBT project management.""" |
62 | | - # Load .env file from current directory if it exists |
63 | | - load_dotenv() |
64 | | - |
65 | | - # Load configuration from file |
66 | | - file_config = load_config_from_file() |
67 | | - file_config = process_config(file_config) |
68 | | - |
69 | | - # Map config file keys to CLI option names |
70 | | - config_mapping = {"altimateApiKey": "token", "altimateInstanceName": "instance_name", "altimateUrl": "backend_url"} |
71 | | - |
72 | | - # Store common options in context, with CLI args taking precedence |
| 14 | + # Ensure context object exists |
73 | 15 | ctx.ensure_object(dict) |
74 | 16 |
|
75 | | - # Apply file config first |
76 | | - for file_key, cli_key in config_mapping.items(): |
77 | | - if file_key in file_config: |
78 | | - ctx.obj[cli_key] = file_config[file_key] |
79 | | - |
80 | | - # Override with CLI arguments if provided |
81 | | - if token is not None: |
82 | | - ctx.obj["token"] = token |
83 | | - if instance_name is not None: |
84 | | - ctx.obj["instance_name"] = instance_name |
85 | | - if backend_url != "https://api.myaltimate.com": # Only override if not default |
86 | | - ctx.obj["backend_url"] = backend_url |
87 | | - |
88 | | - # Set defaults if nothing was provided |
89 | | - ctx.obj.setdefault("token", None) |
90 | | - ctx.obj.setdefault("instance_name", None) |
91 | | - ctx.obj.setdefault("backend_url", "https://api.myaltimate.com") |
92 | | - |
93 | 17 |
|
94 | 18 | datapilot.add_command(dbt) |
95 | 19 | datapilot.add_command(mcp) |
|
0 commit comments