diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 950b500..4d3e8df 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -17,38 +17,28 @@ jobs:
python: ["3"]
os: ["ubuntu-latest"]
include:
- - {python: "3.7", os: "ubuntu-22.04"}
- - {python: "3.8", os: "ubuntu-22.04"}
- {python: "3.9", os: "ubuntu-22.04"}
- {python: "3.10", os: "ubuntu-22.04"}
- {python: "3.11", os: "ubuntu-22.04"}
- {python: "3.12", os: "ubuntu-22.04"}
+ - {python: "3.13", os: "ubuntu-24.04"}
+ - {python: "pypy3.10", os: "ubuntu-24.04"}
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: "Set up Python ${{ matrix.python }}"
- uses: actions/setup-python@v3
+ uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- name: "Install dependencies"
run: |
- # python -m pip install --upgrade pip
python -m pip install pytest
- python -m pip install mock
- python -m pip install flake8
- python -m pip install importlib_metadata
- python -m pip install "setuptools>=62"
- python -m pip install wheel
python -m pip install build
- - name: "Lint with flake8"
- run: |
- # stop the build if there are Python syntax errors or undefined names
- flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
- flake8 . --count --exit-zero --max-complexity=10 --max-line-length=80 --statistics
+ python -m pip install "setuptools>=75"
- name: "Build and test"
run: |
python -m build --no-isolation
pip install dist/dominate*.tar.gz
- pytest
+ pytest --ignore=tests/community
- name: Coveralls
env:
COVERAGE_RCFILE: ".github/workflows/.coveragerc"
@@ -56,5 +46,5 @@ jobs:
run: |
python -m pip install coverage
python -m pip install coveralls
- coverage run --source=dominate -m pytest
+ coverage run --source=dominate -m pytest --ignore=tests/community
python -m coveralls --service=github || true
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..9edd348
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,34 @@
+
+# 1. Welcome additions
+
+Anything that is part of the official HTML spec is likely welcome.
+
+Common patterns of web development, or ease-of-use features are welcome, so long as they are general and are likely to be useful to a broad group and not targetting any specific implimentation.
+
+## 1.1. Testing
+
+All PRs must have 100% test coverage of new code.
+
+New features should include example usage, including motivations.
+
+
+
+# 2. Not interested
+
+For exceptions to these, see #Community
+
+## 2.2. No 3rd party dependencies
+
+Do not add 3rd party dependencies.
+
+## 2.3. No 3rd party integrations
+
+I am not interested in maintaining integrations with a bunch of random JS/web frameworks/libraries. (i.e. HTMX, Flask, Unpoly, whatever)
+
+
+# 3. Community Packages
+
+If you wish to add a feature that would otherwise be disallowed by the above, you can make a community package. See `community/htmx.py` for a trivial example.
+
+Community packages must not be referenced from the main library, and must not do anything unless explicitly imported.
+
diff --git a/MANIFEST.in b/MANIFEST.in
index 11521c7..175a3fa 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,7 +1,7 @@
include README.md
include LICENSE.txt
+include CONTRIBUTING.md
include pyproject.toml
-include setup/setup.py
recursive-include tests *
global-exclude __pycache__
global-exclude *.pyc
diff --git a/Makefile b/Makefile
index 1fe0cc0..1518ac4 100644
--- a/Makefile
+++ b/Makefile
@@ -1,11 +1,8 @@
test:
- -python2 -m pytest .
- python3 -m pytest .
+ python3 -m pytest . --ignore=tests/community
-publish_old: clean test
- python3 setup/setup.py sdist
- python3 setup/setup.py bdist_wheel
- python3 -m twine upload dist/*
+test-community:
+ python3 -m pytest .
publish: clean test
python3 -m build --no-isolation
diff --git a/README.md b/README.md
index 8a21083..78c5eb2 100644
--- a/README.md
+++ b/README.md
@@ -556,7 +556,7 @@ print(d)
Embedding HTML
--------------
-If you need to embed a node of pre-formed HTML coming from a library such as markdown or the like, you can avoid escaped HTML by using the raw method from the dominate.util package:
+If you need to embed a node of pre-formed HTML coming from a library such as markdown or the like you can avoid escaped HTML by using the raw method from the dominate.util package:
```
from dominate.util import raw
@@ -564,7 +564,7 @@ from dominate.util import raw
td(raw('Example'))
```
-Without the raw call, this code would render escaped HTML with lt, etc.
+Without the raw call, this code would render escaped HTML with lt, etc. The behavior of the previous block of code is the same as `td_element.innerHTML="Example"` in JavaScript.
SVG
diff --git a/dominate/__init__.py b/dominate/__init__.py
index 50668cb..becc617 100644
--- a/dominate/__init__.py
+++ b/dominate/__init__.py
@@ -1,4 +1,2 @@
-from ._version import __version__
-version = __version__
-
+from .version import __version__, version
from .document import document
diff --git a/dominate/_version.py b/dominate/_version.py
deleted file mode 100644
index b03f5b5..0000000
--- a/dominate/_version.py
+++ /dev/null
@@ -1 +0,0 @@
-__version__ = '2.9.1'
diff --git a/dominate/community/htmx.py b/dominate/community/htmx.py
new file mode 100644
index 0000000..79c70b1
--- /dev/null
+++ b/dominate/community/htmx.py
@@ -0,0 +1,12 @@
+
+from .. import tags
+
+class HtmxTag:
+ @classmethod
+ def clean_attribute(cls, attribute):
+ attribute = super().clean_attribute(attribute)
+ if attribute.startswith('hx_'):
+ attribute = attribute.replace('_', '-')
+ return attribute
+
+tags.html_tag.__bases__ = (HtmxTag,) + tags.html_tag.__bases__
diff --git a/dominate/dom_tag.py b/dominate/dom_tag.py
index 44ca8ba..b3becf5 100644
--- a/dominate/dom_tag.py
+++ b/dominate/dom_tag.py
@@ -23,7 +23,7 @@
from collections import defaultdict, namedtuple
from functools import wraps
import threading
-from asyncio import get_event_loop
+from asyncio import get_running_loop
from uuid import uuid4
from contextvars import ContextVar
@@ -71,7 +71,7 @@ def _get_thread_context():
context.append(("greenlet", greenlet.getcurrent()))
try:
- if get_event_loop().is_running():
+ if get_running_loop().is_running():
# Only add this extra information if we are actually in a running event loop
context.append(("async", _get_async_context_id()))
# A runtime error is raised if there is no async loop...
@@ -441,7 +441,7 @@ def clean_attribute(attribute):
}.get(attribute, attribute)
# Workaround for Python's reserved words
- if attribute[0] == '_':
+ if attribute[0] == '_' and len(attribute) > 1:
attribute = attribute[1:]
# Workaround for dash
diff --git a/dominate/version.py b/dominate/version.py
new file mode 100644
index 0000000..7b8a4b1
--- /dev/null
+++ b/dominate/version.py
@@ -0,0 +1 @@
+version = __version__ = '3.0.0'
diff --git a/pyproject.toml b/pyproject.toml
index 8aadde0..cb8f2d2 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,7 +1,3 @@
-[build-system]
-requires = ["setuptools>=62"]
-build-backend = "setuptools.build_meta"
-
[project]
name = "dominate"
description = "Dominate is a Python library for creating and manipulating HTML documents using an elegant DOM API."
@@ -10,7 +6,7 @@ authors = [
{name = "Tom Flanagan", email = "tom@zkpq.ca"},
{name = "Jake Wharton"},
]
-requires-python = ">=3.4"
+requires-python = ">=3.9"
keywords = ["framework", "templating", "template", "html", "xhtml", "python", "html5"]
license = {text = "LGPL-3.0-or-newer"}
classifiers = [
@@ -19,12 +15,11 @@ classifiers = [
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
- "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",
+ "Programming Language :: Python :: 3.13",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
"Topic :: Software Development :: Libraries :: Python Modules",
@@ -36,8 +31,13 @@ dynamic = ["version"]
Homepage = "https://github.com/Knio/dominate"
Source = "https://github.com/Knio/dominate"
+
+[build-system]
+requires = ["setuptools>=75"]
+build-backend = "setuptools.build_meta"
+
[tool.setuptools]
packages = ["dominate"]
[tool.setuptools.dynamic]
-version = {attr = "dominate._version.__version__"}
+version = {attr = "dominate.version.version"}
diff --git a/setup/setup.py b/setup/setup.py
deleted file mode 100644
index 31d6c48..0000000
--- a/setup/setup.py
+++ /dev/null
@@ -1,63 +0,0 @@
-__license__ = '''
-This file is part of Dominate.
-
-Dominate is free software: you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as
-published by the Free Software Foundation, either version 3 of
-the License, or (at your option) any later version.
-
-Dominate is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General
-Public License along with dominate. If not, see
-
goodbye cruel world
''' - + assert p('my 1', sup('st'), ' PR').render() == \ '''my 1st PR
''' diff --git a/tests/test_svg.py b/tests/test_svg.py index e5bbec3..6e06b49 100644 --- a/tests/test_svg.py +++ b/tests/test_svg.py @@ -1,9 +1,9 @@ +import sys + import dominate.svg from dominate.tags import * from dominate.svg import * -import pytest - def base(): return svg( @@ -14,7 +14,10 @@ def base(): def get_expected(func): - return func.__doc__.replace('\n ', '\n').strip() + doc = func.__doc__ + if sys.version_info < (3, 13): + doc = doc.replace('\n ', '\n') + return doc.strip() def output_test(func):