lakefront 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 Piotr Nowakowski
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,64 @@
1
+ Metadata-Version: 2.4
2
+ Name: lakefront
3
+ Version: 0.1.0
4
+ Summary: Lakehouse Observability Platform
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+ License-File: LICENSE
8
+ Dynamic: license-file
9
+
10
+ # Lakefront
11
+
12
+ Lakehouse Observability Platform
13
+
14
+ ## About
15
+
16
+ Terminal-first tool for exploring and monitoring Parquet datasets.
17
+ Keyboard-driven TUI.
18
+ Powered by DuckDB.
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ pip install lakefront
24
+ ```
25
+
26
+ ## Setup
27
+
28
+ ```bash
29
+ lakefront db init # initialize local database
30
+ lakefront db reset # wipe and reinitialize
31
+ ```
32
+
33
+ State is stored in `~/.config/lakefront/` — two files:
34
+
35
+ ```
36
+ ~/.config/lakefront/
37
+ ├── .db # projects + sources (DuckDB)
38
+ └── .project # active project name
39
+ ```
40
+
41
+ ## Usage
42
+
43
+ ```bash
44
+ lakefront ui # launch TUI
45
+ ```
46
+
47
+ ### TUI keybindings
48
+
49
+ | key | action |
50
+ | ----------- | -------------- |
51
+ | `n` | new project |
52
+ | `d` | delete project |
53
+ | `enter` | open project |
54
+ | `backspace` | go back |
55
+ | `q` | quit |
56
+
57
+ ## Structure
58
+
59
+ ```
60
+ pkg/
61
+ ├── core/ # ProjectManager, Explorer, models
62
+ ├── tui/ # Textual screens and widgets
63
+ └── cli/ # Typer entrypoint
64
+ ```
@@ -0,0 +1,55 @@
1
+ # Lakefront
2
+
3
+ Lakehouse Observability Platform
4
+
5
+ ## About
6
+
7
+ Terminal-first tool for exploring and monitoring Parquet datasets.
8
+ Keyboard-driven TUI.
9
+ Powered by DuckDB.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ pip install lakefront
15
+ ```
16
+
17
+ ## Setup
18
+
19
+ ```bash
20
+ lakefront db init # initialize local database
21
+ lakefront db reset # wipe and reinitialize
22
+ ```
23
+
24
+ State is stored in `~/.config/lakefront/` — two files:
25
+
26
+ ```
27
+ ~/.config/lakefront/
28
+ ├── .db # projects + sources (DuckDB)
29
+ └── .project # active project name
30
+ ```
31
+
32
+ ## Usage
33
+
34
+ ```bash
35
+ lakefront ui # launch TUI
36
+ ```
37
+
38
+ ### TUI keybindings
39
+
40
+ | key | action |
41
+ | ----------- | -------------- |
42
+ | `n` | new project |
43
+ | `d` | delete project |
44
+ | `enter` | open project |
45
+ | `backspace` | go back |
46
+ | `q` | quit |
47
+
48
+ ## Structure
49
+
50
+ ```
51
+ pkg/
52
+ ├── core/ # ProjectManager, Explorer, models
53
+ ├── tui/ # Textual screens and widgets
54
+ └── cli/ # Typer entrypoint
55
+ ```
@@ -0,0 +1,64 @@
1
+ Metadata-Version: 2.4
2
+ Name: lakefront
3
+ Version: 0.1.0
4
+ Summary: Lakehouse Observability Platform
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+ License-File: LICENSE
8
+ Dynamic: license-file
9
+
10
+ # Lakefront
11
+
12
+ Lakehouse Observability Platform
13
+
14
+ ## About
15
+
16
+ Terminal-first tool for exploring and monitoring Parquet datasets.
17
+ Keyboard-driven TUI.
18
+ Powered by DuckDB.
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ pip install lakefront
24
+ ```
25
+
26
+ ## Setup
27
+
28
+ ```bash
29
+ lakefront db init # initialize local database
30
+ lakefront db reset # wipe and reinitialize
31
+ ```
32
+
33
+ State is stored in `~/.config/lakefront/` — two files:
34
+
35
+ ```
36
+ ~/.config/lakefront/
37
+ ├── .db # projects + sources (DuckDB)
38
+ └── .project # active project name
39
+ ```
40
+
41
+ ## Usage
42
+
43
+ ```bash
44
+ lakefront ui # launch TUI
45
+ ```
46
+
47
+ ### TUI keybindings
48
+
49
+ | key | action |
50
+ | ----------- | -------------- |
51
+ | `n` | new project |
52
+ | `d` | delete project |
53
+ | `enter` | open project |
54
+ | `backspace` | go back |
55
+ | `q` | quit |
56
+
57
+ ## Structure
58
+
59
+ ```
60
+ pkg/
61
+ ├── core/ # ProjectManager, Explorer, models
62
+ ├── tui/ # Textual screens and widgets
63
+ └── cli/ # Typer entrypoint
64
+ ```
@@ -0,0 +1,15 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ lakefront.egg-info/PKG-INFO
5
+ lakefront.egg-info/SOURCES.txt
6
+ lakefront.egg-info/dependency_links.txt
7
+ lakefront.egg-info/top_level.txt
8
+ pkg/cli/src/lakefront/cli/__init__.py
9
+ pkg/core/src/lakefront/core/__init__.py
10
+ pkg/core/src/lakefront/core/bootstrap.py
11
+ pkg/core/src/lakefront/core/config.py
12
+ pkg/core/src/lakefront/core/explorer.py
13
+ pkg/core/src/lakefront/core/manager.py
14
+ pkg/core/src/lakefront/core/models.py
15
+ pkg/tui/src/lakefront/tui/__init__.py
@@ -0,0 +1 @@
1
+ pkg
@@ -0,0 +1,78 @@
1
+ import typer
2
+ from rich.console import Console
3
+ from rich.table import Table
4
+
5
+ app = typer.Typer()
6
+ projects = typer.Typer()
7
+ app.add_typer(projects, name="projects")
8
+ db_app = typer.Typer()
9
+ app.add_typer(db_app, name="db")
10
+
11
+
12
+ console = Console()
13
+
14
+
15
+ @db_app.command(
16
+ help="Initialize the lakefront database. Run this command before using any other commands."
17
+ )
18
+ def init():
19
+ from lakefront.core import bootstrap
20
+
21
+ console.print("[bold green]Initializing database...[/]")
22
+ bootstrap()
23
+
24
+
25
+ @db_app.command(help="Open a duckdb shell connected to the lakefront database.")
26
+ def shell():
27
+ """Open a duckdb shell connected to the lakefront database.
28
+
29
+ Usage:
30
+ $ lakefront db shell
31
+ $ db: SELECT * FROM projects;
32
+ $ db: show tables;
33
+ $ db: describe projects;
34
+ $ db:.exit
35
+ """
36
+ import subprocess
37
+
38
+ from lakefront.core.config import DB_PATH
39
+
40
+ subprocess.run(["duckdb", str(DB_PATH)], check=True)
41
+
42
+
43
+ @db_app.command()
44
+ def reset():
45
+ from lakefront.core import bootstrap, teardown
46
+
47
+ console.print("[bold green]Re-initializing database...[/]")
48
+ teardown()
49
+ bootstrap()
50
+
51
+
52
+ @projects.command("list")
53
+ def list_projects():
54
+ from lakefront.core import ProjectManager
55
+
56
+ pm = ProjectManager()
57
+ projects = pm.list()
58
+ table = Table(title="Projects", show_header=True, header_style="bold white")
59
+ table.add_column("ID", justify="right", style="white", width=6)
60
+ table.add_column("Name", style="dim", width=30)
61
+ table.add_column("Created At", justify="right", style="dim")
62
+ for p in projects:
63
+ table.add_row(str(p.id), p.name, p.created_at.strftime("%Y-%m-%d %H:%M:%S"))
64
+ console.print(table)
65
+
66
+
67
+ @app.command()
68
+ def version():
69
+ from lakefront.core import get_version
70
+
71
+ console.print(f"[white]lakefront v{get_version()} [/]")
72
+
73
+
74
+ @app.command()
75
+ def ui():
76
+ from lakefront.tui import LakeFrontApp
77
+
78
+ LakeFrontApp().run()
@@ -0,0 +1,12 @@
1
+ from .bootstrap import bootstrap, teardown
2
+ from .explorer import Explorer
3
+ from .manager import ProjectManager
4
+
5
+
6
+ def get_version() -> str:
7
+ import importlib.metadata as pkg
8
+
9
+ return pkg.version("lakefront-core")
10
+
11
+
12
+ __all__ = ["ProjectManager", "Explorer", "bootstrap", "teardown", "get_version"]
@@ -0,0 +1,35 @@
1
+ # polon/core/manager.py
2
+
3
+ from .config import CONFIG_DIR, DB_PATH, PROJECTS_DIR, metadb
4
+
5
+
6
+ def bootstrap():
7
+ CONFIG_DIR.mkdir(parents=True, exist_ok=True)
8
+ PROJECTS_DIR.mkdir(parents=True, exist_ok=True)
9
+
10
+ with metadb() as db:
11
+ db.execute("""
12
+ CREATE SEQUENCE IF NOT EXISTS projects_id_seq;
13
+ CREATE TABLE IF NOT EXISTS projects (
14
+ id INTEGER PRIMARY KEY DEFAULT nextval('projects_id_seq'),
15
+ name TEXT NOT NULL UNIQUE,
16
+ path TEXT NOT NULL,
17
+ created_at TIMESTAMP DEFAULT now()
18
+ );
19
+ CREATE SEQUENCE IF NOT EXISTS conf_id_seq;
20
+ CREATE TABLE IF NOT EXISTS conf (
21
+ id INTEGER PRIMARY KEY DEFAULT nextval('conf_id_seq'),
22
+ key TEXT NOT NULL UNIQUE,
23
+ value TEXT NOT NULL,
24
+ created_at TIMESTAMP DEFAULT now()
25
+ );
26
+ """)
27
+
28
+
29
+ def teardown():
30
+ if not DB_PATH.exists():
31
+ return
32
+ with metadb() as db:
33
+ db.execute("DROP TABLE IF EXISTS projects")
34
+ db.execute("DROP SEQUENCE IF EXISTS projects_id_seq")
35
+ DB_PATH.unlink(missing_ok=True)
@@ -0,0 +1,18 @@
1
+ from pathlib import Path
2
+
3
+ import duckdb
4
+
5
+ CONFIG_DIR = Path("~/.config/lakefront").expanduser()
6
+ DB_PATH = CONFIG_DIR / ".db"
7
+ ACTIVE_PATH = CONFIG_DIR / ".project"
8
+ PROJECTS_DIR = Path("~/.local/share/lakefront/projects").expanduser()
9
+
10
+
11
+ def metadb():
12
+ return duckdb.connect(str(DB_PATH))
13
+
14
+
15
+ def make_project_path(name: str) -> Path:
16
+ path = PROJECTS_DIR / name
17
+ path.mkdir(parents=True, exist_ok=True)
18
+ return path
@@ -0,0 +1,5 @@
1
+ class Explorer:
2
+ def profile(self, path: str) -> dict: ...
3
+ def drift(self, path: str) -> list[dict]: ...
4
+ def preview(self, path: str) -> dict: ...
5
+ def sql(self, path: str, query: str) -> dict: ...
@@ -0,0 +1,30 @@
1
+ from .config import ACTIVE_PATH, DB_PATH
2
+ from .models import ProjectDTO, ProjectRepository
3
+
4
+
5
+ class ProjectManager:
6
+ def __init__(self):
7
+ if not DB_PATH.exists():
8
+ raise RuntimeError("database not initialized. run: lakefront db init")
9
+ self.repo = ProjectRepository()
10
+
11
+ def create(self, name: str) -> ProjectDTO:
12
+ return self.repo.save(name)
13
+
14
+ def list(self) -> list[ProjectDTO]:
15
+ return self.repo.find_all()
16
+
17
+ def delete(self, name: str):
18
+ self.repo.delete(name)
19
+ if self.active() == name:
20
+ ACTIVE_PATH.unlink(missing_ok=True)
21
+
22
+ def switch(self, name: str):
23
+ if not self.repo.find_by_name(name):
24
+ raise ValueError(f"project '{name}' does not exist")
25
+ ACTIVE_PATH.write_text(name)
26
+
27
+ def active(self) -> str | None:
28
+ if ACTIVE_PATH.exists():
29
+ return ACTIVE_PATH.read_text().strip()
30
+ return None
@@ -0,0 +1,50 @@
1
+ from dataclasses import dataclass
2
+ from datetime import datetime
3
+
4
+ from .config import make_project_path, metadb
5
+
6
+
7
+ @dataclass
8
+ class ProjectDTO:
9
+ id: int
10
+ name: str
11
+ path: str
12
+ created_at: datetime
13
+
14
+ @classmethod
15
+ def from_record(cls, record: tuple) -> "ProjectDTO":
16
+ return cls(id=record[0], name=record[1], path=record[2], created_at=record[3])
17
+
18
+
19
+ class ProjectConfig:
20
+ def __init__(self, project_id: int):
21
+ self.project_id = project_id
22
+
23
+
24
+ class ProjectRepository:
25
+ def find_by_name(self, name: str) -> ProjectDTO | None:
26
+ with metadb() as db:
27
+ row = db.execute(
28
+ "SELECT id, name, path, created_at FROM projects WHERE name = ?", [name]
29
+ ).fetchone()
30
+ return ProjectDTO.from_record(row) if row else None
31
+
32
+ def find_all(self) -> list[ProjectDTO]:
33
+ with metadb() as db:
34
+ rows = db.execute(
35
+ "SELECT id, name, path, created_at FROM projects ORDER BY created_at DESC"
36
+ ).fetchall()
37
+ return [ProjectDTO.from_record(row) for row in rows]
38
+
39
+ def save(self, name: str) -> ProjectDTO:
40
+ path = make_project_path(name)
41
+ with metadb() as db:
42
+ row = db.execute(
43
+ "INSERT INTO projects (name, path) VALUES (?, ?) RETURNING id, name, path, created_at",
44
+ [name, str(path)],
45
+ ).fetchone()
46
+ return ProjectDTO.from_record(row)
47
+
48
+ def delete(self, name: str):
49
+ with metadb() as db:
50
+ db.execute("DELETE FROM projects WHERE name = ?", [name])
@@ -0,0 +1,224 @@
1
+ from lakefront.core import ProjectManager
2
+ from textual.app import App, ComposeResult
3
+ from textual.binding import Binding
4
+ from textual.containers import Center, Horizontal, Vertical
5
+ from textual.screen import Screen
6
+ from textual.widgets import (
7
+ Button,
8
+ DataTable,
9
+ Footer,
10
+ Header,
11
+ Input,
12
+ Label,
13
+ ListItem,
14
+ ListView,
15
+ Static,
16
+ )
17
+
18
+ pm = ProjectManager()
19
+
20
+
21
+ class NewProjectScreen(Screen):
22
+ BINDINGS = [
23
+ Binding("escape", "app.pop_screen", "Cancel"),
24
+ ]
25
+
26
+ def compose(self) -> ComposeResult:
27
+ yield Header()
28
+ yield Input(placeholder="project name")
29
+ yield Footer()
30
+
31
+ def on_input_submitted(self, event: Input.Submitted):
32
+ pm.create(event.value)
33
+ self.app.pop_screen()
34
+
35
+
36
+ class ProjectView(Screen):
37
+ BINDINGS = [
38
+ Binding("backspace", "app.pop_screen", "Back"),
39
+ Binding("ctrl+r", "run_sql", "Run SQL"),
40
+ ]
41
+
42
+ CSS = """
43
+ #left { width: 25%; border-right: solid #39ff14 20%; }
44
+ #main { width: 1fr; }
45
+ #right { width: 25%; border-left: solid #39ff14 20%; }
46
+
47
+ #sources-list { height: 1fr; }
48
+ #stats-panel { height: 12; padding: 1; }
49
+
50
+ #sql-input { height: 3; }
51
+ #data-table { height: 1fr; }
52
+
53
+ Label {
54
+ color: #39ff14;
55
+ padding: 0 1;
56
+ }
57
+ """
58
+
59
+ def __init__(self, project_name: str, **kwargs):
60
+ super().__init__(**kwargs)
61
+ self.project_name = project_name
62
+
63
+ def compose(self) -> ComposeResult:
64
+ yield Header()
65
+ with Horizontal():
66
+ with Vertical(id="left"):
67
+ yield Label("sources")
68
+ yield ProjectListView(id="sources-list")
69
+ yield Label("statistics")
70
+ yield Static(id="stats-panel")
71
+ with Vertical(id="main"):
72
+ yield Input(placeholder="SELECT * FROM data LIMIT 100", id="sql-input")
73
+ yield DataTable(id="data-table")
74
+ with Vertical(id="right"):
75
+ yield Label("schema")
76
+ yield DataTable(id="schema-table")
77
+ yield Footer()
78
+
79
+ def on_list_view_selected(self, event): ...
80
+
81
+ def action_run_sql(self): ...
82
+
83
+
84
+ class ConfirmScreen(Screen):
85
+ BINDINGS = [
86
+ Binding("escape", "app.pop_screen", "Cancel"),
87
+ ]
88
+
89
+ def __init__(self, message: str, **kwargs):
90
+ super().__init__(**kwargs)
91
+ self.message = message
92
+
93
+ def compose(self) -> ComposeResult:
94
+ yield Header()
95
+ yield Label(self.message)
96
+ yield Button("Yes", id="yes", variant="error")
97
+ yield Button("No", id="no")
98
+ yield Footer()
99
+
100
+ def on_button_pressed(self, event: Button.Pressed):
101
+ self.dismiss(event.button.id == "yes")
102
+
103
+
104
+ LOGO = r"""
105
+ __________ __
106
+ \______ \ ____ _____ | | __
107
+ | ___// __ \\__ \ | |/ /
108
+ | | \ ___/ / __ \| <
109
+ |____| \___ /____ /__|_ \
110
+ \/ \/ \/
111
+ lakehouse observability platform
112
+ """
113
+
114
+
115
+ class ProjectListView(ListView):
116
+ BINDINGS = [
117
+ Binding("j", "cursor_down", "Down", show=False),
118
+ Binding("k", "cursor_up", "Up", show=False),
119
+ ]
120
+
121
+
122
+ class SplashScreen(Screen):
123
+ CSS = """
124
+ .hidden { display: none; }
125
+ SplashScreen ListView {
126
+ width: 40;
127
+ height: auto;
128
+ align: center middle;
129
+ }
130
+ SplashScreen #center {
131
+ width: 40;
132
+ height: auto;
133
+ align: center middle;
134
+ }
135
+ SplashScreen {
136
+ align: center middle;
137
+ }
138
+
139
+ SplashScreen Label {
140
+ width: 40;
141
+ content-align: center middle;
142
+ }
143
+ #logo {
144
+ color: #39ff14;
145
+ content-align: center middle;
146
+ width: 100%;
147
+ }
148
+
149
+ """
150
+ BINDINGS = [
151
+ Binding("n", "new_project", "New"),
152
+ Binding("d", "delete_project", "Delete"),
153
+ Binding("enter", "open_project", "Open"),
154
+ ]
155
+
156
+ def action_cursor_down(self):
157
+ self.query_one(ListView).action_scroll_down()
158
+
159
+ def action_cursor_up(self):
160
+ self.query_one(ListView).action_scroll_up()
161
+
162
+ def on_mount(self):
163
+ lv = self.query_one(ListView)
164
+ lv.clear()
165
+ for project in pm.list():
166
+ lv.append(ListItem(Label(project.name)))
167
+ lv.focus()
168
+
169
+ def on_screen_resume(self):
170
+ self.on_mount()
171
+
172
+ def compose(self) -> ComposeResult:
173
+ yield Header()
174
+ yield Static(LOGO, id="logo")
175
+ yield Center(
176
+ Label("Projects"),
177
+ ProjectListView(),
178
+ Input(placeholder="delete? y/N", id="confirm", classes="hidden"),
179
+ )
180
+ yield Footer()
181
+
182
+ def on_list_view_selected(self, event: ListView.Selected):
183
+ name = str(event.item.query_one(Label).render())
184
+ self.app.push_screen(ProjectView(name))
185
+
186
+ def action_new_project(self):
187
+ self.app.push_screen(NewProjectScreen())
188
+
189
+ def on_input_submitted(self, event: Input.Submitted):
190
+ confirm = self.query_one("#confirm", Input)
191
+ confirm.add_class("hidden")
192
+ if event.value.lower() == "y" and self._pending_delete:
193
+ pm.delete(self._pending_delete)
194
+ self._pending_delete = None
195
+ self.on_mount() # refresh list
196
+ confirm.clear()
197
+ self.query_one(ListView).focus()
198
+
199
+ def action_delete_project(self):
200
+ lv = self.query_one(ListView)
201
+ if lv.highlighted_child:
202
+ self._pending_delete = str(lv.highlighted_child.query_one(Label).render())
203
+ confirm = self.query_one("#confirm", Input)
204
+ confirm.remove_class("hidden")
205
+ confirm.focus()
206
+
207
+
208
+ class LakeFrontApp(App):
209
+ TITLE = "Lakehouse Observability Platform"
210
+ BINDINGS = [
211
+ Binding("q", "quit", "Quit"),
212
+ ]
213
+ CSS = """
214
+ ListItem > ListItem.--highlight {
215
+ background: #39ff14 20%;
216
+ }
217
+
218
+ ListItem > ListItem.--highlight > Label {
219
+ color: #39ff14;
220
+ }
221
+ """
222
+
223
+ def on_mount(self):
224
+ self.push_screen(SplashScreen())
@@ -0,0 +1,46 @@
1
+ [project]
2
+ name = "lakefront"
3
+ version = "0.1.0"
4
+ description = "Lakehouse Observability Platform"
5
+ readme = "README.md"
6
+ requires-python = ">=3.10"
7
+ dependencies = []
8
+
9
+ [tool.uv.workspace]
10
+ members = [
11
+ "pkg/core",
12
+ "pkg/cli",
13
+ "pkg/tui"
14
+ ]
15
+
16
+ [dependency-groups]
17
+ dev = [
18
+ "deptry>=0.24.0",
19
+ "ipython>=8.38.0",
20
+ "pytest>=9.0.2",
21
+ "ruff>=0.15.1",
22
+ ]
23
+
24
+ [tool.pytest.ini_options]
25
+ pythonpath = "pkg/*/src"
26
+ addopts = "-vv --maxfail=1 --tb=short"
27
+ markers = [
28
+ "integration: tests requiring external services like Docker",
29
+ ]
30
+
31
+ [tool.deptry]
32
+ ignore = [
33
+ "DEP003"
34
+ ]
35
+
36
+ [tool.ruff.lint]
37
+ select = ["I", "TID"]
38
+
39
+ [tool.ruff.lint.isort]
40
+ force-sort-within-sections = false
41
+ known-first-party = ["lop"]
42
+ combine-as-imports = true
43
+
44
+ [tool.ruff.lint.flake8-tidy-imports]
45
+ ban-relative-imports = "parents"
46
+
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+