harlequin 2.1.3__tar.gz → 2.2.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 (74) hide show
  1. harlequin-2.2.0/.gitignore +181 -0
  2. {harlequin-2.1.3 → harlequin-2.2.0}/PKG-INFO +39 -43
  3. {harlequin-2.1.3 → harlequin-2.2.0}/README.md +1 -1
  4. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/actions.py +5 -0
  5. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/adapter.py +26 -0
  6. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/app.py +52 -0
  7. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/app.tcss +13 -5
  8. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/cli.py +1 -0
  9. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/components/__init__.py +2 -0
  10. harlequin-2.2.0/harlequin/components/debug_info.py +309 -0
  11. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/components/help_screen.py +7 -6
  12. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin_duckdb/adapter.py +4 -0
  13. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin_sqlite/adapter.py +4 -0
  14. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin_vscode/__init__.py +1 -0
  15. harlequin-2.2.0/pyproject.toml +173 -0
  16. harlequin-2.1.3/pyproject.toml +0 -153
  17. {harlequin-2.1.3 → harlequin-2.2.0}/LICENSE +0 -0
  18. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/__init__.py +0 -0
  19. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/__main__.py +0 -0
  20. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/app_base.py +0 -0
  21. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/autocomplete/__init__.py +0 -0
  22. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/autocomplete/completers.py +0 -0
  23. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/autocomplete/completion.py +0 -0
  24. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/autocomplete/constants.py +0 -0
  25. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/bindings.py +0 -0
  26. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/cache.py +0 -0
  27. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/catalog.py +0 -0
  28. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/catalog_cache.py +0 -0
  29. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/colors.py +0 -0
  30. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/components/code_editor.py +0 -0
  31. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/components/confirm_modal.py +0 -0
  32. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/components/data_catalog/__init__.py +0 -0
  33. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/components/data_catalog/database_tree.py +0 -0
  34. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/components/data_catalog/file_tree.py +0 -0
  35. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/components/data_catalog/s3_tree.py +0 -0
  36. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/components/data_catalog/tree.py +0 -0
  37. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/components/error_modal.py +0 -0
  38. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/components/export_screen.py +0 -0
  39. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/components/help_screen.md +0 -0
  40. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/components/history_screen.py +0 -0
  41. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/components/results_viewer.py +0 -0
  42. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/components/run_query_bar.py +0 -0
  43. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/config.py +0 -0
  44. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/config_wizard.py +0 -0
  45. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/copy_formats.py +0 -0
  46. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/copy_widgets.py +0 -0
  47. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/driver.py +0 -0
  48. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/editor_cache.py +0 -0
  49. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/exception.py +0 -0
  50. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/export.py +0 -0
  51. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/global.tcss +0 -0
  52. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/history.py +0 -0
  53. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/keymap.py +0 -0
  54. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/keys_app.py +0 -0
  55. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/keys_app.tcss +0 -0
  56. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/locale_manager.py +0 -0
  57. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/messages.py +0 -0
  58. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/options.py +0 -0
  59. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/plugins.py +0 -0
  60. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/py.typed +0 -0
  61. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/transaction_mode.py +0 -0
  62. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin/windows_timezone.py +0 -0
  63. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin_duckdb/__init__.py +0 -0
  64. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin_duckdb/catalog.py +0 -0
  65. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin_duckdb/cli_options.py +0 -0
  66. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin_duckdb/completions.py +0 -0
  67. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin_duckdb/interactions.py +0 -0
  68. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin_duckdb/py.typed +0 -0
  69. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin_sqlite/__init__.py +0 -0
  70. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin_sqlite/catalog.py +0 -0
  71. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin_sqlite/cli_options.py +0 -0
  72. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin_sqlite/completions.py +0 -0
  73. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin_sqlite/interactions.py +0 -0
  74. {harlequin-2.1.3/src → harlequin-2.2.0}/harlequin_sqlite/py.typed +0 -0
