Name | dry-foundation JSON |
Version |
1.3.0
JSON |
| download |
home_page | None |
Summary | Tools and components for building customized and consistent small-scale Flask applications. |
upload_time | 2025-09-13 17:31:50 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.10 |
license | GNU GPLv3 |
keywords |
|
VCS |
 |
bugtrack_url |
|
requirements |
nox
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# DRY Foundation
<img src="https://raw.githubusercontent.com/mitchnegus/dry-foundation/main/img/logo/dry-logo.png" alt="DRY Foundation logo" />
Tools and components for building customized and consistent small-scale Flask applications.
## Why DRY?
**Don't Repeat Yourself.** Why write and maintain multiple copies of application infrastructure if it's going to be used and reused?
This package is designed to be a lightweight foundation a Flask application: it performs some of the database setup operations, coordinates database management for robust test suites, and also provides some utilities for enforcing authorization criteria for database access, among other things.
Here are some of the features explained in greater detail.
### Application Factories and Command Line Interfaces
The Flask command line interface (CLI) provides a lot of functionality via it's Click backend.
However, what if a user wishes to launch an application from the command line depending on a certain configuration.
The Flask documentation [shows an example of how to structure an application to leverage multiple configurations via objects](https://flask.palletsprojects.com/en/stable/config/#development-production), but leaves it up to a user to implement the mechanics of passing this configuration to the application via environment variable or some other script.
This package takes a different approach, and provides tools to customize the CLI so that configurations can be loaded dynamically at runtime.
Configurations are predefined (for production, development, and testing), and can be loaded by specifying a launch mode:
- **Production Mode:** Launch an app for production use, drawing from a production-style configuration.
- **Local Mode:** Launch an app for local use, using the Flask development server but still relying on a production-style configuration.
- **Development Mode:** Launch an app for development, with default debugging features and using a development style configuration.
A testing configuration is also built-in to provide test-specific configuration settings.
### Database Setup
One element of an application foundation is the testing infrastructure.
[Flask gives some guidance in the current edition of their documentation](https://flask.palletsprojects.com/en/2.3.x/tutorial/tests/#setup-and-fixtures), and it suggests creating a temporary SQLite database for each test.
This is perfectly fine for simple applications, but adds substantial overhead (and test time) to applications with many tests, especially for those where the database contains some preloaded information.
Instead, it would be preferable to create and use one temporary database instance for the majority of tests that only require read-access to the database, and then only create additional test databases for the tests that modify the state of the database (e.g., SQLAlchemy transactions).[^mocking]
_DRY Foundation_ provides the infrastructure to create databases in both of these cases: a "persistent" database for read-only tests, and "ephemeral" databases for each transaction).
The persistent test database is used by default, but a `transaction_lifetime` decorator can be used to indicate that a given test should use an ephemeral copy.
[^mocking]: Yes, you could also just not create databases and mock the database return functions, but my experience has been that it is even more tedious to maintain a comprehensive set of mocked data to test various intricacies and edge cases while simultaneously ensuring that the mocks behave similarly enough to SQLAlchemy objects.
### Authorization and Data Handlers
The common operations are easy to do using SQLAlchemy, but rather than rolling new functions for each new query in every application, this tool provides a set of handlers that are designed to abstract away a bunch of the tedious details.
Also, my experience is that enforcing authorization constraints when manipulating sophisticated table relationships can be tricky, and so this tool and its handlers provide an interface for managing those authorizations consistently.
It's possible I'm missing a key functionality of SQLAlchemy that enables this behavior elegantly, but I haven't found a satisfiably clean way to do it yet.
Until I become so enlightened, this package creates an interface where each model may define the chain of joins required to establish whether it belongs to an authorized user, and then a handler to query the database and perform those joins for each query.
This is designed to be extensible, since I often want this behavior available for the majority of ORM models in my application.
If you happen to read this and think "This dude's dumb; why on Earth didn't he use _this_ functionality baked into SQLAlchemy?" drop me a line because I'm interested to know what I'm missing.
## Installation
_DRY Foundation_ is registered on the [Python Package Index (PyPI)](https://pypi.org/project/...) for easy installation.
To install the package, simply run
```
pip install dry-foundation
```
The package requires a recent version of Python (3.10+).
## Usage
The app has lots of tools, but the basics can be used just as drop-in replacements for the standard `Flask` object and application factory.
```python
# DRY Application: `dry_application/__init__.py`
from dry_foundation import DryFlask, Factory
@Factory
def create_app(config=None):
app = DryFlask(__name__, app_name="DRY Application")
app.configure(config)
# Anything else performed by the application factory...
return app
```
For a more complete, up-to-date API reference, build and read the docs:
```bash
make docs
# open `docs/build/html/index.html` in your browser
```
## License
This project is licensed under the GNU General Public License, Version 3.
It is fully open-source, and while you are more than welcome to fork, add, modify, etc. it is required that you keep any distributed changes and additions open-source.
## Changes
Changes between versions are tracked in the [changelog](https://github.com/mitchnegus/dry-foundation/blob/main/./CHANGELOG.md).
Raw data
{
"_id": null,
"home_page": null,
"name": "dry-foundation",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": null,
"author": null,
"author_email": "Mitch Negus <mitchnegus57@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/e8/b8/e613e9651d71e7eab740bed3044170df68ab630ab5b037e041ee312f59e2/dry_foundation-1.3.0.tar.gz",
"platform": null,
"description": "# DRY Foundation\n\n<img src=\"https://raw.githubusercontent.com/mitchnegus/dry-foundation/main/img/logo/dry-logo.png\" alt=\"DRY Foundation logo\" />\n\nTools and components for building customized and consistent small-scale Flask applications.\n\n\n## Why DRY?\n\n**Don't Repeat Yourself.** Why write and maintain multiple copies of application infrastructure if it's going to be used and reused?\n\nThis package is designed to be a lightweight foundation a Flask application: it performs some of the database setup operations, coordinates database management for robust test suites, and also provides some utilities for enforcing authorization criteria for database access, among other things.\n\nHere are some of the features explained in greater detail.\n\n\n### Application Factories and Command Line Interfaces\n\nThe Flask command line interface (CLI) provides a lot of functionality via it's Click backend.\nHowever, what if a user wishes to launch an application from the command line depending on a certain configuration.\nThe Flask documentation [shows an example of how to structure an application to leverage multiple configurations via objects](https://flask.palletsprojects.com/en/stable/config/#development-production), but leaves it up to a user to implement the mechanics of passing this configuration to the application via environment variable or some other script.\n\nThis package takes a different approach, and provides tools to customize the CLI so that configurations can be loaded dynamically at runtime.\nConfigurations are predefined (for production, development, and testing), and can be loaded by specifying a launch mode:\n\n- **Production Mode:** Launch an app for production use, drawing from a production-style configuration.\n- **Local Mode:** Launch an app for local use, using the Flask development server but still relying on a production-style configuration.\n- **Development Mode:** Launch an app for development, with default debugging features and using a development style configuration.\n\nA testing configuration is also built-in to provide test-specific configuration settings.\n\n\n### Database Setup\n\nOne element of an application foundation is the testing infrastructure.\n[Flask gives some guidance in the current edition of their documentation](https://flask.palletsprojects.com/en/2.3.x/tutorial/tests/#setup-and-fixtures), and it suggests creating a temporary SQLite database for each test.\nThis is perfectly fine for simple applications, but adds substantial overhead (and test time) to applications with many tests, especially for those where the database contains some preloaded information.\nInstead, it would be preferable to create and use one temporary database instance for the majority of tests that only require read-access to the database, and then only create additional test databases for the tests that modify the state of the database (e.g., SQLAlchemy transactions).[^mocking]\n\n_DRY Foundation_ provides the infrastructure to create databases in both of these cases: a \"persistent\" database for read-only tests, and \"ephemeral\" databases for each transaction).\nThe persistent test database is used by default, but a `transaction_lifetime` decorator can be used to indicate that a given test should use an ephemeral copy.\n\n[^mocking]: Yes, you could also just not create databases and mock the database return functions, but my experience has been that it is even more tedious to maintain a comprehensive set of mocked data to test various intricacies and edge cases while simultaneously ensuring that the mocks behave similarly enough to SQLAlchemy objects.\n\n\n### Authorization and Data Handlers\n\nThe common operations are easy to do using SQLAlchemy, but rather than rolling new functions for each new query in every application, this tool provides a set of handlers that are designed to abstract away a bunch of the tedious details.\nAlso, my experience is that enforcing authorization constraints when manipulating sophisticated table relationships can be tricky, and so this tool and its handlers provide an interface for managing those authorizations consistently.\n\nIt's possible I'm missing a key functionality of SQLAlchemy that enables this behavior elegantly, but I haven't found a satisfiably clean way to do it yet.\nUntil I become so enlightened, this package creates an interface where each model may define the chain of joins required to establish whether it belongs to an authorized user, and then a handler to query the database and perform those joins for each query.\nThis is designed to be extensible, since I often want this behavior available for the majority of ORM models in my application.\n\nIf you happen to read this and think \"This dude's dumb; why on Earth didn't he use _this_ functionality baked into SQLAlchemy?\" drop me a line because I'm interested to know what I'm missing.\n\n\n## Installation\n\n_DRY Foundation_ is registered on the [Python Package Index (PyPI)](https://pypi.org/project/...) for easy installation.\nTo install the package, simply run\n\n```\npip install dry-foundation\n```\n\nThe package requires a recent version of Python (3.10+).\n\n\n## Usage\n\nThe app has lots of tools, but the basics can be used just as drop-in replacements for the standard `Flask` object and application factory.\n\n```python\n# DRY Application: `dry_application/__init__.py`\n\nfrom dry_foundation import DryFlask, Factory\n\n@Factory\ndef create_app(config=None):\n app = DryFlask(__name__, app_name=\"DRY Application\")\n app.configure(config)\n # Anything else performed by the application factory...\n return app\n```\n\nFor a more complete, up-to-date API reference, build and read the docs:\n\n```bash\nmake docs\n# open `docs/build/html/index.html` in your browser\n```\n\n\n## License\n\nThis project is licensed under the GNU General Public License, Version 3.\nIt is fully open-source, and while you are more than welcome to fork, add, modify, etc. it is required that you keep any distributed changes and additions open-source.\n\n\n## Changes\n\nChanges between versions are tracked in the [changelog](https://github.com/mitchnegus/dry-foundation/blob/main/./CHANGELOG.md).\n",
"bugtrack_url": null,
"license": "GNU GPLv3",
"summary": "Tools and components for building customized and consistent small-scale Flask applications.",
"version": "1.3.0",
"project_urls": {
"Changelog": "https://github.com/mitchnegus/DRY-Foundation/blob/main/docs/source/CHANGELOG.md",
"Download": "https://pypi.org/project/dry-foundation/",
"Homepage": "https://github.com/mitchnegus/DRY-Foundation",
"Repository": "https://github.com/mitchnegus/DRY-Foundation"
},
"split_keywords": [],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "6d749e702efdbf260161ab497292f1c782be11c0e15635a715761cc36e48c488",
"md5": "99fe626d3995f07d238582e1d4dc0c8f",
"sha256": "1dd19105b14075236b34b0cd7394f60502bf8ff887488ab299102bdfbfba537a"
},
"downloads": -1,
"filename": "dry_foundation-1.3.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "99fe626d3995f07d238582e1d4dc0c8f",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 44433,
"upload_time": "2025-09-13T17:31:52",
"upload_time_iso_8601": "2025-09-13T17:31:52.000723Z",
"url": "https://files.pythonhosted.org/packages/6d/74/9e702efdbf260161ab497292f1c782be11c0e15635a715761cc36e48c488/dry_foundation-1.3.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "e8b8e613e9651d71e7eab740bed3044170df68ab630ab5b037e041ee312f59e2",
"md5": "5bf1e921955ac5a421f8c4e1b019204a",
"sha256": "081159da2568f8744559ea99a340523effb1c50536ce875cbf6e088328153d1e"
},
"downloads": -1,
"filename": "dry_foundation-1.3.0.tar.gz",
"has_sig": false,
"md5_digest": "5bf1e921955ac5a421f8c4e1b019204a",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 68308,
"upload_time": "2025-09-13T17:31:50",
"upload_time_iso_8601": "2025-09-13T17:31:50.843815Z",
"url": "https://files.pythonhosted.org/packages/e8/b8/e613e9651d71e7eab740bed3044170df68ab630ab5b037e041ee312f59e2/dry_foundation-1.3.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-09-13 17:31:50",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "mitchnegus",
"github_project": "DRY-Foundation",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "nox",
"specs": [
[
">=",
"2025"
]
]
}
],
"lcname": "dry-foundation"
}