pluggle-interface-streamlit 0.1.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 hsnwhte
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,135 @@
1
+ Metadata-Version: 2.4
2
+ Name: pluggle-interface-streamlit
3
+ Version: 0.1.0
4
+ Summary: Browser-based dashboard for Pluggle — run and inspect ETL pipelines interactively, powered by Streamlit.
5
+ Author: hsnwhte
6
+ License: MIT
7
+ Project-URL: Homepage, https://pluggle.org
8
+ Project-URL: Repository, https://github.com/hsnwhte/pluggle-interface-streamlit
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Programming Language :: Python :: 3.14
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Requires-Python: >=3.14
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: pluggle>=0.13.0
16
+ Requires-Dist: streamlit>=1.62
17
+ Provides-Extra: dev
18
+ Requires-Dist: ruff>=0.16; extra == "dev"
19
+ Dynamic: license-file
20
+
21
+ # pluggle-interface-streamlit
22
+
23
+ A browser-based dashboard for [Pluggle](https://pluggle.org) — run and inspect ETL
24
+ pipelines interactively, powered by Streamlit.
25
+
26
+ Pluggle is a plugin-based ETL/sync engine with a CLI and a programmatic API. This
27
+ package adds a third way to drive it: a local web interface where you can configure a
28
+ pipeline, run it, and manage installed transform strategies without touching the command
29
+ line.
30
+
31
+ It is a one-way consumer of Pluggle — Pluggle has no knowledge of this package and does
32
+ not discover it at runtime. Everything goes through Pluggle's declared public interface
33
+ (`pluggle.interfaces.api`), never through its internals.
34
+
35
+ ## Install
36
+
37
+ ```bash
38
+ pip install pluggle-interface-streamlit
39
+ ```
40
+
41
+ Pluggle is pulled in as a dependency. Python 3.14 or newer is required.
42
+
43
+ For local development:
44
+
45
+ ```bash
46
+ git clone https://github.com/hsnwhte/pluggle-interface-streamlit
47
+ cd pluggle-interface-streamlit
48
+ python -m venv .venv && source .venv/bin/activate
49
+ pip install -e ".[dev]"
50
+ ```
51
+
52
+ ## Running
53
+
54
+ ```bash
55
+ streamlit run src/pluggle_interface_streamlit/app.py
56
+ ```
57
+
58
+ The app opens at `http://localhost:8501`.
59
+
60
+ Run this from the project root. The working directory determines where `data/`
61
+ is created and where the theme in `.streamlit/config.toml` is read from.
62
+
63
+ ## Pages
64
+
65
+ **Run** — configure and execute a pipeline. Mirrors the CLI's `run` command:
66
+ source and target type (file, db, api), addresses, table names for database endpoints,
67
+ the transform strategy, and the output format. The target address is prefilled with a
68
+ timestamped path under `data/outputs/` when the target is a file.
69
+
70
+ **Strategies** — browse the curated
71
+ [pluggle-strategies](https://github.com/hsnwhte/pluggle-strategies) catalog, read a
72
+ strategy's README before installing it, install from the catalog or from a local `.py`
73
+ file, and remove installed strategies. The built-in
74
+ `default_v1.0` passthrough strategy cannot be removed.
75
+
76
+ ## Configuration
77
+
78
+ All runtime data — the SQLite store, installed strategies, logs, uploads and pipeline
79
+ outputs — is created under a `data/` folder in the directory you run the app from.
80
+
81
+ Log output is fixed to `data/logs` by this package so that every runtime artifact sits
82
+ in one place; it is not configurable.
83
+
84
+ The remaining Pluggle paths can be overridden with a `.env` file in your working
85
+ directory:
86
+
87
+ ```env
88
+ PLUGGLE_STORE_ADDRESS=sqlite:///data/runtime.sqlite
89
+ PLUGGLE_STRATEGIES_DIR=data/strategies
90
+ ```
91
+
92
+ Pluggle reads these via `os.environ.get(...)` at import time, so no code changes are
93
+ needed.
94
+
95
+ SQLite is the default store and is sufficient here: this is a single-user local tool
96
+ with none of the concurrent-write exposure that would call for PostgreSQL.
97
+
98
+ ### Theme
99
+
100
+ Colours come from `.streamlit/config.toml` in the working directory. Streamlit exposes
101
+ five theme variables; edit `primaryColor` to change the accent used by buttons, selected
102
+ rows, and links.
103
+
104
+ ## Project layout
105
+
106
+ ```
107
+ src/pluggle_interface_streamlit/
108
+ ├── app.py # landing page
109
+ ├── settings.py # package paths (assets, uploads, outputs)
110
+ ├── assets/ # logo and icon
111
+ └── pages/
112
+ ├── 1_Run.py
113
+ └── 2_Strategies.py
114
+ ```
115
+
116
+ `settings.py` distinguishes two roots: `PACKAGE_ROOT` for files shipped with the package
117
+ (assets), and `RUNTIME_ROOT` (`Path.cwd()`) for anything created while running.
118
+ Pluggle's own `settings.py` handles the `mkdir` calls for its directories on import, so
119
+ there is no bootstrap step.
120
+
121
+ ## Scope
122
+
123
+ This package is a generic interface — it runs whatever strategies you have installed and
124
+ makes no assumptions about your data. It is not a hosted service; for a deployed demo of
125
+ Pluggle, see
126
+ [pluggle.org](https://pluggle.org).
127
+
128
+ There are no automated tests. Almost nothing here is more than a Streamlit widget call
129
+ or a thin pass through to `pluggle.interfaces.api`; the engine's own test suite covers
130
+ the logic, and Streamlit's `AppTest` would be brittle against any widget reordering.
131
+ Both pages are verified manually end to end.
132
+
133
+ ## License
134
+
135
+ MIT
@@ -0,0 +1,115 @@
1
+ # pluggle-interface-streamlit
2
+
3
+ A browser-based dashboard for [Pluggle](https://pluggle.org) — run and inspect ETL
4
+ pipelines interactively, powered by Streamlit.
5
+
6
+ Pluggle is a plugin-based ETL/sync engine with a CLI and a programmatic API. This
7
+ package adds a third way to drive it: a local web interface where you can configure a
8
+ pipeline, run it, and manage installed transform strategies without touching the command
9
+ line.
10
+
11
+ It is a one-way consumer of Pluggle — Pluggle has no knowledge of this package and does
12
+ not discover it at runtime. Everything goes through Pluggle's declared public interface
13
+ (`pluggle.interfaces.api`), never through its internals.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ pip install pluggle-interface-streamlit
19
+ ```
20
+
21
+ Pluggle is pulled in as a dependency. Python 3.14 or newer is required.
22
+
23
+ For local development:
24
+
25
+ ```bash
26
+ git clone https://github.com/hsnwhte/pluggle-interface-streamlit
27
+ cd pluggle-interface-streamlit
28
+ python -m venv .venv && source .venv/bin/activate
29
+ pip install -e ".[dev]"
30
+ ```
31
+
32
+ ## Running
33
+
34
+ ```bash
35
+ streamlit run src/pluggle_interface_streamlit/app.py
36
+ ```
37
+
38
+ The app opens at `http://localhost:8501`.
39
+
40
+ Run this from the project root. The working directory determines where `data/`
41
+ is created and where the theme in `.streamlit/config.toml` is read from.
42
+
43
+ ## Pages
44
+
45
+ **Run** — configure and execute a pipeline. Mirrors the CLI's `run` command:
46
+ source and target type (file, db, api), addresses, table names for database endpoints,
47
+ the transform strategy, and the output format. The target address is prefilled with a
48
+ timestamped path under `data/outputs/` when the target is a file.
49
+
50
+ **Strategies** — browse the curated
51
+ [pluggle-strategies](https://github.com/hsnwhte/pluggle-strategies) catalog, read a
52
+ strategy's README before installing it, install from the catalog or from a local `.py`
53
+ file, and remove installed strategies. The built-in
54
+ `default_v1.0` passthrough strategy cannot be removed.
55
+
56
+ ## Configuration
57
+
58
+ All runtime data — the SQLite store, installed strategies, logs, uploads and pipeline
59
+ outputs — is created under a `data/` folder in the directory you run the app from.
60
+
61
+ Log output is fixed to `data/logs` by this package so that every runtime artifact sits
62
+ in one place; it is not configurable.
63
+
64
+ The remaining Pluggle paths can be overridden with a `.env` file in your working
65
+ directory:
66
+
67
+ ```env
68
+ PLUGGLE_STORE_ADDRESS=sqlite:///data/runtime.sqlite
69
+ PLUGGLE_STRATEGIES_DIR=data/strategies
70
+ ```
71
+
72
+ Pluggle reads these via `os.environ.get(...)` at import time, so no code changes are
73
+ needed.
74
+
75
+ SQLite is the default store and is sufficient here: this is a single-user local tool
76
+ with none of the concurrent-write exposure that would call for PostgreSQL.
77
+
78
+ ### Theme
79
+
80
+ Colours come from `.streamlit/config.toml` in the working directory. Streamlit exposes
81
+ five theme variables; edit `primaryColor` to change the accent used by buttons, selected
82
+ rows, and links.
83
+
84
+ ## Project layout
85
+
86
+ ```
87
+ src/pluggle_interface_streamlit/
88
+ ├── app.py # landing page
89
+ ├── settings.py # package paths (assets, uploads, outputs)
90
+ ├── assets/ # logo and icon
91
+ └── pages/
92
+ ├── 1_Run.py
93
+ └── 2_Strategies.py
94
+ ```
95
+
96
+ `settings.py` distinguishes two roots: `PACKAGE_ROOT` for files shipped with the package
97
+ (assets), and `RUNTIME_ROOT` (`Path.cwd()`) for anything created while running.
98
+ Pluggle's own `settings.py` handles the `mkdir` calls for its directories on import, so
99
+ there is no bootstrap step.
100
+
101
+ ## Scope
102
+
103
+ This package is a generic interface — it runs whatever strategies you have installed and
104
+ makes no assumptions about your data. It is not a hosted service; for a deployed demo of
105
+ Pluggle, see
106
+ [pluggle.org](https://pluggle.org).
107
+
108
+ There are no automated tests. Almost nothing here is more than a Streamlit widget call
109
+ or a thin pass through to `pluggle.interfaces.api`; the engine's own test suite covers
110
+ the logic, and Streamlit's `AppTest` would be brittle against any widget reordering.
111
+ Both pages are verified manually end to end.
112
+
113
+ ## License
114
+
115
+ MIT
@@ -0,0 +1,26 @@
1
+ [project]
2
+ name = "pluggle-interface-streamlit"
3
+ version = "0.1.0"
4
+ description = "Browser-based dashboard for Pluggle — run and inspect ETL pipelines interactively, powered by Streamlit."
5
+ readme = "README.md"
6
+ requires-python = ">=3.14"
7
+ license = { text = "MIT" }
8
+ authors = [
9
+ { name = "hsnwhte" }
10
+ ]
11
+ classifiers = [
12
+ "Development Status :: 3 - Alpha",
13
+ "Programming Language :: Python :: 3.14",
14
+ "License :: OSI Approved :: MIT License",
15
+ ]
16
+ dependencies = [
17
+ "pluggle>=0.13.0",
18
+ "streamlit>=1.62",
19
+ ]
20
+
21
+ [project.optional-dependencies]
22
+ dev = ["ruff>=0.16"]
23
+
24
+ [project.urls]
25
+ Homepage = "https://pluggle.org"
26
+ Repository = "https://github.com/hsnwhte/pluggle-interface-streamlit"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
@@ -0,0 +1,23 @@
1
+ from importlib.metadata import version as lib_version
2
+
3
+ import streamlit as st
4
+ from pluggle.interfaces.api import api
5
+
6
+ from pluggle_interface_streamlit.settings import ASSETS_DIR
7
+
8
+ st.set_page_config(page_title="Pluggle", page_icon=str(ASSETS_DIR / "logo.svg"))
9
+ st.logo(str(ASSETS_DIR / "logo.svg"))
10
+
11
+ st.title("Pluggle")
12
+
13
+ st.markdown("""
14
+ Interactive browser interface for the **Pluggle** ETL engine.
15
+
16
+ - **Run** — execute a pipeline from source to target
17
+ - **Strategies** — browse the catalog, install and remove transform strategies
18
+ """)
19
+
20
+ col1, col2, col3 = st.columns(3)
21
+ col1.metric("Installed strategies", len(api.list_installed_strategies()))
22
+ col2.metric("Available in catalog", len(api.get_repo_catalog()))
23
+ col3.metric("Pluggle version", lib_version("pluggle"))
@@ -0,0 +1,76 @@
1
+ from datetime import datetime
2
+
3
+ import streamlit as st
4
+ from pluggle.enums import ContentFormat, PluggleIOType
5
+ from pluggle.exceptions import errors
6
+ from pluggle.interfaces.api import api
7
+ from pluggle.models.dto import InputArgs
8
+ from pydantic import ValidationError
9
+
10
+ from pluggle_interface_streamlit.settings import ASSETS_DIR, OUTPUTS_DIR
11
+
12
+ st.set_page_config(page_title="Pluggle", page_icon=str(ASSETS_DIR / "logo.svg"))
13
+ st.logo(str(ASSETS_DIR / "logo.svg"))
14
+
15
+ st.title("Run Pipeline")
16
+
17
+ source_type = st.radio(
18
+ "Source Type",
19
+ options=list(PluggleIOType),
20
+ format_func=lambda x: x.value,
21
+ horizontal=True,
22
+ )
23
+ source_address = st.text_input(
24
+ "Source Address", placeholder="Enter filepath or URL...", value=""
25
+ )
26
+ source_table = st.text_input("Source Table (database only)")
27
+ installed = api.list_installed_strategies()
28
+ transform_strategy_name = st.selectbox("Transform Strategy", options=installed)
29
+
30
+ target_type = st.radio(
31
+ "Target Type",
32
+ options=list(PluggleIOType),
33
+ format_func=lambda x: x.value,
34
+ horizontal=True,
35
+ )
36
+
37
+ target_table = st.text_input("Target Table (database only)")
38
+ target_format = st.selectbox(
39
+ "Target Format",
40
+ options=list(ContentFormat),
41
+ index=0,
42
+ format_func=lambda x: x.value,
43
+ )
44
+ output_file = str(
45
+ OUTPUTS_DIR
46
+ / f"output_{datetime.now().strftime('%Y%m%d_%H%M%S')}.{target_format.value}"
47
+ )
48
+ target_address = st.text_input(
49
+ "Target Address",
50
+ placeholder="Enter filepath or URL...",
51
+ value=output_file if target_type == PluggleIOType.FILE else "",
52
+ )
53
+
54
+ if st.button("▶ Run", type="primary"):
55
+ try:
56
+ input_args = InputArgs(
57
+ source_type=source_type,
58
+ source_address=source_address,
59
+ source_table=source_table,
60
+ transform_strategy_name=transform_strategy_name,
61
+ target_type=target_type,
62
+ target_address=target_address,
63
+ target_table=target_table,
64
+ target_format=target_format,
65
+ )
66
+ except (ValidationError, AttributeError) as e:
67
+ st.error(f"Invalid input: {e}")
68
+ else:
69
+ try:
70
+ entry_id = api.run(input_args=input_args)
71
+ except errors.PluggleError as e:
72
+ st.error(f"Pipeline failed: {e}")
73
+ except Exception as e:
74
+ st.error(f"Unexpected error: {e}")
75
+ else:
76
+ st.success(f"Success. Entry id: {entry_id}")
@@ -0,0 +1,137 @@
1
+ from pathlib import Path
2
+
3
+ import streamlit as st
4
+ from pluggle.exceptions import errors
5
+ from pluggle.interfaces.api import api
6
+
7
+ from pluggle_interface_streamlit.settings import ASSETS_DIR, UPLOADS_DIR
8
+
9
+ st.set_page_config(page_title="Pluggle", page_icon=str(ASSETS_DIR / "logo.svg"))
10
+ st.logo(str(ASSETS_DIR / "logo.svg"))
11
+
12
+
13
+ @st.dialog("README", width="large")
14
+ def show_readme(name: str, content: str):
15
+ st.subheader(name)
16
+ st.markdown(content)
17
+
18
+
19
+ st.title("Strategies")
20
+ msg = st.session_state.pop("flash", None)
21
+ if msg:
22
+ st.success(msg)
23
+
24
+ installed = api.list_installed_strategies()
25
+
26
+ catalog = api.get_repo_catalog()
27
+ catalog_normalized = [
28
+ {"name": name, "status": "installed" if name in installed else "", **info}
29
+ for name, info in catalog.items()
30
+ ]
31
+
32
+ st.subheader("Available Strategies (Repo)")
33
+ event = st.dataframe(
34
+ catalog_normalized,
35
+ width="stretch",
36
+ on_select="rerun",
37
+ selection_mode="single-row",
38
+ row_height=80,
39
+ column_order=["name", "status", "author", "source_hint", "target_hint", "summary"],
40
+ column_config={
41
+ "name": st.column_config.TextColumn("Strategy Name", width="medium"),
42
+ "status": st.column_config.TextColumn("Status", width="small"),
43
+ "author": st.column_config.TextColumn("Author", width="small"),
44
+ "source_hint": st.column_config.TextColumn("Source", width="small"),
45
+ "target_hint": st.column_config.TextColumn("Target", width="small"),
46
+ "summary": st.column_config.TextColumn("Summary", width="large"),
47
+ },
48
+ hide_index=True,
49
+ )
50
+
51
+
52
+ col_install_from_repo, col_readme, _ = st.columns([1, 1, 3])
53
+
54
+ with col_install_from_repo:
55
+ install_from_repo_clicked = st.button(
56
+ "Install from Repo", type="primary", width="stretch"
57
+ )
58
+ if install_from_repo_clicked:
59
+ if not event.selection.rows:
60
+ st.warning("Select a strategy first.")
61
+ else:
62
+ selected = catalog_normalized[event.selection.rows[0]]
63
+ try:
64
+ new_name = api.install_from_repo(strategy_name=selected["name"])
65
+ except errors.StrategySetupError as e:
66
+ st.error(f"Install failed: {e}")
67
+ else:
68
+ st.session_state.flash = f"Installed: {new_name}"
69
+ st.rerun()
70
+
71
+ with col_readme:
72
+ readme_clicked = st.button("Show README", width="stretch")
73
+ if readme_clicked:
74
+ if not event.selection.rows:
75
+ st.warning("Select a strategy first.")
76
+ else:
77
+ selected = catalog_normalized[event.selection.rows[0]]
78
+ try:
79
+ readme = api.get_readme_from_repo(strategy_name=selected["name"])
80
+ content = readme.read_text(encoding="utf-8")
81
+ show_readme(selected["name"], content)
82
+ except errors.StrategySetupError as e:
83
+ st.error(f"Could not get README: {e}")
84
+
85
+
86
+ st.divider()
87
+
88
+ st.subheader("Install from File")
89
+
90
+
91
+ if "upload_counter" not in st.session_state:
92
+ st.session_state.upload_counter = 0
93
+
94
+ uploaded = st.file_uploader(
95
+ "Strategy File",
96
+ type=["py"],
97
+ key=f"strategy_upload_{st.session_state.upload_counter}",
98
+ accept_multiple_files=False,
99
+ )
100
+ col_install_from_file, _, _ = st.columns([1, 1, 3])
101
+ with col_install_from_file:
102
+ install_from_file_clicked = st.button(
103
+ "Install from File", type="primary", width="stretch"
104
+ )
105
+
106
+ if install_from_file_clicked:
107
+ if uploaded is None:
108
+ st.warning("Select a file first.")
109
+ else:
110
+ target = UPLOADS_DIR / uploaded.name
111
+ target.write_bytes(uploaded.getvalue())
112
+ try:
113
+ new_name = api.install_from_path(file_path=Path(target))
114
+ except errors.StrategySetupError as e:
115
+ st.error(f"Install failed: {e}")
116
+ else:
117
+ st.session_state.flash = f"Installed: {new_name}"
118
+ st.session_state.upload_counter += 1
119
+ st.rerun()
120
+
121
+
122
+ st.divider()
123
+
124
+ st.subheader("Installed Strategies")
125
+ for name in installed:
126
+ col_name, col_action = st.columns([4, 1])
127
+ col_name.text(name)
128
+ if col_action.button(
129
+ "🗑 Remove", key=f"try_remove_{name}", disabled=(name == "default_v1.0")
130
+ ):
131
+ try:
132
+ api.uninstall_strategy(strategy_name=name)
133
+ except errors.StrategySetupError as e:
134
+ st.error(f"Uninstall failed: {e}")
135
+ else:
136
+ st.session_state.flash = f"Removed: {name}"
137
+ st.rerun()
@@ -0,0 +1,12 @@
1
+ from pathlib import Path
2
+
3
+ RUNTIME_ROOT = Path.cwd()
4
+
5
+ PACKAGE_ROOT = Path(__file__).resolve().parent
6
+ ASSETS_DIR = PACKAGE_ROOT / "assets"
7
+
8
+ OUTPUTS_DIR = RUNTIME_ROOT / "data" / "outputs"
9
+ OUTPUTS_DIR.mkdir(parents=True, exist_ok=True)
10
+
11
+ UPLOADS_DIR = RUNTIME_ROOT / "data" / "uploads"
12
+ UPLOADS_DIR.mkdir(parents=True, exist_ok=True)
@@ -0,0 +1,135 @@
1
+ Metadata-Version: 2.4
2
+ Name: pluggle-interface-streamlit
3
+ Version: 0.1.0
4
+ Summary: Browser-based dashboard for Pluggle — run and inspect ETL pipelines interactively, powered by Streamlit.
5
+ Author: hsnwhte
6
+ License: MIT
7
+ Project-URL: Homepage, https://pluggle.org
8
+ Project-URL: Repository, https://github.com/hsnwhte/pluggle-interface-streamlit
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Programming Language :: Python :: 3.14
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Requires-Python: >=3.14
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: pluggle>=0.13.0
16
+ Requires-Dist: streamlit>=1.62
17
+ Provides-Extra: dev
18
+ Requires-Dist: ruff>=0.16; extra == "dev"
19
+ Dynamic: license-file
20
+
21
+ # pluggle-interface-streamlit
22
+
23
+ A browser-based dashboard for [Pluggle](https://pluggle.org) — run and inspect ETL
24
+ pipelines interactively, powered by Streamlit.
25
+
26
+ Pluggle is a plugin-based ETL/sync engine with a CLI and a programmatic API. This
27
+ package adds a third way to drive it: a local web interface where you can configure a
28
+ pipeline, run it, and manage installed transform strategies without touching the command
29
+ line.
30
+
31
+ It is a one-way consumer of Pluggle — Pluggle has no knowledge of this package and does
32
+ not discover it at runtime. Everything goes through Pluggle's declared public interface
33
+ (`pluggle.interfaces.api`), never through its internals.
34
+
35
+ ## Install
36
+
37
+ ```bash
38
+ pip install pluggle-interface-streamlit
39
+ ```
40
+
41
+ Pluggle is pulled in as a dependency. Python 3.14 or newer is required.
42
+
43
+ For local development:
44
+
45
+ ```bash
46
+ git clone https://github.com/hsnwhte/pluggle-interface-streamlit
47
+ cd pluggle-interface-streamlit
48
+ python -m venv .venv && source .venv/bin/activate
49
+ pip install -e ".[dev]"
50
+ ```
51
+
52
+ ## Running
53
+
54
+ ```bash
55
+ streamlit run src/pluggle_interface_streamlit/app.py
56
+ ```
57
+
58
+ The app opens at `http://localhost:8501`.
59
+
60
+ Run this from the project root. The working directory determines where `data/`
61
+ is created and where the theme in `.streamlit/config.toml` is read from.
62
+
63
+ ## Pages
64
+
65
+ **Run** — configure and execute a pipeline. Mirrors the CLI's `run` command:
66
+ source and target type (file, db, api), addresses, table names for database endpoints,
67
+ the transform strategy, and the output format. The target address is prefilled with a
68
+ timestamped path under `data/outputs/` when the target is a file.
69
+
70
+ **Strategies** — browse the curated
71
+ [pluggle-strategies](https://github.com/hsnwhte/pluggle-strategies) catalog, read a
72
+ strategy's README before installing it, install from the catalog or from a local `.py`
73
+ file, and remove installed strategies. The built-in
74
+ `default_v1.0` passthrough strategy cannot be removed.
75
+
76
+ ## Configuration
77
+
78
+ All runtime data — the SQLite store, installed strategies, logs, uploads and pipeline
79
+ outputs — is created under a `data/` folder in the directory you run the app from.
80
+
81
+ Log output is fixed to `data/logs` by this package so that every runtime artifact sits
82
+ in one place; it is not configurable.
83
+
84
+ The remaining Pluggle paths can be overridden with a `.env` file in your working
85
+ directory:
86
+
87
+ ```env
88
+ PLUGGLE_STORE_ADDRESS=sqlite:///data/runtime.sqlite
89
+ PLUGGLE_STRATEGIES_DIR=data/strategies
90
+ ```
91
+
92
+ Pluggle reads these via `os.environ.get(...)` at import time, so no code changes are
93
+ needed.
94
+
95
+ SQLite is the default store and is sufficient here: this is a single-user local tool
96
+ with none of the concurrent-write exposure that would call for PostgreSQL.
97
+
98
+ ### Theme
99
+
100
+ Colours come from `.streamlit/config.toml` in the working directory. Streamlit exposes
101
+ five theme variables; edit `primaryColor` to change the accent used by buttons, selected
102
+ rows, and links.
103
+
104
+ ## Project layout
105
+
106
+ ```
107
+ src/pluggle_interface_streamlit/
108
+ ├── app.py # landing page
109
+ ├── settings.py # package paths (assets, uploads, outputs)
110
+ ├── assets/ # logo and icon
111
+ └── pages/
112
+ ├── 1_Run.py
113
+ └── 2_Strategies.py
114
+ ```
115
+
116
+ `settings.py` distinguishes two roots: `PACKAGE_ROOT` for files shipped with the package
117
+ (assets), and `RUNTIME_ROOT` (`Path.cwd()`) for anything created while running.
118
+ Pluggle's own `settings.py` handles the `mkdir` calls for its directories on import, so
119
+ there is no bootstrap step.
120
+
121
+ ## Scope
122
+
123
+ This package is a generic interface — it runs whatever strategies you have installed and
124
+ makes no assumptions about your data. It is not a hosted service; for a deployed demo of
125
+ Pluggle, see
126
+ [pluggle.org](https://pluggle.org).
127
+
128
+ There are no automated tests. Almost nothing here is more than a Streamlit widget call
129
+ or a thin pass through to `pluggle.interfaces.api`; the engine's own test suite covers
130
+ the logic, and Streamlit's `AppTest` would be brittle against any widget reordering.
131
+ Both pages are verified manually end to end.
132
+
133
+ ## License
134
+
135
+ MIT
@@ -0,0 +1,14 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ src/__init__.py
5
+ src/pluggle_interface_streamlit/__init__.py
6
+ src/pluggle_interface_streamlit/app.py
7
+ src/pluggle_interface_streamlit/settings.py
8
+ src/pluggle_interface_streamlit.egg-info/PKG-INFO
9
+ src/pluggle_interface_streamlit.egg-info/SOURCES.txt
10
+ src/pluggle_interface_streamlit.egg-info/dependency_links.txt
11
+ src/pluggle_interface_streamlit.egg-info/requires.txt
12
+ src/pluggle_interface_streamlit.egg-info/top_level.txt
13
+ src/pluggle_interface_streamlit/pages/1_Run.py
14
+ src/pluggle_interface_streamlit/pages/2_Strategies.py
@@ -0,0 +1,5 @@
1
+ pluggle>=0.13.0
2
+ streamlit>=1.62
3
+
4
+ [dev]
5
+ ruff>=0.16
@@ -0,0 +1,2 @@
1
+ __init__
2
+ pluggle_interface_streamlit