pinky-core 0.1.0.dev1__tar.gz → 0.1.0.dev3__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.
- pinky_core-0.1.0.dev3/.github/workflows/ci.yml +62 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/.github/workflows/publish.yml +2 -2
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/.github/workflows/release.yml +2 -2
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/.gitignore +4 -12
- pinky_core-0.1.0.dev3/.gitleaks.toml +14 -0
- pinky_core-0.1.0.dev3/.pre-commit-config.yaml +187 -0
- pinky_core-0.1.0.dev3/PKG-INFO +228 -0
- pinky_core-0.1.0.dev3/README.md +155 -0
- pinky_core-0.1.0.dev3/docs/.pages +7 -0
- pinky_core-0.1.0.dev3/docs/adr/.pages +2 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/docs/adr/0001-zero-dependency-static-html.md +3 -0
- pinky_core-0.1.0.dev3/docs/explanation/.pages +2 -0
- pinky_core-0.1.0.dev1/docs/explanation/design.md → pinky_core-0.1.0.dev3/docs/explanation/1-design.md +11 -4
- pinky_core-0.1.0.dev1/docs/explanation/features.md → pinky_core-0.1.0.dev3/docs/explanation/2-features.md +7 -18
- pinky_core-0.1.0.dev3/docs/how-to/.pages +2 -0
- pinky_core-0.1.0.dev3/docs/how-to/index.md +1 -0
- pinky_core-0.1.0.dev3/docs/index.md +23 -0
- pinky_core-0.1.0.dev3/docs/mkdocs.yml +24 -0
- pinky_core-0.1.0.dev3/docs/reference/.pages +1 -0
- pinky_core-0.1.0.dev3/docs/reference/api/.pages +2 -0
- pinky_core-0.1.0.dev3/docs/reference/api/fec.md +5 -0
- pinky_core-0.1.0.dev3/docs/reference/api/html.md +5 -0
- pinky_core-0.1.0.dev3/docs/reference/api/lint.md +5 -0
- pinky_core-0.1.0.dev3/docs/reference/api/warnings.md +5 -0
- pinky_core-0.1.0.dev3/docs/reference/generated/coverage_badge.svg +1 -0
- pinky_core-0.1.0.dev3/docs/reference/generated/hooks_badge.svg +12 -0
- pinky_core-0.1.0.dev3/docs/reference/generated/interrogate_badge.svg +58 -0
- pinky_core-0.1.0.dev3/docs/reference/generated/noqa_badge.svg +12 -0
- pinky_core-0.1.0.dev3/docs/tutorials/.pages +2 -0
- pinky_core-0.1.0.dev3/docs/tutorials/index.md +4 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/pyproject.toml +44 -7
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/scripts/deploy_validate_udfs.py +4 -4
- pinky_core-0.1.0.dev3/scripts/hooks/badges.toml +84 -0
- pinky_core-0.1.0.dev3/scripts/hooks/check_forbidden_keywords.py +199 -0
- pinky_core-0.1.0.dev3/scripts/hooks/check_snowpark_api.py +278 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/scripts/hooks/check_typed_api.py +11 -1
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/scripts/hooks/check_zws.py +25 -1
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/scripts/hooks/commit-msg +42 -15
- pinky_core-0.1.0.dev3/scripts/hooks/docs_identity.json +18 -0
- pinky_core-0.1.0.dev3/scripts/hooks/generate-docs +48 -0
- pinky_core-0.1.0.dev3/scripts/hooks/generate_ci_badges.py +152 -0
- pinky_core-0.1.0.dev3/scripts/hooks/render_docs.py +605 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/src/pinky_core/__init__.py +51 -3
- pinky_core-0.1.0.dev3/src/pinky_core/finance/__init__.py +33 -0
- pinky_core-0.1.0.dev3/src/pinky_core/finance/fec.py +551 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/src/pinky_core/fmt.py +8 -1
- pinky_core-0.1.0.dev3/src/pinky_core/html.py +350 -0
- pinky_core-0.1.0.dev3/src/pinky_core/lint.py +287 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/src/pinky_core/schedule.py +220 -8
- pinky_core-0.1.0.dev3/src/pinky_core/sql.py +127 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/src/pinky_core/validate.py +19 -10
- pinky_core-0.1.0.dev3/src/pinky_core/warnings.py +23 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/src/pinky_core/xml.py +5 -2
- pinky_core-0.1.0.dev3/tests/test_fec.py +310 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/tests/test_files.py +5 -5
- pinky_core-0.1.0.dev3/tests/test_html.py +63 -0
- pinky_core-0.1.0.dev3/tests/test_lint.py +104 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/tests/test_schedule.py +121 -1
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/tests/test_sql.py +27 -29
- pinky_core-0.1.0.dev3/tests/test_warnings.py +34 -0
- pinky_core-0.1.0.dev1/.github/workflows/ci.yml +0 -39
- pinky_core-0.1.0.dev1/.pre-commit-config.yaml +0 -125
- pinky_core-0.1.0.dev1/.vscode/extensions.json +0 -35
- pinky_core-0.1.0.dev1/.vscode/settings.json +0 -46
- pinky_core-0.1.0.dev1/AGENT.md +0 -209
- pinky_core-0.1.0.dev1/PKG-INFO +0 -87
- pinky_core-0.1.0.dev1/README.md +0 -30
- pinky_core-0.1.0.dev1/docs/index.md +0 -15
- pinky_core-0.1.0.dev1/mkdocs.dev.yml +0 -3
- pinky_core-0.1.0.dev1/mkdocs.yml +0 -35
- pinky_core-0.1.0.dev1/scripts/hooks/check-docs-up-to-date +0 -36
- pinky_core-0.1.0.dev1/scripts/hooks/check_forbidden_keywords.py +0 -76
- pinky_core-0.1.0.dev1/src/pinky_core/sql.py +0 -83
- pinky_core-0.1.0.dev1/src/pinky_core/sql_custom.py +0 -78
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/.secrets.baseline +0 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/LICENSE +0 -0
- {pinky_core-0.1.0.dev1/docs/reference/generated → pinky_core-0.1.0.dev3/docs/reference}/api/files.md +0 -0
- {pinky_core-0.1.0.dev1/docs/reference/generated → pinky_core-0.1.0.dev3/docs/reference}/api/fmt.md +0 -0
- {pinky_core-0.1.0.dev1/docs/reference/generated → pinky_core-0.1.0.dev3/docs/reference}/api/schedule.md +0 -0
- {pinky_core-0.1.0.dev1/docs/reference/generated → pinky_core-0.1.0.dev3/docs/reference}/api/security.md +0 -0
- {pinky_core-0.1.0.dev1/docs/reference/generated → pinky_core-0.1.0.dev3/docs/reference}/api/sql.md +0 -0
- {pinky_core-0.1.0.dev1/docs/reference/generated → pinky_core-0.1.0.dev3/docs/reference}/api/validate.md +0 -0
- {pinky_core-0.1.0.dev1/docs/reference/generated → pinky_core-0.1.0.dev3/docs/reference}/api/xml.md +0 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/sql/deploy_udf_example.sql +0 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/src/pinky_core/files.py +0 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/src/pinky_core/security.py +0 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/tests/__init__.py +0 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/tests/fixtures/cats_domination.xml +0 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/tests/test_fmt.py +0 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/tests/test_security.py +0 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/tests/test_validate.py +0 -0
- {pinky_core-0.1.0.dev1 → pinky_core-0.1.0.dev3}/tests/test_xml_xpath.py +0 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, develop]
|
|
6
|
+
paths: ['src/**', 'tests/**', 'pyproject.toml', 'scripts/**', '.pre-commit-config.yaml', '.github/workflows/ci.yml']
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [main, develop]
|
|
9
|
+
paths: ['src/**', 'tests/**', 'pyproject.toml', 'scripts/**', '.pre-commit-config.yaml', '.github/workflows/ci.yml']
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
ci:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
env:
|
|
15
|
+
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Python 3.12
|
|
21
|
+
uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.12"
|
|
24
|
+
|
|
25
|
+
- name: Run pre-commit hooks
|
|
26
|
+
# Single source of truth: .pre-commit-config.yaml (ruff, mypy, bandit, gitleaks,
|
|
27
|
+
# detect-secrets, check-zws, check-forbidden-keywords, interrogate, darglint,
|
|
28
|
+
# check-typed-api, mdformat) — replaces the hand-duplicated Lint/Format/Type/Security
|
|
29
|
+
# steps, which only re-implemented 3 of the ~11 hooks and could silently drift from
|
|
30
|
+
# .pre-commit-config.yaml's actual args/excludes. j178/prek-action (not `pip install
|
|
31
|
+
# prek`): official action, caches the prek env between runs, defaults to
|
|
32
|
+
# `prek run --show-diff-on-failure --color=always --all-files`.
|
|
33
|
+
uses: j178/prek-action@v2
|
|
34
|
+
|
|
35
|
+
- name: Install dependencies
|
|
36
|
+
run: pip install -e ".[validate,address,dev]"
|
|
37
|
+
|
|
38
|
+
- name: Tests
|
|
39
|
+
run: pytest
|
|
40
|
+
|
|
41
|
+
precommit-windows:
|
|
42
|
+
# ADR-0023 pilot gate: hermetic pre-commit hooks must run on the brother's
|
|
43
|
+
# machine (Windows, prek only, no toolchain) — this is the real gate, not the Mac.
|
|
44
|
+
runs-on: windows-latest
|
|
45
|
+
strategy:
|
|
46
|
+
matrix:
|
|
47
|
+
shell: [cmd, pwsh]
|
|
48
|
+
defaults:
|
|
49
|
+
run:
|
|
50
|
+
shell: ${{ matrix.shell }}
|
|
51
|
+
steps:
|
|
52
|
+
- uses: actions/checkout@v4
|
|
53
|
+
|
|
54
|
+
- name: Set up Python 3.12
|
|
55
|
+
uses: actions/setup-python@v5
|
|
56
|
+
with:
|
|
57
|
+
python-version: "3.12"
|
|
58
|
+
|
|
59
|
+
- name: Run mdformat hook
|
|
60
|
+
uses: j178/prek-action@v2
|
|
61
|
+
with:
|
|
62
|
+
extra-args: 'mdformat --all-files'
|
|
@@ -17,10 +17,10 @@ jobs:
|
|
|
17
17
|
steps:
|
|
18
18
|
- uses: actions/checkout@v4
|
|
19
19
|
|
|
20
|
-
- name: Set up Python 3.
|
|
20
|
+
- name: Set up Python 3.12
|
|
21
21
|
uses: actions/setup-python@v5
|
|
22
22
|
with:
|
|
23
|
-
python-version: "3.
|
|
23
|
+
python-version: "3.12"
|
|
24
24
|
|
|
25
25
|
- name: Install build
|
|
26
26
|
run: pip install build
|
|
@@ -32,10 +32,10 @@ jobs:
|
|
|
32
32
|
git tag "v${{ steps.version.outputs.version }}"
|
|
33
33
|
git push origin "v${{ steps.version.outputs.version }}"
|
|
34
34
|
|
|
35
|
-
- name: Set up Python 3.
|
|
35
|
+
- name: Set up Python 3.12
|
|
36
36
|
uses: actions/setup-python@v5
|
|
37
37
|
with:
|
|
38
|
-
python-version: "3.
|
|
38
|
+
python-version: "3.12"
|
|
39
39
|
|
|
40
40
|
- name: Install build
|
|
41
41
|
run: pip install build
|
|
@@ -17,26 +17,17 @@ venv/
|
|
|
17
17
|
.conda/
|
|
18
18
|
|
|
19
19
|
# ── Tools cache ──────────────────────────────────────────────────────────────
|
|
20
|
-
.
|
|
21
|
-
.mypy_cache/
|
|
22
|
-
.pytest_cache/
|
|
20
|
+
.cache/*
|
|
23
21
|
.pre-commit-cache/
|
|
24
|
-
htmlcov/
|
|
25
|
-
.coverage
|
|
26
|
-
.coverage.*
|
|
27
|
-
coverage.xml
|
|
28
22
|
|
|
29
23
|
# ── Generated docs ───────────────────────────────────────────────────────────
|
|
30
|
-
# docs/api/ is versioned — regenerate with: pdoc
|
|
24
|
+
# docs/api/ is versioned — regenerate with: pdoc pinky_core -o docs/api/ or wget
|
|
31
25
|
# Heavy wget mirrors are excluded (1 GB+)
|
|
32
26
|
docs/api/*/*.com/
|
|
33
27
|
# Local MkDocs assets — symlinked from pinky-studio for local dev, not committed
|
|
34
28
|
docs/assets/
|
|
35
29
|
site/
|
|
36
|
-
|
|
37
|
-
# ── Provider cache ───────────────────────────────────────────────────────────
|
|
38
|
-
.snowflake-provider/
|
|
39
|
-
|
|
30
|
+
site.nosync/
|
|
40
31
|
# ── Local dev ────────────────────────────────────────────────────────────────
|
|
41
32
|
.local/
|
|
42
33
|
*.local.json
|
|
@@ -51,6 +42,7 @@ connections.toml
|
|
|
51
42
|
.DS_Store
|
|
52
43
|
.AppleDouble
|
|
53
44
|
.LSOverride
|
|
45
|
+
*.icloud
|
|
54
46
|
|
|
55
47
|
# ── VSCode ───────────────────────────────────────────────────────────────────
|
|
56
48
|
# (keep .vscode/extensions.json and .vscode/settings.json — versioned)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Distributed as-is to every onboarded repo's root (see setup/precommit.py distribute()).
|
|
2
|
+
# gitleaks auto-discovers .gitleaks.toml in the scan root — no pre-commit-side wiring needed.
|
|
3
|
+
[extend]
|
|
4
|
+
useDefault = true
|
|
5
|
+
|
|
6
|
+
[allowlist]
|
|
7
|
+
# .secrets.baseline stores detect-secrets' accepted findings as SHA1 hashes (hashed_secret),
|
|
8
|
+
# never the raw secret — that's the whole point of a baseline. A high-entropy hash next to a
|
|
9
|
+
# "secret"-shaped key still trips gitleaks' generic-api-key heuristic the moment a repo's baseline
|
|
10
|
+
# records its first real finding (empty result sets don't trigger it, which is why this went
|
|
11
|
+
# unnoticed until pinky-studio).
|
|
12
|
+
paths = [
|
|
13
|
+
'''\.secrets\.baseline''',
|
|
14
|
+
]
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
---
|
|
2
|
+
# =============================================================================
|
|
3
|
+
# .pre-commit-config.yaml — GENERATED by pinky-workspace/setup.py — DO NOT EDIT
|
|
4
|
+
# =============================================================================
|
|
5
|
+
# Source: pinky-workspace/core/pre-commit/{base,extras/*}.yaml
|
|
6
|
+
# Third-party revs are pinned centrally in this base — bump them here, once.
|
|
7
|
+
# To change which hooks a repo gets, edit the workspace source and re-run setup.py.
|
|
8
|
+
#
|
|
9
|
+
# Install (done automatically by setup.py):
|
|
10
|
+
# pip install pre-commit
|
|
11
|
+
# pre-commit install
|
|
12
|
+
# pre-commit install --hook-type commit-msg
|
|
13
|
+
# =============================================================================
|
|
14
|
+
default_install_hook_types: [pre-commit, commit-msg]
|
|
15
|
+
# Pin explicite : sans ça, les hooks `language: python` (mdformat, mypy, interrogate, darglint…)
|
|
16
|
+
# créent leur venv avec le python3 ambiant du PATH au moment de l'install, pas une version garantie
|
|
17
|
+
# par le repo — non-déterministe en local (CI est protégée par actions/setup-python en amont).
|
|
18
|
+
default_language_version:
|
|
19
|
+
python: python3.12
|
|
20
|
+
|
|
21
|
+
repos:
|
|
22
|
+
# ── Formatting: trailing spaces + newline ─────────────────────────────────
|
|
23
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
24
|
+
rev: v6.0.0
|
|
25
|
+
hooks:
|
|
26
|
+
- id: trailing-whitespace
|
|
27
|
+
- id: end-of-file-fixer
|
|
28
|
+
exclude: ^docs/reference/generated/
|
|
29
|
+
- id: check-yaml
|
|
30
|
+
- id: check-toml
|
|
31
|
+
- id: check-merge-conflict
|
|
32
|
+
- id: debug-statements
|
|
33
|
+
|
|
34
|
+
# ── Docs generation: README + docs/index.md + quality badges ──────────────
|
|
35
|
+
# Universal (every repo, not just the snowflake extra — 2026-07-10, renamed/extended from
|
|
36
|
+
# check-docs-up-to-date). Runs before mdformat below so the regenerated README gets reformatted.
|
|
37
|
+
- repo: local
|
|
38
|
+
hooks:
|
|
39
|
+
- id: generate-docs
|
|
40
|
+
name: Generate docs (README + index.md + badges)
|
|
41
|
+
entry: scripts/hooks/generate-docs
|
|
42
|
+
language: script
|
|
43
|
+
stages: [pre-commit]
|
|
44
|
+
pass_filenames: false
|
|
45
|
+
|
|
46
|
+
# ── Formatting: Markdown ──────────────────────────────────────────────────
|
|
47
|
+
- repo: local
|
|
48
|
+
hooks:
|
|
49
|
+
- id: mdformat
|
|
50
|
+
name: mdformat
|
|
51
|
+
entry: mdformat
|
|
52
|
+
language: python
|
|
53
|
+
additional_dependencies: ["mdformat==1.0.0"]
|
|
54
|
+
files: ^README\.md$
|
|
55
|
+
|
|
56
|
+
# ── Security: secrets & forbidden files ──────────────────────────────────
|
|
57
|
+
# gitleaks' hook has pass_filenames: false (it scans the repo itself, not a file list pre-commit
|
|
58
|
+
# hands it) — a pre-commit `exclude:` here would be silently inert. The real exclusion mechanism
|
|
59
|
+
# is the distributed .gitleaks.toml allowlist (see distribute()/DISTRIBUTED_PATHS): .secrets.baseline
|
|
60
|
+
# stores detect-secrets' accepted findings as SHA1 hashes, never the raw secret, but a high-entropy
|
|
61
|
+
# hash next to a "secret"-shaped key still trips gitleaks' generic-api-key heuristic (found rolling
|
|
62
|
+
# this out to pinky-studio, the first repo whose baseline had a real finding instead of an empty
|
|
63
|
+
# result set).
|
|
64
|
+
- repo: https://github.com/gitleaks/gitleaks
|
|
65
|
+
rev: v8.30.0
|
|
66
|
+
hooks:
|
|
67
|
+
- id: gitleaks
|
|
68
|
+
|
|
69
|
+
# ── Security: alternative secret detection ────────────────────────────────
|
|
70
|
+
- repo: https://github.com/Yelp/detect-secrets
|
|
71
|
+
rev: v1.5.0
|
|
72
|
+
hooks:
|
|
73
|
+
- id: detect-secrets
|
|
74
|
+
args: ["--baseline", ".secrets.baseline"]
|
|
75
|
+
exclude: ^docs/
|
|
76
|
+
|
|
77
|
+
# ── Zero-width spaces (copy-paste from Outlook/Teams) ────────────────────
|
|
78
|
+
- repo: local
|
|
79
|
+
hooks:
|
|
80
|
+
- id: check-zws
|
|
81
|
+
name: "[ZWS] Invisible characters (zero-width)"
|
|
82
|
+
entry: python scripts/hooks/check_zws.py
|
|
83
|
+
language: system
|
|
84
|
+
pass_filenames: true
|
|
85
|
+
|
|
86
|
+
# ── Employer reference guard ──────────────────────────────────────────────
|
|
87
|
+
- repo: local
|
|
88
|
+
hooks:
|
|
89
|
+
- id: check-forbidden-keywords
|
|
90
|
+
name: "[FORBIDDEN] Employer references"
|
|
91
|
+
entry: python scripts/hooks/check_forbidden_keywords.py
|
|
92
|
+
language: system
|
|
93
|
+
pass_filenames: true
|
|
94
|
+
|
|
95
|
+
# ── Commit message format ─────────────────────────────────────────────────
|
|
96
|
+
- repo: local
|
|
97
|
+
hooks:
|
|
98
|
+
- id: commit-msg-format
|
|
99
|
+
name: Commit message format
|
|
100
|
+
entry: scripts/hooks/commit-msg
|
|
101
|
+
language: script
|
|
102
|
+
stages: [commit-msg]
|
|
103
|
+
|
|
104
|
+
# ── EXTRA python — repos with src/ ────────────────────────────────────────
|
|
105
|
+
# Python: ruff lint + format
|
|
106
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
107
|
+
rev: v0.15.15
|
|
108
|
+
hooks:
|
|
109
|
+
- id: ruff-check
|
|
110
|
+
args: [--no-fix]
|
|
111
|
+
- id: ruff-format
|
|
112
|
+
args: [--check]
|
|
113
|
+
|
|
114
|
+
# Python: type checking
|
|
115
|
+
- repo: local
|
|
116
|
+
hooks:
|
|
117
|
+
- id: mypy
|
|
118
|
+
name: mypy
|
|
119
|
+
entry: mypy
|
|
120
|
+
# Hermetic (ADR-0026, supersedes ADR-0023's system carve-out): additional_dependencies is
|
|
121
|
+
# auto-derived per repo by setup.py (build_precommit_config) from THAT repo's own
|
|
122
|
+
# pyproject.toml runtime `dependencies` — mypy pin + real third-party deps, minus internal
|
|
123
|
+
# pinky-* packages (pre-release, not on PyPI, excluded from the derivation).
|
|
124
|
+
# --ignore-missing-imports stays as the residual fallback for those excluded imports only.
|
|
125
|
+
language: python
|
|
126
|
+
additional_dependencies: ["mypy==2.0.0", "pydantic>=2.0", "sqlglot", "unidecode"]
|
|
127
|
+
types: [python]
|
|
128
|
+
args: [--ignore-missing-imports]
|
|
129
|
+
files: ^src/
|
|
130
|
+
# mypy's incremental cache (.mypy_cache/) isn't safe under concurrent access — without
|
|
131
|
+
# this, prek/pre-commit's default file-batch parallelism spawns multiple mypy processes
|
|
132
|
+
# against the same cache dir and one crashes with INTERNAL ERROR (reproduced on
|
|
133
|
+
# pinky-core: a single-process run over the same files passes clean).
|
|
134
|
+
require_serial: true
|
|
135
|
+
|
|
136
|
+
# Python: security
|
|
137
|
+
# B108 (hardcoded /tmp) is skipped workspace-wide: Snowflake execution only exposes
|
|
138
|
+
# /tmp as a writable scratch directory, so it is the sanctioned path, not a smell.
|
|
139
|
+
- repo: https://github.com/PyCQA/bandit
|
|
140
|
+
rev: "1.9.4"
|
|
141
|
+
hooks:
|
|
142
|
+
- id: bandit
|
|
143
|
+
pass_filenames: false
|
|
144
|
+
args: [-r, src/, -ll, --skip, B108]
|
|
145
|
+
|
|
146
|
+
# Docstrings: coverage
|
|
147
|
+
- repo: local
|
|
148
|
+
hooks:
|
|
149
|
+
- id: interrogate
|
|
150
|
+
name: "[DOCSTRING] Coverage"
|
|
151
|
+
entry: interrogate
|
|
152
|
+
language: python
|
|
153
|
+
additional_dependencies: ["interrogate==1.7.0"]
|
|
154
|
+
pass_filenames: false
|
|
155
|
+
args: [src/, --ignore-init-method, --ignore-magic, --ignore-module, --ignore-private]
|
|
156
|
+
|
|
157
|
+
# Docstrings: args/returns match signature
|
|
158
|
+
- repo: local
|
|
159
|
+
hooks:
|
|
160
|
+
- id: darglint
|
|
161
|
+
name: "[DOCSTRING] Args/Returns match"
|
|
162
|
+
entry: darglint
|
|
163
|
+
language: python
|
|
164
|
+
additional_dependencies: ["darglint==1.8.1"]
|
|
165
|
+
types: [python]
|
|
166
|
+
files: ^src/
|
|
167
|
+
|
|
168
|
+
# Typed API guard
|
|
169
|
+
- repo: local
|
|
170
|
+
hooks:
|
|
171
|
+
- id: check-typed-api
|
|
172
|
+
name: "[TYPED-API] No raw dict/tuple/set in public annotations"
|
|
173
|
+
entry: python scripts/hooks/check_typed_api.py
|
|
174
|
+
language: system
|
|
175
|
+
types: [python]
|
|
176
|
+
files: ^src/
|
|
177
|
+
|
|
178
|
+
# ── EXTRA snowflake — Snowpark / Core API repos ───────────────────────────
|
|
179
|
+
# Snowpark / Core API conventions (no session.sql(), canonical method names)
|
|
180
|
+
- repo: local
|
|
181
|
+
hooks:
|
|
182
|
+
- id: check-snowpark-api
|
|
183
|
+
name: "[SNOWPARK-API] No session.sql(), canonical method names"
|
|
184
|
+
entry: python scripts/hooks/check_snowpark_api.py
|
|
185
|
+
language: system
|
|
186
|
+
types: [python]
|
|
187
|
+
files: ^src/
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pinky-core
|
|
3
|
+
Version: 0.1.0.dev3
|
|
4
|
+
Summary: Shared Python utilities for Snowflake development
|
|
5
|
+
Project-URL: Homepage, https://github.com/pinky-and-co/pinky-core
|
|
6
|
+
Project-URL: Repository, https://github.com/pinky-and-co/pinky-core
|
|
7
|
+
Project-URL: Issues, https://github.com/pinky-and-co/pinky-core/issues
|
|
8
|
+
Author: pinky-and-co
|
|
9
|
+
License: MIT License
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2026 pinky-and-co
|
|
12
|
+
|
|
13
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
in the Software without restriction, including without limitation the rights
|
|
16
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
18
|
+
furnished to do so, subject to the following conditions:
|
|
19
|
+
|
|
20
|
+
The above copyright notice and this permission notice shall be included in all
|
|
21
|
+
copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
29
|
+
SOFTWARE.
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Keywords: data-engineering,snowflake,snowpark,utilities
|
|
32
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
33
|
+
Classifier: Operating System :: OS Independent
|
|
34
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
35
|
+
Classifier: Topic :: Database
|
|
36
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
37
|
+
Requires-Python: >=3.12
|
|
38
|
+
Requires-Dist: pydantic>=2.0
|
|
39
|
+
Requires-Dist: sqlglot
|
|
40
|
+
Requires-Dist: unidecode
|
|
41
|
+
Provides-Extra: address
|
|
42
|
+
Requires-Dist: usaddress; extra == 'address'
|
|
43
|
+
Provides-Extra: dev
|
|
44
|
+
Requires-Dist: bandit; extra == 'dev'
|
|
45
|
+
Requires-Dist: darglint; extra == 'dev'
|
|
46
|
+
Requires-Dist: genbadge[coverage]; extra == 'dev'
|
|
47
|
+
Requires-Dist: interrogate; extra == 'dev'
|
|
48
|
+
Requires-Dist: mkdocs-awesome-pages-plugin>=2.0; extra == 'dev'
|
|
49
|
+
Requires-Dist: mkdocs-material>=9.0; extra == 'dev'
|
|
50
|
+
Requires-Dist: mkdocstrings[python]>=0.25; extra == 'dev'
|
|
51
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
52
|
+
Requires-Dist: pre-commit; extra == 'dev'
|
|
53
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
54
|
+
Requires-Dist: pytest-cov; extra == 'dev'
|
|
55
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
56
|
+
Provides-Extra: fec
|
|
57
|
+
Requires-Dist: unidecode; extra == 'fec'
|
|
58
|
+
Provides-Extra: lint
|
|
59
|
+
Requires-Dist: detect-secrets>=1.5; extra == 'lint'
|
|
60
|
+
Requires-Dist: ruff; extra == 'lint'
|
|
61
|
+
Requires-Dist: sqlfluff>=3.0; extra == 'lint'
|
|
62
|
+
Requires-Dist: yamllint>=1.35; extra == 'lint'
|
|
63
|
+
Provides-Extra: schedule
|
|
64
|
+
Requires-Dist: croniter; extra == 'schedule'
|
|
65
|
+
Provides-Extra: validate
|
|
66
|
+
Requires-Dist: email-validator; extra == 'validate'
|
|
67
|
+
Requires-Dist: phonenumbers; extra == 'validate'
|
|
68
|
+
Requires-Dist: python-stdnum; extra == 'validate'
|
|
69
|
+
Provides-Extra: xml
|
|
70
|
+
Requires-Dist: lxml; extra == 'xml'
|
|
71
|
+
Requires-Dist: lxml-stubs; extra == 'xml'
|
|
72
|
+
Description-Content-Type: text/markdown
|
|
73
|
+
|
|
74
|
+
# pinky-core
|
|
75
|
+
|
|
76
|
+
<!-- pinky:readme-badges:start -->
|
|
77
|
+
|
|
78
|
+
<div align="center">
|
|
79
|
+
|
|
80
|
+
<img src="https://assets.pinky-suite.fr/icons/pinky-header.png" width="380" alt="pinky & co">
|
|
81
|
+
|
|
82
|
+

