plsqlwks 0.1.4__tar.gz → 0.1.6__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.
- plsqlwks-0.1.6/MANIFEST.in +8 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/PKG-INFO +234 -11
- plsqlwks-0.1.6/PLUGINS.md +320 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/README.md +231 -10
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/__init__.py +1 -1
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/config/__init__.py +4 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/config/loader.py +18 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/config/models.py +13 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/config/settings.py +42 -1
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/db/execution.py +3 -9
- plsqlwks-0.1.6/plsqlwks/exporting.py +147 -0
- plsqlwks-0.1.6/plsqlwks/html_exporting.py +142 -0
- plsqlwks-0.1.6/plsqlwks/plugins/__init__.py +28 -0
- plsqlwks-0.1.6/plsqlwks/plugins/_result_export.py +162 -0
- plsqlwks-0.1.6/plsqlwks/plugins/api.py +122 -0
- plsqlwks-0.1.6/plsqlwks/plugins/csv_export.py +128 -0
- plsqlwks-0.1.6/plsqlwks/plugins/html_export.py +128 -0
- plsqlwks-0.1.6/plsqlwks/plugins/loader.py +181 -0
- plsqlwks-0.1.6/plsqlwks/plugins/xlsx_export.py +151 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/app.py +48 -8
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/app_input.py +35 -3
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/app_results.py +8 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/constants.py +3 -3
- plsqlwks-0.1.6/plsqlwks/ui/plugin_host.py +183 -0
- plsqlwks-0.1.6/plsqlwks/xlsx_exporting.py +435 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks.egg-info/PKG-INFO +234 -11
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks.egg-info/SOURCES.txt +29 -1
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks.egg-info/requires.txt +3 -0
- plsqlwks-0.1.6/plugin-requirements/csv-export/requirements.txt +1 -0
- plsqlwks-0.1.6/plugin-requirements/html-export/requirements.txt +1 -0
- plsqlwks-0.1.6/plugin-requirements/xlsx-export/requirements.txt +2 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/pyproject.toml +3 -0
- plsqlwks-0.1.6/pytest.ini +8 -0
- plsqlwks-0.1.6/rchar.py +151 -0
- plsqlwks-0.1.6/requirements.txt +1 -0
- plsqlwks-0.1.6/tests/conftest.py +149 -0
- plsqlwks-0.1.6/tests/fixtures/config_exports.txt +56 -0
- plsqlwks-0.1.6/tests/fixtures/ui_exports.txt +459 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/tests/test_config_workspace.py +197 -1
- plsqlwks-0.1.6/tests/test_csv_export_plugin.py +396 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/tests/test_db_helpers.py +30 -0
- plsqlwks-0.1.6/tests/test_exporting.py +276 -0
- plsqlwks-0.1.6/tests/test_html_export_plugin.py +739 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/tests/test_packaging.py +150 -7
- plsqlwks-0.1.6/tests/test_plugins.py +311 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/tests/test_ui_flows.py +24 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/tests/test_ui_keys.py +178 -1
- plsqlwks-0.1.6/tests/test_ui_plugins.py +907 -0
- plsqlwks-0.1.6/tests/test_xlsx_export_plugin.py +1139 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/license.txt +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/__main__.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/config/paths.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/config/session.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/db/__init__.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/db/editing.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/db/explain.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/db/health.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/db/metadata.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/db/models.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/db/session.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/db/sql_analysis.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/db/transactions.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/sqlbinds.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/sqlsplit.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/__init__.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/app_db.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/app_editor.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/app_files.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/app_render.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/app_tabs_browser.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/browser.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/buffer.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/clipboard.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/commands.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/completion.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/db_worker.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/display.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/errors.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/help.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/keys.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/menu.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/results.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/sql.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/state.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/ui/syntax.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks/workspace.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks.egg-info/dependency_links.txt +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks.egg-info/entry_points.txt +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/plsqlwks.egg-info/top_level.txt +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/setup.cfg +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/tests/test_db_editing.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/tests/test_db_worker.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/tests/test_oracle_integration.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/tests/test_pty_keys.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/tests/test_rchar.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/tests/test_sqlbinds.py +0 -0
- {plsqlwks-0.1.4 → plsqlwks-0.1.6}/tests/test_sqlsplit.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plsqlwks
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.6
|
|
4
4
|
Summary: An ncurses SQL and PL/SQL workspace for Oracle databases.
|
|
5
5
|
License-Expression: LicenseRef-plsqlwks-Donationware
|
|
6
6
|
Project-URL: Repository, https://gitlab.com/unununu/plsqlwks
|
|
@@ -13,6 +13,8 @@ Requires-Python: >=3.10
|
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: license.txt
|
|
15
15
|
Requires-Dist: oracledb>=2.0
|
|
16
|
+
Provides-Extra: xlsx
|
|
17
|
+
Requires-Dist: openpyxl>=3.1; extra == "xlsx"
|
|
16
18
|
Provides-Extra: dev
|
|
17
19
|
Requires-Dist: build>=1.2; extra == "dev"
|
|
18
20
|
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
@@ -74,9 +76,6 @@ python3 -m pip install -e '.[dev]'
|
|
|
74
76
|
|
|
75
77
|
`oracledb` is the only runtime dependency. Supporting functionality uses the Python standard library.
|
|
76
78
|
|
|
77
|
-
See the [release checklist](https://gitlab.com/unununu/plsqlwks/-/blob/main/RELEASING.md)
|
|
78
|
-
for the quality, packaging, and GitLab release process.
|
|
79
|
-
|
|
80
79
|
For a regular local install, use:
|
|
81
80
|
|
|
82
81
|
```bash
|
|
@@ -90,11 +89,32 @@ python3 -m pytest -q
|
|
|
90
89
|
python3 -m ruff check .
|
|
91
90
|
```
|
|
92
91
|
|
|
92
|
+
Plugin API and built-in plugin tests are optional and are not part of the
|
|
93
|
+
default core test run. Run them with either opt-in form:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
PLSQLWKS_TEST_PLUGINS=1 python3 -m pytest -q
|
|
97
|
+
python3 -m pytest -q -m plugin
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The CSV and HTML export plugins have no additional dependencies. XLSX export
|
|
101
|
+
uses the optional `openpyxl` package, kept out of the base PLSQLWKS runtime.
|
|
102
|
+
Install a distribution with XLSX support through the standard extra:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
python3 -m pip install 'plsqlwks[xlsx]'
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
For an editable development checkout, install the development and XLSX extras
|
|
109
|
+
together with `python3 -m pip install -e '.[dev,xlsx]'`. The repository also
|
|
110
|
+
retains `plugin-requirements/xlsx-export/requirements.txt` as a compatible
|
|
111
|
+
fallback for existing checkout automation.
|
|
112
|
+
|
|
93
113
|
Oracle integration tests require the connection environment variables shown
|
|
94
114
|
above and an accessible password file. Enable every test group with:
|
|
95
115
|
|
|
96
116
|
```bash
|
|
97
|
-
PLSQLWKS_TEST_ORACLE=1 PLSQLWKS_TEST_PTY=1 PLSQLWKS_TEST_SLOW=1 \
|
|
117
|
+
PLSQLWKS_TEST_ORACLE=1 PLSQLWKS_TEST_PLUGINS=1 PLSQLWKS_TEST_PTY=1 PLSQLWKS_TEST_SLOW=1 \
|
|
98
118
|
python3 -m pytest -q -rs
|
|
99
119
|
```
|
|
100
120
|
|
|
@@ -172,9 +192,9 @@ After a successful quit, plsqlwks records the open file-backed tabs, active tab,
|
|
|
172
192
|
| `F8` | Toggle result grid / row-detail output |
|
|
173
193
|
| `F9` | Show/focus/hide schema browser |
|
|
174
194
|
| `F12` | Choose autocommit or manual transaction mode |
|
|
175
|
-
| `Ctrl-Up` / `Ctrl-Down` | Scroll the focused pane or visible DBMS_OUTPUT |
|
|
195
|
+
| `Ctrl-Up` / `Ctrl-Down` | Scroll the focused pane or visible DBMS_OUTPUT by one line |
|
|
176
196
|
| `Ctrl-W` | Close current file tab |
|
|
177
|
-
| `Ctrl-PageUp` / `Ctrl-PageDown` |
|
|
197
|
+
| `Ctrl-PageUp` / `Ctrl-PageDown` | Scroll focused results by one page; otherwise switch file tabs |
|
|
178
198
|
| `Alt-1`..`Alt-9` | Jump to visible file tab |
|
|
179
199
|
| `Ctrl-Q` | Quit |
|
|
180
200
|
| `Ctrl-C` while running | Interrupt the active database operation |
|
|
@@ -200,7 +220,7 @@ After a successful quit, plsqlwks records the open file-backed tabs, active tab,
|
|
|
200
220
|
| `Delete` | Delete at the cursor |
|
|
201
221
|
| `Ctrl-Backspace` / `Ctrl-Delete` | Delete the previous/next word |
|
|
202
222
|
| `Enter` | Insert a new line |
|
|
203
|
-
| `Tab` | Focus the
|
|
223
|
+
| `Tab` | Focus the results or DBMS_OUTPUT pane |
|
|
204
224
|
| `Shift-Tab` | Autocomplete keywords, schema objects, and columns |
|
|
205
225
|
| `F2` / `Ctrl-S` | Save buffer |
|
|
206
226
|
| `F3` / `Ctrl-O` | Open file |
|
|
@@ -302,6 +322,152 @@ bytes and include a truncation marker with the full size. Truncated LOB cells
|
|
|
302
322
|
cannot be edited safely. Schema-browser DDL is always read in full.
|
|
303
323
|
`F7` cycles a grid fullscreen view that starts with the table header on the first terminal line and uses the last line for data, an editor-only fullscreen view, and a split layout with 2/3 editor and 1/3 data grid.
|
|
304
324
|
|
|
325
|
+
To export the active table, use one of these command paths:
|
|
326
|
+
|
|
327
|
+
- `Alt-O -> Results -> Export loaded rows to CSV`
|
|
328
|
+
- `Alt-O -> Results -> Export loaded rows to HTML`
|
|
329
|
+
- `Alt-O -> Results -> Export loaded rows to XLSX`
|
|
330
|
+
|
|
331
|
+
All three built-in Plugin API commands write the columns and exactly the rows
|
|
332
|
+
currently loaded in the grid; they never fetch additional result pages.
|
|
333
|
+
Relative names and the timestamped default name are resolved under the active
|
|
334
|
+
workspace's `results/` directory; absolute paths are also accepted, and an
|
|
335
|
+
existing file requires confirmation before replacement. Commit or cancel an
|
|
336
|
+
active insert draft before exporting so its temporary row cannot be included.
|
|
337
|
+
Each enabled export remains available in read-only mode because it does not
|
|
338
|
+
execute SQL or change a transaction.
|
|
339
|
+
|
|
340
|
+
The bundled exporters can be enabled independently in the active `config.ini`:
|
|
341
|
+
|
|
342
|
+
```ini
|
|
343
|
+
[plugin.csv-export]
|
|
344
|
+
enabled = yes
|
|
345
|
+
|
|
346
|
+
[plugin.html-export]
|
|
347
|
+
enabled = yes
|
|
348
|
+
|
|
349
|
+
[plugin.xlsx-export]
|
|
350
|
+
enabled = yes
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
Set an exporter's `enabled` value to `no` to omit its command from the
|
|
354
|
+
**Results** menu. A missing or malformed value defaults to enabled so existing
|
|
355
|
+
configurations keep all three commands. These switches affect only the bundled
|
|
356
|
+
exporters, not installed entry-point plugins, and take effect after restarting
|
|
357
|
+
PLSQLWKS.
|
|
358
|
+
|
|
359
|
+
The HTML command writes a standalone UTF-8 HTML5 document with column headings
|
|
360
|
+
and table rows, followed by the loaded-row count and any additional-row notice.
|
|
361
|
+
The result title is used only as browser-tab document metadata, not as a visible
|
|
362
|
+
heading. Document titles, column headers, and cell values are escaped as
|
|
363
|
+
untrusted text. The document contains a static embedded stylesheet, no
|
|
364
|
+
JavaScript, and no external resources. It reports when more rows are available
|
|
365
|
+
in PLSQLWKS but does not fetch them, and it does not open a browser after export.
|
|
366
|
+
|
|
367
|
+
The XLSX command writes one `Query result` worksheet with a header row and the
|
|
368
|
+
currently loaded display rows. The header row is frozen by default so it stays
|
|
369
|
+
visible while scrolling. Genuine source numbers become native Excel
|
|
370
|
+
numeric cells when they fit Excel's range and 15-significant-digit precision;
|
|
371
|
+
fixed-point scale such as `10.50` is preserved. Numeric-looking character data
|
|
372
|
+
and unsafe-precision numbers remain exact text and can still receive Excel's
|
|
373
|
+
number-as-text warning. Headers and other values, including text beginning with
|
|
374
|
+
`=`, `+`, `-`, or `@`, remain literal strings and are never interpreted as
|
|
375
|
+
spreadsheet formulas. The workbook contains no macros, external links, or
|
|
376
|
+
fetched continuation rows and is not opened after export. XLSX support is
|
|
377
|
+
optional and obtains `openpyxl>=3.1` from the standard `plsqlwks[xlsx]` extra;
|
|
378
|
+
the repository plugin requirements file remains a source-checkout fallback.
|
|
379
|
+
Each column uses the larger of its bold column name or widest data value,
|
|
380
|
+
estimated with Calibri 11-compatible proportional glyph widths, clamped from 3
|
|
381
|
+
through 60 units, and given a 17-pixel fit margin. Wrapping remains based on
|
|
382
|
+
logical visual length: values over 60 visual units or containing explicit line
|
|
383
|
+
breaks are wrapped.
|
|
384
|
+
|
|
385
|
+
The HTML plugin accepts three plugin-owned environment settings. They are
|
|
386
|
+
captured when PLSQLWKS loads the plugin:
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
PLSQLWKS_HTML_EXPORT_NULL_VALUE="(null)"
|
|
390
|
+
PLSQLWKS_HTML_EXPORT_THEME="dark"
|
|
391
|
+
PLSQLWKS_HTML_EXPORT_DATE_FORMAT="%d.%m.%Y"
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
`PLSQLWKS_HTML_EXPORT_NULL_VALUE` replaces the exact `<NULL>` grid display
|
|
395
|
+
token and defaults to empty; set it to `<NULL>` or another marker to keep NULL
|
|
396
|
+
values visible. `PLSQLWKS_HTML_EXPORT_THEME` is `bright` (the default) or
|
|
397
|
+
`dark`; both select only bundled static CSS, and printing uses a readable
|
|
398
|
+
bright palette. `PLSQLWKS_HTML_EXPORT_DATE_FORMAT` is empty by default and
|
|
399
|
+
otherwise uses Python `strftime` syntax with the same conservative ISO-display
|
|
400
|
+
matching described for CSV below. These settings affect only generated HTML
|
|
401
|
+
and do not expand Plugin API v1.
|
|
402
|
+
|
|
403
|
+
The XLSX plugin has equivalent plugin-owned environment settings, captured when
|
|
404
|
+
PLSQLWKS loads it:
|
|
405
|
+
|
|
406
|
+
```bash
|
|
407
|
+
PLSQLWKS_XLSX_EXPORT_NULL_VALUE="(null)"
|
|
408
|
+
PLSQLWKS_XLSX_EXPORT_THEME="dark"
|
|
409
|
+
PLSQLWKS_XLSX_EXPORT_DATE_FORMAT="%d.%m.%Y"
|
|
410
|
+
PLSQLWKS_XLSX_EXPORT_AUTO_FILTER="no"
|
|
411
|
+
PLSQLWKS_XLSX_EXPORT_AUTO_WIDTH="no"
|
|
412
|
+
PLSQLWKS_XLSX_EXPORT_FREEZE_TOP_ROW="no"
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
`PLSQLWKS_XLSX_EXPORT_NULL_VALUE` replaces the exact `<NULL>` display token and
|
|
416
|
+
defaults to empty; set it to `<NULL>` or another marker to keep NULL values
|
|
417
|
+
visible. `PLSQLWKS_XLSX_EXPORT_THEME` selects the bundled `bright` (default) or
|
|
418
|
+
`dark` cell styles. `PLSQLWKS_XLSX_EXPORT_DATE_FORMAT` is empty by default and
|
|
419
|
+
otherwise applies Python `strftime` directives to the same strict ISO-shaped
|
|
420
|
+
display strings as CSV and HTML. Formatted date and text values remain literal
|
|
421
|
+
spreadsheet strings rather than formulas or typed Excel dates. The
|
|
422
|
+
`PLSQLWKS_XLSX_EXPORT_AUTO_FILTER` setting enables Excel's column filter
|
|
423
|
+
controls by default. It accepts case-insensitive, whitespace-tolerant `1`,
|
|
424
|
+
`yes`, `true`, or `on` to enable them and `0`, `no`, `false`, or `off` to
|
|
425
|
+
disable them; an unset or malformed value falls back to enabled. When enabled,
|
|
426
|
+
the filter range spans exactly the header and currently loaded rows, without
|
|
427
|
+
applying filter criteria or initially hiding any rows.
|
|
428
|
+
`PLSQLWKS_XLSX_EXPORT_AUTO_WIDTH` controls proportional sizing from the widest
|
|
429
|
+
header or loaded data value and uses the same boolean syntax. When filtering is
|
|
430
|
+
enabled, the header candidate includes three extra character units for the filter
|
|
431
|
+
dropdown. Auto-width defaults to enabled; disabling it leaves Excel's default
|
|
432
|
+
column widths while preserving the existing multiline and over-60-unit cell
|
|
433
|
+
wrapping. `PLSQLWKS_XLSX_EXPORT_FREEZE_TOP_ROW` uses the same boolean syntax,
|
|
434
|
+
defaults to enabled, and keeps row 1 visible while scrolling; disabling it
|
|
435
|
+
leaves the worksheet unfrozen. Freezing is independent of filtering and
|
|
436
|
+
automatic widths. These settings belong to the built-in XLSX plugin and do not
|
|
437
|
+
expand Plugin API v1.
|
|
438
|
+
|
|
439
|
+
The built-in CSV export formatting can also be customized in the active
|
|
440
|
+
`config.ini`:
|
|
441
|
+
|
|
442
|
+
```ini
|
|
443
|
+
[plugin.csv-export]
|
|
444
|
+
separator = ,
|
|
445
|
+
null_value =
|
|
446
|
+
date_format =
|
|
447
|
+
protect_formulas = no
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
`separator` must be one character and defaults to a comma. `null_value`
|
|
451
|
+
defaults to empty, replacing the exact `<NULL>` display value with an empty CSV
|
|
452
|
+
field. Set it to `<NULL>` or another marker to retain a visible value.
|
|
453
|
+
`date_format` defaults to empty, which preserves displayed date values. When
|
|
454
|
+
set, it uses Python `strftime` syntax and formats only calendar-valid,
|
|
455
|
+
full-string ISO display values shaped as `YYYY-MM-DD` or
|
|
456
|
+
`YYYY-MM-DD HH:MM:SS[.digits][+/-HH:MM]`, with one to six fractional digits;
|
|
457
|
+
other text is exported unchanged. This deliberately strict heuristic cannot
|
|
458
|
+
identify non-ISO or otherwise preformatted database date text, while matching
|
|
459
|
+
text-column values are indistinguishable from dates and are formatted too.
|
|
460
|
+
|
|
461
|
+
`protect_formulas` defaults to `no`, preserving the exact field content and
|
|
462
|
+
existing CSV representation. Set it to `yes` for CSV files intended to be
|
|
463
|
+
opened by people in spreadsheet software. The protected mode quotes every
|
|
464
|
+
field and prefixes formula-triggering values with a tab, including risky ASCII
|
|
465
|
+
and full-width prefixes and leading control characters. This also makes
|
|
466
|
+
legitimate leading signed values such as `-42` text and leaves the tab in data
|
|
467
|
+
seen by programmatic CSV readers. OWASP notes that no CSV neutralization is
|
|
468
|
+
universal across all spreadsheet applications and save/re-open workflows, so
|
|
469
|
+
validate this opt-in mode with the applications in use.
|
|
470
|
+
|
|
305
471
|
### Schema Browser
|
|
306
472
|
|
|
307
473
|
The `F9` schema browser groups tables, views, procedures, functions, packages, triggers, sequences, indexes, and private synonyms from the current schema. Type while the browser is focused to filter object names with a case-insensitive substring match; groups without matches are hidden and matching groups expand automatically without changing their saved expansion state.
|
|
@@ -347,8 +513,65 @@ currently be loaded from it.
|
|
|
347
513
|
workspace/
|
|
348
514
|
sql/ saved SQL files
|
|
349
515
|
plsql/ saved PL/SQL files
|
|
350
|
-
results/
|
|
516
|
+
results/ CSV, HTML, XLSX, and other result output
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
The first launch creates the workspace folders and starter SQL/PLSQL files.
|
|
520
|
+
|
|
521
|
+
## Plugin API
|
|
522
|
+
|
|
523
|
+
Plugin API version 1 is a deliberately small, command-only extension point.
|
|
524
|
+
See [PLUGINS.md](PLUGINS.md) for the focused plugin author and testing guide.
|
|
525
|
+
PLSQLWKS uses that same API for its built-in loaded-row CSV, HTML, and XLSX
|
|
526
|
+
exporters; adding formats requires no direct App integration or public API
|
|
527
|
+
expansion.
|
|
528
|
+
Installed Python packages can add commands to the `Alt-O` menu through the
|
|
529
|
+
standard `plsqlwks.plugins` entry-point group:
|
|
530
|
+
|
|
531
|
+
```toml
|
|
532
|
+
[project.entry-points."plsqlwks.plugins"]
|
|
533
|
+
example = "example_package.plugin:create_plugin"
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
A minimal plugin factory is:
|
|
537
|
+
|
|
538
|
+
```python
|
|
539
|
+
from plsqlwks.plugins import Plugin, PluginCommand, PluginContext
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
def show_loaded_count(context: PluginContext) -> None:
|
|
543
|
+
result = context.get_active_result()
|
|
544
|
+
count = len(result.rows) if result is not None else 0
|
|
545
|
+
context.set_status(f"{count} row(s) are currently loaded")
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
def create_plugin() -> Plugin:
|
|
549
|
+
return Plugin(
|
|
550
|
+
id="example",
|
|
551
|
+
name="Example commands",
|
|
552
|
+
commands=(
|
|
553
|
+
PluginCommand(
|
|
554
|
+
id="show-loaded-count",
|
|
555
|
+
section="Results",
|
|
556
|
+
title="Show loaded row count",
|
|
557
|
+
handler=show_loaded_count,
|
|
558
|
+
),
|
|
559
|
+
),
|
|
560
|
+
)
|
|
351
561
|
```
|
|
352
562
|
|
|
353
|
-
The
|
|
354
|
-
|
|
563
|
+
The entry point must resolve to a zero-argument callable returning `Plugin`.
|
|
564
|
+
Handlers receive only `PluginContext`: it provides an immutable snapshot of the
|
|
565
|
+
active tabular result, the results directory, insert-draft detection, text and
|
|
566
|
+
overwrite prompts, status updates, and UI error reporting. API v1 does not
|
|
567
|
+
provide database execution, mutable results, the application or UI state,
|
|
568
|
+
keyboard registration, drawing, events, lifecycle hooks, background jobs,
|
|
569
|
+
settings schemas, hot reload, or workspace-local executable plugins.
|
|
570
|
+
|
|
571
|
+
The `[plugin.csv-export]` section and the documented HTML/XLSX environment
|
|
572
|
+
variables configure only their corresponding PLSQLWKS-supplied plugins. Plugin
|
|
573
|
+
API v1 does not provide a generic settings schema or pass these values to
|
|
574
|
+
installed third-party plugins.
|
|
575
|
+
|
|
576
|
+
Installed plugins are trusted, in-process Python code. They are not sandboxed;
|
|
577
|
+
install plugins only from sources you trust.
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
# PLSQLWKS plugins
|
|
2
|
+
|
|
3
|
+
PLSQLWKS Plugin API version 1 is a small, command-only extension point. A plugin
|
|
4
|
+
can add commands to the Alt-O menu and use the limited `PluginContext` passed to
|
|
5
|
+
its command handler. Installed plugins are trusted, in-process Python code. They
|
|
6
|
+
are **not sandboxed** and should be installed only from sources you trust.
|
|
7
|
+
|
|
8
|
+
## API version 1
|
|
9
|
+
|
|
10
|
+
Import supported types and constants from `plsqlwks.plugins`:
|
|
11
|
+
|
|
12
|
+
- `Plugin` describes a plugin and its commands.
|
|
13
|
+
- `PluginCommand` describes one searchable Alt-O menu command.
|
|
14
|
+
- `PluginContext` is the host interface supplied to a command handler.
|
|
15
|
+
- `ResultSnapshot` is an immutable, tuple-based copy of the active table result.
|
|
16
|
+
- `PluginHandler` and `PluginFactory` are the corresponding callable types.
|
|
17
|
+
- `PLUGIN_API_VERSION` and `PLUGIN_ENTRY_POINT_GROUP` identify the contract.
|
|
18
|
+
|
|
19
|
+
`PluginContext` can read the configured results directory, inspect the active
|
|
20
|
+
result snapshot, detect an active result-grid insert draft, open a text prompt,
|
|
21
|
+
request overwrite confirmation, set status text, and report an error through
|
|
22
|
+
the UI. A snapshot contains exactly the display rows loaded when the command
|
|
23
|
+
starts. Its optional `numeric_values` matrix carries only aligned source
|
|
24
|
+
`Decimal`, `int`, and `float` values; other cells are `None`, and legacy
|
|
25
|
+
snapshots may omit the matrix. No raw rows or Oracle handles cross the plugin
|
|
26
|
+
boundary. `has_more` reports that additional rows exist without exposing a
|
|
27
|
+
continuation or a way to fetch them.
|
|
28
|
+
|
|
29
|
+
API v1 does not provide database execution, mutable query results, application
|
|
30
|
+
or UI state, curses drawing, arbitrary shortcuts, event or lifecycle hooks,
|
|
31
|
+
background jobs, generic third-party plugin settings, hot reload, or
|
|
32
|
+
workspace-local Python-file loading.
|
|
33
|
+
|
|
34
|
+
## Registering an installed plugin
|
|
35
|
+
|
|
36
|
+
Expose a zero-argument factory through the `plsqlwks.plugins` entry-point group:
|
|
37
|
+
|
|
38
|
+
```toml
|
|
39
|
+
[project.entry-points."plsqlwks.plugins"]
|
|
40
|
+
example = "example_package.plugin:create_plugin"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
A minimal `example_package/plugin.py` is:
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from plsqlwks.plugins import Plugin, PluginCommand, PluginContext
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def show_results_directory(context: PluginContext) -> None:
|
|
50
|
+
context.set_status(f"Results directory: {context.results_dir}")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def create_plugin() -> Plugin:
|
|
54
|
+
return Plugin(
|
|
55
|
+
id="example",
|
|
56
|
+
name="Example commands",
|
|
57
|
+
commands=(
|
|
58
|
+
PluginCommand(
|
|
59
|
+
id="show-results-directory",
|
|
60
|
+
section="Workspace",
|
|
61
|
+
title="Show results directory",
|
|
62
|
+
handler=show_results_directory,
|
|
63
|
+
keywords="example results directory",
|
|
64
|
+
),
|
|
65
|
+
),
|
|
66
|
+
)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Plugin IDs must match the safe pattern `^[a-z][a-z0-9_.-]*$` and are globally
|
|
70
|
+
unique. Command IDs must be nonempty and unique within a plugin. The API version
|
|
71
|
+
must match the host version. Built-in plugins load first, followed by installed
|
|
72
|
+
entry points in deterministic name order. A broken or incompatible installed
|
|
73
|
+
plugin is skipped and reported as a startup warning rather than preventing
|
|
74
|
+
PLSQLWKS from starting. An ordinary exception raised by a command is reported
|
|
75
|
+
through the UI instead of terminating the application.
|
|
76
|
+
|
|
77
|
+
## Built-in result exports
|
|
78
|
+
|
|
79
|
+
The bundled CSV, HTML, and XLSX commands are normal built-in `Plugin` objects
|
|
80
|
+
using the same API v1 context available to installed plugins. When enabled,
|
|
81
|
+
they are registered in that order in the **Results** section and have no global
|
|
82
|
+
keyboard shortcuts. None is an App method, and adding export formats requires
|
|
83
|
+
no public API expansion.
|
|
84
|
+
|
|
85
|
+
### Exporter availability
|
|
86
|
+
|
|
87
|
+
Each bundled exporter has an independent switch in the active `config.ini`:
|
|
88
|
+
|
|
89
|
+
```ini
|
|
90
|
+
[plugin.csv-export]
|
|
91
|
+
enabled = yes
|
|
92
|
+
|
|
93
|
+
[plugin.html-export]
|
|
94
|
+
enabled = yes
|
|
95
|
+
|
|
96
|
+
[plugin.xlsx-export]
|
|
97
|
+
enabled = yes
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Set `enabled = no` to omit that exporter's command from the **Results** menu.
|
|
101
|
+
A missing or malformed value defaults to enabled. These switches control only
|
|
102
|
+
the bundled exporters; installed entry-point plugins are still discovered and
|
|
103
|
+
loaded normally. Restart PLSQLWKS after changing an availability switch.
|
|
104
|
+
|
|
105
|
+
### CSV export
|
|
106
|
+
|
|
107
|
+
Choose **Alt-O -> Results -> Export loaded rows to CSV** to export the active
|
|
108
|
+
table snapshot. The command proposes a timestamped name in the workspace
|
|
109
|
+
`results/` directory, accepts relative or absolute paths, and asks before
|
|
110
|
+
replacing an existing file. It writes UTF-8 CSV with a header and exactly the
|
|
111
|
+
currently loaded display rows; it never fetches a continuation page. Export is
|
|
112
|
+
available in read-only mode. An active insert draft must first be committed or
|
|
113
|
+
cancelled so its temporary row cannot be exported.
|
|
114
|
+
|
|
115
|
+
The shared CSV writer writes a temporary sibling file and atomically replaces
|
|
116
|
+
the destination after a successful close. A failed write therefore does not
|
|
117
|
+
turn an existing destination into an apparently successful partial export.
|
|
118
|
+
|
|
119
|
+
### HTML export
|
|
120
|
+
|
|
121
|
+
Choose **Alt-O -> Results -> Export loaded rows to HTML** to write a complete,
|
|
122
|
+
standalone UTF-8 HTML5 document for the active table snapshot. The command
|
|
123
|
+
proposes a timestamped `.html` name in the workspace `results/` directory,
|
|
124
|
+
accepts relative or absolute paths, and asks before replacing an existing file.
|
|
125
|
+
It writes the headers and exactly the currently loaded display rows, followed
|
|
126
|
+
by the loaded-row count and a notice when additional rows remain available; the
|
|
127
|
+
plugin never fetches them. The result title is retained only as browser-tab
|
|
128
|
+
document metadata and is not repeated as a visible heading.
|
|
129
|
+
|
|
130
|
+
The result-derived document title, column names, and cell values are escaped as
|
|
131
|
+
untrusted text. The document has a small static embedded stylesheet and no
|
|
132
|
+
JavaScript, event handlers, forms, frames, images, remote URLs, or external
|
|
133
|
+
resources. Cell whitespace remains readable, and wide tables scroll
|
|
134
|
+
horizontally. The command does not launch a browser.
|
|
135
|
+
|
|
136
|
+
Like CSV export, HTML export is available in read-only mode and rejects an
|
|
137
|
+
active insert draft before reading the result or opening a filename prompt. It
|
|
138
|
+
uses the existing context methods for draft detection, immutable snapshot
|
|
139
|
+
access, the results directory, text and overwrite prompts, status updates, and
|
|
140
|
+
error reporting. Atomic replacement keeps a previous destination intact when
|
|
141
|
+
rendering, writing, or replacement fails.
|
|
142
|
+
|
|
143
|
+
### HTML export configuration
|
|
144
|
+
|
|
145
|
+
The built-in HTML plugin captures these optional environment variables when
|
|
146
|
+
PLSQLWKS loads it:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
PLSQLWKS_HTML_EXPORT_NULL_VALUE="(null)"
|
|
150
|
+
PLSQLWKS_HTML_EXPORT_THEME="dark"
|
|
151
|
+
PLSQLWKS_HTML_EXPORT_DATE_FORMAT="%d.%m.%Y"
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
- `PLSQLWKS_HTML_EXPORT_NULL_VALUE` replaces values exactly equal to the grid's
|
|
155
|
+
`<NULL>` display token. It defaults to empty and may be set to `<NULL>` or
|
|
156
|
+
another marker.
|
|
157
|
+
- `PLSQLWKS_HTML_EXPORT_THEME` selects the bundled static `bright` or `dark`
|
|
158
|
+
stylesheet. It defaults to `bright`; print rules remain bright and readable.
|
|
159
|
+
- `PLSQLWKS_HTML_EXPORT_DATE_FORMAT` accepts Python `strftime` directives. It
|
|
160
|
+
defaults to empty, preserving displayed values.
|
|
161
|
+
|
|
162
|
+
The HTML date option uses the same strict ISO-display matching documented for
|
|
163
|
+
CSV: snapshots have display strings, not Oracle type metadata, so invalid or
|
|
164
|
+
nonmatching text is preserved and a text value having the recognized shape is
|
|
165
|
+
indistinguishable from a date. These are settings of the bundled plugin, not a
|
|
166
|
+
generic Plugin API v1 configuration facility. Code embedding the built-in
|
|
167
|
+
factory may instead pass an immutable `HtmlExportOptions` instance explicitly;
|
|
168
|
+
installed third-party entry-point factories remain zero-argument callables.
|
|
169
|
+
|
|
170
|
+
### XLSX export
|
|
171
|
+
|
|
172
|
+
Choose **Alt-O -> Results -> Export loaded rows to XLSX** to write one `Query
|
|
173
|
+
result` worksheet containing a header and exactly the loaded result snapshot.
|
|
174
|
+
The command proposes a timestamped `.xlsx` name in the workspace `results/`
|
|
175
|
+
directory, accepts relative or absolute paths, and asks before replacing an
|
|
176
|
+
existing file. It does not fetch continuation rows, access the database, start
|
|
177
|
+
a subprocess, or open the resulting workbook. It remains available in
|
|
178
|
+
read-only mode and rejects an active insert draft before reading the snapshot
|
|
179
|
+
or prompting.
|
|
180
|
+
|
|
181
|
+
Headers and text cells are explicitly stored as strings. Genuine source
|
|
182
|
+
numbers become native Excel numeric cells only when they are finite, within
|
|
183
|
+
Excel's supported range, and contain at most 15 significant digits. Fixed-point
|
|
184
|
+
formats preserve visible scale such as `10.50`; excess-precision values and
|
|
185
|
+
numeric-looking character data remain exact text and may retain Excel's
|
|
186
|
+
number-as-text warning. Values beginning with `=`, `+`, `-`, or `@` remain
|
|
187
|
+
literal result text and are never interpreted as spreadsheet formulas. The
|
|
188
|
+
workbook contains no macros or external links. Its snapshot title is stored
|
|
189
|
+
only as document metadata; result data remains confined to the single
|
|
190
|
+
worksheet. Each column uses the larger of its bold column name or widest data
|
|
191
|
+
value, estimated with Calibri 11-compatible proportional glyph widths and
|
|
192
|
+
clamped from 3 through 60 units. A 17-pixel fit margin prevents spreadsheet
|
|
193
|
+
font rendering from clipping the last characters. Wrapping remains based on
|
|
194
|
+
logical visual length: values over 60 visual units or containing explicit line
|
|
195
|
+
breaks are wrapped.
|
|
196
|
+
|
|
197
|
+
XLSX generation uses the optional `openpyxl>=3.1` dependency. It is not a base
|
|
198
|
+
PLSQLWKS runtime dependency. Install a distribution with XLSX support through
|
|
199
|
+
the standard extra:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
python3 -m pip install 'plsqlwks[xlsx]'
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
For an editable checkout, use `python3 -m pip install -e '.[xlsx]'`. The
|
|
206
|
+
repository keeps `plugin-requirements/xlsx-export/requirements.txt` as a
|
|
207
|
+
compatible fallback for existing source-checkout automation.
|
|
208
|
+
|
|
209
|
+
If the dependency is unavailable, invoking the command reports a concise XLSX
|
|
210
|
+
export error through the normal Plugin API UI boundary instead of preventing
|
|
211
|
+
PLSQLWKS from starting.
|
|
212
|
+
|
|
213
|
+
### XLSX export configuration
|
|
214
|
+
|
|
215
|
+
The built-in XLSX plugin captures these optional environment variables when
|
|
216
|
+
PLSQLWKS loads it:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
PLSQLWKS_XLSX_EXPORT_NULL_VALUE="(null)"
|
|
220
|
+
PLSQLWKS_XLSX_EXPORT_THEME="dark"
|
|
221
|
+
PLSQLWKS_XLSX_EXPORT_DATE_FORMAT="%d.%m.%Y"
|
|
222
|
+
PLSQLWKS_XLSX_EXPORT_AUTO_FILTER="no"
|
|
223
|
+
PLSQLWKS_XLSX_EXPORT_AUTO_WIDTH="no"
|
|
224
|
+
PLSQLWKS_XLSX_EXPORT_FREEZE_TOP_ROW="no"
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
- `PLSQLWKS_XLSX_EXPORT_NULL_VALUE` replaces values exactly equal to the grid's
|
|
228
|
+
`<NULL>` display token. It defaults to empty and may be set to `<NULL>` or
|
|
229
|
+
another marker.
|
|
230
|
+
- `PLSQLWKS_XLSX_EXPORT_THEME` selects the bundled `bright` or `dark` cell
|
|
231
|
+
styles and defaults to `bright`.
|
|
232
|
+
- `PLSQLWKS_XLSX_EXPORT_DATE_FORMAT` accepts Python `strftime` directives and
|
|
233
|
+
defaults to empty, preserving displayed values.
|
|
234
|
+
- `PLSQLWKS_XLSX_EXPORT_AUTO_FILTER` controls Excel's column filter controls.
|
|
235
|
+
It defaults to enabled and accepts case-insensitive, whitespace-tolerant
|
|
236
|
+
`1`, `yes`, `true`, or `on` to enable them and `0`, `no`, `false`, or `off`
|
|
237
|
+
to disable them. An unset or malformed value falls back to enabled.
|
|
238
|
+
- `PLSQLWKS_XLSX_EXPORT_AUTO_WIDTH` controls proportional column sizing from
|
|
239
|
+
the widest header or loaded data value. With filtering enabled, the header
|
|
240
|
+
candidate includes three extra character units for the filter dropdown. It
|
|
241
|
+
accepts the same boolean values, defaults to enabled, and leaves Excel's
|
|
242
|
+
default column widths when disabled.
|
|
243
|
+
- `PLSQLWKS_XLSX_EXPORT_FREEZE_TOP_ROW` keeps the first-row header visible
|
|
244
|
+
while scrolling. It accepts the same boolean values, defaults to enabled,
|
|
245
|
+
and leaves the worksheet unfrozen when disabled.
|
|
246
|
+
|
|
247
|
+
When enabled, the auto-filter covers exactly the header row and currently
|
|
248
|
+
loaded rows. It applies no filter criteria, so no data rows are initially
|
|
249
|
+
hidden. Disabling automatic widths does not change cell wrapping: multiline
|
|
250
|
+
values and values above the 60-character-unit wrapping threshold still wrap.
|
|
251
|
+
Freezing is independent of the auto-filter and automatic-width settings.
|
|
252
|
+
|
|
253
|
+
NULL and date transformations follow the same display-string limitations as
|
|
254
|
+
CSV and HTML and remain literal spreadsheet strings. Numeric provenance is
|
|
255
|
+
independent of these settings. These variables configure only the bundled XLSX
|
|
256
|
+
plugin and are not a generic Plugin API v1 settings mechanism. Code embedding
|
|
257
|
+
its factory may pass an immutable `XlsxExportOptions` value; installed
|
|
258
|
+
entry-point factories remain zero-argument callables.
|
|
259
|
+
|
|
260
|
+
### CSV export configuration
|
|
261
|
+
|
|
262
|
+
The built-in CSV plugin reads these host-owned formatting settings from the
|
|
263
|
+
active `config.ini`:
|
|
264
|
+
|
|
265
|
+
```ini
|
|
266
|
+
[plugin.csv-export]
|
|
267
|
+
separator = ,
|
|
268
|
+
null_value =
|
|
269
|
+
date_format =
|
|
270
|
+
protect_formulas = no
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
- `separator` is one character and defaults to `,`.
|
|
274
|
+
- `null_value` is written for values that exactly equal the result grid's
|
|
275
|
+
`<NULL>` display token. It defaults to empty and may be set to `<NULL>` or
|
|
276
|
+
another marker.
|
|
277
|
+
- `date_format` uses Python `strftime` directives. It defaults to empty, which
|
|
278
|
+
preserves the displayed value.
|
|
279
|
+
- `protect_formulas` accepts normal INI boolean values and defaults to `no`.
|
|
280
|
+
When enabled, the plugin protects both headers and formatted data fields
|
|
281
|
+
that begin with spreadsheet formula-triggering ASCII, control, or full-width
|
|
282
|
+
characters. It prefixes those values with a tab and quotes every field so
|
|
283
|
+
the tab remains inside its CSV cell. Missing or malformed values fall back
|
|
284
|
+
to `no`.
|
|
285
|
+
|
|
286
|
+
Date formatting is deliberately conservative because Plugin API snapshots
|
|
287
|
+
contain display strings rather than Oracle type metadata. It is applied only
|
|
288
|
+
to valid, full-string ISO display values shaped as `YYYY-MM-DD` or
|
|
289
|
+
`YYYY-MM-DD HH:MM:SS[.digits][+/-HH:MM]`, with one to six fractional digits.
|
|
290
|
+
Invalid dates, ISO values using other shapes, and all nonmatching text remain
|
|
291
|
+
unchanged. A character value with the same valid shape is indistinguishable
|
|
292
|
+
from a date and is formatted too. The directives supported by `strftime` can
|
|
293
|
+
vary slightly by platform.
|
|
294
|
+
|
|
295
|
+
Formula protection is intended for human spreadsheet viewing. It deliberately
|
|
296
|
+
turns leading signed values such as `-42` into text and exposes the added tab
|
|
297
|
+
to programmatic CSV readers. There is no universal neutralization across all
|
|
298
|
+
spreadsheet applications or save/re-open workflows, so use this opt-in mode
|
|
299
|
+
for the target spreadsheet workflow rather than as a lossless round trip.
|
|
300
|
+
|
|
301
|
+
This section configures only the PLSQLWKS-supplied plugin. Plugin API v1 has no
|
|
302
|
+
generic configuration schema and does not expose these settings to installed
|
|
303
|
+
third-party plugins.
|
|
304
|
+
|
|
305
|
+
## Optional plugin tests
|
|
306
|
+
|
|
307
|
+
Plugin-specific tests are excluded from the default core test run. Run them
|
|
308
|
+
explicitly with either:
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
python3 -m pytest -q -m plugin
|
|
312
|
+
PLSQLWKS_TEST_PLUGINS=1 python3 -m pytest -q
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Compatibility manifests for repository plugins remain under
|
|
316
|
+
`plugin-requirements/<plugin-id>/requirements.txt`. The built-in `csv-export`
|
|
317
|
+
and `html-export` plugins have no extra dependencies beyond PLSQLWKS and the
|
|
318
|
+
Python standard library. The built-in `xlsx-export` plugin uses the standard
|
|
319
|
+
`xlsx` extra for `openpyxl>=3.1`; its manifest is retained as a synchronized
|
|
320
|
+
source-checkout fallback.
|