cuz-toolkit 0.1.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.
- cuz_toolkit-0.1.0/.claude/settings.local.json +19 -0
- cuz_toolkit-0.1.0/.gitignore +42 -0
- cuz_toolkit-0.1.0/.pre-commit-config.yaml +22 -0
- cuz_toolkit-0.1.0/PKG-INFO +169 -0
- cuz_toolkit-0.1.0/README.md +139 -0
- cuz_toolkit-0.1.0/pyproject.toml +138 -0
- cuz_toolkit-0.1.0/src/toolkit/__init__.py +12 -0
- cuz_toolkit-0.1.0/src/toolkit/admin/__init__.py +42 -0
- cuz_toolkit-0.1.0/src/toolkit/admin/mixins.py +551 -0
- cuz_toolkit-0.1.0/src/toolkit/ecpay/__init__.py +61 -0
- cuz_toolkit-0.1.0/src/toolkit/ecpay/client.py +181 -0
- cuz_toolkit-0.1.0/src/toolkit/ecpay/constants.py +79 -0
- cuz_toolkit-0.1.0/src/toolkit/py.typed +0 -0
- cuz_toolkit-0.1.0/src/toolkit/pytest_plugin.py +132 -0
- cuz_toolkit-0.1.0/src/toolkit/testing/__init__.py +17 -0
- cuz_toolkit-0.1.0/src/toolkit/testing/db.py +72 -0
- cuz_toolkit-0.1.0/src/toolkit/tw_address/__init__.py +44 -0
- cuz_toolkit-0.1.0/src/toolkit/tw_address/apps.py +25 -0
- cuz_toolkit-0.1.0/src/toolkit/tw_address/static/toolkit/js/tw-city-admin.js +502 -0
- cuz_toolkit-0.1.0/src/toolkit/tw_address/static/toolkit/js/tw-city-selector.min.js +1 -0
- cuz_toolkit-0.1.0/src/toolkit/tw_banks/__init__.py +79 -0
- cuz_toolkit-0.1.0/src/toolkit/tw_banks/data.json +294 -0
- cuz_toolkit-0.1.0/src/toolkit/unfold/__init__.py +17 -0
- cuz_toolkit-0.1.0/src/toolkit/unfold/apps.py +49 -0
- cuz_toolkit-0.1.0/src/toolkit/unfold/conf.py +63 -0
- cuz_toolkit-0.1.0/src/toolkit/unfold/locale/zh_Hant/LC_MESSAGES/django.mo +0 -0
- cuz_toolkit-0.1.0/src/toolkit/unfold/locale/zh_Hant/LC_MESSAGES/django.po +90 -0
- cuz_toolkit-0.1.0/src/toolkit/unfold/locale_unfold/zh_Hant/LC_MESSAGES/django.mo +0 -0
- cuz_toolkit-0.1.0/src/toolkit/unfold/locale_unfold/zh_Hant/LC_MESSAGES/django.po +877 -0
- cuz_toolkit-0.1.0/src/toolkit/unfold/static/toolkit/unfold/css/trix.css +4 -0
- cuz_toolkit-0.1.0/src/toolkit/unfold/static/toolkit/unfold/js/trix-upload.js +78 -0
- cuz_toolkit-0.1.0/src/toolkit/unfold/templates/unfold/forms/helpers/toolbar.html +121 -0
- cuz_toolkit-0.1.0/src/toolkit/unfold/urls.py +12 -0
- cuz_toolkit-0.1.0/src/toolkit/unfold/views.py +40 -0
- cuz_toolkit-0.1.0/src/toolkit/unfold/widgets.py +15 -0
- cuz_toolkit-0.1.0/src/toolkit/utils/__init__.py +7 -0
- cuz_toolkit-0.1.0/src/toolkit/utils/upload.py +67 -0
- cuz_toolkit-0.1.0/tests/__init__.py +3 -0
- cuz_toolkit-0.1.0/tests/conftest.py +126 -0
- cuz_toolkit-0.1.0/tests/models.py +81 -0
- cuz_toolkit-0.1.0/tests/settings.py +48 -0
- cuz_toolkit-0.1.0/tests/test_ecpay.py +410 -0
- cuz_toolkit-0.1.0/tests/test_mixins.py +992 -0
- cuz_toolkit-0.1.0/tests/test_pytest_plugin.py +251 -0
- cuz_toolkit-0.1.0/tests/test_testing_db.py +18 -0
- cuz_toolkit-0.1.0/tests/test_tw_banks.py +65 -0
- cuz_toolkit-0.1.0/tests/test_unfold.py +408 -0
- cuz_toolkit-0.1.0/tests/test_utils_upload.py +98 -0
- cuz_toolkit-0.1.0/tests/urls.py +9 -0
- cuz_toolkit-0.1.0/uv.lock +614 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(uv run pip show:*)",
|
|
5
|
+
"Bash(find:*)",
|
|
6
|
+
"Bash(uv run pytest:*)",
|
|
7
|
+
"Skill(lint-all)",
|
|
8
|
+
"Bash(uv run mypy:*)",
|
|
9
|
+
"Bash(uv run ruff check:*)",
|
|
10
|
+
"Bash(uv run ruff:*)",
|
|
11
|
+
"Bash(uv run python:*)",
|
|
12
|
+
"Bash(git rev-parse:*)",
|
|
13
|
+
"Bash(ls:*)",
|
|
14
|
+
"Bash(uv run:*)",
|
|
15
|
+
"Bash(uv pip:*)",
|
|
16
|
+
"Bash(cd:*)"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Python-generated files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[oc]
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
wheels/
|
|
7
|
+
*.egg-info
|
|
8
|
+
|
|
9
|
+
# Virtual environments
|
|
10
|
+
.venv
|
|
11
|
+
|
|
12
|
+
# Environment files
|
|
13
|
+
.env
|
|
14
|
+
.env.*
|
|
15
|
+
!.env.example
|
|
16
|
+
|
|
17
|
+
# Django
|
|
18
|
+
*.log
|
|
19
|
+
db.sqlite3
|
|
20
|
+
db.sqlite3-journal
|
|
21
|
+
**/media/*
|
|
22
|
+
!**/media/.gitkeep
|
|
23
|
+
staticfiles/
|
|
24
|
+
|
|
25
|
+
# IDE
|
|
26
|
+
.vscode/
|
|
27
|
+
.idea/
|
|
28
|
+
|
|
29
|
+
# OS
|
|
30
|
+
.DS_Store
|
|
31
|
+
|
|
32
|
+
# Cache
|
|
33
|
+
.mypy_cache/
|
|
34
|
+
.pytest_cache/
|
|
35
|
+
.ruff_cache/
|
|
36
|
+
review-cache/
|
|
37
|
+
|
|
38
|
+
# Coverage
|
|
39
|
+
.coverage
|
|
40
|
+
.coverage.*
|
|
41
|
+
htmlcov/
|
|
42
|
+
coverage.xml
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
3
|
+
rev: v0.15.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: ruff
|
|
6
|
+
args: [--fix]
|
|
7
|
+
- id: ruff-format
|
|
8
|
+
|
|
9
|
+
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
10
|
+
rev: v1.19.1
|
|
11
|
+
hooks:
|
|
12
|
+
- id: mypy
|
|
13
|
+
entry: bash -c 'export MYPYPATH=src && mypy --config=pyproject.toml --install-types --non-interactive --show-traceback .'
|
|
14
|
+
pass_filenames: false
|
|
15
|
+
language: system
|
|
16
|
+
|
|
17
|
+
- repo: https://github.com/PyCQA/bandit
|
|
18
|
+
rev: "1.9.3"
|
|
19
|
+
hooks:
|
|
20
|
+
- id: bandit
|
|
21
|
+
args: ["-c", "pyproject.toml", "-r", "."]
|
|
22
|
+
additional_dependencies: ["bandit[toml]"]
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cuz-toolkit
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A collection of Django utilities: Admin mixins, testing helpers, and common patterns
|
|
5
|
+
Project-URL: Homepage, https://github.com/froggen/django-toolkit
|
|
6
|
+
Project-URL: Repository, https://github.com/froggen/django-toolkit
|
|
7
|
+
Author-email: Ivan <iven12345678900@gmail.com>
|
|
8
|
+
License: MIT
|
|
9
|
+
Keywords: admin,django,mixin,permission,testing,toolkit
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Web Environment
|
|
12
|
+
Classifier: Framework :: Django
|
|
13
|
+
Classifier: Framework :: Django :: 4.0
|
|
14
|
+
Classifier: Framework :: Django :: 4.1
|
|
15
|
+
Classifier: Framework :: Django :: 4.2
|
|
16
|
+
Classifier: Framework :: Django :: 5.0
|
|
17
|
+
Classifier: Framework :: Django :: 5.1
|
|
18
|
+
Classifier: Intended Audience :: Developers
|
|
19
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
20
|
+
Classifier: Operating System :: OS Independent
|
|
21
|
+
Classifier: Programming Language :: Python :: 3
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
24
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
25
|
+
Requires-Python: >=3.13
|
|
26
|
+
Requires-Dist: django>=4.0
|
|
27
|
+
Provides-Extra: unfold
|
|
28
|
+
Requires-Dist: django-unfold>=0.85.0; extra == 'unfold'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# Django Toolkit
|
|
32
|
+
|
|
33
|
+
A collection of Django utilities: Admin mixins, testing helpers, and common patterns.
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# From GitHub
|
|
39
|
+
uv add git+https://github.com/froggen/django-toolkit.git
|
|
40
|
+
|
|
41
|
+
# Local development
|
|
42
|
+
uv add --editable ../django-toolkit
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Modules
|
|
46
|
+
|
|
47
|
+
### toolkit.admin - Admin Mixins
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from django.contrib import admin
|
|
51
|
+
from toolkit.admin import OwnerMixin, ReadOnlyMixin
|
|
52
|
+
from unfold.admin import ModelAdmin
|
|
53
|
+
|
|
54
|
+
@admin.register(Project)
|
|
55
|
+
class ProjectAdmin(OwnerMixin, ModelAdmin):
|
|
56
|
+
owner_field = "user" # Users can only edit their own projects
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### toolkit.testing - Testing Utilities
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from toolkit.testing import has_index_on_columns, get_table_constraints
|
|
63
|
+
|
|
64
|
+
# Verify database indexes exist
|
|
65
|
+
def test_status_index_exists():
|
|
66
|
+
assert has_index_on_columns("invoice", ["status", "created_at"])
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Available Admin Mixins
|
|
70
|
+
|
|
71
|
+
### Permission Control
|
|
72
|
+
|
|
73
|
+
| Mixin | Description |
|
|
74
|
+
|-------|-------------|
|
|
75
|
+
| `SuperuserOnlyMixin` | Only superusers can access |
|
|
76
|
+
| `ReadOnlyMixin` | No add/change/delete, view only |
|
|
77
|
+
| `CRUDMixin` | Basic CRUD for active users |
|
|
78
|
+
| `OwnerMixin` | Users can only access their own data |
|
|
79
|
+
| `ReadOnlyOwnerMixin` | View-only for owned data |
|
|
80
|
+
|
|
81
|
+
### Special Patterns
|
|
82
|
+
|
|
83
|
+
| Mixin | Description |
|
|
84
|
+
|-------|-------------|
|
|
85
|
+
| `ActionsOnlyMixin` | Hide save buttons, use actions only |
|
|
86
|
+
| `SingleObjectMixin` | Redirect to edit/add page (for one-per-user models) |
|
|
87
|
+
|
|
88
|
+
### Inline Mixins
|
|
89
|
+
|
|
90
|
+
| Mixin | Description |
|
|
91
|
+
|-------|-------------|
|
|
92
|
+
| `InlineCRUDMixin` | CRUD for inline models |
|
|
93
|
+
| `ReadOnlyInlineMixin` | Read-only inline |
|
|
94
|
+
|
|
95
|
+
### UI Helpers
|
|
96
|
+
|
|
97
|
+
| Mixin | Description |
|
|
98
|
+
|-------|-------------|
|
|
99
|
+
| `HideRelatedFieldButtonsMixin` | Hide add/edit/delete buttons on FK fields |
|
|
100
|
+
|
|
101
|
+
## Testing Utilities
|
|
102
|
+
|
|
103
|
+
| Function | Description |
|
|
104
|
+
|----------|-------------|
|
|
105
|
+
| `get_table_constraints(table_name)` | Get all constraints and indexes for a table |
|
|
106
|
+
| `has_index_on_columns(table_name, columns)` | Check if an index exists on specified columns |
|
|
107
|
+
|
|
108
|
+
## Usage Examples
|
|
109
|
+
|
|
110
|
+
### Owner-based Permission
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
@admin.register(Article)
|
|
114
|
+
class ArticleAdmin(OwnerMixin, ModelAdmin):
|
|
115
|
+
owner_field = "author"
|
|
116
|
+
list_display = ["title", "author", "created_at"]
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Nested Owner Field
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
@admin.register(Comment)
|
|
123
|
+
class CommentAdmin(OwnerMixin, ModelAdmin):
|
|
124
|
+
owner_field = "post__author" # Comment -> Post -> Author
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Read-only with Owner Filter
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
@admin.register(Order)
|
|
131
|
+
class OrderAdmin(ReadOnlyOwnerMixin, ModelAdmin):
|
|
132
|
+
owner_field = "customer"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Single Object (e.g., User Profile)
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
@admin.register(UserProfile)
|
|
139
|
+
class UserProfileAdmin(SingleObjectMixin, OwnerMixin, ModelAdmin):
|
|
140
|
+
owner_field = "user"
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Actions Only (e.g., Approval Workflow)
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
@admin.register(WithdrawalRequest)
|
|
147
|
+
class WithdrawalRequestAdmin(ActionsOnlyMixin, ModelAdmin):
|
|
148
|
+
readonly_fields = ["amount", "status", "created_at"]
|
|
149
|
+
actions_submit_line = ["approve_action", "reject_action"]
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Index Validation in Tests
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
import pytest
|
|
156
|
+
from toolkit.testing import has_index_on_columns
|
|
157
|
+
|
|
158
|
+
@pytest.mark.django_db
|
|
159
|
+
class TestDatabaseIndexes:
|
|
160
|
+
def test_composite_index_exists(self):
|
|
161
|
+
assert has_index_on_columns("booking", ["status", "start"])
|
|
162
|
+
|
|
163
|
+
def test_single_column_index_exists(self):
|
|
164
|
+
assert has_index_on_columns("payment", ["transaction_id"])
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## License
|
|
168
|
+
|
|
169
|
+
MIT
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Django Toolkit
|
|
2
|
+
|
|
3
|
+
A collection of Django utilities: Admin mixins, testing helpers, and common patterns.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# From GitHub
|
|
9
|
+
uv add git+https://github.com/froggen/django-toolkit.git
|
|
10
|
+
|
|
11
|
+
# Local development
|
|
12
|
+
uv add --editable ../django-toolkit
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Modules
|
|
16
|
+
|
|
17
|
+
### toolkit.admin - Admin Mixins
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from django.contrib import admin
|
|
21
|
+
from toolkit.admin import OwnerMixin, ReadOnlyMixin
|
|
22
|
+
from unfold.admin import ModelAdmin
|
|
23
|
+
|
|
24
|
+
@admin.register(Project)
|
|
25
|
+
class ProjectAdmin(OwnerMixin, ModelAdmin):
|
|
26
|
+
owner_field = "user" # Users can only edit their own projects
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### toolkit.testing - Testing Utilities
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
from toolkit.testing import has_index_on_columns, get_table_constraints
|
|
33
|
+
|
|
34
|
+
# Verify database indexes exist
|
|
35
|
+
def test_status_index_exists():
|
|
36
|
+
assert has_index_on_columns("invoice", ["status", "created_at"])
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Available Admin Mixins
|
|
40
|
+
|
|
41
|
+
### Permission Control
|
|
42
|
+
|
|
43
|
+
| Mixin | Description |
|
|
44
|
+
|-------|-------------|
|
|
45
|
+
| `SuperuserOnlyMixin` | Only superusers can access |
|
|
46
|
+
| `ReadOnlyMixin` | No add/change/delete, view only |
|
|
47
|
+
| `CRUDMixin` | Basic CRUD for active users |
|
|
48
|
+
| `OwnerMixin` | Users can only access their own data |
|
|
49
|
+
| `ReadOnlyOwnerMixin` | View-only for owned data |
|
|
50
|
+
|
|
51
|
+
### Special Patterns
|
|
52
|
+
|
|
53
|
+
| Mixin | Description |
|
|
54
|
+
|-------|-------------|
|
|
55
|
+
| `ActionsOnlyMixin` | Hide save buttons, use actions only |
|
|
56
|
+
| `SingleObjectMixin` | Redirect to edit/add page (for one-per-user models) |
|
|
57
|
+
|
|
58
|
+
### Inline Mixins
|
|
59
|
+
|
|
60
|
+
| Mixin | Description |
|
|
61
|
+
|-------|-------------|
|
|
62
|
+
| `InlineCRUDMixin` | CRUD for inline models |
|
|
63
|
+
| `ReadOnlyInlineMixin` | Read-only inline |
|
|
64
|
+
|
|
65
|
+
### UI Helpers
|
|
66
|
+
|
|
67
|
+
| Mixin | Description |
|
|
68
|
+
|-------|-------------|
|
|
69
|
+
| `HideRelatedFieldButtonsMixin` | Hide add/edit/delete buttons on FK fields |
|
|
70
|
+
|
|
71
|
+
## Testing Utilities
|
|
72
|
+
|
|
73
|
+
| Function | Description |
|
|
74
|
+
|----------|-------------|
|
|
75
|
+
| `get_table_constraints(table_name)` | Get all constraints and indexes for a table |
|
|
76
|
+
| `has_index_on_columns(table_name, columns)` | Check if an index exists on specified columns |
|
|
77
|
+
|
|
78
|
+
## Usage Examples
|
|
79
|
+
|
|
80
|
+
### Owner-based Permission
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
@admin.register(Article)
|
|
84
|
+
class ArticleAdmin(OwnerMixin, ModelAdmin):
|
|
85
|
+
owner_field = "author"
|
|
86
|
+
list_display = ["title", "author", "created_at"]
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Nested Owner Field
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
@admin.register(Comment)
|
|
93
|
+
class CommentAdmin(OwnerMixin, ModelAdmin):
|
|
94
|
+
owner_field = "post__author" # Comment -> Post -> Author
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Read-only with Owner Filter
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
@admin.register(Order)
|
|
101
|
+
class OrderAdmin(ReadOnlyOwnerMixin, ModelAdmin):
|
|
102
|
+
owner_field = "customer"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Single Object (e.g., User Profile)
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
@admin.register(UserProfile)
|
|
109
|
+
class UserProfileAdmin(SingleObjectMixin, OwnerMixin, ModelAdmin):
|
|
110
|
+
owner_field = "user"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Actions Only (e.g., Approval Workflow)
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
@admin.register(WithdrawalRequest)
|
|
117
|
+
class WithdrawalRequestAdmin(ActionsOnlyMixin, ModelAdmin):
|
|
118
|
+
readonly_fields = ["amount", "status", "created_at"]
|
|
119
|
+
actions_submit_line = ["approve_action", "reject_action"]
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Index Validation in Tests
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
import pytest
|
|
126
|
+
from toolkit.testing import has_index_on_columns
|
|
127
|
+
|
|
128
|
+
@pytest.mark.django_db
|
|
129
|
+
class TestDatabaseIndexes:
|
|
130
|
+
def test_composite_index_exists(self):
|
|
131
|
+
assert has_index_on_columns("booking", ["status", "start"])
|
|
132
|
+
|
|
133
|
+
def test_single_column_index_exists(self):
|
|
134
|
+
assert has_index_on_columns("payment", ["transaction_id"])
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## License
|
|
138
|
+
|
|
139
|
+
MIT
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "cuz-toolkit"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "A collection of Django utilities: Admin mixins, testing helpers, and common patterns"
|
|
5
|
+
authors = [
|
|
6
|
+
{name = "Ivan", email = "iven12345678900@gmail.com"}
|
|
7
|
+
]
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
license = {text = "MIT"}
|
|
10
|
+
requires-python = ">=3.13"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"django>=4.0",
|
|
13
|
+
]
|
|
14
|
+
keywords = ["django", "admin", "mixin", "permission", "testing", "toolkit"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"Environment :: Web Environment",
|
|
18
|
+
"Framework :: Django",
|
|
19
|
+
"Framework :: Django :: 4.0",
|
|
20
|
+
"Framework :: Django :: 4.1",
|
|
21
|
+
"Framework :: Django :: 4.2",
|
|
22
|
+
"Framework :: Django :: 5.0",
|
|
23
|
+
"Framework :: Django :: 5.1",
|
|
24
|
+
"Intended Audience :: Developers",
|
|
25
|
+
"License :: OSI Approved :: MIT License",
|
|
26
|
+
"Operating System :: OS Independent",
|
|
27
|
+
"Programming Language :: Python :: 3",
|
|
28
|
+
"Programming Language :: Python :: 3.13",
|
|
29
|
+
"Programming Language :: Python :: 3.14",
|
|
30
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Homepage = "https://github.com/froggen/django-toolkit"
|
|
35
|
+
Repository = "https://github.com/froggen/django-toolkit"
|
|
36
|
+
|
|
37
|
+
[build-system]
|
|
38
|
+
requires = ["hatchling"]
|
|
39
|
+
build-backend = "hatchling.build"
|
|
40
|
+
|
|
41
|
+
[tool.hatch.build.targets.wheel]
|
|
42
|
+
packages = ["src/toolkit"]
|
|
43
|
+
|
|
44
|
+
[project.entry-points.pytest11]
|
|
45
|
+
cuz_toolkit = "toolkit.pytest_plugin"
|
|
46
|
+
|
|
47
|
+
[project.optional-dependencies]
|
|
48
|
+
unfold = [
|
|
49
|
+
"django-unfold>=0.85.0",
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
[tool.pytest.ini_options]
|
|
53
|
+
addopts = "-s -n auto"
|
|
54
|
+
DJANGO_SETTINGS_MODULE = "tests.settings"
|
|
55
|
+
django_find_project = false
|
|
56
|
+
pythonpath = ["."]
|
|
57
|
+
testpaths = ["tests"]
|
|
58
|
+
python_files = ["test_*.py"]
|
|
59
|
+
|
|
60
|
+
[tool.coverage.run]
|
|
61
|
+
source = ["src/toolkit"]
|
|
62
|
+
branch = true
|
|
63
|
+
|
|
64
|
+
[tool.coverage.report]
|
|
65
|
+
omit = ["tests/*"]
|
|
66
|
+
exclude_lines = [
|
|
67
|
+
"pragma: no cover",
|
|
68
|
+
"if TYPE_CHECKING:",
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
[tool.ruff]
|
|
72
|
+
target-version = "py313"
|
|
73
|
+
line-length = 120
|
|
74
|
+
src = ["src"]
|
|
75
|
+
exclude = [
|
|
76
|
+
"**/migrations/*.py",
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
[tool.ruff.lint]
|
|
80
|
+
select = [
|
|
81
|
+
"E", # pycodestyle errors
|
|
82
|
+
"W", # pycodestyle warnings
|
|
83
|
+
"F", # pyflakes
|
|
84
|
+
"I", # isort
|
|
85
|
+
"B", # flake8-bugbear
|
|
86
|
+
"C4", # flake8-comprehensions
|
|
87
|
+
"UP", # pyupgrade
|
|
88
|
+
"SIM", # flake8-simplify
|
|
89
|
+
"PTH", # flake8-use-pathlib
|
|
90
|
+
"RUF", # ruff-specific rules
|
|
91
|
+
"DJ", # flake8-django
|
|
92
|
+
]
|
|
93
|
+
ignore = ["E501", "RUF012"]
|
|
94
|
+
allowed-confusables = [":", ",", "(", ")", "?", "、", "「", "」", "。"]
|
|
95
|
+
|
|
96
|
+
[tool.ruff.format]
|
|
97
|
+
quote-style = "double"
|
|
98
|
+
indent-style = "space"
|
|
99
|
+
skip-magic-trailing-comma = false
|
|
100
|
+
line-ending = "auto"
|
|
101
|
+
|
|
102
|
+
[tool.mypy]
|
|
103
|
+
plugins = ["mypy_django_plugin.main"]
|
|
104
|
+
python_version = "3.13"
|
|
105
|
+
strict = true
|
|
106
|
+
allow_redefinition = true
|
|
107
|
+
exclude = [
|
|
108
|
+
".*/migrations/.*",
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
[[tool.mypy.overrides]]
|
|
112
|
+
module = "tests.*"
|
|
113
|
+
disallow_untyped_defs = false
|
|
114
|
+
disable_error_code = ["type-arg", "assignment", "misc", "call-arg", "attr-defined"]
|
|
115
|
+
|
|
116
|
+
[[tool.mypy.overrides]]
|
|
117
|
+
module = "unfold.*"
|
|
118
|
+
ignore_missing_imports = true
|
|
119
|
+
|
|
120
|
+
[tool.django-stubs]
|
|
121
|
+
django_settings_module = "tests.settings"
|
|
122
|
+
|
|
123
|
+
[tool.bandit]
|
|
124
|
+
exclude_dirs = ["tests", "venv", ".venv", "conftest.py"]
|
|
125
|
+
|
|
126
|
+
[dependency-groups]
|
|
127
|
+
dev = [
|
|
128
|
+
"bandit>=1.9.3",
|
|
129
|
+
"django-stubs[compatible-mypy]>=5.2.9",
|
|
130
|
+
"django-unfold>=0.85.0",
|
|
131
|
+
"mypy>=1.19.1",
|
|
132
|
+
"pre-commit>=4.2.0",
|
|
133
|
+
"pytest>=9.0.2",
|
|
134
|
+
"pytest-cov>=7.0.0",
|
|
135
|
+
"pytest-django>=4.11.1",
|
|
136
|
+
"pytest-xdist>=3.8.0",
|
|
137
|
+
"ruff>=0.15.0",
|
|
138
|
+
]
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Django Toolkit - A collection of Django utilities for common development patterns.
|
|
3
|
+
|
|
4
|
+
Modules:
|
|
5
|
+
toolkit.admin - Admin mixins for permission control
|
|
6
|
+
toolkit.ecpay - ECPay payment gateway integration (signing, verification, constants)
|
|
7
|
+
toolkit.testing - Testing utilities for database validation
|
|
8
|
+
toolkit.unfold - Unfold Admin extension (Trix editor image upload)
|
|
9
|
+
toolkit.utils - Common utilities (UploadToUniquePath, etc.)
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
__version__ = "0.1.0" # pragma: no cover
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Django Admin Mixins - A collection of Django Admin mixins for permission control.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
from toolkit.admin import OwnerMixin, ReadOnlyMixin, CRUDMixin
|
|
6
|
+
|
|
7
|
+
@admin.register(MyModel)
|
|
8
|
+
class MyModelAdmin(OwnerMixin, ModelAdmin):
|
|
9
|
+
owner_field = "user"
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from toolkit.admin.mixins import (
|
|
13
|
+
ActionsOnlyMixin,
|
|
14
|
+
CRUDMixin,
|
|
15
|
+
EditOnlyInlineMixin,
|
|
16
|
+
EditOnlyMixin,
|
|
17
|
+
HideRelatedFieldButtonsMixin,
|
|
18
|
+
InlineCRUDMixin,
|
|
19
|
+
OwnerMixin,
|
|
20
|
+
ReadOnlyInlineMixin,
|
|
21
|
+
ReadOnlyMixin,
|
|
22
|
+
ReadOnlyOwnerMixin,
|
|
23
|
+
SelfOnlyMixin,
|
|
24
|
+
SingleObjectMixin,
|
|
25
|
+
SuperuserOnlyMixin,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
"ActionsOnlyMixin",
|
|
30
|
+
"CRUDMixin",
|
|
31
|
+
"EditOnlyInlineMixin",
|
|
32
|
+
"EditOnlyMixin",
|
|
33
|
+
"HideRelatedFieldButtonsMixin",
|
|
34
|
+
"InlineCRUDMixin",
|
|
35
|
+
"OwnerMixin",
|
|
36
|
+
"ReadOnlyInlineMixin",
|
|
37
|
+
"ReadOnlyMixin",
|
|
38
|
+
"ReadOnlyOwnerMixin",
|
|
39
|
+
"SelfOnlyMixin",
|
|
40
|
+
"SingleObjectMixin",
|
|
41
|
+
"SuperuserOnlyMixin",
|
|
42
|
+
]
|