@@ -0,0 +1,181 @@
1
+ *.db*
2
+ *.db.wal
3
+ *.csv
4
+ *.json
5
+ *.parquet
6
+ *.sql
7
+ *.sqlite
8
+ !tests/data/**/*.db
9
+ !tests/data/**/*.csv
10
+ !tests/data/**/*.json
11
+ !tests/data/**/*.parquet
12
+ !tests/data/**/*.sql
13
+ Pipfile
14
+ snapshot_report.html
15
+ .harlequin.toml
16
+ .profiles
17
+
18
+ # Byte-compiled / optimized / DLL files
19
+ __pycache__/
20
+ *.py[cod]
21
+ *$py.class
22
+
23
+ # C extensions
24
+ *.so
25
+ !tests/data/**/*.so
26
+
27
+ # Distribution / packaging
28
+ .Python
29
+ build/
30
+ develop-eggs/
31
+ dist/
32
+ downloads/
33
+ eggs/
34
+ .eggs/
35
+ lib/
36
+ lib64/
37
+ parts/
38
+ sdist/
39
+ var/
40
+ wheels/
41
+ share/python-wheels/
42
+ *.egg-info/
43
+ .installed.cfg
44
+ *.egg
45
+ MANIFEST
46
+
47
+ # PyInstaller
48
+ # Usually these files are written by a python script from a template
49
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
50
+ *.manifest
51
+ *.spec
52
+
53
+ # Installer logs
54
+ pip-log.txt
55
+ pip-delete-this-directory.txt
56
+
57
+ # Unit test / coverage reports
58
+ htmlcov/
59
+ .tox/
60
+ .nox/
61
+ .coverage
62
+ .coverage.*
63
+ .cache
64
+ nosetests.xml
65
+ coverage.xml
66
+ *.cover
67
+ *.py,cover
68
+ .hypothesis/
69
+ .pytest_cache/
70
+ cover/
71
+
72
+ # Translations
73
+ *.mo
74
+ *.pot
75
+
76
+ # Django stuff:
77
+ *.log
78
+ local_settings.py
79
+ db.sqlite3
80
+ db.sqlite3-journal
81
+
82
+ # Flask stuff:
83
+ instance/
84
+ .webassets-cache
85
+
86
+ # Scrapy stuff:
87
+ .scrapy
88
+
89
+ # Sphinx documentation
90
+ docs/_build/
91
+
92
+ # PyBuilder
93
+ .pybuilder/
94
+ target/
95
+
96
+ # Jupyter Notebook
97
+ .ipynb_checkpoints
98
+
99
+ # IPython
100
+ profile_default/
101
+ ipython_config.py
102
+
103
+ # pyenv
104
+ # For a library or package, you might want to ignore these files since the code is
105
+ # intended to run in multiple environments; otherwise, check them in:
106
+ # .python-version
107
+
108
+ # pipenv
109
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
110
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
111
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
112
+ # install all needed dependencies.
113
+ #Pipfile.lock
114
+
115
+ # poetry
116
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
117
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
118
+ # commonly ignored for libraries.
119
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
120
+ #poetry.lock
121
+
122
+ # pdm
123
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
124
+ #pdm.lock
125
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
126
+ # in version control.
127
+ # https://pdm.fming.dev/#use-with-ide
128
+ .pdm.toml
129
+
130
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
131
+ __pypackages__/
132
+
133
+ # Celery stuff
134
+ celerybeat-schedule
135
+ celerybeat.pid
136
+
137
+ # SageMath parsed files
138
+ *.sage.py
139
+
140
+ # Environments
141
+ .env
142
+ .venv
143
+ env/
144
+ venv/
145
+ ENV/
146
+ env.bak/
147
+ venv.bak/
148
+
149
+ # Spyder project settings
150
+ .spyderproject
151
+ .spyproject
152
+
153
+ # Rope project settings
154
+ .ropeproject
155
+
156
+ # mkdocs documentation
157
+ /site
158
+
159
+ # mypy
160
+ .mypy_cache/
161
+ .dmypy.json
162
+ dmypy.json
163
+
164
+ # ruff
165
+ .ruff_cache
166
+
167
+ # Pyre type checker
168
+ .pyre/
169
+
170
+ # pytype static type analyzer
171
+ .pytype/
172
+
173
+ # Cython debug symbols
174
+ cython_debug/
175
+
176
+ # PyCharm
177
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
178
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
179
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
180
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
181
+ #.idea/
@@ -1,56 +1,53 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: harlequin
3
- Version: 2.1.3
3
+ Version: 2.2.0
4
4
  Summary: The SQL IDE for Your Terminal.
