sqlcompose 0.0.4a1__tar.gz → 0.0.4a2__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.
- {sqlcompose-0.0.4a1/src/sqlcompose.egg-info → sqlcompose-0.0.4a2}/PKG-INFO +22 -7
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2}/README.md +19 -5
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2}/pyproject.toml +6 -3
- sqlcompose-0.0.4a2/src/sqlcompose/core/app.py +30 -0
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2}/src/sqlcompose/core/compat.py +31 -0
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2/src/sqlcompose.egg-info}/PKG-INFO +22 -7
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2}/src/sqlcompose.egg-info/requires.txt +1 -0
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2}/tests/test_app.py +18 -1
- sqlcompose-0.0.4a1/src/sqlcompose/core/app.py +0 -25
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2}/LICENSE +0 -0
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2}/setup.cfg +0 -0
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2}/src/sqlcompose/__init__.py +0 -0
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2}/src/sqlcompose/__main__.py +0 -0
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2}/src/sqlcompose/core/circular_dependency_error.py +0 -0
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2}/src/sqlcompose/core/file_not_found_err.py +0 -0
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2}/src/sqlcompose/core/functions.py +0 -0
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2}/src/sqlcompose/core/include.py +0 -0
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2}/src/sqlcompose/py.typed +0 -0
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2}/src/sqlcompose.egg-info/SOURCES.txt +0 -0
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2}/src/sqlcompose.egg-info/dependency_links.txt +0 -0
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2}/src/sqlcompose.egg-info/entry_points.txt +0 -0
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2}/src/sqlcompose.egg-info/top_level.txt +0 -0
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2}/tests/test_compat.py +0 -0
- {sqlcompose-0.0.4a1 → sqlcompose-0.0.4a2}/tests/test_functions.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlcompose
|
|
3
|
-
Version: 0.0.
|
|
4
|
-
Summary: Composition of
|
|
3
|
+
Version: 0.0.4a2
|
|
4
|
+
Summary: Composition of SQL files
|
|
5
5
|
Author-email: Anders Madsen <anders.madsen@alphavue.com>
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: repository, https://github.com/apmadsen/sqlcompose
|
|
@@ -29,6 +29,7 @@ License-File: LICENSE
|
|
|
29
29
|
Provides-Extra: test
|
|
30
30
|
Requires-Dist: pytest>=8.3.0; extra == "test"
|
|
31
31
|
Requires-Dist: pytest-cov>=6.1.0; extra == "test"
|
|
32
|
+
Requires-Dist: pytest-mock>=3.15; extra == "test"
|
|
32
33
|
Dynamic: license-file
|
|
33
34
|
|
|
34
35
|
[](https://github.com/apmadsen/sqlcompose/actions/workflows/python-test.yml)
|
|
@@ -38,19 +39,33 @@ Dynamic: license-file
|
|
|
38
39
|

|
|
39
40
|
[](https://pepy.tech/projects/sqlcompose)
|
|
40
41
|
|
|
41
|
-
# sqlcompose: Composition of
|
|
42
|
-
sqlcompose
|
|
42
|
+
# sqlcompose: Composition of SQL files
|
|
43
|
+
sqlcompose lets you to compose sql files from multiple files by introducing `$INCLUDE` keywords. The SQL output is composed as CTE's or Common Table Expressions.
|
|
44
|
+
|
|
45
|
+
Using composition, you reduce both complexity and duplication of code thus adhering to the DRY principle.
|
|
46
|
+
|
|
47
|
+
### SQL Dialect
|
|
48
|
+
sqlcompose outputs SQL as standard ANSI SQL. Note though, that no validation is done on either the input or the output.
|
|
43
49
|
|
|
44
50
|
## Examples
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
|
|
52
|
+
### 1. Execute the script with the filename as an argument and output to the console:
|
|
53
|
+
```bash
|
|
47
54
|
sqlcompose query.sql
|
|
48
55
|
```
|
|
56
|
+
|
|
57
|
+
### 2. Pipe data into application and output to a file
|
|
58
|
+
```bash
|
|
59
|
+
cat query.sql | sqlcompose > output.sql
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 3. Execute the script with SQL string as argument
|
|
49
63
|
```bash
|
|
50
64
|
sqlcompose 'select * from $INCLUDE(included-query1.sql)'
|
|
51
65
|
```
|
|
66
|
+
> NOTE: Different consoles have different limitations, so you may have to switch from single to double quotes to allow for using the dollar sign.
|
|
52
67
|
|
|
53
|
-
|
|
68
|
+
### 4. Import it in another python application or package
|
|
54
69
|
```python
|
|
55
70
|
from sqlcompose import load, loads
|
|
56
71
|
# method 1 : loading from a file
|
|
@@ -5,19 +5,33 @@
|
|
|
5
5
|

|
|
6
6
|
[](https://pepy.tech/projects/sqlcompose)
|
|
7
7
|
|
|
8
|
-
# sqlcompose: Composition of
|
|
9
|
-
sqlcompose
|
|
8
|
+
# sqlcompose: Composition of SQL files
|
|
9
|
+
sqlcompose lets you to compose sql files from multiple files by introducing `$INCLUDE` keywords. The SQL output is composed as CTE's or Common Table Expressions.
|
|
10
|
+
|
|
11
|
+
Using composition, you reduce both complexity and duplication of code thus adhering to the DRY principle.
|
|
12
|
+
|
|
13
|
+
### SQL Dialect
|
|
14
|
+
sqlcompose outputs SQL as standard ANSI SQL. Note though, that no validation is done on either the input or the output.
|
|
10
15
|
|
|
11
16
|
## Examples
|
|
12
|
-
|
|
13
|
-
|
|
17
|
+
|
|
18
|
+
### 1. Execute the script with the filename as an argument and output to the console:
|
|
19
|
+
```bash
|
|
14
20
|
sqlcompose query.sql
|
|
15
21
|
```
|
|
22
|
+
|
|
23
|
+
### 2. Pipe data into application and output to a file
|
|
24
|
+
```bash
|
|
25
|
+
cat query.sql | sqlcompose > output.sql
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### 3. Execute the script with SQL string as argument
|
|
16
29
|
```bash
|
|
17
30
|
sqlcompose 'select * from $INCLUDE(included-query1.sql)'
|
|
18
31
|
```
|
|
32
|
+
> NOTE: Different consoles have different limitations, so you may have to switch from single to double quotes to allow for using the dollar sign.
|
|
19
33
|
|
|
20
|
-
|
|
34
|
+
### 4. Import it in another python application or package
|
|
21
35
|
```python
|
|
22
36
|
from sqlcompose import load, loads
|
|
23
37
|
# method 1 : loading from a file
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "sqlcompose"
|
|
3
3
|
dynamic = ["version"]
|
|
4
|
-
description = "Composition of
|
|
4
|
+
description = "Composition of SQL files"
|
|
5
5
|
keywords = ["sql", "composition", "windows", "linux"]
|
|
6
6
|
readme = "README.md"
|
|
7
7
|
authors = [
|
|
@@ -28,7 +28,9 @@ classifiers = [
|
|
|
28
28
|
"Topic :: Software Development :: Libraries",
|
|
29
29
|
"Typing :: Typed"
|
|
30
30
|
]
|
|
31
|
-
dependencies = [
|
|
31
|
+
dependencies = [
|
|
32
|
+
|
|
33
|
+
]
|
|
32
34
|
requires-python = ">= 3.10, < 3.15"
|
|
33
35
|
|
|
34
36
|
[project.urls]
|
|
@@ -41,6 +43,7 @@ repository = "https://github.com/apmadsen/sqlcompose"
|
|
|
41
43
|
test = [
|
|
42
44
|
"pytest>=8.3.0",
|
|
43
45
|
"pytest-cov>=6.1.0",
|
|
46
|
+
"pytest-mock>=3.15"
|
|
44
47
|
]
|
|
45
48
|
|
|
46
49
|
[tool.setuptools-git-versioning]
|
|
@@ -48,4 +51,4 @@ enabled = true
|
|
|
48
51
|
|
|
49
52
|
[build-system]
|
|
50
53
|
requires = ["setuptools >= 77.0.3", "setuptools-git-versioning >= 2.1.0"]
|
|
51
|
-
build-backend = "setuptools.build_meta"
|
|
54
|
+
build-backend = "setuptools.build_meta"
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from argparse import ArgumentParser
|
|
2
|
+
|
|
3
|
+
from sqlcompose.core.functions import load, loads
|
|
4
|
+
from sqlcompose.core.compat import is_file, get_piped_input
|
|
5
|
+
from sqlcompose.core.file_not_found_err import FileNotFoundErr
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def app(args: list[str]) -> tuple[str, int]:
|
|
9
|
+
try:
|
|
10
|
+
from sys import stdin # iport must be done here to allow for test patching
|
|
11
|
+
|
|
12
|
+
if not stdin.isatty() and ( piped := get_piped_input(stdin) ):
|
|
13
|
+
sql = loads(piped)
|
|
14
|
+
else:
|
|
15
|
+
parser = ArgumentParser(prog = "sqlcompose")
|
|
16
|
+
parser.add_argument("input", type=str, help = "SQL expression or location of an SQL file")
|
|
17
|
+
pargs = parser.parse_args(args)
|
|
18
|
+
|
|
19
|
+
if is_file(pargs.input):
|
|
20
|
+
sql = load(pargs.input)
|
|
21
|
+
else:
|
|
22
|
+
sql = loads(pargs.input)
|
|
23
|
+
|
|
24
|
+
return sql, 0
|
|
25
|
+
except SystemExit as ex:
|
|
26
|
+
return str(ex), 2
|
|
27
|
+
except (FileNotFoundErr, FileNotFoundError) as ex:
|
|
28
|
+
return str(ex), 3
|
|
29
|
+
except Exception as ex: # pragma: no cover
|
|
30
|
+
return f"Unexpected error: {ex}", 1
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from os import path, sep
|
|
2
|
+
from typing import TextIO
|
|
2
3
|
from re import compile
|
|
4
|
+
from threading import Thread, Event
|
|
3
5
|
|
|
4
6
|
RX_FILE = compile(r"^[\w,\s-]+\.[A-Za-z]{3}$")
|
|
5
7
|
WINDOWS_PATH_SEP = "\\"
|
|
@@ -42,3 +44,32 @@ def is_file(text: str) -> bool:
|
|
|
42
44
|
return True
|
|
43
45
|
|
|
44
46
|
return False
|
|
47
|
+
|
|
48
|
+
def get_piped_input(pipe: TextIO) -> str:
|
|
49
|
+
"""Reads input from pipe (usually sys.stdin) without blocking.
|
|
50
|
+
"""
|
|
51
|
+
output: list[str] = []
|
|
52
|
+
ev_started = Event()
|
|
53
|
+
ev_done = Event()
|
|
54
|
+
|
|
55
|
+
def fn(output: list[str]):
|
|
56
|
+
try:
|
|
57
|
+
ev_started.set()
|
|
58
|
+
output.append(pipe.read())
|
|
59
|
+
except OSError:
|
|
60
|
+
pass
|
|
61
|
+
finally:
|
|
62
|
+
ev_done.set()
|
|
63
|
+
|
|
64
|
+
thread = Thread(target = fn, args = (output,))
|
|
65
|
+
thread.start()
|
|
66
|
+
|
|
67
|
+
ev_started.wait()
|
|
68
|
+
|
|
69
|
+
if ev_done.wait(0.1): # if there is in fact anything in the pipe, we expect it to be read within 0.1 second
|
|
70
|
+
thread.join()
|
|
71
|
+
else:
|
|
72
|
+
pass # pragma: no cover
|
|
73
|
+
# the thread will block indefinitely, nothing to do about it
|
|
74
|
+
|
|
75
|
+
return output[0] if any(output) else ""
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlcompose
|
|
3
|
-
Version: 0.0.
|
|
4
|
-
Summary: Composition of
|
|
3
|
+
Version: 0.0.4a2
|
|
4
|
+
Summary: Composition of SQL files
|
|
5
5
|
Author-email: Anders Madsen <anders.madsen@alphavue.com>
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: repository, https://github.com/apmadsen/sqlcompose
|
|
@@ -29,6 +29,7 @@ License-File: LICENSE
|
|
|
29
29
|
Provides-Extra: test
|
|
30
30
|
Requires-Dist: pytest>=8.3.0; extra == "test"
|
|
31
31
|
Requires-Dist: pytest-cov>=6.1.0; extra == "test"
|
|
32
|
+
Requires-Dist: pytest-mock>=3.15; extra == "test"
|
|
32
33
|
Dynamic: license-file
|
|
33
34
|
|
|
34
35
|
[](https://github.com/apmadsen/sqlcompose/actions/workflows/python-test.yml)
|
|
@@ -38,19 +39,33 @@ Dynamic: license-file
|
|
|
38
39
|

|
|
39
40
|
[](https://pepy.tech/projects/sqlcompose)
|
|
40
41
|
|
|
41
|
-
# sqlcompose: Composition of
|
|
42
|
-
sqlcompose
|
|
42
|
+
# sqlcompose: Composition of SQL files
|
|
43
|
+
sqlcompose lets you to compose sql files from multiple files by introducing `$INCLUDE` keywords. The SQL output is composed as CTE's or Common Table Expressions.
|
|
44
|
+
|
|
45
|
+
Using composition, you reduce both complexity and duplication of code thus adhering to the DRY principle.
|
|
46
|
+
|
|
47
|
+
### SQL Dialect
|
|
48
|
+
sqlcompose outputs SQL as standard ANSI SQL. Note though, that no validation is done on either the input or the output.
|
|
43
49
|
|
|
44
50
|
## Examples
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
|
|
52
|
+
### 1. Execute the script with the filename as an argument and output to the console:
|
|
53
|
+
```bash
|
|
47
54
|
sqlcompose query.sql
|
|
48
55
|
```
|
|
56
|
+
|
|
57
|
+
### 2. Pipe data into application and output to a file
|
|
58
|
+
```bash
|
|
59
|
+
cat query.sql | sqlcompose > output.sql
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 3. Execute the script with SQL string as argument
|
|
49
63
|
```bash
|
|
50
64
|
sqlcompose 'select * from $INCLUDE(included-query1.sql)'
|
|
51
65
|
```
|
|
66
|
+
> NOTE: Different consoles have different limitations, so you may have to switch from single to double quotes to allow for using the dollar sign.
|
|
52
67
|
|
|
53
|
-
|
|
68
|
+
### 4. Import it in another python application or package
|
|
54
69
|
```python
|
|
55
70
|
from sqlcompose import load, loads
|
|
56
71
|
# method 1 : loading from a file
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# ruff: noqa
|
|
2
2
|
# pyright: basic
|
|
3
|
-
from os import path
|
|
3
|
+
from os import path, chdir, curdir
|
|
4
|
+
from sys import stdin
|
|
5
|
+
from io import StringIO
|
|
4
6
|
from pytest import fixture, raises as assert_raises
|
|
7
|
+
from pytest_mock import MockerFixture
|
|
5
8
|
|
|
6
9
|
from sqlcompose.core.app import app
|
|
7
10
|
|
|
@@ -29,3 +32,17 @@ def test_sql():
|
|
|
29
32
|
result, code = app([f"SELECT * FROM $INCLUDE({path.join('tests', 'main-query.sql')})"])
|
|
30
33
|
assert len(result) > 0
|
|
31
34
|
assert code == 0
|
|
35
|
+
|
|
36
|
+
def test_pipe(mocker: MockerFixture):
|
|
37
|
+
chdir("tests")
|
|
38
|
+
try:
|
|
39
|
+
with open("main-query.sql", "rt", encoding="utf8") as input:
|
|
40
|
+
mocker.patch(f"sys.stdin", input)
|
|
41
|
+
try:
|
|
42
|
+
result, code = app([])
|
|
43
|
+
assert len(result) > 0
|
|
44
|
+
assert code == 0
|
|
45
|
+
finally:
|
|
46
|
+
mocker.resetall()
|
|
47
|
+
finally:
|
|
48
|
+
chdir("..")
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
from argparse import ArgumentParser
|
|
2
|
-
|
|
3
|
-
from sqlcompose.core.functions import load, loads
|
|
4
|
-
from sqlcompose.core.compat import is_file
|
|
5
|
-
from sqlcompose.core.file_not_found_err import FileNotFoundErr
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def app(args: list[str]) -> tuple[str, int]:
|
|
9
|
-
try:
|
|
10
|
-
parser = ArgumentParser(prog = "sqlcompose")
|
|
11
|
-
parser.add_argument("input", type=str, help = "SQL expression or location of an SQL file")
|
|
12
|
-
pargs = parser.parse_args(args)
|
|
13
|
-
|
|
14
|
-
if is_file(pargs.input):
|
|
15
|
-
sql = load(pargs.input)
|
|
16
|
-
else:
|
|
17
|
-
sql = loads(pargs.input)
|
|
18
|
-
|
|
19
|
-
return sql, 0
|
|
20
|
-
except SystemExit as ex:
|
|
21
|
-
return str(ex), 2
|
|
22
|
-
except (FileNotFoundErr, FileNotFoundError) as ex:
|
|
23
|
-
return str(ex), 3
|
|
24
|
-
except Exception as ex: # pragma: no cover
|
|
25
|
-
return f"Unexpected error: {ex}", 1
|
|
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
|