registro-db 1.0.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.
Files changed (171) hide show
  1. registro_db-1.0.0/.editorconfig +15 -0
  2. registro_db-1.0.0/.github/ISSUE_TEMPLATE//342/234/250-feature-request.md +23 -0
  3. registro_db-1.0.0/.github/ISSUE_TEMPLATE//360/237/220/233-bug-report.md +30 -0
  4. registro_db-1.0.0/.github/ISSUE_TEMPLATE//360/237/233/240-task---improvement.md +20 -0
  5. registro_db-1.0.0/.github/PULL_REQUEST_TEMPLATE/PULL_REQUEST_TEMPLATE.md +30 -0
  6. registro_db-1.0.0/.github/workflows/ci.yml +77 -0
  7. registro_db-1.0.0/.github/workflows/release.yml +104 -0
  8. registro_db-1.0.0/.gitignore +119 -0
  9. registro_db-1.0.0/.python-version +1 -0
  10. registro_db-1.0.0/CHANGELOG.md +14 -0
  11. registro_db-1.0.0/CONTRIBUTING.md +252 -0
  12. registro_db-1.0.0/CONTRIBUTORS.md +11 -0
  13. registro_db-1.0.0/LICENSE +21 -0
  14. registro_db-1.0.0/PKG-INFO +270 -0
  15. registro_db-1.0.0/README.md +234 -0
  16. registro_db-1.0.0/SECURITY.md +17 -0
  17. registro_db-1.0.0/config.example.toml +48 -0
  18. registro_db-1.0.0/docker/Dockerfile +49 -0
  19. registro_db-1.0.0/docker/docker-compose.yml +35 -0
  20. registro_db-1.0.0/docker/seeds/mysql/01-demo.sql +10 -0
  21. registro_db-1.0.0/docker/seeds/postgres/01-demo.sql +18 -0
  22. registro_db-1.0.0/mypy.ini +44 -0
  23. registro_db-1.0.0/pyproject.toml +110 -0
  24. registro_db-1.0.0/resources/registro.svg +30 -0
  25. registro_db-1.0.0/ruff.toml +37 -0
  26. registro_db-1.0.0/scripts/check.sh +10 -0
  27. registro_db-1.0.0/scripts/dev.sh +9 -0
  28. registro_db-1.0.0/scripts/fmt.sh +7 -0
  29. registro_db-1.0.0/scripts/lint.sh +13 -0
  30. registro_db-1.0.0/scripts/test.sh +4 -0
  31. registro_db-1.0.0/src/registro_adapters/__init__.py +17 -0
  32. registro_db-1.0.0/src/registro_adapters/_introspect.py +124 -0
  33. registro_db-1.0.0/src/registro_adapters/_params.py +49 -0
  34. registro_db-1.0.0/src/registro_adapters/_typeinfer.py +111 -0
  35. registro_db-1.0.0/src/registro_adapters/base.py +267 -0
  36. registro_db-1.0.0/src/registro_adapters/duckdb_adapter.py +268 -0
  37. registro_db-1.0.0/src/registro_adapters/introspect/__init__.py +5 -0
  38. registro_db-1.0.0/src/registro_adapters/introspect/duckdb.py +263 -0
  39. registro_db-1.0.0/src/registro_adapters/introspect/mysql.py +196 -0
  40. registro_db-1.0.0/src/registro_adapters/introspect/postgres.py +251 -0
  41. registro_db-1.0.0/src/registro_adapters/introspect/sqlite.py +176 -0
  42. registro_db-1.0.0/src/registro_adapters/mysql_adapter.py +437 -0
  43. registro_db-1.0.0/src/registro_adapters/postgres_adapter.py +331 -0
  44. registro_db-1.0.0/src/registro_adapters/py.typed +0 -0
  45. registro_db-1.0.0/src/registro_adapters/registry.py +102 -0
  46. registro_db-1.0.0/src/registro_adapters/sqlite_adapter.py +276 -0
  47. registro_db-1.0.0/src/registro_cli/__init__.py +5 -0
  48. registro_db-1.0.0/src/registro_cli/__main__.py +4 -0
  49. registro_db-1.0.0/src/registro_cli/main.py +363 -0
  50. registro_db-1.0.0/src/registro_cli/py.typed +0 -0
  51. registro_db-1.0.0/src/registro_core/__init__.py +19 -0
  52. registro_db-1.0.0/src/registro_core/config.py +170 -0
  53. registro_db-1.0.0/src/registro_core/errors.py +65 -0
  54. registro_db-1.0.0/src/registro_core/events.py +275 -0
  55. registro_db-1.0.0/src/registro_core/export.py +32 -0
  56. registro_db-1.0.0/src/registro_core/logging.py +203 -0
  57. registro_db-1.0.0/src/registro_core/models/__init__.py +33 -0
  58. registro_db-1.0.0/src/registro_core/models/connection.py +185 -0
  59. registro_db-1.0.0/src/registro_core/models/query.py +66 -0
  60. registro_db-1.0.0/src/registro_core/models/result.py +53 -0
  61. registro_db-1.0.0/src/registro_core/models/schema.py +83 -0
  62. registro_db-1.0.0/src/registro_core/protocols/__init__.py +11 -0
  63. registro_db-1.0.0/src/registro_core/protocols/adapter.py +85 -0
  64. registro_db-1.0.0/src/registro_core/protocols/plugin.py +28 -0
  65. registro_db-1.0.0/src/registro_core/py.typed +0 -0
  66. registro_db-1.0.0/src/registro_core/version.py +17 -0
  67. registro_db-1.0.0/src/registro_engine/__init__.py +16 -0
  68. registro_db-1.0.0/src/registro_engine/executor.py +271 -0
  69. registro_db-1.0.0/src/registro_engine/history.py +165 -0
  70. registro_db-1.0.0/src/registro_engine/introspector.py +97 -0
  71. registro_db-1.0.0/src/registro_engine/pool.py +220 -0
  72. registro_db-1.0.0/src/registro_engine/py.typed +0 -0
  73. registro_db-1.0.0/src/registro_engine/transaction.py +21 -0
  74. registro_db-1.0.0/src/registro_plugins/__init__.py +16 -0
  75. registro_db-1.0.0/src/registro_plugins/api.py +110 -0
  76. registro_db-1.0.0/src/registro_plugins/context.py +75 -0
  77. registro_db-1.0.0/src/registro_plugins/loader.py +196 -0
  78. registro_db-1.0.0/src/registro_plugins/py.typed +0 -0
  79. registro_db-1.0.0/src/registro_plugins/registry.py +80 -0
  80. registro_db-1.0.0/src/registro_tui/__init__.py +5 -0
  81. registro_db-1.0.0/src/registro_tui/app.py +696 -0
  82. registro_db-1.0.0/src/registro_tui/builtin_commands.py +120 -0
  83. registro_db-1.0.0/src/registro_tui/events.py +11 -0
  84. registro_db-1.0.0/src/registro_tui/keymaps/__init__.py +20 -0
  85. registro_db-1.0.0/src/registro_tui/keymaps/_labels.py +39 -0
  86. registro_db-1.0.0/src/registro_tui/keymaps/default.py +62 -0
  87. registro_db-1.0.0/src/registro_tui/keymaps/vim.py +20 -0
  88. registro_db-1.0.0/src/registro_tui/py.typed +0 -0
  89. registro_db-1.0.0/src/registro_tui/registro.tcss +308 -0
  90. registro_db-1.0.0/src/registro_tui/screens/__init__.py +8 -0
  91. registro_db-1.0.0/src/registro_tui/screens/_base.py +76 -0
  92. registro_db-1.0.0/src/registro_tui/screens/command_palette.py +101 -0
  93. registro_db-1.0.0/src/registro_tui/screens/connection.py +114 -0
  94. registro_db-1.0.0/src/registro_tui/screens/help.py +102 -0
  95. registro_db-1.0.0/src/registro_tui/screens/history.py +81 -0
  96. registro_db-1.0.0/src/registro_tui/screens/main.py +44 -0
  97. registro_db-1.0.0/src/registro_tui/screens/row_limit.py +68 -0
  98. registro_db-1.0.0/src/registro_tui/session.py +161 -0
  99. registro_db-1.0.0/src/registro_tui/state.py +37 -0
  100. registro_db-1.0.0/src/registro_tui/themes/__init__.py +8 -0
  101. registro_db-1.0.0/src/registro_tui/themes/_base.py +18 -0
  102. registro_db-1.0.0/src/registro_tui/themes/monokai.py +16 -0
  103. registro_db-1.0.0/src/registro_tui/themes/nord.py +15 -0
  104. registro_db-1.0.0/src/registro_tui/widgets/__init__.py +10 -0
  105. registro_db-1.0.0/src/registro_tui/widgets/action_bar.py +48 -0
  106. registro_db-1.0.0/src/registro_tui/widgets/query_tabs.py +44 -0
  107. registro_db-1.0.0/src/registro_tui/widgets/results_table.py +191 -0
  108. registro_db-1.0.0/src/registro_tui/widgets/schema_tree.py +153 -0
  109. registro_db-1.0.0/src/registro_tui/widgets/sql_editor.py +17 -0
  110. registro_db-1.0.0/src/registro_tui/widgets/status_bar.py +164 -0
  111. registro_db-1.0.0/tests/__init__.py +0 -0
  112. registro_db-1.0.0/tests/adapters/__init__.py +0 -0
  113. registro_db-1.0.0/tests/adapters/_conformance.py +386 -0
  114. registro_db-1.0.0/tests/adapters/conftest.py +78 -0
  115. registro_db-1.0.0/tests/adapters/test_bulk_introspection.py +94 -0
  116. registro_db-1.0.0/tests/adapters/test_cancellation_inflight.py +100 -0
  117. registro_db-1.0.0/tests/adapters/test_conformance_duckdb.py +29 -0
  118. registro_db-1.0.0/tests/adapters/test_conformance_sqlite.py +25 -0
  119. registro_db-1.0.0/tests/adapters/test_dsn_params.py +56 -0
  120. registro_db-1.0.0/tests/adapters/test_duckdb_adapter.py +119 -0
  121. registro_db-1.0.0/tests/adapters/test_introspect.py +157 -0
  122. registro_db-1.0.0/tests/adapters/test_mysql_adapter.py +98 -0
  123. registro_db-1.0.0/tests/adapters/test_mysql_adapter_unit.py +258 -0
  124. registro_db-1.0.0/tests/adapters/test_postgres_adapter.py +65 -0
  125. registro_db-1.0.0/tests/adapters/test_postgres_adapter_unit.py +192 -0
  126. registro_db-1.0.0/tests/adapters/test_registry.py +92 -0
  127. registro_db-1.0.0/tests/adapters/test_sqlite_adapter.py +163 -0
  128. registro_db-1.0.0/tests/adapters/test_typeinfer.py +107 -0
  129. registro_db-1.0.0/tests/cli/__init__.py +0 -0
  130. registro_db-1.0.0/tests/cli/test_main.py +244 -0
  131. registro_db-1.0.0/tests/conftest.py +29 -0
  132. registro_db-1.0.0/tests/core/__init__.py +0 -0
  133. registro_db-1.0.0/tests/core/test_config.py +118 -0
  134. registro_db-1.0.0/tests/core/test_errors.py +58 -0
  135. registro_db-1.0.0/tests/core/test_events.py +239 -0
  136. registro_db-1.0.0/tests/core/test_export.py +33 -0
  137. registro_db-1.0.0/tests/core/test_logging.py +78 -0
  138. registro_db-1.0.0/tests/core/test_models.py +139 -0
  139. registro_db-1.0.0/tests/engine/__init__.py +0 -0
  140. registro_db-1.0.0/tests/engine/test_executor.py +417 -0
  141. registro_db-1.0.0/tests/engine/test_history.py +93 -0
  142. registro_db-1.0.0/tests/engine/test_introspector.py +208 -0
  143. registro_db-1.0.0/tests/engine/test_pool.py +254 -0
  144. registro_db-1.0.0/tests/engine/test_transaction.py +60 -0
  145. registro_db-1.0.0/tests/fixtures/__init__.py +0 -0
  146. registro_db-1.0.0/tests/fixtures/sample_plugin.py +39 -0
  147. registro_db-1.0.0/tests/plugins/__init__.py +0 -0
  148. registro_db-1.0.0/tests/plugins/test_api.py +81 -0
  149. registro_db-1.0.0/tests/plugins/test_context.py +123 -0
  150. registro_db-1.0.0/tests/plugins/test_loader.py +227 -0
  151. registro_db-1.0.0/tests/plugins/test_loader_discovery.py +92 -0
  152. registro_db-1.0.0/tests/plugins/test_panels.py +142 -0
  153. registro_db-1.0.0/tests/plugins/test_registry.py +53 -0
  154. registro_db-1.0.0/tests/scripts/test-integration.sh +41 -0
  155. registro_db-1.0.0/tests/scripts/test.sh +7 -0
  156. registro_db-1.0.0/tests/tui/__init__.py +0 -0
  157. registro_db-1.0.0/tests/tui/test_app_smoke.py +283 -0
  158. registro_db-1.0.0/tests/tui/test_builtin_commands.py +37 -0
  159. registro_db-1.0.0/tests/tui/test_connection_modal.py +187 -0
  160. registro_db-1.0.0/tests/tui/test_help_modal.py +94 -0
  161. registro_db-1.0.0/tests/tui/test_history_panel.py +127 -0
  162. registro_db-1.0.0/tests/tui/test_keymap_conflicts.py +265 -0
  163. registro_db-1.0.0/tests/tui/test_markup_escaping.py +262 -0
  164. registro_db-1.0.0/tests/tui/test_pool_in_app.py +126 -0
  165. registro_db-1.0.0/tests/tui/test_results_pane.py +154 -0
  166. registro_db-1.0.0/tests/tui/test_row_limit.py +81 -0
  167. registro_db-1.0.0/tests/tui/test_schema_tree.py +153 -0
  168. registro_db-1.0.0/tests/tui/test_session_helpers.py +147 -0
  169. registro_db-1.0.0/tests/tui/test_vim_keymap.py +43 -0
  170. registro_db-1.0.0/tests/tui/test_widgets.py +196 -0
  171. registro_db-1.0.0/uv.lock +1312 -0