5
- Home-page: https://harlequin.sh
6
- License: MIT
7
- Author: Ted Conbeer
8
- Author-email: tconbeer@users.noreply.github.com
9
- Requires-Python: >=3.9,<3.14.0
10
- Classifier: License :: OSI Approved :: MIT License
11
- Classifier: Programming Language :: Python :: 3
12
- Classifier: Programming Language :: Python :: 3.9
13
- Classifier: Programming Language :: Python :: 3.10
14
- Classifier: Programming Language :: Python :: 3.11
15
- Classifier: Programming Language :: Python :: 3.12
16
- Classifier: Programming Language :: Python :: 3.13
5
+ Project-URL: Homepage, https://harlequin.sh
6
+ Project-URL: Documentation, https://harlequin.sh/docs/getting-started/index
7
+ Project-URL: Repository, https://github.com/tconbeer/harlequin
8
+ Project-URL: Bug Tracker, https://github.com/tconbeer/harlequin/issues
9
+ Project-URL: Changelog, https://github.com/tconbeer/harlequin/blob/main/CHANGELOG.md
10
+ Author-email: Ted Conbeer <tconbeer@users.noreply.github.com>
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: harlequin,ide,sql,tui
14
+ Requires-Python: <3.14,>=3.9
15
+ Requires-Dist: click==8.1.8
16
+ Requires-Dist: duckdb>=0.8.0
17
+ Requires-Dist: importlib-metadata>=8.0; python_version < '3.10'
18
+ Requires-Dist: numpy<2.1.0,>=2.0.0; python_version < '3.10'
19
+ Requires-Dist: numpy<2.3.0,>=2.1.0; python_version >= '3.10'
20
+ Requires-Dist: platformdirs<5.0,>=3.10
21
+ Requires-Dist: pyarrow>=18.1.0; python_version >= '3.12'
22
+ Requires-Dist: questionary==2.0.1
23
+ Requires-Dist: rich-click==1.8.5
24
+ Requires-Dist: shandy-sqlfmt>=0.19.0
25
+ Requires-Dist: textual-fastdatatable==0.12.0
26
+ Requires-Dist: textual-textarea==0.15.0
27
+ Requires-Dist: textual==0.89.1
28
+ Requires-Dist: tomlkit<0.14.0,>=0.12.5
29
+ Requires-Dist: tree-sitter-sql==0.3.7
30
+ Requires-Dist: tree-sitter<0.25.0,>=0.23.0
17
31
  Provides-Extra: adbc
32
+ Requires-Dist: harlequin-adbc; extra == 'adbc'
18
33
  Provides-Extra: bigquery
34
+ Requires-Dist: harlequin-bigquery; extra == 'bigquery'
19
35
  Provides-Extra: cassandra
36
+ Requires-Dist: harlequin-cassandra; extra == 'cassandra'
20
37
  Provides-Extra: databricks
38
+ Requires-Dist: harlequin-databricks; extra == 'databricks'
21
39
  Provides-Extra: mysql
40
+ Requires-Dist: harlequin-mysql; extra == 'mysql'
22
41
  Provides-Extra: nebulagraph
42
+ Requires-Dist: harlequin-nebulagraph; extra == 'nebulagraph'
23
43
  Provides-Extra: odbc
44
+ Requires-Dist: harlequin-odbc; extra == 'odbc'
24
45
  Provides-Extra: postgres
46
+ Requires-Dist: harlequin-postgres; extra == 'postgres'
25
47
  Provides-Extra: s3
48
+ Requires-Dist: boto3==1.34.22; extra == 's3'
26
49
  Provides-Extra: trino
