david8-duckdb 0.1.0b1__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,29 @@
1
+ Metadata-Version: 2.4
2
+ Name: david8_duckdb
3
+ Version: 0.1.0b1
4
+ Summary: SQL query builder. david8 duckdb dielect
5
+ Author-email: Danila Ganchar <danila.ganchar@gmail.com>
6
+ Maintainer-email: Danila Ganchar <danila.ganchar@gmail.com>
7
+ Project-URL: Homepage, https://github.com/d-ganchar/david8_duckdb
8
+ Project-URL: Changelog, https://github.com/d-ganchar/david8_duckdb/releases
9
+ Project-URL: Issues, https://github.com/d-ganchar/david8_duckdb/issues
10
+ Project-URL: CI, https://github.com/d-ganchar/david8_duckdb/actions
11
+ Project-URL: Documentation, https://github.com/d-ganchar/david8_duckdb/wiki
12
+ Project-URL: Source, https://github.com/d-ganchar/david8_duckdb
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Topic :: Software Development :: Libraries
16
+ Classifier: Topic :: Database
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Requires-Python: <3.14,>=3.11
22
+ Description-Content-Type: text/markdown
23
+ Requires-Dist: david8<2.0.0b1,>=1.0.0b1
24
+
25
+ # david8_duckdb
26
+
27
+ `david8_duckdb` is [DuckDb](https://duckdb.org/) dialect for [david8](https://github.com/d-ganchar/david8)
28
+
29
+ See [Wiki](https://github.com/d-ganchar/david8_duckdb/wiki)
@@ -0,0 +1,5 @@
1
+ # david8_duckdb
2
+
3
+ `david8_duckdb` is [DuckDb](https://duckdb.org/) dialect for [david8](https://github.com/d-ganchar/david8)
4
+
5
+ See [Wiki](https://github.com/d-ganchar/david8_duckdb/wiki)
@@ -0,0 +1,10 @@
1
+ from david8.core.base_dialect import BaseDialect as _BaseDialect
2
+ from david8.param_styles import QMarkParamStyle
3
+
4
+ from .core.query_builder import DuckDbQueryBuilder as _QueryBuilder
5
+ from .protocols.query_builder import QueryBuilderProtocol
6
+
7
+
8
+ def get_qb(is_quote_mode: bool = False) -> QueryBuilderProtocol:
9
+ dialect = _BaseDialect(QMarkParamStyle(), is_quote_mode)
10
+ return _QueryBuilder(dialect)
File without changes
@@ -0,0 +1,11 @@
1
+ from david8.core.base_query_builder import BaseQueryBuilder as _BaseQueryBuilder
2
+ from david8.protocols.sql import AliasedProtocol, ExprProtocol, FunctionProtocol
3
+
4
+ from ..protocols.query_builder import QueryBuilderProtocol
5
+ from ..protocols.sql import SelectProtocol
6
+ from .select_query import DuckDbSelect
7
+
8
+
9
+ class DuckDbQueryBuilder(QueryBuilderProtocol, _BaseQueryBuilder):
10
+ def select(self, *args: str | AliasedProtocol | ExprProtocol | FunctionProtocol) -> SelectProtocol:
11
+ return DuckDbSelect(select_columns=args, dialect=self._dialect)
@@ -0,0 +1,49 @@
1
+ import dataclasses
2
+
3
+ from david8.core.base_dql import BaseSelect as _BaseSelect
4
+ from david8.protocols.dialect import DialectProtocol
5
+
6
+ from ..protocols.sql import SelectProtocol
7
+
8
+
9
+ class DuckDbSelect(_BaseSelect, SelectProtocol):
10
+ from_files: tuple[str, tuple[str, ...]] = dataclasses.field(default_factory=tuple)
11
+
12
+ def from_csv(self, *file_names: str) -> 'SelectProtocol':
13
+ self.from_files = ('read_csv', file_names)
14
+ return self
15
+
16
+ def from_json(self, *file_names: str) -> 'SelectProtocol':
17
+ self.from_files = ('read_json', file_names)
18
+ return self
19
+
20
+ def from_json_objects(self, *file_names: str) -> 'SelectProtocol':
21
+ self.from_files = ('read_json_objects', file_names)
22
+ return self
23
+
24
+ def from_ndjson_objects(self, *file_names: str) -> 'SelectProtocol':
25
+ self.from_files = ('read_ndjson_objects', file_names)
26
+ return self
27
+
28
+ def from_json_objects_auto(self, *file_names: str) -> 'SelectProtocol':
29
+ self.from_files = ('read_json_objects_auto', file_names)
30
+ return self
31
+
32
+ def from_parquet(self, *file_names: str) -> 'SelectProtocol':
33
+ self.from_files = ('read_parquet', file_names)
34
+ return self
35
+
36
+ def from_xlsx(self, file_name: str) -> 'SelectProtocol':
37
+ self.from_files = ('read_xlsx', (file_name,))
38
+ return self
39
+
40
+ def _from_to_sql(self, dialect: DialectProtocol) -> str:
41
+ if not self.from_files:
42
+ return super()._from_to_sql(dialect)
43
+
44
+ if len(self.from_files[1]) > 1:
45
+ files = str(list(self.from_files[1]))
46
+ else:
47
+ files = f"'{self.from_files[1][0]}'"
48
+
49
+ return f' FROM {self.from_files[0]}({files})'
@@ -0,0 +1,9 @@
1
+ from david8.protocols.query_builder import QueryBuilderProtocol as _QueryBuilderProtocol
2
+ from david8.protocols.sql import AliasedProtocol, ExprProtocol, FunctionProtocol
3
+
4
+ from ..protocols.sql import SelectProtocol
5
+
6
+
7
+ class QueryBuilderProtocol(_QueryBuilderProtocol):
8
+ def select(self, *args: str | AliasedProtocol | ExprProtocol | FunctionProtocol) -> SelectProtocol:
9
+ pass
@@ -0,0 +1,38 @@
1
+ from david8.protocols.sql import SelectProtocol as _SelectProtocol
2
+
3
+
4
+ class SelectProtocol(_SelectProtocol):
5
+ def from_csv(self, *file_names: str) -> 'SelectProtocol':
6
+ """
7
+ https://duckdb.org/docs/stable/data/csv/reading_faulty_csv_files
8
+ """
9
+
10
+ def from_json(self, *file_names: str) -> 'SelectProtocol':
11
+ """
12
+ https://duckdb.org/docs/stable/data/json/loading_json#the-read_json-function
13
+ """
14
+
15
+ def from_json_objects(self, *file_names: str) -> 'SelectProtocol':
16
+ """
17
+ https://duckdb.org/docs/stable/data/json/loading_json#functions-for-reading-json-objects
18
+ """
19
+
20
+ def from_ndjson_objects(self, *file_names: str) -> 'SelectProtocol':
21
+ """
22
+ https://duckdb.org/docs/stable/data/json/loading_json#functions-for-reading-json-objects
23
+ """
24
+
25
+ def from_json_objects_auto(self, *file_names: str) -> 'SelectProtocol':
26
+ """
27
+ https://duckdb.org/docs/stable/data/json/loading_json#functions-for-reading-json-objects
28
+ """
29
+
30
+ def from_parquet(self, *file_names: str) -> 'SelectProtocol':
31
+ """
32
+ read_parquet(): https://duckdb.org/docs/stable/data/parquet/overview
33
+ """
34
+
35
+ def from_xlsx(self, file_name: str) -> 'SelectProtocol':
36
+ """
37
+ read_xlsx(): https://duckdb.org/docs/stable/core_extensions/excel
38
+ """
@@ -0,0 +1,29 @@
1
+ Metadata-Version: 2.4
2
+ Name: david8_duckdb
3
+ Version: 0.1.0b1
4
+ Summary: SQL query builder. david8 duckdb dielect
5
+ Author-email: Danila Ganchar <danila.ganchar@gmail.com>
6
+ Maintainer-email: Danila Ganchar <danila.ganchar@gmail.com>
7
+ Project-URL: Homepage, https://github.com/d-ganchar/david8_duckdb
8
+ Project-URL: Changelog, https://github.com/d-ganchar/david8_duckdb/releases
9
+ Project-URL: Issues, https://github.com/d-ganchar/david8_duckdb/issues
10
+ Project-URL: CI, https://github.com/d-ganchar/david8_duckdb/actions
11
+ Project-URL: Documentation, https://github.com/d-ganchar/david8_duckdb/wiki
12
+ Project-URL: Source, https://github.com/d-ganchar/david8_duckdb
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Topic :: Software Development :: Libraries
16
+ Classifier: Topic :: Database
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Requires-Python: <3.14,>=3.11
22
+ Description-Content-Type: text/markdown
23
+ Requires-Dist: david8<2.0.0b1,>=1.0.0b1
24
+
25
+ # david8_duckdb
26
+
27
+ `david8_duckdb` is [DuckDb](https://duckdb.org/) dialect for [david8](https://github.com/d-ganchar/david8)
28
+
29
+ See [Wiki](https://github.com/d-ganchar/david8_duckdb/wiki)
@@ -0,0 +1,15 @@
1
+ README.md
2
+ pyproject.toml
3
+ david8_duckdb/__init__.py
4
+ david8_duckdb.egg-info/PKG-INFO
5
+ david8_duckdb.egg-info/SOURCES.txt
6
+ david8_duckdb.egg-info/dependency_links.txt
7
+ david8_duckdb.egg-info/requires.txt
8
+ david8_duckdb.egg-info/top_level.txt
9
+ david8_duckdb/core/__init__.py
10
+ david8_duckdb/core/query_builder.py
11
+ david8_duckdb/core/select_query.py
12
+ david8_duckdb/protocols/__init__.py
13
+ david8_duckdb/protocols/query_builder.py
14
+ david8_duckdb/protocols/sql.py
15
+ tests/test_select.py
@@ -0,0 +1 @@
1
+ david8<2.0.0b1,>=1.0.0b1
@@ -0,0 +1 @@
1
+ david8_duckdb
@@ -0,0 +1,83 @@
1
+ [project]
2
+ name = "david8_duckdb"
3
+ version = "0.1.0b1"
4
+ description = "SQL query builder. david8 duckdb dielect"
5
+ authors = [{name = "Danila Ganchar", email = "danila.ganchar@gmail.com"}]
6
+ maintainers = [{name = "Danila Ganchar", email = "danila.ganchar@gmail.com"}]
7
+ license-files = ["LICENSE"]
8
+ readme = "README.md"
9
+ requires-python = ">=3.11, < 3.14"
10
+ dependencies = [
11
+ "david8>=1.0.0b1,<2.0.0b1"
12
+ ]
13
+
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "Topic :: Software Development :: Libraries",
18
+ "Topic :: Database",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Programming Language :: Python :: 3.13",
23
+ ]
24
+
25
+
26
+ [project.urls]
27
+ Homepage = "https://github.com/d-ganchar/david8_duckdb"
28
+ Changelog = "https://github.com/d-ganchar/david8_duckdb/releases"
29
+ Issues = "https://github.com/d-ganchar/david8_duckdb/issues"
30
+ CI = "https://github.com/d-ganchar/david8_duckdb/actions"
31
+ Documentation = "https://github.com/d-ganchar/david8_duckdb/wiki"
32
+ Source = "https://github.com/d-ganchar/david8_duckdb"
33
+
34
+
35
+ [build-system]
36
+ requires = ["setuptools>=77.0.0"]
37
+ build-backend = "setuptools.build_meta"
38
+
39
+
40
+ [tool.setuptools.packages]
41
+ find = { include = ["david8_duckdb", "david8_duckdb.*"] }
42
+
43
+
44
+ [dependency-groups]
45
+ dev = [
46
+ "ruff",
47
+ "parameterized",
48
+ "pytest",
49
+ "pytest-cov>=7.0.0",
50
+ ]
51
+
52
+ [lint.select]
53
+
54
+ [lint.isort]
55
+ known-third-party = ["pytest"]
56
+ lines-after-imports = 2
57
+ lines-between-types = 1
58
+
59
+
60
+ [tool.ruff]
61
+ line-length = 120
62
+ exclude = [
63
+ ".bzr",
64
+ ".direnv",
65
+ ".eggs",
66
+ "**/.git",
67
+ "__pycache__",
68
+ "tests/fixtures/",
69
+ "benchmarks/"
70
+ ]
71
+
72
+ [tool.ruff.lint]
73
+ select = ["E", "F", "I", "UP", "N", "B", "W"]
74
+
75
+ [tool.pytest.ini_options]
76
+ testpaths = [
77
+ "tests",
78
+ "--color=yes",
79
+ ]
80
+
81
+ addopts = [
82
+
83
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,93 @@
1
+ from parameterized import parameterized
2
+
3
+ from david8_duckdb.protocols.sql import SelectProtocol
4
+ from tests.base_test import BaseTest
5
+
6
+
7
+ class TestSelect(BaseTest):
8
+ @parameterized.expand([
9
+ (
10
+ BaseTest.qb.select('*').from_csv('faulty.csv'),
11
+ "SELECT * FROM read_csv('faulty.csv')",
12
+ ),
13
+ (
14
+ BaseTest.qb.select('*').from_csv('flights1.csv', 'flights2.csv'),
15
+ "SELECT * FROM read_csv(['flights1.csv', 'flights2.csv'])",
16
+ ),
17
+ ])
18
+ def test_from_csv(self, query: SelectProtocol, exp_sql: str):
19
+ self.assertEqual(query.get_sql(), exp_sql)
20
+
21
+ @parameterized.expand([
22
+ (
23
+ BaseTest.qb.select('*').from_json('todos.json'),
24
+ "SELECT * FROM read_json('todos.json')",
25
+ ),
26
+ (
27
+ BaseTest.qb.select('*').from_json('todos1.json', 'todos2.json'),
28
+ "SELECT * FROM read_json(['todos1.json', 'todos2.json'])",
29
+ ),
30
+ ])
31
+ def test_from_json(self, query: SelectProtocol, exp_sql: str):
32
+ self.assertEqual(query.get_sql(), exp_sql)
33
+
34
+ @parameterized.expand([
35
+ (
36
+ BaseTest.qb.select('*').from_json_objects('todos.json'),
37
+ "SELECT * FROM read_json_objects('todos.json')",
38
+ ),
39
+ (
40
+ BaseTest.qb.select('*').from_json_objects('todos1.json', 'todos2.json'),
41
+ "SELECT * FROM read_json_objects(['todos1.json', 'todos2.json'])",
42
+ ),
43
+ ])
44
+ def test_from_json_objects(self, query: SelectProtocol, exp_sql: str):
45
+ self.assertEqual(query.get_sql(), exp_sql)
46
+
47
+ @parameterized.expand([
48
+ (
49
+ BaseTest.qb.select('*').from_ndjson_objects('todos.json'),
50
+ "SELECT * FROM read_ndjson_objects('todos.json')",
51
+ ),
52
+ (
53
+ BaseTest.qb.select('*').from_ndjson_objects('todos1.json', 'todos2.json'),
54
+ "SELECT * FROM read_ndjson_objects(['todos1.json', 'todos2.json'])",
55
+ ),
56
+ ])
57
+ def test_from_ndjson_objects(self, query: SelectProtocol, exp_sql: str):
58
+ self.assertEqual(query.get_sql(), exp_sql)
59
+
60
+ @parameterized.expand([
61
+ (
62
+ BaseTest.qb.select('*').from_json_objects_auto('todos.json'),
63
+ "SELECT * FROM read_json_objects_auto('todos.json')",
64
+ ),
65
+ (
66
+ BaseTest.qb.select('*').from_json_objects_auto('todos1.json', 'todos2.json'),
67
+ "SELECT * FROM read_json_objects_auto(['todos1.json', 'todos2.json'])",
68
+ ),
69
+ ])
70
+ def test_from_json_objects_auto(self, query: SelectProtocol, exp_sql: str):
71
+ self.assertEqual(query.get_sql(), exp_sql)
72
+
73
+ @parameterized.expand([
74
+ (
75
+ BaseTest.qb.select('*').from_parquet('file.parquet'),
76
+ "SELECT * FROM read_parquet('file.parquet')",
77
+ ),
78
+ (
79
+ BaseTest.qb.select('*').from_parquet('file1.parquet', 'file2.parquet'),
80
+ "SELECT * FROM read_parquet(['file1.parquet', 'file2.parquet'])",
81
+ ),
82
+ ])
83
+ def test_from_parquet(self, query: SelectProtocol, exp_sql: str):
84
+ self.assertEqual(query.get_sql(), exp_sql)
85
+
86
+ @parameterized.expand([
87
+ (
88
+ BaseTest.qb.select('*').from_xlsx('test.xlsx'),
89
+ "SELECT * FROM read_xlsx('test.xlsx')",
90
+ ),
91
+ ])
92
+ def test_from_xlsx(self, query: SelectProtocol, exp_sql: str):
93
+ self.assertEqual(query.get_sql(), exp_sql)