build: move to PEP517 and pyproject.toml, drop support for Py3.6 and Py3.7 (#417)

* chore: move to pyproject.toml

* chore: forced to drop Python 3.6 to upgrade

* chore: drop support for Python 3.6 and 3.7

* chore: remove old references to py36/py37

* chore: remove setup.py, replaced by pyproject.toml
This commit is contained in:
Gabriel Dugny 2024-03-31 19:20:35 +02:00 committed by GitHub
parent 9aa446acc8
commit 84db2b7314
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 94 additions and 76 deletions

View file

@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
strategy: strategy:
matrix: matrix:
python-version: ['3.6', '3.7', '3.8', '3.9', '3.10', '3.11', '3.12'] python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -23,4 +23,4 @@ jobs:
python -m pip install --upgrade pip python -m pip install --upgrade pip
python -m pip install tox tox-gh-actions python -m pip install tox tox-gh-actions
- name: Run tests - name: Run tests
run: tox run: tox

View file

@ -138,12 +138,10 @@ Read on to find out how to build your first component!
## Compatiblity ## Compatiblity
Django-components supports all <a href="https://docs.djangoproject.com/en/dev/faq/install/#what-python-version-can-i-use-with-django">officially supported versions</a> of Django and Python. Django-components supports all supported combinations versions of [Django](https://docs.djangoproject.com/en/dev/faq/install/#what-python-version-can-i-use-with-django) and [Python](https://devguide.python.org/versions/#versions).
| Python version | Django version | | Python version | Django version |
|----------------|--------------------------| |----------------|--------------------------|
| 3.6 | 3.2 |
| 3.7 | 3.2 |
| 3.8 | 3.2, 4.0, 4.1, 4.2 | | 3.8 | 3.2, 4.0, 4.1, 4.2 |
| 3.9 | 3.2, 4.0, 4.1, 4.2 | | 3.9 | 3.2, 4.0, 4.1, 4.2 |
| 3.10 | 3.2, 4.0, 4.1, 4.2, 5.0 | | 3.10 | 3.2, 4.0, 4.1, 4.2, 5.0 |
@ -255,7 +253,7 @@ Components can also be defined in a single file, which is useful for small compo
```python ```python
# In a file called [project root]/components/calendar.py # In a file called [project root]/components/calendar.py
from django_components import component from django_components import component
from django_components import types as t from django_components import types as t
@component.register("calendar") @component.register("calendar")
class Calendar(component.Component): class Calendar(component.Component):
@ -263,16 +261,16 @@ class Calendar(component.Component):
return { return {
"date": date, "date": date,
} }
template: t.django_html = """ template: t.django_html = """
<div class="calendar-component">Today's date is <span>{{ date }}</span></div> <div class="calendar-component">Today's date is <span>{{ date }}</span></div>
""" """
css: t.css = """ css: t.css = """
.calendar-component { width: 200px; background: pink; } .calendar-component { width: 200px; background: pink; }
.calendar-component span { font-weight: bold; } .calendar-component span { font-weight: bold; }
""" """
js: t.js = """ js: t.js = """
(function(){ (function(){
if (document.querySelector(".calendar-component")) { if (document.querySelector(".calendar-component")) {
@ -284,7 +282,7 @@ class Calendar(component.Component):
This makes it easy to create small components without having to create a separate template, CSS, and JS file. This makes it easy to create small components without having to create a separate template, CSS, and JS file.
Note that the `t.django_html`, `t.css`, and `t.js` types are used to specify the type of the template, CSS, and JS files, respectively. This is not necessary, but if you're using VSCode with the [Python Inline Source Syntax Highlighting](https://marketplace.visualstudio.com/items?itemName=samwillis.python-inline-source) extension, it will give you syntax highlighting for the template, CSS, and JS. Note that the `t.django_html`, `t.css`, and `t.js` types are used to specify the type of the template, CSS, and JS files, respectively. This is not necessary, but if you're using VSCode with the [Python Inline Source Syntax Highlighting](https://marketplace.visualstudio.com/items?itemName=samwillis.python-inline-source) extension, it will give you syntax highlighting for the template, CSS, and JS.
## Using slots in templates ## Using slots in templates
@ -416,7 +414,7 @@ This is fine too:
_New in version 0.34_ _New in version 0.34_
Components can now be used as views. To do this, `Component` subclasses Django's `View` class. This means that you can use all of the [methods](https://docs.djangoproject.com/en/5.0/ref/class-based-views/base/#view) of `View` in your component. For example, you can override `get` and `post` to handle GET and POST requests, respectively. Components can now be used as views. To do this, `Component` subclasses Django's `View` class. This means that you can use all of the [methods](https://docs.djangoproject.com/en/5.0/ref/class-based-views/base/#view) of `View` in your component. For example, you can override `get` and `post` to handle GET and POST requests, respectively.
In addition, `Component` now has a `render_to_response` method that renders the component template based on the provided context and slots' data and returns an `HttpResponse` object. In addition, `Component` now has a `render_to_response` method that renders the component template based on the provided context and slots' data and returns an `HttpResponse` object.
@ -428,7 +426,7 @@ from django_components import component
@component.register("calendar") @component.register("calendar")
class Calendar(component.Component): class Calendar(component.Component):
template = """ template = """
<div class="calendar-component"> <div class="calendar-component">
<div class="header"> <div class="header">
@ -439,7 +437,7 @@ class Calendar(component.Component):
</div> </div>
</div> </div>
""" """
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
context = { context = {
"date": request.GET.get("date", "2020-06-06"), "date": request.GET.get("date", "2020-06-06"),
@ -455,7 +453,7 @@ Then, to use this component as a view, you should create a `urls.py` file in you
```python ```python
# In a file called [project root]/components/urls.py # In a file called [project root]/components/urls.py
from django.urls import path from django.urls import path
from calendar import Calendar from calendar import Calendar
urlpatterns = [ urlpatterns = [
path("calendar/", Calendar.as_view()), path("calendar/", Calendar.as_view()),
@ -817,14 +815,12 @@ pytest
The library is also tested across many versions of Python and Django. To run tests that way: The library is also tested across many versions of Python and Django. To run tests that way:
```sh ```sh
pyenv install -s 3.6
pyenv install -s 3.7
pyenv install -s 3.8 pyenv install -s 3.8
pyenv install -s 3.9 pyenv install -s 3.9
pyenv install -s 3.10 pyenv install -s 3.10
pyenv install -s 3.11 pyenv install -s 3.11
pyenv install -s 3.12 pyenv install -s 3.12
pyenv local 3.6 3.7 3.8 3.9 3.10 3.11 3.12 pyenv local 3.8 3.9 3.10 3.11 3.12
tox -p tox -p
``` ```

View file

@ -1,3 +1,48 @@
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[project]
name = "django_components"
version = "0.63"
requires-python = ">=3.8, <4.0"
description = "A way to create simple reusable template components in Django."
keywords = ["django", "components", "css", "js", "html"]
readme = "README.md"
authors = [
{name = "Emil Stenström", email = "emil@emilstenstrom.se"},
]
classifiers = [
"Framework :: Django",
"Framework :: Django :: 3.2",
"Framework :: Django :: 4.0",
"Framework :: Django :: 4.1",
"Framework :: Django :: 4.2",
"Framework :: Django :: 5.0",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
dependencies = [
'Django>=3.2',
]
license = {text = "MIT"}
[project.urls]
Homepage = "https://github.com/EmilStenstrom/django-components/"
[tool.setuptools.packages.find]
where = ["src"]
include = ["django_components*"]
exclude = ["django_components.tests*"]
namespaces = false
[tool.black] [tool.black]
line-length = 119 line-length = 119
include = '\.pyi?$' include = '\.pyi?$'

View file

@ -8,6 +8,35 @@ Version = Tuple[int, ...]
VersionMapping = Dict[Version, List[Version]] VersionMapping = Dict[Version, List[Version]]
def cut_by_content(content: str, cut_from: str, cut_to: str):
return content.split(cut_from)[1].split(cut_to)[0]
def keys_from_content(content: str):
return re.findall(r"<td>(.*?)</td>", content)
def get_python_supported_version(url: str) -> list[Version]:
with request.urlopen(url) as response:
response_content = response.read()
content = response_content.decode("utf-8")
def parse_supported_versions(content: str) -> list[Version]:
content = cut_by_content(
content,
'<section id="supported-versions">',
"</table>",
)
content = cut_by_content(content, "<tbody>", "</tbody>")
lines = content.split("<tr ")
versions = [match[0] for line in lines[1:] if (match := re.findall(r"<p>([\d.]+)</p>", line))]
versions_tuples = [version_to_tuple(version) for version in versions]
return versions_tuples
return parse_supported_versions(content)
def get_supported_versions(url: str): def get_supported_versions(url: str):
with request.urlopen(url) as response: with request.urlopen(url) as response:
response_content = response.read() response_content = response.read()
@ -15,12 +44,6 @@ def get_supported_versions(url: str):
content = response_content.decode("utf-8") content = response_content.decode("utf-8")
def parse_supported_versions(content): def parse_supported_versions(content):
def cut_by_content(content, cut_from, cut_to):
return content.split(cut_from)[1].split(cut_to)[0]
def keys_from_content(content):
return re.findall(r"<td>(.*?)</td>", content)
content = cut_by_content( content = cut_by_content(
content, content,
'<span id="what-python-version-can-i-use-with-django">', '<span id="what-python-version-can-i-use-with-django">',
@ -169,7 +192,7 @@ def build_pyenv(python_to_django: VersionMapping):
def build_ci_python_versions(python_to_django: Dict[str, str]): def build_ci_python_versions(python_to_django: Dict[str, str]):
# Outputs python-version: ['3.6', '3.7', '3.8', '3.9', '3.10', '3.11'] # Outputs python-version, like: ['3.8', '3.9', '3.10', '3.11', '3.12']
lines = [ lines = [
f"'{env_format(python_version, divider='.')}'" for python_version, django_versions in python_to_django.items() f"'{env_format(python_version, divider='.')}'" for python_version, django_versions in python_to_django.items()
] ]
@ -178,11 +201,14 @@ def build_ci_python_versions(python_to_django: Dict[str, str]):
def main(): def main():
active_python = get_python_supported_version("https://devguide.python.org/versions/")
django_to_python = get_supported_versions("https://docs.djangoproject.com/en/dev/faq/install/") django_to_python = get_supported_versions("https://docs.djangoproject.com/en/dev/faq/install/")
latest_version = get_latest_version("https://www.djangoproject.com/download/") latest_version = get_latest_version("https://www.djangoproject.com/download/")
python_to_django = build_python_to_django(django_to_python, latest_version) python_to_django = build_python_to_django(django_to_python, latest_version)
python_to_django = dict(filter(lambda item: item[0] in active_python, python_to_django.items()))
tox_envlist = build_tox_envlist(python_to_django) tox_envlist = build_tox_envlist(python_to_django)
print("Add this to tox.ini:\n") print("Add this to tox.ini:\n")
print("[tox]") print("[tox]")
@ -200,7 +226,7 @@ def main():
print() print()
print() print()
print("Add this to setup.py:\n") print("Add this to pyproject.toml:\n")
pypi_classifiers = build_pypi_classifiers(python_to_django) pypi_classifiers = build_pypi_classifiers(python_to_django)
print(pypi_classifiers) print(pypi_classifiers)
print() print()

View file

@ -1,43 +0,0 @@
# -*- coding: utf-8 -*-
import os
from setuptools import find_packages, setup
VERSION = "0.63"
setup(
name="django_components",
packages=find_packages(where="src", exclude=["tests", "tests.*"]),
package_dir={"": "src"},
package_data={
"django_components": ["py.typed"],
},
version=VERSION,
description="A way to create simple reusable template components in Django.",
long_description=open(os.path.join(os.path.dirname(__file__), "README.md"), encoding="utf8").read(),
long_description_content_type="text/markdown",
author="Emil Stenström",
author_email="emil@emilstenstrom.se",
url="https://github.com/EmilStenstrom/django-components/",
install_requires=["Django>=3.2"],
license="MIT",
keywords=["django", "components", "css", "js", "html"],
classifiers=[
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Framework :: Django :: 3.2",
"Framework :: Django :: 4.0",
"Framework :: Django :: 4.1",
"Framework :: Django :: 4.2",
"Framework :: Django :: 5.0",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Operating System :: OS Independent",
"Framework :: Django",
],
)

10
tox.ini
View file

@ -1,10 +1,9 @@
# This library strives to support the same versions of django and python that django supports: # This library strives to support all officially supported combinations of Python and Django:
# https://docs.djangoproject.com/en/dev/faq/install/#what-python-version-can-i-use-with-django # https://docs.djangoproject.com/en/dev/faq/install/#what-python-version-can-i-use-with-django
# https://devguide.python.org/versions/#versions
[tox] [tox]
envlist = envlist =
py36-django{32}
py37-django{32}
py38-django{32,40,41,42} py38-django{32,40,41,42}
py39-django{32,40,41,42} py39-django{32,40,41,42}
py310-django{32,40,41,42,50} py310-django{32,40,41,42,50}
@ -14,14 +13,9 @@ envlist =
isort isort
coverage coverage
mypy mypy
requires = virtualenv<20.22.0
# https://tox.wiki/en/latest/faq.html#testing-end-of-life-python-versions
[gh-actions] [gh-actions]
python = python =
3.6: py36-django{32}
3.7: py37-django{32}
3.8: py38-django{32,40,41,42} 3.8: py38-django{32,40,41,42}
3.9: py39-django{32,40,41,42} 3.9: py39-django{32,40,41,42}
3.10: py310-django{32,40,41,42,50} 3.10: py310-django{32,40,41,42,50}