diff --git a/.gitignore b/.gitignore index d96c75c..1c17081 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ htmlselenium *.pyc dist *egg-info +public +_modules diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..69daa80 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,112 @@ +# turn on all of the security pipelines +include: + - template: Dependency-Scanning.gitlab-ci.yml + - template: SAST.gitlab-ci.yml + - template: DAST.gitlab-ci.yml + - template: License-Scanning.gitlab-ci.yml + +variables: + # Disable Docker-in-Docker so gemnasium scan uses build container + DS_DISABLE_DIND: "true" + +dependency_scanning: + before_script: + # Install system dependencies required by `pip install requirements.txt` + - apt-get install -y python3-dev postgresql libpq-dev + +test: + stage: test + image: centos:7 + services: + - postgres:latest + variables: + PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" + POSTGRES_DB: ci + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_HOST_AUTH_METHOD: trust + DATABASE_URL: "postgresql://postgres:postgres@postgres:5432/ci" + DATABASE_HOST: postgres + DATABASE_NAME: $POSTGRES_DB + DATABASE_USER: $POSTGRES_USER + DATABASE_PASSWORD: $POSTGRES_PASSWORD + cache: + paths: + - .cache/pip + before_script: + # install required base packages + - yum -y install make gcc python3 python3-devel python3-pip git tree wget unzip + postgresql-devel postgresql-server postgresql-contrib + # install chrome + - wget https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm + - yum -y localinstall google-chrome-stable_current_x86_64.rpm + # install latest chromedriver + - export LATEST_RELEASE=$(curl http://chromedriver.storage.googleapis.com/LATEST_RELEASE) + - wget https://chromedriver.storage.googleapis.com/$LATEST_RELEASE/chromedriver_linux64.zip + - mkdir chromedriver + - unzip chromedriver_linux64.zip -d chromedriver + - export PATH=$PATH:$PWD/chromedriver + # configure python 3 virtualenv + - pip3 install virtualenv + - virtualenv venv + - source venv/bin/activate + # install package requirements + - make reqs + script: + - python -V + - export PGPASSWORD=$POSTGRES_PASSWORD + - psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT 'OK' AS status;" + - make all + artifacts: + paths: + - public + rules: + - if: $CI_COMMIT_BRANCH != "master" + +# deploy documentation to pages +pages: + stage: deploy + image: centos:7 + services: + - postgres:latest + variables: + PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" + POSTGRES_DB: ci + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_HOST_AUTH_METHOD: trust + DATABASE_URL: "postgresql://postgres:postgres@postgres:5432/ci" + DATABASE_HOST: postgres + DATABASE_NAME: $POSTGRES_DB + DATABASE_USER: $POSTGRES_USER + DATABASE_PASSWORD: $POSTGRES_PASSWORD + cache: + paths: + - .cache/pip + before_script: + # install required base packages + - yum -y install make gcc python3 python3-devel python3-pip git tree wget unzip + postgresql-devel postgresql-server postgresql-contrib + # install chrome + - wget https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm + - yum -y localinstall google-chrome-stable_current_x86_64.rpm + # install latest chromedriver + - export LATEST_RELEASE=$(curl http://chromedriver.storage.googleapis.com/LATEST_RELEASE) + - wget https://chromedriver.storage.googleapis.com/$LATEST_RELEASE/chromedriver_linux64.zip + - mkdir chromedriver + - unzip chromedriver_linux64.zip -d chromedriver + - export PATH=$PATH:$PWD/chromedriver + # configure python 3 virtualenv + - pip3 install virtualenv + - virtualenv venv + - source venv/bin/activate + # install package requirements + - make reqs + script: + - python -V + - make all + artifacts: + paths: + - public + rules: + - if: $CI_COMMIT_BRANCH == "master" diff --git a/.travis.yml b/.travis.yml index bba5398..684bdb0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,5 @@ sudo: required language: python -python: - - "2.7" addons: chrome: stable firefox: latest diff --git a/CHANGES b/CHANGES index 95677f2..6f3a7a0 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +1.3.2 (2020-03-24): + + * Update django-selenium-testcase for python3 + 1.3.1 (2019-07-08): * Add method hover_over_button to the NavigationTestMixin to diff --git a/Makefile b/Makefile index 9fe837e..0f6ed39 100644 --- a/Makefile +++ b/Makefile @@ -1,75 +1,115 @@ -.PHONY: check-venv test pep8 clean coverage - -# Clean out potentially stale pyc files +# You can set these variables from the command line +# arguments for sphinx-apidoc autodoc builds + +SPHINXOPTS ?= -n +SPHINXBUILD ?= sphinx-build +SOURCEDIR ?= docs +BUILDDIR ?= public +APIOPTS ?= -f -e +APIDOCBUILD ?= sphinx-apidoc +APISOURCE ?= selenium_testcase +APIDEST ?= docs/_modules + +# Put it first so that "make" without argument is like "make help". +.PHONY: help +help: + @echo "*** Help ***" + @echo " all make clean pep8 flake8 test coverage docs" + @echo " clean remove generaed build files" + @echo " coverage run tests with code coverage being computed" + @echo " reqs update your requirements from requirements.txt" + @echo " reqs-update compile requirements.txt from requirements.in" + @echo " test run tests" + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +# run a complete test suite +.PHONY: all +all: + @echo -e "section_start:`date +%s`:make_clean\r\e[0KMake clean" + make clean + @echo -e "section_end:`date +%s`:make_clean\r\e[0K" + @echo -e "section_start:`date +%s`:make_pycodestyle\r\e[0KMake pycodestyle" + make pycodestyle + @echo -e "section_end:`date +%s`:make_pycodestyle\r\e[0K" + @echo -e "section_start:`date +%s`:make_flake8\r\e[0Kmake flake8" + make flake8 + @echo -e "section_end:`date +%s`:make_flake8\r\e[0K" + @echo -e "section_start:`date +%s`:make_coverage\r\e[0Kmake coverage" + make coverage + make tree + @echo -e "section_end:`date +%s`:make_coverage\r\e[0K" + @echo -e "section_start:`date +%s`:make_docs\r\e[0Kmake docs" + make docs + @echo -e "section_end:`date +%s`:make_docs\r\e[0K" + +# make all docs +.PHONY: docs +docs: + make linkcheck + make html + +# clear the generated files +.PHONY: clean clean: - find . -name "*.pyc" -exec rm {} \; - -# Check that virtualenv is enabled -check-venv: -ifndef VIRTUAL_ENV - $(error VIRTUAL_ENV is undefined, try "workon" command) -endif - -# Install pip requirements.txt file -reqs: check-venv - pip install --upgrade -r requirements.txt - -PEP8_OPTS=--repeat --exclude=static,migrations,js,doc --show-source - -pep8: - pep8 $(PEP8_OPTS) . - -FLAKE8_OPTS=--exclude=static,migrations,js,doc + rm -rf $(BUILDDIR)/* $(APIDEST) + find . -name __pycache__ | xargs rm -rf + +# install requirements using pip +.PHONY: reqs +reqs: + pip install --require-hashes --upgrade -r requirements.txt + +# use pip-compile to lock down requirements +.PHONY: update-reqs reqs-update +update-reqs reqs-update: + pip-compile --no-index --generate-hashes --allow-unsafe + +# pep8 +.PHONY: pep8 pycodestyle +PEP8_OPTS ?= --repeat --exclude=static,migrations,js,docs,venv --show-source +pep8 pycodestyle: + pycodestyle $(PEP8_OPTS) . + +# flake8 +.PHONY: flake8 +FLAKE8_OPTS ?= --exclude=static,migrations,js,docs,venv flake8: flake8 $(FLAKE8_OPTS) . -# -# Unit tests -# +# test +.PHONY: test +TEST_OPTS ?= -v 2 +test: + python ./manage.py test $(TEST_OPTS) -test: check-venv clean - python ./manage.py test --keepdb -v 2 - -travis-tests: check-venv - @echo "travis_fold:start:flake8" - make flake8 - @echo "travis_fold:end:flake8" - - @echo "travis_fold:start:pip_freeze" - pip freeze -l - @echo "travis_fold:end:pip_freeze" - - coverage erase - @echo "travis_fold:start:test" - coverage run $(COVERAGE_ARGS) ./manage.py test --keepdb -v 2 - @echo "travis_fold:end:test" - - @echo "travis_fold:start:coverage" - coverage report - coverage html - @echo "travis_fold:end:coverage" - -# -# Run a django instance with a test project for the current app -# +# tree +.PHONY: tree +tree: + cd public/htmlselenium; tree -h -H . > index.html +# run .PHONY: run -run: check-venv clean - python ./manage.py runserver +RUN_OPTS ?= +run: + python ./manage.py $(RUN_OPTS) runserver -# -# Code coverage -# +# coverage -COVERAGE_ARGS=--source=selenium_testcase --omit=/tests - -coverage: check-venv +COVERAGE_ARGS ?= --source=$(APISOURCE) --omit=/tests +COVERAGE_OPTS ?= --keepdb -v 2 +COVERAGE_REPORT_OPTS ?= -m +COVERAGE_HTML_OPTS ?= -d public/coverage +coverage: coverage erase - coverage run $(COVERAGE_ARGS) ./manage.py test --keepdb -v 2 - coverage report - coverage html - @echo "See ./htmlcov/index.html for coverage report" - -develop-%: check-venv - cd ../$*; python setup.py develop -N - + coverage run $(COVERAGE_ARGS) ./manage.py test $(COVERAGE_OPTS) + coverage report $(COVERAGE_REPORT_OPTS) + coverage html $(COVERAGE_HTML_OPTS) + @echo "See ./public/coverage/index.html for coverage report" + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: +ifdef APISOURCE + @$(APIDOCBUILD) -o "$(APIDEST)" "$(APISOURCE)" $(APIOPTS) +endif + @$(SPHINXBUILD) -b $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/README.md b/README.md index 69598c8..8aa47f4 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,18 @@ django-selenium-testcase ======================== -[![Build Status](https://travis-ci.org/nimbis/django-selenium-testcase.svg?branch=master)](https://travis-ci.org/nimbis/django-selenium-testcase) +[![pipeline status](https://gitlab.nimbis.io/nimbis/sites/django-selenium-testcase/badges/master/pipeline.svg)](https://gitlab.nimbis.io/nimbis/sites/django-selenium-testcase/-/commits/master) +[![coverage report](https://gitlab.nimbis.io/nimbis/sites/django-selenium-testcase/badges/master/coverage.svg)](https://gitlab.nimbis.io/nimbis/sites/django-selenium-testcase/-/commits/master) +Quick Links +----------- + +* [Online Documentation](https://nimbis.pages.nimbis.io/sites/django-selenium-testcase/index.html) +* [Coverage Report](https://nimbis.pages.nimbis.io/sites/django-selenium-testcase/coverage/index.html) +* [Selenium Test](https://nimbis.pages.nimbis.io/sites/django-selenium-testcase/htmlselenium/index.html) + +Introduction +------------ This repository implements a simple subclass of Django LiveServerTestCase that enables selenium testing of the Django live server. Rather than relying on Gherkin syntax found in Lettuce and Aloe tools, this package favors of python diff --git a/docs/README.md b/docs/README.md new file mode 120000 index 0000000..32d46ee --- /dev/null +++ b/docs/README.md @@ -0,0 +1 @@ +../README.md \ No newline at end of file diff --git a/docs/_templates/breadcrumbs.html b/docs/_templates/breadcrumbs.html new file mode 100644 index 0000000..4d9edcb --- /dev/null +++ b/docs/_templates/breadcrumbs.html @@ -0,0 +1,29 @@ +{% extends "!breadcrumbs.html" %} + +{% block breadcrumbs_aside %} + {% if selenium_url %} +
  • + +
  • + {% endif %} + {% if coverage_url %} +
  • + +
  • + {% endif %} + {% if pdf_url %} +
  • + +
  • + {% endif %} + {% if ide_url %} +
  • + +
  • + {% endif %} + {% if gitlab_url %} +
  • + +
  • + {% endif %} +{% endblock %} diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..88b6eea --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,206 @@ +# -*- coding: utf-8 -*- +# +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# 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. + +import os +import sys +import django +sys.path.insert(0, os.path.abspath('..')) +os.environ['DJANGO_SETTINGS_MODULE'] = 'test_project.settings' +django.setup() + +# -- Project information ----------------------------------------------------- + +project = 'Django Selenium Testcase' +project_slug = 'django_selenium_testcase' +copyright = '2020, Nimbis Services, Inc.' +author = 'Nimbis Services, Inc.' + +# The short X.Y version +version = u'' +# The full version, including alpha/beta/rc tags +release = u'' + +gitlab_group = 'nimbis' +gitlab_project = 'templates/documentation' +gitlab_base = 'https://gitlab.nimbis.io/' +pages_base = 'https://nimbis.pages.nimbis.io/' + +# build up links for pages view, gitlab view, and edit on gitlab +# make these None to disable in your template + +pages_url = pages_base + gitlab_project + '/' +gitlab_url = '/'.join( + (gitlab_base, gitlab_group, gitlab_project)) + '/-/blob/master/docs/' +ide_url = gitlab_base + '/'.join( + ('-/ide/project', gitlab_group, gitlab_project, 'edit/master/-/docs/')) + +# pdf_url = None +pdf_url = pages_url + project_slug + '.pdf' + +coverage_url = None +# coverage_url = pages_url + 'coverage/index.html' + +selenium_url = None +# selenium_url = pages_url + 'htmlselenium/index.html' + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# 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.coverage', + 'sphinx.ext.napoleon', + 'sphinx.ext.doctest', + 'sphinx.ext.intersphinx', + 'sphinx.ext.todo', + 'sphinx_git', + 'docxbuilder', + 'recommonmark', +] + +docx_update_fields = True; + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = { + '.rst': 'restructuredtext', + '.txt': 'markdown', + '.md': 'markdown', +} + +# The master toctree document. +master_doc = 'index' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [u'_build', 'Thumbs.db', '.DS_Store'] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = None + + +# -- 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 = "sphinx_rtd_theme" +html_theme_path = ["_themes", ] +html_logo = "logo.png" +html_favicon = "favicon.ico" + +# -- pass some context variables to the context + +html_context = { + 'gitlab_url': gitlab_url, + 'ide_url': ide_url, + 'pages_url': pages_url, + 'pdf_url': pdf_url, + 'coverage_url': coverage_url, + 'selenium_url': selenium_url, +} + +# 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 = { + 'canonical_url': '', + 'analytics_id': '', + 'logo_only': False, + 'display_version': True, + 'prev_next_buttons_location': 'bottom', + 'style_external_links': False, + 'style_nav_header_background': '#343131', + # Toc options + 'collapse_navigation': True, + 'sticky_navigation': True, + 'navigation_depth': 4, + 'includehidden': True, + 'titles_only': False +} + +# 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 = [] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +html_sidebars = { + "**": [ + "about.html", + "navigation.html", + "relations.html", + "searchbox.html", + "donate.html", + ] +} + + +# -- Extension configuration ------------------------------------------------- + + +# -- Options for intersphinx extension --------------------------------------- + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'https://docs.python.org/': None} + +# -- Options for todo extension ---------------------------------------------- + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True +todo_emit_warnings = False + +# -- Options for link check -------------------------------------------------- + +linkcheck_ignore = [ + r'http://localhost:\d+/', + r'https://nimbis.sharepoint.com/.*$', + r'https://github.com/nimbis/.*$', + r'https://account.activedirectory.windowsazure.com/.*$' +] + +# -- Nitpick Ignore ---------------------------------------------------------- + +nitpick_ignore = [ + ('py:class', 'django.apps.config.AppConfig'), + ('py:class', 'django.contrib.staticfiles.testing.StaticLiveServerTestCase'), +] diff --git a/docs/favicon.ico b/docs/favicon.ico new file mode 100644 index 0000000..bb8c2b6 Binary files /dev/null and b/docs/favicon.ico differ diff --git a/docs/images/using-documentation-template.gif b/docs/images/using-documentation-template.gif new file mode 100644 index 0000000..144fa63 Binary files /dev/null and b/docs/images/using-documentation-template.gif differ diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..8ca2394 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,41 @@ +Welcome to Django Selenium TestCase +=================================== + + +Contents +======== + +.. toctree:: + :maxdepth: 2 + :titlesonly: + :glob: + + Quick Start + _modules/modules.rst + +Recent Changes +============== + +See the `source changelog `_ +for a complete change history. + +.. git_changelog:: + :detailed-message-pre: True + +To-Do List +========== + +The following to-do items exist across the document. + +----------------- + +.. todolist:: + +----------------- + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/logo.png b/docs/logo.png new file mode 100644 index 0000000..297a742 Binary files /dev/null and b/docs/logo.png differ diff --git a/manage.py b/manage.py index 29ba849..2753b50 100755 --- a/manage.py +++ b/manage.py @@ -1,22 +1,21 @@ #!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" import os import sys -if __name__ == "__main__": - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project.settings") + +def main(): + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'test_project.settings') try: from django.core.management import execute_from_command_line - except ImportError: - # The above import may fail for some other reason. Ensure that the - # issue is really that Django is missing to avoid masking other - # exceptions on Python 2. - try: - import django # noqa - except ImportError: - raise ImportError( - "Couldn't import Django. Are you sure it's installed and " - "available on your PYTHONPATH environment variable? Did you " - "forget to activate a virtual environment?" - ) - raise + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/requirements.in b/requirements.in new file mode 100644 index 0000000..dfa330f --- /dev/null +++ b/requirements.in @@ -0,0 +1,16 @@ +coverage +Django<3.0 +docxbuilder +flake8 +pycodestyle +pip +pip-tools +psycopg2 +recommonmark +selenium +setuptools +six +sphinx +sphinx-git +sphinx_rtd_theme +sphinxcontrib-napoleon diff --git a/requirements.txt b/requirements.txt index d7e3703..218ba77 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,327 @@ --e . -pep8 -flake8 -coverage -Django<2.0 +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile --allow-unsafe --generate-hashes --no-index +# +alabaster==0.7.12 \ + --hash=sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359 \ + --hash=sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02 \ + # via sphinx +babel==2.8.0 \ + --hash=sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38 \ + --hash=sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4 \ + # via sphinx +certifi==2020.4.5.2 \ + --hash=sha256:5ad7e9a056d25ffa5082862e36f119f7f7cec6457fa07ee2f8c339814b80c9b1 \ + --hash=sha256:9cd41137dc19af6a5e03b630eefe7d1f458d964d406342dd3edf625839b944cc \ + # via requests +chardet==3.0.4 \ + --hash=sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae \ + --hash=sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691 \ + # via requests +click==7.1.2 \ + --hash=sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a \ + --hash=sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc \ + # via pip-tools +commonmark==0.9.1 \ + --hash=sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60 \ + --hash=sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9 \ + # via recommonmark +coverage==5.1 \ + --hash=sha256:00f1d23f4336efc3b311ed0d807feb45098fc86dee1ca13b3d6768cdab187c8a \ + --hash=sha256:01333e1bd22c59713ba8a79f088b3955946e293114479bbfc2e37d522be03355 \ + --hash=sha256:0cb4be7e784dcdc050fc58ef05b71aa8e89b7e6636b99967fadbdba694cf2b65 \ + --hash=sha256:0e61d9803d5851849c24f78227939c701ced6704f337cad0a91e0972c51c1ee7 \ + --hash=sha256:1601e480b9b99697a570cea7ef749e88123c04b92d84cedaa01e117436b4a0a9 \ + --hash=sha256:2742c7515b9eb368718cd091bad1a1b44135cc72468c731302b3d641895b83d1 \ + --hash=sha256:2d27a3f742c98e5c6b461ee6ef7287400a1956c11421eb574d843d9ec1f772f0 \ + --hash=sha256:402e1744733df483b93abbf209283898e9f0d67470707e3c7516d84f48524f55 \ + --hash=sha256:5c542d1e62eece33c306d66fe0a5c4f7f7b3c08fecc46ead86d7916684b36d6c \ + --hash=sha256:5f2294dbf7875b991c381e3d5af2bcc3494d836affa52b809c91697449d0eda6 \ + --hash=sha256:6402bd2fdedabbdb63a316308142597534ea8e1895f4e7d8bf7476c5e8751fef \ + --hash=sha256:66460ab1599d3cf894bb6baee8c684788819b71a5dc1e8fa2ecc152e5d752019 \ + --hash=sha256:782caea581a6e9ff75eccda79287daefd1d2631cc09d642b6ee2d6da21fc0a4e \ + --hash=sha256:79a3cfd6346ce6c13145731d39db47b7a7b859c0272f02cdb89a3bdcbae233a0 \ + --hash=sha256:7a5bdad4edec57b5fb8dae7d3ee58622d626fd3a0be0dfceda162a7035885ecf \ + --hash=sha256:8fa0cbc7ecad630e5b0f4f35b0f6ad419246b02bc750de7ac66db92667996d24 \ + --hash=sha256:a027ef0492ede1e03a8054e3c37b8def89a1e3c471482e9f046906ba4f2aafd2 \ + --hash=sha256:a3f3654d5734a3ece152636aad89f58afc9213c6520062db3978239db122f03c \ + --hash=sha256:a82b92b04a23d3c8a581fc049228bafde988abacba397d57ce95fe95e0338ab4 \ + --hash=sha256:acf3763ed01af8410fc36afea23707d4ea58ba7e86a8ee915dfb9ceff9ef69d0 \ + --hash=sha256:adeb4c5b608574a3d647011af36f7586811a2c1197c861aedb548dd2453b41cd \ + --hash=sha256:b83835506dfc185a319031cf853fa4bb1b3974b1f913f5bb1a0f3d98bdcded04 \ + --hash=sha256:bb28a7245de68bf29f6fb199545d072d1036a1917dca17a1e75bbb919e14ee8e \ + --hash=sha256:bf9cb9a9fd8891e7efd2d44deb24b86d647394b9705b744ff6f8261e6f29a730 \ + --hash=sha256:c317eaf5ff46a34305b202e73404f55f7389ef834b8dbf4da09b9b9b37f76dd2 \ + --hash=sha256:dbe8c6ae7534b5b024296464f387d57c13caa942f6d8e6e0346f27e509f0f768 \ + --hash=sha256:de807ae933cfb7f0c7d9d981a053772452217df2bf38e7e6267c9cbf9545a796 \ + --hash=sha256:dead2ddede4c7ba6cb3a721870f5141c97dc7d85a079edb4bd8d88c3ad5b20c7 \ + --hash=sha256:dec5202bfe6f672d4511086e125db035a52b00f1648d6407cc8e526912c0353a \ + --hash=sha256:e1ea316102ea1e1770724db01998d1603ed921c54a86a2efcb03428d5417e489 \ + --hash=sha256:f90bfc4ad18450c80b024036eaf91e4a246ae287701aaa88eaebebf150868052 \ + # via -r requirements.in +django==2.2.13 \ + --hash=sha256:84f370f6acedbe1f3c41e1a02de44ac206efda3355e427139ecb785b5f596d80 \ + --hash=sha256:e8fe3c2b2212dce6126becab7a693157f1a441a07b62ec994c046c76af5bb66d \ + # via -r requirements.in +docutils==0.16 \ + --hash=sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af \ + --hash=sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc \ + # via recommonmark, sphinx +docxbuilder==1.2.0 \ + --hash=sha256:06a1cc585f06f1ff6810000acf4f23c7f52c504cd3b980f92ce4343882ce2b0d \ + --hash=sha256:a458e050d5f5689c17eba4c2680e551b1a22d00380a81ce72b15a5bde439c4bd \ + # via -r requirements.in +flake8==3.8.2 \ + --hash=sha256:c69ac1668e434d37a2d2880b3ca9aafd54b3a10a3ac1ab101d22f29e29cf8634 \ + --hash=sha256:ccaa799ef9893cebe69fdfefed76865aeaefbb94cb8545617b2298786a4de9a5 \ + # via -r requirements.in +gitdb==4.0.5 \ + --hash=sha256:91f36bfb1ab7949b3b40e23736db18231bf7593edada2ba5c3a174a7b23657ac \ + --hash=sha256:c9e1f2d0db7ddb9a704c2a0217be31214e91a4fe1dea1efad19ae42ba0c285c9 \ + # via gitpython +gitpython==3.1.3 \ + --hash=sha256:e107af4d873daed64648b4f4beb89f89f0cfbe3ef558fc7821ed2331c2f8da1a \ + --hash=sha256:ef1d60b01b5ce0040ad3ec20bc64f783362d41fa0822a2742d3586e1f49bb8ac \ + # via sphinx-git +idna==2.9 \ + --hash=sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb \ + --hash=sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa \ + # via requests +imagesize==1.2.0 \ + --hash=sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1 \ + --hash=sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1 \ + # via sphinx +importlib-metadata==1.6.1 \ + --hash=sha256:0505dd08068cfec00f53a74a0ad927676d7757da81b7436a6eefe4c7cf75c545 \ + --hash=sha256:15ec6c0fd909e893e3a08b3a7c76ecb149122fb14b7efe1199ddd4c7c57ea958 \ + # via flake8 +jinja2==2.11.2 \ + --hash=sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0 \ + --hash=sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035 \ + # via sphinx +lxml==4.5.1 \ + --hash=sha256:06748c7192eab0f48e3d35a7adae609a329c6257495d5e53878003660dc0fec6 \ + --hash=sha256:0790ddca3f825dd914978c94c2545dbea5f56f008b050e835403714babe62a5f \ + --hash=sha256:1aa7a6197c1cdd65d974f3e4953764eee3d9c7b67e3966616b41fab7f8f516b7 \ + --hash=sha256:22c6d34fdb0e65d5f782a4d1a1edb52e0a8365858dafb1c08cb1d16546cf0786 \ + --hash=sha256:2754d4406438c83144f9ffd3628bbe2dcc6d62b20dbc5c1ec4bc4385e5d44b42 \ + --hash=sha256:27ee0faf8077c7c1a589573b1450743011117f1aa1a91d5ae776bbc5ca6070f2 \ + --hash=sha256:2b02c106709466a93ed424454ce4c970791c486d5fcdf52b0d822a7e29789626 \ + --hash=sha256:2d1ddce96cf15f1254a68dba6935e6e0f1fe39247de631c115e84dd404a6f031 \ + --hash=sha256:4f282737d187ae723b2633856085c31ae5d4d432968b7f3f478a48a54835f5c4 \ + --hash=sha256:51bb4edeb36d24ec97eb3e6a6007be128b720114f9a875d6b370317d62ac80b9 \ + --hash=sha256:7eee37c1b9815e6505847aa5e68f192e8a1b730c5c7ead39ff317fde9ce29448 \ + --hash=sha256:7fd88cb91a470b383aafad554c3fe1ccf6dfb2456ff0e84b95335d582a799804 \ + --hash=sha256:9144ce36ca0824b29ebc2e02ca186e54040ebb224292072250467190fb613b96 \ + --hash=sha256:925baf6ff1ef2c45169f548cc85204433e061360bfa7d01e1be7ae38bef73194 \ + --hash=sha256:a636346c6c0e1092ffc202d97ec1843a75937d8c98aaf6771348ad6422e44bb0 \ + --hash=sha256:a87dbee7ad9dce3aaefada2081843caf08a44a8f52e03e0a4cc5819f8398f2f4 \ + --hash=sha256:a9e3b8011388e7e373565daa5e92f6c9cb844790dc18e43073212bb3e76f7007 \ + --hash=sha256:afb53edf1046599991fb4a7d03e601ab5f5422a5435c47ee6ba91ec3b61416a6 \ + --hash=sha256:b26719890c79a1dae7d53acac5f089d66fd8cc68a81f4e4bd355e45470dc25e1 \ + --hash=sha256:b7462cdab6fffcda853338e1741ce99706cdf880d921b5a769202ea7b94e8528 \ + --hash=sha256:b77975465234ff49fdad871c08aa747aae06f5e5be62866595057c43f8d2f62c \ + --hash=sha256:c47a8a5d00060122ca5908909478abce7bbf62d812e3fc35c6c802df8fb01fe7 \ + --hash=sha256:c79e5debbe092e3c93ca4aee44c9a7631bdd407b2871cb541b979fd350bbbc29 \ + --hash=sha256:d8d40e0121ca1606aa9e78c28a3a7d88a05c06b3ca61630242cded87d8ce55fa \ + --hash=sha256:ee2be8b8f72a2772e72ab926a3bccebf47bb727bda41ae070dc91d1fb759b726 \ + --hash=sha256:f95d28193c3863132b1f55c1056036bf580b5a488d908f7d22a04ace8935a3a9 \ + --hash=sha256:fadd2a63a2bfd7fb604508e553d1cf68eca250b2fbdbd81213b5f6f2fbf23529 \ + # via docxbuilder +markupsafe==1.1.1 \ + --hash=sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473 \ + --hash=sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161 \ + --hash=sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235 \ + --hash=sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5 \ + --hash=sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42 \ + --hash=sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff \ + --hash=sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b \ + --hash=sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1 \ + --hash=sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e \ + --hash=sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183 \ + --hash=sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66 \ + --hash=sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b \ + --hash=sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1 \ + --hash=sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15 \ + --hash=sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1 \ + --hash=sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e \ + --hash=sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b \ + --hash=sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905 \ + --hash=sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735 \ + --hash=sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d \ + --hash=sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e \ + --hash=sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d \ + --hash=sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c \ + --hash=sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21 \ + --hash=sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2 \ + --hash=sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5 \ + --hash=sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b \ + --hash=sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6 \ + --hash=sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f \ + --hash=sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f \ + --hash=sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2 \ + --hash=sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7 \ + --hash=sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be \ + # via jinja2 +mccabe==0.6.1 \ + --hash=sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42 \ + --hash=sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f \ + # via flake8 +packaging==20.4 \ + --hash=sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8 \ + --hash=sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181 \ + # via sphinx +pillow==7.1.2 \ + --hash=sha256:04766c4930c174b46fd72d450674612ab44cca977ebbcc2dde722c6933290107 \ + --hash=sha256:0e2a3bceb0fd4e0cb17192ae506d5f082b309ffe5fc370a5667959c9b2f85fa3 \ + --hash=sha256:0f01e63c34f0e1e2580cc0b24e86a5ccbbfa8830909a52ee17624c4193224cd9 \ + --hash=sha256:12e4bad6bddd8546a2f9771485c7e3d2b546b458ae8ff79621214119ac244523 \ + --hash=sha256:1f694e28c169655c50bb89a3fa07f3b854d71eb47f50783621de813979ba87f3 \ + --hash=sha256:3d25dd8d688f7318dca6d8cd4f962a360ee40346c15893ae3b95c061cdbc4079 \ + --hash=sha256:4b02b9c27fad2054932e89f39703646d0c543f21d3cc5b8e05434215121c28cd \ + --hash=sha256:9744350687459234867cbebfe9df8f35ef9e1538f3e729adbd8fde0761adb705 \ + --hash=sha256:a0b49960110bc6ff5fead46013bcb8825d101026d466f3a4de3476defe0fb0dd \ + --hash=sha256:ae2b270f9a0b8822b98655cb3a59cdb1bd54a34807c6c56b76dd2e786c3b7db3 \ + --hash=sha256:b37bb3bd35edf53125b0ff257822afa6962649995cbdfde2791ddb62b239f891 \ + --hash=sha256:b532bcc2f008e96fd9241177ec580829dee817b090532f43e54074ecffdcd97f \ + --hash=sha256:b67a6c47ed963c709ed24566daa3f95a18f07d3831334da570c71da53d97d088 \ + --hash=sha256:b943e71c2065ade6fef223358e56c167fc6ce31c50bc7a02dd5c17ee4338e8ac \ + --hash=sha256:ccc9ad2460eb5bee5642eaf75a0438d7f8887d484490d5117b98edd7f33118b7 \ + --hash=sha256:d23e2aa9b969cf9c26edfb4b56307792b8b374202810bd949effd1c6e11ebd6d \ + --hash=sha256:eaa83729eab9c60884f362ada982d3a06beaa6cc8b084cf9f76cae7739481dfa \ + --hash=sha256:ee94fce8d003ac9fd206496f2707efe9eadcb278d94c271f129ab36aa7181344 \ + --hash=sha256:f455efb7a98557412dc6f8e463c1faf1f1911ec2432059fa3e582b6000fc90e2 \ + --hash=sha256:f46e0e024346e1474083c729d50de909974237c72daca05393ee32389dabe457 \ + --hash=sha256:f54be399340aa602066adb63a86a6a5d4f395adfdd9da2b9a0162ea808c7b276 \ + --hash=sha256:f784aad988f12c80aacfa5b381ec21fd3f38f851720f652b9f33facc5101cf4d \ + # via docxbuilder +pip-tools==5.2.0 \ + --hash=sha256:be6190405e4206526607aa4813bd6d7a949e4fdc180d0db4f3221f3778846cf7 \ + --hash=sha256:edb4ed852d7283d33b9dfe7b59fe9786de716727cbef2326f2a1b03eb9a16ad6 \ + # via -r requirements.in +pockets==0.9.1 \ + --hash=sha256:68597934193c08a08eb2bf6a1d85593f627c22f9b065cc727a4f03f669d96d86 \ + --hash=sha256:9320f1a3c6f7a9133fe3b571f283bcf3353cd70249025ae8d618e40e9f7e92b3 \ + # via sphinxcontrib-napoleon +psycopg2==2.8.5 \ + --hash=sha256:132efc7ee46a763e68a815f4d26223d9c679953cd190f1f218187cb60decf535 \ + --hash=sha256:2327bf42c1744a434ed8ed0bbaa9168cac7ee5a22a9001f6fc85c33b8a4a14b7 \ + --hash=sha256:27c633f2d5db0fc27b51f1b08f410715b59fa3802987aec91aeb8f562724e95c \ + --hash=sha256:2c0afb40cfb4d53487ee2ebe128649028c9a78d2476d14a67781e45dc287f080 \ + --hash=sha256:2df2bf1b87305bd95eb3ac666ee1f00a9c83d10927b8144e8e39644218f4cf81 \ + --hash=sha256:440a3ea2c955e89321a138eb7582aa1d22fe286c7d65e26a2c5411af0a88ae72 \ + --hash=sha256:6a471d4d2a6f14c97a882e8d3124869bc623f3df6177eefe02994ea41fd45b52 \ + --hash=sha256:6b306dae53ec7f4f67a10942cf8ac85de930ea90e9903e2df4001f69b7833f7e \ + --hash=sha256:a0984ff49e176062fcdc8a5a2a670c9bb1704a2f69548bce8f8a7bad41c661bf \ + --hash=sha256:ac5b23d0199c012ad91ed1bbb971b7666da651c6371529b1be8cbe2a7bf3c3a9 \ + --hash=sha256:acf56d564e443e3dea152efe972b1434058244298a94348fc518d6dd6a9fb0bb \ + --hash=sha256:d3b29d717d39d3580efd760a9a46a7418408acebbb784717c90d708c9ed5f055 \ + --hash=sha256:f7d46240f7a1ae1dd95aab38bd74f7428d46531f69219954266d669da60c0818 \ + # via -r requirements.in +pycodestyle==2.6.0 \ + --hash=sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367 \ + --hash=sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e \ + # via -r requirements.in, flake8 +pyflakes==2.2.0 \ + --hash=sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92 \ + --hash=sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8 \ + # via flake8 +pygments==2.6.1 \ + --hash=sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44 \ + --hash=sha256:ff7a40b4860b727ab48fad6360eb351cc1b33cbf9b15a0f689ca5353e9463324 \ + # via sphinx +pyparsing==2.4.7 \ + --hash=sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1 \ + --hash=sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b \ + # via packaging +pytz==2020.1 \ + --hash=sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed \ + --hash=sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048 \ + # via babel, django +recommonmark==0.6.0 \ + --hash=sha256:29cd4faeb6c5268c633634f2d69aef9431e0f4d347f90659fd0aab20e541efeb \ + --hash=sha256:2ec4207a574289355d5b6ae4ae4abb29043346ca12cdd5f07d374dc5987d2852 \ + # via -r requirements.in +requests==2.23.0 \ + --hash=sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee \ + --hash=sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6 \ + # via sphinx +selenium==3.141.0 \ + --hash=sha256:2d7131d7bc5a5b99a2d9b04aaf2612c411b03b8ca1b1ee8d3de5845a9be2cb3c \ + --hash=sha256:deaf32b60ad91a4611b98d8002757f29e6f2c2d5fcaf202e1c9ad06d6772300d \ + # via -r requirements.in +six==1.15.0 \ + --hash=sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259 \ + --hash=sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced \ + # via -r requirements.in, docxbuilder, packaging, pip-tools, pockets, sphinx-git, sphinxcontrib-napoleon +smmap==3.0.4 \ + --hash=sha256:54c44c197c819d5ef1991799a7e30b662d1e520f2ac75c9efbeb54a742214cf4 \ + --hash=sha256:9c98bbd1f9786d22f14b3d4126894d56befb835ec90cef151af566c7e19b5d24 \ + # via gitdb +snowballstemmer==2.0.0 \ + --hash=sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0 \ + --hash=sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52 \ + # via sphinx +sphinx-git==11.0.0 \ + --hash=sha256:6bf9d837de108c79fb7db585ebd590fd48f4d1f830b540420d0ca675f3b9f800 \ + # via -r requirements.in +sphinx-rtd-theme==0.4.3 \ + --hash=sha256:00cf895504a7895ee433807c62094cf1e95f065843bf3acd17037c3e9a2becd4 \ + --hash=sha256:728607e34d60456d736cc7991fd236afb828b21b82f956c5ea75f94c8414040a \ + # via -r requirements.in +sphinx==3.0.4 \ + --hash=sha256:779a519adbd3a70fc7c468af08c5e74829868b0a5b34587b33340e010291856c \ + --hash=sha256:ea64df287958ee5aac46be7ac2b7277305b0381d213728c3a49d8bb9b8415807 \ + # via -r requirements.in, docxbuilder, recommonmark, sphinx-git, sphinx-rtd-theme +sphinxcontrib-applehelp==1.0.2 \ + --hash=sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a \ + --hash=sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58 \ + # via sphinx +sphinxcontrib-devhelp==1.0.2 \ + --hash=sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e \ + --hash=sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4 \ + # via sphinx +sphinxcontrib-htmlhelp==1.0.3 \ + --hash=sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f \ + --hash=sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b \ + # via sphinx +sphinxcontrib-jsmath==1.0.1 \ + --hash=sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178 \ + --hash=sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8 \ + # via sphinx +sphinxcontrib-napoleon==0.7 \ + --hash=sha256:407382beed396e9f2d7f3043fad6afda95719204a1e1a231ac865f40abcbfcf8 \ + --hash=sha256:711e41a3974bdf110a484aec4c1a556799eb0b3f3b897521a018ad7e2db13fef \ + # via -r requirements.in +sphinxcontrib-qthelp==1.0.3 \ + --hash=sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72 \ + --hash=sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6 \ + # via sphinx +sphinxcontrib-serializinghtml==1.1.4 \ + --hash=sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc \ + --hash=sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a \ + # via sphinx +sqlparse==0.3.1 \ + --hash=sha256:022fb9c87b524d1f7862b3037e541f68597a730a8843245c349fc93e1643dc4e \ + --hash=sha256:e162203737712307dfe78860cc56c8da8a852ab2ee33750e33aeadf38d12c548 \ + # via django +urllib3==1.25.9 \ + --hash=sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527 \ + --hash=sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115 \ + # via requests, selenium +zipp==3.1.0 \ + --hash=sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b \ + --hash=sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96 \ + # via importlib-metadata + +# The following packages are considered to be unsafe in a requirements file: +pip==20.1.1 \ + --hash=sha256:27f8dc29387dd83249e06e681ce087e6061826582198a425085e0bf4c1cf3a55 \ + --hash=sha256:b27c4dedae8c41aa59108f2fa38bf78e0890e590545bc8ece7cdceb4ba60f6e4 \ + # via -r requirements.in, pip-tools +setuptools==47.1.1 \ + --hash=sha256:145fa62b9d7bb544fce16e9b5a9bf4ab2032d2f758b7cd674af09a92736aff74 \ + --hash=sha256:74f33f44290f95c5c4a7c13ccc9d6d1a16837fe9dce0acf411dd244e7de95143 \ + # via -r requirements.in, sphinx diff --git a/selenium_testcase/testcases/__init__.py b/selenium_testcase/testcases/__init__.py index c26be84..7446d6e 100644 --- a/selenium_testcase/testcases/__init__.py +++ b/selenium_testcase/testcases/__init__.py @@ -1,9 +1,10 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import +from six.moves import reload_module as reload from django.contrib.staticfiles.testing import StaticLiveServerTestCase -from django.core.urlresolvers import clear_url_caches +from django.urls import clear_url_caches from selenium.webdriver.chrome.options import Options diff --git a/selenium_testcase/testcases/authentication.py b/selenium_testcase/testcases/authentication.py index 8d8bfbe..678a099 100644 --- a/selenium_testcase/testcases/authentication.py +++ b/selenium_testcase/testcases/authentication.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import +from builtins import str +from builtins import object from django.contrib.auth.models import User from django.contrib.sessions.models import Session @@ -8,7 +10,7 @@ from .utils import wait_for -class AuthenticationTestMixin: +class AuthenticationTestMixin(object): login_url = "/accounts/login/" login_username_field = "username" diff --git a/selenium_testcase/testcases/content.py b/selenium_testcase/testcases/content.py index 62145b3..2858310 100644 --- a/selenium_testcase/testcases/content.py +++ b/selenium_testcase/testcases/content.py @@ -1,13 +1,14 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import +from builtins import object from .utils import wait_for from selenium.common.exceptions import NoSuchElementException -class ContentTestMixin: +class ContentTestMixin(object): def should_see_immediately(self, text, **kwargs): """ Assert that DOM contains the given text. """ diff --git a/selenium_testcase/testcases/debug.py b/selenium_testcase/testcases/debug.py index 38a231c..c012084 100644 --- a/selenium_testcase/testcases/debug.py +++ b/selenium_testcase/testcases/debug.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import +from builtins import object import os import inspect @@ -15,7 +16,7 @@ ) -class DebugTestMixin: +class DebugTestMixin(object): """ Add convenience debug methods to selenium test cases. @@ -177,7 +178,7 @@ def render_log(self, template): 'text': self.get_visible_text()}) # write it to the file - self._selenium_log_file.write(html.encode('utf8')) + self._selenium_log_file.write(html) def render_entry_log(self): """ diff --git a/selenium_testcase/testcases/find.py b/selenium_testcase/testcases/find.py index 14118a0..cba1bda 100644 --- a/selenium_testcase/testcases/find.py +++ b/selenium_testcase/testcases/find.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import +from builtins import object from selenium.common.exceptions import NoSuchElementException @@ -11,7 +12,7 @@ ) -class FindTestMixin: +class FindTestMixin(object): # exit to debugger on missing element pdb_on_missing = PDB_ON_MISSING diff --git a/selenium_testcase/testcases/forms.py b/selenium_testcase/testcases/forms.py index e6e76d9..2076506 100644 --- a/selenium_testcase/testcases/forms.py +++ b/selenium_testcase/testcases/forms.py @@ -1,13 +1,14 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import +from builtins import object from selenium.webdriver.common.by import By from .utils import wait_for -class FormTestMixin: +class FormTestMixin(object): # default search element form_search_list = ( diff --git a/selenium_testcase/testcases/navigation.py b/selenium_testcase/testcases/navigation.py index d5bc817..062c9a3 100644 --- a/selenium_testcase/testcases/navigation.py +++ b/selenium_testcase/testcases/navigation.py @@ -1,8 +1,9 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import +from builtins import object -from urlparse import urljoin +from six.moves.urllib.parse import urljoin from django.urls import reverse from selenium.webdriver.support.ui import Select @@ -12,7 +13,7 @@ from .utils import wait_for -class NavigationTestMixin: +class NavigationTestMixin(object): def get_page(self, url): """ Navigate to the given url. """ diff --git a/selenium_testcase/testcases/utils.py b/selenium_testcase/testcases/utils.py index 88a1ea3..02afc00 100644 --- a/selenium_testcase/testcases/utils.py +++ b/selenium_testcase/testcases/utils.py @@ -4,6 +4,7 @@ import sys from time import time, sleep +from six.moves import reload_module as reload from django.conf import settings diff --git a/selenium_testcase/tests/test_navigation.py b/selenium_testcase/tests/test_navigation.py index 84c99c9..5ba4d0c 100644 --- a/selenium_testcase/tests/test_navigation.py +++ b/selenium_testcase/tests/test_navigation.py @@ -33,7 +33,7 @@ def test_get_bad_page(self): self.get_page("/bogus/") self.should_see("Not Found") self.should_see( - "The requested URL /bogus/ was not found on this server.") + "The requested resource was not found on this server.") def test_missing_content_with_retry(self): """ Test retry for missing content """ diff --git a/setup.py b/setup.py index ff59bb5..190156b 100755 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ # setup the project setup( name="django-selenium-testcase", - version="1.3.1", + version="1.3.2", author="Nimbis Services, Inc.", author_email="info@nimbisservices.com", description="Selenium helper methods for Django live server testing.", diff --git a/test_project/settings.py b/test_project/settings.py index 24ac3a4..33f7cdd 100644 --- a/test_project/settings.py +++ b/test_project/settings.py @@ -1,22 +1,23 @@ """ Django settings for test_project project. -Generated by 'django-admin startproject' using Django 1.11.6. +Generated by 'django-admin startproject' using Django 2.2.13. For more information on this file, see -https://docs.djangoproject.com/en/1.11/topics/settings/ +https://docs.djangoproject.com/en/2.2/topics/settings/ For the full list of settings and their values, see -https://docs.djangoproject.com/en/1.11/ref/settings/ +https://docs.djangoproject.com/en/2.2/ref/settings/ """ +import getpass 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__))) # path for selenium generated files -SELENIUM_TESTCASE_BASE_DIR = BASE_DIR +SELENIUM_TESTCASE_BASE_DIR = os.path.join(BASE_DIR, 'public') # turn on all debug features except for PDB SELENIUM_TESTCASE_LOGGING = True @@ -25,17 +26,16 @@ SELENIUM_TESTCASE_PDB_ON_MISSING = False # Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ +# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = '5yv=tze9tzi$#5g^q-k#d#5nh8a&bx!@p@*o@u_)0clzmh8u6d' +SECRET_KEY = '+x^3hmk11)n9_joz3ph7ng+u64m_fbzv5jj*v73(pbege4dq&r' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] - # Application definition INSTALLED_APPS = [ @@ -82,24 +82,28 @@ # Database -# https://docs.djangoproject.com/en/1.11/ref/settings/#databases +# https://docs.djangoproject.com/en/2.2/ref/settings/#databases DATABASES = { 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + 'ENGINE': os.environ.get( + 'DATABASE_ENGINE', 'django.db.backends.postgresql'), + 'NAME': os.environ.get('DATABASE_NAME', 'selenium_testcase'), + 'USER': os.environ.get('DATABASE_USER', getpass.getuser()), + 'PASSWORD': os.environ.get('DATABASE_PASSWORD', ''), + 'HOST': os.environ.get('DATABASE_HOST', ''), + 'PORT': os.environ.get('DATABASE_PORT', '5432'), } } - # Password validation -# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators +# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [] # Internationalization -# https://docs.djangoproject.com/en/1.11/topics/i18n/ +# https://docs.djangoproject.com/en/2.2/topics/i18n/ LANGUAGE_CODE = 'en-us' @@ -113,6 +117,6 @@ # Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/1.11/howto/static-files/ +# https://docs.djangoproject.com/en/2.2/howto/static-files/ STATIC_URL = '/static/' diff --git a/test_project/urls.py b/test_project/urls.py index 37b1ca7..d96ba50 100644 --- a/test_project/urls.py +++ b/test_project/urls.py @@ -1,27 +1,27 @@ """test_project URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/1.11/topics/http/urls/ + https://docs.djangoproject.com/en/2.2/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') + 2. Add a URL to urlpatterns: path('', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') Including another URLconf - 1. Import the include() function: from django.conf.urls import url, include - 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ -from django.conf.urls import url, include from django.contrib import admin -from django.views.generic import TemplateView +from django.urls import path, include +from django.views.generic.base import TemplateView urlpatterns = [ - url('^accounts/', include('django.contrib.auth.urls')), - url(r'^accounts/profile/$', - TemplateView.as_view(template_name='registration/profile.html'), - name='user_profile'), - url(r'^admin/', admin.site.urls), - url(r'', include('selenium_testcase.urls')) + path('admin/', admin.site.urls), + path('accounts/profile/', + TemplateView.as_view(template_name='registration/profile.html'), + name='user_profile'), + path('accounts/', include('django.contrib.auth.urls')), + path('', include('selenium_testcase.urls')) ] diff --git a/test_project/wsgi.py b/test_project/wsgi.py index 4c57701..78bdf00 100644 --- a/test_project/wsgi.py +++ b/test_project/wsgi.py @@ -4,13 +4,13 @@ It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see -https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ +https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/ """ import os from django.core.wsgi import get_wsgi_application -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project.settings") +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'test_project.settings') application = get_wsgi_application()