djaxei 0.0.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.
- djaxei-0.0.0/.bumpversion.cfg +13 -0
- djaxei-0.0.0/.env.example +1 -0
- djaxei-0.0.0/.envrc.example +21 -0
- djaxei-0.0.0/.flake8 +8 -0
- djaxei-0.0.0/.gitignore +19 -0
- djaxei-0.0.0/.isort.cfg +13 -0
- djaxei-0.0.0/.pre-commit-config.yaml +78 -0
- djaxei-0.0.0/.python-version +5 -0
- djaxei-0.0.0/CHANGES.md +4 -0
- djaxei-0.0.0/HISTORY.md +8 -0
- djaxei-0.0.0/LICENSE.txt +21 -0
- djaxei-0.0.0/MANIFEST.in +4 -0
- djaxei-0.0.0/Makefile +97 -0
- djaxei-0.0.0/PKG-INFO +5 -0
- djaxei-0.0.0/README.md +45 -0
- djaxei-0.0.0/TODO.md +3 -0
- djaxei-0.0.0/pyproject.toml +68 -0
- djaxei-0.0.0/pytest.ini +37 -0
- djaxei-0.0.0/setup.cfg +4 -0
- djaxei-0.0.0/src/djaxei/__init__.py +1 -0
- djaxei-0.0.0/src/djaxei/actions.py +100 -0
- djaxei-0.0.0/src/djaxei/admin.py +6 -0
- djaxei-0.0.0/src/djaxei/apps.py +8 -0
- djaxei-0.0.0/src/djaxei/exceptions.py +13 -0
- djaxei-0.0.0/src/djaxei/exp.py +175 -0
- djaxei-0.0.0/src/djaxei/imp.py +40 -0
- djaxei-0.0.0/src/djaxei/migrations/__init__.py +0 -0
- djaxei-0.0.0/src/djaxei/models.py +6 -0
- djaxei-0.0.0/src/djaxei/modems/__init__.py +0 -0
- djaxei-0.0.0/src/djaxei/modems/field.py +53 -0
- djaxei-0.0.0/src/djaxei/modems/model.py +112 -0
- djaxei-0.0.0/src/djaxei/providers/__init__.py +19 -0
- djaxei-0.0.0/src/djaxei/providers/xlsxwriter_provider.py +15 -0
- djaxei-0.0.0/src/djaxei/providers/xlwt_provider.py +19 -0
- djaxei-0.0.0/src/djaxei/templates/djaxei/replace_with_xls.html +6 -0
- djaxei-0.0.0/src/djaxei/tests.py +6 -0
- djaxei-0.0.0/src/djaxei/views.py +6 -0
- djaxei-0.0.0/src/djaxei.egg-info/PKG-INFO +5 -0
- djaxei-0.0.0/src/djaxei.egg-info/SOURCES.txt +68 -0
- djaxei-0.0.0/src/djaxei.egg-info/dependency_links.txt +1 -0
- djaxei-0.0.0/src/djaxei.egg-info/top_level.txt +1 -0
- djaxei-0.0.0/tests/.coveragerc +37 -0
- djaxei-0.0.0/tests/conftest.py +137 -0
- djaxei-0.0.0/tests/demo/demoproject/__init__.py +0 -0
- djaxei-0.0.0/tests/demo/demoproject/app1/__init__.py +0 -0
- djaxei-0.0.0/tests/demo/demoproject/app1/admin.py +6 -0
- djaxei-0.0.0/tests/demo/demoproject/app1/apps.py +8 -0
- djaxei-0.0.0/tests/demo/demoproject/app1/migrations/0001_initial.py +71 -0
- djaxei-0.0.0/tests/demo/demoproject/app1/migrations/__init__.py +0 -0
- djaxei-0.0.0/tests/demo/demoproject/app1/models.py +58 -0
- djaxei-0.0.0/tests/demo/demoproject/app1/views.py +6 -0
- djaxei-0.0.0/tests/demo/demoproject/app2/__init__.py +0 -0
- djaxei-0.0.0/tests/demo/demoproject/app2/admin.py +6 -0
- djaxei-0.0.0/tests/demo/demoproject/app2/apps.py +8 -0
- djaxei-0.0.0/tests/demo/demoproject/app2/migrations/__init__.py +0 -0
- djaxei-0.0.0/tests/demo/demoproject/app2/models.py +6 -0
- djaxei-0.0.0/tests/demo/demoproject/app2/views.py +6 -0
- djaxei-0.0.0/tests/demo/demoproject/settings.py +122 -0
- djaxei-0.0.0/tests/demo/demoproject/urls.py +21 -0
- djaxei-0.0.0/tests/demo/manage.py +22 -0
- djaxei-0.0.0/tests/example.xlsx +0 -0
- djaxei-0.0.0/tests/exports/test_export.py +121 -0
- djaxei-0.0.0/tests/exports/test_field_list_model_modem.py +83 -0
- djaxei-0.0.0/tests/exports/test_roots.py +44 -0
- djaxei-0.0.0/tests/files/example_imp.xlsx +0 -0
- djaxei-0.0.0/tests/imports/exported.xlsx +0 -0
- djaxei-0.0.0/tests/imports/test_imp.py +179 -0
- djaxei-0.0.0/tests/modems/test_datetime_modems.py +41 -0
- djaxei-0.0.0/tests/modems/test_json_modems.py +33 -0
- djaxei-0.0.0/tox.ini +46 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
[bumpversion]
|
|
2
|
+
current_version = 1.2.1
|
|
3
|
+
commit = True
|
|
4
|
+
tag = False
|
|
5
|
+
tag_name = "{new_version}"
|
|
6
|
+
|
|
7
|
+
[bumpversion:file:pyproject.toml]
|
|
8
|
+
search = version = "{current_version}"
|
|
9
|
+
replace = version = "{new_version}"
|
|
10
|
+
|
|
11
|
+
[bumpversion:file:src/djaxei/__init__.py]
|
|
12
|
+
search = __version__ = "{current_version}"
|
|
13
|
+
replace = __version__ = "{new_version}"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
PYPI_TOKEN=...
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
dotenv
|
|
2
|
+
|
|
3
|
+
layout_poetry() {
|
|
4
|
+
if [[ ! -f pyproject.toml ]]; then
|
|
5
|
+
log_error 'No pyproject.toml found. Use `poetry new` or `poetry init` to create one first.'
|
|
6
|
+
exit 2
|
|
7
|
+
fi
|
|
8
|
+
|
|
9
|
+
# local VENV=$(poetry env list --full-path | cut -d' ' -f1)
|
|
10
|
+
local VENV='.venv'
|
|
11
|
+
if [[ -z $VENV || ! -d $VENV/bin ]]; then
|
|
12
|
+
log_error 'No created poetry virtual environment found. Use `poetry install` to create one first.'
|
|
13
|
+
exit 2
|
|
14
|
+
fi
|
|
15
|
+
VENV=$VENV/bin
|
|
16
|
+
export VIRTUAL_ENV=$(echo "$VENV" | rev | cut -d'/' -f2- | rev)
|
|
17
|
+
export POETRY_ACTIVE=1
|
|
18
|
+
PATH_add "$VENV"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
layout poetry
|
djaxei-0.0.0/.flake8
ADDED
djaxei-0.0.0/.gitignore
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.*
|
|
2
|
+
~*
|
|
3
|
+
!.gitignore
|
|
4
|
+
!.env.example
|
|
5
|
+
!.envrc.example
|
|
6
|
+
!.bumpversion.cfg
|
|
7
|
+
!.flake8
|
|
8
|
+
!.isort.cfg
|
|
9
|
+
!.pre-commit-config.yaml
|
|
10
|
+
!tests/.coveragerc
|
|
11
|
+
!.python-version
|
|
12
|
+
|
|
13
|
+
__pycache__
|
|
14
|
+
dist
|
|
15
|
+
|
|
16
|
+
poetry.lock
|
|
17
|
+
db.sqlite3
|
|
18
|
+
*.egg-info
|
|
19
|
+
*.pyc
|
djaxei-0.0.0/.isort.cfg
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
[settings]
|
|
2
|
+
combine_as_imports = true
|
|
3
|
+
default_section = THIRDPARTY
|
|
4
|
+
include_trailing_comma = true
|
|
5
|
+
;forced_separate = django.contrib,django.utils
|
|
6
|
+
line_length = 80
|
|
7
|
+
known_future_library = future,pies
|
|
8
|
+
;known_standard_library =
|
|
9
|
+
known_third_party = rest_framework,django,constance,rest_framework
|
|
10
|
+
known_first_party = bitcaster
|
|
11
|
+
multi_line_output = 0
|
|
12
|
+
balanced_wrapping = true
|
|
13
|
+
sections = FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
exclude: '^$'
|
|
2
|
+
fail_fast: false
|
|
3
|
+
repos:
|
|
4
|
+
- repo: local
|
|
5
|
+
hooks:
|
|
6
|
+
- id: ci-cache-key
|
|
7
|
+
name: update ci-cache-key
|
|
8
|
+
entry: sh .hooks/pre-commit.sh
|
|
9
|
+
language: system
|
|
10
|
+
stages: [commit]
|
|
11
|
+
files: Poetry.lock
|
|
12
|
+
|
|
13
|
+
- id: isort
|
|
14
|
+
args:
|
|
15
|
+
- --check-only
|
|
16
|
+
exclude: tweepy
|
|
17
|
+
name: isort
|
|
18
|
+
entry: isort
|
|
19
|
+
language: system
|
|
20
|
+
types: [python]
|
|
21
|
+
stages: [commit]
|
|
22
|
+
|
|
23
|
+
- id: flake8
|
|
24
|
+
exclude: /(_plugin_template|python_twitter|migrations|tweepy)/
|
|
25
|
+
name: flake8
|
|
26
|
+
entry: flake8
|
|
27
|
+
language: system
|
|
28
|
+
types: [python]
|
|
29
|
+
stages: [commit]
|
|
30
|
+
|
|
31
|
+
- repo: https://github.com/Yelp/detect-secrets
|
|
32
|
+
rev: 0.9.1
|
|
33
|
+
hooks:
|
|
34
|
+
- id: detect-secrets
|
|
35
|
+
args: ['--baseline', '.secrets.baseline']
|
|
36
|
+
exclude: (tests/.*|.*/tenant\.sql|Pipfile\.lock|.*\.js|.gitlab-ci.yml|poetry.lock)
|
|
37
|
+
stages: [push]
|
|
38
|
+
|
|
39
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
40
|
+
rev: v2.1.0
|
|
41
|
+
hooks:
|
|
42
|
+
- id: double-quote-string-fixer
|
|
43
|
+
stages: [commit]
|
|
44
|
+
|
|
45
|
+
- id: debug-statements
|
|
46
|
+
exclude: (_plugin_template|python_twitter)
|
|
47
|
+
stages: [commit]
|
|
48
|
+
|
|
49
|
+
- id: end-of-file-fixer
|
|
50
|
+
exclude: .bumpversion.cfg
|
|
51
|
+
stages: [commit]
|
|
52
|
+
|
|
53
|
+
- id: check-merge-conflict
|
|
54
|
+
stages: [commit]
|
|
55
|
+
|
|
56
|
+
- id: check-case-conflict
|
|
57
|
+
stages: [commit]
|
|
58
|
+
|
|
59
|
+
- repo: https://github.com/saxix/pch
|
|
60
|
+
rev: fc387f4
|
|
61
|
+
hooks:
|
|
62
|
+
- id: check-version-release-match
|
|
63
|
+
args:
|
|
64
|
+
- --pythonpath=src
|
|
65
|
+
- --package=djaxei
|
|
66
|
+
stages: [push]
|
|
67
|
+
|
|
68
|
+
- id: check-untracked
|
|
69
|
+
args:
|
|
70
|
+
- src
|
|
71
|
+
- tests
|
|
72
|
+
stages: [push]
|
|
73
|
+
|
|
74
|
+
- id: check-forbidden
|
|
75
|
+
args:
|
|
76
|
+
- -p
|
|
77
|
+
- \.showbrowser\(
|
|
78
|
+
stages: [commit]
|
djaxei-0.0.0/CHANGES.md
ADDED
djaxei-0.0.0/HISTORY.md
ADDED
djaxei-0.0.0/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020, Giovanni Bronzini
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
djaxei-0.0.0/MANIFEST.in
ADDED
djaxei-0.0.0/Makefile
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
.PHONY: clean clean-test clean-pyc clean-build docs help
|
|
2
|
+
.DEFAULT_GOAL := help
|
|
3
|
+
|
|
4
|
+
VCS_CERT?=/usr/local/share/ca-certificates/path/my_company.crt
|
|
5
|
+
|
|
6
|
+
define BROWSER_PYSCRIPT
|
|
7
|
+
import os, webbrowser, sys
|
|
8
|
+
|
|
9
|
+
from urllib.request import pathname2url
|
|
10
|
+
|
|
11
|
+
webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1])))
|
|
12
|
+
endef
|
|
13
|
+
export BROWSER_PYSCRIPT
|
|
14
|
+
|
|
15
|
+
define PRINT_HELP_PYSCRIPT
|
|
16
|
+
import re, sys
|
|
17
|
+
|
|
18
|
+
for line in sys.stdin:
|
|
19
|
+
match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line)
|
|
20
|
+
if match:
|
|
21
|
+
target, help = match.groups()
|
|
22
|
+
print("%-20s %s" % (target, help))
|
|
23
|
+
endef
|
|
24
|
+
export PRINT_HELP_PYSCRIPT
|
|
25
|
+
|
|
26
|
+
BROWSER := python -c "$$BROWSER_PYSCRIPT"
|
|
27
|
+
|
|
28
|
+
help:
|
|
29
|
+
@python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST)
|
|
30
|
+
|
|
31
|
+
clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts
|
|
32
|
+
|
|
33
|
+
clean-build: ## remove build artifacts
|
|
34
|
+
rm -fr pip-wheel-metadata/
|
|
35
|
+
rm -fr build/
|
|
36
|
+
rm -fr dist/
|
|
37
|
+
rm -fr .eggs/
|
|
38
|
+
find . -name '*.egg-info' -exec rm -fr {} +
|
|
39
|
+
find . -name '*.egg' -exec rm -f {} +
|
|
40
|
+
|
|
41
|
+
clean-pyc: ## remove Python file artifacts
|
|
42
|
+
find . -name '*.pyc' -exec rm -f {} +
|
|
43
|
+
find . -name '*.pyo' -exec rm -f {} +
|
|
44
|
+
find . -name '*~' -exec rm -f {} +
|
|
45
|
+
find . -name '__pycache__' -exec rm -fr {} +
|
|
46
|
+
|
|
47
|
+
clean-test: ## remove test and coverage artifacts
|
|
48
|
+
rm -fr .tox/
|
|
49
|
+
rm -f .coverage
|
|
50
|
+
rm -fr htmlcov/
|
|
51
|
+
rm -fr .pytest_cache
|
|
52
|
+
|
|
53
|
+
lint: ## check style with flake8
|
|
54
|
+
flake8 wlsclick tests
|
|
55
|
+
|
|
56
|
+
test: ## run tests quickly with the default Python
|
|
57
|
+
pytest
|
|
58
|
+
|
|
59
|
+
test-all: ## run tests on every Python version with tox
|
|
60
|
+
tox
|
|
61
|
+
|
|
62
|
+
coverage: ## check code coverage quickly with the default Python
|
|
63
|
+
coverage run --source wlsclick -m pytest
|
|
64
|
+
coverage report -m
|
|
65
|
+
coverage html
|
|
66
|
+
$(BROWSER) htmlcov/index.html
|
|
67
|
+
|
|
68
|
+
docs: ## generate Sphinx HTML documentation, including API docs
|
|
69
|
+
rm -f docs/wlsclick.rst
|
|
70
|
+
rm -f docs/modules.rst
|
|
71
|
+
sphinx-apidoc -o docs/ wlsclick
|
|
72
|
+
$(MAKE) -C docs clean
|
|
73
|
+
$(MAKE) -C docs html
|
|
74
|
+
$(BROWSER) docs/_build/html/index.html
|
|
75
|
+
|
|
76
|
+
servedocs: docs ## compile the docs watching for changes
|
|
77
|
+
watchmedo shell-command -p '*.rst' -c '$(MAKE) -C docs html' -R -D .
|
|
78
|
+
|
|
79
|
+
release: dist ## package and upload a release
|
|
80
|
+
poetry config pypi-token.pypi ${PYPI_TOKEN}
|
|
81
|
+
poetry publish
|
|
82
|
+
|
|
83
|
+
dist: clean ## builds source and wheel package
|
|
84
|
+
poetry build -f sdist
|
|
85
|
+
|
|
86
|
+
install: clean ## install the package to the active Python's site-packages
|
|
87
|
+
poetry install
|
|
88
|
+
|
|
89
|
+
bump: ## Bumps version
|
|
90
|
+
@while :; do \
|
|
91
|
+
read -r -p "bumpversion [major/minor/patch]: " PART; \
|
|
92
|
+
case "$$PART" in \
|
|
93
|
+
major|minor|patch) break ;; \
|
|
94
|
+
esac \
|
|
95
|
+
done ; \
|
|
96
|
+
bumpversion --no-commit --allow-dirty $$PART
|
|
97
|
+
@grep "^version = " pyproject.toml
|
djaxei-0.0.0/PKG-INFO
ADDED
djaxei-0.0.0/README.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# A django admin extension for importing exporting records from/to xls/ods
|
|
2
|
+
|
|
3
|
+
A Python library project using:
|
|
4
|
+
* pytest
|
|
5
|
+
* flake8
|
|
6
|
+
* tox
|
|
7
|
+
* bumpversion
|
|
8
|
+
* isort
|
|
9
|
+
|
|
10
|
+
* Free software: MIT license
|
|
11
|
+
* Documentation: __TBD__
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Features
|
|
15
|
+
|
|
16
|
+
- Requires Python >=3.8, Django>=3.2
|
|
17
|
+
- Currently work only with xlsxwriter
|
|
18
|
+
|
|
19
|
+
- Could help if use [direnv](https://direnv.net/) in dev environment
|
|
20
|
+
|
|
21
|
+
# Contributing
|
|
22
|
+
|
|
23
|
+
See [demo](tests%2Fdemo) in tests folder
|
|
24
|
+
|
|
25
|
+
* TODO
|
|
26
|
+
|
|
27
|
+
# Dev setup
|
|
28
|
+
|
|
29
|
+
1. install direnv
|
|
30
|
+
2. install pyenv
|
|
31
|
+
3. clone project: `git clone https://github.com/GigiusB/djaxei.git`
|
|
32
|
+
4. `cd djaxei`
|
|
33
|
+
5. ```pyenv install `cat .python-version` ```
|
|
34
|
+
6. `pip install -U poetry` # this should install poetry in your pyenv python
|
|
35
|
+
7. `cp .env.example .env`
|
|
36
|
+
8. `cp .envrc.example .envrc`
|
|
37
|
+
9. `direnv allow`
|
|
38
|
+
10. ```poetry env use `pyenv which python` ```
|
|
39
|
+
11. `cd .. ; cd -` # see if it loads the env
|
|
40
|
+
12. poetry install
|
|
41
|
+
13. pytest
|
|
42
|
+
|
|
43
|
+
Credits
|
|
44
|
+
-------
|
|
45
|
+
|
djaxei-0.0.0/TODO.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "djaxei"
|
|
3
|
+
version = "1.2.1"
|
|
4
|
+
description = "A django admin extension for importing exporting records from/to xls/ods"
|
|
5
|
+
authors = ["Giovanni Bronzini <g.bronzini@gmail.com>"]
|
|
6
|
+
license = "MIT"
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
repository = "https://github.com/GigiusB/djaxei.git"
|
|
9
|
+
keywords = ["xls",]
|
|
10
|
+
include = ["README.md", "HISTORY.md", "Makefile"]
|
|
11
|
+
packages = [
|
|
12
|
+
{ include = "djaxei", from = "src" },
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[tool.poetry.dependencies]
|
|
16
|
+
python = ">=3.8.7,<4"
|
|
17
|
+
django = ">=3.2,<5"
|
|
18
|
+
#openpyxl = { version = "<4", optional = true }
|
|
19
|
+
#xlwt = {version = ">=1.2.0", optional = true}
|
|
20
|
+
#xlsxwriter = {version = ">=1.2.8", optional = true}
|
|
21
|
+
openpyxl = ">=3.0.0"
|
|
22
|
+
|
|
23
|
+
#[tool.poetry.dev-dependencies]
|
|
24
|
+
#pytest = "^6.2.5"
|
|
25
|
+
#tox = "^3.24.4"
|
|
26
|
+
#pytest-django = "^4.5.2"
|
|
27
|
+
#factory-boy = "^3.2.1"
|
|
28
|
+
#pytest-pythonpath = "^0.7.3"
|
|
29
|
+
#flake8 = "^4.0.1"
|
|
30
|
+
#isort = "^5.10.1"
|
|
31
|
+
#django-webtest = "^1.9.8"
|
|
32
|
+
#pytest-env = "^0.6.2"
|
|
33
|
+
#pytest-coverage = "^0.0"
|
|
34
|
+
#pytest-echo = "^1.7.1"
|
|
35
|
+
|
|
36
|
+
#[tool.poetry.extras]
|
|
37
|
+
#openpyxl = ["openpyxl"]
|
|
38
|
+
#xlsxwriter = ["xlsxwriter"]
|
|
39
|
+
#xlwt = ["xlwt"]
|
|
40
|
+
|
|
41
|
+
#requires = ["poetry>=1.1"]
|
|
42
|
+
#build-backend = "poetry.masonry.api"
|
|
43
|
+
|
|
44
|
+
#[tool.poetry.group.dev.dependencies]
|
|
45
|
+
#openpyxl = "^3.1.0"
|
|
46
|
+
#xlsxwriter = "^3.0.7"
|
|
47
|
+
pytz = "^2024.1"
|
|
48
|
+
|
|
49
|
+
[tool.poetry.group.dev.dependencies]
|
|
50
|
+
pytest = "*"
|
|
51
|
+
pytest-django = "*"
|
|
52
|
+
flake8 = "*"
|
|
53
|
+
isort = "*"
|
|
54
|
+
bumpversion = "*"
|
|
55
|
+
factory-boy = "*"
|
|
56
|
+
pytest-env = "*"
|
|
57
|
+
pytest-coverage = "*"
|
|
58
|
+
pytest-echo = "*"
|
|
59
|
+
tox = "*"
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
[build-system]
|
|
63
|
+
requires = [
|
|
64
|
+
"setuptools>=61",
|
|
65
|
+
"setuptools_scm[toml]>=6.2"
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
build-backend = "setuptools.build_meta"
|
djaxei-0.0.0/pytest.ini
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[pytest]
|
|
2
|
+
env =
|
|
3
|
+
DJANGO_SETTINGS_MODULE=demoproject.settings
|
|
4
|
+
norecursedirs = data _plugin_template ~* .* node_modules
|
|
5
|
+
pythonpath = ./src, ./tests/demo
|
|
6
|
+
django_find_project = false
|
|
7
|
+
;log_format = %(asctime)s %(levelname)s %(message)s
|
|
8
|
+
;log_date_format = %Y-%m-%d %H:%M:%S
|
|
9
|
+
;log_print = true
|
|
10
|
+
log_cli = 0
|
|
11
|
+
log_cli_level = INFO
|
|
12
|
+
log_cli_format = [%(levelname)-8s] %(message)s (%(filename)s:%(lineno)s)
|
|
13
|
+
log_cli_date_format=%Y-%m-%d %H:%M:%S
|
|
14
|
+
addopts =
|
|
15
|
+
-rs
|
|
16
|
+
-p no:xdist
|
|
17
|
+
-p no:pep8
|
|
18
|
+
-p no:warnings
|
|
19
|
+
--reuse-db
|
|
20
|
+
--tb=short
|
|
21
|
+
--capture=no
|
|
22
|
+
--cov-report=html
|
|
23
|
+
--cov-config=tests/.coveragerc
|
|
24
|
+
--cov=djaxei
|
|
25
|
+
--echo-version=django
|
|
26
|
+
|
|
27
|
+
markers =
|
|
28
|
+
plugin: dispatcher test
|
|
29
|
+
incremental: incremental tests
|
|
30
|
+
skipif_missing: skip test if environment variable does not exists
|
|
31
|
+
paid: paid plugin test
|
|
32
|
+
cli: CLI related tests
|
|
33
|
+
selenium: Run selenium functional tests
|
|
34
|
+
|
|
35
|
+
python_files=test_*.py
|
|
36
|
+
filterwarnings =
|
|
37
|
+
ignore::DeprecationWarning
|
djaxei-0.0.0/setup.cfg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.2.1"
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
from django.contrib import messages
|
|
2
|
+
from django.contrib.admin import helpers
|
|
3
|
+
from django.contrib.admin.utils import get_deleted_objects, model_ngettext
|
|
4
|
+
from django.core.exceptions import PermissionDenied
|
|
5
|
+
from django.db import router
|
|
6
|
+
from django.template.response import TemplateResponse
|
|
7
|
+
from django.utils.encoding import force_text
|
|
8
|
+
from django.utils.translation import ugettext as _, ugettext_lazy
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def replace_selected_validator(modeladmin, request, queryset):
|
|
12
|
+
# Check that the user has delete permission for the actual model
|
|
13
|
+
if not modeladmin.has_delete_permission(request):
|
|
14
|
+
raise PermissionDenied
|
|
15
|
+
return None
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def replace_selected_factory(breadcrumb=None, validate_queryset=None):
|
|
19
|
+
def replace_selected(modeladmin, request, queryset):
|
|
20
|
+
"""
|
|
21
|
+
Default action which deletes the selected objects.
|
|
22
|
+
|
|
23
|
+
This action first displays a confirmation page which shows all the
|
|
24
|
+
deletable objects, or, if the user has no permission one of the related
|
|
25
|
+
childs (foreignkeys), a "permission denied" message.
|
|
26
|
+
|
|
27
|
+
Next, it deletes all selected objects and redirects back to the change list.
|
|
28
|
+
"""
|
|
29
|
+
opts = modeladmin.model._meta
|
|
30
|
+
app_label = opts.app_label
|
|
31
|
+
|
|
32
|
+
if not modeladmin.has_delete_permission(request):
|
|
33
|
+
raise PermissionDenied
|
|
34
|
+
|
|
35
|
+
if validate_queryset:
|
|
36
|
+
validation_error_message = validate_queryset(modeladmin, request, queryset)
|
|
37
|
+
if validation_error_message:
|
|
38
|
+
modeladmin.message_user(request, validation_error_message, messages.WARNING)
|
|
39
|
+
return None
|
|
40
|
+
|
|
41
|
+
using = router.db_for_write(modeladmin.model)
|
|
42
|
+
|
|
43
|
+
# Populate deletable_objects, a data structure of all related objects that
|
|
44
|
+
# will also be deleted.
|
|
45
|
+
deletable_objects, model_count, perms_needed, protected = get_deleted_objects(
|
|
46
|
+
queryset, opts, request.user, modeladmin.admin_site, using)
|
|
47
|
+
|
|
48
|
+
# The user has already confirmed the deletion.
|
|
49
|
+
# Do the deletion and return a None to display the change list view again.
|
|
50
|
+
if request.POST.get('post') and not protected:
|
|
51
|
+
if perms_needed:
|
|
52
|
+
raise PermissionDenied
|
|
53
|
+
n = queryset.count()
|
|
54
|
+
if n:
|
|
55
|
+
for obj in queryset:
|
|
56
|
+
obj_display = force_text(obj)
|
|
57
|
+
modeladmin.log_deletion(request, obj, obj_display)
|
|
58
|
+
queryset.delete()
|
|
59
|
+
modeladmin.message_user(request, _("Successfully deleted %(count)d %(items)s.") % {
|
|
60
|
+
"count": n, "items": model_ngettext(modeladmin.opts, n)
|
|
61
|
+
}, messages.SUCCESS)
|
|
62
|
+
# Return None to display the change list page again.
|
|
63
|
+
return None
|
|
64
|
+
|
|
65
|
+
if len(queryset) == 1:
|
|
66
|
+
objects_name = force_text(opts.verbose_name)
|
|
67
|
+
else:
|
|
68
|
+
objects_name = force_text(opts.verbose_name_plural)
|
|
69
|
+
|
|
70
|
+
if perms_needed or protected:
|
|
71
|
+
title = _("Cannot delete %(name)s") % {"name": objects_name}
|
|
72
|
+
else:
|
|
73
|
+
title = _("Are you sure you want to replace those records with the content of the spreadsheet?")
|
|
74
|
+
|
|
75
|
+
context = dict(
|
|
76
|
+
modeladmin.admin_site.each_context(request),
|
|
77
|
+
title=title,
|
|
78
|
+
objects_name=objects_name,
|
|
79
|
+
deletable_objects=[deletable_objects],
|
|
80
|
+
model_count=dict(model_count).items(),
|
|
81
|
+
queryset=queryset,
|
|
82
|
+
perms_lacking=perms_needed,
|
|
83
|
+
protected=protected,
|
|
84
|
+
opts=opts,
|
|
85
|
+
action_checkbox_name=helpers.ACTION_CHECKBOX_NAME,
|
|
86
|
+
media=modeladmin.media,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
request.current_app = modeladmin.admin_site.name
|
|
90
|
+
|
|
91
|
+
# Display the confirmation page
|
|
92
|
+
return TemplateResponse(request, modeladmin.delete_selected_confirmation_template or [
|
|
93
|
+
"admin/%s/%s/delete_selected_confirmation.html" % (app_label, opts.model_name),
|
|
94
|
+
"admin/%s/delete_selected_confirmation.html" % app_label,
|
|
95
|
+
"admin/delete_selected_confirmation.html"
|
|
96
|
+
], context)
|
|
97
|
+
|
|
98
|
+
replace_selected.short_description = \
|
|
99
|
+
breadcrumb or ugettext_lazy("Replace %(verbose_name_plural)s with xls")
|
|
100
|
+
return replace_selected
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class ImportException(Exception):
|
|
2
|
+
def __init__(self, cause, worksheet=None, *args):
|
|
3
|
+
super(ImportException, self).__init__(*args)
|
|
4
|
+
self.worksheet = worksheet
|
|
5
|
+
self.cause = cause
|
|
6
|
+
|
|
7
|
+
def __str__(self):
|
|
8
|
+
if hasattr(self.cause, 'reference'):
|
|
9
|
+
msg = "[%s:%s] %s: %s" % (self.worksheet, self.cause.reference, self.cause.__class__.__name__, str(self.cause))
|
|
10
|
+
else:
|
|
11
|
+
msg = "[%s] %s: %s" % (self.worksheet, self.cause.__class__.__name__, str(self.cause))
|
|
12
|
+
return msg
|
|
13
|
+
|