django-blog-core 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.
Files changed (64) hide show
  1. django_blog_core-0.1.0/.pre-commit-config.yaml +52 -0
  2. django_blog_core-0.1.0/CHANGELOG.rst +16 -0
  3. django_blog_core-0.1.0/CODEOWNERS +2 -0
  4. django_blog_core-0.1.0/CONTRIBUTING.md +6 -0
  5. django_blog_core-0.1.0/LICENSE +21 -0
  6. django_blog_core-0.1.0/MANIFEST.in +17 -0
  7. django_blog_core-0.1.0/PKG-INFO +173 -0
  8. django_blog_core-0.1.0/README.md +103 -0
  9. django_blog_core-0.1.0/mkdocs.yml +44 -0
  10. django_blog_core-0.1.0/pyproject.toml +211 -0
  11. django_blog_core-0.1.0/requirements/py310-django42.txt +22 -0
  12. django_blog_core-0.1.0/requirements/py310-django52.txt +22 -0
  13. django_blog_core-0.1.0/requirements/py311-django42.txt +18 -0
  14. django_blog_core-0.1.0/requirements/py311-django52.txt +18 -0
  15. django_blog_core-0.1.0/requirements/py312-django42.txt +18 -0
  16. django_blog_core-0.1.0/requirements/py312-django52.txt +18 -0
  17. django_blog_core-0.1.0/requirements/py313-django52.txt +18 -0
  18. django_blog_core-0.1.0/requirements/py314-django52.txt +18 -0
  19. django_blog_core-0.1.0/requirements/runtime.in +2 -0
  20. django_blog_core-0.1.0/runtests.py +52 -0
  21. django_blog_core-0.1.0/setup.cfg +4 -0
  22. django_blog_core-0.1.0/src/blog_core/__init__.py +17 -0
  23. django_blog_core-0.1.0/src/blog_core/admin.py +129 -0
  24. django_blog_core-0.1.0/src/blog_core/apps.py +16 -0
  25. django_blog_core-0.1.0/src/blog_core/conf.py +65 -0
  26. django_blog_core-0.1.0/src/blog_core/extras/__init__.py +13 -0
  27. django_blog_core-0.1.0/src/blog_core/extras/images.py +8 -0
  28. django_blog_core-0.1.0/src/blog_core/extras/search.py +13 -0
  29. django_blog_core-0.1.0/src/blog_core/extras/social.py +9 -0
  30. django_blog_core-0.1.0/src/blog_core/extras/tags.py +8 -0
  31. django_blog_core-0.1.0/src/blog_core/feeds.py +60 -0
  32. django_blog_core-0.1.0/src/blog_core/hookset.py +98 -0
  33. django_blog_core-0.1.0/src/blog_core/management/__init__.py +0 -0
  34. django_blog_core-0.1.0/src/blog_core/management/commands/__init__.py +0 -0
  35. django_blog_core-0.1.0/src/blog_core/management/commands/publish_scheduled_articles.py +40 -0
  36. django_blog_core-0.1.0/src/blog_core/managers.py +43 -0
  37. django_blog_core-0.1.0/src/blog_core/migrations/0001_initial.py +241 -0
  38. django_blog_core-0.1.0/src/blog_core/migrations/__init__.py +0 -0
  39. django_blog_core-0.1.0/src/blog_core/models.py +218 -0
  40. django_blog_core-0.1.0/src/blog_core/render.py +93 -0
  41. django_blog_core-0.1.0/src/blog_core/static/blog_core/css/blog.css +172 -0
  42. django_blog_core-0.1.0/src/blog_core/templates/blog_core/article_detail.html +18 -0
  43. django_blog_core-0.1.0/src/blog_core/templates/blog_core/article_list.html +44 -0
  44. django_blog_core-0.1.0/src/blog_core/templates/blog_core/base.html +19 -0
  45. django_blog_core-0.1.0/src/blog_core/urls.py +40 -0
  46. django_blog_core-0.1.0/src/blog_core/views.py +93 -0
  47. django_blog_core-0.1.0/src/django_blog_core.egg-info/PKG-INFO +173 -0
  48. django_blog_core-0.1.0/src/django_blog_core.egg-info/SOURCES.txt +62 -0
  49. django_blog_core-0.1.0/src/django_blog_core.egg-info/dependency_links.txt +1 -0
  50. django_blog_core-0.1.0/src/django_blog_core.egg-info/not-zip-safe +1 -0
  51. django_blog_core-0.1.0/src/django_blog_core.egg-info/requires.txt +42 -0
  52. django_blog_core-0.1.0/src/django_blog_core.egg-info/top_level.txt +1 -0
  53. django_blog_core-0.1.0/tests/__init__.py +0 -0
  54. django_blog_core-0.1.0/tests/conftest.py +53 -0
  55. django_blog_core-0.1.0/tests/settings.py +75 -0
  56. django_blog_core-0.1.0/tests/test_command.py +59 -0
  57. django_blog_core-0.1.0/tests/test_feeds.py +43 -0
  58. django_blog_core-0.1.0/tests/test_hookset.py +40 -0
  59. django_blog_core-0.1.0/tests/test_models.py +82 -0
  60. django_blog_core-0.1.0/tests/test_render.py +47 -0
  61. django_blog_core-0.1.0/tests/test_smoke.py +16 -0
  62. django_blog_core-0.1.0/tests/test_views.py +73 -0
  63. django_blog_core-0.1.0/tests/urls.py +7 -0
  64. django_blog_core-0.1.0/tox.ini +13 -0
