From bb845a48d697e071cf16e5d903c4621ceabfe8f1 Mon Sep 17 00:00:00 2001 From: Dylan Verheul Date: Sat, 7 Dec 2019 09:35:02 +0100 Subject: [PATCH] Prepare release 1.1.0 (#185) * Prepare release 1.1.0 - Update default Bootstrap to v4.3.1 - Add support for Python 3.8, Django 3 and Django master - Switch to Django `manage.py` for test running - Update Makefile commands - Update tox configuration - Use correct license (BSD-3-Clause) - Fix typo's in docstrings - Update Travis configuration - Drop MANIFEST.in, use setuptools_scm - Stop using _version.py, use git tags for versioning - Fixed issues with labels and input (#174 and #181) --- .coveragerc | 6 - .gitignore | 1 + .travis.yml | 27 +-- CONTRIBUTING.rst | 7 +- HISTORY.rst | 14 ++ LICENSE | 44 ++-- MANIFEST.in | 10 - Makefile | 30 +-- docs/Makefile | 177 ---------------- docs/conf.py | 231 +-------------------- docs/index.rst | 7 +- docs/make.bat | 242 ---------------------- docs/requirements.txt | 3 + example/app/forms.py | 2 +- manage.py | 10 + requirements.txt | 29 ++- runtests.py | 105 ---------- setup.py | 21 +- src/bootstrap4/__init__.py | 1 - src/bootstrap4/_version.py | 1 - src/bootstrap4/bootstrap.py | 14 +- src/bootstrap4/components.py | 2 +- src/bootstrap4/renderers.py | 19 +- src/bootstrap4/templatetags/bootstrap4.py | 26 +-- src/bootstrap4/utils.py | 11 +- src/bootstrap4/widgets.py | 10 +- tests/app/__init__.py | 0 tests/app/settings.py | 53 +++++ tests/{ => app}/urls.py | 0 tests/test_templatetags.py | 16 +- tests/test_version.py | 9 - tests/utils.py | 14 ++ tox.ini | 66 +++--- 33 files changed, 273 insertions(+), 935 deletions(-) delete mode 100644 .coveragerc delete mode 100644 MANIFEST.in delete mode 100644 docs/Makefile delete mode 100644 docs/make.bat create mode 100644 docs/requirements.txt create mode 100755 manage.py delete mode 100644 runtests.py delete mode 100644 src/bootstrap4/_version.py create mode 100644 tests/app/__init__.py create mode 100644 tests/app/settings.py rename tests/{ => app}/urls.py (100%) delete mode 100644 tests/test_version.py diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 36ea56b5..00000000 --- a/.coveragerc +++ /dev/null @@ -1,6 +0,0 @@ -[run] -source = - bootstrap4 - -[html] -directory = reports/htmlcov diff --git a/.gitignore b/.gitignore index 4f2896d6..59f056a3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ *.so # Packages +.eggs *.egg *.egg-info dist diff --git a/.travis.yml b/.travis.yml index 27c99f46..2ccefd79 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,20 @@ -dist: xenial +dist: bionic +language: python + addons: - postgresql: "9.6" + postgresql: 9.6 apt: packages: - - postgresql-9.6-postgis-2.3 -language: python -sudo: false -cache: pip + - postgresql-9.6-postgis-2.5 + +services: + - postgresql + python: - - "3.7" - - "3.6" - - "3.5" -install: pip install tox-travis coverage coveralls + - "3.5" + - "3.6" + - "3.7" + - "3.8" + +install: pip install tox-travis script: tox -after_success: - - coveralls diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 0a428e2d..a877140d 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -101,14 +101,15 @@ Before you submit a pull request, check that it meets these guidelines: 2. If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in README.rst. -3. The pull request should work for Python 2.6, 2.7, and 3.3, and for PyPy. Check +3. The pull request should pass the Continuous Integration tests. Check https://travis-ci.org/dyve/django-bootstrap4/pull_requests - and make sure that the tests pass for all supported Python versions. + and make sure that all tests pass. You can run the tests locally + using `tox`. Tips ---- To run a subset of tests:: - $ python -m unittest tests.test_bootstrap4 + $ python manage.py test tests.test_components diff --git a/HISTORY.rst b/HISTORY.rst index 77294b02..020ae627 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -3,6 +3,20 @@ History ------- +1.1.0 (2019-12-06) +++++++++++++++++++ +- Update default Bootstrap to v4.3.1 +- Add support for Python 3.8, Django 3 and Django master +- Switch to Django `manage.py` for test running +- Update Makefile commands +- Update tox configuration +- Use correct license (BSD-3-Clause) +- Fix typo's in docstrings +- Update Travis configuration +- Drop MANIFEST.in, use setuptools_scm +- Stop using _version.py, use git tags for versioning +- Fixed issues with labels and input (#174 and #181) + 1.0.1 (2019-08-30) ++++++++++++++++++ - Fix support for Python 3.5 (#168) diff --git a/LICENSE b/LICENSE index d3a6fef6..360ae732 100644 --- a/LICENSE +++ b/LICENSE @@ -1,27 +1,29 @@ -Copyright (c) Zostera B.V. and individual contributors. +BSD 3-Clause License + +Copyright (c) Zostera B.V. and individual contributors All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. - 3. Neither the name of Zostera B.V. nor the names of its contributors may be - used to endorse or promote products derived from this software without - specific prior written permission. +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 57163d5d..00000000 --- a/MANIFEST.in +++ /dev/null @@ -1,10 +0,0 @@ -include LICENSE -include HISTORY.rst -include README.rst -include AUTHORS.rst -include CONTRIBUTING.rst -recursive-include docs * -include tox.ini -include runtests.py -graft src -graft tests \ No newline at end of file diff --git a/Makefile b/Makefile index 8b19f893..da42fbe0 100644 --- a/Makefile +++ b/Makefile @@ -1,36 +1,36 @@ -.PHONY: all - -version_file := src/bootstrap4/_version.py -version := $(word 3, $(shell cat ${version_file})) - -version: - @echo $(version) +.PHONY: clean test tox reformat lint docs build publish clean: rm -rf build dist *.egg-info test: - python runtests.py + coverage run manage.py test + coverage report tox: rm -rf .tox tox -doclint: - pydocstyle --add-ignore=D1 src/bootstrap4 example tests *.py - reformat: - docformatter -ir --pre-summary-newline --wrap-summaries=0 --wrap-descriptions=0 src/bootstrap4 example tests *.py isort -rc src/bootstrap4 isort -rc example isort -rc tests isort -rc *.py autoflake -ir *.py src/bootstrap4 example tests --remove-all-unused-imports + docformatter -ir --pre-summary-newline --wrap-summaries=0 --wrap-descriptions=0 src/bootstrap4 example tests *.py black . + +lint: flake8 bootstrap4 example tests *.py + pydocstyle --add-ignore=D1,D202,D301,D413 example tests *.py + +docs: + cd docs && sphinx-build -b html -d _build/doctrees . _build/html + +build: clean docs + python setup.py sdist bdist_wheel + twine check dist/* -publish: clean - cd docs && make html - python setup.py sdist +publish: build twine upload dist/* git tag -a v$(version) -m 'tagging v$(version)' diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index 1005e265..00000000 --- a/docs/Makefile +++ /dev/null @@ -1,177 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = _build - -# User-friendly check for sphinx-build -ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) -$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) -endif - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " xml to make Docutils-native XML files" - @echo " pseudoxml to make pseudoxml-XML files for display purposes" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/complexity.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/complexity.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/complexity" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/complexity" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -latexpdfja: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through platex and dvipdfmx..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." - -info: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." - -gettext: - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." - -xml: - $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml - @echo - @echo "Build finished. The XML files are in $(BUILDDIR)/xml." - -pseudoxml: - $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml - @echo - @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index df2d62db..82ff9c62 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,232 +1,37 @@ import os import sys - -# complexity documentation build configuration file, created by -# sphinx-quickstart on Tue Jul 9 22:26:36 2013. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# sys.path.insert(0, os.path.abspath('.')) +from pkg_resources import get_distribution sys.path.insert(0, os.path.abspath("..")) sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__)))) -os.environ["DJANGO_SETTINGS_MODULE"] = "testsettings" - -# This import can only be done after the sys.path has been changed -import bootstrap4 # noqa +os.environ["DJANGO_SETTINGS_MODULE"] = "tests.app.settings" -# -- General configuration ----------------------------------------------------- +project = "django-bootstrap4" +copyright = "2014-2019, Dylan Verheul" -# If your documentation needs a minimal Sphinx version, state it here. -# needs_sphinx = '1.0' +release = get_distribution(project).version +version = ".".join(release.split(".")[:2]) -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ["sphinx.ext.autodoc", "sphinx.ext.viewcode"] -# Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] -# The suffix of source filenames. source_suffix = ".rst" -# The encoding of source files. -# source_encoding = 'utf-8-sig' - -# The master toctree document. master_doc = "index" -# General information about the project. -project = "django-bootstrap4" -copyright = "2014-2019, Dylan Verheul" - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = bootstrap4.__version__ -# The full version, including alpha/beta/rc tags. -release = bootstrap4.__version__ - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# today = '' -# Else, today_fmt is used as the format for a strftime call. -# today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. exclude_patterns = ["_build"] -# The reST default role (used for this markup: `text`) to use for all documents. -# default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -# add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. pygments_style = "sphinx" -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -# keep_warnings = False - - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. html_theme = "default" -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -# html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -# html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True +htmlhelp_basename = "{project}-doc".format(project=project) -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = "django-bootstrap4doc" - -# -- Options for LaTeX output -------------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). - # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. - # 'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [("index", "django-bootstrap4.tex", "django-bootstrap4 Documentation", "Dylan Verheul", "manual")] -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# latex_use_parts = False - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_domain_indices = True - - -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). man_pages = [("index", "django-bootstrap4", "django-bootstrap4 Documentation", ["Dylan Verheul"], 1)] -# If true, show URL addresses after external links. -# man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------------ - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) texinfo_documents = [ ( "index", @@ -239,26 +44,10 @@ ) ] -# Documents to append as an appendix to all manuals. -# texinfo_appendices = [] - -# If false, no module index is generated. -# texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -# texinfo_no_detailmenu = False - - on_rtd = os.environ.get("READTHEDOCS", None) == "True" if not on_rtd: # only import and set the theme if we're building docs locally - try: - import sphinx_rtd_theme + import sphinx_rtd_theme - html_theme = "sphinx_rtd_theme" - html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] - except Exception: - pass + html_theme = "sphinx_rtd_theme" + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] diff --git a/docs/index.rst b/docs/index.rst index 3210e4ad..7400a9e9 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,10 +1,5 @@ -.. complexity documentation master file, created by - sphinx-quickstart on Tue Jul 9 22:26:36 2013. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - Welcome to django-bootstrap4's documentation! -================================================================= +============================================= Contents: diff --git a/docs/make.bat b/docs/make.bat deleted file mode 100644 index 2b447647..00000000 --- a/docs/make.bat +++ /dev/null @@ -1,242 +0,0 @@ -@ECHO OFF - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set BUILDDIR=_build -set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . -set I18NSPHINXOPTS=%SPHINXOPTS% . -if NOT "%PAPER%" == "" ( - set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% - set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% -) - -if "%1" == "" goto help - -if "%1" == "help" ( - :help - echo.Please use `make ^` where ^ is one of - echo. html to make standalone HTML files - echo. dirhtml to make HTML files named index.html in directories - echo. singlehtml to make a single large HTML file - echo. pickle to make pickle files - echo. json to make JSON files - echo. htmlhelp to make HTML files and a HTML help project - echo. qthelp to make HTML files and a qthelp project - echo. devhelp to make HTML files and a Devhelp project - echo. epub to make an epub - echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter - echo. text to make text files - echo. man to make manual pages - echo. texinfo to make Texinfo files - echo. gettext to make PO message catalogs - echo. changes to make an overview over all changed/added/deprecated items - echo. xml to make Docutils-native XML files - echo. pseudoxml to make pseudoxml-XML files for display purposes - echo. linkcheck to check all external links for integrity - echo. doctest to run all doctests embedded in the documentation if enabled - goto end -) - -if "%1" == "clean" ( - for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i - del /q /s %BUILDDIR%\* - goto end -) - - -%SPHINXBUILD% 2> nul -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "html" ( - %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/html. - goto end -) - -if "%1" == "dirhtml" ( - %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. - goto end -) - -if "%1" == "singlehtml" ( - %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. - goto end -) - -if "%1" == "pickle" ( - %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the pickle files. - goto end -) - -if "%1" == "json" ( - %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the JSON files. - goto end -) - -if "%1" == "htmlhelp" ( - %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run HTML Help Workshop with the ^ -.hhp project file in %BUILDDIR%/htmlhelp. - goto end -) - -if "%1" == "qthelp" ( - %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run "qcollectiongenerator" with the ^ -.qhcp project file in %BUILDDIR%/qthelp, like this: - echo.^> qcollectiongenerator %BUILDDIR%\qthelp\complexity.qhcp - echo.To view the help file: - echo.^> assistant -collectionFile %BUILDDIR%\qthelp\complexity.ghc - goto end -) - -if "%1" == "devhelp" ( - %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. - goto end -) - -if "%1" == "epub" ( - %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The epub file is in %BUILDDIR%/epub. - goto end -) - -if "%1" == "latex" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "latexpdf" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - cd %BUILDDIR%/latex - make all-pdf - cd %BUILDDIR%/.. - echo. - echo.Build finished; the PDF files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "latexpdfja" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - cd %BUILDDIR%/latex - make all-pdf-ja - cd %BUILDDIR%/.. - echo. - echo.Build finished; the PDF files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "text" ( - %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The text files are in %BUILDDIR%/text. - goto end -) - -if "%1" == "man" ( - %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The manual pages are in %BUILDDIR%/man. - goto end -) - -if "%1" == "texinfo" ( - %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. - goto end -) - -if "%1" == "gettext" ( - %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The message catalogs are in %BUILDDIR%/locale. - goto end -) - -if "%1" == "changes" ( - %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes - if errorlevel 1 exit /b 1 - echo. - echo.The overview file is in %BUILDDIR%/changes. - goto end -) - -if "%1" == "linkcheck" ( - %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck - if errorlevel 1 exit /b 1 - echo. - echo.Link check complete; look for any errors in the above output ^ -or in %BUILDDIR%/linkcheck/output.txt. - goto end -) - -if "%1" == "doctest" ( - %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest - if errorlevel 1 exit /b 1 - echo. - echo.Testing of doctests in the sources finished, look at the ^ -results in %BUILDDIR%/doctest/output.txt. - goto end -) - -if "%1" == "xml" ( - %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The XML files are in %BUILDDIR%/xml. - goto end -) - -if "%1" == "pseudoxml" ( - %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. - goto end -) - -:end \ No newline at end of file diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 00000000..fee442e9 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,3 @@ +Django==3.0 +Sphinx==2.2.2 +sphinx_rtd_theme==0.4.3 diff --git a/example/app/forms.py b/example/app/forms.py index b30d15a0..01ba5e67 100644 --- a/example/app/forms.py +++ b/example/app/forms.py @@ -1,6 +1,6 @@ from django import forms from django.contrib.admin.widgets import AdminSplitDateTime -from django.forms.formsets import BaseFormSet, formset_factory +from django.forms import BaseFormSet, formset_factory from bootstrap4.widgets import RadioSelectButtonGroup diff --git a/manage.py b/manage.py new file mode 100755 index 00000000..81aa9b46 --- /dev/null +++ b/manage.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tests.app.settings") + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) diff --git a/requirements.txt b/requirements.txt index 205694a6..1a54d064 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,19 +1,16 @@ -Django>=2.2 +# Developer requirements -# Documentation -Sphinx -sphinx_rtd_theme +# Django is in docs requirements +-r docs/requirements.txt -# Code style black -isort -autoflake -flake8 -pydocstyle -docformatter - -# Tests -beautifulsoup4 - -# PyPI -twine +isort==4.3.21 +autoflake==1.3.1 +flake8==3.7.9 +pydocstyle==4.0.1 +docformatter==1.3.1 +beautifulsoup4==4.8.1 +twine==3.1.1 +pur==5.2.2 +wheel==0.33.6 +tox==3.14.2 diff --git a/runtests.py b/runtests.py deleted file mode 100644 index e47abedc..00000000 --- a/runtests.py +++ /dev/null @@ -1,105 +0,0 @@ -""" -A standalone test runner script, configuring the minimum settings required for django-marina tests to execute. - -Re-use at your own risk: many Django applications will require full -settings and/or templates in order to execute their tests, while -django-marina does not. - -Adapted from James Bennett's https://github.com/ubernostrum/pwned-passwords-django -""" - -import os -import sys - -# Make sure the app is (at least temporarily) on the import path. -APP_DIR = os.path.abspath(os.path.dirname(__file__)) -sys.path.insert(0, APP_DIR) - -# # Minimum settings for the app's tests. -# DEBUG = True -# -# SECRET_KEY = "bootstrap4isawesome" -# -# DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}} -# -# INSTALLED_APPS = ( -# # We test this one -# "bootstrap4", -# ) - - -SETTINGS_DICT = { - "INSTALLED_APPS": ( - # Default Django apps - "django.contrib.admin", - "django.contrib.auth", - "django.contrib.contenttypes", - "django.contrib.sessions", - "django.contrib.messages", - "django.contrib.staticfiles", - "django.contrib.gis", - # Our tests - "bootstrap4", - "tests", - ), - "ROOT_URLCONF": "tests.urls", - "DATABASES": {"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}}, - "MIDDLEWARE": ( - "django.contrib.sessions.middleware.SessionMiddleware", - "django.contrib.auth.middleware.AuthenticationMiddleware", # required for django.contrib.admin - "django.contrib.messages.middleware.MessageMiddleware", # required for django.contrib.admin - ), - "STATIC_URL": "/static/", - "TEMPLATES": [ - { - "BACKEND": "django.template.backends.django.DjangoTemplates", - "APP_DIRS": True, - "OPTIONS": { - "context_processors": [ - "django.contrib.auth.context_processors.auth", - "django.template.context_processors.debug", - "django.template.context_processors.i18n", - "django.template.context_processors.media", - "django.template.context_processors.static", - "django.template.context_processors.tz", - "django.contrib.messages.context_processors.messages", - ] - }, - } - ], - "BOOTSTRAP4": { - "theme_url": "//example.com/theme.css", - "javascript_in_head": True, - "required_css_class": "bootstrap4-req", - "error_css_class": "bootstrap4-err", - "success_css_class": "bootstrap4-bound", - }, -} - - -def run_tests(): - # Making Django run this way is a two-step process. First, call - # settings.configure() to give Django settings to work with: - from django.conf import settings - - settings.configure(**SETTINGS_DICT) - - # Then, call django.setup() to initialize the application registry - # and other bits: - import django - - django.setup() - - # Now we instantiate a test runner... - from django.test.utils import get_runner - - TestRunner = get_runner(settings) - - # And then we run tests and return the results. - test_runner = TestRunner(verbosity=2, interactive=True) - failures = test_runner.run_tests(["tests"]) - sys.exit(failures) - - -if __name__ == "__main__": - run_tests() diff --git a/setup.py b/setup.py index bc8d64b5..6bef5afc 100755 --- a/setup.py +++ b/setup.py @@ -2,18 +2,9 @@ import os -import re from setuptools import find_packages, setup -VERSIONFILE = "src/bootstrap4/_version.py" -VSRE = r"^__version__ = ['\"]([^'\"]*)['\"]" - -try: - VERSION = re.search(VSRE, open(VERSIONFILE, "rt").read(), re.M).group(1) -except: # noqa - raise RuntimeError("Unable to find version string in %s." % (VERSIONFILE,)) - with open(os.path.join(os.path.dirname(__file__), "README.rst")) as readme_file: readme = readme_file.read() @@ -22,13 +13,15 @@ setup( name="django-bootstrap4", - version=VERSION, - url="https://github.com/zostera/django-bootstrap4", - author="Dylan Verheul", - author_email="dylan@dyve.net", description="""Bootstrap support for Django projects""", long_description=readme + "\n\n" + history, - license="BSD", + long_description_content_type="text/x-rst", + author="Dylan Verheul", + author_email="dylan@dyve.net", + url="https://github.com/zostera/django-bootstrap4", + license="BSD-3-Clause", + use_scm_version=True, + setup_requires=["setuptools_scm"], packages=find_packages(where="src"), package_dir={"": "src"}, include_package_data=True, diff --git a/src/bootstrap4/__init__.py b/src/bootstrap4/__init__.py index ad5cc752..e69de29b 100644 --- a/src/bootstrap4/__init__.py +++ b/src/bootstrap4/__init__.py @@ -1 +0,0 @@ -from ._version import __version__ # noqa diff --git a/src/bootstrap4/_version.py b/src/bootstrap4/_version.py deleted file mode 100644 index 5c4105cd..00000000 --- a/src/bootstrap4/_version.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = "1.0.1" diff --git a/src/bootstrap4/bootstrap.py b/src/bootstrap4/bootstrap.py index 9df7c3b9..f9651f47 100644 --- a/src/bootstrap4/bootstrap.py +++ b/src/bootstrap4/bootstrap.py @@ -2,17 +2,15 @@ from django.conf import settings -# Default settings - BOOTSTRAP4_DEFAULTS = { "css_url": { - "href": "https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css", - "integrity": "sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB", + "href": "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css", + "integrity": "sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T", "crossorigin": "anonymous", }, "javascript_url": { - "url": "https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js", - "integrity": "sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T", + "url": "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js", + "integrity": "sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM", "crossorigin": "anonymous", }, "theme_url": None, @@ -27,8 +25,8 @@ "crossorigin": "anonymous", }, "popper_url": { - "url": "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js", - "integrity": "sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49", + "url": "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js", + "integrity": "sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1", "crossorigin": "anonymous", }, "javascript_in_head": False, diff --git a/src/bootstrap4/components.py b/src/bootstrap4/components.py index fc231ec2..8936342e 100644 --- a/src/bootstrap4/components.py +++ b/src/bootstrap4/components.py @@ -1,5 +1,5 @@ from django.utils.safestring import mark_safe -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from bootstrap4.utils import render_tag diff --git a/src/bootstrap4/renderers.py b/src/bootstrap4/renderers.py index d617fed6..21acdfef 100644 --- a/src/bootstrap4/renderers.py +++ b/src/bootstrap4/renderers.py @@ -1,5 +1,8 @@ from bs4 import BeautifulSoup from django.forms import ( + BaseForm, + BaseFormSet, + BoundField, CheckboxInput, CheckboxSelectMultiple, ClearableFileInput, @@ -11,11 +14,9 @@ PasswordInput, RadioSelect, Select, + SelectDateWidget, TextInput, ) -from django.forms.forms import BaseForm, BoundField -from django.forms.formsets import BaseFormSet -from django.forms.widgets import SelectDateWidget from django.utils.html import conditional_escape, escape, strip_tags from django.utils.safestring import mark_safe @@ -333,7 +334,17 @@ def list_to_class(self, html, klass): soup = BeautifulSoup(html, features="html.parser") for label in soup.find_all("label"): label.attrs["class"] = label.attrs.get("class", []) + ["form-check-label"] - label.input.attrs["class"] = label.input.attrs.get("class", []) + ["form-check-input"] + label_input = None + input_id = label.attrs.get("for") + if input_id: + label_input = soup.find(id=input_id) + else: + try: + label_input = label.input + except AttributeError: + pass + if label_input: + label_input.attrs["class"] = label_input.attrs.get("class", []) + ["form-check-input"] return str(soup) def add_checkbox_label(self, html): diff --git a/src/bootstrap4/templatetags/bootstrap4.py b/src/bootstrap4/templatetags/bootstrap4.py index 7272da31..339c9ceb 100644 --- a/src/bootstrap4/templatetags/bootstrap4.py +++ b/src/bootstrap4/templatetags/bootstrap4.py @@ -275,7 +275,7 @@ def bootstrap_jquery(jquery=True): bootstrap_jquery - **Parameters**: + **Parameters**:: :jquery: False|"slim"|True (default=True) @@ -320,7 +320,7 @@ def bootstrap_javascript(jquery=False): bootstrap_javascript - **Parameters**: + **Parameters**:: :jquery: False|"slim"|True (default=False) @@ -365,7 +365,7 @@ def bootstrap_formset(*args, **kwargs): bootstrap_formset - **Parameters**: + **Parameters**:: formset The formset that is being rendered @@ -393,7 +393,7 @@ def bootstrap_formset_errors(*args, **kwargs): bootstrap_formset_errors - **Parameters**: + **Parameters**:: formset The formset that is being rendered @@ -421,7 +421,7 @@ def bootstrap_form(*args, **kwargs): bootstrap_form - **Parameters**: + **Parameters**:: form The form that is to be rendered @@ -463,7 +463,7 @@ def bootstrap_form_errors(*args, **kwargs): bootstrap_form_errors - **Parameters**: + **Parameters**:: form The form that is to be rendered @@ -502,7 +502,7 @@ def bootstrap_field(*args, **kwargs): bootstrap_field - **Parameters**: + **Parameters**:: field @@ -633,7 +633,7 @@ def bootstrap_label(*args, **kwargs): bootstrap_label - **Parameters**: + **Parameters**:: content The label's text @@ -667,7 +667,7 @@ def bootstrap_button(*args, **kwargs): bootstrap_button - **Parameters**: + **Parameters**:: content The text to be displayed in the button @@ -733,7 +733,7 @@ def bootstrap_alert(content, alert_type="info", dismissible=True): bootstrap_alert - **Parameters**: + **Parameters**:: content HTML content of alert @@ -771,7 +771,7 @@ def bootstrap_buttons(parser, token): buttons - **Parameters**: + **Parameters**:: submit Text for a submit button @@ -837,7 +837,7 @@ def bootstrap_messages(context, *args, **kwargs): bootstrap_messages - **Parameters**: + **Parameters**:: None. @@ -866,7 +866,7 @@ def bootstrap_pagination(page, **kwargs): bootstrap_pagination - **Parameters**: + **Parameters**:: page The page of results to show. diff --git a/src/bootstrap4/utils.py b/src/bootstrap4/utils.py index 4b475343..121edb71 100644 --- a/src/bootstrap4/utils.py +++ b/src/bootstrap4/utils.py @@ -1,9 +1,9 @@ import re +from collections.abc import Mapping from urllib.parse import parse_qs, urlparse, urlunparse from django.forms.utils import flatatt -from django.template import Variable, VariableDoesNotExist -from django.template.base import FilterExpression, TemplateSyntaxError, kwarg_re +from django.template.base import FilterExpression, TemplateSyntaxError, Variable, VariableDoesNotExist, kwarg_re from django.template.loader import get_template from django.utils.encoding import force_str from django.utils.html import format_html @@ -12,13 +12,6 @@ from .text import text_value -try: - from collections.abc import Mapping -except ImportError: - # py27 fallback, remove if support for python 2.7 is dropped - from collections import Mapping - - # RegEx for quoted string QUOTED_STRING = re.compile(r'^["\'](?P.+)["\']$') diff --git a/src/bootstrap4/widgets.py b/src/bootstrap4/widgets.py index 1413496e..782d3a3e 100644 --- a/src/bootstrap4/widgets.py +++ b/src/bootstrap4/widgets.py @@ -1,11 +1,11 @@ -from django.forms.widgets import RadioSelect +from django.forms import RadioSelect class RadioSelectButtonGroup(RadioSelect): - """ - This widget renders a Bootstrap 4 set of buttons horizontally instead of typical radio buttons. - - Much more mobile friendly. + """ + This widget renders a Bootstrap 4 set of buttons horizontally instead of typical radio buttons. + + Much more mobile friendly. """ template_name = "bootstrap4/widgets/radio_select_button_group.html" diff --git a/tests/app/__init__.py b/tests/app/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/app/settings.py b/tests/app/settings.py new file mode 100644 index 00000000..9a31fc43 --- /dev/null +++ b/tests/app/settings.py @@ -0,0 +1,53 @@ +SECRET_KEY = "Thanks for using django-bootstrap4!" + +DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}} + +INSTALLED_APPS = ( + # Default Django apps + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "django.contrib.gis", + # Our tests + "bootstrap4", + "tests", +) + +ROOT_URLCONF = "tests.app.urls" + +MIDDLEWARE = ( + "django.contrib.sessions.middleware.SessionMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", # required for django.contrib.admin + "django.contrib.messages.middleware.MessageMiddleware", # required for django.contrib.admin +) + +STATIC_URL = "/static/" + +TEMPLATES = [ + { + "BACKEND": "django.template.backends.django.DjangoTemplates", + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.contrib.auth.context_processors.auth", + "django.template.context_processors.debug", + "django.template.context_processors.i18n", + "django.template.context_processors.media", + "django.template.context_processors.static", + "django.template.context_processors.tz", + "django.contrib.messages.context_processors.messages", + ] + }, + } +] + +BOOTSTRAP4 = { + "theme_url": "//example.com/theme.css", + "javascript_in_head": True, + "required_css_class": "bootstrap4-req", + "error_css_class": "bootstrap4-err", + "success_css_class": "bootstrap4-bound", +} diff --git a/tests/urls.py b/tests/app/urls.py similarity index 100% rename from tests/urls.py rename to tests/app/urls.py diff --git a/tests/test_templatetags.py b/tests/test_templatetags.py index b8437a25..6f0f2ca2 100644 --- a/tests/test_templatetags.py +++ b/tests/test_templatetags.py @@ -3,7 +3,7 @@ from bs4 import BeautifulSoup from django.contrib.messages import constants as DEFAULT_MESSAGE_LEVELS from django.core.paginator import Paginator -from django.forms.formsets import formset_factory +from django.forms import formset_factory from django.test import TestCase, override_settings from django.utils.html import escape @@ -11,8 +11,9 @@ from bootstrap4.exceptions import BootstrapError from bootstrap4.text import text_concat, text_value from bootstrap4.utils import add_css_class, render_tag, url_replace_param +from tests.utils import html_39x27 -from .test_templates import TestForm, render_template, render_template_with_bootstrap, render_template_with_form +from .test_templates import TestForm, render_template, render_template_with_form def render_formset(formset=None, context=None): @@ -303,11 +304,16 @@ def test_subject(self): def test_xss_field(self): res = render_form_field("xss_field") self.assertIn('type="text"', res) + + expect = html_39x27( + '" + ) self.assertIn( - '', - res, + expect, res, ) - self.assertIn('placeholder="XSS" onmouseover="alert('Hello, XSS')" foo=""', res) + expect = html_39x27('placeholder="XSS" onmouseover="alert('Hello, XSS')" foo=""') + self.assertIn(expect, res) def test_password(self): res = render_form_field("password") diff --git a/tests/test_version.py b/tests/test_version.py deleted file mode 100644 index 3579869f..00000000 --- a/tests/test_version.py +++ /dev/null @@ -1,9 +0,0 @@ -from unittest import TestCase - -from bootstrap4 import __version__ - - -class VersionTestCase(TestCase): - def test_version_is_valid(self): - version_parts = __version__.split(".") - self.assertEqual(len(version_parts), 3) diff --git a/tests/utils.py b/tests/utils.py index e69de29b..9a318c1d 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -0,0 +1,14 @@ +from django import get_version + +DJANGO3 = get_version() >= "3" + + +def html_39x27(html): + """ + Return HTML string with ' (Django < 3) instead of ' (Django >= 3). + + See https://docs.djangoproject.com/en/dev/releases/3.0/#miscellaneous + """ + if not DJANGO3: + return html.replace("'", "'") + return html diff --git a/tox.ini b/tox.ini index 3fb4e63d..b0240e7d 100644 --- a/tox.ini +++ b/tox.ini @@ -1,49 +1,55 @@ [tox] envlist = - {py35}-{2.1,2.2} - {py36}-{2.1,2.2} - {py37}-{2.1,2.2} - flake8 + {py35}-{django21,django22} + {py36}-{django21,django22,django30,djangomaster} + {py37}-{django21,django22,django30,djangomaster} + {py38}-{django30,djangomaster} + lint docs - black [testenv] setenv = - PYTHONWARNINGS=module::DeprecationWarning + PYTHONWARNINGS=all +whitelist_externals = make commands = - coverage run --source=bootstrap4 runtests.py - coverage report -m + coverage run --source bootstrap4 manage.py test -v1 --noinput deps = coverage - beautifulsoup4 - 2.1: django>=2.1,<2.2 - 2.2: django>=2.2,<2.3 + django21: Django==2.1.* + django22: Django==2.2.* + django30: Django==3.0.* + djangomaster: https://github.com/django/django/archive/master.tar.gz +after_success : + coveralls -[testenv:docs] -changedir = docs -deps = - django - sphinx - sphinx_rtd_theme -commands = sphinx-build -b html -d {envtmpdir}/doctrees . {envtmpdir}/html +[testenv:lint] +basepython = python3.7 +deps = -r {toxinidir}/requirements.txt +commands = make lint -[testenv:flake8] -deps = flake8==3.6.0 -commands = flake8 +[testenv:docs] +basepython = python3.7 +deps = -r {toxinidir}/docs/requirements.txt +commands = make docs [flake8] -ignore = F401,E731,W503,E501 -select = C,E,F,W,B,B950 +# E731 do not assign a lambda expression +# W503 line break before binary operator (black introduces these) +# E203 whitespace before ':' +ignore = E731,W503,E203 exclude = .git,.tox,__pycache__ max-line-length = 120 -[testenv:black] -passenv = LC_CTYPE -deps = black==19.3b0 -commands = black --check . - [travis] -python: +python : 3.5: py35 3.6: py36 - 3.7: py37, docs, flake8, black + 3.7: py37, docs, flake8 + 3.8: py38 + +[coverage:run] +source = src/bootstrap4 + +[coverage:report] +show_missing = True +skip_covered = True