27
- Requires-Dist: boto3 (>=1.34.22,<2.0.0) ; extra == "s3"
28
- Requires-Dist: click (==8.1.8)
29
- Requires-Dist: duckdb (>=0.8.0)
30
- Requires-Dist: harlequin-adbc (>=0.1) ; extra == "adbc"
31
- Requires-Dist: harlequin-bigquery (>=1.0.3) ; extra == "bigquery"
32
- Requires-Dist: harlequin-cassandra (>=0.1.2) ; extra == "cassandra"
33
- Requires-Dist: harlequin-databricks (>=0.5.2) ; extra == "databricks"
34
- Requires-Dist: harlequin-mysql (>=1.0) ; extra == "mysql"
35
- Requires-Dist: harlequin-nebulagraph (>=0.4.1) ; extra == "nebulagraph"
36
- Requires-Dist: harlequin-odbc (>=0.2) ; extra == "odbc"
37
- Requires-Dist: harlequin-postgres (>=1.0) ; extra == "postgres"
38
- Requires-Dist: harlequin-trino (>=0.1) ; extra == "trino"
39
- Requires-Dist: importlib_metadata (>=8.0) ; python_full_version < "3.10.0"
40
- Requires-Dist: numpy (>=2.0.0,<2.1.0) ; python_full_version < "3.10.0"
41
- Requires-Dist: numpy (>=2.1.0,<2.3.0) ; python_full_version >= "3.10.0"
42
- Requires-Dist: platformdirs (>=3.10,<5.0)
43
- Requires-Dist: pyarrow (>=18.1.0) ; python_full_version >= "3.12.0"
44
- Requires-Dist: questionary (>=2.0.1,<3.0.0)
45
- Requires-Dist: rich-click (==1.8.5)
46
- Requires-Dist: shandy-sqlfmt (>=0.19.0)
47
- Requires-Dist: textual (==0.89.1)
48
- Requires-Dist: textual-fastdatatable (==0.12.0)
49
- Requires-Dist: textual-textarea (==0.15.0)
50
- Requires-Dist: tomlkit (>=0.12.5,<0.14.0)
51
- Requires-Dist: tree-sitter (>=0.23.0,<0.25.0)
52
- Requires-Dist: tree-sitter-sql (==0.3.7)
53
- Project-URL: Repository, https://github.com/tconbeer/harlequin
50
+ Requires-Dist: harlequin-trino; extra == 'trino'
54
51
  Description-Content-Type: text/markdown
55
52
 
56
53
  # Harlequin
@@ -100,7 +97,7 @@ Alternatively, if you know what you're doing, after installing Python 3.9 or abo
100
97
  pip install harlequin
101
98
  ```
102
99
 
103
- There is also a [Homebrew formula](https://formulae.brew.sh/formula/harlequin) for Harlequin, although this is maintained by the community and is not as rigorously tested as the Python installations. Note that the formula includes several Harlequin adapter packages (Postgres, MySQL, and ODBC) and their dependencies, which is convenient but increases the application size.
100
+ There is also a [Homebrew formula](https://formulae.brew.sh/formula/harlequin) for Harlequin, although this is maintained by the community and is not as rigorously tested as the Python installations. Note that the formula includes several Harlequin adapter packages (Postgres, MySQL/MariaDB, and ODBC) and their dependencies, which is convenient but increases the application size.
104
101
 
105
102
  ```bash
106
103
  brew install harlequin