@@ -0,0 +1,52 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v6.0.0
4
+ hooks:
5
+ - id: check-added-large-files
6
+ - id: check-case-conflict
7
+ - id: check-json
8
+ - id: check-merge-conflict
9
+ - id: check-symlinks
10
+ - id: check-toml
11
+ - id: end-of-file-fixer
12
+ - id: trailing-whitespace
13
+ - repo: https://github.com/asottile/pyupgrade
14
+ rev: v3.21.2
15
+ hooks:
16
+ - id: pyupgrade
17
+ args: [--py36-plus]
18
+ - repo: https://github.com/psf/black-pre-commit-mirror
19
+ rev: 26.3.1
20
+ hooks:
21
+ - id: black
22
+ - repo: https://github.com/asottile/blacken-docs
23
+ rev: 1.20.0
24
+ hooks:
25
+ - id: blacken-docs
26
+ additional_dependencies:
27
+ - black>=22.12.0
28
+ - repo: https://github.com/pycqa/isort
29
+ rev: 8.0.1
30
+ hooks:
31
+ - id: isort
32
+ args: ["--profile", "black"]
33
+ - repo: https://github.com/PyCQA/flake8
34
+ rev: 7.3.0
35
+ hooks:
36
+ - id: flake8
37
+ additional_dependencies:
38
+ - flake8-pyproject
39
+ - flake8-bugbear
40
+ - flake8-comprehensions
41
+ - flake8-tidy-imports
42
+ - flake8-typing-imports
43
+ - repo: https://github.com/mgedmin/check-manifest
44
+ rev: "0.51"
45
+ hooks:
46
+ - id: check-manifest
47
+ args: [--no-build-isolation]
48
+ additional_dependencies:
49
+ - Django>=3.2
50
+ - build
51
+ - setuptools>=77
52
+ - wheel
@@ -0,0 +1,16 @@
1
+ =========
2
+ Changelog
3
+ =========
4
+
5
+ .. towncrier release notes start
6
+
7
+ django-blog-core 0.1.0 (2026-08-10)
8
+ ===================================
9
+
10
+ Features
11
+ --------
12
+
13
+ - Initial public release: multi-blog models (Blog, Section, Article),
14
+ ``published()`` manager, hookset, RSS/Atom feeds, ``publish_scheduled_articles``
15
+ management command, admin UX, list/detail templates, Markdown/sanitize extras,
16
+ and stubs for ``[search]``, ``[tags]``, ``[social]``, ``[images]``.
@@ -0,0 +1,2 @@
1
+ # Require review from Code Owners
2
+ * @dlrsp-dev @dlrsp-actions[bot]
@@ -0,0 +1,6 @@
1
+ # Contributing
2
+
3
+ 1. Use a virtualenv and `pip install -e ".[testing,linting]"`.
4
+ 2. Run `pytest` (or `tox -e py313-django52`).
5
+ 3. Add a towncrier fragment under `news/` for user-visible changes.
6
+ 4. Do not commit site-specific names into package code or docs.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2010-present DLRSP (https://dlrsp.org) and other contributors.
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.
@@ -0,0 +1,17 @@
1
+ include *.py
2
+ include *.rst
3
+ include *.md
4
+ include *.toml
5
+ include *.yaml
6
+ include *.yml
7
+ include *.cfg
8
+ include tox.ini
9
+ include LICENSE
10
+ include CODEOWNERS
11
+
12
+ recursive-include requirements *.in *.txt
13
+ recursive-exclude requirements *.py
14
+ recursive-include src *.py *.html *.css *.js *.po *.mo *.gif *.png *.txt *.json
15
+ recursive-include tests *.py
16
+ recursive-include news *.rst
17
+ recursive-exclude docs *
@@ -0,0 +1,173 @@
1
+ Metadata-Version: 2.4
2
+ Name: django-blog-core
3
+ Version: 0.1.0
4
+ Summary: Reusable multi-blog Django app: Blog, Section, Article with draft/schedule/publish, feeds, hookset, and optional Markdown/sanitize extras.
5
+ Author-email: DLRSP <dlrsp.dev@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/DLRSP/django-blog-core
8
+ Project-URL: Documentation, https://dlrsp.github.io/django-blog-core/
9
+ Project-URL: Repository, https://github.com/DLRSP/django-blog-core
10
+ Project-URL: Issues, https://github.com/DLRSP/django-blog-core/issues
11
+ Project-URL: Changelog, https://github.com/DLRSP/django-blog-core/blob/main/CHANGELOG.rst
12
+ Project-URL: Funding, https://github.com/sponsors/DLRSP
13
+ Keywords: django,blog,articles,cms,syndication,rss,atom,markdown,multi-blog
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Environment :: Web Environment
16
+ Classifier: Framework :: Django
17
+ Classifier: Framework :: Django :: 3.2
18
+ Classifier: Framework :: Django :: 4.2
19
+ Classifier: Framework :: Django :: 5.2
20
+ Classifier: Intended Audience :: Developers
21
+ Classifier: Operating System :: OS Independent
22
+ Classifier: Programming Language :: Python
23
+ Classifier: Programming Language :: Python :: 3
24
+ Classifier: Programming Language :: Python :: 3 :: Only
25
+ Classifier: Programming Language :: Python :: 3.10
26
+ Classifier: Programming Language :: Python :: 3.11
27
+ Classifier: Programming Language :: Python :: 3.12
28
+ Classifier: Programming Language :: Python :: 3.13
29
+ Classifier: Programming Language :: Python :: 3.14
30
+ Classifier: Topic :: Internet :: WWW/HTTP
31
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
32
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
33
+ Classifier: Topic :: Software Development :: Libraries
34
+ Requires-Python: >=3.10
35
+ Description-Content-Type: text/markdown
36
+ License-File: LICENSE
37
+ Requires-Dist: Django>=3.2
38
+ Provides-Extra: markdown
39
+ Requires-Dist: markdown>=3.5; extra == "markdown"
40
+ Provides-Extra: sanitize
41
+ Requires-Dist: bleach>=6.0; extra == "sanitize"
42
+ Provides-Extra: search
43
+ Provides-Extra: tags
44
+ Provides-Extra: social
45
+ Provides-Extra: images
46
+ Provides-Extra: all
47
+ Requires-Dist: markdown>=3.5; extra == "all"
48
+ Requires-Dist: bleach>=6.0; extra == "all"
49
+ Provides-Extra: testing
50
+ Requires-Dist: coverage; extra == "testing"
51
+ Requires-Dist: codecov; extra == "testing"
52
+ Requires-Dist: pytest; extra == "testing"
53
+ Requires-Dist: pytest-django; extra == "testing"
54
+ Requires-Dist: markdown>=3.5; extra == "testing"
55
+ Requires-Dist: bleach>=6.0; extra == "testing"
56
+ Provides-Extra: docs
57
+ Requires-Dist: mkdocs>=1.5; extra == "docs"
58
+ Requires-Dist: mkdocs-material>=9.0; extra == "docs"
59
+ Requires-Dist: pymdown-extensions>=10.0; extra == "docs"
60
+ Requires-Dist: mkdocs-git-revision-date-plugin>=2.0; extra == "docs"
61
+ Provides-Extra: linting
62
+ Requires-Dist: flake8; extra == "linting"
63
+ Requires-Dist: flake8-pyproject; extra == "linting"
64
+ Requires-Dist: flake8-bugbear; extra == "linting"
65
+ Requires-Dist: flake8-comprehensions; extra == "linting"
66
+ Requires-Dist: flake8-tidy-imports; extra == "linting"
67
+ Requires-Dist: flake8-typing-imports; extra == "linting"
68
+ Requires-Dist: pylint; extra == "linting"
69
+ Dynamic: license-file
70
+
71
+ # django-blog-core
72
+
73
+ [![CI/CD](https://github.com/DLRSP/django-blog-core/actions/workflows/ci.yaml/badge.svg)](https://github.com/DLRSP/django-blog-core/actions/workflows/ci.yaml)
74
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
75
+
76
+ Reusable **multi-blog** Django app: `Blog`, optional `Section`, and `Article`
77
+ with draft / scheduled / published / archived workflow, RSS + Atom feeds,
78
+ a Pinax-style **hookset**, secret preview URLs, and optional Markdown / HTML
79
+ sanitize extras.
80
+
81
+ > Status: **0.1.0** — publish-ready core. Extras `[search]`, `[tags]`,
82
+ > `[social]`, `[images]` are documented stubs.
83
+
84
+ ## Install
85
+
86
+ ```bash
87
+ pip install django-blog-core
88
+ pip install "django-blog-core[markdown]" # Markdown bodies
89
+ pip install "django-blog-core[sanitize]" # bleach HTML policy
90
+ pip install "django-blog-core[all]" # markdown + sanitize
91
+ ```
92
+
93
+ ## Quickstart
94
+
95
+ ```python
96
+ # settings.py
97
+ INSTALLED_APPS = [
98
+ # ...
99
+ "blog_core",
100
+ ]
101
+
102
+ BLOG_CORE = {
103
+ "PAGINATE_BY": 12,
104
+ "SANITIZE_HTML": True,
105
+ # "HOOKSET": "myapp.hooks.BlogHookSet",
106
+ }
107
+ # Or: BLOG_CORE_HOOKSET = "myapp.hooks.BlogHookSet"
108
+ ```
109
+
110
+ ```python
111
+ # urls.py
112
+ from django.urls import include, path
113
+
114
+ urlpatterns = [
115
+ path("blog/", include("blog_core.urls")),
116
+ ]
117
+ ```
118
+
119
+ ```bash
120
+ python manage.py migrate
121
+ python manage.py publish_scheduled_articles # cron / host scheduler
122
+ ```
123
+
124
+ Create a `Blog` and `Article` in admin. Public list/detail live at
125
+ `/blog/<blog-slug>/` and `/blog/<blog-slug>/<article-slug>/`. Feeds:
126
+
127
+ - `/blog/<blog-slug>/feed/rss/`
128
+ - `/blog/<blog-slug>/feed/atom/`
129
+
130
+ Preview drafts with the secret URL from the admin “Preview” column.
131
+
132
+ ### Public visibility
133
+
134
+ `Article.objects.published()` (alias `public()`) is the single source of truth:
135
+
136
+ `state == "published"` **and** `publish_at <= now`.
137
+
138
+ ### Hookset
139
+
140
+ Subclass `blog_core.hookset.DefaultBlogHookSet` to customize absolute URLs,
141
+ who may view non-public articles, body rendering, and feed titles — without
142
+ forking the package. Hooksets must not widen the public queryset.
143
+
144
+ ### HTML / Markdown safety
145
+
146
+ - Markdown → HTML via the `[markdown]` extra.
147
+ - HTML (and Markdown output) is sanitized with bleach when `[sanitize]` is
148
+ installed and `BLOG_CORE["SANITIZE_HTML"]` is true (default).
149
+ - Without bleach, HTML is escaped rather than passed through.
150
+ - Set `ALLOW_RAW_HTML = True` only if you accept XSS risk. See `docs/sanitize.md`.
151
+
152
+ ### Extras
153
+
154
+ | Extra | Purpose |
155
+ |-------|---------|
156
+ | `[markdown]` | Markdown body rendering |
157
+ | `[sanitize]` | bleach allow-list |
158
+ | `[search]` | stub — Haystack/`published()` index patterns |
159
+ | `[tags]` | stub — tagging integration |
160
+ | `[social]` | stub — share matrix |
161
+ | `[images]` | stub — media attachments |
162
+
163
+ ## Development
164
+
165
+ ```bash
166
+ pip install -e ".[testing]"
167
+ pytest
168
+ # or: tox -e py313-django52
169
+ ```
170
+
171
+ ## License
172
+
173
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,103 @@
1
+ # django-blog-core
2
+
3
+ [![CI/CD](https://github.com/DLRSP/django-blog-core/actions/workflows/ci.yaml/badge.svg)](https://github.com/DLRSP/django-blog-core/actions/workflows/ci.yaml)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
5
+
6
+ Reusable **multi-blog** Django app: `Blog`, optional `Section`, and `Article`
7
+ with draft / scheduled / published / archived workflow, RSS + Atom feeds,
8
+ a Pinax-style **hookset**, secret preview URLs, and optional Markdown / HTML
9
+ sanitize extras.
10
+
11
+ > Status: **0.1.0** — publish-ready core. Extras `[search]`, `[tags]`,
12
+ > `[social]`, `[images]` are documented stubs.
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ pip install django-blog-core
18
+ pip install "django-blog-core[markdown]" # Markdown bodies
19
+ pip install "django-blog-core[sanitize]" # bleach HTML policy
20
+ pip install "django-blog-core[all]" # markdown + sanitize
21
+ ```
22
+
23
+ ## Quickstart
24
+
25
+ ```python
26
+ # settings.py
27
+ INSTALLED_APPS = [
28
+ # ...
29
+ "blog_core",
30
+ ]
31
+
32
+ BLOG_CORE = {
33
+ "PAGINATE_BY": 12,
34
+ "SANITIZE_HTML": True,
35
+ # "HOOKSET": "myapp.hooks.BlogHookSet",
36
+ }
37
+ # Or: BLOG_CORE_HOOKSET = "myapp.hooks.BlogHookSet"
38
+ ```
39
+
40
+ ```python
41
+ # urls.py
42
+ from django.urls import include, path
43
+
44
+ urlpatterns = [
45
+ path("blog/", include("blog_core.urls")),
46
+ ]
47
+ ```
48
+
49
+ ```bash
50
+ python manage.py migrate
51
+ python manage.py publish_scheduled_articles # cron / host scheduler
52
+ ```
53
+
54
+ Create a `Blog` and `Article` in admin. Public list/detail live at
55
+ `/blog/<blog-slug>/` and `/blog/<blog-slug>/<article-slug>/`. Feeds:
56
+
57
+ - `/blog/<blog-slug>/feed/rss/`
58
+ - `/blog/<blog-slug>/feed/atom/`
59
+
60
+ Preview drafts with the secret URL from the admin “Preview” column.
61
+
62
+ ### Public visibility
63
+
64
+ `Article.objects.published()` (alias `public()`) is the single source of truth:
65
+
66
+ `state == "published"` **and** `publish_at <= now`.
67
+
68
+ ### Hookset
69
+
70
+ Subclass `blog_core.hookset.DefaultBlogHookSet` to customize absolute URLs,
71
+ who may view non-public articles, body rendering, and feed titles — without
72
+ forking the package. Hooksets must not widen the public queryset.
73
+
74
+ ### HTML / Markdown safety
75
+
76
+ - Markdown → HTML via the `[markdown]` extra.
77
+ - HTML (and Markdown output) is sanitized with bleach when `[sanitize]` is
78
+ installed and `BLOG_CORE["SANITIZE_HTML"]` is true (default).
79
+ - Without bleach, HTML is escaped rather than passed through.
80
+ - Set `ALLOW_RAW_HTML = True` only if you accept XSS risk. See `docs/sanitize.md`.
81
+
82
+ ### Extras
83
+
84
+ | Extra | Purpose |
85
+ |-------|---------|
86
+ | `[markdown]` | Markdown body rendering |
87
+ | `[sanitize]` | bleach allow-list |
88
+ | `[search]` | stub — Haystack/`published()` index patterns |
89
+ | `[tags]` | stub — tagging integration |
90
+ | `[social]` | stub — share matrix |
91
+ | `[images]` | stub — media attachments |
92
+
93
+ ## Development
94
+
95
+ ```bash
96
+ pip install -e ".[testing]"
97
+ pytest
98
+ # or: tox -e py313-django52
99
+ ```
100
+
101
+ ## License
102
+
103
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,44 @@
1
+ ---
2
+ site_name: django-blog-core
3
+ site_description: Reusable multi-blog Django app with feeds and hookset.
4
+ site_url: https://dlrsp.github.io/django-blog-core/
5
+ repo_url: https://github.com/DLRSP/django-blog-core
6
+ repo_name: DLRSP/django-blog-core
7
+ edit_uri: blob/main/docs/
8
+
9
+ theme:
10
+ name: material
11
+ features:
12
+ - navigation.sections
13
+ - navigation.top
14
+ - content.code.copy
15
+ palette:
16
+ - scheme: default
17
+ primary: teal
18
+ toggle:
19
+ icon: material/weather-night
20
+ name: Switch to dark mode
21
+ - scheme: slate
22
+ primary: teal
23
+ toggle:
24
+ icon: material/weather-sunny
25
+ name: Switch to light mode
26
+
27
+ markdown_extensions:
28
+ - admonition
29
+ - pymdownx.highlight
30
+ - pymdownx.superfences
31
+ - tables
32
+ - toc:
33
+ permalink: true
34
+
35
+ plugins:
36
+ - search
37
+ - git-revision-date
38
+
39
+ nav:
40
+ - Home: index.md
41
+ - Getting started: getting-started.md
42
+ - Hookset: hookset.md
43
+ - Sanitize: sanitize.md
44
+ - Extras: extras.md
@@ -0,0 +1,211 @@
1
+ [build-system]
2
+ requires = [
3
+ "setuptools >= 77",
4
+ "wheel",
5
+ ]
6
+ build-backend = "setuptools.build_meta"
7
+
8
+ [project]
9
+ name = "django-blog-core"
10
+ description = "Reusable multi-blog Django app: Blog, Section, Article with draft/schedule/publish, feeds, hookset, and optional Markdown/sanitize extras."
11
+ authors = [
12
+ { name = "DLRSP", email = "dlrsp.dev@gmail.com" },
13
+ ]
14
+ requires-python = ">=3.10"
15
+ dynamic = ["version"]
16
+ readme = "README.md"
17
+ license = "MIT"
18
+ license-files = ["LICENSE"]
19
+ keywords = [
20
+ "django",
21
+ "blog",
22
+ "articles",
23
+ "cms",
24
+ "syndication",
25
+ "rss",
26
+ "atom",
27
+ "markdown",
28
+ "multi-blog",
29
+ ]
30
+ classifiers = [
31
+ "Development Status :: 4 - Beta",
32
+ "Environment :: Web Environment",
33
+ "Framework :: Django",
34
+ "Framework :: Django :: 3.2",
35
+ "Framework :: Django :: 4.2",
36
+ "Framework :: Django :: 5.2",
37
+ "Intended Audience :: Developers",
38
+ "Operating System :: OS Independent",
39
+ "Programming Language :: Python",
40
+ "Programming Language :: Python :: 3",
41
+ "Programming Language :: Python :: 3 :: Only",
42
+ "Programming Language :: Python :: 3.10",
43
+ "Programming Language :: Python :: 3.11",
44
+ "Programming Language :: Python :: 3.12",
45
+ "Programming Language :: Python :: 3.13",
46
+ "Programming Language :: Python :: 3.14",
47
+ "Topic :: Internet :: WWW/HTTP",
48
+ "Topic :: Internet :: WWW/HTTP :: Dynamic Content",
49
+ "Topic :: Software Development :: Libraries :: Application Frameworks",
50
+ "Topic :: Software Development :: Libraries",
51
+ ]
52
+ dependencies = [
53
+ "Django>=3.2",
54
+ ]
55
+
56
+ [project.urls]
57
+ Homepage = "https://github.com/DLRSP/django-blog-core"
58
+ Documentation = "https://dlrsp.github.io/django-blog-core/"
59
+ Repository = "https://github.com/DLRSP/django-blog-core"
60
+ Issues = "https://github.com/DLRSP/django-blog-core/issues"
61
+ Changelog = "https://github.com/DLRSP/django-blog-core/blob/main/CHANGELOG.rst"
62
+ Funding = "https://github.com/sponsors/DLRSP"
63
+
64
+ [project.optional-dependencies]
65
+ markdown = [
66
+ "markdown>=3.5",
67
+ ]
68
+ sanitize = [
69
+ "bleach>=6.0",
70
+ ]
71
+ search = []
72
+ tags = []
73
+ social = []
74
+ images = []
75
+ all = [
76
+ "markdown>=3.5",
77
+ "bleach>=6.0",
78
+ ]
79
+ testing = [
80
+ "coverage",
81
+ "codecov",
82
+ "pytest",
83
+ "pytest-django",
84
+ "markdown>=3.5",
85
+ "bleach>=6.0",
86
+ ]
87
+ docs = [
88
+ "mkdocs>=1.5",
89
+ "mkdocs-material>=9.0",
90
+ "pymdown-extensions>=10.0",
91
+ "mkdocs-git-revision-date-plugin>=2.0",
92
+ ]
93
+ linting = [
94
+ "flake8",
95
+ "flake8-pyproject",
96
+ "flake8-bugbear",
97
+ "flake8-comprehensions",
98
+ "flake8-tidy-imports",
99
+ "flake8-typing-imports",
100
+ "pylint",
101
+ ]
102
+
103
+ [tool.setuptools]
104
+ package-dir = { "" = "src" }
105
+ include-package-data = true
106
+ zip-safe = false
107
+
108
+ [tool.setuptools.dynamic]
109
+ version = { attr = "blog_core.__version__" }
110
+
111
+ [tool.setuptools.packages.find]
112
+ where = ["src"]
113
+
114
+ [tool.setuptools.data-files]
115
+ "share/django-blog-core/requirements" = [
116
+ "requirements/py310-django42.txt",
117
+ "requirements/py310-django52.txt",
118
+ "requirements/py311-django42.txt",
119
+ "requirements/py311-django52.txt",
120
+ "requirements/py312-django42.txt",
121
+ "requirements/py312-django52.txt",
122
+ "requirements/py313-django52.txt",
123
+ "requirements/py314-django52.txt",
124
+ ]
125
+
126
+ [tool.distutils.bdist_wheel]
127
+ universal = false
128
+
129
+ [tool.black]
130
+ line-length = 80
131
+ target-version = ['py311']
132
+
133
+ [tool.isort]
134
+ profile = "black"
135
+
136
+ [tool.check-manifest]
137
+ ignore = [
138
+ "AGENTS.md",
139
+ ]
140
+
141
+ [tool.flake8]
142
+ max-line-length = 80
143
+ select = ["E", "F", "W", "B", "B950", "C", "I", "TYP"]
144
+ ignore = ["E203", "E501", "W503", "B950"]
145
+ per-file-ignores = [
146
+ "**/migrations/*:B950",
147
+ ]
148
+
149
+ [tool.mypy]
150
+ check_untyped_defs = true
151
+ disallow_any_generics = true
152
+ disallow_incomplete_defs = true
153
+ disallow_untyped_defs = true
154
+ mypy_path = "src/"
155
+ no_implicit_optional = true
156
+ show_error_codes = true
157
+ warn_unreachable = true
158
+ warn_unused_ignores = true
159
+
160
+ [[tool.mypy.overrides]]
161
+ module = "tests.*"
162
+ allow_untyped_defs = true
163
+
164
+ [tool.pytest.ini_options]
165
+ addopts = """\
166
+ --strict-config
167
+ --strict-markers
168
+ --ds=tests.settings
169
+ """
170
+ django_find_project = false
171
+ pythonpath = ["src"]
172
+
173
+ [tool.coverage.paths]
174
+ source = ["src", ".tox/*/site-packages"]
175
+
176
+ [tool.coverage.run]
177
+ branch = true
178
+ source = ["blog_core"]
179
+
180
+ [tool.coverage.report]
181
+ show_missing = true
182
+
183
+ [tool.towncrier]
184
+ package = "blog_core"
185
+ package_dir = "src"
186
+ filename = "CHANGELOG.rst"
187
+ directory = "news/"
188
+ version = "0.1.0"
189
+ issue_format = "`#{issue} <https://github.com/DLRSP/django-blog-core/issues/{issue}>`_"
190
+ type = [
191
+ { name = "Process", directory = "process", showcontent = true },
192
+ { name = "Deprecations and Removals", directory = "removal", showcontent = true },
193
+ { name = "Features", directory = "feature", showcontent = true },
194
+ { name = "Bug Fixes", directory = "bugfix", showcontent = true },
195
+ { name = "Vendored Libraries", directory = "vendor", showcontent = true },
196
+ { name = "Improved Documentation", directory = "doc", showcontent = true },
197
+ { name = "Trivial Changes", directory = "trivial", showcontent = false },
198
+ ]
199
+
200
+ [tool.bumpversion]
201
+ current_version = "0.1.0"
202
+ commit = true
203
+ tag = true
204
+ allow_dirty = true
205
+
206
+ [[tool.bumpversion.files]]
207
+ filename = "./src/blog_core/__init__.py"
208
+ [[tool.bumpversion.files]]
209
+ filename = "pyproject.toml"
210
+ search = 'current_version = "{current_version}"'
211
+ replace = 'current_version = "{new_version}"'
@@ -0,0 +1,22 @@
1
+ #
2
+ # This file is autogenerated by pip-compile with Python 3.10
3
+ # by the following command:
4
+ #
5
+ # pip-compile --allow-unsafe --generate-hashes --output-file=requirements/py310-django42.txt requirements/runtime.in
6
+ #
7
+ asgiref==3.11.1 \
8
+ --hash=sha256:5f184dc43b7e763efe848065441eac62229c9f7b0475f41f80e207a114eda4ce \
9
+ --hash=sha256:e8667a091e69529631969fd45dc268fa79b99c92c5fcdda727757e52146ec133
10
+ # via django
11
+ django==4.2.30 \
12
+ --hash=sha256:4d07aaf1c62f9984842b67c2874ebbf7056a17be253860299b93ae1881faad65 \
13
+ --hash=sha256:4ebc7a434e3819db6cf4b399fb5b3f536310a30e8486f08b66886840be84b37c
14
+ # via -r requirements/runtime.in
15
+ sqlparse==0.5.5 \
16
+ --hash=sha256:12a08b3bf3eec877c519589833aed092e2444e68240a3577e8e26148acc7b1ba \
17
+ --hash=sha256:e20d4a9b0b8585fdf63b10d30066c7c94c5d7a7ec47c889a2d83a3caa93ff28e
18
+ # via django
19
+ typing-extensions==4.15.0 \
20
+ --hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \
21
+ --hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548
22
+ # via asgiref