diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 96acfd23..e16b30f6 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -37,47 +37,16 @@ // Add the IDs of extensions you want installed when the container is created. "extensions": [ // "usernamehw.errorlens", - "charliermarsh.ruff", "streetsidesoftware.code-spell-checker", "GitHub.copilot", "GitHub.copilot-chat", - "ms-vscode.cpptools-extension-pack", - "ms-vscode.cpptools", - "aaron-bond.better-comments", - "alefragnani.project-manager", - "dbaeumer.vscode-eslint", - "DavidAnson.vscode-markdownlint", - "DotJoshJohnson.xml", "donjayamanne.githistory", "ecmel.vscode-html-css", - "esbenp.prettier-vscode", - "george-alisson.html-preview-vscode", - "Gruntfuggly.todo-tree", "hnw.vscode-auto-open-markdown-preview", "kamikillerto.vscode-colorize", "mikestead.dotenv", - "ms-python.isort", - "ms-python.pylint", - "ms-python.python", - "ms-toolsai.jupyter", - "ms-toolsai.jupyter-keymap", - "ms-vscode.makefile-tools", - "njpwerner.autodocstring", "oderwat.indent-rainbow", - "peakchen90.open-html-in-browser", - "pnp.polacode", - "redhat.vscode-yaml", - "streetsidesoftware.code-spell-checker", - "waderyan.gitblame", "wayou.vscode-todo-highlight", - "wholroyd.jinja", - "wix.vscode-import-cost", - "GrapeCity.gc-excelviewer", - "supperchong.pretty-json", - "ms-azuretools.vscode-docker", - "ms-kubernetes-tools.vscode-kubernetes-tools", - "ms-vsliveshare.vsliveshare", - "ms-python.black-formatter" ] } }, diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 119ae183..c5411e59 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -1,3 +1,4 @@ +# .devcontainer docker-compose configuration version: '3.8' services: diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f78c94c..028ed468 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,25 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ## Latest Changes +### Improving SQLAlchemy Queries and Improved Documentation ([v2025.4.17.1](https://github.com/devsetgo/devsetgo_lib/releases/tag/v2025.4.17.1)) + +![DSG Logo](https://raw.githubusercontent.com/devsetgo/devsetgo_lib/refs/heads/main/images/devsetgo_lib_logo_white_bg.svg) +Read the Full Documentation [here](https://devsetgo.github.io/devsetgo_lib/). +#### What's Changed +* fixing sonar issue (#494) @devsetgo +* updating release drafter (#493) @devsetgo +* Improving Examples (#492) @devsetgo +* Fix of issue with distinct queries in read queries (#491) @devsetgo +* updating footer (#490) @devsetgo +* adding raw link to release drafter (#489) @devsetgo +* Improving documentation (#488) @devsetgo +* adding 3.13 testing (#486) @devsetgo + +Built to help reduce copy/paste from multiple projects and uses calendar versioning (year.month.day.build) from [BumpCalver](https://github.com/devsetgo/bumpcalver). + + +Published Date: 2025 April 17, 15:47 + ### New Functions and Updated Documentation ([v2025.4.5.1](https://github.com/devsetgo/devsetgo_lib/releases/tag/v2025.4.5.1)) #### What's Changed diff --git a/coverage-badge.svg b/coverage-badge.svg index 82884f80..96d7ac21 100644 --- a/coverage-badge.svg +++ b/coverage-badge.svg @@ -1 +1 @@ -coverage: 77.63%coverage77.63% +coverage: 99.11%coverage99.11% diff --git a/coverage.xml b/coverage.xml index 5ef22829..e6137229 100644 --- a/coverage.xml +++ b/coverage.xml @@ -1,14 +1,14 @@ - + - /workspaces/devsetgo_lib + dsg_lib - + - + @@ -25,9 +25,9 @@ - + - + @@ -53,11 +53,11 @@ - + - + @@ -79,7 +79,7 @@ - + @@ -123,7 +123,7 @@ - + @@ -134,27 +134,27 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + @@ -416,13 +416,13 @@ - + - + - + @@ -450,7 +450,7 @@ - + @@ -498,25 +498,9 @@ - - - - - - - - - - - - - - - - - + @@ -707,7 +691,7 @@ - + @@ -787,7 +771,7 @@ - + @@ -842,58 +826,60 @@ - + - - - - - + + + + - - + + - - - - - - + + + + + - + - - - - - - - - - + + + + + + + + + + - + - + + + + - + @@ -917,19 +903,19 @@ - + - + - + - + @@ -954,7 +940,7 @@ - + @@ -979,7 +965,7 @@ - + @@ -1033,2143 +1019,5 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/database/database_configuration.md b/docs/database/database_configuration.md index a673860f..14831850 100644 --- a/docs/database/database_configuration.md +++ b/docs/database/database_configuration.md @@ -1,4 +1,15 @@ # Reference +## Supported Databases + +| Database | Library (with link) | Supported Database Versions (via library) | +|---------------|-------------------------------------------------------------------------------------|-----------------------------------------------| +| PostgreSQL | [asyncpg](https://pypi.org/project/asyncpg/) `>=0.21.0`
[SQLAlchemy](https://pypi.org/project/SQLAlchemy/) `>=2.0.10,<2.0.99` | asyncpg supports PostgreSQL 9.2+ | +| SQLite | [aiosqlite](https://pypi.org/project/aiosqlite/) `>=0.17.0`
[SQLAlchemy](https://pypi.org/project/SQLAlchemy/) `>=2.0.10,<2.0.99` | SQLite 3.x | +| Oracle | [oracledb](https://pypi.org/project/oracledb/) `>=2.4.1,<2.5.0`
[SQLAlchemy](https://pypi.org/project/SQLAlchemy/) `>=2.0.10,<2.0.99` | Oracle Database 11.2+ | +| MS SQL Server | [aioodbc](https://pypi.org/project/aioodbc/) `>=0.4.1`
[SQLAlchemy](https://pypi.org/project/SQLAlchemy/) `>=2.0.10,<2.0.99` | SQL Server 2008+ (via ODBC driver) | +| CockroachDB | [sqlalchemy-cockroachdb](https://pypi.org/project/sqlalchemy-cockroachdb/) `<2.0.2`
[SQLAlchemy](https://pypi.org/project/SQLAlchemy/) `>=2.0.10,<2.0.99`
[asyncpg](https://pypi.org/project/asyncpg/) `>=0.21.0` | CockroachDB v19.2+ | +| MySQL | [asyncmy](https://pypi.org/project/asyncmy/) `>=0.2.10`
[SQLAlchemy](https://pypi.org/project/SQLAlchemy/) `>=2.0.10,<2.0.99` | MySQL 5.7+, MariaDB 10.2+ | + ::: dsg_lib.async_database_functions.database_config handler: python diff --git a/docs/release-notes.md b/docs/release-notes.md index 5f78c94c..028ed468 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -4,6 +4,25 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ## Latest Changes +### Improving SQLAlchemy Queries and Improved Documentation ([v2025.4.17.1](https://github.com/devsetgo/devsetgo_lib/releases/tag/v2025.4.17.1)) + +![DSG Logo](https://raw.githubusercontent.com/devsetgo/devsetgo_lib/refs/heads/main/images/devsetgo_lib_logo_white_bg.svg) +Read the Full Documentation [here](https://devsetgo.github.io/devsetgo_lib/). +#### What's Changed +* fixing sonar issue (#494) @devsetgo +* updating release drafter (#493) @devsetgo +* Improving Examples (#492) @devsetgo +* Fix of issue with distinct queries in read queries (#491) @devsetgo +* updating footer (#490) @devsetgo +* adding raw link to release drafter (#489) @devsetgo +* Improving documentation (#488) @devsetgo +* adding 3.13 testing (#486) @devsetgo + +Built to help reduce copy/paste from multiple projects and uses calendar versioning (year.month.day.build) from [BumpCalver](https://github.com/devsetgo/bumpcalver). + + +Published Date: 2025 April 17, 15:47 + ### New Functions and Updated Documentation ([v2025.4.5.1](https://github.com/devsetgo/devsetgo_lib/releases/tag/v2025.4.5.1)) #### What's Changed diff --git a/dsg_lib/__init__.py b/dsg_lib/__init__.py index 2e634f7d..0e358071 100644 --- a/dsg_lib/__init__.py +++ b/dsg_lib/__init__.py @@ -8,7 +8,7 @@ """ from datetime import date -__version__ = "2025.04.17-001" +__version__ = "2025.05.04-001" __author__ = "Mike Ryan" __license__ = "MIT" __copyright__ = f"Copyright© 2021-{date.today().year}" diff --git a/dsg_lib/async_database_functions/database_config.py b/dsg_lib/async_database_functions/database_config.py index 3eacf072..c919dadd 100644 --- a/dsg_lib/async_database_functions/database_config.py +++ b/dsg_lib/async_database_functions/database_config.py @@ -131,6 +131,42 @@ class DBConfig: "pool_recycle", "pool_timeout", }, + "cockroachdb": { # experimental support for CockroachDB + "echo", + "future", + "pool_pre_ping", + "pool_size", + "max_overflow", + "pool_recycle", + "pool_timeout", + }, + "mysql": { # experimental support for MySQL + "echo", + "future", + "pool_pre_ping", + "pool_size", + "max_overflow", + "pool_recycle", + "pool_timeout", + }, + "mssql": { # experimental support for Microsoft SQL Server + "echo", + "future", + "pool_pre_ping", + "pool_size", + "max_overflow", + "pool_recycle", + "pool_timeout", + }, + "oracle": { # experimental support for Oracle + "echo", + "future", + "pool_pre_ping", + "pool_size", + "max_overflow", + "pool_recycle", + "pool_timeout", + }, # Add other engines here... } diff --git a/dsg_lib/common_functions/email_validation.py b/dsg_lib/common_functions/email_validation.py index 29ca5301..6621702d 100644 --- a/dsg_lib/common_functions/email_validation.py +++ b/dsg_lib/common_functions/email_validation.py @@ -213,103 +213,3 @@ def validate_email_address( logger.error(f"Exception: {email} - {str(e)}") logger.debug(f"Exception: {email} - {str(e)}, - {parameters}") return email_dict - - -if __name__ == "__main__": - # create a list of email addresses to check if valid - email_addresses = [ - "bob@devsetgo.com", - "bob@devset.go", - "foo@yahoo.com", - "bob@gmail.com", - "very fake@devsetgo.com", - "jane.doe@example.com", - "john_doe@example.co.uk", - "user.name+tag+sorting@example.com", - "x@example.com", # shortest possible email address - "example-indeed@strange-example.com", - "admin@mailserver1", # local domain name with no TLD - "example@s.example", # see the list of Internet top-level domains - '" "@example.org', # space between the quotes - '"john..doe"@example.org', # quoted double dot - "mailhost!username@example.org", # bangified host route used for uucp mailers - "user%example.com@example.org", # percent sign in local part - "user-@example.org", # valid due to the last character being an allowed character - # Invalid email addresses - "Abc.example.com", # no @ character - "A@b@c@example.com", # only one @ is allowed outside quotation marks - 'a"b(c)d,e:f;gi[j\\k]l@example.com', # none of the special characters in this local part are allowed outside quotation marks - 'just"not"right@example.com', # quoted strings must be dot separated or the only element making up the local-part - 'this is"not\\allowed@example.com', # spaces, quotes, and backslashes may only exist when within quoted strings and preceded by a backslash - 'this\\ still\\"not\\\\allowed@example.com', # even if escaped (preceded by a backslash), spaces, quotes, and backslashes must still be contained by quotes - "1234567890123456789012345678901234567890123456789012345678901234+x@example.com", # local part is longer than 64 characters - # Emails with empty local part - "@example.com", # only valid if allow_empty_local is True - # Emails with non-ASCII characters - "üñîçøðé@example.com", # only valid if allow_smtputf8 is True - "user@üñîçøðé.com", # only valid if allow_smtputf8 is True - # Emails with quoted local part - '"john.doe"@example.com', # only valid if allow_quoted_local is True - '"john..doe"@example.com', # only valid if allow_quoted_local is True - # Emails with display name - "John Doe ", # only valid if allow_display_name is True - # Emails with domain literal - "user@[192.0.2.1]", # only valid if allow_domain_literal is True - # Emails with long local part - "a" * 65 + "@example.com", # local part is longer than 64 characters - # Emails with invalid characters - "john doe@example.com", # space is not allowed - "john@doe@example.com", # only one @ is allowed - "john.doe@.com", # domain can't start with a dot - "john.doe@example..com", # domain can't have two consecutive dots - "test@google.com", - ] - - # create a list of configurations - configurations = [ - { - "check_deliverability": True, - "test_environment": False, - "allow_smtputf8": False, - "allow_empty_local": False, - "allow_quoted_local": False, - "allow_display_name": False, - "allow_domain_literal": False, - "globally_deliverable": None, - "timeout": 10, - "dns_type": "timeout", - }, - { - "check_deliverability": False, - "test_environment": True, - "allow_smtputf8": True, - "allow_empty_local": True, - "allow_quoted_local": True, - "allow_display_name": True, - "allow_domain_literal": True, - "globally_deliverable": None, - "timeout": 5, - "dns_type": "dns", - }, - {"check_deliverability": True}, - # add more configurations here - ] - - import pprint - import time - - t0 = time.time() - validity = [] - - for email in email_addresses: - for config in configurations: - - res = validate_email_address(email, **config) - validity.append(res) - t1 = time.time() - validity = sorted(validity, key=lambda x: x["email"]) - - for v in validity: - pprint.pprint(v, indent=4) - - print(f"Time taken: {t1 - t0:.2f}") diff --git a/dsg_lib/common_functions/logging_config.py b/dsg_lib/common_functions/logging_config.py index 4d67e1f9..980bfd77 100644 --- a/dsg_lib/common_functions/logging_config.py +++ b/dsg_lib/common_functions/logging_config.py @@ -2,7 +2,7 @@ """ This module provides a comprehensive logging setup using the loguru library, facilitating easy logging management for Python applications. -The `config_log` function, central to this module, allows for extensive customization of logging behavior. It supports specifying the logging directory, log file name, logging level, and controls for log rotation, retention, and formatting among other features. Additionally, it offers advanced options like backtrace and diagnose for in-depth debugging, and the ability to append the application name to the log file for clearer identification. +The `config_log` function, central to this module, allows for extensive customization of logging behavior. It supports specifying the logging directory, log file name, logging level, and controls for log rotation, retention, and formatting among other features. Additionally, it offers advanced options like backtrace and diagnose for in-depth debugging, the ability to append the application name to the log file for clearer identification, and control over logger propagation via the `log_propagate` parameter. Usage example: @@ -15,6 +15,7 @@ log_rotation='100 MB', # Size threshold for log rotation log_retention='30 days', # Duration to retain old log files enqueue=True, # Enqueue log messages + log_propagate=False, # Control log propagation ) # Example log messages @@ -228,6 +229,7 @@ def config_log( append_app_name: bool = False, enqueue: bool = True, intercept_standard_logging: bool = True, + log_propagate: bool = False, compression: str = "zip", ): """ @@ -249,6 +251,7 @@ def config_log( append_app_name (bool): Whether to append the application name to the log file name. Defaults to False. enqueue (bool): Whether to enqueue log messages for asynchronous processing. Defaults to True. intercept_standard_logging (bool): Whether to intercept standard logging calls. Defaults to True. + log_propagate (bool): Whether to propagate log messages to ancestor loggers. Defaults to False. compression (str): The compression method for rotated log files (e.g., "zip"). Defaults to 'zip'. Returns: @@ -269,6 +272,7 @@ def config_log( append_app_name=True, enqueue=False, intercept_standard_logging=False, + log_propagate=False, compression='gz' ) @@ -334,7 +338,6 @@ def config_log( diagnose=log_diagnose, ) - basic_config_handlers: list = [] class InterceptHandler(logging.Handler): """ @@ -377,19 +380,24 @@ def emit(self, record): ) # pragma: no cover if intercept_standard_logging: - # Add interceptor handler to all existing loggers - for name in logging.Logger.manager.loggerDict: - logging.getLogger(name).addHandler(InterceptHandler()) - - # Add interceptor handler to the root logger - basic_config_handlers.append(InterceptHandler()) - - # Set the root logger's level to the lowest level possible - logging.getLogger().setLevel(logging.NOTSET) - - if intercept_standard_logging: - # Append an InterceptHandler instance to the handlers list if intercept_standard_logging is True - basic_config_handlers.append(InterceptHandler()) - - if len(basic_config_handlers) > 0: - logging.basicConfig(handlers=basic_config_handlers, level=logging_level.upper()) + # Remove all handlers from all loggers to prevent duplicates + for logger_name in logging.Logger.manager.loggerDict: + log_instance = logging.getLogger(logger_name) + log_instance.handlers = [] + # Optionally, set propagate to False if you want to avoid double propagation + log_instance.propagate = log_propagate + + # Remove handlers from root logger + root_logger = logging.getLogger() + root_logger.handlers = [] + + # Add InterceptHandler to all loggers (including root) + for logger_name in logging.Logger.manager.loggerDict: + logging.getLogger(logger_name).addHandler(InterceptHandler()) + root_logger.addHandler(InterceptHandler()) + + # Set the root logger's level to the lowest level possible + root_logger.setLevel(logging.NOTSET) + else: + # If not intercepting, you may want to configure basicConfig as before + logging.basicConfig(level=logging_level.upper()) diff --git a/ex.py b/ex.py new file mode 100644 index 00000000..6ebda078 --- /dev/null +++ b/ex.py @@ -0,0 +1,39 @@ +from fastapi import FastAPI, Request +from fastapi.responses import HTMLResponse, JSONResponse +from pydantic import BaseModel, Field +from PySchemaForms.form import FormConfig, FormBuilder + +app = FastAPI() + +# Define a simple Pydantic model for the form +class SimpleForm(BaseModel): + name: str = Field(..., title="Your Name") + age: int = Field(..., title="Your Age") + +# Configure the form +form_config = FormConfig( + post_url="/submit", + theme="bootstrap5", + form_title="Simple Example Form" +) +form_builder = FormBuilder(SimpleForm, form_config) + +@app.get("/", response_class=HTMLResponse) +async def show_form(): + html = form_builder.render_html() + return HTMLResponse(content=html) + +@app.post("/submit") +async def submit_form(request: Request): + data = await request.json() + try: + form = SimpleForm(**data) + # Here you could process/store the form data + return JSONResponse({"message": "Success", "data": form.dict()}) + except Exception as e: + return JSONResponse({"error": str(e)}, status_code=400) + +if __name__ == "__main__": + import uvicorn + uvicorn.run(app, host="127.0.0.1", port=5000) +# To run the example, save this code in a file named `example.py` and run it using: diff --git a/examples/fastapi_example.py b/examples/fastapi_example.py index a839b161..9edf034b 100644 --- a/examples/fastapi_example.py +++ b/examples/fastapi_example.py @@ -105,7 +105,7 @@ log_serializer=False, logging_directory="log", log_name="log.log", - intercept_standard_logging=False, + intercept_standard_logging=True, ) # Create a DBConfig instance config = { diff --git a/makefile b/makefile index 16d8bb5a..02f053c9 100644 --- a/makefile +++ b/makefile @@ -1,6 +1,6 @@ # Variables REPONAME = devsetgo_lib -APP_VERSION = 2025.04.17-001 +APP_VERSION = 2025.05.04-001 PYTHON = python3 PIP = $(PYTHON) -m pip PYTEST = $(PYTHON) -m pytest @@ -83,7 +83,7 @@ test: ## Run the project's tests pytest genbadge coverage -i /workspaces/$(REPONAME)/coverage.xml genbadge tests -i /workspaces/$(REPONAME)/report.xml - sed -i "s|/workspaces/$(REPONAME)|$(shell pwd)|" coverage.xml + sed -i 's|.*|dsg_lib|' /workspaces/devsetgo_lib/coverage.xml tests: test ## Run the project's tests diff --git a/pyproject.toml b/pyproject.toml index 544fb97f..9da8505b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "devsetgo_lib" -version = "2025.4.17.1" +version = "2025.5.4.1" requires-python = ">=3.9" description = "DevSetGo Library is a Python library offering reusable functions for efficient coding. It includes file operations, calendar utilities, pattern matching, advanced logging with loguru, FastAPI endpoints, async database handling, and email validation. Designed for ease of use and versatility, it's a valuable tool for Python developers.\n" keywords = [ "python", "library", "reusable functions", "file operations", "calendar utilities", "pattern matching", "logging", "loguru", "FastAPI", "async database", "CRUD operations", "email validation", "development tools",] @@ -32,8 +32,10 @@ postgres = [ "asyncpg>=0.21.0", "sqlalchemy>=2.0.10,<2.0.99",] sqlite = [ "aiosqlite>=0.17.0", "sqlalchemy>=2.0.10,<2.0.99",] oracle = [ "oracledb>=2.4.1,<2.5.0", "sqlalchemy>=2.0.10,<2.0.99",] mssql = [ "aioodbc>=0.4.1", "sqlalchemy>=2.0.10,<2.0.99",] +cockroachdb = [ "sqlalchemy-cockroachdb<2.0.2", "sqlalchemy>=2.0.10,<2.0.99", "asyncpg>=0.21.0",] +mysql = [ "asyncmy>=0.2.10", "sqlalchemy>=2.0.10,<2.0.99",] fastapi = [ "fastapi>=0.100.0", "pydantic[email]>=2.0",] -all = [ "asyncpg>=0.21.0", "sqlalchemy>=2.0.10,<2.0.99", "aiosqlite>=0.17.0", "oracledb>=2.4.1,<2.5.0", "fastapi>=0.100.0", "pydantic[email]>=2.0", "aioodbc>=0.4.1",] +all = [ "asyncpg>=0.21.0", "sqlalchemy>=2.0.10,<2.0.99", "aiosqlite>=0.17.0", "oracledb>=2.4.1,<2.5.0", "fastapi>=0.100.0", "pydantic[email]>=2.0", "aioodbc>=0.4.1", "sqlalchemy-cockroachdb<2.0.0", "asyncmy>=0.2.10",] [project.scripts] @@ -64,7 +66,7 @@ line_length = 100 version_format = "{current_date}-{build_count:03}" date_format = "%Y.%m.%d" timezone = "America/New_York" -git_tag = false +git_tag = true auto_commit = false [[tool.bumpcalver.file]] path = "makefile" @@ -72,12 +74,20 @@ file_type = "makefile" variable = "APP_VERSION" version_standard = "standard" +# [[tool.bumpcalver.file]] +# path = "sonar-project.properties" +# file_type = "toml" +# variable = "project.version" +# version_standard = "python" + + [[tool.bumpcalver.file]] path = "pyproject.toml" file_type = "toml" -variable = "project.version" +variable = "sonar.projectVersion" version_standard = "python" + [[tool.bumpcalver.file]] path = "dsg_lib/__init__.py" file_type = "python" @@ -97,13 +107,13 @@ source = [ "dsg_lib",] omit = [ "setup.py", "_venv/*", "tests/*", "examples/*", "ex.py", "ex_*.py",] [tool.coverage.report] -exclude_lines = [ "pragma: no cover", "if __name__", "def main", "import_sqlalchemy",] +exclude_lines = [ "pragma: no cover", "if __name__ == .__main__.:", "def main", "import_sqlalchemy",] [tool.pytest.ini_options] norecursedirs = [ "/tests",] testpaths = [ "tests",] python_files = [ "test_*.py", "*_test.py",] -addopts = [ "--cov=./", "--cov-report=html", "--cov-report=xml", "--junitxml=report.xml", "--html=htmlcov/_test_report.html", "--self-contained-html", "-ra", "--strict-markers", "--tb=short", "-p", "pytester",] +addopts = [ "--cov=dsg_lib", "--cov-report=html", "--cov-report=xml", "--junitxml=report.xml", "--html=htmlcov/_test_report.html", "--self-contained-html", "-ra", "--strict-markers", "--tb=short", "-p", "pytester",] [tool.hatch.build.targets.sdist] include = [ "/dsg_lib",] diff --git a/report.xml b/report.xml index 505cf43f..65ea015c 100644 --- a/report.xml +++ b/report.xml @@ -1 +1 @@ - + diff --git a/requirements.txt b/requirements.txt index ddbd4d13..3a1a3894 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ asyncpg==0.30.0 # Vulnerabilities: None autoflake==2.3.1 # Vulnerabilities: None autopep8==2.3.2 # Vulnerabilities: None black==25.1.0 # Vulnerabilities: None -bumpcalver==2024.12.14.1 # Vulnerabilities: None +bumpcalver==2025.4.12.1 # From 2024.12.14.1 | Vulnerabilities: None click==8.1.8 # Vulnerabilities: None fastapi[all]==0.115.12 # Vulnerabilities: None flake8==7.2.0 # Vulnerabilities: None @@ -12,33 +12,33 @@ genbadge[all]==1.1.2 # Vulnerabilities: None hatchling==1.27.0 # Vulnerabilities: None loguru==0.7.3 # Vulnerabilities: None mike==2.1.3 # Vulnerabilities: None -mkdocs-material==9.6.11 # From 9.6.9 | Vulnerabilities: None -mkdocs-print-site-plugin==2.7.2 # From 2.7.1 | Vulnerabilities: None -mkdocstrings[python,shell]==0.29.1 # From 0.29.0 | Vulnerabilities: None -oracledb==3.1.0 # From 3.0.0 | Vulnerabilities: None -packaging==24.2 # Vulnerabilities: None +mkdocs-material==9.6.12 # From 9.6.11 | Vulnerabilities: None +mkdocs-print-site-plugin==2.7.2 # Vulnerabilities: None +mkdocstrings[python,shell]==0.29.1 # Vulnerabilities: None +oracledb==3.1.0 # Vulnerabilities: None +packaging==25.0 # From 24.2 | Vulnerabilities: None pre-commit==4.2.0 # Vulnerabilities: None psycopg2==2.9.10 # Vulnerabilities: None Pygments==2.19.1 # Vulnerabilities: None -pylint==3.3.6 # Vulnerabilities: None -pymdown-extensions==10.14.3 # Vulnerabilities: None +pylint==3.3.7 # From 3.3.6 | Vulnerabilities: None +pymdown-extensions==10.15 # From 10.14.3 | Vulnerabilities: None pytest==8.3.5 # Vulnerabilities: None pytest-asyncio==0.26.0 # Vulnerabilities: None -pytest-cov==6.1.1 # From 6.0.0 | Vulnerabilities: None +pytest-cov==6.1.1 # Vulnerabilities: None pytest-html==4.1.1 # Vulnerabilities: None pytest-mock==3.14.0 # Vulnerabilities: None pytest-runner==6.0.1 # Vulnerabilities: None pytest-xdist==3.6.1 # Vulnerabilities: None python-json-logger==3.3.0 # Vulnerabilities: None PyYAML==6.0.2 # Vulnerabilities: None -ruff==0.11.4 # From 0.11.2 | Vulnerabilities: None +ruff==0.11.8 # From 0.11.4 | Vulnerabilities: None SQLAlchemy==2.0.40 # Vulnerabilities: None -structlog==25.2.0 # Vulnerabilities: None +structlog==25.3.0 # From 25.2.0 | Vulnerabilities: None toml==0.10.2 # Vulnerabilities: None tox==4.25.0 # Vulnerabilities: None tqdm==4.67.1 # Vulnerabilities: None twine==6.1.0 # Vulnerabilities: None watchdog==6.0.0 # Vulnerabilities: None -watchfiles==1.0.4 # Vulnerabilities: None +watchfiles==1.0.5 # From 1.0.4 | Vulnerabilities: None wheel==0.45.1 # Vulnerabilities: None xmltodict==0.14.2 # Vulnerabilities: None diff --git a/sonar-project.properties b/sonar-project.properties index 53cf957f..2c621502 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,7 +1,7 @@ sonar.projectKey=devsetgo_devsetgo_lib sonar.organization=devsetgo sonar.projectName=devsetgo_lib -sonar.projectVersion=0.11.0 +sonar.projectVersion=2025.5.4.1 sonar.language=python sonar.python.version=3.9, 3.10, 3.11,3.12 sonar.sources=dsg_lib diff --git a/tests/test_file_functions.py b/tests/test_common_functions/test_file_functions/test_file_functions.py similarity index 100% rename from tests/test_file_functions.py rename to tests/test_common_functions/test_file_functions/test_file_functions.py diff --git a/tests/test_common_functions/test_logging_config.py b/tests/test_common_functions/test_logging_config.py index 44ecaedc..33f475e9 100644 --- a/tests/test_common_functions/test_logging_config.py +++ b/tests/test_common_functions/test_logging_config.py @@ -23,6 +23,7 @@ def test_config_log_with_valid_params(self, mock_logger): append_app_name=False, enqueue=True, intercept_standard_logging=True, + log_propagate=False, compression="zip", ) mock_logger.configure.assert_called_once() @@ -30,15 +31,15 @@ def test_config_log_with_valid_params(self, mock_logger): def test_config_log_with_invalid_level(self): with self.assertRaises(ValueError): - config_log(logging_level="INVALID") + config_log(logging_level="INVALID", log_propagate=False) # def test_config_log_with_invalid_log_name(self): # with self.assertRaises(ValueError): - # config_log(log_name="invalid_name") + # config_log(log_name="invalid_name", log_propagate=False) @patch("dsg_lib.common_functions.logging_config.logger") def test_config_log_with_app_name(self, mock_logger): - config_log(app_name="my_app", append_app_name=True) + config_log(app_name="my_app", append_app_name=True, log_propagate=False) mock_logger.configure.assert_called_once() mock_logger.add.assert_called_once()