DSG_LIB
Description | Common functions for Python applications. This is to increase reusability and limit rewritting the same functions in multiple applications. It also allows for defects to be addressed quickly and then be propigated across applications. |
Author(s) | Mike Ryan |
Repository | https://github.com/devsetgo/dsg_lib |
Copyright | Copyright © 2016 - 2024 Mike Ryan |
Table of Contents
Support Python Versions
CI/CD Pipeline:
SonarCloud:
DevSetGo Common Library¶
Introduction¶
The DevSetGo Common Library is a comprehensive package of common functions designed to eliminate repetitive coding and enhance code reusability. It aims to save developers time and effort across various projects.
Compatibility and Testing¶
- Tested on: Windows, Linux.
- Compatibility: Potentially compatible with MacOS (feedback on issues is appreciated).
Library Functions¶
Common Functions¶
- File Functions:
- CSV File Functions
- JSON File Functions
- Text File Functions
- Folder Functions:
- Make Directory
- Remove Directory
- Last File Changed
- Directory List
- Calendar Functions:
- Get Month
- Get Month Number
- Patterns:
- Pattern Between Two Characters
- Logging:
- Logging configuration and interceptor
FastAPI Endpoints¶
- Systems Health Endpoints:
- Status/Health, Heapdump, Uptime
- HTTP Codes:
- Method to generate HTTP response codes
Async Database¶
- Database Config
- Async Session
- CRUD Operations
Examples and Usage¶
Refer to the Recipes Pages
Installation Guide¶
pip install devsetgo-lib
# Aysync database setup
pip install devsetgo-lib[sqlite]
pip install devsetgo-lib[postgres]
# Consider these experimental and untested
pip install devsetgo-lib[oracle]
pip install devsetgo-lib[mssql]
pip install devsetgo-lib[mysql]
# For adding FastAPI endpoints
pip install devsetgo-lib[fastapi]
# Install everything
pip install devsetgo-lib[all]
Contribution and Feedback¶
Contributions and feedback are highly appreciated. Please refer to our Contribution Guidelines.
License¶
Author Information¶
Further Documentation¶
For more detailed information, visit LINK_TO_DETAILED_DOCUMENTATION.
Quick Start¶
Install¶
pip install devsetgo-lib
# Aysync database setup
pip install devsetgo-lib[sqlite]
pip install devsetgo-lib[postgres]
# Consider these experimental and untested
pip install devsetgo-lib[oracle]
pip install devsetgo-lib[mssql]
pip install devsetgo-lib[mysql]
# For adding FastAPI endpoints
pip install devsetgo-lib[fastapi]
# Install everything
pip install devsetgo-lib[all]
See documentation for more examples of library use
Common Functions ↵
Reference¶
dsg_lib.common_functions.logging_config
¶
This module provides a function to configure and set up a logger using the loguru package.
The config_log
function takes several optional parameters to customize the logger's behavior,
including the logging directory, log name, logging level, log rotation size, log retention period,
and more. It also provides an option to append the application name to the log file name.
Example:
from dsg_lib.common_functions.logging_config import config_log
config_log(
logging_directory='logs', # Directory where logs will be stored
log_name='log', # Name of the log file (extension will be added automatically set v0.12.2)
logging_level='DEBUG', # Logging level
log_rotation='100 MB', # Log rotation size
log_retention='30 days', # Log retention period
log_backtrace=True, # Enable backtrace
log_format="<green>{time:YYYY-MM-DD HH:mm:ss.SSSSSS}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>", # Log format
log_serializer=False, # Disable log serialization
log_diagnose=True, # Enable diagnose
app_name='my_app', # Application name
append_app_name=True # Append application name to the log file name
)
logger.debug("This is a debug message")
logger.info("This is an info message")
logger.error("This is an error message")
logger.warning("This is a warning message")
logger.critical("This is a critical message")
config_log(logging_directory='log', log_name='log', logging_level='INFO', log_rotation='100 MB', log_retention='30 days', log_backtrace=False, log_format=None, log_serializer=False, log_diagnose=False, app_name=None, append_app_name=False)
¶
Configures and sets up a logger using the loguru package.
Parameters: - logging_directory (str): The directory where logs will be stored. Default is "log". - log_name (str): The name of the log file. Default is "log" (extension automatically set in 0.12.2). - logging_level (str): The logging level. Default is "INFO". - log_rotation (str): The log rotation size. Default is "100 MB". - log_retention (str): The log retention period. Default is "30 days". - log_backtrace (bool): Whether to enable backtrace. Default is False. - log_format (str): The log format. Default is None. - log_serializer (bool): Whether to disable log serialization. Default is False. - log_diagnose (bool): Whether to enable diagnose. Default is False. - app_name (str): The application name. Default is None. - append_app_name (bool): Whether to append the application name to the log file name. Default is False.
Raises: - ValueError: If the provided logging level is not valid.
Usage Example:
from logging_config import config_log
config_log(
logging_directory='logs',
log_name='app.log',
logging_level='DEBUG',
log_rotation='500 MB',
log_retention='10 days',
log_backtrace=True,
log_format="<green>{time:YYYY-MM-DD HH:mm:ss.SSSSSS}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
log_serializer=False,
log_diagnose=True,
app_name='my_app',
append_app_name=True
)
Source code in dsg_lib/common_functions/logging_config.py
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
|
Reference¶
dsg_lib.common_functions.file_functions
¶
file_functions.py
This module provides a function to delete a file with a specified name from a specified directory.
Functions:
Name | Description |
---|---|
delete_file |
str) -> str:
Deletes a file with the specified file name from the directory specified
by the Args: file_name (str): The name of the file to be deleted. Returns: str: A string indicating that the file has been deleted. Raises: TypeError: If the file name is not a string. ValueError: If the file name contains a forward slash or backslash, or if the file type is not supported. FileNotFoundError: If the file does not exist. |
Example:
from dsg_lib.common_functions import file_functions
file_functions.delete_file("test.csv")
# Outputs: 'complete'
create_sample_files(file_name, sample_size)
¶
Create sample CSV and JSON files with random data.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
file_name |
str
|
The base name for the sample files (without extension). |
required |
sample_size |
int
|
The number of rows to generate for the sample files. |
required |
Returns:
Type | Description |
---|---|
None
|
None |
Raises:
Type | Description |
---|---|
Exception
|
If an error occurs while creating the sample files. |
Example: ```python from dsg_lib.common_functions import file_functions
file_functions.create_sample_files("test", 100)
Creates 'test.csv' and 'test.json' each with 100 rows of random data ```¶
Source code in dsg_lib/common_functions/file_functions.py
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 |
|
delete_file(file_name)
¶
Deletes a file with the specified file name from the specified directory. The file type is determined by the file extension.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
directory_to_files |
str
|
The directory where the file is located. |
required |
file_name |
str
|
The name of the file to be deleted. |
required |
Returns:
Name | Type | Description |
---|---|---|
str |
str
|
A message indicating whether the file has been deleted successfully |
str
|
or an error occurred. |
Raises:
Type | Description |
---|---|
TypeError
|
If the directory or file name is not a string. ValueError: If |
is not supported. FileNotFoundError
|
If the file does not exist. |
Example:
from dsg_lib.common_functions import file_functions
file_functions.delete_file("test.csv")
# Outputs: 'File deleted successfully'
Source code in dsg_lib/common_functions/file_functions.py
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
|
generate_random_date()
¶
Generate a random datetime string in the format yyyy-mm-dd hh:mm:ss.ffffff.
Returns:
Name | Type | Description |
---|---|---|
str |
str
|
A randomly generated datetime string. |
Example:
from dsg_lib.common_functions import file_functions
random_date = file_functions.generate_random_date()
# Returns: '1992-03-15 10:30:45.123456'
Source code in dsg_lib/common_functions/file_functions.py
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 |
|
open_csv(file_name, delimiter=',', quote_level='minimal', skip_initial_space=True)
¶
Opens a CSV file with the specified file name and returns its contents as a list of dictionaries.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
file_name |
str
|
The name of the file to open. Should include the '.csv' |
required |
extension. |
delimiter (str
|
The character used to separate |
required |
fields |
in the CSV file. Defaults to ','. quote_level (str
|
|
required |
optional) |
Whether to skip initial whitespace in the CSV file. Defaults |
required |
Returns:
Name | Type | Description |
---|---|---|
list |
list
|
The contents of the CSV file as a list of dictionaries. Each |
list
|
dictionary represents a row in the CSV file, where the keys are column |
|
list
|
names and the values are the data for those columns. |
Raises:
Type | Description |
---|---|
TypeError
|
If |
is not a valid level. FileNotFoundError
|
If the file does not exist. |
Example:
from dsg_lib.common_functions import file_functions data =
file_functions.open_csv("test.csv", delimiter=";", quote_level="all",
skip_initial_space=False) # Returns: [{'column1': 'value1', 'column2':
'value2'}]
Source code in dsg_lib/common_functions/file_functions.py
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 |
|
open_json(file_name)
¶
Open a JSON file and load its contents into a dictionary.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
file_name |
str
|
The name of the JSON file to open. |
required |
Returns:
Name | Type | Description |
---|---|---|
dict |
dict
|
The contents of the JSON file as a dictionary. |
Raises:
Type | Description |
---|---|
TypeError
|
If the file name is not a string. FileNotFoundError: If the |
Source code in dsg_lib/common_functions/file_functions.py
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
|
open_text(file_name)
¶
Opens a text file with the specified file name and returns its contents as a string.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
file_name |
str
|
The name of the file to open. Should include the '.txt' |
required |
Returns:
Name | Type | Description |
---|---|---|
str |
str
|
The contents of the text file as a string. |
Raises:
Type | Description |
---|---|
TypeError
|
If the |
forward slash. FileNotFoundError
|
If the file does not exist. |
Example:
from dsg_lib.common_functions import file_functions
data = file_functions.open_text("test.txt")
# Returns: 'This is a test text file.'
Source code in dsg_lib/common_functions/file_functions.py
591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 |
|
save_csv(file_name, data, root_folder=None, delimiter=',', quotechar='"')
¶
Saves a list of dictionaries as a CSV file with the specified file name in the specified directory. Each dictionary in the list should represent a row in the CSV file.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
file_name |
str
|
The name of the file to save the data in. Should |
required |
include |
the '.csv' extension. data (list
|
The data to be saved. Each |
required |
optional) |
The root directory where the file will be saved. If None, the |
required | |
(str, |
optional
|
The character used to separate fields in the CSV file. |
required |
Defaults |
to ','. quotechar (str
|
The character used to quote |
required |
Returns:
Name | Type | Description |
---|---|---|
str |
str
|
A message indicating whether the file has been saved successfully |
str
|
or an error occurred. |
Raises:
Type | Description |
---|---|
TypeError
|
If the data is not a list, or the file name, delimiter, or |
quotechar is not a string. ValueError
|
If the file name does not end |
Example: ```python from dsg_lib.common_functions import file_functions
data = [{"column1": "value1", "column2": "value2"}]
file_functions.save_csv("test.csv", data, "/path/to/directory", delimiter=";", quotechar="'")
Saves data to '/path/to/directory/test.csv'¶
```
Source code in dsg_lib/common_functions/file_functions.py
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 |
|
save_json(file_name, data, root_folder=None)
¶
Saves a dictionary or a list as a JSON file with the specified file name in the specified directory.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
file_name |
str
|
The name of the file to save the data in. Should |
required |
include |
the '.json' extension. data (list or dict
|
The data to be |
required |
saved. |
root_folder (str
|
The root directory where the file |
required |
Returns:
Name | Type | Description |
---|---|---|
str |
str
|
A message indicating whether the file has been saved successfully |
str
|
or an error occurred. |
Raises:
Type | Description |
---|---|
TypeError
|
If the data is not a list or a dictionary, or the file name |
or directory is not a string. ValueError
|
If the file name contains a |
Example:
from dsg_lib.common_functions import file_functions
data = {"key": "value"}
file_functions.save_json("test.json", data, "/path/to/directory")
# Saves data to '/path/to/directory/test.json'
Source code in dsg_lib/common_functions/file_functions.py
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
|
save_text(file_name, data, root_folder=None)
¶
Saves a string of text to a file with the specified file name in the specified directory.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
file_name |
str
|
The name of the file to save the data in. Should not |
required |
include |
the '.txt' extension. data (str
|
The text data to be saved. |
required |
root_folder |
str
|
The root directory where the file will be |
None
|
Returns:
Name | Type | Description |
---|---|---|
str |
str
|
A message indicating whether the file has been saved successfully |
str
|
or an error occurred. |
Raises:
Type | Description |
---|---|
TypeError
|
If the |
contains a forward slash or backslash. FileNotFoundError
|
If the |
Example:
from dsg_lib.common_functions import file_functions
file_functions.save_text("test", "This is a test text file.", "/path/to/directory")
# Saves data to '/path/to/directory/test.txt'
Source code in dsg_lib/common_functions/file_functions.py
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 |
|
Reference¶
dsg_lib.common_functions.folder_functions
¶
This module contains functions for working with directories and files.
Functions:
Name | Description |
---|---|
last_data_files_changed |
Get the last modified file in a |
get_directory_list |
Get a list of directories in the |
specified directory. make_folder |
Make a folder in a |
specific directory. remove_folder |
Remove a folder from the |
Example:
from dsg_lib.common_functions import folder_functions
# Get the last modified file in a directory time_stamp, file_path =
folder_functions.last_data_files_changed("/path/to/directory") # Returns:
(datetime.datetime(2022, 1, 1, 12, 0, 0), '/path/to/directory/test.txt')
# Get a list of directories in the specified directory directories =
folder_functions.get_directory_list("/path/to/directory") # Returns:
['/path/to/directory/dir1', '/path/to/directory/dir2']
# Make a folder in a specific directory
folder_functions.make_folder("/path/to/directory/new_folder") # Creates a new
folder at '/path/to/directory/new_folder'
# Remove a folder from the specified directory
folder_functions.remove_folder("/path/to/directory/old_folder") # Removes the
folder at '/path/to/directory/old_folder'
get_directory_list(file_directory)
¶
Get a list of directories in the specified directory.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
file_directory |
str
|
The path of the directory to check. |
required |
Returns:
Type | Description |
---|---|
List[str]
|
List[str]: A list of directories in the specified directory. |
Raises:
Type | Description |
---|---|
FileNotFoundError
|
If the directory does not exist. |
Example:
from dsg_lib import file_functions
directories = file_functions.get_directory_list("/path/to/directory")
# Returns: ['/path/to/directory/dir1', '/path/to/directory/dir2']
Source code in dsg_lib/common_functions/folder_functions.py
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
|
last_data_files_changed(directory_path)
¶
Get the last modified file in a directory and return its modification time and path.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
directory_path |
str
|
The path of the directory to check. |
required |
Returns:
Type | Description |
---|---|
datetime
|
Tuple[datetime, str]: A tuple containing the modification time and path |
str
|
of the last modified file. |
Raises:
Type | Description |
---|---|
FileNotFoundError
|
If the directory does not exist. |
Example:
from dsg_lib import file_functions
time_stamp, file_path = file_functions.last_data_files_changed("/path/to/directory")
# Returns: (datetime.datetime(2022, 1, 1, 12, 0, 0), '/path/to/directory/test.txt')
Source code in dsg_lib/common_functions/folder_functions.py
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
|
remove_folder(file_directory)
¶
Remove a folder from the specified directory.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
file_directory |
str
|
The directory containing the folder to be removed. |
required |
Returns:
Type | Description |
---|---|
None
|
None. |
Raises:
Type | Description |
---|---|
FileNotFoundError
|
If the specified directory does not exist. OSError: |
Example:
from dsg_lib.common_functions import file_functions
file_functions.remove_folder("/path/to/directory/old_folder")
# Removes the folder at '/path/to/directory/old_folder'
Source code in dsg_lib/common_functions/folder_functions.py
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
|
Reference¶
dsg_lib.common_functions.patterns
¶
This module contains functions for pattern searching in text using regular expressions.
The main function in this module is pattern_between_two_char
, which searches
for all patterns between two characters in a given string. The function uses
Python's built-in re
module for regex searching and the loguru
module for
logging.
Functions:
Name | Description |
---|---|
pattern_between_two_char |
str, left_characters: str, |
right_characters |
str) -> dict: Searches for all patterns between two characters (left and right) in a given string using regular expressions. |
Example
from dsg_lib.common_functions import patterns
text = "Hello, my name is 'John Doe' and I live in 'New York'." left_char =
"'" right_char = "'"
results = patterns.pattern_between_two_char(text, left_char, right_char)
print(results) ``` This will output: ```python {
'found': ['John Doe', 'New York'], 'matched_found': 2,
'pattern_parameters': {
'left_character': "'", 'right_character': "'", 'regex_pattern':
"'(.+?)'", 'text_string': "Hello, my name is 'John Doe' and I live
in 'New York'."
}
}
pattern_between_two_char(text_string, left_characters, right_characters)
¶
Searches for all patterns between two characters (left and right) in a given string using regular expressions.
This function takes a string and two characters as input, and returns a dictionary containing all patterns found between the two characters in the string. The dictionary also includes the number of matches found and the regex pattern used for searching.
The function uses Python's built-in re
module for regex searching and the
loguru
module for logging.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
text_string |
str
|
The string in which to search for patterns. |
required |
left_characters |
str
|
The character(s) that appear(s) immediately to |
required |
the |
left of the desired pattern. right_characters (str
|
The |
required |
Returns:
Name | Type | Description |
---|---|---|
dict |
dict
|
A dictionary with the following keys: - "found": a list of strings containing all patterns found. - "matched_found": the number of patterns found. - "pattern_parameters": a dictionary with the following keys: - "left_character": the escaped left character string used to build the regex pattern. - "right_character": the escaped right character string used to build the regex pattern. - "regex_pattern": the final regex pattern used for searching. - "text_string": the escaped input string used for searching. |
Example
from dsg_lib.common_functions import patterns
text = "Hello, my name is 'John Doe' and I live in 'New York'."
left_char = "'" right_char = "'"
results = patterns.pattern_between_two_char(text, left_char, right_char)
print(results) ``` This will output: ```python {
'found': ['John Doe', 'New York'], 'matched_found': 2,
'pattern_parameters': {
'left_character': "'", 'right_character': "'", 'regex_pattern':
"'(.+?)'", 'text_string': "Hello, my name is 'John Doe' and I
live in 'New York'."
}
}
Source code in dsg_lib/common_functions/patterns.py
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
|
Reference¶
dsg_lib.common_functions.calendar_functions
¶
This module provides two main functions to convert between month numbers and their corresponding names.
Functions:
Name | Description |
---|---|
get_month |
int) -> str: Converts an integer month number to its corresponding month name. Args: month (int): An integer between 1 and 12 representing the month number. Returns: str: The full name of the month corresponding to the input month number. If the input is not within the range of 1-12, returns "Invalid month number". If the input is not an integer, returns "Invalid input, integer is required". |
get_month_number |
str) -> int: Converts a month name to its corresponding month number. Args: month_name (str): A string containing the full name of a month. Returns: int: The month number corresponding to the input month name. If the input is not a valid month name, returns -1. If the input is not a string, returns "Invalid input, string is required". |
Example:
from dsg_lib.common_functions.calendar_functions import get_month,
get_month_number print(get_month(1))
# Outputs: 'January'
print(get_month_number('January'))
# Outputs: 1
This module is part of the dsg_lib package and is used for handling and converting between month numbers and names.
get_month(month)
¶
Converts an integer month number to its corresponding month name.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
month |
int
|
An integer or integer-like float between 1 and 12 |
required |
Returns:
Name | Type | Description |
---|---|---|
str |
str
|
The full name of the month corresponding to the input month number. If the input is not within the range of 1-12, returns "Invalid month number". If the input is not an integer or integer-like float, returns "Invalid input, integer is required". |
Source code in dsg_lib/common_functions/calendar_functions.py
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
|
get_month_number(month_name)
¶
Converts a month name to its corresponding month number.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
month_name |
str
|
A string containing the full name of a month. |
required |
Returns:
Name | Type | Description |
---|---|---|
int |
int
|
The month number corresponding to the input month name. If the input is not a valid month name or not a string, returns -1. |
Source code in dsg_lib/common_functions/calendar_functions.py
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
|
Ended: Common Functions
FastAPI Functions ↵
Reference¶
dsg_lib.fastapi_functions.http_codes
¶
http_codes.py
This module provides a dictionary of HTTP status codes and their descriptions.
The dictionary ALL_HTTP_CODES
contains the HTTP status codes as keys. Each key
maps to another dictionary that contains a description of the status code, an
extended description, and a link to its documentation on the Mozilla Developer Network (MDN).
Example:
from dsg_lib.fastapi_functions import http_codes
# Get the description, extended description, and link for HTTP status code 200
status_200 = http_codes.ALL_HTTP_CODES[200]
print(status_200)
# {'description': 'OK', 'extended_description': 'The request has succeeded', 'link': 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200'}
Attributes:
Name | Type | Description |
---|---|---|
ALL_HTTP_CODES |
dict
|
A dictionary of HTTP status codes. Each key is an |
DELETE_CODES = generate_code_dict(common_codes + [202, 204, 205, 409])
module-attribute
¶
DELETE_CODES is a dictionary of HTTP status codes for DELETE requests. It includes all the common codes, plus some additional codes that are specific to DELETE requests.
Example:
from dsg_lib.fastapi_functions import http_codes
# Print the dictionary of HTTP status codes for DELETE requests
print(http_codes.DELETE_CODES)
GET_CODES = generate_code_dict(common_codes + [206, 304, 307, 410, 502])
module-attribute
¶
GET_CODES is a dictionary of HTTP status codes for GET requests. It includes all the common codes, plus some additional codes that are specific to GET requests.
Example:
from dsg_lib.fastapi_functions import http_codes
# Print the dictionary of HTTP status codes for GET requests
print(http_codes.GET_CODES)
PATCH_CODES = generate_code_dict(common_codes + [202, 204, 206, 409, 412, 413])
module-attribute
¶
PATCH_CODES is a dictionary of HTTP status codes for PATCH requests. It includes all the common codes, plus some additional codes that are specific to PATCH requests.
Example:
from dsg_lib.fastapi_functions import http_codes
# Print the dictionary of HTTP status codes for PATCH requests
print(http_codes.PATCH_CODES)
POST_CODES = generate_code_dict(common_codes + [201, 202, 205, 307, 409, 413, 415])
module-attribute
¶
POST_CODES is a dictionary of HTTP status codes for POST requests. It includes all the common codes, plus some additional codes that are specific to POST requests.
Example:
from dsg_lib.fastapi_functions import http_codes
# Print the dictionary of HTTP status codes for POST requests
print(http_codes.POST_CODES)
PUT_CODES = generate_code_dict(common_codes + [202, 204, 206, 409, 412, 413])
module-attribute
¶
PUT_CODES is a dictionary of HTTP status codes for PUT requests. It includes all the common codes, plus some additional codes that are specific to PUT requests.
Example:
from dsg_lib.fastapi_functions import http_codes
# Print the dictionary of HTTP status codes for PUT requests
print(http_codes.PUT_CODES)
generate_code_dict(codes, description_only=False)
¶
Generate a dictionary of specific HTTP error codes from the http_codes dictionary.
This function takes a list of HTTP status codes and an optional boolean flag. If the flag is True, the function returns a dictionary where each key is an HTTP status code from the input list and each value is the corresponding description from the ALL_HTTP_CODES dictionary. If the flag is False, the function returns a dictionary where each key is an HTTP status code from the input list and each value is the corresponding dictionary from the ALL_HTTP_CODES dictionary.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
codes |
list
|
A list of HTTP status codes. |
required |
description_only |
bool
|
If True, only the description of the codes will be returned. |
False
|
Returns:
Name | Type | Description |
---|---|---|
dict |
A dictionary where each key is an HTTP error code from the input |
|
list and each value depends on the description_only parameter. If |
||
description_only is True, the value is the description string. If |
||
description_only is False, the value is a dictionary with keys |
||
'description', 'extended_description', and 'link'. |
Example:
from dsg_lib.fastapi_functions import http_codes
# Generate a dictionary for HTTP status codes 200 and 404
status_dict = http_codes.generate_code_dict([200, 404])
print(status_dict)
# {200: {'description': 'OK', 'extended_description': 'The request has succeeded', 'link': 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200'},
# 404: {'description': 'Not Found', 'extended_description': 'The requested resource could not be found', 'link': 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404'}}
# Generate a dictionary for HTTP status codes 200 and 404 with only descriptions
status_dict = http_codes.generate_code_dict([200, 404], description_only=True)
print(status_dict) # {200: 'OK', 404: 'Not Found'}
Source code in dsg_lib/fastapi_functions/http_codes.py
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
|
dsg_lib.fastapi_functions._all_codes
¶
This module contains a dictionary mapping HTTP status codes to their descriptions, extended descriptions, and links to their documentation.
Each key in this dictionary is an HTTP status code, and each value is another dictionary with keys 'description', 'extended_description', and 'link'.
The 'description' key maps to a brief string that describes the HTTP status code. The 'extended_description' key maps to a more detailed explanation of the status code. The 'link' key maps to a string that is a link to the documentation for the HTTP status code.
Example
from dsg_lib.fastapi_functions.http_codes import ALL_HTTP_CODES
# Get the dictionary for HTTP status code 200
status_200 = ALL_HTTP_CODES[200]
print(status_200)
# Output: {'description': 'OK', 'extended_description': 'The request has succeeded.', 'link': 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200'}
# Get the description for HTTP status code 404
description_404 = ALL_HTTP_CODES[404]['description']
print(description_404) # Output: 'Not Found'
# Get the extended description for HTTP status code 200
extended_description_200 = ALL_HTTP_CODES[200]['extended_description']
print(extended_description_200) # Output: 'The request has succeeded.'
# Get the link to the documentation for HTTP status code 500
link_500 = ALL_HTTP_CODES[500]['link']
print(link_500) # Output: 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500'
Reference¶
dsg_lib.fastapi_functions.system_health_endpoints
¶
This module provides a configurable health endpoint for a FastAPI application. It includes the following routes:
-
/api/health/status
: Returns the status of the application. If the application is running, it will return{"status": "UP"}
. This endpoint can be enabled or disabled using the configuration. -
/api/health/uptime
: Returns the uptime of the application in a dictionary with the keys "Days", "Hours", "Minutes", and "Seconds". The uptime is calculated from the time the application was started. This endpoint can be enabled or disabled using the configuration. -
/api/health/heapdump
: Returns a heap dump of the application. The heap dump is a list of dictionaries, each representing a line of code. Each dictionary includes the filename, line number, size of memory consumed, and the number of times the line is referenced. This endpoint can be enabled or disabled using the configuration.
The module uses the FastAPI
, time
, tracemalloc
, loguru
, packaging
, and
dsg_lib.fastapi.http_codes
modules.
Functions:
Name | Description |
---|---|
create_health_router |
dict) -> FastAPI.APIRouter: Creates a FastAPI router with health endpoints based on the provided configuration. |
Example
from FastAPI import FastAPI
from dsg_lib.fastapi_functions import
system_health_endpoints
app = FastAPI()
# User configuration
config = {
"enable_status_endpoint": True,
"enable_uptime_endpoint": False,
"enable_heapdump_endpoint": True,
}
# Health router
health_router =
system_health_endpoints.create_health_router(config)
app.include_router(health_router, prefix="/api/health",
tags=["system-health"])
# Get the status of the application
response = client.get("/api/health/status")
print(response.json()) # {"status": "UP"}
# Get the uptime of the application response =
client.get("/api/health/uptime")
print(response.json())
# {"uptime": {"Days": 0, "Hours": 0, "Minutes": 1, "Seconds": 42.17}}
# Get the heap dump of the application response =
client.get("/api/health/heapdump")
print(response.json())
# {"memory_use":{"current": "123456", "peak": "789012"}, "heap_dump": [{"filename": "main.py", "lineno": 10, "size": 1234, "count": 1}, ...]}
create_health_router(config)
¶
Create a health router with the following endpoints:
-
/status
: Returns the status of the application. This endpoint can be enabled or disabled using theenable_status_endpoint
key in the configuration. -
/uptime
: Returns the uptime of the application. This endpoint can be enabled or disabled using theenable_uptime_endpoint
key in the configuration. -
/heapdump
: Returns a heap dump of the application. This endpoint can be enabled or disabled using theenable_heapdump_endpoint
key in the configuration.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
config |
dict
|
A dictionary with the configuration for the endpoints. |
required |
Returns:
Name | Type | Description |
---|---|---|
APIRouter |
A FastAPI router with the configured endpoints. |
Example
from FastAPI import FastAPI
from dsg_lib.fastapi_functions import
system_health_endpoints
app = FastAPI()
# User configuration
config = {
"enable_status_endpoint": True,
"enable_uptime_endpoint": False,
"enable_heapdump_endpoint": True,
}
# Health router
health_router =
system_health_endpoints.create_health_router(config)
app.include_router(health_router, prefix="/api/health",
tags=["system-health"])
# Get the status of the application
response = client.get("/api/health/status")
print(response.json()) # {"status": "UP"}
# Get the uptime of the application response =
client.get("/api/health/uptime")
print(response.json())
# {"uptime": {"Days": 0, "Hours": 0, "Minutes": 1, "Seconds": 42.17}}
# Get the heap dump of the application response =
client.get("/api/health/heapdump")
print(response.json())
# {"memory_use":{"current": "123456", "peak": "789012"}, "heap_dump": [{"filename": "main.py", "lineno": 10, "size": 1234, "count": 1}, ...]}
Source code in dsg_lib/fastapi_functions/system_health_endpoints.py
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 |
|
Ended: FastAPI Functions
Database Functions ↵
Reference¶
dsg_lib.async_database_functions.base_schema
¶
This module defines the base schema for database models in the application.
The module uses SQLAlchemy as the ORM and provides a SchemaBase
class that all
other models should inherit from. The SchemaBase
class includes common columns
that are needed for most models like pkid
, date_created
, and date_updated
.
pkid
: A unique identifier for each record. It's a string representation of a UUID.date_created
: The date and time when a particular row was inserted into the table. It defaults to the current UTC time when the instance is created.date_updated
: The date and time when a particular row was last updated. It defaults to the current UTC time whenever the instance is updated.
To create a new database model, import this module and extend the SchemaBase
class.
Example:
from dsg_lib.async_database_functions import base_schema
class MyModel(base_schema.SchemaBaseSQLite):
# Define your model-specific columns here my_column =
base_schema.Column(base_schema.String(50))
SchemaBaseCockroachDB
¶
This class provides a base schema that includes common columns for most models when using a CockroachDB database. CockroachDB uses the same syntax as PostgreSQL. All other models should inherit from this class.
Attributes:
Name | Type | Description |
---|---|---|
pkid |
str
|
A unique identifier for each record. It's a string |
date_created |
datetime
|
The date and time when a particular row was |
date_updated |
datetime
|
The date and time when a particular row was |
Example:
from dsg_lib.async_database_functions import base_schema
from sqlalchemy.orm import declarative_base
BASE = declarative_base()
class MyModel(base_schema.SchemaBaseCockroachDB, BASE):
# Define your model-specific columns here
my_column = base_schema.Column(base_schema.String(50))
Source code in dsg_lib/async_database_functions/base_schema.py
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 |
|
SchemaBaseFirebird
¶
This class provides a base schema that includes common columns for most models when using a Firebird database. All other models should inherit from this class.
Attributes:
Name | Type | Description |
---|---|---|
pkid |
str
|
A unique identifier for each record. It's a string |
date_created |
datetime
|
The date and time when a particular row was |
date_updated |
datetime
|
The date and time when a particular row was |
Example:
from dsg_lib.async_database_functions import base_schema
from sqlalchemy.orm import declarative_base
BASE = declarative_base()
class MyModel(base_schema.SchemaBaseFirebird, BASE):
# Define your model-specific columns here
my_column = base_schema.Column(base_schema.String(50))
Source code in dsg_lib/async_database_functions/base_schema.py
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 |
|
SchemaBaseMSSQL
¶
This class provides a base schema that includes common columns for most models when using a Microsoft SQL Server database. All other models should inherit from this class.
Attributes:
Name | Type | Description |
---|---|---|
pkid |
str
|
A unique identifier for each record. It's a string |
date_created |
datetime
|
The date and time when a particular row was |
date_updated |
datetime
|
The date and time when a particular row was |
Example:
from dsg_lib.async_database_functions import base_schema
from sqlalchemy.orm import declarative_base
BASE = declarative_base()
class MyModel(base_schema.SchemaBaseMSSQL, BASE):
# Define your model-specific columns here
my_column = base_schema.Column(base_schema.String(50))
Source code in dsg_lib/async_database_functions/base_schema.py
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 |
|
SchemaBaseMySQL
¶
This class provides a base schema that includes common columns for most models when using a MySQL database. All other models should inherit from this class.
Attributes:
Name | Type | Description |
---|---|---|
pkid |
str
|
A unique identifier for each record. It's a string |
date_created |
datetime
|
The date and time when a particular row was |
date_updated |
datetime
|
The date and time when a particular row was |
Example:
from dsg_lib.async_database_functions import base_schema
from sqlalchemy.orm import declarative_base
BASE = declarative_base()
class MyModel(base_schema.SchemaBaseMySQL, BASE):
# Define your model-specific columns here
my_column = base_schema.Column(base_schema.String(50))
Source code in dsg_lib/async_database_functions/base_schema.py
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
|
SchemaBaseOracle
¶
This class provides a base schema that includes common columns for most models when using an Oracle database. All other models should inherit from this class.
Attributes:
Name | Type | Description |
---|---|---|
pkid |
str
|
A unique identifier for each record. It's a string |
date_created |
datetime
|
The date and time when a particular row was |
date_updated |
datetime
|
The date and time when a particular row was |
Example:
from dsg_lib.async_database_functions import base_schema
from sqlalchemy.orm import declarative_base
BASE = declarative_base()
class MyModel(base_schema.SchemaBaseOracle, BASE):
# Define your model-specific columns here
my_column = base_schema.Column(base_schema.String(50))
Source code in dsg_lib/async_database_functions/base_schema.py
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
|
SchemaBasePostgres
¶
This class provides a base schema that includes common columns for most models when using a PostgreSQL database. All other models should inherit from this class.
Attributes:
Name | Type | Description |
---|---|---|
pkid |
str
|
A unique identifier for each record. It's a string |
date_created |
datetime
|
The date and time when a particular row was |
date_updated |
datetime
|
The date and time when a particular row was |
Example:
from dsg_lib.async_database_functions import base_schema
from sqlalchemy.orm import declarative_base
BASE = declarative_base()
class MyModel(base_schema.SchemaBasePostgres, BASE):
# Define your model-specific columns here
my_column = base_schema.Column(base_schema.String(50))
Source code in dsg_lib/async_database_functions/base_schema.py
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
|
SchemaBaseSQLite
¶
This class provides a base schema that includes common columns for most models. All other models should inherit from this class.
Attributes:
Name | Type | Description |
---|---|---|
pkid |
str
|
A unique identifier for each record. It's a string |
date_created |
datetime
|
The date and time when a particular row was |
date_updated |
datetime
|
The date and time when a particular row was |
Example:
from dsg_lib.async_database_functions import base_schema
from sqlalchemy.orm import declarative_base
BASE = declarative_base()
class MyModel(base_schema.SchemaBase, BASE):
# Define your model-specific columns here
my_column = base_schema.Column(base_schema.String(50))
Source code in dsg_lib/async_database_functions/base_schema.py
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
|
SchemaBaseSybase
¶
This class provides a base schema that includes common columns for most models when using a Sybase database. All other models should inherit from this class.
Attributes:
Name | Type | Description |
---|---|---|
pkid |
str
|
A unique identifier for each record. It's a string |
date_created |
datetime
|
The date and time when a particular row was |
date_updated |
datetime
|
The date and time when a particular row was |
Example:
from dsg_lib.async_database_functions import base_schema
from sqlalchemy.orm import declarative_base
BASE = declarative_base()
class MyModel(base_schema.SchemaBaseSybase, BASE):
# Define your model-specific columns here
my_column = base_schema.Column(base_schema.String(50))
Source code in dsg_lib/async_database_functions/base_schema.py
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 |
|
Reference¶
dsg_lib.async_database_functions.database_config
¶
This module provides classes and functions for managing asynchronous database operations using SQLAlchemy and asyncio.
The main classes are DBConfig, which manages the database configuration and creates a SQLAlchemy engine and a MetaData instance, and AsyncDatabase, which uses an instance of DBConfig to perform asynchronous database operations.
The module also provides a function, import_sqlalchemy, which tries to import SQLAlchemy and its components, and raises an ImportError if SQLAlchemy is not installed or if the installed version is not compatible.
The module uses the logger from the dsg_lib
for logging, and the time
module
for working with times. It also uses the contextlib
module for creating
context managers, and the typing
module for type hinting.
The BASE
variable is a base class for declarative database models. It is
created using the declarative_base
function from sqlalchemy.orm
.
This module is part of the dsg_lib
package, which provides utilities for
working with databases in Python.
Example:
from dsg_lib.async_database_functions import database_config
# Define your database configuration config = {
"database_uri": "postgresql+asyncpg://user:password@localhost/dbname",
"echo": True, "future": True, "pool_pre_ping": True, "pool_size": 5,
"max_overflow": 10, "pool_recycle": 3600, "pool_timeout": 30,
}
# Create a DBConfig instance db_config = database_config.DBConfig(config)
# Use the DBConfig instance to get a database session async with
db_config.get_db_session() as session:
# Perform your database operations here pass
DBConfig
¶
A class used to manage the database configuration and create a SQLAlchemy engine.
Attributes:
Name | Type | Description |
---|---|---|
config |
dict
|
A dictionary containing the database configuration |
parameters. |
engine (Engine
|
The SQLAlchemy engine created with the |
database |
URI from the config. metadata (MetaData
|
The SQLAlchemy |
Create Engine Support Functions by Database Type Confirmed by testing [SQLITE, PostrgeSQL] To Be Tested [MySQL, Oracle, MSSQL] and should be considered experimental ------- Option SQLite PostgreSQL MySQL Oracle MSSQL echo Yes Yes Yes Yes Yes future Yes Yes Yes Yes Yes pool_pre_ping Yes Yes Yes Yes Yes pool_size No Yes Yes Yes Yes max_overflow No Yes Yes Yes Yes pool_recycle Yes Yes Yes Yes Yes pool_timeout No Yes Yes Yes Yes
Example:
from dsg_lib.async_database_functions import database_config
# Define your database configuration config = {
"database_uri": "postgresql+asyncpg://user:password@localhost/dbname",
"echo": True, "future": True, "pool_pre_ping": True, "pool_size": 5,
"max_overflow": 10, "pool_recycle": 3600, "pool_timeout": 30,
}
# Create a DBConfig instance db_config = database_config.DBConfig(config)
# Use the DBConfig instance to get a database session async with
db_config.get_db_session() as session:
# Perform your database operations here pass
Source code in dsg_lib/async_database_functions/database_config.py
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
|
__init__(config)
¶
Initializes the DBConfig instance with the given database configuration.
The configuration should be a dictionary with the following keys: -
"database_uri": The URI for the database. - "echo": If True, the engine
will log all statements as well as a repr()
of their parameter lists
to the engines logger, which defaults to sys.stdout. - "future": If
True, use the future version of SQLAlchemy, which supports asyncio. -
"pool_pre_ping": If True, the pool will test the connection for liveness
upon each checkout. - "pool_size": The size of the connection pool to be
maintained. - "max_overflow": The number of connections that can be
opened above the pool_size
setting, when all other connections are in
use. - "pool_recycle": The number of seconds after which a connection is
automatically recycled. This is required for MySQL, which removes
connections after 8 hours idle by default. - "pool_timeout": The number
of seconds to wait before giving up on getting a connection from the
pool.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
config |
Dict
|
A dictionary containing the database configuration |
required |
Raises:
Type | Description |
---|---|
Exception
|
If there are unsupported parameters for the database |
Example:
from dsg_lib.async_database_functions import database_config
# Define your database configuration config = {
"database_uri":
"postgresql+asyncpg://user:password@localhost/dbname", "echo": True,
"future": True, "pool_pre_ping": True, "pool_size": 5,
"max_overflow": 10, "pool_recycle": 3600, "pool_timeout": 30,
}
# Create a DBConfig instance db_config =
database_config.DBConfig(config)
Source code in dsg_lib/async_database_functions/database_config.py
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
|
get_db_session()
async
¶
This method returns a context manager that provides a new database session.
The session is created using the SQLAlchemy engine from the DBConfig instance, and it does not expire on commit. The session is of type AsyncSession.
This method should be used with the async with
statement.
Yields:
Name | Type | Description |
---|---|---|
AsyncSession |
A new SQLAlchemy asynchronous session. |
Raises:
Type | Description |
---|---|
SQLAlchemyError
|
If a database error occurs. |
Example:
from dsg_lib.async_database_functions import database_config
# Define your database configuration config = {
"database_uri":
"postgresql+asyncpg://user:password@localhost/dbname", "echo": True,
"future": True, "pool_pre_ping": True, "pool_size": 5,
"max_overflow": 10, "pool_recycle": 3600, "pool_timeout": 30,
}
# Create a DBConfig instance db_config =
database_config.DBConfig(config)
# Use the DBConfig instance to get a database session async with
db_config.get_db_session() as session:
# Perform your database operations here pass
Source code in dsg_lib/async_database_functions/database_config.py
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
|
Reference¶
dsg_lib.async_database_functions.async_database
¶
async_database.py.
This module provides classes for managing asynchronous database operations using SQLAlchemy and asyncio.
Classes:
Name | Description |
---|---|
- DBConfig |
Manages the database configuration. |
- AsyncDatabase |
Manages the asynchronous database operations. |
The DBConfig class initializes the database configuration and creates a SQLAlchemy engine and a MetaData instance.
The AsyncDatabase class uses an instance of DBConfig to perform asynchronous database operations. It provides methods to get a database session and to create tables in the database.
This module uses the logger from the dsg_lib.common_functions for logging.
Example:
from dsg_lib.async_database_functions import (
async_database,
base_schema,
database_config,
database_operations,
)
# Create a DBConfig instance
config = {
"database_uri": "sqlite+aiosqlite:///:memory:?cache=shared",
"echo": False,
"future": True,
"pool_recycle": 3600,
}
# create database configuration
db_config = database_config.DBConfig(config)
# Create an AsyncDatabase instance
async_db = async_database.AsyncDatabase(db_config)
# Create a DatabaseOperations instance
db_ops = database_operations.DatabaseOperations(async_db)
AsyncDatabase
¶
A class used to manage the asynchronous database operations.
Attributes¶
db_config : DBConfig an instance of DBConfig class containing the database configuration Base : Base the declarative base model for SQLAlchemy
Methods¶
get_db_session(): Returns a context manager that provides a new database session. create_tables(): Asynchronously creates all tables in the database.
Source code in dsg_lib/async_database_functions/async_database.py
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
|
__init__(db_config)
¶
Initialize the AsyncDatabase class with an instance of DBConfig.
Parameters: db_config (DBConfig): An instance of DBConfig class containing the database configuration.
Returns: None
Source code in dsg_lib/async_database_functions/async_database.py
73 74 75 76 77 78 79 80 81 82 83 84 |
|
create_tables()
async
¶
This method asynchronously creates all tables in the database.
Parameters: None
Returns: None
Source code in dsg_lib/async_database_functions/async_database.py
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
|
get_db_session()
¶
This method returns a context manager that provides a new database session.
Parameters: None
Returns: contextlib._GeneratorContextManager: A context manager that provides a new database session.
Source code in dsg_lib/async_database_functions/async_database.py
86 87 88 89 90 91 92 93 94 95 96 |
|
Reference¶
Configuration Matrix¶
Create Engine Support Functions by Database Type Confirmed by testing [SQLITE, PostgreSQL] To Be Tested [MySQL, Oracle, MSSQL] and should be considered experimental.
Option | SQLite | PostgreSQL | MySQL | Oracle | MSSQL |
---|---|---|---|---|---|
echo | Yes | Yes | Yes | Yes | Yes |
future | Yes | Yes | Yes | Yes | Yes |
pool_pre_ping | Yes | Yes | Yes | Yes | Yes |
pool_size | No | Yes | Yes | Yes | Yes |
max_overflow | No | Yes | Yes | Yes | Yes |
pool_recycle | Yes | Yes | Yes | Yes | Yes |
pool_timeout | No | Yes | Yes | Yes | Yes |
dsg_lib.async_database_functions.database_operations
¶
This module contains tests for the DatabaseOperations class in the dsg_lib module.
The DatabaseOperations class provides methods for performing CRUD operations on a database using SQLAlchemy's asynchronous session.
The methods include:
create_one
: Creates a single record in the database.create_many
: Creates multiple records in the database.read_one
: Reads a single record from the database.read_many
: Reads multiple records from the database.update_one
: Updates a single record in the database.update_many
: Updates multiple records in the database.delete_one
: Deletes a single record from the database.delete_many
: Deletes multiple records from the database.count_query
: Counts the number of records that match a given query.
Each method is tested to ensure it performs the expected operation and handles errors correctly. The tests use the pytest-asyncio plugin to run the asynchronous methods in an event loop, and the unittest.mock library to mock the database session and simulate errors.
The tests are organized into a single class, TestDatabaseOperations, which contains one test method for each method in the DatabaseOperations class. Each test method follows the Arrange-Act-Assert pattern: it sets up the necessary objects and state (Arrange), calls the method being tested (Act), and checks that the results are as expected (Assert).
DatabaseOperations
¶
This class provides methods for performing CRUD operations on a database using SQLAlchemy's asynchronous session.
The methods include:
create_one
: Creates a single record in the database.create_many
: Creates multiple records in the database.read_one
: Reads a single record from the database.read_many
: Reads multiple records from the database.update_one
: Updates a single record in the database.update_many
: Updates multiple records in the database.delete_one
: Deletes a single record from the database.delete_many
: Deletes multiple records from the database.count_query
: Counts the number of records that match a given query.get_column_details
: Gets the details of the columns in a table.get_primary_keys
: Gets the primary keys of a table.get_table_names
: Gets the names of all tables in the database.
Examples:
data = await db_ops.create_one(User(name='John Doe'))
data = await db_ops.create_many([User(name='John Doe'), User(name='Jane Doe')])
data = await db_ops.read_one(User, 1)
data = await db_ops.read_many(User, [1, 2, 3])
data = await db_ops.update_one(User, 1, {'name': 'John Smith'})
data = await db_ops.update_many(User, [1, 2], [{'name': 'John Smith'}, {'name': 'Jane Smith'}])
data = await db_ops.delete_one(User, 1)
data = await db_ops.delete_many(User, [1, 2, 3])
data = await db_ops.count_query(select(User))
data = await db_ops.get_column_details(User)
data = await db_ops.get_primary_keys(User)
data = await db_ops.get_table_names()
Source code in dsg_lib/async_database_functions/database_operations.py
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 |
|
__init__(async_db)
¶
Initializes a new instance of the DatabaseOperations class.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
async_db |
AsyncDatabase
|
An instance of the |
required |
Example:
from dsg_lib.async_database_functions import (
async_database,
base_schema,
database_config,
database_operations,
)
config = {
# "database_uri": "postgresql+asyncpg://postgres:postgres@postgresdb/postgres",
"database_uri": "sqlite+aiosqlite:///:memory:?cache=shared",
"echo": False,
"future": True,
# "pool_pre_ping": True,
# "pool_size": 10,
# "max_overflow": 10,
"pool_recycle": 3600,
# "pool_timeout": 30,
}
db_config = database_config.DBConfig(config)
async_db = async_database.AsyncDatabase(db_config)
db_ops = database_operations.DatabaseOperations(async_db)
Source code in dsg_lib/async_database_functions/database_operations.py
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
|
count_query(query)
async
¶
Executes a count query on the database and returns the number of records that match the query.
This asynchronous method accepts a SQLAlchemy Select
query object and
returns the count of records that match the query. This is particularly
useful for getting the total number of records that satisfy certain
conditions without actually fetching the records themselves.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
query |
Select
|
A SQLAlchemy |
required |
Returns:
Name | Type | Description |
---|---|---|
int |
The number of records that match the query. |
Raises:
Type | Description |
---|---|
Exception
|
If any error occurs during the execution of the query. |
Example
from dsg_lib.async_database_functions import (
async_database,
base_schema,
database_config,
database_operations,
)
# Create a DBConfig instance
config = {
# "database_uri": "postgresql+asyncpg://postgres:postgres@postgresdb/postgres",
"database_uri": "sqlite+aiosqlite:///:memory:?cache=shared",
"echo": False,
"future": True,
# "pool_pre_ping": True,
# "pool_size": 10,
# "max_overflow": 10,
"pool_recycle": 3600,
# "pool_timeout": 30,
}
# create database configuration
db_config = database_config.DBConfig(config)
# Create an AsyncDatabase instance
async_db = async_database.AsyncDatabase(db_config)
# Create a DatabaseOperations instance
db_ops = database_operations.DatabaseOperations(async_db)
# count query
count = await db_ops.count_query(select(User).where(User.age > 30))
Source code in dsg_lib/async_database_functions/database_operations.py
653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 |
|
create_many(records)
async
¶
Adds multiple records to the database.
This asynchronous method accepts a list of record objects and adds them to the database. If the operation is successful, it returns the added records. This method is useful for bulk inserting multiple rows into a database table efficiently.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
records |
list[Base]
|
A list of instances of the SQLAlchemy |
required |
Returns:
Type | Description |
---|---|
list[Base]: A list of instances of the records that were added to |
|
the database. |
Raises:
Type | Description |
---|---|
Exception
|
If any error occurs during the database operation. |
Example
from dsg_lib.async_database_functions import (
async_database,
base_schema,
database_config,
database_operations,
)
# Create a DBConfig instance
config = {
# "database_uri": "postgresql+asyncpg://postgres:postgres@postgresdb/postgres",
"database_uri": "sqlite+aiosqlite:///:memory:?cache=shared",
"echo": False,
"future": True,
# "pool_pre_ping": True,
# "pool_size": 10,
# "max_overflow": 10,
"pool_recycle": 3600,
# "pool_timeout": 30,
}
# create database configuration
db_config = database_config.DBConfig(config)
# Create an AsyncDatabase instance
async_db = async_database.AsyncDatabase(db_config)
# Create a DatabaseOperations instance
db_ops = database_operations.DatabaseOperations(async_db)
# create many records
records = await db_ops.create_many([User(name='John Doe'), User(name='Jane Doe')])
Source code in dsg_lib/async_database_functions/database_operations.py
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 |
|
create_one(record)
async
¶
Adds a single record to the database.
This asynchronous method accepts a record object and adds it to the database. If the operation is successful, it returns the added record. The method is useful for inserting a new row into a database table.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
record |
Base
|
An instance of the SQLAlchemy declarative base class |
required |
Returns:
Name | Type | Description |
---|---|---|
Base |
The instance of the record that was added to the database. |
Raises:
Type | Description |
---|---|
Exception
|
If any error occurs during the database operation. |
Example
from dsg_lib.async_database_functions import (
async_database,
base_schema,
database_config,
database_operations,
)
# Create a DBConfig instance
config = {
# "database_uri": "postgresql+asyncpg://postgres:postgres@postgresdb/postgres",
"database_uri": "sqlite+aiosqlite:///:memory:?cache=shared",
"echo": False,
"future": True,
# "pool_pre_ping": True,
# "pool_size": 10,
# "max_overflow": 10,
"pool_recycle": 3600,
# "pool_timeout": 30,
}
# create database configuration
db_config = database_config.DBConfig(config)
# Create an AsyncDatabase instance
async_db = async_database.AsyncDatabase(db_config)
# Create a DatabaseOperations instance
db_ops = database_operations.DatabaseOperations(async_db)
# create one record
record = await db_ops.create_one(User(name='John Doe'))
Source code in dsg_lib/async_database_functions/database_operations.py
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 |
|
delete_many(table, id_column_name='pkid', id_values=None)
async
¶
Deletes multiple records from the specified table in the database.
This method takes a table, an optional id column name, and a list of id values. It deletes the records in the table where the id column matches any of the id values in the list.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
table |
Type[DeclarativeMeta]
|
The table from which to delete records. |
required |
id_column_name |
str
|
The name of the id column in the table. Defaults to "pkid". |
'pkid'
|
id_values |
List[int]
|
A list of id values for the records to delete. Defaults to []. |
None
|
Returns:
Name | Type | Description |
---|---|---|
int |
int
|
The number of records deleted from the table. |
Example:
from dsg_lib.async_database_functions import (
async_database,
base_schema,
database_config,
database_operations,
)
# Create a DBConfig instance
config = {
"database_uri": "sqlite+aiosqlite:///:memory:?cache=shared",
"echo": False,
"future": True,
"pool_recycle": 3600,
}
# create database configuration
db_config = database_config.DBConfig(config)
# Create an AsyncDatabase instance
async_db = async_database.AsyncDatabase(db_config)
# Create a DatabaseOperations instance
db_ops = database_operations.DatabaseOperations(async_db)
# Delete multiple records
deleted_count = await db_ops.delete_many(User, 'id', [1, 2, 3])
print(f"Deleted {deleted_count} records.")
Source code in dsg_lib/async_database_functions/database_operations.py
1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 |
|
delete_one(table, record_id)
async
¶
Deletes a single record from the database based on the provided table and record ID.
This asynchronous method accepts a SQLAlchemy Table
object and a
record ID. It attempts to delete the record with the given ID from the
specified table. If the record is successfully deleted, it returns a
success message. If no record with the given ID is found, it returns an
error message.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
table |
Table
|
An instance of the SQLAlchemy |
required |
deleted. |
record_id (str
|
The ID of the record to be deleted. |
required |
Returns:
Name | Type | Description |
---|---|---|
dict |
A dictionary containing a success message if the record was |
|
deleted successfully, or an error message if the record was not |
||
found or an exception occurred. |
Raises:
Type | Description |
---|---|
Exception
|
If any error occurs during the delete operation. |
Example
from dsg_lib.async_database_functions import (
async_database,
base_schema,
database_config,
database_operations,
)
# Create a DBConfig instance
config = {
# "database_uri": "postgresql+asyncpg://postgres:postgres@postgresdb/postgres",
"database_uri": "sqlite+aiosqlite:///:memory:?cache=shared",
"echo": False,
"future": True,
# "pool_pre_ping": True,
# "pool_size": 10,
# "max_overflow": 10,
"pool_recycle": 3600,
# "pool_timeout": 30,
}
# create database configuration
db_config = database_config.DBConfig(config)
# Create an AsyncDatabase instance
async_db = async_database.AsyncDatabase(db_config)
# Create a DatabaseOperations instance
db_ops = database_operations.DatabaseOperations(async_db)
# delete one record
result = await db_ops.delete_one(User, 1)
Source code in dsg_lib/async_database_functions/database_operations.py
1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 |
|
get_columns_details(table)
async
¶
Retrieves the details of the columns of a given table.
This asynchronous method accepts a table object and returns a dictionary. Each key in the dictionary is a column name from the table, and the corresponding value is another dictionary containing details about that column, such as type, if it's nullable, if it's a primary key, if it's unique, its autoincrement status, and its default value.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
table |
Table
|
An instance of the SQLAlchemy Table class |
required |
Returns:
Name | Type | Description |
---|---|---|
dict |
A dictionary where each key is a column name, and each value |
|
is a dictionary with the column's details. |
Raises:
Type | Description |
---|---|
Exception
|
If any error occurs during the database operation. |
Example:
from sqlalchemy import Table, MetaData, Column,
Integer, String from dsg_lib.async_database_functions import module_name metadata = MetaData()
my_table = Table('my_table', metadata,
Column('id', Integer, primary_key=True), Column('name',
String))
from dsg_lib.async_database_functions import (
async_database,
base_schema,
database_config,
database_operations,
)
# Create a DBConfig instance
config = {
# "database_uri": "postgresql+asyncpg://postgres:postgres@postgresdb/postgres",
"database_uri": "sqlite+aiosqlite:///:memory:?cache=shared",
"echo": False,
"future": True,
# "pool_pre_ping": True,
# "pool_size": 10,
# "max_overflow": 10,
"pool_recycle": 3600,
# "pool_timeout": 30,
}
# create database configuration
db_config = database_config.DBConfig(config)
# Create an AsyncDatabase instance
async_db = async_database.AsyncDatabase(db_config)
# Create a DatabaseOperations instance
db_ops = database_operations.DatabaseOperations(async_db)
# get columns details
columns = await db_ops.get_columns_details(my_table)
Source code in dsg_lib/async_database_functions/database_operations.py
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 |
|
get_primary_keys(table)
async
¶
Retrieves the primary keys of a given table.
This asynchronous method accepts a table object and returns a list containing the names of its primary keys. It is useful for understanding the structure of the table and for operations that require knowledge of the primary keys.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
table |
Table
|
An instance of the SQLAlchemy Table class |
required |
Returns:
Name | Type | Description |
---|---|---|
list |
A list containing the names of the primary keys of the table. |
Raises:
Type | Description |
---|---|
Exception
|
If any error occurs during the database operation. |
Example
from sqlalchemy import Table, MetaData, Column, Integer,
String from dsg_lib.async_database_functions import module_name metadata = MetaData()
my_table = Table('my_table', metadata,
Column('id', Integer, primary_key=True),
Column('name', String, primary_key=True))
from dsg_lib.async_database_functions import (
async_database,
base_schema,
database_config,
database_operations,
)
# Create a DBConfig instance
config = {
# "database_uri": "postgresql+asyncpg://postgres:postgres@postgresdb/postgres",
"database_uri": "sqlite+aiosqlite:///:memory:?cache=shared",
"echo": False,
"future": True,
# "pool_pre_ping": True,
# "pool_size": 10,
# "max_overflow": 10,
"pool_recycle": 3600,
# "pool_timeout": 30,
}
# create database configuration
db_config = database_config.DBConfig(config)
# Create an AsyncDatabase instance
async_db = async_database.AsyncDatabase(db_config)
# Create a DatabaseOperations instance
db_ops = database_operations.DatabaseOperations(async_db)
# get primary keys
primary_keys = await db_ops.get_primary_keys(my_table)
Source code in dsg_lib/async_database_functions/database_operations.py
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 |
|
get_table_names()
async
¶
Retrieves the names of all tables in the database.
This asynchronous method returns a list containing the names of all tables in the database. It is useful for database introspection, allowing the user to know which tables are available in the current database context.
Returns:
Name | Type | Description |
---|---|---|
list |
A list containing the names of all tables in the database. |
Raises:
Type | Description |
---|---|
Exception
|
If any error occurs during the database operation. |
Example
from dsg_lib.async_database_functions import (
async_database,
base_schema,
database_config,
database_operations,
)
# Create a DBConfig instance
config = {
# "database_uri": "postgresql+asyncpg://postgres:postgres@postgresdb/postgres",
"database_uri": "sqlite+aiosqlite:///:memory:?cache=shared",
"echo": False,
"future": True,
# "pool_pre_ping": True,
# "pool_size": 10,
# "max_overflow": 10,
"pool_recycle": 3600,
# "pool_timeout": 30,
}
# create database configuration
db_config = database_config.DBConfig(config)
# Create an AsyncDatabase instance
async_db = async_database.AsyncDatabase(db_config)
# Create a DatabaseOperations instance
db_ops = database_operations.DatabaseOperations(async_db)
# get table names
table_names = await db_ops.get_table_names()
Source code in dsg_lib/async_database_functions/database_operations.py
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 |
|
read_multi_query(queries, limit=500, offset=0)
async
¶
Executes multiple fetch queries on the database and returns a dictionary of results for each query.
This asynchronous method takes a dictionary where each key is a query
name and each value is a SQLAlchemy Select
query object. It also
accepts optional limit and offset parameters. The method executes each
query and returns a dictionary where each key is the query name, and the
corresponding value is a list of records that match that query.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
queries |
Dict[str, Select]
|
A dictionary of SQLAlchemy |
required |
query |
objects. limit (int
|
The maximum number of records |
required |
to |
return for each query. Defaults to 500. offset (int
|
|
required |
Returns:
Name | Type | Description |
---|---|---|
dict |
A dictionary where each key is a query name and each value is |
|
a list of records that match the query. |
Raises:
Type | Description |
---|---|
Exception
|
If any error occurs during the execution of the queries. |
Example
from dsg_lib.async_database_functions import (
async_database,
base_schema,
database_config,
database_operations,
)
# Create a DBConfig instance
config = {
# "database_uri": "postgresql+asyncpg://postgres:postgres@postgresdb/postgres",
"database_uri": "sqlite+aiosqlite:///:memory:?cache=shared",
"echo": False,
"future": True,
# "pool_pre_ping": True,
# "pool_size": 10,
# "max_overflow": 10,
"pool_recycle": 3600,
# "pool_timeout": 30,
}
# create database configuration
db_config = database_config.DBConfig(config)
# Create an AsyncDatabase instance
async_db = async_database.AsyncDatabase(db_config)
# Create a DatabaseOperations instance
db_ops = database_operations.DatabaseOperations(async_db)
# read multi query
queries = {
"query1": select(User).where(User.age > 30),
"query2": select(User).where(User.age < 20),
}
results = await db_ops.read_multi_query(queries, limit=10)
Source code in dsg_lib/async_database_functions/database_operations.py
817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 |
|
read_one_record(query)
async
¶
Retrieves a single record from the database based on the provided query.
This asynchronous method accepts a SQL query object and returns the first record that matches the query. If no record matches the query, it returns None. This method is useful for fetching specific data when the expected result is a single record.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
query |
Select
|
An instance of the SQLAlchemy Select class, |
required |
Returns:
Name | Type | Description |
---|---|---|
Result |
The first record that matches the query or None if no record matches. |
Raises:
Type | Description |
---|---|
Exception
|
If any error occurs during the database operation. |
Example
from dsg_lib.async_database_functions import (
async_database,
base_schema,
database_config,
database_operations,
)
# Create a DBConfig instance
config = {
# "database_uri": "postgresql+asyncpg://postgres:postgres@postgresdb/postgres",
"database_uri": "sqlite+aiosqlite:///:memory:?cache=shared",
"echo": False,
"future": True,
# "pool_pre_ping": True,
# "pool_size": 10,
# "max_overflow": 10,
"pool_recycle": 3600,
# "pool_timeout": 30,
}
# create database configuration
db_config = database_config.DBConfig(config)
# Create an AsyncDatabase instance
async_db = async_database.AsyncDatabase(db_config)
# Create a DatabaseOperations instance
db_ops = database_operations.DatabaseOperations(async_db)
# read one record
record = await db_ops.read_one_record(select(User).where(User.name == 'John Doe'))
Source code in dsg_lib/async_database_functions/database_operations.py
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 |
|
read_query(query, limit=500, offset=0)
async
¶
Executes a fetch query on the database and returns a list of records that match the query.
This asynchronous method accepts a SQLAlchemy Select
query object
along with optional limit and offset parameters. It returns a list of
records that match the query, with the number of records controlled by
the limit, and the starting point of the records determined by the
offset.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
query |
Select
|
A SQLAlchemy |
required |
conditions |
to fetch records for. limit (int
|
The maximum |
required |
optional) |
The number of records to skip before starting to return |
required |
Returns:
Name | Type | Description |
---|---|---|
list |
A list of records that match the query. |
Raises:
Type | Description |
---|---|
Exception
|
If any error occurs during the execution of the query. |
Example
from dsg_lib.async_database_functions import (
async_database,
base_schema,
database_config,
database_operations,
)
# Create a DBConfig instance
config = {
# "database_uri": "postgresql+asyncpg://postgres:postgres@postgresdb/postgres",
"database_uri": "sqlite+aiosqlite:///:memory:?cache=shared",
"echo": False,
"future": True,
# "pool_pre_ping": True,
# "pool_size": 10,
# "max_overflow": 10,
"pool_recycle": 3600,
# "pool_timeout": 30,
}
# create database configuration
db_config = database_config.DBConfig(config)
# Create an AsyncDatabase instance
async_db = async_database.AsyncDatabase(db_config)
# Create a DatabaseOperations instance
db_ops = database_operations.DatabaseOperations(async_db)
# read query
records = await db_ops.read_query(select(User).where(User.age > 30), limit=10)
Source code in dsg_lib/async_database_functions/database_operations.py
726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 |
|
update_one(table, record_id, new_values)
async
¶
Updates a single record in the database identified by its ID.
This asynchronous method takes a SQLAlchemy Table
object, a record ID,
and a dictionary of new values to update the record. It updates the
specified record in the given table with the new values. The method does
not allow updating certain fields, such as 'id' or 'date_created'.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
table |
Table
|
The SQLAlchemy |
required |
in |
the database. record_id (str
|
The ID of the record to be |
required |
updated. |
new_values (dict
|
A dictionary containing the fields to |
required |
Returns:
Name | Type | Description |
---|---|---|
Base |
The updated record if successful; otherwise, an error |
|
dictionary. |
Raises:
Type | Description |
---|---|
Exception
|
If any error occurs during the update operation. |
Example
from dsg_lib.async_database_functions import (
async_database,
base_schema,
database_config,
database_operations,
)
# Create a DBConfig instance
config = {
# "database_uri": "postgresql+asyncpg://postgres:postgres@postgresdb/postgres",
"database_uri": "sqlite+aiosqlite:///:memory:?cache=shared",
"echo": False,
"future": True,
# "pool_pre_ping": True,
# "pool_size": 10,
# "max_overflow": 10,
"pool_recycle": 3600,
# "pool_timeout": 30,
}
# create database configuration
db_config = database_config.DBConfig(config)
# Create an AsyncDatabase instance
async_db = async_database.AsyncDatabase(db_config)
# Create a DatabaseOperations instance
db_ops = database_operations.DatabaseOperations(async_db)
# update one record
record = await db_ops.update_one(User, 1, {'name': 'John Smith'})
Source code in dsg_lib/async_database_functions/database_operations.py
909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 |
|
handle_exceptions(ex)
¶
Handles exceptions for database operations.
This function checks the type of the exception, logs an appropriate error message, and returns a dictionary containing the error details.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
ex |
Exception
|
The exception to handle. |
required |
Returns:
Name | Type | Description |
---|---|---|
dict |
Dict[str, str]
|
A dictionary containing the error details. The dictionary has two |
keys |
Dict[str, str]
|
'error' and 'details'. |
Example:
from dsg_lib.async_database_functions import database_operations
try:
# Some database operation that might raise an exception pass
except Exception as ex:
error_details = database_operations.handle_exceptions(ex)
print(error_details)
Source code in dsg_lib/async_database_functions/database_operations.py
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
|
Ended: Database Functions
Recipes ↵
Full Example of FastAPI with Aync Database and Endpoints¶
You can find this in the examples folder of the repository.
Install dependencies¶
pip install dsg_lib[all] tqdm
Make App¶
Copy the fastapi code below after installing. (assumption is main.py)
# -*- coding: utf-8 -*-
import datetime
import secrets
import time
from contextlib import asynccontextmanager
from fastapi import Body, FastAPI, Query
from fastapi.responses import RedirectResponse
from loguru import logger
from pydantic import BaseModel, EmailStr
from sqlalchemy import Column, ForeignKey, Select, String
from sqlalchemy.orm import relationship
from tqdm import tqdm
from dsg_lib.async_database_functions import (
async_database,
base_schema,
database_config,
database_operations,
)
from dsg_lib.common_functions import logging_config
logging_config.config_log(
logging_level="INFO", log_serializer=False, log_name="log.log"
)
@asynccontextmanager
async def lifespan(app: FastAPI):
logger.info("starting up")
# Create the tables in the database
await async_db.create_tables()
create_users = True
if create_users:
await create_a_bunch_of_users(single_entry=24, many_entries=2000)
yield
logger.info("shutting down")
# Create an instance of the FastAPI class
app = FastAPI(
title="FastAPI Example", # The title of the API
description="This is an example of a FastAPI application using the DevSetGo Toolkit.", # A brief description of the API
version="0.1.0", # The version of the API
docs_url="/docs", # The URL where the API documentation will be served
redoc_url="/redoc", # The URL where the ReDoc documentation will be served
openapi_url="/openapi.json", # The URL where the OpenAPI schema will be served
debug=True, # Enable debug mode
middleware=[], # A list of middleware to include in the application
routes=[], # A list of routes to include in the application
lifespan=lifespan, # this is the replacement for the startup and shutdown events
)
@app.get("/")
async def root():
"""
Root endpoint of API
Returns:
Redrects to openapi document
"""
# redirect to openapi docs
logger.info("Redirecting to OpenAPI docs")
response = RedirectResponse(url="/docs")
return response
from dsg_lib.fastapi_functions import ( # , system_tools_endpoints
system_health_endpoints,
)
config_health = {
"enable_status_endpoint": True,
"enable_uptime_endpoint": True,
"enable_heapdump_endpoint": True,
}
app.include_router(
system_health_endpoints.create_health_router(config=config_health),
prefix="/api/health",
tags=["system-health"],
)
# Create a DBConfig instance
config = {
# "database_uri": "postgresql+asyncpg://postgres:postgres@postgresdb/postgres",
"database_uri": "sqlite+aiosqlite:///:memory:?cache=shared",
"echo": False,
"future": True,
# "pool_pre_ping": True,
# "pool_size": 10,
# "max_overflow": 10,
"pool_recycle": 3600,
# "pool_timeout": 30,
}
# create database configuration
db_config = database_config.DBConfig(config)
# Create an AsyncDatabase instance
async_db = async_database.AsyncDatabase(db_config)
# Create a DatabaseOperations instance
db_ops = database_operations.DatabaseOperations(async_db)
class User(base_schema.SchemaBase, async_db.Base):
"""
User table storing user details like first name, last name, and email
"""
__tablename__ = "users"
__table_args__ = {
"comment": "User table storing user details like first name, last name, and email"
}
first_name = Column(String(50), unique=False, index=True) # First name of the user
last_name = Column(String(50), unique=False, index=True) # Last name of the user
email = Column(
String(200), unique=True, index=True, nullable=True
) # Email of the user, must be unique
addresses = relationship(
"Address", order_by="Address.pkid", back_populates="user"
) # Relationship to the Address class
class Address(base_schema.SchemaBase, async_db.Base):
"""
Address table storing address details like street, city, and zip code
"""
__tablename__ = "addresses"
__table_args__ = {
"comment": "Address table storing address details like street, city, and zip code"
}
street = Column(String(200), unique=False, index=True) # Street of the address
city = Column(String(200), unique=False, index=True) # City of the address
zip = Column(String(50), unique=False, index=True) # Zip code of the address
user_id = Column(
String(36), ForeignKey("users.pkid")
) # Foreign key to the User table
user = relationship(
"User", back_populates="addresses"
) # Relationship to the User class
async def create_a_bunch_of_users(single_entry=0, many_entries=0):
logger.info(f"single_entry: {single_entry}")
await async_db.create_tables()
# Create a list to hold the user data
# Create a loop to generate user data
for i in tqdm(range(single_entry), desc="executing one"):
value = secrets.token_hex(16)
user = User(
first_name=f"First{value}",
last_name=f"Last{value}",
email=f"user{value}@example.com",
)
logger.info(f"created_users: {user}")
await db_ops.create_one(user)
users = []
# Create a loop to generate user data
for i in tqdm(range(many_entries), desc="executing many"):
value_one = secrets.token_hex(4)
value_two = secrets.token_hex(8)
user = User(
first_name=f"First{value_one}{i}{value_two}",
last_name=f"Last{value_one}{i}{value_two}",
email=f"user{value_one}{i}{value_two}@example.com",
)
logger.info(f"created_users: {user.first_name}")
users.append(user)
# Use db_ops to add the users to the database
await db_ops.create_many(users)
@app.get("/database/get-primary-key", tags=["Database Examples"])
async def table_primary_key():
logger.info("Getting primary key of User table")
pk = await db_ops.get_primary_keys(User)
logger.info(f"Primary key of User table: {pk}")
return {"pk": pk}
@app.get("/database/get-column-details", tags=["Database Examples"])
async def table_column_details():
logger.info("Getting column details of User table")
columns = await db_ops.get_columns_details(User)
logger.info(f"Column details of User table: {columns}")
return {"columns": columns}
@app.get("/database/get-tables", tags=["Database Examples"])
async def table_table_details():
logger.info("Getting table names")
tables = await db_ops.get_table_names()
logger.info(f"Table names: {tables}")
return {"table_names": tables}
@app.get("/database/get-count", tags=["Database Examples"])
async def get_count():
logger.info("Getting count of users")
count = await db_ops.count_query(Select(User))
logger.info(f"Count of users: {count}")
return {"count": count}
@app.get("/database/get-all", tags=["Database Examples"])
async def get_all(offset: int = 0, limit: int = Query(100, le=100000, ge=1)):
logger.info(f"Getting all users with offset {offset} and limit {limit}")
records = await db_ops.read_query(Select(User).offset(offset).limit(limit))
logger.info(f"Retrieved {len(records)} users")
return {"records": records}
@app.get("/database/get-one-record", tags=["Database Examples"])
async def read_one_record(record_id: str):
logger.info(f"Reading one record with id {record_id}")
record = await db_ops.read_one_record(Select(User).where(User.pkid == record_id))
logger.info(f"Record with id {record_id}: {record}")
return record
class UserBase(BaseModel):
first_name: str
last_name: str
email: EmailStr
class UserCreate(UserBase):
pass
@app.post("/database/create-one-record", status_code=201, tags=["Database Examples"])
async def create_one_record(new_user: UserCreate):
logger.info(f"Creating one record: {new_user}")
user = User(**new_user.dict())
record = await db_ops.create_one(user)
logger.info(f"Created record: {record}")
return record
@app.post("/database/create-many-records", status_code=201, tags=["Database Examples"])
async def create_many_records(number_of_users: int = Query(100, le=1000, ge=1)):
logger.info(f"Creating {number_of_users} records")
t0 = time.time()
users = []
# Create a loop to generate user data
for i in tqdm(range(number_of_users), desc="executing many"):
value_one = secrets.token_hex(4)
value_two = secrets.token_hex(8)
user = User(
first_name=f"First{value_one}{i}{value_two}",
last_name=f"Last{value_one}{i}{value_two}",
email=f"user{value_one}{i}{value_two}@example.com",
)
logger.info(f"Created user: {user.first_name}")
users.append(user)
# Use db_ops to add the users to the database
await db_ops.create_many(users)
t1 = time.time()
process_time = format(t1 - t0, ".4f")
logger.info(f"Created {number_of_users} records in {process_time} seconds")
return {"number_of_users": number_of_users, "process_time": process_time}
@app.put("/database/update-one-record", status_code=200, tags=["Database Examples"])
async def update_one_record(
id: str = Body(
...,
description="UUID to update",
examples=["6087cce8-0bdd-48c2-ba96-7d557dae843e"],
),
first_name: str = Body(..., examples=["Agent"]),
last_name: str = Body(..., examples=["Smith"]),
email: str = Body(..., examples=["jim@something.com"]),
):
logger.info(f"Updating one record with id {id}")
# adding date_updated to new_values as it is not supported in sqlite \
# and other database may not either.
new_values = {
"first_name": first_name,
"last_name": last_name,
"email": email,
"date_updated": datetime.datetime.now(datetime.timezone.utc),
}
record = await db_ops.update_one(table=User, record_id=id, new_values=new_values)
logger.info(f"Updated record with id {id}")
return record
@app.delete("/database/delete-one-record", status_code=200, tags=["Database Examples"])
async def delete_one_record(record_id: str = Body(...)):
logger.info(f"Deleting one record with id {record_id}")
record = await db_ops.delete_one(table=User, record_id=record_id)
logger.info(f"Deleted record with id {record_id}")
return record
@app.delete(
"/database/delete-many-records-aka-this-is-a-bad-idea",
status_code=201,
tags=["Database Examples"],
)
async def delete_many_records(
id_values: list = Body(...), id_column_name: str = "pkid"
):
logger.info(f"Deleting many records with ids {id_values}")
record = await db_ops.delete_many(
table=User, id_column_name="pkid", id_values=id_values
)
logger.info(f"Deleted records with ids {id_values}")
return record
@app.get(
"/database/get-list-of-records-to-paste-into-delete-many-records",
tags=["Database Examples"],
)
async def read_list_of_records(
offset: int = Query(0, le=1000, ge=0), limit: int = Query(100, le=10000, ge=1)
):
logger.info(f"Reading list of records with offset {offset} and limit {limit}")
records = await db_ops.read_query(Select(User), offset=offset, limit=limit)
records_list = []
for record in records:
records_list.append(record.pkid)
logger.info(f"Read list of records: {records_list}")
return records_list
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=5000)
Run Code¶
In the console (linux) run the code below. Open browser to http://127.0.0.1:5000 to see app.
python3 main.py
Examples¶
Here are a few examples of how to use the database functions
Asyncio Script Example¶
Example of how to use in a script
import asyncio
from sqlalchemy import select
from dsg_lib.async_database_functions import database_config, async_database, database_operations
# Configuration
config = {
"database_uri": "sqlite+aiosqlite:///:memory:?cache=shared",
"echo": False,
"future": True,
"pool_recycle": 3600,
}
# Create a DBConfig instance
db_config = database_config.DBConfig(config)
# Create an AsyncDatabase instance
async_db = async_database.AsyncDatabase(db_config)
# Create a DatabaseOperations instance
db_ops = database_operations.DatabaseOperations(async_db)
# User class
class User(async_db.Base):
__tablename__ = "users"
first_name = Column(String, unique=False, index=True)
last_name = Column(String, unique=False, index=True)
email = Column(String, unique=True, index=True, nullable=True)
# Async function to get all users
async def get_all_users():
# Create a select query
query = select(User)
# Execute the query and fetch all results
users = await db_ops.read_query(query)
# Print the users
for user in users:
print(f"User: {user.first_name} {user.last_name}, Email: {user.email}")
# Run the async function
asyncio.run(get_all_users())
FastAPI Example¶
# -*- coding: utf-8 -*-
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.responses import RedirectResponse
from loguru import logger
from tqdm import tqdm
from dsg_lib import logging_config
logging_config.config_log(
logging_level="Debug", log_serializer=False, log_name="log.log"
)
@asynccontextmanager
async def lifespan(app: FastAPI):
logger.info("starting up")
# Create the tables in the database
await async_db.create_tables()
create_users = True
if create_users:
await create_a_bunch_of_users(single_entry=23, many_entries=100)
yield
logger.info("shutting down")
# Create an instance of the FastAPI class
app = FastAPI(
title="FastAPI Example", # The title of the API
description="This is an example of a FastAPI application using the DevSetGo Toolkit.", # A brief description of the API
version="0.1.0", # The version of the API
docs_url="/docs", # The URL where the API documentation will be served
redoc_url="/redoc", # The URL where the ReDoc documentation will be served
openapi_url="/openapi.json", # The URL where the OpenAPI schema will be served
debug=True, # Enable debug mode
middleware=[], # A list of middleware to include in the application
routes=[], # A list of routes to include in the application
lifespan=lifespan,
)
@app.get("/")
async def root():
"""
Root endpoint of API
Returns:
Redrects to openapi document
"""
# redirect to openapi docs
logger.info("Redirecting to OpenAPI docs")
response = RedirectResponse(url="/docs")
return response
from sqlalchemy import Column, Delete, Select, String, Update
from dsg_lib import (
async_database,
base_schema,
database_config,
database_operations,
)
# Create a DBConfig instance
config = {
# "database_uri": "postgresql+asyncpg://postgres:postgres@postgresdb/postgres",
"database_uri": "sqlite+aiosqlite:///:memory:?cache=shared",
"echo": False,
"future": True,
# "pool_pre_ping": True,
# "pool_size": 10,
# "max_overflow": 10,
"pool_recycle": 3600,
# "pool_timeout": 30,
}
db_config = database_config.DBConfig(config)
# Create an AsyncDatabase instance
async_db = async_database.AsyncDatabase(db_config)
# Create a DatabaseOperations instance
db_ops = database_operations.DatabaseOperations(async_db)
# User class inherits from SchemaBase and async_db.Base
# This class represents the User table in the database
class User(base_schema.SchemaBase, async_db.Base):
__tablename__ = "users" # Name of the table in the database
# Define the columns of the table
first_name = Column(String, unique=False, index=True) # First name of the user
last_name = Column(String, unique=False, index=True) # Last name of the user
email = Column(
String, unique=True, index=True, nullable=True
) # Email of the user, must be unique
async def create_a_bunch_of_users(single_entry=0, many_entries=0):
logger.info(f"single_entry: {single_entry}")
await async_db.create_tables()
# Create a list to hold the user data
# Create a loop to generate user data
for i in tqdm(range(single_entry), desc="executing one"):
value = secrets.token_hex(16)
user = User(
first_name=f"First{value}",
last_name=f"Last{value}",
email=f"user{value}@example.com",
)
logger.info(f"created_users: {user}")
await db_ops.create_one(user)
users = []
# Create a loop to generate user data
for i in tqdm(range(many_entries), desc="executing many"):
value_one = secrets.token_hex(4)
value_two = secrets.token_hex(8)
user = User(
first_name=f"First{value_one}{i}{value_two}",
last_name=f"Last{value_one}{i}{value_two}",
email=f"user{value_one}{i}{value_two}@example.com",
)
logger.info(f"created_users: {user.first_name}")
users.append(user)
# Use db_ops to add the users to the database
await db_ops.create_many(users)
@app.get("/database/get-count")
async def get_count():
count = await db_ops.count_query(Select(User))
return {"count": count}
# endpoint to get list of user
@app.get("/database/get-all")
async def get_all(offset: int = 0, limit: int = 100):
records = await db_ops.read_query(Select(User).offset(offset).limit(limit))
return {"records": records}
@app.get("/database/get-primary-key")
async def table_primary_key():
pk = await db_ops.get_primary_keys(User)
return {"pk": pk}
@app.get("/database/get-column-details")
async def table_column_details():
columns = await db_ops.get_columns_details(User)
return {"columns": columns}
@app.get("/database/get-tables")
async def table_table_details():
tables = await db_ops.get_table_names()
return {"table_names": tables}
@app.get("/database/get-one-record")
async def get_one_record(record_id: str):
record = await db_ops.get_one_record(Select(User).where(User.pkid == record_id))
return {"record": record}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=5000)
Logging Example¶
# -*- coding: utf-8 -*-
import logging
import secrets
from uuid import uuid4
from loguru import logger
from tqdm import tqdm
from dsg_lib.common_functions import logging_config
logging_config.config_log(
logging_directory="log",
# or None and defaults to logging
# log_name="log.json",
# or None and defaults to "log.log"
logging_level="debug",
# or "info" or "debug" or "warning" or "error" or "critical"
# or None and defaults to "info"
log_rotation="10 MB",
# or None and default is 10 MB
log_retention="1 Day",
# or None and defaults to "14 Days"
log_backtrace=True,
# or None and defaults to False
app_name="my_app",
# app name is used to identify the application
# this is an optional field
enable_trace_id=True,
# service id is used to identify the service
# this is an optional field
append_app_name=True,
# append app name to log file name defaults to false
append_trace_id=True,
# append app name and service name to log file name defaults to false
)
# after configuring logging
# user loguru to log messages
logger.debug("This is a debug message")
logger.info("This is an info message")
logger.error("This is an error message")
logger.warning("This is a warning message")
logger.critical("This is a critical message")
# will intercept all standard logging messages also
logging.debug("This is a debug message")
logging.info("This is an info message")
logging.error("This is an error message")
logging.warning("This is a warning message")
logging.critical("This is a critical message")
def div_zero(x, y):
try:
return x / y
except ZeroDivisionError as e:
logger.error(f"{e}")
logging.error(f"{e}")
@logger.catch
def div_zero_two(x, y):
return x / y
a = div_zero(x=1, y=0)
b = div_zero_two(x=1, y=0)
for _ in tqdm(range(5), ascii=True):
# log a lot of data
logging.debug(f"Lets make this a big message {secrets.token_urlsafe(32)}")
Patterns¶
# -*- coding: utf-8 -*-
import pprint
from random import randint
from dsg_lib.common_functions.patterns import pattern_between_two_char
ASCII_LIST = [
" ",
"!",
'""',
"#",
"$",
"%",
"&",
"'",
"(",
")",
"*",
"+",
",",
"-",
".",
"/",
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
":",
";",
"<",
"=",
">",
"?",
"@",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
"[",
"\\",
"]",
"^",
"_",
"`",
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
"{",
"|",
"}",
"~",
"€",
"‚",
"ƒ",
"„",
"…",
"†",
"‡",
"ˆ",
"‰",
"Š",
"‹",
"Œ",
"Ž",
"‘",
"’",
"“",
"”",
"•",
"–",
"—",
"˜",
"™",
"š",
"›",
"œ",
"ž",
"Ÿ",
"¡",
"¢",
"£",
"¤",
"¥",
"¦",
"§",
"¨",
"©",
"ª",
"«",
"¬",
"®",
"¯",
"°",
"±",
"²",
"³",
"´",
"µ",
"¶",
"·",
"¸",
"¹",
"º",
"»",
"¼",
"½",
"¾",
"¿",
"À",
"Á",
"Â",
"Ã",
"Ä",
"Å",
"Æ",
"Ç",
"È",
"É",
"Ê",
"Ë",
"Ì",
"Í",
"Î",
"Ï",
"Ð",
"Ñ",
"Ò",
"Ó",
"Ô",
"Õ",
"Ö",
"×",
"Ø",
"Ù",
"Ú",
"Û",
"Ü",
"Ý",
"Þ",
"ß",
"à",
"á",
"â",
"ã",
"ä",
"å",
"æ",
"ç",
"è",
"é",
"ê",
"ë",
"ì",
"í",
"î",
"ï",
"ð",
"ñ",
"ò",
"ó",
"ô",
"õ",
"ö",
"÷",
"ø",
"ù",
"ú",
"û",
"ü",
"ý",
"þ",
"ÿ",
]
pp = pprint.PrettyPrinter(indent=4)
def pattern_find(left_char: str, right_char: str, text_block: str):
data = pattern_between_two_char(text_block, left_char, right_char)
pp.pprint(data)
def run_examples():
text_block = "Lfound oneR Lfound twoR"
left_char = "L"
right_char = "R"
pattern_find(left_char=left_char, right_char=right_char, text_block=text_block)
for _ in range(100):
long_input = "xyz" * randint(100, 100000)
long_text = f"{long_input}abc<one>123<two>456<three>{long_input}"
result = pattern_between_two_char(
text_string=long_text, left_characters="<", right_characters=">"
)
print(result["found"])
if __name__ == "__main__":
run_examples()
Ended: Recipes
About ↵
Contributing¶
Please feel to contribute to this project. Adding common functions is the intent and if you have one to add or improve an existing it is greatly appreciated.
Ways to Contribute!¶
- Add or improve a function
- Add or improve documentation
- Add or improve Tests
- Report or fix a bug
Ended: About
Changelog¶
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog
Latest Changes¶
Adding Delete Many and minor fixes (v0.11.2)¶
What's Changed¶
- Adding Delete Many and Other Updates (#381) @devsetgo
- pip(deps): bump mkdocs-material from 9.5.2 to 9.5.3 (#377) @dependabot
- pip(deps): bump fastapi[all] from 0.105.0 to 0.108.0 (#375) @dependabot
- pip(deps): bump sqlalchemy from 2.0.23 to 2.0.24 (#374) @dependabot
- pip(deps): bump pytest from 7.4.3 to 7.4.4 (#373) @dependabot
- pip(deps): bump black from 23.12.0 to 23.12.1 (#376) @dependabot
- github actionts(deps): bump actions/setup-python from 4 to 5 (#378) @dependabot
Published Date: 2024 January 20, 00:07
Breaking Change (v0.11.1)¶
What's Changed¶
- Bump of Version to 0.11.1 (#371) @devsetgo
- Query Improvement (#370) @devsetgo
- 368 get one record should return an empty value when called (#369) @devsetgo
- updating docs from v0.11.0 release (#367) @devsetgo
Published Date: 2023 December 23, 10:49
Full Release of New Features (v0.11.0)¶
What's Changed¶
- Prep for Release (#366) @devsetgo
- Fixing sonar settings (#365) @devsetgo
- Fixes and improvements (#364) @devsetgo
- Dev (#362) @devsetgo
- Fix of issues from Beta release (#361) @devsetgo
- 359 tables are created before create tables is called (#360) @devsetgo
- Change Log (#358) @devsetgo
- fixing latest-changes (#357) @devsetgo
- removing jinja template from Latest Changes Action (#356) @devsetgo
- Action fixing adding main (#355) @devsetgo
- Fixing actions (#354) @devsetgo
- Fixing Beta Publishing issues and Documentation Improvements (#353) @devsetgo
- Update setup.py for sub packages (#352) @devsetgo
- Import Bug Fix (#351) @devsetgo
- Latest Changes Action Fix (#350) @devsetgo
- Next Release (#349) @devsetgo
- Dev (#348) @devsetgo
- pip(deps): bump autopep8 from 2.0.2 to 2.0.4 (#343) @dependabot
- pip(deps): bump wheel from 0.41.2 to 0.42.0 (#345) @dependabot
- pip(deps): bump mkdocstrings[python] from 0.21.2 to 0.24.0 (#346) @dependabot
- pip(deps): bump mkdocs from 1.4.3 to 1.5.3 (#347) @dependabot
- pip(deps): bump flake8 from 6.0.0 to 6.1.0 (#332) @dependabot
- pip(deps): bump click from 8.1.3 to 8.1.7 (#337) @dependabot
- pip(deps): bump wheel from 0.40.0 to 0.41.2 (#339) @dependabot
- github actionts(deps): bump actions/checkout from 2 to 4 (#340) @dependabot
- pip(deps): bump mkdocs-material from 9.1.17 to 9.4.2 (#341) @dependabot
- pip(deps): bump black from 23.3.0 to 23.9.1 (#342) @dependabot
- pip(deps): bump mkdocs-material from 9.1.15 to 9.1.17 (#326) @dependabot
- pip(deps): bump pytest from 7.3.1 to 7.4.0 (#327) @dependabot
- pip(deps): bump mkdocs from 1.4.2 to 1.4.3 (#328) @dependabot
- pip(deps): bump autoflake from 2.1.1 to 2.2.0 (#329) @dependabot
- pip(deps): bump pre-commit from 3.2.2 to 3.3.3 (#330) @dependabot
- pip(deps): bump mkdocs-material from 9.1.9 to 9.1.15 (#325) @dependabot
- pip(deps): bump autoflake from 2.0.2 to 2.1.1 (#324) @dependabot
- pip(deps): bump pytest-xdist from 3.2.1 to 3.3.1 (#323) @dependabot
- pip(deps): bump tox from 4.4.11 to 4.5.2 (#322) @dependabot
- pip(deps): bump pytest-cov from 4.0.0 to 4.1.0 (#321) @dependabot
- pip(deps): bump loguru from 0.6.0 to 0.7.0 (#317) @dependabot
- pip(deps): bump mkdocs-gen-files from 0.4.0 to 0.5.0 (#314) @dependabot
- pip(deps): bump pylint from 2.17.2 to 2.17.4 (#319) @dependabot
- pip(deps): bump mkdocs-material from 9.1.6 to 9.1.9 (#320) @dependabot
- pip(deps): bump pytest from 7.3.0 to 7.3.1 (#318) @dependabot
Published Date: 2023 December 17, 22:00
Beta Release with fixes for multiple issues (v0.11.0-beta3-fix1)¶
What's Changed¶
- Dev (#362) @devsetgo
- Fix of issues from Beta release (#361) @devsetgo
- 359 tables are created before create tables is called (#360) @devsetgo
- Change Log (#358) @devsetgo
- fixing latest-changes (#357) @devsetgo
- removing jinja template from Latest Changes Action (#356) @devsetgo
- Action fixing adding main (#355) @devsetgo
- Fixing actions (#354) @devsetgo
- Fixing Beta Publishing issues and Documentation Improvements (#353) @devsetgo
- Update setup.py for sub packages (#352) @devsetgo
- Import Bug Fix (#351) @devsetgo
- Latest Changes Action Fix (#350) @devsetgo
- Next Release (#349) @devsetgo
- Dev (#348) @devsetgo
- pip(deps): bump autopep8 from 2.0.2 to 2.0.4 (#343) @dependabot
- pip(deps): bump wheel from 0.41.2 to 0.42.0 (#345) @dependabot
- pip(deps): bump mkdocstrings[python] from 0.21.2 to 0.24.0 (#346) @dependabot
- pip(deps): bump mkdocs from 1.4.3 to 1.5.3 (#347) @dependabot
- pip(deps): bump flake8 from 6.0.0 to 6.1.0 (#332) @dependabot
- pip(deps): bump click from 8.1.3 to 8.1.7 (#337) @dependabot
- pip(deps): bump wheel from 0.40.0 to 0.41.2 (#339) @dependabot
- github actionts(deps): bump actions/checkout from 2 to 4 (#340) @dependabot
- pip(deps): bump mkdocs-material from 9.1.17 to 9.4.2 (#341) @dependabot
- pip(deps): bump black from 23.3.0 to 23.9.1 (#342) @dependabot
- pip(deps): bump mkdocs-material from 9.1.15 to 9.1.17 (#326) @dependabot
- pip(deps): bump pytest from 7.3.1 to 7.4.0 (#327) @dependabot
- pip(deps): bump mkdocs from 1.4.2 to 1.4.3 (#328) @dependabot
- pip(deps): bump autoflake from 2.1.1 to 2.2.0 (#329) @dependabot
- pip(deps): bump pre-commit from 3.2.2 to 3.3.3 (#330) @dependabot
- pip(deps): bump mkdocs-material from 9.1.9 to 9.1.15 (#325) @dependabot
- pip(deps): bump autoflake from 2.0.2 to 2.1.1 (#324) @dependabot
- pip(deps): bump pytest-xdist from 3.2.1 to 3.3.1 (#323) @dependabot
- pip(deps): bump tox from 4.4.11 to 4.5.2 (#322) @dependabot
- pip(deps): bump pytest-cov from 4.0.0 to 4.1.0 (#321) @dependabot
- pip(deps): bump loguru from 0.6.0 to 0.7.0 (#317) @dependabot
- pip(deps): bump mkdocs-gen-files from 0.4.0 to 0.5.0 (#314) @dependabot
- pip(deps): bump pylint from 2.17.2 to 2.17.4 (#319) @dependabot
- pip(deps): bump mkdocs-material from 9.1.6 to 9.1.9 (#320) @dependabot
- pip(deps): bump pytest from 7.3.0 to 7.3.1 (#318) @dependabot
Published Date: 2023 December 17, 16:23
Fixing AsyncDatabase create tables (v0.11.0-beta3)¶
What's Changed¶
- Fix of issues from Beta release (#361) @devsetgo
- 359 tables are created before create tables is called (#360) @devsetgo
- Change Log (#358) @devsetgo
- fixing latest-changes (#357) @devsetgo
- removing jinja template from Latest Changes Action (#356) @devsetgo
- Action fixing adding main (#355) @devsetgo
- Fixing actions (#354) @devsetgo
- Fixing Beta Publishing issues and Documentation Improvements (#353) @devsetgo
- Update setup.py for sub packages (#352) @devsetgo
- Import Bug Fix (#351) @devsetgo
- Latest Changes Action Fix (#350) @devsetgo
- Next Release (#349) @devsetgo
- Dev (#348) @devsetgo
- pip(deps): bump autopep8 from 2.0.2 to 2.0.4 (#343) @dependabot
- pip(deps): bump wheel from 0.41.2 to 0.42.0 (#345) @dependabot
- pip(deps): bump mkdocstrings[python] from 0.21.2 to 0.24.0 (#346) @dependabot
- pip(deps): bump mkdocs from 1.4.3 to 1.5.3 (#347) @dependabot
- pip(deps): bump flake8 from 6.0.0 to 6.1.0 (#332) @dependabot
- pip(deps): bump click from 8.1.3 to 8.1.7 (#337) @dependabot
- pip(deps): bump wheel from 0.40.0 to 0.41.2 (#339) @dependabot
- github actionts(deps): bump actions/checkout from 2 to 4 (#340) @dependabot
- pip(deps): bump mkdocs-material from 9.1.17 to 9.4.2 (#341) @dependabot
- pip(deps): bump black from 23.3.0 to 23.9.1 (#342) @dependabot
- pip(deps): bump mkdocs-material from 9.1.15 to 9.1.17 (#326) @dependabot
- pip(deps): bump pytest from 7.3.1 to 7.4.0 (#327) @dependabot
- pip(deps): bump mkdocs from 1.4.2 to 1.4.3 (#328) @dependabot
- pip(deps): bump autoflake from 2.1.1 to 2.2.0 (#329) @dependabot
- pip(deps): bump pre-commit from 3.2.2 to 3.3.3 (#330) @dependabot
- pip(deps): bump mkdocs-material from 9.1.9 to 9.1.15 (#325) @dependabot
- pip(deps): bump autoflake from 2.0.2 to 2.1.1 (#324) @dependabot
- pip(deps): bump pytest-xdist from 3.2.1 to 3.3.1 (#323) @dependabot
- pip(deps): bump tox from 4.4.11 to 4.5.2 (#322) @dependabot
- pip(deps): bump pytest-cov from 4.0.0 to 4.1.0 (#321) @dependabot
- pip(deps): bump loguru from 0.6.0 to 0.7.0 (#317) @dependabot
- pip(deps): bump mkdocs-gen-files from 0.4.0 to 0.5.0 (#314) @dependabot
- pip(deps): bump pylint from 2.17.2 to 2.17.4 (#319) @dependabot
- pip(deps): bump mkdocs-material from 9.1.6 to 9.1.9 (#320) @dependabot
- pip(deps): bump pytest from 7.3.0 to 7.3.1 (#318) @dependabot
Published Date: 2023 December 17, 16:18
Build Updates (v0.11.0-beta2)¶
What's Changed¶
- Change Log (#358) @devsetgo
- fixing latest-changes (#357) @devsetgo
- removing jinja template from Latest Changes Action (#356) @devsetgo
- Action fixing adding main (#355) @devsetgo
- Fixing actions (#354) @devsetgo
- Fixing Beta Publishing issues and Documentation Improvements (#353) @devsetgo
- Update setup.py for sub packages (#352) @devsetgo
- Import Bug Fix (#351) @devsetgo
- Latest Changes Action Fix (#350) @devsetgo
- Next Release (#349) @devsetgo
- Dev (#348) @devsetgo
- pip(deps): bump autopep8 from 2.0.2 to 2.0.4 (#343) @dependabot
- pip(deps): bump wheel from 0.41.2 to 0.42.0 (#345) @dependabot
- pip(deps): bump mkdocstrings[python] from 0.21.2 to 0.24.0 (#346) @dependabot
- pip(deps): bump mkdocs from 1.4.3 to 1.5.3 (#347) @dependabot
- pip(deps): bump flake8 from 6.0.0 to 6.1.0 (#332) @dependabot
- pip(deps): bump click from 8.1.3 to 8.1.7 (#337) @dependabot
- pip(deps): bump wheel from 0.40.0 to 0.41.2 (#339) @dependabot
- github actionts(deps): bump actions/checkout from 2 to 4 (#340) @dependabot
- pip(deps): bump mkdocs-material from 9.1.17 to 9.4.2 (#341) @dependabot
- pip(deps): bump black from 23.3.0 to 23.9.1 (#342) @dependabot
- pip(deps): bump mkdocs-material from 9.1.15 to 9.1.17 (#326) @dependabot
- pip(deps): bump pytest from 7.3.1 to 7.4.0 (#327) @dependabot
- pip(deps): bump mkdocs from 1.4.2 to 1.4.3 (#328) @dependabot
- pip(deps): bump autoflake from 2.1.1 to 2.2.0 (#329) @dependabot
- pip(deps): bump pre-commit from 3.2.2 to 3.3.3 (#330) @dependabot
- pip(deps): bump mkdocs-material from 9.1.9 to 9.1.15 (#325) @dependabot
- pip(deps): bump autoflake from 2.0.2 to 2.1.1 (#324) @dependabot
- pip(deps): bump pytest-xdist from 3.2.1 to 3.3.1 (#323) @dependabot
- pip(deps): bump tox from 4.4.11 to 4.5.2 (#322) @dependabot
- pip(deps): bump pytest-cov from 4.0.0 to 4.1.0 (#321) @dependabot
- pip(deps): bump loguru from 0.6.0 to 0.7.0 (#317) @dependabot
- pip(deps): bump mkdocs-gen-files from 0.4.0 to 0.5.0 (#314) @dependabot
- pip(deps): bump pylint from 2.17.2 to 2.17.4 (#319) @dependabot
- pip(deps): bump mkdocs-material from 9.1.6 to 9.1.9 (#320) @dependabot
- pip(deps): bump pytest from 7.3.0 to 7.3.1 (#318) @dependabot
Published Date: 2023 December 16, 20:34
Beta Release with fixes for multiple issues (v0.11.0-beta1-fix5)¶
What's Changed¶
- fixing latest-changes (#357) @devsetgo
- removing jinja template from Latest Changes Action (#356) @devsetgo
- Action fixing adding main (#355) @devsetgo
- Fixing actions (#354) @devsetgo
- Fixing Beta Publishing issues and Documentation Improvements (#353) @devsetgo
- Update setup.py for sub packages (#352) @devsetgo
- Import Bug Fix (#351) @devsetgo
- Latest Changes Action Fix (#350) @devsetgo
- Next Release (#349) @devsetgo
- Dev (#348) @devsetgo
- pip(deps): bump autopep8 from 2.0.2 to 2.0.4 (#343) @dependabot
- pip(deps): bump wheel from 0.41.2 to 0.42.0 (#345) @dependabot
- pip(deps): bump mkdocstrings[python] from 0.21.2 to 0.24.0 (#346) @dependabot
- pip(deps): bump mkdocs from 1.4.3 to 1.5.3 (#347) @dependabot
- pip(deps): bump flake8 from 6.0.0 to 6.1.0 (#332) @dependabot
- pip(deps): bump click from 8.1.3 to 8.1.7 (#337) @dependabot
- pip(deps): bump wheel from 0.40.0 to 0.41.2 (#339) @dependabot
- github actionts(deps): bump actions/checkout from 2 to 4 (#340) @dependabot
- pip(deps): bump mkdocs-material from 9.1.17 to 9.4.2 (#341) @dependabot
- pip(deps): bump black from 23.3.0 to 23.9.1 (#342) @dependabot
- pip(deps): bump mkdocs-material from 9.1.15 to 9.1.17 (#326) @dependabot
- pip(deps): bump pytest from 7.3.1 to 7.4.0 (#327) @dependabot
- pip(deps): bump mkdocs from 1.4.2 to 1.4.3 (#328) @dependabot
- pip(deps): bump autoflake from 2.1.1 to 2.2.0 (#329) @dependabot
- pip(deps): bump pre-commit from 3.2.2 to 3.3.3 (#330) @dependabot
- pip(deps): bump mkdocs-material from 9.1.9 to 9.1.15 (#325) @dependabot
- pip(deps): bump autoflake from 2.0.2 to 2.1.1 (#324) @dependabot
- pip(deps): bump pytest-xdist from 3.2.1 to 3.3.1 (#323) @dependabot
- pip(deps): bump tox from 4.4.11 to 4.5.2 (#322) @dependabot
- pip(deps): bump pytest-cov from 4.0.0 to 4.1.0 (#321) @dependabot
- pip(deps): bump loguru from 0.6.0 to 0.7.0 (#317) @dependabot
- pip(deps): bump mkdocs-gen-files from 0.4.0 to 0.5.0 (#314) @dependabot
- pip(deps): bump pylint from 2.17.2 to 2.17.4 (#319) @dependabot
- pip(deps): bump mkdocs-material from 9.1.6 to 9.1.9 (#320) @dependabot
- pip(deps): bump pytest from 7.3.0 to 7.3.1 (#318) @dependabot
Published Date: 2023 December 16, 16:33
Build Fixes (v0.11.0-beta1-fix4)¶
What's Changed¶
- Update setup.py for sub packages (#352) @devsetgo
- Import Bug Fix (#351) @devsetgo
- Latest Changes Action Fix (#350) @devsetgo
- Next Release (#349) @devsetgo
- Dev (#348) @devsetgo
- pip(deps): bump autopep8 from 2.0.2 to 2.0.4 (#343) @dependabot
- pip(deps): bump wheel from 0.41.2 to 0.42.0 (#345) @dependabot
- pip(deps): bump mkdocstrings[python] from 0.21.2 to 0.24.0 (#346) @dependabot
- pip(deps): bump mkdocs from 1.4.3 to 1.5.3 (#347) @dependabot
- pip(deps): bump flake8 from 6.0.0 to 6.1.0 (#332) @dependabot
- pip(deps): bump click from 8.1.3 to 8.1.7 (#337) @dependabot
- pip(deps): bump wheel from 0.40.0 to 0.41.2 (#339) @dependabot
- github actionts(deps): bump actions/checkout from 2 to 4 (#340) @dependabot
- pip(deps): bump mkdocs-material from 9.1.17 to 9.4.2 (#341) @dependabot
- pip(deps): bump black from 23.3.0 to 23.9.1 (#342) @dependabot
- pip(deps): bump mkdocs-material from 9.1.15 to 9.1.17 (#326) @dependabot
- pip(deps): bump pytest from 7.3.1 to 7.4.0 (#327) @dependabot
- pip(deps): bump mkdocs from 1.4.2 to 1.4.3 (#328) @dependabot
- pip(deps): bump autoflake from 2.1.1 to 2.2.0 (#329) @dependabot
- pip(deps): bump pre-commit from 3.2.2 to 3.3.3 (#330) @dependabot
- pip(deps): bump mkdocs-material from 9.1.9 to 9.1.15 (#325) @dependabot
- pip(deps): bump autoflake from 2.0.2 to 2.1.1 (#324) @dependabot
- pip(deps): bump pytest-xdist from 3.2.1 to 3.3.1 (#323) @dependabot
- pip(deps): bump tox from 4.4.11 to 4.5.2 (#322) @dependabot
- pip(deps): bump pytest-cov from 4.0.0 to 4.1.0 (#321) @dependabot
- pip(deps): bump loguru from 0.6.0 to 0.7.0 (#317) @dependabot
- pip(deps): bump mkdocs-gen-files from 0.4.0 to 0.5.0 (#314) @dependabot
- pip(deps): bump pylint from 2.17.2 to 2.17.4 (#319) @dependabot
- pip(deps): bump mkdocs-material from 9.1.6 to 9.1.9 (#320) @dependabot
- pip(deps): bump pytest from 7.3.0 to 7.3.1 (#318) @dependabot
Published Date: 2023 December 12, 11:45
Async Database and FastAPI functions (v0.11.0-beta0)¶
What's Changed¶
- Dev (#348) @devsetgo - New functionality and documentation for FastAPI Endpoints and Async Database Functionality
- pip(deps): bump autopep8 from 2.0.2 to 2.0.4 (#343) @dependabot
- pip(deps): bump wheel from 0.41.2 to 0.42.0 (#345) @dependabot
- pip(deps): bump mkdocstrings[python] from 0.21.2 to 0.24.0 (#346) @dependabot
- pip(deps): bump mkdocs from 1.4.3 to 1.5.3 (#347) @dependabot
- pip(deps): bump flake8 from 6.0.0 to 6.1.0 (#332) @dependabot
- pip(deps): bump click from 8.1.3 to 8.1.7 (#337) @dependabot
- pip(deps): bump wheel from 0.40.0 to 0.41.2 (#339) @dependabot
- github actionts(deps): bump actions/checkout from 2 to 4 (#340) @dependabot
- pip(deps): bump mkdocs-material from 9.1.17 to 9.4.2 (#341) @dependabot
- pip(deps): bump black from 23.3.0 to 23.9.1 (#342) @dependabot
- pip(deps): bump mkdocs-material from 9.1.15 to 9.1.17 (#326) @dependabot
- pip(deps): bump pytest from 7.3.1 to 7.4.0 (#327) @dependabot
- pip(deps): bump mkdocs from 1.4.2 to 1.4.3 (#328) @dependabot
- pip(deps): bump autoflake from 2.1.1 to 2.2.0 (#329) @dependabot
- pip(deps): bump pre-commit from 3.2.2 to 3.3.3 (#330) @dependabot
- pip(deps): bump mkdocs-material from 9.1.9 to 9.1.15 (#325) @dependabot
- pip(deps): bump autoflake from 2.0.2 to 2.1.1 (#324) @dependabot
- pip(deps): bump pytest-xdist from 3.2.1 to 3.3.1 (#323) @dependabot
- pip(deps): bump tox from 4.4.11 to 4.5.2 (#322) @dependabot
- pip(deps): bump pytest-cov from 4.0.0 to 4.1.0 (#321) @dependabot
- pip(deps): bump loguru from 0.6.0 to 0.7.0 (#317) @dependabot
- pip(deps): bump mkdocs-gen-files from 0.4.0 to 0.5.0 (#314) @dependabot
- pip(deps): bump pylint from 2.17.2 to 2.17.4 (#319) @dependabot
- pip(deps): bump mkdocs-material from 9.1.6 to 9.1.9 (#320) @dependabot
- pip(deps): bump pytest from 7.3.0 to 7.3.1 (#318) @dependabot
Published Date: 2023 December 10, 20:17
Pattern Analysis Update and Bug Fix (v0.10.1)¶
What's Changed¶
- Improvement to the patterns analysis (#313) @devsetgo
- pip(deps): bump mkdocs-material from 9.1.3 to 9.1.5 (#308) @dependabot
- pip(deps): bump pre-commit from 3.2.0 to 3.2.1 (#310) @dependabot
- pip(deps): bump watchdog from 2.3.1 to 3.0.0 (#309) @dependabot
- pip(deps): bump pylint from 2.17.0 to 2.17.1 (#311) @dependabot
- pip(deps): bump tox from 4.4.7 to 4.4.8 (#312) @dependabot
Published Date: 2023 April 08, 21:45
ChatGPT Driven Improvements (v0.10.0)¶
ChatGPT¶
Using ChatGPT to improve tests, find bugs, and improve performance. Code coverage is at 100% and the code base appears to be performing better than before.
Major changes are in PR #304
What's Changed¶
- latest change fix for regex pattern. (#307) @devsetgo
- Dev (#306) @devsetgo
- Workflow changes (#305) @devsetgo
- ChatGPT Driven Improvements (#304) @devsetgo
- pip(deps): bump pre-commit from 3.0.2 to 3.1.1 (#300) @dependabot
- pip(deps): bump pytest-xdist from 3.1.0 to 3.2.0 (#302) @dependabot
- pip(deps): bump autoflake from 2.0.0 to 2.0.1 (#299) @dependabot
- pip(deps): bump watchdog from 2.1.9 to 2.3.1 (#301) @dependabot
- pip(deps): bump pytest from 7.2.0 to 7.2.1 (#303) @dependabot
- pip(deps): bump pylint from 2.15.7 to 2.16.1 (#298) @dependabot
- pip(deps): bump autopep8 from 2.0.0 to 2.0.1 (#289) @dependabot
- pip(deps): bump pylint from 2.15.7 to 2.15.10 (#295) @dependabot
- pip(deps): bump black from 22.10.0 to 23.1.0 (#294) @dependabot
- pip(deps): bump tox from 3.27.1 to 4.4.4 (#296) @dependabot
- pip(deps): bump pre-commit from 2.20.0 to 3.0.2 (#297) @dependabot
Published Date: 2023 April 01, 00:27
Open CSV enhancements and library updates (v0.9.0)¶
What's Changed¶
- fix of latest changes (#288) @devsetgo
- Open_CSV Enhancements (#287) @devsetgo
- pip(deps): bump pytest-cov from 3.0.0 to 4.0.0 (#274) @dependabot
- pip(deps): bump mkdocs-material from 8.4.2 to 8.5.5 (#276) @dependabot
- pip(deps): bump autoflake from 1.5.3 to 1.6.1 (#275) @dependabot
- pip(deps): bump tqdm from 4.64.0 to 4.64.1 (#273) @dependabot
- pip(deps): bump pytest from 7.1.2 to 7.1.3 (#272) @dependabot
- pip(deps): bump mkdocs from 1.3.1 to 1.4.0 (#271) @dependabot
- pip(deps): bump tox from 3.25.1 to 3.26.0 (#269) @dependabot
- pip(deps): bump pylint from 2.15.0 to 2.15.3 (#270) @dependabot
- pip(deps): bump mkdocs-material from 8.3.9 to 8.4.2 (#268) @dependabot
- pip(deps): bump autopep8 from 1.6.0 to 1.7.0 (#264) @dependabot
- pip(deps): bump pylint from 2.14.5 to 2.15.0 (#265) @dependabot
- pip(deps): bump autoflake from 1.4 to 1.5.3 (#263) @dependabot
- pip(deps): bump black from 22.6.0 to 22.8.0 (#267) @dependabot
- pip(deps): bump flake8 from 5.0.1 to 5.0.4 (#266) @dependabot
- pip(deps): bump pre-commit from 2.19.0 to 2.20.0 (#260) @dependabot
- pip(deps): bump mkdocs from 1.3.0 to 1.3.1 (#261) @dependabot
- pip(deps): bump flake8 from 4.0.1 to 5.0.1 (#259) @dependabot
- pip(deps): bump mkdocs-material from 8.3.8 to 8.3.9 (#258) @dependabot
- pip(deps): bump pylint from 2.14.4 to 2.14.5 (#262) @dependabot
- pip(deps): bump twine from 4.0.0 to 4.0.1 (#252) @dependabot
- pip(deps): bump pylint from 2.14.0 to 2.14.4 (#251) @dependabot
- pip(deps): bump mkdocs-material from 8.2.16 to 8.3.8 (#253) @dependabot
- pip(deps): bump black from 22.3.0 to 22.6.0 (#254) @dependabot
- pip(deps): bump tox from 3.25.0 to 3.25.1 (#255) @dependabot
- pip(deps): bump watchdog from 2.1.8 to 2.1.9 (#256) @dependabot
- github actionts(deps): bump actions/setup-python from 3 to 4 (#257) @dependabot
- pip(deps): bump pylint from 2.13.7 to 2.14.0 (#250) @dependabot
- pip(deps): bump watchdog from 2.1.7 to 2.1.8 (#246) @dependabot
- pip(deps): bump pre-commit from 2.18.1 to 2.19.0 (#248) @dependabot
- pip(deps): bump mkdocs-material from 8.2.12 to 8.2.16 (#249) @dependabot
- pip(deps): bump tox from 3.24.5 to 3.25.0 (#242) @dependabot
- pip(deps): bump pre-commit from 2.17.0 to 2.18.1 (#243) @dependabot
- pip(deps): bump click from 8.1.2 to 8.1.3 (#245) @dependabot
- pip(deps): bump pylint from 2.13.4 to 2.13.7 (#240) @dependabot
- pip(deps): bump tqdm from 4.63.1 to 4.64.0 (#244) @dependabot
- pip(deps): bump mkdocs-material from 8.2.8 to 8.2.12 (#241) @dependabot
- pip(deps): bump pytest from 7.1.1 to 7.1.2 (#239) @dependabot
- pip(deps): bump watchdog from 2.1.6 to 2.1.7 (#238) @dependabot
- pip(deps): bump pylint from 2.12.2 to 2.13.4 (#237) @dependabot
- pip(deps): bump mkdocs from 1.2.3 to 1.3.0 (#234) @dependabot
- pip(deps): bump tqdm from 4.63.0 to 4.63.1 (#233) @dependabot
- pip(deps): bump black from 22.1.0 to 22.3.0 (#236) @dependabot
- pip(deps): bump pytest from 7.0.1 to 7.1.1 (#231) @dependabot
- pip(deps): bump click from 8.0.4 to 8.1.2 (#235) @dependabot
- pip(deps): bump mkdocs-material from 8.2.5 to 8.2.8 (#232) @dependabot
- pip(deps): bump twine from 3.8.0 to 4.0.0 (#230) @dependabot
- document updates (#229) @devsetgo
Published Date: 2022 December 04, 16:55
Additional Logging Configuration (v0.8.0)¶
What's Changed¶
- New Logging Configuration items (#228) @devsetgo
- pip(deps): bump tqdm from 4.62.3 to 4.63.0 (#224) @dependabot
- pip(deps): bump mkdocs-material from 8.2.3 to 8.2.4 (#227) @dependabot
- github actionts(deps): bump actions/setup-python from 2.3.1 to 3 (#226) @dependabot
- pip(deps): bump mkdocs-material from 8.1.9 to 8.2.3 (#225) @dependabot
- pip(deps): bump twine from 3.7.1 to 3.8.0 (#223) @dependabot
- pip(deps): bump pytest from 6.2.5 to 7.0.1 (#222) @dependabot
- pip(deps): bump pytest-runner from 5.3.1 to 6.0.0 (#221) @dependabot
- pip(deps): bump loguru from 0.5.3 to 0.6.0 (#218) @dependabot
- pip(deps): bump black from 21.12b0 to 22.1.0 (#219) @dependabot
- pip(deps): bump mkdocs-material from 8.1.8 to 8.1.9 (#220) @dependabot
Published Date: 2022 March 12, 21:07
(v0.7.1)¶
What's Changed¶
- Bump version: 0.7.0 → 0.7.1 (#217) @devsetgo
- Hotfix for setup file (#216) @devsetgo
Published Date: 2022 January 29, 01:51
Logging to Beta Testing (v0.7.0)¶
Logging is now has basic unit tests and is more ready to use with live application.
What's Changed¶
- Adding Logging Config (#215) @devsetgo
- pip(deps): bump pre-commit from 2.15.0 to 2.16.0 (#210) @dependabot
- pip(deps): bump pylint from 2.12.1 to 2.12.2 (#211) @dependabot
- pip(deps): bump tox from 3.24.4 to 3.24.5 (#212) @dependabot
- pip(deps): bump black from 21.11b1 to 21.12b0 (#213) @dependabot
- pip(deps): bump twine from 3.6.0 to 3.7.1 (#214) @dependabot
- pip(deps): bump twine from 3.5.0 to 3.6.0 (#204) @dependabot
- pip(deps): bump coverage-badge from 1.0.2 to 1.1.0 (#205) @dependabot
- pip(deps): bump mkdocs-material from 7.3.6 to 8.0.2 (#206) @dependabot
- pip(deps): bump pylint from 2.11.1 to 2.12.1 (#207) @dependabot
- pip(deps): bump black from 21.10b0 to 21.11b1 (#208) @dependabot
- github actionts(deps): bump actions/setup-python from 2.2.2 to 2.3.1 (#209) @dependabot
- Dev (#203) @devsetgo
- pip(deps): bump tox from 3.24.3 to 3.24.4 (#193) @dependabot
- pip(deps): bump tqdm from 4.62.2 to 4.62.3 (#194) @dependabot
- pip(deps): bump pylint from 2.10.2 to 2.11.1 (#195) @dependabot
- pip(deps): bump mkdocs-material from 7.2.6 to 7.3.0 (#196) @dependabot
- pip(deps): bump black from 21.8b0 to 21.9b0 (#197) @dependabot
- pip(deps): bump mkdocs-material from 7.2.4 to 7.2.6 (#189) @dependabot
- pip(deps): bump pytest from 6.2.4 to 6.2.5 (#191) @dependabot
- pip(deps): bump watchdog from 2.1.3 to 2.1.5 (#192) @dependabot
- pip(deps): bump tox from 3.24.1 to 3.24.3 (#190) @dependabot
- pip(deps): bump pre-commit from 2.14.0 to 2.15.0 (#188) @dependabot
- pip(deps): bump black from 21.7b0 to 21.8b0 (#187) @dependabot
- pip(deps): bump pylint from 2.9.6 to 2.10.2 (#184) @dependabot
- pip(deps): bump tqdm from 4.62.0 to 4.62.2 (#185) @dependabot
- github actionts(deps): bump actions/setup-python from 1 to 2.2.2 (#182) @dependabot
- Bump wheel from 0.36.2 to 0.37.0 (#180) @dependabot
- Bump mkdocs-material from 7.2.2 to 7.2.4 (#181) @dependabot
- Bump tox from 3.24.0 to 3.24.1 (#177) @dependabot
- Bump mkdocs-material from 7.2.1 to 7.2.2 (#178) @dependabot
- Bump pre-commit from 2.13.0 to 2.14.0 (#179) @dependabot
- Bump pylint from 2.9.5 to 2.9.6 (#176) @dependabot
- Bump tqdm from 4.61.2 to 4.62.0 (#175) @dependabot
- Bump mkdocs-material from 7.1.10 to 7.2.1 (#174) @dependabot
- Bump twine from 3.4.1 to 3.4.2 (#171) @dependabot
- Bump pylint from 2.9.3 to 2.9.5 (#170) @dependabot
- Bump mkdocs from 1.2.1 to 1.2.2 (#173) @dependabot
- documentation update (#169) @devsetgo
- README fix (#168) @devsetgo
Published Date: 2022 January 29, 01:42
Logging Configuration (v0.6.0)¶
What's Changed¶
- Adding Logging and Cleanup (#167) @devsetgo
- Bump tqdm from 4.61.1 to 4.61.2 (#166) @dependabot
- Bump pylint from 2.8.3 to 2.9.3 (#165) @dependabot
- Bump watchdog from 2.1.2 to 2.1.3 (#164) @dependabot
- Bump mkdocs-material from 7.1.8 to 7.1.9 (#163) @dependabot
- Bump tqdm from 4.61.0 to 4.61.1 (#162) @dependabot
- Bump mkdocs-material from 7.1.7 to 7.1.8 (#161) @dependabot
- Bump mkdocs from 1.1.2 to 1.2.1 (#159) @dependabot
- Bump black from 21.5b2 to 21.6b0 (#158) @dependabot
- Bump mkdocs-material from 7.1.6 to 7.1.7 (#160) @dependabot
- Bump pytest-cov from 2.12.0 to 2.12.1 (#154) @dependabot
- Bump pylint from 2.8.2 to 2.8.3 (#155) @dependabot
- Bump black from 21.5b1 to 21.5b2 (#156) @dependabot
- Bump mkdocs-material from 7.1.5 to 7.1.6 (#157) @dependabot
- Bump tqdm from 4.60.0 to 4.61.0 (#153) @dependabot
- Bump pre-commit from 2.12.1 to 2.13.0 (#151) @dependabot
- Bump pytest-runner from 5.3.0 to 5.3.1 (#152) @dependabot
- Bump mkdocs-material from 7.1.4 to 7.1.5 (#150) @dependabot
- Bump watchdog from 2.1.1 to 2.1.2 (#149) @dependabot
- Bump click from 7.1.2 to 8.0.1 (#148) @dependabot
- Bump black from 21.5b0 to 21.5b1 (#147) @dependabot
- Bump watchdog from 2.1.0 to 2.1.1 (#146) @dependabot
- Bump pytest-cov from 2.11.1 to 2.12.0 (#145) @dependabot
- Bump flake8 from 3.9.1 to 3.9.2 (#143) @dependabot
- Bump pytest from 6.2.3 to 6.2.4 (#139) @dependabot
- Bump watchdog from 2.0.3 to 2.1.0 (#138) @dependabot
- Bump black from 21.4b2 to 21.5b0 (#140) @dependabot
- Bump mkdocs-material from 7.1.3 to 7.1.4 (#141) @dependabot
- Dev (#142) @devsetgo
- Bump tox from 3.23.0 to 3.23.1 (#137) @dependabot
- Bump autopep8 from 1.5.6 to 1.5.7 (#136) @dependabot
- Bump pylint from 2.7.4 to 2.8.2 (#135) @dependabot
- Bump black from 20.8b1 to 21.4b2 (#134) @dependabot
- Bump mkdocs-material from 7.1.2 to 7.1.3 (#133) @dependabot
- Adding SonarCloud Code Coverage (#130) @devsetgo
- Bump mkdocs-material from 7.1.1 to 7.1.2 (#132) @dependabot
- Bump watchdog from 2.0.2 to 2.0.3 (#131) @dependabot
- Bump pre-commit from 2.12.0 to 2.12.1 (#129) @dependabot
- Bump flake8 from 3.9.0 to 3.9.1 (#128) @dependabot
- Bump mkdocs-material from 7.1.0 to 7.1.1 (#127) @dependabot
- Bump tqdm from 4.59.0 to 4.60.0 (#124) @dependabot
- Bump pytest from 6.2.2 to 6.2.3 (#125) @dependabot
- Bump pre-commit from 2.11.1 to 2.12.0 (#126) @dependabot
- Bump pylint from 2.7.2 to 2.7.4 (#122) @dependabot
- Bump mkdocs-material from 7.0.6 to 7.1.0 (#123) @dependabot
- Bump mkdocs-material from 7.0.5 to 7.0.6 (#121) @dependabot
- Bump flake8 from 3.8.4 to 3.9.0 (#120) @dependabot
- Bump twine from 3.3.0 to 3.4.1 (#118) @dependabot
- Bump autopep8 from 1.5.5 to 1.5.6 (#119) @dependabot
Published Date: 2021 July 16, 23:44
Fixing Publish (v0.5.0-2)¶
What's Changed¶
- adding update for publish (#117) @devsetgo
Published Date: 2021 March 18, 17:19
Calendar and RegEx Function + Documentation (v0.5.0)¶
What's Changed¶
- Adding Calendar Functions (#116) @devsetgo
- Bump pre-commit from 2.10.1 to 2.11.1 (#113) @dependabot
- update to Saturday (#115) @devsetgo
- Bump tqdm from 4.58.0 to 4.59.0 (#112) @dependabot
- Bump mkdocs-material from 7.0.4 to 7.0.5 (#114) @dependabot
- fixes for mkdoc material update (#111) @devsetgo
- Bump tox from 3.22.0 to 3.23.0 (#109) @dependabot
- Bump mkdocs-material from 7.0.2 to 7.0.4 (#108) @dependabot
- Bump pylint from 2.7.1 to 2.7.2 (#107) @dependabot
- Bump coverage from 5.4 to 5.5 (#110) @dependabot
- Bump pylint from 2.6.2 to 2.7.1 (#103) @dependabot
- Bump mkdocs-material from 6.2.8 to 7.0.2 (#104) @dependabot
- Bump watchdog from 2.0.1 to 2.0.2 (#105) @dependabot
- Bump tqdm from 4.57.0 to 4.58.0 (#106) @dependabot
- Bump tox from 3.21.4 to 3.22.0 (#101) @dependabot
- Bump watchdog from 2.0.0 to 2.0.1 (#99) @dependabot
- Bump pylint from 2.6.0 to 2.6.2 (#102) @dependabot
- Bump tqdm from 4.56.2 to 4.57.0 (#100) @dependabot
- Bump pytest-runner from 5.2 to 5.3.0 (#98) @dependabot
- Bump tqdm from 4.56.0 to 4.56.2 (#97) @dependabot
- Bump watchdog from 1.0.2 to 2.0.0 (#96) @dependabot
- Bump pre-commit from 2.10.0 to 2.10.1 (#95) @dependabot
- Bump mkdocs-material from 6.2.6 to 6.2.8 (#94) @dependabot
- Bump tox from 3.21.3 to 3.21.4 (#93) @dependabot
- Bump autopep8 from 1.5.4 to 1.5.5 (#92) @dependabot
- Bump tox from 3.21.2 to 3.21.3 (#87) @dependabot
- Bump mkdocs-material from 6.2.5 to 6.2.6 (#88) @dependabot
- Bump pytest from 6.2.1 to 6.2.2 (#89) @dependabot
- Bump coverage from 5.3.1 to 5.4 (#91) @dependabot
- Bump pre-commit from 2.9.3 to 2.10.0 (#90) @dependabot
- Bump tox from 3.21.1 to 3.21.2 (#84) @dependabot
- Bump mkdocs-material from 6.2.4 to 6.2.5 (#85) @dependabot
- Bump pytest-cov from 2.10.1 to 2.11.1 (#86) @dependabot
- Bump tox from 3.20.1 to 3.21.1 (#81) @dependabot
- Bump mkdocs-material from 6.2.3 to 6.2.4 (#82) @dependabot
- Bump tqdm from 4.55.1 to 4.56.0 (#83) @dependabot
- Bump tqdm from 4.55.0 to 4.55.1 (#80) @dependabot
- Bump mkdocs-material from 6.2.2 to 6.2.3 (#79) @dependabot
Published Date: 2021 March 18, 17:06
Minor updates and library updates. (v0.4.1)¶
What's Changed¶
- Updates and Minor updates (#78) @devsetgo
- Bump tqdm from 4.54.1 to 4.55.0 (#77) @dependabot
- Bump twine from 3.2.0 to 3.3.0 (#76) @dependabot
- Bump coverage from 5.3 to 5.3.1 (#74) @dependabot
- Bump mkdocs-material from 6.1.7 to 6.2.2 (#75) @dependabot
- Bump watchdog from 0.10.4 to 1.0.2 (#73) @dependabot
- Bump pytest from 6.1.2 to 6.2.1 (#71) @dependabot
- Bump wheel from 0.36.1 to 0.36.2 (#70) @dependabot
- Bump tqdm from 4.54.0 to 4.54.1 (#67) @dependabot
- Bump mkdocs-material from 6.1.6 to 6.1.7 (#68) @dependabot
- Bump pre-commit from 2.9.2 to 2.9.3 (#69) @dependabot
- Bump wheel from 0.36.0 to 0.36.1 (#66) @dependabot
- Bump wheel from 0.35.1 to 0.36.0 (#64) @dependabot
- Bump tqdm from 4.53.0 to 4.54.0 (#65) @dependabot
- Bump pre-commit from 2.8.2 to 2.9.2 (#61) @dependabot
- Bump mkdocs-material from 6.1.5 to 6.1.6 (#60) @dependabot
- Bump tqdm from 4.52.0 to 4.53.0 (#62) @dependabot
- Bump watchdog from 0.10.3 to 0.10.4 (#63) @dependabot
- Bump tqdm from 4.51.0 to 4.52.0 (#59) @dependabot
- Bump mkdocs-material from 6.1.4 to 6.1.5 (#58) @dependabot
- Bump mkdocs-material from 6.1.2 to 6.1.4 (#57) @dependabot
- Bump pre-commit from 2.8.0 to 2.8.2 (#55) @dependabot
- Bump mkdocs-material from 6.1.0 to 6.1.2 (#56) @dependabot
- Bump pytest from 6.1.1 to 6.1.2 (#52) @dependabot
- Bump pre-commit from 2.7.1 to 2.8.0 (#53) @dependabot
- Bump tqdm from 4.50.2 to 4.51.0 (#54) @dependabot
- Bump mkdocs-material from 6.0.2 to 6.1.0 (#51) @dependabot
- Bump tqdm from 4.50.1 to 4.50.2 (#49) @dependabot
- Bump tox from 3.20.0 to 3.20.1 (#50) @dependabot
- Bump pytest from 6.1.0 to 6.1.1 (#48) @dependabot
- Bump mkdocs-material from 6.0.1 to 6.0.2 (#47) @dependabot
- Bump flake8 from 3.8.3 to 3.8.4 (#45) @dependabot
- Bump tqdm from 4.50.0 to 4.50.1 (#44) @dependabot
- Bump bump2version from 1.0.0 to 1.0.1 (#46) @dependabot
- Bump tqdm from 4.49.0 to 4.50.0 (#42) @dependabot
- Bump black from 19.10b0 to 20.8b1 (#43) @dependabot
- Bump tqdm from 4.46.0 to 4.49.0 (#40) @dependabot
- Bump pytest from 5.4.2 to 6.1.0 (#39) @dependabot
- Bump coverage from 5.1 to 5.3 (#38) @dependabot
- Bump autoflake from 1.3.1 to 1.4 (#41) @dependabot
- Bump twine from 3.1.1 to 3.2.0 (#37) @dependabot
- Bump wheel from 0.34.2 to 0.35.1 (#34) @dependabot
- Bump pytest-cov from 2.9.0 to 2.10.1 (#36) @dependabot
- Bump watchdog from 0.10.2 to 0.10.3 (#35) @dependabot
- Bump mkdocs-material from 5.2.2 to 6.0.1 (#33) @dependabot
- Bump pylint from 2.5.2 to 2.6.0 (#32) @dependabot-preview
- Bump pre-commit from 2.4.0 to 2.7.1 (#31) @dependabot-preview
- Bump tox from 3.15.1 to 3.20.0 (#30) @dependabot-preview
- Bump flake8 from 3.8.2 to 3.8.3 (#29) @dependabot-preview
- Bump autopep8 from 1.5.2 to 1.5.4 (#28) @dependabot-preview
Published Date: 2020 December 26, 23:51
0.4.0 - save_csv options (v0.4.0)¶
[0.4.0] - Examples and Data¶
Added¶
- skipping version 0.3.0 and adding to 0.4.0
- Adding delimiter option to save_csv
- Tests to check if delimiter > 1 character
- set ',' if none
- Adding quotechar option to save_csv
- Tests to check if quotechar > 1 character
- set '"' if none
- Add test of non-list to save_csv
[0.3.0] - Examples and Data¶
Added¶
- Adding examples (see examples folder)
- Adding file_function documentation
- Adding documents site - https://devsetgo.github.io/devsetgo_lib/
Published Date: 2020 April 16, 21:54
Improvements (v0.2.0)¶
- Improved Tests
- Improved Errors
- Adding more logging
Published Date: 2020 January 26, 21:08
v0.1.1 (v0.1.1)¶
- New documentation
- fixes to pypi deployment
Published Date: 2020 January 26, 17:26
Beta Release (v0.1.0b2)¶
Basic Function (file and folder) Publish to PyPi (fixing PyPi publishing issues) Needs documentation.
Published Date: 2020 January 26, 13:03
Pypi Beta Release (v0.1.0b)¶
Change to semantic versioning - Publish to Pypi - Base Functions
Published Date: 2020 January 26, 12:53