|
|
83
|
+

|
|
84
|
+

|
|
85
|
+

|
|
86
|
+

|
|
87
|
+
[](https://github.com/j178/prek)
|
|
88
|
+
|
|
89
|
+
**[Install](#install) • [Documentation](#documentation) • [License](#license)**
|
|
90
|
+
|
|
91
|
+
</div>
|
|
92
|
+
<!-- pinky:readme-badges:end -->
|
|
93
|
+
|
|
94
|
+
<!-- pinky:readme-tagline:start -->
|
|
95
|
+
|
|
96
|
+
Shared Python utilities for Snowflake development.
|
|
97
|
+
|
|
98
|
+
Part of the [pinky-and-co](https://github.com/pinky-and-co) suite.
|
|
99
|
+
|
|
100
|
+
<!-- pinky:readme-tagline:end -->
|
|
101
|
+
|
|
102
|
+
______________________________________________________________________
|
|
103
|
+
|
|
104
|
+
## Why pinky?
|
|
105
|
+
|
|
106
|
+
<!-- pinky:readme-why:start -->
|
|
107
|
+
|
|
108
|
+
The modern data stack was built on a good idea — **best of breed**. One tool for ingestion, one for transformation, one for orchestration, one for observability.
|
|
109
|
+
|
|
110
|
+
The reality: more licenses, same delivery time, and most of your energy goes into *the glue*.
|
|
111
|
+
|
|
112
|
+
Snowflake collapsed the stack. **Pinky makes it operational.**
|
|
113
|
+
|
|
114
|
+
Do it right, and the credits follow.
|
|
115
|
+
|
|
116
|
+
**Rationalized costs · Pure Python · Snowflake Native First**
|
|
117
|
+
|
|
118
|
+
<!-- pinky:readme-why:end -->
|
|
119
|
+
|
|
120
|
+
______________________________________________________________________
|
|
121
|
+
|
|
122
|
+
## Install
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
pip install pinky-core
|
|
126
|
+
pip install "pinky-core[validate]" # with SIRET, IBAN, email, phone validators
|
|
127
|
+
pip install "pinky-core[address]" # with address parsing
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
______________________________________________________________________
|
|
131
|
+
|
|
132
|
+
## Documentation
|
|
133
|
+
|
|
134
|
+
<!-- pinky:readme-docs:start -->
|
|
135
|
+
|
|
136
|
+
**Explanation**
|
|
137
|
+
|
|
138
|
+
- [Design](docs/explanation/1-design.md)
|
|
139
|
+
- [Features](docs/explanation/2-features.md)
|
|
140
|
+
|
|
141
|
+
**API reference**
|
|
142
|
+
|
|
143
|
+
- [Generated API docs](docs/reference/api/)
|
|
144
|
+
|
|
145
|
+
**Decisions**
|
|
146
|
+
|
|
147
|
+
- [ADRs](docs/adr/)
|
|
148
|
+
|
|
149
|
+
**Structure**
|
|
150
|
+
|
|
151
|
+
<details>
|
|
152
|
+
<summary>Show the directory tree</summary>
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
pinky-core/
|
|
156
|
+
├── .github/
|
|
157
|
+
│ └── workflows/
|
|
158
|
+
│ ├── ci.yml
|
|
159
|
+
│ ├── publish.yml
|
|
160
|
+
│ └── release.yml
|
|
161
|
+
├── scripts/
|
|
162
|
+
│ ├── hooks/
|
|
163
|
+
│ │ ├── badges.toml
|
|
164
|
+
│ │ ├── check_forbidden_keywords.py
|
|
165
|
+
│ │ ├── check_snowpark_api.py
|
|
166
|
+
│ │ ├── check_typed_api.py
|
|
167
|
+
│ │ ├── check_zws.py
|
|
168
|
+
│ │ ├── commit-msg
|
|
169
|
+
│ │ ├── docs_identity.json
|
|
170
|
+
│ │ ├── generate-docs
|
|
171
|
+
│ │ ├── generate_ci_badges.py
|
|
172
|
+
│ │ └── render_docs.py
|
|
173
|
+
│ └── deploy_validate_udfs.py
|
|
174
|
+
├── sql/
|
|
175
|
+
│ └── deploy_udf_example.sql
|
|
176
|
+
├── src/
|
|
177
|
+
│ └── pinky_core/
|
|
178
|
+
│ ├── finance/
|
|
179
|
+
│ │ ├── __init__.py
|
|
180
|
+
│ │ └── fec.py
|
|
181
|
+
│ ├── __init__.py
|
|
182
|
+
│ ├── files.py
|
|
183
|
+
│ ├── fmt.py
|
|
184
|
+
│ ├── html.py
|
|
185
|
+
│ ├── lint.py
|
|
186
|
+
│ ├── schedule.py
|
|
187
|
+
│ ├── security.py
|
|
188
|
+
│ ├── sql.py
|
|
189
|
+
│ ├── validate.py
|
|
190
|
+
│ ├── warnings.py
|
|
191
|
+
│ └── xml.py
|
|
192
|
+
├── tests/
|
|
193
|
+
│ ├── fixtures/
|
|
194
|
+
│ │ └── cats_domination.xml
|
|
195
|
+
│ ├── __init__.py
|
|
196
|
+
│ ├── test_fec.py
|
|
197
|
+
│ ├── test_files.py
|
|
198
|
+
│ ├── test_fmt.py
|
|
199
|
+
│ ├── test_html.py
|
|
200
|
+
│ ├── test_lint.py
|
|
201
|
+
│ ├── test_schedule.py
|
|
202
|
+
│ ├── test_security.py
|
|
203
|
+
│ ├── test_sql.py
|
|
204
|
+
│ ├── test_validate.py
|
|
205
|
+
│ ├── test_warnings.py
|
|
206
|
+
│ └── test_xml_xpath.py
|
|
207
|
+
├── .gitignore
|
|
208
|
+
├── .gitleaks.toml
|
|
209
|
+
├── .pre-commit-config.yaml
|
|
210
|
+
├── .secrets.baseline
|
|
211
|
+
├── LICENSE
|
|
212
|
+
├── pyproject.toml
|
|
213
|
+
└── README.md
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
</details>
|
|
217
|
+
|
|
218
|
+
<!-- pinky:readme-docs:end -->
|
|
219
|
+
|
|
220
|
+
______________________________________________________________________
|
|
221
|
+
|
|
222
|
+
## License
|
|
223
|
+
|
|
224
|
+
<!-- pinky:readme-license:start -->
|
|
225
|
+
|
|
226
|
+
MIT — see [LICENSE](LICENSE).
|
|
227
|
+
|
|
228
|
+
<!-- pinky:readme-license:end -->
|