lakeship 0.3.0__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.
lakeship-0.3.0/LICENSE ADDED
@@ -0,0 +1,10 @@
1
+ Copyright (c) 2026 TrustedLake. Todos os direitos reservados.
2
+
3
+ Este software e todo o seu codigo-fonte sao propriedade exclusiva da TrustedLake.
4
+ E vedado copiar, modificar, distribuir, sublicenciar ou usar este software, no
5
+ todo ou em parte, sem autorizacao previa e por escrito da TrustedLake.
6
+
7
+ A instalacao deste pacote via PyPI concede ao usuario uma licenca limitada,
8
+ pessoal, nao exclusiva e revogavel para uso do software conforme os Termos de
9
+ Servico da TrustedLake, nao constituindo cessao de direitos de propriedade
10
+ intelectual nem licenca de codigo aberto.
@@ -0,0 +1,47 @@
1
+ Metadata-Version: 2.4
2
+ Name: lakeship
3
+ Version: 0.3.0
4
+ Summary: Publique dashboards estaticos com um comando.
5
+ License: Proprietary
6
+ Requires-Python: >=3.9
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Requires-Dist: typer>=0.12
10
+ Requires-Dist: pyyaml>=6.0
11
+ Requires-Dist: requests>=2.31
12
+ Dynamic: license-file
13
+
14
+ # Lakeship
15
+
16
+ Publique dashboards estaticos com um comando. Vercel para Analytics.
17
+
18
+ ## O que e
19
+
20
+ Lakeship e uma CLI e plataforma pra desenvolvedores que constroem dashboards
21
+ estaticos (HTML/CSS/JS) e querem publica-los, versiona-los e conecta-los a
22
+ dados de um data lake sem cuidar de infraestrutura AWS na mao.
23
+
24
+ ## Instalacao
25
+
26
+ pip install lakeship
27
+
28
+ ## Uso basico
29
+
30
+ lakeship init --project meu-dashboard
31
+ lakeship login
32
+ lakeship publish
33
+
34
+ ## Comandos disponiveis
35
+
36
+ Rode lakeship commands pra ver a lista completa, com a descricao de cada um.
37
+ Hoje inclui: init, login, publish, status, rollback, commands.
38
+
39
+ ## Status do projeto
40
+
41
+ Este pacote esta em desenvolvimento ativo (v0.3.0). Publicar dashboards de
42
+ verdade requer a API da Lakeship configurada e acessivel via --api-url ou
43
+ a URL padrao configurada no pacote.
44
+
45
+ ## Licenca
46
+
47
+ Software proprietario da TrustedLake. Veja o arquivo LICENSE.
@@ -0,0 +1,34 @@
1
+ # Lakeship
2
+
3
+ Publique dashboards estaticos com um comando. Vercel para Analytics.
4
+
5
+ ## O que e
6
+
7
+ Lakeship e uma CLI e plataforma pra desenvolvedores que constroem dashboards
8
+ estaticos (HTML/CSS/JS) e querem publica-los, versiona-los e conecta-los a
9
+ dados de um data lake sem cuidar de infraestrutura AWS na mao.
10
+
11
+ ## Instalacao
12
+
13
+ pip install lakeship
14
+
15
+ ## Uso basico
16
+
17
+ lakeship init --project meu-dashboard
18
+ lakeship login
19
+ lakeship publish
20
+
21
+ ## Comandos disponiveis
22
+
23
+ Rode lakeship commands pra ver a lista completa, com a descricao de cada um.
24
+ Hoje inclui: init, login, publish, status, rollback, commands.
25
+
26
+ ## Status do projeto
27
+
28
+ Este pacote esta em desenvolvimento ativo (v0.3.0). Publicar dashboards de
29
+ verdade requer a API da Lakeship configurada e acessivel via --api-url ou
30
+ a URL padrao configurada no pacote.
31
+
32
+ ## Licenca
33
+
34
+ Software proprietario da TrustedLake. Veja o arquivo LICENSE.
@@ -0,0 +1,22 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "lakeship"
7
+ version = "0.3.0"
8
+ description = "Publique dashboards estaticos com um comando."
9
+ requires-python = ">=3.9"
10
+ readme = "README.md"
11
+ license = {text = "Proprietary"}
12
+ dependencies = [
13
+ "typer>=0.12",
14
+ "pyyaml>=6.0",
15
+ "requests>=2.31",
16
+ ]
17
+
18
+ [project.scripts]
19
+ lakeship = "lakeship.cli:app"
20
+
21
+ [tool.setuptools.packages.find]
22
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
@@ -0,0 +1,211 @@
1
+ import json
2
+ from pathlib import Path
3
+
4
+ import requests
5
+ import typer
6
+
7
+ from lakeship.project_schema import ProjectConfig, load_config, save_config
8
+ from lakeship.packaging import create_package
9
+
10
+ app = typer.Typer(name='lakeship', help='Lakeship: publique dashboards estaticos com um comando.')
11
+
12
+ DEFAULT_API_URL = 'http://127.0.0.1:8000'
13
+ CREDENTIALS_PATH = Path.home() / '.lakeship' / 'credentials.json'
14
+
15
+
16
+ def _save_credentials(token: str, email: str) -> Path:
17
+ CREDENTIALS_PATH.parent.mkdir(parents=True, exist_ok=True)
18
+ CREDENTIALS_PATH.write_text(json.dumps({'token': token, 'email': email}))
19
+ return CREDENTIALS_PATH
20
+
21
+
22
+ def _load_credentials():
23
+ if not CREDENTIALS_PATH.is_file():
24
+ return None
25
+ return json.loads(CREDENTIALS_PATH.read_text())
26
+
27
+
28
+ @app.command()
29
+ def init(
30
+ project: str = typer.Option(None, help='Nome do projeto (minusculas, digitos, hifen)'),
31
+ build_dir: str = typer.Option('dist', help='Diretorio de build estatico'),
32
+ ):
33
+ '''Cria o arquivo lakeship.yaml no diretorio atual.'''
34
+ if project is None:
35
+ project = Path.cwd().name.lower().replace('_', '-').replace(' ', '-')
36
+ try:
37
+ config = ProjectConfig(project=project, build_dir=build_dir)
38
+ except ValueError as exc:
39
+ typer.echo(f'Erro: {exc}', err=True)
40
+ raise typer.Exit(code=1)
41
+ path = save_config(config, Path.cwd())
42
+ typer.echo(f'Criado {path}')
43
+
44
+
45
+ @app.command()
46
+ def login(
47
+ email: str = typer.Option(..., prompt=True, help='Seu email'),
48
+ senha: str = typer.Option(..., prompt=True, hide_input=True, help='Sua senha'),
49
+ api_url: str = typer.Option(DEFAULT_API_URL, help='URL da API da Lakeship'),
50
+ ):
51
+ '''Autentica na Lakeship e guarda o token localmente.'''
52
+ try:
53
+ response = requests.post(f'{api_url}/api/auth/login/', json={'email': email, 'senha': senha}, timeout=10)
54
+ except requests.RequestException as exc:
55
+ typer.echo(f'Erro ao conectar na API ({api_url}): {exc}', err=True)
56
+ raise typer.Exit(code=1)
57
+ if response.status_code != 200:
58
+ typer.echo(f'Erro: credenciais invalidas ou API indisponivel (status {response.status_code})', err=True)
59
+ raise typer.Exit(code=1)
60
+ token = response.json()['token']
61
+ path = _save_credentials(token, email)
62
+ typer.echo(f'Autenticado como {email}. Credenciais salvas em {path}')
63
+
64
+
65
+ @app.command()
66
+ def publish(
67
+ api_url: str = typer.Option(DEFAULT_API_URL, help='URL da API da Lakeship'),
68
+ ):
69
+ '''Valida o lakeship.yaml, empacota o build_dir, e envia pra API da Lakeship (se autenticado).'''
70
+ try:
71
+ config = load_config(Path.cwd())
72
+ except (FileNotFoundError, ValueError) as exc:
73
+ typer.echo(f'Erro: {exc}', err=True)
74
+ raise typer.Exit(code=1)
75
+
76
+ build_dir = Path.cwd() / config.build_dir
77
+ output_dir = Path.cwd() / '.lakeship' / 'packages'
78
+ try:
79
+ info = create_package(build_dir, config.project, output_dir)
80
+ except (FileNotFoundError, ValueError) as exc:
81
+ typer.echo(f'Erro: {exc}', err=True)
82
+ raise typer.Exit(code=1)
83
+
84
+ typer.echo(f'Pacote criado: {info.zip_path} (versao {info.version})')
85
+
86
+ creds = _load_credentials()
87
+ if creds is None:
88
+ typer.echo('Voce nao esta autenticado (rode: lakeship login). Pacote gerado apenas localmente.')
89
+ return
90
+
91
+ try:
92
+ with open(info.zip_path, 'rb') as f:
93
+ response = requests.post(
94
+ f'{api_url}/api/dashboards/publish/',
95
+ headers={'Authorization': f'Token {creds["token"]}'},
96
+ data={'nome': config.project, 'build_dir': config.build_dir},
97
+ files={'file': f},
98
+ timeout=60,
99
+ )
100
+ except requests.RequestException as exc:
101
+ typer.echo(f'Erro ao publicar na API ({api_url}): {exc}', err=True)
102
+ raise typer.Exit(code=1)
103
+
104
+ if response.status_code != 202:
105
+ typer.echo(f'Erro ao publicar (status {response.status_code}): {response.text}', err=True)
106
+ raise typer.Exit(code=1)
107
+
108
+ result = response.json()
109
+ typer.echo(f'Publicado: dashboard {result["dashboard_id"]}, versao {result["versao"]} (status: {result["status"]})')
110
+
111
+
112
+ @app.command()
113
+ def status(
114
+ api_url: str = typer.Option(DEFAULT_API_URL, help='URL da API da Lakeship'),
115
+ ):
116
+ '''Mostra o historico de versoes do dashboard do projeto atual.'''
117
+ try:
118
+ config = load_config(Path.cwd())
119
+ except (FileNotFoundError, ValueError) as exc:
120
+ typer.echo(f'Erro: {exc}', err=True)
121
+ raise typer.Exit(code=1)
122
+
123
+ creds = _load_credentials()
124
+ if creds is None:
125
+ typer.echo('Voce nao esta autenticado (rode: lakeship login).', err=True)
126
+ raise typer.Exit(code=1)
127
+
128
+ headers = {'Authorization': f'Token {creds["token"]}'}
129
+ try:
130
+ response = requests.get(f'{api_url}/api/dashboards/', headers=headers, timeout=10)
131
+ response.raise_for_status()
132
+ except requests.RequestException as exc:
133
+ typer.echo(f'Erro ao consultar a API ({api_url}): {exc}', err=True)
134
+ raise typer.Exit(code=1)
135
+
136
+ dashboards = [d for d in response.json() if d['nome'] == config.project]
137
+ if not dashboards:
138
+ typer.echo(f'Nenhum dashboard encontrado com nome {config.project!r}.')
139
+ return
140
+ dashboard_id = dashboards[0]['id']
141
+
142
+ try:
143
+ response = requests.get(f'{api_url}/api/dashboards/{dashboard_id}/versoes/', headers=headers, timeout=10)
144
+ response.raise_for_status()
145
+ except requests.RequestException as exc:
146
+ typer.echo(f'Erro ao consultar versoes ({api_url}): {exc}', err=True)
147
+ raise typer.Exit(code=1)
148
+
149
+ for v in response.json():
150
+ typer.echo(f'{v["publicado_em"]} versao={v["versao"]} status={v["status"]}')
151
+
152
+
153
+ @app.command()
154
+ def rollback(
155
+ versao: str = typer.Argument(..., help='Versao pra qual voltar'),
156
+ api_url: str = typer.Option(DEFAULT_API_URL, help='URL da API da Lakeship'),
157
+ ):
158
+ '''Reverte o dashboard do projeto atual pra uma versao anterior ja publicada.'''
159
+ try:
160
+ config = load_config(Path.cwd())
161
+ except (FileNotFoundError, ValueError) as exc:
162
+ typer.echo(f'Erro: {exc}', err=True)
163
+ raise typer.Exit(code=1)
164
+
165
+ creds = _load_credentials()
166
+ if creds is None:
167
+ typer.echo('Voce nao esta autenticado (rode: lakeship login).', err=True)
168
+ raise typer.Exit(code=1)
169
+
170
+ headers = {'Authorization': f'Token {creds["token"]}'}
171
+ try:
172
+ response = requests.get(f'{api_url}/api/dashboards/', headers=headers, timeout=10)
173
+ response.raise_for_status()
174
+ except requests.RequestException as exc:
175
+ typer.echo(f'Erro ao consultar a API ({api_url}): {exc}', err=True)
176
+ raise typer.Exit(code=1)
177
+
178
+ dashboards = [d for d in response.json() if d['nome'] == config.project]
179
+ if not dashboards:
180
+ typer.echo(f'Nenhum dashboard encontrado com nome {config.project!r}.')
181
+ raise typer.Exit(code=1)
182
+ dashboard_id = dashboards[0]['id']
183
+
184
+ try:
185
+ response = requests.post(
186
+ f'{api_url}/api/dashboards/{dashboard_id}/versoes/{versao}/rollback/',
187
+ headers=headers, timeout=10,
188
+ )
189
+ except requests.RequestException as exc:
190
+ typer.echo(f'Erro ao reverter ({api_url}): {exc}', err=True)
191
+ raise typer.Exit(code=1)
192
+
193
+ if response.status_code != 200:
194
+ typer.echo(f'Erro ao reverter (status {response.status_code}): {response.text}', err=True)
195
+ raise typer.Exit(code=1)
196
+
197
+ result = response.json()
198
+ typer.echo(f'Revertido para versao {result["versao"]} (status: {result["status"]})')
199
+
200
+
201
+ @app.command()
202
+ def commands():
203
+ '''Lista todos os comandos disponiveis da lakeship CLI.'''
204
+ for cmd_info in app.registered_commands:
205
+ name = cmd_info.name or cmd_info.callback.__name__
206
+ help_text = (cmd_info.callback.__doc__ or '').strip().splitlines()[0] if cmd_info.callback.__doc__ else ''
207
+ typer.echo(f'{name}\t{help_text}')
208
+
209
+
210
+ if __name__ == '__main__':
211
+ app()
@@ -0,0 +1,25 @@
1
+ from dataclasses import dataclass
2
+ from pathlib import Path
3
+ import zipfile
4
+ from datetime import datetime
5
+
6
+ @dataclass
7
+ class PackageInfo:
8
+ project: str
9
+ version: str
10
+ zip_path: Path
11
+ created_at: str
12
+
13
+ def create_package(build_dir: Path, project_name: str, output_dir: Path) -> PackageInfo:
14
+ if not build_dir.is_dir():
15
+ raise FileNotFoundError(f'build_dir nao encontrado: {build_dir}')
16
+ files = [f for f in build_dir.rglob('*') if f.is_file()]
17
+ if not files:
18
+ raise ValueError(f'build_dir esta vazio: {build_dir}')
19
+ version = datetime.now().strftime('%Y%m%d%H%M%S')
20
+ output_dir.mkdir(parents=True, exist_ok=True)
21
+ zip_path = output_dir / f'{project_name}-{version}.zip'
22
+ with zipfile.ZipFile(zip_path, 'w') as zf:
23
+ for f in files:
24
+ zf.write(f, arcname=f.relative_to(build_dir))
25
+ return PackageInfo(project=project_name, version=version, zip_path=zip_path, created_at=datetime.now().isoformat())
@@ -0,0 +1,34 @@
1
+ from dataclasses import dataclass, asdict
2
+ from pathlib import Path
3
+ import re
4
+ import yaml
5
+
6
+ CONFIG_FILENAME = 'lakeship.yaml'
7
+
8
+ _NAME_RE = re.compile(r'^[a-z0-9-]+$')
9
+
10
+ @dataclass
11
+ class ProjectConfig:
12
+ project: str
13
+ build_dir: str = 'dist'
14
+
15
+ def __post_init__(self):
16
+ if not _NAME_RE.match(self.project):
17
+ raise ValueError(f'project invalido: {self.project!r} - use apenas minusculas, digitos e hifen')
18
+ if not self.build_dir:
19
+ raise ValueError('build_dir nao pode ser vazio')
20
+
21
+ def load_config(project_dir: Path) -> ProjectConfig:
22
+ path = project_dir / CONFIG_FILENAME
23
+ if not path.is_file():
24
+ raise FileNotFoundError(f'arquivo de config nao encontrado: {path}')
25
+ data = yaml.safe_load(path.read_text(encoding='utf-8'))
26
+ if not data or 'project' not in data:
27
+ raise ValueError(f'chave project ausente em {path}')
28
+ return ProjectConfig(**data)
29
+
30
+ def save_config(config: ProjectConfig, project_dir: Path) -> Path:
31
+ project_dir.mkdir(parents=True, exist_ok=True)
32
+ path = project_dir / CONFIG_FILENAME
33
+ path.write_text(yaml.safe_dump(asdict(config)), encoding='utf-8')
34
+ return path
@@ -0,0 +1,47 @@
1
+ Metadata-Version: 2.4
2
+ Name: lakeship
3
+ Version: 0.3.0
4
+ Summary: Publique dashboards estaticos com um comando.
5
+ License: Proprietary
6
+ Requires-Python: >=3.9
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Requires-Dist: typer>=0.12
10
+ Requires-Dist: pyyaml>=6.0
11
+ Requires-Dist: requests>=2.31
12
+ Dynamic: license-file
13
+
14
+ # Lakeship
15
+
16
+ Publique dashboards estaticos com um comando. Vercel para Analytics.
17
+
18
+ ## O que e
19
+
20
+ Lakeship e uma CLI e plataforma pra desenvolvedores que constroem dashboards
21
+ estaticos (HTML/CSS/JS) e querem publica-los, versiona-los e conecta-los a
22
+ dados de um data lake sem cuidar de infraestrutura AWS na mao.
23
+
24
+ ## Instalacao
25
+
26
+ pip install lakeship
27
+
28
+ ## Uso basico
29
+
30
+ lakeship init --project meu-dashboard
31
+ lakeship login
32
+ lakeship publish
33
+
34
+ ## Comandos disponiveis
35
+
36
+ Rode lakeship commands pra ver a lista completa, com a descricao de cada um.
37
+ Hoje inclui: init, login, publish, status, rollback, commands.
38
+
39
+ ## Status do projeto
40
+
41
+ Este pacote esta em desenvolvimento ativo (v0.3.0). Publicar dashboards de
42
+ verdade requer a API da Lakeship configurada e acessivel via --api-url ou
43
+ a URL padrao configurada no pacote.
44
+
45
+ ## Licenca
46
+
47
+ Software proprietario da TrustedLake. Veja o arquivo LICENSE.
@@ -0,0 +1,13 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ src/lakeship/__init__.py
5
+ src/lakeship/cli.py
6
+ src/lakeship/packaging.py
7
+ src/lakeship/project_schema.py
8
+ src/lakeship.egg-info/PKG-INFO
9
+ src/lakeship.egg-info/SOURCES.txt
10
+ src/lakeship.egg-info/dependency_links.txt
11
+ src/lakeship.egg-info/entry_points.txt
12
+ src/lakeship.egg-info/requires.txt
13
+ src/lakeship.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ lakeship = lakeship.cli:app
@@ -0,0 +1,3 @@
1
+ typer>=0.12
2
+ pyyaml>=6.0
3
+ requests>=2.31
@@ -0,0 +1 @@
1
+ lakeship