@@ -213,4 +210,3 @@ Please consider [sponsoring Harlequin's author](https://github.com/sponsors/tcon
213
210
  Thanks for your interest in Harlequin! Harlequin is primarily maintained by [Ted Conbeer](https://github.com/tconbeer), but he welcomes all contributions!
214
211
 
215
212
  Please see [`CONTRIBUTING.md`](./CONTRIBUTING.md) for more information.
216
-
@@ -45,7 +45,7 @@ Alternatively, if you know what you're doing, after installing Python 3.9 or abo
45
45
  pip install harlequin
46
46
  ```
47
47
 
48
- There is also a [Homebrew formula](https://formulae.brew.sh/formula/harlequin) for Harlequin, although this is maintained by the community and is not as rigorously tested as the Python installations. Note that the formula includes several Harlequin adapter packages (Postgres, MySQL, and ODBC) and their dependencies, which is convenient but increases the application size.
48
+ There is also a [Homebrew formula](https://formulae.brew.sh/formula/harlequin) for Harlequin, although this is maintained by the community and is not as rigorously tested as the Python installations. Note that the formula includes several Harlequin adapter packages (Postgres, MySQL/MariaDB, and ODBC) and their dependencies, which is convenient but increases the application size.
49
49
 
50
50
  ```bash
51
51
  brew install harlequin
@@ -68,6 +68,11 @@ HARLEQUIN_ACTIONS = {
68
68
  target=None,
69
69
  action="toggle_full_screen",
70
70
  ),
71
+ "show_debug_info": Action(
72
+ target=None,
73
+ action="show_debug_info",
74
+ description="Debug Info",
75
+ ),
71
76
  "show_query_history": Action(
72
77
  target=None,
73
78
  action="show_query_history",
@@ -207,12 +207,21 @@ class HarlequinAdapter(ABC):
207
207
  disregard any extra (unexpected) kwargs. They should not rely on the
208
208
  option's default values, as those will not be passed by the CLI when
209
209
  initializing the adapter.
210
+
211
+ Adapters can provide client-side (Harlequin adapter) details using the
212
+ ADAPTER_DETAILS class variable. It is expected to be formatted as markdown.
213
+
214
+ Adapters can also provide server-side (DB driver) details using the
215
+ ADAPTER_DRIVER_DETAILS class variable. It is expected to be formatted
216
+ as markdown.
210
217
  """
211
218
 
212
219
  ADAPTER_OPTIONS: list[HarlequinAdapterOption] | None = None
213
220
  COPY_FORMATS: list[HarlequinCopyFormat] | None = None
214
221
  """DEPRECATED. Adapter Copy formats are now ignored by Harlequin."""
215
222
  IMPLEMENTS_CANCEL = False
223
+ ADAPTER_DETAILS: str | None = None
224
+ ADAPTER_DRIVER_DETAILS: str | None = None
216
225
 
217
226
  @abstractmethod
218
227
  def __init__(self, conn_str: Sequence[str], **options: Any) -> None:
@@ -267,3 +276,20 @@ class HarlequinAdapter(ABC):
267
276
  also provide options for customizing the Export dialog GUI.
268
277
  """
269
278
  return self.COPY_FORMATS is not None
279
+
280
+ @property
281
+ def provides_details(self) -> bool:
282
+ """
283
+ True if the adapter provides an optional description of itself, visible
284
+ on Harlequin's debugging info screen, NOT including
285
+ driver or connection details, which should be ADAPTER_DRIVER_DETAILS.
286
+ """
287
+ return self.ADAPTER_DETAILS is not None
288
+
289
+ @property
290
+ def provides_driver_details(self) -> bool:
291
+ """
292
+ True if the adapter provides an optional description of its driver
293
+ or connection.
294
+ """
295
+ return self.ADAPTER_DRIVER_DETAILS is not None
@@ -57,6 +57,7 @@ from harlequin.catalog_cache import (
57
57
  from harlequin.components import (
58
58
  CodeEditor,
59
59
  DataCatalog,
60
+ DebugInfoScreen,
60
61
  EditorCollection,
61
62
  ErrorModal,
62
63
  ExportScreen,
@@ -69,6 +70,12 @@ from harlequin.components import (
69
70
  from harlequin.components.confirm_modal import ConfirmModal
70
71
  from harlequin.components.data_catalog import ContextMenu
71
72
  from harlequin.components.data_catalog.tree import HarlequinTree
73
+ from harlequin.components.debug_info import AdapterDebugInfo, HarlequinDebugInfo
74
+ from harlequin.config import (
75
+ get_config_for_profile,
76
+ get_highest_priority_existing_config_file,
77
+ load_config,
78
+ )
72
79
  from harlequin.copy_formats import HARLEQUIN_COPY_FORMATS, WINDOWS_COPY_FORMATS
73
80
  from harlequin.driver import HarlequinDriver
74
81
  from harlequin.editor_cache import BufferState, Cache
@@ -182,6 +189,7 @@ class Harlequin(AppBase):
182
189
  def __init__(
183
190
  self,
184
191
  adapter: HarlequinAdapter,
192
+ profile_name: str | None = None,
185
193
  *,
186
194
  keymap_names: Sequence[str] | None = None,
187
195
  user_defined_keymaps: Sequence[HarlequinKeyMap] | None = None,
@@ -201,6 +209,7 @@ class Harlequin(AppBase):
201
209
  watch_css=watch_css,
202
210
  )
203
211
  self.adapter = adapter
212
+ self.profile_name = profile_name
204
213
  self.connection_hash = connection_hash
205
214
  self.history: History | None = None
206
215
  self.show_files = show_files
@@ -279,6 +288,8 @@ class Harlequin(AppBase):
279
288
  and self.editor._has_focus_within
280
289
  ):
281
290
  self.editor.text_input._pause_blink(visible=True)
291
+
292
+ ## TODO: PREVENT DUPLICATE SCREENS HERE.
282
293
  return super().push_screen( # type: ignore[no-any-return,call-overload]
283
294
  screen,
284
295
  callback=callback,
@@ -951,6 +962,47 @@ class Harlequin(AppBase):
951
962
  def action_show_help_screen(self) -> None:
952
963
  self.push_screen(HelpScreen(id="help_screen"))
953
964
 
965
+ def action_show_debug_info(self) -> None:
966
+ SCREEN_ID = "debug_info_screen"
967
+ if self.screen.id == SCREEN_ID:
968
+ # already showing this screen.
969
+ return
970
+
971
+ config_path = get_highest_priority_existing_config_file()
972
+ config = load_config(config_path)
973
+ profile_name = self.profile_name
974
+ active_profile_config, _ = get_config_for_profile(config_path, profile_name)
975
+ active_profile_name = profile_name or config.get("default_profile")
976
+ adapter_options = getattr(self.adapter, "ADAPTER_OPTIONS", None)
977
+ adapter_type = type(self.adapter).__name__
978
+
979
+ harlequin_info = HarlequinDebugInfo(
980
+ active_profile_config=active_profile_config,
981
+ active_profile_name=active_profile_name,
982
+ all_keymaps=list(self.all_keymaps.keys()),
983
+ config=config,
984
+ config_path=config_path,
985
+ keymap_names=self.keymap_names,
986
+ theme=self.theme,
987
+ )
988
+ adapter_info = AdapterDebugInfo(
989
+ adapter_options=adapter_options,
990
+ adapter_type=adapter_type,
991
+ adapter_details=self.adapter.ADAPTER_DETAILS
992
+ if self.adapter.provides_details
993
+ else "No details were provided by adapter.",
994
+ adapter_driver_details=self.adapter.ADAPTER_DRIVER_DETAILS
995
+ if self.adapter.provides_driver_details
996
+ else "No details were provided by the database driver.",
997
+ )
998
+ self.push_screen(
999
+ DebugInfoScreen(
1000
+ harlequin_details=harlequin_info.parse_info(),
1001
+ adapter_details=adapter_info.parse_info(),
1002
+ id=SCREEN_ID,
1003
+ )
1004
+ )
1005
+
954
1006
  def action_toggle_full_screen(self) -> None:
955
1007
  self.full_screen = not self.full_screen
956
1008
 
@@ -418,7 +418,9 @@ HelpScreen {
418
418
  padding: 0;
419
419
  }
420
420
 
421
- #help_outer {
421
+ /* Shared Components */
422
+
423
+ #modal_outer {
422
424
  border: round $border-color-focus;
423
425
  background: $background;
424
426
  margin: 2 4;
@@ -426,22 +428,22 @@ HelpScreen {
426
428
  max-width: 88;
427
429
  }
428
430
 
429
- #help_header {
431
+ #modal_header {
430
432
  dock: top;
431
433
  margin: 0 0 1 0;
432
434
  padding: 0 1;
433
435
  }
434
436
 
435
- #help_inner {
437
+ #modal_inner {
436
438
  border: round $border-color-nofocus;
437
439
  padding: 0 0 0 0;
438
440
  }
439
441
 
440
- #help_info {
442
+ #modal_info {
441
443
  padding: 0 0 0 0;
442
444
  }
443
445
 
444
- #help_footer {
446
+ #modal_footer {
445
447
  dock: bottom;
446
448
  color: $text-muted;
447
449
  margin: 1 0 0 0;
@@ -618,6 +620,12 @@ HistoryScreen .history-screen--error-label {
618
620
  text-style: bold italic;
619
621
  }
620
622
 
623
+ /* DEBUG INFO SCREEN */
624
+
625
+ DebugInfoScreen {
626
+ align: center middle;
627
+ padding: 0;
628
+ }
621
629
 
622
630
  /* ConfirmModal */
623
631
 
@@ -367,6 +367,7 @@ def build_cli() -> click.Command:
367
367
 
368
368
  tui = Harlequin(
369
369
  adapter=adapter_instance,
370
+ profile_name=profile,
370
371
  keymap_names=keymap_names,
371
372
  user_defined_keymaps=user_defined_keymaps,
372
373
  connection_hash=connection_id,
@@ -1,5 +1,6 @@
1
1
  from harlequin.components.code_editor import CodeEditor, EditorCollection
2
2
  from harlequin.components.data_catalog import DataCatalog, HarlequinTree
3
+ from harlequin.components.debug_info import DebugInfoScreen
3
4
  from harlequin.components.error_modal import ErrorModal
4
5
  from harlequin.components.export_screen import ExportScreen, export_callback
5
6
  from harlequin.components.help_screen import HelpScreen
@@ -15,6 +16,7 @@ __all__ = [
15
16
  "export_callback",
16
17
  "HelpScreen",
17
18
  "ResultsTable",
19
+ "DebugInfoScreen",
18
20
  "ResultsViewer",
19
21
  "RunQueryBar",
20
22
  "DataCatalog",