mirror of
https://github.com/pacnpal/django-anymail.git
synced 2025-12-20 11:51:05 -05:00
Use tox for running tests and building docs
* Set up tox for testing supported Django/Python combinations * Also include tox env for checking and building docs * Use tox-travis for Travis CI integration * Add tests against Django master * Document building docs and running tests with tox
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,6 +3,8 @@
|
|||||||
*.pyc
|
*.pyc
|
||||||
*.egg
|
*.egg
|
||||||
*.egg-info
|
*.egg-info
|
||||||
|
.eggs/
|
||||||
|
.tox/
|
||||||
build/
|
build/
|
||||||
dist/
|
dist/
|
||||||
docs/_build/
|
docs/_build/
|
||||||
|
|||||||
78
.travis.yml
78
.travis.yml
@@ -11,6 +11,8 @@ branches:
|
|||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
|
- { env: LINT_AND_DOCS=true, python: 3.6 }
|
||||||
|
|
||||||
# Anymail supports the same python versions as Django, excluding Python 3.2, but adding pypy.
|
# Anymail supports the same python versions as Django, excluding Python 3.2, but adding pypy.
|
||||||
# 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
|
||||||
|
|
||||||
@@ -18,54 +20,52 @@ matrix:
|
|||||||
# combinations, to avoid rapidly consuming the testing accounts' entire send allotments.
|
# combinations, to avoid rapidly consuming the testing accounts' entire send allotments.
|
||||||
|
|
||||||
# Django 1.8: Python 2.7, 3.3, 3.4, 3.5
|
# Django 1.8: Python 2.7, 3.3, 3.4, 3.5
|
||||||
- { env: DJANGO=django==1.8 RUN_LIVE_TESTS=true, python: 2.7 }
|
- { env: DJANGO=1.8 RUN_LIVE_TESTS=true, python: 2.7 }
|
||||||
- { env: DJANGO=django==1.8, python: 3.3 }
|
- { env: DJANGO=1.8, python: 3.3 }
|
||||||
- { env: DJANGO=django==1.8, python: 3.4 }
|
- { env: DJANGO=1.8, python: 3.4 }
|
||||||
- { env: DJANGO=django==1.8, python: 3.5 }
|
- { env: DJANGO=1.8, python: 3.5 }
|
||||||
- { env: DJANGO=django==1.8, python: pypy }
|
- { env: DJANGO=1.8, python: pypy }
|
||||||
# Django 1.9: Python 2.7, 3.4, 3.5
|
# Django 1.9: Python 2.7, 3.4, 3.5
|
||||||
- { env: DJANGO=django==1.9, python: 2.7 }
|
- { env: DJANGO=1.9, python: 2.7 }
|
||||||
- { env: DJANGO=django==1.9, python: 3.4 }
|
- { env: DJANGO=1.9, python: 3.4 }
|
||||||
- { env: DJANGO=django==1.9, python: 3.5 }
|
- { env: DJANGO=1.9, python: 3.5 }
|
||||||
- { env: DJANGO=django==1.9, python: pypy }
|
- { env: DJANGO=1.9, python: pypy }
|
||||||
# Django 1.10: Python 2.7, 3.4, 3.5
|
# Django 1.10: Python 2.7, 3.4, 3.5
|
||||||
- { env: DJANGO=django==1.10, python: 2.7 }
|
- { env: DJANGO=1.10, python: 2.7 }
|
||||||
- { env: DJANGO=django==1.10, python: 3.4 }
|
- { env: DJANGO=1.10, python: 3.4 }
|
||||||
- { env: DJANGO=django==1.10, python: 3.5 }
|
- { env: DJANGO=1.10, python: 3.5 }
|
||||||
- { env: DJANGO=django==1.10, python: pypy }
|
- { env: DJANGO=1.10, python: pypy }
|
||||||
# Django 1.11: Python 2.7, 3.4, 3.5, or 3.6
|
# Django 1.11: Python 2.7, 3.4, 3.5, or 3.6
|
||||||
- { env: DJANGO=django==1.11, python: 2.7 }
|
- { env: DJANGO=1.11, python: 2.7 }
|
||||||
- { env: DJANGO=django==1.11, python: 3.4 }
|
- { env: DJANGO=1.11, python: 3.4 }
|
||||||
- { env: DJANGO=django==1.11, python: 3.5 }
|
- { env: DJANGO=1.11, python: 3.5 }
|
||||||
- { env: DJANGO=django==1.11, python: 3.6 }
|
- { env: DJANGO=1.11, python: 3.6 }
|
||||||
- { env: DJANGO=django==1.11, python: pypy }
|
- { env: DJANGO=1.11, python: pypy }
|
||||||
# Django 2.0: Python 3.5+
|
# Django 2.0: Python 3.5+
|
||||||
- { env: DJANGO=django==2.0, python: 3.5 }
|
- { env: DJANGO=2.0, python: 3.5 }
|
||||||
- { env: DJANGO=django==2.0 RUN_LIVE_TESTS=true, python: 3.6 }
|
- { env: DJANGO=2.0 RUN_LIVE_TESTS=true, python: 3.6 }
|
||||||
|
- { env: DJANGO=2.0, python: pypy3 }
|
||||||
# Django 2.1 (prerelease): Python 3.5+
|
# Django 2.1 (prerelease): Python 3.5+
|
||||||
#- { env: DJANGO="--pre django", python: 3.5 }
|
#- { env: DJANGO=2.1, python: 3.5 }
|
||||||
#- { env: DJANGO="--pre django", python: 3.6 }
|
#- { env: DJANGO=2.1, python: 3.6 }
|
||||||
|
# Django development master (direct from GitHub source):
|
||||||
|
- { env: DJANGO=master, python: 3.6 }
|
||||||
|
- { env: DJANGO=master, python: 3.7-dev }
|
||||||
|
|
||||||
- { env: FLAKE8=true, python: 2.7 }
|
allow_failures:
|
||||||
- { env: FLAKE8=true, python: 3.6 }
|
- env: DJANGO=2.1
|
||||||
|
python: 3.5
|
||||||
# allow_failures:
|
- env: DJANGO=2.1
|
||||||
# - env: DJANGO="--pre django"
|
python: 3.6
|
||||||
# - python: 3.6
|
- env: DJANGO=master
|
||||||
|
python: 3.6
|
||||||
|
- env: DJANGO=master
|
||||||
|
python: 3.7-dev
|
||||||
|
|
||||||
cache: pip
|
cache: pip
|
||||||
|
|
||||||
# If env DJANGO is set, install Anymail and run tests
|
|
||||||
# If env FLAKE8 is set, run flake8
|
|
||||||
install:
|
install:
|
||||||
- pip install --upgrade setuptools pip
|
- pip install tox-travis
|
||||||
- if [[ -n $DJANGO ]]; then pip install $DJANGO; fi
|
|
||||||
# For now, install Anymail including all optional ESPs, and test at once
|
|
||||||
# (in future, might want to matrix ESPs to test cross-dependencies)
|
|
||||||
- if [[ -n $DJANGO ]]; then pip install .[mailgun,mailjet,mandrill,postmark,sendinblue,sendgrid,sparkpost]; fi
|
|
||||||
- if [[ -n $FLAKE8 ]]; then pip install flake8; fi
|
|
||||||
- pip list
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- if [[ -n $DJANGO ]]; then python setup.py test; fi
|
- tox
|
||||||
- if [[ -n $FLAKE8 ]]; then flake8; fi
|
|
||||||
|
|||||||
31
docs/_readme/docutils.cfg
Normal file
31
docs/_readme/docutils.cfg
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# docutils (rst2html) config for generating static HTML that approximates
|
||||||
|
# PyPI package description rendering (as of 3/2018).
|
||||||
|
#
|
||||||
|
# Usage (in package root dir):
|
||||||
|
# python setup.py --long-description | rst2html.py --config=docs/_readme/docutils.cfg > ${OUTDIR}/readme.html
|
||||||
|
#
|
||||||
|
# Requires docutils and pygments (both are installed with Sphinx)
|
||||||
|
|
||||||
|
[general]
|
||||||
|
# Duplicate docutils config used by PyPA readme_renderer.
|
||||||
|
# https://github.com/pypa/readme_renderer/blob/master/readme_renderer/rst.py
|
||||||
|
# (This isn't exactly what's used on legacy PyPI, but it's close enough.)
|
||||||
|
cloak_email_addresses = True
|
||||||
|
doctitle_xform = True
|
||||||
|
sectsubtitle_xform = True
|
||||||
|
initial_header_level = 2
|
||||||
|
file_insertion_enabled = False
|
||||||
|
math_output = MathJax
|
||||||
|
raw_enabled = False
|
||||||
|
smart_quotes = True
|
||||||
|
strip_comments = True
|
||||||
|
syntax_highlight = short
|
||||||
|
|
||||||
|
# Halt rendering and throw an exception if there was any errors or warnings from docutils.
|
||||||
|
halt_level = 2
|
||||||
|
# DON'T Disable all system messages from being reported.
|
||||||
|
# (We're not running inside readme_renderer, so *do* want to see warnings and errors.)
|
||||||
|
# report_level = 5
|
||||||
|
|
||||||
|
# Approximate PyPI's styles:
|
||||||
|
stylesheet = docs/_readme/readme.css
|
||||||
74
docs/_readme/readme.css
Normal file
74
docs/_readme/readme.css
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
readme.css
|
||||||
|
Approximates PyPI package description rendering as of 3/2018,
|
||||||
|
using docutils rst2html output.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Borrow base docutils and pygments styles directly from PyPI: */
|
||||||
|
@import url("https://pypi.python.org/static/css/docutils.css");
|
||||||
|
@import url("https://pypi.python.org/static/css/pygments.css"); /* requires rst2html 'short' classnames */
|
||||||
|
|
||||||
|
/* Subset of PyPI site styles applicable to package description: */
|
||||||
|
HTML, BODY {
|
||||||
|
font-family: Arial, Verdana, Geneva, "Bitstream Vera Sans", Helvetica, sans-serif;
|
||||||
|
font-size: 103%;
|
||||||
|
color: #000;
|
||||||
|
background-color: #FFF;
|
||||||
|
}
|
||||||
|
H1, H2, H3, H4, H5 {
|
||||||
|
font-family: Georgia, "Bitstream Vera Serif", "New York", Palatino, serif;
|
||||||
|
font-weight: normal;
|
||||||
|
line-height: 1em;
|
||||||
|
}
|
||||||
|
H1 {
|
||||||
|
font-size: 160%;
|
||||||
|
color: #234764;
|
||||||
|
margin: 0.7em 0;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
H2 {
|
||||||
|
font-size: 140%;
|
||||||
|
color: #366D9C;
|
||||||
|
margin: 0.7em 0 0.7em 0;
|
||||||
|
}
|
||||||
|
IMG {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
A:link {
|
||||||
|
color: #00A;
|
||||||
|
}
|
||||||
|
A:visited {
|
||||||
|
color: #551A8B;
|
||||||
|
}
|
||||||
|
P A:link, P A:visited,
|
||||||
|
UL A:link, UL A:visited,
|
||||||
|
OL A:link, OL A:visited {
|
||||||
|
text-decoration: none;
|
||||||
|
border-bottom: 1px dashed #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Additional styles, to account for not having all of PyPI's wrapper and navigation divs: */
|
||||||
|
body {
|
||||||
|
line-height: 1.5;
|
||||||
|
font-size: 14.6px; /* ~computed font-size in PyPI's div#content */
|
||||||
|
}
|
||||||
|
h1.title {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
ul, li {
|
||||||
|
margin-left: 1em;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
pre {
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 11.9px; /* ~computed font-size in PyPI's div#content pre */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Give the page a little breathing room: */
|
||||||
|
.document {
|
||||||
|
max-width: 960px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
@@ -1,3 +1,10 @@
|
|||||||
|
.. role:: shell(code)
|
||||||
|
:language: shell
|
||||||
|
|
||||||
|
.. role:: rst(code)
|
||||||
|
:language: rst
|
||||||
|
|
||||||
|
|
||||||
.. _contributing:
|
.. _contributing:
|
||||||
|
|
||||||
Contributing
|
Contributing
|
||||||
@@ -48,6 +55,8 @@ Pull requests are always welcome to fix bugs and improve support for ESP and Dja
|
|||||||
(basically, :pep:`8` with longer lines OK).
|
(basically, :pep:`8` with longer lines OK).
|
||||||
* By submitting a pull request, you're agreeing to release your changes under under
|
* By submitting a pull request, you're agreeing to release your changes under under
|
||||||
the same BSD license as the rest of this project.
|
the same BSD license as the rest of this project.
|
||||||
|
* Documentation is appreciated, but not required.
|
||||||
|
(Please don't let missing or incomplete documentation keep you from contributing code.)
|
||||||
|
|
||||||
.. Intentionally point to Django dev branch for coding docs (rather than Django stable):
|
.. Intentionally point to Django dev branch for coding docs (rather than Django stable):
|
||||||
.. _Django coding style:
|
.. _Django coding style:
|
||||||
@@ -57,32 +66,121 @@ Pull requests are always welcome to fix bugs and improve support for ESP and Dja
|
|||||||
Testing
|
Testing
|
||||||
-------
|
-------
|
||||||
|
|
||||||
Anymail is `tested on Travis`_ against several combinations of Django
|
Anymail is `tested on Travis CI`_ against several combinations of Django
|
||||||
and Python versions. (Full list in `.travis.yml`_.)
|
and Python versions. Tests are run at least once a week, to check whether ESP APIs
|
||||||
|
and other dependencies have changed out from under Anymail.
|
||||||
|
|
||||||
|
For local development, the recommended test command is
|
||||||
|
:shell:`tox -e django20-py36,django18-py27,lint`, which tests a representative
|
||||||
|
combination of Python and Django versions. It also runs :pypi:`flake8` and other
|
||||||
|
code-style checkers. Some other test options are covered below, but using this
|
||||||
|
tox command catches most problems, and is a good pre-pull-request check.
|
||||||
|
|
||||||
Most of the included tests verify that Anymail constructs the expected ESP API
|
Most of the included tests verify that Anymail constructs the expected ESP API
|
||||||
calls, without actually calling the ESP's API or sending any email. So these tests
|
calls, without actually calling the ESP's API or sending any email. So these tests
|
||||||
don't require API keys, but they *do* require `mock`_ (``pip install mock``).
|
don't require API keys, but they *do* require :pypi:`mock` and all ESP-specific
|
||||||
|
package requirements.
|
||||||
|
|
||||||
To run the tests, either:
|
To run the tests, you can:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ python setup.py test
|
$ python setup.py test # (also installs test dependencies if needed)
|
||||||
|
|
||||||
or:
|
Or:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ pip install mock sparkpost # install test dependencies
|
||||||
$ python runtests.py
|
$ python runtests.py
|
||||||
|
|
||||||
Anymail also includes some integration tests, which do call the live ESP APIs.
|
## this command can also run just a few test cases, e.g.:
|
||||||
These integration tests require API keys (and sometimes other settings) they
|
$ python runtests.py tests.test_mailgun_backend tests.test_mailgun_webhooks
|
||||||
get from from environment variables. They're skipped if these keys aren't present.
|
|
||||||
If you want to run them, look in the ``*_integration_tests.py``
|
|
||||||
files in the `tests source`_ for specific requirements.
|
|
||||||
|
|
||||||
.. _.travis.yml: https://github.com/anymail/django-anymail/blob/master/.travis.yml
|
Or to test against multiple versions of Python and Django all at once, use :pypi:`tox`.
|
||||||
|
You'll need at least Python 2.7 and Python 3.6 available. (If your system doesn't come
|
||||||
|
with those, `pyenv`_ is a helpful way to install and manage multiple Python versions.)
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ pip install tox # (if you haven't already)
|
||||||
|
$ tox -e django20-py36,django18-py27,lint # test recommended environments
|
||||||
|
|
||||||
|
## you can also run just some test cases, e.g.:
|
||||||
|
$ tox -e django20-py36,django18-py27 tests.test_mailgun_backend tests.test_utils
|
||||||
|
|
||||||
|
## to test more Python/Django versions:
|
||||||
|
$ tox # ALL 20+ envs! (grab a coffee, or use `detox` to run tests in parallel)
|
||||||
|
$ tox --skip-missing-interpreters # if some Python versions aren't installed
|
||||||
|
|
||||||
|
In addition to the mocked tests, Anymail has integration tests which *do* call live ESP APIs.
|
||||||
|
These tests are normally skipped; to run them, set environment variables with the necessary
|
||||||
|
API keys or other settings. For example:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ export MAILGUN_TEST_API_KEY='your-Mailgun-API-key'
|
||||||
|
$ export MAILGUN_TEST_DOMAIN='mail.example.com' # sending domain for that API key
|
||||||
|
$ tox -e django20-py36 tests.test_mailgun_integration
|
||||||
|
|
||||||
|
Check the ``*_integration_tests.py`` files in the `tests source`_ to see which variables
|
||||||
|
are required for each ESP. Depending on the supported features, the integration tests for
|
||||||
|
a particular ESP send around 5-15 individual messages. For ESPs that don't offer a sandbox,
|
||||||
|
these will be real sends charged to your account (again, see the notes in each test case).
|
||||||
|
Be sure to specify a particular testenv with tox's `-e` option, or tox may repeat the tests
|
||||||
|
for all 20+ supported combinations of Python and Django, sending hundreds of messages.
|
||||||
|
|
||||||
|
|
||||||
|
.. _pyenv: https://github.com/pyenv/pyenv
|
||||||
|
.. _tested on Travis CI: https://travis-ci.org/anymail/django-anymail
|
||||||
.. _tests source: https://github.com/anymail/django-anymail/blob/master/tests
|
.. _tests source: https://github.com/anymail/django-anymail/blob/master/tests
|
||||||
.. _mock: http://www.voidspace.org.uk/python/mock/index.html
|
.. _.travis.yml: https://github.com/anymail/django-anymail/blob/master/.travis.yml
|
||||||
.. _tested on Travis: https://travis-ci.org/anymail/django-anymail
|
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
-------------
|
||||||
|
|
||||||
|
As noted above, Anymail welcomes pull requests with missing or incomplete
|
||||||
|
documentation. (Code without docs is better than no contribution at all.)
|
||||||
|
But documentation---even needing edits---is always appreciated, as are pull
|
||||||
|
requests simply to improve the docs themselves.
|
||||||
|
|
||||||
|
Like many Python packages, Anymail's docs use :pypi:`Sphinx`. If you've never
|
||||||
|
worked with Sphinx or reStructuredText, Django's `Writing Documentation`_ can
|
||||||
|
get you started.
|
||||||
|
|
||||||
|
It's easiest to build Anymail's docs using tox:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ pip install tox # (if you haven't already)
|
||||||
|
$ tox -e docs # build the docs using Sphinx
|
||||||
|
|
||||||
|
You can run Python's simple HTTP server to view them:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ (cd .tox/docs/_html; python3 -m http.server 8123 --bind 127.0.0.1)
|
||||||
|
|
||||||
|
... and then open http://localhost:8123/ in a browser. Leave the server running,
|
||||||
|
and just re-run the tox command and refresh your browser as you make changes.
|
||||||
|
|
||||||
|
If you've edited the main README.rst, you can preview an approximation of what
|
||||||
|
will end up on PyPI at http://localhost:8123/readme.html.
|
||||||
|
|
||||||
|
Anymail's Sphinx conf sets up a few enhancements you can use in the docs:
|
||||||
|
|
||||||
|
* Loads `intersphinx`_ mappings for Python 3, Django (stable), and Requests.
|
||||||
|
Docs can refer to things like :rst:`:ref:`django:topics-testing-email``
|
||||||
|
or :rst:`:class:`django.core.mail.EmailMessage``.
|
||||||
|
* Supports much of `Django's added markup`_, notably :rst:`:setting:`
|
||||||
|
for documenting or referencing Django and Anymail settings.
|
||||||
|
* Allows linking to Python packages with :rst:`:pypi:`package-name``
|
||||||
|
(via `extlinks`_).
|
||||||
|
|
||||||
|
.. _Django's added markup:
|
||||||
|
https://docs.djangoproject.com/en/stable/internals/contributing/writing-documentation/#django-specific-markup
|
||||||
|
.. _extlinks: http://www.sphinx-doc.org/en/stable/ext/extlinks.html
|
||||||
|
.. _intersphinx: http://www.sphinx-doc.org/en/master/ext/intersphinx.html
|
||||||
|
.. _Writing Documentation:
|
||||||
|
https://docs.djangoproject.com/en/stable/internals/contributing/writing-documentation/
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
"""
|
"""
|
||||||
Django settings for Anymail tests.
|
Django settings for Anymail tests.
|
||||||
|
|
||||||
Generated by 'django-admin startproject' using Django 2.0a1.
|
Generated by 'django-admin startproject' using Django 2.0.3.
|
||||||
|
|
||||||
For more information on this file, see
|
For more information on this file, see
|
||||||
https://docs.djangoproject.com/en/dev/topics/settings/
|
https://docs.djangoproject.com/en/2.0/topics/settings/
|
||||||
|
|
||||||
For the full list of settings and their values, see
|
For the full list of settings and their values, see
|
||||||
https://docs.djangoproject.com/en/dev/ref/settings/
|
https://docs.djangoproject.com/en/2.0/ref/settings/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@@ -17,7 +17,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|||||||
|
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
# Quick-start development settings - unsuitable for production
|
||||||
# See https://docs.djangoproject.com/en/dev/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
|
||||||
|
|
||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
SECRET_KEY = 'NOT_FOR_PRODUCTION_USE'
|
SECRET_KEY = 'NOT_FOR_PRODUCTION_USE'
|
||||||
@@ -72,7 +72,7 @@ WSGI_APPLICATION = 'tests.wsgi.application'
|
|||||||
|
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
# https://docs.djangoproject.com/en/dev/ref/settings/#databases
|
# https://docs.djangoproject.com/en/2.0/ref/settings/#databases
|
||||||
|
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
@@ -83,7 +83,7 @@ DATABASES = {
|
|||||||
|
|
||||||
|
|
||||||
# Password validation
|
# Password validation
|
||||||
# https://docs.djangoproject.com/en/dev/ref/settings/#auth-password-validators
|
# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
AUTH_PASSWORD_VALIDATORS = [
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
{
|
{
|
||||||
@@ -102,7 +102,7 @@ AUTH_PASSWORD_VALIDATORS = [
|
|||||||
|
|
||||||
|
|
||||||
# Internationalization
|
# Internationalization
|
||||||
# https://docs.djangoproject.com/en/dev/topics/i18n/
|
# https://docs.djangoproject.com/en/2.0/topics/i18n/
|
||||||
|
|
||||||
LANGUAGE_CODE = 'en-us'
|
LANGUAGE_CODE = 'en-us'
|
||||||
|
|
||||||
@@ -116,6 +116,6 @@ USE_TZ = True
|
|||||||
|
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
# Static files (CSS, JavaScript, Images)
|
||||||
# https://docs.djangoproject.com/en/dev/howto/static-files/
|
# https://docs.djangoproject.com/en/2.0/howto/static-files/
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
|
|||||||
121
tests/test_settings/settings_2_1.py
Normal file
121
tests/test_settings/settings_2_1.py
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
"""
|
||||||
|
Django settings for Anymail tests.
|
||||||
|
|
||||||
|
Generated by 'django-admin startproject' using Django 2.1.dev20180313162727.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/dev/topics/settings/
|
||||||
|
|
||||||
|
For the full list of settings and their values, see
|
||||||
|
https://docs.djangoproject.com/en/dev/ref/settings/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||||
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
|
||||||
|
# Quick-start development settings - unsuitable for production
|
||||||
|
# See https://docs.djangoproject.com/en/dev/howto/deployment/checklist/
|
||||||
|
|
||||||
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
|
SECRET_KEY = 'NOT_FOR_PRODUCTION_USE'
|
||||||
|
|
||||||
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
|
DEBUG = True
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = []
|
||||||
|
|
||||||
|
|
||||||
|
# Application definition
|
||||||
|
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
'django.contrib.admin',
|
||||||
|
'django.contrib.auth',
|
||||||
|
'django.contrib.contenttypes',
|
||||||
|
'django.contrib.sessions',
|
||||||
|
'django.contrib.messages',
|
||||||
|
'django.contrib.staticfiles',
|
||||||
|
'anymail',
|
||||||
|
]
|
||||||
|
|
||||||
|
MIDDLEWARE = [
|
||||||
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
|
]
|
||||||
|
|
||||||
|
ROOT_URLCONF = 'tests.test_settings.urls'
|
||||||
|
|
||||||
|
TEMPLATES = [
|
||||||
|
{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'DIRS': [],
|
||||||
|
'APP_DIRS': True,
|
||||||
|
'OPTIONS': {
|
||||||
|
'context_processors': [
|
||||||
|
'django.template.context_processors.debug',
|
||||||
|
'django.template.context_processors.request',
|
||||||
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
WSGI_APPLICATION = 'tests.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
|
# Database
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#databases
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Password validation
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Internationalization
|
||||||
|
# https://docs.djangoproject.com/en/dev/topics/i18n/
|
||||||
|
|
||||||
|
LANGUAGE_CODE = 'en-us'
|
||||||
|
|
||||||
|
TIME_ZONE = 'UTC'
|
||||||
|
|
||||||
|
USE_I18N = True
|
||||||
|
|
||||||
|
USE_L10N = True
|
||||||
|
|
||||||
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
|
# Static files (CSS, JavaScript, Images)
|
||||||
|
# https://docs.djangoproject.com/en/dev/howto/static-files/
|
||||||
|
|
||||||
|
STATIC_URL = '/static/'
|
||||||
102
tox.ini
Normal file
102
tox.ini
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
[tox]
|
||||||
|
envlist =
|
||||||
|
# Test these environments first, to catch most errors early...
|
||||||
|
lint
|
||||||
|
django20-py36
|
||||||
|
django18-py27
|
||||||
|
docs
|
||||||
|
# ... then test all the other supported combinations:
|
||||||
|
django20-py{35,py3}
|
||||||
|
django111-py{27,34,35,36,py2}
|
||||||
|
django110-py{27,34,35,py2}
|
||||||
|
django19-py{27,34,35,py2}
|
||||||
|
django18-py{33,34,35,py2}
|
||||||
|
# ... then prereleases (if available):
|
||||||
|
#django21-py{35,36}
|
||||||
|
djangoMaster-py{36,37}
|
||||||
|
|
||||||
|
[testenv]
|
||||||
|
deps =
|
||||||
|
django18: django>=1.8,<1.9
|
||||||
|
django19: django>=1.9,<1.10
|
||||||
|
django110: django>=1.10,<1.11
|
||||||
|
django111: django>=1.11,<1.12
|
||||||
|
django20: django>=2.0,<2.1
|
||||||
|
django21: django>=2.1a1
|
||||||
|
djangoMaster: https://github.com/django/django/tarball/master
|
||||||
|
# testing dependencies (duplicates setup.py tests_require):
|
||||||
|
mock
|
||||||
|
sparkpost
|
||||||
|
ignore_outcome =
|
||||||
|
django21: True
|
||||||
|
djangoMaster: True
|
||||||
|
usedevelop = True
|
||||||
|
args_are_paths = False
|
||||||
|
commands =
|
||||||
|
python --version
|
||||||
|
# pip install .[mailgun,...,sparkpost] ## usedevelop=True + manual deps is much faster on repeat runs
|
||||||
|
python runtests.py {posargs}
|
||||||
|
passenv =
|
||||||
|
RUN_LIVE_TESTS
|
||||||
|
CONTINUOUS_INTEGRATION
|
||||||
|
MAILGUN_TEST_*
|
||||||
|
MAILJET_TEST_*
|
||||||
|
MANDRILL_TEST_*
|
||||||
|
POSTMARK_TEST_*
|
||||||
|
SENDINBLUE_TEST_*
|
||||||
|
SENDGRID_TEST_*
|
||||||
|
SPARKPOST_TEST_*
|
||||||
|
|
||||||
|
[testenv:lint]
|
||||||
|
basepython = python3
|
||||||
|
skip_install = True
|
||||||
|
passenv =
|
||||||
|
CONTINUOUS_INTEGRATION
|
||||||
|
# (but not any of the live test API keys)
|
||||||
|
deps =
|
||||||
|
flake8
|
||||||
|
commands =
|
||||||
|
python --version
|
||||||
|
flake8 --version
|
||||||
|
flake8
|
||||||
|
|
||||||
|
[testenv:docs]
|
||||||
|
basepython = python3
|
||||||
|
skip_install = True
|
||||||
|
passenv =
|
||||||
|
CONTINUOUS_INTEGRATION
|
||||||
|
# (but not any of the live test API keys)
|
||||||
|
setenv =
|
||||||
|
DOCS_BUILD_DIR={envdir}/_html
|
||||||
|
whitelist_externals = /bin/bash
|
||||||
|
deps =
|
||||||
|
sphinx
|
||||||
|
sphinx-rtd-theme
|
||||||
|
commands =
|
||||||
|
# Verify README.rst as used in setup.py long_description:
|
||||||
|
python setup.py check --restructuredtext --strict
|
||||||
|
# Build and verify docs:
|
||||||
|
sphinx-build -W -b dirhtml docs {env:DOCS_BUILD_DIR}
|
||||||
|
# Build README.rst into html:
|
||||||
|
/bin/bash -c 'python setup.py --long-description \
|
||||||
|
| rst2html.py --config=docs/_readme/docutils.cfg \
|
||||||
|
> {env:DOCS_BUILD_DIR}/readme.html'
|
||||||
|
|
||||||
|
[travis]
|
||||||
|
unignore_outcomes = True
|
||||||
|
python =
|
||||||
|
3.6: py36, lint, docs
|
||||||
|
|
||||||
|
[travis:env]
|
||||||
|
DJANGO =
|
||||||
|
1.8: django18
|
||||||
|
1.9: django19
|
||||||
|
1.10: django110
|
||||||
|
1.11: django111
|
||||||
|
2.0: django20
|
||||||
|
2.1: django21
|
||||||
|
master: djangoMaster
|
||||||
|
LINT_AND_DOCS =
|
||||||
|
true: lint, docs
|
||||||
|
docs: docs
|
||||||
|
lint: lint
|
||||||
Reference in New Issue
Block a user