SQLPyHelper 0.1.4__tar.gz → 0.1.6__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.
@@ -1,10 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: SQLPyHelper
3
- Version: 0.1.4
3
+ Version: 0.1.6
4
4
  Summary: A simple SQL database helper package for Python.
5
5
  Home-page: https://github.com/adebayopeter/sqlpyhelper
6
6
  Author: Adebayo Olaonipekun
7
7
  Author-email: pekunmi@live.com
8
+ Project-URL: Documentation, https://sqlpyhelper.readthedocs.io/en/latest/
8
9
  Project-URL: Source, https://github.com/adebayopeter/sqlpyhelper
9
10
  Project-URL: Bug Tracker, https://github.com/adebayopeter/sqlpyhelper/issues
10
11
  Project-URL: Changelog, https://github.com/adebayopeter/sqlpyhelper/blob/main/CHANGELOG.md
@@ -32,12 +33,12 @@ Requires-Dist: mysql-connector-python; extra == "mysql"
32
33
  Provides-Extra: sqlserver
33
34
  Requires-Dist: pyodbc; extra == "sqlserver"
34
35
  Provides-Extra: oracle
35
- Requires-Dist: cx_Oracle; extra == "oracle"
36
+ Requires-Dist: oracledb; extra == "oracle"
36
37
  Provides-Extra: all
37
38
  Requires-Dist: psycopg2; extra == "all"
38
39
  Requires-Dist: mysql-connector-python; extra == "all"
39
40
  Requires-Dist: pyodbc; extra == "all"
40
- Requires-Dist: cx_Oracle; extra == "all"
41
+ Requires-Dist: oracledb; extra == "all"
41
42
  Dynamic: author
42
43
  Dynamic: author-email
43
44
  Dynamic: classifier