@@ -0,0 +1,15 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ indent_style = space
7
+ indent_size = 4
8
+ insert_final_newline = true
9
+ trim_trailing_whitespace = true
10
+
11
+ [*.{yml,yaml,toml,json}]
12
+ indent_size = 2
13
+
14
+ [*.md]
15
+ trim_trailing_whitespace = false
@@ -0,0 +1,23 @@
1
+ ---
2
+ name: '✨ Feature Request'
3
+ about: Suggest an idea or a new functionality
4
+ title: '[FEATURE]: '
5
+ labels: enhancement
6
+ assignees: ''
7
+ ---
8
+
9
+ ### Is your feature request related to a problem?
10
+
11
+ A clear and concise description of what the problem is (e.g. I'm always frustrated when...).
12
+
13
+ ### Describe the solution you'd like
14
+
15
+ A clear and concise description of what you want to happen.
16
+
17
+ ### Describe alternatives you've considered
18
+
19
+ A clear and concise description of any alternative solutions or features you've considered.
20
+
21
+ ### Additional context
22
+
23
+ Add any other context or screenshots about the feature request here.
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: "\U0001F41B Bug Report"
3
+ about: Report an error or unexpected behavior
4
+ title: '[BUG]: '
5
+ labels: bug
6
+ assignees: ''
7
+ ---
8
+
9
+ ### Bug Description
10
+
11
+ A clear and concise description of what the bug is.
12
+
13
+ ### Steps to Reproduce
14
+
15
+ 1. Go to '...'
16
+ 2. Click on '....'
17
+ 3. Scroll down to '....'
18
+ 4. See error
19
+
20
+ ### Expected Behavior
21
+
22
+ A clear and concise description of what you expected to happen.
23
+
24
+ ### Screenshots / Logs
25
+
26
+ If applicable, add screenshots or paste console logs to help explain your problem.
27
+
28
+ ### Environment
29
+
30
+ - **Version:**
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: "\U0001F6E0 Task / Improvement"
3
+ about: Maintenance, refactoring, or small improvements
4
+ title: '[TASK]: '
5
+ labels: maintenance
6
+ assignees: ''
7
+ ---
8
+
9
+ ### Description
10
+
11
+ A clear and concise description of what needs to be done.
12
+
13
+ ### Motivation
14
+
15
+ Why is this task necessary or beneficial for the project?
16
+
17
+ ### Checklist
18
+
19
+ - [ ] Task 1
20
+ - [ ] Task 2
@@ -0,0 +1,30 @@
1
+ ## Description
2
+
3
+ <!-- Provide a brief summary of the changes and the motivation behind them. -->
4
+
5
+ ## Related Issue
6
+
7
+ <!-- Link the issue here using the syntax: Fixes #123 or Related to #123 -->
8
+
9
+ ## Type of Change
10
+
11
+ - [ ] 🐛 Bug fix (non-breaking change which fixes an issue)
12
+ - [ ] ✨ New feature (non-breaking change which adds functionality)
13
+ - [ ] 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
14
+ - [ ] 🛠 Maintenance / Refactoring
15
+
16
+ ## How Has This Been Tested?
17
+
18
+ <!-- Describe the tests that you ran to verify your changes. -->
19
+
20
+ - [ ] Manual testing (please describe)
21
+ - [ ] Unit tests added/updated
22
+ - [ ] Integration tests added/updated
23
+
24
+ ## Checklist
25
+
26
+ - [ ] My code follows the style guidelines of this project
27
+ - [ ] I have performed a self-review of my code
28
+ - [ ] I have commented my code, particularly in hard-to-understand areas
29
+ - [ ] I have made corresponding changes to the documentation
30
+ - [ ] My changes generate no new warnings
@@ -0,0 +1,77 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths-ignore:
7
+ - '**.md'
8
+ - 'docs/**'
9
+ pull_request:
10
+ paths-ignore:
11
+ - '**.md'
12
+ - 'docs/**'
13
+ workflow_dispatch:
14
+ workflow_call:
15
+
16
+ concurrency:
17
+ group: ${{ github.workflow }}-${{ github.ref }}
18
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
19
+
20
+ permissions:
21
+ contents: read
22
+
23
+ jobs:
24
+ lint:
25
+ runs-on: ubuntu-24.04
26
+ steps:
27
+ - uses: actions/checkout@v6
28
+
29
+ - name: Install uv
30
+ uses: astral-sh/setup-uv@v8.1.0
31
+ with:
32
+ enable-cache: true
33
+ cache-suffix: "lint"
34
+ python-version: "3.13"
35
+
36
+ - name: Sync workspace
37
+ run: uv sync --all-extras --dev --frozen
38
+
39
+ - name: Lint (ruff format + check + mypy)
40
+ run: ./scripts/lint.sh
41
+
42
+ test:
43
+ runs-on: ${{ matrix.os }}
44
+ defaults:
45
+ run:
46
+ shell: bash
47
+ strategy:
48
+ matrix:
49
+ os: [ubuntu-24.04, macos-15]
50
+ fail-fast: false
51
+ steps:
52
+ - uses: actions/checkout@v6
53
+
54
+ - name: Install uv
55
+ uses: astral-sh/setup-uv@v8.1.0
56
+ with:
57
+ enable-cache: true
58
+ cache-suffix: "test"
59
+ python-version: "3.13"
60
+
61
+ - name: Sync workspace
62
+ run: uv sync --all-extras --dev --frozen
63
+
64
+ - name: Test (pytest + coverage gate)
65
+ run: ./tests/scripts/test.sh
66
+ env:
67
+ REGISTRO_TEST_MARKERS: ${{ matrix.os == 'ubuntu-24.04' && 'integration or not integration' || 'not integration' }}
68
+
69
+ dependency-review:
70
+ name: Dependency Review
71
+ runs-on: ubuntu-24.04
72
+ if: github.event_name == 'pull_request'
73
+ steps:
74
+ - name: Checkout repository
75
+ uses: actions/checkout@v6
76
+ - name: Dependency Review
77
+ uses: actions/dependency-review-action@v4
@@ -0,0 +1,104 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ validate:
14
+ runs-on: ubuntu-24.04
15
+ steps:
16
+ - uses: actions/checkout@v6
17
+ - name: Install uv
18
+ uses: astral-sh/setup-uv@v8.1.0
19
+ with:
20
+ enable-cache: true
21
+ python-version: "3.13"
22
+ - name: Validate tag version against pyproject.toml
23
+ run: |
24
+ if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
25
+ TAG_VERSION="${GITHUB_REF#refs/tags/v}"
26
+ PY_VERSION=$(uv run python -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])')
27
+ echo "Tag version: $TAG_VERSION | pyproject.toml version: $PY_VERSION"
28
+ if [[ "$TAG_VERSION" != "$PY_VERSION" ]]; then
29
+ echo "::error::Tag version ($TAG_VERSION) does not match pyproject.toml version ($PY_VERSION)"
30
+ exit 1
31
+ fi
32
+ fi
33
+
34
+ checks:
35
+ uses: ./.github/workflows/ci.yml
36
+
37
+ release:
38
+ needs: [validate, checks]
39
+ runs-on: ubuntu-24.04
40
+ environment: release
41
+ permissions:
42
+ contents: write
43
+ id-token: write
44
+ steps:
45
+ - uses: actions/checkout@v6
46
+
47
+ - name: Install uv
48
+ uses: astral-sh/setup-uv@v8.1.0
49
+ with:
50
+ enable-cache: true
51
+ python-version: "3.13"
52
+
53
+ - name: Sync workspace
54
+ run: uv sync --all-extras --dev --frozen
55
+
56
+ - name: Build packages
57
+ run: uv build --out-dir dist
58
+
59
+ - name: Generate Checksums
60
+ run: |
61
+ (cd dist && sha256sum *.tar.gz *.whl) > SHA256SUMS
62
+
63
+ - name: Extract Changelog Entry
64
+ id: extract_changelog
65
+ env:
66
+ GITHUB_REF_NAME: ${{ github.ref_name }}
67
+ run: |
68
+ uv run python -c '
69
+ import os, re, uuid
70
+ version = os.environ["GITHUB_REF_NAME"].lstrip("v")
71
+ with open("CHANGELOG.md") as f:
72
+ content = f.read()
73
+ pattern = rf"(?m)^##\s+\[?{re.escape(version)}\]?(.*?)(?=^##\s+\[?|\Z)"
74
+ match = re.search(pattern, content, re.DOTALL)
75
+ notes = ""
76
+ if match:
77
+ raw_notes = match.group(1).strip()
78
+ lines = raw_notes.splitlines()
79
+ if lines and (re.search(r"\d{4}-\d{1,2}-\d{1,2}", lines[0]) or not lines[0].strip()):
80
+ notes = "\n".join(lines[1:]).strip()
81
+ else:
82
+ notes = raw_notes
83
+ if not notes:
84
+ notes = "No changelog entry found for this release."
85
+ github_output = os.environ.get("GITHUB_OUTPUT")
86
+ if github_output:
87
+ delimiter = f"EOF_{uuid.uuid4().hex}"
88
+ with open(github_output, "a") as f:
89
+ f.write(f"body<<{delimiter}\n{notes}\n{delimiter}\n")
90
+ '
91
+
92
+ - name: Create GitHub Release
93
+ uses: softprops/action-gh-release@v3
94
+ with:
95
+ name: Registro ${{ github.ref_name }}
96
+ body: ${{ steps.extract_changelog.outputs.body }}
97
+ files: |
98
+ dist/*.tar.gz
99
+ dist/*.whl
100
+ SHA256SUMS
101
+ generate_release_notes: false
102
+
103
+ - name: Publish package distributions to PyPI
104
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,119 @@
1
+ # Python bytecode / runtime
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+
8
+ # Distribution / Packaging
9
+ build/
10
+ develop-eggs/
11
+ dist/
12
+ downloads/
13
+ eggs/
14
+ .eggs/
15
+ lib/
16
+ lib64/
17
+ parts/
18
+ sdist/
19
+ var/
20
+ wheels/
21
+ share/python-wheels/
22
+ *.egg-info/
23
+ .installed.cfg
24
+ *.egg
25
+ MANIFEST
26
+
27
+ # Virtual Environments and uv
28
+ .venv/
29
+ venv/
30
+ env/
31
+ .uv/
32
+ .uv-cache/
33
+ pip-wheel-metadata/
34
+
35
+ # Linting / Type-checking / Testing
36
+ .mypy_cache/
37
+ .ruff_cache/
38
+ .pytest_cache/
39
+ .hypothesis/
40
+ .nox/
41
+ .tox/
42
+ .dmypy.json
43
+ dmypy.json
44
+ .pre-commit-cache/
45
+
46
+ # Coverage
47
+ .coverage
48
+ .coverage.*
49
+ htmlcov/
50
+ coverage.xml
51
+ *.cover
52
+
53
+ # Jupyter / Notebooks
54
+ .ipynb_checkpoints/
55
+
56
+ # Environment / Secrets
57
+ .env
58
+ .env.*
59
+ !.env.example
60
+ !.env.template
61
+ config.toml
62
+ !config.example.toml
63
+
64
+ # Docker (local overrides)
65
+ docker-compose.override.yml
66
+
67
+ # Registro (project-specific runtime & storage)
68
+ *.db
69
+ *.sqlite
70
+ *.sqlite3
71
+ *.duckdb
72
+ *.log
73
+ registro.log
74
+ .registro/
75
+ scratch/
76
+
77
+ # IDEs and Editors
78
+ .vscode/
79
+ .idea/
80
+ .zed/
81
+ *.swp
82
+ *.swo
83
+ *~
84
+ *.bak
85
+ *.sublime-project
86
+ *.sublime-workspace
87
+
88
+ # OS / System
89
+ .DS_Store
90
+ .DS_Store?
91
+ ._*
92
+ .Spotlight-V100
93
+ .Trashes
94
+ ehthumbs.db
95
+ Thumbs.db
96
+ desktop.ini
97
+
98
+ # AI Tools & Agents
99
+ .openai/
100
+ .chatgpt/
101
+ gpt-config.json
102
+ openai.config.json
103
+ .anthropic/
104
+ .claude/
105
+ claude.config.json
106
+ claude-settings.json
107
+ .prompts/
108
+ .prompt-cache/
109
+ .ai/
110
+ .gemini/
111
+ .antigravity/
112
+ .antigravitycli/
113
+ .copilot/
114
+ .codex/
115
+ .cagent/
116
+ .cursor/
117
+ .windsurf/
118
+ .cline/
119
+ CLAUDE.md
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,14 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [1.0.0] - 2026-09-23
11
+
12
+ ### Added
13
+
14
+ - First implementation of Registro.
@@ -0,0 +1,252 @@
1
+ # Contributing to Registro 📟
2
+
3
+ Thank you for your interest in contributing to **Registro**! We welcome contributions, bug reports, feature requests, and security improvements from the community.
4
+
5
+ ---
6
+
7
+ ## 🛠️ Development Setup
8
+
9
+ Registro uses [uv](https://github.com/astral-sh/uv) for fast, modern Python package management and workflow orchestration.
10
+
11
+ ### Prerequisites
12
+
13
+ - **Python 3.13 or newer**
14
+ - **uv** (Install via `curl -LsSf https://astral.sh/uv/install.sh | sh` or your package manager)
15
+
16
+ ### Quick Start
17
+
18
+ 1. **Fork and Clone the Repository**
19
+ ```bash
20
+ git clone https://github.com/YOUR_USERNAME/registro.git
21
+ cd registro
22
+ ```
23
+
24
+ 2. **Synchronize Dependencies**
25
+ Initialize the virtual environment and install all packages (including development packages and all database extras):
26
+ ```bash
27
+ uv sync --all-extras --dev
28
+ ```
29
+ *Alternatively, run `./scripts/dev.sh` to initialize the environment.*
30
+
31
+ 3. **Activate the Environment**
32
+ ```bash
33
+ source .venv/bin/activate
34
+ ```
35
+
36
+ ---
37
+
38
+ ## ⚙️ Coding Standards & Tools
39
+
40
+ We use strict quality gates to maintain codebase health. All of these run automatically on CI, but you should run them locally before submitting changes.
41
+
42
+ ### Developer Scripts
43
+
44
+ We provide dedicated helper scripts under `scripts/` to streamline local workflows:
45
+
46
+ | Script | Purpose |
47
+ | :--- | :--- |
48
+ | `./scripts/dev.sh` | Synchronizes virtual environment with all extras and dev dependencies |
49
+ | `./scripts/fmt.sh` | Formats code with Ruff and applies safe linter autofixes |
50
+ | `./scripts/lint.sh` | Runs Ruff format check, Ruff lint check, and MyPy strict type check |
51
+ | `./scripts/test.sh` | Runs the offline test suite with coverage reporting |
52
+ | `./scripts/check.sh` | The pre-PR quality gate (runs `./scripts/lint.sh` and `./scripts/test.sh`) |
53
+
54
+ ### Manual Linting & Formatting
55
+
56
+ We use **Ruff** for formatting and linting, and **MyPy** for strict static type checking:
57
+
58
+ - **Check formatting:**
59
+ ```bash
60
+ uv run ruff format --check .
61
+ ```
62
+ - **Format code:**
63
+ ```bash
64
+ uv run ruff format .
65
+ # Or run ./scripts/fmt.sh
66
+ ```
67
+ - **Lint code:**
68
+ ```bash
69
+ uv run ruff check .
70
+ ```
71
+ - **Strict type checking:**
72
+ ```bash
73
+ uv run mypy --config-file=mypy.ini src
74
+ ```
75
+
76
+ ---
77
+
78
+ ## 🧪 Testing
79
+
80
+ We use **Pytest** for running our test suite with strict coverage requirements.
81
+
82
+ - **Run unit tests (offline suite):**
83
+ ```bash
84
+ uv run pytest -m "not integration" --cov=src
85
+ # Or simply:
86
+ ./scripts/test.sh
87
+ ```
88
+ - **Run integration tests (requires Docker daemon for PostgreSQL and MySQL):**
89
+ ```bash
90
+ ./tests/scripts/test-integration.sh
91
+ ```
92
+
93
+ ### Coverage Quality Gate
94
+
95
+ Our test suite enforces an **84% minimum test coverage gate** (`fail_under = 84` in `pyproject.toml`). The offline suite run must satisfy this gate on its own without relying on server-backed integration tests.
96
+
97
+ ### The Ultimate Quality Gate
98
+
99
+ Before submitting any Pull Request, ensure that formatting, linting, type-checking, and test coverage all pass cleanly by running:
100
+ ```bash
101
+ ./scripts/check.sh
102
+ ```
103
+
104
+ ---
105
+
106
+ ## 🔌 Writing Plugins
107
+
108
+ Registro features an extensible, plugin-first architecture. You can contribute new plugins or create external plugins to add dockable panels, custom commands, and event listeners.
109
+
110
+ ### Plugin Protocol
111
+
112
+ A Registro plugin implements the structural `Plugin` protocol (`registro_core.protocols.plugin.Plugin`):
113
+
114
+ ```python
115
+ from registro_core.protocols.plugin import PluginManifest
116
+ from registro_plugins.context import PluginContext
117
+
118
+
119
+ class MyPlugin:
120
+ manifest = PluginManifest(
121
+ id="my_plugin",
122
+ name="My Plugin",
123
+ version="1.0.0",
124
+ description="A custom Registro plugin",
125
+ )
126
+
127
+ def on_load(self, ctx: PluginContext) -> None:
128
+ """Called when the plugin is loaded."""
129
+ ...
130
+
131
+ def on_unload(self, ctx: PluginContext) -> None:
132
+ """Called when the plugin is unloaded or during app shutdown."""
133
+ ...
134
+ ```
135
+
136
+ ### Packaging & Discovery
137
+
138
+ Plugins are discovered dynamically via Python entry points in the `registro.plugins` group. Add the following to your `pyproject.toml`:
139
+
140
+ ```toml
141
+ [project.entry-points."registro.plugins"]
142
+ my_plugin = "my_package.plugin:MyPlugin"
143
+ ```
144
+
145
+ You can verify that Registro discovers your plugin by running:
146
+ ```bash
147
+ registro plugins list
148
+ ```
149
+
150
+ ### Subscribing to Event Bus Hooks
151
+
152
+ Plugins can subscribe to asynchronous lifecycle events on the `EventBus`. Key events defined in [events.py](src/registro_core/events.py) include:
153
+
154
+ - `ConnectionOpened` / `ConnectionClosed`
155
+ - `QueryStarted` / `QueryProgress` / `QueryCompleted` / `QueryFailed` / `QueryCancelled`
156
+ - `SchemaRefreshed`
157
+ - `PluginLoaded` / `PluginUnloaded`
158
+
159
+ The `@hook` decorator tags a method with the target event name. In `on_load`, subscribe your handler to the event class via `ctx.subscribe`:
160
+
161
+ ```python
162
+ from registro_core.events import QueryStarted
163
+ from registro_plugins.api import hook, hook_event, is_hook
164
+ from registro_plugins.context import PluginContext
165
+
166
+
167
+ class QueryLoggerPlugin:
168
+ manifest = PluginManifest(id="query_logger", name="Query Logger")
169
+
170
+ @hook("query.started")
171
+ async def handle_query_started(self, ev: QueryStarted) -> None:
172
+ # Asynchronously handle query start
173
+ pass
174
+
175
+ def on_load(self, ctx: PluginContext) -> None:
176
+ for name in dir(self):
177
+ fn = getattr(self, name)
178
+ if is_hook(fn) and hook_event(fn) == "query.started":
179
+ ctx.subscribe(QueryStarted, fn)
180
+
181
+ def on_unload(self, ctx: PluginContext) -> None:
182
+ pass
183
+ ```
184
+
185
+ ### Registering Commands and Panels
186
+
187
+ Plugins can contribute actions to the fuzzy command palette (`Ctrl+P`) and dockable panels to the main UI:
188
+
189
+ ```python
190
+ from textual.widgets import Static
191
+ from registro_plugins.api import Command, Panel
192
+ from registro_plugins.context import PluginContext
193
+
194
+
195
+ class AnalyticsPlugin:
196
+ manifest = PluginManifest(id="analytics", name="Analytics")
197
+
198
+ def on_load(self, ctx: PluginContext) -> None:
199
+ # Register a command for the command palette (Ctrl+P)
200
+ async def run_diagnostics(context: PluginContext) -> None:
201
+ context.logger.info("Diagnostics started")
202
+
203
+ ctx.register_command(
204
+ Command(
205
+ id="analytics.diagnostics",
206
+ title="Run Database Diagnostics",
207
+ handler=run_diagnostics,
208
+ category="Analytics",
209
+ )
210
+ )
211
+
212
+ # Register a dockable panel ("left", "right", or "bottom")
213
+ def create_panel(_context: PluginContext) -> Static:
214
+ return Static("★ Analytics Rail Content", id="analytics-panel-content")
215
+
216
+ ctx.register_panel(
217
+ Panel(
218
+ id="analytics.sidebar",
219
+ title="Analytics",
220
+ placement="right",
221
+ factory=create_panel,
222
+ initial_size=30,
223
+ )
224
+ )
225
+
226
+ def on_unload(self, ctx: PluginContext) -> None:
227
+ pass
228
+ ```
229
+
230
+ ### Context & Host Services
231
+
232
+ Each plugin receives an isolated `PluginContext` providing:
233
+ - `ctx.subscribe(event_class, handler)`: Register an async event handler.
234
+ - `ctx.publish(event)`: Publish custom events across the event bus.
235
+ - `ctx.register_command(command)`: Add an action to the fuzzy command palette.
236
+ - `ctx.register_panel(panel)`: Mount a sidebar or bottom panel into the TUI grid.
237
+ - `ctx.get_service(name)`: Access host services (such as `"introspector"`, `"history"`, or `"config"`).
238
+ - `ctx.logger`: Context-bound structured logger (`logger.bind(plugin_id=...)`).
239
+
240
+ ---
241
+
242
+ ## 📥 Submitting a Pull Request
243
+
244
+ 1. Create a logical feature branch: `git checkout -b feature/my-cool-feature`.
245
+ 2. Write tests covering your implementation.
246
+ 3. Verify that `./scripts/check.sh` passes successfully (formatting, linting, type checks, and 84% coverage gate).
247
+ 4. Commit your changes with clear, descriptive commit messages.
248
+ 5. Push to your fork and open a Pull Request.
249
+
250
+ ---
251
+
252
+ Happy coding! 📟
@@ -0,0 +1,11 @@
1
+ # Contributors 👥
2
+
3
+ A huge thank you to everyone who has contributed to **Registro**!
4
+
5
+ ## ✨ Lead Maintainer
6
+
7
+ - **Salvatore Corvaglia** ([@salvatorecorvaglia](https://github.com/salvatorecorvaglia))
8
+
9
+ ## 🌟 Contributors
10
+
11
+ _Want to contribute? Check out [CONTRIBUTING.md](./CONTRIBUTING.md) to get started!_