diff --git a/.coveragerc b/.coveragerc index c5d5d41a..e8b0850a 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,20 +1,34 @@ [run] -source = djangocms_installer branch = True +source = djangocms_installer omit = djangocms_installer/share/* djangocms_installer/__main__.py - djangocms_installer/main.py djangocms_installer/compat.py djangocms_installer/config/urls_i18n.py djangocms_installer/config/urls_noi18n.py djangocms_installer/config/settings.py - tests/* [report] +omit = *migrations*,*tests*,*test_utils* +# Regexes for lines to exclude from consideration exclude_lines = + # Have to re-enable the standard pragma pragma: no cover + + # Don't complain about missing debug-only code: def __repr__ + if self\.debug + + # Don't complain if tests don't hit defensive assertion code: raise AssertionError raise NotImplementedError + + # Don't complain if non-runnable code isn't run: + if 0: if __name__ == .__main__.: + +ignore_errors = True + +[html] +directory = coverage_html diff --git a/.editorconfig b/.editorconfig index 56def90a..d979ee91 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,27 +8,27 @@ end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true -max_line_length = 80 +max_line_length = 120 [*.md] trim_trailing_whitespace = false [*.rst] -max_line_length = 80 +max_line_length = 120 [*.py] -max_line_length = 100 +max_line_length = 120 [*.{scss,html}] indent_size = 2 indent_style = space max_line_length = 120 -[*.js] +[*.{js,vue,json}] indent_size = 2 max_line_length = 120 -[*.yml] +[*.{yml,yaml}] indent_size = 2 [Makefile] diff --git a/.github/ISSUE_TEMPLATE/---bug-report.md b/.github/ISSUE_TEMPLATE/---bug-report.md new file mode 100644 index 00000000..19d08d85 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/---bug-report.md @@ -0,0 +1,48 @@ +--- +name: "\U0001F41B Bug report" +about: Create a report to help us improve +title: '' +labels: 'type: bug' +assignees: '' + +--- + + + +## Description + + + +## Steps to reproduce + + + +## Versions + + + +## Expected behaviour + + + +## Actual behaviour + + + +## Additional information + + diff --git a/.github/ISSUE_TEMPLATE/---feature-request.md b/.github/ISSUE_TEMPLATE/---feature-request.md new file mode 100644 index 00000000..5b74e5fe --- /dev/null +++ b/.github/ISSUE_TEMPLATE/---feature-request.md @@ -0,0 +1,42 @@ +--- +name: "\U0001F389 Feature request" +about: Share your idea, let's discuss it! +title: '' +labels: 'type: feature' +assignees: '' + +--- + + + +## Description + + + +## Use cases + + + +## Proposed solution + + + +## Alternatives + + + +## Additional information + + diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..9d2bdc76 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,18 @@ +# Description + +Describe: + +* Content of the pull request +* Feature added / Problem fixed + +## References + +Provide any github issue fixed (as in ``Fix #XYZ``) + +# Checklist + +* [ ] I have read the [contribution guide](https://djangocms-installer.readthedocs.io/en/latest/contributing.html) +* [ ] Code lint checked via `inv lint` +* [ ] ``changes`` file included (see [docs](https://djangocms-installer.readthedocs.io/en/latest/contributing.html#pull-request-guidelines)) +* [ ] Usage documentation added in case of new features +* [ ] Tests added diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..a9c8f143 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,41 @@ +name: Code quality + +on: [push, pull_request] + +jobs: + lint: + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[skip ci]')" + strategy: + matrix: + python-version: [3.8] + toxenv: [pep8, isort, black, pypi-description, docs, towncrier] + steps: + - uses: actions/checkout@v2 + with: + repository: ${{ github.event.pull_request.head.repo.full_name }} + ref: ${{ github.event.pull_request.head.ref }} + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Cache pip + uses: actions/cache@v1 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ matrix.toxenv }} + restore-keys: | + ${{ runner.os }}-pip-${{ matrix.toxenv }} + - name: Cache tox + uses: actions/cache@v1 + with: + path: .tox + key: ${{ runner.os }}-lint-${{ matrix.toxenv }}-${{ hashFiles('setup.cfg') }} + restore-keys: | + ${{ runner.os }}-lint-${{ matrix.toxenv }}- + - name: Install dependencies + run: | + python -m pip install --upgrade pip setuptools tox>=1.8 + - name: Test with tox + run: | + tox -e${{ matrix.toxenv }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 00000000..535f2906 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,38 @@ +name: Upload Python Package + +on: + release: + types: [published,prereleased] + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v1 + with: + python-version: '3.x' + - name: Cache pip + uses: actions/cache@v1 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ matrix.toxenv }} + restore-keys: | + ${{ runner.os }}-pip-${{ matrix.toxenv }} + - name: Cache tox + uses: actions/cache@v1 + with: + path: .tox + key: ${{ runner.os }}-tox-release-${{ hashFiles('setup.cfg') }} + restore-keys: | + ${{ runner.os }}-tox-release- + - name: Install dependencies + run: | + python -m pip install --upgrade pip setuptools tox>=1.8 + - name: Build and publish + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + run: | + tox -erelease diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..33bc4435 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,51 @@ +name: Tox tests + +on: [push, pull_request] + +jobs: + test: + if: "!contains(github.event.head_commit.message, '[skip ci]')" + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.8, 3.7, 3.6, 3.5] + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Cache pip + uses: actions/cache@v1 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ matrix.python-version }} + restore-keys: | + ${{ runner.os }}-pip-${{ matrix.python-version }} + - name: Cache tox + uses: actions/cache@v1 + with: + path: .tox + key: ${{ runner.os }}-tox-${{ matrix.python-version }}-${{ hashFiles('setup.cfg') }} + restore-keys: | + ${{ runner.os }}-tox-${{ matrix.python-version }}- + - name: Install dependencies + run: | + sudo apt-get install gettext sqlite3 + python -m pip install --upgrade pip tox>=3.5 + - name: Test with tox + env: + TOX_ENV: py + COMMAND: coverage run + COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COVERALLS_SERVICE_NAME: github + run: | + tox -e$TOX_ENV + .tox/$TOX_ENV/bin/coverage xml + .tox/$TOX_ENV/bin/coveralls + - uses: codecov/codecov-action@v1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + flags: unittests + file: ./coverage.xml + fail_ci_if_error: false diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..3ab6ebf5 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,62 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +exclude: "(.idea|node_modules|.tox)" +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v3.1.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files + - id: check-builtin-literals + - id: check-executables-have-shebangs + - id: check-merge-conflict + - id: check-toml + - id: fix-encoding-pragma + args: + - --remove + - repo: https://github.com/timothycrosley/isort + rev: "5.0.2" + hooks: + - id: isort + - repo: https://github.com/psf/black + rev: 19.10b0 + hooks: + - id: black + - repo: https://gitlab.com/pycqa/flake8 + rev: 3.8.3 + hooks: + - id: flake8 + additional_dependencies: + - flake8-broken-line + - flake8-bugbear + - flake8-builtins + - flake8-coding + - flake8-commas + - flake8-comprehensions + - flake8-eradicate + - flake8-quotes + - flake8-tidy-imports + - pep8-naming + - repo: https://github.com/econchick/interrogate + rev: 1.2.0 + hooks: + - id: interrogate + args: + - "-cpyproject.toml" + - "--quiet" + - repo: https://github.com/asottile/pyupgrade + rev: v2.6.2 + hooks: + - id: pyupgrade + args: + - --py3-plus + - repo: local + hooks: + - id: towncrier + name: towncrier + entry: inv towncrier-check + language: system + pass_filenames: false + always_run: true diff --git a/.pyup.yml b/.pyup.yml new file mode 100644 index 00000000..2809577e --- /dev/null +++ b/.pyup.yml @@ -0,0 +1,7 @@ +update: all +pin: False +branch: +schedule: "every day" +search: True +branch_prefix: pyup/ +close_prs: True diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 00000000..b17953b2 --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,15 @@ +version: 2 + +sphinx: + configuration: docs/conf.py + fail_on_warning: true + +formats: + - epub + - pdf + +python: + version: 3.7 + install: + - requirements: requirements-test.txt + system_packages: false diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 0dcd5c46..00000000 --- a/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -language: python -dist: xenial - -python: - - 3.8 - - 3.7 - - 3.6 - - 3.5 - -env: - - global: - - LANG='en_US.UTF-8' - - matrix: - - TEST='1' - - TEST='pep8' - - TEST='isort' - - TEST='docs' - -before_script: - - echo "Europe/Rome" | sudo tee /etc/timezone - - sudo dpkg-reconfigure --frontend noninteractive tzdata - -before_install: - - pip install codecov - -# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors -install: - - pip install -U setuptools tox virtualenv coveralls>=2 - - "if [[ $TRAVIS_PYTHON_VERSION == '3.5' ]]; then export TOX_ENV=py35; fi" - - "if [[ $TRAVIS_PYTHON_VERSION == '3.6' ]]; then export TOX_ENV=py36; fi" - - "if [[ $TRAVIS_PYTHON_VERSION == '3.7' ]]; then export TOX_ENV=py37; fi" - - "if [[ $TRAVIS_PYTHON_VERSION == '3.8' ]]; then export TOX_ENV=py38; fi" - - "if [[ $TEST != '1' ]]; then export TOX_ENV=$TEST; fi" - -# command to run tests, e.g. python setup.py test -script: COMMAND='coverage run --source=djangocms_installer' tox -e$TOX_ENV - -after_success: - - coverage report -m - - codecov - - coveralls - -matrix: - exclude: - - python: 3.5 - env: TEST='pep8' - - python: 3.5 - env: TEST='isort' - - python: 3.5 - env: TEST='docs' - - python: 3.6 - env: TEST='pep8' - - python: 3.6 - env: TEST='isort' - - python: 3.6 - env: TEST='docs' - - python: 3.7 - env: TEST='pep8' - - python: 3.7 - env: TEST='isort' - - python: 3.7 - env: TEST='docs' - -notifications: - webhooks: https://ring.nephila.it/packages/hook/ diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 0fb24265..42532fea 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -1,6 +1,6 @@ -============ +############ Contributing -============ +############ Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given. @@ -8,10 +8,10 @@ little bit helps, and credit will always be given. You can contribute in many ways: Types of Contributions ----------------------- +********************** Report Bugs -~~~~~~~~~~~ +=========== Report bugs at https://github.com/nephila/djangocms-installer/issues. @@ -22,26 +22,26 @@ If you are reporting a bug, please include: * Detailed steps to reproduce the bug. Fix Bugs -~~~~~~~~ +======== Look through the GitHub issues for bugs. Anything tagged with "bug" is open to whoever wants to implement it. Implement Features -~~~~~~~~~~~~~~~~~~ +================== Look through the GitHub issues for features. Anything tagged with "feature" is open to whoever wants to implement it. Write Documentation -~~~~~~~~~~~~~~~~~~~ +=================== -django CMS Installer could always use more documentation, whether as part of the -official django CMS Installer docs, in docstrings, or even on the web in blog posts, +djangocms-installer could always use more documentation, whether as part of the +official djangocms-installer docs, in docstrings, or even on the web in blog posts, articles, and such. Submit Feedback -~~~~~~~~~~~~~~~ +=============== The best way to send feedback is to file an issue at https://github.com/nephila/djangocms-installer/issues. @@ -52,25 +52,24 @@ If you are proposing a feature: * Remember that this is a volunteer-driven project, and that contributions are welcome :) +************ Get Started! ------------- +************ -Ready to contribute? Here's how to set up `djangocms-installer` for local development. +Ready to contribute? Here's how to set up ``djangocms-installer`` for local development. -1. Fork the `djangocms-installer` repo on GitHub. +1. Fork the ``djangocms-installer`` repo on GitHub. 2. Clone your fork locally:: $ git clone git@github.com:your_name_here/djangocms-installer.git -3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development:: +3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper + installed, this is how you set up your fork for local development:: $ mkvirtualenv djangocms-installer $ cd djangocms-installer/ - $ python setup.py develop $ pip install -r requirements-test.txt - -the last one is to get the requirements including testing and development -tools installed. + $ pip install -e . 4. Create a branch for local development:: @@ -81,10 +80,10 @@ Now you can make your changes locally. 5. When you're done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox:: - $ flake8 djangocms-installer tests - $ python setup.py test $ tox +To get tox, pip install it into your virtualenv. + 6. Commit your changes and push your branch to GitHub:: $ git add . @@ -93,22 +92,74 @@ tests, including testing other Python versions with tox:: 7. Submit a pull request through the GitHub website. -Pull Request Guidelines ------------------------ +Development tips +---------------- -Before you submit a pull request, check that it meets these guidelines: +This project allows you to use `pre-commit `_ to ensure an easy compliance +to the project code styles. + +If you want to use it, install it globally (for example with ``pip3 install --user precommit``, +but check `installation instruction `. +When first cloning the project ensure you install the git hooks by running ``pre-commit install``. -1. The pull request should include tests. -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 - https://travis-ci.org/nephila/djangocms-installer/pull_requests - and make sure that the tests pass for all supported Python versions. +From now on every commit will be checked against our code style. -Tips ----- +Check also the available tox environments with ``tox -l``: the ones not marked with a python version number are tools +to help you work on the project buy checking / formatting code style, running docs etc. -To run a subset of tests:: +Testing tips +---------------- +You can test your project using any specific combination of python, django and django cms. + +For example ``tox -epy3.7-django30-cms37`` runs the tests on python 3.7, Django 3.0 and django CMS 3.7. + +Pull Request Guidelines +======================= + +Before you submit a pull request, check that it meets these guidelines: - $ python setup.py test -s tests.main +#. Pull request must be named with the following naming scheme: + + ``/(-)-description`` + + See below for available types. + +#. The pull request should include tests. +#. If the pull request adds functionality, the docs should be updated. + Documentation must be added in ``docs`` directory, and must include usage + information for the end user. + In case of public API method, add extended docstrings with full parameters + description and usage example. +#. Add a changes file in ``changes`` directory describing the contribution in + one line. It will be added automatically to the history file upon release. + File must be named as ``.`` with type being: + + * ``.feature``: For new features. + * ``.bugfix``: For bug fixes. + * ``.doc``: For documentation improvement. + * ``.removal``: For deprecation or removal of public API. + * ``.misc``: For general issues. + + Check `towncrier`_ documentation for more details. + +#. The pull request should work for all python / django / django CMS versions + declared in tox.ini. + Check the CI and make sure that the tests pass for all supported versions. + +Release a version +================= + +#. Update authors file +#. Merge ``develop`` on ``master`` branch +#. Bump release via task: ``inv tag-release (major|minor|patch)`` +#. Update changelog via towncrier: ``towncrier --yes`` +#. Commit changelog with ``git commit --amend`` to merge with bumpversion commit +#. Create tag ``git tag `` +#. Push tag to github +#. Publish the release from the tags page +#. If pipeline succeeds, push ``master`` +#. Merge ``master`` back on ``develop`` +#. Bump developement version via task: ``inv tag-dev -l (major|minor|patch)`` +#. Push ``develop`` + +.. _towncrier: https://pypi.org/project/towncrier/#news-fragments diff --git a/HISTORY.rst b/HISTORY.rst index 84a324ec..f3c52ad3 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1,34 +1,33 @@ .. :changelog: +******* History -------- +******* -unreleased -++++++++++++++++++ +.. towncrier release notes start -* Nothing yet 1.2.3 (2020-04-23) -++++++++++++++++++ +=================== * Fixed support for staticfiles * Fixed X_FRAME_OPTIONS default 1.2.2 (2020-04-23) -++++++++++++++++++ +=================== * Added support for Django 3.0 * Added support for django CMS 3.7.2 1.2.1 (2019-12-27) -++++++++++++++++++ +=================== * Pinned formtools version on django 1.11 to avoid python 2 issues * Unpinned psycopg2 version for Django 2.2+ * Added support for "shorthand" postgres django backend 1.2.0 (2019-11-04) -++++++++++++++++++ +=================== * Added support for django CMS 3.7 - Django 2.2 * Added support for Python 3.7 @@ -39,81 +38,81 @@ unreleased * Dropped support for aldryn-boilerplates 1.1.1 (2019-06-29) -++++++++++++++++++ +=================== * Fixed project name check * Pinned psycopg2 version to avoid issues in Python 3.6+ 1.1.0 (2019-03-05) -++++++++++++++++++ +=================== * Added support for django CMS 3.6 * Added detection of incompatible DJANGO_SETTINGS_MODULE environment variable * Added detection of mismatched Django version between currently installed and declared one 1.0.2 (2018-11-21) -++++++++++++++++++ +=================== * Bumped html5lib / djangocms-text-ckeditor version 1.0.1 (2018-06-03) -++++++++++++++++++ +=================== * Pinned django-polymorphic version to fix issues with django < 1.11 * Pinned djangocms core plugins versions 1.0.0 (2018-02-01) -++++++++++++++++++ +=================== * Dropped cmsplugin-filer in favor of core plugins which now use filer * Added django CMS 3.5 0.9.8 (2018-01-10) -++++++++++++++++++ +=================== * Raised more informative messages on command failures * Fixed tests for django CMS develop 0.9.7 (2017-07-15) -++++++++++++++++++ +=================== * Improved django-admin invocation to support more python environments layouts 0.9.6 (2017-03-12) -++++++++++++++++++ +=================== * Added more Django 1.10 fixes / cleanups * Added python 3.6 compatibility 0.9.5 (2017-02-16) -++++++++++++++++++ +=================== * Added more Django 1.10 fixes / cleanups 0.9.4 (2017-01-03) -++++++++++++++++++ +=================== * Added support for Django 1.10 * Added 'lts' keyword (it's now the default instead of 'stable') 0.9.3 (2016-11-16) -++++++++++++++++++ +=================== * Fixed issue with create_user command 0.9.2 (2016-11-12) -++++++++++++++++++ +=================== * Fixed search 'django-admin.py' * Improved error reporting during package installation 0.9.1 (2016-10-02) -++++++++++++++++++ +=================== * Fixed issue with -p parameter 0.9.0 (2016-09-15) -++++++++++++++++++ +=================== * Drop support for Python 2.6 * Drop support for Django < 1.8 @@ -132,12 +131,12 @@ unreleased * Disable permission by default 0.8.12 (2016-08-27) -+++++++++++++++++++ +===================+ * Pin plugins versions 0.8.11 (2016-07-15) -+++++++++++++++++++ +===================+ * Better plugins version pinning * Move sitemaps to non-language prefix url @@ -145,17 +144,17 @@ unreleased * Pin html5lib version 0.8.10 (2016-05-28) -+++++++++++++++++++ +===================+ * Add support for django CMS 3.3 final 0.8.9 (2016-05-19) -++++++++++++++++++ +=================== * Add support for django CMS 3.3rc 0.8.8 (2016-05-06) -++++++++++++++++++ +=================== * Force language codes to lowercase * Force i18n if multiple languages is provided @@ -163,24 +162,24 @@ unreleased * Fix error in Django 1.9 regexp 0.8.7 (2016-02-23) -++++++++++++++++++ +=================== * Add clearer cleanup message 0.8.6 (2016-02-05) -++++++++++++++++++ +=================== * Add support for Django 1.9 * Fix formatting CONN_MAX_AGE * Improve error handling in case of fatal error 0.8.5 (2015-12-24) -++++++++++++++++++ +=================== * Fix createsuperuser command 0.8.4 (2015-12-21) -++++++++++++++++++ +=================== * Remove flash plugin from installed plugins * Add ``--verbose`` option to improve debug @@ -188,20 +187,20 @@ unreleased * Improve documentation 0.8.3 (2015-11-25) -++++++++++++++++++ +=================== * Improve text editor plugin version selection * Improve admin style version selection 0.8.2 (2015-11-24) -++++++++++++++++++ +=================== * Add support for django CMS 3.2 * Add support for apphook reload middleware * Add viewport meta tag for mobile devices support 0.8.1 (2015-10-11) -++++++++++++++++++ +=================== * Add option to not install plugins * Add Python 3.5 to build matrix @@ -211,72 +210,72 @@ unreleased * Improve documentation 0.8.0 (2015-08-30) -++++++++++++++++++ +=================== * Options can now be provided via an ini file for easy scripting * Better migration modules discovery strategy * Minor fixes 0.7.9 (2015-07-21) -++++++++++++++++++ +=================== * Better Django 1.8 support * Fix error with newer Pillow versions 0.7.8 (2015-06-27) -++++++++++++++++++ +=================== * Add Django 1.8 support * Fix template styles 0.7.7 (2015-06-05) -++++++++++++++++++ +=================== * Switch to cloudflare CDN for bootstrap template * Fix support for django-filer 0.9.10 0.7.6 (2015-05-01) -++++++++++++++++++ +=================== * Switch to django CMS 3.1 as stable django CMS release * Rework the Django supported matrix * Always use djangocms-link instead of cmsplugin-filer-link 0.7.5 (2015-04-21) -++++++++++++++++++ +=================== * Add support for django CMS 3.1 * Switch to Django 1.7 as stable django release 0.7.4 (2015-04-14) -++++++++++++++++++ +=================== * Add automatic timezone detection * Pin django-reversion versions * Make installer more compatible with windows environment 0.7.3 (2015-04-08) -++++++++++++++++++ +=================== * Fix issues with django CMS requirements * Fix minor issues in shipped templates 0.7.2 (2015-02-08) -++++++++++++++++++ +=================== * Fixed Windows compatibility issues * Fixed python 3 compatibility issues * Add a flag to skip the project directory emptiness check 0.7.1 (2015-01-15) -++++++++++++++++++ +=================== * Ask for permission before cleanup * Clarify the `-p` parameter * Check if the project directory is empty before proceeding 0.7.0 (2015-01-10) -++++++++++++++++++ +=================== * Improved support for Django 1.7 and django CMS develop (3.1) * Totally new test strategy @@ -284,7 +283,7 @@ unreleased * Improved support for cleanup after failure 0.6.0 (2014-11-30) -++++++++++++++++++ +=================== * Add support for installing aldryn-boilerplate * Force installing all packages (-I) when creating the project virtualenv @@ -293,13 +292,13 @@ unreleased * Add preliminary support for django CMS develop (3.1) 0.5.4 (2014-08-14) -++++++++++++++++++ +=================== * Fix reversion version selection for older Django versions * Better project name validation 0.5.3 (2014-07-23) -++++++++++++++++++ +=================== * Add support for easy_thumbnails 2.0 migrations * Fix asking for creating user even when --no-input flag is used @@ -308,18 +307,18 @@ unreleased * Switch to official django-filer and cmsplugin-filer releases for CMS 3.0 0.5.2 (2014-05-30) -++++++++++++++++++ +=================== * Pin reversion to 1.8 waiting for a proper fix in django CMS 0.5.1 (2014-05-22) -++++++++++++++++++ +=================== * Fix error in bootstrap template handling * Add clarification about custom template set and starting page 0.5.0 (2014-05-21) -++++++++++++++++++ +=================== * Add dump-requirements argument * Add user provided extra setting @@ -328,7 +327,7 @@ unreleased * Documentation update 0.4.2 (2014-04-26) -++++++++++++++++++ +=================== * Use current cms.context_processors.cms_settings instead of deprecated one * Document some fixes for library issues @@ -336,38 +335,38 @@ unreleased * Switch default Django version to stable instead of 1.5 0.4.1 (2014-04-09) -++++++++++++++++++ +=================== * Fix some newlines issues in the settings file 0.4.0 (2014-04-09) -++++++++++++++++++ +=================== * Update for django CMS 3.0 stable! * Fixes for settings parameter 0.3.5 (2014-04-03) -++++++++++++++++++ +=================== * Update for django CMS 3.0c2 0.3.4 (2014-03-29) -++++++++++++++++++ +=================== * Fix issues with django CMS 2.4 0.3.3 (2014-03-20) -++++++++++++++++++ +=================== * Better handling of differenct CMS version configuration 0.3.2 (2014-03-18) -++++++++++++++++++ +=================== * Fix some versioned dependency resolve error 0.3.1 (2014-03-16) -++++++++++++++++++ +=================== * Fix error in loading resource files * Fix error with non-standard python executable paths @@ -375,13 +374,13 @@ unreleased * Fix error installing django-filer 0.3.0 (2014-03-15) -++++++++++++++++++ +=================== * Sync with django CMS RC1 changes * Use external django CMS plugins instead of removed core ones 0.2.0 (2014-02-06) -++++++++++++++++++ +=================== * Project renamed to djangocms-installer * Bugfixes @@ -394,11 +393,11 @@ unreleased * Can now creates a dummy starting page 0.1.1 (2013-10-20) -++++++++++++++++++ +=================== * Improved documentation on how to fix installation in case of missing libraries. 0.1.0 (2013-10-19) -++++++++++++++++++ +=================== * First public release. diff --git a/Makefile b/Makefile deleted file mode 100644 index 2dd7ef45..00000000 --- a/Makefile +++ /dev/null @@ -1,54 +0,0 @@ -.PHONY: clean-pyc clean-build docs - -help: - @echo "clean-build - remove build artifacts" - @echo "clean-pyc - remove Python file artifacts" - @echo "lint - check style with flake8" - @echo "test - run tests quickly with the default Python" - @echo "testall - run tests on every Python version with tox" - @echo "coverage - check code coverage quickly with the default Python" - @echo "docs - generate Sphinx HTML documentation, including API docs" - @echo "release - package and upload a release" - @echo "sdist - package" - -clean: clean-build clean-pyc - -clean-build: - rm -fr build/ - rm -fr dist/ - rm -fr *.egg-info - -clean-pyc: - find . -name '*.pyc' -exec rm -f {} + - find . -name '*.pyo' -exec rm -f {} + - find . -name '*~' -exec rm -f {} + - -lint: - flake8 djangocms_installer - -test: - python setup.py test - -test-all: - tox - -coverage: - coverage run --source djangocms-installer setup.py test - coverage report -m - coverage html - open htmlcov/index.html - -docs: - rm -f docs/djangocms_installer.*.rst - rm -f docs/modules.rst - sphinx-apidoc -o docs/ djangocms_installer - $(MAKE) -C docs clean - $(MAKE) -C docs html - -release: clean - python setup.py clean --all sdist bdist_wheel - twine upload dist/* - -sdist: clean - python setup.py sdist - ls -l dist diff --git a/README.rst b/README.rst index e6801912..5863b88f 100644 --- a/README.rst +++ b/README.rst @@ -2,7 +2,7 @@ django CMS Installer ==================== -|Gitter| |PyPiVersion| |PyVersion| |Status| |TestCoverage| |CodeClimate| |License| +|Gitter| |PyPiVersion| |PyVersion| |GAStatus| |TestCoverage| |CodeClimate| |License| Command to easily bootstrap django CMS projects @@ -122,9 +122,9 @@ Please check that the ``.py`` extension is associated correctly with Python inte :target: https://pypi.python.org/pypi/djangocms-installer :alt: Python versions -.. |Status| image:: https://img.shields.io/travis/nephila/djangocms-installer.svg?style=flat-square - :target: https://travis-ci.org/nephila/djangocms-installer - :alt: Latest Travis CI build status +.. |GAStatus| image:: https://github.com/nephila/djangocms-installer/workflows/Tox%20tests/badge.svg + :target: https://github.com/nephila/django-app-helper + :alt: Latest CI build status .. |TestCoverage| image:: https://img.shields.io/coveralls/nephila/djangocms-installer/master.svg?style=flat-square :target: https://coveralls.io/r/nephila/djangocms-installer?branch=master diff --git a/changes/362.feature b/changes/362.feature new file mode 100644 index 00000000..764929a2 --- /dev/null +++ b/changes/362.feature @@ -0,0 +1 @@ +Move to Github Actions diff --git a/changes/363.feature b/changes/363.feature new file mode 100644 index 00000000..b4032a58 --- /dev/null +++ b/changes/363.feature @@ -0,0 +1 @@ +Adopt modern packaging layour diff --git a/changes/364.feature b/changes/364.feature new file mode 100644 index 00000000..75e44cab --- /dev/null +++ b/changes/364.feature @@ -0,0 +1 @@ +Reformat with black diff --git a/djangocms_installer/__init__.py b/djangocms_installer/__init__.py index 702c8686..0527766c 100644 --- a/djangocms_installer/__init__.py +++ b/djangocms_installer/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- -__author__ = 'Iacopo Spalletti' -__email__ = 'i.spalletti@nephila.it' -__version__ = '1.3.0dev1' +__author__ = "Iacopo Spalletti" +__email__ = "i.spalletti@nephila.it" +__version__ = "1.3.0dev1" diff --git a/djangocms_installer/__main__.py b/djangocms_installer/__main__.py index 9db8b175..846f02d4 100644 --- a/djangocms_installer/__main__.py +++ b/djangocms_installer/__main__.py @@ -1,11 +1,8 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - import sys from .main import execute -if __name__ == '__main__': +if __name__ == "__main__": status = execute() if status: sys.exit(status) diff --git a/djangocms_installer/compat.py b/djangocms_installer/compat.py index ccc30e93..ba804153 100644 --- a/djangocms_installer/compat.py +++ b/djangocms_installer/compat.py @@ -1,43 +1,26 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - import subprocess -import six - -if six.PY3: - input = input - - def clean(value): - if value: - return value.strip() - else: - return value - unicode = str +def clean(value): + if value and isinstance(value, str): + return value.strip() + else: + return value -else: - input = raw_input # NOQA - def clean(value): - if value: - return value.strip().decode('utf-8') - else: - return value +if "check_output" not in dir(subprocess): - unicode = unicode # NOQA - -if 'check_output' not in dir(subprocess): def f(*popenargs, **kwargs): - if 'stdout' in kwargs: - raise ValueError('stdout argument not allowed, it will be overridden.') + if "stdout" in kwargs: + raise ValueError("stdout argument not allowed, it will be overridden.") process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs) output, unused_err = process.communicate() retcode = process.poll() if retcode: - cmd = kwargs.get('args') + cmd = kwargs.get("args") if cmd is None: cmd = popenargs[0] raise subprocess.CalledProcessError(retcode, cmd) return output + subprocess.check_output = f diff --git a/djangocms_installer/config/__init__.py b/djangocms_installer/config/__init__.py index 36838d3c..eae91c22 100644 --- a/djangocms_installer/config/__init__.py +++ b/djangocms_installer/config/__init__.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - import argparse import locale import os.path @@ -9,9 +6,8 @@ from distutils.version import LooseVersion import pytz -import six -from .. import compat, utils +from .. import compat from ..utils import less_than_version, supported_versions from . import data, ini from .internal import DbAction, validate_project @@ -28,10 +24,11 @@ def parse(args): if isinstance(timezone, pytz.BaseTzInfo): timezone = timezone.zone except Exception: # pragma: no cover - timezone = 'UTC' - if timezone == 'local': - timezone = 'UTC' - parser = argparse.ArgumentParser(description="""Bootstrap a django CMS project. + timezone = "UTC" + if timezone == "local": + timezone = "UTC" + parser = argparse.ArgumentParser( + description="""Bootstrap a django CMS project. Major usage modes: - wizard: djangocms -w -p /path/whatever project_name: ask for all the options through a @@ -45,116 +42,258 @@ def parse(args): Check https://djangocms-installer.readthedocs.io/en/latest/usage.html for detailed usage information. -""", formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument('--config-file', dest='config_file', action='store', - default=None, - help='Configuration file for djangocms_installer') - parser.add_argument('--config-dump', dest='config_dump', action='store', - default=None, - help='Dump configuration file with current args') - parser.add_argument('--db', '-d', dest='db', action=DbAction, - default='sqlite://localhost/project.db', - help='Database configuration (in URL format). ' - 'Example: sqlite://localhost/project.db') - parser.add_argument('--i18n', '-i', dest='i18n', action='store', - choices=('yes', 'no'), - default='yes', help='Activate Django I18N / L10N setting; this is ' - 'automatically activated if more than ' - 'language is provided') - parser.add_argument('--use-tz', '-z', dest='use_timezone', action='store', - choices=('yes', 'no'), - default='yes', help='Activate Django timezone support') - parser.add_argument('--timezone', '-t', dest='timezone', - required=False, default=timezone, - action='store', help='Optional default time zone. Example: Europe/Rome') - parser.add_argument('--reversion', '-e', dest='reversion', action='store', - choices=('yes', 'no'), - default='yes', help='Install and configure reversion support ' - '(only for django CMS 3.2 and 3.3)') - parser.add_argument('--permissions', dest='permissions', action='store', - choices=('yes', 'no'), - default='no', help='Activate CMS permission management') - parser.add_argument('--pip-options', help='pass custom pip options', default='') - parser.add_argument('--languages', '-l', dest='languages', action='append', - help='Languages to enable. Option can be provided multiple times, or as a ' - 'comma separated list. Only language codes supported by Django can ' - 'be used here. Example: en, fr-FR, it-IT') - parser.add_argument('--django-version', dest='django_version', action='store', - choices=data.DJANGO_SUPPORTED, - default=data.DJANGO_DEFAULT, help='Django version') - parser.add_argument('--cms-version', '-v', dest='cms_version', action='store', - choices=data.DJANGOCMS_SUPPORTED, - default=data.DJANGOCMS_DEFAULT, help='django CMS version') - parser.add_argument('--parent-dir', '-p', dest='project_directory', - default='', - action='store', help='Optional project parent directory') - parser.add_argument('--bootstrap', dest='bootstrap', action='store', - choices=('yes', 'no'), - default='no', help='Use Bootstrap 4 Theme') - parser.add_argument('--templates', dest='templates', action='store', - default='no', help='Use custom template set') - parser.add_argument('--starting-page', dest='starting_page', action='store', - choices=('yes', 'no'), - default='no', help='Load a starting page with examples after installation ' - '(english language only). Choose "no" if you use a ' - 'custom template set.') - parser.add_argument(dest='project_name', action='store', - help='Name of the project to be created') +""", + formatter_class=argparse.RawTextHelpFormatter, + ) + parser.add_argument( + "--config-file", + dest="config_file", + action="store", + default=None, + help="Configuration file for djangocms_installer", + ) + parser.add_argument( + "--config-dump", + dest="config_dump", + action="store", + default=None, + help="Dump configuration file with current args", + ) + parser.add_argument( + "--db", + "-d", + dest="db", + action=DbAction, + default="sqlite://localhost/project.db", + help="Database configuration (in URL format). " "Example: sqlite://localhost/project.db", + ) + parser.add_argument( + "--i18n", + "-i", + dest="i18n", + action="store", + choices=("yes", "no"), + default="yes", + help="Activate Django I18N / L10N setting; this is " + "automatically activated if more than " + "language is provided", + ) + parser.add_argument( + "--use-tz", + "-z", + dest="use_timezone", + action="store", + choices=("yes", "no"), + default="yes", + help="Activate Django timezone support", + ) + parser.add_argument( + "--timezone", + "-t", + dest="timezone", + required=False, + default=timezone, + action="store", + help="Optional default time zone. Example: Europe/Rome", + ) + parser.add_argument( + "--reversion", + "-e", + dest="reversion", + action="store", + choices=("yes", "no"), + default="yes", + help="Install and configure reversion support " "(only for django CMS 3.2 and 3.3)", + ) + parser.add_argument( + "--permissions", + dest="permissions", + action="store", + choices=("yes", "no"), + default="no", + help="Activate CMS permission management", + ) + parser.add_argument("--pip-options", help="pass custom pip options", default="") + parser.add_argument( + "--languages", + "-l", + dest="languages", + action="append", + help="Languages to enable. Option can be provided multiple times, or as a " + "comma separated list. Only language codes supported by Django can " + "be used here. Example: en, fr-FR, it-IT", + ) + parser.add_argument( + "--django-version", + dest="django_version", + action="store", + choices=data.DJANGO_SUPPORTED, + default=data.DJANGO_DEFAULT, + help="Django version", + ) + parser.add_argument( + "--cms-version", + "-v", + dest="cms_version", + action="store", + choices=data.DJANGOCMS_SUPPORTED, + default=data.DJANGOCMS_DEFAULT, + help="django CMS version", + ) + parser.add_argument( + "--parent-dir", + "-p", + dest="project_directory", + default="", + action="store", + help="Optional project parent directory", + ) + parser.add_argument( + "--bootstrap", + dest="bootstrap", + action="store", + choices=("yes", "no"), + default="no", + help="Use Bootstrap 4 Theme", + ) + parser.add_argument( + "--templates", dest="templates", action="store", default="no", help="Use custom template set", + ) + parser.add_argument( + "--starting-page", + dest="starting_page", + action="store", + choices=("yes", "no"), + default="no", + help="Load a starting page with examples after installation " + '(english language only). Choose "no" if you use a ' + "custom template set.", + ) + parser.add_argument(dest="project_name", action="store", help="Name of the project to be created") # Command that lists the supported plugins in verbose description - parser.add_argument('--list-plugins', '-P', dest='plugins', action='store_true', - help='List plugins that\'s going to be installed and configured') + parser.add_argument( + "--list-plugins", + "-P", + dest="plugins", + action="store_true", + help="List plugins that's going to be installed and configured", + ) # Command that lists the supported plugins in verbose description - parser.add_argument('--dump-requirements', '-R', dest='dump_reqs', action='store_true', - help='It dumps the requirements that would be installed according to ' - 'parameters given. Together with --requirements argument is useful ' - 'for customizing the virtualenv') + parser.add_argument( + "--dump-requirements", + "-R", + dest="dump_reqs", + action="store_true", + help="It dumps the requirements that would be installed according to " + "parameters given. Together with --requirements argument is useful " + "for customizing the virtualenv", + ) # Advanced options. These have a predefined default and are not asked # by config wizard. - parser.add_argument('--no-input', '-q', dest='noinput', action='store_true', - default=True, help='Don\'t run the configuration wizard, just use the ' - 'provided values') - parser.add_argument('--wizard', '-w', dest='wizard', action='store_true', - default=False, help='Run the configuration wizard') - parser.add_argument('--verbose', dest='verbose', action='store_true', - default=False, - help='Be more verbose and don\'t swallow subcommands output') - parser.add_argument('--filer', '-f', dest='filer', action='store_true', - default=True, help='Install and configure django-filer plugins ' - '- Always enabled') - parser.add_argument('--requirements', '-r', dest='requirements_file', action='store', - default=None, help='Externally defined requirements file') - parser.add_argument('--no-deps', '-n', dest='no_deps', action='store_true', - default=False, help='Don\'t install package dependencies') - parser.add_argument('--no-plugins', dest='no_plugins', action='store_true', - default=False, help='Don\'t install plugins') - parser.add_argument('--no-db-driver', dest='no_db_driver', action='store_true', - default=False, help='Don\'t install database package') - parser.add_argument('--no-sync', '-m', dest='no_sync', action='store_true', - default=False, help='Don\'t run syncdb / migrate after bootstrapping') - parser.add_argument('--no-user', '-u', dest='no_user', action='store_true', - default=False, help='Don\'t create the admin user') - parser.add_argument('--template', dest='template', action='store', - default=None, help='The path or URL to load the django project ' - 'template from.') - parser.add_argument('--extra-settings', dest='extra_settings', action='store', - default=None, help='The path to an file that contains extra settings.') - parser.add_argument('--skip-empty-check', '-s', dest='skip_project_dir_check', - action='store_true', - default=False, help='Skip the check if project dir is empty.') - parser.add_argument('--delete-project-dir', '-c', dest='delete_project_dir', - action='store_true', - default=False, help='Delete project directory on creation failure.') - parser.add_argument('--utc', dest='utc', - action='store_true', - default=False, help='Use UTC timezone.') - - if '--utc' in args: + parser.add_argument( + "--no-input", + "-q", + dest="noinput", + action="store_true", + default=True, + help="Don't run the configuration wizard, just use the " "provided values", + ) + parser.add_argument( + "--wizard", "-w", dest="wizard", action="store_true", default=False, help="Run the configuration wizard", + ) + parser.add_argument( + "--verbose", + dest="verbose", + action="store_true", + default=False, + help="Be more verbose and don't swallow subcommands output", + ) + parser.add_argument( + "--filer", + "-f", + dest="filer", + action="store_true", + default=True, + help="Install and configure django-filer plugins " "- Always enabled", + ) + parser.add_argument( + "--requirements", + "-r", + dest="requirements_file", + action="store", + default=None, + help="Externally defined requirements file", + ) + parser.add_argument( + "--no-deps", + "-n", + dest="no_deps", + action="store_true", + default=False, + help="Don't install package dependencies", + ) + parser.add_argument( + "--no-plugins", dest="no_plugins", action="store_true", default=False, help="Don't install plugins", + ) + parser.add_argument( + "--no-db-driver", + dest="no_db_driver", + action="store_true", + default=False, + help="Don't install database package", + ) + parser.add_argument( + "--no-sync", + "-m", + dest="no_sync", + action="store_true", + default=False, + help="Don't run syncdb / migrate after bootstrapping", + ) + parser.add_argument( + "--no-user", "-u", dest="no_user", action="store_true", default=False, help="Don't create the admin user", + ) + parser.add_argument( + "--template", + dest="template", + action="store", + default=None, + help="The path or URL to load the django project " "template from.", + ) + parser.add_argument( + "--extra-settings", + dest="extra_settings", + action="store", + default=None, + help="The path to an file that contains extra settings.", + ) + parser.add_argument( + "--skip-empty-check", + "-s", + dest="skip_project_dir_check", + action="store_true", + default=False, + help="Skip the check if project dir is empty.", + ) + parser.add_argument( + "--delete-project-dir", + "-c", + dest="delete_project_dir", + action="store_true", + default=False, + help="Delete project directory on creation failure.", + ) + parser.add_argument( + "--utc", dest="utc", action="store_true", default=False, help="Use UTC timezone.", + ) + + if "--utc" in args: for action in parser._positionals._actions: - if action.dest == 'timezone': - action.default = 'UTC' + if action.dest == "timezone": + action.default = "UTC" # If config_args then pretend that config args came from the stdin and run parser again. config_args = ini.parse_config_file(parser, args) @@ -171,36 +310,33 @@ def parse(args): # First of all, check if the project name is valid if not validate_project(args.project_name): sys.stderr.write( - 'Project name "{0}" is not valid or it\'s already defined. ' - 'Please use only numbers, letters and underscores.\n'.format(args.project_name) + 'Project name "{}" is not valid or it\'s already defined. ' + "Please use only numbers, letters and underscores.\n".format(args.project_name) ) sys.exit(3) # Checking the given path - setattr(args, 'project_path', os.path.join(args.project_directory, args.project_name).strip()) + args.project_path = os.path.join(args.project_directory, args.project_name).strip() if not args.skip_project_dir_check: - if (os.path.exists(args.project_directory) and - [path for path in os.listdir(args.project_directory) if not path.startswith('.')]): + if os.path.exists(args.project_directory) and [ + path for path in os.listdir(args.project_directory) if not path.startswith(".") + ]: sys.stderr.write( - 'Path "{0}" already exists and is not empty, please choose a different one\n' - 'If you want to use this path anyway use the -s flag to skip this check.\n' - ''.format(args.project_directory) + 'Path "{}" already exists and is not empty, please choose a different one\n' + "If you want to use this path anyway use the -s flag to skip this check.\n" + "".format(args.project_directory) ) sys.exit(4) if os.path.exists(args.project_path): - sys.stderr.write( - 'Path "{0}" already exists, please choose a different one\n'.format(args.project_path) - ) + sys.stderr.write('Path "{}" already exists, please choose a different one\n'.format(args.project_path)) sys.exit(4) if args.config_dump and os.path.isfile(args.config_dump): - sys.stdout.write( - 'Cannot dump because given configuration file "{0}" exists.\n'.format(args.config_dump) - ) + sys.stdout.write('Cannot dump because given configuration file "{}" exists.\n'.format(args.config_dump)) sys.exit(8) - args = _manage_args(parser, args) + args = _manage_args(parser, args) # what do we want here?! # * if languages are given as multiple arguments, let's use it as is @@ -210,107 +346,103 @@ def parse(args): if not args.languages: try: - args.languages = [locale.getdefaultlocale()[0].split('_')[0]] + args.languages = [locale.getdefaultlocale()[0].split("_")[0]] except Exception: # pragma: no cover - args.languages = ['en'] - elif isinstance(args.languages, six.string_types): - args.languages = args.languages.split(',') - elif len(args.languages) == 1 and isinstance(args.languages[0], six.string_types): - args.languages = args.languages[0].split(',') + args.languages = ["en"] + elif isinstance(args.languages, str): + args.languages = args.languages.split(",") + elif len(args.languages) == 1 and isinstance(args.languages[0], str): + args.languages = args.languages[0].split(",") args.languages = [lang.strip().lower() for lang in args.languages] if len(args.languages) > 1: - args.i18n = 'yes' + args.i18n = "yes" args.filer = True # Convert version to numeric format for easier checking try: django_version, cms_version = supported_versions(args.django_version, args.cms_version) - cms_package = data.PACKAGE_MATRIX.get( - cms_version, data.PACKAGE_MATRIX[data.DJANGOCMS_LTS] - ) + cms_package = data.PACKAGE_MATRIX.get(cms_version, data.PACKAGE_MATRIX[data.DJANGOCMS_LTS]) except RuntimeError as e: # pragma: no cover - sys.stderr.write(compat.unicode(e)) + sys.stderr.write(str(e)) sys.exit(6) if django_version is None: # pragma: no cover sys.stderr.write( - 'Please provide a Django supported version: {0}. Only Major.Minor ' - 'version selector is accepted\n'.format(', '.join(data.DJANGO_SUPPORTED)) + "Please provide a Django supported version: {}. Only Major.Minor " + "version selector is accepted\n".format(", ".join(data.DJANGO_SUPPORTED)) ) sys.exit(6) if cms_version is None: # pragma: no cover sys.stderr.write( - 'Please provide a django CMS supported version: {0}. Only Major.Minor ' - 'version selector is accepted\n'.format(', '.join(data.DJANGOCMS_SUPPORTED)) + "Please provide a django CMS supported version: {}. Only Major.Minor " + "version selector is accepted\n".format(", ".join(data.DJANGOCMS_SUPPORTED)) ) sys.exit(6) - default_settings = '{}.settings'.format(args.project_name) - env_settings = os.environ.get('DJANGO_SETTINGS_MODULE', default_settings) + default_settings = "{}.settings".format(args.project_name) + env_settings = os.environ.get("DJANGO_SETTINGS_MODULE", default_settings) if env_settings != default_settings: sys.stderr.write( - '`DJANGO_SETTINGS_MODULE` is currently set to \'{0}\' which is not compatible with ' - 'djangocms installer.\nPlease unset `DJANGO_SETTINGS_MODULE` and re-run the installer ' - '\n'.format(env_settings) + "`DJANGO_SETTINGS_MODULE` is currently set to '{}' which is not compatible with " + "djangocms installer.\nPlease unset `DJANGO_SETTINGS_MODULE` and re-run the installer " + "\n".format(env_settings) ) sys.exit(10) - if not getattr(args, 'requirements_file'): + if not args.requirements_file: requirements = [] # django CMS version check - if args.cms_version == 'develop': + if args.cms_version == "develop": requirements.append(cms_package) - warnings.warn(data.VERSION_WARNING.format('develop', 'django CMS')) - elif args.cms_version == 'rc': # pragma: no cover + warnings.warn(data.VERSION_WARNING.format("develop", "django CMS")) + elif args.cms_version == "rc": # pragma: no cover requirements.append(cms_package) - elif args.cms_version == 'beta': # pragma: no cover + elif args.cms_version == "beta": # pragma: no cover requirements.append(cms_package) - warnings.warn(data.VERSION_WARNING.format('beta', 'django CMS')) + warnings.warn(data.VERSION_WARNING.format("beta", "django CMS")) else: requirements.append(cms_package) - if args.cms_version in ('rc', 'develop'): - requirements.extend(data.REQUIREMENTS['cms-master']) - elif LooseVersion(cms_version) >= LooseVersion('3.7'): - requirements.extend(data.REQUIREMENTS['cms-3.7']) + if args.cms_version in ("rc", "develop"): + requirements.extend(data.REQUIREMENTS["cms-master"]) + elif LooseVersion(cms_version) >= LooseVersion("3.7"): + requirements.extend(data.REQUIREMENTS["cms-3.7"]) if not args.no_db_driver: requirements.append(args.db_driver) if not args.no_plugins: - if args.cms_version in ('rc', 'develop'): - requirements.extend(data.REQUIREMENTS['plugins-master']) - elif LooseVersion(cms_version) >= LooseVersion('3.7'): - requirements.extend(data.REQUIREMENTS['plugins-3.7']) - requirements.extend(data.REQUIREMENTS['filer']) + if args.cms_version in ("rc", "develop"): + requirements.extend(data.REQUIREMENTS["plugins-master"]) + elif LooseVersion(cms_version) >= LooseVersion("3.7"): + requirements.extend(data.REQUIREMENTS["plugins-3.7"]) + requirements.extend(data.REQUIREMENTS["filer"]) # Django version check - if args.django_version == 'develop': # pragma: no cover + if args.django_version == "develop": # pragma: no cover requirements.append(data.DJANGO_DEVELOP) - warnings.warn(data.VERSION_WARNING.format('develop', 'Django')) - elif args.django_version == 'beta': # pragma: no cover + warnings.warn(data.VERSION_WARNING.format("develop", "Django")) + elif args.django_version == "beta": # pragma: no cover requirements.append(data.DJANGO_BETA) - warnings.warn(data.VERSION_WARNING.format('beta', 'Django')) + warnings.warn(data.VERSION_WARNING.format("beta", "Django")) else: - requirements.append('Django<{0}'.format(less_than_version(django_version))) + requirements.append("Django<{}".format(less_than_version(django_version))) - if django_version == '2.2': - requirements.extend(data.REQUIREMENTS['django-2.2']) - elif django_version == '3.0': - requirements.extend(data.REQUIREMENTS['django-3.0']) + if django_version == "2.2": + requirements.extend(data.REQUIREMENTS["django-2.2"]) + elif django_version == "3.0": + requirements.extend(data.REQUIREMENTS["django-3.0"]) - requirements.extend(data.REQUIREMENTS['default']) + requirements.extend(data.REQUIREMENTS["default"]) - setattr(args, 'requirements', '\n'.join(requirements).strip()) + args.requirements = "\n".join(requirements).strip() # Convenient shortcuts - setattr(args, 'cms_version', cms_version) - setattr(args, 'django_version', django_version) - setattr(args, 'settings_path', - os.path.join(args.project_directory, args.project_name, 'settings.py').strip()) - setattr(args, 'urlconf_path', - os.path.join(args.project_directory, args.project_name, 'urls.py').strip()) + args.cms_version = cms_version + args.django_version = django_version + args.settings_path = os.path.join(args.project_directory, args.project_name, "settings.py").strip() + args.urlconf_path = os.path.join(args.project_directory, args.project_name, "urls.py").strip() if args.config_dump: ini.dump_config_file(args.config_dump, args, parser) @@ -319,7 +451,7 @@ def parse(args): def get_settings(): - module = __import__(str('djangocms_installer.config'), globals(), locals(), [str('settings')]) + module = __import__("djangocms_installer.config", globals(), locals(), ["settings"]) return module.settings @@ -331,63 +463,57 @@ def show_plugins(): """ Shows a descriptive text about supported plugins """ - sys.stdout.write(compat.unicode(data.PLUGIN_LIST_TEXT)) + sys.stdout.write(str(data.PLUGIN_LIST_TEXT)) def show_requirements(args): """ Prints the list of requirements according to the arguments provided """ - sys.stdout.write(compat.unicode(args.requirements)) + sys.stdout.write(str(args.requirements)) -def _manage_args(parser, args): +def _manage_args(parser, args): """ Checks and validate provided input """ for item in data.CONFIGURABLE_OPTIONS: action = parser._option_string_actions[item] - choices = default = '' + choices = default = "" input_value = getattr(args, action.dest) new_val = None - # cannot count this until we find a way to test input - if not args.noinput: # pragma: no cover + if not args.noinput: if action.choices: - choices = ' (choices: {0})'.format(', '.join(action.choices)) + choices = " (choices: {})".format(", ".join(action.choices)) if input_value: if type(input_value) == list: - default = ' [default {0}]'.format(', '.join(input_value)) + default = " [default {}]".format(", ".join(input_value)) else: - default = ' [default {0}]'.format(input_value) + default = " [default {}]".format(input_value) while not new_val: - prompt = '{0}{1}{2}: '.format(action.help, choices, default) - if action.choices in ('yes', 'no'): - new_val = utils.query_yes_no(prompt) - else: - new_val = compat.input(prompt) + prompt = "{}{}{}: ".format(action.help, choices, default) + new_val = input(prompt) new_val = compat.clean(new_val) if not new_val and input_value: new_val = input_value - if new_val and action.dest == 'templates': - if new_val != 'no' and not os.path.isdir(new_val): - sys.stdout.write('Given directory does not exists, retry\n') + if new_val and action.dest == "templates": + if new_val != "no" and not os.path.isdir(new_val): + sys.stdout.write("Given directory does not exists, retry\n") new_val = False - if new_val and action.dest == 'db': + if new_val and action.dest == "db": action(parser, args, new_val, action.option_strings) new_val = getattr(args, action.dest) else: - if not input_value and action.required: - raise ValueError( - 'Option {0} is required when in no-input mode'.format(action.dest) - ) + if not input_value and action.required: # pragma: no cover + raise ValueError("Option {} is required when in no-input mode".format(action.dest)) new_val = input_value - if action.dest == 'db': + if action.dest == "db": action(parser, args, new_val, action.option_strings) new_val = getattr(args, action.dest) - if action.dest == 'templates' and (new_val == 'no' or not os.path.isdir(new_val)): + if action.dest == "templates" and (new_val == "no" or not os.path.isdir(new_val)): new_val = False - if action.dest in ('bootstrap', 'starting_page'): - new_val = (new_val == 'yes') + if action.dest in ("bootstrap", "starting_page"): + new_val = new_val is True or new_val == "yes" setattr(args, action.dest, new_val) return args diff --git a/djangocms_installer/config/data.py b/djangocms_installer/config/data.py index 01ffb783..3401e233 100644 --- a/djangocms_installer/config/data.py +++ b/djangocms_installer/config/data.py @@ -1,128 +1,109 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - import sys import time -bust = {'bust': time.time()} +bust = {"bust": time.time()} -CONFIGURABLE_OPTIONS = ['--db', '--cms-version', '--django-version', '--i18n', - '--reversion', '--languages', '--timezone', '--use-tz', - '--permissions', '--bootstrap', '--templates', - '--starting-page'] +CONFIGURABLE_OPTIONS = [ + "--db", + "--cms-version", + "--django-version", + "--i18n", + "--reversion", + "--languages", + "--timezone", + "--use-tz", + "--permissions", + "--bootstrap", + "--templates", + "--starting-page", +] -DJANGOCMS_DEVELOP = 'https://github.com/yakky/django-cms/archive/develop.zip?{bust}'.format( - **bust -) -DJANGOCMS_RC = 'https://github.com/divio/django-cms/archive/release/3.7.x.zip?{bust}'.format( - **bust -) +DJANGOCMS_DEVELOP = "https://github.com/yakky/django-cms/archive/develop.zip?{bust}".format(**bust) +DJANGOCMS_RC = "https://github.com/divio/django-cms/archive/release/3.7.x.zip?{bust}".format(**bust) DJANGOCMS_BETA = DJANGOCMS_RC -DJANGOCMS_37 = 'django-cms>=3.7,<3.8' +DJANGOCMS_37 = "django-cms>=3.7,<3.8" -DJANGOCMS_SUPPORTED = ('3.7', 'stable', 'lts', 'develop', 'rc') -DJANGOCMS_STABLE = '3.7' -DJANGOCMS_LTS = '3.7' +DJANGOCMS_SUPPORTED = ("3.7", "stable", "lts", "develop", "rc") +DJANGOCMS_STABLE = "3.7" +DJANGOCMS_LTS = "3.7" DJANGOCMS_DEFAULT = DJANGOCMS_STABLE -DJANGO_DEVELOP = 'https://github.com/django/django/archive/master.zip?{bust}'.format(**bust) -DJANGO_BETA = 'https://github.com/django/django/archive/master.zip?{bust}'.format(**bust) +DJANGO_DEVELOP = "https://github.com/django/django/archive/master.zip?{bust}".format(**bust) +DJANGO_BETA = "https://github.com/django/django/archive/master.zip?{bust}".format(**bust) if sys.version_info >= (3, 6): - DJANGO_SUPPORTED = ('2.2', '3.0', 'stable', 'lts') - DJANGO_STABLE = '3.0' - DJANGO_LTS = '2.2' + DJANGO_SUPPORTED = ("2.2", "3.0", "stable", "lts") + DJANGO_STABLE = "3.0" + DJANGO_LTS = "2.2" else: - DJANGO_SUPPORTED = ('2.2', 'stable', 'lts') - DJANGO_STABLE = '2.2' - DJANGO_LTS = '2.2' + DJANGO_SUPPORTED = ("2.2", "stable", "lts") + DJANGO_STABLE = "2.2" + DJANGO_LTS = "2.2" DJANGO_DEFAULT = DJANGO_STABLE CMS_VERSION_MATRIX = { - 'stable': DJANGOCMS_STABLE, - 'lts': DJANGOCMS_LTS, - 'rc': DJANGOCMS_RC, - 'beta': DJANGOCMS_BETA, - 'develop': DJANGOCMS_DEVELOP, + "stable": DJANGOCMS_STABLE, + "lts": DJANGOCMS_LTS, + "rc": DJANGOCMS_RC, + "beta": DJANGOCMS_BETA, + "develop": DJANGOCMS_DEVELOP, } DJANGO_VERSION_MATRIX = { - 'stable': DJANGO_STABLE, - 'lts': DJANGO_LTS, - 'rc': DJANGO_STABLE, - 'beta': DJANGO_STABLE, - 'develop': DJANGO_STABLE + "stable": DJANGO_STABLE, + "lts": DJANGO_LTS, + "rc": DJANGO_STABLE, + "beta": DJANGO_STABLE, + "develop": DJANGO_STABLE, } VERSION_MATRIX = { - '3.7': ('2.2', '3.0'), - DJANGOCMS_BETA: ('2.2', '3.0'), - DJANGOCMS_RC: ('2.2', '3.0'), - DJANGOCMS_DEVELOP: ('2.2', '3.0'), + "3.7": ("2.2", "3.0"), + DJANGOCMS_BETA: ("2.2", "3.0"), + DJANGOCMS_RC: ("2.2", "3.0"), + DJANGOCMS_DEVELOP: ("2.2", "3.0"), } PACKAGE_MATRIX = { - '3.7': DJANGOCMS_37, + "3.7": DJANGOCMS_37, DJANGOCMS_RC: DJANGOCMS_RC, DJANGOCMS_BETA: DJANGOCMS_BETA, DJANGOCMS_DEVELOP: DJANGOCMS_DEVELOP, } REQUIREMENTS = { - 'default': [ - 'html5lib>=1.0.1', - 'Pillow>=3.0', - 'six', - 'pytz', - ], - 'django-2.2': [ - 'django-classy-tags>=0.9', - 'django-sekizai>=1.0', - 'django-mptt>0.9', - ], - 'django-3.0': [ - 'django-classy-tags>=0.9', - 'django-sekizai>=1.0', - 'django-mptt>0.9', - ], - 'cms-3.7': [ - 'djangocms-admin-style>=1.5,<1.6', - 'django-treebeard>=4.0,<5.0', - ], - 'cms-master': [ - 'https://github.com/divio/djangocms-admin-style/archive/master.zip?{bust}'.format(**bust), - 'django-treebeard>=4.0,<5.0', - ], - 'plugins-3.7': [ - 'djangocms-text-ckeditor>=3.7,<4.0', - 'djangocms-link>=2.5,<2.7', - 'djangocms-icon>=1.4,<1.6', - 'djangocms-style>=2.2,<2.4', - 'djangocms-googlemap>=1.3,<1.5', - 'djangocms-snippet>=2.2,<2.4', - 'djangocms-video>=2.1,<2.4', - 'djangocms-file>=2.3,<2.5', - 'djangocms-picture>=2.3,<2.5', - 'djangocms-bootstrap4>=1.5,<1.7', - ], - 'plugins-master': [ - 'https://github.com/divio/djangocms-text-ckeditor/archive/master.zip?{bust}' - ''.format(**bust), - 'https://github.com/divio/djangocms-file/archive/master.zip?{bust}'.format(**bust), - 'https://github.com/divio/djangocms-link/archive/master.zip?{bust}'.format(**bust), - 'https://github.com/divio/djangocms-icon/archive/master.zip?{bust}'.format(**bust), - 'https://github.com/divio/djangocms-style/archive/master.zip?{bust}'.format(**bust), - 'https://github.com/divio/djangocms-googlemap/archive/master.zip?{bust}'.format(**bust), - 'https://github.com/divio/djangocms-snippet/archive/master.zip?{bust}'.format(**bust), - 'https://github.com/divio/djangocms-picture/archive/master.zip?{bust}'.format(**bust), - 'https://github.com/divio/djangocms-video/archive/master.zip?{bust}'.format(**bust), - 'https://github.com/divio/djangocms-bootstrap4/archive/master.zip?{bust}'.format(**bust), - ], - 'plugins-basic': [ + "default": ["html5lib>=1.0.1", "Pillow>=3.0", "six", "pytz"], + "django-2.2": ["django-classy-tags>=0.9", "django-sekizai>=1.0", "django-mptt>0.9"], + "django-3.0": ["django-classy-tags>=0.9", "django-sekizai>=1.0", "django-mptt>0.9"], + "cms-3.7": ["djangocms-admin-style>=1.5,<1.6", "django-treebeard>=4.0,<5.0"], + "cms-master": [ + "https://github.com/divio/djangocms-admin-style/archive/master.zip?{bust}".format(**bust), + "django-treebeard>=4.0,<5.0", ], - 'plugins-basic-master': [ + "plugins-3.7": [ + "djangocms-text-ckeditor>=3.7,<4.0", + "djangocms-link>=2.5,<2.7", + "djangocms-icon>=1.4,<1.6", + "djangocms-style>=2.2,<2.4", + "djangocms-googlemap>=1.3,<1.5", + "djangocms-snippet>=2.2,<2.4", + "djangocms-video>=2.1,<2.4", + "djangocms-file>=2.3,<2.5", + "djangocms-picture>=2.3,<2.5", + "djangocms-bootstrap4>=1.5,<1.7", ], - 'filer': [ - 'easy_thumbnails', - 'django-filer>=1.3', + "plugins-master": [ + "https://github.com/divio/djangocms-text-ckeditor/archive/master.zip?{bust}" "".format(**bust), + "https://github.com/divio/djangocms-file/archive/master.zip?{bust}".format(**bust), + "https://github.com/divio/djangocms-link/archive/master.zip?{bust}".format(**bust), + "https://github.com/divio/djangocms-icon/archive/master.zip?{bust}".format(**bust), + "https://github.com/divio/djangocms-style/archive/master.zip?{bust}".format(**bust), + "https://github.com/divio/djangocms-googlemap/archive/master.zip?{bust}".format(**bust), + "https://github.com/divio/djangocms-snippet/archive/master.zip?{bust}".format(**bust), + "https://github.com/divio/djangocms-picture/archive/master.zip?{bust}".format(**bust), + "https://github.com/divio/djangocms-video/archive/master.zip?{bust}".format(**bust), + "https://github.com/divio/djangocms-bootstrap4/archive/master.zip?{bust}".format(**bust), ], + "plugins-basic": [], + "plugins-basic-master": [], + "filer": ["easy_thumbnails", "django-filer>=1.3"], } TEMPLATES_1_8 = """ @@ -155,12 +136,12 @@ """ DRIVERS = { - 'django.db.backends.postgresql': 'psycopg2', - 'django.db.backends.postgresql_psycopg2': 'psycopg2', - 'django.contrib.gis.db.backends.postgis': 'postgis', - 'django.db.backends.postgresql_postgis': 'postgis', - 'django.db.backends.mysql': 'mysqlclient', - 'django.db.backends.sqlite3': '', + "django.db.backends.postgresql": "psycopg2", + "django.db.backends.postgresql_psycopg2": "psycopg2", + "django.contrib.gis.db.backends.postgis": "postgis", + "django.db.backends.postgresql_postgis": "postgis", + "django.db.backends.mysql": "mysqlclient", + "django.db.backends.sqlite3": "", } DEFAULT_PROJECT_HEADER = """# -*- coding: utf-8 -*- @@ -177,4 +158,4 @@ BASE_DIR = os.path.dirname(os.path.dirname(__file__)) """ -VERSION_WARNING = '{0} version of {1} is not supported and it may not work as expected' +VERSION_WARNING = "{0} version of {1} is not supported and it may not work as expected" diff --git a/djangocms_installer/config/ini.py b/djangocms_installer/config/ini.py index 00526b54..f72d61d3 100644 --- a/djangocms_installer/config/ini.py +++ b/djangocms_installer/config/ini.py @@ -1,17 +1,9 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - import sys +from configparser import ConfigParser from .data import CMS_VERSION_MATRIX, DJANGO_VERSION_MATRIX -try: - from configparser import ConfigParser # Python 3. -except ImportError: - from ConfigParser import ConfigParser # Python 2. - - -SECTION = 'djangocms_installer' +SECTION = "djangocms_installer" def parse_config_file(parser, stdin_args): @@ -39,7 +31,7 @@ def parse_config_file(parser, stdin_args): config = ConfigParser() if not config.read(parsed_args.config_file): - sys.stderr.write('Config file "{0}" doesn\'t exists\n'.format(parsed_args.config_file)) + sys.stderr.write('Config file "{}" doesn\'t exists\n'.format(parsed_args.config_file)) sys.exit(7) # It isn't used anywhere. config_args = _convert_config_to_stdin(config, parser) @@ -55,41 +47,44 @@ def dump_config_file(filename, args, parser=None): config.set(SECTION, attr, args.attr) else: keys_empty_values_not_pass = ( - '--extra-settings', '--languages', '--requirements', '--template', '--timezone') + "--extra-settings", + "--languages", + "--requirements", + "--template", + "--timezone", + ) # positionals._option_string_actions for action in parser._actions: - if action.dest in ('help', 'config_file', 'config_dump', 'project_name'): + if action.dest in ("help", "config_file", "config_dump", "project_name"): continue keyp = action.option_strings[0] - option_name = keyp.lstrip('-') + option_name = keyp.lstrip("-") option_value = getattr(args, action.dest) - if any([i for i in keys_empty_values_not_pass if i in action.option_strings]): - if action.dest == 'languages': - if len(option_value) == 1 and option_value[0] == 'en': - config.set(SECTION, option_name, '') + if any(i for i in keys_empty_values_not_pass if i in action.option_strings): + if action.dest == "languages": + if len(option_value) == 1 and option_value[0] == "en": + config.set(SECTION, option_name, "") else: - config.set(SECTION, option_name, ','.join(option_value)) + config.set(SECTION, option_name, ",".join(option_value)) else: - config.set(SECTION, option_name, option_value if option_value else '') - elif action.choices == ('yes', 'no'): - config.set(SECTION, option_name, 'yes' if option_value else 'no') - elif action.dest == 'templates': - config.set(SECTION, option_name, option_value if option_value else 'no') - elif action.dest == 'cms_version': - version = ('stable' if option_value == CMS_VERSION_MATRIX['stable'] - else option_value) + config.set(SECTION, option_name, option_value if option_value else "") + elif action.choices == ("yes", "no"): + config.set(SECTION, option_name, "yes" if option_value else "no") + elif action.dest == "templates": + config.set(SECTION, option_name, option_value if option_value else "no") + elif action.dest == "cms_version": + version = "stable" if option_value == CMS_VERSION_MATRIX["stable"] else option_value config.set(SECTION, option_name, version) - elif action.dest == 'django_version': - version = ('stable' if option_value == DJANGO_VERSION_MATRIX['stable'] - else option_value) + elif action.dest == "django_version": + version = "stable" if option_value == DJANGO_VERSION_MATRIX["stable"] else option_value config.set(SECTION, option_name, version) elif action.const: - config.set(SECTION, option_name, 'true' if option_value else 'false') + config.set(SECTION, option_name, "true" if option_value else "false") else: config.set(SECTION, option_name, str(option_value)) - with open(filename, 'w') as fp: + with open(filename, "w") as fp: config.write(fp) @@ -100,10 +95,15 @@ def _convert_config_to_stdin(config, parser): @see https://docs.python.org/3.4/library/configparser.html#supported-datatypes """ keys_empty_values_not_pass = ( - '--extra-settings', '--languages', '--requirements', '--template', '--timezone') + "--extra-settings", + "--languages", + "--requirements", + "--template", + "--timezone", + ) args = [] for key, val in config.items(SECTION): - keyp = '--{0}'.format(key) + keyp = "--{}".format(key) action = parser._option_string_actions[keyp] if action.const: @@ -112,10 +112,10 @@ def _convert_config_to_stdin(config, parser): args.append(keyp) except ValueError: args.extend([keyp, val]) # Pass it as is to get the error from ArgumentParser. - elif any([i for i in keys_empty_values_not_pass if i in action.option_strings]): + elif any(i for i in keys_empty_values_not_pass if i in action.option_strings): # Some keys with empty values shouldn't be passed into args to use their defaults # from ArgumentParser. - if val != '': + if val != "": args.extend([keyp, val]) else: args.extend([keyp, val]) diff --git a/djangocms_installer/config/internal.py b/djangocms_installer/config/internal.py index 07662ae6..6a59fc16 100644 --- a/djangocms_installer/config/internal.py +++ b/djangocms_installer/config/internal.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - import keyword import re import sys @@ -10,22 +7,23 @@ from .data import DRIVERS -project_name_rx = re.compile(r'^[a-z0-9_A-Z]+$') +project_name_rx = re.compile(r"^[a-z0-9_A-Z]+$") class DbAction(Action): - def __call__(self, parser, namespace, values, option_string): parsed = dj_database_url.parse(values) - if parsed.get('ENGINE', None): - if DRIVERS[parsed['ENGINE']] == 'postgis': - sys.stdout.write('postgis installation is not supported at the moment.\n' - 'You need to install and configure the backend.\n') + if parsed.get("ENGINE", None): + if DRIVERS[parsed["ENGINE"]] == "postgis": + sys.stdout.write( + "postgis installation is not supported at the moment.\n" + "You need to install and configure the backend.\n" + ) setattr(namespace, self.dest, values) - setattr(namespace, '{0}_parsed'.format(self.dest), parsed) - setattr(namespace, '{0}_driver'.format(self.dest), DRIVERS[parsed['ENGINE']]) + setattr(namespace, "{}_parsed".format(self.dest), parsed) + setattr(namespace, "{}_driver".format(self.dest), DRIVERS[parsed["ENGINE"]]) else: - raise ValueError('Database URL not recognized, try again') + raise ValueError("Database URL not recognized, try again") def validate_project(project_name): diff --git a/djangocms_installer/config/settings.py b/djangocms_installer/config/settings.py index 93575032..658be1e6 100644 --- a/djangocms_installer/config/settings.py +++ b/djangocms_installer/config/settings.py @@ -1,147 +1,123 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', - 'django.template.loaders.eggs.Loader', + "django.template.loaders.filesystem.Loader", + "django.template.loaders.app_directories.Loader", + "django.template.loaders.eggs.Loader", ) MIDDLEWARE_CLASSES = [ - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.locale.LocaleMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'cms.middleware.user.CurrentUserMiddleware', - 'cms.middleware.page.CurrentPageMiddleware', - 'cms.middleware.toolbar.ToolbarMiddleware', - 'cms.middleware.language.LanguageCookieMiddleware', + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.locale.LocaleMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", + "cms.middleware.user.CurrentUserMiddleware", + "cms.middleware.page.CurrentPageMiddleware", + "cms.middleware.toolbar.ToolbarMiddleware", + "cms.middleware.language.LanguageCookieMiddleware", ] TEMPLATE_CONTEXT_PROCESSORS = [ - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', - 'django.template.context_processors.i18n', - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.template.context_processors.media', - 'django.template.context_processors.csrf', - 'django.template.context_processors.tz', - 'sekizai.context_processors.sekizai', - 'django.template.context_processors.static' + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + "django.template.context_processors.i18n", + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.template.context_processors.media", + "django.template.context_processors.csrf", + "django.template.context_processors.tz", + "sekizai.context_processors.sekizai", + "django.template.context_processors.static", ] TEMPLATE_CONTEXT_PROCESSORS_3 = [ - 'cms.context_processors.cms_settings', + "cms.context_processors.cms_settings", ] -TEMPLATE_DIRS = ( -) +TEMPLATE_DIRS = () INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.admin', - 'django.contrib.sites', - 'django.contrib.sitemaps', - 'django.contrib.staticfiles', - 'django.contrib.messages', - 'cms', - 'menus', - 'sekizai', + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.admin", + "django.contrib.sites", + "django.contrib.sitemaps", + "django.contrib.staticfiles", + "django.contrib.messages", + "cms", + "menus", + "sekizai", ) -MPTT_APPS = ( - 'mptt', -) +MPTT_APPS = ("mptt",) -TREEBEARD_APPS = ( - 'treebeard', -) +TREEBEARD_APPS = ("treebeard",) FILER_PLUGINS_3 = ( - 'filer', - 'easy_thumbnails', - 'djangocms_bootstrap4', - 'djangocms_bootstrap4.contrib.bootstrap4_alerts', - 'djangocms_bootstrap4.contrib.bootstrap4_badge', - 'djangocms_bootstrap4.contrib.bootstrap4_card', - 'djangocms_bootstrap4.contrib.bootstrap4_carousel', - 'djangocms_bootstrap4.contrib.bootstrap4_collapse', - 'djangocms_bootstrap4.contrib.bootstrap4_content', - 'djangocms_bootstrap4.contrib.bootstrap4_grid', - 'djangocms_bootstrap4.contrib.bootstrap4_jumbotron', - 'djangocms_bootstrap4.contrib.bootstrap4_link', - 'djangocms_bootstrap4.contrib.bootstrap4_listgroup', - 'djangocms_bootstrap4.contrib.bootstrap4_media', - 'djangocms_bootstrap4.contrib.bootstrap4_picture', - 'djangocms_bootstrap4.contrib.bootstrap4_tabs', - 'djangocms_bootstrap4.contrib.bootstrap4_utilities', - 'djangocms_file', - 'djangocms_icon', - 'djangocms_link', - 'djangocms_picture', - 'djangocms_style', - 'djangocms_snippet', - 'djangocms_googlemap', - 'djangocms_video', + "filer", + "easy_thumbnails", + "djangocms_bootstrap4", + "djangocms_bootstrap4.contrib.bootstrap4_alerts", + "djangocms_bootstrap4.contrib.bootstrap4_badge", + "djangocms_bootstrap4.contrib.bootstrap4_card", + "djangocms_bootstrap4.contrib.bootstrap4_carousel", + "djangocms_bootstrap4.contrib.bootstrap4_collapse", + "djangocms_bootstrap4.contrib.bootstrap4_content", + "djangocms_bootstrap4.contrib.bootstrap4_grid", + "djangocms_bootstrap4.contrib.bootstrap4_jumbotron", + "djangocms_bootstrap4.contrib.bootstrap4_link", + "djangocms_bootstrap4.contrib.bootstrap4_listgroup", + "djangocms_bootstrap4.contrib.bootstrap4_media", + "djangocms_bootstrap4.contrib.bootstrap4_picture", + "djangocms_bootstrap4.contrib.bootstrap4_tabs", + "djangocms_bootstrap4.contrib.bootstrap4_utilities", + "djangocms_file", + "djangocms_icon", + "djangocms_link", + "djangocms_picture", + "djangocms_style", + "djangocms_snippet", + "djangocms_googlemap", + "djangocms_video", ) -CMS_3_HEAD = ( - 'djangocms_admin_style', -) +CMS_3_HEAD = ("djangocms_admin_style",) -CMS_3_APPLICATIONS = ( - 'djangocms_text_ckeditor', -) +CMS_3_APPLICATIONS = ("djangocms_text_ckeditor",) -REVERSION_APPLICATIONS = ( - 'reversion', -) -SOUTH_APPLICATIONS = ( - 'south', -) +REVERSION_APPLICATIONS = ("reversion",) +SOUTH_APPLICATIONS = ("south",) CMS_TEMPLATES = ( - ('fullwidth.html', 'Fullwidth'), - ('sidebar_left.html', 'Sidebar Left'), - ('sidebar_right.html', 'Sidebar Right') + ("fullwidth.html", "Fullwidth"), + ("sidebar_left.html", "Sidebar Left"), + ("sidebar_right.html", "Sidebar Right"), ) CMS_TEMPLATES_BOOTSTRAP = ( - ('page.html', 'Page'), - ('feature.html', 'Page with Feature'), + ("page.html", "Page"), + ("feature.html", "Page with Feature"), ) -LANGUAGES = ( -) +LANGUAGES = () CMS_LANGUAGES = { - 1: [ - ], - 'default': { - 'redirect_on_fallback': True, - 'public': True, - 'hide_untranslated': False, - } + 1: [], + "default": {"redirect_on_fallback": True, "public": True, "hide_untranslated": False}, } CMS_PERMISSION = True CMS_PLACEHOLDER_CONF = {} THUMBNAIL_PROCESSORS = ( - 'easy_thumbnails.processors.colorspace', - 'easy_thumbnails.processors.autocrop', - 'filer.thumbnail_processors.scale_and_crop_with_subject_location', - 'easy_thumbnails.processors.filters', + "easy_thumbnails.processors.colorspace", + "easy_thumbnails.processors.autocrop", + "filer.thumbnail_processors.scale_and_crop_with_subject_location", + "easy_thumbnails.processors.filters", ) -URLCONF = { - -} +URLCONF = {} -APPHOOK_RELOAD_MIDDLEWARE_CLASS = 'cms.middleware.utils.ApphookReloadMiddleware' +APPHOOK_RELOAD_MIDDLEWARE_CLASS = "cms.middleware.utils.ApphookReloadMiddleware" diff --git a/djangocms_installer/config/urls_i18n.py b/djangocms_installer/config/urls_i18n.py index 254c6ba7..8d6432e6 100644 --- a/djangocms_installer/config/urls_i18n.py +++ b/djangocms_installer/config/urls_i18n.py @@ -1,30 +1,21 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - from cms.sitemaps import CMSSitemap from django.conf import settings -from django.conf.urls import include, url from django.conf.urls.i18n import i18n_patterns +from django.conf.urls.static import static from django.contrib import admin from django.contrib.sitemaps.views import sitemap -from django.contrib.staticfiles.urls import staticfiles_urlpatterns -from django.views.static import serve +from django.urls import include, path admin.autodiscover() urlpatterns = [ - url(r'^sitemap\.xml$', sitemap, - {'sitemaps': {'cmspages': CMSSitemap}}), + path("sitemap.xml", sitemap, {"sitemaps": {"cmspages": CMSSitemap}}), ] -urlpatterns += i18n_patterns( - url(r'^admin/', admin.site.urls), # NOQA - url(r'^', include('cms.urls')), -) + +urlpatterns += i18n_patterns(path("admin/", admin.site.urls), path("", include("cms.urls"))) # This is only needed when using runserver. if settings.DEBUG: - urlpatterns = [ - url(r'^media/(?P.*)$', serve, - {'document_root': settings.MEDIA_ROOT, 'show_indexes': True}), - ] + staticfiles_urlpatterns() + urlpatterns + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/djangocms_installer/config/urls_noi18n.py b/djangocms_installer/config/urls_noi18n.py index 80b31d3e..0240e0af 100644 --- a/djangocms_installer/config/urls_noi18n.py +++ b/djangocms_installer/config/urls_noi18n.py @@ -1,29 +1,22 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - from cms.sitemaps import CMSSitemap from django.conf import settings -from django.conf.urls import include, url +from django.conf.urls.static import static from django.contrib import admin from django.contrib.sitemaps.views import sitemap -from django.contrib.staticfiles.urls import staticfiles_urlpatterns -from django.views.static import serve +from django.urls import include, path admin.autodiscover() urlpatterns = [ - url(r'^sitemap\.xml$', sitemap, - {'sitemaps': {'cmspages': CMSSitemap}}), + path("sitemap.xml", sitemap, {"sitemaps": {"cmspages": CMSSitemap}}), ] urlpatterns += [ - url(r'^admin/', admin.site.urls), # NOQA - url(r'^', include('cms.urls')), + path("admin/", admin.site.urls), + path("", include("cms.urls")), ] # This is only needed when using runserver. if settings.DEBUG: - urlpatterns = [ - url(r'^media/(?P.*)$', serve, - {'document_root': settings.MEDIA_ROOT, 'show_indexes': True}), - ] + staticfiles_urlpatterns() + urlpatterns + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/djangocms_installer/django/__init__.py b/djangocms_installer/django/__init__.py index 3a443c2d..dc3550dc 100644 --- a/djangocms_installer/django/__init__.py +++ b/djangocms_installer/django/__init__.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - import glob import os import re @@ -12,8 +9,6 @@ from distutils.version import LooseVersion from shlex import quote as shlex_quote -from six import iteritems - from ..config import data, get_settings from ..utils import chdir, format_val @@ -25,37 +20,34 @@ def create_project(config_data): :param config_data: configuration data """ env = deepcopy(dict(os.environ)) - env[str('DJANGO_SETTINGS_MODULE')] = str('{0}.settings'.format(config_data.project_name)) - env[str('PYTHONPATH')] = str(os.pathsep.join(map(shlex_quote, sys.path))) + env["DJANGO_SETTINGS_MODULE"] = str("{}.settings".format(config_data.project_name)) + env["PYTHONPATH"] = str(os.pathsep.join(map(shlex_quote, sys.path))) kwargs = {} args = [] if config_data.template: - kwargs['template'] = config_data.template + kwargs["template"] = config_data.template args.append(config_data.project_name) if config_data.project_directory: args.append(config_data.project_directory) if not os.path.exists(config_data.project_directory): os.makedirs(config_data.project_directory) - base_cmd = 'django-admin.py' + base_cmd = "django-admin.py" start_cmds = [os.path.join(os.path.dirname(sys.executable), base_cmd)] - start_cmd_pnodes = ['Scripts'] - start_cmds.extend([ - os.path.join(os.path.dirname(sys.executable), pnode, base_cmd) - for pnode in start_cmd_pnodes - ]) + start_cmd_pnodes = ["Scripts"] + start_cmds.extend([os.path.join(os.path.dirname(sys.executable), pnode, base_cmd) for pnode in start_cmd_pnodes]) start_cmd = [base_cmd] for p in start_cmds: if os.path.exists(p): start_cmd = [sys.executable, p] break - cmd_args = start_cmd + ['startproject'] + args + cmd_args = start_cmd + ["startproject"] + args if config_data.verbose: - sys.stdout.write('Project creation command: {0}\n'.format(' '.join(cmd_args))) + sys.stdout.write("Project creation command: {}\n".format(" ".join(cmd_args))) try: output = subprocess.check_output(cmd_args, stderr=subprocess.STDOUT) - sys.stdout.write(output.decode('utf-8')) + sys.stdout.write(output.decode("utf-8")) except subprocess.CalledProcessError as e: # pragma: no cover - raise RuntimeError(e.output.decode('utf-8')) + raise RuntimeError(e.output.decode("utf-8")) def copy_files(config_data): @@ -65,23 +57,23 @@ def copy_files(config_data): :param config_data: configuration data """ - if config_data.i18n == 'yes': - urlconf_path = os.path.join(os.path.dirname(__file__), '../config/urls_i18n.py') + if config_data.i18n == "yes": + urlconf_path = os.path.join(os.path.dirname(__file__), "../config/urls_i18n.py") else: - urlconf_path = os.path.join(os.path.dirname(__file__), '../config/urls_noi18n.py') - share_path = os.path.join(os.path.dirname(__file__), '../share') - template_path = os.path.join(share_path, 'templates') - - media_project = os.path.join(config_data.project_directory, 'media') - static_main = os.path.join(config_data.project_path, 'static') - static_project = os.path.join(config_data.project_directory, 'static') - template_target = os.path.join(config_data.project_path, 'templates') + urlconf_path = os.path.join(os.path.dirname(__file__), "../config/urls_noi18n.py") + share_path = os.path.join(os.path.dirname(__file__), "../share") + template_path = os.path.join(share_path, "templates") + + media_project = os.path.join(config_data.project_directory, "media") + static_main = os.path.join(config_data.project_path, "static") + static_project = os.path.join(config_data.project_directory, "static") + template_target = os.path.join(config_data.project_path, "templates") if config_data.templates and os.path.isdir(config_data.templates): template_path = config_data.templates elif config_data.bootstrap: - template_path = os.path.join(template_path, 'bootstrap') + template_path = os.path.join(template_path, "bootstrap") else: - template_path = os.path.join(template_path, 'basic') + template_path = os.path.join(template_path, "basic") shutil.copy(urlconf_path, config_data.urlconf_path) if media_project: @@ -92,19 +84,19 @@ def copy_files(config_data): os.makedirs(static_project) if not os.path.exists(template_target): os.makedirs(template_target) - for filename in glob.glob(os.path.join(template_path, '*.html')): + for filename in glob.glob(os.path.join(template_path, "*.html")): if os.path.isfile(filename): shutil.copy(filename, template_target) if config_data.noinput and not config_data.no_user: - script_path = os.path.join(share_path, 'create_user.py') + script_path = os.path.join(share_path, "create_user.py") if os.path.isfile(script_path): - shutil.copy(script_path, os.path.join(config_data.project_path, '..')) + shutil.copy(script_path, os.path.join(config_data.project_path, "..")) if config_data.starting_page: - for filename in glob.glob(os.path.join(share_path, 'starting_page.*')): + for filename in glob.glob(os.path.join(share_path, "starting_page.*")): if os.path.isfile(filename): - shutil.copy(filename, os.path.join(config_data.project_path, '..')) + shutil.copy(filename, os.path.join(config_data.project_path, "..")) def patch_settings(config_data): @@ -115,94 +107,96 @@ def patch_settings(config_data): :param config_data: configuration data """ import django + current_django_version = LooseVersion(django.__version__) declared_django_version = LooseVersion(config_data.django_version) if not os.path.exists(config_data.settings_path): # pragma: no cover sys.stderr.write( - 'Error while creating target project, ' - 'please check the given configuration: {0}\n'.format(config_data.settings_path) + "Error while creating target project, " + "please check the given configuration: {}\n".format(config_data.settings_path) ) return sys.exit(5) if current_django_version.version[:2] != declared_django_version.version[:2]: sys.stderr.write( - 'Currently installed Django version {} differs from the declared {}. ' - 'Please check the given `--django-version` installer argument, your virtualenv ' - 'configuration and any package forcing a different Django version' - '\n'.format( - current_django_version, declared_django_version - ) + "Currently installed Django version {} differs from the declared {}. " + "Please check the given `--django-version` installer argument, your virtualenv " + "configuration and any package forcing a different Django version" + "\n".format(current_django_version, declared_django_version) ) return sys.exit(9) overridden_settings = ( - 'MIDDLEWARE_CLASSES', 'MIDDLEWARE', 'INSTALLED_APPS', 'TEMPLATE_LOADERS', - 'TEMPLATE_CONTEXT_PROCESSORS', 'TEMPLATE_DIRS', 'LANGUAGES' + "MIDDLEWARE_CLASSES", + "MIDDLEWARE", + "INSTALLED_APPS", + "TEMPLATE_LOADERS", + "TEMPLATE_CONTEXT_PROCESSORS", + "TEMPLATE_DIRS", + "LANGUAGES", ) - extra_settings = '' + extra_settings = "" - with open(config_data.settings_path, 'r') as fd_original: + with open(config_data.settings_path) as fd_original: original = fd_original.read() # extra settings reading if config_data.extra_settings and os.path.exists(config_data.extra_settings): - with open(config_data.extra_settings, 'r') as fd_extra: + with open(config_data.extra_settings) as fd_extra: extra_settings = fd_extra.read() - original = original.replace('# -*- coding: utf-8 -*-\n', '') + original = original.replace("# -*- coding: utf-8 -*-\n", "") - DATA_DIR = 'DATA_DIR = os.path.dirname(os.path.dirname(__file__))\n' - STATICFILES_DIR = 'os.path.join(BASE_DIR, \'{0}\', \'static\'),'.format( - config_data.project_name - ) + DATA_DIR = "DATA_DIR = os.path.dirname(os.path.dirname(__file__))\n" # noqa + STATICFILES_DIR = "os.path.join(BASE_DIR, '{}', 'static'),".format(config_data.project_name) # noqa original = data.DEFAULT_PROJECT_HEADER + DATA_DIR + original - original += 'MEDIA_URL = \'/media/\'\n' - original += 'MEDIA_ROOT = os.path.join(DATA_DIR, \'media\')\n' - original += 'STATIC_ROOT = os.path.join(DATA_DIR, \'static\')\n' + original += "MEDIA_URL = '/media/'\n" + original += "MEDIA_ROOT = os.path.join(DATA_DIR, 'media')\n" + original += "STATIC_ROOT = os.path.join(DATA_DIR, 'static')\n" original += """ STATICFILES_DIRS = ( - {0} + {} ) -""".format(STATICFILES_DIR) - original = original.replace('# -*- coding: utf-8 -*-\n', '') +""".format( + STATICFILES_DIR + ) + original = original.replace("# -*- coding: utf-8 -*-\n", "") # I18N - if config_data.i18n == 'no': - original = original.replace('I18N = True', 'I18N = False') - original = original.replace('L10N = True', 'L10N = False') + if config_data.i18n == "no": + original = original.replace("I18N = True", "I18N = False") + original = original.replace("L10N = True", "L10N = False") # TZ - if config_data.use_timezone == 'no': - original = original.replace('USE_TZ = True', 'USE_TZ = False') + if config_data.use_timezone == "no": + original = original.replace("USE_TZ = True", "USE_TZ = False") if config_data.languages: original = original.replace( - 'LANGUAGE_CODE = \'en-us\'', 'LANGUAGE_CODE = \'{0}\''.format(config_data.languages[0]) + "LANGUAGE_CODE = 'en-us'", "LANGUAGE_CODE = '{}'".format(config_data.languages[0]), ) if config_data.timezone: - original = original.replace( - 'TIME_ZONE = \'UTC\'', 'TIME_ZONE = \'{0}\''.format(config_data.timezone) - ) + original = original.replace("TIME_ZONE = 'UTC'", "TIME_ZONE = '{}'".format(config_data.timezone)) for item in overridden_settings: - item_re = re.compile(r'{0} = [^\]]+\]'.format(item), re.DOTALL | re.MULTILINE) - original = item_re.sub('', original) + item_re = re.compile(r"{} = [^\]]+\]".format(item), re.DOTALL | re.MULTILINE) + original = item_re.sub("", original) # TEMPLATES is special, so custom regexp needed - item_re = re.compile(r'TEMPLATES = .+\},\n\s+\},\n]$', re.DOTALL | re.MULTILINE) - original = item_re.sub('', original) + item_re = re.compile(r"TEMPLATES = .+\},\n\s+\},\n]$", re.DOTALL | re.MULTILINE) + original = item_re.sub("", original) # DATABASES is a dictionary, so different regexp needed - item_re = re.compile(r'DATABASES = [^\}]+\}[^\}]+\}', re.DOTALL | re.MULTILINE) - original = item_re.sub('', original) - if original.find('SITE_ID') == -1: - original += 'SITE_ID = 1\n\n' + item_re = re.compile(r"DATABASES = [^\}]+\}[^\}]+\}", re.DOTALL | re.MULTILINE) + original = item_re.sub("", original) + if original.find("SITE_ID") == -1: + original += "SITE_ID = 1\n\n" original += _build_settings(config_data) # Append extra settings at the end of the file - original += ('\n' + extra_settings) + original += "\n" + extra_settings - with open(config_data.settings_path, 'w') as fd_dest: + with open(config_data.settings_path, "w") as fd_dest: fd_dest.write(original) @@ -212,111 +206,127 @@ def _build_settings(config_data): :param config_data: configuration data """ - spacer = ' ' + spacer = " " text = [] - vars = get_settings() - - vars.MIDDLEWARE_CLASSES.insert(0, vars.APPHOOK_RELOAD_MIDDLEWARE_CLASS) - - processors = vars.TEMPLATE_CONTEXT_PROCESSORS + vars.TEMPLATE_CONTEXT_PROCESSORS_3 - text.append(data.TEMPLATES_1_8.format( - loaders=(',\n' + spacer * 4).join([ - "'{0}'".format(var) for var in vars.TEMPLATE_LOADERS - if ( - LooseVersion(config_data.django_version) < LooseVersion('2.0') or - 'eggs' not in var - ) - ]), - processors=(',\n' + spacer * 4).join(["'{0}'".format(var) for var in processors]), - dirs="os.path.join(BASE_DIR, '{0}', 'templates'),".format(config_data.project_name) - )) + settings_data = get_settings() + + settings_data.MIDDLEWARE_CLASSES.insert(0, settings_data.APPHOOK_RELOAD_MIDDLEWARE_CLASS) + + processors = settings_data.TEMPLATE_CONTEXT_PROCESSORS + settings_data.TEMPLATE_CONTEXT_PROCESSORS_3 + text.append( + data.TEMPLATES_1_8.format( + loaders=(",\n" + spacer * 4).join( + [ + "'{}'".format(var) + for var in settings_data.TEMPLATE_LOADERS + if (LooseVersion(config_data.django_version) < LooseVersion("2.0") or "eggs" not in var) + ] + ), + processors=(",\n" + spacer * 4).join(["'{}'".format(var) for var in processors]), + dirs="os.path.join(BASE_DIR, '{}', 'templates'),".format(config_data.project_name), + ) + ) - text.append('MIDDLEWARE = [\n{0}{1}\n]'.format( - spacer, (',\n' + spacer).join(['\'{0}\''.format(var) - for var in vars.MIDDLEWARE_CLASSES]) - )) + text.append( + "MIDDLEWARE = [\n{}{}\n]".format( + spacer, (",\n" + spacer).join(["'{}'".format(var) for var in settings_data.MIDDLEWARE_CLASSES]), + ) + ) - apps = list(vars.INSTALLED_APPS) - apps = list(vars.CMS_3_HEAD) + apps - apps.extend(vars.TREEBEARD_APPS) - apps.extend(vars.CMS_3_APPLICATIONS) + apps = list(settings_data.INSTALLED_APPS) + apps = list(settings_data.CMS_3_HEAD) + apps + apps.extend(settings_data.TREEBEARD_APPS) + apps.extend(settings_data.CMS_3_APPLICATIONS) if not config_data.no_plugins: - apps.extend(vars.FILER_PLUGINS_3) + apps.extend(settings_data.FILER_PLUGINS_3) - text.append('INSTALLED_APPS = [\n{0}{1}\n]'.format( - spacer, (',\n' + spacer).join(['\'{0}\''.format(var) for var in apps] + - ['\'{0}\''.format(config_data.project_name)]) - )) + text.append( + "INSTALLED_APPS = [\n{}{}\n]".format( + spacer, + (",\n" + spacer).join(["'{}'".format(var) for var in apps] + ["'{}'".format(config_data.project_name)]), + ) + ) - text.append('LANGUAGES = (\n{0}{1}\n{0}{2}\n)'.format( - spacer, '## Customize this', - ('\n' + spacer).join(['(\'{0}\', gettext(\'{0}\')),'.format(item) for item in config_data.languages]) # NOQA - )) + text.append( + "LANGUAGES = (\n{0}{1}\n{0}{2}\n)".format( + spacer, + "## Customize this", + ("\n" + spacer).join(["('{0}', gettext('{0}')),".format(item) for item in config_data.languages]), # NOQA + ) + ) - cms_langs = deepcopy(vars.CMS_LANGUAGES) + cms_langs = deepcopy(settings_data.CMS_LANGUAGES) for lang in config_data.languages: - lang_dict = {'code': lang, 'name': lang} - lang_dict.update(copy(cms_langs['default'])) + lang_dict = {"code": lang, "name": lang} + lang_dict.update(copy(cms_langs["default"])) cms_langs[1].append(lang_dict) - cms_text = ['CMS_LANGUAGES = {'] - cms_text.append('{0}{1}'.format(spacer, '## Customize this')) - for key, value in iteritems(cms_langs): - if key == 'default': - cms_text.append('{0}\'{1}\': {{'.format(spacer, key)) - for config_name, config_value in iteritems(value): - cms_text.append('{0}\'{1}\': {2},'.format(spacer * 2, config_name, config_value)) - cms_text.append('{0}}},'.format(spacer)) + cms_text = ["CMS_LANGUAGES = {"] + cms_text.append("{}{}".format(spacer, "## Customize this")) + for key, value in cms_langs.items(): + if key == "default": + cms_text.append("{0}'{1}': {{".format(spacer, key)) + for config_name, config_value in value.items(): + cms_text.append("{}'{}': {},".format(spacer * 2, config_name, config_value)) + cms_text.append("{0}}},".format(spacer)) else: - cms_text.append('{0}{1}: ['.format(spacer, key)) + cms_text.append("{}{}: [".format(spacer, key)) for lang in value: - cms_text.append('{0}{{'.format(spacer * 2)) - for config_name, config_value in iteritems(lang): - if config_name == 'code': - cms_text.append('{0}\'{1}\': \'{2}\','.format(spacer * 3, config_name, config_value)) # NOQA - elif config_name == 'name': - cms_text.append('{0}\'{1}\': gettext(\'{2}\'),'.format(spacer * 3, config_name, config_value)) # NOQA + cms_text.append("{0}{{".format(spacer * 2)) + for config_name, config_value in lang.items(): + if config_name == "code": + cms_text.append("{}'{}': '{}',".format(spacer * 3, config_name, config_value)) # NOQA + elif config_name == "name": + cms_text.append("{}'{}': gettext('{}'),".format(spacer * 3, config_name, config_value)) # NOQA else: - cms_text.append('{0}\'{1}\': {2},'.format( - spacer * 3, config_name, config_value - )) - cms_text.append('{0}}},'.format(spacer * 2)) - cms_text.append('{0}],'.format(spacer)) - cms_text.append('}') + cms_text.append("{}'{}': {},".format(spacer * 3, config_name, config_value)) + cms_text.append("{0}}},".format(spacer * 2)) + cms_text.append("{}],".format(spacer)) + cms_text.append("}") - text.append('\n'.join(cms_text)) + text.append("\n".join(cms_text)) if config_data.bootstrap: - cms_templates = 'CMS_TEMPLATES_BOOTSTRAP' + cms_templates = "CMS_TEMPLATES_BOOTSTRAP" else: - cms_templates = 'CMS_TEMPLATES' + cms_templates = "CMS_TEMPLATES" - text.append('CMS_TEMPLATES = (\n{0}{1}\n{0}{2}\n)'.format( - spacer, '## Customize this', - (',\n' + spacer).join( - ['(\'{0}\', \'{1}\')'.format(*item) for item in getattr(vars, cms_templates)] + text.append( + "CMS_TEMPLATES = (\n{0}{1}\n{0}{2}\n)".format( + spacer, + "## Customize this", + (",\n" + spacer).join(["('{}', '{}')".format(*item) for item in getattr(settings_data, cms_templates)]), ) - )) - - text.append('X_FRAME_OPTIONS = \'SAMEORIGIN\'') - text.append('CMS_PERMISSION = {0}'.format(vars.CMS_PERMISSION)) - text.append('CMS_PLACEHOLDER_CONF = {0}'.format(vars.CMS_PLACEHOLDER_CONF)) + ) - database = ['\'{0}\': {1}'.format(key, format_val(val)) for key, val in sorted(config_data.db_parsed.items(), key=lambda x: x[0])] # NOQA - text.append(textwrap.dedent(""" + text.append("X_FRAME_OPTIONS = 'SAMEORIGIN'") + text.append("CMS_PERMISSION = {}".format(settings_data.CMS_PERMISSION)) + text.append("CMS_PLACEHOLDER_CONF = {}".format(settings_data.CMS_PLACEHOLDER_CONF)) + + database = [ + "'{}': {}".format(key, format_val(val)) + for key, val in sorted(config_data.db_parsed.items(), key=lambda x: x[0]) + ] # NOQA + text.append( + textwrap.dedent( + """ DATABASES = {{ 'default': {{ {0} }} - }}""").strip().format((',\n' + spacer * 2).join(database))) # NOQA + }}""" + ) + .strip() + .format((",\n" + spacer * 2).join(database)) + ) # NOQA if config_data.filer: - text.append('THUMBNAIL_PROCESSORS = (\n{0}{1}\n)'.format( - spacer, (',\n' + spacer).join( - ['\'{0}\''.format(var) for var in vars.THUMBNAIL_PROCESSORS] + text.append( + "THUMBNAIL_PROCESSORS = (\n{}{}\n)".format( + spacer, (",\n" + spacer).join(["'{}'".format(var) for var in settings_data.THUMBNAIL_PROCESSORS]), ) - )) - return '\n\n'.join(text) + ) + return "\n\n".join(text) def setup_database(config_data): @@ -327,39 +337,33 @@ def setup_database(config_data): """ with chdir(config_data.project_directory): env = deepcopy(dict(os.environ)) - env[str('DJANGO_SETTINGS_MODULE')] = str('{0}.settings'.format(config_data.project_name)) - env[str('PYTHONPATH')] = str(os.pathsep.join(map(shlex_quote, sys.path))) + env["DJANGO_SETTINGS_MODULE"] = str("{}.settings".format(config_data.project_name)) + env["PYTHONPATH"] = str(os.pathsep.join(map(shlex_quote, sys.path))) commands = [] - commands.append( - [sys.executable, '-W', 'ignore', 'manage.py', 'migrate'], - ) + commands.append([sys.executable, "-W", "ignore", "manage.py", "migrate"]) if config_data.verbose: - sys.stdout.write( - 'Database setup commands: {0}\n'.format( - ', '.join([' '.join(cmd) for cmd in commands]) - ) - ) + sys.stdout.write("Database setup commands: {}\n".format(", ".join([" ".join(cmd) for cmd in commands]))) for command in commands: try: - output = subprocess.check_output( - command, env=env, stderr=subprocess.STDOUT - ) - sys.stdout.write(output.decode('utf-8')) + output = subprocess.check_output(command, env=env, stderr=subprocess.STDOUT) + sys.stdout.write(output.decode("utf-8")) except subprocess.CalledProcessError as e: # pragma: no cover if config_data.verbose: - sys.stdout.write(e.output.decode('utf-8')) + sys.stdout.write(e.output.decode("utf-8")) raise if not config_data.no_user: - sys.stdout.write('Creating admin user\n') + sys.stdout.write("Creating admin user\n") if config_data.noinput: create_user(config_data) else: # pragma: no cover - subprocess.check_call(' '.join( - [sys.executable, '-W', 'ignore', 'manage.py', 'createsuperuser'] - ), shell=True, stderr=subprocess.STDOUT) + subprocess.check_call( + " ".join([sys.executable, "-W", "ignore", "manage.py", "createsuperuser"]), + shell=True, + stderr=subprocess.STDOUT, + ) def create_user(config_data): @@ -370,14 +374,12 @@ def create_user(config_data): """ with chdir(os.path.abspath(config_data.project_directory)): env = deepcopy(dict(os.environ)) - env[str('DJANGO_SETTINGS_MODULE')] = str('{0}.settings'.format(config_data.project_name)) - env[str('PYTHONPATH')] = str(os.pathsep.join(map(shlex_quote, sys.path))) - subprocess.check_call( - [sys.executable, 'create_user.py'], env=env, stderr=subprocess.STDOUT - ) - for ext in ['py', 'pyc']: + env["DJANGO_SETTINGS_MODULE"] = str("{}.settings".format(config_data.project_name)) + env["PYTHONPATH"] = str(os.pathsep.join(map(shlex_quote, sys.path))) + subprocess.check_call([sys.executable, "create_user.py"], env=env, stderr=subprocess.STDOUT) + for ext in ["py", "pyc"]: try: - os.remove('create_user.{0}'.format(ext)) + os.remove("create_user.{}".format(ext)) except OSError: pass @@ -390,13 +392,11 @@ def load_starting_page(config_data): """ with chdir(os.path.abspath(config_data.project_directory)): env = deepcopy(dict(os.environ)) - env[str('DJANGO_SETTINGS_MODULE')] = str('{0}.settings'.format(config_data.project_name)) - env[str('PYTHONPATH')] = str(os.pathsep.join(map(shlex_quote, sys.path))) - subprocess.check_call( - [sys.executable, 'starting_page.py'], env=env, stderr=subprocess.STDOUT - ) - for ext in ['py', 'pyc', 'json']: + env["DJANGO_SETTINGS_MODULE"] = str("{}.settings".format(config_data.project_name)) + env["PYTHONPATH"] = str(os.pathsep.join(map(shlex_quote, sys.path))) + subprocess.check_call([sys.executable, "starting_page.py"], env=env, stderr=subprocess.STDOUT) + for ext in ["py", "pyc", "json"]: try: - os.remove('starting_page.{0}'.format(ext)) + os.remove("starting_page.{}".format(ext)) except OSError: pass diff --git a/djangocms_installer/install/__init__.py b/djangocms_installer/install/__init__.py index ef5cbe61..81826bcd 100644 --- a/djangocms_installer/install/__init__.py +++ b/djangocms_installer/install/__init__.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - import logging import os.path import shutil @@ -9,7 +6,7 @@ from djangocms_installer.utils import query_yes_no -logger = logging.getLogger('') +logger = logging.getLogger("") def check_install(config_data): @@ -29,90 +26,90 @@ def check_install(config_data): from PIL import Image try: - im = Image.open(os.path.join(os.path.dirname(__file__), '../share/test_image.png')) + im = Image.open(os.path.join(os.path.dirname(__file__), "../share/test_image.png")) im.load() - except IOError: # pragma: no cover + except OSError: # pragma: no cover errors.append( 'Pillow is not compiled with PNG support, see "Libraries installation issues" ' - 'documentation section: https://djangocms-installer.readthedocs.io/en/latest/' - 'libraries.html.' + "documentation section: https://djangocms-installer.readthedocs.io/en/latest/" + "libraries.html." ) try: - im = Image.open(os.path.join(os.path.dirname(__file__), '../share/test_image.jpg')) + im = Image.open(os.path.join(os.path.dirname(__file__), "../share/test_image.jpg")) im.load() - except IOError: # pragma: no cover + except OSError: # pragma: no cover errors.append( 'Pillow is not compiled with JPEG support, see "Libraries installation issues" ' - 'documentation section: https://djangocms-installer.readthedocs.io/en/latest/' - 'libraries.html' + "documentation section: https://djangocms-installer.readthedocs.io/en/latest/" + "libraries.html" ) except ImportError: # pragma: no cover errors.append( 'Pillow is not installed check for installation errors and see "Libraries installation' ' issues" documentation section: https://djangocms-installer.readthedocs.io/en/latest/' - 'libraries.html' + "libraries.html" ) # PostgreSQL test - if config_data.db_driver == 'psycopg2' and not config_data.no_db_driver: # pragma: no cover + if config_data.db_driver == "psycopg2" and not config_data.no_db_driver: # pragma: no cover try: import psycopg2 # NOQA except ImportError: errors.append( - 'PostgreSQL driver is not installed, but you configured a PostgreSQL database, ' + "PostgreSQL driver is not installed, but you configured a PostgreSQL database, " 'please check your installation and see "Libraries installation issues" ' - 'documentation section: https://djangocms-installer.readthedocs.io/en/latest/' - 'libraries.html' + "documentation section: https://djangocms-installer.readthedocs.io/en/latest/" + "libraries.html" ) # MySQL test - if config_data.db_driver == 'mysqlclient' and not config_data.no_db_driver: # pragma: no cover # NOQA + if config_data.db_driver == "mysqlclient" and not config_data.no_db_driver: # pragma: no cover # NOQA try: import MySQLdb # NOQA except ImportError: errors.append( - 'MySQL driver is not installed, but you configured a MySQL database, please check ' + "MySQL driver is not installed, but you configured a MySQL database, please check " 'your installation and see "Libraries installation issues" documentation section: ' - 'https://djangocms-installer.readthedocs.io/en/latest/libraries.html' + "https://djangocms-installer.readthedocs.io/en/latest/libraries.html" ) if errors: # pragma: no cover - raise EnvironmentError('\n'.join(errors)) + raise OSError("\n".join(errors)) -def requirements(req_file, pip_options='', is_file=False, verbose=False): - args = ['install', '--disable-pip-version-check'] +def requirements(req_file, pip_options="", is_file=False, verbose=False): + args = ["install", "--disable-pip-version-check"] if not verbose: - args.append('-q') + args.append("-q") if pip_options: - args.extend([opt for opt in pip_options.split(' ') if opt]) + args.extend([opt for opt in pip_options.split(" ") if opt]) if is_file: # pragma: no cover - args += ['-r', req_file] + args += ["-r", req_file] else: - args.extend(['{0}'.format(package) for package in req_file.split()]) - cmd = [sys.executable, '-mpip'] + args + args.extend(["{}".format(package) for package in req_file.split()]) + cmd = [sys.executable, "-mpip"] + args if verbose: - sys.stdout.write('python path: {0}\n'.format(sys.executable)) - sys.stdout.write('packages install command: {0}\n'.format(' '.join(cmd))) + sys.stdout.write("python path: {}\n".format(sys.executable)) + sys.stdout.write("packages install command: {}\n".format(" ".join(cmd))) try: - subprocess.check_output(['python', '-msite'], stderr=subprocess.STDOUT) + subprocess.check_output(["python", "-msite"], stderr=subprocess.STDOUT) output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) - sys.stdout.write(output.decode('utf-8')) + sys.stdout.write(output.decode("utf-8")) except Exception as e: # pragma: no cover - logger.error('cmd : %s :%s' % (e.cmd, e.output)) + logger.error("cmd : {} :{}".format(e.cmd, e.output)) raise return True def write_requirements(config_data): - with open(os.path.join(config_data.project_directory, 'requirements.txt'), 'w') as reqfile: + with open(os.path.join(config_data.project_directory, "requirements.txt"), "w") as reqfile: reqfile.write(config_data.requirements) def cleanup(requirements): # pragma: no cover import pip - args = ['uninstall', '-q', '-y'] + args = ["uninstall", "-q", "-y"] args.extend(requirements.split()) pip.main(args) return True @@ -126,21 +123,17 @@ def cleanup_directory(config_data): choice = False if config_data.noinput is False and not config_data.verbose: # pragma: no cover choice = query_yes_no( - 'The installation failed.\n' - 'Do you want to clean up by removing {0}?\n' - '\tWarning: this will delete all files in:\n' - '\t\t{0}\n' - 'Do you want to cleanup?'.format( - os.path.abspath(config_data.project_directory) - ), - 'no' + "The installation failed.\n" + "Do you want to clean up by removing {0}?\n" + "\tWarning: this will delete all files in:\n" + "\t\t{0}\n" + "Do you want to cleanup?".format(os.path.abspath(config_data.project_directory)), + "no", ) else: - sys.stdout.write('The installation has failed.\n') - if config_data.skip_project_dir_check is False and (choice or - (config_data.noinput and - config_data.delete_project_dir)): - sys.stdout.write('Removing everything under {0}\n'.format( - os.path.abspath(config_data.project_directory) - )) + sys.stdout.write("The installation has failed.\n") + if config_data.skip_project_dir_check is False and ( + choice or (config_data.noinput and config_data.delete_project_dir) + ): + sys.stdout.write("Removing everything under {}\n".format(os.path.abspath(config_data.project_directory))) shutil.rmtree(config_data.project_directory, True) diff --git a/djangocms_installer/main.py b/djangocms_installer/main.py index 01d965a6..c74d5a1e 100644 --- a/djangocms_installer/main.py +++ b/djangocms_installer/main.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - import logging import os import sys @@ -10,7 +7,7 @@ def execute(): # Log info and above to console - logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO) + logging.basicConfig(format="%(levelname)s: %(message)s", level=logging.INFO) config_data = config.parse(sys.argv[1:]) try: @@ -20,22 +17,20 @@ def execute(): config.show_requirements(config_data) else: sys.stdout.write( - 'Creating the project\n' - 'Please wait while I install dependencies\n' - 'If I am stuck for a long time, please check for connectivity / PyPi issues\n' + "Creating the project\n" + "Please wait while I install dependencies\n" + "If I am stuck for a long time, please check for connectivity / PyPi issues\n" ) if not config_data.no_deps: if config_data.requirements_file: install.requirements( - config_data.requirements_file, config_data.pip_options, True, - verbose=config_data.verbose + config_data.requirements_file, config_data.pip_options, True, verbose=config_data.verbose, ) else: install.requirements( - config_data.requirements, config_data.pip_options, - verbose=config_data.verbose + config_data.requirements, config_data.pip_options, verbose=config_data.verbose, ) - sys.stdout.write('Dependencies installed\nCreating the project\n') + sys.stdout.write("Dependencies installed\nCreating the project\n") install.check_install(config_data) django.create_project(config_data) django.patch_settings(config_data) @@ -46,15 +41,15 @@ def execute(): django.load_starting_page(config_data) if not config_data.requirements_file: install.write_requirements(config_data) - sys.stdout.write('All done!\n') + sys.stdout.write("All done!\n") sys.stdout.write( - 'Get into "{0}" directory and type "python manage.py runserver" to start your ' - 'project\n'.format(os.path.abspath(config_data.project_directory)) + 'Get into "{}" directory and type "python manage.py runserver" to start your ' + "project\n".format(os.path.abspath(config_data.project_directory)) ) except Exception: # Clean up your own mess install.cleanup_directory(config_data) - doc_message = 'Check documentation at https://djangocms-installer.readthedocs.io' - exception_message = '\n\n{0}\n\n{1}\n\n{0}\n\n'.format('*' * len(doc_message), doc_message) + doc_message = "Check documentation at https://djangocms-installer.readthedocs.io" + exception_message = "\n\n{0}\n\n{1}\n\n{0}\n\n".format("*" * len(doc_message), doc_message) sys.stdout.write(exception_message) raise diff --git a/djangocms_installer/share/__init__.py b/djangocms_installer/share/__init__.py index 40a96afc..e69de29b 100644 --- a/djangocms_installer/share/__init__.py +++ b/djangocms_installer/share/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/djangocms_installer/share/create_user.py b/djangocms_installer/share/create_user.py index 6ed50d01..b9aa55ec 100644 --- a/djangocms_installer/share/create_user.py +++ b/djangocms_installer/share/create_user.py @@ -1,13 +1,10 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - from django.contrib.auth import get_user_model -if __name__ == '__main__': +if __name__ == "__main__": import django django.setup() User = get_user_model() if not User.objects.filter(is_superuser=True).exists(): - User.objects.create_superuser('admin', 'admin@admin.com', 'admin') + User.objects.create_superuser("admin", "admin@admin.com", "admin") diff --git a/djangocms_installer/share/starting_page.py b/djangocms_installer/share/starting_page.py index 6be2ff9c..8d7140c4 100644 --- a/djangocms_installer/share/starting_page.py +++ b/djangocms_installer/share/starting_page.py @@ -1,55 +1,50 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - import json def create_pages(): + from cms.api import add_plugin, create_page, publish_page from cms.models import Placeholder - from cms.api import create_page, add_plugin, publish_page from django.conf import settings from django.contrib.auth.models import User from django.utils.translation import ugettext_lazy as _ placeholder = {} - with open('starting_page.json') as data_file: + with open("starting_page.json") as data_file: content = json.load(data_file) try: # try to get a feature template with fallback template = settings.CMS_TEMPLATES[1][0] - if template != 'feature.html': + if template != "feature.html": template = settings.CMS_TEMPLATES[0][0] except IndexError: template = settings.CMS_TEMPLATES[0][0] lang = settings.LANGUAGES[0][0] - page = create_page(_('Home'), template, lang) - placeholder['main'] = page.placeholders.get(slot='content') + page = create_page(_("Home"), template, lang) + placeholder["main"] = page.placeholders.get(slot="content") try: # try to get a feature placeholder - placeholder_feature = page.placeholders.get(slot='feature') - add_plugin(placeholder_feature, 'TextPlugin', lang, body=content['feature']) + placeholder_feature = page.placeholders.get(slot="feature") + add_plugin(placeholder_feature, "TextPlugin", lang, body=content["feature"]) except Placeholder.DoesNotExist: # fallback, add it to the - add_plugin(placeholder['main'], 'TextPlugin', lang, body=content['feature']) + add_plugin(placeholder["main"], "TextPlugin", lang, body=content["feature"]) # Add main content to a Bootstrap4GridRow - row_plugin = add_plugin(placeholder['main'], 'Bootstrap4GridRowPlugin', lang) - for column_content in content['main']: - col = add_plugin( - placeholder['main'], 'Bootstrap4GridColumnPlugin', lang, target=row_plugin - ) - add_plugin(placeholder['main'], 'TextPlugin', lang, body=column_content, target=col) + row_plugin = add_plugin(placeholder["main"], "Bootstrap4GridRowPlugin", lang) + for column_content in content["main"]: + col = add_plugin(placeholder["main"], "Bootstrap4GridColumnPlugin", lang, target=row_plugin) + add_plugin(placeholder["main"], "TextPlugin", lang, body=column_content, target=col) # In order to publish the page there needs to be at least one user if User.objects.count() > 0: publish_page(page, User.objects.all()[0], lang) -if __name__ == '__main__': +if __name__ == "__main__": import django django.setup() diff --git a/djangocms_installer/utils.py b/djangocms_installer/utils.py index 1676ec39..fddcc5e8 100644 --- a/djangocms_installer/utils.py +++ b/djangocms_installer/utils.py @@ -1,14 +1,8 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - import os import sys from decimal import Decimal, InvalidOperation from distutils.version import LooseVersion -from six import text_type - -from . import compat from .config.data import CMS_VERSION_MATRIX, DJANGO_VERSION_MATRIX, VERSION_MATRIX @@ -26,21 +20,21 @@ def query_yes_no(question, default=None): # pragma: no cover Code borrowed from cookiecutter https://github.com/audreyr/cookiecutter/blob/master/cookiecutter/prompt.py """ - valid = {'yes': True, 'y': True, 'ye': True, 'no': False, 'n': False} + valid = {"yes": True, "y": True, "ye": True, "no": False, "n": False} if default is None: - prompt = ' [y/n] ' - elif default == 'yes': - prompt = ' [Y/n] ' - elif default == 'no': - prompt = ' [y/N] ' + prompt = " [y/n] " + elif default == "yes": + prompt = " [Y/n] " + elif default == "no": + prompt = " [y/N] " else: - raise ValueError('invalid default answer: "{0}"'.format(default)) + raise ValueError('invalid default answer: "{}"'.format(default)) while True: sys.stdout.write(question + prompt) - choice = compat.input().lower() + choice = input().lower() - if default is not None and choice == '': + if default is not None and choice == "": return valid[default] elif choice in valid: return valid[choice] @@ -73,23 +67,26 @@ def supported_versions(django, cms): try: if ( - cms_version and django_version and - not (LooseVersion(VERSION_MATRIX[compat.unicode(cms_version)][0]) <= - LooseVersion(compat.unicode(django_version)) <= - LooseVersion(VERSION_MATRIX[compat.unicode(cms_version)][-1])) + cms_version + and django_version + and not ( + LooseVersion(VERSION_MATRIX[str(cms_version)][0]) + <= LooseVersion(str(django_version)) + <= LooseVersion(VERSION_MATRIX[str(cms_version)][-1]) + ) ): raise RuntimeError( - 'Django and django CMS versions doesn\'t match: ' - 'Django {0} is not supported by django CMS {1}'.format(django_version, cms_version) + "Django and django CMS versions doesn't match: " + "Django {} is not supported by django CMS {}".format(django_version, cms_version) ) except KeyError: raise RuntimeError( - 'Django and django CMS versions doesn\'t match: ' - 'Django {0} is not supported by django CMS {1}'.format(django_version, cms_version) + "Django and django CMS versions doesn't match: " + "Django {} is not supported by django CMS {}".format(django_version, cms_version) ) return ( - compat.unicode(django_version) if django_version else django_version, - compat.unicode(cms_version) if cms_version else cms_version + str(django_version) if django_version else django_version, + str(cms_version) if cms_version else cms_version, ) @@ -98,17 +95,18 @@ def less_than_version(value): Converts the current version to the next one for inserting into requirements in the ' < version' format """ - items = list(map(int, str(value).split('.'))) + items = list(map(int, str(value).split("."))) if len(items) == 1: items.append(0) items[1] += 1 - return '.'.join(map(str, items)) + return ".".join(map(str, items)) -class chdir(object): +class chdir: # noqa """ Context manager for changing the current working directory """ + def __init__(self, new_path): self.new_path = new_path @@ -126,8 +124,8 @@ def format_val(val): :param val: any value :return: formatted string """ - val = text_type(val) + val = str(val) if val.isdigit(): return int(val) else: - return '\'{0}\''.format(val) + return "'{}'".format(val) diff --git a/docs/Makefile b/docs/Makefile index 1005e265..0e35bee9 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -174,4 +174,4 @@ 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 + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/docs/authors.rst b/docs/authors.rst index 94292d01..e122f914 100644 --- a/docs/authors.rst +++ b/docs/authors.rst @@ -1 +1 @@ -.. include:: ../AUTHORS.rst \ No newline at end of file +.. include:: ../AUTHORS.rst diff --git a/docs/conf.py b/docs/conf.py index fb41ff2d..b0ba7efa 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- # # complexity documentation build configuration file, created by # sphinx-quickstart on Tue Jul 9 22:26:36 2013. @@ -15,52 +14,49 @@ import os import sys -import sphinx.environment -from docutils.utils import get_source_line - # 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('.')) +# sys.path.insert(0, os.path.abspath('.')) cwd = os.getcwd() parent = os.path.dirname(cwd) sys.path.append(parent) -import djangocms_installer # isort:skip - +import djangocms_installer # isort:skip # noqa -def _warn_node(self, msg, node, *args, **kwargs): - if not msg.startswith('nonlocal image URI found:'): - self._warnfunc(msg, '%s:%s' % get_source_line(node)) - -sphinx.environment.BuildEnvironment.warn_node = _warn_node # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +# 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.doctest', 'sphinx.ext.intersphinx', - 'sphinx.ext.todo', 'sphinx.ext.coverage', - 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode'] +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.doctest", + "sphinx.ext.intersphinx", + "sphinx.ext.todo", + "sphinx.ext.coverage", + "sphinx.ext.ifconfig", + "sphinx.ext.viewcode", +] # Add any paths that contain templates here, relative to this directory. -#templates_path = ['_templates'] +# templates_path = ['_templates'] # The suffix of source filenames. -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = u'django CMS Installer' -copyright = u'2013, Iacopo Spalletti' +project = "django CMS Installer" +copyright = "2013, Iacopo Spalletti" # noqa # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -73,174 +69,168 @@ def _warn_node(self, msg, node, *args, **kwargs): # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -#language = None +# language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# 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'] +exclude_patterns = ["_build"] # The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# 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 +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False +# 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 = 'sphinx_rtd_theme' +html_theme = "sphinx_rtd_theme" # 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 = {} +# html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +# html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -#html_title = None +# html_title = None # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# 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 +# 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 +# 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'] +# 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' +# 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 +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +# html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = 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 = '' +# html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None # Output file base name for HTML help builder. -htmlhelp_basename = 'djangocms_installerdoc' +htmlhelp_basename = "djangocms_installerdoc" # -- 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': '', + # 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', 'djangocms_installer.tex', u'django CMS Installer Documentation', - u'Iacopo Spalletti', 'manual'), + ("index", "djangocms_installer.tex", "django CMS Installer Documentation", "Iacopo Spalletti", "manual",), ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# 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', 'djangocms_installer', u'django CMS Installer Documentation', - [u'Iacopo Spalletti'], 1) -] +man_pages = [("index", "djangocms_installer", "django CMS Installer Documentation", ["Iacopo Spalletti"], 1,)] # If true, show URL addresses after external links. -#man_show_urls = False +# man_show_urls = False # -- Options for Texinfo output ------------------------------------------------ @@ -249,19 +239,25 @@ def _warn_node(self, msg, node, *args, **kwargs): # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'djangocms_installer', u'django CMS Installer Documentation', - u'Iacopo Spalletti', 'djangocms_installer', 'One line description of project.', - 'Miscellaneous'), + ( + "index", + "djangocms_installer", + "django CMS Installer Documentation", + "Iacopo Spalletti", + "djangocms_installer", + "One line description of project.", + "Miscellaneous", + ), ] # Documents to append as an appendix to all manuals. -#texinfo_appendices = [] +# texinfo_appendices = [] # If false, no module index is generated. -#texinfo_domain_indices = True +# texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' +# texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False +# texinfo_no_detailmenu = False diff --git a/docs/contributing.rst b/docs/contributing.rst index 3bdd7dc2..e582053e 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -1 +1 @@ -.. include:: ../CONTRIBUTING.rst \ No newline at end of file +.. include:: ../CONTRIBUTING.rst diff --git a/docs/history.rst b/docs/history.rst index bec23d82..25064996 100644 --- a/docs/history.rst +++ b/docs/history.rst @@ -1 +1 @@ -.. include:: ../HISTORY.rst \ No newline at end of file +.. include:: ../HISTORY.rst diff --git a/docs/make.bat b/docs/make.bat index 2b447647..2df9a8cb 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -239,4 +239,4 @@ if "%1" == "pseudoxml" ( goto end ) -:end \ No newline at end of file +:end diff --git a/docs/readme.rst b/docs/readme.rst index 6b2b3ec6..72a33558 100644 --- a/docs/readme.rst +++ b/docs/readme.rst @@ -1 +1 @@ -.. include:: ../README.rst \ No newline at end of file +.. include:: ../README.rst diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..3e01b4aa --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,30 @@ +[build-system] +requires = ["setuptools>=40.6.0", "wheel"] +build-backend = "setuptools.build_meta" + +[tool.black] +line-length = 119 +target-version = ["py27"] +include = 'app_helper/*py' + +[tool.towncrier] +package = "app_helper" +directory = "changes" +filename = "HISTORY.rst" +title_format = "{version} ({project_date})" + +[tool.interrogate] +ignore-init-method = true +ignore-init-module = true +ignore-magic = false +ignore-semiprivate = false +ignore-private = false +ignore-module = true +ignore-nested-functions = true +fail-under = 0 +exclude = ["docs", ".tox"] +ignore-regex = ["^get$", "^mock_.*", ".*BaseClass.*"] +verbose = 0 +quiet = false +whitelist-regex = [] +color = true diff --git a/requirements-test.txt b/requirements-test.txt index d5cbf9a5..42aa8933 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -4,3 +4,4 @@ tox mock pillow coverage>=5 +coveralls>=2 diff --git a/requirements.txt b/requirements.txt index a042b633..d6e1198b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1 @@ -dj-database-url>=0.4 -pip -six -tzlocal +-e . diff --git a/setup.cfg b/setup.cfg index 13b0770e..4b8e093d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,19 +1,81 @@ -[flake8] -exclude = *.egg-info,.git,.settings,.tox,build,dist,docs,requirements,tmp,*migrations*,*south_migrations*,tests,data,.eggs -max-line-length = 99 +[bumpversion] +current_version = 2.0.0.dev0 +parse = (?P\d+)\.(?P\d+)\.(?P\d+)(\.?)(?P[a-z]*)(?P\d*) +serialize = + {major}.{minor}.{patch}.{release}{relver} + {major}.{minor}.{patch} +commit = True +tag = True +sign_tags = True +tag_name = {new_version} +message = Release {new_version} + +[bumpversion:part:release] +optional_value = gamma +values = + dev + a + b + rc + gamma + +[bumpversion:file:djangocms_installer/__init__.py] [metadata] -license-file = LICENSE +name = djangocms-installer +version = attr: djangocms_installer.__version__ +url = https://github.com/nephila/djangocms-installer +project_urls = + Documentation = https://djangocms-installer.readthedocs.io/ +author = Iacopo Spalletti +author_email = i.spalletti@nephila.it +description = Command to easily bootstrap django CMS projects +long_description = file: README.rst, HISTORY.rst +long_description_content_type = text/x-rst +license = BSD +license_file = LICENSE +classifiers = + Development Status :: 5 - Production/Stable, + Framework :: Django, + Intended Audience :: Developers, + License :: OSI Approved :: BSD License, + Natural Language :: English, + Programming Language :: Python :: 3, + Programming Language :: Python :: 3.5, + Programming Language :: Python :: 3.6, + Programming Language :: Python :: 3.7, + Programming Language :: Python :: 3.8, + Framework :: Django, + Framework :: Django :: 2.2, + Framework :: Django :: 3.0, + Topic :: Software Development -[wheel] -universal = 1 +[options] +include_package_data = True +install_requires = + dj-database-url>=0.4 + six + tzlocal +setup_requires = + setuptools +packages = find: +python_requires = >=3.5 +test_suite = tests +zip_safe = False + +[options.package_data] +* = *.txt, *.rst +djangocms_installer = *.html *.png *.gif *js *jpg *jpeg *svg *py *mo *po -[isort] -line_length = 99 -skip = migrations, south_migrations -combine_as_imports = true -default_section = THIRDPARTY -include_trailing_comma = true -known_first_party = djangocms_installer -multi_line_output = 5 -not_skip = __init__.py +[options.entry_points] +console_scripts = + djangocms = djangocms_installer.main:execute + +[upload] +repository = https://upload.pypi.org/legacy/ + +[sdist] +formats = zip + +[bdist_wheel] +universal = 1 diff --git a/setup.py b/setup.py index 7b566965..b908cbe5 100644 --- a/setup.py +++ b/setup.py @@ -1,63 +1,3 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- +import setuptools -import os -import sys - -from setuptools import find_packages, setup - -import djangocms_installer - -if sys.argv[-1] == 'publish': - os.system('python setup.py sdist upload') - sys.exit() - -readme = open('README.rst').read() -history = open('HISTORY.rst').read().replace('.. :changelog:', '') - -requirements = open('requirements.txt').readlines() -test_requirements = [] - - -setup( - name='djangocms-installer', - version=djangocms_installer.__version__, - description='Command to easily bootstrap django CMS projects', - long_description=readme + '\n\n' + history, - author='Iacopo Spalletti', - author_email='i.spalletti@nephila.it', - url='https://github.com/nephila/djangocms-installer', - packages=find_packages(), - package_dir={'djangocms_installer': 'djangocms_installer'}, - include_package_data=True, - install_requires=requirements, - entry_points={ - 'console_scripts': [ - 'djangocms = djangocms_installer.main:execute', - ] - }, - license='BSD', - zip_safe=False, - keywords='djangocms-installer', - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Framework :: Django', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: BSD License', - 'Natural Language :: English', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Framework :: Django', - 'Framework :: Django :: 1.11', - 'Framework :: Django :: 2.0', - 'Framework :: Django :: 2.1', - 'Framework :: Django :: 2.2', - 'Topic :: Software Development', - ], - test_suite='tests', - tests_require=test_requirements -) +setuptools.setup() diff --git a/tasks.py b/tasks.py new file mode 100644 index 00000000..82261dda --- /dev/null +++ b/tasks.py @@ -0,0 +1,140 @@ +import io +import os +import re +import sys +from glob import glob + +from invoke import task + +DOCS_PORT = os.environ.get("DOCS_PORT", 8000) +#: branch prefixes for which some checks are skipped +SPECIAL_BRANCHES = ("master", "develop", "release") + + +@task +def clean(c): + """ Remove artifacts and binary files. """ + c.run("python setup.py clean --all") + patterns = ["build", "dist"] + patterns.extend(glob("*.egg*")) + patterns.append("docs/_build") + patterns.append("**/*.pyc") + for pattern in patterns: + c.run("rm -rf {}".format(pattern)) + + +@task +def lint(c): + """ Run linting tox environments. """ + c.run("tox -epep8,isort,black,pypi-description") + + +@task # NOQA +def format(c): # NOQA + """ Run code formatting tasks. """ + c.run("tox -eblacken,isort_format") + + +@task +def towncrier_check(c): # NOQA + """ Check towncrier files. """ + output = io.StringIO() + c.run("git branch --contains HEAD", out_stream=output) + skipped_branch_prefix = ["pull/", "develop", "master", "HEAD"] + # cleanup branch names by removing PR-only names in local, remote and disconnected branches to ensure the current + # (i.e. user defined) branch name is used + branches = list( + filter( + lambda x: x and all(not x.startswith(part) for part in skipped_branch_prefix), + ( + branch.replace("origin/", "").replace("remotes/", "").strip("* (") + for branch in output.getvalue().split("\n") + ), + ) + ) + print("Candidate branches", ", ".join(output.getvalue().split("\n"))) + if not branches: + # if no branch name matches, we are in one of the excluded branches above, so we just exit + print("Skip check, branch excluded by configuration") + return + branch = branches[0] + towncrier_file = None + for branch in branches: + if any(branch.startswith(prefix) for prefix in SPECIAL_BRANCHES): + sys.exit(0) + try: + parts = re.search(r"(?P\w+)/\D*(?P\d+)\D*", branch).groups() + towncrier_file = os.path.join("changes", "{1}.{0}".format(*parts)) + if not os.path.exists(towncrier_file) or os.path.getsize(towncrier_file) == 0: + print( + "=========================\n" + "Current tree does not contain the towncrier file {} or file is empty\n" + "please check CONTRIBUTING documentation.\n" + "=========================" + "".format(towncrier_file) + ) + sys.exit(2) + else: + break + except AttributeError: + pass + if not towncrier_file: + print( + "=========================\n" + "Branch {} does not respect the '/(-)-description' format\n" + "=========================\n" + "".format(branch) + ) + sys.exit(1) + + +@task +def test(c): + """ Run test in local environment. """ + c.run("python setup.py test") + + +@task +def test_all(c): + """ Run all tox environments. """ + c.run("tox") + + +@task +def coverage(c): + """ Run test with coverage in local environment. """ + c.run("coverage erase") + c.run("run setup.py test") + c.run("report -m") + + +@task +def tag_release(c, level): + """ Tag release version. """ + c.run("bumpversion --list %s --no-tag" % level) + + +@task +def tag_dev(c, level="patch"): + """ Tag development version. """ + c.run("bumpversion --list %s --message='Bump develop version [ci skip]' --no-tag" % level) + + +@task(pre=[clean]) +def docbuild(c): + """ Build documentation. """ + os.chdir("docs") + build_dir = os.environ.get("BUILD_DIR", "_build/html") + c.run("python -msphinx -W -b html -d _build/doctrees . %s" % build_dir) + + +@task(docbuild) +def docserve(c): + """ Serve docs at http://localhost:$DOCS_PORT/ (default port is 8000). """ + from livereload import Server + + server = Server() + server.watch("docs/conf.py", lambda: docbuild(c)) + server.watch("CONTRIBUTING.rst", lambda: docbuild(c)) + server.watch("docs/*.rst", lambda: docbuild(c)) + server.serve(port=DOCS_PORT, root="_build/html") diff --git a/tests/__init__.py b/tests/__init__.py index 40a96afc..e69de29b 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/tests/base.py b/tests/base.py index a3f82431..180ee5c4 100644 --- a/tests/base.py +++ b/tests/base.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - import os import shutil import subprocess @@ -11,7 +8,7 @@ from six import StringIO -SYSTEM_ACTIVATE = os.path.join(os.path.dirname(sys.executable), 'activate_this.py') +SYSTEM_ACTIVATE = os.path.join(os.path.dirname(sys.executable), "activate_this.py") class BaseTestClass(unittest.TestCase): @@ -22,18 +19,19 @@ class BaseTestClass(unittest.TestCase): def _remove_project_dir(self): if ( - self.project_dir and os.path.exists(self.project_dir) and - not os.environ.get('INSTALLER_TEST_KEEP_VIRTUALENV') + self.project_dir + and os.path.exists(self.project_dir) + and not os.environ.get("INSTALLER_TEST_KEEP_VIRTUALENV") ): shutil.rmtree(self.project_dir) self.project_dir = None def _create_project_dir(self): - if os.environ.get('USE_SHM', 'no') == 'yes': - if os.path.exists('/run/shm'): - self.project_dir = tempfile.mkdtemp(dir='/run/shm') - elif os.path.exists('/dev/shm'): - self.project_dir = tempfile.mkdtemp(dir='/dev/shm') + if os.environ.get("USE_SHM", "no") == "yes": + if os.path.exists("/run/shm"): + self.project_dir = tempfile.mkdtemp(dir="/run/shm") + elif os.path.exists("/dev/shm"): + self.project_dir = tempfile.mkdtemp(dir="/dev/shm") else: self.project_dir = tempfile.mkdtemp() else: @@ -43,8 +41,8 @@ def tearDown(self): self._remove_project_dir() self.stdout = None self.stderr = None - if 'DJANGO_SETTINGS_MODULE' in os.environ: - del os.environ['DJANGO_SETTINGS_MODULE'] + if "DJANGO_SETTINGS_MODULE" in os.environ: + del os.environ["DJANGO_SETTINGS_MODULE"] sys.path = self.syspath def setUp(self): @@ -56,57 +54,61 @@ def setUp(self): class IsolatedTestClass(BaseTestClass): virtualenv_dir = None - activate_this = '' + activate_this = "" def _remove_project_dir(self): - super(IsolatedTestClass, self)._remove_project_dir() + super()._remove_project_dir() if ( - self.virtualenv_dir and not os.environ.get('INSTALLER_TEST_VIRTUALENV', False) and - not os.environ.get('INSTALLER_TEST_KEEP_VIRTUALENV') + self.virtualenv_dir + and not os.environ.get("INSTALLER_TEST_VIRTUALENV", False) + and not os.environ.get("INSTALLER_TEST_KEEP_VIRTUALENV") ): if self.verbose: - print('remove virtualenv', self.virtualenv_dir) + print("remove virtualenv", self.virtualenv_dir) shutil.rmtree(self.virtualenv_dir) self.virtualenv_dir = None def _create_project_dir(self): - super(IsolatedTestClass, self)._create_project_dir() - if os.environ.get('INSTALLER_TEST_VIRTUALENV', False): - self.virtualenv_dir = os.environ.get('INSTALLER_TEST_VIRTUALENV') + super()._create_project_dir() + if os.environ.get("INSTALLER_TEST_VIRTUALENV", False): + self.virtualenv_dir = os.environ.get("INSTALLER_TEST_VIRTUALENV") else: self.virtualenv_dir = tempfile.mkdtemp() if self.verbose: - print('creating virtualenv', self.virtualenv_dir) + print("creating virtualenv", self.virtualenv_dir) def tearDown(self): if self.verbose: - print('deactivating virtualenv', self.virtualenv_dir) + print("deactivating virtualenv", self.virtualenv_dir) if os.path.exists(SYSTEM_ACTIVATE): with open(SYSTEM_ACTIVATE) as f: - code = compile(f.read(), SYSTEM_ACTIVATE, 'exec') + code = compile(f.read(), SYSTEM_ACTIVATE, "exec") + # fmt: off exec(code, dict(__file__=SYSTEM_ACTIVATE)) - sys.executable = os.path.join(os.path.dirname(SYSTEM_ACTIVATE), 'python') - super(IsolatedTestClass, self).tearDown() + # fmt: on + sys.executable = os.path.join(os.path.dirname(SYSTEM_ACTIVATE), "python") + super().tearDown() modules = copy(sys.modules) for module in modules: - if 'django' in module: + if "django" in module: del sys.modules[module] def setUp(self): - super(IsolatedTestClass, self).setUp() + super().setUp() if os.path.exists(SYSTEM_ACTIVATE): - subprocess.check_call([ - 'virtualenv', '--always-copy', '-q', '--python=%s' % sys.executable, - self.virtualenv_dir - ]) - activate_temp = os.path.join(self.virtualenv_dir, 'bin', 'activate_this.py') + subprocess.check_call( + ["virtualenv", "--always-copy", "-q", "--python=%s" % sys.executable, self.virtualenv_dir] + ) + activate_temp = os.path.join(self.virtualenv_dir, "bin", "activate_this.py") with open(activate_temp) as f: - code = compile(f.read(), activate_temp, 'exec') + code = compile(f.read(), activate_temp, "exec") + # fmt: off exec(code, dict(__file__=activate_temp)) + # fmt: on if self.verbose: - print('activating virtualenv', self.virtualenv_dir) - sys.executable = os.path.join(self.virtualenv_dir, 'bin', 'python') - os.environ['VIRTUAL_ENV'] = self.virtualenv_dir + print("activating virtualenv", self.virtualenv_dir) + sys.executable = os.path.join(self.virtualenv_dir, "bin", "python") + os.environ["VIRTUAL_ENV"] = self.virtualenv_dir def get_stable_django(latest=False, lts=False): @@ -121,11 +123,11 @@ def get_stable_django(latest=False, lts=False): :param lts: Latest lts version """ if latest and not sys.version_info < (3, 6) and not lts: - dj_ver = '3.0' - match = 'Django<3.1' + dj_ver = "3.0" + match = "Django<3.1" else: - dj_ver = '2.2' - match = 'Django<2.3' + dj_ver = "2.2" + match = "Django<2.3" return dj_ver, match @@ -135,6 +137,6 @@ def get_stable_djangocms(): Takes into account arguments and python version. """ - dj_ver = '3.7' - match = 'django-cms<3.8' + dj_ver = "3.7" + match = "django-cms<3.8" return dj_ver, match diff --git a/tests/config.py b/tests/config.py index ce4a8633..3a27e85e 100644 --- a/tests/config.py +++ b/tests/config.py @@ -1,20 +1,15 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - import copy import os import sys +import tempfile from argparse import Namespace +from unittest.mock import patch -import six -from mock import patch -from six import StringIO, text_type +from six import StringIO from tzlocal import get_localzone from djangocms_installer import config -from djangocms_installer.config.data import ( - CMS_VERSION_MATRIX, DJANGO_VERSION_MATRIX, DJANGOCMS_BETA, DJANGOCMS_DEVELOP, DJANGOCMS_RC, -) +from djangocms_installer.config import data from djangocms_installer.install import check_install from djangocms_installer.utils import less_than_version, supported_versions @@ -22,22 +17,22 @@ class TestConfig(BaseTestClass): - def test_default_config(self): dj_version, dj_match = get_stable_django(latest=True) - conf_data = config.parse(['--db=postgres://user:pwd@host/dbname', - '-q', '-p'+self.project_dir, 'example_prj']) + conf_data = config.parse( + ["--db=postgres://user:pwd@host/dbname", "-q", "-p" + self.project_dir, "example_prj"] + ) - self.assertEqual(conf_data.project_name, 'example_prj') + self.assertEqual(conf_data.project_name, "example_prj") - self.assertEqual(conf_data.cms_version, '3.7') + self.assertEqual(conf_data.cms_version, "3.7") self.assertEqual(conf_data.django_version, dj_version) - self.assertEqual(conf_data.i18n, 'yes') - self.assertEqual(conf_data.reversion, 'yes') - self.assertEqual(conf_data.permissions, 'no') - self.assertEqual(conf_data.use_timezone, 'yes') - self.assertEqual(conf_data.db, 'postgres://user:pwd@host/dbname') + self.assertEqual(conf_data.i18n, "yes") + self.assertEqual(conf_data.reversion, "yes") + self.assertEqual(conf_data.permissions, "no") + self.assertEqual(conf_data.use_timezone, "yes") + self.assertEqual(conf_data.db, "postgres://user:pwd@host/dbname") self.assertEqual(conf_data.no_db_driver, False) self.assertEqual(conf_data.no_deps, False) @@ -47,554 +42,635 @@ def test_default_config(self): def test_cli_config(self): with self.assertRaises(SystemExit): - dj_version = '1.8' - config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '--cms-version=stable', - '--django-version={0}'.format(dj_version), - '--i18n=no', - '--reversion=no', - '--permissions=no', - '--use-tz=no', - '-tEurope/Rome', - '-len-CA', '-lde', '-lit', - '-p'+self.project_dir, - 'example_prj']) + dj_version = "1.8" + config.parse( + [ + "-q", + "--db=postgres://user:pwd@host/dbname", + "--cms-version=stable", + "--django-version={}".format(dj_version), + "--i18n=no", + "--reversion=no", + "--permissions=no", + "--use-tz=no", + "-tEurope/Rome", + "-len-CA", + "-lde", + "-lit", + "-p" + self.project_dir, + "example_prj", + ] + ) dj_version, dj_match = get_stable_django() - cms_version = 'develop' - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '--django-version={0}'.format(dj_version), - '--cms-version={0}'.format(cms_version), - '--i18n=no', - '--reversion=no', - '--permissions=no', - '--use-tz=no', - '-tEurope/Rome', - '-len', '-lde', '-lit', - '-p'+self.project_dir, - 'example_prj']) - - self.assertEqual(conf_data.project_name, 'example_prj') - - self.assertEqual(str(conf_data.cms_version), DJANGOCMS_DEVELOP) + cms_version = "develop" + conf_data = config.parse( + [ + "-q", + "--db=postgres://user:pwd@host/dbname", + "--django-version={}".format(dj_version), + "--cms-version={}".format(cms_version), + "--i18n=no", + "--reversion=no", + "--permissions=no", + "--use-tz=no", + "-tEurope/Rome", + "-len", + "-lde", + "-lit", + "-p" + self.project_dir, + "example_prj", + ] + ) + + self.assertEqual(conf_data.project_name, "example_prj") + + self.assertEqual(str(conf_data.cms_version), data.DJANGOCMS_DEVELOP) self.assertEqual(str(conf_data.django_version), dj_version) - self.assertEqual(conf_data.i18n, 'yes') - self.assertEqual(conf_data.reversion, 'no') - self.assertEqual(conf_data.permissions, 'no') - self.assertEqual(conf_data.use_timezone, 'no') - self.assertEqual(conf_data.timezone, 'Europe/Rome') - self.assertEqual(conf_data.languages, ['en', 'de', 'it']) + self.assertEqual(conf_data.i18n, "yes") + self.assertEqual(conf_data.reversion, "no") + self.assertEqual(conf_data.permissions, "no") + self.assertEqual(conf_data.use_timezone, "no") + self.assertEqual(conf_data.timezone, "Europe/Rome") + self.assertEqual(conf_data.languages, ["en", "de", "it"]) self.assertEqual(conf_data.project_directory, self.project_dir) - self.assertEqual(conf_data.db, 'postgres://user:pwd@host/dbname') - self.assertEqual(conf_data.db_driver, 'psycopg2') + self.assertEqual(conf_data.db, "postgres://user:pwd@host/dbname") + self.assertEqual(conf_data.db_driver, "psycopg2") + + conf_data = config.parse( + [ + "-q", + "--db=postgres://user:pwd@host/dbname", + "--django-version={}".format(dj_version), + "--cms-version={}".format(cms_version), + "--i18n=no", + "--reversion=no", + "--permissions=no", + "--use-tz=no", + "-tEurope/Rome", + "-len,de,it", + "-p" + self.project_dir, + "example_prj", + ] + ) + + self.assertEqual(conf_data.project_name, "example_prj") + + self.assertEqual(str(conf_data.cms_version), data.DJANGOCMS_DEVELOP) + self.assertEqual(str(conf_data.django_version), dj_version) + self.assertEqual(conf_data.i18n, "yes") + self.assertEqual(conf_data.reversion, "no") + self.assertEqual(conf_data.permissions, "no") + self.assertEqual(conf_data.use_timezone, "no") + self.assertEqual(conf_data.timezone, "Europe/Rome") + self.assertEqual(conf_data.languages, ["en", "de", "it"]) + self.assertEqual(conf_data.project_directory, self.project_dir) + self.assertEqual(conf_data.db, "postgres://user:pwd@host/dbname") + self.assertEqual(conf_data.db_driver, "psycopg2") def test_version_misdj_match(self): with self.assertRaises(SystemExit): - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '--cms-version=stable', - '--django-version=1.4', - '--i18n=no', - '--reversion=no', - '--permissions=no', - '--use-tz=no', - '-tEurope/Rome', - '-len', '-lde', '-lit', - '-p'+self.project_dir, - 'example_prj']) + config.parse( + [ + "-q", + "--db=postgres://user:pwd@host/dbname", + "--cms-version=stable", + "--django-version=1.4", + "--i18n=no", + "--reversion=no", + "--permissions=no", + "--use-tz=no", + "-tEurope/Rome", + "-len", + "-lde", + "-lit", + "-p" + self.project_dir, + "example_prj", + ] + ) def test_cli_config_commaseparated_languages(self): - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '-len,de,it', - '-p'+self.project_dir, - 'example_prj' - ]) - - self.assertEqual(conf_data.languages, ['en', 'de', 'it']) + conf_data = config.parse( + ["-q", "--db=postgres://user:pwd@host/dbname", "-len,de,it", "-p" + self.project_dir, "example_prj"] + ) + + self.assertEqual(conf_data.languages, ["en", "de", "it"]) + + def test_cli_config_missing_param(self): + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): + with self.assertRaises(SystemExit) as e: + conf_data = config.parse(["-q"]) + self.assertEqual(conf_data.languages, ["en"]) + self.assertEqual(e.exception.code, 2) + + def test_cli_config_input(self): + templates = tempfile.mkdtemp() + prj_dir = "param_w_input" + user_input = [ + "sqlite://localhost/project.db", # db + "stable", # cms_version + "stable", # django_version + "yes", # i18n + "", # reversion + "en", # languages + "", # timezone + "yes", # use_timezone + "yes", # permissions + "yes", # bootstrap + "not_exist", # templates + templates, # templates + "yes", # starting_page + ] + with patch("builtins.input", side_effect=user_input): + conf_data = config.parse(["-w", "-t=Europe/Rome", "-len", "-lde", "-eno", prj_dir]) + self.assertEqual(conf_data.languages, ["en"]) + self.assertEqual(conf_data.use_timezone, "yes") + self.assertEqual(conf_data.timezone, "Europe/Rome") + self.assertEqual(conf_data.permissions, "yes") + self.assertEqual(conf_data.i18n, "yes") + self.assertEqual(conf_data.django_version, data.DJANGO_STABLE) + self.assertEqual(conf_data.cms_version, data.DJANGOCMS_STABLE) + self.assertEqual(conf_data.db, "sqlite://localhost/project.db") + self.assertEqual(conf_data.bootstrap, True) + self.assertEqual(conf_data.reversion, "no") + self.assertEqual(conf_data.starting_page, True) + self.assertEqual(conf_data.templates, templates) + self.assertEqual(conf_data.templates, templates) def test_cli_config_comma_languages_with_space(self): - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '-len , de , it', - '-p'+self.project_dir, - 'example_prj' - ]) + conf_data = config.parse( + ["-q", "--db=postgres://user:pwd@host/dbname", "-len , de , it", "-p" + self.project_dir, "example_prj"] + ) - self.assertEqual(conf_data.languages, ['en', 'de', 'it']) + self.assertEqual(conf_data.languages, ["en", "de", "it"]) def test_invalid_choices(self): - with patch('sys.stdout', self.stdout): - with patch('sys.stderr', self.stderr): + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): with self.assertRaises(SystemExit) as error: - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '--cms-version=2.6', - '--django-version=1.1', - '--i18n=no', - '-p'+self.project_dir, - 'example_prj']) + config.parse( + [ + "-q", + "--db=postgres://user:pwd@host/dbname", + "--cms-version=2.6", + "--django-version=1.1", + "--i18n=no", + "-p" + self.project_dir, + "example_prj", + ] + ) self.assertEqual(error.exception.code, 2) - if six.PY3: - self.assertTrue(self.stderr.getvalue().find('--cms-version/-v: invalid choice: \'2.6\'') > -1) - else: - self.assertTrue(self.stderr.getvalue().find('--cms-version/-v: invalid choice: u\'2.6\'') > -1) + self.assertTrue(self.stderr.getvalue().find("--cms-version/-v: invalid choice: '2.6'") > -1) def test_invalid_project_name(self): - with patch('sys.stdout', self.stdout): + with patch("sys.stdout", self.stdout): stderr_tmp = StringIO() - with patch('sys.stderr', stderr_tmp): + with patch("sys.stderr", stderr_tmp): with self.assertRaises(SystemExit) as error: - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '-p'+self.project_dir, - 'test']) + config.parse(["-q", "--db=postgres://user:pwd@host/dbname", "-p" + self.project_dir, "test"]) self.assertEqual(error.exception.code, 3) self.assertTrue(stderr_tmp.getvalue().find('Project name "test" is not valid') > -1) stderr_tmp = StringIO() - with patch('sys.stderr', stderr_tmp): + with patch("sys.stderr", stderr_tmp): with self.assertRaises(SystemExit) as error: - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '-p'+self.project_dir, - 'assert']) + config.parse(["-q", "--db=postgres://user:pwd@host/dbname", "-p" + self.project_dir, "assert"]) self.assertEqual(error.exception.code, 3) self.assertTrue(stderr_tmp.getvalue().find('Project name "assert" is not valid') > -1) stderr_tmp = StringIO() - with patch('sys.stderr', stderr_tmp): + with patch("sys.stderr", stderr_tmp): with self.assertRaises(SystemExit) as error: - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '-p'+self.project_dir, - 'values']) + config.parse(["-q", "--db=postgres://user:pwd@host/dbname", "-p" + self.project_dir, "values"]) self.assertEqual(error.exception.code, 3) self.assertTrue(stderr_tmp.getvalue().find('Project name "values" is not valid') > -1) stderr_tmp = StringIO() - with patch('sys.stderr', stderr_tmp): + with patch("sys.stderr", stderr_tmp): with self.assertRaises(SystemExit) as error: - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '-p'+self.project_dir, - 'project-name']) + config.parse( + ["-q", "--db=postgres://user:pwd@host/dbname", "-p" + self.project_dir, "project-name"] + ) self.assertEqual(error.exception.code, 3) self.assertTrue(stderr_tmp.getvalue().find('Project name "project-name" is not valid') > -1) stderr_tmp = StringIO() - with patch('sys.stderr', stderr_tmp): + with patch("sys.stderr", stderr_tmp): with self.assertRaises(SystemExit) as error: - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '-p'+self.project_dir, - 'project.name']) + config.parse( + ["-q", "--db=postgres://user:pwd@host/dbname", "-p" + self.project_dir, "project.name"] + ) self.assertEqual(error.exception.code, 3) self.assertTrue(stderr_tmp.getvalue().find('Project name "project.name" is not valid') > -1) stderr_tmp = StringIO() - with patch('sys.stderr', stderr_tmp): + with patch("sys.stderr", stderr_tmp): with self.assertRaises(SystemExit) as error: - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '-p'+self.project_dir, - 'project?name']) + config.parse( + ["-q", "--db=postgres://user:pwd@host/dbname", "-p" + self.project_dir, "project?name"] + ) self.assertEqual(error.exception.code, 3) self.assertTrue(stderr_tmp.getvalue().find('Project name "project?name" is not valid') > -1) def test_invalid_project_path(self): - prj_dir = 'example_prj' + prj_dir = "example_prj" existing_path = os.path.join(self.project_dir, prj_dir) os.makedirs(existing_path) - with patch('sys.stdout', self.stdout): - with patch('sys.stderr', self.stderr): + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): with self.assertRaises(SystemExit) as error: - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '-p'+self.project_dir, - prj_dir]) + conf_data = config.parse( + ["-q", "--db=postgres://user:pwd@host/dbname", "-p" + self.project_dir, prj_dir, "-s"] + ) self.assertEqual(conf_data.project_path, existing_path) self.assertEqual(error.exception.code, 4) - self.assertTrue(self.stderr.getvalue().find('Path "%s" already exists and is not empty' % self.project_dir) > -1) + out = self.stderr.getvalue() + expected = 'Path "{}/{}" already exists, please choose a different one'.format(self.project_dir, prj_dir) + self.assertTrue(out.find(expected) > -1) def test_invalid_project_dir(self): - prj_dir = 'example_prj' - existing_path = os.path.join(self.project_dir, 'a_file') - with open(existing_path, 'w') as f: - f.write('') - with patch('sys.stdout', self.stdout): - with patch('sys.stderr', self.stderr): + prj_dir = "example_prj" + existing_path = os.path.join(self.project_dir, "a_file") + with open(existing_path, "w") as f: + f.write("") + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): with self.assertRaises(SystemExit) as error: - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '-p'+self.project_dir, - prj_dir]) + conf_data = config.parse( + ["-q", "--db=postgres://user:pwd@host/dbname", "-p" + self.project_dir, prj_dir] + ) self.assertEqual(conf_data.project_path, existing_path) self.assertEqual(error.exception.code, 4) - self.assertTrue(self.stderr.getvalue().find('Path "%s" already exists and is not empty' % self.project_dir) > -1) + self.assertTrue( + self.stderr.getvalue().find('Path "%s" already exists and is not empty' % self.project_dir) > -1 + ) def test_invalid_project_dir_skip(self): - prj_dir = 'example_prj' - existing_path = os.path.join(self.project_dir, 'a_file') - with open(existing_path, 'w') as f: - f.write('') - with patch('sys.stdout', self.stdout): - with patch('sys.stderr', self.stderr): - conf_data = config.parse([ - '-q', '-s', - '--db=postgres://user:pwd@host/dbname', - '-p'+self.project_dir, - prj_dir]) - self.assertFalse(self.stderr.getvalue().find('Path "%s" already exists and is not empty' % self.project_dir) > -1) + prj_dir = "example_prj" + existing_path = os.path.join(self.project_dir, "a_file") + with open(existing_path, "w") as f: + f.write("") + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): + config.parse(["-q", "-s", "--db=postgres://user:pwd@host/dbname", "-p" + self.project_dir, prj_dir]) + self.assertFalse( + self.stderr.getvalue().find('Path "%s" already exists and is not empty' % self.project_dir) > -1 + ) def test_valid_project_dir(self): - prj_dir = 'example_prj' - existing_path = os.path.join(self.project_dir, '.hidden_file') - with open(existing_path, 'w') as f: - f.write('') - with patch('sys.stdout', self.stdout): - with patch('sys.stderr', self.stderr): - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '-p'+self.project_dir, - prj_dir]) - self.assertFalse(self.stderr.getvalue().find('Path "%s" already exists and is not empty' % self.project_dir) > -1) + prj_dir = "example_prj" + existing_path = os.path.join(self.project_dir, ".hidden_file") + with open(existing_path, "w") as f: + f.write("") + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): + config.parse(["-q", "--db=postgres://user:pwd@host/dbname", "-p" + self.project_dir, prj_dir]) + self.assertFalse( + self.stderr.getvalue().find('Path "%s" already exists and is not empty' % self.project_dir) > -1 + ) def test_invalid_django_settings_module(self): - prj_dir = 'example_prj' - existing_path = os.path.join(self.project_dir, '.hidden_file') - with open(existing_path, 'w') as f: - f.write('') - os.environ['DJANGO_SETTINGS_MODULE'] = 'some_module.settings' - with patch('sys.stdout', self.stdout): - with patch('sys.stderr', self.stderr): + prj_dir = "example_prj" + existing_path = os.path.join(self.project_dir, ".hidden_file") + with open(existing_path, "w") as f: + f.write("") + os.environ["DJANGO_SETTINGS_MODULE"] = "some_module.settings" + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): with self.assertRaises(SystemExit) as error: - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '-p'+self.project_dir, - prj_dir]) + config.parse(["-q", "--db=postgres://user:pwd@host/dbname", "-p" + self.project_dir, prj_dir]) self.assertEqual(error.exception.code, 10) - self.assertTrue(self.stderr.getvalue().find('DJANGO_SETTINGS_MODULE') > -1) - self.assertTrue(self.stderr.getvalue().find('some_module.settings') > -1) + self.assertTrue(self.stderr.getvalue().find("DJANGO_SETTINGS_MODULE") > -1) + self.assertTrue(self.stderr.getvalue().find("some_module.settings") > -1) def test_valid_django_settings_module(self): - prj_dir = 'example_prj' - existing_path = os.path.join(self.project_dir, '.hidden_file') - with open(existing_path, 'w') as f: - f.write('') - os.environ['DJANGO_SETTINGS_MODULE'] = 'example_prj.settings' - with patch('sys.stdout', self.stdout): - with patch('sys.stderr', self.stderr): - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '-p'+self.project_dir, - prj_dir]) - self.assertFalse(self.stderr.getvalue().find('DJANGO_SETTINGS_MODULE') > -1) - self.assertFalse(self.stderr.getvalue().find('some_module.settings') > -1) + prj_dir = "example_prj" + existing_path = os.path.join(self.project_dir, ".hidden_file") + with open(existing_path, "w") as f: + f.write("") + os.environ["DJANGO_SETTINGS_MODULE"] = "example_prj.settings" + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): + config.parse(["-q", "--db=postgres://user:pwd@host/dbname", "-p" + self.project_dir, prj_dir]) + self.assertFalse(self.stderr.getvalue().find("DJANGO_SETTINGS_MODULE") > -1) + self.assertFalse(self.stderr.getvalue().find("some_module.settings") > -1) def test_latest_version(self): - self.assertEqual(less_than_version('2.4'), '2.5') - self.assertEqual(less_than_version('3'), '3.1') - self.assertEqual(less_than_version('3.0.1'), '3.1.1') + self.assertEqual(less_than_version("2.4"), "2.5") + self.assertEqual(less_than_version("3"), "3.1") + self.assertEqual(less_than_version("3.0.1"), "3.1.1") - @unittest.skipIf(sys.version_info[0] < 3, - reason='django 2+ only supports python 3') + @unittest.skipIf(sys.version_info[0] < 3, reason="django 2+ only supports python 3") def test_supported_versions(self): dj_version, dj_match = get_stable_django(latest=True) - self.assertEqual(supported_versions('stable', 'stable'), (dj_version, '3.7')) - self.assertEqual(supported_versions('stable', '3.1.10'), (dj_version, None)) - self.assertEqual(supported_versions('stable', 'rc'), (dj_version, DJANGOCMS_RC)) - self.assertEqual(supported_versions('stable', 'beta'), (dj_version, DJANGOCMS_BETA)) - self.assertEqual(supported_versions('stable', 'develop'), (dj_version, DJANGOCMS_DEVELOP)) - self.assertEqual(supported_versions('lts', 'rc'), ('2.2', DJANGOCMS_RC)) - self.assertEqual(supported_versions('lts', 'lts'), ('2.2', '3.7')) + self.assertEqual(supported_versions("stable", "stable"), (dj_version, "3.7")) + self.assertEqual(supported_versions("stable", "3.1.10"), (dj_version, None)) + self.assertEqual(supported_versions("stable", "rc"), (dj_version, data.DJANGOCMS_RC)) + self.assertEqual(supported_versions("stable", "beta"), (dj_version, data.DJANGOCMS_BETA)) + self.assertEqual(supported_versions("stable", "develop"), (dj_version, data.DJANGOCMS_DEVELOP)) + self.assertEqual(supported_versions("lts", "rc"), ("2.2", data.DJANGOCMS_RC)) + self.assertEqual(supported_versions("lts", "lts"), ("2.2", "3.7")) with self.assertRaises(RuntimeError): - supported_versions('stable', '2.4'), ('1.5', '2.4') + supported_versions("stable", "2.4"), ("1.5", "2.4") with self.assertRaises(RuntimeError): - supported_versions('1.5', 'stable'), ('1.8', '3.1') + supported_versions("1.5", "stable"), ("1.8", "3.1") with self.assertRaises(RuntimeError): - self.assertEqual(supported_versions('1.9', 'stable'), ('1.9', '3.5')) - self.assertEqual(supported_versions('1.8', 'stable'), ('1.8', '3.5')) - self.assertEqual(supported_versions('1.9', '3.5'), ('1.9', '3.5')) - self.assertEqual(supported_versions('1.8', 'lts'), ('1.8', '3.7')) - self.assertEqual(supported_versions('1.8.3', 'stable'), (None, '3.6')) + self.assertEqual(supported_versions("1.9", "stable"), ("1.9", "3.5")) + self.assertEqual(supported_versions("1.8", "stable"), ("1.8", "3.5")) + self.assertEqual(supported_versions("1.9", "3.5"), ("1.9", "3.5")) + self.assertEqual(supported_versions("1.8", "lts"), ("1.8", "3.7")) + self.assertEqual(supported_versions("1.8.3", "stable"), (None, "3.6")) def test_requirements(self): """ Test for different configuration and package versions """ dj_version, dj_match = get_stable_django(lts=True) - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '--cms-version=3.7', - '--django-version={0}'.format(dj_version), - '--i18n=no', - '-f', - '-p'+self.project_dir, - 'example_prj']) - print(conf_data.requirements) + conf_data = config.parse( + [ + "-q", + "--db=postgres://user:pwd@host/dbname", + "--cms-version=3.7", + "--django-version={}".format(dj_version), + "--i18n=no", + "-f", + "-p" + self.project_dir, + "example_prj", + ] + ) self.assertTrue(conf_data.requirements.find(config.data.DJANGOCMS_37) > -1) self.assertTrue(conf_data.requirements.find(dj_match) > -1) - self.assertFalse(conf_data.requirements.find('django-reversion') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-text-ckeditor>=3.7,<4.0') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-admin-style>=1.5') > -1) - self.assertTrue(conf_data.requirements.find('django-filer') > -1) - self.assertTrue(conf_data.requirements.find('cmsplugin-filer') == -1) - self.assertTrue(conf_data.requirements.find('djangocms-file') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-text-ckeditor') > -1) - self.assertTrue(conf_data.requirements.find('psycopg2') > -1) + self.assertFalse(conf_data.requirements.find("django-reversion") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-text-ckeditor>=3.7,<4.0") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-admin-style>=1.5") > -1) + self.assertTrue(conf_data.requirements.find("django-filer") > -1) + self.assertTrue(conf_data.requirements.find("cmsplugin-filer") == -1) + self.assertTrue(conf_data.requirements.find("djangocms-file") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-text-ckeditor") > -1) + self.assertTrue(conf_data.requirements.find("psycopg2") > -1) dj_version, dj_match = get_stable_django(latest=True) - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '--i18n=no', - '--cms-version=stable', - '--django-version={}'.format(dj_version), - '--reversion=yes', - '-p'+self.project_dir, - 'example_prj']) + conf_data = config.parse( + [ + "-q", + "--db=postgres://user:pwd@host/dbname", + "--i18n=no", + "--cms-version=stable", + "--django-version={}".format(dj_version), + "--reversion=yes", + "-p" + self.project_dir, + "example_prj", + ] + ) self.assertTrue(conf_data.requirements.find(config.data.DJANGOCMS_37) > -1) self.assertTrue(conf_data.requirements.find(dj_match) > -1) - self.assertFalse(conf_data.requirements.find('django-reversion') > -1) - self.assertTrue(conf_data.requirements.find('cmsplugin-filer') == -1) - self.assertTrue(conf_data.requirements.find('djangocms-admin-style') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-text-ckeditor>=3.7,<4.0') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-bootstrap4') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-file') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-flash') == -1) - self.assertTrue(conf_data.requirements.find('djangocms-googlemap') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-inherit') == -1) - self.assertTrue(conf_data.requirements.find('djangocms-link') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-picture') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-style') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-teaser') == -1) - self.assertTrue(conf_data.requirements.find('djangocms-video') > -1) - self.assertTrue(conf_data.requirements.find('psycopg2') > -1) + self.assertFalse(conf_data.requirements.find("django-reversion") > -1) + self.assertTrue(conf_data.requirements.find("cmsplugin-filer") == -1) + self.assertTrue(conf_data.requirements.find("djangocms-admin-style") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-text-ckeditor>=3.7,<4.0") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-bootstrap4") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-file") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-flash") == -1) + self.assertTrue(conf_data.requirements.find("djangocms-googlemap") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-inherit") == -1) + self.assertTrue(conf_data.requirements.find("djangocms-link") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-picture") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-style") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-teaser") == -1) + self.assertTrue(conf_data.requirements.find("djangocms-video") > -1) + self.assertTrue(conf_data.requirements.find("psycopg2") > -1) dj_version, dj_match = get_stable_django(lts=True) - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '--i18n=no', - '--cms-version=develop', - '--django-version={}'.format(dj_version), - '-f', - '--reversion=yes', - '-p'+self.project_dir, - 'example_prj']) + conf_data = config.parse( + [ + "-q", + "--db=postgres://user:pwd@host/dbname", + "--i18n=no", + "--cms-version=develop", + "--django-version={}".format(dj_version), + "-f", + "--reversion=yes", + "-p" + self.project_dir, + "example_prj", + ] + ) self.assertTrue(conf_data.requirements.find(config.data.DJANGOCMS_DEVELOP) > -1) self.assertTrue(conf_data.requirements.find(dj_match) > -1) - self.assertFalse(conf_data.requirements.find('django-reversion') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-text-ckeditor') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-admin-style') > -1) - self.assertTrue(conf_data.requirements.find('django-filer') > -1) - self.assertTrue(conf_data.requirements.find('cmsplugin-filer') == -1) - self.assertTrue(conf_data.requirements.find('djangocms-bootstrap4') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-file') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-flash') == -1) - self.assertTrue(conf_data.requirements.find('djangocms-googlemap') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-inherit') == -1) - self.assertTrue(conf_data.requirements.find('djangocms-link') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-picture') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-style') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-teaser') == -1) - self.assertTrue(conf_data.requirements.find('djangocms-video') > -1) - self.assertTrue(conf_data.requirements.find('psycopg2') > -1) + self.assertFalse(conf_data.requirements.find("django-reversion") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-text-ckeditor") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-admin-style") > -1) + self.assertTrue(conf_data.requirements.find("django-filer") > -1) + self.assertTrue(conf_data.requirements.find("cmsplugin-filer") == -1) + self.assertTrue(conf_data.requirements.find("djangocms-bootstrap4") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-file") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-flash") == -1) + self.assertTrue(conf_data.requirements.find("djangocms-googlemap") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-inherit") == -1) + self.assertTrue(conf_data.requirements.find("djangocms-link") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-picture") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-style") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-teaser") == -1) + self.assertTrue(conf_data.requirements.find("djangocms-video") > -1) + self.assertTrue(conf_data.requirements.find("psycopg2") > -1) with self.assertRaises(SystemExit): - dj_version = '1.8' - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '--i18n=no', - '--cms-version=develop', - '--django-version={0}'.format(dj_version), - '-f', - '--reversion=yes', - '-p'+self.project_dir, - 'example_prj']) + dj_version = "1.8" + conf_data = config.parse( + [ + "-q", + "--db=postgres://user:pwd@host/dbname", + "--i18n=no", + "--cms-version=develop", + "--django-version={}".format(dj_version), + "-f", + "--reversion=yes", + "-p" + self.project_dir, + "example_prj", + ] + ) dj_version, dj_match = get_stable_django(latest=True) - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '--i18n=no', - '--cms-version=develop', - '--django-version={0}'.format(dj_version), - '-f', - '--reversion=yes', - '-p'+self.project_dir, - 'example_prj']) + conf_data = config.parse( + [ + "-q", + "--db=postgres://user:pwd@host/dbname", + "--i18n=no", + "--cms-version=develop", + "--django-version={}".format(dj_version), + "-f", + "--reversion=yes", + "-p" + self.project_dir, + "example_prj", + ] + ) self.assertTrue(conf_data.requirements.find(config.data.DJANGOCMS_DEVELOP) > -1) self.assertTrue(conf_data.requirements.find(dj_match) > -1) - self.assertFalse(conf_data.requirements.find('django-reversion') > -1) - self.assertTrue(conf_data.requirements.find('django-treebeard') > -1) + self.assertFalse(conf_data.requirements.find("django-reversion") > -1) + self.assertTrue(conf_data.requirements.find("django-treebeard") > -1) dj_version, dj_match = get_stable_django() - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '--i18n=no', - '--cms-version=develop', - '--django-version={}'.format(dj_version), - '-f', - '--reversion=yes', - '-z=yes', - '-p'+self.project_dir, - 'example_prj']) + conf_data = config.parse( + [ + "-q", + "--db=postgres://user:pwd@host/dbname", + "--i18n=no", + "--cms-version=develop", + "--django-version={}".format(dj_version), + "-f", + "--reversion=yes", + "-z=yes", + "-p" + self.project_dir, + "example_prj", + ] + ) self.assertTrue(conf_data.requirements.find(config.data.DJANGOCMS_DEVELOP) > -1) self.assertTrue(conf_data.requirements.find(dj_match) > -1) - self.assertFalse(conf_data.requirements.find('django-reversion') > -1) - self.assertTrue(conf_data.requirements.find('https://github.com/divio/djangocms-link') > -1) - self.assertTrue(conf_data.requirements.find('https://github.com/divio/djangocms-style') > -1) - self.assertTrue(conf_data.requirements.find('https://github.com/divio/djangocms-googlemap') > -1) - self.assertTrue(conf_data.requirements.find('https://github.com/divio/djangocms-snippet') > -1) - self.assertTrue(conf_data.requirements.find('https://github.com/divio/djangocms-video') > -1) - self.assertTrue(conf_data.requirements.find('https://github.com/divio/djangocms-bootstrap4') > -1) - self.assertTrue(conf_data.requirements.find('https://github.com/divio/djangocms-admin-style') > -1) - self.assertTrue(conf_data.requirements.find('https://github.com/divio/djangocms-text-ckeditor') > -1) - self.assertTrue(conf_data.requirements.find('pytz') > -1) - - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '--i18n=no', - '--cms-version=3.7', - '--django-version={}'.format(dj_version), - '-f', - '--reversion=yes', - '-z=yes', - '-p'+self.project_dir, - 'example_prj']) + self.assertFalse(conf_data.requirements.find("django-reversion") > -1) + self.assertTrue(conf_data.requirements.find("https://github.com/divio/djangocms-link") > -1) + self.assertTrue(conf_data.requirements.find("https://github.com/divio/djangocms-style") > -1) + self.assertTrue(conf_data.requirements.find("https://github.com/divio/djangocms-googlemap") > -1) + self.assertTrue(conf_data.requirements.find("https://github.com/divio/djangocms-snippet") > -1) + self.assertTrue(conf_data.requirements.find("https://github.com/divio/djangocms-video") > -1) + self.assertTrue(conf_data.requirements.find("https://github.com/divio/djangocms-bootstrap4") > -1) + self.assertTrue(conf_data.requirements.find("https://github.com/divio/djangocms-admin-style") > -1) + self.assertTrue(conf_data.requirements.find("https://github.com/divio/djangocms-text-ckeditor") > -1) + self.assertTrue(conf_data.requirements.find("pytz") > -1) + + conf_data = config.parse( + [ + "-q", + "--db=postgres://user:pwd@host/dbname", + "--i18n=no", + "--cms-version=3.7", + "--django-version={}".format(dj_version), + "-f", + "--reversion=yes", + "-z=yes", + "-p" + self.project_dir, + "example_prj", + ] + ) self.assertTrue(conf_data.requirements.find(config.data.DJANGOCMS_37) > -1) self.assertTrue(conf_data.requirements.find(dj_match) > -1) - self.assertFalse(conf_data.requirements.find('django-reversion') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-text-ckeditor>=3.7') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-admin-style') > -1) - self.assertTrue(conf_data.requirements.find('pytz') > -1) + self.assertFalse(conf_data.requirements.find("django-reversion") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-text-ckeditor>=3.7") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-admin-style") > -1) + self.assertTrue(conf_data.requirements.find("pytz") > -1) dj_version, dj_match = get_stable_django(lts=True) - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '--i18n=no', - '--cms-version=3.7', - '--django-version={}'.format(dj_version), - '-f', - '--reversion=yes', - '-z=yes', - '-p'+self.project_dir, - 'example_prj']) + conf_data = config.parse( + [ + "-q", + "--db=postgres://user:pwd@host/dbname", + "--i18n=no", + "--cms-version=3.7", + "--django-version={}".format(dj_version), + "-f", + "--reversion=yes", + "-z=yes", + "-p" + self.project_dir, + "example_prj", + ] + ) self.assertTrue(conf_data.requirements.find(config.data.DJANGOCMS_37) > -1) self.assertTrue(conf_data.requirements.find(dj_match) > -1) - self.assertFalse(conf_data.requirements.find('django-reversion') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-text-ckeditor>=3.7') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-admin-style') > -1) - self.assertTrue(conf_data.requirements.find('pytz') > -1) + self.assertFalse(conf_data.requirements.find("django-reversion") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-text-ckeditor>=3.7") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-admin-style") > -1) + self.assertTrue(conf_data.requirements.find("pytz") > -1) dj_version, dj_match = get_stable_django(lts=True) - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '--i18n=no', - '--cms-version=develop', - '--django-version={0}'.format(dj_version), - '--reversion=yes', - '-z=yes', - '-p'+self.project_dir, - 'example_prj']) + conf_data = config.parse( + [ + "-q", + "--db=postgres://user:pwd@host/dbname", + "--i18n=no", + "--cms-version=develop", + "--django-version={}".format(dj_version), + "--reversion=yes", + "-z=yes", + "-p" + self.project_dir, + "example_prj", + ] + ) self.assertTrue(conf_data.requirements.find(config.data.DJANGOCMS_DEVELOP) > -1) self.assertTrue(conf_data.requirements.find(dj_match) > -1) - self.assertTrue(conf_data.requirements.find('djangocms-text-ckeditor') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-admin-style') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-teaser') == -1) - self.assertTrue(conf_data.requirements.find('south') == -1) + self.assertTrue(conf_data.requirements.find("djangocms-text-ckeditor") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-admin-style") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-teaser") == -1) + self.assertTrue(conf_data.requirements.find("south") == -1) dj_version, dj_match = get_stable_django() - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '--i18n=no', - '--cms-version=develop', - '--django-version={0}'.format(dj_version), - '--reversion=yes', - '--no-plugins', - '-z=yes', - '-p'+self.project_dir, - 'example_prj']) + conf_data = config.parse( + [ + "-q", + "--db=postgres://user:pwd@host/dbname", + "--i18n=no", + "--cms-version=develop", + "--django-version={}".format(dj_version), + "--reversion=yes", + "--no-plugins", + "-z=yes", + "-p" + self.project_dir, + "example_prj", + ] + ) self.assertTrue(conf_data.requirements.find(config.data.DJANGOCMS_DEVELOP) > -1) self.assertTrue(conf_data.requirements.find(dj_match) > -1) - self.assertFalse(conf_data.requirements.find('django-reversion') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-text-ckeditor') == -1) - self.assertTrue(conf_data.requirements.find('djangocms-admin-style/archive/master') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-teaser') == -1) - self.assertTrue(conf_data.requirements.find('south') == -1) + self.assertFalse(conf_data.requirements.find("django-reversion") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-text-ckeditor") == -1) + self.assertTrue(conf_data.requirements.find("djangocms-admin-style/archive/master") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-teaser") == -1) + self.assertTrue(conf_data.requirements.find("south") == -1) dj_version, dj_match = get_stable_django(lts=True) - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '--i18n=no', - '--cms-version=develop', - '--django-version={0}'.format(dj_version), - '--reversion=yes', - '--no-plugins', - '-z=yes', - '-p'+self.project_dir, - 'example_prj']) + conf_data = config.parse( + [ + "-q", + "--db=postgres://user:pwd@host/dbname", + "--i18n=no", + "--cms-version=develop", + "--django-version={}".format(dj_version), + "--reversion=yes", + "--no-plugins", + "-z=yes", + "-p" + self.project_dir, + "example_prj", + ] + ) self.assertTrue(conf_data.requirements.find(config.data.DJANGOCMS_DEVELOP) > -1) self.assertTrue(conf_data.requirements.find(dj_match) > -1) - self.assertFalse(conf_data.requirements.find('django-reversion') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-text-ckeditor') == -1) - self.assertTrue(conf_data.requirements.find('djangocms-admin-style/archive/master.zip') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-teaser/archive/master.zip') == -1) - self.assertTrue(conf_data.requirements.find('south') == -1) + self.assertFalse(conf_data.requirements.find("django-reversion") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-text-ckeditor") == -1) + self.assertTrue(conf_data.requirements.find("djangocms-admin-style/archive/master.zip") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-teaser/archive/master.zip") == -1) + self.assertTrue(conf_data.requirements.find("south") == -1) dj_version, dj_match = get_stable_django(lts=True) requirements_21 = [ - '-q', - '--db=postgres://user:pwd@host/dbname', - '--i18n=no', - '--cms-version=develop', - '--django-version={0}'.format(dj_version), - '--reversion=yes', - '--no-plugins', - '-z=yes', - '-p'+self.project_dir, - 'example_prj' + "-q", + "--db=postgres://user:pwd@host/dbname", + "--i18n=no", + "--cms-version=develop", + "--django-version={}".format(dj_version), + "--reversion=yes", + "--no-plugins", + "-z=yes", + "-p" + self.project_dir, + "example_prj", ] if sys.version_info < (3, 5,): with self.assertRaises(SystemExit): @@ -604,79 +680,68 @@ def test_requirements(self): self.assertTrue(conf_data.requirements.find(config.data.DJANGOCMS_DEVELOP) > -1) self.assertTrue(conf_data.requirements.find(dj_match) > -1) - self.assertFalse(conf_data.requirements.find('django-reversion') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-text-ckeditor') == -1) - self.assertTrue(conf_data.requirements.find('djangocms-admin-style/archive/master.zip') > -1) - self.assertTrue(conf_data.requirements.find('djangocms-teaser/archive/master.zip') == -1) - self.assertTrue(conf_data.requirements.find('south') == -1) - self.assertTrue(conf_data.requirements.find('psycopg2') > -1) + self.assertFalse(conf_data.requirements.find("django-reversion") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-text-ckeditor") == -1) + self.assertTrue(conf_data.requirements.find("djangocms-admin-style/archive/master.zip") > -1) + self.assertTrue(conf_data.requirements.find("djangocms-teaser/archive/master.zip") == -1) + self.assertTrue(conf_data.requirements.find("south") == -1) + self.assertTrue(conf_data.requirements.find("psycopg2") > -1) dj_version, dj_match = get_stable_django(lts=True) - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '--cms-version=lts', - '--django-version={}'.format(dj_version), - '-p'+self.project_dir, - 'example_prj']) + conf_data = config.parse( + [ + "-q", + "--db=postgres://user:pwd@host/dbname", + "--cms-version=lts", + "--django-version={}".format(dj_version), + "-p" + self.project_dir, + "example_prj", + ] + ) self.assertTrue(conf_data.requirements.find(config.data.DJANGOCMS_37) > -1) self.assertTrue(conf_data.requirements.find(dj_match) > -1) dj_version, dj_match = get_stable_django(latest=True) - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '--cms-version=stable', - '--django-version={}'.format(dj_version), - '-p'+self.project_dir, - 'example_prj']) - - self.assertTrue(conf_data.requirements.find(config.data.DJANGOCMS_37) - > -1) + conf_data = config.parse( + [ + "-q", + "--db=postgres://user:pwd@host/dbname", + "--cms-version=stable", + "--django-version={}".format(dj_version), + "-p" + self.project_dir, + "example_prj", + ] + ) + + self.assertTrue(conf_data.requirements.find(config.data.DJANGOCMS_37) > -1) self.assertTrue(conf_data.requirements.find(dj_match) > -1) def test_bootstrap(self): """ Verify handling of bootstrap parameter """ - conf_data = config.parse([ - '-q', - '-p'+self.project_dir, - 'example_prj']) + conf_data = config.parse(["-q", "-p" + self.project_dir, "example_prj"]) self.assertFalse(conf_data.bootstrap) - conf_data = config.parse([ - '--bootstrap=yes', '-q', - '-p'+self.project_dir, - 'example_prj']) + conf_data = config.parse(["--bootstrap=yes", "-q", "-p" + self.project_dir, "example_prj"]) self.assertTrue(conf_data.bootstrap) def test_starting_page(self): """ Verify handling of starting-page parameter """ - conf_data = config.parse([ - '-q', - '-p'+self.project_dir, - 'example_prj']) + conf_data = config.parse(["-q", "-p" + self.project_dir, "example_prj"]) self.assertFalse(conf_data.starting_page) - conf_data = config.parse([ - '--starting-page=yes', '-q', - '-p'+self.project_dir, - 'example_prj']) + conf_data = config.parse(["--starting-page=yes", "-q", "-p" + self.project_dir, "example_prj"]) self.assertTrue(conf_data.starting_page) def test_auto_i18n(self): """ Verify setting automatic i18n support if multiple languages """ - conf_data = config.parse([ - '-q', '-len,de' - '--i18n=no', - '-p' + self.project_dir, - 'example_prj']) + conf_data = config.parse(["-q", "-len,de" "--i18n=no", "-p" + self.project_dir, "example_prj"]) self.assertTrue(conf_data.i18n) def test_utc(self): @@ -685,96 +750,88 @@ def test_utc(self): """ default_tz = get_localzone() - conf_data = config.parse([ - '-q', - '-p'+self.project_dir, - 'example_prj']) - self.assertEqual(text_type(conf_data.timezone), default_tz.zone) + conf_data = config.parse(["-q", "-p" + self.project_dir, "example_prj"]) + self.assertEqual(str(conf_data.timezone), default_tz.zone) - conf_data = config.parse([ - '-q', '--utc', - '-p'+self.project_dir, - 'example_prj']) - self.assertEqual(conf_data.timezone, 'UTC') + conf_data = config.parse(["-q", "--utc", "-p" + self.project_dir, "example_prj"]) + self.assertEqual(conf_data.timezone, "UTC") - @patch('tzlocal.get_localzone') + @patch("tzlocal.get_localzone") def test_timezone(self, mock_get_localzone): """ Verify handling problem with detecting timezone """ - mock_get_localzone.return_value = 'local' - conf_data = config.parse([ - '-q', - '-p'+self.project_dir, - 'example_prj']) - self.assertEqual(text_type(conf_data.timezone), 'UTC') + mock_get_localzone.return_value = "local" + conf_data = config.parse(["-q", "-p" + self.project_dir, "example_prj"]) + self.assertEqual(str(conf_data.timezone), "UTC") def test_templates(self): """- Verify handling of valid (existing) and invalid (non-existing) templates directory parameter """ - conf_data = config.parse([ - '--templates=/foo/bar', '-q', - '-p'+self.project_dir, - 'example_prj']) + conf_data = config.parse(["--templates=/foo/bar", "-q", "-p" + self.project_dir, "example_prj"]) self.assertFalse(conf_data.templates) - tpl_path = os.path.join(os.path.dirname(__file__), 'test_templates') + tpl_path = os.path.join(os.path.dirname(__file__), "test_templates") - conf_data = config.parse([ - '--templates=%s' % tpl_path, '-q', - '-p'+self.project_dir, - 'example_prj']) + conf_data = config.parse(["--templates=%s" % tpl_path, "-q", "-p" + self.project_dir, "example_prj"]) self.assertEqual(conf_data.templates, tpl_path) def suspend_test_check_install(self): import pip + # discard the argparser errors - with patch('sys.stdout', self.stdout): - with patch('sys.stderr', self.stderr): + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): # clean the virtualenv try: - pip.main(['uninstall', '-y', 'psycopg2']) + pip.main(["uninstall", "-y", "psycopg2"]) except pip.exceptions.UninstallationError: - ## package not installed, all is fine + # package not installed, all is fine pass try: - pip.main(['uninstall', '-y', 'pillow']) + pip.main(["uninstall", "-y", "pillow"]) except pip.exceptions.UninstallationError: - ## package not installed, all is fine + # package not installed, all is fine pass try: - pip.main(['uninstall', '-y', 'mysql-python']) + pip.main(["uninstall", "-y", "mysql-python"]) except pip.exceptions.UninstallationError: - ## package not installed, all is fine + # package not installed, all is fine pass # Check postgres / pillow - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '--django-version=1.8', - '--i18n=no', - '-f', - '-p'+self.project_dir, - 'example_prj']) + conf_data = config.parse( + [ + "-q", + "--db=postgres://user:pwd@host/dbname", + "--django-version=1.8", + "--i18n=no", + "-f", + "-p" + self.project_dir, + "example_prj", + ] + ) with self.assertRaises(EnvironmentError) as context_error: check_install(conf_data) - self.assertTrue(str(context_error.exception).find('Pillow is not installed') > -1) - self.assertTrue(str(context_error.exception).find('PostgreSQL driver is not installed') > -1) + self.assertTrue(str(context_error.exception).find("Pillow is not installed") > -1) + self.assertTrue(str(context_error.exception).find("PostgreSQL driver is not installed") > -1) # Check mysql - conf_data = config.parse([ - '-q', - '--db=mysql://user:pwd@host/dbname', - '--django-version=1.8', - '--i18n=no', - '-f', - '-p'+self.project_dir, - 'example_prj']) + conf_data = config.parse( + [ + "-q", + "--db=mysql://user:pwd@host/dbname", + "--django-version=1.8", + "--i18n=no", + "-f", + "-p" + self.project_dir, + "example_prj", + ] + ) with self.assertRaises(EnvironmentError) as context_error: check_install(conf_data) - self.assertTrue(str(context_error.exception).find('MySQL driver is not installed') > -1) + self.assertTrue(str(context_error.exception).find("MySQL driver is not installed") > -1) def test_show_plugins(self): sys.stdout = StringIO() @@ -788,14 +845,17 @@ def test_show_requirements(self): dj_version, dj_match = get_stable_django() try: - conf_data = config.parse([ - '-q', - '--db=mysql://user:pwd@host/dbname', - '--django-version={0}'.format(dj_version), - '--i18n=no', - '-f', - '-p'+self.project_dir, - 'example_prj']) + conf_data = config.parse( + [ + "-q", + "--db=mysql://user:pwd@host/dbname", + "--django-version={}".format(dj_version), + "--i18n=no", + "-f", + "-p" + self.project_dir, + "example_prj", + ] + ) config.show_requirements(conf_data) finally: sys.stdout = sys.__stdout__ @@ -803,47 +863,49 @@ def test_show_requirements(self): class TestBaseConfig(unittest.TestCase): base_dir = os.path.dirname(os.path.dirname(__file__)) - config_dir = os.path.join(base_dir, 'tests/fixtures/configs') - args = ['--config-file', '-s', '-q', 'example_prj'] - django_version = DJANGO_VERSION_MATRIX['stable'] - config_fixture = Namespace(**{ - 'bootstrap': False, - 'cms_version': CMS_VERSION_MATRIX['stable'], - 'db': 'sqlite://localhost/project.db', - 'django_version': django_version, - 'dump_reqs': False, - 'extra_settings': None, - 'filer': True, - 'i18n': 'yes', - 'languages': ['en'], - 'no_db_driver': False, - 'no_deps': False, - 'noinput': True, - 'no_sync': False, - 'no_user': False, - 'permissions': 'yes', - 'pip_options': '', - 'plugins': False, - 'project_directory': os.path.abspath('.'), - 'project_name': 'example_prj', - 'requirements_file': None, - 'reversion': 'yes', - 'skip_project_dir_check': True, - 'starting_page': False, - 'template': None, - 'templates': False, - 'timezone': get_localzone().zone, - 'use_timezone': 'yes', - 'utc': False, - 'no_plugins': False, - 'verbose': False, - 'wizard': False, - 'delete_project_dir': False, - }) + config_dir = os.path.join(base_dir, "tests/fixtures/configs") + args = ["--config-file", "-s", "-q", "example_prj"] + django_version = data.DJANGO_VERSION_MATRIX["stable"] + config_fixture = Namespace( + **{ + "bootstrap": False, + "cms_version": data.CMS_VERSION_MATRIX["stable"], + "db": "sqlite://localhost/project.db", + "django_version": django_version, + "dump_reqs": False, + "extra_settings": None, + "filer": True, + "i18n": "yes", + "languages": ["en"], + "no_db_driver": False, + "no_deps": False, + "noinput": True, + "no_sync": False, + "no_user": False, + "permissions": "yes", + "pip_options": "", + "plugins": False, + "project_directory": os.path.abspath("."), + "project_name": "example_prj", + "requirements_file": None, + "reversion": "yes", + "skip_project_dir_check": True, + "starting_page": False, + "template": None, + "templates": False, + "timezone": get_localzone().zone, + "use_timezone": "yes", + "utc": False, + "no_plugins": False, + "verbose": False, + "wizard": False, + "delete_project_dir": False, + } + ) def __init__(self, *args, **kwargs): - self.config_not_exists = self.conf('config-dump.ini') - super(TestBaseConfig, self).__init__(*args, **kwargs) + self.config_not_exists = self.conf("config-dump.ini") + super().__init__(*args, **kwargs) def tearDown(self): if os.path.isfile(self.config_not_exists): @@ -855,81 +917,89 @@ def conf(self, filename): def unused(self, config_data): """Remove not configurable keys.""" for attr in ( - 'config_dump', 'config_file', 'db_driver', 'db_parsed', 'project_path', 'settings_path', - 'urlconf_path' + "config_dump", + "config_file", + "db_driver", + "db_parsed", + "project_path", + "settings_path", + "urlconf_path", ): delattr(config_data, attr) # When `requirements` arg is used then requirements attr isn't set. - if hasattr(config_data, 'requirements'): - delattr(config_data, 'requirements') + if hasattr(config_data, "requirements"): + delattr(config_data, "requirements") - @unittest.skipIf(sys.version_info[0] < 3, - reason='django 2+ only supports python 3') + @unittest.skipIf(sys.version_info[0] < 3, reason="django 2+ only supports python 3") def test_parse_config_file(self, *args): """Tests .config.__init__._parse_config_file function.""" dj_version, __ = get_stable_django(latest=True) dj_lts_version, __ = get_stable_django(lts=True) with self.assertRaises(SystemExit) as error: - config.parse(self.args[0:1] + [self.conf('config-not-exists.ini')] + self.args[1:]) + config.parse(self.args[0:1] + [self.conf("config-not-exists.ini")] + self.args[1:]) self.assertEqual(7, error.exception.code) - args = self.args[0:1] + [self.conf('config-01.ini')] + self.args[1:] + args = self.args[0:1] + [self.conf("config-01.ini")] + self.args[1:] config_data = config.parse(args) self.unused(config_data) self.assertEqual(self.config_fixture, config_data) # Check if config value and changed value equals. test_data = [ - ('config-02.ini', None, ( - ('cms_version', '3.7'), - ('db', 'postgres://user:pwd@host:54321/dbname'), - ('django_version', dj_lts_version), - )), - ('config-03.ini', None, ( - ('cms_version', '3.7'), - ('i18n', 'no'), - ('django_version', dj_version), - )), - ('config-04.ini', None, (('cms_version', '3.7'), ('use_timezone', 'no'))), - ('config-05.ini', None, (('cms_version', '3.7'), ('timezone', 'Europe/London'))), - ('config-06.ini', None, (('cms_version', '3.7'), ('reversion', 'no'))), - ('config-07.ini', None, (('cms_version', '3.7'), ('permissions', 'no'), ('django_version', dj_lts_version))), - ('config-08.ini', None, ( - ('cms_version', '3.7'), - ('i18n', 'no'), - ('languages', ['ru']), - ('django_version', dj_lts_version) - )), - ('config-09.ini', None, ( - ('cms_version', '3.7'), - ('i18n', 'yes'), - ('languages', ['en', 'ru']), - ('django_version', dj_lts_version) - )), - ('config-10.ini', 'django_version', dj_lts_version), - ('config-11.ini', 'project_directory', '/test/me'), - ('config-12.ini', None, ( - ('bootstrap', True), - ('django_version', dj_lts_version) - )), - ('config-13.ini', 'templates', '.'), - ('config-14.ini', 'starting_page', True), - ('config-15.ini', 'plugins', True), - ('config-16.ini', 'dump_reqs', True), - ('config-17.ini', 'noinput', True), - ('config-18.ini', 'filer', True), - ('config-19.ini', 'requirements_file', '/test/reqs'), - ('config-20.ini', 'no_deps', True), - ('config-21.ini', 'no_db_driver', True), - ('config-22.ini', 'no_sync', True), - ('config-23.ini', 'no_user', True), - ('config-24.ini', 'template', '/test/template'), - ('config-25.ini', 'extra_settings', '/test/extra_settings'), - ('config-26.ini', 'skip_project_dir_check', True), - ('config-27.ini', 'utc', True), - ('config-28.ini', 'no_plugins', True), - ('config-30.ini', 'verbose', True), - ('config-32.ini', 'delete_project_dir', True), + ( + "config-02.ini", + None, + ( + ("cms_version", "3.7"), + ("db", "postgres://user:pwd@host:54321/dbname"), + ("django_version", dj_lts_version), + ), + ), + ("config-03.ini", None, (("cms_version", "3.7"), ("i18n", "no"), ("django_version", dj_version),)), + ("config-04.ini", None, (("cms_version", "3.7"), ("use_timezone", "no"))), + ("config-05.ini", None, (("cms_version", "3.7"), ("timezone", "Europe/London"))), + ("config-06.ini", None, (("cms_version", "3.7"), ("reversion", "no"))), + ( + "config-07.ini", + None, + (("cms_version", "3.7"), ("permissions", "no"), ("django_version", dj_lts_version)), + ), + ( + "config-08.ini", + None, + (("cms_version", "3.7"), ("i18n", "no"), ("languages", ["ru"]), ("django_version", dj_lts_version)), + ), + ( + "config-09.ini", + None, + ( + ("cms_version", "3.7"), + ("i18n", "yes"), + ("languages", ["en", "ru"]), + ("django_version", dj_lts_version), + ), + ), + ("config-10.ini", "django_version", dj_lts_version), + ("config-11.ini", "project_directory", "/test/me"), + ("config-12.ini", None, (("bootstrap", True), ("django_version", dj_lts_version))), + ("config-13.ini", "templates", "."), + ("config-14.ini", "starting_page", True), + ("config-15.ini", "plugins", True), + ("config-16.ini", "dump_reqs", True), + ("config-17.ini", "noinput", True), + ("config-18.ini", "filer", True), + ("config-19.ini", "requirements_file", "/test/reqs"), + ("config-20.ini", "no_deps", True), + ("config-21.ini", "no_db_driver", True), + ("config-22.ini", "no_sync", True), + ("config-23.ini", "no_user", True), + ("config-24.ini", "template", "/test/template"), + ("config-25.ini", "extra_settings", "/test/extra_settings"), + ("config-26.ini", "skip_project_dir_check", True), + ("config-27.ini", "utc", True), + ("config-28.ini", "no_plugins", True), + ("config-30.ini", "verbose", True), + ("config-32.ini", "delete_project_dir", True), ] fixture = copy.copy(self.config_fixture) for filename, key, val in test_data: @@ -943,21 +1013,21 @@ def test_parse_config_file(self, *args): self.unused(config_data) self.assertEqual(fixture, config_data) # Check if config value and changed value equals. - @patch('sys.stdout') - @patch('sys.stderr') + @patch("sys.stdout") + @patch("sys.stderr") def test_dump_config_file(self, *args): """Tests .config.ini.dump_config_file function.""" - config_exists = self.conf('config-01.ini') + config_exists = self.conf("config-01.ini") with self.assertRaises(SystemExit) as error: - config.parse(['--config-dump', config_exists] + self.args[1:] + ['-p', '.']) + config.parse(["--config-dump", config_exists] + self.args[1:] + ["-p", "."]) self.assertEqual(8, error.exception.code) - config.parse(['--config-dump', self.config_not_exists] + self.args[1:] + ['-p', '.']) + config.parse(["--config-dump", self.config_not_exists] + self.args[1:] + ["-p", "."]) self.assertTrue(os.path.isfile(self.config_not_exists)) fixture = copy.copy(self.config_fixture) - setattr(fixture, 'timezone', get_localzone().zone) + fixture.timezone = get_localzone().zone # Load dumped config. args = self.args[0:1] + [self.config_not_exists] + self.args[1:] config_data = config.parse(args) diff --git a/tests/django.py b/tests/django.py index b9bb2972..dee6b286 100644 --- a/tests/django.py +++ b/tests/django.py @@ -1,13 +1,9 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - import os.path import re import sqlite3 import sys import textwrap - -from mock import patch +from unittest.mock import patch from djangocms_installer import config, django, install @@ -15,39 +11,46 @@ class TestDjango(IsolatedTestClass): - templates_basic = set( - ( - ('fullwidth.html', 'Fullwidth'), - ('sidebar_left.html', 'Sidebar Left'), - ('sidebar_right.html', 'Sidebar Right'), - ) - ) - templates_bootstrap = set( - ( - ('page.html', 'Page'), - ('feature.html', 'Page with Feature') - ) - ) + templates_basic = { + ("fullwidth.html", "Fullwidth"), + ("sidebar_left.html", "Sidebar Left"), + ("sidebar_right.html", "Sidebar Right"), + } + templates_bootstrap = {("page.html", "Page"), ("feature.html", "Page with Feature")} def test_create_project(self): dj_version, dj_match = get_stable_django() - config_data = config.parse(['--db=postgres://user:pwd@host/dbname', - '--cms-version=develop', '--django=%s' % dj_version, - '-q', '-p' + self.project_dir, 'example_prj']) + config_data = config.parse( + [ + "--db=postgres://user:pwd@host/dbname", + "--cms-version=develop", + "--django=%s" % dj_version, + "-q", + "-p" + self.project_dir, + "example_prj", + ] + ) install.requirements(config_data.requirements) django.create_project(config_data) - self.assertTrue(os.path.exists(os.path.join(self.project_dir, 'example_prj'))) + self.assertTrue(os.path.exists(os.path.join(self.project_dir, "example_prj"))) def test_django_admin_errors(self): dj_version, dj_match = get_stable_django() - config_data = config.parse(['--db=postgres://user:pwd@host/dbname', - '--cms-version=develop', '--django=%s' % dj_version, - '-q', '-p' + self.project_dir, 'example_prj']) + config_data = config.parse( + [ + "--db=postgres://user:pwd@host/dbname", + "--cms-version=develop", + "--django=%s" % dj_version, + "-q", + "-p" + self.project_dir, + "example_prj", + ] + ) install.requirements(config_data.requirements) - config_data.project_name = 'example.prj' + config_data.project_name = "example.prj" with self.assertRaises(RuntimeError) as e: django.create_project(config_data) - self.assertTrue('\'example.prj\' is not a valid project name.' in str(e.exception)) + self.assertTrue("'example.prj' is not a valid project name." in str(e.exception)) def test_copy_data(self): """ @@ -57,15 +60,22 @@ def test_copy_data(self): cms_stable, cms_match = get_stable_djangocms() # Basic template - config_data = config.parse(['--db=postgres://user:pwd@host/dbname', - '--cms-version=%s' % cms_stable, '--django=%s' % dj_version, - '-q', '-p' + self.project_dir, 'test_copy_data_1']) + config_data = config.parse( + [ + "--db=postgres://user:pwd@host/dbname", + "--cms-version=%s" % cms_stable, + "--django=%s" % dj_version, + "-q", + "-p" + self.project_dir, + "test_copy_data_1", + ] + ) os.makedirs(config_data.project_path) django.copy_files(config_data) - starting_page_py = os.path.join(config_data.project_directory, 'starting_page.py') - starting_page_json = os.path.join(config_data.project_directory, 'starting_page.json') - basic_template = os.path.join(config_data.project_path, 'templates', 'fullwidth.html') - boostrap_template = os.path.join(config_data.project_path, 'templates', 'feature.html') + starting_page_py = os.path.join(config_data.project_directory, "starting_page.py") + starting_page_json = os.path.join(config_data.project_directory, "starting_page.json") + basic_template = os.path.join(config_data.project_path, "templates", "fullwidth.html") + boostrap_template = os.path.join(config_data.project_path, "templates", "feature.html") self.assertFalse(os.path.exists(starting_page_py)) self.assertFalse(os.path.exists(starting_page_json)) self.assertFalse(os.path.exists(boostrap_template)) @@ -73,16 +83,23 @@ def test_copy_data(self): # Bootstrap template self._create_project_dir() - config_data = config.parse(['--db=postgres://user:pwd@host/dbname', - '--django=%s' % dj_version, - '--cms-version=%s' % cms_stable, '--bootstrap=yes', - '-q', '-p' + self.project_dir, 'test_copy_data_2']) + config_data = config.parse( + [ + "--db=postgres://user:pwd@host/dbname", + "--django=%s" % dj_version, + "--cms-version=%s" % cms_stable, + "--bootstrap=yes", + "-q", + "-p" + self.project_dir, + "test_copy_data_2", + ] + ) os.makedirs(config_data.project_path) django.copy_files(config_data) - starting_page_py = os.path.join(config_data.project_directory, 'starting_page.py') - starting_page_json = os.path.join(config_data.project_directory, 'starting_page.json') - basic_template = os.path.join(config_data.project_path, 'templates', 'fullwidth.html') - boostrap_template = os.path.join(config_data.project_path, 'templates', 'feature.html') + starting_page_py = os.path.join(config_data.project_directory, "starting_page.py") + starting_page_json = os.path.join(config_data.project_directory, "starting_page.json") + basic_template = os.path.join(config_data.project_path, "templates", "fullwidth.html") + boostrap_template = os.path.join(config_data.project_path, "templates", "feature.html") self.assertFalse(os.path.exists(starting_page_py)) self.assertFalse(os.path.exists(starting_page_json)) self.assertTrue(os.path.exists(boostrap_template)) @@ -90,30 +107,44 @@ def test_copy_data(self): # Custom template self._create_project_dir() - tpl_path = os.path.join(os.path.dirname(__file__), 'test_templates') - config_data = config.parse(['--db=postgres://user:pwd@host/dbname', - '--django=%s' % dj_version, - '--cms-version=%s' % cms_stable, '--templates=%s' % tpl_path, - '-q', '-p' + self.project_dir, 'example_prj']) + tpl_path = os.path.join(os.path.dirname(__file__), "test_templates") + config_data = config.parse( + [ + "--db=postgres://user:pwd@host/dbname", + "--django=%s" % dj_version, + "--cms-version=%s" % cms_stable, + "--templates=%s" % tpl_path, + "-q", + "-p" + self.project_dir, + "example_prj", + ] + ) os.makedirs(config_data.project_path) django.copy_files(config_data) - basic_template = os.path.join(config_data.project_path, 'templates', 'fullwidth.html') - boostrap_template = os.path.join(config_data.project_path, 'templates', 'feature.html') - custom_template = os.path.join(config_data.project_path, 'templates', 'left.html') + basic_template = os.path.join(config_data.project_path, "templates", "fullwidth.html") + boostrap_template = os.path.join(config_data.project_path, "templates", "feature.html") + custom_template = os.path.join(config_data.project_path, "templates", "left.html") self.assertTrue(os.path.exists(custom_template)) self.assertFalse(os.path.exists(boostrap_template)) self.assertFalse(os.path.exists(basic_template)) # Starting page self._create_project_dir() - config_data = config.parse(['--db=postgres://user:pwd@host/dbname', - '--django=%s' % dj_version, - '--cms-version=%s' % cms_stable, '--starting-page=yes', - '-q', '-p' + self.project_dir, 'example_prj']) + config_data = config.parse( + [ + "--db=postgres://user:pwd@host/dbname", + "--django=%s" % dj_version, + "--cms-version=%s" % cms_stable, + "--starting-page=yes", + "-q", + "-p" + self.project_dir, + "example_prj", + ] + ) os.makedirs(config_data.project_path) django.copy_files(config_data) - starting_page_py = os.path.join(config_data.project_directory, 'starting_page.py') - starting_page_json = os.path.join(config_data.project_directory, 'starting_page.json') + starting_page_py = os.path.join(config_data.project_directory, "starting_page.py") + starting_page_json = os.path.join(config_data.project_directory, "starting_page.json") self.assertTrue(os.path.exists(starting_page_py)) self.assertTrue(os.path.exists(starting_page_json)) @@ -121,14 +152,23 @@ def test_patch_22_settings(self): dj_version, dj_match = get_stable_django() cms_stable, cms_match = get_stable_djangocms() - extra_path = os.path.join(os.path.dirname(__file__), 'data', 'extra_settings.py') - config_data = config.parse(['--db=sqlite://localhost/test.db', - '--lang=en', '--extra-settings=%s' % extra_path, - '--cms-version=%s' % cms_stable, - '--django-version=%s' % dj_version, - '--timezone=Europe/Moscow', - '-q', '-u', '-zno', '--i18n=no', - '-p' + self.project_dir, 'example_path_111_settings']) + extra_path = os.path.join(os.path.dirname(__file__), "data", "extra_settings.py") + config_data = config.parse( + [ + "--db=sqlite://localhost/test.db", + "--lang=en", + "--extra-settings=%s" % extra_path, + "--cms-version=%s" % cms_stable, + "--django-version=%s" % dj_version, + "--timezone=Europe/Moscow", + "-q", + "-u", + "-zno", + "--i18n=no", + "-p" + self.project_dir, + "example_path_111_settings", + ] + ) install.requirements(config_data.requirements) django.create_project(config_data) django.patch_settings(config_data) @@ -136,26 +176,37 @@ def test_patch_22_settings(self): # settings is importable even in non django environment sys.path.append(config_data.project_directory) - project = __import__(config_data.project_name, globals(), locals(), [str('settings')]) + project = __import__(config_data.project_name, globals(), locals(), ["settings"]) # checking for django options - self.assertEqual(project.settings.MEDIA_ROOT, - os.path.join(config_data.project_directory, 'media')) - self.assertEqual(project.settings.MEDIA_URL, '/media/') + self.assertEqual( + project.settings.MEDIA_ROOT, os.path.join(config_data.project_directory, "media"), + ) + self.assertEqual(project.settings.MEDIA_URL, "/media/") # Data from external settings files - self.assertIsNotNone(getattr(project.settings, 'MIDDLEWARE', None)) - self.assertIsNone(getattr(project.settings, 'MIDDLEWARE_CLASSES', None)) + self.assertIsNotNone(getattr(project.settings, "MIDDLEWARE", None)) + self.assertIsNone(getattr(project.settings, "MIDDLEWARE_CLASSES", None)) def test_patch_django_22_37(self): dj_version, dj_match = get_stable_django() - config_data = config.parse(['--db=sqlite://localhost/test.db', - '--lang=en', '--bootstrap=yes', - '--django-version=%s' % dj_version, - '--cms-version=3.7', '--timezone=Europe/Moscow', - '-q', '-u', '-zno', '--i18n=no', - '-p' + self.project_dir, 'test_patch_django_111_36']) + config_data = config.parse( + [ + "--db=sqlite://localhost/test.db", + "--lang=en", + "--bootstrap=yes", + "--django-version=%s" % dj_version, + "--cms-version=3.7", + "--timezone=Europe/Moscow", + "-q", + "-u", + "-zno", + "--i18n=no", + "-p" + self.project_dir, + "test_patch_django_111_36", + ] + ) install.requirements(config_data.requirements) django.create_project(config_data) @@ -167,59 +218,66 @@ def test_patch_django_22_37(self): # settings is importable even in non django environment sys.path.append(config_data.project_directory) - project = __import__(config_data.project_name, globals(), locals(), [str('settings')]) + project = __import__(config_data.project_name, globals(), locals(), ["settings"]) # checking for django options self.assertEqual( - project.settings.MEDIA_ROOT, os.path.join(config_data.project_directory, 'media') - ) - self.assertEqual(project.settings.MEDIA_URL, '/media/') - - self.assertEqual(project.settings.TIME_ZONE, 'Europe/Moscow') - self.assertTrue('cmsplugin_filer_image' not in project.settings.INSTALLED_APPS) - self.assertTrue('cmsplugin_filer_file' not in project.settings.INSTALLED_APPS) - self.assertTrue('cmsplugin_filer_folder' not in project.settings.INSTALLED_APPS) - self.assertTrue('cmsplugin_filer_link' not in project.settings.INSTALLED_APPS) - self.assertTrue('cmsplugin_filer_teaser' not in project.settings.INSTALLED_APPS) - self.assertTrue('cmsplugin_filer_utils' not in project.settings.INSTALLED_APPS) - self.assertTrue('cmsplugin_filer_video' not in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_text_ckeditor' in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_admin_style' in project.settings.INSTALLED_APPS) - self.assertTrue('filer' in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_bootstrap4' in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_file' in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_flash' not in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_googlemap' in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_inherit' not in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_link' in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_picture' in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_style' in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_teaser' not in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_video' in project.settings.INSTALLED_APPS) - self.assertTrue( - config.get_settings().APPHOOK_RELOAD_MIDDLEWARE_CLASS in - project.settings.MIDDLEWARE + project.settings.MEDIA_ROOT, os.path.join(config_data.project_directory, "media"), ) + self.assertEqual(project.settings.MEDIA_URL, "/media/") + + self.assertEqual(project.settings.TIME_ZONE, "Europe/Moscow") + self.assertTrue("cmsplugin_filer_image" not in project.settings.INSTALLED_APPS) + self.assertTrue("cmsplugin_filer_file" not in project.settings.INSTALLED_APPS) + self.assertTrue("cmsplugin_filer_folder" not in project.settings.INSTALLED_APPS) + self.assertTrue("cmsplugin_filer_link" not in project.settings.INSTALLED_APPS) + self.assertTrue("cmsplugin_filer_teaser" not in project.settings.INSTALLED_APPS) + self.assertTrue("cmsplugin_filer_utils" not in project.settings.INSTALLED_APPS) + self.assertTrue("cmsplugin_filer_video" not in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_text_ckeditor" in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_admin_style" in project.settings.INSTALLED_APPS) + self.assertTrue("filer" in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_bootstrap4" in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_file" in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_flash" not in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_googlemap" in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_inherit" not in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_link" in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_picture" in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_style" in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_teaser" not in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_video" in project.settings.INSTALLED_APPS) + self.assertTrue(config.get_settings().APPHOOK_RELOAD_MIDDLEWARE_CLASS in project.settings.MIDDLEWARE) self.assertEqual(set(project.settings.CMS_TEMPLATES), self.templates_bootstrap) self.assertTrue(project.settings.TEMPLATES) - self.assertEqual(len(re.findall('BASE_DIR = ', settings)), 1) - self.assertEqual(len(re.findall('STATIC_ROOT', settings)), 1) - self.assertEqual(len(re.findall('MEDIA_ROOT =', settings)), 1) - self.assertEqual(len(re.findall('STATICFILES_DIRS', settings)), 1) - - @unittest.skipIf(sys.version_info[:2] not in ((3, 6), (3, 7), (3, 8),), - reason='django 3.0 only supports python 3.6, 3.7 and 3.8') + self.assertEqual(len(re.findall("BASE_DIR = ", settings)), 1) + self.assertEqual(len(re.findall("STATIC_ROOT", settings)), 1) + self.assertEqual(len(re.findall("MEDIA_ROOT =", settings)), 1) + self.assertEqual(len(re.findall("STATICFILES_DIRS", settings)), 1) + + @unittest.skipIf( + sys.version_info[:2] not in ((3, 6), (3, 7), (3, 8),), + reason="django 3.0 only supports python 3.6, 3.7 and 3.8", + ) def test_patch_django_30_develop(self): dj_version, dj_match = get_stable_django(latest=True) - extra_path = os.path.join(os.path.dirname(__file__), 'data', 'extra_settings.py') + extra_path = os.path.join(os.path.dirname(__file__), "data", "extra_settings.py") params = [ - '--db=sqlite://localhost/test.db', '--lang=en', '--extra-settings=%s' % extra_path, - '--django-version=%s' % dj_version, - '-f', '--cms-version=develop', '--timezone=Europe/Moscow', - '-q', '-u', '-zno', '--i18n=no', '-p' + self.project_dir, - 'test_patch_django_30_develop' + "--db=sqlite://localhost/test.db", + "--lang=en", + "--extra-settings=%s" % extra_path, + "--django-version=%s" % dj_version, + "-f", + "--cms-version=develop", + "--timezone=Europe/Moscow", + "-q", + "-u", + "-zno", + "--i18n=no", + "-p" + self.project_dir, + "test_patch_django_30_develop", ] config_data = config.parse(params) install.requirements(config_data.requirements) @@ -229,25 +287,31 @@ def test_patch_django_30_develop(self): # settings is importable even in non django environment sys.path.append(config_data.project_directory) - project = __import__(config_data.project_name, globals(), locals(), [str('settings')]) + project = __import__(config_data.project_name, globals(), locals(), ["settings"]) # checking for django options self.assertTrue(project.settings.TEMPLATES) - self.assertFalse(getattr(project.settings, 'TEMPLATES_DIR', False)) - self.assertTrue( - config.get_settings().APPHOOK_RELOAD_MIDDLEWARE_CLASS in - project.settings.MIDDLEWARE - ) + self.assertFalse(getattr(project.settings, "TEMPLATES_DIR", False)) + self.assertTrue(config.get_settings().APPHOOK_RELOAD_MIDDLEWARE_CLASS in project.settings.MIDDLEWARE) def test_patch_django_22_rc(self): dj_version, dj_match = get_stable_django(lts=True) - extra_path = os.path.join(os.path.dirname(__file__), 'data', 'extra_settings.py') + extra_path = os.path.join(os.path.dirname(__file__), "data", "extra_settings.py") params = [ - '--db=sqlite://localhost/test.db', '--lang=en', '--extra-settings=%s' % extra_path, - '--django-version=%s' % dj_version, '-f', '--cms-version=rc', - '--timezone=Europe/Moscow', '-q', '-u', '-zno', '--i18n=no', '-p' + self.project_dir, - 'test_patch_django_22_rc' + "--db=sqlite://localhost/test.db", + "--lang=en", + "--extra-settings=%s" % extra_path, + "--django-version=%s" % dj_version, + "-f", + "--cms-version=rc", + "--timezone=Europe/Moscow", + "-q", + "-u", + "-zno", + "--i18n=no", + "-p" + self.project_dir, + "test_patch_django_22_rc", ] config_data = config.parse(params) install.requirements(config_data.requirements) @@ -257,25 +321,31 @@ def test_patch_django_22_rc(self): # settings is importable even in non django environment sys.path.append(config_data.project_directory) - project = __import__(config_data.project_name, globals(), locals(), [str('settings')]) + project = __import__(config_data.project_name, globals(), locals(), ["settings"]) # checking for django options self.assertTrue(project.settings.TEMPLATES) - self.assertFalse(getattr(project.settings, 'TEMPLATES_DIR', False)) - self.assertTrue( - config.get_settings().APPHOOK_RELOAD_MIDDLEWARE_CLASS in - project.settings.MIDDLEWARE - ) + self.assertFalse(getattr(project.settings, "TEMPLATES_DIR", False)) + self.assertTrue(config.get_settings().APPHOOK_RELOAD_MIDDLEWARE_CLASS in project.settings.MIDDLEWARE) def test_patch_django_22_develop(self): dj_version, dj_match = get_stable_django(lts=True) - extra_path = os.path.join(os.path.dirname(__file__), 'data', 'extra_settings.py') + extra_path = os.path.join(os.path.dirname(__file__), "data", "extra_settings.py") params = [ - '--db=sqlite://localhost/test.db', '--lang=en', '--extra-settings=%s' % extra_path, - '--django-version=%s' % dj_version, '-f', '--cms-version=develop', - '--timezone=Europe/Moscow', '-q', '-u', '-zno', '--i18n=no', '-p' + self.project_dir, - 'test_patch_django_21_develop' + "--db=sqlite://localhost/test.db", + "--lang=en", + "--extra-settings=%s" % extra_path, + "--django-version=%s" % dj_version, + "-f", + "--cms-version=develop", + "--timezone=Europe/Moscow", + "-q", + "-u", + "-zno", + "--i18n=no", + "-p" + self.project_dir, + "test_patch_django_21_develop", ] config_data = config.parse(params) install.requirements(config_data.requirements) @@ -285,27 +355,36 @@ def test_patch_django_22_develop(self): # settings is importable even in non django environment sys.path.append(config_data.project_directory) - project = __import__(config_data.project_name, globals(), locals(), [str('settings')]) + project = __import__(config_data.project_name, globals(), locals(), ["settings"]) # checking for django options self.assertTrue(project.settings.TEMPLATES) - self.assertFalse(getattr(project.settings, 'TEMPLATES_DIR', False)) - self.assertTrue( - config.get_settings().APPHOOK_RELOAD_MIDDLEWARE_CLASS in - project.settings.MIDDLEWARE - ) + self.assertFalse(getattr(project.settings, "TEMPLATES_DIR", False)) + self.assertTrue(config.get_settings().APPHOOK_RELOAD_MIDDLEWARE_CLASS in project.settings.MIDDLEWARE) def test_patch_django_base_no_plugins(self): dj_version, dj_match = get_stable_django() cms_stable, cms_match = get_stable_djangocms() - extra_path = os.path.join(os.path.dirname(__file__), 'data', 'extra_settings.py') - config_data = config.parse(['--db=sqlite://localhost/test.db', - '--lang=en', '--extra-settings=%s' % extra_path, - '--django-version=%s' % dj_version, '-f', '--no-plugins', - '--cms-version=%s' % cms_stable, '--timezone=Europe/Moscow', - '-q', '-u', '-zno', '--i18n=no', - '-p' + self.project_dir, 'test_patch_django_111_no_plugins']) + extra_path = os.path.join(os.path.dirname(__file__), "data", "extra_settings.py") + config_data = config.parse( + [ + "--db=sqlite://localhost/test.db", + "--lang=en", + "--extra-settings=%s" % extra_path, + "--django-version=%s" % dj_version, + "-f", + "--no-plugins", + "--cms-version=%s" % cms_stable, + "--timezone=Europe/Moscow", + "-q", + "-u", + "-zno", + "--i18n=no", + "-p" + self.project_dir, + "test_patch_django_111_no_plugins", + ] + ) install.requirements(config_data.requirements) django.create_project(config_data) django.patch_settings(config_data) @@ -313,41 +392,50 @@ def test_patch_django_base_no_plugins(self): # settings is importable even in non django environment sys.path.append(config_data.project_directory) - project = __import__(config_data.project_name, globals(), locals(), [str('settings')]) + project = __import__(config_data.project_name, globals(), locals(), ["settings"]) # checking for django options self.assertTrue(project.settings.TEMPLATES) - self.assertFalse(getattr(project.settings, 'TEMPLATES_DIR', False)) - self.assertFalse('djangocms_file' in project.settings.INSTALLED_APPS) - self.assertFalse('djangocms_flash' in project.settings.INSTALLED_APPS) - self.assertFalse('djangocms_googlemap' in project.settings.INSTALLED_APPS) - self.assertFalse('djangocms_inherit' in project.settings.INSTALLED_APPS) - self.assertFalse('djangocms_link' in project.settings.INSTALLED_APPS) - self.assertFalse('djangocms_picture' in project.settings.INSTALLED_APPS) - self.assertFalse('djangocms_teaser' in project.settings.INSTALLED_APPS) - self.assertFalse('djangocms_video' in project.settings.INSTALLED_APPS) - self.assertFalse('cms.plugins.file' in project.settings.INSTALLED_APPS) - self.assertFalse('cms.plugins.flash' in project.settings.INSTALLED_APPS) - self.assertFalse('cms.plugins.googlemap' in project.settings.INSTALLED_APPS) - self.assertFalse('cms.plugins.inherit' in project.settings.INSTALLED_APPS) - self.assertFalse('cms.plugins.link' in project.settings.INSTALLED_APPS) - self.assertFalse('cms.plugins.picture' in project.settings.INSTALLED_APPS) - self.assertFalse('cms.plugins.teaser' in project.settings.INSTALLED_APPS) - self.assertFalse('cms.plugins.text' in project.settings.INSTALLED_APPS) - self.assertFalse('cms.plugins.twitter' in project.settings.INSTALLED_APPS) - self.assertFalse('cms.plugins.video' in project.settings.INSTALLED_APPS) + self.assertFalse(getattr(project.settings, "TEMPLATES_DIR", False)) + self.assertFalse("djangocms_file" in project.settings.INSTALLED_APPS) + self.assertFalse("djangocms_flash" in project.settings.INSTALLED_APPS) + self.assertFalse("djangocms_googlemap" in project.settings.INSTALLED_APPS) + self.assertFalse("djangocms_inherit" in project.settings.INSTALLED_APPS) + self.assertFalse("djangocms_link" in project.settings.INSTALLED_APPS) + self.assertFalse("djangocms_picture" in project.settings.INSTALLED_APPS) + self.assertFalse("djangocms_teaser" in project.settings.INSTALLED_APPS) + self.assertFalse("djangocms_video" in project.settings.INSTALLED_APPS) + self.assertFalse("cms.plugins.file" in project.settings.INSTALLED_APPS) + self.assertFalse("cms.plugins.flash" in project.settings.INSTALLED_APPS) + self.assertFalse("cms.plugins.googlemap" in project.settings.INSTALLED_APPS) + self.assertFalse("cms.plugins.inherit" in project.settings.INSTALLED_APPS) + self.assertFalse("cms.plugins.link" in project.settings.INSTALLED_APPS) + self.assertFalse("cms.plugins.picture" in project.settings.INSTALLED_APPS) + self.assertFalse("cms.plugins.teaser" in project.settings.INSTALLED_APPS) + self.assertFalse("cms.plugins.text" in project.settings.INSTALLED_APPS) + self.assertFalse("cms.plugins.twitter" in project.settings.INSTALLED_APPS) + self.assertFalse("cms.plugins.video" in project.settings.INSTALLED_APPS) def test_patch(self): dj_version, dj_match = get_stable_django() cms_stable, cms_match = get_stable_djangocms() - config_data = config.parse(['--db=sqlite://localhost/test.db', - '--lang=en', - '--cms-version=%s' % cms_stable, - '--django-version=%s' % dj_version, - '--timezone=Europe/Moscow', - '-f', '-q', '-u', '-zno', '--i18n=no', - '-p' + self.project_dir, 'example_path_patch']) + config_data = config.parse( + [ + "--db=sqlite://localhost/test.db", + "--lang=en", + "--cms-version=%s" % cms_stable, + "--django-version=%s" % dj_version, + "--timezone=Europe/Moscow", + "-f", + "-q", + "-u", + "-zno", + "--i18n=no", + "-p" + self.project_dir, + "example_path_patch", + ] + ) install.requirements(config_data.requirements) django.create_project(config_data) django.patch_settings(config_data) @@ -358,167 +446,186 @@ def test_patch(self): # settings is importable even in non django environment sys.path.append(config_data.project_directory) - project = __import__(config_data.project_name, globals(), locals(), [str('settings')]) + project = __import__(config_data.project_name, globals(), locals(), ["settings"]) # checking for django options self.assertFalse(project.settings.USE_L10N) self.assertFalse(project.settings.USE_TZ) - self.assertEqual(project.settings.TIME_ZONE, 'Europe/Moscow') - self.assertEqual(project.settings.LANGUAGE_CODE, 'en') - self.assertTrue(project.settings.MEDIA_ROOT, - os.path.join(config_data.project_directory, 'media')) - self.assertEqual(project.settings.MEDIA_URL, '/media/') - # - # checking for standard CMS settings + self.assertEqual(project.settings.TIME_ZONE, "Europe/Moscow") + self.assertEqual(project.settings.LANGUAGE_CODE, "en") self.assertTrue( - 'sekizai.context_processors.sekizai' in - project.settings.TEMPLATES[0]['OPTIONS']['context_processors'] + project.settings.MEDIA_ROOT, os.path.join(config_data.project_directory, "media"), ) + self.assertEqual(project.settings.MEDIA_URL, "/media/") + # + # checking for standard CMS settings self.assertTrue( - 'cms.middleware.toolbar.ToolbarMiddleware' in project.settings.MIDDLEWARE + "sekizai.context_processors.sekizai" in project.settings.TEMPLATES[0]["OPTIONS"]["context_processors"] ) - self.assertTrue(project.settings.CMS_LANGUAGES['default']['redirect_on_fallback']) - self.assertEqual(project.settings.CMS_LANGUAGES[1][0]['code'], 'en') + self.assertTrue("cms.middleware.toolbar.ToolbarMiddleware" in project.settings.MIDDLEWARE) + self.assertTrue(project.settings.CMS_LANGUAGES["default"]["redirect_on_fallback"]) + self.assertEqual(project.settings.CMS_LANGUAGES[1][0]["code"], "en") # checking mptt / treebeard - self.assertFalse('mptt' in project.settings.INSTALLED_APPS) - self.assertTrue('treebeard' in project.settings.INSTALLED_APPS) + self.assertFalse("mptt" in project.settings.INSTALLED_APPS) + self.assertTrue("treebeard" in project.settings.INSTALLED_APPS) # checking for filer (optional) settings - self.assertTrue('filer' in project.settings.INSTALLED_APPS) - self.assertTrue('easy_thumbnails' in project.settings.INSTALLED_APPS) - self.assertTrue('cmsplugin_filer_image' not in project.settings.INSTALLED_APPS) - self.assertTrue('cmsplugin_filer_file' not in project.settings.INSTALLED_APPS) - self.assertTrue('cmsplugin_filer_folder' not in project.settings.INSTALLED_APPS) - self.assertTrue('cmsplugin_filer_link' not in project.settings.INSTALLED_APPS) - self.assertTrue('cmsplugin_filer_teaser' not in project.settings.INSTALLED_APPS) - self.assertTrue('cmsplugin_filer_utils' not in project.settings.INSTALLED_APPS) - self.assertTrue('cmsplugin_filer_video' not in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_text_ckeditor' in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_admin_style' in project.settings.INSTALLED_APPS) - self.assertTrue('filer' in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_file' in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_flash' not in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_googlemap' in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_inherit' not in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_link' in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_picture' in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_style' in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_teaser' not in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_video' in project.settings.INSTALLED_APPS) - self.assertTrue('djangocms_bootstrap4' in project.settings.INSTALLED_APPS) - self.assertTrue(hasattr(project.settings, 'THUMBNAIL_PROCESSORS')) + self.assertTrue("filer" in project.settings.INSTALLED_APPS) + self.assertTrue("easy_thumbnails" in project.settings.INSTALLED_APPS) + self.assertTrue("cmsplugin_filer_image" not in project.settings.INSTALLED_APPS) + self.assertTrue("cmsplugin_filer_file" not in project.settings.INSTALLED_APPS) + self.assertTrue("cmsplugin_filer_folder" not in project.settings.INSTALLED_APPS) + self.assertTrue("cmsplugin_filer_link" not in project.settings.INSTALLED_APPS) + self.assertTrue("cmsplugin_filer_teaser" not in project.settings.INSTALLED_APPS) + self.assertTrue("cmsplugin_filer_utils" not in project.settings.INSTALLED_APPS) + self.assertTrue("cmsplugin_filer_video" not in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_text_ckeditor" in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_admin_style" in project.settings.INSTALLED_APPS) + self.assertTrue("filer" in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_file" in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_flash" not in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_googlemap" in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_inherit" not in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_link" in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_picture" in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_style" in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_teaser" not in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_video" in project.settings.INSTALLED_APPS) + self.assertTrue("djangocms_bootstrap4" in project.settings.INSTALLED_APPS) + self.assertTrue(hasattr(project.settings, "THUMBNAIL_PROCESSORS")) self.assertTrue( - 'cms.context_processors.cms_settings' in - project.settings.TEMPLATES[0]['OPTIONS']['context_processors'] + "cms.context_processors.cms_settings" in project.settings.TEMPLATES[0]["OPTIONS"]["context_processors"] ) self.assertTrue( - 'cms.context_processors.media' not in - project.settings.TEMPLATES[0]['OPTIONS']['context_processors'] + "cms.context_processors.media" not in project.settings.TEMPLATES[0]["OPTIONS"]["context_processors"] ) # basic urlconf check - self.assertTrue('cms.urls' in urlconf) - self.assertTrue('staticfiles_urlpatterns' in urlconf) + self.assertTrue("cms.urls" in urlconf) + self.assertTrue("static(settings.MEDIA_URL" in urlconf) + self.assertTrue("static(settings.STATIC_URL" in urlconf) sys.path.remove(config_data.project_directory) del project - del (sys.modules["%s.settings" % config_data.project_name]) + del sys.modules["%s.settings" % config_data.project_name] def test_database_setup_filer(self): dj_version, dj_match = get_stable_django() cms_stable, cms_match = get_stable_djangocms() - config_data = config.parse(['--db=sqlite://localhost/test.db', - '--cms-version=%s' % cms_stable, - '-f', '-q', '-u', '--django-version=%s' % dj_version, - '-p' + self.project_dir, 'cms_project']) + config_data = config.parse( + [ + "--db=sqlite://localhost/test.db", + "--cms-version=%s" % cms_stable, + "-f", + "-q", + "-u", + "--django-version=%s" % dj_version, + "-p" + self.project_dir, + "cms_project", + ] + ) install.requirements(config_data.requirements) django.create_project(config_data) django.patch_settings(config_data) django.copy_files(config_data) django.setup_database(config_data) - project_db = sqlite3.connect(os.path.join(config_data.project_directory, 'test.db')) + project_db = sqlite3.connect(os.path.join(config_data.project_directory, "test.db")) # Checking content type table to check for correct applications setup - query = project_db.execute( - 'SELECT * FROM django_content_type WHERE app_label="cms" AND model="page"' - ) + query = project_db.execute('SELECT * FROM django_content_type WHERE app_label="cms" AND model="page"') row = query.fetchone() - self.assertTrue('page' in row) - self.assertTrue('cms' in row) + self.assertTrue("page" in row) + self.assertTrue("cms" in row) # No data in CMS tables at setup time, but if query succeed database # schema should be fine - query = project_db.execute('SELECT * FROM cms_page') + query = project_db.execute("SELECT * FROM cms_page") self.assertTrue(query) # No data in auth tables at setup time due to the no-input - query = project_db.execute('SELECT * FROM auth_user') + query = project_db.execute("SELECT * FROM auth_user") self.assertTrue(query) # No data in CMS tables at setup time, but if query succeed database # schema should be fine - query = project_db.execute('SELECT * FROM cms_page') + query = project_db.execute("SELECT * FROM cms_page") self.assertTrue(query) # Check filer data - query = project_db.execute( - 'SELECT * FROM django_content_type WHERE app_label="filer" AND model="image"' - ) + query = project_db.execute('SELECT * FROM django_content_type WHERE app_label="filer" AND model="image"') row = query.fetchone() - self.assertTrue('filer' in row) - self.assertTrue('image' in row) + self.assertTrue("filer" in row) + self.assertTrue("image" in row) def test_starting_page(self): dj_version, dj_match = get_stable_django() cms_stable, cms_match = get_stable_djangocms() - config_data = config.parse(['--db=sqlite://localhost/test.db', - '--cms-version=%s' % cms_stable, - '-q', '-u', '--django-version=%s' % dj_version, - '--starting-page=yes', - '-p' + self.project_dir, 'cms_project']) + config_data = config.parse( + [ + "--db=sqlite://localhost/test.db", + "--cms-version=%s" % cms_stable, + "-q", + "-u", + "--django-version=%s" % dj_version, + "--starting-page=yes", + "-p" + self.project_dir, + "cms_project", + ] + ) install.requirements(config_data.requirements) django.create_project(config_data) django.patch_settings(config_data) django.copy_files(config_data) django.setup_database(config_data) django.load_starting_page(config_data) - project_db = sqlite3.connect(os.path.join(config_data.project_directory, 'test.db')) + project_db = sqlite3.connect(os.path.join(config_data.project_directory, "test.db")) # Check loaded data - query = project_db.execute('SELECT * FROM cms_page') + query = project_db.execute("SELECT * FROM cms_page") row = query.fetchone() - self.assertTrue('fullwidth.html' in row) + self.assertTrue("fullwidth.html" in row) - query = project_db.execute('SELECT * FROM cms_title') + query = project_db.execute("SELECT * FROM cms_title") row = query.fetchone() - self.assertTrue('Home' in row) + self.assertTrue("Home" in row) - query = project_db.execute('SELECT * FROM cms_cmsplugin') + query = project_db.execute("SELECT * FROM cms_cmsplugin") row = query.fetchone() - self.assertTrue('TextPlugin' in row) + self.assertTrue("TextPlugin" in row) def test_force_django(self): dj_version, dj_match = get_stable_django() cms_stable, cms_match = get_stable_djangocms() - config_data = config.parse(['--db=sqlite://localhost/test.db', - '-q', '-u', '--starting-page=yes', - '--cms-version=%s' % cms_stable, '--django=%s' % dj_version, - '-p' + self.project_dir, 'cms_project']) + config_data = config.parse( + [ + "--db=sqlite://localhost/test.db", + "-q", + "-u", + "--starting-page=yes", + "--cms-version=%s" % cms_stable, + "--django=%s" % dj_version, + "-p" + self.project_dir, + "cms_project", + ] + ) install.requirements(config_data.requirements) - install.requirements('django<1.9') + install.requirements("django<1.9") django.create_project(config_data) - with patch('sys.stdout', self.stdout): - with patch('sys.stderr', self.stderr): + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): with self.assertRaises(SystemExit) as error: django.patch_settings(config_data) self.assertEqual(error.exception.code, 9) - self.assertTrue(self.stderr.getvalue().find( - 'Currently installed Django version 1.8.19 differs from the declared %s' % dj_version - ) > -1) + self.assertTrue( + self.stderr.getvalue().find( + "Currently installed Django version 1.8.19 differs from the declared %s" % dj_version + ) + > -1 + ) class TestBaseDjango(unittest.TestCase): @@ -527,11 +634,20 @@ def test_build_settings(self): dj_version, dj_match = get_stable_django() cms_stable, cms_match = get_stable_djangocms() - config_data = config.parse(['--db=postgres://user:pwd@host:5432/dbname', - '--cms-version=%s' % cms_stable, '--django=%s' % dj_version, - '-q', '-p .', 'example_prj']) + config_data = config.parse( + [ + "--db=postgres://user:pwd@host:5432/dbname", + "--cms-version=%s" % cms_stable, + "--django=%s" % dj_version, + "-q", + "-p .", + "example_prj", + ] + ) settings = django._build_settings(config_data) - self.assertTrue(textwrap.dedent(''' + self.assertTrue( + textwrap.dedent( + """ DATABASES = { 'default': { 'CONN_MAX_AGE': 0, @@ -542,5 +658,8 @@ def test_build_settings(self): 'PORT': 5432, 'USER': 'user' } - }''').strip() in settings) - self.assertTrue('X_FRAME_OPTIONS = \'SAMEORIGIN\'' in settings) + }""" + ).strip() + in settings + ) + self.assertTrue("X_FRAME_OPTIONS = 'SAMEORIGIN'" in settings) diff --git a/tests/fixtures/configs/config-30.ini b/tests/fixtures/configs/config-30.ini index 2ffffe31..7e885ef6 100644 --- a/tests/fixtures/configs/config-30.ini +++ b/tests/fixtures/configs/config-30.ini @@ -29,4 +29,3 @@ no-plugins = true verbose = true wizard = false delete-project-dir = false - diff --git a/tests/main.py b/tests/main.py index af794c6b..d1f9160f 100644 --- a/tests/main.py +++ b/tests/main.py @@ -1,15 +1,10 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - import os import subprocess import sys from shutil import rmtree from subprocess import CalledProcessError from tempfile import mkdtemp - -from mock import patch -from six import binary_type +from unittest.mock import patch from djangocms_installer import config, install, main @@ -17,209 +12,271 @@ class TestMain(IsolatedTestClass): - def test_requirements_invocation(self): dj_version, dj_match = get_stable_django(latest=True) - with patch('sys.stdout', self.stdout): - with patch('sys.stderr', self.stderr): - sys.argv = ['main'] + ['--db=sqlite://localhost/test.db', - '-len', '--cms-version=stable', '-R', - '-q', '-u', '-p' + self.project_dir, - 'example_prj'] + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): + sys.argv = ["main"] + [ + "--db=sqlite://localhost/test.db", + "-len", + "--cms-version=stable", + "-R", + "-q", + "-u", + "-p" + self.project_dir, + "example_prj", + ] main.execute() stdout = self.stdout.getvalue() self.assertTrue(stdout.find(dj_match) > -1) - self.assertFalse(stdout.find('django-reversion') > -1) - self.assertTrue(stdout.find('djangocms-text-ckeditor') > -1) - self.assertTrue(stdout.find('djangocms-admin-style') > -1) - self.assertTrue(stdout.find('djangocms-bootstrap4') > -1) - self.assertTrue(stdout.find('djangocms-file') > -1) - self.assertTrue(stdout.find('djangocms-flash') == -1) - self.assertTrue(stdout.find('djangocms-googlemap') > -1) - self.assertTrue(stdout.find('djangocms-inherit') == -1) - self.assertTrue(stdout.find('djangocms-link') > -1) - self.assertTrue(stdout.find('djangocms-picture') > -1) - self.assertTrue(stdout.find('djangocms-style') > -1) - self.assertTrue(stdout.find('djangocms-snippet') > -1) - self.assertTrue(stdout.find('cmsplugin-filer') == -1) - self.assertTrue(stdout.find('djangocms-teaser') == -1) - self.assertTrue(stdout.find('djangocms-video') > -1) + self.assertFalse(stdout.find("django-reversion") > -1) + self.assertTrue(stdout.find("djangocms-text-ckeditor") > -1) + self.assertTrue(stdout.find("djangocms-admin-style") > -1) + self.assertTrue(stdout.find("djangocms-bootstrap4") > -1) + self.assertTrue(stdout.find("djangocms-file") > -1) + self.assertTrue(stdout.find("djangocms-flash") == -1) + self.assertTrue(stdout.find("djangocms-googlemap") > -1) + self.assertTrue(stdout.find("djangocms-inherit") == -1) + self.assertTrue(stdout.find("djangocms-link") > -1) + self.assertTrue(stdout.find("djangocms-picture") > -1) + self.assertTrue(stdout.find("djangocms-style") > -1) + self.assertTrue(stdout.find("djangocms-snippet") > -1) + self.assertTrue(stdout.find("cmsplugin-filer") == -1) + self.assertTrue(stdout.find("djangocms-teaser") == -1) + self.assertTrue(stdout.find("djangocms-video") > -1) def cleanup_ask(self): dj_version, dj_match = get_stable_django() - with patch('sys.stdout', self.stdout): - with patch('sys.stderr', self.stderr): - conf_data = config.parse([ - '-q', - '--db=postgres://user:pwd@host/dbname', - '--i18n=no', - '--django-version=%s' % dj_version, - '-f', - '-p'+self.project_dir, - 'example_prj']) + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): + conf_data = config.parse( + [ + "-q", + "--db=postgres://user:pwd@host/dbname", + "--i18n=no", + "--django-version=%s" % dj_version, + "-f", + "-p" + self.project_dir, + "example_prj", + ] + ) install.cleanup_directory(conf_data) self.assertFalse(os.path.exists(self.project_dir)) def cleanup_skip(self): dj_version, dj_match = get_stable_django() - with patch('sys.stdout', self.stdout): - with patch('sys.stderr', self.stderr): - conf_data = config.parse([ - '-q', - '-s', - '--db=postgres://user:pwd@host/dbname', - '--i18n=no', - '--django-version=%s' % dj_version, - '-f', - '-p'+self.project_dir, - 'example_prj']) + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): + conf_data = config.parse( + [ + "-q", + "-s", + "--db=postgres://user:pwd@host/dbname", + "--i18n=no", + "--django-version=%s" % dj_version, + "-f", + "-p" + self.project_dir, + "example_prj", + ] + ) install.cleanup_directory(conf_data) self.assertTrue(os.path.exists(self.project_dir)) def test_main_invocation(self): dj_version, dj_match = get_stable_django() base_dir = mkdtemp() - project_dir = os.path.join(base_dir, 'example_prj') + project_dir = os.path.join(base_dir, "example_prj") original_dir = os.getcwd() os.chdir(base_dir) - with patch('sys.stdout', self.stdout): - with patch('sys.stderr', self.stderr): - sys.argv = ['main'] + ['--db=sqlite://localhost/test.db', - '-len', '--cms-version=stable', '--django=%s' % dj_version, - '-q', '-u', '--verbose', - 'example_prj'] + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): + sys.argv = ["main"] + [ + "--db=sqlite://localhost/test.db", + "-len", + "--cms-version=stable", + "--django=%s" % dj_version, + "-q", + "-u", + "--verbose", + "example_prj", + ] main.execute() - self.assertTrue(os.path.exists(os.path.join(project_dir, 'static'))) - self.assertTrue(os.path.exists(os.path.join(project_dir, 'requirements.txt'))) - self.assertTrue(os.path.exists(os.path.join(project_dir, 'example_prj', 'static'))) - with open(os.path.join(project_dir, 'requirements.txt'), 'r') as req_file: + self.assertTrue(os.path.exists(os.path.join(project_dir, "static"))) + self.assertTrue(os.path.exists(os.path.join(project_dir, "requirements.txt"))) + self.assertTrue(os.path.exists(os.path.join(project_dir, "example_prj", "static"))) + with open(os.path.join(project_dir, "requirements.txt")) as req_file: text = req_file.read() - self.assertTrue(text.find('djangocms-text-ckeditor') > -1) + self.assertTrue(text.find("djangocms-text-ckeditor") > -1) # Checking we successfully completed the whole process - self.assertTrue('Successfully installed ' in self.stdout.getvalue()) - self.assertTrue(('Get into "%s" directory and type "python manage.py runserver" to start your project' % project_dir) in self.stdout.getvalue()) + self.assertTrue("Successfully installed " in self.stdout.getvalue()) + self.assertTrue( + ( + 'Get into "%s" directory and type "python manage.py runserver" to start your project' + % project_dir + ) + in self.stdout.getvalue() + ) os.chdir(original_dir) rmtree(base_dir) def test_base_invocation(self): base_dir = mkdtemp() - project_dir = os.path.join(base_dir, 'example_prj') + project_dir = os.path.join(base_dir, "example_prj") original_dir = os.getcwd() os.chdir(base_dir) - with patch('sys.stdout', self.stdout): - with patch('sys.stderr', self.stderr): - sys.argv = ['main'] + ['--cms-version=stable', 'example_prj'] + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): + sys.argv = ["main"] + ["--cms-version=stable", "example_prj"] main.execute() - self.assertTrue(os.path.exists(os.path.join(project_dir, 'static'))) - self.assertTrue(os.path.exists(os.path.join(project_dir, 'requirements.txt'))) - self.assertTrue(os.path.exists(os.path.join(project_dir, 'example_prj', 'static'))) - with open(os.path.join(project_dir, 'requirements.txt'), 'r') as req_file: + self.assertTrue(os.path.exists(os.path.join(project_dir, "static"))) + self.assertTrue(os.path.exists(os.path.join(project_dir, "requirements.txt"))) + self.assertTrue(os.path.exists(os.path.join(project_dir, "example_prj", "static"))) + with open(os.path.join(project_dir, "requirements.txt")) as req_file: text = req_file.read() - self.assertTrue(text.find('djangocms-text-ckeditor') > -1) - self.assertTrue(('Get into "%s" directory and type "python manage.py runserver" to start your project' % project_dir) in self.stdout.getvalue()) + self.assertTrue(text.find("djangocms-text-ckeditor") > -1) + self.assertTrue( + ( + 'Get into "%s" directory and type "python manage.py runserver" to start your project' + % project_dir + ) + in self.stdout.getvalue() + ) os.chdir(project_dir) - with patch('sys.stdout', self.stdout): - out = subprocess.check_output(['sqlite3', 'project.db', 'SELECT COUNT(*) FROM auth_user WHERE username="admin"']) - self.assertEqual(binary_type(out), binary_type(b'1\n')) + with patch("sys.stdout", self.stdout): + out = subprocess.check_output( + ["sqlite3", "project.db", 'SELECT COUNT(*) FROM auth_user WHERE username="admin"'] + ) + self.assertEqual(bytes(out), bytes(b"1\n")) os.chdir(original_dir) rmtree(base_dir) def test_two_langs_invocation(self): dj_version, dj_match = get_stable_django() - with patch('sys.stdout', self.stdout): - with patch('sys.stderr', self.stderr): - sys.argv = ['main'] + ['--db=sqlite://localhost/test.db', - '-len-GB', '-lfr-fr', '--cms-version=stable', '--verbose', - '--django=%s' % dj_version, - '-q', '-u', '-p' + self.project_dir, - 'example_prj'] + + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): + sys.argv = ["main"] + [ + "--db=sqlite://localhost/test.db", + "-len-GB", + "-lfr-fr", + "--cms-version=stable", + "--verbose", + "--django=%s" % dj_version, + "-q", + "-u", + "-p" + self.project_dir, + "example_prj", + ] try: main.execute() # Checking we successfully completed the whole process - self.assertTrue(('Get into "%s" directory and type "python manage.py runserver" to start your project' % self.project_dir) in self.stdout.getvalue()) + self.assertTrue( + ( + 'Get into "%s" directory and type "python manage.py runserver" to start your project' + % self.project_dir + ) + in self.stdout.getvalue() + ) except Exception as e: print(e) def test_develop(self): dj_version, dj_match = get_stable_django(lts=True) - with patch('sys.stdout', self.stdout): - with patch('sys.stderr', self.stderr): - sys.argv = ['main'] + ['--db=sqlite://localhost/test.db', - '-len', '--cms-version=develop', '--django=%s' % dj_version, - '-q', '-u', '-p'+self.project_dir, - 'example_prj'] + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): + sys.argv = ["main"] + [ + "--db=sqlite://localhost/test.db", + "-len", + "--cms-version=develop", + "--django=%s" % dj_version, + "-q", + "-u", + "-p" + self.project_dir, + "example_prj", + ] main.execute() # Checking we successfully completed the whole process - self.assertTrue(('Get into "%s" directory and type "python manage.py runserver" to start your project' % self.project_dir) in self.stdout.getvalue()) + self.assertTrue( + ( + 'Get into "%s" directory and type "python manage.py runserver" to start your project' + % self.project_dir + ) + in self.stdout.getvalue() + ) def test_cleanup(self): - with patch('sys.stdout', self.stdout): - with patch('sys.stderr', self.stderr): + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): with self.assertRaises((CalledProcessError, EnvironmentError)): - sys.argv = ['main'] + ['--db=postgres://user:pwd@host/dbname', - '-len', '--no-db-driver', '-c', - '-q', '-u', '-p'+self.project_dir, - 'example_prj'] + sys.argv = ["main"] + [ + "--db=postgres://user:pwd@host/dbname", + "-len", + "--no-db-driver", + "-c", + "-q", + "-u", + "-p" + self.project_dir, + "example_prj", + ] main.execute() self.assertFalse(os.path.exists(self.project_dir)) def test_no_cleanup(self): - with patch('sys.stdout', self.stdout): - with patch('sys.stderr', self.stderr): + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): with self.assertRaises((CalledProcessError, EnvironmentError)): - sys.argv = ['main'] + ['--db=postgres://user:pwd@host/dbname', - '-len', '--no-db-driver', - '-q', '-u', '-p' + self.project_dir, - 'example_prj'] + sys.argv = ["main"] + [ + "--db=postgres://user:pwd@host/dbname", + "-len", + "--no-db-driver", + "-q", + "-u", + "-p" + self.project_dir, + "example_prj", + ] main.execute() self.assertTrue(os.path.exists(self.project_dir)) def test_i18n_urls(self): base_dir = mkdtemp() - project_dir = os.path.join(base_dir, 'example_prj') + project_dir = os.path.join(base_dir, "example_prj") original_dir = os.getcwd() os.chdir(base_dir) - with patch('sys.stdout', self.stdout): - with patch('sys.stderr', self.stderr): - sys.argv = ['main'] + ['--i18n=yes', '--cms-version=stable', 'example_prj'] + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): + sys.argv = ["main"] + [ + "--i18n=yes", + "--cms-version=stable", + "example_prj", + ] main.execute() - self.assertTrue( - os.path.exists( - os.path.join(project_dir, 'example_prj', 'urls.py') - ) - ) - with open(os.path.join(project_dir, 'example_prj', 'urls.py'), - 'r') as urls_file: + self.assertTrue(os.path.exists(os.path.join(project_dir, "example_prj", "urls.py"))) + with open(os.path.join(project_dir, "example_prj", "urls.py")) as urls_file: urls = urls_file.read() - self.assertTrue( - urls.find('urlpatterns += i18n_patterns(') > -1 - ) + self.assertTrue(urls.find("urlpatterns += i18n_patterns(") > -1) os.chdir(original_dir) rmtree(base_dir) def test_noi18n_urls(self): base_dir = mkdtemp() - project_dir = os.path.join(base_dir, 'example_prj') + project_dir = os.path.join(base_dir, "example_prj") original_dir = os.getcwd() os.chdir(base_dir) - with patch('sys.stdout', self.stdout): - with patch('sys.stderr', self.stderr): - sys.argv = ['main'] + ['--i18n=no', '--cms-version=stable', 'example_prj'] + with patch("sys.stdout", self.stdout): + with patch("sys.stderr", self.stderr): + sys.argv = ["main"] + [ + "--i18n=no", + "--cms-version=stable", + "example_prj", + ] main.execute() - self.assertTrue( - os.path.exists( - os.path.join(project_dir, 'example_prj', 'urls.py') - ) - ) - with open(os.path.join(project_dir, 'example_prj', 'urls.py'), - 'r') as urls_file: + self.assertTrue(os.path.exists(os.path.join(project_dir, "example_prj", "urls.py"))) + with open(os.path.join(project_dir, "example_prj", "urls.py")) as urls_file: urls = urls_file.read() - self.assertTrue( - urls.find('urlpatterns += i18n_patterns(') == -1 - ) + self.assertTrue(urls.find("urlpatterns += i18n_patterns(") == -1) os.chdir(original_dir) rmtree(base_dir) diff --git a/tox.ini b/tox.ini index 2eeeb38e..2b3b75ec 100644 --- a/tox.ini +++ b/tox.ini @@ -1,12 +1,24 @@ [tox] -downloadcache = {toxworkdir}/cache -envlist = pep8,isort,docs,py{38,37,36,35} +envlist = + black + blacken + docs + isort + isort_format + pep8 + pypi-description + towncrier + py{38,37,36,35} passenv = LANG +skip_missing_interpreters = True [testenv] commands = {env:COMMAND:python} setup.py test deps = -r{toxinidir}/requirements-test.txt +passenv = + COMMAND + PYTEST_* recreate = True setenv = LANGUAGE = en_US.UTF-8 @@ -16,37 +28,139 @@ setenv = commands = coverage run setup.py test coverage report -m +recreate = False [testenv:pep8] -commands = flake8 -deps = flake8 +commands = + {envpython} -m flake8 + {envpython} -minterrogate -c pyproject.toml djangocms_installer tests +deps = + interrogate + flake8 + flake8-broken-line + flake8-bugbear + flake8-builtins + flake8-coding + flake8-commas + flake8-comprehensions + flake8-eradicate + flake8-quotes + flake8-tidy-imports + pep8-naming +recreate = False skip_install = true [testenv:isort] -commands = isort -c -rc -df -deps = isort +commands = + {envpython} -m isort -c --df djangocms_installer tests +deps = isort>5,<5.1 +recreate = False +skip_install = true + +[testenv:isort_format] +commands = + {envpython} -m isort djangocms_installer tests +deps = {[testenv:isort]deps} +recreate = False +skip_install = true + +[testenv:black] +commands = + {envpython} -m black --check --diff . +deps = black +recreate = False +skip_install = true + +[testenv:blacken] +commands = + {envpython} -m black . +deps = {[testenv:black]deps} +recreate = False skip_install = true [testenv:docs] -changedir = docs -commands= - sphinx-build -W -b html -d {envtmpdir}/doctrees . {toxinidir}/docs/_build/html +commands = + {envpython} -m invoke docbuild deps = + invoke sphinx sphinx-rtd-theme + sphinx-autobuild + livereload~=2.6 -rrequirements-test.txt skip_install = true +[testenv:towncrier] +commands = + {envpython} -m invoke towncrier-check +deps = + invoke +recreate = False +skip_install = true + +[testenv:pypi-description] +commands = + {envpython} -m invoke clean + {envpython} -m check_manifest + {envpython} -m pep517.build . + {envpython} -m twine check dist/* +deps = + invoke + check-manifest + pep517 + twine +recreate = False +skip_install = true + +[testenv:release] +commands = + {envpython} -m invoke clean + {envpython} -m check_manifest + {envpython} -m pep517.build . + {envpython} -m twine upload {posargs} dist/* +deps = {[testenv:pypi-description]deps} +passenv = + TWINE_* +recreate = False +skip_install = true + +[flake8] +exclude = *.egg-info,.git,.settings,.tox,build,dist,docs,requirements,tmp,*migrations*,tests,data +ignore = E800, W503, C812, C813, C815, C818, C819, C408 +max-line-length = 119 +# flake8-quotes +inline-quotes = double +# flake8-coding +no-accept-encodings = True +# flake8-tidy-imports +banned-modules = __future__ = this project supports python3 only + [isort] -line_length = 99 -skip = migrations, south_migrations combine_as_imports = true default_section = THIRDPARTY +force_grid_wrap = 0 include_trailing_comma = true known_first_party = djangocms_installer -multi_line_output = 5 -not_skip = __init__.py +line_length = 119 +multi_line_output = 3 +skip = data, .tox +use_parentheses = True -[flake8] -exclude = *.egg-info,.git,.settings,.tox,build,dist,docs,requirements,tmp,*migrations*,*south_migrations*,tests,data,.eggs -max-line-length = 99 +[check-manifest] +ignore = + .* + *.ini + *.toml + *.json + *.sample + *.txt + *.yml + *.yaml + .tx/** + changes/** + docs/** + tasks.py + tests/** + *.mo +ignore-bad-ideas = + *.mo