@@ -59,10 +60,19 @@ Dynamic: summary
59
60
  [![Python versions](https://img.shields.io/pypi/pyversions/sqlpyhelper.svg)](https://pypi.org/project/sqlpyhelper/)
60
61
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://github.com/adebayopeter/sqlpyhelper/blob/main/LICENSE)
61
62
  [![GitHub stars](https://img.shields.io/github/stars/adebayopeter/sqlpyhelper?style=social)](https://github.com/adebayopeter/sqlpyhelper)
63
+ [![Documentation](https://readthedocs.org/projects/sqlpyhelper/badge/?version=latest)](https://sqlpyhelper.readthedocs.io/en/latest/)
62
64
 
63
- # 📌 SQLPyHelper v.0.1.4 🚀
65
+ SQLPyHelper is a lightweight Python library that gives you a single, consistent API across **SQLite, PostgreSQL, MySQL, SQL Server, and Oracle** — without the overhead of an ORM.
64
66
 
65
- A Python library for simplified database interactions across **SQLite, PostgreSQL, MySQL, SQL Server, and Oracle**. SQLPyHelper provides an intuitive API for handling queries, connection pooling, transactions, logging, and backups efficiently.
67
+ If you need to run queries, manage transactions, pool connections, or back up tables across multiple database types without learning SQLAlchemy's abstraction layer or wiring up five different drivers manually, SQLPyHelper handles that boilerplate for you.
68
+
69
+ ```python
70
+ # Works identically across all five supported databases
71
+ with SQLPyHelper(db_type="postgres", host="localhost", user="user",
72
+ password="pass", database="mydb") as db:
73
+ db.execute_query("INSERT INTO orders (item) VALUES (%s)", ("Laptop",))
74
+ results = db.fetch_all()
75
+ ```
66
76
 
67
77
  ## 📖 Table of Contents
68
78
  - [🚀 Features](#-features)
@@ -81,7 +91,7 @@ A Python library for simplified database interactions across **SQLite, PostgreSQ
81
91
 
82
92
  ---
83
93
 
84
- ## 🚀 Features in v0.1.3
94
+ ## 🚀 Features in v0.1.4
85
95
  - Unified connection pooling for multiple databases.
86
96
  - Automatic reconnection for lost connections.
87
97
  - Transaction support (BEGIN, ROLLBACK, COMMIT).
@@ -92,10 +102,21 @@ A Python library for simplified database interactions across **SQLite, PostgreSQ
92
102
 
93
103
  ---
94
104
  ## 📦 Installation
95
- #### Install via PyPI:
105
+
106
+ Install the base package (includes SQLite support out of the box):
96
107
  ```sh
97
108
  pip install sqlpyhelper
98
109
  ```
110
+
111
+ Install with your database driver:
112
+ ```sh
113
+ pip install sqlpyhelper[postgres] # PostgreSQL
114
+ pip install sqlpyhelper[mysql] # MySQL
115
+ pip install sqlpyhelper[sqlserver] # SQL Server
116
+ pip install sqlpyhelper[oracle] # Oracle
117
+ pip install sqlpyhelper[all] # All databases
118
+ ```
119
+
99
120
  📌 Package on PyPI: [SQLPyHelper on PyPI](https://pypi.org/project/SQLPyHelper/)
100
121
 
101
122
  For local development:
@@ -208,7 +229,9 @@ db.return_connection_to_pool(conn)
208
229
  | `return_connection_to_pool(conn)` | Returns connection back to pool. |
209
230
  | `begin_transaction()` | Begins an **explicit transaction**. |
210
231
  | `rollback_transaction()` | Rolls back **uncommitted transactions**. |
232
+ | `commit_transaction()` | Commits the current transaction. |
211
233
  | `close()` | Closes the database connection safely. |
234
+ | `__enter__` / `__exit__()` | Use as a context manager — connection closes automatically. |
212
235
 
213
236
  ---
214
237
  ## 🌍 Contributing
@@ -5,10 +5,19 @@
5
5
  [![Python versions](https://img.shields.io/pypi/pyversions/sqlpyhelper.svg)](https://pypi.org/project/sqlpyhelper/)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://github.com/adebayopeter/sqlpyhelper/blob/main/LICENSE)
7
7
  [![GitHub stars](https://img.shields.io/github/stars/adebayopeter/sqlpyhelper?style=social)](https://github.com/adebayopeter/sqlpyhelper)
8
+ [![Documentation](https://readthedocs.org/projects/sqlpyhelper/badge/?version=latest)](https://sqlpyhelper.readthedocs.io/en/latest/)
8
9
 
9
- # 📌 SQLPyHelper v.0.1.4 🚀
10
+ SQLPyHelper is a lightweight Python library that gives you a single, consistent API across **SQLite, PostgreSQL, MySQL, SQL Server, and Oracle** — without the overhead of an ORM.
10
11
 
11
- A Python library for simplified database interactions across **SQLite, PostgreSQL, MySQL, SQL Server, and Oracle**. SQLPyHelper provides an intuitive API for handling queries, connection pooling, transactions, logging, and backups efficiently.
12
+ If you need to run queries, manage transactions, pool connections, or back up tables across multiple database types without learning SQLAlchemy's abstraction layer or wiring up five different drivers manually, SQLPyHelper handles that boilerplate for you.
13
+
14
+ ```python
15
+ # Works identically across all five supported databases
16
+ with SQLPyHelper(db_type="postgres", host="localhost", user="user",
17
+ password="pass", database="mydb") as db:
18
+ db.execute_query("INSERT INTO orders (item) VALUES (%s)", ("Laptop",))
19
+ results = db.fetch_all()
20
+ ```
12
21
 
13
22
  ## 📖 Table of Contents
14
23
  - [🚀 Features](#-features)
@@ -27,7 +36,7 @@ A Python library for simplified database interactions across **SQLite, PostgreSQ
27
36
 
28
37
  ---
29
38
 
30
- ## 🚀 Features in v0.1.3
39
+ ## 🚀 Features in v0.1.4
31
40
  - Unified connection pooling for multiple databases.
32
41
  - Automatic reconnection for lost connections.
33
42
  - Transaction support (BEGIN, ROLLBACK, COMMIT).
@@ -38,10 +47,21 @@ A Python library for simplified database interactions across **SQLite, PostgreSQ
38
47
 
39
48
  ---
40
49
  ## 📦 Installation
41
- #### Install via PyPI:
50
+
51
+ Install the base package (includes SQLite support out of the box):
42
52
  ```sh
43
53
  pip install sqlpyhelper
44
54
  ```
55
+
56
+ Install with your database driver:
57
+ ```sh
58
+ pip install sqlpyhelper[postgres] # PostgreSQL
59
+ pip install sqlpyhelper[mysql] # MySQL
60
+ pip install sqlpyhelper[sqlserver] # SQL Server
61
+ pip install sqlpyhelper[oracle] # Oracle
62
+ pip install sqlpyhelper[all] # All databases
63
+ ```
64
+
45
65
  📌 Package on PyPI: [SQLPyHelper on PyPI](https://pypi.org/project/SQLPyHelper/)
46
66
 
47
67
  For local development:
@@ -154,7 +174,9 @@ db.return_connection_to_pool(conn)
154
174
  | `return_connection_to_pool(conn)` | Returns connection back to pool. |
155
175
  | `begin_transaction()` | Begins an **explicit transaction**. |
156
176
  | `rollback_transaction()` | Rolls back **uncommitted transactions**. |
177
+ | `commit_transaction()` | Commits the current transaction. |
157
178
  | `close()` | Closes the database connection safely. |
179
+ | `__enter__` / `__exit__()` | Use as a context manager — connection closes automatically. |
158
180
 
159
181
  ---
160
182
  ## 🌍 Contributing
@@ -1,10 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: SQLPyHelper
3
- Version: 0.1.4
3
+ Version: 0.1.6
4
4
  Summary: A simple SQL database helper package for Python.
5
5
  Home-page: https://github.com/adebayopeter/sqlpyhelper
6
6
  Author: Adebayo Olaonipekun
7
7
  Author-email: pekunmi@live.com
8
+ Project-URL: Documentation, https://sqlpyhelper.readthedocs.io/en/latest/
8
9
  Project-URL: Source, https://github.com/adebayopeter/sqlpyhelper
9
10
  Project-URL: Bug Tracker, https://github.com/adebayopeter/sqlpyhelper/issues
10
11
  Project-URL: Changelog, https://github.com/adebayopeter/sqlpyhelper/blob/main/CHANGELOG.md
@@ -32,12 +33,12 @@ Requires-Dist: mysql-connector-python; extra == "mysql"
32
33
  Provides-Extra: sqlserver
33
34
  Requires-Dist: pyodbc; extra == "sqlserver"
34
35
  Provides-Extra: oracle
35
- Requires-Dist: cx_Oracle; extra == "oracle"
36
+ Requires-Dist: oracledb; extra == "oracle"
36
37
  Provides-Extra: all
37
38
  Requires-Dist: psycopg2; extra == "all"
38
39
  Requires-Dist: mysql-connector-python; extra == "all"
39
40
  Requires-Dist: pyodbc; extra == "all"
40
- Requires-Dist: cx_Oracle; extra == "all"
41
+ Requires-Dist: oracledb; extra == "all"
41
42
  Dynamic: author
42
43
  Dynamic: author-email
43
44
  Dynamic: classifier
@@ -59,10 +60,19 @@ Dynamic: summary
59
60
  [![Python versions](https://img.shields.io/pypi/pyversions/sqlpyhelper.svg)](https://pypi.org/project/sqlpyhelper/)
60
61
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://github.com/adebayopeter/sqlpyhelper/blob/main/LICENSE)
61
62
  [![GitHub stars](https://img.shields.io/github/stars/adebayopeter/sqlpyhelper?style=social)](https://github.com/adebayopeter/sqlpyhelper)
63
+ [![Documentation](https://readthedocs.org/projects/sqlpyhelper/badge/?version=latest)](https://sqlpyhelper.readthedocs.io/en/latest/)
62
64
 
63
- # 📌 SQLPyHelper v.0.1.4 🚀
65
+ SQLPyHelper is a lightweight Python library that gives you a single, consistent API across **SQLite, PostgreSQL, MySQL, SQL Server, and Oracle** — without the overhead of an ORM.
64
66
 
65
- A Python library for simplified database interactions across **SQLite, PostgreSQL, MySQL, SQL Server, and Oracle**. SQLPyHelper provides an intuitive API for handling queries, connection pooling, transactions, logging, and backups efficiently.
67
+ If you need to run queries, manage transactions, pool connections, or back up tables across multiple database types without learning SQLAlchemy's abstraction layer or wiring up five different drivers manually, SQLPyHelper handles that boilerplate for you.
68
+
69
+ ```python
70
+ # Works identically across all five supported databases
71
+ with SQLPyHelper(db_type="postgres", host="localhost", user="user",
72
+ password="pass", database="mydb") as db:
73
+ db.execute_query("INSERT INTO orders (item) VALUES (%s)", ("Laptop",))
74
+ results = db.fetch_all()
75
+ ```
66
76
 
67
77
  ## 📖 Table of Contents
68
78
  - [🚀 Features](#-features)
@@ -81,7 +91,7 @@ A Python library for simplified database interactions across **SQLite, PostgreSQ
81
91
 
82
92
  ---
83
93
 
84
- ## 🚀 Features in v0.1.3
94
+ ## 🚀 Features in v0.1.4
85
95
  - Unified connection pooling for multiple databases.
86
96
  - Automatic reconnection for lost connections.
87
97
  - Transaction support (BEGIN, ROLLBACK, COMMIT).
@@ -92,10 +102,21 @@ A Python library for simplified database interactions across **SQLite, PostgreSQ
92
102
 
93
103
  ---
94
104
  ## 📦 Installation
95
- #### Install via PyPI:
105
+
106
+ Install the base package (includes SQLite support out of the box):
96
107
  ```sh
97
108
  pip install sqlpyhelper
98
109
  ```
110
+
111
+ Install with your database driver:
112
+ ```sh
113
+ pip install sqlpyhelper[postgres] # PostgreSQL
114
+ pip install sqlpyhelper[mysql] # MySQL
115
+ pip install sqlpyhelper[sqlserver] # SQL Server
116
+ pip install sqlpyhelper[oracle] # Oracle
117
+ pip install sqlpyhelper[all] # All databases
118
+ ```
119
+
99
120
  📌 Package on PyPI: [SQLPyHelper on PyPI](https://pypi.org/project/SQLPyHelper/)
100
121
 
101
122
  For local development:
@@ -208,7 +229,9 @@ db.return_connection_to_pool(conn)
208
229
  | `return_connection_to_pool(conn)` | Returns connection back to pool. |
209
230
  | `begin_transaction()` | Begins an **explicit transaction**. |
210
231
  | `rollback_transaction()` | Rolls back **uncommitted transactions**. |
232
+ | `commit_transaction()` | Commits the current transaction. |
211
233
  | `close()` | Closes the database connection safely. |
234
+ | `__enter__` / `__exit__()` | Use as a context manager — connection closes automatically. |
212
235
 
213
236
  ---
214
237
  ## 🌍 Contributing
@@ -1,5 +1,7 @@
1
1
  LICENSE
2
2
  README.md
3
+ pyproject.toml
4
+ setup.cfg
3
5
  setup.py
4
6
  SQLPyHelper.egg-info/PKG-INFO
5
7
  SQLPyHelper.egg-info/SOURCES.txt
@@ -12,5 +14,4 @@ sqlpyhelper/automation_utils.py
12
14
  sqlpyhelper/cli.py
13
15
  sqlpyhelper/db_helper.py
14
16
  sqlpyhelper/py.typed
15
- test/test_automation.py
16
17
  test/test_sqlpyhelper.py
@@ -5,13 +5,13 @@ click
5
5
  psycopg2
6
6
  mysql-connector-python
7
7
  pyodbc
8
- cx_Oracle
8
+ oracledb
9
9
 
10
10
  [mysql]
11
11
  mysql-connector-python
12
12
 
13
13
  [oracle]
14
- cx_Oracle
14
+ oracledb
15
15
 
16
16
  [postgres]
17
17
  psycopg2
@@ -0,0 +1,6 @@
1
+ [tool.black]
2
+ line-length = 88
3
+
4
+ [tool.isort]
5
+ profile = "black"
6
+ line_length = 88
@@ -0,0 +1,21 @@
1
+ [flake8]
2
+ max-line-length = 120
3
+ ignore =
4
+ E203,
5
+ E501,
6
+ W503
7
+ exclude =
8
+ venv,
9
+ .git,
10
+ __pycache__,
11
+ dist,
12
+ build,
13
+ *.egg-info
14
+
15
+ [mypy]
16
+ ignore_missing_imports = True
17
+
18
+ [egg_info]
19
+ tag_build =
20
+ tag_date = 0
21
+
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as f:
5
5
 
6
6
  setup(
7
7
  name='SQLPyHelper',
8
- version='0.1.4',
8
+ version='0.1.6',
9
9
  description='A simple SQL database helper package for Python.',
10
10
  long_description=long_description,
11
11
  long_description_content_type="text/markdown",
@@ -25,12 +25,12 @@ setup(
25
25
  "postgres": ["psycopg2"],
26
26
  "mysql": ["mysql-connector-python"],
27
27
  "sqlserver": ["pyodbc"],
28
- "oracle": ["cx_Oracle"],
28
+ "oracle": ["oracledb"],
29
29
  "all": [
30
30
  "psycopg2",
31
31
  "mysql-connector-python",
32
32
  "pyodbc",
33
- "cx_Oracle",
33
+ "oracledb",
34
34
  ],
35
35
  },
36
36
  keywords=[
@@ -38,6 +38,7 @@ setup(
38
38
  "sqlserver", "oracle", "db", "query", "helper",
39
39
  ],
40
40
  project_urls={
41
+ "Documentation": "https://sqlpyhelper.readthedocs.io/en/latest/",
41
42
  "Source": "https://github.com/adebayopeter/sqlpyhelper",
42
43
  "Bug Tracker": "https://github.com/adebayopeter/sqlpyhelper/issues",
43
44
  "Changelog": "https://github.com/adebayopeter/sqlpyhelper/blob/main/CHANGELOG.md",
@@ -1,9 +1,9 @@
1
1
  # Match the version in setup.py
2
- __version__ = "0.1.4"
2
+ __version__ = "0.1.6"
3
3
 
4
- from sqlpyhelper.db_helper import (
5
- SQLPyHelperError,
4
+ from sqlpyhelper.db_helper import ( # noqa: F401
5
+ BackupError,
6
6
  ConnectionError,
7
7
  QueryError,
8
- BackupError,
8
+ SQLPyHelperError,
9
9
  )
@@ -1,9 +1,11 @@
1
- import pandas as pd
2
- from sqlpyhelper.db_helper import SQLPyHelper
3
- import subprocess
4
- from datetime import datetime
5
1
  import os
6
2
  import shutil
3
+ import subprocess
4
+ from datetime import datetime
5
+
6
+ import pandas as pd
7
+
8
+ from sqlpyhelper.db_helper import SQLPyHelper
7
9
 
8
10
 
9
11
  class AutomationUtils:
@@ -43,12 +45,17 @@ class AutomationUtils:
43
45
  subprocess.run(
44
46
  [
45
47
  "pg_dump",
46
- "-h", host,
47
- "-p", port,
48
- "-U", user,
48
+ "-h",
49
+ host,
50
+ "-p",
51
+ port,
52
+ "-U",
53
+ user,
49
54
  db_name,
50
- "-F", "c",
51
- "-f", filepath,
55
+ "-F",
56
+ "c",
57
+ "-f",
58
+ filepath,
52
59
  ],
53
60
  check=True,
54
61
  shell=False,
@@ -82,7 +89,7 @@ class AutomationUtils:
82
89
  entity_column (str): Column representing entity ID.
83
90
  date_column (str): Column representing timestamp/date.
84
91
  """
85
- if self.db.db_type == 'sqlite':
92
+ if self.db.db_type == "sqlite":
86
93
  month_expr = f"strftime('%Y-%m', {date_column})"
87
94
  else:
88
95
  month_expr = f"DATE_TRUNC('month', {date_column})"
@@ -95,7 +102,9 @@ class AutomationUtils:
95
102
  self.db.execute_query(query)
96
103
  return self.db.fetch_all()
97
104
 
98
- def aggregate_column(self, table, value_column, group_column=None, time_column=None):
105
+ def aggregate_column(
106
+ self, table, value_column, group_column=None, time_column=None
107
+ ):
99
108
  """
100
109
  Computes sum of any value column grouped by entity or month.
101
110
 
@@ -105,7 +114,7 @@ class AutomationUtils:
105
114
  group_column (str, optional): Entity or category to group by.
106
115
  time_column (str, optional): Timestamp to extract month grouping.
107
116
  """
108
- if self.db.db_type == 'sqlite':
117
+ if self.db.db_type == "sqlite":
109
118
  month_expr = f"strftime('%Y-%m', {time_column})"
110
119
  else:
111
120
  month_expr = f"DATE_TRUNC('month', {time_column})"
@@ -133,11 +142,13 @@ class AutomationUtils:
133
142
  threshold (int): Number of standard deviations from mean to flag as outlier.
134
143
  """
135
144
  query = f"""
136
- SELECT *, {numeric_column}
137
- AS value FROM {table}
145
+ SELECT *, {numeric_column} AS value FROM {table}
138
146
  """
139
147
  self.db.execute_query(query)
140
- data = pd.DataFrame(self.db.fetch_all(), columns=[desc[0] for desc in self.db.cursor.description])
148
+ data = pd.DataFrame(
149
+ self.db.fetch_all(),
150
+ columns=[desc[0] for desc in self.db.cursor.description],
151
+ )
141
152
 
142
153
  mean_val = data["value"].mean()
143
154
  std_val = data["value"].std()
@@ -0,0 +1,199 @@
1
+ import click
2
+
3
+ from sqlpyhelper.automation_utils import AutomationUtils
4
+ from sqlpyhelper.db_helper import SQLPyHelper
5
+
6
+
7
+ @click.group()
8
+ def cli():
9
+ """SQLPyHelper Command Line Interface"""
10
+ pass
11
+
12
+
13
+ @cli.command()
14
+ @click.option("--db_type", help="Type of database (e.g., sqlite, postgres, mysql)")
15
+ @click.option("--host", help="Database host")
16
+ @click.option("--user", help="Username")
17
+ @click.option("--password", help="Password")
18
+ @click.option("--database", help="Database name or file")
19
+ @click.option("--query", required=True, help="SQL query to run")
20
+ def run_query(db_type, host, user, password, database, query):
21
+ """Run a single SQL query and print results"""
22
+ db = SQLPyHelper(
23
+ db_type=db_type, host=host, user=user, password=password, database=database
24
+ )
25
+ results = db.execute_query(query)
26
+ for row in results:
27
+ click.echo(row)
28
+ db.close()
29
+
30
+
31
+ @cli.command()
32
+ @click.option("--db_type", required=True)
33
+ @click.option("--host")
34
+ @click.option("--user")
35
+ @click.option("--password")
36
+ @click.option("--database", required=True)
37
+ def interactive_shell(db_type, host, user, password, database):
38
+ """Launch an interactive SQL shell"""
39
+ db = SQLPyHelper(
40
+ db_type=db_type, host=host, user=user, password=password, database=database
41
+ )
42
+ click.echo("Interactive shell started. Type your SQL query or 'exit'")
43
+ while True:
44
+ query = input("sqlpy> ")
45
+ if query.lower() in ("exit", "quit"):
46
+ break
47
+ try:
48
+ db.execute_query(query)
49
+ results = db.fetch_all()
50
+ for row in results:
51
+ click.echo(row)
52
+ except Exception as e:
53
+ click.echo(f"Error: {e}")
54
+ db.close()
55
+
56
+
57
+ @cli.command()
58
+ @click.option("--target", default="local", help="Backup destination")
59
+ @click.option("--tag", default="autobackup", help="Tag for backup file naming")
60
+ @click.option("--db-type")
61
+ @click.option("--host")
62
+ @click.option("--user")
63
+ @click.option("--password")
64
+ @click.option("--database")
65
+ @click.option("--port")
66
+ def backup(target, tag, db_type, host, user, password, database, port):
67
+ """Create a timestamped backup of the connected database."""
68
+ utils = AutomationUtils(
69
+ db_type=db_type,
70
+ host=host,
71
+ user=user,
72
+ password=password,
73
+ database=database,
74
+ port=port,
75
+ )
76
+ utils.backup_database(target=target, tag=tag)
77
+
78
+
79
+ @cli.command()
80
+ @click.option("--file", required=True, help="Path to CSV file")
81
+ @click.option("--table", required=True, help="Destination table")
82
+ @click.option(
83
+ "--if-exists",
84
+ default="append",
85
+ type=click.Choice(["append", "replace"]),
86
+ help="What to do if table exists",
87
+ )
88
+ @click.option("--db-type")
89
+ @click.option("--host")
90
+ @click.option("--user")
91
+ @click.option("--password")
92
+ @click.option("--database")
93
+ @click.option("--port")
94
+ def load_data(file, table, if_exists, db_type, host, user, password, database, port):
95
+ """Load data from CSV into database table."""
96
+ utils = AutomationUtils(
97
+ db_type=db_type,
98
+ host=host,
99
+ user=user,
100
+ password=password,
101
+ database=database,
102
+ port=port,
103
+ )
104
+ utils.load_data_from_csv(file, table, if_exists=if_exists)
105
+
106
+
107
+ @cli.command()
108
+ @click.option("--table", required=True)
109
+ @click.option("--entity-column", required=True)
110
+ @click.option("--date-column", required=True)
111
+ @click.option("--db-type")
112
+ @click.option("--host")
113
+ @click.option("--user")
114
+ @click.option("--password")
115
+ @click.option("--database")
116
+ @click.option("--port")
117
+ def detect_missing_periods(
118
+ table, entity_column, date_column, db_type, host, user, password, database, port
119
+ ):
120
+ """Flag entities with fewer than 12 months of activity."""
121
+ utils = AutomationUtils(
122
+ db_type=db_type,
123
+ host=host,
124
+ user=user,
125
+ password=password,
126
+ database=database,
127
+ port=port,
128
+ )
129
+ results = utils.detect_missing_periods(table, entity_column, date_column)
130
+ for row in results:
131
+ click.echo(row)
132
+
133
+
134
+ @cli.command()
135
+ @click.option("--table", required=True)
136
+ @click.option("--value-column", required=True)
137
+ @click.option("--group-column")
138
+ @click.option("--time-column")
139
+ @click.option("--db-type")
140
+ @click.option("--host")
141
+ @click.option("--user")
142
+ @click.option("--password")
143
+ @click.option("--database")
144
+ @click.option("--port")
145
+ def aggregate(
146
+ table,
147
+ value_column,
148
+ group_column,
149
+ time_column,
150
+ db_type,
151
+ host,
152
+ user,
153
+ password,
154
+ database,
155
+ port,
156
+ ):
157
+ """Aggregate numeric column optionally grouped by entity and time."""
158
+ utils = AutomationUtils(
159
+ db_type=db_type,
160
+ host=host,
161
+ user=user,
162
+ password=password,
163
+ database=database,
164
+ port=port,
165
+ )
166
+ results = utils.aggregate_column(table, value_column, group_column, time_column)
167
+ for row in results:
168
+ click.echo(row)
169
+
170
+
171
+ @cli.command()
172
+ @click.option("--table", required=True)
173
+ @click.option("--numeric-column", required=True)
174
+ @click.option("--threshold", default=2, type=int)
175
+ @click.option("--db-type")
176
+ @click.option("--host")
177
+ @click.option("--user")
178
+ @click.option("--password")
179
+ @click.option("--database")
180
+ @click.option("--port")
181
+ def detect_outliers(
182
+ table, numeric_column, threshold, db_type, host, user, password, database, port
183
+ ):
184
+ """Flag rows where values deviate statistically from average."""
185
+ utils = AutomationUtils(
186
+ db_type=db_type,
187
+ host=host,
188
+ user=user,
189
+ password=password,
190
+ database=database,
191
+ port=port,
192
+ )
193
+ results = utils.detect_outliers(table, numeric_column, threshold)
194
+ for row in results:
195
+ click.echo(row)
196
+
197
+
198
+ if __name__ == "__main__":
199
+ cli()