From c5bb3cd2db8c6d30204e54bc5dde74eaf85dfb53 Mon Sep 17 00:00:00 2001 From: Iacopo Spalletti Date: Sat, 16 May 2020 21:57:59 +0200 Subject: [PATCH] Update tooling (#568) * Move package metadata to setup.cfg * Port to github actions * Add towncrier * Add bumpversion * Add pre-commit * Add github issues / PR templates * Improve contributing documentation * Reformat code --- .codeclimate.yml | 1 - .coveragerc | 2 +- .editorconfig | 10 +- .github/ISSUE_TEMPLATE/---bug-report.md | 48 + .github/ISSUE_TEMPLATE/---feature-request.md | 42 + .github/pull_request_template.md | 18 + .github/workflows/publish.yml | 38 + .github/workflows/test.yml | 94 ++ .gitignore | 525 ++++++++++- .gitlab-ci.yml | 5 - .pre-commit-config.yaml | 44 + .travis.yml | 62 -- AUTHORS.rst | 1 + CONTRIBUTING.rst | 115 ++- HISTORY.rst | 130 +-- LICENSE | 2 +- Makefile | 51 -- README.rst | 8 +- aldryn_config.py | 3 +- changes/.directory | 0 changes/546.feature | 1 + changes/564.feature | 1 + changes/567.feature | 1 + cms_helper.py | 157 ++-- djangocms_blog/__init__.py | 9 +- djangocms_blog/admin.py | 401 ++++----- djangocms_blog/apps.py | 7 +- djangocms_blog/cms_appconfig.py | 143 ++- djangocms_blog/cms_apps.py | 27 +- djangocms_blog/cms_menus.py | 70 +- djangocms_blog/cms_plugins.py | 133 +-- djangocms_blog/cms_toolbars.py | 73 +- djangocms_blog/cms_wizards.py | 73 +- djangocms_blog/feeds.py | 138 ++- djangocms_blog/fields.py | 3 +- djangocms_blog/forms.py | 123 ++- djangocms_blog/liveblog/__init__.py | 3 +- djangocms_blog/liveblog/apps.py | 7 +- djangocms_blog/liveblog/cms_plugins.py | 19 +- djangocms_blog/liveblog/consumers.py | 14 +- .../liveblog/migrations/0001_initial.py | 60 +- .../migrations/0002_liveblog_title.py | 11 +- .../migrations/0003_auto_20160917_0123.py | 25 +- djangocms_blog/liveblog/models.py | 69 +- djangocms_blog/liveblog/routing.py | 6 +- .../liveblog/static/liveblog/js/liveblog.js | 1 - .../locale/ar/LC_MESSAGES/django.po | 2 +- .../locale/de/LC_MESSAGES/django.po | 2 +- .../locale/es/LC_MESSAGES/django.po | 2 +- .../locale/et/LC_MESSAGES/django.po | 2 +- .../locale/fr/LC_MESSAGES/django.po | 2 +- .../locale/it/LC_MESSAGES/django.po | 2 +- .../locale/lt/LC_MESSAGES/django.po | 2 +- .../locale/nb_NO/LC_MESSAGES/django.po | 2 +- .../locale/nl/LC_MESSAGES/django.po | 2 +- .../locale/pl_PL/LC_MESSAGES/django.po | 2 +- .../locale/pt_BR/LC_MESSAGES/django.po | 2 +- .../locale/ru/LC_MESSAGES/django.po | 2 +- .../locale/sl/LC_MESSAGES/django.po | 2 +- .../locale/tr/LC_MESSAGES/django.po | 2 +- djangocms_blog/managers.py | 85 +- djangocms_blog/media/__init__.py | 1 - djangocms_blog/media/base.py | 30 +- djangocms_blog/migrations/0001_initial.py | 299 ++++-- djangocms_blog/migrations/0002_post_sites.py | 21 +- .../migrations/0003_auto_20141201_2252.py | 19 +- .../migrations/0004_auto_20150108_1435.py | 52 +- .../migrations/0005_auto_20150212_1118.py | 21 +- .../migrations/0006_auto_20150214_1907.py | 13 +- .../migrations/0007_auto_20150719_0933.py | 206 +++-- .../migrations/0008_auto_20150814_0831.py | 13 +- .../0009_latestpostsplugin_tags_new.py | 52 +- .../migrations/0010_auto_20150923_1151.py | 157 ++-- .../migrations/0011_auto_20151024_1809.py | 88 +- .../migrations/0012_auto_20151220_1734.py | 8 +- .../migrations/0013_auto_20160201_2235.py | 12 +- .../migrations/0014_auto_20160215_1331.py | 28 +- .../migrations/0015_auto_20160408_1849.py | 10 +- .../migrations/0016_auto_20160502_1741.py | 17 +- .../migrations/0017_thumbnail_move.py | 8 +- .../migrations/0018_thumbnail_move2.py | 44 +- .../migrations/0019_thumbnail_move3.py | 18 +- .../migrations/0020_thumbnail_move4.py | 34 +- .../migrations/0021_auto_20160823_2008.py | 76 +- .../migrations/0021_post_liveblog.py | 17 +- .../migrations/0022_auto_20160605_2305.py | 12 +- .../migrations/0022_auto_20170304_1040.py | 19 +- .../migrations/0023_auto_20160626_1539.py | 28 +- .../migrations/0024_auto_20160706_1524.py | 43 +- .../migrations/0025_auto_20160803_0858.py | 19 +- djangocms_blog/migrations/0026_merge.py | 9 +- .../migrations/0027_post_date_featured.py | 10 +- .../migrations/0028_auto_20170304_1040.py | 19 +- .../migrations/0029_post_related.py | 10 +- .../migrations/0030_auto_20170509_1831.py | 12 +- .../migrations/0031_auto_20170610_1744.py | 14 +- .../migrations/0032_auto_20180109_0023.py | 46 +- .../migrations/0033_auto_20180226_1410.py | 11 +- djangocms_blog/migrations/0034_merge.py | 10 +- .../0035_posttranslation_subtitle.py | 10 +- .../migrations/0036_auto_20180913_1809.py | 10 +- .../migrations/0037_auto_20190806_0743.py | 78 +- djangocms_blog/migrations/0038_post_media.py | 21 +- .../migrations/0039_auto_20200331_2227.py | 24 +- djangocms_blog/models.py | 464 +++++----- djangocms_blog/search_indexes.py | 31 +- djangocms_blog/settings.py | 249 +++-- djangocms_blog/sitemaps/__init__.py | 8 +- .../css/djangocms_blog_admin.css | 2 +- djangocms_blog/taggit_urls.py | 3 +- .../djangocms_blog/plugins/archive.html | 2 +- .../plugins/latest_entries.html | 2 +- .../djangocms_blog/plugins/tags.html | 2 +- .../djangocms_blog/post_archive.html | 1 - djangocms_blog/templatetags/__init__.py | 1 - djangocms_blog/templatetags/djangocms_blog.py | 13 +- djangocms_blog/urls.py | 42 +- djangocms_blog/views.py | 142 ++- docs/conf.py | 180 ++-- docs/contributing.rst | 2 +- docs/features/media.rst | 1 - docs/index.rst | 1 - pyproject.toml | 14 + requirements-test.txt | 12 +- setup.cfg | 105 ++- setup.py | 66 +- tasks.py | 124 +++ tests/__init__.py | 1 - tests/base.py | 254 +++--- tests/media_app/__init__.py | 1 - tests/media_app/cms_plugins.py | 13 +- tests/media_app/migrations/0001_initial.py | 53 +- tests/media_app/models.py | 39 +- tests/test_indexing.py | 24 +- tests/test_liveblog.py | 101 +-- tests/test_media.py | 63 +- tests/test_menu.py | 112 +-- tests/test_models.py | 848 ++++++++---------- tests/test_plugins.py | 269 +++--- tests/test_setup.py | 21 +- tests/test_toolbar.py | 22 +- tests/test_utils/__init__.py | 1 - tests/test_utils/admin.py | 13 +- tests/test_utils/blog_urls.py | 40 +- tests/test_utils/migrations/0001_initial.py | 104 ++- tests/test_utils/models.py | 3 +- tests/test_utils/routing.py | 17 +- tests/test_utils/urls.py | 32 +- tests/test_views.py | 350 ++++---- tests/test_wizards.py | 147 +-- tox.ini | 136 ++- 151 files changed, 4841 insertions(+), 3826 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/---bug-report.md create mode 100644 .github/ISSUE_TEMPLATE/---feature-request.md create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/publish.yml create mode 100644 .github/workflows/test.yml delete mode 100644 .gitlab-ci.yml create mode 100644 .pre-commit-config.yaml delete mode 100644 .travis.yml delete mode 100644 Makefile create mode 100644 changes/.directory create mode 100644 changes/546.feature create mode 100644 changes/564.feature create mode 100644 changes/567.feature mode change 100755 => 100644 djangocms_blog/admin.py create mode 100644 pyproject.toml create mode 100644 tasks.py diff --git a/.codeclimate.yml b/.codeclimate.yml index 8175fbf4..f58837e4 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -5,5 +5,4 @@ languages: Python: true exclude_paths: - 'djangocms_blog/migrations/*' - - 'djangocms_blog/south_migrations/*' - 'tests/*' diff --git a/.coveragerc b/.coveragerc index a4430137..385d795f 100644 --- a/.coveragerc +++ b/.coveragerc @@ -3,7 +3,7 @@ branch = True source = djangocms_blog [report] -omit = ../*migrations*,../*tests*,../*compat.* +omit = *migrations*,*tests*,*test_utils* # Regexes for lines to exclude from consideration exclude_lines = # Have to re-enable the standard pragma 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..0b53690a --- /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..63c17532 --- /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://django-app-helper.readthedocs.io/en/latest/contributing.html) +* [ ] Code lint checked via `inv lint` +* [ ] ``changes`` file included (see [docs](https://django-app-helper.readthedocs.io/en/latest/contributing.html#pull-request-guidelines)) +* [ ] Usage documentation added in case of new features +* [ ] Tests added 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..314e13c0 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,94 @@ +name: Linting - Tests + +on: [push] + +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 + - 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 }} + + 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] + django: [30, 22] + cms: [37] + exclude: + - python-version: 3.5 + django: 30 + 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.toxenv }} + restore-keys: | + ${{ runner.os }}-pip-${{ matrix.toxenv }} + - name: Cache tox + uses: actions/cache@v1 + with: + path: .tox + key: ${{ runner.os }}-tox-${{ format('{{py{0}-django{1}-cms{2}}}', matrix.python-version, matrix.django, matrix.cms) }}-${{ hashFiles('setup.cfg') }} + restore-keys: | + ${{ runner.os }}-tox-${{ format('{{py{0}-django{1}-cms{2}}}', matrix.python-version, matrix.django, matrix.cms) }}- + - name: Install dependencies + run: | + sudo apt-get install gettext + python -m pip install --upgrade pip tox>=3.5 + - name: Test with tox + env: + TOX_ENV: ${{ format('py{0}-django{1}-cms{2}', matrix.python-version, matrix.django, matrix.cms) }} + COMMAND: coverage run + COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} + 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 + services: + redis: + image: redis + ports: + - 6379:6379 diff --git a/.gitignore b/.gitignore index c915ae70..0137a63e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,49 +1,524 @@ + +# Created by https://www.gitignore.io/api/vim,node,sass,vuejs,linux,macos,django,python,pycharm,windows,virtualenv,sublimetext,visualstudiocode +# Edit at https://www.gitignore.io/?templates=vim,node,sass,vuejs,linux,macos,django,python,pycharm,windows,virtualenv,sublimetext,visualstudiocode + +### Django ### +*.log +*.pot +*.pyc +__pycache__/ +local_settings.py +db.sqlite3 +db.sqlite3-journal +media + +# If your build process includes running collectstatic, then you probably don't need or want to include staticfiles/ +# in your Git repository. Update and uncomment the following line accordingly. +# /staticfiles/ + +### Django.Python Stack ### +# Byte-compiled / optimized / DLL files *.py[cod] +*$py.class # C extensions *.so -# Packages -*.egg -*.egg-info -dist -build -eggs -parts -bin -var -sdist -develop-eggs +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ .installed.cfg -lib -lib64 +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec # Installer logs pip-log.txt +pip-delete-this-directory.txt # Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ .coverage -.tox +.coverage.* +.cache nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject # Mr Developer .mr.developer.cfg .project .pydevproject -# Complexity -output/*.html -output/*/index.html +# mkdocs documentation +/site -# Sphinx -docs/build +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json -*.lokalize -lokalize* - -.idea -docs/_build +# Pyre type checker +.pyre/ +### Linux ### *~ -*.db + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Node ### +# Logs +logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test + +# parcel-bundler cache (https://parceljs.org/) + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# rollup.js default build output + +# Uncomment the public line if your project uses Gatsby +# https://nextjs.org/blog/next-9-1#public-directory-support +# https://create-react-app.dev/docs/using-the-public-folder/#docsNav +# public + +# Storybook build outputs +.out +.storybook-out + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# Temporary folders +tmp/ +temp/ + +### PyCharm ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### PyCharm Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +.idea/**/sonarlint/ + +# SonarQube Plugin +.idea/**/sonarIssues.xml + +# Markdown Navigator plugin +.idea/**/markdown-navigator.xml +.idea/**/markdown-navigator/ + +### Python ### +# Byte-compiled / optimized / DLL files + +# C extensions + +# Distribution / packaging + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. + +# Installer logs + +# Unit test / coverage reports + +# Translations + +# Scrapy stuff: + +# Sphinx documentation + +# PyBuilder + +# pyenv + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. + +# celery beat schedule file + +# SageMath parsed files + +# Spyder project settings + +# Rope project settings + +# Mr Developer + +# mkdocs documentation + +# mypy + +# Pyre type checker + +### Sass ### +.sass-cache/ +*.css.map +*.sass.map +*.scss.map + +### SublimeText ### +# Cache files for Sublime Text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# Workspace files are user-specific +*.sublime-workspace + +# Project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using Sublime Text +# *.sublime-project + +# SFTP configuration file +sftp-config.json + +# Package control specific files +Package Control.last-run +Package Control.ca-list +Package Control.ca-bundle +Package Control.system-ca-bundle +Package Control.cache/ +Package Control.ca-certs/ +Package Control.merged-ca-bundle +Package Control.user-ca-bundle +oscrypto-ca-bundle.crt +bh_unicode_properties.cache + +# Sublime-github package stores a github token in this file +# https://packagecontrol.io/packages/sublime-github +GitHub.sublime-settings + +### Vim ### +# Swap +[._]*.s[a-v][a-z] +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim +Sessionx.vim + +# Temporary +.netrwhist + +# Auto-generated tag files +tags + +# Persistent undo +[._]*.un~ + +# Coc configuration directory +.vim + +### VirtualEnv ### +# Virtualenv +# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ +pyvenv.cfg +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +pip-selfcheck.json + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history + +### Vuejs ### +# Recommended template: Node.gitignore + +npm-debug.log +yarn-error.log + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.gitignore.io/api/vim,node,sass,vuejs,linux,macos,django,python,pycharm,windows,virtualenv,sublimetext,visualstudiocode + + *.sqlite +data diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index efbafceb..00000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,5 +0,0 @@ -# This file is generated by GitLab CI -ci: - script: - - COMMAND="coverage run" tox -epep8,isort,py27-django111-cms34,py36-django111-cms35 - - if [[ $? -eq 0 ]]; then coverage report; fi diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..0c40b3ed --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,44 @@ +# 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: v2.5.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: '4.3.21' + hooks: + - id: isort + - repo: https://github.com/psf/black + rev: 19.10b0 + hooks: + - id: black + - repo: https://gitlab.com/pycqa/flake8 + rev: 3.8.0a2 + hooks: + - id: flake8 + - repo: https://github.com/asottile/pyupgrade + rev: v2.2.1 + 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/.travis.yml b/.travis.yml deleted file mode 100644 index bdc1afa9..00000000 --- a/.travis.yml +++ /dev/null @@ -1,62 +0,0 @@ -language: python -dist: xenial - -python: - - 3.8 - - 3.7 - - 3.6 - - 3.5 - -env: - matrix: - - TOXENV='pep8' - - TOXENV='isort' - - TOXENV='docs' - - DJANGO='django30' CMS='cms37' - - DJANGO='django22' CMS='cms37' - -services: - - redis-server - -install: - - "if [[ $TRAVIS_PYTHON_VERSION == '3.5' ]]; then export PYVER=py35; fi" - - "if [[ $TRAVIS_PYTHON_VERSION == '3.6' ]]; then export PYVER=py36; fi" - - "if [[ $TRAVIS_PYTHON_VERSION == '3.7' ]]; then export PYVER=py37; fi" - - "if [[ $TRAVIS_PYTHON_VERSION == '3.8' ]]; then export PYVER=py38; fi" - - "if [[ ${DJANGO}z != 'z' ]]; then export TOXENV=$PYVER-$DJANGO-$CMS; fi" - -script: COMMAND='coverage run' tox -e$TOXENV -- --verbose=2 - -before_install: - - pip install -U setuptools tox>=1.8 coveralls codecov wheel pip -after_success: - - codecov - - coveralls - -matrix: - exclude: - - python: 3.5 - env: DJANGO='django30' CMS='cms37' - - python: 3.5 - env: TOXENV='docs' - - python: 3.5 - env: TOXENV='pep8' - - python: 3.5 - env: TOXENV='isort' - - python: 3.6 - env: TOXENV='docs' - - python: 3.6 - env: TOXENV='pep8' - - python: 3.6 - env: TOXENV='isort' - - python: 3.7 - env: TOXENV='docs' - - python: 3.7 - env: TOXENV='pep8' - - python: 3.7 - env: TOXENV='isort' - - -cache: pip - - diff --git a/AUTHORS.rst b/AUTHORS.rst index a1a32d58..c1072922 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -24,6 +24,7 @@ Contributors * Felipe Farias * frnhr * furiousdave +* G3RB3N * Georgiy Kutsurua * German Ilyin * Jens Diemer diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 4fc4e880..6fde2cbd 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -1,13 +1,12 @@ -============ +############ Contributing -============ +############ Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given. You can contribute in many ways: -********************** Types of Contributions ********************** @@ -34,15 +33,6 @@ Implement Features Look through the GitHub issues for features. Anything tagged with "feature" is open to whoever wants to implement it. -Branching model -~~~~~~~~~~~~~~~ - -When planning a code cotnribution, these is the project branching model: - -* new features goes to develop -* bugfixes for releases goes to release/Y.Z.x branches -* master is just a snapshot of the latest stable release and should not be targeted - Write Documentation =================== @@ -66,18 +56,20 @@ If you are proposing a feature: Get Started! ************ -Ready to contribute? Here's how to set up `djangocms-blog` for local development. +Ready to contribute? Here's how to set up ``djangocms-blog`` for local development. -1. Fork the `djangocms-blog` repo on GitHub. +1. Fork the ``djangocms-blog`` repo on GitHub. 2. Clone your fork locally:: $ git clone git@github.com:your_name_here/djangocms-blog.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-blog $ cd djangocms-blog/ - $ python setup.py develop + $ pip install -r requirements-test.txt + $ pip install -e . 4. Create a branch for local development:: @@ -90,7 +82,7 @@ tests, including testing other Python versions with tox:: $ tox -To get tox, just pip install them into your virtualenv. +To get tox, pip install it into your virtualenv. 6. Commit your changes and push your branch to GitHub:: @@ -100,25 +92,80 @@ To get tox, just pip install them into your virtualenv. 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. -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.7, 3.4, 3.5 and 3.6. Check - https://travis-ci.org/nephila/djangocms-blog/pull_requests - and make sure that the tests pass for all supported Python versions. +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``. -**** -Tips -**** +From now on every commit will be checked against our code style. -To run a subset of tests:: +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. - $ pip install -r requirements-test.txt - $ python cms_helper.py test tests.test_views +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. + +As the project uses `pytest `_ as test runner, you can pass any pytest option by setting the +``PYTEST_ARGS`` environment variable, usually by prepending to the ``tox`` command. Example:: + + PYTEST_ARGS=" -s tests/test_plugins.py::PluginTest -p no:warnings" tox -epy3.7-django30-cms37 + + +Pull Request Guidelines +======================= + +Before you submit a pull request, check that it meets these guidelines: + +#. 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 b3b9fb58..01bca8ab 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1,26 +1,20 @@ .. :changelog: -======= +******* History -======= +******* -********** -Unreleased -********** +.. towncrier release notes start -* Add BLOG_USE_FALLBACK_LANGUAGE_IN_URL setting - -******************* 1.1.1 (2020-05-15) -******************* +================== * Fix channels support * Avoid admin exception for related posts when config is None * Fix error when overriding templates folder -******************* 1.1.0 (2020-05-04) -******************* +================== * Add support for django 3.0 * Add BlogAuthorPostsListPlugin to show posts per author @@ -32,9 +26,8 @@ Unreleased * Fix to respect current locale for category names * Improve documentation for meta tags -******************* 1.0.0 (2019-11-04) -******************* +================== * Add support for django CMS 3.7 * Add support for Python 3.7 @@ -45,86 +38,74 @@ Unreleased * Drop support for django CMS < 3.5 * Drop older compatibilities -******************* 0.9.11 (2019-08-06) -******************* +=================== * Use menu_empty_categories config for BlogCategoryPlugin * Purge menu cache when deleting a BlogConfig -******************* 0.9.10 (2019-07-02) -******************* +=================== * Fixed allow_unicode kwarg for AutoSlugField * Fixed sphinx conf isort * Set category as requested or not depending on the permalink setting -****************** 0.9.9 (2019-04-05) -****************** +================== * Fixed issue with thumbnails not being preserved in admin form * Pinned django-taggit version -****************** 0.9.8 (2019-01-13) -****************** +================== * Fixed test environment in Django 1.8, 1.9 * Added related posts to templates / documentation * Added a fix for multiple error messages when slug is not unique -****************** 0.9.7 (2018-05-05) -****************** +================== * Fixed subtitle field not added to the admin -****************** 0.9.6 (2018-05-02) -****************** +================== * Fixed string representation when model has no language * Added subtitle field -****************** 0.9.5 (2018-04-07) -****************** +================== * Fixed jquery path in Django 1.9+"Fix jquery path in Django 1.9+ * Added configurable blog abstract/text CKEditor -****************** 0.9.4 (2018-03-24) -****************** +================== * Fixed migration error from 0.8 to 0.9 -****************** 0.9.3 (2018-03-12) -****************** +================== * Added dependency on lxml used in feeds * Fixed warning on django CMS 3.5 * Fixed wizard in Django 1.11 * Updated translations -****************** 0.9.2 (2018-02-27) -****************** +================== * Fixed missing migration -****************** 0.9.1 (2018-02-22) -****************** +================== * Added Django 1.11 support -****************** 0.9.0 (2018-02-20) -****************** +================== * Added support for django CMS 3.4, 3.5 * Dropped support for Django<1.8, django CMS<3.2. @@ -150,92 +131,78 @@ Unreleased * Generate valid slug in wizard if the given one is taken * Limit categories / related in forms only to current lan -******************* 0.8.13 (2017-07-25) -******************* +=================== * Dropped python 2.6 compatibility * Fixed exceptions in __str__ * Fixed issue with duplicated categories in menu -******************* 0.8.12 (2017-03-11) -******************* +=================== * Fixed migrations on Django 1.10 -******************* 0.8.11 (2017-03-04) -******************* +=================== * Fixed support for aldryn-apphooks-config 0.3.1 -******************* 0.8.10 (2017-01-02) -******************* +=================== * Fix error in get_absolute_url -****************** 0.8.9 (2016-10-25) -****************** +================== * Optimized querysets * Fixed slug generation in wizard -****************** 0.8.8 (2016-09-04) -****************** +================== * Fixed issue with one migration * Improved support for django CMS 3.4 -****************** 0.8.7 (2016-08-25) -****************** +================== * Added support for django CMS 3.4 * Fixed issue with multisite support -****************** 0.8.6 (2016-08-03) -****************** +================== * Set the correct language during indexing -****************** 0.8.5 (2016-06-26) -****************** +================== * Fixed issues with ThumbnailOption migration under mysql. -****************** 0.8.4 (2016-06-22) -****************** +================== * Fixed issues with cmsplugin-filer 1.1. -****************** 0.8.3 (2016-06-21) -****************** +================== * Stricter filer dependency versioning. -****************** 0.8.2 (2016-06-12) -****************** +================== * Aldryn-only release. No code changes -****************** 0.8.1 (2016-06-11) -****************** +================== * Aldryn-only release. No code changes -****************** 0.8.0 (2016-06-05) -****************** +================== * Added django-knocker integration * Changed the default value of date_published to null @@ -249,9 +216,8 @@ Unreleased * Added API to set default sites if user has permission only for a subset of sites * Added Aldryn integration -****************** 0.7.0 (2016-03-19) -****************** +================== * Make categories non required * Fix tests with parler>=1.6 @@ -266,33 +232,29 @@ Unreleased * Mitigate issue when apphook config can't be retrieved * Mitigate issue when wizard double registration is triggered -****************** 0.6.3 (2015-12-22) -****************** +================== * Add BLOG_ADMIN_POST_FIELDSET_FILTER to filter admin fieldsets * Ensure correct creation of full URL for canonical urls * Move constants to settings * Fix error when no config is found -****************** 0.6.2 (2015-11-16) -****************** +================== * Add app_config field to BlogLatestEntriesPlugin * Fix __str__ plugins method * Fix bug when selecting plugins template -****************** 0.6.1 (2015-10-31) -****************** +================== * Improve toolbar: add all languages for each post * Improve toolbar: add per-apphook configurable changefreq, priority -****************** 0.6.0 (2015-10-30) -****************** +================== * Add support for django CMS 3.2 Wizard * Add support for Apphook Config @@ -302,9 +264,8 @@ Unreleased * LatestPostsPlugin tags field has been changed to a plain TaggableManager field. A migration is in place to move the data, but backup your data first. -****************** 0.5.0 (2015-08-09) -****************** +================== * Add support for Django 1.8 * Drop dependency on Django select2 @@ -313,9 +274,8 @@ Unreleased * Add categories menu * Add option to disable the abstract -****************** 0.4.0 (2015-03-22) -****************** +================== * Fix Django 1.7 issues * Fix dependencies on python 3 when using wheel packages @@ -323,16 +283,14 @@ Unreleased * Fix various templates issues * UX fixes in the admin -****************** 0.3.1 (2015-01-07) -****************** +================== * Fix page_name in template * Set cascade to set null for post image and thumbnail options -****************** 0.3.0 (2015-01-04) -****************** +================== * Multisite support * Configurable default author support @@ -348,9 +306,8 @@ Unreleased * Django 1.7 support * Python 3.3 and 3.4 support -****************** 0.2.0 (2014-09-24) -****************** +================== * **INCOMPATIBLE CHANGE**: view names changed! * Based on django parler 1.0 @@ -362,8 +319,7 @@ Unreleased * Simpler TextField-based content editing for simpler blogs * Add support for custom user models -****************** 0.1.0 (2014-03-06) -****************** +================== * First experimental release diff --git a/LICENSE b/LICENSE index 52ecf502..7fa59d7e 100644 --- a/LICENSE +++ b/LICENSE @@ -9,4 +9,4 @@ Redistribution and use in source and binary forms, with or without modification, * Neither the name of djangocms-blog nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Makefile b/Makefile deleted file mode 100644 index 00fcdf7b..00000000 --- a/Makefile +++ /dev/null @@ -1,51 +0,0 @@ -.PHONY: clean-pyc clean-build docs livehtml -PYTHON = python - -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 "release - package and upload a release" - @echo "sdist - package" - -clean: clean-build clean-pyc - -clean-build: - python setup.py clean --all - 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: - tox -epep8,isort - -test: - python cms_helper.py djangocms_blog test - -test-all: - tox - -coverage: - coverage erase - coverage run cms_helper.py djangocms_blog - coverage report -m - - -sdist: clean - python setup.py sdist - ls -l dist - -release: clean - python setup.py clean --all sdist bdist_wheel - python -mtwine upload dist/* - -livehtml: - sphinx-autobuild -b html -p5000 -H0.0.0.0 -E -j auto -d docs/_build/doctrees --poll docs docs/_build/html diff --git a/README.rst b/README.rst index 32a3353f..a1d22c4b 100644 --- a/README.rst +++ b/README.rst @@ -2,7 +2,7 @@ djangocms-blog ============== -|Gitter| |PyPiVersion| |PyVersion| |Status| |TestCoverage| |CodeClimate| |License| +|Gitter| |PyPiVersion| |PyVersion| |GAStatus| |TestCoverage| |CodeClimate| |License| django CMS blog application - Support for multilingual posts, placeholders, social network meta tags and configurable apphooks. @@ -68,9 +68,9 @@ See DjangoPackages for an updated list https://www.djangopackages.com/packages/p :target: https://pypi.python.org/pypi/djangocms-blog :alt: Python versions -.. |Status| image:: https://img.shields.io/travis/nephila/djangocms-blog.svg?style=flat-square - :target: https://travis-ci.org/nephila/djangocms-blog - :alt: Latest Travis CI build status +.. |GAStatus| image:: https://github.com/nephila/djangocms-blog/workflows/Linting%20-%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-blog/master.svg?style=flat-square :target: https://coveralls.io/r/nephila/djangocms-blog?branch=master diff --git a/aldryn_config.py b/aldryn_config.py index 19597f83..64804ffb 100644 --- a/aldryn_config.py +++ b/aldryn_config.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- try: from divio_cli import forms except ImportError: @@ -7,5 +6,5 @@ class Form(forms.BaseForm): def to_settings(self, data, settings): - settings['ADDON_URLS'].append('djangocms_blog.taggit_urls') + settings["ADDON_URLS"].append("djangocms_blog.taggit_urls") return settings diff --git a/changes/.directory b/changes/.directory new file mode 100644 index 00000000..e69de29b diff --git a/changes/546.feature b/changes/546.feature new file mode 100644 index 00000000..312f9c8a --- /dev/null +++ b/changes/546.feature @@ -0,0 +1 @@ +Add option to allow fallback language in post/category URLs diff --git a/changes/564.feature b/changes/564.feature new file mode 100644 index 00000000..8654be5b --- /dev/null +++ b/changes/564.feature @@ -0,0 +1 @@ +Update to modern tooling and port to github actions diff --git a/changes/567.feature b/changes/567.feature new file mode 100644 index 00000000..05e1e69c --- /dev/null +++ b/changes/567.feature @@ -0,0 +1 @@ +Moved post slug to top of post admin form diff --git a/cms_helper.py b/cms_helper.py index 8b1d42fc..a5aab74d 100755 --- a/cms_helper.py +++ b/cms_helper.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- import os import sys @@ -11,150 +10,96 @@ def gettext(s): HELPER_SETTINGS = dict( - ROOT_URLCONF='tests.test_utils.urls', + ROOT_URLCONF="tests.test_utils.urls", INSTALLED_APPS=[ - 'filer', - 'parler', - 'meta', - 'easy_thumbnails', - 'django.contrib.sitemaps', - 'djangocms_text_ckeditor', - 'taggit', - 'taggit_autosuggest', - 'aldryn_apphooks_config', - 'aldryn_search', - 'djangocms_video', - 'sortedm2m', - 'tests.media_app', + "filer", + "parler", + "meta", + "easy_thumbnails", + "django.contrib.sitemaps", + "djangocms_text_ckeditor", + "taggit", + "taggit_autosuggest", + "aldryn_apphooks_config", + "aldryn_search", + "djangocms_video", + "sortedm2m", + "tests.media_app", ], - LANGUAGE_CODE='en', - LANGUAGES=( - ('en', gettext('English')), - ('fr', gettext('French')), - ('it', gettext('Italiano')), - ), + LANGUAGE_CODE="en", + LANGUAGES=(("en", gettext("English")), ("fr", gettext("French")), ("it", gettext("Italiano"))), CMS_LANGUAGES={ 1: [ - { - 'code': 'en', - 'name': gettext('English'), - 'public': True, - }, - { - 'code': 'it', - 'name': gettext('Italiano'), - 'public': True, - }, - { - 'code': 'fr', - 'name': gettext('French'), - 'public': True, - }, - ], - 2: [ - { - 'code': 'en', - 'name': gettext('English'), - 'public': True, - }, + {"code": "en", "name": gettext("English"), "public": True}, + {"code": "it", "name": gettext("Italiano"), "public": True}, + {"code": "fr", "name": gettext("French"), "public": True}, ], - 'default': { - 'hide_untranslated': False, - }, + 2: [{"code": "en", "name": gettext("English"), "public": True}], + "default": {"hide_untranslated": False}, }, PARLER_LANGUAGES={ - 1: ( - {'code': 'en'}, - {'code': 'it'}, - {'code': 'fr'}, - ), - 2: ( - {'code': 'en'}, - ), - 'default': { - 'fallbacks': ['en'], - 'hide_untranslated': False, - } + 1: ({"code": "en"}, {"code": "it"}, {"code": "fr"}), + 2: ({"code": "en"},), + "default": {"fallbacks": ["en"], "hide_untranslated": False}, }, MIGRATION_MODULES={}, - CMS_TEMPLATES=( - ('blog.html', 'Blog template'), - ), - META_SITE_PROTOCOL='http', + CMS_TEMPLATES=(("blog.html", "Blog template"),), + META_SITE_PROTOCOL="http", META_USE_SITES=True, - META_SITE_DOMAIN='example.com', + META_SITE_DOMAIN="example.com", META_USE_OG_PROPERTIES=True, META_USE_TWITTER_PROPERTIES=True, META_USE_GOOGLEPLUS_PROPERTIES=True, 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", ), USE_TZ=True, - TIME_ZONE='UTC', + TIME_ZONE="UTC", FILE_UPLOAD_TEMP_DIR=mkdtemp(), SITE_ID=1, - HAYSTACK_CONNECTIONS={ - 'default': {} - }, - CACHES={ - 'default': { - 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', - } - }, + HAYSTACK_CONNECTIONS={"default": {}}, + CACHES={"default": {"BACKEND": "django.core.cache.backends.locmem.LocMemCache"}}, BLOG_AUTO_SETUP=False, - ALLOWED_HOSTS=['*'], - TEST_RUNNER='app_helper.pytest_runner.PytestTestRunner', + ALLOWED_HOSTS=["*"], + TEST_RUNNER="app_helper.pytest_runner.PytestTestRunner", ) -try: - import cmsplugin_filer_image.migrations_django # pragma: no cover # NOQA - - HELPER_SETTINGS[ - 'MIGRATION_MODULES' - ]['cmsplugin_filer_image'] = 'cmsplugin_filer_image.migrations_django' - -except ImportError: - pass - try: import knocker # pragma: no cover # NOQA - HELPER_SETTINGS['INSTALLED_APPS'].append('knocker') - HELPER_SETTINGS['INSTALLED_APPS'].append('channels') - HELPER_SETTINGS['INSTALLED_APPS'].append('djangocms_blog.liveblog') - HELPER_SETTINGS['ASGI_APPLICATION'] = 'tests.test_utils.routing.application' - HELPER_SETTINGS['CHANNEL_LAYERS'] = { - 'default': { - 'BACKEND': 'channels_redis.core.RedisChannelLayer', - 'CONFIG': { - 'hosts': [('localhost', 6379)], - }, - }, + HELPER_SETTINGS["INSTALLED_APPS"].append("knocker") + HELPER_SETTINGS["INSTALLED_APPS"].append("channels") + HELPER_SETTINGS["INSTALLED_APPS"].append("djangocms_blog.liveblog") + HELPER_SETTINGS["ASGI_APPLICATION"] = "tests.test_utils.routing.application" + HELPER_SETTINGS["CHANNEL_LAYERS"] = { + "default": {"BACKEND": "channels_redis.core.RedisChannelLayer", "CONFIG": {"hosts": [("localhost", 6379)]}}, } except ImportError: pass -os.environ['AUTH_USER_MODEL'] = 'tests.test_utils.CustomUser' +os.environ["AUTH_USER_MODEL"] = "tests.test_utils.CustomUser" -if 'server' in sys.argv[:3]: - HELPER_SETTINGS['BLOG_AUTO_SETUP'] = True +if "server" in sys.argv[:3]: + HELPER_SETTINGS["BLOG_AUTO_SETUP"] = True def run(): from app_helper import runner - runner.cms('djangocms_blog') + + runner.cms("djangocms_blog") def setup(): from app_helper import runner - runner.setup('djangocms_blog', sys.modules[__name__], use_cms=True) + + runner.setup("djangocms_blog", sys.modules[__name__], use_cms=True) -if __name__ == '__main__': +if __name__ == "__main__": run() -if __name__ == 'cms_helper': +if __name__ == "cms_helper": # this is needed to run cms_helper in pycharm setup() diff --git a/djangocms_blog/__init__.py b/djangocms_blog/__init__.py index 6b4eeff7..49916bc6 100644 --- a/djangocms_blog/__init__.py +++ b/djangocms_blog/__init__.py @@ -1,6 +1,5 @@ -# -*- coding: utf-8 -*- -__author__ = 'Iacopo Spalletti' -__email__ = 'i.spalletti@nephila.it' -__version__ = '1.1.2.dev0' +__author__ = "Iacopo Spalletti" +__email__ = "i.spalletti@nephila.it" +__version__ = "1.1.2.dev0" -default_app_config = 'djangocms_blog.apps.BlogAppConfig' +default_app_config = "djangocms_blog.apps.BlogAppConfig" diff --git a/djangocms_blog/admin.py b/djangocms_blog/admin.py old mode 100755 new mode 100644 index 9c2131b8..d64a09c5 --- a/djangocms_blog/admin.py +++ b/djangocms_blog/admin.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from copy import deepcopy from aldryn_apphooks_config.admin import BaseAppHookConfig, ModelAppHookConfig @@ -12,9 +11,8 @@ from django.http import HttpResponseRedirect from django.urls import reverse from django.utils import timezone -from django.utils.translation import get_language_from_request, ugettext_lazy as _, ungettext as __ +from django.utils.translation import get_language_from_request, gettext_lazy as _, ngettext as __ from parler.admin import TranslatableAdmin -from six import callable, text_type from .cms_appconfig import BlogConfig from .forms import CategoryAdminForm, PostAdminForm @@ -23,22 +21,22 @@ class SiteListFilter(admin.SimpleListFilter): - title = _('site') - parameter_name = 'sites' + title = _("site") + parameter_name = "sites" def lookups(self, request, model_admin): - restricted_sites = model_admin.get_restricted_sites(request).values_list('id', flat=True) + restricted_sites = model_admin.get_restricted_sites(request).values_list("id", flat=True) qs = Site.objects.all() if restricted_sites: qs = qs.filter(id__in=restricted_sites) - return [(site.id, text_type(site.name)) for site in qs] + return [(site.id, str(site.name)) for site in qs] def queryset(self, request, queryset): try: - if 'sites' in self.used_parameters: - return queryset.on_site(Site.objects.get(pk=self.used_parameters['sites'])) + if "sites" in self.used_parameters: + return queryset.on_site(Site.objects.get(pk=self.used_parameters["sites"])) return queryset except Site.DoesNotExist as e: # pragma: no cover raise admin.options.IncorrectLookupParameters(e) @@ -49,70 +47,56 @@ def queryset(self, request, queryset): class BlogCategoryAdmin(ModelAppHookConfig, TranslatableAdmin): form = CategoryAdminForm list_display = [ - 'name', 'parent', 'app_config', 'all_languages_column', + "name", + "parent", + "app_config", + "all_languages_column", ] def get_prepopulated_fields(self, request, obj=None): app_config_default = self._app_config_select(request, obj) - if app_config_default is None and request.method == 'GET': + if app_config_default is None and request.method == "GET": return {} - return {'slug': ('name',)} + return {"slug": ("name",)} class Media: - css = { - 'all': ('%sdjangocms_blog/css/%s' % (settings.STATIC_URL, 'djangocms_blog_admin.css'),) - } + css = {"all": ("{}djangocms_blog/css/{}".format(settings.STATIC_URL, "djangocms_blog_admin.css"),)} -class PostAdmin(PlaceholderAdminMixin, FrontendEditableAdminMixin, - ModelAppHookConfig, TranslatableAdmin): +class PostAdmin(PlaceholderAdminMixin, FrontendEditableAdminMixin, ModelAppHookConfig, TranslatableAdmin): form = PostAdminForm - list_display = [ - 'title', 'author', 'date_published', 'app_config', 'all_languages_column', - 'date_published_end' - ] - search_fields = ('translations__title',) - date_hierarchy = 'date_published' - raw_id_fields = ['author'] - frontend_editable_fields = ('title', 'abstract', 'post_text') - enhance_exclude = ('main_image', 'tags') + list_display = ["title", "author", "date_published", "app_config", "all_languages_column", "date_published_end"] + search_fields = ("translations__title",) + date_hierarchy = "date_published" + raw_id_fields = ["author"] + frontend_editable_fields = ("title", "abstract", "post_text") + enhance_exclude = ("main_image", "tags") actions = [ - 'make_published', - 'make_unpublished', - 'enable_comments', - 'disable_comments', + "make_published", + "make_unpublished", + "enable_comments", + "disable_comments", ] - if apps.is_installed('djangocms_blog.liveblog'): - actions += ['enable_liveblog', 'disable_liveblog'] + if apps.is_installed("djangocms_blog.liveblog"): + actions += ["enable_liveblog", "disable_liveblog"] _fieldsets = [ - (None, { - 'fields': [ - ['title', 'subtitle', 'slug', 'publish'], - ['categories', 'app_config'] - ] - }), - (None, { - 'fields': [[]] - }), - (_('Info'), { - 'fields': [['tags'], - ['date_published', 'date_published_end', 'date_featured'], - ['enable_comments']], - 'classes': ('collapse',) - }), - (_('Images'), { - 'fields': [['main_image', 'main_image_thumbnail', 'main_image_full']], - 'classes': ('collapse',) - }), - (_('SEO'), { - 'fields': [['meta_description', 'meta_title', 'meta_keywords']], - 'classes': ('collapse',) - }), + (None, {"fields": ["title", "subtitle", "slug", "publish", ["categories", "app_config"]]}), + (None, {"fields": [[]]}), + ( + _("Info"), + { + "fields": ["tags", ["date_published", "date_published_end", "date_featured"], ["enable_comments"]], + "classes": ("collapse",), + }, + ), + ( + _("Images"), + {"fields": [["main_image", "main_image_thumbnail", "main_image_full"]], "classes": ("collapse",)}, + ), + (_("SEO"), {"fields": [["meta_description", "meta_title", "meta_keywords"]], "classes": ("collapse",)}), ] - app_config_values = { - 'default_published': 'publish' - } + app_config_values = {"default_published": "publish"} _sites = None # Bulk actions for post admin @@ -122,79 +106,75 @@ def make_published(self, request, queryset): saved as date_published. queryset must not be empty (ensured by DjangoCMS). """ - cnt1 = queryset.filter( - date_published__isnull=True, - publish=False, - ).update(date_published=timezone.now(), publish=True) - cnt2 = queryset.filter( - date_published__isnull=False, - publish=False, - ).update(publish=True) + cnt1 = queryset.filter(date_published__isnull=True, publish=False,).update( + date_published=timezone.now(), publish=True + ) + cnt2 = queryset.filter(date_published__isnull=False, publish=False,).update(publish=True) messages.add_message( - request, messages.INFO, - __('%(updates)d entry published.', - '%(updates)d entries published.', cnt1+cnt2) % { - 'updates': cnt1+cnt2, }) + request, + messages.INFO, + __("%(updates)d entry published.", "%(updates)d entries published.", cnt1 + cnt2) + % {"updates": cnt1 + cnt2}, + ) def make_unpublished(self, request, queryset): """ Bulk action to mark selected posts as UNpublished. queryset must not be empty (ensured by DjangoCMS). """ - updates = queryset.filter(publish=True)\ - .update(publish=False) + updates = queryset.filter(publish=True).update(publish=False) messages.add_message( - request, messages.INFO, - __('%(updates)d entry unpublished.', - '%(updates)d entries unpublished.', updates) % { - 'updates': updates, }) + request, + messages.INFO, + __("%(updates)d entry unpublished.", "%(updates)d entries unpublished.", updates) % {"updates": updates}, + ) def enable_comments(self, request, queryset): """ Bulk action to enable comments for selected posts. queryset must not be empty (ensured by DjangoCMS). """ - updates = queryset.filter(enable_comments=False)\ - .update(enable_comments=True) + updates = queryset.filter(enable_comments=False).update(enable_comments=True) messages.add_message( - request, messages.INFO, - __('Comments for %(updates)d entry enabled.', - 'Comments for %(updates)d entries enabled', updates) % { - 'updates': updates, }) + request, + messages.INFO, + __("Comments for %(updates)d entry enabled.", "Comments for %(updates)d entries enabled", updates) + % {"updates": updates}, + ) def disable_comments(self, request, queryset): """ Bulk action to disable comments for selected posts. queryset must not be empty (ensured by DjangoCMS). """ - updates = queryset.filter(enable_comments=True)\ - .update(enable_comments=False) + updates = queryset.filter(enable_comments=True).update(enable_comments=False) messages.add_message( - request, messages.INFO, - __('Comments for %(updates)d entry disabled.', - 'Comments for %(updates)d entries disabled.', updates) % { - 'updates': updates, }) + request, + messages.INFO, + __("Comments for %(updates)d entry disabled.", "Comments for %(updates)d entries disabled.", updates) + % {"updates": updates}, + ) def enable_liveblog(self, request, queryset): """ Bulk action to enable comments for selected posts. queryset must not be empty (ensured by DjangoCMS). """ - updates = queryset.filter(enable_liveblog=False)\ - .update(enable_liveblog=True) + updates = queryset.filter(enable_liveblog=False).update(enable_liveblog=True) messages.add_message( - request, messages.INFO, - __('Liveblog for %(updates)d entry enabled.', - 'Liveblog for %(updates)d entries enabled.', updates) % { - 'updates': updates, }) + request, + messages.INFO, + __("Liveblog for %(updates)d entry enabled.", "Liveblog for %(updates)d entries enabled.", updates) + % {"updates": updates}, + ) def disable_liveblog(self, request, queryset): """ Bulk action to disable comments for selected posts. queryset must not be empty (ensured by DjangoCMS). """ - updates = queryset.filter(enable_liveblog=True)\ - .update(enable_liveblog=False) + updates = queryset.filter(enable_liveblog=True).update(enable_liveblog=False) messages.add_message( - request, messages.INFO, - __('Liveblog for %(updates)d entry enabled.', - 'Liveblog for %(updates)d entries enabled.') % { - 'updates': updates, }) + request, + messages.INFO, + __("Liveblog for %(updates)d entry enabled.", "Liveblog for %(updates)d entries enabled.") + % {"updates": updates}, + ) # Make bulk action menu entries localizable make_published.short_description = _("Publish selection") @@ -205,15 +185,17 @@ def disable_liveblog(self, request, queryset): disable_liveblog.short_description = _("Disable liveblog for selection ") def get_list_filter(self, request): - filters = ['app_config', 'publish', 'date_published'] - if get_setting('MULTISITE'): + filters = ["app_config", "publish", "date_published"] + if get_setting("MULTISITE"): filters.append(SiteListFilter) try: from taggit_helpers.admin import TaggitListFilter + filters.append(TaggitListFilter) except ImportError: # pragma: no cover try: from taggit_helpers import TaggitListFilter + filters.append(TaggitListFilter) except ImportError: pass @@ -224,10 +206,13 @@ def get_urls(self): Customize the modeladmin urls """ urls = [ - url(r'^publish/([0-9]+)/$', self.admin_site.admin_view(self.publish_post), - name='djangocms_blog_publish_article'), + url( + r"^publish/([0-9]+)/$", + self.admin_site.admin_view(self.publish_post), + name="djangocms_blog_publish_article", + ), ] - urls.extend(super(PostAdmin, self).get_urls()) + urls.extend(super().get_urls()) return urls def post_add_plugin(self, request, obj1, obj2=None): @@ -235,12 +220,12 @@ def post_add_plugin(self, request, obj1, obj2=None): plugin = obj1 elif isinstance(obj2, CMSPlugin): plugin = obj2 - if plugin.plugin_type in get_setting('LIVEBLOG_PLUGINS'): - plugin = plugin.move(plugin.get_siblings().first(), 'first-sibling') + if plugin.plugin_type in get_setting("LIVEBLOG_PLUGINS"): + plugin = plugin.move(plugin.get_siblings().first(), "first-sibling") if isinstance(obj1, CMSPlugin): - return super(PostAdmin, self).post_add_plugin(request, plugin) + return super().post_add_plugin(request, plugin) elif isinstance(obj2, CMSPlugin): - return super(PostAdmin, self).post_add_plugin(request, obj1, plugin) + return super().post_add_plugin(request, obj1, plugin) def publish_post(self, request, pk): """ @@ -258,9 +243,9 @@ def publish_post(self, request, pk): return HttpResponseRedirect(post.get_absolute_url(language)) except Exception: try: - return HttpResponseRedirect(request.META['HTTP_REFERER']) + return HttpResponseRedirect(request.META["HTTP_REFERER"]) except KeyError: - return HttpResponseRedirect(reverse('djangocms_blog:posts-latest')) + return HttpResponseRedirect(reverse("djangocms_blog:posts-latest")) def has_restricted_sites(self, request): """ @@ -291,10 +276,10 @@ def get_restricted_sites(self, request): return Site.objects.none() def _set_config_defaults(self, request, form, obj=None): - form = super(PostAdmin, self)._set_config_defaults(request, form, obj) + form = super()._set_config_defaults(request, form, obj) sites = self.get_restricted_sites(request) - if 'sites' in form.base_fields and sites.exists(): - form.base_fields['sites'].queryset = self.get_restricted_sites(request).all() + if "sites" in form.base_fields and sites.exists(): + form.base_fields["sites"].queryset = self.get_restricted_sites(request).all() return form def _get_available_posts(self, config): @@ -311,8 +296,8 @@ def get_fieldsets(self, request, obj=None): :return: fieldsets configuration """ app_config_default = self._app_config_select(request, obj) - if app_config_default is None and request.method == 'GET': - return super(PostAdmin, self).get_fieldsets(request, obj) + if app_config_default is None and request.method == "GET": + return super().get_fieldsets(request, obj) if not obj: config = app_config_default else: @@ -325,64 +310,56 @@ def get_fieldsets(self, request, obj=None): placeholder = bool(config.use_placeholder) related = bool(config.use_related) else: - abstract = get_setting('USE_ABSTRACT') - placeholder = get_setting('USE_PLACEHOLDER') - related = get_setting('USE_RELATED') + abstract = get_setting("USE_ABSTRACT") + placeholder = get_setting("USE_PLACEHOLDER") + related = get_setting("USE_RELATED") if related: related_posts = self._get_available_posts(config) if abstract: - fsets[0][1]['fields'].append('abstract') + fsets[0][1]["fields"].append("abstract") if not placeholder: - fsets[0][1]['fields'].append('post_text') - if get_setting('MULTISITE') and not self.has_restricted_sites(request): - fsets[1][1]['fields'][0].append('sites') + fsets[0][1]["fields"].append("post_text") + if get_setting("MULTISITE") and not self.has_restricted_sites(request): + fsets[1][1]["fields"][0].append("sites") if request.user.is_superuser: - fsets[1][1]['fields'][0].append('author') - if apps.is_installed('djangocms_blog.liveblog'): - fsets[2][1]['fields'][2].append('enable_liveblog') - filter_function = get_setting('ADMIN_POST_FIELDSET_FILTER') + fsets[1][1]["fields"][0].append("author") + if apps.is_installed("djangocms_blog.liveblog"): + fsets[2][1]["fields"][2].append("enable_liveblog") + filter_function = get_setting("ADMIN_POST_FIELDSET_FILTER") if related_posts: - fsets[1][1]['fields'][0].append('related') + fsets[1][1]["fields"][0].append("related") if callable(filter_function): fsets = filter_function(fsets, request, obj=obj) return fsets def get_prepopulated_fields(self, request, obj=None): - return {'slug': ('title',)} + return {"slug": ("title",)} def save_model(self, request, obj, form, change): obj._set_default_author(request.user) - super(PostAdmin, self).save_model(request, obj, form, change) + super().save_model(request, obj, form, change) def get_queryset(self, request): - qs = super(PostAdmin, self).get_queryset(request) + qs = super().get_queryset(request) sites = self.get_restricted_sites(request) if sites.exists(): - pks = list(sites.all().values_list('pk', flat=True)) + pks = list(sites.all().values_list("pk", flat=True)) qs = qs.filter(sites__in=pks) return qs.distinct() def save_related(self, request, form, formsets, change): if self.get_restricted_sites(request).exists(): - if 'sites' in form.cleaned_data: - form_sites = form.cleaned_data.get('sites', []) - removed = set( - self.get_restricted_sites(request).all() - ).difference(form_sites) - diff_original = set( - form.instance.sites.all() - ).difference(removed).union(form_sites) - form.cleaned_data['sites'] = diff_original + if "sites" in form.cleaned_data: + form_sites = form.cleaned_data.get("sites", []) + removed = set(self.get_restricted_sites(request).all()).difference(form_sites) + diff_original = set(form.instance.sites.all()).difference(removed).union(form_sites) + form.cleaned_data["sites"] = diff_original else: - form.instance.sites.add( - *self.get_restricted_sites(request).all().values_list('pk', flat=True) - ) - super(PostAdmin, self).save_related(request, form, formsets, change) + form.instance.sites.add(*self.get_restricted_sites(request).all().values_list("pk", flat=True)) + super().save_related(request, form, formsets, change) class Media: - css = { - 'all': ('%sdjangocms_blog/css/%s' % (settings.STATIC_URL, 'djangocms_blog_admin.css'),) - } + css = {"all": ("{}djangocms_blog/css/{}".format(settings.STATIC_URL, "djangocms_blog_admin.css"),)} class BlogConfigAdmin(BaseAppHookConfig, TranslatableAdmin): @@ -395,75 +372,81 @@ def get_fieldsets(self, request, obj=None): Fieldsets configuration """ return [ - (None, { - 'fields': ('type', 'namespace', 'app_title', 'object_name') - }), - (_('Generic'), { - 'fields': ( - 'config.default_published', 'config.use_placeholder', 'config.use_abstract', - 'config.set_author', 'config.use_related', - ) - }), - (_('Layout'), { - 'fields': ( - 'config.paginate_by', 'config.url_patterns', 'config.template_prefix', - 'config.menu_structure', 'config.menu_empty_categories', - ('config.default_image_full', 'config.default_image_thumbnail'), - ), - 'classes': ('collapse',) - }), - (_('Notifications'), { - 'fields': ( - 'config.send_knock_create', 'config.send_knock_update' - ), - 'classes': ('collapse',) - }), - (_('Sitemap'), { - 'fields': ( - 'config.sitemap_changefreq', 'config.sitemap_priority', - ), - 'classes': ('collapse',) - }), - (_('Meta'), { - 'fields': ( - 'config.object_type', - ) - }), - ('Open Graph', { - 'fields': ( - 'config.og_type', 'config.og_app_id', 'config.og_profile_id', - 'config.og_publisher', 'config.og_author_url', 'config.og_author', - ), - 'description': _( - 'You can provide plain strings, Post model attribute or method names' - ) - }), - ('Twitter', { - 'fields': ( - 'config.twitter_type', 'config.twitter_site', 'config.twitter_author', - ), - 'description': _( - 'You can provide plain strings, Post model attribute or method names' - ) - }), - ('Google+', { - 'fields': ( - 'config.gplus_type', 'config.gplus_author', - ), - 'description': _( - 'You can provide plain strings, Post model attribute or method names' - ) - }), + (None, {"fields": ("type", "namespace", "app_title", "object_name")}), + ( + _("Generic"), + { + "fields": ( + "config.default_published", + "config.use_placeholder", + "config.use_abstract", + "config.set_author", + "config.use_related", + ) + }, + ), + ( + _("Layout"), + { + "fields": ( + "config.paginate_by", + "config.url_patterns", + "config.template_prefix", + "config.menu_structure", + "config.menu_empty_categories", + ("config.default_image_full", "config.default_image_thumbnail"), + ), + "classes": ("collapse",), + }, + ), + ( + _("Notifications"), + {"fields": ("config.send_knock_create", "config.send_knock_update"), "classes": ("collapse",)}, + ), + ( + _("Sitemap"), + {"fields": ("config.sitemap_changefreq", "config.sitemap_priority",), "classes": ("collapse",)}, + ), + (_("Meta"), {"fields": ("config.object_type",)}), + ( + "Open Graph", + { + "fields": ( + "config.og_type", + "config.og_app_id", + "config.og_profile_id", + "config.og_publisher", + "config.og_author_url", + "config.og_author", + ), + "description": _("You can provide plain strings, Post model attribute or method names"), + }, + ), + ( + "Twitter", + { + "fields": ("config.twitter_type", "config.twitter_site", "config.twitter_author",), + "description": _("You can provide plain strings, Post model attribute or method names"), + }, + ), + ( + "Google+", + { + "fields": ("config.gplus_type", "config.gplus_author",), + "description": _("You can provide plain strings, Post model attribute or method names"), + }, + ), ] def save_model(self, request, obj, form, change): """ Clear menu cache when changing menu structure """ - if 'config.menu_structure' in form.changed_data: + if "config.menu_structure" in form.changed_data: from menus.menu_pool import menu_pool + menu_pool.clear(all=True) - return super(BlogConfigAdmin, self).save_model(request, obj, form, change) + return super().save_model(request, obj, form, change) admin.site.register(BlogCategory, BlogCategoryAdmin) diff --git a/djangocms_blog/apps.py b/djangocms_blog/apps.py index 224eda70..0b7a6979 100644 --- a/djangocms_blog/apps.py +++ b/djangocms_blog/apps.py @@ -1,8 +1,7 @@ -# -*- coding: utf-8 -*- from django.apps import AppConfig -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ class BlogAppConfig(AppConfig): - name = 'djangocms_blog' - verbose_name = _('django CMS Blog') + name = "djangocms_blog" + verbose_name = _("django CMS Blog") diff --git a/djangocms_blog/cms_appconfig.py b/djangocms_blog/cms_appconfig.py index b5a26e4d..f3269168 100644 --- a/djangocms_blog/cms_appconfig.py +++ b/djangocms_blog/cms_appconfig.py @@ -1,10 +1,9 @@ -# -*- coding: utf-8 -*- from aldryn_apphooks_config.models import AppHookConfig from aldryn_apphooks_config.utils import setup_config from app_data import AppDataForm from django import forms from django.db import models -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from filer.models import ThumbnailOption from parler.models import TranslatableModel, TranslatedFields @@ -15,146 +14,146 @@ class BlogConfig(TranslatableModel, AppHookConfig): """ Adds some translatable, per-app-instance fields. """ + translations = TranslatedFields( - app_title=models.CharField(_('application title'), max_length=234), - object_name=models.CharField( - _('object name'), max_length=234, default=get_setting('DEFAULT_OBJECT_NAME') - ), + app_title=models.CharField(_("application title"), max_length=234), + object_name=models.CharField(_("object name"), max_length=234, default=get_setting("DEFAULT_OBJECT_NAME")), ) class Meta: - verbose_name = _('blog config') - verbose_name_plural = _('blog configs') + verbose_name = _("blog config") + verbose_name_plural = _("blog configs") def get_app_title(self): - return getattr(self, 'app_title', _('untitled')) + return getattr(self, "app_title", _("untitled")) class BlogConfigForm(AppDataForm): default_published = forms.BooleanField( - label=_('Post published by default'), required=False, - initial=get_setting('DEFAULT_PUBLISHED') + label=_("Post published by default"), required=False, initial=get_setting("DEFAULT_PUBLISHED") ) default_image_full = forms.ModelChoiceField( - label=_('Default size of full images'), + label=_("Default size of full images"), queryset=ThumbnailOption.objects.all(), required=False, - help_text=_('If left empty the image size will have to be set for ' - 'every newly created post.'), + help_text=_("If left empty the image size will have to be set for " "every newly created post."), ) default_image_thumbnail = forms.ModelChoiceField( - label=_('Default size of thumbnail images'), + label=_("Default size of thumbnail images"), queryset=ThumbnailOption.objects.all(), required=False, - help_text=_('If left empty the thumbnail image size will have to be ' - 'set for every newly created post.'), + help_text=_("If left empty the thumbnail image size will have to be " "set for every newly created post."), ) url_patterns = forms.ChoiceField( - label=_('Permalink structure'), required=False, - initial=get_setting('AVAILABLE_PERMALINK_STYLES')[0][0], - choices=get_setting('AVAILABLE_PERMALINK_STYLES') + label=_("Permalink structure"), + required=False, + initial=get_setting("AVAILABLE_PERMALINK_STYLES")[0][0], + choices=get_setting("AVAILABLE_PERMALINK_STYLES"), ) use_placeholder = forms.BooleanField( - label=_('Use placeholder and plugins for article body'), required=False, - initial=get_setting('USE_PLACEHOLDER') + label=_("Use placeholder and plugins for article body"), required=False, initial=get_setting("USE_PLACEHOLDER") ) use_abstract = forms.BooleanField( - label=_('Use abstract field'), required=False, - initial=get_setting('USE_ABSTRACT') + label=_("Use abstract field"), required=False, initial=get_setting("USE_ABSTRACT") ) use_related = forms.BooleanField( - label=_('Enable related posts'), required=False, - initial=get_setting('USE_RELATED') + label=_("Enable related posts"), required=False, initial=get_setting("USE_RELATED") ) set_author = forms.BooleanField( - label=_('Set author'), required=False, help_text=_('Set author by default'), - initial=get_setting('AUTHOR_DEFAULT') + label=_("Set author"), + required=False, + help_text=_("Set author by default"), + initial=get_setting("AUTHOR_DEFAULT"), ) paginate_by = forms.IntegerField( - label=_('Paginate size'), required=False, initial=get_setting('PAGINATION'), - help_text=_('When paginating list views, how many articles per page?') + label=_("Paginate size"), + required=False, + initial=get_setting("PAGINATION"), + help_text=_("When paginating list views, how many articles per page?"), ) template_prefix = forms.CharField( - label=_('Template prefix'), required=False, initial='', - help_text=_('Alternative directory to load the blog templates from') + label=_("Template prefix"), + required=False, + initial="", + help_text=_("Alternative directory to load the blog templates from"), ) menu_structure = forms.ChoiceField( - label=_('Menu structure'), required=True, - choices=get_setting('MENU_TYPES'), initial=MENU_TYPE_COMPLETE, - help_text=_('Structure of the django CMS menu') + label=_("Menu structure"), + required=True, + choices=get_setting("MENU_TYPES"), + initial=MENU_TYPE_COMPLETE, + help_text=_("Structure of the django CMS menu"), ) menu_empty_categories = forms.BooleanField( - label=_('Show empty categories in menu'), initial=get_setting('MENU_EMPTY_CATEGORIES'), + label=_("Show empty categories in menu"), + initial=get_setting("MENU_EMPTY_CATEGORIES"), required=False, - help_text=_('Show categories with no post attached in the menu') + help_text=_("Show categories with no post attached in the menu"), ) sitemap_changefreq = forms.ChoiceField( - label=_('Sitemap changefreq'), required=True, - choices=get_setting('SITEMAP_CHANGEFREQ'), - initial=get_setting('SITEMAP_CHANGEFREQ_DEFAULT'), - help_text=_('Changefreq attribute for sitemap items') + label=_("Sitemap changefreq"), + required=True, + choices=get_setting("SITEMAP_CHANGEFREQ"), + initial=get_setting("SITEMAP_CHANGEFREQ_DEFAULT"), + help_text=_("Changefreq attribute for sitemap items"), ) sitemap_priority = forms.CharField( - label=_('Sitemap priority'), required=True, - initial=get_setting('SITEMAP_PRIORITY_DEFAULT'), - help_text=_('Priority attribute for sitemap items') + label=_("Sitemap priority"), + required=True, + initial=get_setting("SITEMAP_PRIORITY_DEFAULT"), + help_text=_("Priority attribute for sitemap items"), ) object_type = forms.ChoiceField( - label=_('Object type'), required=False, - choices=get_setting('TYPES'), initial=get_setting('TYPE') + label=_("Object type"), required=False, choices=get_setting("TYPES"), initial=get_setting("TYPE") ) og_type = forms.ChoiceField( - label=_('Facebook type'), required=False, - choices=get_setting('FB_TYPES'), initial=get_setting('FB_TYPE') + label=_("Facebook type"), required=False, choices=get_setting("FB_TYPES"), initial=get_setting("FB_TYPE") ) og_app_id = forms.CharField( - max_length=200, label=_('Facebook application ID'), required=False, - initial=get_setting('FB_PROFILE_ID') + max_length=200, label=_("Facebook application ID"), required=False, initial=get_setting("FB_PROFILE_ID") ) og_profile_id = forms.CharField( - max_length=200, label=_('Facebook profile ID'), required=False, - initial=get_setting('FB_PROFILE_ID') + max_length=200, label=_("Facebook profile ID"), required=False, initial=get_setting("FB_PROFILE_ID") ) og_publisher = forms.CharField( - max_length=200, label=_('Facebook page URL'), required=False, - initial=get_setting('FB_PUBLISHER') + max_length=200, label=_("Facebook page URL"), required=False, initial=get_setting("FB_PUBLISHER") ) og_author_url = forms.CharField( - max_length=200, label=_('Facebook author URL'), required=False, - initial=get_setting('FB_AUTHOR_URL') + max_length=200, label=_("Facebook author URL"), required=False, initial=get_setting("FB_AUTHOR_URL") ) og_author = forms.CharField( - max_length=200, label=_('Facebook author'), required=False, - initial=get_setting('FB_AUTHOR') + max_length=200, label=_("Facebook author"), required=False, initial=get_setting("FB_AUTHOR") ) twitter_type = forms.ChoiceField( - label=_('Twitter type'), required=False, - choices=get_setting('TWITTER_TYPES'), initial=get_setting('TWITTER_TYPE') + label=_("Twitter type"), + required=False, + choices=get_setting("TWITTER_TYPES"), + initial=get_setting("TWITTER_TYPE"), ) twitter_site = forms.CharField( - max_length=200, label=_('Twitter site handle'), required=False, - initial=get_setting('TWITTER_SITE') + max_length=200, label=_("Twitter site handle"), required=False, initial=get_setting("TWITTER_SITE") ) twitter_author = forms.CharField( - max_length=200, label=_('Twitter author handle'), required=False, - initial=get_setting('TWITTER_AUTHOR') + max_length=200, label=_("Twitter author handle"), required=False, initial=get_setting("TWITTER_AUTHOR") ) gplus_type = forms.ChoiceField( - label=_('Google+ type'), required=False, - choices=get_setting('GPLUS_TYPES'), initial=get_setting('GPLUS_TYPE') + label=_("Google+ type"), required=False, choices=get_setting("GPLUS_TYPES"), initial=get_setting("GPLUS_TYPE") ) gplus_author = forms.CharField( - max_length=200, label=_('Google+ author name'), required=False, - initial=get_setting('GPLUS_AUTHOR') + max_length=200, label=_("Google+ author name"), required=False, initial=get_setting("GPLUS_AUTHOR") ) send_knock_create = forms.BooleanField( - label=_('Send notifications on post publish'), required=False, initial=False, - help_text=_('Emits a desktop notification -if enabled- when publishing a new post') + label=_("Send notifications on post publish"), + required=False, + initial=False, + help_text=_("Emits a desktop notification -if enabled- when publishing a new post"), ) send_knock_update = forms.BooleanField( - label=_('Send notifications on post update'), required=False, initial=False, - help_text=_('Emits a desktop notification -if enabled- when editing a published post') + label=_("Send notifications on post update"), + required=False, + initial=False, + help_text=_("Emits a desktop notification -if enabled- when editing a published post"), ) diff --git a/djangocms_blog/cms_apps.py b/djangocms_blog/cms_apps.py index 00d25e21..292b558a 100644 --- a/djangocms_blog/cms_apps.py +++ b/djangocms_blog/cms_apps.py @@ -1,7 +1,6 @@ -# -*- coding: utf-8 -*- from aldryn_apphooks_config.app_base import CMSConfigApp from cms.apphook_pool import apphook_pool -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from djangocms_apphook_setup.base import AutoCMSAppMixin from .cms_appconfig import BlogConfig @@ -11,25 +10,25 @@ @apphook_pool.register class BlogApp(AutoCMSAppMixin, CMSConfigApp): - name = _('Blog') - _urls = [get_setting('URLCONF')] - app_name = 'djangocms_blog' + name = _("Blog") + _urls = [get_setting("URLCONF")] + app_name = "djangocms_blog" app_config = BlogConfig _menus = [BlogCategoryMenu] auto_setup = { - 'enabled': get_setting('AUTO_SETUP'), - 'home title': get_setting('AUTO_HOME_TITLE'), - 'page title': get_setting('AUTO_BLOG_TITLE'), - 'namespace': get_setting('AUTO_NAMESPACE'), - 'config_fields': {}, - 'config_translated_fields': { - 'app_title': get_setting('AUTO_APP_TITLE'), - 'object_name': get_setting('DEFAULT_OBJECT_NAME') + "enabled": get_setting("AUTO_SETUP"), + "home title": get_setting("AUTO_HOME_TITLE"), + "page title": get_setting("AUTO_BLOG_TITLE"), + "namespace": get_setting("AUTO_NAMESPACE"), + "config_fields": {}, + "config_translated_fields": { + "app_title": get_setting("AUTO_APP_TITLE"), + "object_name": get_setting("DEFAULT_OBJECT_NAME"), }, } def get_urls(self, page=None, language=None, **kwargs): - return [get_setting('URLCONF')] + return [get_setting("URLCONF")] @property def urls(self): diff --git a/djangocms_blog/cms_menus.py b/djangocms_blog/cms_menus.py index 647ef296..14374cd0 100644 --- a/djangocms_blog/cms_menus.py +++ b/djangocms_blog/cms_menus.py @@ -1,18 +1,15 @@ -# -*- coding: utf-8 -*- from cms.apphook_pool import apphook_pool from cms.menu_bases import CMSAttachMenu from django.contrib.sites.shortcuts import get_current_site from django.db.models.signals import post_delete, post_save from django.urls import resolve -from django.utils.translation import get_language_from_request, ugettext_lazy as _ +from django.utils.translation import get_language_from_request, gettext_lazy as _ from menus.base import Modifier, NavigationNode from menus.menu_pool import menu_pool from .cms_appconfig import BlogConfig from .models import BlogCategory, Post -from .settings import ( - MENU_TYPE_CATEGORIES, MENU_TYPE_COMPLETE, MENU_TYPE_NONE, MENU_TYPE_POSTS, get_setting, -) +from .settings import MENU_TYPE_CATEGORIES, MENU_TYPE_COMPLETE, MENU_TYPE_NONE, MENU_TYPE_POSTS, get_setting class BlogCategoryMenu(CMSAttachMenu): @@ -21,7 +18,8 @@ class BlogCategoryMenu(CMSAttachMenu): Handles all types of blog menu """ - name = _('Blog menu') + + name = _("Blog menu") _config = {} def get_nodes(self, request): @@ -49,7 +47,7 @@ def get_nodes(self, request): namespace=self.instance.application_namespace ) config = self._config[self.instance.application_namespace] - if not getattr(request, 'toolbar', False) or not request.toolbar.edit_mode_active: + if not getattr(request, "toolbar", False) or not request.toolbar.edit_mode_active: if self.instance == self.instance.get_draft_object(): return [] else: @@ -59,34 +57,33 @@ def get_nodes(self, request): categories_menu = True if config and config.menu_structure in (MENU_TYPE_COMPLETE, MENU_TYPE_POSTS): posts_menu = True - if config and config.menu_structure in (MENU_TYPE_NONE, ): + if config and config.menu_structure in (MENU_TYPE_NONE,): return nodes used_categories = [] if posts_menu: posts = Post.objects - if hasattr(self, 'instance') and self.instance: + if hasattr(self, "instance") and self.instance: posts = posts.namespace(self.instance.application_namespace).on_site() - posts = posts.active_translations(language).distinct().\ - select_related('app_config').prefetch_related('translations', 'categories') + posts = ( + posts.active_translations(language) + .distinct() + .select_related("app_config") + .prefetch_related("translations", "categories") + ) for post in posts: post_id = None parent = None - used_categories.extend(post.categories.values_list('pk', flat=True)) + used_categories.extend(post.categories.values_list("pk", flat=True)) if categories_menu: category = post.categories.first() if category: - parent = '{0}-{1}'.format(category.__class__.__name__, category.pk) - post_id = '{0}-{1}'.format(post.__class__.__name__, post.pk), + parent = "{}-{}".format(category.__class__.__name__, category.pk) + post_id = ("{}-{}".format(post.__class__.__name__, post.pk),) else: - post_id = '{0}-{1}'.format(post.__class__.__name__, post.pk), + post_id = ("{}-{}".format(post.__class__.__name__, post.pk),) if post_id: - node = NavigationNode( - post.get_title(), - post.get_absolute_url(language), - post_id, - parent - ) + node = NavigationNode(post.get_title(), post.get_absolute_url(language), post_id, parent) nodes.append(node) if categories_menu: @@ -94,25 +91,22 @@ def get_nodes(self, request): if config: categories = categories.namespace(self.instance.application_namespace) if config and not config.menu_empty_categories: - categories = categories.active_translations(language).filter( - pk__in=used_categories - ).distinct() + categories = categories.active_translations(language).filter(pk__in=used_categories).distinct() else: categories = categories.active_translations(language).distinct() - categories = categories.order_by('parent__id', 'translations__name').\ - select_related('app_config').prefetch_related('translations') + categories = ( + categories.order_by("parent__id", "translations__name") + .select_related("app_config") + .prefetch_related("translations") + ) added_categories = [] for category in categories: if category.pk not in added_categories: node = NavigationNode( category.name, category.get_absolute_url(), - '{0}-{1}'.format(category.__class__.__name__, category.pk), - ( - '{0}-{1}'.format( - category.__class__.__name__, category.parent.id - ) if category.parent else None - ) + "{}-{}".format(category.__class__.__name__, category.pk), + ("{}-{}".format(category.__class__.__name__, category.parent.id) if category.parent else None), ) nodes.append(node) added_categories.append(category.pk) @@ -126,6 +120,7 @@ class BlogNavModifier(Modifier): a particular blog post is viewed, a corresponding category is selected in menu """ + _config = {} def modify(self, request, nodes, namespace, root_id, post_cut, breadcrumb): @@ -141,7 +136,7 @@ def modify(self, request, nodes, namespace, root_id, post_cut, breadcrumb): """ app = None config = None - if getattr(request, 'current_page', None) and request.current_page.application_urls: + if getattr(request, "current_page", None) and request.current_page.application_urls: app = apphook_pool.get_apphook(request.current_page.application_urls) if app and app.app_config: @@ -150,17 +145,14 @@ def modify(self, request, nodes, namespace, root_id, post_cut, breadcrumb): self._config[namespace] = app.get_config(namespace) config = self._config[namespace] try: - if config and ( - not isinstance(config, BlogConfig) or - config.menu_structure != MENU_TYPE_CATEGORIES - ): + if config and (not isinstance(config, BlogConfig) or config.menu_structure != MENU_TYPE_CATEGORIES): return nodes except AttributeError: # pragma: no cover # in case `menu_structure` is not present in config return nodes if post_cut: return nodes - current_post = getattr(request, get_setting('CURRENT_POST_IDENTIFIER'), None) + current_post = getattr(request, get_setting("CURRENT_POST_IDENTIFIER"), None) category = None if current_post and current_post.__class__ == Post: category = current_post.categories.first() @@ -168,7 +160,7 @@ def modify(self, request, nodes, namespace, root_id, post_cut, breadcrumb): return nodes for node in nodes: - if '{0}-{1}'.format(category.__class__.__name__, category.pk) == node.id: + if "{}-{}".format(category.__class__.__name__, category.pk) == node.id: node.selected = True return nodes diff --git a/djangocms_blog/cms_plugins.py b/djangocms_blog/cms_plugins.py index 622aa5df..0b777ef4 100644 --- a/djangocms_blog/cms_plugins.py +++ b/djangocms_blog/cms_plugins.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os.path from cms.plugin_base import CMSPluginBase @@ -13,17 +12,15 @@ class BlogPlugin(CMSPluginBase): - module = get_setting('PLUGIN_MODULE_NAME') + module = get_setting("PLUGIN_MODULE_NAME") def get_render_template(self, context, instance, placeholder): - templates = [ - os.path.join('djangocms_blog', instance.template_folder, self.base_render_template) - ] + templates = [os.path.join("djangocms_blog", instance.template_folder, self.base_render_template)] if instance.app_config and instance.app_config.template_prefix: - templates.insert(0, os.path.join( - instance.app_config.template_prefix, instance.template_folder, - self.base_render_template - )) + templates.insert( + 0, + os.path.join(instance.app_config.template_prefix, instance.template_folder, self.base_render_template), + ) selected = select_template(templates) return selected.template.name @@ -34,19 +31,23 @@ class BlogLatestEntriesPlugin(BlogPlugin): Non cached plugin which returns the latest posts taking into account the user / toolbar state """ - name = get_setting('LATEST_ENTRIES_PLUGIN_NAME') + + name = get_setting("LATEST_ENTRIES_PLUGIN_NAME") model = LatestPostsPlugin form = LatestEntriesForm - filter_horizontal = ('categories',) - fields = ['app_config', 'latest_posts', 'tags', 'categories'] + \ - ['template_folder'] if len(get_setting('PLUGIN_TEMPLATE_FOLDERS')) > 1 else [] + filter_horizontal = ("categories",) + fields = ( + ["app_config", "latest_posts", "tags", "categories"] + ["template_folder"] + if len(get_setting("PLUGIN_TEMPLATE_FOLDERS")) > 1 + else [] + ) cache = False - base_render_template = 'latest_entries.html' + base_render_template = "latest_entries.html" def render(self, context, instance, placeholder): - context = super(BlogLatestEntriesPlugin, self).render(context, instance, placeholder) - context['posts_list'] = instance.get_posts(context['request'], published_only=False) - context['TRUNCWORDS_COUNT'] = get_setting('POSTS_LIST_TRUNCWORDS_COUNT') + context = super().render(context, instance, placeholder) + context["posts_list"] = instance.get_posts(context["request"], published_only=False) + context["TRUNCWORDS_COUNT"] = get_setting("POSTS_LIST_TRUNCWORDS_COUNT") return context @@ -54,94 +55,102 @@ class BlogLatestEntriesPluginCached(BlogPlugin): """ Cached plugin which returns the latest published posts """ - name = get_setting('LATEST_ENTRIES_PLUGIN_NAME_CACHED') + + name = get_setting("LATEST_ENTRIES_PLUGIN_NAME_CACHED") model = LatestPostsPlugin form = LatestEntriesForm - filter_horizontal = ('categories',) - fields = ['app_config', 'latest_posts', 'tags', 'categories'] + \ - ['template_folder'] if len(get_setting('PLUGIN_TEMPLATE_FOLDERS')) > 1 else [] - base_render_template = 'latest_entries.html' + filter_horizontal = ("categories",) + fields = ( + ["app_config", "latest_posts", "tags", "categories"] + ["template_folder"] + if len(get_setting("PLUGIN_TEMPLATE_FOLDERS")) > 1 + else [] + ) + base_render_template = "latest_entries.html" def render(self, context, instance, placeholder): - context = super(BlogLatestEntriesPluginCached, self).render(context, instance, placeholder) - context['posts_list'] = instance.get_posts(context['request']) - context['TRUNCWORDS_COUNT'] = get_setting('POSTS_LIST_TRUNCWORDS_COUNT') + context = super().render(context, instance, placeholder) + context["posts_list"] = instance.get_posts(context["request"]) + context["TRUNCWORDS_COUNT"] = get_setting("POSTS_LIST_TRUNCWORDS_COUNT") return context class BlogAuthorPostsPlugin(BlogPlugin): - module = get_setting('PLUGIN_MODULE_NAME') - name = get_setting('AUTHOR_POSTS_PLUGIN_NAME') + module = get_setting("PLUGIN_MODULE_NAME") + name = get_setting("AUTHOR_POSTS_PLUGIN_NAME") model = AuthorEntriesPlugin form = AuthorPostsForm - base_render_template = 'authors.html' - filter_horizontal = ['authors'] - fields = ['app_config', 'current_site', 'authors'] + \ - ['template_folder'] if len(get_setting('PLUGIN_TEMPLATE_FOLDERS')) > 1 else [] - exclude = ['template_folder'] if len(get_setting('PLUGIN_TEMPLATE_FOLDERS')) >= 1 else [] + base_render_template = "authors.html" + filter_horizontal = ["authors"] + fields = ( + ["app_config", "current_site", "authors"] + ["template_folder"] + if len(get_setting("PLUGIN_TEMPLATE_FOLDERS")) > 1 + else [] + ) + exclude = ["template_folder"] if len(get_setting("PLUGIN_TEMPLATE_FOLDERS")) >= 1 else [] def render(self, context, instance, placeholder): - context = super(BlogAuthorPostsPlugin, self).render(context, instance, placeholder) - context['authors_list'] = instance.get_authors(context['request']) + context = super().render(context, instance, placeholder) + context["authors_list"] = instance.get_authors(context["request"]) return context class BlogAuthorPostsListPlugin(BlogAuthorPostsPlugin): - name = get_setting('AUTHOR_POSTS_LIST_PLUGIN_NAME') - base_render_template = 'authors_posts.html' - fields = ['app_config', 'current_site', 'authors', 'latest_posts'] + \ - ['template_folder'] if len(get_setting('PLUGIN_TEMPLATE_FOLDERS')) > 1 else [] + name = get_setting("AUTHOR_POSTS_LIST_PLUGIN_NAME") + base_render_template = "authors_posts.html" + fields = ( + ["app_config", "current_site", "authors", "latest_posts"] + ["template_folder"] + if len(get_setting("PLUGIN_TEMPLATE_FOLDERS")) > 1 + else [] + ) class BlogTagsPlugin(BlogPlugin): - module = get_setting('PLUGIN_MODULE_NAME') - name = get_setting('TAGS_PLUGIN_NAME') + module = get_setting("PLUGIN_MODULE_NAME") + name = get_setting("TAGS_PLUGIN_NAME") model = GenericBlogPlugin - base_render_template = 'tags.html' - exclude = ['template_folder'] if len(get_setting('PLUGIN_TEMPLATE_FOLDERS')) >= 1 else [] + base_render_template = "tags.html" + exclude = ["template_folder"] if len(get_setting("PLUGIN_TEMPLATE_FOLDERS")) >= 1 else [] def render(self, context, instance, placeholder): - context = super(BlogTagsPlugin, self).render(context, instance, placeholder) - qs = instance.post_queryset(context['request']) - context['tags'] = Post.objects.tag_cloud(queryset=qs.published()) + context = super().render(context, instance, placeholder) + qs = instance.post_queryset(context["request"]) + context["tags"] = Post.objects.tag_cloud(queryset=qs.published()) return context class BlogCategoryPlugin(BlogPlugin): - module = get_setting('PLUGIN_MODULE_NAME') - name = get_setting('CATEGORY_PLUGIN_NAME') + module = get_setting("PLUGIN_MODULE_NAME") + name = get_setting("CATEGORY_PLUGIN_NAME") model = GenericBlogPlugin - base_render_template = 'categories.html' - exclude = ['template_folder'] if len(get_setting('PLUGIN_TEMPLATE_FOLDERS')) >= 1 else [] + base_render_template = "categories.html" + exclude = ["template_folder"] if len(get_setting("PLUGIN_TEMPLATE_FOLDERS")) >= 1 else [] def render(self, context, instance, placeholder): - context = super(BlogCategoryPlugin, self).render(context, instance, placeholder) + context = super().render(context, instance, placeholder) qs = BlogCategory.objects.active_translations() if instance.app_config: qs = qs.namespace(instance.app_config.namespace) if instance.current_site: - site = get_current_site(context['request']) - qs = qs.filter( - models.Q(blog_posts__sites__isnull=True) | models.Q(blog_posts__sites=site.pk) - ) + site = get_current_site(context["request"]) + qs = qs.filter(models.Q(blog_posts__sites__isnull=True) | models.Q(blog_posts__sites=site.pk)) categories = qs.distinct() if instance.app_config and not instance.app_config.menu_empty_categories: categories = qs.filter(blog_posts__isnull=False).distinct() - context['categories'] = categories + context["categories"] = categories return context class BlogArchivePlugin(BlogPlugin): - module = get_setting('PLUGIN_MODULE_NAME') - name = get_setting('ARCHIVE_PLUGIN_NAME') + module = get_setting("PLUGIN_MODULE_NAME") + name = get_setting("ARCHIVE_PLUGIN_NAME") model = GenericBlogPlugin - base_render_template = 'archive.html' - exclude = ['template_folder'] if len(get_setting('PLUGIN_TEMPLATE_FOLDERS')) >= 1 else [] + base_render_template = "archive.html" + exclude = ["template_folder"] if len(get_setting("PLUGIN_TEMPLATE_FOLDERS")) >= 1 else [] def render(self, context, instance, placeholder): - context = super(BlogArchivePlugin, self).render(context, instance, placeholder) - qs = instance.post_queryset(context['request']) - context['dates'] = Post.objects.get_months(queryset=qs.published()) + context = super().render(context, instance, placeholder) + qs = instance.post_queryset(context["request"]) + context["dates"] = Post.objects.get_months(queryset=qs.published()) return context diff --git a/djangocms_blog/cms_toolbars.py b/djangocms_blog/cms_toolbars.py index ed2e88c4..1c98b6d5 100644 --- a/djangocms_blog/cms_toolbars.py +++ b/djangocms_blog/cms_toolbars.py @@ -1,69 +1,72 @@ -# -*- coding: utf-8 -*- from cms.toolbar_base import CMSToolbar from cms.toolbar_pool import toolbar_pool from cms.utils.urlutils import admin_reverse from django.urls import reverse -from django.utils.translation import override, ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _, override from .settings import get_setting @toolbar_pool.register class BlogToolbar(CMSToolbar): - def populate(self): - if (not self.is_current_app and not get_setting('ENABLE_THROUGH_TOOLBAR_MENU')) or \ - not self.request.user.has_perm('djangocms_blog.add_post'): - return # pragma: no cover - admin_menu = self.toolbar.get_or_create_menu('djangocms_blog', _('Blog')) + if ( + not self.is_current_app and not get_setting("ENABLE_THROUGH_TOOLBAR_MENU") + ) or not self.request.user.has_perm("djangocms_blog.add_post"): + return # pragma: no cover + admin_menu = self.toolbar.get_or_create_menu("djangocms_blog", _("Blog")) with override(self.current_lang): - url = reverse('admin:djangocms_blog_post_changelist') - admin_menu.add_modal_item(_('Post list'), url=url) - url = reverse('admin:djangocms_blog_post_add') - admin_menu.add_modal_item(_('Add post'), url=url) - current_config = getattr(self.request, get_setting('CURRENT_NAMESPACE'), None) + url = reverse("admin:djangocms_blog_post_changelist") + admin_menu.add_modal_item(_("Post list"), url=url) + url = reverse("admin:djangocms_blog_post_add") + admin_menu.add_modal_item(_("Add post"), url=url) + current_config = getattr(self.request, get_setting("CURRENT_NAMESPACE"), None) if current_config: - url = reverse('admin:djangocms_blog_blogconfig_change', args=(current_config.pk,)) - admin_menu.add_modal_item(_('Edit configuration'), url=url) + url = reverse("admin:djangocms_blog_blogconfig_change", args=(current_config.pk,)) + admin_menu.add_modal_item(_("Edit configuration"), url=url) - current_post = getattr(self.request, get_setting('CURRENT_POST_IDENTIFIER'), None) - if current_post and self.request.user.has_perm('djangocms_blog.change_post'): # pragma: no cover # NOQA - admin_menu.add_modal_item(_('Edit Post'), reverse( - 'admin:djangocms_blog_post_change', args=(current_post.pk,)), - active=True) + current_post = getattr(self.request, get_setting("CURRENT_POST_IDENTIFIER"), None) + if current_post and self.request.user.has_perm("djangocms_blog.change_post"): # pragma: no cover # NOQA + admin_menu.add_modal_item( + _("Edit Post"), reverse("admin:djangocms_blog_post_change", args=(current_post.pk,)), active=True + ) def add_publish_button(self): """ Adds the publish button to the toolbar if the current post is unpublished """ - current_post = getattr(self.request, get_setting('CURRENT_POST_IDENTIFIER'), None) - if (self.toolbar.edit_mode_active and current_post and - not current_post.publish and - self.request.user.has_perm('djangocms_blog.change_post') - ): # pragma: no cover # NOQA - classes = ['cms-btn-action', 'blog-publish'] - title = _('Publish {0} now').format(current_post.app_config.object_name) + current_post = getattr(self.request, get_setting("CURRENT_POST_IDENTIFIER"), None) + if ( + self.toolbar.edit_mode_active + and current_post + and not current_post.publish + and self.request.user.has_perm("djangocms_blog.change_post") + ): # pragma: no cover # NOQA + classes = ["cms-btn-action", "blog-publish"] + title = _("Publish {0} now").format(current_post.app_config.object_name) - url = admin_reverse('djangocms_blog_publish_article', args=(current_post.pk,)) + url = admin_reverse("djangocms_blog_publish_article", args=(current_post.pk,)) self.toolbar.add_button(title, url=url, extra_classes=classes, side=self.toolbar.RIGHT) def post_template_populate(self): - current_post = getattr(self.request, get_setting('CURRENT_POST_IDENTIFIER'), None) - if current_post and self.request.user.has_perm('djangocms_blog.change_post'): # pragma: no cover # NOQA + current_post = getattr(self.request, get_setting("CURRENT_POST_IDENTIFIER"), None) + if current_post and self.request.user.has_perm("djangocms_blog.change_post"): # pragma: no cover # NOQA # removing page meta menu, if present, to avoid confusion - try: # pragma: no cover + try: # pragma: no cover import djangocms_page_meta # NOQA - menu = self.request.toolbar.get_or_create_menu('page') - pagemeta = menu.get_or_create_menu('pagemeta', 'meta') + + menu = self.request.toolbar.get_or_create_menu("page") + pagemeta = menu.get_or_create_menu("pagemeta", "meta") menu.remove_item(pagemeta) except ImportError: pass # removing page tags menu, if present, to avoid confusion - try: # pragma: no cover + try: # pragma: no cover import djangocms_page_tags # NOQA - menu = self.request.toolbar.get_or_create_menu('page') - pagetags = menu.get_or_create_menu('pagetags', 'tags') + + menu = self.request.toolbar.get_or_create_menu("page") + pagetags = menu.get_or_create_menu("pagetags", "tags") menu.remove_item(pagetags) except ImportError: pass diff --git a/djangocms_blog/cms_wizards.py b/djangocms_blog/cms_wizards.py index 9be3e28d..ce67dcb7 100644 --- a/djangocms_blog/cms_wizards.py +++ b/djangocms_blog/cms_wizards.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import warnings from cms.utils.permissions import get_current_user @@ -6,7 +5,7 @@ from cms.wizards.wizard_pool import AlreadyRegisteredException, wizard_pool from django import forms from django.conf import settings -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from .cms_appconfig import BlogConfig from .fields import slugify @@ -18,52 +17,56 @@ class PostWizardForm(PostAdminFormBase): default_appconfig = None slug = forms.SlugField( - label=_('Slug'), max_length=752, required=False, - help_text=_('Leave empty for automatic slug, or override as required.'), + label=_("Slug"), + max_length=752, + required=False, + help_text=_("Leave empty for automatic slug, or override as required."), ) def __init__(self, *args, **kwargs): - if 'initial' not in kwargs or not kwargs.get('initial', False): - kwargs['initial'] = {} - kwargs['initial']['app_config'] = self.default_appconfig - if 'data' in kwargs and kwargs['data'] is not None: - data = kwargs['data'].copy() - data['1-app_config'] = self.default_appconfig - kwargs['data'] = data - super(PostWizardForm, self).__init__(*args, **kwargs) - self.fields['app_config'].widget = forms.Select( - attrs=self.fields['app_config'].widget.attrs, - choices=self.fields['app_config'].widget.choices, + if "initial" not in kwargs or not kwargs.get("initial", False): + kwargs["initial"] = {} + kwargs["initial"]["app_config"] = self.default_appconfig + if "data" in kwargs and kwargs["data"] is not None: + data = kwargs["data"].copy() + data["1-app_config"] = self.default_appconfig + kwargs["data"] = data + super().__init__(*args, **kwargs) + self.fields["app_config"].widget = forms.Select( + attrs=self.fields["app_config"].widget.attrs, choices=self.fields["app_config"].widget.choices, ) - self.fields['app_config'].widget.attrs['disabled'] = True - if 'categories' in self.fields: - self.fields['categories'].queryset = self.available_categories + self.fields["app_config"].widget.attrs["disabled"] = True + if "categories" in self.fields: + self.fields["categories"].queryset = self.available_categories class Meta: model = Post - fields = ['app_config', 'title', 'slug', 'abstract', 'categories'] + fields = ["app_config", "title", "slug", "abstract", "categories"] class Media: - js = ('admin/js/vendor/jquery/jquery.js', 'admin/js/jquery.init.js',) + js = ( + "admin/js/vendor/jquery/jquery.js", + "admin/js/jquery.init.js", + ) def save(self, commit=True): self.instance._set_default_author(get_current_user()) - return super(PostWizardForm, self).save(commit) + return super().save(commit) def clean_slug(self): """ Generate a valid slug, in case the given one is taken """ - source = self.cleaned_data.get('slug', '') + source = self.cleaned_data.get("slug", "") lang_choice = self.language_code if not source: - source = slugify(self.cleaned_data.get('title', '')) + source = slugify(self.cleaned_data.get("title", "")) qs = Post._default_manager.active_translations(lang_choice).language(lang_choice) - used = list(qs.values_list('translations__slug', flat=True)) + used = list(qs.values_list("translations__slug", flat=True)) slug = source i = 1 while slug in used: - slug = '%s-%s' % (source, i) + slug = "{}-{}".format(source, i) i += 1 return slug @@ -72,18 +75,16 @@ class PostWizard(Wizard): pass -for config in BlogConfig.objects.all().order_by('namespace'): - seed = slugify('{0}.{1}'.format(config.app_title, config.namespace)) +for config in BlogConfig.objects.all().order_by("namespace"): + seed = slugify("{}.{}".format(config.app_title, config.namespace)) new_wizard = type(str(seed), (PostWizard,), {}) - new_form = type(str('{0}Form').format(seed), (PostWizardForm,), { - 'default_appconfig': config.pk - }) + new_form = type("{}Form".format(seed), (PostWizardForm,), {"default_appconfig": config.pk}) post_wizard = new_wizard( - title=_('New {0}').format(config.object_name), + title=_("New {0}").format(config.object_name), weight=200, form=new_form, model=Post, - description=_('Create a new {0} in {1}').format(config.object_name, config.app_title), + description=_("Create a new {0} in {1}").format(config.object_name, config.app_title), ) try: wizard_pool.register(post_wizard) @@ -91,6 +92,8 @@ class PostWizard(Wizard): if settings.DEBUG: raise else: - warnings.warn('Wizard {0} cannot be registered. Please make sure that ' - 'BlogConfig.namespace {1} and BlogConfig.app_title {2} are' - 'unique together'.format(seed, config.namespace, config.app_title)) + warnings.warn( + "Wizard {} cannot be registered. Please make sure that " + "BlogConfig.namespace {} and BlogConfig.app_title {} are" + "unique together".format(seed, config.namespace, config.app_title) + ) diff --git a/djangocms_blog/feeds.py b/djangocms_blog/feeds.py index 284c01ea..7d9b3a7e 100644 --- a/djangocms_blog/feeds.py +++ b/djangocms_blog/feeds.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from html import unescape from aldryn_apphooks_config.utils import get_app_instance @@ -11,7 +10,7 @@ from django.utils.html import strip_tags from django.utils.safestring import mark_safe from django.utils.text import normalize_newlines -from django.utils.translation import get_language_from_request, ugettext as _ +from django.utils.translation import get_language_from_request, gettext as _ from lxml import etree from six import BytesIO @@ -23,34 +22,32 @@ class LatestEntriesFeed(Feed): feed_type = Rss201rev2Feed - feed_items_number = get_setting('FEED_LATEST_ITEMS') + feed_items_number = get_setting("FEED_LATEST_ITEMS") def __call__(self, request, *args, **kwargs): self.request = request self.namespace, self.config = get_app_instance(request) - return super(LatestEntriesFeed, self).__call__(request, *args, **kwargs) + return super().__call__(request, *args, **kwargs) def link(self): - return reverse('%s:posts-latest' % self.namespace, current_app=self.namespace) + return reverse("%s:posts-latest" % self.namespace, current_app=self.namespace) def title(self): return Site.objects.get_current().name def description(self): - return _('Blog articles on %(site_name)s') % {'site_name': Site.objects.get_current().name} + return _("Blog articles on %(site_name)s") % {"site_name": Site.objects.get_current().name} def items(self, obj=None): - return Post.objects.namespace( - self.namespace - ).published().order_by('-date_published')[:self.feed_items_number] + return Post.objects.namespace(self.namespace).published().order_by("-date_published")[: self.feed_items_number] def item_title(self, item): - return mark_safe(item.safe_translation_getter('title')) + return mark_safe(item.safe_translation_getter("title")) def item_description(self, item): if item.app_config.use_abstract: - return mark_safe(item.safe_translation_getter('abstract')) - return mark_safe(item.safe_translation_getter('post_text')) + return mark_safe(item.safe_translation_getter("abstract")) + return mark_safe(item.safe_translation_getter("post_text")) def item_updateddate(self, item): return item.date_modified @@ -69,114 +66,107 @@ def item_author_url(self, item): class TagFeed(LatestEntriesFeed): - feed_items_number = get_setting('FEED_TAGS_ITEMS') + feed_items_number = get_setting("FEED_TAGS_ITEMS") def get_object(self, request, tag): return tag # pragma: no cover def items(self, obj=None): - return Post.objects.published().filter(tags__slug=obj)[:self.feed_items_number] + return Post.objects.published().filter(tags__slug=obj)[: self.feed_items_number] class FBInstantFeed(Rss201rev2Feed): - date_format = '%Y-%m-%dT%H:%M:%S%z' + date_format = "%Y-%m-%dT%H:%M:%S%z" def rss_attributes(self): - return { - 'version': self._version, - 'xmlns:content': 'http://purl.org/rss/1.0/modules/content/' - } + return {"version": self._version, "xmlns:content": "http://purl.org/rss/1.0/modules/content/"} def add_root_elements(self, handler): - handler.addQuickElement('title', self.feed['title']) - handler.addQuickElement('link', self.feed['link']) - handler.addQuickElement('description', self.feed['description']) - if self.feed['language'] is not None: - handler.addQuickElement('language', self.feed['language']) - for cat in self.feed['categories']: - handler.addQuickElement('category', cat) - if self.feed['feed_copyright'] is not None: - handler.addQuickElement('copyright', self.feed['feed_copyright']) - handler.addQuickElement( - 'lastBuildDate', self.latest_post_date().strftime(self.date_format) - ) - if self.feed['ttl'] is not None: - handler.addQuickElement('ttl', self.feed['ttl']) + handler.addQuickElement("title", self.feed["title"]) + handler.addQuickElement("link", self.feed["link"]) + handler.addQuickElement("description", self.feed["description"]) + if self.feed["language"] is not None: + handler.addQuickElement("language", self.feed["language"]) + for cat in self.feed["categories"]: + handler.addQuickElement("category", cat) + if self.feed["feed_copyright"] is not None: + handler.addQuickElement("copyright", self.feed["feed_copyright"]) + handler.addQuickElement("lastBuildDate", self.latest_post_date().strftime(self.date_format)) + if self.feed["ttl"] is not None: + handler.addQuickElement("ttl", self.feed["ttl"]) def add_item_elements(self, handler, item): - super(FBInstantFeed, self).add_item_elements(handler, item) - if item['author']: - handler.addQuickElement('author', item['author']) - if item['date_pub'] is not None: - handler.addQuickElement('pubDate', item['date_pub'].strftime(self.date_format)) - if item['date_mod'] is not None: - handler.addQuickElement('modDate', item['date_mod'].strftime(self.date_format)) - - handler.startElement('description', {}) - handler._write(''.format( - unescape(normalize_newlines(force_text(item['abstract'])).replace('\n', ' '))) + super().add_item_elements(handler, item) + if item["author"]: + handler.addQuickElement("author", item["author"]) + if item["date_pub"] is not None: + handler.addQuickElement("pubDate", item["date_pub"].strftime(self.date_format)) + if item["date_mod"] is not None: + handler.addQuickElement("modDate", item["date_mod"].strftime(self.date_format)) + + handler.startElement("description", {}) + handler._write( + "".format(unescape(normalize_newlines(force_text(item["abstract"])).replace("\n", " "))) ) - handler.endElement('description') - handler.startElement('content:encoded', {}) - handler._write('') - handler._write(unescape(force_text(item['content']))) - handler._write(']]>') - handler.endElement('content:encoded') + handler.endElement("description") + handler.startElement("content:encoded", {}) + handler._write("") + handler._write(unescape(force_text(item["content"]))) + handler._write("]]>") + handler.endElement("content:encoded") class FBInstantArticles(LatestEntriesFeed): feed_type = FBInstantFeed - feed_items_number = get_setting('FEED_INSTANT_ITEMS') + feed_items_number = get_setting("FEED_INSTANT_ITEMS") def items(self, obj=None): - return Post.objects.namespace( - self.namespace - ).published().order_by('-date_modified')[:self.feed_items_number] + return Post.objects.namespace(self.namespace).published().order_by("-date_modified")[: self.feed_items_number] def _clean_html(self, content): body = BytesIO(content) document = etree.iterparse(body, html=True) - for a, e in document: - if not (e.text and e.text.strip()) and len(e) == 0 and e.tag == 'p': - e.getparent().remove(e) - if e.tag in ('h3', 'h4', 'h5', 'h6') and 'op-kicker' not in e.attrib.get('class', ''): - e.tag = 'h2' + for _a, element in document: + if not (element.text and element.text.strip()) and len(element) == 0 and element.tag == "p": + element.getparent().remove(element) + if element.tag in ("h3", "h4", "h5", "h6") and "op-kicker" not in element.attrib.get("class", ""): + element.tag = "h2" return etree.tostring(document.root) def item_extra_kwargs(self, item): if not item: return {} language = get_language_from_request(self.request, check_path=True) - key = item.get_cache_key(language, 'feed') + key = item.get_cache_key(language, "feed") content = cache.get(key) if not content: view = PostDetailView.as_view(instant_article=True) - response = view(self.request, slug=item.safe_translation_getter('slug')) + response = view(self.request, slug=item.safe_translation_getter("slug")) response.render() content = self._clean_html(response.content) - cache.set(key, content, timeout=get_setting('FEED_CACHE_TIMEOUT')) + cache.set(key, content, timeout=get_setting("FEED_CACHE_TIMEOUT")) if item.app_config.use_abstract: - abstract = strip_tags(item.safe_translation_getter('abstract')) + abstract = strip_tags(item.safe_translation_getter("abstract")) else: - abstract = strip_tags(item.safe_translation_getter('post_text')) + abstract = strip_tags(item.safe_translation_getter("post_text")) return { - 'author': item.get_author_name(), - 'content': content, - 'date': item.date_modified, - 'date_pub': item.date_modified, - 'date_mod': item.date_modified, - 'abstract': abstract + "author": item.get_author_name(), + "content": content, + "date": item.date_modified, + "date_pub": item.date_modified, + "date_mod": item.date_modified, + "abstract": abstract, } def item_categories(self, item): - return [category.safe_translation_getter('name') for category in item.categories.all()] + return [category.safe_translation_getter("name") for category in item.categories.all()] def item_author_name(self, item): - return '' + return "" def item_author_url(self, item): - return '' + return "" def item_description(self, item): return None diff --git a/djangocms_blog/fields.py b/djangocms_blog/fields.py index e5ff0cd6..f6007bf3 100644 --- a/djangocms_blog/fields.py +++ b/djangocms_blog/fields.py @@ -1,7 +1,6 @@ -# -*- coding: utf-8 -*- from django.utils.text import slugify as django_slugify -__all__ = ['slugify'] +__all__ = ["slugify"] def slugify(base): diff --git a/djangocms_blog/forms.py b/djangocms_blog/forms.py index ab475fe5..1852c7b2 100644 --- a/djangocms_blog/forms.py +++ b/djangocms_blog/forms.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django import forms from django.conf import settings from django.contrib.auth import get_user_model @@ -22,72 +21,61 @@ class ConfigFormBase: @cached_property def app_config(self): - if getattr(self.instance, 'app_config_id', None): + if getattr(self.instance, "app_config_id", None): return self.instance.app_config - elif 'app_config' in self.initial: - return BlogConfig.objects.get(pk=self.initial['app_config']) - elif self.data.get('app_config', None): - return BlogConfig.objects.get(pk=self.data['app_config']) + elif "app_config" in self.initial: + return BlogConfig.objects.get(pk=self.initial["app_config"]) + elif self.data.get("app_config", None): + return BlogConfig.objects.get(pk=self.data["app_config"]) return None class CategoryAdminForm(ConfigFormBase, TranslatableModelForm): - def __init__(self, *args, **kwargs): - self.base_fields['meta_description'].validators = [ - MaxLengthValidator(get_setting('META_DESCRIPTION_LENGTH')) - ] - original_attrs = self.base_fields['meta_description'].widget.attrs - if 'cols' in original_attrs: - del original_attrs['cols'] - if 'rows' in original_attrs: - del original_attrs['rows'] - original_attrs['maxlength'] = get_setting('META_DESCRIPTION_LENGTH') - self.base_fields['meta_description'].widget = forms.TextInput(original_attrs) - super(CategoryAdminForm, self).__init__(*args, **kwargs) - - if 'parent' in self.fields: - qs = self.fields['parent'].queryset + self.base_fields["meta_description"].validators = [MaxLengthValidator(get_setting("META_DESCRIPTION_LENGTH"))] + original_attrs = self.base_fields["meta_description"].widget.attrs + if "cols" in original_attrs: + del original_attrs["cols"] + if "rows" in original_attrs: + del original_attrs["rows"] + original_attrs["maxlength"] = get_setting("META_DESCRIPTION_LENGTH") + self.base_fields["meta_description"].widget = forms.TextInput(original_attrs) + super().__init__(*args, **kwargs) + + if "parent" in self.fields: + qs = self.fields["parent"].queryset if self.instance.pk: - qs = qs.exclude( - pk__in=[self.instance.pk] + [child.pk for child in self.instance.descendants()] - ) + qs = qs.exclude(pk__in=[self.instance.pk] + [child.pk for child in self.instance.descendants()]) config = None - if getattr(self.instance, 'app_config_id', None): + if getattr(self.instance, "app_config_id", None): qs = qs.namespace(self.instance.app_config.namespace) - elif 'app_config' in self.initial: - config = BlogConfig.objects.get(pk=self.initial['app_config']) - elif self.data.get('app_config', None): - config = BlogConfig.objects.get(pk=self.data['app_config']) + elif "app_config" in self.initial: + config = BlogConfig.objects.get(pk=self.initial["app_config"]) + elif self.data.get("app_config", None): + config = BlogConfig.objects.get(pk=self.data["app_config"]) if config: qs = qs.namespace(config.namespace) - self.fields['parent'].queryset = qs + self.fields["parent"].queryset = qs class Meta: model = BlogCategory - fields = '__all__' + fields = "__all__" class LatestEntriesForm(forms.ModelForm): def __init__(self, *args, **kwargs): - super(LatestEntriesForm, self).__init__(*args, **kwargs) - self.fields['tags'].widget = TagAutoSuggest('taggit.Tag') + super().__init__(*args, **kwargs) + self.fields["tags"].widget = TagAutoSuggest("taggit.Tag") class Media: - css = { - 'all': ('%sdjangocms_blog/css/%s' % ( - settings.STATIC_URL, 'djangocms_blog_admin.css' - ),) - } + css = {"all": ("{}djangocms_blog/css/{}".format(settings.STATIC_URL, "djangocms_blog_admin.css"),)} class AuthorPostsForm(forms.ModelForm): def __init__(self, *args, **kwargs): - super(AuthorPostsForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # apply distinct due to django issue #11707 - self.fields['authors'].queryset = User.objects.filter( - djangocms_blog_post_author__publish=True - ).distinct() + self.fields["authors"].queryset = User.objects.filter(djangocms_blog_post_author__publish=True).distinct() class PostAdminFormBase(ConfigFormBase, TranslatableModelForm): @@ -97,7 +85,7 @@ class PostAdminFormBase(ConfigFormBase, TranslatableModelForm): class Meta: model = Post - fields = '__all__' + fields = "__all__" @cached_property def available_categories(self): @@ -111,41 +99,36 @@ def _post_clean_translation(self, translation): # which needs to be fixed in parler # operating at form level ensure that if the model is validated outside the form # the uniqueness check is not disabled - super(PostAdminFormBase, self)._post_clean_translation(translation) + super()._post_clean_translation(translation) self._validate_unique = False class PostAdminForm(PostAdminFormBase): - def __init__(self, *args, **kwargs): - self.base_fields['meta_description'].validators = [ - MaxLengthValidator(get_setting('META_DESCRIPTION_LENGTH')) - ] - original_attrs = self.base_fields['meta_description'].widget.attrs - if 'cols' in original_attrs: - del original_attrs['cols'] - if 'rows' in original_attrs: - del original_attrs['rows'] - original_attrs['maxlength'] = get_setting('META_DESCRIPTION_LENGTH') - self.base_fields['meta_description'].widget = forms.TextInput(original_attrs) - self.base_fields['meta_title'].validators = [ - MaxLengthValidator(get_setting('META_TITLE_LENGTH')) - ] - super(PostAdminForm, self).__init__(*args, **kwargs) - if 'categories' in self.fields: + self.base_fields["meta_description"].validators = [MaxLengthValidator(get_setting("META_DESCRIPTION_LENGTH"))] + original_attrs = self.base_fields["meta_description"].widget.attrs + if "cols" in original_attrs: + del original_attrs["cols"] + if "rows" in original_attrs: + del original_attrs["rows"] + original_attrs["maxlength"] = get_setting("META_DESCRIPTION_LENGTH") + self.base_fields["meta_description"].widget = forms.TextInput(original_attrs) + self.base_fields["meta_title"].validators = [MaxLengthValidator(get_setting("META_TITLE_LENGTH"))] + super().__init__(*args, **kwargs) + if "categories" in self.fields: if self.app_config and self.app_config.url_patterns == PERMALINK_TYPE_CATEGORY: - self.fields['categories'].required = True - self.fields['categories'].queryset = self.available_categories + self.fields["categories"].required = True + self.fields["categories"].queryset = self.available_categories - if 'app_config' in self.fields: + if "app_config" in self.fields: # Don't allow app_configs to be added here. The correct way to add an # apphook-config is to create an apphook on a cms Page. - self.fields['app_config'].widget.can_add_related = False + self.fields["app_config"].widget.can_add_related = False if self.app_config: - if not self.initial.get('main_image_full', ''): - self.initial['main_image_full'] = \ - self.app_config.app_data['config'].get('default_image_full') - if not self.initial.get('main_image_thumbnail', ''): - self.initial['main_image_thumbnail'] = \ - self.app_config.app_data['config'].get('default_image_thumbnail') + if not self.initial.get("main_image_full", ""): + self.initial["main_image_full"] = self.app_config.app_data["config"].get("default_image_full") + if not self.initial.get("main_image_thumbnail", ""): + self.initial["main_image_thumbnail"] = self.app_config.app_data["config"].get( + "default_image_thumbnail" + ) diff --git a/djangocms_blog/liveblog/__init__.py b/djangocms_blog/liveblog/__init__.py index 1237786a..638ccb26 100644 --- a/djangocms_blog/liveblog/__init__.py +++ b/djangocms_blog/liveblog/__init__.py @@ -1,2 +1 @@ -# -*- coding: utf-8 -*- -default_app_config = 'djangocms_blog.liveblog.apps.LiveBlogAppConfig' +default_app_config = "djangocms_blog.liveblog.apps.LiveBlogAppConfig" diff --git a/djangocms_blog/liveblog/apps.py b/djangocms_blog/liveblog/apps.py index 2dc51c67..036a145e 100644 --- a/djangocms_blog/liveblog/apps.py +++ b/djangocms_blog/liveblog/apps.py @@ -1,8 +1,7 @@ -# -*- coding: utf-8 -*- from django.apps import AppConfig -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ class LiveBlogAppConfig(AppConfig): - name = 'djangocms_blog.liveblog' - verbose_name = _('Liveblog') + name = "djangocms_blog.liveblog" + verbose_name = _("Liveblog") diff --git a/djangocms_blog/liveblog/cms_plugins.py b/djangocms_blog/liveblog/cms_plugins.py index 7d058ff3..3f76f931 100644 --- a/djangocms_blog/liveblog/cms_plugins.py +++ b/djangocms_blog/liveblog/cms_plugins.py @@ -1,6 +1,5 @@ -# -*- coding: utf-8 -*- from cms.plugin_pool import plugin_pool -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from djangocms_text_ckeditor.cms_plugins import TextPlugin from djangocms_blog.settings import get_setting @@ -9,21 +8,21 @@ class LiveblogPlugin(TextPlugin): - module = get_setting('PLUGIN_MODULE_NAME') - name = _('Liveblog item') + module = get_setting("PLUGIN_MODULE_NAME") + name = _("Liveblog item") model = Liveblog - fields = ('title', 'publish', 'body', 'post_date') - render_template = 'liveblog/plugins/liveblog.html' + fields = ("title", "publish", "body", "post_date") + render_template = "liveblog/plugins/liveblog.html" def save_model(self, request, obj, form, change): - super(LiveblogPlugin, self).save_model(request, obj, form, change) + super().save_model(request, obj, form, change) if obj.publish: obj.send(request) def render(self, context, instance, placeholder): - context = super(LiveblogPlugin, self).render(context, instance, placeholder) - instance.content = context['body'] - context['instance'] = instance + context = super().render(context, instance, placeholder) + instance.content = context["body"] + context["instance"] = instance return context diff --git a/djangocms_blog/liveblog/consumers.py b/djangocms_blog/liveblog/consumers.py index 310aa0bd..27d2bd89 100644 --- a/djangocms_blog/liveblog/consumers.py +++ b/djangocms_blog/liveblog/consumers.py @@ -1,19 +1,15 @@ -# -*- coding: utf-8 -*- - from channels.generic.websocket import JsonWebsocketConsumer from ..models import Post class LiveblogConsumer(JsonWebsocketConsumer): - def _get_post(self, kwargs): - apphook = kwargs.get('apphook') - lang = kwargs.get('lang') - slug = kwargs.get('post') + apphook = kwargs.get("apphook") + lang = kwargs.get("lang") + slug = kwargs.get("post") try: - return Post.objects.namespace(apphook).language(lang).active_translations( - slug=slug).get() + return Post.objects.namespace(apphook).language(lang).active_translations(slug=slug).get() except Post.DoesNotExist: return @@ -25,7 +21,7 @@ def get_groups(self): """ Connect users to the group of the post according to the URL parameters """ - post = self._get_post(self.scope['url_route']['kwargs']) + post = self._get_post(self.scope["url_route"]["kwargs"]) if post: return [post.liveblog_group] else: diff --git a/djangocms_blog/liveblog/migrations/0001_initial.py b/djangocms_blog/liveblog/migrations/0001_initial.py index 4e451743..7abd740d 100644 --- a/djangocms_blog/liveblog/migrations/0001_initial.py +++ b/djangocms_blog/liveblog/migrations/0001_initial.py @@ -1,32 +1,56 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models -import filer.fields.image import django.db.models.deletion +import filer.fields.image +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('cms', '0013_urlconfrevision'), - ('filer', '0003_thumbnailoption'), + ("cms", "0013_urlconfrevision"), + ("filer", "0003_thumbnailoption"), ] operations = [ migrations.CreateModel( - name='Liveblog', + name="Liveblog", fields=[ - ('cmsplugin_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='cms.CMSPlugin', on_delete=django.db.models.deletion.CASCADE)), - ('body', models.TextField(verbose_name='body')), - ('publish', models.BooleanField(default=False, verbose_name='publish liveblog entry')), - ('image', filer.fields.image.FilerImageField(related_name='djangocms_blog_liveblog_image', on_delete=django.db.models.deletion.SET_NULL, verbose_name='image', blank=True, to='filer.Image', null=True)), - ('thumbnail', models.ForeignKey(related_name='djangocms_blog_liveblog_thumbnail', on_delete=django.db.models.deletion.SET_NULL, verbose_name='thumbnail size', blank=True, to='filer.ThumbnailOption', null=True)), + ( + "cmsplugin_ptr", + models.OneToOneField( + parent_link=True, + auto_created=True, + primary_key=True, + serialize=False, + to="cms.CMSPlugin", + on_delete=django.db.models.deletion.CASCADE, + ), + ), + ("body", models.TextField(verbose_name="body")), + ("publish", models.BooleanField(default=False, verbose_name="publish liveblog entry")), + ( + "image", + filer.fields.image.FilerImageField( + related_name="djangocms_blog_liveblog_image", + on_delete=django.db.models.deletion.SET_NULL, + verbose_name="image", + blank=True, + to="filer.Image", + null=True, + ), + ), + ( + "thumbnail", + models.ForeignKey( + related_name="djangocms_blog_liveblog_thumbnail", + on_delete=django.db.models.deletion.SET_NULL, + verbose_name="thumbnail size", + blank=True, + to="filer.ThumbnailOption", + null=True, + ), + ), ], - options={ - 'verbose_name': 'liveblog entry', - 'verbose_name_plural': 'liveblog entries', - }, - bases=('cms.cmsplugin',), + options={"verbose_name": "liveblog entry", "verbose_name_plural": "liveblog entries",}, + bases=("cms.cmsplugin",), ), ] diff --git a/djangocms_blog/liveblog/migrations/0002_liveblog_title.py b/djangocms_blog/liveblog/migrations/0002_liveblog_title.py index b59c5adb..dfecb9c8 100644 --- a/djangocms_blog/liveblog/migrations/0002_liveblog_title.py +++ b/djangocms_blog/liveblog/migrations/0002_liveblog_title.py @@ -1,20 +1,17 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('liveblog', '0001_initial'), + ("liveblog", "0001_initial"), ] operations = [ migrations.AddField( - model_name='liveblog', - name='title', - field=models.CharField(default='', max_length=255, verbose_name='title'), + model_name="liveblog", + name="title", + field=models.CharField(default="", max_length=255, verbose_name="title"), preserve_default=False, ), ] diff --git a/djangocms_blog/liveblog/migrations/0003_auto_20160917_0123.py b/djangocms_blog/liveblog/migrations/0003_auto_20160917_0123.py index 765e379d..d58cf6ee 100644 --- a/djangocms_blog/liveblog/migrations/0003_auto_20160917_0123.py +++ b/djangocms_blog/liveblog/migrations/0003_auto_20160917_0123.py @@ -1,27 +1,32 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.9.9 on 2016-09-16 23:23 -from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion import django.utils.timezone +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('liveblog', '0002_liveblog_title'), + ("liveblog", "0002_liveblog_title"), ] operations = [ migrations.AddField( - model_name='liveblog', - name='post_date', - field=models.DateTimeField(blank=True, default=django.utils.timezone.now, verbose_name='post date'), + model_name="liveblog", + name="post_date", + field=models.DateTimeField(blank=True, default=django.utils.timezone.now, verbose_name="post date"), ), migrations.AlterField( - model_name='liveblog', - name='cmsplugin_ptr', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='liveblog_liveblog', serialize=False, to='cms.CMSPlugin'), + model_name="liveblog", + name="cmsplugin_ptr", + field=models.OneToOneField( + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + related_name="liveblog_liveblog", + serialize=False, + to="cms.CMSPlugin", + ), ), ] diff --git a/djangocms_blog/liveblog/models.py b/djangocms_blog/liveblog/models.py index 45358873..a648c5c4 100644 --- a/djangocms_blog/liveblog/models.py +++ b/djangocms_blog/liveblog/models.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from operator import itemgetter from asgiref.sync import async_to_sync @@ -8,16 +7,14 @@ from django.db import models from django.template import Context from django.utils.timezone import now -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from djangocms_text_ckeditor.models import AbstractText from filer.fields.image import FilerImageField -from six import python_2_unicode_compatible from djangocms_blog.models import Post, thumbnail_model from djangocms_blog.settings import DATE_FORMAT -@python_2_unicode_compatible class LiveblogInterface(models.Model): """ Abstract Liveblog plugin model, reusable to customize the liveblogging @@ -26,12 +23,13 @@ class LiveblogInterface(models.Model): When implementing this, you **must** call ``self._post_save()`` in the concrete plugin model ``save`` method. """ - publish = models.BooleanField(_('publish liveblog entry'), default=False) - post_date = models.DateTimeField(_('post date'), blank=True, default=now) + + publish = models.BooleanField(_("publish liveblog entry"), default=False) + post_date = models.DateTimeField(_("post date"), blank=True, default=now) class Meta: - verbose_name = _('liveblog entry') - verbose_name_plural = _('liveblog entries') + verbose_name = _("liveblog entry") + verbose_name_plural = _("liveblog entries") abstract = True def __str__(self): @@ -45,10 +43,8 @@ def _post_save(self): """ items = [] for model in LiveblogInterface.__subclasses__(): - items.extend( - model.objects.filter(placeholder=self.placeholder).values('pk', 'post_date') - ) - order = reversed([item['pk'] for item in sorted(items, key=itemgetter('post_date'))]) + items.extend(model.objects.filter(placeholder=self.placeholder).values("pk", "post_date")) + order = reversed([item["pk"] for item in sorted(items, key=itemgetter("post_date"))]) reorder_plugins(self.placeholder, None, self.language, order) @property @@ -58,16 +54,11 @@ def liveblog_group(self): return post.liveblog_group def render(self, request): - context = Context({ - 'request': request - }) + context = Context({"request": request}) from cms.plugin_rendering import ContentRenderer + renderer = ContentRenderer(request) - return renderer.render_plugin( - instance=self, - context=context, - placeholder=self.placeholder, - ) + return renderer.render_plugin(instance=self, context=context, placeholder=self.placeholder,) def send(self, request): """ @@ -76,11 +67,11 @@ def send(self, request): if self.liveblog_group: content = self.render(request) notification = { - 'id': self.pk, - 'content': content, - 'creation_date': self.post_date.strftime(DATE_FORMAT), - 'changed_date': self.changed_date.strftime(DATE_FORMAT), - 'type': 'send.json', + "id": self.pk, + "content": content, + "creation_date": self.post_date.strftime(DATE_FORMAT), + "changed_date": self.changed_date.strftime(DATE_FORMAT), + "type": "send.json", } channel_layer = get_channel_layer() async_to_sync(channel_layer.group_send)(self.liveblog_group, notification) @@ -90,27 +81,33 @@ class Liveblog(LiveblogInterface, AbstractText): """ Basic liveblog plugin model """ + cmsplugin_ptr = models.OneToOneField( - CMSPlugin, - related_name='%(app_label)s_%(class)s', primary_key=True, - parent_link=True, on_delete=models.CASCADE + CMSPlugin, related_name="%(app_label)s_%(class)s", primary_key=True, parent_link=True, on_delete=models.CASCADE ) - title = models.CharField(_('title'), max_length=255) + title = models.CharField(_("title"), max_length=255) image = FilerImageField( - verbose_name=_('image'), blank=True, null=True, on_delete=models.SET_NULL, - related_name='djangocms_blog_liveblog_image' + verbose_name=_("image"), + blank=True, + null=True, + on_delete=models.SET_NULL, + related_name="djangocms_blog_liveblog_image", ) thumbnail = models.ForeignKey( - thumbnail_model, verbose_name=_('thumbnail size'), on_delete=models.SET_NULL, - blank=True, null=True, related_name='djangocms_blog_liveblog_thumbnail' + thumbnail_model, + verbose_name=_("thumbnail size"), + on_delete=models.SET_NULL, + blank=True, + null=True, + related_name="djangocms_blog_liveblog_thumbnail", ) class Meta: - verbose_name = _('liveblog entry') - verbose_name_plural = _('liveblog entries') + verbose_name = _("liveblog entry") + verbose_name_plural = _("liveblog entries") def save(self, *args, **kwargs): - super(Liveblog, self).save(*args, **kwargs) + super().save(*args, **kwargs) self._post_save() def __str__(self): diff --git a/djangocms_blog/liveblog/routing.py b/djangocms_blog/liveblog/routing.py index 3a5b3857..c550a0bd 100644 --- a/djangocms_blog/liveblog/routing.py +++ b/djangocms_blog/liveblog/routing.py @@ -1,10 +1,6 @@ -# -*- coding: utf-8 -*- - from channels.routing import URLRouter from django.urls import path from .consumers import LiveblogConsumer -channel_routing = URLRouter([ - path('///', LiveblogConsumer), -]) +channel_routing = URLRouter([path("///", LiveblogConsumer)]) diff --git a/djangocms_blog/liveblog/static/liveblog/js/liveblog.js b/djangocms_blog/liveblog/static/liveblog/js/liveblog.js index 4fcdd790..52e6b3ea 100644 --- a/djangocms_blog/liveblog/static/liveblog/js/liveblog.js +++ b/djangocms_blog/liveblog/static/liveblog/js/liveblog.js @@ -22,4 +22,3 @@ document.addEventListener("DOMContentLoaded", function() { }; }, false); - diff --git a/djangocms_blog/locale/ar/LC_MESSAGES/django.po b/djangocms_blog/locale/ar/LC_MESSAGES/django.po index 35a98c97..3df473c5 100644 --- a/djangocms_blog/locale/ar/LC_MESSAGES/django.po +++ b/djangocms_blog/locale/ar/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # Bashar Al-Abdulhadi, 2016 # Bashar Al-Abdulhadi, 2014 diff --git a/djangocms_blog/locale/de/LC_MESSAGES/django.po b/djangocms_blog/locale/de/LC_MESSAGES/django.po index bfb0bfef..e4f8fb51 100644 --- a/djangocms_blog/locale/de/LC_MESSAGES/django.po +++ b/djangocms_blog/locale/de/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # Christoph Reimers , 2014 # fsbraun , 2016 diff --git a/djangocms_blog/locale/es/LC_MESSAGES/django.po b/djangocms_blog/locale/es/LC_MESSAGES/django.po index 9bac9df8..a9c78ac6 100644 --- a/djangocms_blog/locale/es/LC_MESSAGES/django.po +++ b/djangocms_blog/locale/es/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # David , 2015 msgid "" diff --git a/djangocms_blog/locale/et/LC_MESSAGES/django.po b/djangocms_blog/locale/et/LC_MESSAGES/django.po index 16bd553b..0915fd5d 100644 --- a/djangocms_blog/locale/et/LC_MESSAGES/django.po +++ b/djangocms_blog/locale/et/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # Rivo Zängov , 2018 msgid "" diff --git a/djangocms_blog/locale/fr/LC_MESSAGES/django.po b/djangocms_blog/locale/fr/LC_MESSAGES/django.po index 91db1be0..bfd1ff67 100644 --- a/djangocms_blog/locale/fr/LC_MESSAGES/django.po +++ b/djangocms_blog/locale/fr/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # Alban Tiberghien , 2017 # Iacopo Spalletti, 2014 diff --git a/djangocms_blog/locale/it/LC_MESSAGES/django.po b/djangocms_blog/locale/it/LC_MESSAGES/django.po index 27f36bdf..7f697d4d 100644 --- a/djangocms_blog/locale/it/LC_MESSAGES/django.po +++ b/djangocms_blog/locale/it/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # Iacopo Spalletti, 2014 # yakky , 2014-2019 diff --git a/djangocms_blog/locale/lt/LC_MESSAGES/django.po b/djangocms_blog/locale/lt/LC_MESSAGES/django.po index 4370d77f..c874dead 100644 --- a/djangocms_blog/locale/lt/LC_MESSAGES/django.po +++ b/djangocms_blog/locale/lt/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # Matas Dailyda , 2015-2018 msgid "" diff --git a/djangocms_blog/locale/nb_NO/LC_MESSAGES/django.po b/djangocms_blog/locale/nb_NO/LC_MESSAGES/django.po index 2f7b73c5..5affc801 100644 --- a/djangocms_blog/locale/nb_NO/LC_MESSAGES/django.po +++ b/djangocms_blog/locale/nb_NO/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # fivethreeo , 2016 # fivethreeo , 2016 diff --git a/djangocms_blog/locale/nl/LC_MESSAGES/django.po b/djangocms_blog/locale/nl/LC_MESSAGES/django.po index 390f3320..85e2edc7 100644 --- a/djangocms_blog/locale/nl/LC_MESSAGES/django.po +++ b/djangocms_blog/locale/nl/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # René Mulder , 2016 # Zingende Vogel , 2018 diff --git a/djangocms_blog/locale/pl_PL/LC_MESSAGES/django.po b/djangocms_blog/locale/pl_PL/LC_MESSAGES/django.po index 48870696..fec08ba8 100644 --- a/djangocms_blog/locale/pl_PL/LC_MESSAGES/django.po +++ b/djangocms_blog/locale/pl_PL/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # marcingarbarczykapz , 2019 msgid "" diff --git a/djangocms_blog/locale/pt_BR/LC_MESSAGES/django.po b/djangocms_blog/locale/pt_BR/LC_MESSAGES/django.po index bbebf93d..a5fb4616 100644 --- a/djangocms_blog/locale/pt_BR/LC_MESSAGES/django.po +++ b/djangocms_blog/locale/pt_BR/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # Diego Ponci , 2016 msgid "" diff --git a/djangocms_blog/locale/ru/LC_MESSAGES/django.po b/djangocms_blog/locale/ru/LC_MESSAGES/django.po index 98677048..6e724888 100644 --- a/djangocms_blog/locale/ru/LC_MESSAGES/django.po +++ b/djangocms_blog/locale/ru/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # Iacopo Spalletti, 2014 # Rustam Mirzaev , 2016-2018 diff --git a/djangocms_blog/locale/sl/LC_MESSAGES/django.po b/djangocms_blog/locale/sl/LC_MESSAGES/django.po index e2e37df0..81024fcf 100644 --- a/djangocms_blog/locale/sl/LC_MESSAGES/django.po +++ b/djangocms_blog/locale/sl/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # Iacopo Spalletti, 2014 msgid "" diff --git a/djangocms_blog/locale/tr/LC_MESSAGES/django.po b/djangocms_blog/locale/tr/LC_MESSAGES/django.po index 4349a97a..a62e8aa5 100644 --- a/djangocms_blog/locale/tr/LC_MESSAGES/django.po +++ b/djangocms_blog/locale/tr/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # Rustam Mirzaev , 2016,2018 # Rustam Mirzaev , 2015 diff --git a/djangocms_blog/managers.py b/djangocms_blog/managers.py index d8ce3ec9..2c95493a 100644 --- a/djangocms_blog/managers.py +++ b/djangocms_blog/managers.py @@ -1,9 +1,6 @@ -# -*- coding: utf-8 -*- from collections import Counter -from aldryn_apphooks_config.managers.parler import ( - AppHookConfigTranslatableManager, AppHookConfigTranslatableQueryset, -) +from aldryn_apphooks_config.managers.parler import AppHookConfigTranslatableManager, AppHookConfigTranslatableQueryset from django.contrib.contenttypes.models import ContentType from django.contrib.sites.models import Site from django.db import models @@ -11,7 +8,6 @@ class TaggedFilterItem: - def tagged(self, other_model=None, queryset=None): """ Restituisce una queryset di elementi del model taggati, @@ -26,21 +22,24 @@ def _taglist(self, other_model=None, queryset=None): o queryset passati come argomento """ from taggit.models import TaggedItem - filter = None + + filters = None if queryset is not None: - filter = set() + filters = set() for item in queryset.all(): - filter.update(item.tags.all()) - filter = set([tag.id for tag in filter]) + filters.update(item.tags.all()) + filters = {tag.id for tag in filters} elif other_model is not None: - filter = set(TaggedItem.objects.filter( - content_type__model=other_model.__name__.lower() - ).values_list('tag_id', flat=True)) - tags = set(TaggedItem.objects.filter( - content_type__model=self.model.__name__.lower() - ).values_list('tag_id', flat=True)) - if filter is not None: - tags = tags.intersection(filter) + filters = set( + TaggedItem.objects.filter(content_type__model=other_model.__name__.lower()).values_list( + "tag_id", flat=True + ) + ) + tags = set( + TaggedItem.objects.filter(content_type__model=self.model.__name__.lower()).values_list("tag_id", flat=True) + ) + if filters is not None: + tags = tags.intersection(filters) return list(tags) def tag_list(self, other_model=None, queryset=None): @@ -49,29 +48,32 @@ def tag_list(self, other_model=None, queryset=None): al model o queryset passati come argomento """ from taggit.models import Tag + return Tag.objects.filter(id__in=self._taglist(other_model, queryset)) def tag_list_slug(self, other_model=None, queryset=None): queryset = self.tag_list(other_model, queryset) - return queryset.values('slug') + return queryset.values("slug") def tag_cloud(self, other_model=None, queryset=None, published=True, on_site=False): from taggit.models import TaggedItem + if on_site: queryset = queryset.on_site() tag_ids = self._taglist(other_model, queryset) kwargs = {} if published: kwargs = { - 'object_id__in': self.model.objects.published(), - 'content_type': ContentType.objects.get_for_model(self.model), + "object_id__in": self.model.objects.published(), + "content_type": ContentType.objects.get_for_model(self.model), } - kwargs['tag_id__in'] = tag_ids - counted_tags = dict(TaggedItem.objects - .filter(**kwargs) - .values('tag') - .annotate(count=models.Count('tag')) - .values_list('tag', 'count')) + kwargs["tag_id__in"] = tag_ids + counted_tags = dict( + TaggedItem.objects.filter(**kwargs) + .values("tag") + .annotate(count=models.Count("tag")) + .values_list("tag", "count") + ) tags = TaggedItem.tag_model().objects.filter(pk__in=counted_tags.keys()) for tag in tags: tag.count = counted_tags[tag.pk] @@ -79,22 +81,20 @@ def tag_cloud(self, other_model=None, queryset=None, published=True, on_site=Fal class GenericDateQuerySet(AppHookConfigTranslatableQueryset): - start_date_field = 'date_published' - fallback_date_field = 'date_modified' - end_date_field = 'date_published_end' - publish_field = 'publish' + start_date_field = "date_published" + fallback_date_field = "date_modified" + end_date_field = "date_published_end" + publish_field = "publish" def on_site(self, site=None): if not site: site = Site.objects.get_current() - return self.filter(models.Q(sites__isnull=True) | - models.Q(sites=site.pk)) + return self.filter(models.Q(sites__isnull=True) | models.Q(sites=site.pk)) def published(self, current_site=True): queryset = self.published_future(current_site) if self.start_date_field: - return queryset.filter( - **{'%s__lte' % self.start_date_field: now()}) + return queryset.filter(**{"%s__lte" % self.start_date_field: now()}) else: return queryset @@ -104,9 +104,8 @@ def published_future(self, current_site=True): else: queryset = self if self.end_date_field: - qfilter = ( - models.Q(**{'%s__gte' % self.end_date_field: now()}) | - models.Q(**{'%s__isnull' % self.end_date_field: True}) + qfilter = models.Q(**{"%s__gte" % self.end_date_field: now()}) | models.Q( + **{"%s__isnull" % self.end_date_field: True} ) queryset = queryset.filter(qfilter) return queryset.filter(**{self.publish_field: True}) @@ -117,9 +116,7 @@ def archived(self, current_site=True): else: queryset = self if self.end_date_field: - qfilter = ( - models.Q(**{'%s__lte' % self.end_date_field: now()}) - ) + qfilter = models.Q(**{"%s__lte" % self.end_date_field: now()}) queryset = queryset.filter(qfilter) return queryset.filter(**{self.publish_field: True}) @@ -142,7 +139,7 @@ class GenericDateTaggedManager(TaggedFilterItem, AppHookConfigTranslatableManage queryset_class = GenericDateQuerySet def get_queryset(self, *args, **kwargs): - return super(GenericDateTaggedManager, self).get_queryset(*args, **kwargs) + return super().get_queryset(*args, **kwargs) def published(self, current_site=True): return self.get_queryset().published(current_site) @@ -182,5 +179,7 @@ def get_months(self, queryset=None, current_site=True): date_counter = Counter(dates) dates = set(dates) dates = sorted(dates, reverse=True) - return [{'date': now().replace(year=year, month=month, day=1), - 'count': date_counter[year, month]} for year, month in dates] + return [ + {"date": now().replace(year=year, month=month, day=1), "count": date_counter[year, month]} + for year, month in dates + ] diff --git a/djangocms_blog/media/__init__.py b/djangocms_blog/media/__init__.py index 40a96afc..e69de29b 100644 --- a/djangocms_blog/media/__init__.py +++ b/djangocms_blog/media/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/djangocms_blog/media/base.py b/djangocms_blog/media/base.py index 2c366069..f24c9f94 100644 --- a/djangocms_blog/media/base.py +++ b/djangocms_blog/media/base.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- class MediaAttachmentPluginMixin: """ Base class for media-enabled plugins. @@ -9,11 +8,12 @@ class MediaAttachmentPluginMixin: * media_url: property that provides the media public URL * _media_autoconfiguration: configuration dictionary (see documentation for details) """ + _media_autoconfiguration = { - 'params': [], - 'thumb_url': '', - 'main_url': '', - 'callable': None, + "params": [], + "thumb_url": "", + "main_url": "", + "callable": None, } """ Configuration dictionary. **All** the keys are required: @@ -55,16 +55,16 @@ def media_params(self): :rtype: dict """ if not self._cached_params: - for pattern in self._media_autoconfiguration['params']: + for pattern in self._media_autoconfiguration["params"]: match = pattern.match(self.media_url) if match: - if self._media_autoconfiguration['callable']: - self._cached_params = getattr( - self, self._media_autoconfiguration['callable'] - )(**match.groupdict()) + if self._media_autoconfiguration["callable"]: + self._cached_params = getattr(self, self._media_autoconfiguration["callable"])( + **match.groupdict() + ) else: self._cached_params = match.groupdict() - self._cached_params['url'] = self.media_url + self._cached_params["url"] = self.media_url return self._cached_params @property @@ -88,8 +88,8 @@ def media_id(self): :rtype: str """ try: - return self.media_params['media_id'] - except KeyError: + return self.media_params["media_id"] + except KeyError: # pragma: no cover return None def get_main_image(self): @@ -98,7 +98,7 @@ def get_main_image(self): :rtype: str """ - return self._media_autoconfiguration['main_url'] % self.media_params + return self._media_autoconfiguration["main_url"] % self.media_params def get_thumb_image(self): """ @@ -106,4 +106,4 @@ def get_thumb_image(self): :rtype: str """ - return self._media_autoconfiguration['thumb_url'] % self.media_params + return self._media_autoconfiguration["thumb_url"] % self.media_params diff --git a/djangocms_blog/migrations/0001_initial.py b/djangocms_blog/migrations/0001_initial.py index b29811d4..34f76813 100644 --- a/djangocms_blog/migrations/0001_initial.py +++ b/djangocms_blog/migrations/0001_initial.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - import cms.models.fields import django.utils.timezone import djangocms_text_ckeditor.fields @@ -9,10 +6,11 @@ import taggit_autosuggest.managers from django.conf import settings from django.db import migrations, models -from djangocms_blog.models import thumbnail_model from filer.settings import FILER_IMAGE_MODEL -ACTUAL_FILER_IMAGE_MODEL = FILER_IMAGE_MODEL or 'filer.Image' +from djangocms_blog.models import thumbnail_model + +ACTUAL_FILER_IMAGE_MODEL = FILER_IMAGE_MODEL or "filer.Image" class Migration(migrations.Migration): @@ -20,120 +18,261 @@ class Migration(migrations.Migration): dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), migrations.swappable_dependency(ACTUAL_FILER_IMAGE_MODEL), - ('cms', '__first__'), - ('taggit', '__first__'), - ('filer', '0003_thumbnailoption'), + ("cms", "__first__"), + ("taggit", "__first__"), + ("filer", "0003_thumbnailoption"), ] operations = [ migrations.CreateModel( - name='AuthorEntriesPlugin', + name="AuthorEntriesPlugin", fields=[ - ('cmsplugin_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='cms.CMSPlugin', on_delete=models.deletion.CASCADE)), - ('latest_posts', models.IntegerField(default=5, help_text='The number of author articles to be displayed.', verbose_name='Articles')), - ('authors', models.ManyToManyField(to=settings.AUTH_USER_MODEL, verbose_name='Authors')), + ( + "cmsplugin_ptr", + models.OneToOneField( + parent_link=True, + auto_created=True, + primary_key=True, + serialize=False, + to="cms.CMSPlugin", + on_delete=models.deletion.CASCADE, + ), + ), + ( + "latest_posts", + models.IntegerField( + default=5, help_text="The number of author articles to be displayed.", verbose_name="Articles" + ), + ), + ("authors", models.ManyToManyField(to=settings.AUTH_USER_MODEL, verbose_name="Authors")), ], - options={ - 'abstract': False, - }, - bases=('cms.cmsplugin',), + options={"abstract": False,}, + bases=("cms.cmsplugin",), ), migrations.CreateModel( - name='BlogCategory', + name="BlogCategory", fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='created at')), - ('date_modified', models.DateTimeField(auto_now=True, verbose_name='modified at')), - ('parent', models.ForeignKey(verbose_name='parent', blank=True, to='djangocms_blog.BlogCategory', null=True, on_delete=models.deletion.CASCADE)), + ("id", models.AutoField(verbose_name="ID", serialize=False, auto_created=True, primary_key=True)), + ("date_created", models.DateTimeField(auto_now_add=True, verbose_name="created at")), + ("date_modified", models.DateTimeField(auto_now=True, verbose_name="modified at")), + ( + "parent", + models.ForeignKey( + verbose_name="parent", + blank=True, + to="djangocms_blog.BlogCategory", + null=True, + on_delete=models.deletion.CASCADE, + ), + ), ], - options={ - 'verbose_name': 'blog category', - 'verbose_name_plural': 'blog categories', - }, + options={"verbose_name": "blog category", "verbose_name_plural": "blog categories",}, bases=(models.Model,), ), migrations.CreateModel( - name='BlogCategoryTranslation', + name="BlogCategoryTranslation", fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('language_code', models.CharField(db_index=True, max_length=15, verbose_name='Language', choices=settings.LANGUAGES)), - ('name', models.CharField(max_length=255, verbose_name='name')), - ('slug', models.SlugField(verbose_name='slug', blank=True)), - ('master', models.ForeignKey(related_name='translations', editable=False, to='djangocms_blog.BlogCategory', null=True, on_delete=models.deletion.CASCADE)), + ("id", models.AutoField(verbose_name="ID", serialize=False, auto_created=True, primary_key=True)), + ( + "language_code", + models.CharField( + db_index=True, max_length=15, verbose_name="Language", choices=settings.LANGUAGES + ), + ), + ("name", models.CharField(max_length=255, verbose_name="name")), + ("slug", models.SlugField(verbose_name="slug", blank=True)), + ( + "master", + models.ForeignKey( + related_name="translations", + editable=False, + to="djangocms_blog.BlogCategory", + null=True, + on_delete=models.deletion.CASCADE, + ), + ), ], options={ - 'db_table': 'djangocms_blog_blogcategory_translation', - 'verbose_name': 'blog category Translation', - 'default_permissions': (), + "db_table": "djangocms_blog_blogcategory_translation", + "verbose_name": "blog category Translation", + "default_permissions": (), }, bases=(models.Model,), ), migrations.CreateModel( - name='LatestPostsPlugin', + name="LatestPostsPlugin", fields=[ - ('cmsplugin_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='cms.CMSPlugin', on_delete=models.deletion.CASCADE)), - ('latest_posts', models.IntegerField(default=5, help_text='The number of latests articles to be displayed.', verbose_name='Articles')), - ('categories', models.ManyToManyField(help_text='Show only the blog articles tagged with chosen categories.', to='djangocms_blog.BlogCategory', blank=True)), - ('tags', models.ManyToManyField(help_text='Show only the blog articles tagged with chosen tags.', to='taggit.Tag', blank=True)), + ( + "cmsplugin_ptr", + models.OneToOneField( + parent_link=True, + auto_created=True, + primary_key=True, + serialize=False, + to="cms.CMSPlugin", + on_delete=models.deletion.CASCADE, + ), + ), + ( + "latest_posts", + models.IntegerField( + default=5, help_text="The number of latests articles to be displayed.", verbose_name="Articles" + ), + ), + ( + "categories", + models.ManyToManyField( + help_text="Show only the blog articles tagged with chosen categories.", + to="djangocms_blog.BlogCategory", + blank=True, + ), + ), + ( + "tags", + models.ManyToManyField( + help_text="Show only the blog articles tagged with chosen tags.", to="taggit.Tag", blank=True + ), + ), ], - options={ - 'abstract': False, - }, - bases=('cms.cmsplugin',), + options={"abstract": False,}, + bases=("cms.cmsplugin",), ), migrations.CreateModel( - name='Post', + name="Post", fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('date_created', models.DateTimeField(auto_now_add=True)), - ('date_modified', models.DateTimeField(auto_now=True)), - ('date_published', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Published Since')), - ('date_published_end', models.DateTimeField(null=True, verbose_name='Published Until', blank=True)), - ('publish', models.BooleanField(default=False, verbose_name='Publish')), - ('enable_comments', models.BooleanField(default=True, verbose_name='Enable comments on post')), - ('author', models.ForeignKey(related_name='djangocms_blog_post_author', verbose_name='Author', blank=True, to=settings.AUTH_USER_MODEL, null=True, on_delete=models.deletion.PROTECT)), - ('categories', models.ManyToManyField(related_name='blog_posts', verbose_name='category', to='djangocms_blog.BlogCategory')), - ('content', cms.models.fields.PlaceholderField(slotname='post_content', editable=False, to='cms.Placeholder', null=True)), - ('main_image', filer.fields.image.FilerImageField(related_name='djangocms_blog_post_image', verbose_name='Main image', blank=True, to=ACTUAL_FILER_IMAGE_MODEL, null=True, on_delete=models.deletion.SET_NULL)), - ('main_image_full', models.ForeignKey(related_name='djangocms_blog_post_full', verbose_name='Main image full', blank=True, to=thumbnail_model, null=True, on_delete=models.deletion.SET_NULL)), - ('main_image_thumbnail', models.ForeignKey(related_name='djangocms_blog_post_thumbnail', verbose_name='Main image thumbnail', blank=True, to=thumbnail_model, null=True, on_delete=models.deletion.SET_NULL)), - ('tags', taggit_autosuggest.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags')), + ("id", models.AutoField(verbose_name="ID", serialize=False, auto_created=True, primary_key=True)), + ("date_created", models.DateTimeField(auto_now_add=True)), + ("date_modified", models.DateTimeField(auto_now=True)), + ( + "date_published", + models.DateTimeField(default=django.utils.timezone.now, verbose_name="Published Since"), + ), + ("date_published_end", models.DateTimeField(null=True, verbose_name="Published Until", blank=True)), + ("publish", models.BooleanField(default=False, verbose_name="Publish")), + ("enable_comments", models.BooleanField(default=True, verbose_name="Enable comments on post")), + ( + "author", + models.ForeignKey( + related_name="djangocms_blog_post_author", + verbose_name="Author", + blank=True, + to=settings.AUTH_USER_MODEL, + null=True, + on_delete=models.deletion.PROTECT, + ), + ), + ( + "categories", + models.ManyToManyField( + related_name="blog_posts", verbose_name="category", to="djangocms_blog.BlogCategory" + ), + ), + ( + "content", + cms.models.fields.PlaceholderField( + slotname="post_content", editable=False, to="cms.Placeholder", null=True + ), + ), + ( + "main_image", + filer.fields.image.FilerImageField( + related_name="djangocms_blog_post_image", + verbose_name="Main image", + blank=True, + to=ACTUAL_FILER_IMAGE_MODEL, + null=True, + on_delete=models.deletion.SET_NULL, + ), + ), + ( + "main_image_full", + models.ForeignKey( + related_name="djangocms_blog_post_full", + verbose_name="Main image full", + blank=True, + to=thumbnail_model, + null=True, + on_delete=models.deletion.SET_NULL, + ), + ), + ( + "main_image_thumbnail", + models.ForeignKey( + related_name="djangocms_blog_post_thumbnail", + verbose_name="Main image thumbnail", + blank=True, + to=thumbnail_model, + null=True, + on_delete=models.deletion.SET_NULL, + ), + ), + ( + "tags", + taggit_autosuggest.managers.TaggableManager( + to="taggit.Tag", + through="taggit.TaggedItem", + blank=True, + help_text="A comma-separated list of tags.", + verbose_name="Tags", + ), + ), ], options={ - 'ordering': ('-date_published', '-date_created'), - 'get_latest_by': 'date_published', - 'verbose_name': 'blog article', - 'verbose_name_plural': 'blog articles', + "ordering": ("-date_published", "-date_created"), + "get_latest_by": "date_published", + "verbose_name": "blog article", + "verbose_name_plural": "blog articles", }, bases=(meta.models.ModelMeta, models.Model), ), migrations.CreateModel( - name='PostTranslation', + name="PostTranslation", fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('language_code', models.CharField(db_index=True, max_length=15, verbose_name='Language', choices=settings.LANGUAGES)), - ('title', models.CharField(max_length=255, verbose_name='Title')), - ('slug', models.SlugField(verbose_name='slug', blank=True)), - ('abstract', djangocms_text_ckeditor.fields.HTMLField(verbose_name='Abstract')), - ('meta_description', models.TextField(default='', verbose_name='Post meta description', blank=True)), - ('meta_keywords', models.TextField(default='', verbose_name='Post meta keywords', blank=True)), - ('meta_title', models.CharField(default='', help_text='used in title tag and social sharing', max_length=255, verbose_name='Post meta title', blank=True)), - ('post_text', djangocms_text_ckeditor.fields.HTMLField(default='', verbose_name='Text', blank=True)), - ('master', models.ForeignKey(related_name='translations', editable=False, to='djangocms_blog.Post', null=True, on_delete=models.deletion.CASCADE)), + ("id", models.AutoField(verbose_name="ID", serialize=False, auto_created=True, primary_key=True)), + ( + "language_code", + models.CharField( + db_index=True, max_length=15, verbose_name="Language", choices=settings.LANGUAGES + ), + ), + ("title", models.CharField(max_length=255, verbose_name="Title")), + ("slug", models.SlugField(verbose_name="slug", blank=True)), + ("abstract", djangocms_text_ckeditor.fields.HTMLField(verbose_name="Abstract")), + ("meta_description", models.TextField(default="", verbose_name="Post meta description", blank=True)), + ("meta_keywords", models.TextField(default="", verbose_name="Post meta keywords", blank=True)), + ( + "meta_title", + models.CharField( + default="", + help_text="used in title tag and social sharing", + max_length=255, + verbose_name="Post meta title", + blank=True, + ), + ), + ("post_text", djangocms_text_ckeditor.fields.HTMLField(default="", verbose_name="Text", blank=True)), + ( + "master", + models.ForeignKey( + related_name="translations", + editable=False, + to="djangocms_blog.Post", + null=True, + on_delete=models.deletion.CASCADE, + ), + ), ], options={ - 'db_table': 'djangocms_blog_post_translation', - 'verbose_name': 'blog article Translation', - 'default_permissions': (), + "db_table": "djangocms_blog_post_translation", + "verbose_name": "blog article Translation", + "default_permissions": (), }, bases=(models.Model,), ), migrations.AlterUniqueTogether( - name='posttranslation', - unique_together=set([('language_code', 'master'), ('language_code', 'slug')]), + name="posttranslation", unique_together={("language_code", "master"), ("language_code", "slug")}, ), migrations.AlterUniqueTogether( - name='blogcategorytranslation', - unique_together=set([('language_code', 'master'), ('language_code', 'slug')]), + name="blogcategorytranslation", unique_together={("language_code", "master"), ("language_code", "slug")}, ), ] diff --git a/djangocms_blog/migrations/0002_post_sites.py b/djangocms_blog/migrations/0002_post_sites.py index 65b75be1..b9dedfc0 100644 --- a/djangocms_blog/migrations/0002_post_sites.py +++ b/djangocms_blog/migrations/0002_post_sites.py @@ -1,21 +1,24 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('sites', '__first__'), - ('djangocms_blog', '0001_initial'), + ("sites", "__first__"), + ("djangocms_blog", "0001_initial"), ] operations = [ migrations.AddField( - model_name='post', - name='sites', - field=models.ManyToManyField(help_text='Select sites in which to show the post. If none is set it will bevisible in all the configured sites.', to='sites.Site', null=True, verbose_name='Site(s', blank=True), + model_name="post", + name="sites", + field=models.ManyToManyField( + help_text="Select sites in which to show the post. If none is set it will bevisible in all the configured sites.", + to="sites.Site", + null=True, + verbose_name="Site(s", + blank=True, + ), preserve_default=True, ), ] diff --git a/djangocms_blog/migrations/0003_auto_20141201_2252.py b/djangocms_blog/migrations/0003_auto_20141201_2252.py index f59bbd3b..ba35353d 100644 --- a/djangocms_blog/migrations/0003_auto_20141201_2252.py +++ b/djangocms_blog/migrations/0003_auto_20141201_2252.py @@ -1,20 +1,23 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0002_post_sites'), + ("djangocms_blog", "0002_post_sites"), ] operations = [ migrations.AlterField( - model_name='post', - name='sites', - field=models.ManyToManyField(help_text='Select sites in which to show the post. If none is set it will be visible in all the configured sites.', to='sites.Site', null=True, verbose_name='Site(s)', blank=True), + model_name="post", + name="sites", + field=models.ManyToManyField( + help_text="Select sites in which to show the post. If none is set it will be visible in all the configured sites.", + to="sites.Site", + null=True, + verbose_name="Site(s)", + blank=True, + ), preserve_default=True, ), ] diff --git a/djangocms_blog/migrations/0004_auto_20150108_1435.py b/djangocms_blog/migrations/0004_auto_20150108_1435.py index db4ecfae..6d77faa1 100644 --- a/djangocms_blog/migrations/0004_auto_20150108_1435.py +++ b/djangocms_blog/migrations/0004_auto_20150108_1435.py @@ -1,41 +1,59 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - import django.db.models.deletion import filer.fields.image from django.db import migrations, models -from djangocms_blog.models import thumbnail_model from filer.settings import FILER_IMAGE_MODEL -ACTUAL_FILER_IMAGE_MODEL = FILER_IMAGE_MODEL or 'filer.Image' +from djangocms_blog.models import thumbnail_model +ACTUAL_FILER_IMAGE_MODEL = FILER_IMAGE_MODEL or "filer.Image" -class Migration(migrations.Migration): +class Migration(migrations.Migration): dependencies = [ migrations.swappable_dependency(ACTUAL_FILER_IMAGE_MODEL), - ('djangocms_blog', '0003_auto_20141201_2252'), - ('filer', '0003_thumbnailoption'), + ("djangocms_blog", "0003_auto_20141201_2252"), + ("filer", "0003_thumbnailoption"), ] operations = [ migrations.AlterField( - model_name='post', - name='main_image', - field=filer.fields.image.FilerImageField(related_name='djangocms_blog_post_image', on_delete=django.db.models.deletion.SET_NULL, verbose_name='Main image', blank=True, to=ACTUAL_FILER_IMAGE_MODEL, null=True), + model_name="post", + name="main_image", + field=filer.fields.image.FilerImageField( + related_name="djangocms_blog_post_image", + on_delete=django.db.models.deletion.SET_NULL, + verbose_name="Main image", + blank=True, + to=ACTUAL_FILER_IMAGE_MODEL, + null=True, + ), preserve_default=True, ), migrations.AlterField( - model_name='post', - name='main_image_full', - field=models.ForeignKey(related_name='djangocms_blog_post_full', on_delete=django.db.models.deletion.SET_NULL, verbose_name='Main image full', blank=True, to=thumbnail_model, null=True), + model_name="post", + name="main_image_full", + field=models.ForeignKey( + related_name="djangocms_blog_post_full", + on_delete=django.db.models.deletion.SET_NULL, + verbose_name="Main image full", + blank=True, + to=thumbnail_model, + null=True, + ), preserve_default=True, ), migrations.AlterField( - model_name='post', - name='main_image_thumbnail', - field=models.ForeignKey(related_name='djangocms_blog_post_thumbnail', on_delete=django.db.models.deletion.SET_NULL, verbose_name='Main image thumbnail', blank=True, to=thumbnail_model, null=True), + model_name="post", + name="main_image_thumbnail", + field=models.ForeignKey( + related_name="djangocms_blog_post_thumbnail", + on_delete=django.db.models.deletion.SET_NULL, + verbose_name="Main image thumbnail", + blank=True, + to=thumbnail_model, + null=True, + ), preserve_default=True, ), ] diff --git a/djangocms_blog/migrations/0005_auto_20150212_1118.py b/djangocms_blog/migrations/0005_auto_20150212_1118.py index 60b0e42e..676f4a11 100644 --- a/djangocms_blog/migrations/0005_auto_20150212_1118.py +++ b/djangocms_blog/migrations/0005_auto_20150212_1118.py @@ -1,27 +1,26 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations import cms.models.fields +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0004_auto_20150108_1435'), + ("djangocms_blog", "0004_auto_20150108_1435"), ] operations = [ migrations.AlterField( - model_name='post', - name='content', - field=cms.models.fields.PlaceholderField(slotname='post_content', to='cms.Placeholder', null=True, related_name='post_content', editable=False), + model_name="post", + name="content", + field=cms.models.fields.PlaceholderField( + slotname="post_content", to="cms.Placeholder", null=True, related_name="post_content", editable=False + ), preserve_default=True, ), migrations.AlterField( - model_name='post', - name='enable_comments', - field=models.BooleanField(default=False, verbose_name='Enable comments on post'), + model_name="post", + name="enable_comments", + field=models.BooleanField(default=False, verbose_name="Enable comments on post"), preserve_default=True, ), ] diff --git a/djangocms_blog/migrations/0006_auto_20150214_1907.py b/djangocms_blog/migrations/0006_auto_20150214_1907.py index afa42347..63f37ada 100644 --- a/djangocms_blog/migrations/0006_auto_20150214_1907.py +++ b/djangocms_blog/migrations/0006_auto_20150214_1907.py @@ -1,21 +1,18 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations import djangocms_text_ckeditor.fields +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0005_auto_20150212_1118'), + ("djangocms_blog", "0005_auto_20150212_1118"), ] operations = [ migrations.AlterField( - model_name='posttranslation', - name='abstract', - field=djangocms_text_ckeditor.fields.HTMLField(verbose_name='Abstract', blank=True, default=''), + model_name="posttranslation", + name="abstract", + field=djangocms_text_ckeditor.fields.HTMLField(verbose_name="Abstract", blank=True, default=""), preserve_default=True, ), ] diff --git a/djangocms_blog/migrations/0007_auto_20150719_0933.py b/djangocms_blog/migrations/0007_auto_20150719_0933.py index b74bc464..cf0be381 100644 --- a/djangocms_blog/migrations/0007_auto_20150719_0933.py +++ b/djangocms_blog/migrations/0007_auto_20150719_0933.py @@ -1,171 +1,217 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - import django.db.models.deletion import django.utils.timezone import djangocms_text_ckeditor.fields import filer.fields.image from django.conf import settings from django.db import migrations, models -from djangocms_blog.models import thumbnail_model from filer.settings import FILER_IMAGE_MODEL -ACTUAL_FILER_IMAGE_MODEL = FILER_IMAGE_MODEL or 'filer.Image' +from djangocms_blog.models import thumbnail_model + +ACTUAL_FILER_IMAGE_MODEL = FILER_IMAGE_MODEL or "filer.Image" class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0006_auto_20150214_1907'), + ("djangocms_blog", "0006_auto_20150214_1907"), migrations.swappable_dependency(ACTUAL_FILER_IMAGE_MODEL), - ('filer', '0003_thumbnailoption'), + ("filer", "0003_thumbnailoption"), ] operations = [ migrations.AlterModelOptions( - name='blogcategorytranslation', - options={'managed': True, 'verbose_name': 'blog category Translation', 'default_permissions': ()}, + name="blogcategorytranslation", + options={"managed": True, "verbose_name": "blog category Translation", "default_permissions": ()}, ), migrations.AlterModelOptions( - name='posttranslation', - options={'managed': True, 'verbose_name': 'blog article Translation', 'default_permissions': ()}, + name="posttranslation", + options={"managed": True, "verbose_name": "blog article Translation", "default_permissions": ()}, ), migrations.AlterField( - model_name='authorentriesplugin', - name='authors', - field=models.ManyToManyField(verbose_name='authors', to=settings.AUTH_USER_MODEL), + model_name="authorentriesplugin", + name="authors", + field=models.ManyToManyField(verbose_name="authors", to=settings.AUTH_USER_MODEL), preserve_default=True, ), migrations.AlterField( - model_name='authorentriesplugin', - name='latest_posts', - field=models.IntegerField(help_text='The number of author articles to be displayed.', verbose_name='articles', default=5), + model_name="authorentriesplugin", + name="latest_posts", + field=models.IntegerField( + help_text="The number of author articles to be displayed.", verbose_name="articles", default=5 + ), preserve_default=True, ), migrations.AlterField( - model_name='blogcategorytranslation', - name='language_code', - field=models.CharField(db_index=True, verbose_name='Language', max_length=15), + model_name="blogcategorytranslation", + name="language_code", + field=models.CharField(db_index=True, verbose_name="Language", max_length=15), preserve_default=True, ), migrations.AlterField( - model_name='latestpostsplugin', - name='categories', - field=models.ManyToManyField(blank=True, help_text='Show only the blog articles tagged with chosen categories.', verbose_name='filter by category', to='djangocms_blog.BlogCategory'), + model_name="latestpostsplugin", + name="categories", + field=models.ManyToManyField( + blank=True, + help_text="Show only the blog articles tagged with chosen categories.", + verbose_name="filter by category", + to="djangocms_blog.BlogCategory", + ), preserve_default=True, ), migrations.AlterField( - model_name='latestpostsplugin', - name='latest_posts', - field=models.IntegerField(help_text='The number of latests articles to be displayed.', verbose_name='articles', default=5), + model_name="latestpostsplugin", + name="latest_posts", + field=models.IntegerField( + help_text="The number of latests articles to be displayed.", verbose_name="articles", default=5 + ), preserve_default=True, ), migrations.AlterField( - model_name='latestpostsplugin', - name='tags', - field=models.ManyToManyField(blank=True, help_text='Show only the blog articles tagged with chosen tags.', verbose_name='filter by tag', to='taggit.Tag'), + model_name="latestpostsplugin", + name="tags", + field=models.ManyToManyField( + blank=True, + help_text="Show only the blog articles tagged with chosen tags.", + verbose_name="filter by tag", + to="taggit.Tag", + ), preserve_default=True, ), migrations.AlterField( - model_name='post', - name='author', - field=models.ForeignKey(blank=True, verbose_name='author', to=settings.AUTH_USER_MODEL, related_name='djangocms_blog_post_author', null=True, on_delete=models.deletion.PROTECT), + model_name="post", + name="author", + field=models.ForeignKey( + blank=True, + verbose_name="author", + to=settings.AUTH_USER_MODEL, + related_name="djangocms_blog_post_author", + null=True, + on_delete=models.deletion.PROTECT, + ), preserve_default=True, ), migrations.AlterField( - model_name='post', - name='date_created', - field=models.DateTimeField(auto_now_add=True, verbose_name='created'), + model_name="post", + name="date_created", + field=models.DateTimeField(auto_now_add=True, verbose_name="created"), preserve_default=True, ), migrations.AlterField( - model_name='post', - name='date_modified', - field=models.DateTimeField(auto_now=True, verbose_name='last modified'), + model_name="post", + name="date_modified", + field=models.DateTimeField(auto_now=True, verbose_name="last modified"), preserve_default=True, ), migrations.AlterField( - model_name='post', - name='date_published', - field=models.DateTimeField(verbose_name='published Since', default=django.utils.timezone.now), + model_name="post", + name="date_published", + field=models.DateTimeField(verbose_name="published Since", default=django.utils.timezone.now), preserve_default=True, ), migrations.AlterField( - model_name='post', - name='date_published_end', - field=models.DateTimeField(blank=True, verbose_name='published Until', null=True), + model_name="post", + name="date_published_end", + field=models.DateTimeField(blank=True, verbose_name="published Until", null=True), preserve_default=True, ), migrations.AlterField( - model_name='post', - name='enable_comments', - field=models.BooleanField(verbose_name='enable comments on post', default=True), + model_name="post", + name="enable_comments", + field=models.BooleanField(verbose_name="enable comments on post", default=True), preserve_default=True, ), migrations.AlterField( - model_name='post', - name='main_image', - field=filer.fields.image.FilerImageField(on_delete=django.db.models.deletion.SET_NULL, blank=True, verbose_name='main image', to=ACTUAL_FILER_IMAGE_MODEL, related_name='djangocms_blog_post_image', null=True), + model_name="post", + name="main_image", + field=filer.fields.image.FilerImageField( + on_delete=django.db.models.deletion.SET_NULL, + blank=True, + verbose_name="main image", + to=ACTUAL_FILER_IMAGE_MODEL, + related_name="djangocms_blog_post_image", + null=True, + ), preserve_default=True, ), migrations.AlterField( - model_name='post', - name='main_image_full', - field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, blank=True, verbose_name='main image full', to=thumbnail_model, related_name='djangocms_blog_post_full', null=True), + model_name="post", + name="main_image_full", + field=models.ForeignKey( + on_delete=django.db.models.deletion.SET_NULL, + blank=True, + verbose_name="main image full", + to=thumbnail_model, + related_name="djangocms_blog_post_full", + null=True, + ), preserve_default=True, ), migrations.AlterField( - model_name='post', - name='main_image_thumbnail', - field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, blank=True, verbose_name='main image thumbnail', to=thumbnail_model, related_name='djangocms_blog_post_thumbnail', null=True), + model_name="post", + name="main_image_thumbnail", + field=models.ForeignKey( + on_delete=django.db.models.deletion.SET_NULL, + blank=True, + verbose_name="main image thumbnail", + to=thumbnail_model, + related_name="djangocms_blog_post_thumbnail", + null=True, + ), preserve_default=True, ), migrations.AlterField( - model_name='post', - name='publish', - field=models.BooleanField(verbose_name='publish', default=False), + model_name="post", + name="publish", + field=models.BooleanField(verbose_name="publish", default=False), preserve_default=True, ), migrations.AlterField( - model_name='posttranslation', - name='abstract', - field=djangocms_text_ckeditor.fields.HTMLField(verbose_name='abstract'), + model_name="posttranslation", + name="abstract", + field=djangocms_text_ckeditor.fields.HTMLField(verbose_name="abstract"), preserve_default=True, ), migrations.AlterField( - model_name='posttranslation', - name='language_code', - field=models.CharField(db_index=True, verbose_name='Language', max_length=15), + model_name="posttranslation", + name="language_code", + field=models.CharField(db_index=True, verbose_name="Language", max_length=15), preserve_default=True, ), migrations.AlterField( - model_name='posttranslation', - name='meta_description', - field=models.TextField(blank=True, verbose_name='post meta description', default=''), + model_name="posttranslation", + name="meta_description", + field=models.TextField(blank=True, verbose_name="post meta description", default=""), preserve_default=True, ), migrations.AlterField( - model_name='posttranslation', - name='meta_keywords', - field=models.TextField(blank=True, verbose_name='post meta keywords', default=''), + model_name="posttranslation", + name="meta_keywords", + field=models.TextField(blank=True, verbose_name="post meta keywords", default=""), preserve_default=True, ), migrations.AlterField( - model_name='posttranslation', - name='meta_title', - field=models.CharField(blank=True, help_text='used in title tag and social sharing', verbose_name='post meta title', max_length=255, default=''), + model_name="posttranslation", + name="meta_title", + field=models.CharField( + blank=True, + help_text="used in title tag and social sharing", + verbose_name="post meta title", + max_length=255, + default="", + ), preserve_default=True, ), migrations.AlterField( - model_name='posttranslation', - name='post_text', - field=djangocms_text_ckeditor.fields.HTMLField(blank=True, verbose_name='text', default=''), + model_name="posttranslation", + name="post_text", + field=djangocms_text_ckeditor.fields.HTMLField(blank=True, verbose_name="text", default=""), preserve_default=True, ), migrations.AlterField( - model_name='posttranslation', - name='title', - field=models.CharField(verbose_name='title', max_length=255), + model_name="posttranslation", + name="title", + field=models.CharField(verbose_name="title", max_length=255), preserve_default=True, ), ] diff --git a/djangocms_blog/migrations/0008_auto_20150814_0831.py b/djangocms_blog/migrations/0008_auto_20150814_0831.py index 8978a1f2..ba20b3e7 100644 --- a/djangocms_blog/migrations/0008_auto_20150814_0831.py +++ b/djangocms_blog/migrations/0008_auto_20150814_0831.py @@ -1,21 +1,18 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations import djangocms_text_ckeditor.fields +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0007_auto_20150719_0933'), + ("djangocms_blog", "0007_auto_20150719_0933"), ] operations = [ migrations.AlterField( - model_name='posttranslation', - name='abstract', - field=djangocms_text_ckeditor.fields.HTMLField(default=b'', verbose_name='abstract', blank=True), + model_name="posttranslation", + name="abstract", + field=djangocms_text_ckeditor.fields.HTMLField(default=b"", verbose_name="abstract", blank=True), preserve_default=True, ), ] diff --git a/djangocms_blog/migrations/0009_latestpostsplugin_tags_new.py b/djangocms_blog/migrations/0009_latestpostsplugin_tags_new.py index 045e2835..1d19d6b6 100644 --- a/djangocms_blog/migrations/0009_latestpostsplugin_tags_new.py +++ b/djangocms_blog/migrations/0009_latestpostsplugin_tags_new.py @@ -1,26 +1,25 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations -from django.contrib.contenttypes.models import ContentType import taggit_autosuggest.managers +from django.contrib.contenttypes.models import ContentType +from django.db import migrations, models def migrate_tags(apps, schema_editor): - LatestPostsPlugin = apps.get_model('djangocms_blog', 'LatestPostsPlugin') - Tag = apps.get_model('taggit', 'Tag') - TaggedItem = apps.get_model('taggit', 'TaggedItem') + LatestPostsPlugin = apps.get_model("djangocms_blog", "LatestPostsPlugin") + Tag = apps.get_model("taggit", "Tag") + TaggedItem = apps.get_model("taggit", "TaggedItem") plugin_content_type = ContentType.objects.get_for_model(LatestPostsPlugin) for tag in Tag.objects.all(): for plugin in tag.latestpostsplugin_set.all(): - if not TaggedItem.objects.filter(tag=tag, object_id=plugin.pk, content_type_id=plugin_content_type.pk).exists(): + if not TaggedItem.objects.filter( + tag=tag, object_id=plugin.pk, content_type_id=plugin_content_type.pk + ).exists(): TaggedItem.objects.create(tag=tag, object_id=plugin.pk, content_type_id=plugin_content_type.pk) def migrate_tags_reverse(apps, schema_editor): - LatestPostsPlugin = apps.get_model('djangocms_blog', 'LatestPostsPlugin') - Tag = apps.get_model('taggit', 'Tag') - TaggedItem = apps.get_model('taggit', 'TaggedItem') + LatestPostsPlugin = apps.get_model("djangocms_blog", "LatestPostsPlugin") + Tag = apps.get_model("taggit", "Tag") + TaggedItem = apps.get_model("taggit", "TaggedItem") plugin_content_type = ContentType.objects.get_for_model(LatestPostsPlugin) for tagged in TaggedItem.objects.filter(content_type_id=plugin_content_type.pk): post = LatestPostsPlugin.objects.get(pk=tagged.object_id) @@ -31,25 +30,24 @@ def migrate_tags_reverse(apps, schema_editor): class Migration(migrations.Migration): dependencies = [ - ('taggit', '__first__'), - ('djangocms_blog', '0008_auto_20150814_0831'), + ("taggit", "__first__"), + ("djangocms_blog", "0008_auto_20150814_0831"), ] operations = [ migrations.AddField( - model_name='latestpostsplugin', - name='tags_new', - field=taggit_autosuggest.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='Show only the blog articles tagged with chosen tags.', verbose_name='filter by tag'), + model_name="latestpostsplugin", + name="tags_new", + field=taggit_autosuggest.managers.TaggableManager( + to="taggit.Tag", + through="taggit.TaggedItem", + blank=True, + help_text="Show only the blog articles tagged with chosen tags.", + verbose_name="filter by tag", + ), preserve_default=True, - ), - migrations.RunPython(migrate_tags, migrate_tags_reverse), - migrations.RemoveField( - model_name='latestpostsplugin', - name='tags', - ), - migrations.RenameField( - model_name='latestpostsplugin', - old_name='tags_new', - new_name='tags', ), + migrations.RunPython(migrate_tags, migrate_tags_reverse), + migrations.RemoveField(model_name="latestpostsplugin", name="tags",), + migrations.RenameField(model_name="latestpostsplugin", old_name="tags_new", new_name="tags",), ] diff --git a/djangocms_blog/migrations/0010_auto_20150923_1151.py b/djangocms_blog/migrations/0010_auto_20150923_1151.py index c0920a4f..4c997d7d 100644 --- a/djangocms_blog/migrations/0010_auto_20150923_1151.py +++ b/djangocms_blog/migrations/0010_auto_20150923_1151.py @@ -1,95 +1,146 @@ - #-*- coding: utf-8 -*- -from __future__ import unicode_literals - import aldryn_apphooks_config.fields import app_data.fields import djangocms_text_ckeditor.fields -from django.db import models, migrations +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('cms', '__first__'), - ('djangocms_blog', '0009_latestpostsplugin_tags_new'), + ("cms", "__first__"), + ("djangocms_blog", "0009_latestpostsplugin_tags_new"), ] operations = [ migrations.CreateModel( - name='BlogConfig', + name="BlogConfig", fields=[ - ('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)), - ('type', models.CharField(verbose_name='type', max_length=100)), - ('namespace', models.CharField(default=None, verbose_name='instance namespace', unique=True, max_length=100)), - ('app_data', app_data.fields.AppDataField(editable=False, default='{}')), + ("id", models.AutoField(auto_created=True, verbose_name="ID", serialize=False, primary_key=True)), + ("type", models.CharField(verbose_name="type", max_length=100)), + ( + "namespace", + models.CharField(default=None, verbose_name="instance namespace", unique=True, max_length=100), + ), + ("app_data", app_data.fields.AppDataField(editable=False, default="{}")), ], - options={ - 'abstract': False, - }, + options={"abstract": False,}, ), migrations.CreateModel( - name='BlogConfigTranslation', + name="BlogConfigTranslation", fields=[ - ('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)), - ('language_code', models.CharField(db_index=True, verbose_name='Language', max_length=15)), - ('app_title', models.CharField(verbose_name='application title', max_length=234)), - ('master', models.ForeignKey(editable=False, to='djangocms_blog.BlogConfig', related_name='translations', null=True, on_delete=models.deletion.CASCADE)), + ("id", models.AutoField(auto_created=True, verbose_name="ID", serialize=False, primary_key=True)), + ("language_code", models.CharField(db_index=True, verbose_name="Language", max_length=15)), + ("app_title", models.CharField(verbose_name="application title", max_length=234)), + ( + "master", + models.ForeignKey( + editable=False, + to="djangocms_blog.BlogConfig", + related_name="translations", + null=True, + on_delete=models.deletion.CASCADE, + ), + ), ], options={ - 'verbose_name': 'blog config Translation', - 'db_table': 'djangocms_blog_blogconfig_translation', - 'default_permissions': (), - 'db_tablespace': '', - 'managed': True, + "verbose_name": "blog config Translation", + "db_table": "djangocms_blog_blogconfig_translation", + "default_permissions": (), + "db_tablespace": "", + "managed": True, }, ), migrations.CreateModel( - name='GenericBlogPlugin', + name="GenericBlogPlugin", fields=[ - ('cmsplugin_ptr', models.OneToOneField(parent_link=True, serialize=False, primary_key=True, auto_created=True, to='cms.CMSPlugin', on_delete=models.deletion.CASCADE)), - ('app_config', aldryn_apphooks_config.fields.AppHookConfigField(verbose_name='app. config', blank=True, to='djangocms_blog.BlogConfig', help_text='When selecting a value, the form is reloaded to get the updated default')), + ( + "cmsplugin_ptr", + models.OneToOneField( + parent_link=True, + serialize=False, + primary_key=True, + auto_created=True, + to="cms.CMSPlugin", + on_delete=models.deletion.CASCADE, + ), + ), + ( + "app_config", + aldryn_apphooks_config.fields.AppHookConfigField( + verbose_name="app. config", + blank=True, + to="djangocms_blog.BlogConfig", + help_text="When selecting a value, the form is reloaded to get the updated default", + ), + ), ], - options={ - 'abstract': False, - }, - bases=('cms.cmsplugin',), + options={"abstract": False,}, + bases=("cms.cmsplugin",), ), migrations.AlterField( - model_name='posttranslation', - name='abstract', - field=djangocms_text_ckeditor.fields.HTMLField(default='', verbose_name='abstract', blank=True), + model_name="posttranslation", + name="abstract", + field=djangocms_text_ckeditor.fields.HTMLField(default="", verbose_name="abstract", blank=True), ), migrations.AddField( - model_name='authorentriesplugin', - name='app_config', - field=aldryn_apphooks_config.fields.AppHookConfigField(default=None, blank=True, verbose_name='app. config', to='djangocms_blog.BlogConfig', help_text='When selecting a value, the form is reloaded to get the updated default', null=True), + model_name="authorentriesplugin", + name="app_config", + field=aldryn_apphooks_config.fields.AppHookConfigField( + default=None, + blank=True, + verbose_name="app. config", + to="djangocms_blog.BlogConfig", + help_text="When selecting a value, the form is reloaded to get the updated default", + null=True, + ), preserve_default=False, ), migrations.AddField( - model_name='blogcategory', - name='app_config', - field=aldryn_apphooks_config.fields.AppHookConfigField(default=None, verbose_name='app. config', to='djangocms_blog.BlogConfig', help_text='When selecting a value, the form is reloaded to get the updated default', null=True), + model_name="blogcategory", + name="app_config", + field=aldryn_apphooks_config.fields.AppHookConfigField( + default=None, + verbose_name="app. config", + to="djangocms_blog.BlogConfig", + help_text="When selecting a value, the form is reloaded to get the updated default", + null=True, + ), preserve_default=False, ), migrations.AddField( - model_name='latestpostsplugin', - name='app_config', - field=aldryn_apphooks_config.fields.AppHookConfigField(default=None, blank=True, verbose_name='app. config', to='djangocms_blog.BlogConfig', help_text='When selecting a value, the form is reloaded to get the updated default', null=True), + model_name="latestpostsplugin", + name="app_config", + field=aldryn_apphooks_config.fields.AppHookConfigField( + default=None, + blank=True, + verbose_name="app. config", + to="djangocms_blog.BlogConfig", + help_text="When selecting a value, the form is reloaded to get the updated default", + null=True, + ), preserve_default=False, ), migrations.AddField( - model_name='post', - name='app_config', - field=aldryn_apphooks_config.fields.AppHookConfigField(default=None, verbose_name='app. config', to='djangocms_blog.BlogConfig', help_text='When selecting a value, the form is reloaded to get the updated default', null=True), + model_name="post", + name="app_config", + field=aldryn_apphooks_config.fields.AppHookConfigField( + default=None, + verbose_name="app. config", + to="djangocms_blog.BlogConfig", + help_text="When selecting a value, the form is reloaded to get the updated default", + null=True, + ), preserve_default=False, ), - migrations.AlterUniqueTogether( - name='blogconfigtranslation', - unique_together=set([('language_code', 'master')]), - ), + migrations.AlterUniqueTogether(name="blogconfigtranslation", unique_together={("language_code", "master")},), migrations.AlterField( - model_name='post', - name='sites', - field=models.ManyToManyField(to='sites.Site', help_text='Select sites in which to show the post. If none is set it will be visible in all the configured sites.', blank=True, verbose_name='Site(s)'), + model_name="post", + name="sites", + field=models.ManyToManyField( + to="sites.Site", + help_text="Select sites in which to show the post. If none is set it will be visible in all the configured sites.", + blank=True, + verbose_name="Site(s)", + ), ), ] diff --git a/djangocms_blog/migrations/0011_auto_20151024_1809.py b/djangocms_blog/migrations/0011_auto_20151024_1809.py index 9c777d7f..26e308e1 100644 --- a/djangocms_blog/migrations/0011_auto_20151024_1809.py +++ b/djangocms_blog/migrations/0011_auto_20151024_1809.py @@ -1,57 +1,85 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models -import django.utils.timezone import aldryn_apphooks_config.fields +import django.utils.timezone +from django.db import migrations, models + from djangocms_blog.settings import get_setting class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0010_auto_20150923_1151'), + ("djangocms_blog", "0010_auto_20150923_1151"), ] operations = [ migrations.AddField( - model_name='blogconfigtranslation', - name='object_name', - field=models.CharField(verbose_name='object name', default=get_setting('DEFAULT_OBJECT_NAME'), max_length=234), + model_name="blogconfigtranslation", + name="object_name", + field=models.CharField( + verbose_name="object name", default=get_setting("DEFAULT_OBJECT_NAME"), max_length=234 + ), ), migrations.AlterField( - model_name='authorentriesplugin', - name='app_config', - field=aldryn_apphooks_config.fields.AppHookConfigField(blank=True, help_text='When selecting a value, the form is reloaded to get the updated default', to='djangocms_blog.BlogConfig', verbose_name='app. config', null=True), + model_name="authorentriesplugin", + name="app_config", + field=aldryn_apphooks_config.fields.AppHookConfigField( + blank=True, + help_text="When selecting a value, the form is reloaded to get the updated default", + to="djangocms_blog.BlogConfig", + verbose_name="app. config", + null=True, + ), ), migrations.AlterField( - model_name='blogcategory', - name='app_config', - field=aldryn_apphooks_config.fields.AppHookConfigField(help_text='When selecting a value, the form is reloaded to get the updated default', to='djangocms_blog.BlogConfig', verbose_name='app. config', null=True), + model_name="blogcategory", + name="app_config", + field=aldryn_apphooks_config.fields.AppHookConfigField( + help_text="When selecting a value, the form is reloaded to get the updated default", + to="djangocms_blog.BlogConfig", + verbose_name="app. config", + null=True, + ), ), migrations.AlterField( - model_name='genericblogplugin', - name='app_config', - field=aldryn_apphooks_config.fields.AppHookConfigField(blank=True, help_text='When selecting a value, the form is reloaded to get the updated default', to='djangocms_blog.BlogConfig', verbose_name='app. config', null=True), + model_name="genericblogplugin", + name="app_config", + field=aldryn_apphooks_config.fields.AppHookConfigField( + blank=True, + help_text="When selecting a value, the form is reloaded to get the updated default", + to="djangocms_blog.BlogConfig", + verbose_name="app. config", + null=True, + ), ), migrations.AlterField( - model_name='latestpostsplugin', - name='app_config', - field=aldryn_apphooks_config.fields.AppHookConfigField(blank=True, help_text='When selecting a value, the form is reloaded to get the updated default', to='djangocms_blog.BlogConfig', verbose_name='app. config', null=True), + model_name="latestpostsplugin", + name="app_config", + field=aldryn_apphooks_config.fields.AppHookConfigField( + blank=True, + help_text="When selecting a value, the form is reloaded to get the updated default", + to="djangocms_blog.BlogConfig", + verbose_name="app. config", + null=True, + ), ), migrations.AlterField( - model_name='post', - name='app_config', - field=aldryn_apphooks_config.fields.AppHookConfigField(help_text='When selecting a value, the form is reloaded to get the updated default', to='djangocms_blog.BlogConfig', verbose_name='app. config', null=True), + model_name="post", + name="app_config", + field=aldryn_apphooks_config.fields.AppHookConfigField( + help_text="When selecting a value, the form is reloaded to get the updated default", + to="djangocms_blog.BlogConfig", + verbose_name="app. config", + null=True, + ), ), migrations.AlterField( - model_name='post', - name='date_published', - field=models.DateTimeField(verbose_name='published since', default=django.utils.timezone.now), + model_name="post", + name="date_published", + field=models.DateTimeField(verbose_name="published since", default=django.utils.timezone.now), ), migrations.AlterField( - model_name='post', - name='date_published_end', - field=models.DateTimeField(blank=True, verbose_name='published until', null=True), + model_name="post", + name="date_published_end", + field=models.DateTimeField(blank=True, verbose_name="published until", null=True), ), ] diff --git a/djangocms_blog/migrations/0012_auto_20151220_1734.py b/djangocms_blog/migrations/0012_auto_20151220_1734.py index 1d469fdb..a2caf1f2 100644 --- a/djangocms_blog/migrations/0012_auto_20151220_1734.py +++ b/djangocms_blog/migrations/0012_auto_20151220_1734.py @@ -1,18 +1,14 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0011_auto_20151024_1809'), + ("djangocms_blog", "0011_auto_20151024_1809"), ] operations = [ migrations.AlterModelOptions( - name='blogconfig', - options={'verbose_name': 'blog config', 'verbose_name_plural': 'blog configs'}, + name="blogconfig", options={"verbose_name": "blog config", "verbose_name_plural": "blog configs"}, ), ] diff --git a/djangocms_blog/migrations/0013_auto_20160201_2235.py b/djangocms_blog/migrations/0013_auto_20160201_2235.py index ffdafe1d..62763f04 100644 --- a/djangocms_blog/migrations/0013_auto_20160201_2235.py +++ b/djangocms_blog/migrations/0013_auto_20160201_2235.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.9.2 on 2016-02-01 21:35 -from __future__ import unicode_literals from django.db import migrations, models @@ -8,13 +6,15 @@ class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0012_auto_20151220_1734'), + ("djangocms_blog", "0012_auto_20151220_1734"), ] operations = [ migrations.AlterField( - model_name='post', - name='categories', - field=models.ManyToManyField(blank=True, related_name='blog_posts', to='djangocms_blog.BlogCategory', verbose_name='category'), + model_name="post", + name="categories", + field=models.ManyToManyField( + blank=True, related_name="blog_posts", to="djangocms_blog.BlogCategory", verbose_name="category" + ), ), ] diff --git a/djangocms_blog/migrations/0014_auto_20160215_1331.py b/djangocms_blog/migrations/0014_auto_20160215_1331.py index 57417265..1e4f560c 100644 --- a/djangocms_blog/migrations/0014_auto_20160215_1331.py +++ b/djangocms_blog/migrations/0014_auto_20160215_1331.py @@ -1,26 +1,25 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from cms.models import Page from cms.utils.i18n import get_language_list from django.db import migrations, models def forwards(apps, schema_editor): - BlogConfig = apps.get_model('djangocms_blog', 'BlogConfig') - BlogConfigTranslation = apps.get_model('djangocms_blog', 'BlogConfigTranslation') - Post = apps.get_model('djangocms_blog', 'Post') - BlogCategory = apps.get_model('djangocms_blog', 'BlogCategory') - GenericBlogPlugin = apps.get_model('djangocms_blog', 'GenericBlogPlugin') - LatestPostsPlugin = apps.get_model('djangocms_blog', 'LatestPostsPlugin') - AuthorEntriesPlugin = apps.get_model('djangocms_blog', 'AuthorEntriesPlugin') + BlogConfig = apps.get_model("djangocms_blog", "BlogConfig") + BlogConfigTranslation = apps.get_model("djangocms_blog", "BlogConfigTranslation") + Post = apps.get_model("djangocms_blog", "Post") + BlogCategory = apps.get_model("djangocms_blog", "BlogCategory") + GenericBlogPlugin = apps.get_model("djangocms_blog", "GenericBlogPlugin") + LatestPostsPlugin = apps.get_model("djangocms_blog", "LatestPostsPlugin") + AuthorEntriesPlugin = apps.get_model("djangocms_blog", "AuthorEntriesPlugin") config = None - for page in Page.objects.drafts().filter(application_urls='BlogApp'): + for page in Page.objects.drafts().filter(application_urls="BlogApp"): config, created = BlogConfig.objects.get_or_create(namespace=page.application_namespace) if not BlogConfigTranslation.objects.exists(): for lang in get_language_list(): title = page.get_title(lang) - translation = BlogConfigTranslation.objects.create(language_code=lang, master_id=config.pk, app_title=title) + translation = BlogConfigTranslation.objects.create( + language_code=lang, master_id=config.pk, app_title=title + ) if config: for model in (Post, BlogCategory, GenericBlogPlugin, LatestPostsPlugin, AuthorEntriesPlugin): for item in model.objects.filter(app_config__isnull=True): @@ -32,11 +31,12 @@ def backwards(apps, schema_editor): # No need for backward data migration pass + class Migration(migrations.Migration): dependencies = [ - ('cms', '0004_auto_20140924_1038'), - ('djangocms_blog', '0013_auto_20160201_2235'), + ("cms", "0004_auto_20140924_1038"), + ("djangocms_blog", "0013_auto_20160201_2235"), ] operations = [ diff --git a/djangocms_blog/migrations/0015_auto_20160408_1849.py b/djangocms_blog/migrations/0015_auto_20160408_1849.py index 4a705a56..a22e1d32 100644 --- a/djangocms_blog/migrations/0015_auto_20160408_1849.py +++ b/djangocms_blog/migrations/0015_auto_20160408_1849.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.9.5 on 2016-04-08 16:49 -from __future__ import unicode_literals from django.db import migrations, models @@ -8,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0014_auto_20160215_1331'), + ("djangocms_blog", "0014_auto_20160215_1331"), ] operations = [ migrations.AlterField( - model_name='post', - name='date_published', - field=models.DateTimeField(blank=True, null=True, verbose_name='published since'), + model_name="post", + name="date_published", + field=models.DateTimeField(blank=True, null=True, verbose_name="published since"), ), ] diff --git a/djangocms_blog/migrations/0016_auto_20160502_1741.py b/djangocms_blog/migrations/0016_auto_20160502_1741.py index 20ea0ecc..54244b86 100644 --- a/djangocms_blog/migrations/0016_auto_20160502_1741.py +++ b/djangocms_blog/migrations/0016_auto_20160502_1741.py @@ -1,24 +1,21 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0015_auto_20160408_1849'), + ("djangocms_blog", "0015_auto_20160408_1849"), ] operations = [ migrations.AlterField( - model_name='blogcategorytranslation', - name='slug', - field=models.SlugField(max_length=255, verbose_name='slug', blank=True), + model_name="blogcategorytranslation", + name="slug", + field=models.SlugField(max_length=255, verbose_name="slug", blank=True), ), migrations.AlterField( - model_name='posttranslation', - name='slug', - field=models.SlugField(max_length=255, verbose_name='slug', blank=True), + model_name="posttranslation", + name="slug", + field=models.SlugField(max_length=255, verbose_name="slug", blank=True), ), ] diff --git a/djangocms_blog/migrations/0017_thumbnail_move.py b/djangocms_blog/migrations/0017_thumbnail_move.py index 178d8403..1c90b634 100644 --- a/djangocms_blog/migrations/0017_thumbnail_move.py +++ b/djangocms_blog/migrations/0017_thumbnail_move.py @@ -1,15 +1,13 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.db import migrations, models + from djangocms_blog.models import thumbnail_model class Migration(migrations.Migration): dependencies = [ - ('filer', '0003_thumbnailoption'), - ('djangocms_blog', '0016_auto_20160502_1741'), + ("filer", "0003_thumbnailoption"), + ("djangocms_blog", "0016_auto_20160502_1741"), ] operations = [] diff --git a/djangocms_blog/migrations/0018_thumbnail_move2.py b/djangocms_blog/migrations/0018_thumbnail_move2.py index 832eb5ea..9bc3946c 100644 --- a/djangocms_blog/migrations/0018_thumbnail_move2.py +++ b/djangocms_blog/migrations/0018_thumbnail_move2.py @@ -1,38 +1,46 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.db import migrations, models + from djangocms_blog.models import thumbnail_model class Migration(migrations.Migration): - if 'cmsplugin_filer' not in thumbnail_model: + if "cmsplugin_filer" not in thumbnail_model: dependencies = [ - ('djangocms_blog', '0017_thumbnail_move'), + ("djangocms_blog", "0017_thumbnail_move"), ] operations = [ migrations.AddField( - model_name='post', - name='main_image_full_new', - field=models.ForeignKey(related_name='djangocms_blog_post_full', - verbose_name='Main image full', blank=True, - to=thumbnail_model, null=True, on_delete=models.deletion.SET_NULL), + model_name="post", + name="main_image_full_new", + field=models.ForeignKey( + related_name="djangocms_blog_post_full", + verbose_name="Main image full", + blank=True, + to=thumbnail_model, + null=True, + on_delete=models.deletion.SET_NULL, + ), ), migrations.AddField( - model_name='post', - name='main_image_thumbnail_new', - field=models.ForeignKey(related_name='djangocms_blog_post_thumbnail', - verbose_name='Main image thumbnail', blank=True, - to=thumbnail_model, null=True, on_delete=models.deletion.SET_NULL), + model_name="post", + name="main_image_thumbnail_new", + field=models.ForeignKey( + related_name="djangocms_blog_post_thumbnail", + verbose_name="Main image thumbnail", + blank=True, + to=thumbnail_model, + null=True, + on_delete=models.deletion.SET_NULL, + ), ), ] else: dependencies = [ - ('filer', '__first__'), - ('cmsplugin_filer_image', '__first__'), - ('djangocms_blog', '0017_thumbnail_move'), + ("filer", "__first__"), + ("cmsplugin_filer_image", "__first__"), + ("djangocms_blog", "0017_thumbnail_move"), ] operations = [] diff --git a/djangocms_blog/migrations/0019_thumbnail_move3.py b/djangocms_blog/migrations/0019_thumbnail_move3.py index ea4f7f50..b6dea980 100644 --- a/djangocms_blog/migrations/0019_thumbnail_move3.py +++ b/djangocms_blog/migrations/0019_thumbnail_move3.py @@ -1,12 +1,10 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.db import migrations, models + from djangocms_blog.models import thumbnail_model def move_thumbnail_opt_to_filer(apps, schema_editor): - Post = apps.get_model('djangocms_blog', 'Post') + Post = apps.get_model("djangocms_blog", "Post") for post in Post.objects.all(): post.main_image_full_new_id = post.main_image_full_id post.main_image_thumbnail_new_id = post.main_image_thumbnail_id @@ -14,7 +12,7 @@ def move_thumbnail_opt_to_filer(apps, schema_editor): def move_thumbnail_opt_to_plugin(apps, schema_editor): - Post = apps.get_model('djangocms_blog', 'Post') + Post = apps.get_model("djangocms_blog", "Post") for post in Post.objects.all(): post.main_image_full_id = post.main_image_full_new_id post.main_image_thumbnail_id = post.main_image_thumbnail_new_id @@ -22,9 +20,9 @@ def move_thumbnail_opt_to_plugin(apps, schema_editor): class Migration(migrations.Migration): - if 'cmsplugin_filer' not in thumbnail_model: + if "cmsplugin_filer" not in thumbnail_model: dependencies = [ - ('djangocms_blog', '0018_thumbnail_move2'), + ("djangocms_blog", "0018_thumbnail_move2"), ] operations = [ @@ -32,9 +30,9 @@ class Migration(migrations.Migration): ] else: dependencies = [ - ('filer', '__first__'), - ('cmsplugin_filer_image', '__first__'), - ('djangocms_blog', '0018_thumbnail_move2'), + ("filer", "__first__"), + ("cmsplugin_filer_image", "__first__"), + ("djangocms_blog", "0018_thumbnail_move2"), ] operations = [] diff --git a/djangocms_blog/migrations/0020_thumbnail_move4.py b/djangocms_blog/migrations/0020_thumbnail_move4.py index b895cb15..e9997d98 100644 --- a/djangocms_blog/migrations/0020_thumbnail_move4.py +++ b/djangocms_blog/migrations/0020_thumbnail_move4.py @@ -1,42 +1,28 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.db import migrations, models + from djangocms_blog.models import thumbnail_model class Migration(migrations.Migration): - if 'cmsplugin_filer' not in thumbnail_model: + if "cmsplugin_filer" not in thumbnail_model: dependencies = [ - ('djangocms_blog', '0019_thumbnail_move3'), + ("djangocms_blog", "0019_thumbnail_move3"), ] operations = [ - migrations.RemoveField( - model_name='post', - name='main_image_full' - ), - migrations.RemoveField( - model_name='post', - name='main_image_thumbnail', - ), + migrations.RemoveField(model_name="post", name="main_image_full"), + migrations.RemoveField(model_name="post", name="main_image_thumbnail",), + migrations.RenameField(model_name="post", old_name="main_image_full_new", new_name="main_image_full",), migrations.RenameField( - model_name='post', - old_name='main_image_full_new', - new_name='main_image_full', + model_name="post", old_name="main_image_thumbnail_new", new_name="main_image_thumbnail", ), - migrations.RenameField( - model_name='post', - old_name='main_image_thumbnail_new', - new_name='main_image_thumbnail', - ) ] else: dependencies = [ - ('filer', '__first__'), - ('cmsplugin_filer_image', '__first__'), - ('djangocms_blog', '0019_thumbnail_move3'), + ("filer", "__first__"), + ("cmsplugin_filer_image", "__first__"), + ("djangocms_blog", "0019_thumbnail_move3"), ] operations = [] diff --git a/djangocms_blog/migrations/0021_auto_20160823_2008.py b/djangocms_blog/migrations/0021_auto_20160823_2008.py index 026dae80..f0a2dcc2 100644 --- a/djangocms_blog/migrations/0021_auto_20160823_2008.py +++ b/djangocms_blog/migrations/0021_auto_20160823_2008.py @@ -1,41 +1,77 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models + from djangocms_blog.models import thumbnail_model class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0020_thumbnail_move4'), + ("djangocms_blog", "0020_thumbnail_move4"), ] operations = [ migrations.AlterField( - model_name='authorentriesplugin', - name='cmsplugin_ptr', - field=models.OneToOneField(parent_link=True, related_name='djangocms_blog_authorentriesplugin', auto_created=True, primary_key=True, serialize=False, to='cms.CMSPlugin', on_delete=models.deletion.CASCADE), + model_name="authorentriesplugin", + name="cmsplugin_ptr", + field=models.OneToOneField( + parent_link=True, + related_name="djangocms_blog_authorentriesplugin", + auto_created=True, + primary_key=True, + serialize=False, + to="cms.CMSPlugin", + on_delete=models.deletion.CASCADE, + ), ), migrations.AlterField( - model_name='genericblogplugin', - name='cmsplugin_ptr', - field=models.OneToOneField(parent_link=True, related_name='djangocms_blog_genericblogplugin', auto_created=True, primary_key=True, serialize=False, to='cms.CMSPlugin', on_delete=models.deletion.CASCADE), + model_name="genericblogplugin", + name="cmsplugin_ptr", + field=models.OneToOneField( + parent_link=True, + related_name="djangocms_blog_genericblogplugin", + auto_created=True, + primary_key=True, + serialize=False, + to="cms.CMSPlugin", + on_delete=models.deletion.CASCADE, + ), ), migrations.AlterField( - model_name='latestpostsplugin', - name='cmsplugin_ptr', - field=models.OneToOneField(parent_link=True, related_name='djangocms_blog_latestpostsplugin', auto_created=True, primary_key=True, serialize=False, to='cms.CMSPlugin', on_delete=models.deletion.CASCADE), + model_name="latestpostsplugin", + name="cmsplugin_ptr", + field=models.OneToOneField( + parent_link=True, + related_name="djangocms_blog_latestpostsplugin", + auto_created=True, + primary_key=True, + serialize=False, + to="cms.CMSPlugin", + on_delete=models.deletion.CASCADE, + ), ), migrations.AlterField( - model_name='post', - name='main_image_full', - field=models.ForeignKey(related_name='djangocms_blog_post_full', on_delete=django.db.models.deletion.SET_NULL, verbose_name='main image full', blank=True, to=thumbnail_model, null=True), + model_name="post", + name="main_image_full", + field=models.ForeignKey( + related_name="djangocms_blog_post_full", + on_delete=django.db.models.deletion.SET_NULL, + verbose_name="main image full", + blank=True, + to=thumbnail_model, + null=True, + ), ), migrations.AlterField( - model_name='post', - name='main_image_thumbnail', - field=models.ForeignKey(related_name='djangocms_blog_post_thumbnail', on_delete=django.db.models.deletion.SET_NULL, verbose_name='main image thumbnail', blank=True, to=thumbnail_model, null=True), + model_name="post", + name="main_image_thumbnail", + field=models.ForeignKey( + related_name="djangocms_blog_post_thumbnail", + on_delete=django.db.models.deletion.SET_NULL, + verbose_name="main image thumbnail", + blank=True, + to=thumbnail_model, + null=True, + ), ), ] diff --git a/djangocms_blog/migrations/0021_post_liveblog.py b/djangocms_blog/migrations/0021_post_liveblog.py index 28e9aa4e..8f13abac 100644 --- a/djangocms_blog/migrations/0021_post_liveblog.py +++ b/djangocms_blog/migrations/0021_post_liveblog.py @@ -1,21 +1,20 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models import cms.models.fields +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('cms', '__first__'), - ('djangocms_blog', '0020_thumbnail_move4'), + ("cms", "__first__"), + ("djangocms_blog", "0020_thumbnail_move4"), ] operations = [ migrations.AddField( - model_name='post', - name='liveblog', - field=cms.models.fields.PlaceholderField(related_name='live_blog', slotname='live_blog', editable=False, to='cms.Placeholder', null=True), + model_name="post", + name="liveblog", + field=cms.models.fields.PlaceholderField( + related_name="live_blog", slotname="live_blog", editable=False, to="cms.Placeholder", null=True + ), ), ] diff --git a/djangocms_blog/migrations/0022_auto_20160605_2305.py b/djangocms_blog/migrations/0022_auto_20160605_2305.py index 25e78923..27d98d9e 100644 --- a/djangocms_blog/migrations/0022_auto_20160605_2305.py +++ b/djangocms_blog/migrations/0022_auto_20160605_2305.py @@ -1,21 +1,19 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.9.7 on 2016-06-05 21:05 -from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0021_post_liveblog'), + ("djangocms_blog", "0021_post_liveblog"), ] operations = [ migrations.AddField( - model_name='post', - name='enable_liveblog', - field=models.BooleanField(default=False, verbose_name='enable liveblog on post'), + model_name="post", + name="enable_liveblog", + field=models.BooleanField(default=False, verbose_name="enable liveblog on post"), ), ] diff --git a/djangocms_blog/migrations/0022_auto_20170304_1040.py b/djangocms_blog/migrations/0022_auto_20170304_1040.py index 8a6ec778..022a137b 100644 --- a/djangocms_blog/migrations/0022_auto_20170304_1040.py +++ b/djangocms_blog/migrations/0022_auto_20170304_1040.py @@ -1,29 +1,24 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.9.12 on 2017-03-04 09:40 -from __future__ import unicode_literals from distutils.version import LooseVersion -from django.db import migrations, models - import aldryn_apphooks_config +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0021_auto_20160823_2008'), + ("djangocms_blog", "0021_auto_20160823_2008"), ] - if LooseVersion(aldryn_apphooks_config.__version__) > LooseVersion('0.3.0'): + if LooseVersion(aldryn_apphooks_config.__version__) > LooseVersion("0.3.0"): operations = [ migrations.AlterField( - model_name='blogconfig', - name='namespace', - field=models.CharField(default=None, max_length=100, unique=True, verbose_name='Instance namespace'), + model_name="blogconfig", + name="namespace", + field=models.CharField(default=None, max_length=100, unique=True, verbose_name="Instance namespace"), ), migrations.AlterField( - model_name='blogconfig', - name='type', - field=models.CharField(max_length=100, verbose_name='Type'), + model_name="blogconfig", name="type", field=models.CharField(max_length=100, verbose_name="Type"), ), ] diff --git a/djangocms_blog/migrations/0023_auto_20160626_1539.py b/djangocms_blog/migrations/0023_auto_20160626_1539.py index 5748fae6..b6d07946 100644 --- a/djangocms_blog/migrations/0023_auto_20160626_1539.py +++ b/djangocms_blog/migrations/0023_auto_20160626_1539.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.9.6 on 2016-06-26 13:39 -from __future__ import unicode_literals from django.db import migrations, models @@ -8,23 +6,29 @@ class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0022_auto_20160605_2305'), + ("djangocms_blog", "0022_auto_20160605_2305"), ] operations = [ migrations.AddField( - model_name='authorentriesplugin', - name='current_site', - field=models.BooleanField(default=True, help_text='Select items from the current site only', verbose_name='current site'), + model_name="authorentriesplugin", + name="current_site", + field=models.BooleanField( + default=True, help_text="Select items from the current site only", verbose_name="current site" + ), ), migrations.AddField( - model_name='genericblogplugin', - name='current_site', - field=models.BooleanField(default=True, help_text='Select items from the current site only', verbose_name='current site'), + model_name="genericblogplugin", + name="current_site", + field=models.BooleanField( + default=True, help_text="Select items from the current site only", verbose_name="current site" + ), ), migrations.AddField( - model_name='latestpostsplugin', - name='current_site', - field=models.BooleanField(default=True, help_text='Select items from the current site only', verbose_name='current site'), + model_name="latestpostsplugin", + name="current_site", + field=models.BooleanField( + default=True, help_text="Select items from the current site only", verbose_name="current site" + ), ), ] diff --git a/djangocms_blog/migrations/0024_auto_20160706_1524.py b/djangocms_blog/migrations/0024_auto_20160706_1524.py index fa348416..5c6b1c64 100644 --- a/djangocms_blog/migrations/0024_auto_20160706_1524.py +++ b/djangocms_blog/migrations/0024_auto_20160706_1524.py @@ -1,33 +1,48 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.db import migrations, models from djangocms_blog.settings import get_setting -BLOG_PLUGIN_TEMPLATE_FOLDERS = get_setting('PLUGIN_TEMPLATE_FOLDERS') +BLOG_PLUGIN_TEMPLATE_FOLDERS = get_setting("PLUGIN_TEMPLATE_FOLDERS") class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0023_auto_20160626_1539'), + ("djangocms_blog", "0023_auto_20160626_1539"), ] operations = [ migrations.AddField( - model_name='authorentriesplugin', - name='template_folder', - field=models.CharField(default='plugins', verbose_name='Plugin template', max_length=200, help_text='Select plugin template to load for this instance', choices=BLOG_PLUGIN_TEMPLATE_FOLDERS), + model_name="authorentriesplugin", + name="template_folder", + field=models.CharField( + default="plugins", + verbose_name="Plugin template", + max_length=200, + help_text="Select plugin template to load for this instance", + choices=BLOG_PLUGIN_TEMPLATE_FOLDERS, + ), ), migrations.AddField( - model_name='genericblogplugin', - name='template_folder', - field=models.CharField(default='plugins', verbose_name='Plugin template', max_length=200, help_text='Select plugin template to load for this instance', choices=BLOG_PLUGIN_TEMPLATE_FOLDERS), + model_name="genericblogplugin", + name="template_folder", + field=models.CharField( + default="plugins", + verbose_name="Plugin template", + max_length=200, + help_text="Select plugin template to load for this instance", + choices=BLOG_PLUGIN_TEMPLATE_FOLDERS, + ), ), migrations.AddField( - model_name='latestpostsplugin', - name='template_folder', - field=models.CharField(default='plugins', verbose_name='Plugin template', max_length=200, help_text='Select plugin template to load for this instance', choices=BLOG_PLUGIN_TEMPLATE_FOLDERS), + model_name="latestpostsplugin", + name="template_folder", + field=models.CharField( + default="plugins", + verbose_name="Plugin template", + max_length=200, + help_text="Select plugin template to load for this instance", + choices=BLOG_PLUGIN_TEMPLATE_FOLDERS, + ), ), ] diff --git a/djangocms_blog/migrations/0025_auto_20160803_0858.py b/djangocms_blog/migrations/0025_auto_20160803_0858.py index f613c9b3..7ca7c20e 100644 --- a/djangocms_blog/migrations/0025_auto_20160803_0858.py +++ b/djangocms_blog/migrations/0025_auto_20160803_0858.py @@ -1,21 +1,26 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.9.9 on 2016-08-03 06:58 -from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0024_auto_20160706_1524'), + ("djangocms_blog", "0024_auto_20160706_1524"), ] operations = [ migrations.AlterField( - model_name='blogcategory', - name='parent', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='djangocms_blog.BlogCategory', verbose_name='parent'), + model_name="blogcategory", + name="parent", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="children", + to="djangocms_blog.BlogCategory", + verbose_name="parent", + ), ), ] diff --git a/djangocms_blog/migrations/0026_merge.py b/djangocms_blog/migrations/0026_merge.py index 0d0ad8c1..a056b6b6 100644 --- a/djangocms_blog/migrations/0026_merge.py +++ b/djangocms_blog/migrations/0026_merge.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.9.9 on 2016-08-25 20:24 -from __future__ import unicode_literals from django.db import migrations @@ -8,9 +6,8 @@ class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0021_auto_20160823_2008'), - ('djangocms_blog', '0025_auto_20160803_0858'), + ("djangocms_blog", "0021_auto_20160823_2008"), + ("djangocms_blog", "0025_auto_20160803_0858"), ] - operations = [ - ] + operations = [] diff --git a/djangocms_blog/migrations/0027_post_date_featured.py b/djangocms_blog/migrations/0027_post_date_featured.py index 693b58a2..ade5a88d 100644 --- a/djangocms_blog/migrations/0027_post_date_featured.py +++ b/djangocms_blog/migrations/0027_post_date_featured.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.10.5 on 2017-01-25 11:15 -from __future__ import unicode_literals from django.db import migrations, models @@ -8,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0026_merge'), + ("djangocms_blog", "0026_merge"), ] operations = [ migrations.AddField( - model_name='post', - name='date_featured', - field=models.DateTimeField(blank=True, null=True, verbose_name='featured date'), + model_name="post", + name="date_featured", + field=models.DateTimeField(blank=True, null=True, verbose_name="featured date"), ), ] diff --git a/djangocms_blog/migrations/0028_auto_20170304_1040.py b/djangocms_blog/migrations/0028_auto_20170304_1040.py index 1652fe88..255a03d8 100644 --- a/djangocms_blog/migrations/0028_auto_20170304_1040.py +++ b/djangocms_blog/migrations/0028_auto_20170304_1040.py @@ -1,29 +1,24 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.9.12 on 2017-03-04 09:40 -from __future__ import unicode_literals from distutils.version import LooseVersion -from django.db import migrations, models - import aldryn_apphooks_config +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0027_post_date_featured'), + ("djangocms_blog", "0027_post_date_featured"), ] - if LooseVersion(aldryn_apphooks_config.__version__) > LooseVersion('0.3.0'): + if LooseVersion(aldryn_apphooks_config.__version__) > LooseVersion("0.3.0"): operations = [ migrations.AlterField( - model_name='blogconfig', - name='namespace', - field=models.CharField(default=None, max_length=100, unique=True, verbose_name='Instance namespace'), + model_name="blogconfig", + name="namespace", + field=models.CharField(default=None, max_length=100, unique=True, verbose_name="Instance namespace"), ), migrations.AlterField( - model_name='blogconfig', - name='type', - field=models.CharField(max_length=100, verbose_name='Type'), + model_name="blogconfig", name="type", field=models.CharField(max_length=100, verbose_name="Type"), ), ] diff --git a/djangocms_blog/migrations/0029_post_related.py b/djangocms_blog/migrations/0029_post_related.py index 1a252dbf..a3abfd1c 100644 --- a/djangocms_blog/migrations/0029_post_related.py +++ b/djangocms_blog/migrations/0029_post_related.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.10.5 on 2017-04-07 07:35 -from __future__ import unicode_literals from django.db import migrations, models @@ -8,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0028_auto_20170304_1040'), + ("djangocms_blog", "0028_auto_20170304_1040"), ] operations = [ migrations.AddField( - model_name='post', - name='related', - field=models.ManyToManyField(blank=True, to='djangocms_blog.Post', verbose_name='Related Posts'), + model_name="post", + name="related", + field=models.ManyToManyField(blank=True, to="djangocms_blog.Post", verbose_name="Related Posts"), ), ] diff --git a/djangocms_blog/migrations/0030_auto_20170509_1831.py b/djangocms_blog/migrations/0030_auto_20170509_1831.py index 8c9e48fd..1412c6e2 100644 --- a/djangocms_blog/migrations/0030_auto_20170509_1831.py +++ b/djangocms_blog/migrations/0030_auto_20170509_1831.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.10.5 on 2017-07-22 05:28 -from __future__ import unicode_literals from django.db import migrations, models @@ -8,13 +6,15 @@ class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0029_post_related'), + ("djangocms_blog", "0029_post_related"), ] operations = [ migrations.AlterField( - model_name='posttranslation', - name='slug', - field=models.SlugField(allow_unicode=True, blank=True, db_index=False, max_length=255, verbose_name='slug'), + model_name="posttranslation", + name="slug", + field=models.SlugField( + allow_unicode=True, blank=True, db_index=False, max_length=255, verbose_name="slug" + ), ), ] diff --git a/djangocms_blog/migrations/0031_auto_20170610_1744.py b/djangocms_blog/migrations/0031_auto_20170610_1744.py index e8fedaba..e86742fe 100644 --- a/djangocms_blog/migrations/0031_auto_20170610_1744.py +++ b/djangocms_blog/migrations/0031_auto_20170610_1744.py @@ -1,22 +1,22 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.10.5 on 2017-06-10 12:14 -from __future__ import unicode_literals -from django.db import migrations import sortedm2m.fields +from django.db import migrations from sortedm2m.operations import AlterSortedManyToManyField class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0030_auto_20170509_1831'), + ("djangocms_blog", "0030_auto_20170509_1831"), ] operations = [ AlterSortedManyToManyField( - model_name='post', - name='related', - field=sortedm2m.fields.SortedManyToManyField(blank=True, help_text=None, to='djangocms_blog.Post', verbose_name='Related Posts'), + model_name="post", + name="related", + field=sortedm2m.fields.SortedManyToManyField( + blank=True, help_text=None, to="djangocms_blog.Post", verbose_name="Related Posts" + ), ), ] diff --git a/djangocms_blog/migrations/0032_auto_20180109_0023.py b/djangocms_blog/migrations/0032_auto_20180109_0023.py index b67ecf45..39b9d4ec 100644 --- a/djangocms_blog/migrations/0032_auto_20180109_0023.py +++ b/djangocms_blog/migrations/0032_auto_20180109_0023.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.10.8 on 2018-01-08 23:23 -from __future__ import unicode_literals from django.db import migrations, models @@ -8,38 +6,44 @@ class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0031_auto_20170610_1744'), + ("djangocms_blog", "0031_auto_20170610_1744"), ] operations = [ migrations.AddField( - model_name='blogcategorytranslation', - name='meta_description', - field=models.TextField(blank=True, default='', verbose_name='post meta description'), + model_name="blogcategorytranslation", + name="meta_description", + field=models.TextField(blank=True, default="", verbose_name="post meta description"), ), migrations.AlterField( - model_name='blogcategorytranslation', - name='name', - field=models.CharField(max_length=752, verbose_name='name'), + model_name="blogcategorytranslation", + name="name", + field=models.CharField(max_length=752, verbose_name="name"), ), migrations.AlterField( - model_name='blogcategorytranslation', - name='slug', - field=models.SlugField(blank=True, max_length=752, verbose_name='slug'), + model_name="blogcategorytranslation", + name="slug", + field=models.SlugField(blank=True, max_length=752, verbose_name="slug"), ), migrations.AlterField( - model_name='posttranslation', - name='meta_title', - field=models.CharField(blank=True, default='', help_text='used in title tag and social sharing', max_length=2000, verbose_name='post meta title'), + model_name="posttranslation", + name="meta_title", + field=models.CharField( + blank=True, + default="", + help_text="used in title tag and social sharing", + max_length=2000, + verbose_name="post meta title", + ), ), migrations.AlterField( - model_name='posttranslation', - name='slug', - field=models.SlugField(allow_unicode=True, blank=True, db_index=False, max_length=752, verbose_name='slug'), + model_name="posttranslation", + name="slug", + field=models.SlugField( + allow_unicode=True, blank=True, db_index=False, max_length=752, verbose_name="slug" + ), ), migrations.AlterField( - model_name='posttranslation', - name='title', - field=models.CharField(max_length=752, verbose_name='title'), + model_name="posttranslation", name="title", field=models.CharField(max_length=752, verbose_name="title"), ), ] diff --git a/djangocms_blog/migrations/0033_auto_20180226_1410.py b/djangocms_blog/migrations/0033_auto_20180226_1410.py index 53dd2fb5..4e639e93 100644 --- a/djangocms_blog/migrations/0033_auto_20180226_1410.py +++ b/djangocms_blog/migrations/0033_auto_20180226_1410.py @@ -1,19 +1,16 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0032_auto_20180109_0023'), + ("djangocms_blog", "0032_auto_20180109_0023"), ] operations = [ migrations.AlterField( - model_name='blogcategorytranslation', - name='meta_description', - field=models.TextField(blank=True, verbose_name='category meta description', default=''), + model_name="blogcategorytranslation", + name="meta_description", + field=models.TextField(blank=True, verbose_name="category meta description", default=""), ), ] diff --git a/djangocms_blog/migrations/0034_merge.py b/djangocms_blog/migrations/0034_merge.py index fbcfab3c..43144a4f 100644 --- a/djangocms_blog/migrations/0034_merge.py +++ b/djangocms_blog/migrations/0034_merge.py @@ -1,15 +1,11 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0022_auto_20170304_1040'), - ('djangocms_blog', '0033_auto_20180226_1410'), + ("djangocms_blog", "0022_auto_20170304_1040"), + ("djangocms_blog", "0033_auto_20180226_1410"), ] - operations = [ - ] + operations = [] diff --git a/djangocms_blog/migrations/0035_posttranslation_subtitle.py b/djangocms_blog/migrations/0035_posttranslation_subtitle.py index 2492bad7..bc721dc1 100644 --- a/djangocms_blog/migrations/0035_posttranslation_subtitle.py +++ b/djangocms_blog/migrations/0035_posttranslation_subtitle.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.11 on 2018-04-13 14:09 -from __future__ import unicode_literals from django.db import migrations, models @@ -8,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0034_merge'), + ("djangocms_blog", "0034_merge"), ] operations = [ migrations.AddField( - model_name='posttranslation', - name='subtitle', - field=models.CharField(blank=True, default='', max_length=767, verbose_name='subtitle'), + model_name="posttranslation", + name="subtitle", + field=models.CharField(blank=True, default="", max_length=767, verbose_name="subtitle"), ), ] diff --git a/djangocms_blog/migrations/0036_auto_20180913_1809.py b/djangocms_blog/migrations/0036_auto_20180913_1809.py index 7609334e..920f7017 100644 --- a/djangocms_blog/migrations/0036_auto_20180913_1809.py +++ b/djangocms_blog/migrations/0036_auto_20180913_1809.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.11.15 on 2018-09-13 18:09 -from __future__ import unicode_literals from django.db import migrations, models @@ -8,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0035_posttranslation_subtitle'), + ("djangocms_blog", "0035_posttranslation_subtitle"), ] operations = [ migrations.AlterField( - model_name='posttranslation', - name='slug', - field=models.SlugField(allow_unicode=True, blank=True, max_length=752, verbose_name='slug'), + model_name="posttranslation", + name="slug", + field=models.SlugField(allow_unicode=True, blank=True, max_length=752, verbose_name="slug"), ), ] diff --git a/djangocms_blog/migrations/0037_auto_20190806_0743.py b/djangocms_blog/migrations/0037_auto_20190806_0743.py index b198e725..29505aed 100644 --- a/djangocms_blog/migrations/0037_auto_20190806_0743.py +++ b/djangocms_blog/migrations/0037_auto_20190806_0743.py @@ -1,47 +1,83 @@ # Generated by Django 2.1.11 on 2019-08-06 05:43 -from django.conf import settings -from django.db import migrations, models import django.db.models.deletion import parler.fields import taggit_autosuggest.managers +from django.conf import settings +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0036_auto_20180913_1809'), + ("djangocms_blog", "0036_auto_20180913_1809"), ] operations = [ migrations.AlterField( - model_name='authorentriesplugin', - name='authors', - field=models.ManyToManyField(limit_choices_to={'djangocms_blog_post_author__publish': True}, to=settings.AUTH_USER_MODEL, verbose_name='authors'), + model_name="authorentriesplugin", + name="authors", + field=models.ManyToManyField( + limit_choices_to={"djangocms_blog_post_author__publish": True}, + to=settings.AUTH_USER_MODEL, + verbose_name="authors", + ), ), migrations.AlterField( - model_name='blogcategorytranslation', - name='master', - field=parler.fields.TranslationsForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='djangocms_blog.BlogCategory'), + model_name="blogcategorytranslation", + name="master", + field=parler.fields.TranslationsForeignKey( + editable=False, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="translations", + to="djangocms_blog.BlogCategory", + ), ), migrations.AlterField( - model_name='blogconfigtranslation', - name='master', - field=parler.fields.TranslationsForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='djangocms_blog.BlogConfig'), + model_name="blogconfigtranslation", + name="master", + field=parler.fields.TranslationsForeignKey( + editable=False, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="translations", + to="djangocms_blog.BlogConfig", + ), ), migrations.AlterField( - model_name='latestpostsplugin', - name='tags', - field=taggit_autosuggest.managers.TaggableManager(blank=True, help_text='Show only the blog articles tagged with chosen tags.', related_name='djangocms_blog_latest_post', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='filter by tag'), + model_name="latestpostsplugin", + name="tags", + field=taggit_autosuggest.managers.TaggableManager( + blank=True, + help_text="Show only the blog articles tagged with chosen tags.", + related_name="djangocms_blog_latest_post", + through="taggit.TaggedItem", + to="taggit.Tag", + verbose_name="filter by tag", + ), ), migrations.AlterField( - model_name='post', - name='tags', - field=taggit_autosuggest.managers.TaggableManager(blank=True, help_text='A comma-separated list of tags.', related_name='djangocms_blog_tags', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + model_name="post", + name="tags", + field=taggit_autosuggest.managers.TaggableManager( + blank=True, + help_text="A comma-separated list of tags.", + related_name="djangocms_blog_tags", + through="taggit.TaggedItem", + to="taggit.Tag", + verbose_name="Tags", + ), ), migrations.AlterField( - model_name='posttranslation', - name='master', - field=parler.fields.TranslationsForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='djangocms_blog.Post'), + model_name="posttranslation", + name="master", + field=parler.fields.TranslationsForeignKey( + editable=False, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="translations", + to="djangocms_blog.Post", + ), ), ] diff --git a/djangocms_blog/migrations/0038_post_media.py b/djangocms_blog/migrations/0038_post_media.py index db39f4a9..771e63e2 100644 --- a/djangocms_blog/migrations/0038_post_media.py +++ b/djangocms_blog/migrations/0038_post_media.py @@ -1,23 +1,28 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.11.24 on 2019-09-14 10:45 -from __future__ import unicode_literals import cms.models.fields -from django.db import migrations import django.db.models.deletion +from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('cms', '0020_old_tree_cleanup'), - ('djangocms_blog', '0037_auto_20190806_0743'), + ("cms", "0020_old_tree_cleanup"), + ("djangocms_blog", "0037_auto_20190806_0743"), ] operations = [ migrations.AddField( - model_name='post', - name='media', - field=cms.models.fields.PlaceholderField(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='media', slotname='media', to='cms.Placeholder'), + model_name="post", + name="media", + field=cms.models.fields.PlaceholderField( + editable=False, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="media", + slotname="media", + to="cms.Placeholder", + ), ), ] diff --git a/djangocms_blog/migrations/0039_auto_20200331_2227.py b/djangocms_blog/migrations/0039_auto_20200331_2227.py index 171bb043..bb607f4d 100644 --- a/djangocms_blog/migrations/0039_auto_20200331_2227.py +++ b/djangocms_blog/migrations/0039_auto_20200331_2227.py @@ -6,28 +6,26 @@ class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0038_post_media'), + ("djangocms_blog", "0038_post_media"), ] operations = [ migrations.AlterField( - model_name='blogcategorytranslation', - name='name', - field=models.CharField(max_length=752, verbose_name='name'), + model_name="blogcategorytranslation", + name="name", + field=models.CharField(max_length=752, verbose_name="name"), ), migrations.AlterField( - model_name='blogcategorytranslation', - name='slug', - field=models.SlugField(blank=True, max_length=752, verbose_name='slug'), + model_name="blogcategorytranslation", + name="slug", + field=models.SlugField(blank=True, max_length=752, verbose_name="slug"), ), migrations.AlterField( - model_name='posttranslation', - name='slug', - field=models.SlugField(allow_unicode=True, blank=True, max_length=752, verbose_name='slug'), + model_name="posttranslation", + name="slug", + field=models.SlugField(allow_unicode=True, blank=True, max_length=752, verbose_name="slug"), ), migrations.AlterField( - model_name='posttranslation', - name='title', - field=models.CharField(max_length=752, verbose_name='title'), + model_name="posttranslation", name="title", field=models.CharField(max_length=752, verbose_name="title"), ), ] diff --git a/djangocms_blog/models.py b/djangocms_blog/models.py index 665f0dcf..8e7f6be0 100644 --- a/djangocms_blog/models.py +++ b/djangocms_blog/models.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import hashlib from aldryn_apphooks_config.fields import AppHookConfigField @@ -16,7 +15,7 @@ from django.utils.encoding import force_bytes, force_text from django.utils.functional import cached_property from django.utils.html import escape, strip_tags -from django.utils.translation import get_language, ugettext, ugettext_lazy as _ +from django.utils.translation import get_language, gettext, gettext_lazy as _ from djangocms_text_ckeditor.fields import HTMLField from filer.fields.image import FilerImageField from filer.models import ThumbnailOption @@ -31,23 +30,23 @@ from .managers import GenericDateTaggedManager from .settings import get_setting -BLOG_CURRENT_POST_IDENTIFIER = get_setting('CURRENT_POST_IDENTIFIER') -BLOG_CURRENT_NAMESPACE = get_setting('CURRENT_NAMESPACE') -BLOG_PLUGIN_TEMPLATE_FOLDERS = get_setting('PLUGIN_TEMPLATE_FOLDERS') +BLOG_CURRENT_POST_IDENTIFIER = get_setting("CURRENT_POST_IDENTIFIER") +BLOG_CURRENT_NAMESPACE = get_setting("CURRENT_NAMESPACE") +BLOG_PLUGIN_TEMPLATE_FOLDERS = get_setting("PLUGIN_TEMPLATE_FOLDERS") -thumbnail_model = '%s.%s' % ( - ThumbnailOption._meta.app_label, ThumbnailOption.__name__ -) +thumbnail_model = "{}.{}".format(ThumbnailOption._meta.app_label, ThumbnailOption.__name__) try: from knocker.mixins import KnockerModel except ImportError: + class KnockerModel: """ Stub class if django-knocker is not installed """ + pass @@ -61,7 +60,7 @@ def _get_language(instance, language): language = instance.get_current_language() if language and language in available_languages: return language - if get_setting('USE_FALLBACK_LANGUAGE_IN_URL'): + if get_setting("USE_FALLBACK_LANGUAGE_IN_URL"): for fallback_language in instance.get_fallback_languages(): if fallback_language in available_languages: return fallback_language @@ -69,13 +68,12 @@ def _get_language(instance, language): class BlogMetaMixin(ModelMeta): - def get_meta_attribute(self, param): """ Retrieves django-meta attributes from apphook config instance :param param: django-meta attribute passed as key """ - return self._get_meta_value(param, getattr(self.app_config, param)) or '' + return self._get_meta_value(param, getattr(self.app_config, param)) or "" def get_locale(self): return self.get_current_language() @@ -91,52 +89,48 @@ class BlogCategory(BlogMetaMixin, TranslatableModel): """ Blog category """ + parent = models.ForeignKey( - 'self', verbose_name=_('parent'), null=True, blank=True, related_name='children', - on_delete=models.CASCADE - ) - date_created = models.DateTimeField(_('created at'), auto_now_add=True) - date_modified = models.DateTimeField(_('modified at'), auto_now=True) - app_config = AppHookConfigField( - BlogConfig, null=True, verbose_name=_('app. config') + "self", verbose_name=_("parent"), null=True, blank=True, related_name="children", on_delete=models.CASCADE ) + date_created = models.DateTimeField(_("created at"), auto_now_add=True) + date_modified = models.DateTimeField(_("modified at"), auto_now=True) + app_config = AppHookConfigField(BlogConfig, null=True, verbose_name=_("app. config")) translations = TranslatedFields( - name=models.CharField(_('name'), max_length=752), - slug=models.SlugField(_('slug'), max_length=752, blank=True, db_index=True), - meta_description=models.TextField( - verbose_name=_('category meta description'), blank=True, default='' - ), - meta={'unique_together': (('language_code', 'slug'),)} + name=models.CharField(_("name"), max_length=752), + slug=models.SlugField(_("slug"), max_length=752, blank=True, db_index=True), + meta_description=models.TextField(verbose_name=_("category meta description"), blank=True, default=""), + meta={"unique_together": (("language_code", "slug"),)}, ) objects = AppHookConfigTranslatableManager() _metadata = { - 'title': 'get_title', - 'description': 'get_description', - 'og_description': 'get_description', - 'twitter_description': 'get_description', - 'gplus_description': 'get_description', - 'locale': 'get_locale', - 'object_type': 'get_meta_attribute', - 'og_type': 'get_meta_attribute', - 'og_app_id': 'get_meta_attribute', - 'og_profile_id': 'get_meta_attribute', - 'og_publisher': 'get_meta_attribute', - 'og_author_url': 'get_meta_attribute', - 'og_author': 'get_meta_attribute', - 'twitter_type': 'get_meta_attribute', - 'twitter_site': 'get_meta_attribute', - 'twitter_author': 'get_meta_attribute', - 'gplus_type': 'get_meta_attribute', - 'gplus_author': 'get_meta_attribute', - 'url': 'get_absolute_url', + "title": "get_title", + "description": "get_description", + "og_description": "get_description", + "twitter_description": "get_description", + "gplus_description": "get_description", + "locale": "get_locale", + "object_type": "get_meta_attribute", + "og_type": "get_meta_attribute", + "og_app_id": "get_meta_attribute", + "og_profile_id": "get_meta_attribute", + "og_publisher": "get_meta_attribute", + "og_author_url": "get_meta_attribute", + "og_author": "get_meta_attribute", + "twitter_type": "get_meta_attribute", + "twitter_site": "get_meta_attribute", + "twitter_author": "get_meta_attribute", + "gplus_type": "get_meta_attribute", + "gplus_author": "get_meta_attribute", + "url": "get_absolute_url", } class Meta: - verbose_name = _('blog category') - verbose_name_plural = _('blog categories') + verbose_name = _("blog category") + verbose_name_plural = _("blog categories") def descendants(self): children = [] @@ -161,24 +155,22 @@ def count_all_sites(self): def get_absolute_url(self, lang=None): lang = _get_language(self, lang) if self.has_translation(lang): - slug = self.safe_translation_getter('slug', language_code=lang) + slug = self.safe_translation_getter("slug", language_code=lang) return reverse( - '%s:posts-category' % self.app_config.namespace, - kwargs={'category': slug}, - current_app=self.app_config.namespace + "%s:posts-category" % self.app_config.namespace, + kwargs={"category": slug}, + current_app=self.app_config.namespace, ) # in case category doesn't exist in this language, gracefully fallback # to posts-latest - return reverse( - '%s:posts-latest' % self.app_config.namespace, current_app=self.app_config.namespace - ) + return reverse("%s:posts-latest" % self.app_config.namespace, current_app=self.app_config.namespace) def __str__(self): - default = ugettext('BlogCategory (no translation)') - return self.safe_translation_getter('name', any_language=True, default=default) + default = gettext("BlogCategory (no translation)") + return self.safe_translation_getter("name", any_language=True, default=default) def save(self, *args, **kwargs): - super(BlogCategory, self).save(*args, **kwargs) + super().save(*args, **kwargs) for lang in self.get_available_languages(): self.set_current_language(lang) if not self.slug and self.name: @@ -186,11 +178,11 @@ def save(self, *args, **kwargs): self.save_translations() def get_title(self): - title = self.safe_translation_getter('name', any_language=True) + title = self.safe_translation_getter("name", any_language=True) return title.strip() def get_description(self): - description = self.safe_translation_getter('meta_description', any_language=True) + description = self.safe_translation_getter("meta_description", any_language=True) return escape(strip_tags(description)).strip() @@ -198,122 +190,138 @@ class Post(KnockerModel, BlogMetaMixin, TranslatableModel): """ Blog post """ - author = models.ForeignKey(dj_settings.AUTH_USER_MODEL, - verbose_name=_('author'), null=True, blank=True, - related_name='djangocms_blog_post_author', on_delete=models.PROTECT) - - date_created = models.DateTimeField(_('created'), auto_now_add=True) - date_modified = models.DateTimeField(_('last modified'), auto_now=True) - date_published = models.DateTimeField(_('published since'), null=True, blank=True) - date_published_end = models.DateTimeField(_('published until'), null=True, blank=True) - date_featured = models.DateTimeField(_('featured date'), null=True, blank=True) - publish = models.BooleanField(_('publish'), default=False) - categories = models.ManyToManyField('djangocms_blog.BlogCategory', verbose_name=_('category'), - related_name='blog_posts', blank=True) - main_image = FilerImageField(verbose_name=_('main image'), blank=True, null=True, - on_delete=models.SET_NULL, - related_name='djangocms_blog_post_image') - main_image_thumbnail = models.ForeignKey(thumbnail_model, - verbose_name=_('main image thumbnail'), - related_name='djangocms_blog_post_thumbnail', - on_delete=models.SET_NULL, - blank=True, null=True) - main_image_full = models.ForeignKey(thumbnail_model, - verbose_name=_('main image full'), - related_name='djangocms_blog_post_full', - on_delete=models.SET_NULL, - blank=True, null=True) - enable_comments = models.BooleanField(verbose_name=_('enable comments on post'), - default=get_setting('ENABLE_COMMENTS')) - sites = models.ManyToManyField('sites.Site', verbose_name=_('Site(s)'), blank=True, - help_text=_('Select sites in which to show the post. ' - 'If none is set it will be ' - 'visible in all the configured sites.')) - app_config = AppHookConfigField( - BlogConfig, null=True, verbose_name=_('app. config') + + author = models.ForeignKey( + dj_settings.AUTH_USER_MODEL, + verbose_name=_("author"), + null=True, + blank=True, + related_name="djangocms_blog_post_author", + on_delete=models.PROTECT, ) + date_created = models.DateTimeField(_("created"), auto_now_add=True) + date_modified = models.DateTimeField(_("last modified"), auto_now=True) + date_published = models.DateTimeField(_("published since"), null=True, blank=True) + date_published_end = models.DateTimeField(_("published until"), null=True, blank=True) + date_featured = models.DateTimeField(_("featured date"), null=True, blank=True) + publish = models.BooleanField(_("publish"), default=False) + categories = models.ManyToManyField( + "djangocms_blog.BlogCategory", verbose_name=_("category"), related_name="blog_posts", blank=True + ) + main_image = FilerImageField( + verbose_name=_("main image"), + blank=True, + null=True, + on_delete=models.SET_NULL, + related_name="djangocms_blog_post_image", + ) + main_image_thumbnail = models.ForeignKey( + thumbnail_model, + verbose_name=_("main image thumbnail"), + related_name="djangocms_blog_post_thumbnail", + on_delete=models.SET_NULL, + blank=True, + null=True, + ) + main_image_full = models.ForeignKey( + thumbnail_model, + verbose_name=_("main image full"), + related_name="djangocms_blog_post_full", + on_delete=models.SET_NULL, + blank=True, + null=True, + ) + enable_comments = models.BooleanField( + verbose_name=_("enable comments on post"), default=get_setting("ENABLE_COMMENTS") + ) + sites = models.ManyToManyField( + "sites.Site", + verbose_name=_("Site(s)"), + blank=True, + help_text=_( + "Select sites in which to show the post. " + "If none is set it will be " + "visible in all the configured sites." + ), + ) + app_config = AppHookConfigField(BlogConfig, null=True, verbose_name=_("app. config")) + translations = TranslatedFields( - title=models.CharField(_('title'), max_length=752), - slug=models.SlugField(_('slug'), max_length=752, blank=True, - db_index=True, allow_unicode=True), - subtitle=models.CharField(verbose_name=_('subtitle'), max_length=767, - blank=True, default=''), - abstract=HTMLField(_('abstract'), blank=True, default='', - configuration='BLOG_ABSTRACT_CKEDITOR'), - meta_description=models.TextField(verbose_name=_('post meta description'), - blank=True, default=''), - meta_keywords=models.TextField(verbose_name=_('post meta keywords'), - blank=True, default=''), - meta_title=models.CharField(verbose_name=_('post meta title'), - help_text=_('used in title tag and social sharing'), - max_length=2000, - blank=True, default=''), - post_text=HTMLField(_('text'), default='', blank=True, - configuration='BLOG_POST_TEXT_CKEDITOR'), - meta={'unique_together': (('language_code', 'slug'),)} + title=models.CharField(_("title"), max_length=752), + slug=models.SlugField(_("slug"), max_length=752, blank=True, db_index=True, allow_unicode=True), + subtitle=models.CharField(verbose_name=_("subtitle"), max_length=767, blank=True, default=""), + abstract=HTMLField(_("abstract"), blank=True, default="", configuration="BLOG_ABSTRACT_CKEDITOR"), + meta_description=models.TextField(verbose_name=_("post meta description"), blank=True, default=""), + meta_keywords=models.TextField(verbose_name=_("post meta keywords"), blank=True, default=""), + meta_title=models.CharField( + verbose_name=_("post meta title"), + help_text=_("used in title tag and social sharing"), + max_length=2000, + blank=True, + default="", + ), + post_text=HTMLField(_("text"), default="", blank=True, configuration="BLOG_POST_TEXT_CKEDITOR"), + meta={"unique_together": (("language_code", "slug"),)}, ) - media = PlaceholderField('media', related_name='media') - content = PlaceholderField('post_content', related_name='post_content') - liveblog = PlaceholderField('live_blog', related_name='live_blog') - enable_liveblog = models.BooleanField(verbose_name=_('enable liveblog on post'), - default=False) + media = PlaceholderField("media", related_name="media") + content = PlaceholderField("post_content", related_name="post_content") + liveblog = PlaceholderField("live_blog", related_name="live_blog") + enable_liveblog = models.BooleanField(verbose_name=_("enable liveblog on post"), default=False) objects = GenericDateTaggedManager() - tags = TaggableManager(blank=True, related_name='djangocms_blog_tags') + tags = TaggableManager(blank=True, related_name="djangocms_blog_tags") - related = SortedManyToManyField('self', - verbose_name=_('Related Posts'), - blank=True, - symmetrical=False) + related = SortedManyToManyField("self", verbose_name=_("Related Posts"), blank=True, symmetrical=False) _metadata = { - 'title': 'get_title', - 'description': 'get_description', - 'keywords': 'get_keywords', - 'og_description': 'get_description', - 'twitter_description': 'get_description', - 'gplus_description': 'get_description', - 'locale': 'get_locale', - 'image': 'get_image_full_url', - 'image_width': 'get_image_width', - 'image_height': 'get_image_height', - 'object_type': 'get_meta_attribute', - 'og_type': 'get_meta_attribute', - 'og_app_id': 'get_meta_attribute', - 'og_profile_id': 'get_meta_attribute', - 'og_publisher': 'get_meta_attribute', - 'og_author_url': 'get_meta_attribute', - 'og_author': 'get_meta_attribute', - 'twitter_type': 'get_meta_attribute', - 'twitter_site': 'get_meta_attribute', - 'twitter_author': 'get_meta_attribute', - 'gplus_type': 'get_meta_attribute', - 'gplus_author': 'get_meta_attribute', - 'published_time': 'date_published', - 'modified_time': 'date_modified', - 'expiration_time': 'date_published_end', - 'tag': 'get_tags', - 'url': 'get_absolute_url', + "title": "get_title", + "description": "get_description", + "keywords": "get_keywords", + "og_description": "get_description", + "twitter_description": "get_description", + "gplus_description": "get_description", + "locale": "get_locale", + "image": "get_image_full_url", + "image_width": "get_image_width", + "image_height": "get_image_height", + "object_type": "get_meta_attribute", + "og_type": "get_meta_attribute", + "og_app_id": "get_meta_attribute", + "og_profile_id": "get_meta_attribute", + "og_publisher": "get_meta_attribute", + "og_author_url": "get_meta_attribute", + "og_author": "get_meta_attribute", + "twitter_type": "get_meta_attribute", + "twitter_site": "get_meta_attribute", + "twitter_author": "get_meta_attribute", + "gplus_type": "get_meta_attribute", + "gplus_author": "get_meta_attribute", + "published_time": "date_published", + "modified_time": "date_modified", + "expiration_time": "date_published_end", + "tag": "get_tags", + "url": "get_absolute_url", } class Meta: - verbose_name = _('blog article') - verbose_name_plural = _('blog articles') - ordering = ('-date_published', '-date_created') - get_latest_by = 'date_published' + verbose_name = _("blog article") + verbose_name_plural = _("blog articles") + ordering = ("-date_published", "-date_created") + get_latest_by = "date_published" def __str__(self): - default = ugettext('Post (no translation)') - return self.safe_translation_getter('title', any_language=True, default=default) + default = gettext("Post (no translation)") + return self.safe_translation_getter("title", any_language=True, default=default) @property def guid(self, language=None): if not language: language = self.get_current_language() - base_string = '-{0}-{2}-{1}-'.format( - language, self.app_config.namespace, - self.safe_translation_getter('slug', language_code=language, any_language=True) + base_string = "-{0}-{2}-{1}-".format( + language, + self.app_config.namespace, + self.safe_translation_getter("slug", language_code=language, any_language=True), ) return hashlib.sha256(force_bytes(base_string)).hexdigest() @@ -331,7 +339,7 @@ def save(self, *args, **kwargs): self.date_published = timezone.now() if not self.slug and self.title: self.slug = slugify(self.title) - super(Post, self).save(*args, **kwargs) + super().save(*args, **kwargs) def save_translation(self, translation, *args, **kwargs): """ @@ -339,7 +347,7 @@ def save_translation(self, translation, *args, **kwargs): """ if not translation.slug and translation.title: translation.slug = slugify(translation.title) - super(Post, self).save_translation(translation, *args, **kwargs) + super().save_translation(translation, *args, **kwargs) def get_absolute_url(self, lang=None): lang = _get_language(self, lang) @@ -350,26 +358,25 @@ def get_absolute_url(self, lang=None): current_date = self.date_published else: current_date = self.date_created - urlconf = get_setting('PERMALINK_URLS')[self.app_config.url_patterns] - if '' in urlconf: - kwargs['year'] = current_date.year - if '' in urlconf: - kwargs['month'] = '%02d' % current_date.month - if '' in urlconf: - kwargs['day'] = '%02d' % current_date.day - if '' in urlconf: - kwargs['slug'] = self.safe_translation_getter( - 'slug', language_code=lang, any_language=True + urlconf = get_setting("PERMALINK_URLS")[self.app_config.url_patterns] + if "" in urlconf: + kwargs["year"] = current_date.year + if "" in urlconf: + kwargs["month"] = "%02d" % current_date.month + if "" in urlconf: + kwargs["day"] = "%02d" % current_date.day + if "" in urlconf: + kwargs["slug"] = self.safe_translation_getter("slug", language_code=lang, any_language=True) # NOQA + if "" in urlconf: + kwargs["category"] = category.safe_translation_getter( + "slug", language_code=lang, any_language=True ) # NOQA - if '' in urlconf: - kwargs['category'] = category.safe_translation_getter( - 'slug', language_code=lang, any_language=True) # NOQA - return reverse('%s:post-detail' % self.app_config.namespace, kwargs=kwargs) + return reverse("%s:post-detail" % self.app_config.namespace, kwargs=kwargs) def get_title(self): - title = self.safe_translation_getter('meta_title', any_language=True) + title = self.safe_translation_getter("meta_title", any_language=True) if not title: - title = self.safe_translation_getter('title', any_language=True) + title = self.safe_translation_getter("title", any_language=True) return title.strip() def get_keywords(self): @@ -377,18 +384,18 @@ def get_keywords(self): Returns the list of keywords (as python list) :return: list """ - return self.safe_translation_getter('meta_keywords', default='').strip().split(',') + return self.safe_translation_getter("meta_keywords", default="").strip().split(",") def get_description(self): - description = self.safe_translation_getter('meta_description', any_language=True) + description = self.safe_translation_getter("meta_description", any_language=True) if not description: - description = self.safe_translation_getter('abstract', any_language=True) + description = self.safe_translation_getter("abstract", any_language=True) return escape(strip_tags(description)).strip() def get_image_full_url(self): if self.main_image: return self.build_absolute_uri(self.main_image.url) - return '' + return "" def get_image_width(self): if self.main_image: @@ -403,7 +410,7 @@ def get_tags(self): Returns the list of object tags as comma separated list """ taglist = [tag.name for tag in self.tags.all()] - return ','.join(taglist) + return ",".join(taglist) def get_author(self): """ @@ -413,68 +420,66 @@ def get_author(self): def _set_default_author(self, current_user): if not self.author_id and self.app_config.set_author: - if get_setting('AUTHOR_DEFAULT') is True: + if get_setting("AUTHOR_DEFAULT") is True: user = current_user else: - user = get_user_model().objects.get(username=get_setting('AUTHOR_DEFAULT')) + user = get_user_model().objects.get(username=get_setting("AUTHOR_DEFAULT")) self.author = user def thumbnail_options(self): if self.main_image_thumbnail_id: return self.main_image_thumbnail.as_dict else: - return get_setting('IMAGE_THUMBNAIL_SIZE') + return get_setting("IMAGE_THUMBNAIL_SIZE") def full_image_options(self): if self.main_image_full_id: return self.main_image_full.as_dict else: - return get_setting('IMAGE_FULL_SIZE') + return get_setting("IMAGE_FULL_SIZE") @property def is_published(self): """ Checks wether the blog post is *really* published by checking publishing dates too """ - return (self.publish and - (self.date_published and self.date_published <= timezone.now()) and - (self.date_published_end is None or self.date_published_end > timezone.now()) - ) + return ( + self.publish + and (self.date_published and self.date_published <= timezone.now()) + and (self.date_published_end is None or self.date_published_end > timezone.now()) + ) def should_knock(self, signal_type, created=False): """ Returns whether to emit knocks according to the post state """ - new = (self.app_config.send_knock_create and self.is_published and - self.date_published == self.date_modified) + new = self.app_config.send_knock_create and self.is_published and self.date_published == self.date_modified updated = self.app_config.send_knock_update and self.is_published - return (new or updated) and signal_type in ('post_save', 'post_delete') + return (new or updated) and signal_type in ("post_save", "post_delete") def get_cache_key(self, language, prefix): - return 'djangocms-blog:{2}:{0}:{1}'.format(language, self.guid, prefix) + return "djangocms-blog:{2}:{0}:{1}".format(language, self.guid, prefix) @property def liveblog_group(self): - return 'liveblog-{apphook}-{lang}-{post}'.format( + return "liveblog-{apphook}-{lang}-{post}".format( lang=self.get_current_language(), apphook=self.app_config.namespace, - post=self.safe_translation_getter('slug', any_language=True) + post=self.safe_translation_getter("slug", any_language=True), ) class BasePostPlugin(CMSPlugin): - app_config = AppHookConfigField( - BlogConfig, null=True, verbose_name=_('app. config'), blank=True - ) + app_config = AppHookConfigField(BlogConfig, null=True, verbose_name=_("app. config"), blank=True) current_site = models.BooleanField( - _('current site'), default=True, help_text=_('Select items from the current site only') + _("current site"), default=True, help_text=_("Select items from the current site only") ) template_folder = models.CharField( max_length=200, - verbose_name=_('Plugin template'), - help_text=_('Select plugin template to load for this instance'), + verbose_name=_("Plugin template"), + help_text=_("Select plugin template to load for this instance"), default=BLOG_PLUGIN_TEMPLATE_FOLDERS[0][0], - choices=BLOG_PLUGIN_TEMPLATE_FOLDERS + choices=BLOG_PLUGIN_TEMPLATE_FOLDERS, ) class Meta: @@ -486,8 +491,8 @@ def optimize(self, qs): :param qs: queryset to optimize :return: optimized queryset """ - return qs.select_related('app_config').prefetch_related( - 'translations', 'categories', 'categories__translations', 'categories__app_config' + return qs.select_related("app_config").prefetch_related( + "translations", "categories", "categories__translations", "categories__app_config" ) def post_queryset(self, request=None, published_only=True): @@ -498,26 +503,37 @@ def post_queryset(self, request=None, published_only=True): if self.current_site: posts = posts.on_site(get_current_site(request)) posts = posts.active_translations(language_code=language) - if (published_only or not request or not getattr(request, 'toolbar', False) or - not request.toolbar.edit_mode_active): + if ( + published_only + or not request + or not getattr(request, "toolbar", False) + or not request.toolbar.edit_mode_active + ): posts = posts.published(current_site=self.current_site) return self.optimize(posts.all()) class LatestPostsPlugin(BasePostPlugin): - latest_posts = models.IntegerField(_('articles'), default=get_setting('LATEST_POSTS'), - help_text=_('The number of latests ' - 'articles to be displayed.')) - tags = TaggableManager(_('filter by tag'), blank=True, - help_text=_('Show only the blog articles tagged with chosen tags.'), - related_name='djangocms_blog_latest_post') - categories = models.ManyToManyField('djangocms_blog.BlogCategory', blank=True, - verbose_name=_('filter by category'), - help_text=_('Show only the blog articles tagged ' - 'with chosen categories.')) + latest_posts = models.IntegerField( + _("articles"), + default=get_setting("LATEST_POSTS"), + help_text=_("The number of latests " "articles to be displayed."), + ) + tags = TaggableManager( + _("filter by tag"), + blank=True, + help_text=_("Show only the blog articles tagged with chosen tags."), + related_name="djangocms_blog_latest_post", + ) + categories = models.ManyToManyField( + "djangocms_blog.BlogCategory", + blank=True, + verbose_name=_("filter by category"), + help_text=_("Show only the blog articles tagged " "with chosen categories."), + ) def __str__(self): - return force_text(_('%s latest articles by tag') % self.latest_posts) + return force_text(_("%s latest articles by tag") % self.latest_posts) def copy_relations(self, oldinstance): for tag in oldinstance.tags.all(): @@ -531,21 +547,23 @@ def get_posts(self, request, published_only=True): posts = posts.filter(tags__in=list(self.tags.all())) if self.categories.exists(): posts = posts.filter(categories__in=list(self.categories.all())) - return self.optimize(posts.distinct())[:self.latest_posts] + return self.optimize(posts.distinct())[: self.latest_posts] class AuthorEntriesPlugin(BasePostPlugin): authors = models.ManyToManyField( - dj_settings.AUTH_USER_MODEL, verbose_name=_('authors'), - limit_choices_to={'djangocms_blog_post_author__publish': True} + dj_settings.AUTH_USER_MODEL, + verbose_name=_("authors"), + limit_choices_to={"djangocms_blog_post_author__publish": True}, ) latest_posts = models.IntegerField( - _('articles'), default=get_setting('LATEST_POSTS'), - help_text=_('The number of author articles to be displayed.') + _("articles"), + default=get_setting("LATEST_POSTS"), + help_text=_("The number of author articles to be displayed."), ) def __str__(self): - return force_text(_('%s latest articles by author') % self.latest_posts) + return force_text(_("%s latest articles by author") % self.latest_posts) def copy_relations(self, oldinstance): self.authors.set(oldinstance.authors.all()) @@ -561,7 +579,7 @@ def get_authors(self, request): # total nb of articles author.count = qs.count() # "the number of author articles to be displayed" - author.posts = qs[:self.latest_posts] + author.posts = qs[: self.latest_posts] return authors @@ -570,18 +588,18 @@ class Meta: abstract = False def __str__(self): - return force_text(_('generic blog plugin')) + return force_text(_("generic blog plugin")) @receiver(pre_delete, sender=Post) def pre_delete_post(sender, instance, **kwargs): for language in instance.get_available_languages(): - key = instance.get_cache_key(language, 'feed') + key = instance.get_cache_key(language, "feed") cache.delete(key) @receiver(post_save, sender=Post) def post_save_post(sender, instance, **kwargs): for language in instance.get_available_languages(): - key = instance.get_cache_key(language, 'feed') + key = instance.get_cache_key(language, "feed") cache.delete(key) diff --git a/djangocms_blog/search_indexes.py b/djangocms_blog/search_indexes.py index 33ea1b2d..fa368bf4 100644 --- a/djangocms_blog/search_indexes.py +++ b/djangocms_blog/search_indexes.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from aldryn_search.helpers import get_plugin_index_data from aldryn_search.utils import get_index_base, strip_tags from django.utils.encoding import force_text @@ -10,13 +9,13 @@ class PostIndex(get_index_base()): - haystack_use_for_indexing = get_setting('ENABLE_SEARCH') + haystack_use_for_indexing = get_setting("ENABLE_SEARCH") index_title = True - author = indexes.CharField(indexed=True, model_attr='get_author') + author = indexes.CharField(indexed=True, model_attr="get_author") keywords = indexes.CharField(null=True) - tags = indexes.CharField(null=True, model_attr='get_tags') + tags = indexes.CharField(null=True, model_attr="get_tags") post_text = indexes.CharField(null=True) def get_title(self, post): @@ -38,8 +37,7 @@ def index_queryset(self, using=None): return qs def get_index_queryset(self, language): - return self.get_model().objects.published().active_translations( - language_code=language) + return self.get_model().objects.published().active_translations(language_code=language) def get_model(self): return Post @@ -47,7 +45,7 @@ def get_model(self): def get_search_data(self, post, language, request): with switch_language(post, language): description = post.get_description() - abstract = strip_tags(post.safe_translation_getter('abstract', default='')) + abstract = strip_tags(post.safe_translation_getter("abstract", default="")) keywords = post.get_keywords() text_bits = [] @@ -56,26 +54,25 @@ def get_search_data(self, post, language, request): if description: text_bits.append(description) if keywords: - text_bits.append(' '.join(keywords)) - self.prepared_data['keywords'] = ','.join(keywords) + text_bits.append(" ".join(keywords)) + self.prepared_data["keywords"] = ",".join(keywords) for category in post.categories.all(): - text_bits.append( - force_text(category.safe_translation_getter('name'))) + text_bits.append(force_text(category.safe_translation_getter("name"))) for tag in post.tags.all(): text_bits.append(force_text(tag.name)) - if get_setting('USE_PLACEHOLDER'): + if get_setting("USE_PLACEHOLDER"): plugins = post.content.cmsplugin_set.filter(language=language) content_bits = [] for base_plugin in plugins: content = get_plugin_index_data(base_plugin, request) - content_bits.append(' '.join(content)) - post_text = ' '.join(content_bits) + content_bits.append(" ".join(content)) + post_text = " ".join(content_bits) else: - post_text = post.safe_translation_getter('post_text') + post_text = post.safe_translation_getter("post_text") if post_text: post_text = strip_tags(post_text) - self.prepared_data['post_text'] = post_text + self.prepared_data["post_text"] = post_text text_bits.append(post_text) - return ' '.join(text_bits) + return " ".join(text_bits) diff --git a/djangocms_blog/settings.py b/djangocms_blog/settings.py index 1cb9c955..bc107081 100644 --- a/djangocms_blog/settings.py +++ b/djangocms_blog/settings.py @@ -1,166 +1,123 @@ -# -*- coding: utf-8 -*- -MENU_TYPE_COMPLETE = 'complete' -MENU_TYPE_CATEGORIES = 'categories' -MENU_TYPE_POSTS = 'posts' -MENU_TYPE_NONE = 'none' +MENU_TYPE_COMPLETE = "complete" +MENU_TYPE_CATEGORIES = "categories" +MENU_TYPE_POSTS = "posts" +MENU_TYPE_NONE = "none" DATE_FORMAT = "%a %d %b %Y %H:%M" -PERMALINK_TYPE_FULL_DATE = 'full_date' -PERMALINK_TYPE_SHORT_DATE = 'short_date' -PERMALINK_TYPE_CATEGORY = 'category' -PERMALINK_TYPE_SLUG = 'slug' +PERMALINK_TYPE_FULL_DATE = "full_date" +PERMALINK_TYPE_SHORT_DATE = "short_date" +PERMALINK_TYPE_CATEGORY = "category" +PERMALINK_TYPE_SLUG = "slug" def get_setting(name): from django.conf import settings - from django.utils.translation import ugettext_lazy as _ + from django.utils.translation import gettext_lazy as _ from meta import settings as meta_settings - PERMALINKS = ( - (PERMALINK_TYPE_FULL_DATE, _('Full date')), - (PERMALINK_TYPE_SHORT_DATE, _('Year / Month')), - (PERMALINK_TYPE_CATEGORY, _('Category')), - (PERMALINK_TYPE_SLUG, _('Just slug')), + PERMALINKS = ( # noqa + (PERMALINK_TYPE_FULL_DATE, _("Full date")), + (PERMALINK_TYPE_SHORT_DATE, _("Year / Month")), + (PERMALINK_TYPE_CATEGORY, _("Category")), + (PERMALINK_TYPE_SLUG, _("Just slug")), ) - PERMALINKS_URLS = { - PERMALINK_TYPE_FULL_DATE: ( - r'^(?P\d{4})/(?P\d{1,2})/(?P\d{1,2})/(?P\w[-\w]*)/$' - ), - PERMALINK_TYPE_SHORT_DATE: ( - r'^(?P\d{4})/(?P\d{1,2})/(?P\w[-\w]*)/$' - ), - PERMALINK_TYPE_CATEGORY: ( - r'^(?P\w[-\w]*)/(?P\w[-\w]*)/$' - ), - PERMALINK_TYPE_SLUG: ( - r'^(?P\w[-\w]*)/$' - ), + PERMALINKS_URLS = { # noqa + PERMALINK_TYPE_FULL_DATE: r"^(?P\d{4})/(?P\d{1,2})/(?P\d{1,2})/(?P\w[-\w]*)/$", + PERMALINK_TYPE_SHORT_DATE: r"^(?P\d{4})/(?P\d{1,2})/(?P\w[-\w]*)/$", + PERMALINK_TYPE_CATEGORY: r"^(?P\w[-\w]*)/(?P\w[-\w]*)/$", + PERMALINK_TYPE_SLUG: r"^(?P\w[-\w]*)/$", } - MENU_TYPES = ( - (MENU_TYPE_COMPLETE, _('Categories and posts')), - (MENU_TYPE_CATEGORIES, _('Categories only')), - (MENU_TYPE_POSTS, _('Posts only')), - (MENU_TYPE_NONE, _('None')), + MENU_TYPES = ( # noqa + (MENU_TYPE_COMPLETE, _("Categories and posts")), + (MENU_TYPE_CATEGORIES, _("Categories only")), + (MENU_TYPE_POSTS, _("Posts only")), + (MENU_TYPE_NONE, _("None")), ) - SITEMAP_CHANGEFREQ_LIST = ( - ('always', _('always')), - ('hourly', _('hourly')), - ('daily', _('daily')), - ('weekly', _('weekly')), - ('monthly', _('monthly')), - ('yearly', _('yearly')), - ('never', _('never')), + SITEMAP_CHANGEFREQ_LIST = ( # noqa + ("always", _("always")), + ("hourly", _("hourly")), + ("daily", _("daily")), + ("weekly", _("weekly")), + ("monthly", _("monthly")), + ("yearly", _("yearly")), + ("never", _("never")), ) default = { - 'BLOG_IMAGE_THUMBNAIL_SIZE': getattr(settings, 'BLOG_IMAGE_THUMBNAIL_SIZE', { - 'size': '120x120', - 'crop': True, - 'upscale': False - }), - - 'BLOG_IMAGE_FULL_SIZE': getattr(settings, 'BLOG_IMAGE_FULL_SIZE', { - 'size': '640x120', - 'crop': True, - 'upscale': False - }), - - 'BLOG_URLCONF': getattr(settings, 'BLOG_URLCONF', 'djangocms_blog.urls'), - 'BLOG_PAGINATION': getattr(settings, 'BLOG_PAGINATION', 10), - 'BLOG_LATEST_POSTS': getattr(settings, 'BLOG_LATEST_POSTS', 5), - 'BLOG_POSTS_LIST_TRUNCWORDS_COUNT': getattr( - settings, 'BLOG_POSTS_LIST_TRUNCWORDS_COUNT', 100 + "BLOG_IMAGE_THUMBNAIL_SIZE": getattr( + settings, "BLOG_IMAGE_THUMBNAIL_SIZE", {"size": "120x120", "crop": True, "upscale": False} ), - 'BLOG_META_DESCRIPTION_LENGTH': getattr( - settings, 'BLOG_META_DESCRIPTION_LENGTH', 320 + "BLOG_IMAGE_FULL_SIZE": getattr( + settings, "BLOG_IMAGE_FULL_SIZE", {"size": "640x120", "crop": True, "upscale": False} ), - 'BLOG_META_TITLE_LENGTH': getattr( - settings, 'BLOG_META_TITLE_LENGTH', 70 + "BLOG_URLCONF": getattr(settings, "BLOG_URLCONF", "djangocms_blog.urls"), + "BLOG_PAGINATION": getattr(settings, "BLOG_PAGINATION", 10), + "BLOG_LATEST_POSTS": getattr(settings, "BLOG_LATEST_POSTS", 5), + "BLOG_POSTS_LIST_TRUNCWORDS_COUNT": getattr(settings, "BLOG_POSTS_LIST_TRUNCWORDS_COUNT", 100), + "BLOG_META_DESCRIPTION_LENGTH": getattr(settings, "BLOG_META_DESCRIPTION_LENGTH", 320), + "BLOG_META_TITLE_LENGTH": getattr(settings, "BLOG_META_TITLE_LENGTH", 70), + "BLOG_MENU_TYPES": MENU_TYPES, + "BLOG_MENU_EMPTY_CATEGORIES": getattr(settings, "MENU_EMPTY_CATEGORIES", True), + "BLOG_TYPE": getattr(settings, "BLOG_TYPE", "Article"), + "BLOG_TYPES": meta_settings.OBJECT_TYPES, + "BLOG_FB_TYPE": getattr(settings, "BLOG_FB_TYPE", "Article"), + "BLOG_FB_TYPES": getattr(settings, "BLOG_FB_TYPES", meta_settings.FB_TYPES), + "BLOG_FB_APPID": getattr(settings, "BLOG_FB_APPID", meta_settings.FB_APPID), + "BLOG_FB_PROFILE_ID": getattr(settings, "BLOG_FB_PROFILE_ID", meta_settings.FB_PROFILE_ID), + "BLOG_FB_PUBLISHER": getattr(settings, "BLOG_FB_PUBLISHER", meta_settings.FB_PUBLISHER), + "BLOG_FB_AUTHOR_URL": getattr(settings, "BLOG_FB_AUTHOR_URL", "get_author_url"), + "BLOG_FB_AUTHOR": getattr(settings, "BLOG_FB_AUTHOR", "get_author_name"), + "BLOG_TWITTER_TYPE": getattr(settings, "BLOG_TWITTER_TYPE", "summary"), + "BLOG_TWITTER_TYPES": getattr(settings, "BLOG_TWITTER_TYPES", meta_settings.TWITTER_TYPES), + "BLOG_TWITTER_SITE": getattr(settings, "BLOG_TWITTER_SITE", meta_settings.TWITTER_SITE), + "BLOG_TWITTER_AUTHOR": getattr(settings, "BLOG_TWITTER_AUTHOR", "get_author_twitter"), + "BLOG_GPLUS_TYPE": getattr(settings, "BLOG_GPLUS_TYPE", "Blog"), + "BLOG_GPLUS_TYPES": getattr(settings, "BLOG_GPLUS_TYPES", meta_settings.GPLUS_TYPES), + "BLOG_GPLUS_AUTHOR": getattr(settings, "BLOG_GPLUS_AUTHOR", "get_author_gplus"), + "BLOG_ENABLE_COMMENTS": getattr(settings, "BLOG_ENABLE_COMMENTS", True), + "BLOG_USE_ABSTRACT": getattr(settings, "BLOG_USE_ABSTRACT", True), + "BLOG_USE_PLACEHOLDER": getattr(settings, "BLOG_USE_PLACEHOLDER", True), + "BLOG_USE_RELATED": getattr(settings, "BLOG_USE_RELATED", True), + "BLOG_MULTISITE": getattr(settings, "BLOG_MULTISITE", True), + "BLOG_AUTHOR_DEFAULT": getattr(settings, "BLOG_AUTHOR_DEFAULT", True), + "BLOG_DEFAULT_PUBLISHED": getattr(settings, "BLOG_DEFAULT_PUBLISHED", False), + "BLOG_ADMIN_POST_FIELDSET_FILTER": getattr(settings, "BLOG_ADMIN_POST_FIELDSET_FILTER", False), + "BLOG_AVAILABLE_PERMALINK_STYLES": getattr(settings, "BLOG_AVAILABLE_PERMALINK_STYLES", PERMALINKS), + "BLOG_PERMALINK_URLS": getattr(settings, "BLOG_PERMALINK_URLS", PERMALINKS_URLS), + "BLOG_DEFAULT_OBJECT_NAME": getattr(settings, "BLOG_DEFAULT_OBJECT_NAME", "Article"), + "BLOG_AUTO_SETUP": getattr(settings, "BLOG_AUTO_SETUP", True), + "BLOG_AUTO_HOME_TITLE": getattr(settings, "BLOG_AUTO_HOME_TITLE", "Home"), + "BLOG_AUTO_BLOG_TITLE": getattr(settings, "BLOG_AUTO_BLOG_TITLE", "Blog"), + "BLOG_AUTO_APP_TITLE": getattr(settings, "BLOG_AUTO_APP_TITLE", "Blog"), + "BLOG_AUTO_NAMESPACE": getattr(settings, "BLOG_AUTO_NAMESPACE", "Blog"), + "BLOG_SITEMAP_PRIORITY_DEFAULT": getattr(settings, "BLOG_SITEMAP_PRIORITY_DEFAULT", "0.5"), + "BLOG_SITEMAP_CHANGEFREQ": getattr(settings, "BLOG_SITEMAP_CHANGEFREQ", SITEMAP_CHANGEFREQ_LIST), + "BLOG_SITEMAP_CHANGEFREQ_DEFAULT": getattr(settings, "BLOG_SITEMAP_CHANGEFREQ_DEFAULT", "monthly"), + "BLOG_ENABLE_SEARCH": getattr(settings, "BLOG_ENABLE_SEARCH", True), + "BLOG_CURRENT_POST_IDENTIFIER": getattr(settings, "BLOG_CURRENT_POST_IDENTIFIER", "djangocms_post_current"), + "BLOG_CURRENT_NAMESPACE": getattr(settings, "BLOG_CURRENT_NAMESPACE", "djangocms_post_current_config"), + "BLOG_ENABLE_THROUGH_TOOLBAR_MENU": getattr(settings, "BLOG_ENABLE_THROUGH_TOOLBAR_MENU", False), + "BLOG_PLUGIN_MODULE_NAME": getattr(settings, "BLOG_PLUGIN_MODULE_NAME", _("Blog")), + "BLOG_LATEST_ENTRIES_PLUGIN_NAME": getattr( + settings, "BLOG_LATEST_ENTRIES_PLUGIN_NAME", _("Latest Blog Articles") ), - 'BLOG_MENU_TYPES': MENU_TYPES, - 'BLOG_MENU_EMPTY_CATEGORIES': getattr(settings, 'MENU_EMPTY_CATEGORIES', True), - 'BLOG_TYPE': getattr(settings, 'BLOG_TYPE', 'Article'), - 'BLOG_TYPES': meta_settings.OBJECT_TYPES, - 'BLOG_FB_TYPE': getattr(settings, 'BLOG_FB_TYPE', 'Article'), - 'BLOG_FB_TYPES': getattr(settings, 'BLOG_FB_TYPES', meta_settings.FB_TYPES), - 'BLOG_FB_APPID': getattr(settings, 'BLOG_FB_APPID', meta_settings.FB_APPID), - 'BLOG_FB_PROFILE_ID': getattr(settings, 'BLOG_FB_PROFILE_ID', meta_settings.FB_PROFILE_ID), - 'BLOG_FB_PUBLISHER': getattr(settings, 'BLOG_FB_PUBLISHER', meta_settings.FB_PUBLISHER), - 'BLOG_FB_AUTHOR_URL': getattr(settings, 'BLOG_FB_AUTHOR_URL', 'get_author_url'), - 'BLOG_FB_AUTHOR': getattr(settings, 'BLOG_FB_AUTHOR', 'get_author_name'), - 'BLOG_TWITTER_TYPE': getattr(settings, 'BLOG_TWITTER_TYPE', 'summary'), - 'BLOG_TWITTER_TYPES': getattr(settings, 'BLOG_TWITTER_TYPES', meta_settings.TWITTER_TYPES), - 'BLOG_TWITTER_SITE': getattr(settings, 'BLOG_TWITTER_SITE', meta_settings.TWITTER_SITE), - 'BLOG_TWITTER_AUTHOR': getattr(settings, 'BLOG_TWITTER_AUTHOR', 'get_author_twitter'), - 'BLOG_GPLUS_TYPE': getattr(settings, 'BLOG_GPLUS_TYPE', 'Blog'), - 'BLOG_GPLUS_TYPES': getattr(settings, 'BLOG_GPLUS_TYPES', meta_settings.GPLUS_TYPES), - 'BLOG_GPLUS_AUTHOR': getattr(settings, 'BLOG_GPLUS_AUTHOR', 'get_author_gplus'), - 'BLOG_ENABLE_COMMENTS': getattr(settings, 'BLOG_ENABLE_COMMENTS', True), - 'BLOG_USE_ABSTRACT': getattr(settings, 'BLOG_USE_ABSTRACT', True), - 'BLOG_USE_PLACEHOLDER': getattr(settings, 'BLOG_USE_PLACEHOLDER', True), - 'BLOG_USE_RELATED': getattr(settings, 'BLOG_USE_RELATED', True), - 'BLOG_MULTISITE': getattr(settings, 'BLOG_MULTISITE', True), - 'BLOG_AUTHOR_DEFAULT': getattr(settings, 'BLOG_AUTHOR_DEFAULT', True), - 'BLOG_DEFAULT_PUBLISHED': getattr(settings, 'BLOG_DEFAULT_PUBLISHED', False), - 'BLOG_ADMIN_POST_FIELDSET_FILTER': getattr( - settings, 'BLOG_ADMIN_POST_FIELDSET_FILTER', False), - 'BLOG_AVAILABLE_PERMALINK_STYLES': getattr( - settings, 'BLOG_AVAILABLE_PERMALINK_STYLES', PERMALINKS + "BLOG_LATEST_ENTRIES_PLUGIN_NAME_CACHED": getattr( + settings, "BLOG_LATEST_ENTRIES_PLUGIN_NAME_CACHED", _("Latest Blog Articles - Cache") ), - 'BLOG_PERMALINK_URLS': getattr(settings, 'BLOG_PERMALINK_URLS', PERMALINKS_URLS), - 'BLOG_DEFAULT_OBJECT_NAME': getattr(settings, 'BLOG_DEFAULT_OBJECT_NAME', 'Article'), - - 'BLOG_AUTO_SETUP': getattr(settings, 'BLOG_AUTO_SETUP', True), - 'BLOG_AUTO_HOME_TITLE': getattr(settings, 'BLOG_AUTO_HOME_TITLE', 'Home'), - 'BLOG_AUTO_BLOG_TITLE': getattr(settings, 'BLOG_AUTO_BLOG_TITLE', 'Blog'), - 'BLOG_AUTO_APP_TITLE': getattr(settings, 'BLOG_AUTO_APP_TITLE', 'Blog'), - 'BLOG_AUTO_NAMESPACE': getattr(settings, 'BLOG_AUTO_NAMESPACE', 'Blog'), - - 'BLOG_SITEMAP_PRIORITY_DEFAULT': getattr(settings, 'BLOG_SITEMAP_PRIORITY_DEFAULT', '0.5'), - 'BLOG_SITEMAP_CHANGEFREQ': getattr( - settings, 'BLOG_SITEMAP_CHANGEFREQ', SITEMAP_CHANGEFREQ_LIST + "BLOG_AUTHOR_POSTS_PLUGIN_NAME": getattr(settings, "BLOG_AUTHOR_POSTS_PLUGIN_NAME", _("Author Blog Articles")), + "BLOG_AUTHOR_POSTS_LIST_PLUGIN_NAME": getattr( + settings, "BLOG_AUTHOR_POSTS_LIST_PLUGIN_NAME", _("Author Blog Articles List") ), - 'BLOG_SITEMAP_CHANGEFREQ_DEFAULT': getattr( - settings, 'BLOG_SITEMAP_CHANGEFREQ_DEFAULT', 'monthly' + "BLOG_TAGS_PLUGIN_NAME": getattr(settings, "BLOG_TAGS_PLUGIN_NAME", _("Tags")), + "BLOG_CATEGORY_PLUGIN_NAME": getattr(settings, "BLOG_CATEGORY_PLUGIN_NAME", _("Categories")), + "BLOG_ARCHIVE_PLUGIN_NAME": getattr(settings, "BLOG_ARCHIVE_PLUGIN_NAME", _("Archive")), + "BLOG_FEED_CACHE_TIMEOUT": getattr(settings, "BLOG_FEED_CACHE_TIMEOUT", 3600), + "BLOG_FEED_INSTANT_ITEMS": getattr(settings, "BLOG_FEED_INSTANT_ITEMS", 50), + "BLOG_FEED_LATEST_ITEMS": getattr(settings, "BLOG_FEED_LATEST_ITEMS", 10), + "BLOG_FEED_TAGS_ITEMS": getattr(settings, "BLOG_FEED_TAGS_ITEMS", 10), + "BLOG_LIVEBLOG_PLUGINS": getattr(settings, "BLOG_LIVEBLOG_PLUGINS", ("LiveblogPlugin",)), + "BLOG_PLUGIN_TEMPLATE_FOLDERS": getattr( + settings, "BLOG_PLUGIN_TEMPLATE_FOLDERS", (("plugins", _("Default template")),) ), - - 'BLOG_ENABLE_SEARCH': getattr(settings, 'BLOG_ENABLE_SEARCH', True), - 'BLOG_CURRENT_POST_IDENTIFIER': getattr( - settings, 'BLOG_CURRENT_POST_IDENTIFIER', 'djangocms_post_current'), - 'BLOG_CURRENT_NAMESPACE': getattr( - settings, 'BLOG_CURRENT_NAMESPACE', 'djangocms_post_current_config'), - 'BLOG_ENABLE_THROUGH_TOOLBAR_MENU': getattr( - settings, 'BLOG_ENABLE_THROUGH_TOOLBAR_MENU', False), - - 'BLOG_PLUGIN_MODULE_NAME': getattr(settings, 'BLOG_PLUGIN_MODULE_NAME', _('Blog')), - 'BLOG_LATEST_ENTRIES_PLUGIN_NAME': getattr( - settings, 'BLOG_LATEST_ENTRIES_PLUGIN_NAME', _('Latest Blog Articles')), - 'BLOG_LATEST_ENTRIES_PLUGIN_NAME_CACHED': getattr( - settings, 'BLOG_LATEST_ENTRIES_PLUGIN_NAME_CACHED', _('Latest Blog Articles - Cache')), - 'BLOG_AUTHOR_POSTS_PLUGIN_NAME': getattr( - settings, 'BLOG_AUTHOR_POSTS_PLUGIN_NAME', _('Author Blog Articles')), - 'BLOG_AUTHOR_POSTS_LIST_PLUGIN_NAME': getattr( - settings, 'BLOG_AUTHOR_POSTS_LIST_PLUGIN_NAME', _('Author Blog Articles List')), - 'BLOG_TAGS_PLUGIN_NAME': getattr( - settings, 'BLOG_TAGS_PLUGIN_NAME', _('Tags')), - 'BLOG_CATEGORY_PLUGIN_NAME': getattr( - settings, 'BLOG_CATEGORY_PLUGIN_NAME', _('Categories')), - 'BLOG_ARCHIVE_PLUGIN_NAME': getattr( - settings, 'BLOG_ARCHIVE_PLUGIN_NAME', _('Archive')), - 'BLOG_FEED_CACHE_TIMEOUT': getattr( - settings, 'BLOG_FEED_CACHE_TIMEOUT', 3600), - 'BLOG_FEED_INSTANT_ITEMS': getattr( - settings, 'BLOG_FEED_INSTANT_ITEMS', 50), - 'BLOG_FEED_LATEST_ITEMS': getattr( - settings, 'BLOG_FEED_LATEST_ITEMS', 10), - 'BLOG_FEED_TAGS_ITEMS': getattr( - settings, 'BLOG_FEED_TAGS_ITEMS', 10), - 'BLOG_LIVEBLOG_PLUGINS': getattr( - settings, 'BLOG_LIVEBLOG_PLUGINS', ('LiveblogPlugin',)), - - 'BLOG_PLUGIN_TEMPLATE_FOLDERS': getattr( - settings, 'BLOG_PLUGIN_TEMPLATE_FOLDERS', (('plugins', _('Default template')),)), - 'BLOG_USE_FALLBACK_LANGUAGE_IN_URL': getattr( - settings, 'BLOG_USE_FALLBACK_LANGUAGE_IN_URL', False), - + "BLOG_USE_FALLBACK_LANGUAGE_IN_URL": getattr(settings, "BLOG_USE_FALLBACK_LANGUAGE_IN_URL", False), } - return default['BLOG_%s' % name] + return default["BLOG_%s" % name] diff --git a/djangocms_blog/sitemaps/__init__.py b/djangocms_blog/sitemaps/__init__.py index ba2b292b..bea10b9e 100644 --- a/djangocms_blog/sitemaps/__init__.py +++ b/djangocms_blog/sitemaps/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from cms.utils import get_language_list from django.contrib.sitemaps import Sitemap from django.urls.exceptions import NoReverseMatch @@ -9,20 +8,19 @@ class BlogSitemap(Sitemap): - def __init__(self, *args, **kwargs): - super(BlogSitemap, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.url_cache = {} def priority(self, obj): if obj and obj.app_config: return obj.app_config.sitemap_priority - return get_setting('SITEMAP_PRIORITY_DEFAULT') + return get_setting("SITEMAP_PRIORITY_DEFAULT") def changefreq(self, obj): if obj and obj.app_config: return obj.app_config.sitemap_changefreq - return get_setting('SITEMAP_CHANGEFREQ_DEFAULT') + return get_setting("SITEMAP_CHANGEFREQ_DEFAULT") def location(self, obj): with smart_override(obj.get_current_language()): diff --git a/djangocms_blog/static/djangocms_blog/css/djangocms_blog_admin.css b/djangocms_blog/static/djangocms_blog/css/djangocms_blog_admin.css index 855da1b9..dc911843 100644 --- a/djangocms_blog/static/djangocms_blog/css/djangocms_blog_admin.css +++ b/djangocms_blog/static/djangocms_blog/css/djangocms_blog_admin.css @@ -43,4 +43,4 @@ ul.as-selections.vTextField { ul.as-selections li { list-style: none; -} \ No newline at end of file +} diff --git a/djangocms_blog/taggit_urls.py b/djangocms_blog/taggit_urls.py index c7b3196a..4984f0da 100644 --- a/djangocms_blog/taggit_urls.py +++ b/djangocms_blog/taggit_urls.py @@ -1,6 +1,5 @@ -# -*- coding: utf-8 -*- from django.conf.urls import include, url urlpatterns = [ - url(r'^taggit_autosuggest/', include('taggit_autosuggest.urls')), + url(r"^taggit_autosuggest/", include("taggit_autosuggest.urls")), ] diff --git a/djangocms_blog/templates/djangocms_blog/plugins/archive.html b/djangocms_blog/templates/djangocms_blog/plugins/archive.html index 190a43c8..86489880 100644 --- a/djangocms_blog/templates/djangocms_blog/plugins/archive.html +++ b/djangocms_blog/templates/djangocms_blog/plugins/archive.html @@ -28,4 +28,4 @@

{% trans "Archive" %}

{% endwith %} -{% endspaceless %} \ No newline at end of file +{% endspaceless %} diff --git a/djangocms_blog/templates/djangocms_blog/plugins/latest_entries.html b/djangocms_blog/templates/djangocms_blog/plugins/latest_entries.html index b43bea66..c2276d58 100644 --- a/djangocms_blog/templates/djangocms_blog/plugins/latest_entries.html +++ b/djangocms_blog/templates/djangocms_blog/plugins/latest_entries.html @@ -8,4 +8,4 @@ {% endfor %} -{% endspaceless %} \ No newline at end of file +{% endspaceless %} diff --git a/djangocms_blog/templates/djangocms_blog/plugins/tags.html b/djangocms_blog/templates/djangocms_blog/plugins/tags.html index c4ebb486..4267ff38 100644 --- a/djangocms_blog/templates/djangocms_blog/plugins/tags.html +++ b/djangocms_blog/templates/djangocms_blog/plugins/tags.html @@ -16,4 +16,4 @@

{% trans "Tags" %}

{% endfor %} -{% endspaceless %} \ No newline at end of file +{% endspaceless %} diff --git a/djangocms_blog/templates/djangocms_blog/post_archive.html b/djangocms_blog/templates/djangocms_blog/post_archive.html index f3ebbd1c..0d56bc99 100644 --- a/djangocms_blog/templates/djangocms_blog/post_archive.html +++ b/djangocms_blog/templates/djangocms_blog/post_archive.html @@ -1,2 +1 @@ {% extends "djangocms_blog/post_list.html" %} - diff --git a/djangocms_blog/templatetags/__init__.py b/djangocms_blog/templatetags/__init__.py index 40a96afc..e69de29b 100644 --- a/djangocms_blog/templatetags/__init__.py +++ b/djangocms_blog/templatetags/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/djangocms_blog/templatetags/djangocms_blog.py b/djangocms_blog/templatetags/djangocms_blog.py index 87c2ced3..c2bac0e7 100644 --- a/djangocms_blog/templatetags/djangocms_blog.py +++ b/djangocms_blog/templatetags/djangocms_blog.py @@ -1,11 +1,10 @@ -# -*- coding: utf-8 -*- from cms.utils.plugins import get_plugins from django import template register = template.Library() -@register.simple_tag(name='media_plugins', takes_context=True) +@register.simple_tag(name="media_plugins", takes_context=True) def media_plugins(context, post): """ Extract :py:class:`djangocms_blog.media.base.MediaAttachmentPluginMixin` @@ -25,13 +24,13 @@ def media_plugins(context, post): :return: list of :py:class:`djangocms_blog.media.base.MediaAttachmentPluginMixin` plugins :rtype: List[djangocms_blog.media.base.MediaAttachmentPluginMixin] """ - request = context['request'] + request = context["request"] if post.media.get_plugins().exists(): return get_plugins(request, post.media, None) return [] -@register.simple_tag(name='media_images', takes_context=True) +@register.simple_tag(name="media_images", takes_context=True) def media_images(context, post, main=True): """ Extract images of the given size from all the @@ -64,16 +63,16 @@ def media_images(context, post, main=True): """ plugins = media_plugins(context, post) if main: - image_method = 'get_main_image' + image_method = "get_main_image" else: - image_method = 'get_thumb_image' + image_method = "get_thumb_image" images = [] for plugin in plugins: try: images.append(getattr(plugin, image_method)()) except Exception: try: - image = getattr(plugin, 'poster') + image = plugin.poster if image: images.append(image.url) except AttributeError: diff --git a/djangocms_blog/urls.py b/djangocms_blog/urls.py index ff164dd6..2d98d5b2 100644 --- a/djangocms_blog/urls.py +++ b/djangocms_blog/urls.py @@ -1,45 +1,37 @@ -# -*- coding: utf-8 -*- from django.conf.urls import url from .feeds import FBInstantArticles, LatestEntriesFeed, TagFeed from .settings import get_setting from .views import ( - AuthorEntriesView, CategoryEntriesView, PostArchiveView, PostDetailView, PostListView, + AuthorEntriesView, + CategoryEntriesView, + PostArchiveView, + PostDetailView, + PostListView, TaggedListView, ) def get_urls(): - urls = get_setting('PERMALINK_URLS') + urls = get_setting("PERMALINK_URLS") details = [] for urlconf in urls.values(): - details.append( - url(urlconf, PostDetailView.as_view(), name='post-detail'), - ) + details.append(url(urlconf, PostDetailView.as_view(), name="post-detail"),) return details detail_urls = get_urls() # module-level app_name attribute as per django 1.9+ -app_name = 'djangocms_blog' +app_name = "djangocms_blog" urlpatterns = [ - url(r'^$', - PostListView.as_view(), name='posts-latest'), - url(r'^feed/$', - LatestEntriesFeed(), name='posts-latest-feed'), - url(r'^feed/fb/$', - FBInstantArticles(), name='posts-latest-feed-fb'), - url(r'^(?P\d{4})/$', - PostArchiveView.as_view(), name='posts-archive'), - url(r'^(?P\d{4})/(?P\d{1,2})/$', - PostArchiveView.as_view(), name='posts-archive'), - url(r'^author/(?P[\w\.@+-]+)/$', - AuthorEntriesView.as_view(), name='posts-author'), - url(r'^category/(?P[\w\.@+-]+)/$', - CategoryEntriesView.as_view(), name='posts-category'), - url(r'^tag/(?P[-\w]+)/$', - TaggedListView.as_view(), name='posts-tagged'), - url(r'^tag/(?P[-\w]+)/feed/$', - TagFeed(), name='posts-tagged-feed'), + url(r"^$", PostListView.as_view(), name="posts-latest"), + url(r"^feed/$", LatestEntriesFeed(), name="posts-latest-feed"), + url(r"^feed/fb/$", FBInstantArticles(), name="posts-latest-feed-fb"), + url(r"^(?P\d{4})/$", PostArchiveView.as_view(), name="posts-archive"), + url(r"^(?P\d{4})/(?P\d{1,2})/$", PostArchiveView.as_view(), name="posts-archive"), + url(r"^author/(?P[\w\.@+-]+)/$", AuthorEntriesView.as_view(), name="posts-author"), + url(r"^category/(?P[\w\.@+-]+)/$", CategoryEntriesView.as_view(), name="posts-category"), + url(r"^tag/(?P[-\w]+)/$", TaggedListView.as_view(), name="posts-tagged"), + url(r"^tag/(?P[-\w]+)/feed/$", TagFeed(), name="posts-tagged-feed"), ] + detail_urls diff --git a/djangocms_blog/views.py b/djangocms_blog/views.py index da73db84..df0435f9 100644 --- a/djangocms_blog/views.py +++ b/djangocms_blog/views.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os.path from aldryn_apphooks_config.mixins import AppConfigMixin @@ -28,161 +27,146 @@ def optimize(self, qs): :param qs: queryset to optimize :return: optimized queryset """ - return qs.select_related('app_config').prefetch_related( - 'translations', 'categories', 'categories__translations', 'categories__app_config' + return qs.select_related("app_config").prefetch_related( + "translations", "categories", "categories__translations", "categories__app_config" ) def get_view_url(self): if not self.view_url_name: - raise ImproperlyConfigured( - 'Missing `view_url_name` attribute on {0}'.format(self.__class__.__name__) - ) - - url = reverse( - self.view_url_name, - args=self.args, - kwargs=self.kwargs, - current_app=self.namespace - ) + raise ImproperlyConfigured("Missing `view_url_name` attribute on {}".format(self.__class__.__name__)) + + url = reverse(self.view_url_name, args=self.args, kwargs=self.kwargs, current_app=self.namespace) return self.request.build_absolute_uri(url) def get_queryset(self): language = get_language() - queryset = self.model._default_manager.namespace( - self.namespace - ).active_translations( - language_code=language - ) - if not getattr(self.request, 'toolbar', None) or not self.request.toolbar.edit_mode_active: + queryset = self.model._default_manager.namespace(self.namespace).active_translations(language_code=language) + if not getattr(self.request, "toolbar", None) or not self.request.toolbar.edit_mode_active: queryset = queryset.published() - setattr(self.request, get_setting('CURRENT_NAMESPACE'), self.config) + setattr(self.request, get_setting("CURRENT_NAMESPACE"), self.config) return self.optimize(queryset.on_site()) def get_template_names(self): - template_path = (self.config and self.config.template_prefix) or 'djangocms_blog' + template_path = (self.config and self.config.template_prefix) or "djangocms_blog" return os.path.join(template_path, self.base_template_name) class BaseBlogListView(BaseBlogView): - context_object_name = 'post_list' - base_template_name = 'post_list.html' + context_object_name = "post_list" + base_template_name = "post_list.html" def get_context_data(self, **kwargs): - context = super(BaseBlogListView, self).get_context_data(**kwargs) - context['TRUNCWORDS_COUNT'] = get_setting('POSTS_LIST_TRUNCWORDS_COUNT') + context = super().get_context_data(**kwargs) + context["TRUNCWORDS_COUNT"] = get_setting("POSTS_LIST_TRUNCWORDS_COUNT") return context def get_paginate_by(self, queryset): - return (self.config and self.config.paginate_by) or get_setting('PAGINATION') + return (self.config and self.config.paginate_by) or get_setting("PAGINATION") class PostDetailView(TranslatableSlugMixin, BaseBlogView, DetailView): - context_object_name = 'post' - base_template_name = 'post_detail.html' - slug_field = 'slug' - view_url_name = 'djangocms_blog:post-detail' + context_object_name = "post" + base_template_name = "post_detail.html" + slug_field = "slug" + view_url_name = "djangocms_blog:post-detail" instant_article = False def liveblog_enabled(self): - return self.object.enable_liveblog and apps.is_installed('djangocms_blog.liveblog') + return self.object.enable_liveblog and apps.is_installed("djangocms_blog.liveblog") def get_template_names(self): if self.instant_article: - template_path = (self.config and self.config.template_prefix) or 'djangocms_blog' - return os.path.join(template_path, 'post_instant_article.html') + template_path = (self.config and self.config.template_prefix) or "djangocms_blog" + return os.path.join(template_path, "post_instant_article.html") else: - return super(PostDetailView, self).get_template_names() + return super().get_template_names() def get_queryset(self): queryset = self.model._default_manager.all() - if not getattr(self.request, 'toolbar', None) or not self.request.toolbar.edit_mode_active: + if not getattr(self.request, "toolbar", None) or not self.request.toolbar.edit_mode_active: queryset = queryset.published() return self.optimize(queryset) def get(self, *args, **kwargs): # submit object to cms to get corrent language switcher and selected category behavior - if hasattr(self.request, 'toolbar'): + if hasattr(self.request, "toolbar"): self.request.toolbar.set_object(self.get_object()) - return super(PostDetailView, self).get(*args, **kwargs) + return super().get(*args, **kwargs) def get_context_data(self, **kwargs): - context = super(PostDetailView, self).get_context_data(**kwargs) - context['meta'] = self.get_object().as_meta() - context['instant_article'] = self.instant_article - context['use_placeholder'] = get_setting('USE_PLACEHOLDER') - setattr(self.request, get_setting('CURRENT_POST_IDENTIFIER'), self.get_object()) + context = super().get_context_data(**kwargs) + context["meta"] = self.get_object().as_meta() + context["instant_article"] = self.instant_article + context["use_placeholder"] = get_setting("USE_PLACEHOLDER") + setattr(self.request, get_setting("CURRENT_POST_IDENTIFIER"), self.get_object()) return context class PostListView(BaseBlogListView, ListView): - view_url_name = 'djangocms_blog:posts-latest' + view_url_name = "djangocms_blog:posts-latest" class PostArchiveView(BaseBlogListView, ListView): - date_field = 'date_published' + date_field = "date_published" allow_empty = True allow_future = True - view_url_name = 'djangocms_blog:posts-archive' + view_url_name = "djangocms_blog:posts-archive" def get_queryset(self): - qs = super(PostArchiveView, self).get_queryset() - if 'month' in self.kwargs: - qs = qs.filter(**{'%s__month' % self.date_field: self.kwargs['month']}) - if 'year' in self.kwargs: - qs = qs.filter(**{'%s__year' % self.date_field: self.kwargs['year']}) + qs = super().get_queryset() + if "month" in self.kwargs: + qs = qs.filter(**{"%s__month" % self.date_field: self.kwargs["month"]}) + if "year" in self.kwargs: + qs = qs.filter(**{"%s__year" % self.date_field: self.kwargs["year"]}) return self.optimize(qs) def get_context_data(self, **kwargs): - kwargs['month'] = int(self.kwargs.get('month')) if 'month' in self.kwargs else None - kwargs['year'] = int(self.kwargs.get('year')) if 'year' in self.kwargs else None - if kwargs['year']: - kwargs['archive_date'] = now().replace(kwargs['year'], kwargs['month'] or 1, 1) - context = super(PostArchiveView, self).get_context_data(**kwargs) + kwargs["month"] = int(self.kwargs.get("month")) if "month" in self.kwargs else None + kwargs["year"] = int(self.kwargs.get("year")) if "year" in self.kwargs else None + if kwargs["year"]: + kwargs["archive_date"] = now().replace(kwargs["year"], kwargs["month"] or 1, 1) + context = super().get_context_data(**kwargs) return context class TaggedListView(BaseBlogListView, ListView): - view_url_name = 'djangocms_blog:posts-tagged' + view_url_name = "djangocms_blog:posts-tagged" def get_queryset(self): - qs = super(TaggedListView, self).get_queryset() - return self.optimize(qs.filter(tags__slug=self.kwargs['tag'])) + qs = super().get_queryset() + return self.optimize(qs.filter(tags__slug=self.kwargs["tag"])) def get_context_data(self, **kwargs): - kwargs['tagged_entries'] = (self.kwargs.get('tag') - if 'tag' in self.kwargs else None) - context = super(TaggedListView, self).get_context_data(**kwargs) + kwargs["tagged_entries"] = self.kwargs.get("tag") if "tag" in self.kwargs else None + context = super().get_context_data(**kwargs) return context class AuthorEntriesView(BaseBlogListView, ListView): - view_url_name = 'djangocms_blog:posts-author' + view_url_name = "djangocms_blog:posts-author" def get_queryset(self): - qs = super(AuthorEntriesView, self).get_queryset() - if 'username' in self.kwargs: - qs = qs.filter(**{'author__%s' % User.USERNAME_FIELD: self.kwargs['username']}) + qs = super().get_queryset() + if "username" in self.kwargs: + qs = qs.filter(**{"author__%s" % User.USERNAME_FIELD: self.kwargs["username"]}) return self.optimize(qs) def get_context_data(self, **kwargs): - kwargs['author'] = get_object_or_404( - User, - **{User.USERNAME_FIELD: self.kwargs.get('username')} - ) - context = super(AuthorEntriesView, self).get_context_data(**kwargs) + kwargs["author"] = get_object_or_404(User, **{User.USERNAME_FIELD: self.kwargs.get("username")}) + context = super().get_context_data(**kwargs) return context class CategoryEntriesView(BaseBlogListView, ListView): _category = None - view_url_name = 'djangocms_blog:posts-category' + view_url_name = "djangocms_blog:posts-category" @property def category(self): if not self._category: try: self._category = BlogCategory.objects.active_translations( - get_language(), slug=self.kwargs['category'] + get_language(), slug=self.kwargs["category"] ).get() except BlogCategory.DoesNotExist: raise Http404 @@ -190,18 +174,18 @@ def category(self): def get(self, *args, **kwargs): # submit object to cms toolbar to get correct language switcher behavior - if hasattr(self.request, 'toolbar'): + if hasattr(self.request, "toolbar"): self.request.toolbar.set_object(self.category) - return super(CategoryEntriesView, self).get(*args, **kwargs) + return super().get(*args, **kwargs) def get_queryset(self): - qs = super(CategoryEntriesView, self).get_queryset() - if 'category' in self.kwargs: + qs = super().get_queryset() + if "category" in self.kwargs: qs = qs.filter(categories=self.category.pk) return self.optimize(qs) def get_context_data(self, **kwargs): - kwargs['category'] = self.category - context = super(CategoryEntriesView, self).get_context_data(**kwargs) - context['meta'] = self.category.as_meta() + kwargs["category"] = self.category + context = super().get_context_data(**kwargs) + context["meta"] = self.category.as_meta() return context diff --git a/docs/conf.py b/docs/conf.py index e6e29bb6..850acb94 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # djangocms-blog documentation build configuration file, created by # sphinx-quickstart on Sun Jun 5 23:27:04 2016. @@ -12,69 +11,61 @@ # All configuration values have a default; values that are commented out # serve to show the default. +# fmt: off import os -import shlex import sys -import sphinx.environment -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. import sphinx_rtd_theme -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('.')) parent = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) sys.path.insert(0, parent) -sys.path.insert(0, os.path.join(parent, 'tests')) - -import cms_helper # isort:skip -import djangocms_blog # isort:skip -cms_helper.setup() +sys.path.insert(0, os.path.join(parent, "tests")) +import cms_helper # isort:skip # noqa +import djangocms_blog # isort:skip # noqa +# fmt: on -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)) +cms_helper.setup() -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.autodoc", + "sphinx.ext.doctest", + "sphinx.ext.intersphinx", + "sphinx.ext.todo", + "sphinx.ext.coverage", ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +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'djangocms-blog' -copyright = u'2016, Iacopo Spalletti' -author = u'Iacopo Spalletti' +project = "djangocms-blog" +copyright = "2016, Iacopo Spalletti" # noqa +author = "Iacopo Spalletti" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -94,37 +85,37 @@ def _warn_node(self, msg, node, *args, **kwargs): # 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 # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = True @@ -141,151 +132,144 @@ def _warn_node(self, msg, node, *args, **kwargs): # 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"] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. -#html_extra_path = [] +# html_extra_path = [] # 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 # Language to be used for generating the HTML full-text search index. # Sphinx supports the following languages: # 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' # 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' -#html_search_language = 'en' +# html_search_language = 'en' # A dictionary with options for the search language support, empty by default. # Now only 'ja' uses this config value -#html_search_options = {'type': 'default'} +# html_search_options = {'type': 'default'} # The name of a javascript file (relative to the configuration directory) that # implements a search results scorer. If empty, the default will be used. -#html_search_scorer = 'scorer.js' +# html_search_scorer = 'scorer.js' # Output file base name for HTML help builder. -htmlhelp_basename = 'djangocms-blogdoc' +htmlhelp_basename = "djangocms-blogdoc" # -- 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': '', - -# Latex figure (float) alignment -#'figure_align': 'htbp', + # The paper size ('letterpaper' or 'a4paper'). + # 'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + # 'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + # 'preamble': '', + # Latex figure (float) alignment + # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'djangocms-blog.tex', u'djangocms-blog Documentation', - u'Iacopo Spalletti', 'manual'), + (master_doc, "djangocms-blog.tex", "djangocms-blog 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 = [ - (master_doc, 'djangocms-blog', u'djangocms-blog Documentation', - [author], 1) -] +man_pages = [(master_doc, "djangocms-blog", "djangocms-blog Documentation", [author], 1)] # If true, show URL addresses after external links. -#man_show_urls = False +# man_show_urls = False # -- Options for Texinfo output ------------------------------------------- @@ -294,23 +278,29 @@ def _warn_node(self, msg, node, *args, **kwargs): # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'djangocms-blog', u'djangocms-blog Documentation', - author, 'djangocms-blog', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + "djangocms-blog", + "djangocms-blog Documentation", + author, + "djangocms-blog", + "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 # Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'https://docs.python.org/': None} +intersphinx_mapping = {"https://docs.python.org/": None} 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/features/media.rst b/docs/features/media.rst index b7ad0ca0..014b5ec1 100644 --- a/docs/features/media.rst +++ b/docs/features/media.rst @@ -208,4 +208,3 @@ placeholder allows to extract the image from the field and display along with the generated previews by seamlessly using ``media_images``. The rendering of the full content is of course fully supported. - diff --git a/docs/index.rst b/docs/index.rst index 4a39bda8..811632f7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -31,4 +31,3 @@ Indices and tables * :ref:`genindex` * :ref:`search` - diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..a76a177b --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,14 @@ +[build-system] +requires = ["setuptools>=40.6.0", "wheel"] +build-backend = "setuptools.build_meta" + +[tool.black] +line-length = 119 +target-version = ["py27"] +include = 'djangocms_blog/*py' + +[tool.towncrier] +package = "djangocms_blog" +directory = "changes" +filename = "HISTORY.rst" +title_format = "{version} ({project_date})" diff --git a/requirements-test.txt b/requirements-test.txt index 3b35ab39..15e0649c 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,17 +1,19 @@ -r requirements.txt coverage -coveralls -mock>=1.0.1 -django-nose>=1.2 -flake8 +coveralls>=2.0 +wheel +pep517 +invoke tox>=2.0 wheel pysolr -django-parler>=1.6 aldryn-search django-taggit-helpers django-app-helper>=2.0.0a2 sphinx-autobuild djangocms-video +pytest pytest-django pytest-asyncio +bump2version +https://github.com/hawkowl/towncrier/archive/master.zip diff --git a/setup.cfg b/setup.cfg index 511f713a..aaa90751 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,19 +1,94 @@ -[flake8] -exclude = *.egg-info,.git,.settings,.tox,build,dist,docs,requirements,tmp,*migrations*,*south_migrations*,tests,data -max-line-length = 99 +[bumpversion] +current_version = 1.2.0a1 +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_blog/__init__.py] [metadata] -license-file = LICENSE +name = djangocms-blog +version = attr: djangocms_blog.__version__ +url = https://github.com/nephila/djangocms-blog +project_urls = + Documentation = https://djangocms-blog.readthedocs.io/ +author = Iacopo Spalletti +author_email = i.spalletti@nephila.it +description = The blog application for django CMS +long_description = file: README.rst, HISTORY.rst +long_description_content_type = text/x-rst +license = BSD +license_file = LICENSE +classifiers = + License :: OSI Approved :: BSD License + Development Status :: 5 - Production/Stable + Framework :: Django + Framework :: Django :: 2.2 + Framework :: Django :: 3.0 + Programming Language :: Python + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.5 + Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 -[wheel] -universal = 1 +[options] +include_package_data = True +install_requires = + django-parler>=2.0 + django-cms>=3.7 + django-taggit>=1.0 + django-filer>=1.4 + pytz + django-taggit-templatetags + django-taggit-autosuggest + djangocms-text-ckeditor>=3.9 + easy-thumbnails>=2.4.1 + django-meta>=1.4 + aldryn-apphooks-config>=0.5 + djangocms-apphook-setup + django-sortedm2m +setup_requires = + setuptools +packages = djangocms_blog +python_requires = >=3.5 +test_suite = cms_helper.run +zip_safe = False +keywords = + djangocms-blog + blog + django + wordpress + multilingual + +[options.package_data] +* = *.txt, *.rst +djangocms_blog = *.html *.png *.gif *js *jpg *jpeg *svg *py *mo *po -[isort] -line_length = 99 -skip = migrations, south_migrations, .tox -combine_as_imports = true -default_section = THIRDPARTY -include_trailing_comma = true -known_first_party = djangocms_blog -multi_line_output = 5 -not_skip = __init__.py +[options.extras_require] +search = aldryn-search +taggit-helpers = django-taggit-helpers + +[upload] +repository = https://upload.pypi.org/legacy/ + +[sdist] +formats = zip + +[bdist_wheel] +universal = 1 diff --git a/setup.py b/setup.py index 053878be..b908cbe5 100644 --- a/setup.py +++ b/setup.py @@ -1,65 +1,3 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -from setuptools import setup +import setuptools -import djangocms_blog - -version = djangocms_blog.__version__ - - -readme = open('README.rst').read() -history = open('HISTORY.rst').read().replace('.. :changelog:', '') - - -setup( - name='djangocms-blog', - version=version, - description='A djangoCMS blog application', - long_description=readme + '\n\n' + history, - author='Iacopo Spalletti', - author_email='i.spalletti@nephila.it', - url='https://github.com/nephila/djangocms-blog', - packages=[ - 'djangocms_blog', - ], - include_package_data=True, - install_requires=[ - 'django-parler>=2.0', - 'django-cms>=3.7', - 'django-taggit>=1.0', - 'django-filer>=1.4', - 'pytz', - 'django-taggit-templatetags', - 'django-taggit-autosuggest', - 'djangocms-text-ckeditor>=3.9', - 'easy-thumbnails>=2.4.1,<2.8', - 'django-meta>=1.4', - 'aldryn-apphooks-config>=0.5', - 'djangocms-apphook-setup', - 'django-sortedm2m', - 'lxml', - ], - extras_require={ - 'search': ['aldryn-search'], - 'taggit-helpers': ['django-taggit-helpers'] - }, - license='BSD', - zip_safe=False, - keywords='djangocms-blog, blog, django, wordpress, multilingual', - test_suite='cms_helper.run', - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Framework :: Django', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: BSD License', - 'Natural Language :: English', - 'Framework :: Django', - 'Framework :: Django :: 2.2', - 'Framework :: Django :: 3.0', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - ], -) +setuptools.setup() diff --git a/tasks.py b/tasks.py new file mode 100644 index 00000000..d0645d33 --- /dev/null +++ b/tasks.py @@ -0,0 +1,124 @@ +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 -a --contains HEAD", out_stream=output) + branches = [branch.replace("remotes/origin/", "") for branch in output.getvalue().strip("*").split()] + towncrier_file = None + branch = branches[0] + 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 51d8f8a1..28dd17c3 100644 --- a/tests/base.py +++ b/tests/base.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import json import os from copy import deepcopy @@ -27,130 +26,173 @@ class BaseTest(BaseTestCase): """ Base class with utility function """ + category_1 = None thumb_1 = None thumb_2 = None _pages_data = ( - {'en': {'title': 'page one', 'template': 'blog.html', 'publish': True}, - 'fr': {'title': 'page un', 'publish': True}, - 'it': {'title': 'pagina uno', 'publish': True}}, - {'en': {'title': 'page two', 'template': 'blog.html', 'publish': True, - 'apphook': 'BlogApp', 'apphook_namespace': 'sample_app'}, - 'fr': {'title': 'page deux', 'publish': True}, - 'it': {'title': 'pagina due', 'publish': True}}, - {'en': {'title': 'page three', 'template': 'blog.html', 'publish': True, - 'apphook': 'BlogApp', 'apphook_namespace': 'sample_app2'}, - 'fr': {'title': 'page trois', 'publish': True}, - 'it': {'title': 'pagina tre', 'publish': True}}, + { + "en": {"title": "page one", "template": "blog.html", "publish": True}, + "fr": {"title": "page un", "publish": True}, + "it": {"title": "pagina uno", "publish": True}, + }, + { + "en": { + "title": "page two", + "template": "blog.html", + "publish": True, + "apphook": "BlogApp", + "apphook_namespace": "sample_app", + }, + "fr": {"title": "page deux", "publish": True}, + "it": {"title": "pagina due", "publish": True}, + }, + { + "en": { + "title": "page three", + "template": "blog.html", + "publish": True, + "apphook": "BlogApp", + "apphook_namespace": "sample_app2", + }, + "fr": {"title": "page trois", "publish": True}, + "it": {"title": "pagina tre", "publish": True}, + }, ) _post_data = ( - {'en': {'title': 'First post', 'abstract': '

first line

', - 'description': 'This is the description', 'keywords': 'keyword1, keyword2', - 'text': 'Post text', 'app_config': 'sample_app', 'publish': True}, - 'it': {'title': 'Primo post', 'abstract': '

prima riga

', - 'description': 'Questa è la descrizione', 'keywords': 'keyword1, keyword2', - 'text': 'Testo del post'}, - }, - {'en': {'title': 'Second post', 'abstract': '

second post first line

', - 'description': 'Second post description', 'keywords': 'keyword3, keyword4', - 'text': 'Second post text', 'app_config': 'sample_app', 'publish': False}, - 'it': {'title': 'Secondo post', 'abstract': '

prima riga del secondo post

', - 'description': 'Descrizione del secondo post', 'keywords': 'keyword3, keyword4', - 'text': 'Testo del secondo post', 'app_config': 'sample_app'}, - }, - {'en': {'title': 'Third post', 'abstract': '

third post first line

', - 'description': 'third post description', 'keywords': 'keyword5, keyword6', - 'text': 'Third post text', 'app_config': 'sample_app', 'publish': False}, - 'it': {'title': 'Terzo post', 'abstract': '

prima riga del terzo post

', - 'description': 'Descrizione del terzo post', 'keywords': 'keyword5, keyword6', - 'text': 'Testo del terzo post'}, - }, - {'en': {'title': 'Different appconfig', - 'abstract': '

Different appconfig first line

', - 'description': 'Different appconfig description', 'keywords': 'keyword5, keyword6', - 'text': 'Different appconfig text', 'app_config': 'sample_app2', 'publish': True}, - 'it': {'title': 'Altro appconfig', 'abstract': '

prima riga del Altro appconfig

', - 'description': 'Descrizione Altro appconfig', 'keywords': 'keyword5, keyword6', - 'text': 'Testo del Altro appconfig'}, - }, + { + "en": { + "title": "First post", + "abstract": "

first line

", + "description": "This is the description", + "keywords": "keyword1, keyword2", + "text": "Post text", + "app_config": "sample_app", + "publish": True, + }, + "it": { + "title": "Primo post", + "abstract": "

prima riga

", + "description": "Questa è la descrizione", + "keywords": "keyword1, keyword2", + "text": "Testo del post", + }, + }, + { + "en": { + "title": "Second post", + "abstract": "

second post first line

", + "description": "Second post description", + "keywords": "keyword3, keyword4", + "text": "Second post text", + "app_config": "sample_app", + "publish": False, + }, + "it": { + "title": "Secondo post", + "abstract": "

prima riga del secondo post

", + "description": "Descrizione del secondo post", + "keywords": "keyword3, keyword4", + "text": "Testo del secondo post", + "app_config": "sample_app", + }, + }, + { + "en": { + "title": "Third post", + "abstract": "

third post first line

", + "description": "third post description", + "keywords": "keyword5, keyword6", + "text": "Third post text", + "app_config": "sample_app", + "publish": False, + }, + "it": { + "title": "Terzo post", + "abstract": "

prima riga del terzo post

", + "description": "Descrizione del terzo post", + "keywords": "keyword5, keyword6", + "text": "Testo del terzo post", + }, + }, + { + "en": { + "title": "Different appconfig", + "abstract": "

Different appconfig first line

", + "description": "Different appconfig description", + "keywords": "keyword5, keyword6", + "text": "Different appconfig text", + "app_config": "sample_app2", + "publish": True, + }, + "it": { + "title": "Altro appconfig", + "abstract": "

prima riga del Altro appconfig

", + "description": "Descrizione Altro appconfig", + "keywords": "keyword5, keyword6", + "text": "Testo del Altro appconfig", + }, + }, ) _categories_data = ( - {'en': {'name': 'Very loud', 'app_config': 'sample_app'}, - 'it': {'name': 'Fortissimo'}, - }, - {'en': {'name': 'Very very silent', 'app_config': 'sample_app'}, - 'it': {'name': 'Pianississimo'}, - }, - {'en': {'name': 'Almost', 'app_config': 'sample_app'}, - 'it': {'name': 'Mezzo'}, - }, - {'en': {'name': 'Drums', 'app_config': 'sample_app2'}, - 'it': {'name': 'Tamburi'}, - }, - {'en': {'name': 'Guitars', 'app_config': 'sample_app2'}, - 'it': {'name': 'Chitarre'}, - }, - {'en': {'name': 'Loud', 'parent_id': _get_cat_pk('en', 'Almost'), - 'app_config': 'sample_app'}, - 'it': {'name': 'Forte', 'parent_id': _get_cat_pk('it', 'Mezzo')}, - }, - {'en': {'name': 'Silent', 'parent_id': _get_cat_pk('en', 'Almost'), - 'app_config': 'sample_app'}, - }, + {"en": {"name": "Very loud", "app_config": "sample_app"}, "it": {"name": "Fortissimo"}}, + {"en": {"name": "Very very silent", "app_config": "sample_app"}, "it": {"name": "Pianississimo"}}, + {"en": {"name": "Almost", "app_config": "sample_app"}, "it": {"name": "Mezzo"}}, + {"en": {"name": "Drums", "app_config": "sample_app2"}, "it": {"name": "Tamburi"}}, + {"en": {"name": "Guitars", "app_config": "sample_app2"}, "it": {"name": "Chitarre"}}, + { + "en": {"name": "Loud", "parent_id": _get_cat_pk("en", "Almost"), "app_config": "sample_app"}, + "it": {"name": "Forte", "parent_id": _get_cat_pk("it", "Mezzo")}, + }, + {"en": {"name": "Silent", "parent_id": _get_cat_pk("en", "Almost"), "app_config": "sample_app"}}, ) @classmethod def setUpClass(cls): - super(BaseTest, cls).setUpClass() + super().setUpClass() cls.thumb_1, __ = ThumbnailOption.objects.get_or_create( - name='base', width=100, height=100, crop=True, upscale=False + name="base", width=100, height=100, crop=True, upscale=False ) cls.thumb_2, __ = ThumbnailOption.objects.get_or_create( - name='main', width=200, height=200, crop=False, upscale=False - ) - cls.app_config_1, __ = BlogConfig.objects.get_or_create( - namespace='sample_app' + name="main", width=200, height=200, crop=False, upscale=False ) - cls.app_config_2, __ = BlogConfig.objects.get_or_create( - namespace='sample_app2' - ) - cls.app_config_1.app_title = 'app1' - cls.app_config_1.object_name = 'Blog' + cls.app_config_1, __ = BlogConfig.objects.get_or_create(namespace="sample_app") + cls.app_config_2, __ = BlogConfig.objects.get_or_create(namespace="sample_app2") + cls.app_config_1.app_title = "app1" + cls.app_config_1.object_name = "Blog" cls.app_config_1.app_data.config.paginate_by = 1 cls.app_config_1.app_data.config.send_knock_create = True cls.app_config_1.app_data.config.send_knock_update = True cls.app_config_1.save() - cls.app_config_2.app_title = 'app2' - cls.app_config_2.object_name = 'Article' + cls.app_config_2.app_title = "app2" + cls.app_config_2.object_name = "Article" cls.app_config_2.app_data.config.paginate_by = 2 cls.app_config_2.app_data.config.send_knock_create = True cls.app_config_2.app_data.config.send_knock_update = True cls.app_config_2.save() cls.app_configs = { - 'sample_app': cls.app_config_1, - 'sample_app2': cls.app_config_2, + "sample_app": cls.app_config_1, + "sample_app2": cls.app_config_2, } - cls.category_1 = BlogCategory.objects.create( - name='category 1', app_config=cls.app_config_1 - ) - cls.category_1.set_current_language('it', initialize=True) - cls.category_1.name = 'categoria 1' + cls.category_1 = BlogCategory.objects.create(name="category 1", app_config=cls.app_config_1) + cls.category_1.set_current_language("it", initialize=True) + cls.category_1.name = "categoria 1" cls.category_1.save() - cls.site_2, __ = Site.objects.get_or_create(domain='http://example2.com', name='example 2') - cls.site_3, __ = Site.objects.get_or_create(domain='http://example3.com', name='example 3') + cls.site_2, __ = Site.objects.get_or_create(domain="http://example2.com", name="example 2") + cls.site_3, __ = Site.objects.get_or_create(domain="http://example3.com", name="example 3") cache.clear() @classmethod def tearDownClass(cls): cache.clear() - super(BaseTest, cls).tearDownClass() + super().tearDownClass() def tearDown(self): cache.clear() - super(BaseTest, self).tearDown() + super().tearDown() def get_nodes(self, menu_pool, request): try: @@ -159,14 +201,14 @@ def get_nodes(self, menu_pool, request): nodes = menu_pool.get_nodes(request) return nodes - def _get_category(self, data, category=None, lang='en'): + def _get_category(self, data, category=None, lang="en"): data = deepcopy(data) for k, v in data.items(): - if hasattr(v, '__call__'): + if hasattr(v, "__call__"): data[k] = v() if not category: with smart_override(lang): - data['app_config'] = self.app_configs[data['app_config']] + data["app_config"] = self.app_configs[data["app_config"]] category = BlogCategory.objects.create(**data) else: category.set_current_language(lang, initialize=True) @@ -175,24 +217,24 @@ def _get_category(self, data, category=None, lang='en'): category.save() return category - def _get_post(self, data, post=None, lang='en', sites=None): + def _get_post(self, data, post=None, lang="en", sites=None): if not post: post_data = { - 'author': self.user, - 'title': data['title'], - 'abstract': data['abstract'], - 'meta_description': data['description'], - 'meta_keywords': data['keywords'], - 'app_config': self.app_configs[data['app_config']] + "author": self.user, + "title": data["title"], + "abstract": data["abstract"], + "meta_description": data["description"], + "meta_keywords": data["keywords"], + "app_config": self.app_configs[data["app_config"]], } post = Post.objects.create(**post_data) else: post.create_translation( lang, - title=data['title'], - abstract=data['abstract'], - meta_description=data['description'], - meta_keywords=data['keywords'] + title=data["title"], + abstract=data["abstract"], + meta_description=data["description"], + meta_keywords=data["keywords"], ) post.categories.add(self.category_1) if sites: @@ -206,9 +248,9 @@ def get_posts(self, sites=None): if Post.objects.all().exists(): return list(Post.objects.all()) for post in self._post_data: - post1 = self._get_post(post['en'], sites=sites) - post1 = self._get_post(post['it'], post=post1, lang='it') - post1.publish = post['en']['publish'] + post1 = self._get_post(post["en"], sites=sites) + post1 = self._get_post(post["it"], post=post1, lang="it") + post1.publish = post["en"]["publish"] post1.main_image = self.create_filer_image_object() post1.save() posts.append(post1) @@ -230,7 +272,7 @@ def _reload_menus(self): menu_pool.discover_menus() # All cms menu modifiers should be removed from menu_pool.modifiers # so that they do not interfere with our menu nodes - menu_pool.modifiers = [m for m in menu_pool.modifiers if m.__module__.startswith('djangocms_blog')] + menu_pool.modifiers = [m for m in menu_pool.modifiers if m.__module__.startswith("djangocms_blog")] self._reset_menus() def read_json(self, path, raw=False): @@ -245,7 +287,7 @@ def read_json(self, path, raw=False): :type: (dict|str) """ full_path = os.path.join(os.path.dirname(__file__), path) - with open(full_path, 'r') as src: + with open(full_path) as src: if raw: return src.read() else: diff --git a/tests/media_app/__init__.py b/tests/media_app/__init__.py index 40a96afc..e69de29b 100644 --- a/tests/media_app/__init__.py +++ b/tests/media_app/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/tests/media_app/cms_plugins.py b/tests/media_app/cms_plugins.py index 634400b7..e9d0df40 100644 --- a/tests/media_app/cms_plugins.py +++ b/tests/media_app/cms_plugins.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from cms.plugin_base import CMSPluginBase from cms.plugin_pool import plugin_pool @@ -8,14 +7,14 @@ @plugin_pool.register_plugin class YouTubePlugin(CMSPluginBase): model = YoutTubeVideo - module = 'Media' - name = 'You Tube' - render_template = 'media_app/youtube.html' + module = "Media" + name = "You Tube" + render_template = "media_app/youtube.html" @plugin_pool.register_plugin class VimeoPlugin(CMSPluginBase): model = Vimeo - module = 'Media' - name = 'Vimeo' - render_template = 'media_app/vimeo.html' + module = "Media" + name = "Vimeo" + render_template = "media_app/vimeo.html" diff --git a/tests/media_app/migrations/0001_initial.py b/tests/media_app/migrations/0001_initial.py index 4f6d8f2a..571eb476 100644 --- a/tests/media_app/migrations/0001_initial.py +++ b/tests/media_app/migrations/0001_initial.py @@ -1,9 +1,8 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.11.24 on 2019-09-14 10:45 -from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models + import djangocms_blog.media.base @@ -12,30 +11,48 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('cms', '0020_old_tree_cleanup'), + ("cms", "0020_old_tree_cleanup"), ] operations = [ migrations.CreateModel( - name='Vimeo', + name="Vimeo", fields=[ - ('cmsplugin_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='media_app_vimeo', serialize=False, to='cms.CMSPlugin')), - ('url', models.URLField(verbose_name='Video URL')), + ( + "cmsplugin_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + related_name="media_app_vimeo", + serialize=False, + to="cms.CMSPlugin", + ), + ), + ("url", models.URLField(verbose_name="Video URL")), ], - options={ - 'abstract': False, - }, - bases=(djangocms_blog.media.base.MediaAttachmentPluginMixin, 'cms.cmsplugin'), + options={"abstract": False,}, + bases=(djangocms_blog.media.base.MediaAttachmentPluginMixin, "cms.cmsplugin"), ), migrations.CreateModel( - name='YoutTubeVideo', + name="YoutTubeVideo", fields=[ - ('cmsplugin_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='media_app_youttubevideo', serialize=False, to='cms.CMSPlugin')), - ('url', models.URLField(verbose_name='video URL')), + ( + "cmsplugin_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + related_name="media_app_youttubevideo", + serialize=False, + to="cms.CMSPlugin", + ), + ), + ("url", models.URLField(verbose_name="video URL")), ], - options={ - 'abstract': False, - }, - bases=(djangocms_blog.media.base.MediaAttachmentPluginMixin, 'cms.cmsplugin'), + options={"abstract": False,}, + bases=(djangocms_blog.media.base.MediaAttachmentPluginMixin, "cms.cmsplugin"), ), ] diff --git a/tests/media_app/models.py b/tests/media_app/models.py index f0f6cc0c..865a8056 100644 --- a/tests/media_app/models.py +++ b/tests/media_app/models.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import re import requests @@ -9,16 +8,16 @@ class YoutTubeVideo(MediaAttachmentPluginMixin, CMSPlugin): - url = models.URLField('video URL') + url = models.URLField("video URL") _media_autoconfiguration = { - 'params': [ - re.compile('^https://youtu.be/(?P[-\\w]+)$'), - re.compile('^https://www.youtube.com/watch\\?v=(?P[-\\w]+)$') + "params": [ + re.compile("^https://youtu.be/(?P[-\\w]+)$"), + re.compile("^https://www.youtube.com/watch\\?v=(?P[-\\w]+)$"), ], - 'thumb_url': 'https://img.youtube.com/vi/%(media_id)s/hqdefault.jpg', - 'main_url': 'https://img.youtube.com/vi/%(media_id)s/maxresdefault.jpg', - 'callable': None, + "thumb_url": "https://img.youtube.com/vi/%(media_id)s/hqdefault.jpg", + "main_url": "https://img.youtube.com/vi/%(media_id)s/maxresdefault.jpg", + "callable": None, } def __str__(self): @@ -30,15 +29,13 @@ def media_url(self): class Vimeo(MediaAttachmentPluginMixin, CMSPlugin): - url = models.URLField('Video URL') + url = models.URLField("Video URL") _media_autoconfiguration = { - 'params': [ - re.compile('^https://vimeo.com/(?P[-0-9]+)$'), - ], - 'thumb_url': '%(thumb_url)s', - 'main_url': '%(main_url)s', - 'callable': 'vimeo_data', + "params": [re.compile("^https://vimeo.com/(?P[-0-9]+)$")], + "thumb_url": "%(thumb_url)s", + "main_url": "%(main_url)s", + "callable": "vimeo_data", } def __str__(self): @@ -51,23 +48,17 @@ def media_url(self): @property def media_title(self): try: - return self.media_params['title'] + return self.media_params["title"] except KeyError: return None def vimeo_data(self, media_id): - response = requests.get( - 'https://vimeo.com/api/v2/video/%(media_id)s.json' % {'media_id': media_id, } - ) + response = requests.get("https://vimeo.com/api/v2/video/{media_id}.json".format(media_id=media_id,)) json = response.json() data = {} if json: data = json[0] data.update( - { - 'media_id': media_id, - 'main_url': data['thumbnail_large'], - 'thumb_url': data['thumbnail_medium'], - } + {"media_id": media_id, "main_url": data["thumbnail_large"], "thumb_url": data["thumbnail_medium"]} ) return data diff --git a/tests/test_indexing.py b/tests/test_indexing.py index 85160380..5394aace 100644 --- a/tests/test_indexing.py +++ b/tests/test_indexing.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from cms.api import add_plugin from haystack.constants import DEFAULT_ALIAS from haystack.query import SearchQuerySet @@ -9,29 +8,28 @@ class BlogIndexingTests(BaseTest): - sample_text = ('First post first line This is the description keyword1 ' - 'keyword2 category 1 a tag test body') + sample_text = "First post first line This is the description keyword1 " "keyword2 category 1 a tag test body" def setUp(self): self.get_pages() def test_blog_post_is_indexed_using_prepare(self): """This tests the indexing path way used by update_index mgmt command""" - post = self._get_post(self._post_data[0]['en']) - post = self._get_post(self._post_data[0]['it'], post, 'it') - post.tags.add('a tag') - add_plugin(post.content, 'TextPlugin', language='en', body='test body') + post = self._get_post(self._post_data[0]["en"]) + post = self._get_post(self._post_data[0]["it"], post, "it") + post.tags.add("a tag") + add_plugin(post.content, "TextPlugin", language="en", body="test body") index = self.get_post_index() index.index_queryset(DEFAULT_ALIAS) # initialises index._backend_alias indexed = index.prepare(post) - self.assertEqual(post.get_title(), indexed['title']) - self.assertEqual(post.get_description(), indexed['description']) - self.assertEqual(post.get_tags(), indexed['tags']) - self.assertEqual(self.sample_text, indexed['text']) - self.assertEqual(post.get_absolute_url(), indexed['url']) - self.assertEqual(post.date_published, indexed['pub_date']) + self.assertEqual(post.get_title(), indexed["title"]) + self.assertEqual(post.get_description(), indexed["description"]) + self.assertEqual(post.get_tags(), indexed["tags"]) + self.assertEqual(self.sample_text, indexed["text"]) + self.assertEqual(post.get_absolute_url(), indexed["url"]) + self.assertEqual(post.date_published, indexed["pub_date"]) def test_searchqueryset(self): posts = self.get_posts() diff --git a/tests/test_liveblog.py b/tests/test_liveblog.py index 8def5fd6..6b64b25a 100644 --- a/tests/test_liveblog.py +++ b/tests/test_liveblog.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - from datetime import timedelta import pytest @@ -20,10 +18,9 @@ async def _connect(post): - path = "liveblog/%(namespace)s/%(lang)s/%(slug)s/" % { - 'namespace': post.app_config.namespace, 'lang': post.get_current_language(), - 'slug': post.slug - } + path = "liveblog/{namespace}/{lang}/{slug}/".format( + namespace=post.app_config.namespace, lang=post.get_current_language(), slug=post.slug, + ) communicator = WebsocketCommunicator(application, path) connected, __ = await communicator.connect() assert connected @@ -39,12 +36,9 @@ def get_request(path): @database_sync_to_async def get_post(): - config, __ = BlogConfig.objects.get_or_create(namespace='bla_bla_bla') + config, __ = BlogConfig.objects.get_or_create(namespace="bla_bla_bla") - post_data = { - 'title': words(count=3, common=False), - 'app_config': config - } + post_data = {"title": words(count=3, common=False), "app_config": config} post = Post.objects.create(**post_data) post.enable_liveblog = True post.save() @@ -60,10 +54,7 @@ def delete_post(post): @database_sync_to_async def add_livelobg_plugin(placeholder, publish=True): plugin_text = words(count=3, common=False) - plugin = add_plugin( - placeholder, 'LiveblogPlugin', language='en', body=plugin_text, - publish=publish - ) + plugin = add_plugin(placeholder, "LiveblogPlugin", language="en", body=plugin_text, publish=publish) __, admin = plugin.get_plugin_instance() admin.save_model(get_request("/"), plugin, None, None) return plugin, admin, plugin_text @@ -88,21 +79,21 @@ async def test_add_plugin(): plugin, admin, plugin_text = await add_livelobg_plugin(post.liveblog) rendered = await communicator.receive_json_from() - assert plugin.pk == rendered['id'] - assert plugin.creation_date.strftime(DATE_FORMAT) == rendered['creation_date'] - assert plugin.changed_date.strftime(DATE_FORMAT) == rendered['changed_date'] - assert rendered['content'].find('data-post-id="{}"'.format(plugin.pk)) > -1 - assert rendered['content'].find(plugin_text) > -1 + assert plugin.pk == rendered["id"] + assert plugin.creation_date.strftime(DATE_FORMAT) == rendered["creation_date"] + assert plugin.changed_date.strftime(DATE_FORMAT) == rendered["changed_date"] + assert rendered["content"].find('data-post-id="{}"'.format(plugin.pk)) > -1 + assert rendered["content"].find(plugin_text) > -1 plugin, admin, new_plugin_text = await update_livelobg_plugin_content(plugin) rendered = await communicator.receive_json_from() - assert plugin.pk == rendered['id'] - assert plugin.creation_date.strftime(DATE_FORMAT) == rendered['creation_date'] - assert plugin.changed_date.strftime(DATE_FORMAT) == rendered['changed_date'] - assert rendered['content'].find('data-post-id="{}"'.format(plugin.pk)) > -1 - assert rendered['content'].find(new_plugin_text) > -1 - assert rendered['content'].find(plugin_text) == -1 + assert plugin.pk == rendered["id"] + assert plugin.creation_date.strftime(DATE_FORMAT) == rendered["creation_date"] + assert plugin.changed_date.strftime(DATE_FORMAT) == rendered["changed_date"] + assert rendered["content"].find('data-post-id="{}"'.format(plugin.pk)) > -1 + assert rendered["content"].find(new_plugin_text) > -1 + assert rendered["content"].find(plugin_text) == -1 await communicator.disconnect() await delete_post(post) @@ -119,12 +110,12 @@ async def test_add_plugin_no_publish(): plugin, admin, new_plugin_text = await update_livelobg_plugin_content(plugin, publish=True) rendered = await communicator.receive_json_from() - assert plugin.pk == rendered['id'] - assert plugin.creation_date.strftime(DATE_FORMAT) == rendered['creation_date'] - assert plugin.changed_date.strftime(DATE_FORMAT) == rendered['changed_date'] - assert rendered['content'].find('data-post-id="{}"'.format(plugin.pk)) > -1 - assert rendered['content'].find(new_plugin_text) > -1 - assert rendered['content'].find(plugin_text) == -1 + assert plugin.pk == rendered["id"] + assert plugin.creation_date.strftime(DATE_FORMAT) == rendered["creation_date"] + assert plugin.changed_date.strftime(DATE_FORMAT) == rendered["changed_date"] + assert rendered["content"].find('data-post-id="{}"'.format(plugin.pk)) > -1 + assert rendered["content"].find(new_plugin_text) > -1 + assert rendered["content"].find(plugin_text) == -1 await communicator.disconnect() await delete_post(post) @@ -138,7 +129,7 @@ async def test_disconnect(): plugin, admin, plugin_text = await add_livelobg_plugin(post.liveblog) rendered = await communicator.receive_json_from() - assert rendered['content'] + assert rendered["content"] await communicator.disconnect() @@ -152,7 +143,7 @@ async def test_disconnect(): @pytest.mark.asyncio async def test_nopost(): post = await get_post() - post.slug = 'something' + post.slug = "something" communicator = await _connect(post) assert await communicator.receive_nothing() is True @@ -189,17 +180,15 @@ def test_plugin_render(self): post = posts[0] post.enable_liveblog = True post.save() - plugin = add_plugin( - post.liveblog, 'LiveblogPlugin', language='en', body='live text', publish=False - ) - rendered = self.render_plugin(pages[0], 'en', plugin, edit=True) + plugin = add_plugin(post.liveblog, "LiveblogPlugin", language="en", body="live text", publish=False) + rendered = self.render_plugin(pages[0], "en", plugin, edit=True) self.assertFalse(rendered.strip()) plugin.publish = True plugin.save() - rendered = self.render_plugin(pages[0], 'en', plugin, edit=True) + rendered = self.render_plugin(pages[0], "en", plugin, edit=True) self.assertTrue(rendered.find('data-post-id="{}"'.format(plugin.pk)) > -1) - self.assertTrue(rendered.find('live text') > -1) + self.assertTrue(rendered.find("live text") > -1) def test_plugins_order(self): posts = self.get_posts() @@ -211,25 +200,37 @@ def test_plugins_order(self): current_date = now() plugin_1 = add_plugin( - post.liveblog, 'LiveblogPlugin', language='en', body='plugin 1', publish=True, - post_date=current_date - timedelta(seconds=1) + post.liveblog, + "LiveblogPlugin", + language="en", + body="plugin 1", + publish=True, + post_date=current_date - timedelta(seconds=1), ) plugin_2 = add_plugin( - post.liveblog, 'LiveblogPlugin', language='en', body='plugin 2', publish=True, - post_date=current_date - timedelta(seconds=5) + post.liveblog, + "LiveblogPlugin", + language="en", + body="plugin 2", + publish=True, + post_date=current_date - timedelta(seconds=5), ) plugin_3 = add_plugin( - post.liveblog, 'LiveblogPlugin', language='en', body='plugin 3', publish=True, - post_date=current_date - timedelta(seconds=10) + post.liveblog, + "LiveblogPlugin", + language="en", + body="plugin 3", + publish=True, + post_date=current_date - timedelta(seconds=10), ) self.assertEqual( - list(Liveblog.objects.all().order_by('position').values_list('pk', flat=True)), - [plugin_1.pk, plugin_2.pk, plugin_3.pk] + list(Liveblog.objects.all().order_by("position").values_list("pk", flat=True)), + [plugin_1.pk, plugin_2.pk, plugin_3.pk], ) plugin_1.post_date = current_date - timedelta(seconds=20) plugin_1.save() self.assertEqual( - list(Liveblog.objects.all().order_by('position').values_list('pk', flat=True)), - [plugin_2.pk, plugin_3.pk, plugin_1.pk] + list(Liveblog.objects.all().order_by("position").values_list("pk", flat=True)), + [plugin_2.pk, plugin_3.pk, plugin_1.pk], ) diff --git a/tests/test_media.py b/tests/test_media.py index 2bf45228..86cf49c3 100644 --- a/tests/test_media.py +++ b/tests/test_media.py @@ -1,8 +1,7 @@ -# -*- coding: utf-8 -*- import os +from unittest.mock import MagicMock, patch from cms.api import add_plugin -from mock import MagicMock, patch from djangocms_blog.templatetags.djangocms_blog import media_images, media_plugins @@ -10,26 +9,17 @@ class MediaTest(BaseTest): - def setUp(self): - super(MediaTest, self).setUp() + super().setUp() self.get_pages() posts = self.get_posts() self.post = posts[0] self.youtube = add_plugin( - self.post.media, 'YouTubePlugin', language='en', - url='https://www.youtube.com/watch?v=szbGc7ymFhQ' - ) - self.vimeo = add_plugin( - self.post.media, 'VimeoPlugin', language='en', - url='https://vimeo.com/12915013' - ) - self.media_text = add_plugin( - self.post.media, 'TextPlugin', language='en', body='random text' - ) - self.general_text = add_plugin( - self.post.content, 'TextPlugin', language='en', body='body text' + self.post.media, "YouTubePlugin", language="en", url="https://www.youtube.com/watch?v=szbGc7ymFhQ" ) + self.vimeo = add_plugin(self.post.media, "VimeoPlugin", language="en", url="https://vimeo.com/12915013") + self.media_text = add_plugin(self.post.media, "TextPlugin", language="en", body="random text") + self.general_text = add_plugin(self.post.content, "TextPlugin", language="en", body="body text") def _get_request_mock(self, json_path): response = self.read_json(json_path) @@ -39,12 +29,12 @@ def _get_request_mock(self, json_path): def test_no_media_plugins(self): self.post.media.get_plugins().delete() - context = {'request': self.request('/')} + context = {"request": self.request("/")} plugins = media_plugins(context, self.post) self.assertEqual(0, len(plugins)) def test_media_plugins(self): - context = {'request': self.request('/')} + context = {"request": self.request("/")} plugins = media_plugins(context, self.post) self.assertEqual(3, len(plugins)) self.assertIn(self.youtube, plugins) @@ -55,31 +45,28 @@ def test_media_plugins(self): def test_djangocms_video_plugins(self): filer_image = self.create_filer_image_object() src_thumbs = [ - 'https://img.youtube.com/vi/szbGc7ymFhQ/hqdefault.jpg', - 'https://i.vimeocdn.com/video/73266401_200x150.jpg', - filer_image.url + "https://img.youtube.com/vi/szbGc7ymFhQ/hqdefault.jpg", + "https://i.vimeocdn.com/video/73266401_200x150.jpg", + filer_image.url, ] - add_plugin( - self.post.media, 'VideoPlayerPlugin', language='en', - poster=filer_image - ) - context = {'request': self.request('/')} + add_plugin(self.post.media, "VideoPlayerPlugin", language="en", poster=filer_image) + context = {"request": self.request("/")} images = media_images(context, self.post, main=False) self.assertEqual(3, len(images)) self.assertEqual(images, src_thumbs) - @patch('tests.media_app.models.requests.get') + @patch("tests.media_app.models.requests.get") def test_media_images(self, get_request): src_images = [ - 'https://img.youtube.com/vi/szbGc7ymFhQ/maxresdefault.jpg', - 'https://i.vimeocdn.com/video/73266401_640.jpg' + "https://img.youtube.com/vi/szbGc7ymFhQ/maxresdefault.jpg", + "https://i.vimeocdn.com/video/73266401_640.jpg", ] src_thumbs = [ - 'https://img.youtube.com/vi/szbGc7ymFhQ/hqdefault.jpg', - 'https://i.vimeocdn.com/video/73266401_200x150.jpg' + "https://img.youtube.com/vi/szbGc7ymFhQ/hqdefault.jpg", + "https://i.vimeocdn.com/video/73266401_200x150.jpg", ] - get_request.return_value = self._get_request_mock(os.path.join('fixtures', 'vimeo.json')) - context = {'request': self.request('/')} + get_request.return_value = self._get_request_mock(os.path.join("fixtures", "vimeo.json")) + context = {"request": self.request("/")} images = media_images(context, self.post) self.assertEqual(2, len(images)) self.assertEqual(images, src_images) @@ -88,11 +75,11 @@ def test_media_images(self, get_request): self.assertEqual(2, len(images)) self.assertEqual(images, src_thumbs) - @patch('tests.media_app.models.requests.get') + @patch("tests.media_app.models.requests.get") def test_media_attributes(self, get_request): - src_ids = ['szbGc7ymFhQ', '12915013'] - get_request.return_value = self._get_request_mock(os.path.join('fixtures', 'vimeo.json')) - context = {'request': self.request('/')} + src_ids = ["szbGc7ymFhQ", "12915013"] + get_request.return_value = self._get_request_mock(os.path.join("fixtures", "vimeo.json")) + context = {"request": self.request("/")} plugins = media_plugins(context, self.post) - dst_ids = [media.media_id for media in plugins if hasattr(media, 'media_id')] + dst_ids = [media.media_id for media in plugins if hasattr(media, "media_id")] self.assertEqual(dst_ids, src_ids) diff --git a/tests/test_menu.py b/tests/test_menu.py index fea38db0..6e36670f 100644 --- a/tests/test_menu.py +++ b/tests/test_menu.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from aldryn_apphooks_config.utils import get_app_instance from django.utils.translation import activate from menus.menu_pool import menu_pool @@ -6,9 +5,7 @@ from djangocms_blog.cms_appconfig import BlogConfig from djangocms_blog.models import BlogCategory -from djangocms_blog.settings import ( - MENU_TYPE_CATEGORIES, MENU_TYPE_COMPLETE, MENU_TYPE_NONE, MENU_TYPE_POSTS, -) +from djangocms_blog.settings import MENU_TYPE_CATEGORIES, MENU_TYPE_COMPLETE, MENU_TYPE_NONE, MENU_TYPE_POSTS from djangocms_blog.views import CategoryEntriesView, PostDetailView from .base import BaseTest @@ -18,15 +15,15 @@ class MenuTest(BaseTest): cats = [] def setUp(self): - super(MenuTest, self).setUp() + super().setUp() self.cats = [self.category_1] for i, lang_data in enumerate(self._categories_data): - cat = self._get_category(lang_data['en']) - if 'it' in lang_data: - cat = self._get_category(lang_data['it'], cat, 'it') + cat = self._get_category(lang_data["en"]) + if "it" in lang_data: + cat = self._get_category(lang_data["it"], cat, "it") self.cats.append(cat) - activate('en') + activate("en") self._reload_menus() def test_menu_cache_clear_blogconfig(self): @@ -36,20 +33,21 @@ def test_menu_cache_clear_blogconfig(self): from menus.models import CacheKey from django.core.cache import cache + pages = self.get_pages() self.get_posts() self.reload_urlconf() - app_config_test = BlogConfig.objects.create(namespace='test_config') - app_config_test.app_title = 'appx' - app_config_test.object_name = 'Blogx' + app_config_test = BlogConfig.objects.create(namespace="test_config") + app_config_test.app_title = "appx" + app_config_test.object_name = "Blogx" app_config_test.save() - lang = 'en' + lang = "en" with smart_override(lang): self._reset_menus() request = self.get_page_request(pages[1], self.user, pages[1].get_absolute_url(lang), edit=True) self.get_nodes(menu_pool, request) - keys = CacheKey.objects.get_keys().distinct().values_list('key', flat=True) + keys = CacheKey.objects.get_keys().distinct().values_list("key", flat=True) self.assertTrue(cache.get_many(keys)) app_config_test.delete() self.assertFalse(cache.get_many(keys)) @@ -61,30 +59,29 @@ def test_menu_cache_clear_category(self): from menus.models import CacheKey from django.core.cache import cache + pages = self.get_pages() self.get_posts() self.reload_urlconf() - lang = 'en' + lang = "en" with smart_override(lang): self._reset_menus() request = self.get_page_request(pages[1], self.user, pages[1].get_absolute_url(lang), edit=True) self.get_nodes(menu_pool, request) - keys = CacheKey.objects.get_keys().distinct().values_list('key', flat=True) + keys = CacheKey.objects.get_keys().distinct().values_list("key", flat=True) self.assertTrue(cache.get_many(keys)) - category_test = BlogCategory.objects.create( - name='category test', app_config=self.app_config_1 - ) - category_test.set_current_language('it', initialize=True) - category_test.name = 'categoria test' + category_test = BlogCategory.objects.create(name="category test", app_config=self.app_config_1) + category_test.set_current_language("it", initialize=True) + category_test.name = "categoria test" category_test.save() self.assertFalse(cache.get_many(keys)) self.get_nodes(menu_pool, request) - keys = CacheKey.objects.get_keys().distinct().values_list('key', flat=True) + keys = CacheKey.objects.get_keys().distinct().values_list("key", flat=True) self.assertTrue(cache.get_many(keys)) category_test.delete() self.assertFalse(cache.get_many(keys)) - keys = CacheKey.objects.get_keys().distinct().values_list('key', flat=True) + keys = CacheKey.objects.get_keys().distinct().values_list("key", flat=True) self.assertFalse(keys) def test_menu_nodes(self): @@ -95,24 +92,25 @@ def test_menu_nodes(self): posts = self.get_posts() self.reload_urlconf() - for lang in ('en', 'it'): + for lang in ("en", "it"): with smart_override(lang): self._reset_menus() request = self.get_page_request(pages[1], self.user, pages[1].get_absolute_url(lang), edit=True) nodes = self.get_nodes(menu_pool, request) self.assertTrue(len(nodes), BlogCategory.objects.all().count() + len(pages)) - nodes_url = set([node.get_absolute_url() for node in nodes]) - cats_url = set([cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang)]) + nodes_url = {node.get_absolute_url() for node in nodes} + cats_url = {cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang)} self.assertTrue(cats_url.issubset(nodes_url)) self._reset_menus() posts[0].categories.clear() - for lang in ('en', 'it'): + for lang in ("en", "it"): with smart_override(lang): self._reset_menus() - request = self.get_page_request(pages[1].get_draft_object(), self.user, pages[1].get_draft_object().get_absolute_url(lang)) + request = self.get_page_request( + pages[1].get_draft_object(), self.user, pages[1].get_draft_object().get_absolute_url(lang) + ) nodes = self.get_nodes(menu_pool, request) - urls = [node.get_absolute_url() for node in nodes] nodes_url = [node.get_absolute_url() for node in nodes] self.assertTrue(len(nodes_url), BlogCategory.objects.all().count() + len(pages)) self.assertFalse(posts[0].get_absolute_url(lang) in nodes_url) @@ -130,26 +128,34 @@ def test_menu_options(self): cats_without_post_url = {} posts_url = {} - languages = ('en', 'it') + languages = ("en", "it") for lang in languages: with smart_override(lang): self._reset_menus() - cats_url[lang] = set([cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang)]) - cats_with_post_url[lang] = set([cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang) and cat.blog_posts.published().exists()]) + cats_url[lang] = {cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang)} + cats_with_post_url[lang] = { + cat.get_absolute_url() + for cat in self.cats + if cat.has_translation(lang) and cat.blog_posts.published().exists() + } cats_without_post_url[lang] = cats_url[lang].difference(cats_with_post_url[lang]) - posts_url[lang] = set([post.get_absolute_url(lang) for post in posts if post.has_translation(lang) and post.app_config == self.app_config_1]) + posts_url[lang] = { + post.get_absolute_url(lang) + for post in posts + if post.has_translation(lang) and post.app_config == self.app_config_1 + } # No item in the menu self.app_config_1.app_data.config.menu_structure = MENU_TYPE_NONE self.app_config_1.save() self._reset_menus() for lang in languages: - request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang) + request = self.get_page_request(None, self.user, r"/%s/page-two/" % lang) with smart_override(lang): self._reset_menus() nodes = self.get_nodes(menu_pool, request) - nodes_url = set([node.get_absolute_url() for node in nodes]) + nodes_url = {node.get_absolute_url() for node in nodes} self.assertFalse(cats_url[lang].issubset(nodes_url)) self.assertFalse(posts_url[lang].issubset(nodes_url)) @@ -158,11 +164,11 @@ def test_menu_options(self): self.app_config_1.save() self._reset_menus() for lang in languages: - request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang) + request = self.get_page_request(None, self.user, r"/%s/page-two/" % lang) with smart_override(lang): self._reset_menus() nodes = self.get_nodes(menu_pool, request) - nodes_url = set([node.get_absolute_url() for node in nodes]) + nodes_url = {node.get_absolute_url() for node in nodes} self.assertFalse(cats_url[lang].issubset(nodes_url)) self.assertTrue(posts_url[lang].issubset(nodes_url)) @@ -171,11 +177,11 @@ def test_menu_options(self): self.app_config_1.save() self._reset_menus() for lang in languages: - request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang) + request = self.get_page_request(None, self.user, r"/%s/page-two/" % lang) with smart_override(lang): self._reset_menus() nodes = self.get_nodes(menu_pool, request) - nodes_url = set([node.get_absolute_url() for node in nodes]) + nodes_url = {node.get_absolute_url() for node in nodes} self.assertTrue(cats_url[lang].issubset(nodes_url)) self.assertFalse(posts_url[lang].issubset(nodes_url)) @@ -184,11 +190,11 @@ def test_menu_options(self): self.app_config_1.save() self._reset_menus() for lang in languages: - request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang) + request = self.get_page_request(None, self.user, r"/%s/page-two/" % lang) with smart_override(lang): self._reset_menus() nodes = self.get_nodes(menu_pool, request) - nodes_url = set([node.get_absolute_url() for node in nodes]) + nodes_url = {node.get_absolute_url() for node in nodes} self.assertTrue(cats_url[lang].issubset(nodes_url)) self.assertTrue(posts_url[lang].issubset(nodes_url)) @@ -199,11 +205,11 @@ def test_menu_options(self): self.app_config_2.save() self._reset_menus() for lang in languages: - request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang) + request = self.get_page_request(None, self.user, r"/%s/page-two/" % lang) with smart_override(lang): self._reset_menus() nodes = self.get_nodes(menu_pool, request) - nodes_url = set([node.url for node in nodes]) + nodes_url = {node.url for node in nodes} self.assertTrue(cats_with_post_url[lang].issubset(nodes_url)) self.assertFalse(cats_without_post_url[lang].intersection(nodes_url)) self.assertTrue(posts_url[lang].issubset(nodes_url)) @@ -224,17 +230,15 @@ def test_modifier(self): tests = ( # view class, view kwarg, view object, category - (PostDetailView, 'slug', posts[0], posts[0].categories.first()), - (CategoryEntriesView, 'category', self.cats[2], self.cats[2]) + (PostDetailView, "slug", posts[0], posts[0].categories.first()), + (CategoryEntriesView, "category", self.cats[2], self.cats[2]), ) self.app_config_1.app_data.config.menu_structure = MENU_TYPE_COMPLETE self.app_config_1.save() for view_cls, kwarg, obj, cat in tests: - with smart_override('en'): - with switch_language(obj, 'en'): - request = self.get_page_request( - pages[1], self.user, path=obj.get_absolute_url() - ) + with smart_override("en"): + with switch_language(obj, "en"): + request = self.get_page_request(pages[1], self.user, path=obj.get_absolute_url()) self._reset_menus() menu_pool.clear(all=True) view_obj = view_cls() @@ -255,11 +259,9 @@ def test_modifier(self): self.app_config_1.app_data.config.menu_structure = MENU_TYPE_CATEGORIES self.app_config_1.save() for view_cls, kwarg, obj, cat in tests: - with smart_override('en'): - with switch_language(obj, 'en'): - request = self.get_page_request( - pages[1], self.user, path=obj.get_absolute_url() - ) + with smart_override("en"): + with switch_language(obj, "en"): + request = self.get_page_request(pages[1], self.user, path=obj.get_absolute_url()) self._reset_menus() menu_pool.clear(all=True) view_obj = view_cls() diff --git a/tests/test_models.py b/tests/test_models.py index daf1d530..bd12afea 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,8 +1,8 @@ -# -*- coding: utf-8 -*- import re from contextlib import contextmanager from copy import deepcopy from datetime import timedelta +from unittest import SkipTest import parler from cms.api import add_plugin @@ -19,6 +19,7 @@ from django.utils.html import strip_tags from django.utils.timezone import now from django.utils.translation import get_language, override +from filer.models import ThumbnailOption from menus.menu_pool import menu_pool from parler.tests.utils import override_parler_settings from parler.utils.conf import add_default_language_settings @@ -28,82 +29,60 @@ from djangocms_blog.cms_appconfig import BlogConfig, BlogConfigForm from djangocms_blog.forms import CategoryAdminForm, PostAdminForm from djangocms_blog.models import BlogCategory, Post -from djangocms_blog.settings import ( - MENU_TYPE_NONE, PERMALINK_TYPE_CATEGORY, PERMALINK_TYPE_FULL_DATE, get_setting, -) +from djangocms_blog.settings import MENU_TYPE_NONE, PERMALINK_TYPE_CATEGORY, PERMALINK_TYPE_FULL_DATE, get_setting from .base import BaseTest -try: # pragma: no cover - from cmsplugin_filer_image.models import ThumbnailOption # NOQA -except ImportError: # pragma: no cover - from filer.models import ThumbnailOption # NOQA - - - -try: - from unittest import SkipTest -except ImportError: - from django.utils.unittest import SkipTest - try: from knocker.signals import pause_knocks except ImportError: + @contextmanager def pause_knocks(obj): yield class AdminTest(BaseTest): - def setUp(self): - super(AdminTest, self).setUp() + super().setUp() admin.autodiscover() self.default_thumbnail = ThumbnailOption.objects.create( - name='Blog thumbnail', - width=120, - height=120, - crop=True, - upscale=True, + name="Blog thumbnail", width=120, height=120, crop=True, upscale=True, ) self.default_full = ThumbnailOption.objects.create( - name='Blog image', - width=800, - height=200, - crop=True, - upscale=True, + name="Blog image", width=800, height=200, crop=True, upscale=True, ) def test_admin_thumbnails(self): self.get_pages() custom_thumbnail = ThumbnailOption.objects.create( - name='Custom thumbnail', width=120, height=120, crop=True, upscale=True, + name="Custom thumbnail", width=120, height=120, crop=True, upscale=True, ) custom_full = ThumbnailOption.objects.create( - name='Custom image', width=800, height=200, crop=True, upscale=True, + name="Custom image", width=800, height=200, crop=True, upscale=True, ) post_admin = admin.site._registry[Post] - request = self.get_page_request('/', self.user, r'/en/blog/', edit=False) + request = self.get_page_request("/", self.user, r"/en/blog/", edit=False) - post = self._get_post(self._post_data[0]['en']) - post = self._get_post(self._post_data[0]['it'], post, 'it') + post = self._get_post(self._post_data[0]["en"]) + post = self._get_post(self._post_data[0]["it"], post, "it") response = post_admin.change_view(request, str(post.pk)) response.render() - self.assertRegexpMatches(force_text(response.content), r'[^>]*>Custom image') - self.assertRegexpMatches(force_text(response.content), r'[^>]*>Custom thumbnail') - self.assertRegexpMatches(force_text(response.content), r'[^>]*>Blog image') - self.assertRegexpMatches(force_text(response.content), r'[^>]*>Blog thumbnail') + self.assertRegexpMatches(force_text(response.content), r"[^>]*>Custom image") + self.assertRegexpMatches(force_text(response.content), r"[^>]*>Custom thumbnail") + self.assertRegexpMatches(force_text(response.content), r"[^>]*>Blog image") + self.assertRegexpMatches(force_text(response.content), r"[^>]*>Blog thumbnail") post.main_image_full = custom_full post.main_image_thumbnail = custom_thumbnail post.save() response = post_admin.change_view(request, str(post.pk)) response.render() - self.assertRegexpMatches(force_text(response.content), r'selected[^>]*>Custom image') - self.assertRegexpMatches(force_text(response.content), r'selected[^>]*>Custom thumbnail') + self.assertRegexpMatches(force_text(response.content), r"selected[^>]*>Custom image") + self.assertRegexpMatches(force_text(response.content), r"selected[^>]*>Custom thumbnail") self.app_config_1.app_data.config.default_image_full = self.default_full self.app_config_1.app_data.config.default_image_thumbnail = self.default_thumbnail @@ -114,23 +93,23 @@ def test_admin_thumbnails(self): response = post_admin.change_view(request, str(post.pk)) response.render() - self.assertRegexpMatches(force_text(response.content), r'selected[^>]*>Blog image') - self.assertRegexpMatches(force_text(response.content), r'selected[^>]*>Blog thumbnail') + self.assertRegexpMatches(force_text(response.content), r"selected[^>]*>Blog image") + self.assertRegexpMatches(force_text(response.content), r"selected[^>]*>Blog thumbnail") def test_admin_category_required(self): self.get_pages() post_admin = admin.site._registry[Post] - request = self.get_page_request('/', self.user, r'/en/blog/', edit=False) - BlogCategory.objects.create(name='category 1 - blog 2', app_config=self.app_config_2) + request = self.get_page_request("/", self.user, r"/en/blog/", edit=False) + BlogCategory.objects.create(name="category 1 - blog 2", app_config=self.app_config_2) - post = self._get_post(self._post_data[0]['en']) - post = self._get_post(self._post_data[0]['it'], post, 'it') + post = self._get_post(self._post_data[0]["en"]) + post = self._get_post(self._post_data[0]["it"], post, "it") response = post_admin.change_view(request, str(post.pk)) self.assertEqual( - response.context_data['adminform'].form.fields['categories'].required, - self.app_config_1.url_patterns == PERMALINK_TYPE_CATEGORY + response.context_data["adminform"].form.fields["categories"].required, + self.app_config_1.url_patterns == PERMALINK_TYPE_CATEGORY, ) self.app_config_1.app_data.config.url_patterns = PERMALINK_TYPE_CATEGORY @@ -138,8 +117,8 @@ def test_admin_category_required(self): response = post_admin.change_view(request, str(post.pk)) self.assertEqual( - response.context_data['adminform'].form.fields['categories'].required, - self.app_config_1.url_patterns == PERMALINK_TYPE_CATEGORY + response.context_data["adminform"].form.fields["categories"].required, + self.app_config_1.url_patterns == PERMALINK_TYPE_CATEGORY, ) self.app_config_1.app_data.config.url_patterns = PERMALINK_TYPE_FULL_DATE @@ -149,10 +128,10 @@ def test_admin_post_views(self): self.get_pages() post_admin = admin.site._registry[Post] - request = self.get_page_request('/', self.user, r'/en/blog/', edit=False) + request = self.get_page_request("/", self.user, r"/en/blog/", edit=False) - post = self._get_post(self._post_data[0]['en']) - post = self._get_post(self._post_data[0]['it'], post, 'it') + post = self._get_post(self._post_data[0]["en"]) + post = self._get_post(self._post_data[0]["it"], post, "it") # Add view only contains the apphook selection widget response = post_admin.add_view(request) @@ -171,9 +150,15 @@ def test_admin_post_views(self): except AssertionError: self.assertRegexpMatches(force_text(response.content), r'maxlength="320"[^>]*id="id_meta_description"') try: - self.assertRegexpMatches(force_text(response.content), r'selected[^>]*value="%s">Blog / sample_app' % self.app_config_1.pk) + self.assertRegexpMatches( + force_text(response.content), + r'selected[^>]*value="%s">Blog / sample_app' % self.app_config_1.pk, + ) except AssertionError: - self.assertRegexpMatches(force_text(response.content), r'value="%s"[^>]*selected[^>]*>Blog / sample_app' % self.app_config_1.pk) + self.assertRegexpMatches( + force_text(response.content), + r'value="%s"[^>]*selected[^>]*>Blog / sample_app' % self.app_config_1.pk, + ) # Test for publish view post.publish = False @@ -181,76 +166,78 @@ def test_admin_post_views(self): response = post_admin.publish_post(request, str(post.pk)) # Redirects to current post self.assertEqual(response.status_code, 302) - self.assertEqual(response['Location'], post.get_absolute_url()) + self.assertEqual(response["Location"], post.get_absolute_url()) post = self.reload_model(post) # post is publshed self.assertTrue(post.publish) # Non-existing post is redirected to posts list - response = post_admin.publish_post(request, str('1000000')) + response = post_admin.publish_post(request, "1000000") self.assertEqual(response.status_code, 302) - self.assertEqual(response['Location'], reverse('djangocms_blog:posts-latest')) + self.assertEqual(response["Location"], reverse("djangocms_blog:posts-latest")) # unless a referer is set - request.META['HTTP_REFERER'] = '/' - response = post_admin.publish_post(request, str('1000000')) + request.META["HTTP_REFERER"] = "/" + response = post_admin.publish_post(request, "1000000") self.assertEqual(response.status_code, 302) - self.assertEqual(response['Location'], '/') + self.assertEqual(response["Location"], "/") def test_admin_changelist_view(self): posts = self.get_posts() post_admin = admin.site._registry[Post] - request = self.get_page_request('/', self.user, r'/en/blog/', edit=False) + request = self.get_page_request("/", self.user, r"/en/blog/", edit=False) # Normal changelist, all existing posts response = post_admin.changelist_view(request) - self.assertEqual(response.context_data['cl'].queryset.count(), len(posts)) - self.assertTrue(posts[0] in response.context_data['cl'].queryset.all()) + self.assertEqual(response.context_data["cl"].queryset.count(), len(posts)) + self.assertTrue(posts[0] in response.context_data["cl"].queryset.all()) # Site 2 is added to first post, but no changelist filter, no changes posts[0].sites.add(self.site_2) response = post_admin.changelist_view(request) - self.assertTrue(posts[0] in response.context_data['cl'].queryset.all()) + self.assertTrue(posts[0] in response.context_data["cl"].queryset.all()) # Filtering on site, first post not shown - request = self.get_page_request('/', self.user, r'/en/blog/?sites=1', edit=False) + request = self.get_page_request("/", self.user, r"/en/blog/?sites=1", edit=False) response = post_admin.changelist_view(request) - self.assertEqual(response.context_data['cl'].queryset.count(), len(posts) - 1) - self.assertTrue(posts[0] not in response.context_data['cl'].queryset.all()) + self.assertEqual(response.context_data["cl"].queryset.count(), len(posts) - 1) + self.assertTrue(posts[0] not in response.context_data["cl"].queryset.all()) # Removing site filtering, first post appears again - request = self.get_page_request('/', self.user, r'/en/blog/?', edit=False) + request = self.get_page_request("/", self.user, r"/en/blog/?", edit=False) response = post_admin.changelist_view(request) - self.assertEqual(response.context_data['cl'].queryset.count(), len(posts)) - self.assertTrue(posts[0] in response.context_data['cl'].queryset.all()) + self.assertEqual(response.context_data["cl"].queryset.count(), len(posts)) + self.assertTrue(posts[0] in response.context_data["cl"].queryset.all()) # Filtering on the apphook config and site - request = self.get_page_request('/', self.user, r'/en/blog/?app_config__id__exact=%s&sites=1' % self.app_config_1.pk, edit=False) + request = self.get_page_request( + "/", self.user, r"/en/blog/?app_config__id__exact=%s&sites=1" % self.app_config_1.pk, edit=False + ) response = post_admin.changelist_view(request) # First and last post in the list are now in the queryset - self.assertEqual(response.context_data['cl'].queryset.count(), len(posts) - 2) - self.assertTrue(posts[0] not in response.context_data['cl'].queryset.all()) - self.assertTrue(posts[-1] not in response.context_data['cl'].queryset.all()) + self.assertEqual(response.context_data["cl"].queryset.count(), len(posts) - 2) + self.assertTrue(posts[0] not in response.context_data["cl"].queryset.all()) + self.assertTrue(posts[-1] not in response.context_data["cl"].queryset.all()) # Publishing one post, two published in total posts[1].publish = True posts[1].save() published = Post.objects.published(current_site=False) - request = self.get_page_request('/', self.user, r'/en/blog/?publish__exact=1', edit=False) + request = self.get_page_request("/", self.user, r"/en/blog/?publish__exact=1", edit=False) response = post_admin.changelist_view(request) # The admin queryset and the model queryset are the same - self.assertEqual(response.context_data['cl'].queryset.count(), published.count()) + self.assertEqual(response.context_data["cl"].queryset.count(), published.count()) # Published post is in the changelist queryset - self.assertTrue(posts[1] in response.context_data['cl'].queryset.all()) + self.assertTrue(posts[1] in response.context_data["cl"].queryset.all()) def test_admin_blogconfig_views(self): post_admin = admin.site._registry[BlogConfig] - request = self.get_page_request('/', self.user, r'/en/blog/', edit=False) + request = self.get_page_request("/", self.user, r"/en/blog/", edit=False) # Add view only has an empty form - no type response = post_admin.add_view(request) response.render() - self.assertNotContains(response, 'djangocms_blog.cms_appconfig.BlogConfig') + self.assertNotContains(response, "djangocms_blog.cms_appconfig.BlogConfig") try: self.assertRegexpMatches(force_text(response.content), r'maxlength="100"[^>]*id="id_namespace"') except AssertionError: @@ -258,7 +245,7 @@ def test_admin_blogconfig_views(self): # Changeview is 'normal', with a few preselected items response = post_admin.change_view(request, str(self.app_config_1.pk)) - self.assertContains(response, 'djangocms_blog.cms_appconfig.BlogConfig') + self.assertContains(response, "djangocms_blog.cms_appconfig.BlogConfig") try: self.assertRegexpMatches(force_text(response.content), r'selected[^>]*value="Article">Article') except AssertionError: @@ -271,12 +258,12 @@ def test_admin_blogconfig_views(self): except AssertionError: self.assertRegexpMatches(force_text(response.content), r'id="id_config-og_app_id"[^>]*maxlength="200"') - self.assertContains(response, 'sample_app') + self.assertContains(response, "sample_app") def test_admin_category_views(self): category_admin = admin.site._registry[BlogCategory] - request = self.get_page_request('/', self.user, r'/en/blog/', edit=False) - BlogCategory.objects.create(name='category 1 - blog 2', app_config=self.app_config_2) + request = self.get_page_request("/", self.user, r"/en/blog/", edit=False) + BlogCategory.objects.create(name="category 1 - blog 2", app_config=self.app_config_2) # Add view only has an empty form - no type response = category_admin.add_view(request) @@ -284,20 +271,20 @@ def test_admin_category_views(self): self.assertContains(response, '' % self.app_config_1.pk) # Add view select categories on the given appconfig, even when reloading the form - request.POST = QueryDict('app_config=%s' % self.app_config_1.pk) - request.method = 'POST' + request.POST = QueryDict("app_config=%s" % self.app_config_1.pk) + request.method = "POST" response = category_admin.add_view(request) self.assertEqual( - list(response.context_data['adminform'].form.fields['parent'].queryset), - list(BlogCategory.objects.filter(app_config=self.app_config_1)) + list(response.context_data["adminform"].form.fields["parent"].queryset), + list(BlogCategory.objects.filter(app_config=self.app_config_1)), ) - request.GET = QueryDict('app_config=%s' % self.app_config_1.pk) - request.method = 'GET' + request.GET = QueryDict("app_config=%s" % self.app_config_1.pk) + request.method = "GET" response = category_admin.add_view(request) self.assertEqual( - list(response.context_data['adminform'].form.fields['parent'].queryset), - list(BlogCategory.objects.filter(app_config=self.app_config_1)) + list(response.context_data["adminform"].form.fields["parent"].queryset), + list(BlogCategory.objects.filter(app_config=self.app_config_1)), ) # Changeview is 'normal', with a few preselected items @@ -313,127 +300,119 @@ def test_admin_category_views(self): except AssertionError: self.assertRegexpMatches(force_text(response.content), r'maxlength="320"[^>]*id="id_meta_description"') try: - self.assertRegexpMatches(force_text(response.content), r'selected[^>]*value="%s">Blog / sample_app' % self.app_config_1.pk) + self.assertRegexpMatches( + force_text(response.content), + r'selected[^>]*value="%s">Blog / sample_app' % self.app_config_1.pk, + ) except AssertionError: - self.assertRegexpMatches(force_text(response.content), r'value="%s"[^>]*selected[^>]*>Blog / sample_app' % self.app_config_1.pk) + self.assertRegexpMatches( + force_text(response.content), + r'value="%s"[^>]*selected[^>]*>Blog / sample_app' % self.app_config_1.pk, + ) def test_form(self): posts = self.get_posts() with override_settings(BLOG_META_DESCRIPTION_LENGTH=20, BLOG_META_TITLE_LENGTH=20): - form = PostAdminForm( - data={'meta_description': 'major text over 20 characters long'}, - instance=posts[0] - ) + form = PostAdminForm(data={"meta_description": "major text over 20 characters long"}, instance=posts[0]) self.assertFalse(form.is_valid()) - form = PostAdminForm( - data={'meta_title': 'major text over 20 characters long'}, - instance=posts[0] - ) + form = PostAdminForm(data={"meta_title": "major text over 20 characters long"}, instance=posts[0]) self.assertFalse(form.is_valid()) form = CategoryAdminForm( - data={'meta_description': 'major text over 20 characters long'}, - instance=self.category_1 + data={"meta_description": "major text over 20 characters long"}, instance=self.category_1 ) self.assertFalse(form.is_valid()) - form = PostAdminForm( - data={'meta_description': 'mini text'}, - instance=posts[0] - ) + form = PostAdminForm(data={"meta_description": "mini text"}, instance=posts[0]) self.assertFalse(form.is_valid()) - form = PostAdminForm( - data={'meta_title': 'mini text'}, - instance=posts[0] - ) + form = PostAdminForm(data={"meta_title": "mini text"}, instance=posts[0]) self.assertFalse(form.is_valid()) - form = CategoryAdminForm( - data={'meta_description': 'mini text'}, - instance=self.category_1 - ) + form = CategoryAdminForm(data={"meta_description": "mini text"}, instance=self.category_1) self.assertFalse(form.is_valid()) def test_admin_category_parents(self): - category1 = BlogCategory.objects.create(name='tree category 1', app_config=self.app_config_1) - category2 = BlogCategory.objects.create(name='tree category 2', parent=category1, app_config=self.app_config_1) - category3 = BlogCategory.objects.create(name='tree category 3', parent=category2, app_config=self.app_config_1) - BlogCategory.objects.create(name='tree category 4', parent=category3, app_config=self.app_config_1) - BlogCategory.objects.create(name='category different branch', app_config=self.app_config_2) + category1 = BlogCategory.objects.create(name="tree category 1", app_config=self.app_config_1) + category2 = BlogCategory.objects.create(name="tree category 2", parent=category1, app_config=self.app_config_1) + category3 = BlogCategory.objects.create(name="tree category 3", parent=category2, app_config=self.app_config_1) + BlogCategory.objects.create(name="tree category 4", parent=category3, app_config=self.app_config_1) + BlogCategory.objects.create(name="category different branch", app_config=self.app_config_2) post_admin = admin.site._registry[BlogCategory] - request = self.get_page_request('/', self.user, r'/en/blog/?app_config=%s' % self.app_config_1.pk, edit=False) + request = self.get_page_request("/", self.user, r"/en/blog/?app_config=%s" % self.app_config_1.pk, edit=False) # Add view shows all the exising categories response = post_admin.add_view(request) self.assertTrue( - response.context_data['adminform'].form.fields['parent'].queryset, - BlogCategory.objects.filter(app_config=self.app_config_1) + response.context_data["adminform"].form.fields["parent"].queryset, + BlogCategory.objects.filter(app_config=self.app_config_1), ) # Changeview hides the children of the current category response = post_admin.change_view(request, str(category2.pk)) self.assertTrue( - response.context_data['adminform'].form.fields['parent'].queryset, - BlogCategory.objects.filter(app_config=self.app_config_1, parent__isnull=True) + response.context_data["adminform"].form.fields["parent"].queryset, + BlogCategory.objects.filter(app_config=self.app_config_1, parent__isnull=True), ) # Test second apphook categories - request = self.get_page_request('/', self.user, r'/en/blog/?app_config=%s' % self.app_config_2.pk, edit=False) + request = self.get_page_request("/", self.user, r"/en/blog/?app_config=%s" % self.app_config_2.pk, edit=False) response = post_admin.add_view(request) self.assertTrue( - response.context_data['adminform'].form.fields['parent'].queryset, - BlogCategory.objects.filter(app_config=self.app_config_2) + response.context_data["adminform"].form.fields["parent"].queryset, + BlogCategory.objects.filter(app_config=self.app_config_2), ) def test_admin_fieldsets(self): post_admin = admin.site._registry[Post] - request = self.get_page_request('/', self.user_staff, r'/en/blog/?app_config=%s' % self.app_config_1.pk, edit=False) + request = self.get_page_request( + "/", self.user_staff, r"/en/blog/?app_config=%s" % self.app_config_1.pk, edit=False + ) # Use placeholder self.app_config_1.app_data.config.use_placeholder = True self.app_config_1.save() fsets = post_admin.get_fieldsets(request) - self.assertFalse('post_text' in fsets[0][1]['fields']) + self.assertFalse("post_text" in fsets[0][1]["fields"]) self.app_config_1.app_data.config.use_placeholder = False self.app_config_1.save() fsets = post_admin.get_fieldsets(request) - self.assertTrue('post_text' in fsets[0][1]['fields']) + self.assertTrue("post_text" in fsets[0][1]["fields"]) self.app_config_1.app_data.config.use_placeholder = True self.app_config_1.save() fsets = post_admin.get_fieldsets(request) - self.assertFalse('post_text' in fsets[0][1]['fields']) + self.assertFalse("post_text" in fsets[0][1]["fields"]) # Use related posts self.app_config_1.app_data.config.use_related = True self.app_config_1.save() fsets = post_admin.get_fieldsets(request) - self.assertFalse('related' in fsets[1][1]['fields'][0]) + self.assertFalse("related" in fsets[1][1]["fields"][0]) - Post.objects.language('en').create(title='post x', app_config=self.app_config_1) + Post.objects.language("en").create(title="post x", app_config=self.app_config_1) fsets = post_admin.get_fieldsets(request) - self.assertTrue('related' in fsets[1][1]['fields'][0]) + self.assertTrue("related" in fsets[1][1]["fields"][0]) self.app_config_1.app_data.config.use_related = False self.app_config_1.save() fsets = post_admin.get_fieldsets(request) - self.assertFalse('related' in fsets[1][1]['fields'][0]) + self.assertFalse("related" in fsets[1][1]["fields"][0]) self.app_config_1.app_data.config.use_related = True self.app_config_1.save() fsets = post_admin.get_fieldsets(request) - self.assertTrue('related' in fsets[1][1]['fields'][0]) + self.assertTrue("related" in fsets[1][1]["fields"][0]) # Use abstract self.app_config_1.app_data.config.use_abstract = True self.app_config_1.save() fsets = post_admin.get_fieldsets(request) - self.assertTrue('abstract' in fsets[0][1]['fields']) + self.assertTrue("abstract" in fsets[0][1]["fields"]) self.app_config_1.app_data.config.use_abstract = False self.app_config_1.save() fsets = post_admin.get_fieldsets(request) - self.assertFalse('abstract' in fsets[0][1]['fields']) + self.assertFalse("abstract" in fsets[0][1]["fields"]) self.app_config_1.app_data.config.use_abstract = True self.app_config_1.app_data.config.default_image_full = self.default_full @@ -442,55 +421,54 @@ def test_admin_fieldsets(self): with self.settings(BLOG_MULTISITE=True): fsets = post_admin.get_fieldsets(request) - self.assertTrue('sites' in fsets[1][1]['fields'][0]) + self.assertTrue("sites" in fsets[1][1]["fields"][0]) with self.settings(BLOG_MULTISITE=False): fsets = post_admin.get_fieldsets(request) - self.assertFalse('sites' in fsets[1][1]['fields'][0]) + self.assertFalse("sites" in fsets[1][1]["fields"][0]) - request = self.get_page_request( - '/', self.user, r'/en/blog/?app_config=%s' % self.app_config_1.pk, edit=False - ) + request = self.get_page_request("/", self.user, r"/en/blog/?app_config=%s" % self.app_config_1.pk, edit=False) fsets = post_admin.get_fieldsets(request) - self.assertTrue('author' in fsets[1][1]['fields'][0]) + self.assertTrue("author" in fsets[1][1]["fields"][0]) with self.login_user_context(self.user): request = self.get_request( - '/', 'en', user=self.user, path=r'/en/blog/?app_config=%s' % self.app_config_1.pk + "/", "en", user=self.user, path=r"/en/blog/?app_config=%s" % self.app_config_1.pk ) msg_mid = MessageMiddleware() msg_mid.process_request(request) post_admin = admin.site._registry[Post] response = post_admin.add_view(request) self.assertTrue( - response.context_data['adminform'].form.fields['categories'].queryset, - BlogCategory.objects.filter(app_config=self.app_config_1) + response.context_data["adminform"].form.fields["categories"].queryset, + BlogCategory.objects.filter(app_config=self.app_config_1), ) response.render() self.assertContains(response, 'id="id_sites"') - self.assertRegexpMatches(force_text(response.content), r'selected[^>]*>Blog image') - self.assertRegexpMatches(force_text(response.content), r'selected[^>]*>Blog thumbnail') + self.assertRegexpMatches(force_text(response.content), r"selected[^>]*>Blog image") + self.assertRegexpMatches(force_text(response.content), r"selected[^>]*>Blog thumbnail") # Add view select categories on the given appconfig, even when reloading the form - request.POST = QueryDict('app_config=%s' % self.app_config_1.pk) - request.method = 'POST' + request.POST = QueryDict("app_config=%s" % self.app_config_1.pk) + request.method = "POST" response = post_admin.add_view(request) self.assertTrue( - response.context_data['adminform'].form.fields['categories'].queryset, - BlogCategory.objects.filter(app_config=self.app_config_1) + response.context_data["adminform"].form.fields["categories"].queryset, + BlogCategory.objects.filter(app_config=self.app_config_1), ) - request.GET = QueryDict('app_config=%s' % self.app_config_1.pk) - request.method = 'GET' + request.GET = QueryDict("app_config=%s" % self.app_config_1.pk) + request.method = "GET" response = post_admin.add_view(request) self.assertTrue( - response.context_data['adminform'].form.fields['categories'].queryset, - BlogCategory.objects.filter(app_config=self.app_config_1) + response.context_data["adminform"].form.fields["categories"].queryset, + BlogCategory.objects.filter(app_config=self.app_config_1), ) self.user.sites.add(self.site_1) with self.login_user_context(self.user): - request = self.get_request('/', 'en', user=self.user, - path=r'/en/blog/?app_config=%s' % self.app_config_1.pk) + request = self.get_request( + "/", "en", user=self.user, path=r"/en/blog/?app_config=%s" % self.app_config_1.pk + ) msg_mid = MessageMiddleware() msg_mid.process_request(request) post_admin = admin.site._registry[Post] @@ -506,16 +484,14 @@ def test_admin_queryset(self): posts[0].sites.add(self.site_1) posts[1].sites.add(self.site_2) - request = self.get_request('/', 'en', user=self.user, - path=r'/en/blog/?app_config=%s' % self.app_config_1.pk) + request = self.get_request("/", "en", user=self.user, path=r"/en/blog/?app_config=%s" % self.app_config_1.pk) post_admin = admin.site._registry[Post] post_admin._sites = None qs = post_admin.get_queryset(request) self.assertEqual(qs.count(), 4) self.user.sites.add(self.site_2) - request = self.get_request('/', 'en', user=self.user, - path=r'/en/blog/?app_config=%s' % self.app_config_1.pk) + request = self.get_request("/", "en", user=self.user, path=r"/en/blog/?app_config=%s" % self.app_config_1.pk) post_admin = admin.site._registry[Post] post_admin._sites = None qs = post_admin.get_queryset(request) @@ -525,110 +501,119 @@ def test_admin_queryset(self): def test_admin_auto_author(self): pages = self.get_pages() - data = deepcopy(self._post_data[0]['en']) + data = deepcopy(self._post_data[0]["en"]) with self.login_user_context(self.user): self.app_config_1.app_data.config.set_author = True self.app_config_1.save() - data['date_published_0'] = now().strftime('%Y-%m-%d') - data['date_published_1'] = now().strftime('%H:%M:%S') - data['categories'] = self.category_1.pk - data['app_config'] = self.app_config_1.pk - request = self.post_request(pages[0], 'en', user=self.user, data=data, path=r'/en/blog/?app_config=%s' % self.app_config_1.pk) + data["date_published_0"] = now().strftime("%Y-%m-%d") + data["date_published_1"] = now().strftime("%H:%M:%S") + data["categories"] = self.category_1.pk + data["app_config"] = self.app_config_1.pk + request = self.post_request( + pages[0], "en", user=self.user, data=data, path=r"/en/blog/?app_config=%s" % self.app_config_1.pk + ) msg_mid = MessageMiddleware() msg_mid.process_request(request) post_admin = admin.site._registry[Post] response = post_admin.add_view(request) self.assertEqual(response.status_code, 302) self.assertEqual(Post.objects.count(), 1) - self.assertEqual(Post.objects.get(translations__slug='first-post').author_id, request.user.pk) + self.assertEqual(Post.objects.get(translations__slug="first-post").author_id, request.user.pk) self.app_config_1.app_data.config.set_author = False self.app_config_1.save() - data = deepcopy(self._post_data[1]['en']) - data['date_published_0'] = now().strftime('%Y-%m-%d') - data['date_published_1'] = now().strftime('%H:%M:%S') - data['categories'] = self.category_1.pk - data['app_config'] = self.app_config_1.pk - request = self.post_request(pages[0], 'en', user=self.user, data=data, path=r'/en/blog/?app_config=%s' % self.app_config_1.pk) + data = deepcopy(self._post_data[1]["en"]) + data["date_published_0"] = now().strftime("%Y-%m-%d") + data["date_published_1"] = now().strftime("%H:%M:%S") + data["categories"] = self.category_1.pk + data["app_config"] = self.app_config_1.pk + request = self.post_request( + pages[0], "en", user=self.user, data=data, path=r"/en/blog/?app_config=%s" % self.app_config_1.pk + ) msg_mid = MessageMiddleware() msg_mid.process_request(request) post_admin = admin.site._registry[Post] response = post_admin.add_view(request) self.assertEqual(response.status_code, 302) self.assertEqual(Post.objects.count(), 2) - self.assertEqual(Post.objects.get(translations__slug='second-post').author_id, None) + self.assertEqual(Post.objects.get(translations__slug="second-post").author_id, None) - with self.settings(BLOG_AUTHOR_DEFAULT='staff'): + with self.settings(BLOG_AUTHOR_DEFAULT="staff"): self.app_config_1.app_data.config.set_author = True self.app_config_1.save() - data = deepcopy(self._post_data[2]['en']) - data['date_published_0'] = now().strftime('%Y-%m-%d') - data['date_published_1'] = now().strftime('%H:%M:%S') - data['categories'] = self.category_1.pk - data['app_config'] = self.app_config_1.pk - request = self.post_request(pages[0], 'en', user=self.user, data=data, path=r'/en/blog/?app_config=%s' % self.app_config_1.pk) + data = deepcopy(self._post_data[2]["en"]) + data["date_published_0"] = now().strftime("%Y-%m-%d") + data["date_published_1"] = now().strftime("%H:%M:%S") + data["categories"] = self.category_1.pk + data["app_config"] = self.app_config_1.pk + request = self.post_request( + pages[0], "en", user=self.user, data=data, path=r"/en/blog/?app_config=%s" % self.app_config_1.pk + ) msg_mid = MessageMiddleware() msg_mid.process_request(request) post_admin = admin.site._registry[Post] response = post_admin.add_view(request) self.assertEqual(response.status_code, 302) self.assertEqual(Post.objects.count(), 3) - self.assertEqual(Post.objects.get(translations__slug='third-post').author.username, 'staff') + self.assertEqual(Post.objects.get(translations__slug="third-post").author.username, "staff") def test_admin_fieldsets_filter(self): post_admin = admin.site._registry[Post] - request = self.get_page_request('/', self.user_normal, r'/en/blog/?app_config=%s' % self.app_config_1.pk) + request = self.get_page_request("/", self.user_normal, r"/en/blog/?app_config=%s" % self.app_config_1.pk) post_admin._sites = None fsets = post_admin.get_fieldsets(request) - self.assertFalse('author' in fsets[1][1]['fields'][0]) - self.assertTrue('sites' in fsets[1][1]['fields'][0]) + self.assertFalse("author" in fsets[1][1]["fields"][0]) + self.assertTrue("sites" in fsets[1][1]["fields"][0]) post_admin._sites = None def filter_function(fs, request, obj=None): if request.user == self.user_normal: - fs[1][1]['fields'][0].append('author') + fs[1][1]["fields"][0].append("author") return fs self.user_normal.sites.add(self.site_1) - request = self.get_page_request('/', self.user_normal, r'/en/blog/?app_config=%s' % self.app_config_1.pk) + request = self.get_page_request("/", self.user_normal, r"/en/blog/?app_config=%s" % self.app_config_1.pk) post_admin._sites = None with self.settings(BLOG_ADMIN_POST_FIELDSET_FILTER=filter_function): fsets = post_admin.get_fieldsets(request) - self.assertTrue('author' in fsets[1][1]['fields'][0]) - self.assertFalse('sites' in fsets[1][1]['fields'][0]) + self.assertTrue("author" in fsets[1][1]["fields"][0]) + self.assertFalse("sites" in fsets[1][1]["fields"][0]) post_admin._sites = None self.user_normal.sites.clear() def test_admin_post_text(self): pages = self.get_pages() - post = self._get_post(self._post_data[0]['en']) + post = self._get_post(self._post_data[0]["en"]) with pause_knocks(post): with self.login_user_context(self.user): with self.settings(BLOG_USE_PLACEHOLDER=False): - data = {'post_text': 'ehi text', 'title': 'some title'} - request = self.post_request(pages[0], 'en', user=self.user, data=data, path='/en/?edit_fields=post_text') + data = {"post_text": "ehi text", "title": "some title"} + request = self.post_request( + pages[0], "en", user=self.user, data=data, path="/en/?edit_fields=post_text" + ) msg_mid = MessageMiddleware() msg_mid.process_request(request) post_admin = admin.site._registry[Post] - response = post_admin.edit_field(request, post.pk, 'en') + response = post_admin.edit_field(request, post.pk, "en") self.assertEqual(response.status_code, 200) - modified_post = Post.objects.language('en').get(pk=post.pk) - self.assertEqual(modified_post.safe_translation_getter('post_text'), data['post_text']) + modified_post = Post.objects.language("en").get(pk=post.pk) + self.assertEqual(modified_post.safe_translation_getter("post_text"), data["post_text"]) def test_admin_site(self): pages = self.get_pages() - post = self._get_post(self._post_data[0]['en']) + post = self._get_post(self._post_data[0]["en"]) # no restrictions, sites are assigned with self.login_user_context(self.user): data = { - 'sites': [self.site_1.pk, self.site_2.pk], 'title': 'some title', - 'app_config': self.app_config_1.pk + "sites": [self.site_1.pk, self.site_2.pk], + "title": "some title", + "app_config": self.app_config_1.pk, } - request = self.post_request(pages[0], 'en', user=self.user, data=data, path='/en/') + request = self.post_request(pages[0], "en", user=self.user, data=data, path="/en/") self.assertEquals(post.sites.count(), 0) msg_mid = MessageMiddleware() msg_mid.process_request(request) @@ -648,10 +633,11 @@ def test_admin_site(self): self.user = self.reload_model(self.user) with self.login_user_context(self.user): data = { - 'sites': [self.site_2.pk, self.site_3.pk], 'title': 'some title', - 'app_config': self.app_config_1.pk + "sites": [self.site_2.pk, self.site_3.pk], + "title": "some title", + "app_config": self.app_config_1.pk, } - request = self.post_request(pages[0], 'en', user=self.user, data=data, path='/en/') + request = self.post_request(pages[0], "en", user=self.user, data=data, path="/en/") self.assertEquals(post.sites.count(), 2) msg_mid = MessageMiddleware() msg_mid.process_request(request) @@ -672,11 +658,8 @@ def test_admin_site(self): self.user.sites.add(self.site_2) self.user.sites.add(self.site_3) with self.login_user_context(self.user): - data = { - 'sites': [self.site_3.pk], 'title': 'some title', - 'app_config': self.app_config_1.pk - } - request = self.post_request(pages[0], 'en', user=self.user, data=data, path='/en/') + data = {"sites": [self.site_3.pk], "title": "some title", "app_config": self.app_config_1.pk} + request = self.post_request(pages[0], "en", user=self.user, data=data, path="/en/") self.assertEquals(post.sites.count(), 3) msg_mid = MessageMiddleware() msg_mid.process_request(request) @@ -697,11 +680,8 @@ def test_admin_site(self): self.user.sites.add(self.site_2) self.user.sites.add(self.site_3) with self.login_user_context(self.user): - data = { - 'sites': [], 'title': 'some title', - 'app_config': self.app_config_1.pk - } - request = self.post_request(pages[0], 'en', user=self.user, data=data, path='/en/') + data = {"sites": [], "title": "some title", "app_config": self.app_config_1.pk} + request = self.post_request(pages[0], "en", user=self.user, data=data, path="/en/") self.assertEquals(post.sites.count(), 2) msg_mid = MessageMiddleware() msg_mid.process_request(request) @@ -723,18 +703,18 @@ def test_admin_clear_menu(self): self._reload_menus() pages = self.get_pages() - post = self._get_post(self._post_data[0]['en']) + post = self._get_post(self._post_data[0]["en"]) - request = self.get_page_request(None, self.user, r'/en/page-two/') + request = self.get_page_request(None, self.user, r"/en/page-two/") first_nodes = self.get_nodes(menu_pool, request) self._reset_menus() with pause_knocks(post): with self.login_user_context(self.user): - data = dict(namespace='sample_app', app_title='app1', object_name='Blog') - data['config-menu_structure'] = MENU_TYPE_NONE - data['config-sitemap_changefreq'] = 'weekly' - data['config-sitemap_priority'] = '0.5' - request = self.post_request(pages[0], 'en', user=self.user, data=data) + data = dict(namespace="sample_app", app_title="app1", object_name="Blog") + data["config-menu_structure"] = MENU_TYPE_NONE + data["config-sitemap_changefreq"] = "weekly" + data["config-sitemap_priority"] = "0.5" + request = self.post_request(pages[0], "en", user=self.user, data=data) msg_mid = MessageMiddleware() msg_mid.process_request(request) config_admin = admin.site._registry[BlogConfig] @@ -744,7 +724,6 @@ def test_admin_clear_menu(self): class ModelsTest(BaseTest): - def test_category_attributes(self): posts = self.get_posts() posts[0].publish = True @@ -752,9 +731,7 @@ def test_category_attributes(self): posts[1].publish = True posts[1].save() posts[1].sites.add(self.site_2) - new_category = BlogCategory.objects.create( - name='category 2', app_config=self.app_config_1 - ) + new_category = BlogCategory.objects.create(name="category 2", app_config=self.app_config_1) posts[1].categories.add(new_category) with self.settings(SITE_ID=2): @@ -773,23 +750,23 @@ def test_category_attributes(self): self.assertEqual(self.category_1.count_all_sites, 2) def test_slug(self): - post = Post.objects.language('en').create(title='I am a title') - self.assertEqual(post.slug, 'i-am-a-title') + post = Post.objects.language("en").create(title="I am a title") + self.assertEqual(post.slug, "i-am-a-title") def test_model_attributes(self): self.get_pages() - self.app_config_1.app_data.config.gplus_author = 'RandomJoe' + self.app_config_1.app_data.config.gplus_author = "RandomJoe" self.app_config_1.save() featured_date = now() + timedelta(days=40) - post = self._get_post(self._post_data[0]['en']) - post = self._get_post(self._post_data[0]['it'], post, 'it') + post = self._get_post(self._post_data[0]["en"]) + post = self._get_post(self._post_data[0]["it"], post, "it") post.main_image = self.create_filer_image_object() post.publish = True post.save() - post.set_current_language('en') + post.set_current_language("en") self.assertEqual(post.date, post.date_published) post.date_featured = featured_date @@ -797,23 +774,23 @@ def test_model_attributes(self): self.assertEqual(post.date, featured_date) meta_en = post.as_meta() - self.assertEqual(meta_en.og_type, get_setting('FB_TYPE')) + self.assertEqual(meta_en.og_type, get_setting("FB_TYPE")) self.assertEqual(meta_en.title, post.title) self.assertTrue(meta_en.url.endswith(post.get_absolute_url())) self.assertEqual(meta_en.description, post.meta_description) - self.assertEqual(meta_en.keywords, post.meta_keywords.split(',')) + self.assertEqual(meta_en.keywords, post.meta_keywords.split(",")) self.assertEqual(meta_en.published_time, post.date_published) - self.assertEqual(meta_en.locale, 'en') - self.assertEqual(meta_en.twitter_site, '') - self.assertEqual(meta_en.twitter_author, '') - self.assertEqual(meta_en.twitter_type, 'summary') - self.assertEqual(meta_en.gplus_author, 'RandomJoe') - self.assertEqual(meta_en.gplus_type, 'Blog') - self.assertEqual(meta_en.og_type, 'Article') + self.assertEqual(meta_en.locale, "en") + self.assertEqual(meta_en.twitter_site, "") + self.assertEqual(meta_en.twitter_author, "") + self.assertEqual(meta_en.twitter_type, "summary") + self.assertEqual(meta_en.gplus_author, "RandomJoe") + self.assertEqual(meta_en.gplus_type, "Blog") + self.assertEqual(meta_en.og_type, "Article") self.assertEqual(meta_en.image_width, post.main_image.width) self.assertEqual(meta_en.image_height, post.main_image.height) self.assertEqual(meta_en.facebook_app_id, None) - post.set_current_language('it') + post.set_current_language("it") meta_it = post.as_meta() self.assertEqual(meta_it.title, post.title) self.assertTrue(meta_it.url.endswith(post.get_absolute_url())) @@ -822,70 +799,65 @@ def test_model_attributes(self): category = post.categories.first() meta_cat = category.as_meta() - self.assertEqual(meta_cat.og_type, get_setting('FB_TYPE')) + self.assertEqual(meta_cat.og_type, get_setting("FB_TYPE")) self.assertEqual(meta_cat.title, category.name) self.assertEqual(meta_cat.description, category.meta_description) - self.assertEqual(meta_cat.locale, 'en') - self.assertEqual(meta_cat.twitter_site, '') - self.assertEqual(meta_cat.twitter_author, '') - self.assertEqual(meta_cat.twitter_type, 'summary') - self.assertEqual(meta_cat.gplus_author, 'RandomJoe') - self.assertEqual(meta_cat.gplus_type, 'Blog') - self.assertEqual(meta_cat.og_type, 'Article') + self.assertEqual(meta_cat.locale, "en") + self.assertEqual(meta_cat.twitter_site, "") + self.assertEqual(meta_cat.twitter_author, "") + self.assertEqual(meta_cat.twitter_type, "summary") + self.assertEqual(meta_cat.gplus_author, "RandomJoe") + self.assertEqual(meta_cat.gplus_type, "Blog") + self.assertEqual(meta_cat.og_type, "Article") self.assertEqual(meta_cat.facebook_app_id, None) self.assertTrue(meta_cat.url.endswith(category.get_absolute_url())) - with override('en'): + with override("en"): post.set_current_language(get_language()) - kwargs = {'year': post.date_published.year, - 'month': '%02d' % post.date_published.month, - 'day': '%02d' % post.date_published.day, - 'slug': post.safe_translation_getter('slug', any_language=get_language())} + kwargs = { + "year": post.date_published.year, + "month": "%02d" % post.date_published.month, + "day": "%02d" % post.date_published.day, + "slug": post.safe_translation_getter("slug", any_language=get_language()), + } url_en = reverse( - '%s:post-detail' % self.app_config_1.namespace, - kwargs=kwargs, - current_app=self.app_config_1.namespace + "%s:post-detail" % self.app_config_1.namespace, kwargs=kwargs, current_app=self.app_config_1.namespace ) self.assertEqual(url_en, post.get_absolute_url()) - with override('it'): + with override("it"): post.set_current_language(get_language()) - kwargs = {'year': post.date_published.year, - 'month': '%02d' % post.date_published.month, - 'day': '%02d' % post.date_published.day, - 'slug': post.safe_translation_getter('slug', any_language=get_language())} + kwargs = { + "year": post.date_published.year, + "month": "%02d" % post.date_published.month, + "day": "%02d" % post.date_published.day, + "slug": post.safe_translation_getter("slug", any_language=get_language()), + } url_it = reverse( - '%s:post-detail' % self.app_config_1.namespace, - kwargs=kwargs, - current_app=self.app_config_1.namespace + "%s:post-detail" % self.app_config_1.namespace, kwargs=kwargs, current_app=self.app_config_1.namespace ) self.assertEqual(url_it, post.get_absolute_url()) self.assertNotEqual(url_it, url_en) - self.assertEqual(post.get_full_url(), 'http://example.com%s' % url_it) - self.assertEqual(post.get_image_full_url(), 'http://example.com%s' % post.main_image.url) + self.assertEqual(post.get_full_url(), "http://example.com%s" % url_it) + self.assertEqual(post.get_image_full_url(), "http://example.com%s" % post.main_image.url) - self.assertEqual(post.thumbnail_options(), get_setting('IMAGE_THUMBNAIL_SIZE')) - self.assertEqual(post.full_image_options(), get_setting('IMAGE_FULL_SIZE')) + self.assertEqual(post.thumbnail_options(), get_setting("IMAGE_THUMBNAIL_SIZE")) + self.assertEqual(post.full_image_options(), get_setting("IMAGE_FULL_SIZE")) post.main_image_thumbnail = self.thumb_1 post.main_image_full = self.thumb_2 - self.assertEqual(post.thumbnail_options(), { - 'size': (100, 100), - 'width': 100, 'height': 100, - 'crop': True, - 'upscale': False - }) - self.assertEqual(post.full_image_options(), { - 'size': (200, 200), - 'width': 200, 'height': 200, - 'crop': False, - 'upscale': False - }) - - post.set_current_language('en') - post.meta_title = 'meta title' - self.assertEqual(post.get_title(), 'meta title') + self.assertEqual( + post.thumbnail_options(), {"size": (100, 100), "width": 100, "height": 100, "crop": True, "upscale": False} + ) + self.assertEqual( + post.full_image_options(), + {"size": (200, 200), "width": 200, "height": 200, "crop": False, "upscale": False}, + ) + + post.set_current_language("en") + post.meta_title = "meta title" + self.assertEqual(post.get_title(), "meta title") # Assess is_published property post.publish = False @@ -930,123 +902,102 @@ def test_model_attributes(self): def test_urls(self): self.get_pages() - post = self._get_post(self._post_data[0]['en']) - post = self._get_post(self._post_data[0]['it'], post, 'it') + post = self._get_post(self._post_data[0]["en"]) + post = self._get_post(self._post_data[0]["it"], post, "it") # default - self.assertTrue(re.match(r'.*\d{4}/\d{2}/\d{2}/%s/$' % post.slug, post.get_absolute_url())) + self.assertTrue(re.match(r".*\d{4}/\d{2}/\d{2}/%s/$" % post.slug, post.get_absolute_url())) # full date - self.app_config_1.app_data.config.url_patterns = 'full_date' + self.app_config_1.app_data.config.url_patterns = "full_date" self.app_config_1.save() post.app_config = self.app_config_1 - self.assertTrue(re.match(r'.*\d{4}/\d{2}/\d{2}/%s/$' % post.slug, post.get_absolute_url())) + self.assertTrue(re.match(r".*\d{4}/\d{2}/\d{2}/%s/$" % post.slug, post.get_absolute_url())) # short date - self.app_config_1.app_data.config.url_patterns = 'short_date' + self.app_config_1.app_data.config.url_patterns = "short_date" self.app_config_1.save() post.app_config = self.app_config_1 - self.assertTrue(re.match(r'.*\d{4}/\d{2}/%s/$' % post.slug, post.get_absolute_url())) + self.assertTrue(re.match(r".*\d{4}/\d{2}/%s/$" % post.slug, post.get_absolute_url())) # category - self.app_config_1.app_data.config.url_patterns = 'category' + self.app_config_1.app_data.config.url_patterns = "category" self.app_config_1.save() post.app_config = self.app_config_1 - self.assertTrue(re.match(r'.*/\w[-\w]*/%s/$' % post.slug, post.get_absolute_url())) + self.assertTrue(re.match(r".*/\w[-\w]*/%s/$" % post.slug, post.get_absolute_url())) self.assertTrue( - re.match( - r'.*%s/%s/$' % (post.categories.first().slug, post.slug), - post.get_absolute_url() - ) + re.match(r".*{}/{}/$".format(post.categories.first().slug, post.slug), post.get_absolute_url()) ) # slug only - self.app_config_1.app_data.config.url_patterns = 'category' + self.app_config_1.app_data.config.url_patterns = "category" self.app_config_1.save() post.app_config = self.app_config_1 - self.assertTrue(re.match(r'.*/%s/$' % post.slug, post.get_absolute_url())) + self.assertTrue(re.match(r".*/%s/$" % post.slug, post.get_absolute_url())) def test_url_language(self): self.get_pages() - post = self._get_post(self._post_data[0]['en']) - post = self._get_post(self._post_data[0]['it'], post, 'it') + post = self._get_post(self._post_data[0]["en"]) + post = self._get_post(self._post_data[0]["it"], post, "it") - with override('it'): - self.assertEqual(post.get_current_language(), 'en') - self.assertEqual(post.get_absolute_url(), post.get_absolute_url('it')) + with override("it"): + self.assertEqual(post.get_current_language(), "en") + self.assertEqual(post.get_absolute_url(), post.get_absolute_url("it")) - post.set_current_language('it') - with override('en'): - self.assertEqual(post.get_current_language(), 'it') - self.assertEqual(post.get_absolute_url(), post.get_absolute_url('en')) + post.set_current_language("it") + with override("en"): + self.assertEqual(post.get_current_language(), "it") + self.assertEqual(post.get_absolute_url(), post.get_absolute_url("en")) def test_url_language_use_fallback(self): self.get_pages() - post = self._get_post(self._post_data[0]['en']) + post = self._get_post(self._post_data[0]["en"]) PARLER_FALLBACK = { - 1: ( - {'code': 'en'}, - {'code': 'it'}, - ), - 'default': { - 'fallbacks': ['fr', 'en'], - 'hide_untranslated': False, - } + 1: ({"code": "en"}, {"code": "it"},), + "default": {"fallbacks": ["fr", "en"], "hide_untranslated": False}, } PARLER_FALLBACK = add_default_language_settings(PARLER_FALLBACK) with override_parler_settings(PARLER_LANGUAGES=PARLER_FALLBACK): - with override('it'): - post.set_current_language('it') - self.assertEqual(post.get_absolute_url(), post.get_absolute_url('it')) + with override("it"): + post.set_current_language("it") + self.assertEqual(post.get_absolute_url(), post.get_absolute_url("it")) with override_settings(BLOG_USE_FALLBACK_LANGUAGE_IN_URL=True): - with override('it'): - post.set_current_language('it') - self.assertEqual(post.get_absolute_url(), post.get_absolute_url('en')) + with override("it"): + post.set_current_language("it") + self.assertEqual(post.get_absolute_url(), post.get_absolute_url("en")) def test_manager(self): self.get_pages() - post1 = self._get_post(self._post_data[0]['en']) - post2 = self._get_post(self._post_data[1]['en']) + post1 = self._get_post(self._post_data[0]["en"]) + post2 = self._get_post(self._post_data[1]["en"]) # default queryset, published and unpublished posts months = Post.objects.get_months() for data in months: - self.assertEqual( - data['date'].date(), - now().replace(year=now().year, month=now().month, day=1).date() - ) - self.assertEqual(data['count'], 2) + self.assertEqual(data["date"].date(), now().replace(year=now().year, month=now().month, day=1).date()) + self.assertEqual(data["count"], 2) # custom queryset, only published post1.publish = True post1.save() months = Post.objects.get_months(Post.objects.published()) for data in months: - self.assertEqual( - data['date'].date(), - now().replace(year=now().year, month=now().month, day=1).date() - ) - self.assertEqual(data['count'], 1) + self.assertEqual(data["date"].date(), now().replace(year=now().year, month=now().month, day=1).date()) + self.assertEqual(data["count"], 1) # Move post to different site to filter it out post2.sites.add(self.site_2) months = Post.objects.get_months() for data in months: - self.assertEqual( - data['date'].date(), - now().replace(year=now().year, month=now().month, day=1).date() - ) - self.assertEqual(data['count'], 1) + self.assertEqual(data["date"].date(), now().replace(year=now().year, month=now().month, day=1).date()) + self.assertEqual(data["count"], 1) months = Post.objects.get_months(current_site=False) for data in months: - self.assertEqual( - data['date'].date(), - now().replace(year=now().year, month=now().month, day=1).date() - ) - self.assertEqual(data['count'], 2) + self.assertEqual(data["date"].date(), now().replace(year=now().year, month=now().month, day=1).date()) + self.assertEqual(data["count"], 2) post2.sites.clear() self.assertEqual(len(Post.objects.available()), 1) @@ -1090,33 +1041,33 @@ def test_manager(self): self.assertEqual(len(Post.objects.published(current_site=False)), 2) # counting with language fallback enabled - self._get_post(self._post_data[0]['it'], post1, 'it') - self.assertEqual(len(Post.objects.filter_by_language('it')), 1) - self.assertEqual(len(Post.objects.filter_by_language('it', current_site=False)), 2) + self._get_post(self._post_data[0]["it"], post1, "it") + self.assertEqual(len(Post.objects.filter_by_language("it")), 1) + self.assertEqual(len(Post.objects.filter_by_language("it", current_site=False)), 2) post2.sites.clear() # No fallback - parler.appsettings.PARLER_LANGUAGES['default']['hide_untranslated'] = True + parler.appsettings.PARLER_LANGUAGES["default"]["hide_untranslated"] = True for index, lang in enumerate(parler.appsettings.PARLER_LANGUAGES[Site.objects.get_current().pk]): - parler.appsettings.PARLER_LANGUAGES[Site.objects.get_current().pk][index]['hide_untranslated'] = True - self.assertEqual(len(Post.objects.filter_by_language('it')), 1) - parler.appsettings.PARLER_LANGUAGES['default']['hide_untranslated'] = False + parler.appsettings.PARLER_LANGUAGES[Site.objects.get_current().pk][index]["hide_untranslated"] = True + self.assertEqual(len(Post.objects.filter_by_language("it")), 1) + parler.appsettings.PARLER_LANGUAGES["default"]["hide_untranslated"] = False for index, lang in enumerate(parler.appsettings.PARLER_LANGUAGES[Site.objects.get_current().pk]): - parler.appsettings.PARLER_LANGUAGES[Site.objects.get_current().pk][index]['hide_untranslated'] = False + parler.appsettings.PARLER_LANGUAGES[Site.objects.get_current().pk][index]["hide_untranslated"] = False def test_tag_cloud(self): - post1 = self._get_post(self._post_data[0]['en']) - post2 = self._get_post(self._post_data[1]['en']) - post1.tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4') + post1 = self._get_post(self._post_data[0]["en"]) + post2 = self._get_post(self._post_data[1]["en"]) + post1.tags.add("tag 1", "tag 2", "tag 3", "tag 4") post1.save() - post2.tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8') + post2.tags.add("tag 6", "tag 2", "tag 5", "tag 8") post2.save() self.assertEqual(len(Post.objects.tag_cloud()), 0) tags = [] for tag in Tag.objects.all(): - if tag.slug == 'tag-2': + if tag.slug == "tag-2": tag.count = 2 else: tag.count = 1 @@ -1127,10 +1078,10 @@ def test_tag_cloud(self): tags_1 = [] for tag in Tag.objects.all(): - if tag.slug == 'tag-2': + if tag.slug == "tag-2": tag.count = 2 tags_1.append(tag) - elif tag.slug in ('tag-1', 'tag-3', 'tag-4'): + elif tag.slug in ("tag-1", "tag-3", "tag-4"): tag.count = 1 tags_1.append(tag) @@ -1144,22 +1095,20 @@ def test_tag_cloud(self): self.assertEqual(tags1, tags2) self.assertEqual( - list(Post.objects.tagged(queryset=Post.objects.filter(pk=post1.pk)).order_by('pk').values_list('pk')), - list(Post.objects.filter(pk__in=(post1.pk, post2.pk)).order_by('pk').values_list('pk')) + list(Post.objects.tagged(queryset=Post.objects.filter(pk=post1.pk)).order_by("pk").values_list("pk")), + list(Post.objects.filter(pk__in=(post1.pk, post2.pk)).order_by("pk").values_list("pk")), ) def test_plugin_latest(self): - post1 = self._get_post(self._post_data[0]['en']) - self._get_post(self._post_data[1]['en']) - post1.tags.add('tag 1') + post1 = self._get_post(self._post_data[0]["en"]) + self._get_post(self._post_data[1]["en"]) + post1.tags.add("tag 1") post1.save() - request = self.get_page_request('/', AnonymousUser(), r'/en/blog/', edit=False) - request_auth = self.get_page_request('/', self.user_staff, r'/en/blog/', edit=False) - request_edit = self.get_page_request('/', self.user_staff, r'/en/blog/', edit=True) - plugin = add_plugin( - post1.content, 'BlogLatestEntriesPlugin', language='en', app_config=self.app_config_1 - ) - tag = Tag.objects.get(slug='tag-1') + request = self.get_page_request("/", AnonymousUser(), r"/en/blog/", edit=False) + request_auth = self.get_page_request("/", self.user_staff, r"/en/blog/", edit=False) + request_edit = self.get_page_request("/", self.user_staff, r"/en/blog/", edit=True) + plugin = add_plugin(post1.content, "BlogLatestEntriesPlugin", language="en", app_config=self.app_config_1) + tag = Tag.objects.get(slug="tag-1") plugin.tags.add(tag) # unauthenticated users get no post self.assertEqual(len(plugin.get_posts(request)), 0) @@ -1174,32 +1123,25 @@ def test_plugin_latest(self): class ModelsTest2(BaseTest): - def test_copy_plugin_latest(self): - post1 = self._get_post(self._post_data[0]['en']) - post2 = self._get_post(self._post_data[1]['en']) - tag1 = Tag.objects.create(name='tag 1') - tag2 = Tag.objects.create(name='tag 2') - plugin = add_plugin( - post1.content, 'BlogLatestEntriesPlugin', language='en', app_config=self.app_config_1 - ) + post1 = self._get_post(self._post_data[0]["en"]) + post2 = self._get_post(self._post_data[1]["en"]) + tag1 = Tag.objects.create(name="tag 1") + tag2 = Tag.objects.create(name="tag 2") + plugin = add_plugin(post1.content, "BlogLatestEntriesPlugin", language="en", app_config=self.app_config_1) plugin.tags.add(tag1) plugin.tags.add(tag2) - plugins = list(post1.content.cmsplugin_set.filter(language='en').order_by( - 'path', 'depth', 'position' - )) + plugins = list(post1.content.cmsplugin_set.filter(language="en").order_by("path", "depth", "position")) copy_plugins_to(plugins, post2.content) new = list(downcast_plugins(post2.content.cmsplugin_set.all())) - self.assertEqual(set(new[0].tags.all()), set([tag1, tag2])) + self.assertEqual(set(new[0].tags.all()), {tag1, tag2}) self.assertEqual(set(new[0].tags.all()), set(plugin.tags.all())) def test_plugin_author(self): - post1 = self._get_post(self._post_data[0]['en']) - post2 = self._get_post(self._post_data[1]['en']) - request = self.get_page_request('/', AnonymousUser(), r'/en/blog/', edit=False) - plugin = add_plugin( - post1.content, 'BlogAuthorPostsPlugin', language='en', app_config=self.app_config_1 - ) + post1 = self._get_post(self._post_data[0]["en"]) + post2 = self._get_post(self._post_data[1]["en"]) + request = self.get_page_request("/", AnonymousUser(), r"/en/blog/", edit=False) + plugin = add_plugin(post1.content, "BlogAuthorPostsPlugin", language="en", app_config=self.app_config_1) plugin.authors.add(self.user) self.assertEqual(len(plugin.get_posts(request)), 0) self.assertEqual(plugin.get_authors(request)[0].count, 0) @@ -1215,76 +1157,66 @@ def test_plugin_author(self): self.assertEqual(plugin.get_authors(request)[0].count, 2) def test_copy_plugin_author(self): - post1 = self._get_post(self._post_data[0]['en']) - post2 = self._get_post(self._post_data[1]['en']) - plugin = add_plugin( - post1.content, 'BlogAuthorPostsPlugin', language='en', app_config=self.app_config_1 - ) + post1 = self._get_post(self._post_data[0]["en"]) + post2 = self._get_post(self._post_data[1]["en"]) + plugin = add_plugin(post1.content, "BlogAuthorPostsPlugin", language="en", app_config=self.app_config_1) plugin.authors.add(self.user) - plugins = list(post1.content.cmsplugin_set.filter(language='en').order_by( - 'path', 'depth', 'position' - )) + plugins = list(post1.content.cmsplugin_set.filter(language="en").order_by("path", "depth", "position")) copy_plugins_to(plugins, post2.content) new = list(downcast_plugins(post2.content.cmsplugin_set.all())) - self.assertEqual(set(new[0].authors.all()), set([self.user])) + self.assertEqual(set(new[0].authors.all()), {self.user}) def test_multisite(self): - with override('en'): - post1 = self._get_post(self._post_data[0]['en'], sites=(self.site_1,)) - post2 = self._get_post(self._post_data[1]['en'], sites=(self.site_2,)) - post3 = self._get_post(self._post_data[2]['en'], sites=(self.site_2, self.site_1)) + with override("en"): + post1 = self._get_post(self._post_data[0]["en"], sites=(self.site_1,)) + post2 = self._get_post(self._post_data[1]["en"], sites=(self.site_2,)) + post3 = self._get_post(self._post_data[2]["en"], sites=(self.site_2, self.site_1)) self.assertEqual(len(Post.objects.all()), 3) - with self.settings(**{'SITE_ID': self.site_1.pk}): + with self.settings(**{"SITE_ID": self.site_1.pk}): self.assertEqual(len(Post.objects.all().on_site()), 2) - self.assertEqual(set(list(Post.objects.all().on_site())), set([post1, post3])) - with self.settings(**{'SITE_ID': self.site_2.pk}): + self.assertEqual(set(list(Post.objects.all().on_site())), {post1, post3}) + with self.settings(**{"SITE_ID": self.site_2.pk}): self.assertEqual(len(Post.objects.all().on_site()), 2) - self.assertEqual(set(list(Post.objects.all().on_site())), set([post2, post3])) + self.assertEqual(set(list(Post.objects.all().on_site())), {post2, post3}) def test_str_repr(self): self.get_pages() - post1 = self._get_post(self._post_data[0]['en']) - post1.meta_description = '' + post1 = self._get_post(self._post_data[0]["en"]) + post1.meta_description = "" post1.main_image = None post1.save() self.assertEqual(force_text(post1), post1.title) self.assertEqual(post1.get_description(), strip_tags(post1.abstract)) - self.assertEqual(post1.get_image_full_url(), '') + self.assertEqual(post1.get_image_full_url(), "") self.assertEqual(post1.get_author(), self.user) - self.assertEqual(force_text(post1.categories.first()), 'category 1') + self.assertEqual(force_text(post1.categories.first()), "category 1") - plugin = add_plugin( - post1.content, 'BlogAuthorPostsPlugin', language='en', app_config=self.app_config_1 - ) - self.assertEqual(force_text(plugin.__str__()), '5 latest articles by author') + plugin = add_plugin(post1.content, "BlogAuthorPostsPlugin", language="en", app_config=self.app_config_1) + self.assertEqual(force_text(plugin.__str__()), "5 latest articles by author") - plugin = add_plugin( - post1.content, 'BlogLatestEntriesPlugin', language='en', app_config=self.app_config_1 - ) - self.assertEqual(force_text(plugin.__str__()), '5 latest articles by tag') + plugin = add_plugin(post1.content, "BlogLatestEntriesPlugin", language="en", app_config=self.app_config_1) + self.assertEqual(force_text(plugin.__str__()), "5 latest articles by tag") - plugin = add_plugin( - post1.content, 'BlogArchivePlugin', language='en', app_config=self.app_config_1 - ) - self.assertEqual(force_text(plugin.__str__()), 'generic blog plugin') + plugin = add_plugin(post1.content, "BlogArchivePlugin", language="en", app_config=self.app_config_1) + self.assertEqual(force_text(plugin.__str__()), "generic blog plugin") no_translation_post = Post() - no_translation_default_title = 'Post (no translation)' + no_translation_default_title = "Post (no translation)" self.assertEqual(force_text(no_translation_post), no_translation_default_title) class KnockerTest(BaseTest): - @classmethod def setUpClass(cls): try: - import knocker - super(KnockerTest, cls).setUpClass() + import knocker # noqa + + super().setUpClass() except ImportError: - raise SkipTest('django-knocker not installed, skipping tests') + raise SkipTest("django-knocker not installed, skipping tests") def test_model_attributes(self): self.get_pages() @@ -1293,63 +1225,61 @@ def test_model_attributes(self): for language in posts[0].get_available_languages(): with smart_override(language): posts[0].set_current_language(language) - knock_create = posts[0].as_knock(signal_type='post_save', created=True) - self.assertEqual(knock_create['title'], - 'new {0}'.format(posts[0]._meta.verbose_name)) - self.assertEqual(knock_create['message'], posts[0].title) - self.assertEqual(knock_create['language'], language) + knock_create = posts[0].as_knock(signal_type="post_save", created=True) + self.assertEqual(knock_create["title"], "new {}".format(posts[0]._meta.verbose_name)) + self.assertEqual(knock_create["message"], posts[0].title) + self.assertEqual(knock_create["language"], language) for language in posts[0].get_available_languages(): with smart_override(language): posts[0].set_current_language(language) - knock_create = posts[0].as_knock(signal_type='post_save', created=False) - self.assertEqual(knock_create['title'], - 'new {0}'.format(posts[0]._meta.verbose_name)) - self.assertEqual(knock_create['message'], posts[0].title) - self.assertEqual(knock_create['language'], language) + knock_create = posts[0].as_knock(signal_type="post_save", created=False) + self.assertEqual(knock_create["title"], "new {}".format(posts[0]._meta.verbose_name)) + self.assertEqual(knock_create["message"], posts[0].title) + self.assertEqual(knock_create["language"], language) def test_should_knock(self): self.get_pages() post_data = { - 'author': self.user, - 'title': 'post 1', - 'abstract': 'post 1', - 'meta_description': 'post 1', - 'meta_keywords': 'post 1', - 'app_config': self.app_config_1 + "author": self.user, + "title": "post 1", + "abstract": "post 1", + "meta_description": "post 1", + "meta_keywords": "post 1", + "app_config": self.app_config_1, } post = Post.objects.create(**post_data) # Object is not published, no knock - self.assertFalse(post.should_knock(signal_type='post_save')) + self.assertFalse(post.should_knock(signal_type="post_save")) post.publish = True post.save() # Object is published, send knock - self.assertTrue(post.should_knock(signal_type='post_save')) + self.assertTrue(post.should_knock(signal_type="post_save")) # Knock disabled for updates self.app_config_1.app_data.config.send_knock_update = False self.app_config_1.save() - post.abstract = 'what' + post.abstract = "what" post.save() - self.assertFalse(post.should_knock(signal_type='post_save')) + self.assertFalse(post.should_knock(signal_type="post_save")) # Knock disabled for publishing self.app_config_1.app_data.config.send_knock_create = False self.app_config_1.save() post_data = { - 'author': self.user, - 'title': 'post 2', - 'abstract': 'post 2', - 'meta_description': 'post 2', - 'meta_keywords': 'post 2', - 'app_config': self.app_config_1 + "author": self.user, + "title": "post 2", + "abstract": "post 2", + "meta_description": "post 2", + "meta_keywords": "post 2", + "app_config": self.app_config_1, } post = Post.objects.create(**post_data) - self.assertFalse(post.should_knock(signal_type='post_save')) + self.assertFalse(post.should_knock(signal_type="post_save")) post.publish = True post.save() - self.assertFalse(post.should_knock(signal_type='post_save')) + self.assertFalse(post.should_knock(signal_type="post_save")) # Restore default values self.app_config_1.app_data.config.send_knock_create = True diff --git a/tests/test_plugins.py b/tests/test_plugins.py index 3070bd19..e6453067 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os.path import re @@ -19,114 +18,89 @@ class PluginTest(BaseTest): - def test_plugin_latest_cached(self): pages = self.get_pages() posts = self.get_posts() - posts[0].tags.add('tag 1') + posts[0].tags.add("tag 1") posts[0].publish = True posts[0].save() - ph = pages[0].placeholders.get(slot='content') + ph = pages[0].placeholders.get(slot="content") - plugin = add_plugin( - ph, 'BlogLatestEntriesPluginCached', language='en', app_config=self.app_config_1 - ) - rendered = self.render_plugin(pages[0], 'en', plugin, edit=True) + plugin = add_plugin(ph, "BlogLatestEntriesPluginCached", language="en", app_config=self.app_config_1) + rendered = self.render_plugin(pages[0], "en", plugin, edit=True) try: - self.assertTrue( - rendered.find('cms-plugin-djangocms_blog-post-abstract-%s' % posts[0].pk) > -1 - ) + self.assertTrue(rendered.find("cms-plugin-djangocms_blog-post-abstract-%s" % posts[0].pk) > -1) except AssertionError: - self.assertTrue( - rendered.find('cms_plugin-djangocms_blog-post-abstract-%s' % posts[0].pk) > -1 - ) - self.assertTrue(rendered.find('

first line

') > -1) + self.assertTrue(rendered.find("cms_plugin-djangocms_blog-post-abstract-%s" % posts[0].pk) > -1) + self.assertTrue(rendered.find("

first line

") > -1) self.assertTrue(rendered.find('
-1) self.assertTrue(rendered.find(posts[0].get_absolute_url()) > -1) - plugin_nocache = add_plugin( - ph, 'BlogLatestEntriesPlugin', language='en', app_config=self.app_config_1 - ) + plugin_nocache = add_plugin(ph, "BlogLatestEntriesPlugin", language="en", app_config=self.app_config_1) # FIXME: Investigate the correct number of queries expected here with self.assertNumQueries(17): - self.render_plugin(pages[0], 'en', plugin_nocache) + self.render_plugin(pages[0], "en", plugin_nocache) with self.assertNumQueries(17): - self.render_plugin(pages[0], 'en', plugin) + self.render_plugin(pages[0], "en", plugin) with self.assertNumQueries(17): - rendered = self.render_plugin(pages[0], 'en', plugin) + rendered = self.render_plugin(pages[0], "en", plugin) - self.assertTrue(rendered.find('

first line

') > -1) + self.assertTrue(rendered.find("

first line

") > -1) self.assertTrue(rendered.find('
-1) self.assertTrue(rendered.find(posts[0].get_absolute_url()) > -1) def test_plugin_latest(self): pages = self.get_pages() posts = self.get_posts() - posts[0].tags.add('tag 1') + posts[0].tags.add("tag 1") posts[0].publish = True posts[0].save() - ph = pages[0].placeholders.get(slot='content') + ph = pages[0].placeholders.get(slot="content") - plugin = add_plugin( - ph, 'BlogLatestEntriesPlugin', language='en', app_config=self.app_config_1 - ) - tag = Tag.objects.get(slug='tag-1') + plugin = add_plugin(ph, "BlogLatestEntriesPlugin", language="en", app_config=self.app_config_1) + tag = Tag.objects.get(slug="tag-1") plugin.tags.add(tag) - rendered = self.render_plugin(pages[0], 'en', plugin, edit=True) + rendered = self.render_plugin(pages[0], "en", plugin, edit=True) try: - self.assertTrue( - rendered.find('cms-plugin-djangocms_blog-post-abstract-%s' % posts[0].pk) > -1 - ) + self.assertTrue(rendered.find("cms-plugin-djangocms_blog-post-abstract-%s" % posts[0].pk) > -1) except AssertionError: - self.assertTrue( - rendered.find('cms_plugin-djangocms_blog-post-abstract-%s' % posts[0].pk) > -1 - ) - self.assertTrue( - rendered.find(reverse('djangocms_blog:posts-tagged', kwargs={'tag': tag.slug})) > -1 - ) - self.assertTrue(rendered.find('

first line

') > -1) + self.assertTrue(rendered.find("cms_plugin-djangocms_blog-post-abstract-%s" % posts[0].pk) > -1) + self.assertTrue(rendered.find(reverse("djangocms_blog:posts-tagged", kwargs={"tag": tag.slug})) > -1) + self.assertTrue(rendered.find("

first line

") > -1) self.assertTrue(rendered.find('
-1) self.assertTrue(rendered.find(posts[0].get_absolute_url()) > -1) - category_2 = BlogCategory.objects.create(name='category 2', app_config=self.app_config_1) - category_2.set_current_language('it', initialize=True) - category_2.name = 'categoria 2' + category_2 = BlogCategory.objects.create(name="category 2", app_config=self.app_config_1) + category_2.set_current_language("it", initialize=True) + category_2.name = "categoria 2" category_2.save() - category_2.set_current_language('en') + category_2.set_current_language("en") posts[1].categories.add(category_2) - plugin = add_plugin( - ph, 'BlogLatestEntriesPlugin', language='en', app_config=self.app_config_1 - ) + plugin = add_plugin(ph, "BlogLatestEntriesPlugin", language="en", app_config=self.app_config_1) plugin.categories.add(category_2) - rendered = self.render_plugin(pages[0], 'en', plugin, edit=True) + rendered = self.render_plugin(pages[0], "en", plugin, edit=True) try: - self.assertTrue( - rendered.find('cms-plugin-djangocms_blog-post-abstract-%s' % posts[1].pk) > -1 - ) + self.assertTrue(rendered.find("cms-plugin-djangocms_blog-post-abstract-%s" % posts[1].pk) > -1) except AssertionError: - self.assertTrue( - rendered.find('cms_plugin-djangocms_blog-post-abstract-%s' % posts[1].pk) > -1 - ) + self.assertTrue(rendered.find("cms_plugin-djangocms_blog-post-abstract-%s" % posts[1].pk) > -1) self.assertTrue( - rendered.find( - reverse('djangocms_blog:posts-category', kwargs={'category': category_2.slug}) - ) > -1 + rendered.find(reverse("djangocms_blog:posts-category", kwargs={"category": category_2.slug})) > -1 ) - self.assertTrue(rendered.find('

second post first line

') > -1) + self.assertTrue(rendered.find("

second post first line

") > -1) self.assertTrue(rendered.find('
-1) self.assertTrue(rendered.find(posts[1].get_absolute_url()) > -1) # Checking copy relations - ph = pages[0].placeholders.get(slot='content') - original = ph.get_plugins('en') - pages[0].publish('en') + ph = pages[0].placeholders.get(slot="content") + original = ph.get_plugins("en") + pages[0].publish("en") published = pages[0].get_public_object() - ph = published.placeholders.get(slot='content') - new = ph.get_plugins('en') + ph = published.placeholders.get(slot="content") + new = ph.get_plugins("en") self.assertNotEqual(original, new) casted_tags, __ = new[0].get_plugin_instance() @@ -139,15 +113,15 @@ def test_plugin_latest(self): self.assertEqual(casted_categories.categories.count(), 1) posts[1].sites.add(self.site_2) - rendered = self.render_plugin(pages[0], 'en', plugin, edit=True) - self.assertFalse(rendered.find('

second post first line

') > -1) + rendered = self.render_plugin(pages[0], "en", plugin, edit=True) + self.assertFalse(rendered.find("

second post first line

") > -1) posts[1].sites.remove(self.site_2) - rendered = self.render_plugin(pages[0], 'en', plugin, edit=True) - self.assertTrue(rendered.find('

second post first line

') > -1) + rendered = self.render_plugin(pages[0], "en", plugin, edit=True) + self.assertTrue(rendered.find("

second post first line

") > -1) - plugin = add_plugin(ph, 'BlogLatestEntriesPlugin', language='en') - rendered = self.render_plugin(pages[0], 'en', plugin, edit=False) + plugin = add_plugin(ph, "BlogLatestEntriesPlugin", language="en") + rendered = self.render_plugin(pages[0], "en", plugin, edit=False) # data is picked from both apphook configs self.assertTrue(rendered.find('
-1) self.assertTrue(rendered.find('
-1) @@ -155,23 +129,21 @@ def test_plugin_latest(self): def test_plugin_tags(self): pages = self.get_pages() posts = self.get_posts() - posts[0].tags.add('tag 1', 'tag 2', 'test tag') + posts[0].tags.add("tag 1", "tag 2", "test tag") posts[0].publish = True posts[0].save() - posts[1].tags.add('test tag', 'another tag') + posts[1].tags.add("test tag", "another tag") posts[1].publish = True posts[1].save() - ph = pages[0].placeholders.get(slot='content') - plugin = add_plugin(ph, 'BlogTagsPlugin', language='en', app_config=self.app_config_1) - rendered = self.render_plugin(pages[0], 'en', plugin, edit=True) + ph = pages[0].placeholders.get(slot="content") + plugin = add_plugin(ph, "BlogTagsPlugin", language="en", app_config=self.app_config_1) + rendered = self.render_plugin(pages[0], "en", plugin, edit=True) for tag in Tag.objects.all(): - self.assertTrue(rendered.find( - reverse('djangocms_blog:posts-tagged', kwargs={'tag': tag.slug}) - ) > -1) - if tag.slug == 'test-tag': - rf = '\s+%s\s+\(\s+%s articles' % (tag.name, 2) + self.assertTrue(rendered.find(reverse("djangocms_blog:posts-tagged", kwargs={"tag": tag.slug})) > -1) + if tag.slug == "test-tag": + rf = r"\s+{}\s+\(\s+{} articles".format(tag.name, 2) else: - rf = '\s+%s\s+\(\s+%s article' % (tag.name, 1) + rf = r"\s+{}\s+\(\s+{} article".format(tag.name, 1) rx = re.compile(rf) self.assertEqual(len(rx.findall(rendered)), 1) @@ -182,24 +154,28 @@ def test_blog_archive_plugin(self): posts[0].save() posts[1].publish = True posts[1].save() - ph = pages[0].placeholders.get(slot='content') - plugin = add_plugin(ph, 'BlogArchivePlugin', language='en', app_config=self.app_config_1) + ph = pages[0].placeholders.get(slot="content") + plugin = add_plugin(ph, "BlogArchivePlugin", language="en", app_config=self.app_config_1) plugin_class = plugin.get_plugin_class_instance() - context = self.get_plugin_context(pages[0], 'en', plugin, edit=True) + context = self.get_plugin_context(pages[0], "en", plugin, edit=True) context = plugin_class.render(context, plugin, ph) - self.assertEqual(context['dates'][0]['date'].date(), now().replace(year=now().year, month=now().month, day=1).date()) - self.assertEqual(context['dates'][0]['count'], 2) + self.assertEqual( + context["dates"][0]["date"].date(), now().replace(year=now().year, month=now().month, day=1).date() + ) + self.assertEqual(context["dates"][0]["count"], 2) posts[1].publish = False posts[1].save() context = plugin_class.render(context, plugin, ph) - self.assertEqual(context['dates'][0]['date'].date(), now().replace(year=now().year, month=now().month, day=1).date()) - self.assertEqual(context['dates'][0]['count'], 1) + self.assertEqual( + context["dates"][0]["date"].date(), now().replace(year=now().year, month=now().month, day=1).date() + ) + self.assertEqual(context["dates"][0]["count"], 1) def test_templates(self): def _test_custom_templates_path(parts): - templates_path = os.path.join(os.path.dirname(__file__), 'test_utils', 'templates') + templates_path = os.path.join(os.path.dirname(__file__), "test_utils", "templates") self.app_config_1.app_data.config.template_prefix = parts[0] self.app_config_1.save() @@ -207,47 +183,41 @@ def _test_custom_templates_path(parts): plugin.template_folder = parts[1] plugin.save() dir_parts = (templates_path,) + parts - template_parts = parts + (plugin_class.base_render_template, ) + template_parts = parts + (plugin_class.base_render_template,) try: os.makedirs(os.path.join(*dir_parts)) except OSError: pass fake_template = os.path.join(*template_parts) - with open(os.path.join(templates_path, fake_template), 'w'): - self.assertEqual( - plugin_class.get_render_template(context, plugin, ph), - fake_template - ) + with open(os.path.join(templates_path, fake_template), "w"): + self.assertEqual(plugin_class.get_render_template(context, plugin, ph), fake_template) plugin.template_folder = tmp plugin.save() - self.app_config_1.app_data.config.template_prefix = '' + self.app_config_1.app_data.config.template_prefix = "" self.app_config_1.save() os.unlink(os.path.join(templates_path, fake_template)) - posts = self.get_posts() + self.get_posts() pages = self.get_pages() - ph = pages[0].placeholders.get(slot='content') - plugin = add_plugin( - ph, 'BlogLatestEntriesPlugin', language='en', app_config=self.app_config_1 - ) + ph = pages[0].placeholders.get(slot="content") + plugin = add_plugin(ph, "BlogLatestEntriesPlugin", language="en", app_config=self.app_config_1) - context = self.get_plugin_context(pages[0], 'en', plugin) + context = self.get_plugin_context(pages[0], "en", plugin) plugin_class = plugin.get_plugin_class_instance() self.assertEqual( plugin_class.get_render_template(context, plugin, ph), - os.path.join('djangocms_blog', plugin.template_folder, plugin_class.base_render_template) + os.path.join("djangocms_blog", plugin.template_folder, plugin_class.base_render_template), ) - custom_parts = ('whatever', 'whereever') + custom_parts = ("whatever", "whereever") _test_custom_templates_path(custom_parts) - custom_parts = ('djangocms_blog', 'whereever') + custom_parts = ("djangocms_blog", "whereever") _test_custom_templates_path(custom_parts) class PluginTest10(BaseTest): - def test_plugin_authors(self): pages = self.get_pages() posts = self.get_posts() @@ -255,43 +225,43 @@ def test_plugin_authors(self): posts[0].save() posts[1].publish = True posts[1].save() - ph = pages[0].placeholders.get(slot='content') - plugin = add_plugin(ph, 'BlogAuthorPostsPlugin', language='en', app_config=self.app_config_1) + ph = pages[0].placeholders.get(slot="content") + plugin = add_plugin(ph, "BlogAuthorPostsPlugin", language="en", app_config=self.app_config_1) - rendered = self.render_plugin(pages[0], 'en', plugin, edit=True) - self.assertTrue(rendered.find('No author found') > -1) + rendered = self.render_plugin(pages[0], "en", plugin, edit=True) + self.assertTrue(rendered.find("No author found") > -1) plugin.authors.add(self.user) - rendered = self.render_plugin(pages[0], 'en', plugin, edit=True) - self.assertTrue(rendered.find('/en/blog/author/admin/') > -1) - self.assertTrue(rendered.find('2 articles') > -1) + rendered = self.render_plugin(pages[0], "en", plugin, edit=True) + self.assertTrue(rendered.find("/en/blog/author/admin/") > -1) + self.assertTrue(rendered.find("2 articles") > -1) plugin.authors.add(self.user_staff) - rendered = self.render_plugin(pages[0], 'en', plugin, edit=True) - self.assertTrue(rendered.find('/en/blog/author/staff/') > -1) - self.assertTrue(rendered.find('0 articles') > -1) + rendered = self.render_plugin(pages[0], "en", plugin, edit=True) + self.assertTrue(rendered.find("/en/blog/author/staff/") > -1) + self.assertTrue(rendered.find("0 articles") > -1) plugin.authors.add(self.user_normal) - rendered = self.render_plugin(pages[0], 'en', plugin, edit=True) - self.assertTrue(rendered.find('/en/blog/author/normal/') > -1) - self.assertTrue(rendered.find('0 articles') > -1) + rendered = self.render_plugin(pages[0], "en", plugin, edit=True) + self.assertTrue(rendered.find("/en/blog/author/normal/") > -1) + self.assertTrue(rendered.find("0 articles") > -1) # Checking copy relations - ph = pages[0].placeholders.get(slot='content') - original = ph.get_plugins('en') - pages[0].publish('en') + ph = pages[0].placeholders.get(slot="content") + original = ph.get_plugins("en") + pages[0].publish("en") published = pages[0].get_public_object() - ph = published.placeholders.get(slot='content') - new = ph.get_plugins('en') + ph = published.placeholders.get(slot="content") + new = ph.get_plugins("en") self.assertNotEqual(original, new) casted_authors, __ = new[0].get_plugin_instance() self.assertEqual(casted_authors.authors.count(), 3) def test_plugin_authors_admin(self): - other_author = User.objects.create(username='other_author') - non_author = User.objects.create(username='non_author') - unpublished_author = User.objects.create(username='unpublished_author') + other_author = User.objects.create(username="other_author") + non_author = User.objects.create(username="non_author") + unpublished_author = User.objects.create(username="unpublished_author") pages = self.get_pages() posts = self.get_posts() posts[0].publish = True @@ -302,18 +272,18 @@ def test_plugin_authors_admin(self): posts[2].publish = False posts[2].author = unpublished_author posts[2].save() - ph = pages[0].placeholders.get(slot='content') + ph = pages[0].placeholders.get(slot="content") page_admin = admin.site._registry[Page] parms = { - 'cms_path': '/en/', - 'placeholder_id': ph.pk, - 'plugin_type': 'BlogAuthorPostsPlugin', - 'plugin_language': 'en' + "cms_path": "/en/", + "placeholder_id": ph.pk, + "plugin_type": "BlogAuthorPostsPlugin", + "plugin_language": "en", } - path = '/en/?%s' % urlencode(parms) - request = self.get_request(pages[0], 'en', user=self.user, path=path) + path = "/en/?%s" % urlencode(parms) + request = self.get_request(pages[0], "en", user=self.user, path=path) response = page_admin.add_plugin(request) - form_authors = response.context_data['adminform'].form.fields['authors'].queryset + form_authors = response.context_data["adminform"].form.fields["authors"].queryset self.assertEqual(form_authors.count(), 2) self.assertIn(other_author, form_authors) self.assertIn(self.user, form_authors) @@ -322,57 +292,50 @@ def test_plugin_authors_admin(self): class PluginTest2(BaseTest): - def test_blog_category_plugin(self): pages = self.get_pages() posts = self.get_posts() - self.category_1.set_current_language('en') + self.category_1.set_current_language("en") posts[0].publish = True posts[0].save() posts[1].publish = True posts[1].save() posts[1].sites.add(self.site_2) - new_category = BlogCategory.objects.create( - name='category 2', app_config=self.app_config_1 - ) + new_category = BlogCategory.objects.create(name="category 2", app_config=self.app_config_1) posts[1].categories.add(new_category) - ph = pages[0].placeholders.get(slot='content') - plugin = add_plugin( - ph, 'BlogCategoryPlugin', language='en', app_config=self.app_config_1 - ) + ph = pages[0].placeholders.get(slot="content") + plugin = add_plugin(ph, "BlogCategoryPlugin", language="en", app_config=self.app_config_1) plugin_class = plugin.get_plugin_class_instance() - context = self.get_plugin_context(pages[0], 'en', plugin, edit=True) + context = self.get_plugin_context(pages[0], "en", plugin, edit=True) context = plugin_class.render(context, plugin, ph) - self.assertTrue(context['categories']) - self.assertEqual(list(context['categories']), [self.category_1]) + self.assertTrue(context["categories"]) + self.assertEqual(list(context["categories"]), [self.category_1]) plugin.current_site = False plugin.save() context = plugin_class.render(context, plugin, ph) - self.assertEqual(list(context['categories']), [self.category_1, new_category]) + self.assertEqual(list(context["categories"]), [self.category_1, new_category]) plugin.current_site = True plugin.save() with self.settings(SITE_ID=2): context = plugin_class.render(context, plugin, ph) - self.assertEqual(list(context['categories']), [self.category_1, new_category]) + self.assertEqual(list(context["categories"]), [self.category_1, new_category]) plugin.current_site = False plugin.save() with self.settings(SITE_ID=2): context = plugin_class.render(context, plugin, ph) - self.assertEqual(list(context['categories']), [self.category_1, new_category]) + self.assertEqual(list(context["categories"]), [self.category_1, new_category]) - empty_category = BlogCategory.objects.create( - name='empty 2', app_config=self.app_config_1 - ) + empty_category = BlogCategory.objects.create(name="empty 2", app_config=self.app_config_1) self.app_config_1.app_data.config.menu_empty_categories = False self.app_config_1.save() context = plugin_class.render(context, plugin, ph) - self.assertEqual(list(context['categories']), [self.category_1, new_category]) + self.assertEqual(list(context["categories"]), [self.category_1, new_category]) self.app_config_1.app_data.config.menu_empty_categories = True self.app_config_1.save() context = plugin_class.render(context, plugin, ph) - self.assertEqual(list(context['categories']), [self.category_1, new_category, empty_category]) + self.assertEqual(list(context["categories"]), [self.category_1, new_category, empty_category]) diff --git a/tests/test_setup.py b/tests/test_setup.py index f5c2584b..06399477 100644 --- a/tests/test_setup.py +++ b/tests/test_setup.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import sys from cms.api import create_page, create_title @@ -18,20 +17,19 @@ @override_settings(BLOG_AUTO_SETUP=True) class SetupTest(BaseTest): - @classmethod def setUpClass(cls): # Skipping initialization to start with clean database super(BaseTest, cls).setUpClass() def setUp(self): - super(SetupTest, self).setUp() + super().setUp() from cms.apphook_pool import apphook_pool delete = [ - 'djangocms_blog', - 'djangocms_blog.cms_app', - 'djangocms_blog.cms_apps', + "djangocms_blog", + "djangocms_blog.cms_app", + "djangocms_blog.cms_apps", ] for module in delete: if module in sys.modules: @@ -57,7 +55,7 @@ def test_setup_filled(self): # Tests starts with no page and no config self.assertFalse(Page.objects.exists()) self.assertFalse(BlogConfig.objects.exists()) - set_home = hasattr(Page, 'set_as_homepage') + set_home = hasattr(Page, "set_as_homepage") langs = get_language_list() home = None @@ -65,15 +63,12 @@ def test_setup_filled(self): with override(lang): if not home: home = create_page( - 'a new home', language=lang, - template='blog.html', in_navigation=True, published=True + "a new home", language=lang, template="blog.html", in_navigation=True, published=True ) if set_home: home.set_as_homepage() else: - create_title( - language=lang, title='a new home', page=home - ) + create_title(language=lang, title="a new home", page=home) home.publish(lang) # importing cms_app triggers the auto setup @@ -85,4 +80,4 @@ def test_setup_filled(self): home = Page.objects.get_home() for lang in langs: - self.assertEqual(home.get_title(lang), 'a new home') + self.assertEqual(home.get_title(lang), "a new home") diff --git a/tests/test_toolbar.py b/tests/test_toolbar.py index c2406160..bb02b21b 100644 --- a/tests/test_toolbar.py +++ b/tests/test_toolbar.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from cms.toolbar.items import ButtonList, ModalItem from django.urls import reverse from django.utils.encoding import force_text @@ -9,15 +8,15 @@ class ToolbarTest(BaseTest): - def test_toolbar_with_items(self): """ Test that Blog toolbar is present and contains all items """ from cms.toolbar.toolbar import CMSToolbar + posts = self.get_posts() pages = self.get_pages() - request = self.get_page_request(pages[0], self.user, r'/en/blog/', edit=True) + request = self.get_page_request(pages[0], self.user, r"/en/blog/", edit=True) setattr(request, BLOG_CURRENT_POST_IDENTIFIER, posts[0]) posts[0].publish = False @@ -26,15 +25,18 @@ def test_toolbar_with_items(self): toolbar.populate() toolbar.post_template_populate() toolbar.get_left_items() - blog_menu = toolbar.menus['djangocms_blog'] - self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse('admin:djangocms_blog_post_changelist'))), 1) - self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse('admin:djangocms_blog_post_add'))), 1) - self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse('admin:djangocms_blog_post_change', args=(posts[0].pk,)))), 1) + blog_menu = toolbar.menus["djangocms_blog"] + self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse("admin:djangocms_blog_post_changelist"))), 1) + self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse("admin:djangocms_blog_post_add"))), 1) + self.assertEqual( + len(blog_menu.find_items(ModalItem, url=reverse("admin:djangocms_blog_post_change", args=(posts[0].pk,)))), + 1, + ) # Publish button only appears if current post is unpublished right = toolbar.get_right_items() buttons = sum([item.buttons for item in right if isinstance(item, ButtonList)], []) - self.assertTrue([button for button in buttons if force_text(button.name) == 'Publish Blog now']) + self.assertTrue([button for button in buttons if force_text(button.name) == "Publish Blog now"]) # Publish button does not appears if current post is published posts[0].publish = True @@ -44,7 +46,7 @@ def test_toolbar_with_items(self): toolbar.post_template_populate() right = toolbar.get_right_items() buttons = sum([item.buttons for item in right if isinstance(item, ButtonList)], []) - self.assertFalse([button for button in buttons if force_text(button.name) == 'Publish Blog now']) + self.assertFalse([button for button in buttons if force_text(button.name) == "Publish Blog now"]) # Publish button does not appears if other posts but the current one are unpublished posts[1].publish = True @@ -54,4 +56,4 @@ def test_toolbar_with_items(self): toolbar.post_template_populate() right = toolbar.get_right_items() buttons = sum([item.buttons for item in right if isinstance(item, ButtonList)], []) - self.assertFalse([button for button in buttons if force_text(button.name) == 'Publish Blog now']) + self.assertFalse([button for button in buttons if force_text(button.name) == "Publish Blog now"]) diff --git a/tests/test_utils/__init__.py b/tests/test_utils/__init__.py index 40a96afc..e69de29b 100644 --- a/tests/test_utils/__init__.py +++ b/tests/test_utils/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/tests/test_utils/admin.py b/tests/test_utils/admin.py index a48bd820..5b4dabfe 100644 --- a/tests/test_utils/admin.py +++ b/tests/test_utils/admin.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.contrib import admin from django.contrib.auth.admin import UserAdmin from django.utils.translation import ugettext_lazy as _ @@ -10,12 +9,12 @@ class CustomUserAdmin(UserAdmin): model = CustomUser fieldsets = ( - (None, {'fields': ('username', 'password')}), - (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}), - (_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser', - 'groups', 'user_permissions')}), - (_('Important dates'), {'fields': ('last_login', 'date_joined')}), - (_('Sites'), {'fields': ('sites',)}) + (None, {"fields": ("username", "password")}), + (_("Personal info"), {"fields": ("first_name", "last_name", "email")}), + (_("Permissions"), {"fields": ("is_active", "is_staff", "is_superuser", "groups", "user_permissions")}), + (_("Important dates"), {"fields": ("last_login", "date_joined")}), + (_("Sites"), {"fields": ("sites",)}), ) + admin.site.register(CustomUser, CustomUserAdmin) diff --git a/tests/test_utils/blog_urls.py b/tests/test_utils/blog_urls.py index ae34c449..586bc9c5 100644 --- a/tests/test_utils/blog_urls.py +++ b/tests/test_utils/blog_urls.py @@ -1,43 +1,35 @@ -# -*- coding: utf-8 -*- from django.conf.urls import url from djangocms_blog.feeds import FBInstantArticles, LatestEntriesFeed, TagFeed from djangocms_blog.settings import get_setting from djangocms_blog.views import ( - AuthorEntriesView, CategoryEntriesView, PostArchiveView, PostDetailView, PostListView, + AuthorEntriesView, + CategoryEntriesView, + PostArchiveView, + PostDetailView, + PostListView, TaggedListView, ) def get_urls(): - urls = get_setting('PERMALINK_URLS') + urls = get_setting("PERMALINK_URLS") details = [] for urlconf in urls.values(): - details.append( - url(urlconf, PostDetailView.as_view(), name='post-detail'), - ) + details.append(url(urlconf, PostDetailView.as_view(), name="post-detail"),) return details detail_urls = get_urls() urlpatterns = [ - url(r'^latests/$', - PostListView.as_view(), name='posts-latest'), - url(r'^feed/$', - LatestEntriesFeed(), name='posts-latest-feed'), - url(r'^feed/fb/$', - FBInstantArticles(), name='posts-latest-feed-fb'), - url(r'^(?P\d{4})/$', - PostArchiveView.as_view(), name='posts-archive'), - url(r'^(?P\d{4})/(?P\d{1,2})/$', - PostArchiveView.as_view(), name='posts-archive'), - url(r'^author/(?P[\w\.@+-]+)/$', - AuthorEntriesView.as_view(), name='posts-author'), - url(r'^category/(?P[\w\.@+-]+)/$', - CategoryEntriesView.as_view(), name='posts-category'), - url(r'^tag/(?P[-\w]+)/$', - TaggedListView.as_view(), name='posts-tagged'), - url(r'^tag/(?P[-\w]+)/feed/$', - TagFeed(), name='posts-tagged-feed'), + url(r"^latests/$", PostListView.as_view(), name="posts-latest"), + url(r"^feed/$", LatestEntriesFeed(), name="posts-latest-feed"), + url(r"^feed/fb/$", FBInstantArticles(), name="posts-latest-feed-fb"), + url(r"^(?P\d{4})/$", PostArchiveView.as_view(), name="posts-archive"), + url(r"^(?P\d{4})/(?P\d{1,2})/$", PostArchiveView.as_view(), name="posts-archive"), + url(r"^author/(?P[\w\.@+-]+)/$", AuthorEntriesView.as_view(), name="posts-author"), + url(r"^category/(?P[\w\.@+-]+)/$", CategoryEntriesView.as_view(), name="posts-category"), + url(r"^tag/(?P[-\w]+)/$", TaggedListView.as_view(), name="posts-tagged"), + url(r"^tag/(?P[-\w]+)/feed/$", TagFeed(), name="posts-tagged-feed"), ] + detail_urls diff --git a/tests/test_utils/migrations/0001_initial.py b/tests/test_utils/migrations/0001_initial.py index 8eb5613b..32672610 100644 --- a/tests/test_utils/migrations/0001_initial.py +++ b/tests/test_utils/migrations/0001_initial.py @@ -1,43 +1,93 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models +import django.contrib.auth.models import django.core.validators import django.utils.timezone -import django.contrib.auth.models +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('auth', '__first__'), - ('sites', '__first__'), + ("auth", "__first__"), + ("sites", "__first__"), ] operations = [ migrations.CreateModel( - name='CustomUser', + name="CustomUser", fields=[ - ('id', models.AutoField(serialize=False, auto_created=True, primary_key=True, verbose_name='ID')), - ('password', models.CharField(verbose_name='password', max_length=128)), - ('last_login', models.DateTimeField(verbose_name='last login', null=True, blank=True)), - ('is_superuser', models.BooleanField(verbose_name='superuser status', help_text='Designates that this user has all permissions without explicitly assigning them.', default=False)), - ('username', models.CharField(help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', unique=True, verbose_name='username', validators=[django.core.validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.', 'invalid')], max_length=30, error_messages={'unique': 'A user with that username already exists.'})), - ('first_name', models.CharField(verbose_name='first name', max_length=30, blank=True)), - ('last_name', models.CharField(verbose_name='last name', max_length=30, blank=True)), - ('email', models.EmailField(verbose_name='email address', max_length=254, blank=True)), - ('is_staff', models.BooleanField(verbose_name='staff status', help_text='Designates whether the user can log into this admin site.', default=False)), - ('is_active', models.BooleanField(verbose_name='active', help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', default=True)), - ('date_joined', models.DateTimeField(verbose_name='date joined', default=django.utils.timezone.now)), - ('groups', models.ManyToManyField(help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_query_name='user', related_name='user_set', verbose_name='groups', blank=True, to='auth.Group')), - ('sites', models.ManyToManyField(to='sites.Site')), - ('user_permissions', models.ManyToManyField(help_text='Specific permissions for this user.', related_query_name='user', related_name='user_set', verbose_name='user permissions', blank=True, to='auth.Permission')), + ("id", models.AutoField(serialize=False, auto_created=True, primary_key=True, verbose_name="ID")), + ("password", models.CharField(verbose_name="password", max_length=128)), + ("last_login", models.DateTimeField(verbose_name="last login", null=True, blank=True)), + ( + "is_superuser", + models.BooleanField( + verbose_name="superuser status", + help_text="Designates that this user has all permissions without explicitly assigning them.", + default=False, + ), + ), + ( + "username", + models.CharField( + help_text="Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.", + unique=True, + verbose_name="username", + validators=[ + django.core.validators.RegexValidator( + "^[\\w.@+-]+$", + "Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.", + "invalid", + ) + ], + max_length=30, + error_messages={"unique": "A user with that username already exists."}, + ), + ), + ("first_name", models.CharField(verbose_name="first name", max_length=30, blank=True)), + ("last_name", models.CharField(verbose_name="last name", max_length=30, blank=True)), + ("email", models.EmailField(verbose_name="email address", max_length=254, blank=True)), + ( + "is_staff", + models.BooleanField( + verbose_name="staff status", + help_text="Designates whether the user can log into this admin site.", + default=False, + ), + ), + ( + "is_active", + models.BooleanField( + verbose_name="active", + help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.", + default=True, + ), + ), + ("date_joined", models.DateTimeField(verbose_name="date joined", default=django.utils.timezone.now)), + ( + "groups", + models.ManyToManyField( + help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.", + related_query_name="user", + related_name="user_set", + verbose_name="groups", + blank=True, + to="auth.Group", + ), + ), + ("sites", models.ManyToManyField(to="sites.Site")), + ( + "user_permissions", + models.ManyToManyField( + help_text="Specific permissions for this user.", + related_query_name="user", + related_name="user_set", + verbose_name="user permissions", + blank=True, + to="auth.Permission", + ), + ), ], - options={ - 'verbose_name': 'user', - 'abstract': False, - 'verbose_name_plural': 'users', - }, + options={"verbose_name": "user", "abstract": False, "verbose_name_plural": "users",}, bases=(models.Model,), ), ] diff --git a/tests/test_utils/models.py b/tests/test_utils/models.py index dbc63c0d..a4b78108 100644 --- a/tests/test_utils/models.py +++ b/tests/test_utils/models.py @@ -1,10 +1,9 @@ -# -*- coding: utf-8 -*- from django.contrib.auth.models import AbstractUser from django.db import models class CustomUser(AbstractUser): - sites = models.ManyToManyField('sites.Site') + sites = models.ManyToManyField("sites.Site") def get_sites(self): return self.sites diff --git a/tests/test_utils/routing.py b/tests/test_utils/routing.py index fe6c116b..d0d96119 100644 --- a/tests/test_utils/routing.py +++ b/tests/test_utils/routing.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - from channels.auth import AuthMiddlewareStack from channels.routing import ProtocolTypeRouter, URLRouter from django.urls import path @@ -7,11 +5,10 @@ from djangocms_blog.liveblog.routing import channel_routing as djangocms_blog_routing -application = ProtocolTypeRouter({ - 'websocket': AuthMiddlewareStack( - URLRouter([ - path('knocker/', knocker_routing), - path('liveblog/', djangocms_blog_routing), - ]) - ), -}) +application = ProtocolTypeRouter( + { + "websocket": AuthMiddlewareStack( + URLRouter([path("knocker/", knocker_routing), path("liveblog/", djangocms_blog_routing)]) + ), + } +) diff --git a/tests/test_utils/urls.py b/tests/test_utils/urls.py index f7e08ce4..0303589e 100644 --- a/tests/test_utils/urls.py +++ b/tests/test_utils/urls.py @@ -1,14 +1,13 @@ -# -*- coding: utf-8 -*- import sys from cms.sitemaps import CMSSitemap -from cms.utils.conf import get_cms_setting from django.conf import settings -from django.conf.urls import include, url +from django.conf.urls import include from django.conf.urls.i18n import i18n_patterns from django.contrib import admin from django.contrib.sitemaps.views import sitemap from django.contrib.staticfiles.urls import staticfiles_urlpatterns +from django.urls import path from django.views.i18n import JavaScriptCatalog from django.views.static import serve @@ -17,27 +16,14 @@ admin.autodiscover() urlpatterns = [ - url(r'^media/(?P.*)$', serve, - {'document_root': settings.MEDIA_ROOT, 'show_indexes': True}), - url(r'^media/cms/(?P.*)$', serve, - {'document_root': get_cms_setting('MEDIA_ROOT'), 'show_indexes': True}), - url(r'^jsi18n/$', JavaScriptCatalog.as_view(), name='javascript-catalog'), - url(r'^taggit_autosuggest/', include('taggit_autosuggest.urls')), - url(r'^sitemap\.xml$', sitemap, - { - 'sitemaps': { - 'cmspages': CMSSitemap, 'blog': BlogSitemap, - } - }), + path("media/", serve, {"document_root": settings.MEDIA_ROOT, "show_indexes": True}), + path("jsi18n/", JavaScriptCatalog.as_view(), name="javascript-catalog"), + path("taggit_autosuggest/", include("taggit_autosuggest.urls")), + path("itemap.xml", sitemap, {"sitemaps": {"cmspages": CMSSitemap, "blog": BlogSitemap}}), ] urlpatterns += staticfiles_urlpatterns() -if 'server' not in sys.argv: - urlpatterns += i18n_patterns( - url(r'^blog/', include('djangocms_blog.urls')), - ) -urlpatterns += i18n_patterns( - url(r'^admin/', admin.site.urls), - url(r'^', include('cms.urls')), -) +if "server" not in sys.argv: + urlpatterns += i18n_patterns(path("blog/", include("djangocms_blog.urls")),) +urlpatterns += i18n_patterns(path("admin/", admin.site.urls), path("", include("cms.urls")),) diff --git a/tests/test_views.py b/tests/test_views.py index 77ef3aa4..660260c7 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os.path from aldryn_apphooks_config.utils import get_app_instance @@ -21,7 +20,11 @@ from djangocms_blog.settings import get_setting from djangocms_blog.sitemaps import BlogSitemap from djangocms_blog.views import ( - AuthorEntriesView, CategoryEntriesView, PostArchiveView, PostDetailView, PostListView, + AuthorEntriesView, + CategoryEntriesView, + PostArchiveView, + PostDetailView, + PostListView, TaggedListView, ) @@ -29,30 +32,28 @@ class CustomUrlViewTest(BaseTest): - - @override_settings(BLOG_URLCONF='tests.test_utils.blog_urls') + @override_settings(BLOG_URLCONF="tests.test_utils.blog_urls") def test_post_list_view_custom_urlconf(self): pages = self.get_pages() self.get_posts() - self.get_request(pages[1], 'en', AnonymousUser()) - self.assertEqual(reverse('sample_app:posts-latest'), '/en/page-two/latests/') + self.get_request(pages[1], "en", AnonymousUser()) + self.assertEqual(reverse("sample_app:posts-latest"), "/en/page-two/latests/") class ViewTest(BaseTest): - def test_post_list_view_base_urlconf(self): pages = self.get_pages() self.get_posts() - self.get_request(pages[1], 'en', AnonymousUser()) - self.assertEqual(reverse('sample_app:posts-latest'), '/en/page-two/') + self.get_request(pages[1], "en", AnonymousUser()) + self.assertEqual(reverse("sample_app:posts-latest"), "/en/page-two/") def test_post_list_view(self): pages = self.get_pages() posts = self.get_posts() - request = self.get_request(pages[1], 'en', AnonymousUser()) + request = self.get_request(pages[1], "en", AnonymousUser()) - with smart_override('en'): + with smart_override("en"): view_obj = PostListView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) @@ -61,38 +62,38 @@ def test_post_list_view(self): self.assertEqual(list(view_obj.get_queryset()), [posts[0]]) self.assertEqual(getattr(request, BLOG_CURRENT_NAMESPACE), self.app_config_1) - request = self.get_page_request(pages[1], self.user, lang='en', edit=False) + request = self.get_page_request(pages[1], self.user, lang="en", edit=False) view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.request = request view_obj.kwargs = {} qs = view_obj.get_queryset() self.assertEqual(qs.count(), 1) - self.assertEqual(set(qs), set([posts[0]])) + self.assertEqual(set(qs), {posts[0]}) - request = self.get_page_request(pages[1], self.user, lang='en', edit=True) + request = self.get_page_request(pages[1], self.user, lang="en", edit=True) view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.request = request - self.assertEqual(set(view_obj.get_queryset()), set([posts[0], posts[1], posts[2]])) + self.assertEqual(set(view_obj.get_queryset()), {posts[0], posts[1], posts[2]}) view_obj.kwargs = {} view_obj.args = () view_obj.object_list = view_obj.get_queryset() view_obj.paginate_by = 1 context = view_obj.get_context_data(object_list=view_obj.object_list) - self.assertTrue(context['is_paginated']) - self.assertEqual(list(context['post_list']), [posts[0]]) - self.assertEqual(context['paginator'].count, 3) - self.assertEqual(context['post_list'][0].title, 'First post') + self.assertTrue(context["is_paginated"]) + self.assertEqual(list(context["post_list"]), [posts[0]]) + self.assertEqual(context["paginator"].count, 3) + self.assertEqual(context["post_list"][0].title, "First post") response = view_obj.render_to_response(context) - self.assertContains(response, context['post_list'][0].get_absolute_url()) + self.assertContains(response, context["post_list"][0].get_absolute_url()) self.assertEqual(getattr(request, BLOG_CURRENT_NAMESPACE), self.app_config_1) posts[1].sites.add(self.site_2) self.assertTrue(view_obj.get_queryset().count(), 2) self.assertFalse(posts[1] in view_obj.get_queryset()) - with smart_override('it'): - request = self.get_page_request(pages[1], self.user, lang='it', edit=True) + with smart_override("it"): + request = self.get_page_request(pages[1], self.user, lang="it", edit=True) view_obj = PostListView() view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.request = request @@ -100,50 +101,45 @@ def test_post_list_view(self): view_obj.kwargs = {} view_obj.object_list = view_obj.get_queryset() context = view_obj.get_context_data(object_list=view_obj.object_list) - self.assertEqual(context['post_list'][0].title, 'Primo post') + self.assertEqual(context["post_list"][0].title, "Primo post") response = view_obj.render_to_response(context) - self.assertContains(response, context['post_list'][0].get_absolute_url()) - blog_menu = request.toolbar.get_or_create_menu('djangocms_blog', _('Blog')) + self.assertContains(response, context["post_list"][0].get_absolute_url()) + blog_menu = request.toolbar.get_or_create_menu("djangocms_blog", _("Blog")) self.assertEqual(len(blog_menu.items), 3) - self.assertEqual(len(blog_menu.find_items( - ModalItem, url=reverse('admin:djangocms_blog_post_changelist') - )), 1) - self.assertEqual(len(blog_menu.find_items( - ModalItem, url=reverse('admin:djangocms_blog_post_add') - )), 1) - self.assertEqual(len(blog_menu.find_items( - ModalItem, url=reverse( - 'admin:djangocms_blog_blogconfig_change', args=(self.app_config_1.pk,) - ) - )), 1) + self.assertEqual( + len(blog_menu.find_items(ModalItem, url=reverse("admin:djangocms_blog_post_changelist"))), 1 + ) + self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse("admin:djangocms_blog_post_add"))), 1) + self.assertEqual( + len( + blog_menu.find_items( + ModalItem, url=reverse("admin:djangocms_blog_blogconfig_change", args=(self.app_config_1.pk,)) + ) + ), + 1, + ) def test_get_view_url(self): pages = self.get_pages() self.get_posts() # Test the custom version of get_view_url against the different namespaces - request = self.get_request(pages[1], 'en', AnonymousUser()) + request = self.get_request(pages[1], "en", AnonymousUser()) view_obj_1 = PostListView() view_obj_1.request = request view_obj_1.args = () view_obj_1.kwargs = {} view_obj_1.namespace, view_obj_1.config = get_app_instance(request) - self.assertEqual( - view_obj_1.get_view_url(), - 'http://testserver{0}'.format(pages[1].get_absolute_url()) - ) + self.assertEqual(view_obj_1.get_view_url(), "http://testserver{}".format(pages[1].get_absolute_url())) - request = self.get_request(pages[2], 'en', AnonymousUser()) + request = self.get_request(pages[2], "en", AnonymousUser()) view_obj_2 = PostListView() view_obj_2.request = request view_obj_2.args = () view_obj_2.kwargs = {} view_obj_2.namespace, view_obj_2.config = get_app_instance(request) - self.assertEqual( - view_obj_2.get_view_url(), - 'http://testserver{0}'.format(pages[2].get_absolute_url()) - ) + self.assertEqual(view_obj_2.get_view_url(), "http://testserver{}".format(pages[2].get_absolute_url())) view_obj_2.view_url_name = None with self.assertRaises(ImproperlyConfigured): @@ -154,20 +150,13 @@ def test_post_list_view_fallback(self): self.get_posts() PARLER_FALLBACK = { - 1: ( - {'code': 'en'}, - {'code': 'it'}, - {'code': 'fr', 'hide_untranslated': True}, - ), - 'default': { - 'fallback': 'en', - 'hide_untranslated': False, - } + 1: ({"code": "en"}, {"code": "it"}, {"code": "fr", "hide_untranslated": True},), + "default": {"fallback": "en", "hide_untranslated": False}, } - with smart_override('fr'): + with smart_override("fr"): view_obj = PostListView() - request = self.get_page_request(pages[1], self.user, lang='fr', edit=True) + request = self.get_page_request(pages[1], self.user, lang="fr", edit=True) view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.kwargs = {} @@ -179,7 +168,7 @@ def test_post_list_view_fallback(self): with override_parler_settings(PARLER_LANGUAGES=PARLER_FALLBACK): view_obj = PostListView() - request = self.get_page_request(pages[1], self.user, lang='fr', edit=True) + request = self.get_page_request(pages[1], self.user, lang="fr", edit=True) view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.kwargs = {} @@ -191,50 +180,50 @@ def test_post_detail_view(self): pages = self.get_pages() posts = self.get_posts() - with smart_override('en'): - with switch_language(posts[0], 'en'): - request = self.get_page_request(pages[1], AnonymousUser(), lang='en', edit=False) + with smart_override("en"): + with switch_language(posts[0], "en"): + request = self.get_page_request(pages[1], AnonymousUser(), lang="en", edit=False) view_obj = PostDetailView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) with self.assertRaises(Http404): - view_obj.kwargs = {'slug': 'not-existing'} + view_obj.kwargs = {"slug": "not-existing"} post_obj = view_obj.get_object() - view_obj.kwargs = {'slug': posts[0].slug} + view_obj.kwargs = {"slug": posts[0].slug} post_obj = view_obj.get_object() self.assertEqual(post_obj, posts[0]) - self.assertEqual(post_obj.language_code, 'en') + self.assertEqual(post_obj.language_code, "en") - with smart_override('it'): - with switch_language(posts[0], 'it'): - request = self.get_page_request(pages[1], AnonymousUser(), lang='it', edit=False) + with smart_override("it"): + with switch_language(posts[0], "it"): + request = self.get_page_request(pages[1], AnonymousUser(), lang="it", edit=False) view_obj = PostDetailView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) - view_obj.kwargs = {'slug': posts[0].slug} + view_obj.kwargs = {"slug": posts[0].slug} post_obj = view_obj.get_object() self.assertEqual(post_obj, posts[0]) - self.assertEqual(post_obj.language_code, 'it') + self.assertEqual(post_obj.language_code, "it") view_obj.object = post_obj context = view_obj.get_context_data() - self.assertEqual(context['post'], posts[0]) - self.assertEqual(context['post'].language_code, 'it') - self.assertTrue(context['meta']) + self.assertEqual(context["post"], posts[0]) + self.assertEqual(context["post"].language_code, "it") + self.assertTrue(context["meta"]) def test_post_archive_view(self): pages = self.get_pages() posts = self.get_posts() - with smart_override('en'): - request = self.get_page_request(pages[1], AnonymousUser(), lang='en', edit=False) + with smart_override("en"): + request = self.get_page_request(pages[1], AnonymousUser(), lang="en", edit=False) view_obj = PostArchiveView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) - view_obj.kwargs = {'year': now().year, 'month': now().month} + view_obj.kwargs = {"year": now().year, "month": now().month} # One post only, anonymous request qs = view_obj.get_queryset() @@ -243,32 +232,34 @@ def test_post_archive_view(self): view_obj.object_list = qs context = view_obj.get_context_data(object_list=view_obj.object_list) - self.assertEqual(context['archive_date'].date(), now().replace(year=now().year, month=now().month, day=1).date()) + self.assertEqual( + context["archive_date"].date(), now().replace(year=now().year, month=now().month, day=1).date() + ) def test_category_entries_view(self): pages = self.get_pages() posts = self.get_posts() - with smart_override('en'): - request = self.get_page_request(pages[1], self.user, lang='en', edit=True) + with smart_override("en"): + request = self.get_page_request(pages[1], self.user, lang="en", edit=True) view_obj = CategoryEntriesView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) - view_obj.kwargs = {'category': 'category-1'} + view_obj.kwargs = {"category": "category-1"} qs = view_obj.get_queryset() self.assertEqual(qs.count(), 3) - self.assertEqual(set(qs), set([posts[0], posts[1], posts[2]])) + self.assertEqual(set(qs), {posts[0], posts[1], posts[2]}) view_obj.paginate_by = 1 view_obj.object_list = qs context = view_obj.get_context_data(object_list=view_obj.object_list) - self.assertTrue(context['category']) - self.assertEqual(context['category'], self.category_1) - self.assertTrue(context['is_paginated']) - self.assertEqual(list(context['post_list']), [posts[0]]) - self.assertEqual(context['paginator'].count, 3) - self.assertEqual(context['post_list'][0].title, 'First post') - self.assertTrue(context['meta']) + self.assertTrue(context["category"]) + self.assertEqual(context["category"], self.category_1) + self.assertTrue(context["is_paginated"]) + self.assertEqual(list(context["post_list"]), [posts[0]]) + self.assertEqual(context["paginator"].count, 3) + self.assertEqual(context["post_list"][0].title, "First post") + self.assertTrue(context["meta"]) request = self.get_page_request(pages[1], self.user, edit=False) view_obj.request = request @@ -279,25 +270,25 @@ def test_author_entries_view(self): pages = self.get_pages() posts = self.get_posts() - with smart_override('en'): - request = self.get_page_request(pages[1], self.user, lang='en', edit=True) + with smart_override("en"): + request = self.get_page_request(pages[1], self.user, lang="en", edit=True) view_obj = AuthorEntriesView() view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.request = request - view_obj.kwargs = {'username': self.user.get_username()} + view_obj.kwargs = {"username": self.user.get_username()} qs = view_obj.get_queryset() self.assertEqual(qs.count(), 3) - self.assertEqual(set(qs), set([posts[0], posts[1], posts[2]])) + self.assertEqual(set(qs), {posts[0], posts[1], posts[2]}) view_obj.paginate_by = 1 view_obj.object_list = qs context = view_obj.get_context_data(object_list=view_obj.object_list) - self.assertTrue(context['author']) - self.assertEqual(context['author'], self.user) - self.assertTrue(context['is_paginated']) - self.assertEqual(list(context['post_list']), [posts[0]]) - self.assertEqual(context['paginator'].count, 3) - self.assertEqual(context['post_list'][0].title, 'First post') + self.assertTrue(context["author"]) + self.assertEqual(context["author"], self.user) + self.assertTrue(context["is_paginated"]) + self.assertEqual(list(context["post_list"]), [posts[0]]) + self.assertEqual(context["paginator"].count, 3) + self.assertEqual(context["post_list"][0].title, "First post") request = self.get_page_request(pages[1], self.user, edit=False) view_obj.request = request @@ -308,87 +299,86 @@ def test_templates(self): pages = self.get_pages() self.get_posts() - with smart_override('en'): + with smart_override("en"): request = self.get_page_request(pages[1], self.user, edit=True) view_obj = PostListView() view_obj.request = request view_obj.namespace = self.app_config_1.namespace view_obj.config = self.app_config_1 - self.assertEqual(view_obj.get_template_names(), os.path.join('djangocms_blog', 'post_list.html')) + self.assertEqual(view_obj.get_template_names(), os.path.join("djangocms_blog", "post_list.html")) - self.app_config_1.app_data.config.template_prefix = 'whatever' + self.app_config_1.app_data.config.template_prefix = "whatever" self.app_config_1.save() - self.assertEqual(view_obj.get_template_names(), os.path.join('whatever', 'post_list.html')) - self.app_config_1.app_data.config.template_prefix = '' + self.assertEqual(view_obj.get_template_names(), os.path.join("whatever", "post_list.html")) + self.app_config_1.app_data.config.template_prefix = "" self.app_config_1.save() def test_non_existing_blog_category_should_raise_404(self): pages = self.get_pages() - with smart_override('en'): - request = self.get_request(pages[1], 'en', AnonymousUser()) + with smart_override("en"): + request = self.get_request(pages[1], "en", AnonymousUser()) view_obj = CategoryEntriesView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) with self.assertRaises(Http404): - view_obj.kwargs = {'category': 'unknown-category'} + view_obj.kwargs = {"category": "unknown-category"} view_obj.get_queryset() def test_non_existing_author_should_raise_404(self): pages = self.get_pages() - with smart_override('en'): - request = self.get_request(pages[1], 'en', AnonymousUser()) + with smart_override("en"): + request = self.get_request(pages[1], "en", AnonymousUser()) view_obj = AuthorEntriesView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) with self.assertRaises(Http404): - view_obj.kwargs = {'username': 'unknown-author'} + view_obj.kwargs = {"username": "unknown-author"} view_obj.get_context_data() class TaggedItemViewTest(BaseTest): - def test_taggedlist_view(self): pages = self.get_pages() posts = self.get_posts() - posts[0].tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4') + posts[0].tags.add("tag 1", "tag 2", "tag 3", "tag 4") posts[0].save() - posts[1].tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8') + posts[1].tags.add("tag 6", "tag 2", "tag 5", "tag 8") posts[1].save() - with smart_override('en'): - request = self.get_page_request(pages[1], self.user, lang='en', edit=True) + with smart_override("en"): + request = self.get_page_request(pages[1], self.user, lang="en", edit=True) view_obj = TaggedListView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) - view_obj.kwargs = {'tag': 'tag-2'} + view_obj.kwargs = {"tag": "tag-2"} qs = view_obj.get_queryset() self.assertEqual(qs.count(), 2) - self.assertEqual(set(qs), set([posts[0], posts[1]])) + self.assertEqual(set(qs), {posts[0], posts[1]}) view_obj.paginate_by = 1 view_obj.object_list = qs context = view_obj.get_context_data(object_list=view_obj.object_list) - self.assertTrue(context['tagged_entries'], 'tag-2') - self.assertTrue(context['is_paginated']) - self.assertEqual(list(context['post_list']), [posts[0]]) - self.assertEqual(context['paginator'].count, 2) - self.assertEqual(context['post_list'][0].title, 'First post') + self.assertTrue(context["tagged_entries"], "tag-2") + self.assertTrue(context["is_paginated"]) + self.assertEqual(list(context["post_list"]), [posts[0]]) + self.assertEqual(context["paginator"].count, 2) + self.assertEqual(context["post_list"][0].title, "First post") def test_feed(self): - self.user.first_name = 'Admin' - self.user.last_name = 'User' + self.user.first_name = "Admin" + self.user.last_name = "User" self.user.save() pages = self.get_pages() posts = self.get_posts() - posts[0].tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4') + posts[0].tags.add("tag 1", "tag 2", "tag 3", "tag 4") posts[0].author = self.user posts[0].save() - posts[1].tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8') + posts[1].tags.add("tag 6", "tag 2", "tag 5", "tag 8") posts[1].save() - posts[0].set_current_language('en') + posts[0].set_current_language("en") - with smart_override('en'): - with switch_language(posts[0], 'en'): + with smart_override("en"): + with switch_language(posts[0], "en"): request = self.get_page_request(pages[1], self.user, path=posts[0].get_absolute_url()) @@ -398,50 +388,44 @@ def test_feed(self): self.reload_urlconf() xml = feed(request) self.assertContains(xml, posts[0].get_absolute_url()) - self.assertContains(xml, 'Blog articles on example.com') - self.assertContains(xml, 'Admin User') + self.assertContains(xml, "Blog articles on example.com") + self.assertContains(xml, "Admin User") - with smart_override('it'): - with switch_language(posts[0], 'it'): + with smart_override("it"): + with switch_language(posts[0], "it"): feed = LatestEntriesFeed() feed.namespace, feed.config = get_app_instance(request) self.assertEqual(list(feed.items()), [posts[0]]) request = self.get_page_request(pages[1], self.user, path=posts[0].get_absolute_url()) xml = feed(request) self.assertContains(xml, posts[0].get_absolute_url()) - self.assertContains(xml, 'Articoli del blog su example.com') + self.assertContains(xml, "Articoli del blog su example.com") feed = TagFeed() feed.namespace = self.app_config_1.namespace feed.config = self.app_config_1 - self.assertEqual(list(feed.items('tag-2')), [posts[0]]) + self.assertEqual(list(feed.items("tag-2")), [posts[0]]) -class SitemapViewTest(BaseTest): +class SitemapViewTest(BaseTest): def test_sitemap(self): self.get_pages() posts = self.get_posts() - posts[0].tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4') + posts[0].tags.add("tag 1", "tag 2", "tag 3", "tag 4") posts[0].save() - posts[1].tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8') + posts[1].tags.add("tag 6", "tag 2", "tag 5", "tag 8") posts[1].publish = True posts[1].save() - posts[0].set_current_language('en') + posts[0].set_current_language("en") sitemap = BlogSitemap() self.assertEqual(len(sitemap.items()), 6) for item in sitemap.items(): self.assertEqual(sitemap.lastmod(item).date(), now().date()) - self.assertEqual( - sitemap.priority(item), get_setting('SITEMAP_PRIORITY_DEFAULT') - ) - self.assertEqual( - sitemap.changefreq(item), get_setting('SITEMAP_CHANGEFREQ_DEFAULT') - ) + self.assertEqual(sitemap.priority(item), get_setting("SITEMAP_PRIORITY_DEFAULT")) + self.assertEqual(sitemap.changefreq(item), get_setting("SITEMAP_CHANGEFREQ_DEFAULT")) with smart_override(item.get_current_language()): - self.assertEqual( - sitemap.location(item), item.get_absolute_url() - ) + self.assertEqual(sitemap.location(item), item.get_absolute_url()) def test_sitemap_with_unpublished(self): pages = self.get_pages() @@ -452,8 +436,8 @@ def test_sitemap_with_unpublished(self): # unpublish all the pages for page in pages: - page.unpublish('en') - page.unpublish('it') + page.unpublish("en") + page.unpublish("it") reload_urlconf() @@ -462,8 +446,8 @@ def test_sitemap_with_unpublished(self): def test_sitemap_config(self): self.get_pages() self.get_posts() - self.app_config_1.app_data.config.sitemap_changefreq = 'daily' - self.app_config_1.app_data.config.sitemap_priority = '0.2' + self.app_config_1.app_data.config.sitemap_changefreq = "daily" + self.app_config_1.app_data.config.sitemap_priority = "0.2" self.app_config_1.save() sitemap = BlogSitemap() @@ -471,61 +455,45 @@ def test_sitemap_config(self): for item in sitemap.items(): self.assertEqual(sitemap.lastmod(item).date(), now().date()) if item.app_config == self.app_config_1: - self.assertEqual( - sitemap.priority(item), '0.2' - ) - self.assertEqual( - sitemap.changefreq(item), 'daily' - ) + self.assertEqual(sitemap.priority(item), "0.2") + self.assertEqual(sitemap.changefreq(item), "daily") else: - self.assertEqual( - sitemap.priority(item), get_setting('SITEMAP_PRIORITY_DEFAULT') - ) - self.assertEqual( - sitemap.changefreq(item), get_setting('SITEMAP_CHANGEFREQ_DEFAULT') - ) - self.assertEqual( - sitemap.priority(None), get_setting('SITEMAP_PRIORITY_DEFAULT') - ) - self.assertEqual( - sitemap.changefreq(None), get_setting('SITEMAP_CHANGEFREQ_DEFAULT') - ) + self.assertEqual(sitemap.priority(item), get_setting("SITEMAP_PRIORITY_DEFAULT")) + self.assertEqual(sitemap.changefreq(item), get_setting("SITEMAP_CHANGEFREQ_DEFAULT")) + self.assertEqual(sitemap.priority(None), get_setting("SITEMAP_PRIORITY_DEFAULT")) + self.assertEqual(sitemap.changefreq(None), get_setting("SITEMAP_CHANGEFREQ_DEFAULT")) class InstanctArticlesViewTest(BaseTest): - def test_instant_articles(self): - self.user.first_name = 'Admin' - self.user.last_name = 'User' + self.user.first_name = "Admin" + self.user.last_name = "User" self.user.save() pages = self.get_pages() posts = self.get_posts() - posts[0].tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4') + posts[0].tags.add("tag 1", "tag 2", "tag 3", "tag 4") posts[0].categories.add(self.category_1) posts[0].author = self.user posts[0].save() - add_plugin( - posts[0].content, 'TextPlugin', language='en', body='

Ciao

Ciao

' - ) - - with smart_override('en'): - with switch_language(posts[0], 'en'): - request = self.get_page_request( - pages[1], self.user, path=posts[0].get_absolute_url() - ) + add_plugin(posts[0].content, "TextPlugin", language="en", body="

Ciao

Ciao

") + + with smart_override("en"): + with switch_language(posts[0], "en"): + request = self.get_page_request(pages[1], self.user, path=posts[0].get_absolute_url()) feed = FBInstantArticles() feed.namespace, feed.config = get_app_instance(request) self.assertEqual(list(feed.items()), [posts[0]]) xml = feed(request) - self.assertContains(xml, '{0}'.format(posts[0].guid)) - self.assertContains(xml, 'content:encoded') - self.assertContains(xml, 'class="op-modified" datetime="{0}"'.format( - posts[0].date_modified.strftime(FBInstantFeed.date_format) - )) - self.assertContains(xml, ''.format( - posts[0].get_full_url() - )) + self.assertContains(xml, "{}".format(posts[0].guid)) + self.assertContains(xml, "content:encoded") + self.assertContains( + xml, + 'class="op-modified" datetime="{}"'.format( + posts[0].date_modified.strftime(FBInstantFeed.date_format) + ), + ) + self.assertContains(xml, ''.format(posts[0].get_full_url())) # Assert text transformation - self.assertContains(xml, '

Ciao

Ciao

') - self.assertContains(xml, 'Admin User') + self.assertContains(xml, "

Ciao

Ciao

") + self.assertContains(xml, "Admin User") diff --git a/tests/test_wizards.py b/tests/test_wizards.py index 854142d6..1085cab3 100644 --- a/tests/test_wizards.py +++ b/tests/test_wizards.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import sys from django.http import QueryDict @@ -9,22 +8,18 @@ class WizardTest(BaseTest): - def setUp(self): - try: - from cms.wizards.wizard_pool import wizard_pool - delete = [ - 'djangocms_blog', - 'djangocms_blog.cms_wizards', - ] - for module in delete: - if module in sys.modules: - del sys.modules[module] - wizard_pool._reset() - except ImportError: - # Not in django CMS 3.2+, no cleanup needed - pass - super(WizardTest, self).setUp() + from cms.wizards.wizard_pool import wizard_pool + + delete = [ + "djangocms_blog", + "djangocms_blog.cms_wizards", + ] + for module in delete: + if module in sys.modules: + del sys.modules[module] + wizard_pool._reset() + super().setUp() def get_querydict(self, source): tmp = QueryDict(mutable=True) @@ -37,20 +32,22 @@ def test_wizard(self): Test that Blog wizard is present and contains all items """ from cms.wizards.wizard_pool import wizard_pool + self.get_pages() titles = [entry.title for entry in wizard_pool.get_entries()] - self.assertTrue('New Blog' in titles) - self.assertTrue('New Article' in titles) + self.assertTrue("New Blog" in titles) + self.assertTrue("New Article" in titles) def test_wizard_init(self): from cms.utils.permissions import current_user from cms.wizards.wizard_pool import wizard_pool from djangocms_blog.models import Post + self.get_pages() - cat_1 = BlogCategory.objects.create(name='category 1 - blog 1', app_config=self.app_config_1) - cat_2 = BlogCategory.objects.create(name='category 1 - blog 2', app_config=self.app_config_2) + cat_1 = BlogCategory.objects.create(name="category 1 - blog 1", app_config=self.app_config_1) + cat_2 = BlogCategory.objects.create(name="category 1 - blog 2", app_config=self.app_config_2) cats = { self.app_config_1.pk: cat_1, self.app_config_2.pk: cat_2, @@ -58,33 +55,43 @@ def test_wizard_init(self): with current_user(self.user_staff): wizs = [entry for entry in wizard_pool.get_entries() if entry.model == Post] for index, wiz in enumerate(wizs): - app_config = self.app_config_1.pk if wiz.title == 'New Blog' else self.app_config_2.pk + app_config = self.app_config_1.pk if wiz.title == "New Blog" else self.app_config_2.pk form = wiz.form() - self.assertTrue(form.initial.get('app_config', False), app_config) - self.assertTrue(form.fields['app_config'].widget.attrs['disabled']) - - form = wiz.form(data=self.get_querydict({ - '1-title': 'title{0}'.format(index), - '1-abstract': 'abstract{0}'.format(index), - '1-categories': cats[app_config].pk, - }), prefix=1) + self.assertTrue(form.initial.get("app_config", False), app_config) + self.assertTrue(form.fields["app_config"].widget.attrs["disabled"]) + + form = wiz.form( + data=self.get_querydict( + { + "1-title": "title{}".format(index), + "1-abstract": "abstract{}".format(index), + "1-categories": cats[app_config].pk, + } + ), + prefix=1, + ) self.assertEqual(form.default_appconfig, app_config) self.assertTrue(form.is_valid()) - self.assertEqual(form.cleaned_data['app_config'].pk, app_config) + self.assertEqual(form.cleaned_data["app_config"].pk, app_config) instance = form.save() self.assertEqual(instance.author, self.user_staff) - with self.settings(BLOG_AUTHOR_DEFAULT='normal'): + with self.settings(BLOG_AUTHOR_DEFAULT="normal"): for index, wiz in enumerate(wizs): - app_config = self.app_config_1.pk if wiz.title == 'New Blog' else self.app_config_2.pk - form = wiz.form(data=self.get_querydict({ - '1-title': 'title-2{0}'.format(index), - '1-abstract': 'abstract-2{0}'.format(index), - '1-categories': cats[app_config].pk, - }), prefix=1) + app_config = self.app_config_1.pk if wiz.title == "New Blog" else self.app_config_2.pk + form = wiz.form( + data=self.get_querydict( + { + "1-title": "title-2{}".format(index), + "1-abstract": "abstract-2{}".format(index), + "1-categories": cats[app_config].pk, + } + ), + prefix=1, + ) self.assertEqual(form.default_appconfig, app_config) self.assertTrue(form.is_valid()) - self.assertEqual(form.cleaned_data['app_config'].pk, app_config) + self.assertEqual(form.cleaned_data["app_config"].pk, app_config) instance = form.save() self.assertEqual(instance.author, self.user_normal) @@ -92,66 +99,72 @@ def test_wizard_duplicate_slug(self): from cms.utils.permissions import current_user from cms.wizards.wizard_pool import wizard_pool from djangocms_blog.models import Post + self.get_pages() - cat_2 = BlogCategory.objects.create(name='category 1 - blog 2', app_config=self.app_config_2) + cat_2 = BlogCategory.objects.create(name="category 1 - blog 2", app_config=self.app_config_2) with current_user(self.user_staff): wiz = None for wiz in wizard_pool.get_entries(): - if wiz.model == Post and wiz.title == 'New Blog': + if wiz.model == Post and wiz.title == "New Blog": break - form = wiz.form(data=self.get_querydict({ - '1-title': 'title article', - '1-abstract': 'abstract article', - '1-categories': self.category_1.pk, - }), prefix=1) + form = wiz.form( + data=self.get_querydict( + {"1-title": "title article", "1-abstract": "abstract article", "1-categories": self.category_1.pk} + ), + prefix=1, + ) self.assertEqual(form.default_appconfig, self.app_config_1.pk) self.assertTrue(form.is_valid()) instance1 = form.save() - self.assertEqual(instance1.slug, 'title-article') - - form = wiz.form(data=self.get_querydict({ - '1-title': 'title article', - '1-abstract': 'abstract article', - '1-categories': self.category_1.pk, - }), prefix=1) + self.assertEqual(instance1.slug, "title-article") + + form = wiz.form( + data=self.get_querydict( + {"1-title": "title article", "1-abstract": "abstract article", "1-categories": self.category_1.pk} + ), + prefix=1, + ) self.assertEqual(form.default_appconfig, self.app_config_1.pk) self.assertTrue(form.is_valid()) instance2 = form.save() - self.assertEqual(instance2.slug, 'title-article-1') + self.assertEqual(instance2.slug, "title-article-1") for wiz in wizard_pool.get_entries(): - if wiz.model == Post and wiz.title == 'New Article': + if wiz.model == Post and wiz.title == "New Article": break - form = wiz.form(data=self.get_querydict({ - '1-title': 'title article', - '1-abstract': 'abstract article', - '1-categories': cat_2.pk, - }), prefix=1) + form = wiz.form( + data=self.get_querydict( + {"1-title": "title article", "1-abstract": "abstract article", "1-categories": cat_2.pk} + ), + prefix=1, + ) self.assertEqual(form.default_appconfig, self.app_config_2.pk) self.assertTrue(form.is_valid()) instance3 = form.save() - self.assertEqual(instance3.slug, 'title-article-2') + self.assertEqual(instance3.slug, "title-article-2") def test_wizard_init_categories_check(self): from cms.utils.permissions import current_user from cms.wizards.wizard_pool import wizard_pool from djangocms_blog.models import Post + self.get_pages() with current_user(self.user_staff): wiz = None for wiz in wizard_pool.get_entries(): - if wiz.model == Post and wiz.title == 'New Article': + if wiz.model == Post and wiz.title == "New Article": break - form = wiz.form(data=self.get_querydict({ - '1-title': 'title article', - '1-abstract': 'abstract article', - '1-categories': self.category_1.pk, - }), prefix=1) + form = wiz.form( + data=self.get_querydict( + {"1-title": "title article", "1-abstract": "abstract article", "1-categories": self.category_1.pk} + ), + prefix=1, + ) self.assertEqual(form.default_appconfig, self.app_config_2.pk) self.assertFalse(form.is_valid()) - self.assertTrue('categories' in form.errors.keys()) + self.assertTrue("categories" in form.errors.keys()) def test_wizard_import(self): # The following import should not fail in any django CMS version diff --git a/tox.ini b/tox.ini index 8afd7459..742c4f57 100644 --- a/tox.ini +++ b/tox.ini @@ -1,10 +1,15 @@ [tox] envlist = + black + blacken docs - pep8 isort - py{38,37,36}-django{30}-cms{37} - py{38,37,36,35}-django{22}-cms{37} + isort_format + pep8 + pypi-description + towncrier + py{3.8,3.7,3.6}-django{30}-cms{37} + py{3.8,3.7,3.6,3.5}-django{22}-cms{37} [testenv] commands = {env:COMMAND:python} cms_helper.py djangocms_blog test {posargs} @@ -25,23 +30,132 @@ deps = channels-redis aldryn-apphooks-config>=0.6.0 -r{toxinidir}/requirements-test.txt +passenv = + COMMAND + PYTEST_* + +[testenv:pep8] +commands = + {envpython} -m flake8 +deps = + flake8 + flake8-broken-line + flake8-bugbear + flake8-builtins + flake8-coding # Enable when dropping python2 + flake8-commas + flake8-comprehensions + flake8-eradicate + flake8-quotes + flake8-tidy-imports + pep8-naming +skip_install = true [testenv:isort] +commands = + {envpython} -m isort -c -rc -df deps = isort -commands = isort -c -rc -df skip_install = true -[testenv:pep8] -deps = flake8 -commands = flake8 +[testenv:isort_format] +commands = + {envpython} -m isort -rc -y +deps = {[testenv:isort]deps} +skip_install = true + +[testenv:black] +commands = + {envpython} -m black --check --diff . +deps = black +skip_install = true + +[testenv:blacken] +commands = + {envpython} -m black . +deps = {[testenv:black]deps} skip_install = true [testenv:docs] -changedir = docs +commands = + {envpython} -m invoke docbuild deps = + invoke sphinx sphinx-rtd-theme - -rrequirements-docs.txt -commands= - sphinx-build -W -b html -d {envtmpdir}/doctrees . {toxinidir}/docs/_build/html + livereload~=2.6 + -rrequirements-test.txt skip_install = true + +[testenv:towncrier] +commands = + {envpython} -m invoke towncrier-check +deps = + invoke +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 +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_* +skip_install = true + +[flake8] +exclude = *.egg-info,.git,.settings,.tox,build,dist,docs,requirements,tmp,*migrations*,tests,data +ignore = E800, W503, C812, C813, C815, C819, 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] +combine_as_imports = true +default_section = THIRDPARTY +force_grid_wrap = 0 +include_trailing_comma = true +known_first_party = djangocms_blog +line_length = 119 +multi_line_output = 3 +not_skip = __init__.py +skip = data, .tox +use_parentheses = True + +[check-manifest] +ignore = + .* + *.ini + *.toml + *.json + *.txt + *.yml + *.yaml + .tx/** + changes/** + docs/** + cms_helper.py + aldryn_config.py + tasks.py + tests/** + *.mo +ignore-bad-ideas = + *.mo