GeneralManager 0.15.1__tar.gz → 0.16.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of GeneralManager might be problematic. Click here for more details.
- {generalmanager-0.15.1/src/GeneralManager.egg-info → generalmanager-0.16.0}/PKG-INFO +42 -82
- generalmanager-0.16.0/README.md +108 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/pyproject.toml +1 -1
- {generalmanager-0.15.1 → generalmanager-0.16.0/src/GeneralManager.egg-info}/PKG-INFO +42 -82
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/GeneralManager.egg-info/SOURCES.txt +13 -0
- generalmanager-0.16.0/src/general_manager/__init__.py +27 -0
- generalmanager-0.16.0/src/general_manager/_types/__init__.py +3 -0
- generalmanager-0.16.0/src/general_manager/_types/api.py +18 -0
- generalmanager-0.16.0/src/general_manager/_types/bucket.py +16 -0
- generalmanager-0.16.0/src/general_manager/_types/cache.py +20 -0
- generalmanager-0.16.0/src/general_manager/_types/factory.py +44 -0
- generalmanager-0.16.0/src/general_manager/_types/general_manager.py +28 -0
- generalmanager-0.16.0/src/general_manager/_types/interface.py +18 -0
- generalmanager-0.16.0/src/general_manager/_types/manager.py +18 -0
- generalmanager-0.16.0/src/general_manager/_types/measurement.py +16 -0
- generalmanager-0.16.0/src/general_manager/_types/permission.py +14 -0
- generalmanager-0.16.0/src/general_manager/_types/rule.py +12 -0
- generalmanager-0.16.0/src/general_manager/_types/utils.py +30 -0
- generalmanager-0.16.0/src/general_manager/api/__init__.py +28 -0
- generalmanager-0.16.0/src/general_manager/bucket/__init__.py +28 -0
- generalmanager-0.16.0/src/general_manager/cache/__init__.py +28 -0
- generalmanager-0.16.0/src/general_manager/factory/__init__.py +28 -0
- generalmanager-0.16.0/src/general_manager/interface/__init__.py +28 -0
- generalmanager-0.16.0/src/general_manager/manager/__init__.py +28 -0
- generalmanager-0.16.0/src/general_manager/measurement/__init__.py +28 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/permission/__init__.py +8 -12
- generalmanager-0.16.0/src/general_manager/public_api_registry.py +160 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/rule/__init__.py +7 -6
- generalmanager-0.16.0/src/general_manager/utils/__init__.py +28 -0
- generalmanager-0.15.1/README.md +0 -148
- generalmanager-0.15.1/src/general_manager/__init__.py +0 -49
- generalmanager-0.15.1/src/general_manager/api/__init__.py +0 -36
- generalmanager-0.15.1/src/general_manager/bucket/__init__.py +0 -32
- generalmanager-0.15.1/src/general_manager/cache/__init__.py +0 -38
- generalmanager-0.15.1/src/general_manager/factory/__init__.py +0 -34
- generalmanager-0.15.1/src/general_manager/interface/__init__.py +0 -36
- generalmanager-0.15.1/src/general_manager/manager/__init__.py +0 -36
- generalmanager-0.15.1/src/general_manager/measurement/__init__.py +0 -37
- generalmanager-0.15.1/src/general_manager/utils/__init__.py +0 -44
- {generalmanager-0.15.1 → generalmanager-0.16.0}/LICENSE +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/setup.cfg +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/GeneralManager.egg-info/dependency_links.txt +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/GeneralManager.egg-info/requires.txt +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/GeneralManager.egg-info/top_level.txt +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/api/graphql.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/api/mutation.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/api/property.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/apps.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/bucket/baseBucket.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/bucket/calculationBucket.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/bucket/databaseBucket.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/bucket/groupBucket.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/cache/cacheDecorator.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/cache/cacheTracker.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/cache/dependencyIndex.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/cache/modelDependencyCollector.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/cache/signals.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/factory/autoFactory.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/factory/factories.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/factory/factoryMethods.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/interface/baseInterface.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/interface/calculationInterface.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/interface/databaseBasedInterface.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/interface/databaseInterface.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/interface/models.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/interface/readOnlyInterface.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/manager/generalManager.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/manager/groupManager.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/manager/input.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/manager/meta.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/measurement/measurement.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/measurement/measurementField.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/permission/basePermission.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/permission/fileBasedPermission.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/permission/managerBasedPermission.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/permission/mutationPermission.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/permission/permissionChecks.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/permission/permissionDataManager.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/permission/utils.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/rule/handler.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/rule/rule.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/utils/argsToKwargs.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/utils/filterParser.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/utils/formatString.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/utils/jsonEncoder.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/utils/makeCacheKey.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/utils/noneToZero.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/utils/pathMapping.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/utils/public_api.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/src/general_manager/utils/testing.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/tests/test_settings.py +0 -0
- {generalmanager-0.15.1 → generalmanager-0.16.0}/tests/test_urls.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GeneralManager
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.16.0
|
|
4
4
|
Summary: Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching.
|
|
5
5
|
Author-email: Tim Kleindick <tkleindick@yahoo.de>
|
|
6
6
|
License: MIT License
|
|
@@ -73,129 +73,89 @@ Dynamic: license-file
|
|
|
73
73
|
|
|
74
74
|
## Overview
|
|
75
75
|
|
|
76
|
-
GeneralManager
|
|
76
|
+
GeneralManager helps teams ship complex, data-driven products on top of Django without rewriting the same plumbing for every project. It combines domain modelling, GraphQL APIs, calculations, and permission logic in one toolkit so that you can focus on business rules instead of infrastructure.
|
|
77
77
|
|
|
78
|
-
##
|
|
79
|
-
|
|
80
|
-
### 1. **Data Management**
|
|
81
|
-
- **Flexibility**: Supports managing all kinds of data, not just projects and derivatives.
|
|
82
|
-
- **Database Integration**: Seamless integration with the Django ORM for database operations.
|
|
83
|
-
- **External Interfaces**: Support for interfaces to other programs, such as Excel.
|
|
84
|
-
|
|
85
|
-
### 2. **Data Modeling**
|
|
86
|
-
- **Django Models**: The data structure is based on Django models, extended by custom fields like `MeasurementField`.
|
|
87
|
-
- **Rules and Validations**: Define rules for data validation, e.g., ensuring that a project's start date is before its end date.
|
|
78
|
+
## Documentation
|
|
88
79
|
|
|
89
|
-
|
|
90
|
-
- Automatic generation of GraphQL interfaces for all models.
|
|
91
|
-
- Support for custom queries and mutations.
|
|
80
|
+
The full documentation is published on GitHub Pages: [GeneralManager Documentation](https://timkleindick.github.io/general_manager/). It covers tutorials, concept guides, API reference, and examples.
|
|
92
81
|
|
|
93
|
-
|
|
94
|
-
- **ManagerBasedPermission**: A flexible permission system based on user roles and attributes.
|
|
95
|
-
- Attribute-level CRUD permissions.
|
|
96
|
-
|
|
97
|
-
### 5. **Interfaces**
|
|
98
|
-
- **CalculationInterface**: Allows the implementation of calculation logic.
|
|
99
|
-
- **DatabaseInterface**: Provides a standardized interface for database operations.
|
|
100
|
-
- **ReadOnlyInterface**: For read-only data access.
|
|
82
|
+
## Key Features
|
|
101
83
|
|
|
102
|
-
|
|
103
|
-
- **
|
|
104
|
-
- **
|
|
84
|
+
- **Domain-first modelling**: Describe rich business entities in plain Python and let GeneralManager project them onto the Django ORM.
|
|
85
|
+
- **GraphQL without boilerplate**: Generate a complete API, then extend it with custom queries and mutations when needed.
|
|
86
|
+
- **Attribute-based access control**: Enforce permissions with `ManagerBasedPermission` down to single fields and operations.
|
|
87
|
+
- **Deterministic calculations**: Ship reusable interfaces e.g. for volume distributions, KPI calculations, and derived data.
|
|
88
|
+
- **Factory-powered testing**: Create large, realistic datasets quickly for demos, QA, and load tests.
|
|
89
|
+
- **Composable interfaces**: Connect to databases, spreadsheets, or computed sources with the same consistent abstractions.
|
|
105
90
|
|
|
106
|
-
##
|
|
91
|
+
## Quick Start
|
|
107
92
|
|
|
108
93
|
### Installation
|
|
109
94
|
|
|
110
|
-
Install the
|
|
95
|
+
Install the package from PyPI:
|
|
111
96
|
|
|
112
97
|
```bash
|
|
113
98
|
pip install GeneralManager
|
|
114
99
|
```
|
|
115
100
|
|
|
116
|
-
###
|
|
117
|
-
|
|
118
|
-
The following example demonstrates how to create a GeneralManager and generate sample data (in this case 10 projects):
|
|
101
|
+
### Minimal example
|
|
119
102
|
|
|
120
103
|
```python
|
|
104
|
+
from datetime import date
|
|
105
|
+
from typing import Optional
|
|
106
|
+
|
|
107
|
+
from django.db.models import CharField, DateField
|
|
108
|
+
|
|
121
109
|
from general_manager import GeneralManager
|
|
122
110
|
from general_manager.interface.database import DatabaseInterface
|
|
123
|
-
from general_manager.measurement import
|
|
111
|
+
from general_manager.measurement import Measurement, MeasurementField
|
|
124
112
|
from general_manager.permission import ManagerBasedPermission
|
|
125
113
|
|
|
114
|
+
|
|
126
115
|
class Project(GeneralManager):
|
|
127
116
|
name: str
|
|
128
117
|
start_date: Optional[date]
|
|
129
118
|
end_date: Optional[date]
|
|
130
119
|
total_capex: Optional[Measurement]
|
|
131
|
-
derivative_list: DatabaseBucket[Derivative]
|
|
132
120
|
|
|
133
121
|
class Interface(DatabaseInterface):
|
|
134
122
|
name = CharField(max_length=50)
|
|
135
|
-
number = CharField(max_length=7, validators=[RegexValidator(r"^AP\d{4,5}$")])
|
|
136
|
-
description = TextField(null=True, blank=True)
|
|
137
123
|
start_date = DateField(null=True, blank=True)
|
|
138
124
|
end_date = DateField(null=True, blank=True)
|
|
139
125
|
total_capex = MeasurementField(base_unit="EUR", null=True, blank=True)
|
|
140
126
|
|
|
141
|
-
class Meta:
|
|
142
|
-
constraints = [
|
|
143
|
-
constraints.UniqueConstraint(
|
|
144
|
-
fields=["name", "number"], name="unique_booking"
|
|
145
|
-
)
|
|
146
|
-
]
|
|
147
|
-
|
|
148
|
-
rules = [
|
|
149
|
-
Rule["Project"](
|
|
150
|
-
lambda x: cast(date, x.start_date) < cast(date, x.end_date)
|
|
151
|
-
),
|
|
152
|
-
Rule["Project"](lambda x: cast(Measurement, x.total_capex) >= "0 EUR"),
|
|
153
|
-
]
|
|
154
|
-
|
|
155
|
-
class Factory:
|
|
156
|
-
name = LazyProjectName()
|
|
157
|
-
end_date = LazyDeltaDate(365 * 6, "start_date")
|
|
158
|
-
total_capex = LazyMeasurement(75_000, 1_000_000, "EUR")
|
|
159
|
-
|
|
160
127
|
class Permission(ManagerBasedPermission):
|
|
161
|
-
__read__ = ["
|
|
162
|
-
__create__ = ["
|
|
163
|
-
__update__ = ["
|
|
164
|
-
__delete__ = ["admin", "isMatchingKeyAccount", "isProjectTeamMember"]
|
|
128
|
+
__read__ = ["public"]
|
|
129
|
+
__create__ = ["isAdmin"]
|
|
130
|
+
__update__ = ["isAdmin"]
|
|
165
131
|
|
|
166
|
-
total_capex = {"update": ["isSalesResponsible", "isProjectManager"]}
|
|
167
132
|
|
|
168
133
|
Project.Factory.createBatch(10)
|
|
169
134
|
```
|
|
170
135
|
|
|
171
|
-
|
|
136
|
+
The example above defines a project model, exposes it through the auto-generated GraphQL schema, and produces ten sample records with a single call. The full documentation walks through extending this setup with custom rules, interfaces, and queries.
|
|
172
137
|
|
|
173
|
-
|
|
138
|
+
## Core Building Blocks
|
|
174
139
|
|
|
175
|
-
|
|
140
|
+
- **Entities & interfaces**: Compose domain entities with database-backed or computed interfaces to control persistence and data flows.
|
|
141
|
+
- **Rules & validation**: Protect your data with declarative constraints and business rules that run automatically.
|
|
142
|
+
- **Permissions**: Implement attribute-based access control with reusable policies that match your organisation’s roles.
|
|
143
|
+
- **GraphQL layer**: Serve a typed schema that mirrors your models and stays in sync as you iterate.
|
|
144
|
+
- **Caching & calculations**: Use the built-in caching decorator and calculation helpers to keep derived data fast and reliable.
|
|
176
145
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
totalCapex {
|
|
184
|
-
value
|
|
185
|
-
unit
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
```
|
|
146
|
+
## Production-Ready Extras
|
|
147
|
+
|
|
148
|
+
- Works with Postgres, SQLite, and any database supported by Django.
|
|
149
|
+
- Plays nicely with CI thanks to deterministic factories, typing, and code coverage.
|
|
150
|
+
- Ships with MkDocs documentation, auto-generated API reference, and a growing cookbook of recipes.
|
|
151
|
+
- Designed for teams: opinionated defaults without blocking custom extensions or overrides.
|
|
190
152
|
|
|
191
|
-
##
|
|
153
|
+
## Use Cases
|
|
192
154
|
|
|
193
|
-
-
|
|
194
|
-
-
|
|
195
|
-
-
|
|
196
|
-
-
|
|
197
|
-
- **Data Validation**: Automatic validation of data through rules and constraints.
|
|
198
|
-
- **Caching**: Automatic cache generation with the `@cached` decorator to improve performance.
|
|
155
|
+
- Internal tooling that mirrors real-world workflows, pricing models, or asset hierarchies.
|
|
156
|
+
- Customer-facing platforms that combine transactional data with live calculations.
|
|
157
|
+
- Analytics products that need controlled data sharing between teams or clients.
|
|
158
|
+
- Proof-of-concept projects that must scale into production without a rewrite.
|
|
199
159
|
|
|
200
160
|
## Requirements
|
|
201
161
|
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# GeneralManager
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/GeneralManager/)
|
|
4
|
+
[](https://pypi.org/project/GeneralManager/)
|
|
5
|
+
[](https://github.com/TimKleindick/general_manager/actions/workflows/test.yml)
|
|
6
|
+
[](https://app.codecov.io/gh/TimKleindick/general_manager)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
GeneralManager helps teams ship complex, data-driven products on top of Django without rewriting the same plumbing for every project. It combines domain modelling, GraphQL APIs, calculations, and permission logic in one toolkit so that you can focus on business rules instead of infrastructure.
|
|
12
|
+
|
|
13
|
+
## Documentation
|
|
14
|
+
|
|
15
|
+
The full documentation is published on GitHub Pages: [GeneralManager Documentation](https://timkleindick.github.io/general_manager/). It covers tutorials, concept guides, API reference, and examples.
|
|
16
|
+
|
|
17
|
+
## Key Features
|
|
18
|
+
|
|
19
|
+
- **Domain-first modelling**: Describe rich business entities in plain Python and let GeneralManager project them onto the Django ORM.
|
|
20
|
+
- **GraphQL without boilerplate**: Generate a complete API, then extend it with custom queries and mutations when needed.
|
|
21
|
+
- **Attribute-based access control**: Enforce permissions with `ManagerBasedPermission` down to single fields and operations.
|
|
22
|
+
- **Deterministic calculations**: Ship reusable interfaces e.g. for volume distributions, KPI calculations, and derived data.
|
|
23
|
+
- **Factory-powered testing**: Create large, realistic datasets quickly for demos, QA, and load tests.
|
|
24
|
+
- **Composable interfaces**: Connect to databases, spreadsheets, or computed sources with the same consistent abstractions.
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
### Installation
|
|
29
|
+
|
|
30
|
+
Install the package from PyPI:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install GeneralManager
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Minimal example
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from datetime import date
|
|
40
|
+
from typing import Optional
|
|
41
|
+
|
|
42
|
+
from django.db.models import CharField, DateField
|
|
43
|
+
|
|
44
|
+
from general_manager import GeneralManager
|
|
45
|
+
from general_manager.interface.database import DatabaseInterface
|
|
46
|
+
from general_manager.measurement import Measurement, MeasurementField
|
|
47
|
+
from general_manager.permission import ManagerBasedPermission
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class Project(GeneralManager):
|
|
51
|
+
name: str
|
|
52
|
+
start_date: Optional[date]
|
|
53
|
+
end_date: Optional[date]
|
|
54
|
+
total_capex: Optional[Measurement]
|
|
55
|
+
|
|
56
|
+
class Interface(DatabaseInterface):
|
|
57
|
+
name = CharField(max_length=50)
|
|
58
|
+
start_date = DateField(null=True, blank=True)
|
|
59
|
+
end_date = DateField(null=True, blank=True)
|
|
60
|
+
total_capex = MeasurementField(base_unit="EUR", null=True, blank=True)
|
|
61
|
+
|
|
62
|
+
class Permission(ManagerBasedPermission):
|
|
63
|
+
__read__ = ["public"]
|
|
64
|
+
__create__ = ["isAdmin"]
|
|
65
|
+
__update__ = ["isAdmin"]
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
Project.Factory.createBatch(10)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The example above defines a project model, exposes it through the auto-generated GraphQL schema, and produces ten sample records with a single call. The full documentation walks through extending this setup with custom rules, interfaces, and queries.
|
|
72
|
+
|
|
73
|
+
## Core Building Blocks
|
|
74
|
+
|
|
75
|
+
- **Entities & interfaces**: Compose domain entities with database-backed or computed interfaces to control persistence and data flows.
|
|
76
|
+
- **Rules & validation**: Protect your data with declarative constraints and business rules that run automatically.
|
|
77
|
+
- **Permissions**: Implement attribute-based access control with reusable policies that match your organisation’s roles.
|
|
78
|
+
- **GraphQL layer**: Serve a typed schema that mirrors your models and stays in sync as you iterate.
|
|
79
|
+
- **Caching & calculations**: Use the built-in caching decorator and calculation helpers to keep derived data fast and reliable.
|
|
80
|
+
|
|
81
|
+
## Production-Ready Extras
|
|
82
|
+
|
|
83
|
+
- Works with Postgres, SQLite, and any database supported by Django.
|
|
84
|
+
- Plays nicely with CI thanks to deterministic factories, typing, and code coverage.
|
|
85
|
+
- Ships with MkDocs documentation, auto-generated API reference, and a growing cookbook of recipes.
|
|
86
|
+
- Designed for teams: opinionated defaults without blocking custom extensions or overrides.
|
|
87
|
+
|
|
88
|
+
## Use Cases
|
|
89
|
+
|
|
90
|
+
- Internal tooling that mirrors real-world workflows, pricing models, or asset hierarchies.
|
|
91
|
+
- Customer-facing platforms that combine transactional data with live calculations.
|
|
92
|
+
- Analytics products that need controlled data sharing between teams or clients.
|
|
93
|
+
- Proof-of-concept projects that must scale into production without a rewrite.
|
|
94
|
+
|
|
95
|
+
## Requirements
|
|
96
|
+
|
|
97
|
+
- Python >= 3.12
|
|
98
|
+
- Django >= 5.2
|
|
99
|
+
- Additional dependencies (see `requirements.txt`):
|
|
100
|
+
- `graphene`
|
|
101
|
+
- `numpy`
|
|
102
|
+
- `Pint`
|
|
103
|
+
- `factory_boy`
|
|
104
|
+
- and more.
|
|
105
|
+
|
|
106
|
+
## License
|
|
107
|
+
|
|
108
|
+
This project is distributed under the **MIT License**. For further details see the [LICENSE](./LICENSE) file.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "GeneralManager"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.16.0"
|
|
8
8
|
description = "Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "Tim Kleindick", email = "tkleindick@yahoo.de" }]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GeneralManager
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.16.0
|
|
4
4
|
Summary: Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching.
|
|
5
5
|
Author-email: Tim Kleindick <tkleindick@yahoo.de>
|
|
6
6
|
License: MIT License
|
|
@@ -73,129 +73,89 @@ Dynamic: license-file
|
|
|
73
73
|
|
|
74
74
|
## Overview
|
|
75
75
|
|
|
76
|
-
GeneralManager
|
|
76
|
+
GeneralManager helps teams ship complex, data-driven products on top of Django without rewriting the same plumbing for every project. It combines domain modelling, GraphQL APIs, calculations, and permission logic in one toolkit so that you can focus on business rules instead of infrastructure.
|
|
77
77
|
|
|
78
|
-
##
|
|
79
|
-
|
|
80
|
-
### 1. **Data Management**
|
|
81
|
-
- **Flexibility**: Supports managing all kinds of data, not just projects and derivatives.
|
|
82
|
-
- **Database Integration**: Seamless integration with the Django ORM for database operations.
|
|
83
|
-
- **External Interfaces**: Support for interfaces to other programs, such as Excel.
|
|
84
|
-
|
|
85
|
-
### 2. **Data Modeling**
|
|
86
|
-
- **Django Models**: The data structure is based on Django models, extended by custom fields like `MeasurementField`.
|
|
87
|
-
- **Rules and Validations**: Define rules for data validation, e.g., ensuring that a project's start date is before its end date.
|
|
78
|
+
## Documentation
|
|
88
79
|
|
|
89
|
-
|
|
90
|
-
- Automatic generation of GraphQL interfaces for all models.
|
|
91
|
-
- Support for custom queries and mutations.
|
|
80
|
+
The full documentation is published on GitHub Pages: [GeneralManager Documentation](https://timkleindick.github.io/general_manager/). It covers tutorials, concept guides, API reference, and examples.
|
|
92
81
|
|
|
93
|
-
|
|
94
|
-
- **ManagerBasedPermission**: A flexible permission system based on user roles and attributes.
|
|
95
|
-
- Attribute-level CRUD permissions.
|
|
96
|
-
|
|
97
|
-
### 5. **Interfaces**
|
|
98
|
-
- **CalculationInterface**: Allows the implementation of calculation logic.
|
|
99
|
-
- **DatabaseInterface**: Provides a standardized interface for database operations.
|
|
100
|
-
- **ReadOnlyInterface**: For read-only data access.
|
|
82
|
+
## Key Features
|
|
101
83
|
|
|
102
|
-
|
|
103
|
-
- **
|
|
104
|
-
- **
|
|
84
|
+
- **Domain-first modelling**: Describe rich business entities in plain Python and let GeneralManager project them onto the Django ORM.
|
|
85
|
+
- **GraphQL without boilerplate**: Generate a complete API, then extend it with custom queries and mutations when needed.
|
|
86
|
+
- **Attribute-based access control**: Enforce permissions with `ManagerBasedPermission` down to single fields and operations.
|
|
87
|
+
- **Deterministic calculations**: Ship reusable interfaces e.g. for volume distributions, KPI calculations, and derived data.
|
|
88
|
+
- **Factory-powered testing**: Create large, realistic datasets quickly for demos, QA, and load tests.
|
|
89
|
+
- **Composable interfaces**: Connect to databases, spreadsheets, or computed sources with the same consistent abstractions.
|
|
105
90
|
|
|
106
|
-
##
|
|
91
|
+
## Quick Start
|
|
107
92
|
|
|
108
93
|
### Installation
|
|
109
94
|
|
|
110
|
-
Install the
|
|
95
|
+
Install the package from PyPI:
|
|
111
96
|
|
|
112
97
|
```bash
|
|
113
98
|
pip install GeneralManager
|
|
114
99
|
```
|
|
115
100
|
|
|
116
|
-
###
|
|
117
|
-
|
|
118
|
-
The following example demonstrates how to create a GeneralManager and generate sample data (in this case 10 projects):
|
|
101
|
+
### Minimal example
|
|
119
102
|
|
|
120
103
|
```python
|
|
104
|
+
from datetime import date
|
|
105
|
+
from typing import Optional
|
|
106
|
+
|
|
107
|
+
from django.db.models import CharField, DateField
|
|
108
|
+
|
|
121
109
|
from general_manager import GeneralManager
|
|
122
110
|
from general_manager.interface.database import DatabaseInterface
|
|
123
|
-
from general_manager.measurement import
|
|
111
|
+
from general_manager.measurement import Measurement, MeasurementField
|
|
124
112
|
from general_manager.permission import ManagerBasedPermission
|
|
125
113
|
|
|
114
|
+
|
|
126
115
|
class Project(GeneralManager):
|
|
127
116
|
name: str
|
|
128
117
|
start_date: Optional[date]
|
|
129
118
|
end_date: Optional[date]
|
|
130
119
|
total_capex: Optional[Measurement]
|
|
131
|
-
derivative_list: DatabaseBucket[Derivative]
|
|
132
120
|
|
|
133
121
|
class Interface(DatabaseInterface):
|
|
134
122
|
name = CharField(max_length=50)
|
|
135
|
-
number = CharField(max_length=7, validators=[RegexValidator(r"^AP\d{4,5}$")])
|
|
136
|
-
description = TextField(null=True, blank=True)
|
|
137
123
|
start_date = DateField(null=True, blank=True)
|
|
138
124
|
end_date = DateField(null=True, blank=True)
|
|
139
125
|
total_capex = MeasurementField(base_unit="EUR", null=True, blank=True)
|
|
140
126
|
|
|
141
|
-
class Meta:
|
|
142
|
-
constraints = [
|
|
143
|
-
constraints.UniqueConstraint(
|
|
144
|
-
fields=["name", "number"], name="unique_booking"
|
|
145
|
-
)
|
|
146
|
-
]
|
|
147
|
-
|
|
148
|
-
rules = [
|
|
149
|
-
Rule["Project"](
|
|
150
|
-
lambda x: cast(date, x.start_date) < cast(date, x.end_date)
|
|
151
|
-
),
|
|
152
|
-
Rule["Project"](lambda x: cast(Measurement, x.total_capex) >= "0 EUR"),
|
|
153
|
-
]
|
|
154
|
-
|
|
155
|
-
class Factory:
|
|
156
|
-
name = LazyProjectName()
|
|
157
|
-
end_date = LazyDeltaDate(365 * 6, "start_date")
|
|
158
|
-
total_capex = LazyMeasurement(75_000, 1_000_000, "EUR")
|
|
159
|
-
|
|
160
127
|
class Permission(ManagerBasedPermission):
|
|
161
|
-
__read__ = ["
|
|
162
|
-
__create__ = ["
|
|
163
|
-
__update__ = ["
|
|
164
|
-
__delete__ = ["admin", "isMatchingKeyAccount", "isProjectTeamMember"]
|
|
128
|
+
__read__ = ["public"]
|
|
129
|
+
__create__ = ["isAdmin"]
|
|
130
|
+
__update__ = ["isAdmin"]
|
|
165
131
|
|
|
166
|
-
total_capex = {"update": ["isSalesResponsible", "isProjectManager"]}
|
|
167
132
|
|
|
168
133
|
Project.Factory.createBatch(10)
|
|
169
134
|
```
|
|
170
135
|
|
|
171
|
-
|
|
136
|
+
The example above defines a project model, exposes it through the auto-generated GraphQL schema, and produces ten sample records with a single call. The full documentation walks through extending this setup with custom rules, interfaces, and queries.
|
|
172
137
|
|
|
173
|
-
|
|
138
|
+
## Core Building Blocks
|
|
174
139
|
|
|
175
|
-
|
|
140
|
+
- **Entities & interfaces**: Compose domain entities with database-backed or computed interfaces to control persistence and data flows.
|
|
141
|
+
- **Rules & validation**: Protect your data with declarative constraints and business rules that run automatically.
|
|
142
|
+
- **Permissions**: Implement attribute-based access control with reusable policies that match your organisation’s roles.
|
|
143
|
+
- **GraphQL layer**: Serve a typed schema that mirrors your models and stays in sync as you iterate.
|
|
144
|
+
- **Caching & calculations**: Use the built-in caching decorator and calculation helpers to keep derived data fast and reliable.
|
|
176
145
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
totalCapex {
|
|
184
|
-
value
|
|
185
|
-
unit
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
```
|
|
146
|
+
## Production-Ready Extras
|
|
147
|
+
|
|
148
|
+
- Works with Postgres, SQLite, and any database supported by Django.
|
|
149
|
+
- Plays nicely with CI thanks to deterministic factories, typing, and code coverage.
|
|
150
|
+
- Ships with MkDocs documentation, auto-generated API reference, and a growing cookbook of recipes.
|
|
151
|
+
- Designed for teams: opinionated defaults without blocking custom extensions or overrides.
|
|
190
152
|
|
|
191
|
-
##
|
|
153
|
+
## Use Cases
|
|
192
154
|
|
|
193
|
-
-
|
|
194
|
-
-
|
|
195
|
-
-
|
|
196
|
-
-
|
|
197
|
-
- **Data Validation**: Automatic validation of data through rules and constraints.
|
|
198
|
-
- **Caching**: Automatic cache generation with the `@cached` decorator to improve performance.
|
|
155
|
+
- Internal tooling that mirrors real-world workflows, pricing models, or asset hierarchies.
|
|
156
|
+
- Customer-facing platforms that combine transactional data with live calculations.
|
|
157
|
+
- Analytics products that need controlled data sharing between teams or clients.
|
|
158
|
+
- Proof-of-concept projects that must scale into production without a rewrite.
|
|
199
159
|
|
|
200
160
|
## Requirements
|
|
201
161
|
|
|
@@ -8,6 +8,19 @@ src/GeneralManager.egg-info/requires.txt
|
|
|
8
8
|
src/GeneralManager.egg-info/top_level.txt
|
|
9
9
|
src/general_manager/__init__.py
|
|
10
10
|
src/general_manager/apps.py
|
|
11
|
+
src/general_manager/public_api_registry.py
|
|
12
|
+
src/general_manager/_types/__init__.py
|
|
13
|
+
src/general_manager/_types/api.py
|
|
14
|
+
src/general_manager/_types/bucket.py
|
|
15
|
+
src/general_manager/_types/cache.py
|
|
16
|
+
src/general_manager/_types/factory.py
|
|
17
|
+
src/general_manager/_types/general_manager.py
|
|
18
|
+
src/general_manager/_types/interface.py
|
|
19
|
+
src/general_manager/_types/manager.py
|
|
20
|
+
src/general_manager/_types/measurement.py
|
|
21
|
+
src/general_manager/_types/permission.py
|
|
22
|
+
src/general_manager/_types/rule.py
|
|
23
|
+
src/general_manager/_types/utils.py
|
|
11
24
|
src/general_manager/api/__init__.py
|
|
12
25
|
src/general_manager/api/graphql.py
|
|
13
26
|
src/general_manager/api/mutation.py
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Convenience access to GeneralManager core components."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any
|
|
6
|
+
|
|
7
|
+
from general_manager.public_api_registry import GENERAL_MANAGER_EXPORTS
|
|
8
|
+
from general_manager.utils.public_api import build_module_dir, resolve_export
|
|
9
|
+
|
|
10
|
+
__all__ = list(GENERAL_MANAGER_EXPORTS)
|
|
11
|
+
|
|
12
|
+
_MODULE_MAP = GENERAL_MANAGER_EXPORTS
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from general_manager._types.general_manager import * # noqa: F401,F403
|
|
16
|
+
|
|
17
|
+
def __getattr__(name: str) -> Any:
|
|
18
|
+
return resolve_export(
|
|
19
|
+
name,
|
|
20
|
+
module_all=__all__,
|
|
21
|
+
module_map=_MODULE_MAP,
|
|
22
|
+
module_globals=globals(),
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def __dir__() -> list[str]:
|
|
27
|
+
return build_module_dir(module_all=__all__, module_globals=globals())
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""Type-only imports for public API re-exports."""
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"GraphQL",
|
|
7
|
+
"MeasurementScalar",
|
|
8
|
+
"MeasurementType",
|
|
9
|
+
"graphQlMutation",
|
|
10
|
+
"graphQlProperty",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
from general_manager.api.graphql import GraphQL
|
|
14
|
+
from general_manager.api.graphql import MeasurementScalar
|
|
15
|
+
from general_manager.api.graphql import MeasurementType
|
|
16
|
+
from general_manager.api.mutation import graphQlMutation
|
|
17
|
+
from general_manager.api.property import graphQlProperty
|
|
18
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""Type-only imports for public API re-exports."""
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"Bucket",
|
|
7
|
+
"CalculationBucket",
|
|
8
|
+
"DatabaseBucket",
|
|
9
|
+
"GroupBucket",
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
from general_manager.bucket.baseBucket import Bucket
|
|
13
|
+
from general_manager.bucket.calculationBucket import CalculationBucket
|
|
14
|
+
from general_manager.bucket.databaseBucket import DatabaseBucket
|
|
15
|
+
from general_manager.bucket.groupBucket import GroupBucket
|
|
16
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""Type-only imports for public API re-exports."""
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"CacheBackend",
|
|
7
|
+
"DependencyTracker",
|
|
8
|
+
"cached",
|
|
9
|
+
"invalidate_cache_key",
|
|
10
|
+
"record_dependencies",
|
|
11
|
+
"remove_cache_key_from_index",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
from general_manager.cache.cacheDecorator import CacheBackend
|
|
15
|
+
from general_manager.cache.cacheTracker import DependencyTracker
|
|
16
|
+
from general_manager.cache.cacheDecorator import cached
|
|
17
|
+
from general_manager.cache.dependencyIndex import invalidate_cache_key
|
|
18
|
+
from general_manager.cache.dependencyIndex import record_dependencies
|
|
19
|
+
from general_manager.cache.dependencyIndex import remove_cache_key_from_index
|
|
20
|
+
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""Type-only imports for public API re-exports."""
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"AutoFactory",
|
|
7
|
+
"LazyBoolean",
|
|
8
|
+
"LazyChoice",
|
|
9
|
+
"LazyDateBetween",
|
|
10
|
+
"LazyDateTimeBetween",
|
|
11
|
+
"LazyDateToday",
|
|
12
|
+
"LazyDecimal",
|
|
13
|
+
"LazyDeltaDate",
|
|
14
|
+
"LazyFakerAddress",
|
|
15
|
+
"LazyFakerEmail",
|
|
16
|
+
"LazyFakerName",
|
|
17
|
+
"LazyFakerSentence",
|
|
18
|
+
"LazyFakerUrl",
|
|
19
|
+
"LazyInteger",
|
|
20
|
+
"LazyMeasurement",
|
|
21
|
+
"LazyProjectName",
|
|
22
|
+
"LazySequence",
|
|
23
|
+
"LazyUUID",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
from general_manager.factory.autoFactory import AutoFactory
|
|
27
|
+
from general_manager.factory.factoryMethods import LazyBoolean
|
|
28
|
+
from general_manager.factory.factoryMethods import LazyChoice
|
|
29
|
+
from general_manager.factory.factoryMethods import LazyDateBetween
|
|
30
|
+
from general_manager.factory.factoryMethods import LazyDateTimeBetween
|
|
31
|
+
from general_manager.factory.factoryMethods import LazyDateToday
|
|
32
|
+
from general_manager.factory.factoryMethods import LazyDecimal
|
|
33
|
+
from general_manager.factory.factoryMethods import LazyDeltaDate
|
|
34
|
+
from general_manager.factory.factoryMethods import LazyFakerAddress
|
|
35
|
+
from general_manager.factory.factoryMethods import LazyFakerEmail
|
|
36
|
+
from general_manager.factory.factoryMethods import LazyFakerName
|
|
37
|
+
from general_manager.factory.factoryMethods import LazyFakerSentence
|
|
38
|
+
from general_manager.factory.factoryMethods import LazyFakerUrl
|
|
39
|
+
from general_manager.factory.factoryMethods import LazyInteger
|
|
40
|
+
from general_manager.factory.factoryMethods import LazyMeasurement
|
|
41
|
+
from general_manager.factory.factoryMethods import LazyProjectName
|
|
42
|
+
from general_manager.factory.factoryMethods import LazySequence
|
|
43
|
+
from general_manager.factory.factoryMethods import LazyUUID
|
|
44
|
+
|