quantilica-cli 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.
- quantilica_cli-0.3.0/.githooks/pre-commit +27 -0
- quantilica_cli-0.3.0/.github/workflows/publish.yml +66 -0
- quantilica_cli-0.3.0/.github/workflows/test.yml +38 -0
- quantilica_cli-0.3.0/.gitignore +38 -0
- quantilica_cli-0.3.0/CHANGELOG.md +35 -0
- quantilica_cli-0.3.0/LICENSE +21 -0
- quantilica_cli-0.3.0/PKG-INFO +48 -0
- quantilica_cli-0.3.0/README.md +25 -0
- quantilica_cli-0.3.0/pyproject.toml +70 -0
- quantilica_cli-0.3.0/quantilica/cli/__init__.py +10 -0
- quantilica_cli-0.3.0/quantilica/cli/cli.py +154 -0
- quantilica_cli-0.3.0/quantilica/cli/manifests.py +322 -0
- quantilica_cli-0.3.0/quantilica/cli/progress.py +61 -0
- quantilica_cli-0.3.0/quantilica/cli/sdk.py +296 -0
- quantilica_cli-0.3.0/quantilica/cli/sources.py +293 -0
- quantilica_cli-0.3.0/quantilica/cli/ui.py +166 -0
- quantilica_cli-0.3.0/quantilica/py.typed +0 -0
- quantilica_cli-0.3.0/tests/__init__.py +0 -0
- quantilica_cli-0.3.0/tests/test_manifests.py +180 -0
- quantilica_cli-0.3.0/tests/test_sources.py +122 -0
- quantilica_cli-0.3.0/tests/test_ui.py +47 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Formata e verifica os arquivos Python staged com `ruff check --fix` e `ruff format` antes do commit.
|
|
3
|
+
#
|
|
4
|
+
# Instalação (uma vez por clone):
|
|
5
|
+
# git config core.hooksPath .githooks
|
|
6
|
+
#
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
cd "$(git rev-parse --show-toplevel)"
|
|
10
|
+
|
|
11
|
+
mapfile -t files < <(git diff --cached --name-only --diff-filter=ACMR -- '*.py')
|
|
12
|
+
|
|
13
|
+
if [ "${#files[@]}" -eq 0 ]; then
|
|
14
|
+
exit 0
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
if ! uv run ruff check --fix "${files[@]}"; then
|
|
18
|
+
echo "pre-commit: ruff check falhou — commit abortado." >&2
|
|
19
|
+
exit 1
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
if ! uv run ruff format "${files[@]}"; then
|
|
23
|
+
echo "pre-commit: ruff format falhou — commit abortado." >&2
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
git add -- "${files[@]}"
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build:
|
|
10
|
+
name: Build distribution
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- name: Install uv
|
|
16
|
+
uses: astral-sh/setup-uv@v5
|
|
17
|
+
|
|
18
|
+
- name: Build sdist and wheel
|
|
19
|
+
run: uv build
|
|
20
|
+
|
|
21
|
+
- name: Upload build artifacts
|
|
22
|
+
uses: actions/upload-artifact@v4
|
|
23
|
+
with:
|
|
24
|
+
name: dist
|
|
25
|
+
path: dist/
|
|
26
|
+
|
|
27
|
+
publish-testpypi:
|
|
28
|
+
name: Publish to TestPyPI
|
|
29
|
+
needs: build
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
environment:
|
|
32
|
+
name: testpypi
|
|
33
|
+
url: https://test.pypi.org/p/quantilica-cli
|
|
34
|
+
permissions:
|
|
35
|
+
id-token: write
|
|
36
|
+
steps:
|
|
37
|
+
- name: Download build artifacts
|
|
38
|
+
uses: actions/download-artifact@v4
|
|
39
|
+
with:
|
|
40
|
+
name: dist
|
|
41
|
+
path: dist/
|
|
42
|
+
|
|
43
|
+
- name: Publish to TestPyPI
|
|
44
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
45
|
+
with:
|
|
46
|
+
repository-url: https://test.pypi.org/legacy/
|
|
47
|
+
skip-existing: true
|
|
48
|
+
|
|
49
|
+
publish-pypi:
|
|
50
|
+
name: Publish to PyPI
|
|
51
|
+
needs: publish-testpypi
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
environment:
|
|
54
|
+
name: pypi
|
|
55
|
+
url: https://pypi.org/p/quantilica-cli
|
|
56
|
+
permissions:
|
|
57
|
+
id-token: write
|
|
58
|
+
steps:
|
|
59
|
+
- name: Download build artifacts
|
|
60
|
+
uses: actions/download-artifact@v4
|
|
61
|
+
with:
|
|
62
|
+
name: dist
|
|
63
|
+
path: dist/
|
|
64
|
+
|
|
65
|
+
- name: Publish to PyPI
|
|
66
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: Test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
name: Test (Python ${{ matrix.python-version }})
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
python-version: ["3.12", "3.13"]
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Install uv
|
|
22
|
+
uses: astral-sh/setup-uv@v5
|
|
23
|
+
with:
|
|
24
|
+
enable-cache: true
|
|
25
|
+
|
|
26
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
27
|
+
run: uv python install ${{ matrix.python-version }}
|
|
28
|
+
|
|
29
|
+
- name: Install dependencies
|
|
30
|
+
run: uv sync --group dev
|
|
31
|
+
|
|
32
|
+
- name: Lint with ruff
|
|
33
|
+
run: |
|
|
34
|
+
uv run ruff check src/ tests/
|
|
35
|
+
uv run ruff format --check src/ tests/
|
|
36
|
+
|
|
37
|
+
- name: Run tests
|
|
38
|
+
run: uv run pytest
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Build / packaging
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
build/
|
|
6
|
+
dist/
|
|
7
|
+
|
|
8
|
+
# Virtual envs e caches do uv
|
|
9
|
+
.venv/
|
|
10
|
+
.uv-cache/
|
|
11
|
+
|
|
12
|
+
# Lockfile — libs não versionam uv.lock
|
|
13
|
+
uv.lock
|
|
14
|
+
|
|
15
|
+
# Caches de teste / lint / tipos
|
|
16
|
+
.pytest_cache/
|
|
17
|
+
.ruff_cache/
|
|
18
|
+
.mypy_cache/
|
|
19
|
+
|
|
20
|
+
# Cobertura
|
|
21
|
+
.coverage
|
|
22
|
+
.coverage.*
|
|
23
|
+
htmlcov/
|
|
24
|
+
|
|
25
|
+
# Editor / IDE / OS
|
|
26
|
+
.vscode/
|
|
27
|
+
.idea/
|
|
28
|
+
.DS_Store
|
|
29
|
+
Thumbs.db
|
|
30
|
+
*.swp
|
|
31
|
+
|
|
32
|
+
# Logs e env locais
|
|
33
|
+
*.log
|
|
34
|
+
.env
|
|
35
|
+
.env.local
|
|
36
|
+
|
|
37
|
+
# Claude
|
|
38
|
+
.claude/
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Todas as mudanças notáveis deste projeto serão documentadas neste arquivo.
|
|
4
|
+
|
|
5
|
+
O formato segue [Keep a Changelog](https://keepachangelog.com/pt-BR/1.1.0/),
|
|
6
|
+
e este projeto adere ao [Semantic Versioning](https://semver.org/lang/pt-BR/).
|
|
7
|
+
|
|
8
|
+
## [0.3.0] - 2026-08-10
|
|
9
|
+
|
|
10
|
+
### Adicionado
|
|
11
|
+
- Extensão da `FetcherApp` (`sdk.py`) com suporte opcional para `FtpClient`.
|
|
12
|
+
- Exposição do método `download_datasets` na `FetcherApp` para uso por comandos Typer customizados nos plugins.
|
|
13
|
+
- Aceitação e passagem do parâmetro `aliases_dict` para personalização total dos subcomandos por fetcher.
|
|
14
|
+
|
|
15
|
+
### Alterado
|
|
16
|
+
- Padrão de metadados do pacote portado integralmente para a PEP 639 (licença) e PEP 561 (tipagem estática).
|
|
17
|
+
|
|
18
|
+
## [0.2.2] - 2026-07-28
|
|
19
|
+
*(Release retroativo não documentado)*
|
|
20
|
+
|
|
21
|
+
## [0.2.0] - 2026-07-15
|
|
22
|
+
*(Release retroativo não documentado)*
|
|
23
|
+
|
|
24
|
+
## [0.1.0] - 2026-06-04
|
|
25
|
+
|
|
26
|
+
Primeira entrada em formato Keep a Changelog; documenta o estado do pacote nesta
|
|
27
|
+
versão.
|
|
28
|
+
|
|
29
|
+
### Adicionado
|
|
30
|
+
|
|
31
|
+
- CLI unificada `quantilica` que descobre e monta os fetchers instalados via
|
|
32
|
+
entry points `quantilica.fetchers`, sem depender diretamente dos pacotes de
|
|
33
|
+
fetcher.
|
|
34
|
+
- Comando `list-sources` e montagem automática dos sub-apps Typer de cada fetcher
|
|
35
|
+
instalado (`quantilica <fonte> ...`).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Quantilica
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: quantilica-cli
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Unified CLI for Quantilica open data fetchers
|
|
5
|
+
Author-email: "Komesu, D.K." <daniel@dkko.me>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: brazil,cli,open-data,quantilica
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Typing :: Typed
|
|
18
|
+
Requires-Python: >=3.12
|
|
19
|
+
Requires-Dist: quantilica-core>=0.4.0
|
|
20
|
+
Requires-Dist: rich>=13.0.0
|
|
21
|
+
Requires-Dist: typer>=0.15.0
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# quantilica-cli
|
|
25
|
+
|
|
26
|
+
CLI unificada para o ecossistema Quantilica de dados abertos brasileiros.
|
|
27
|
+
|
|
28
|
+
## Instalação
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install quantilica-cli
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Instale os fetchers desejados separadamente:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install comex-fetcher inmet-fetcher rtn-fetcher
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Uso
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
quantilica --help
|
|
44
|
+
quantilica list-sources
|
|
45
|
+
quantilica comex sync 2024
|
|
46
|
+
quantilica inmet sync 2020 2021
|
|
47
|
+
quantilica td sync --dataset prices
|
|
48
|
+
```
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# quantilica-cli
|
|
2
|
+
|
|
3
|
+
CLI unificada para o ecossistema Quantilica de dados abertos brasileiros.
|
|
4
|
+
|
|
5
|
+
## Instalação
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install quantilica-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Instale os fetchers desejados separadamente:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install comex-fetcher inmet-fetcher rtn-fetcher
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Uso
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
quantilica --help
|
|
21
|
+
quantilica list-sources
|
|
22
|
+
quantilica comex sync 2024
|
|
23
|
+
quantilica inmet sync 2020 2021
|
|
24
|
+
quantilica td sync --dataset prices
|
|
25
|
+
```
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "quantilica-cli"
|
|
3
|
+
version = "0.3.0"
|
|
4
|
+
description = "Unified CLI for Quantilica open data fetchers"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [{ name = "Komesu, D.K.", email = "daniel@dkko.me" }]
|
|
7
|
+
license = "MIT"
|
|
8
|
+
license-files = ["LICENSE"]
|
|
9
|
+
requires-python = ">=3.12"
|
|
10
|
+
keywords = ["quantilica", "cli", "open-data", "brazil"]
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Development Status :: 3 - Alpha",
|
|
13
|
+
"Environment :: Console",
|
|
14
|
+
"Intended Audience :: Science/Research",
|
|
15
|
+
"Intended Audience :: Developers",
|
|
16
|
+
"Typing :: Typed",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Programming Language :: Python :: 3.13",
|
|
21
|
+
]
|
|
22
|
+
dependencies = [
|
|
23
|
+
"quantilica-core>=0.4.0",
|
|
24
|
+
"rich>=13.0.0",
|
|
25
|
+
"typer>=0.15.0",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.scripts]
|
|
29
|
+
quantilica = "quantilica.cli.cli:main"
|
|
30
|
+
|
|
31
|
+
[dependency-groups]
|
|
32
|
+
dev = ["ruff>=0.9.0", "pytest>=8.0.0"]
|
|
33
|
+
|
|
34
|
+
# Os fetchers são instalados independentemente pelo usuário — quantilica-cli
|
|
35
|
+
# os descobre via entry points (grupo "quantilica.fetchers") sem dependência direta.
|
|
36
|
+
# Exemplo de instalação local para desenvolvimento:
|
|
37
|
+
# uv pip install -e ../comex-fetcher ../rtn-fetcher ...
|
|
38
|
+
|
|
39
|
+
# Para desenvolvimento local do quantilica-core em conjunto com o CLI:
|
|
40
|
+
# cd quantilica-cli && uv pip install -e ../quantilica-core (sem [tool.uv.sources])
|
|
41
|
+
# Em produção, quantilica-core é instalado via git+https (declarado em dependencies).
|
|
42
|
+
|
|
43
|
+
# [tool.hatch.metadata]
|
|
44
|
+
# allow-direct-references = true
|
|
45
|
+
|
|
46
|
+
[tool.hatch.build]
|
|
47
|
+
sources = ["src"]
|
|
48
|
+
|
|
49
|
+
[tool.hatch.build.targets.wheel]
|
|
50
|
+
packages = ["src/quantilica/cli"]
|
|
51
|
+
|
|
52
|
+
[build-system]
|
|
53
|
+
requires = ["hatchling>=1.27"]
|
|
54
|
+
build-backend = "hatchling.build"
|
|
55
|
+
|
|
56
|
+
[tool.pytest.ini_options]
|
|
57
|
+
testpaths = ["tests"]
|
|
58
|
+
addopts = ["-p", "no:cacheprovider"]
|
|
59
|
+
|
|
60
|
+
[tool.ruff]
|
|
61
|
+
line-length = 88
|
|
62
|
+
|
|
63
|
+
[tool.ruff.lint]
|
|
64
|
+
select = ["E", "F", "I", "UP", "B"]
|
|
65
|
+
|
|
66
|
+
[tool.ruff.lint.per-file-ignores]
|
|
67
|
+
"src/quantilica/cli/sources.py" = ["E501"]
|
|
68
|
+
"src/quantilica/cli/cli.py" = ["E501"]
|
|
69
|
+
"src/quantilica/cli/sdk.py" = ["E501"]
|
|
70
|
+
"tests/*" = ["E501"]
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"""Unified CLI entry point for Quantilica fetchers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import sys
|
|
7
|
+
from importlib.metadata import entry_points
|
|
8
|
+
from typing import Annotated
|
|
9
|
+
|
|
10
|
+
import typer
|
|
11
|
+
from rich.console import Console
|
|
12
|
+
from rich.logging import RichHandler
|
|
13
|
+
from rich.table import Table
|
|
14
|
+
|
|
15
|
+
from quantilica.cli import __version__
|
|
16
|
+
from quantilica.cli.manifests import app as manifests_app
|
|
17
|
+
from quantilica.cli.sources import (
|
|
18
|
+
app as sources_app,
|
|
19
|
+
)
|
|
20
|
+
from quantilica.cli.sources import (
|
|
21
|
+
cmd_doctor,
|
|
22
|
+
cmd_install,
|
|
23
|
+
cmd_uninstall,
|
|
24
|
+
fetch_remote_sources,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
FETCHER_GROUP = "quantilica.fetchers"
|
|
28
|
+
COMMAND_GROUP = "quantilica.commands"
|
|
29
|
+
|
|
30
|
+
app = typer.Typer(
|
|
31
|
+
name="quantilica",
|
|
32
|
+
help="Quantilica — ferramentas de dados abertos brasileiros.",
|
|
33
|
+
no_args_is_help=True,
|
|
34
|
+
)
|
|
35
|
+
app.add_typer(manifests_app, name="manifests")
|
|
36
|
+
app.add_typer(sources_app, name="sources")
|
|
37
|
+
|
|
38
|
+
# Adiciona comandos top-level install, uninstall e doctor
|
|
39
|
+
app.command("install")(cmd_install)
|
|
40
|
+
app.command("uninstall")(cmd_uninstall)
|
|
41
|
+
app.command("doctor")(cmd_doctor)
|
|
42
|
+
|
|
43
|
+
console = Console()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _load_plugins(group: str) -> dict[str, typer.Typer]:
|
|
47
|
+
plugins: dict[str, typer.Typer] = {}
|
|
48
|
+
for ep in entry_points(group=group):
|
|
49
|
+
try:
|
|
50
|
+
plugins[ep.name] = ep.load()
|
|
51
|
+
except Exception as exc:
|
|
52
|
+
console.print(
|
|
53
|
+
f"[yellow]Aviso:[/yellow] falha ao carregar plugin '{ep.name}': {exc}"
|
|
54
|
+
)
|
|
55
|
+
return plugins
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _register_plugins() -> None:
|
|
59
|
+
# Fetchers e comandos ficam na raiz: `quantilica <nome>`.
|
|
60
|
+
for name, plugin_app in _load_plugins(FETCHER_GROUP).items():
|
|
61
|
+
app.add_typer(plugin_app, name=name)
|
|
62
|
+
for name, plugin_app in _load_plugins(COMMAND_GROUP).items():
|
|
63
|
+
app.add_typer(plugin_app, name=name)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
_register_plugins()
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _version_callback(value: bool) -> None:
|
|
70
|
+
if value:
|
|
71
|
+
console.print(f"quantilica {__version__}")
|
|
72
|
+
raise typer.Exit()
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@app.callback()
|
|
76
|
+
def root_callback(
|
|
77
|
+
version: bool | None = typer.Option(
|
|
78
|
+
None,
|
|
79
|
+
"--version",
|
|
80
|
+
"-V",
|
|
81
|
+
callback=_version_callback,
|
|
82
|
+
is_eager=True,
|
|
83
|
+
help="Exibe a versão e encerra.",
|
|
84
|
+
),
|
|
85
|
+
) -> None:
|
|
86
|
+
"""Quantilica CLI."""
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@app.command("list-sources")
|
|
90
|
+
def list_sources(
|
|
91
|
+
remote: Annotated[
|
|
92
|
+
bool,
|
|
93
|
+
typer.Option(
|
|
94
|
+
"--remote", help="Exibe todas as fontes conhecidas no registro remoto"
|
|
95
|
+
),
|
|
96
|
+
] = False,
|
|
97
|
+
) -> None:
|
|
98
|
+
"""Lista as fontes de dados instaladas ou disponíveis no repositório."""
|
|
99
|
+
plugins = _load_plugins(FETCHER_GROUP)
|
|
100
|
+
|
|
101
|
+
if remote:
|
|
102
|
+
remote_registry = fetch_remote_sources()
|
|
103
|
+
table = Table(title="Todas as fontes de dados conhecidas", show_header=True)
|
|
104
|
+
table.add_column("Fonte", style="cyan")
|
|
105
|
+
table.add_column("Pacote", style="magenta")
|
|
106
|
+
table.add_column("Status", style="green")
|
|
107
|
+
|
|
108
|
+
for name, dist in sorted(remote_registry.items()):
|
|
109
|
+
status = (
|
|
110
|
+
"[green]Instalado[/green]"
|
|
111
|
+
if name in plugins
|
|
112
|
+
else "[dim]Não instalado[/dim]"
|
|
113
|
+
)
|
|
114
|
+
table.add_row(name, dist, status)
|
|
115
|
+
|
|
116
|
+
console.print(table)
|
|
117
|
+
return
|
|
118
|
+
|
|
119
|
+
if not plugins:
|
|
120
|
+
console.print(
|
|
121
|
+
"[yellow]Nenhum fetcher instalado.[/yellow]\n"
|
|
122
|
+
"Use 'quantilica install <fonte>' para instalar um fetcher (ex: quantilica install comex)."
|
|
123
|
+
)
|
|
124
|
+
return
|
|
125
|
+
|
|
126
|
+
table = Table(title="Fontes instaladas", show_header=True)
|
|
127
|
+
table.add_column("Comando", style="cyan")
|
|
128
|
+
table.add_column("Descrição", style="green")
|
|
129
|
+
|
|
130
|
+
for name, plugin_app in sorted(plugins.items()):
|
|
131
|
+
info = getattr(plugin_app, "info", None)
|
|
132
|
+
description = ""
|
|
133
|
+
if info and hasattr(info, "help") and info.help:
|
|
134
|
+
description = info.help
|
|
135
|
+
table.add_row(f"quantilica {name}", description)
|
|
136
|
+
|
|
137
|
+
console.print(table)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def main() -> None:
|
|
141
|
+
if hasattr(sys.stdout, "reconfigure"):
|
|
142
|
+
sys.stdout.reconfigure(encoding="utf-8", errors="replace") # type: ignore
|
|
143
|
+
logging.basicConfig(
|
|
144
|
+
level=logging.INFO,
|
|
145
|
+
format="%(message)s",
|
|
146
|
+
datefmt="[%X]",
|
|
147
|
+
handlers=[RichHandler(rich_tracebacks=True, show_path=False)],
|
|
148
|
+
force=True,
|
|
149
|
+
)
|
|
150
|
+
app()
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
if __name__ == "__main__":
|
|
154
|
+
main()
|