datasentry-core 0.4.0__tar.gz → 0.5.1__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.
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/PKG-INFO +1 -1
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/pyproject.toml +1 -1
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/__init__.py +1 -1
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/connectors/__init__.py +2 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/connectors/registry.py +3 -1
- datasentry_core-0.5.1/src/datasentry_core/connectors/sqlite.py +87 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/.gitignore +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/README.md +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/connectors/base.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/connectors/csv.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/connectors/duckdb.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/connectors/errors.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/connectors/file_based.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/connectors/jsonl.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/connectors/parquet.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/connectors/spec.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/connectors/xlsx.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/contracts/__init__.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/contracts/exporters.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/__init__.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/base.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/common.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/cross_field.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/cross_table.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/datetime.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/initial/__init__.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/initial/anomaly_ml.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/initial/categorical.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/initial/formula.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/initial/missing.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/initial/numeric.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/initial/textual.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/initial/uniqueness.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/missingness.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/runner.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/safe_eval.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/textual_variants.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/drift/__init__.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/drift/engine.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/engine/__init__.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/engine/base.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/engine/duckdb.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/engine/fusion.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/engine/profiler.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/engine/sql_guard.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/llm/provider.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/models/__init__.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/models/audit.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/models/contract.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/models/detector.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/models/drift.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/models/enums.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/models/evidence.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/models/feedback.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/models/fingerprint.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/models/issue.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/models/llm.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/models/profile.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/models/quality.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/models/repair.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/models/rules.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/models/scan.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/models/validation.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/plugins.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/privacy/redactor.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/repair/__init__.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/repair/engine.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/reporting/__init__.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/reporting/html.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/reporting/interactive.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/reporting/junit.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/reporting/markdown.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/reporting/sarif.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/rules/engine.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/scoring/__init__.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/scoring/engine.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/scoring/gate.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/scoring/quality.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/scoring/weights.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/storage/__init__.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/storage/paths.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/storage/schema.py +0 -0
- {datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/storage/store.py +0 -0
|
@@ -22,6 +22,7 @@ from datasentry_core.connectors.jsonl import JsonlConnector
|
|
|
22
22
|
from datasentry_core.connectors.parquet import ParquetConnector
|
|
23
23
|
from datasentry_core.connectors.registry import ConnectorRegistry, default_registry
|
|
24
24
|
from datasentry_core.connectors.spec import DataSourceSpec, DataSourceType
|
|
25
|
+
from datasentry_core.connectors.sqlite import SqliteConnector
|
|
25
26
|
from datasentry_core.connectors.xlsx import XlsxConnector
|
|
26
27
|
|
|
27
28
|
__all__ = [
|
|
@@ -42,6 +43,7 @@ __all__ = [
|
|
|
42
43
|
"ParquetConnector",
|
|
43
44
|
"SamplingMethod",
|
|
44
45
|
"SchemaInfo",
|
|
46
|
+
"SqliteConnector",
|
|
45
47
|
"UnsafeSqlError",
|
|
46
48
|
"UnsupportedFormatError",
|
|
47
49
|
"XlsxConnector",
|
|
@@ -9,6 +9,7 @@ from datasentry_core.connectors.errors import UnsupportedFormatError
|
|
|
9
9
|
from datasentry_core.connectors.jsonl import JsonlConnector
|
|
10
10
|
from datasentry_core.connectors.parquet import ParquetConnector
|
|
11
11
|
from datasentry_core.connectors.spec import DataSourceSpec
|
|
12
|
+
from datasentry_core.connectors.sqlite import SqliteConnector
|
|
12
13
|
from datasentry_core.connectors.xlsx import XlsxConnector
|
|
13
14
|
|
|
14
15
|
|
|
@@ -45,11 +46,12 @@ class ConnectorRegistry:
|
|
|
45
46
|
|
|
46
47
|
|
|
47
48
|
def default_registry() -> ConnectorRegistry:
|
|
48
|
-
"""默认注册表:文件型连接器 + DuckDB 文件连接器(Step 38
|
|
49
|
+
"""默认注册表:文件型连接器 + DuckDB/SQLite 文件连接器(Step 38/54)。"""
|
|
49
50
|
registry = ConnectorRegistry()
|
|
50
51
|
registry.register(CsvConnector())
|
|
51
52
|
registry.register(ParquetConnector())
|
|
52
53
|
registry.register(JsonlConnector())
|
|
53
54
|
registry.register(XlsxConnector())
|
|
54
55
|
registry.register(DuckdbConnector())
|
|
56
|
+
registry.register(SqliteConnector())
|
|
55
57
|
return registry
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""SQLite 数据源连接器(Step 54:V3 多数据源第一落点)。
|
|
2
|
+
|
|
3
|
+
对 `.db` / `.sqlite` / `.sqlite3` 文件经 DuckDB 的 sqlite 扩展
|
|
4
|
+
(sqlite_scan 表函数)暴露只读 data 视图,复用 FileDataHandle
|
|
5
|
+
共享实现(schema/read_sample/sql_aggregate/count_rows/fingerprint/
|
|
6
|
+
warnings)。表名必填(spec.table_name);路径/表名一律字符串
|
|
7
|
+
字面量转义(防注入)。
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from collections.abc import Iterator
|
|
13
|
+
|
|
14
|
+
import pyarrow as pa
|
|
15
|
+
|
|
16
|
+
from datasentry_core.connectors.base import FrameBatch
|
|
17
|
+
from datasentry_core.connectors.errors import DataSourceNotFoundError
|
|
18
|
+
from datasentry_core.connectors.file_based import FileDataHandle
|
|
19
|
+
from datasentry_core.connectors.spec import DataSourceSpec, DataSourceType
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _sql_string_literal(value: str) -> str:
|
|
23
|
+
return "'" + value.replace("'", "''") + "'"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class SQLiteDataHandle(FileDataHandle):
|
|
27
|
+
"""SQLite 文件表数据句柄(只读,表名必填)。"""
|
|
28
|
+
|
|
29
|
+
def __init__(self, spec: DataSourceSpec) -> None:
|
|
30
|
+
super().__init__(spec)
|
|
31
|
+
if spec.path is None or not spec.path.is_file():
|
|
32
|
+
raise DataSourceNotFoundError(f"sqlite file not found: {spec.path}")
|
|
33
|
+
if spec.table_name is None:
|
|
34
|
+
raise DataSourceNotFoundError("sqlite connector requires table_name")
|
|
35
|
+
self._table_name = spec.table_name
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def table_name(self) -> str | None:
|
|
39
|
+
return self._table_name
|
|
40
|
+
|
|
41
|
+
def _ensure_view(self) -> None:
|
|
42
|
+
if self._view_ready:
|
|
43
|
+
return
|
|
44
|
+
assert self._path is not None
|
|
45
|
+
self._executor.execute_setup("LOAD sqlite")
|
|
46
|
+
self._executor.execute_setup(
|
|
47
|
+
"CREATE OR REPLACE VIEW data AS "
|
|
48
|
+
f"SELECT * FROM sqlite_scan({_sql_string_literal(str(self._path))}, "
|
|
49
|
+
f"{_sql_string_literal(self._table_name)})"
|
|
50
|
+
)
|
|
51
|
+
self._view_ready = True
|
|
52
|
+
|
|
53
|
+
def read_batches(self, batch_size: int = 65536) -> Iterator[FrameBatch]:
|
|
54
|
+
self._check_open()
|
|
55
|
+
if batch_size < 1:
|
|
56
|
+
raise ValueError("batch_size must be >= 1")
|
|
57
|
+
self._ensure_view()
|
|
58
|
+
row_offset = 0
|
|
59
|
+
for idx, batch in enumerate(
|
|
60
|
+
self._executor.execute_stream("SELECT * FROM data", batch_size)
|
|
61
|
+
):
|
|
62
|
+
table = pa.Table.from_batches([batch])
|
|
63
|
+
yield FrameBatch(
|
|
64
|
+
source=self._spec,
|
|
65
|
+
table=table,
|
|
66
|
+
batch_index=idx,
|
|
67
|
+
row_offset=row_offset,
|
|
68
|
+
)
|
|
69
|
+
row_offset += table.num_rows
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class SqliteConnector:
|
|
73
|
+
"""SQLite 文件连接器(Step 54,V3 多数据源第一落点)。"""
|
|
74
|
+
|
|
75
|
+
connector_id = "sqlite"
|
|
76
|
+
display_name = "SQLite"
|
|
77
|
+
|
|
78
|
+
def supports(self, source: DataSourceSpec) -> bool:
|
|
79
|
+
return source.source_type == DataSourceType.SQLITE and source.path is not None
|
|
80
|
+
|
|
81
|
+
def open(self, source: DataSourceSpec) -> SQLiteDataHandle:
|
|
82
|
+
if source.table_name is None:
|
|
83
|
+
raise DataSourceNotFoundError("sqlite connector requires table_name")
|
|
84
|
+
return SQLiteDataHandle(source)
|
|
85
|
+
|
|
86
|
+
def close(self) -> None:
|
|
87
|
+
pass
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/connectors/file_based.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/cross_field.py
RENAMED
|
File without changes
|
{datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/cross_table.py
RENAMED
|
File without changes
|
|
File without changes
|
{datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/initial/__init__.py
RENAMED
|
File without changes
|
{datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/initial/anomaly_ml.py
RENAMED
|
File without changes
|
{datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/initial/categorical.py
RENAMED
|
File without changes
|
{datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/initial/formula.py
RENAMED
|
File without changes
|
{datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/initial/missing.py
RENAMED
|
File without changes
|
{datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/initial/numeric.py
RENAMED
|
File without changes
|
{datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/initial/textual.py
RENAMED
|
File without changes
|
{datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/initial/uniqueness.py
RENAMED
|
File without changes
|
{datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/missingness.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/detectors/textual_variants.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datasentry_core-0.4.0 → datasentry_core-0.5.1}/src/datasentry_core/reporting/interactive.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|