From 75d221545585bdf0dfa9ae1387341130fc37c303 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sat, 4 Dec 2021 08:36:09 -0600 Subject: [PATCH 01/51] Updates URL of the project to Jazzband. #164 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index cbf5c6f..a8a277f 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ setup( author='Corey Oordt', author_email='coreyoordt@gmail.com', include_package_data=True, - url='http://github.com/callowayproject/django-categories', + url='http://github.com/jazzband/django-categories', packages=find_packages(exclude=['example*', ]), classifiers=[ 'Framework :: Django', From f98f8a176111a6adfd621b47fa3fb2089bd7c83f Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sat, 4 Dec 2021 08:57:30 -0600 Subject: [PATCH 02/51] Added Jazzband badge to README. Also changed it to Markdown. --- README.md | 175 +++++++++++++++++++++++++++++++++++++++++++++ README.rst | 203 ----------------------------------------------------- setup.py | 3 +- 3 files changed, 177 insertions(+), 204 deletions(-) create mode 100644 README.md delete mode 100644 README.rst diff --git a/README.md b/README.md new file mode 100644 index 0000000..1d723fd --- /dev/null +++ b/README.md @@ -0,0 +1,175 @@ +# Django Categories + +[![Jazzband](https://jazzband.co/static/img/badge.svg)](https://jazzband.co/) + +Django Categories grew out of our need to provide a basic hierarchical taxonomy management system that multiple applications could use independently or in concert. + +As a news site, our stories, photos, and other content get divided into "sections" and we wanted all the apps to use the same set of sections. As our needs grew, the Django Categories grew in the functionality it gave to category handling within web pages. + +## Features of the project + +**Multiple trees, or a single tree.** +You can treat all the records as a single tree, shared by all the applications. You can also treat each of the top level records as individual trees, for different apps or uses. + +**Easy handling of hierarchical data.** +We use [Django MPTT](http://pypi.python.org/pypi/django-mptt) to manage the data efficiently and provide the extra access functions. + +**Easy importation of data.** +Import a tree or trees of space- or tab-indented data with a Django management command. + +**Metadata for better SEO on web pages** +Include all the metadata you want for easy inclusion on web pages. + +**Link uncategorized objects to a category** +Attach any number of objects to a category, even if the objects themselves aren't categorized. + +**Hierarchical Admin** +Shows the data in typical tree form with disclosure triangles + +**Template Helpers** +Easy ways for displaying the tree data in templates: + +- **Show one level of a tree.** All root categories or just children of a specified category + +- **Show multiple levels.** Ancestors of category, category and all children of category or a category and its children + +## Changes + +### New in 1.8 + +* Support for Django 3.1 +* Removed support for Python 2.7 + +### New in 1.7 + +* Support for Django 3 + +### New in 1.6 + +* Support for Django 2 + +### New in 1.5 + +* Support for Django 1.10 + +### New in 1.4 + +* Support for Python 2.7, 3.4 and 3.5 +* Support for Django 1.9 +* Dropped support for Django 1.7 and older + +### New in 1.3 + +* Support for Django 1.6, 1.7 and 1.8 +* Dropped support for Django versions 1.5 and below + +### New in 1.2 + +* Support for Django 1.5 +* Dropped support for Django 1.2 +* Dropped caching within the app +* Removed the old settings compatibility layer. *Must use new dictionary-based settings!* + + +### New in 1.1 + +* Fixed a cosmetic bug in the Django 1.4 admin. Action checkboxes now only appear once. + +* Template tags are refactored to allow easy use of any model derived from ``CategoryBase``. + +* Improved test suite. + +* Improved some of the documentation. + + +### Upgrade path from 1.0.2 to 1.0.3 + +Due to some data corruption with 1.0.2 migrations, a partially new set of migrations has been written in 1.0.3; and this will cause issues for users on 1.0.2 version. There is also an issue with South version 0.7.4. South version 0.7.3 or 0.7.5 or greater works fine. + +For a clean upgrade from 1.0.2 to 1.0.3 you have to delete previous version of 0010 migration (named 0010_changed_category_relation.py) and fakes the new 00010, 0011 and 0012. + +Therefore after installing new version of django-categories, for each project to upgrade you should execute the following commans in order + + python manage.py migrate categories 0010_add_field_categoryrelation_category --fake --delete-ghost-migrations + python manage.py migrate categories 0011_move_category_fks --fake + python manage.py migrate categories 0012_remove_story_field --fake + python manage.py migrate categories 0013_null_category_id + +This way both the exact database layout and migration history is restored between the two installation paths (new installation from 1.0.3 and upgrade from 1.0.2 to 1.0.3). + +Last migration is needed to set the correct null value for `category_id` field when upgrading from 1.0.2 while is a noop for 1.0.3. + +### New in 1.0 + +**Abstract Base Class for generic hierarchical category models.** + When you want a multiple types of categories and don't want them all part of the same model, you can now easily create new models by subclassing `CategoryBase`. You can also add additional metadata as necessary. + + Your model's can subclass `CategoryBaseAdminForm` and `CategoryBaseAdmin` to get the hierarchical management in the admin. + + See the docs for more information. + +**Increased the default caching time on views.** + The default setting for `CACHE_VIEW_LENGTH` was `0`, which means it would tell the browser to *never* cache the page. It is now `600`, which is the default for [CACHE_MIDDLEWARE_SECONDS](https://docs.djangoproject.com/en/1.3/ref/settings/#cache-middleware-seconds) + +**Updated for use with Django-MPTT 0.5.** + Just a few tweaks. + +**Initial compatibility with Django 1.4.** + More is coming, but at least it works. + +**Slug transliteration for non-ASCII characters.** + A new setting, ``SLUG_TRANSLITERATOR``, allows you to specify a function for converting the non-ASCII characters to ASCII characters before the slugification. Works great with [Unidecode](http://pypi.python.org/pypi/Unidecode). + +### Updated in 0.8.8 + +The `editor` app was placed inside the categories app, `categories.editor`, to avoid any name clashes. + +#### Upgrading + +A setting change is all that is needed: + + INSTALLED_APPS = ( + 'categories', + 'categories.editor', + ) + +### New in 0.8 + +**Added an active field.** As an alternative to deleting categories, you can make them inactive. + +Also added a manager method ``active()`` to query only the active categories and added Admin Actions to activate or deactivate an item. + +**Improved import.** Previously the import saved items in the reverse order to the imported file. Now them import in order. + +### New in 0.7 + +**Added South migrations.** All the previous SQL scripts have been converted to South migrations. + +**Can add category fields via management command (and South).** +The new ability to setup category relationships in ``settings.py`` works fine if you are starting from scratch, but not if you want to add it after you have set up the database. Now there is a management command to make sure all the correct fields and tables are created. + +**Added an alternate_url field.** +This allows the specification of a URL that is not derived from the category hierarchy. + +**New JAVASCRIPT_URL setting.** +This allows some customization of the `genericcollections.js` file. + +**New get_latest_objects_by_category template tag.** This will do pretty much what it says. + + +### New in 0.6 + +**Class-based views.** +Works great with Django 1.3 or [django-cbv](http://pypi.python.org/pypi/django-cbv) + +**New Settings infrastructure.** +To be more like the Django project, we are migrating from individual `CATEGORIES_*` settings to a dictionary named `CATEGORIES_SETTINGS`. Use of the previous settings will still work but will generate a `DeprecationError`. + +**The tree's initially expanded state is now configurable.** +`EDITOR_TREE_INITIAL_STATE` allows a `collapsed` or `expanded` value. The default is `collapsed`. + +**Optional Thumbnail field.** +Have a thumbnail for each category! + +**"Categorize" models in settings.** +Now you don't have to modify the model to add a `Category` relationship. Use the new settings to "wire" categories to different models. diff --git a/README.rst b/README.rst deleted file mode 100644 index 8a46b34..0000000 --- a/README.rst +++ /dev/null @@ -1,203 +0,0 @@ -================= -Django Categories -================= - -|BUILD|_ - -.. |BUILD| image:: - https://travis-ci.org/callowayproject/django-categories.svg?branch=master -.. _BUILD: https://travis-ci.org/callowayproject/django-categories - - -Django Categories grew out of our need to provide a basic hierarchical taxonomy management system that multiple applications could use independently or in concert. - -As a news site, our stories, photos, and other content get divided into "sections" and we wanted all the apps to use the same set of sections. As our needs grew, the Django Categories grew in the functionality it gave to category handling within web pages. - -New in 1.8 -========== - -* Support for Django 3.1 -* Removed support for Python 2.7 - -New in 1.7 -========== - -* Support for Django 3 - -New in 1.6 -========== - -* Support for Django 2 - -New in 1.5 -========== - -* Support for Django 1.10 - -New in 1.4 -========== - -* Support for Python 2.7, 3.4 and 3.5 -* Support for Django 1.9 -* Dropped support for Django 1.7 and older - -New in 1.3 -========== - -* Support for Django 1.6, 1.7 and 1.8 -* Dropped support for Django versions 1.5 and below - -New in 1.2 -========== - -* Support for Django 1.5 -* Dropped support for Django 1.2 -* Dropped caching within the app -* Removed the old settings compatibility layer. *Must use new dictionary-based settings!* - - - -New in 1.1 -========== - -* Fixed a cosmetic bug in the Django 1.4 admin. Action checkboxes now only appear once. - -* Template tags are refactored to allow easy use of any model derived from ``CategoryBase``. - -* Improved test suite. - -* Improved some of the documentation. - - -Upgrade path from 1.0.2 to 1.0.3 -================================ - -Due to some data corruption with 1.0.2 migrations, a partially new set of migrations has been written in 1.0.3; and this will cause issues for users on 1.0.2 version. There is also an issue with South version 0.7.4. South version 0.7.3 or 0.7.5 or greater works fine. - -For a clean upgrade from 1.0.2 to 1.0.3 you have to delete previous version of 0010 migration (named 0010_changed_category_relation.py) and fakes the new 00010, 0011 and 0012. - -Therefore after installing new version of django-categories, for each project to upgrade you should execute the following commans in order:: - - python manage.py migrate categories 0010_add_field_categoryrelation_category --fake --delete-ghost-migrations - python manage.py migrate categories 0011_move_category_fks --fake - python manage.py migrate categories 0012_remove_story_field --fake - python manage.py migrate categories 0013_null_category_id - -This way both the exact database layout and migration history is restored between the two installation paths (new installation from 1.0.3 and upgrade from 1.0.2 to 1.0.3). - -Last migration is needed to set the correct null value for `category_id` field when upgrading from 1.0.2 while is a noop for 1.0.3. - -New in 1.0 -========== - -**Abstract Base Class for generic hierarchical category models** - When you want a multiple types of categories and don't want them all part of the same model, you can now easily create new models by subclassing ``CategoryBase``. You can also add additional metadata as necessary. - - Your model's can subclass ``CategoryBaseAdminForm`` and ``CategoryBaseAdmin`` to get the hierarchical management in the admin. - - See the docs for more information. - -**Increased the default caching time on views** - The default setting for ``CACHE_VIEW_LENGTH`` was ``0``, which means it would tell the browser to *never* cache the page. It is now ``600``, which is the default for `CACHE_MIDDLEWARE_SECONDS `_ - -**Updated for use with Django-MPTT 0.5** - Just a few tweaks. - -**Initial compatibility with Django 1.4** - More is coming, but at least it works. - -**Slug transliteration for non-ASCII characters** - A new setting, ``SLUG_TRANSLITERATOR``, allows you to specify a function for converting the non-ASCII characters to ASCII characters before the slugification. Works great with `Unidecode `_. - -Updated in 0.8.8 -================ - -The `editor` app was placed inside the categories app, `categories.editor`, to avoid any name clashes. - -Upgrading ---------- - -A setting change is all that is needed:: - - INSTALLED_APPS = ( - 'categories', - 'categories.editor', - ) - -New in 0.8 -========== - -**Added an active field** - As an alternative to deleting categories, you can make them inactive. - - Also added a manager method ``active()`` to query only the active categories and added Admin Actions to activate or deactivate an item. - -**Improved import** - Previously the import saved items in the reverse order to the imported file. Now them import in order. - -New in 0.7 -========== - -**Added South migrations** - All the previous SQL scripts have been converted to South migrations. - -**Can add category fields via management command (and South)** - The new ability to setup category relationships in ``settings.py`` works fine if you are starting from scratch, but not if you want to add it after you have set up the database. Now there is a management command to make sure all the correct fields and tables are created. - -**Added an alternate_url field** - This allows the specification of a URL that is not derived from the category hierarchy. - -**New JAVASCRIPT_URL setting** - This allows some customization of the ``genericcollections.js`` file. - -**New get_latest_objects_by_category template tag** - This will do pretty much what it says. - - -New in 0.6 -========== - -**Class-based views** - Works great with Django 1.3 or `django-cbv `_ - -**New Settings infrastructure** - To be more like the Django project, we are migrating from individual CATEGORIES_* settings to a dictionary named ``CATEGORIES_SETTINGS``\ . Use of the previous settings will still work but will generate a ``DeprecationError``\ . - -**The tree's initially expanded state is now configurable** - ``EDITOR_TREE_INITIAL_STATE`` allows a ``collapsed`` or ``expanded`` value. The default is ``collapsed``\ . - -**Optional Thumbnail field** - Have a thumbnail for each category! - -**"Categorize" models in settings** - Now you don't have to modify the model to add a ``Category`` relationship. Use the new settings to "wire" categories to different models. - -Features of the project -======================= - -**Multiple trees, or a single tree** - You can treat all the records as a single tree, shared by all the applications. You can also treat each of the top level records as individual trees, for different apps or uses. - -**Easy handling of hierarchical data** - We use `Django MPTT `_ to manage the data efficiently and provide the extra access functions. - -**Easy importation of data** - Import a tree or trees of space- or tab-indented data with a Django management command. - -**Metadata for better SEO on web pages** - Include all the metadata you want for easy inclusion on web pages. - -**Link uncategorized objects to a category** - Attach any number of objects to a category, even if the objects themselves aren't categorized. - -**Hierarchical Admin** - Shows the data in typical tree form with disclosure triangles - -**Template Helpers** - Easy ways for displaying the tree data in templates: - - **Show one level of a tree** - All root categories or just children of a specified category - - **Show multiple levels** - Ancestors of category, category and all children of category or a category and its children diff --git a/setup.py b/setup.py index a8a277f..834ce3c 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ import categories import os try: - long_description = open('README.rst').read() + long_description = open('README.md').read() except IOError: long_description = '' @@ -17,6 +17,7 @@ setup( version=categories.get_version(), description='A way to handle one or more hierarchical category trees in django.', long_description=long_description, + long_description_content_type="text/markdown", author='Corey Oordt', author_email='coreyoordt@gmail.com', include_package_data=True, From 60669d81b6d0072f567532c8d6cb00ea4856f5db Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sat, 4 Dec 2021 08:58:51 -0600 Subject: [PATCH 03/51] Added contributing documentation. #164 --- CONTRIBUTING.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..ad78220 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,3 @@ +[![Jazzband](https://jazzband.co/static/img/jazzband.svg)](https://jazzband.co/) + +This is a [Jazzband](https://jazzband.co/) project. By contributing you agree to abide by the [Contributor Code of Conduct](https://jazzband.co/about/conduct) and follow the [guidelines](https://jazzband.co/about/guidelines). From 277b49134e7a488a21d7431b8fcce682d0e7895e Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sat, 4 Dec 2021 09:05:56 -0600 Subject: [PATCH 04/51] Updated gitignore to be more ignorative --- .gitignore | 186 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 170 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index 74065d1..bf5515f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,20 +1,174 @@ -*.pyc -dev.db -local_settings.py -media/ugc +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python build/ -src/ -pip-log.txt -media/js/*.r*.js -media/css/*.r*.css -*DS_Store -*.egg-info -doc_src/_build -MANIFEST +develop-eggs/ dist/ -.venv -example/media/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.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/ -htmlcov +.nox/ .coverage -.python-version +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints +*/.ipynb_checkpoints/* + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .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 + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# Mr Developer +.mr.developer.cfg +.project +.pydevproject + +# Pycharm/Intellij +.idea + +# VSCode +.vscode + +# Docker +docker-compose* +**/docker-compose* + +# Complexity +output/*.html +output/*/index.html + +# Testing artifacts +junit-*.xml +flake8-errors.txt + +RELEASE.txt +site-packages +reports +test-reports/* From 3854609626d6f280c8e2d6c0dc583cc399cb4a34 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sat, 4 Dec 2021 09:10:26 -0600 Subject: [PATCH 05/51] Adds GitHub Actions to run Tox. #164 --- .github/workflows/run-tests.yaml | 24 ++++++++++++++++++++++++ .travis.yml | 12 ------------ tox.ini | 10 +++++++++- 3 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/run-tests.yaml delete mode 100644 .travis.yml diff --git a/.github/workflows/run-tests.yaml b/.github/workflows/run-tests.yaml new file mode 100644 index 0000000..154beb9 --- /dev/null +++ b/.github/workflows/run-tests.yaml @@ -0,0 +1,24 @@ +name: Run Tox tests +on: + - push + - pull_request + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [ 3.6, 3.7, 3.8, 3.9, 3.10 ] + + steps: + - uses: actions/checkout@v1 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install tox tox-gh-actions + - name: Test with tox + run: tox diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 8ac2512..0000000 --- a/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -sudo: false - -dist: xenial - -language: python - -python: - - "3.6" - -install: pip install tox-travis - -script: tox diff --git a/tox.ini b/tox.ini index 04440c5..e5243f8 100644 --- a/tox.ini +++ b/tox.ini @@ -2,9 +2,17 @@ envlist = begin py36-lint - py36-django{111,2,21,22,3,31} + py{36,37,38,39,10}-django{111,2,21,22,3,31} coverage-report +[gh-actions] +python = + 3.6: py36 + 3.7: py37 + 3.8: py38 + 3.9: py39 + 3.10: py310 + [testenv] deps= django2: Django>=2.0,<2.1 From d2beca9c091e7a95a1674da79f84b259c73b4d6a Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sat, 4 Dec 2021 09:13:45 -0600 Subject: [PATCH 06/51] Updated references to Python 3.10. #164 --- .github/workflows/run-tests.yaml | 2 +- tox.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run-tests.yaml b/.github/workflows/run-tests.yaml index 154beb9..8f42dd8 100644 --- a/.github/workflows/run-tests.yaml +++ b/.github/workflows/run-tests.yaml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [ 3.6, 3.7, 3.8, 3.9, 3.10 ] + python-version: [ 3.6, 3.7, 3.8, 3.9, "3.10" ] steps: - uses: actions/checkout@v1 diff --git a/tox.ini b/tox.ini index e5243f8..21b7ca1 100644 --- a/tox.ini +++ b/tox.ini @@ -2,7 +2,7 @@ envlist = begin py36-lint - py{36,37,38,39,10}-django{111,2,21,22,3,31} + py{36,37,38,39,310}-django{111,2,21,22,3,31} coverage-report [gh-actions] From a1ebb970736ad2e91512191fddd84323ae893345 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sat, 4 Dec 2021 09:17:49 -0600 Subject: [PATCH 07/51] Removed Python 3.10 testing until compatibility established. --- .github/workflows/run-tests.yaml | 2 +- README.md | 2 ++ tox.ini | 3 +-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/run-tests.yaml b/.github/workflows/run-tests.yaml index 8f42dd8..4180436 100644 --- a/.github/workflows/run-tests.yaml +++ b/.github/workflows/run-tests.yaml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [ 3.6, 3.7, 3.8, 3.9, "3.10" ] + python-version: [ 3.6, 3.7, 3.8, 3.9 ] steps: - uses: actions/checkout@v1 diff --git a/README.md b/README.md index 1d723fd..7386fca 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ As a news site, our stories, photos, and other content get divided into "section ## Features of the project +Currently incompatible with Python 3.10. + **Multiple trees, or a single tree.** You can treat all the records as a single tree, shared by all the applications. You can also treat each of the top level records as individual trees, for different apps or uses. diff --git a/tox.ini b/tox.ini index 21b7ca1..1cbc21e 100644 --- a/tox.ini +++ b/tox.ini @@ -2,7 +2,7 @@ envlist = begin py36-lint - py{36,37,38,39,310}-django{111,2,21,22,3,31} + py{36,37,38,39}-django{111,2,21,22,3,31} coverage-report [gh-actions] @@ -11,7 +11,6 @@ python = 3.7: py37 3.8: py38 3.9: py39 - 3.10: py310 [testenv] deps= From efd3b0e3038d03016ce04c323bef62675399c4ab Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sat, 4 Dec 2021 09:34:27 -0600 Subject: [PATCH 08/51] Added codecov uploading to Tox. #164 --- tox.ini | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index 1cbc21e..f827a7b 100644 --- a/tox.ini +++ b/tox.ini @@ -23,6 +23,7 @@ deps= coverage pillow ipdb + codecov -r{toxinidir}/requirements.txt commands= @@ -40,5 +41,6 @@ commands= [testenv:coverage-report] commands = - coverage report -m - coverage html + coverage report -m + coverage html + codecov From bf8229b2f2c9fa93d6a7a88f9168a02b0ccc8d66 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sat, 4 Dec 2021 09:59:04 -0600 Subject: [PATCH 09/51] Updated tox to run coverage commands together. --- tox.ini | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index f827a7b..6c131ce 100644 --- a/tox.ini +++ b/tox.ini @@ -27,7 +27,17 @@ deps= -r{toxinidir}/requirements.txt commands= - coverage run --source=categories --omit='.tox/*,example/*,*/tests/*' {toxinidir}/example/manage.py test --settings='settings-testing' categories{posargs} + coverage erase + coverage run \ + --source=categories \ + --omit='.tox/*,example/*,*/tests/*' \ + {toxinidir}/example/manage.py \ + test \ + --settings='settings-testing' \ + categories{posargs} + coverage report -m + coverage html + codecov [testenv:begin] commands = coverage erase From cacf71737ae2022db013dfebd17c773b16cce81a Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sat, 4 Dec 2021 10:16:54 -0600 Subject: [PATCH 10/51] Changed codecov uploading pattern. --- .github/workflows/run-tests.yaml | 23 +++++++++++++++++++++++ tox.ini | 1 - 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run-tests.yaml b/.github/workflows/run-tests.yaml index 4180436..5d979a8 100644 --- a/.github/workflows/run-tests.yaml +++ b/.github/workflows/run-tests.yaml @@ -12,13 +12,36 @@ jobs: steps: - uses: actions/checkout@v1 + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} + + + - name: Get pip cache dir + id: pip-cache + run: | + echo "::set-output name=dir::$(pip cache dir)" + + - name: Cache + uses: actions/cache@v2 + with: + path: ${{ steps.pip-cache.outputs.dir }} + key: + ${{ matrix.python-version }}-v1-${{ hashFiles('**/requirements.txt') }}-${{ hashFiles('**/tox.ini') }} + restore-keys: | + ${{ matrix.python-version }}-v1- + - name: Install dependencies run: | python -m pip install --upgrade pip pip install tox tox-gh-actions + - name: Test with tox run: tox + + - name: Upload coverage + uses: codecov/codecov-action@v1 + with: + name: Python ${{ matrix.python-version }} diff --git a/tox.ini b/tox.ini index 6c131ce..5782542 100644 --- a/tox.ini +++ b/tox.ini @@ -37,7 +37,6 @@ commands= categories{posargs} coverage report -m coverage html - codecov [testenv:begin] commands = coverage erase From 571623598fb12dbf9fe9f661e3659bf7bc12a037 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sat, 4 Dec 2021 10:27:10 -0600 Subject: [PATCH 11/51] Added XML reporting for code coverage. #164 --- tox.ini | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index 5782542..075aaf2 100644 --- a/tox.ini +++ b/tox.ini @@ -13,6 +13,8 @@ python = 3.9: py39 [testenv] +passenv = GITHUB_* + deps= django2: Django>=2.0,<2.1 django21: Django>=2.1,<2.2 @@ -36,7 +38,7 @@ commands= --settings='settings-testing' \ categories{posargs} coverage report -m - coverage html + coverage xml [testenv:begin] commands = coverage erase @@ -51,5 +53,5 @@ commands= [testenv:coverage-report] commands = coverage report -m - coverage html + coverage xml codecov From 3bfe1ad1313579117bb10921400da68a55a76e0d Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sun, 5 Dec 2021 08:34:15 -0600 Subject: [PATCH 12/51] Added pre-commit configuration and configuration for the tools. --- .pre-commit-config.yaml | 51 +++++++++++++++++++++++++ README.md | 1 + pyproject.toml | 82 +++++++++++++++++++++++++++++++++++++++++ requirements.txt | 4 +- setup.cfg | 36 ++++++++++++++++++ setup.py | 70 +++++++++++++++++++++++------------ 6 files changed, 218 insertions(+), 26 deletions(-) create mode 100644 .pre-commit-config.yaml create mode 100644 pyproject.toml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..9e54b49 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,51 @@ +repos: + - repo: https://github.com/timothycrosley/isort + rev: 5.10.1 + hooks: + - id: isort + additional_dependencies: [toml] + - repo: https://github.com/python/black + rev: 21.11b1 + hooks: + - id: black + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.0.1 + hooks: + - id: check-added-large-files + - id: check-case-conflict + - id: check-executables-have-shebangs + - id: check-json + - id: check-merge-conflict + - id: check-shebang-scripts-are-executable + - id: check-symlinks + - id: check-toml + - id: check-yaml + - id: debug-statements + - id: end-of-file-fixer + exclude: "^tests/resources/" + - id: fix-byte-order-marker + - id: fix-encoding-pragma + args: ["--remove"] + - id: requirements-txt-fixer + - repo: https://gitlab.com/pycqa/flake8 + rev: 3.9.2 + hooks: + - id: flake8 + - repo: https://github.com/pycqa/pydocstyle + rev: 6.1.1 + hooks: + - id: pydocstyle + exclude: test.* + additional_dependencies: [toml] + - repo: https://github.com/terrencepreilly/darglint + rev: v1.8.1 + hooks: + - id: darglint + args: + - -v 2 + - "--message-template={path}:{line} in `{obj}`:\n {msg_id}: {msg}" + - --strictness=short + - repo: https://github.com/econchick/interrogate + rev: 1.5.0 # or master if you're bold + hooks: + - id: interrogate diff --git a/README.md b/README.md index 7386fca..0f8741b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Django Categories [![Jazzband](https://jazzband.co/static/img/badge.svg)](https://jazzband.co/) +[![codecov](https://codecov.io/gh/jazzband/django-categories/branch/master/graph/badge.svg?token=rW8mpdZqWQ)](https://codecov.io/gh/jazzband/django-categories) Django Categories grew out of our need to provide a basic hierarchical taxonomy management system that multiple applications could use independently or in concert. diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..126de67 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,82 @@ +[build-system] +requires = [ + "setuptools >= 40.9.0", + "wheel", +] +build-backend = "setuptools.build_meta" + +[tool.coverage.run] +branch = true +omit = ["**/test_*.py"] + +[tool.coverage.report] +omit = [ + "*site-packages*", + "*tests*", + "*.tox*", +] +show_missing = true +exclude_lines = [ + "raise NotImplementedError", + "pragma: no-coverage", +] + +[tool.interrogate] +ignore-init-method = true +ignore-init-module = false +ignore-magic = true +ignore-semiprivate = false +ignore-private = false +ignore-property-decorators = false +ignore-module = false +ignore-nested-functions = true +ignore-nested-classes = true +ignore-setters = false +fail-under = 95 +exclude = ["setup.py", "docs", "build", "test"] +ignore-regex = ["^get$", "^mock_.*", ".*BaseClass.*"] +verbose = 0 +quiet = false +whitelist-regex = [] +color = true + +[tool.isort] +py_version = "38" +force_grid_wrap = 0 +use_parentheses = true +line_length = 88 +known_typing = ["typing", "types", "typing_extensions", "mypy", "mypy_extensions"] +sections = ["FUTURE", "TYPING", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"] +include_trailing_comma = true +profile = "black" +multi_line_output = 3 +indent = 4 +color_output = true + +[tool.pydocstyle] +convention = "google" +add-ignore = ["D107", "D200", "D212"] +match = "(?!test_).*\\.py" + +[tool.black] +line-length = 119 +target-version = ['py38', 'py39'] +include = '\.pyi?$' +exclude = ''' +/( + \.eggs + | \.git + | \.hg + | \.mypy_cache + | \.tox + | \.venv + | _build + | buck-out + | build + | dist + # The following are specific to Black, you probably don't want those. + | blib2to3 + | tests/data + | profiling +)/ +''' diff --git a/requirements.txt b/requirements.txt index 0d767c5..b0a4601 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -django-mptt==0.11.0 -unicode-slugify==0.1.3 +django-mptt +unicode-slugify diff --git a/setup.cfg b/setup.cfg index 2a9acf1..bfc227d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,2 +1,38 @@ +[metadata] +name = django-categories +description = A way to handle one or more hierarchical category trees in django. +long_description = file:README.md +long_description_content_type = "text/markdown" +author = Corey Oordt +author_email = coreyoordt@gmail.com +url = http://github.com/jazzband/django-categories +classifiers = + Framework :: Django + +[options] +zip_safe=False +include_package_data=True + +[options.packages.find] +exclude = + example* + docs + build +include = categories + +[flake8] +ignore = D203,W503,E501 +exclude = + .git + .tox + docs + build + dist + doc_src +max-line-length = 119 + +[darglint] +ignore=DAR402 + [bdist_wheel] universal = 1 diff --git a/setup.py b/setup.py index 834ce3c..da41c03 100644 --- a/setup.py +++ b/setup.py @@ -1,31 +1,53 @@ -from setuptools import setup, find_packages +"""The setup script.""" + +from pathlib import Path + +from setuptools import setup + import categories -import os -try: - long_description = open('README.md').read() -except IOError: - long_description = '' -try: - reqs = open(os.path.join(os.path.dirname(__file__), 'requirements.txt')).read() -except (IOError, OSError): - reqs = '' +def parse_reqs(filepath: str) -> list: + """ + Parse a file path containing requirements and return a list of requirements. + + Will properly follow ``-r`` and ``--requirements`` links like ``pip``. This + means nested requirements will be returned as one list. + + Other ``pip``-specific lines are excluded. + + Args: + filepath: The path to the requirements file + + Returns: + All the requirements as a list. + """ + path = Path(filepath) + reqstr = path.read_text() + reqs = [] + for line in reqstr.splitlines(): + line = line.strip() + if line == "": + continue + elif not line or line.startswith("#"): + # comments are lines that start with # only + continue + elif line.startswith("-r") or line.startswith("--requirement"): + _, new_filename = line.split() + new_file_path = path.parent / new_filename + reqs.extend(parse_reqs(new_file_path)) + elif line.startswith("-f") or line.startswith("-i") or line.startswith("--"): + continue + elif line.startswith("-Z") or line.startswith("--always-unzip"): + continue + else: + reqs.append(line) + return reqs + + +requirements = parse_reqs("requirements.txt") setup( - name='django-categories', version=categories.get_version(), - description='A way to handle one or more hierarchical category trees in django.', - long_description=long_description, - long_description_content_type="text/markdown", - author='Corey Oordt', - author_email='coreyoordt@gmail.com', - include_package_data=True, - url='http://github.com/jazzband/django-categories', - packages=find_packages(exclude=['example*', ]), - classifiers=[ - 'Framework :: Django', - ], - install_requires=reqs, - dependency_links=[] + install_requires=requirements, ) From 5961d6b80ffcd85e791f7f7c073ae820a1ef985e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 5 Dec 2021 14:34:46 +0000 Subject: [PATCH 13/51] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- LICENSE.txt | 1 - categories/__init__.py | 24 ++- categories/admin.py | 74 ++++---- categories/apps.py | 15 +- categories/base.py | 96 +++++----- categories/editor/settings.py | 10 +- .../editor/static/editor/jquery.treeTable.css | 2 +- .../editor/static/editor/jquery.treeTable.js | 2 +- .../editor/grappelli_tree_list_results.html | 2 +- .../templates/admin/editor/tree_editor.html | 2 +- .../templatetags/admin_tree_list_tags.py | 70 ++++---- categories/editor/tree_editor.py | 170 ++++++++++-------- categories/fields.py | 11 +- categories/fixtures/musicgenres.json | 2 +- categories/fixtures/test_category_spaces.txt | 2 +- categories/fixtures/test_category_tabs.txt | 2 +- categories/genericcollection.py | 13 +- categories/locale/it/LC_MESSAGES/django.po | 1 - .../commands/add_category_fields.py | 8 +- .../commands/drop_category_field.py | 15 +- .../management/commands/import_categories.py | 27 +-- categories/migration.py | 12 +- categories/migrations/0001_initial.py | 132 ++++++++++---- .../migrations/0002_auto_20170217_1111.py | 21 ++- .../migrations/0003_auto_20200306_1050.py | 33 ++-- .../migrations/0004_auto_20200517_1832.py | 14 +- categories/models.py | 88 +++++---- categories/registration.py | 70 ++++---- categories/settings.py | 44 ++--- categories/static/js/genericcollections.js | 2 +- .../templates/categories/ancestors_ul.html | 2 +- categories/templates/categories/base.html | 2 +- .../templates/categories/breadcrumbs.html | 2 +- .../templates/categories/category_detail.html | 2 +- .../templates/categories/category_list.html | 2 +- categories/templates/categories/ul_tree.html | 2 +- categories/templatetags/category_tags.py | 102 ++++++----- categories/tests/test_admin.py | 66 +++---- categories/tests/test_category_import.py | 35 ++-- categories/tests/test_manager.py | 5 +- categories/tests/test_mgmt_commands.py | 10 +- categories/tests/test_models.py | 11 +- categories/tests/test_registration.py | 36 ++-- categories/tests/test_templatetags.py | 49 ++--- categories/tests/test_views.py | 64 +++---- categories/urls.py | 18 +- categories/views.py | 101 +++++------ doc_src/_static/default.css | 2 +- doc_src/_static/toc.js | 2 +- doc_src/adding_the_fields.rst | 2 +- doc_src/code_examples/custom_categories1.py | 2 +- doc_src/code_examples/custom_categories3.py | 28 ++- doc_src/code_examples/custom_categories4.py | 3 +- doc_src/code_examples/custom_categories5.py | 4 +- doc_src/code_examples/custom_categories6.py | 6 +- doc_src/code_examples/custom_categories7.py | 29 +-- doc_src/conf.py | 25 ++- doc_src/index.rst | 1 - doc_src/reference/management_commands.rst | 2 +- doc_src/reference/settings.rst | 2 +- doc_src/usage.rst | 1 - doc_src/usage_example_template.html | 2 +- example/settings-testing.py | 127 +++++++------ example/settings.py | 130 +++++++------- example/simpletext/admin.py | 17 +- example/simpletext/migrations/0001_initial.py | 53 +++--- .../migrations/0002_auto_20171204_0721.py | 37 ++-- .../migrations/0003_auto_20200306_0928.py | 14 +- example/simpletext/models.py | 15 +- example/simpletext/tests.py | 6 +- example/static/editor/jquery.treeTable.css | 2 +- example/static/editor/jquery.treeTable.js | 2 +- example/static/js/genericcollections.js | 2 +- example/urls.py | 15 +- 74 files changed, 1079 insertions(+), 926 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 57bc88a..261eeb9 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -199,4 +199,3 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - diff --git a/categories/__init__.py b/categories/__init__.py index 7808fc0..0dad974 100644 --- a/categories/__init__.py +++ b/categories/__init__.py @@ -1,23 +1,19 @@ -__version_info__ = { - 'major': 1, - 'minor': 8, - 'micro': 0, - 'releaselevel': 'final', - 'serial': 1 -} +__version_info__ = {"major": 1, "minor": 8, "micro": 0, "releaselevel": "final", "serial": 1} def get_version(short=False): - assert __version_info__['releaselevel'] in ('alpha', 'beta', 'final') - vers = ["%(major)i.%(minor)i" % __version_info__, ] - if __version_info__['micro'] and not short: + assert __version_info__["releaselevel"] in ("alpha", "beta", "final") + vers = [ + "%(major)i.%(minor)i" % __version_info__, + ] + if __version_info__["micro"] and not short: vers.append(".%(micro)i" % __version_info__) - if __version_info__['releaselevel'] != 'final' and not short: - vers.append('%s%i' % (__version_info__['releaselevel'][0], __version_info__['serial'])) - return ''.join(vers) + if __version_info__["releaselevel"] != "final" and not short: + vers.append("%s%i" % (__version_info__["releaselevel"][0], __version_info__["serial"])) + return "".join(vers) __version__ = get_version() -default_app_config = 'categories.apps.CategoriesConfig' +default_app_config = "categories.apps.CategoriesConfig" diff --git a/categories/admin.py b/categories/admin.py index 5c0eaba..5c11755 100644 --- a/categories/admin.py +++ b/categories/admin.py @@ -1,17 +1,17 @@ -from django.contrib import admin from django import forms +from django.contrib import admin from django.utils.translation import ugettext_lazy as _ +from .base import CategoryBaseAdmin, CategoryBaseAdminForm from .genericcollection import GenericCollectionTabularInline -from .settings import RELATION_MODELS, JAVASCRIPT_URL, REGISTER_ADMIN from .models import Category -from .base import CategoryBaseAdminForm, CategoryBaseAdmin -from .settings import MODEL_REGISTRY +from .settings import JAVASCRIPT_URL, MODEL_REGISTRY, REGISTER_ADMIN, RELATION_MODELS class NullTreeNodeChoiceField(forms.ModelChoiceField): """A ModelChoiceField for tree nodes.""" - def __init__(self, level_indicator='---', *args, **kwargs): + + def __init__(self, level_indicator="---", *args, **kwargs): self.level_indicator = level_indicator super(NullTreeNodeChoiceField, self).__init__(*args, **kwargs) @@ -20,7 +20,7 @@ class NullTreeNodeChoiceField(forms.ModelChoiceField): Creates labels which represent the tree level of each node when generating option labels. """ - return '%s %s' % (self.level_indicator * getattr(obj, obj._mptt_meta.level_attr), obj) + return "%s %s" % (self.level_indicator * getattr(obj, obj._mptt_meta.level_attr), obj) if RELATION_MODELS: @@ -33,38 +33,43 @@ if RELATION_MODELS: class CategoryAdminForm(CategoryBaseAdminForm): class Meta: model = Category - fields = '__all__' + fields = "__all__" def clean_alternate_title(self): - if self.instance is None or not self.cleaned_data['alternate_title']: - return self.cleaned_data['name'] + if self.instance is None or not self.cleaned_data["alternate_title"]: + return self.cleaned_data["name"] else: - return self.cleaned_data['alternate_title'] + return self.cleaned_data["alternate_title"] class CategoryAdmin(CategoryBaseAdmin): form = CategoryAdminForm - list_display = ('name', 'alternate_title', 'active') + list_display = ("name", "alternate_title", "active") fieldsets = ( - (None, { - 'fields': ('parent', 'name', 'thumbnail', 'active') - }), - (_('Meta Data'), { - 'fields': ('alternate_title', 'alternate_url', 'description', - 'meta_keywords', 'meta_extra'), - 'classes': ('collapse',), - }), - (_('Advanced'), { - 'fields': ('order', 'slug'), - 'classes': ('collapse',), - }), + (None, {"fields": ("parent", "name", "thumbnail", "active")}), + ( + _("Meta Data"), + { + "fields": ("alternate_title", "alternate_url", "description", "meta_keywords", "meta_extra"), + "classes": ("collapse",), + }, + ), + ( + _("Advanced"), + { + "fields": ("order", "slug"), + "classes": ("collapse",), + }, + ), ) if RELATION_MODELS: - inlines = [InlineCategoryRelation, ] + inlines = [ + InlineCategoryRelation, + ] class Media: - js = (JAVASCRIPT_URL + 'genericcollections.js',) + js = (JAVASCRIPT_URL + "genericcollections.js",) if REGISTER_ADMIN: @@ -72,18 +77,21 @@ if REGISTER_ADMIN: for model, modeladmin in list(admin.site._registry.items()): if model in list(MODEL_REGISTRY.values()) and modeladmin.fieldsets: - fieldsets = getattr(modeladmin, 'fieldsets', ()) - fields = [cat.split('.')[2] for cat in MODEL_REGISTRY if MODEL_REGISTRY[cat] == model] + fieldsets = getattr(modeladmin, "fieldsets", ()) + fields = [cat.split(".")[2] for cat in MODEL_REGISTRY if MODEL_REGISTRY[cat] == model] # check each field to see if already defined for cat in fields: for k, v in fieldsets: - if cat in v['fields']: + if cat in v["fields"]: fields.remove(cat) # if there are any fields left, add them under the categories fieldset if len(fields) > 0: admin.site.unregister(model) - admin.site.register(model, type('newadmin', (modeladmin.__class__,), { - 'fieldsets': fieldsets + (('Categories', { - 'fields': fields - }),) - })) + admin.site.register( + model, + type( + "newadmin", + (modeladmin.__class__,), + {"fieldsets": fieldsets + (("Categories", {"fields": fields}),)}, + ), + ) diff --git a/categories/apps.py b/categories/apps.py index 02e70e0..1bc058e 100644 --- a/categories/apps.py +++ b/categories/apps.py @@ -2,16 +2,18 @@ from django.apps import AppConfig class CategoriesConfig(AppConfig): - name = 'categories' + name = "categories" verbose_name = "Categories" def __init__(self, *args, **kwargs): super(CategoriesConfig, self).__init__(*args, **kwargs) from django.db.models.signals import class_prepared + class_prepared.connect(handle_class_prepared) def ready(self): from django.db.models.signals import post_migrate + from .migration import migrate_app post_migrate.connect(migrate_app) @@ -21,17 +23,18 @@ def handle_class_prepared(sender, **kwargs): """ See if this class needs registering of fields """ - from .settings import M2M_REGISTRY, FK_REGISTRY from .registration import registry + from .settings import FK_REGISTRY, M2M_REGISTRY + sender_app = sender._meta.app_label sender_name = sender._meta.model_name for key, val in list(FK_REGISTRY.items()): - app_name, model_name = key.split('.') + app_name, model_name = key.split(".") if app_name == sender_app and sender_name == model_name: - registry.register_model(app_name, sender, 'ForeignKey', val) + registry.register_model(app_name, sender, "ForeignKey", val) for key, val in list(M2M_REGISTRY.items()): - app_name, model_name = key.split('.') + app_name, model_name = key.split(".") if app_name == sender_app and sender_name == model_name: - registry.register_model(app_name, sender, 'ManyToManyField', val) + registry.register_model(app_name, sender, "ManyToManyField", val) diff --git a/categories/base.py b/categories/base.py index 29319f4..9517565 100644 --- a/categories/base.py +++ b/categories/base.py @@ -4,25 +4,23 @@ with customizable metadata and its own name space. """ import sys +from django import forms from django.contrib import admin from django.db import models -from django import forms from django.utils.encoding import force_text - -from mptt.models import MPTTModel +from django.utils.translation import ugettext_lazy as _ from mptt.fields import TreeForeignKey from mptt.managers import TreeManager +from mptt.models import MPTTModel from slugify import slugify from .editor.tree_editor import TreeEditor from .settings import ALLOW_SLUG_CHANGE, SLUG_TRANSLITERATOR -from django.utils.translation import ugettext_lazy as _ - - if sys.version_info[0] < 3: # Remove this after dropping support of Python 2 from django.utils.encoding import python_2_unicode_compatible else: + def python_2_unicode_compatible(x): return x @@ -31,6 +29,7 @@ class CategoryManager(models.Manager): """ A manager that adds an "active()" method for all active categories """ + def active(self): """ Only categories that are active @@ -44,17 +43,18 @@ class CategoryBase(MPTTModel): This base model includes the absolute bare bones fields and methods. One could simply subclass this model and do nothing else and it should work. """ + parent = TreeForeignKey( - 'self', + "self", on_delete=models.CASCADE, blank=True, null=True, - related_name='children', - verbose_name=_('parent'), + related_name="children", + verbose_name=_("parent"), ) - name = models.CharField(max_length=100, verbose_name=_('name')) - slug = models.SlugField(verbose_name=_('slug')) - active = models.BooleanField(default=True, verbose_name=_('active')) + name = models.CharField(max_length=100, verbose_name=_("name")) + slug = models.SlugField(verbose_name=_("slug")) + active = models.BooleanField(default=True, verbose_name=_("active")) objects = CategoryManager() tree = TreeManager() @@ -78,23 +78,28 @@ class CategoryBase(MPTTModel): def __str__(self): ancestors = self.get_ancestors() - return ' > '.join([force_text(i.name) for i in ancestors] + [self.name, ]) + return " > ".join( + [force_text(i.name) for i in ancestors] + + [ + self.name, + ] + ) class Meta: abstract = True - unique_together = ('parent', 'name') - ordering = ('tree_id', 'lft') + unique_together = ("parent", "name") + ordering = ("tree_id", "lft") class MPTTMeta: - order_insertion_by = 'name' + order_insertion_by = "name" class CategoryBaseAdminForm(forms.ModelForm): def clean_slug(self): - if not self.cleaned_data.get('slug', None): + if not self.cleaned_data.get("slug", None): if self.instance is None or not ALLOW_SLUG_CHANGE: - self.cleaned_data['slug'] = slugify(SLUG_TRANSLITERATOR(self.cleaned_data['name'])) - return self.cleaned_data['slug'][:50] + self.cleaned_data["slug"] = slugify(SLUG_TRANSLITERATOR(self.cleaned_data["name"])) + return self.cleaned_data["slug"][:50] def clean(self): @@ -107,72 +112,71 @@ class CategoryBaseAdminForm(forms.ModelForm): # Validate slug is valid in that level kwargs = {} - if self.cleaned_data.get('parent', None) is None: - kwargs['parent__isnull'] = True + if self.cleaned_data.get("parent", None) is None: + kwargs["parent__isnull"] = True else: - kwargs['parent__pk'] = int(self.cleaned_data['parent'].id) - this_level_slugs = [c['slug'] for c in opts.model.objects.filter(**kwargs).values('id', 'slug') if c['id'] != self.instance.id] - if self.cleaned_data['slug'] in this_level_slugs: - raise forms.ValidationError(_('The slug must be unique among ' - 'the items at its level.')) + kwargs["parent__pk"] = int(self.cleaned_data["parent"].id) + this_level_slugs = [ + c["slug"] for c in opts.model.objects.filter(**kwargs).values("id", "slug") if c["id"] != self.instance.id + ] + if self.cleaned_data["slug"] in this_level_slugs: + raise forms.ValidationError(_("The slug must be unique among " "the items at its level.")) # Validate Category Parent # Make sure the category doesn't set itself or any of its children as # its parent. - if self.cleaned_data.get('parent', None) is None or self.instance.id is None: + if self.cleaned_data.get("parent", None) is None or self.instance.id is None: return self.cleaned_data if self.instance.pk: - decendant_ids = self.instance.get_descendants().values_list('id', flat=True) + decendant_ids = self.instance.get_descendants().values_list("id", flat=True) else: decendant_ids = [] - if self.cleaned_data['parent'].id == self.instance.id: - raise forms.ValidationError(_("You can't set the parent of the " - "item to itself.")) - elif self.cleaned_data['parent'].id in decendant_ids: - raise forms.ValidationError(_("You can't set the parent of the " - "item to a descendant.")) + if self.cleaned_data["parent"].id == self.instance.id: + raise forms.ValidationError(_("You can't set the parent of the " "item to itself.")) + elif self.cleaned_data["parent"].id in decendant_ids: + raise forms.ValidationError(_("You can't set the parent of the " "item to a descendant.")) return self.cleaned_data class CategoryBaseAdmin(TreeEditor, admin.ModelAdmin): form = CategoryBaseAdminForm - list_display = ('name', 'active') - search_fields = ('name',) - prepopulated_fields = {'slug': ('name',)} + list_display = ("name", "active") + search_fields = ("name",) + prepopulated_fields = {"slug": ("name",)} - actions = ['activate', 'deactivate'] + actions = ["activate", "deactivate"] def get_actions(self, request): actions = super(CategoryBaseAdmin, self).get_actions(request) - if 'delete_selected' in actions: - del actions['delete_selected'] + if "delete_selected" in actions: + del actions["delete_selected"] return actions def deactivate(self, request, queryset): """ Set active to False for selected items """ - selected_cats = self.model.objects.filter( - pk__in=[int(x) for x in request.POST.getlist('_selected_action')]) + selected_cats = self.model.objects.filter(pk__in=[int(x) for x in request.POST.getlist("_selected_action")]) for item in selected_cats: if item.active: item.active = False item.save() item.children.all().update(active=False) - deactivate.short_description = _('Deactivate selected categories and their children') + + deactivate.short_description = _("Deactivate selected categories and their children") def activate(self, request, queryset): """ Set active to True for selected items """ - selected_cats = self.model.objects.filter( - pk__in=[int(x) for x in request.POST.getlist('_selected_action')]) + selected_cats = self.model.objects.filter(pk__in=[int(x) for x in request.POST.getlist("_selected_action")]) for item in selected_cats: item.active = True item.save() item.children.all().update(active=True) - activate.short_description = _('Activate selected categories and their children') + + activate.short_description = _("Activate selected categories and their children") diff --git a/categories/editor/settings.py b/categories/editor/settings.py index af293e5..5ea2e61 100644 --- a/categories/editor/settings.py +++ b/categories/editor/settings.py @@ -1,13 +1,13 @@ -from django.conf import settings import django +from django.conf import settings DJANGO10_COMPAT = django.VERSION[0] < 1 or (django.VERSION[0] == 1 and django.VERSION[1] < 1) -STATIC_URL = getattr(settings, 'STATIC_URL', settings.MEDIA_URL) +STATIC_URL = getattr(settings, "STATIC_URL", settings.MEDIA_URL) if STATIC_URL is None: STATIC_URL = settings.MEDIA_URL -MEDIA_PATH = getattr(settings, 'EDITOR_MEDIA_PATH', '%seditor/' % STATIC_URL) +MEDIA_PATH = getattr(settings, "EDITOR_MEDIA_PATH", "%seditor/" % STATIC_URL) -TREE_INITIAL_STATE = getattr(settings, 'EDITOR_TREE_INITIAL_STATE', 'collapsed') +TREE_INITIAL_STATE = getattr(settings, "EDITOR_TREE_INITIAL_STATE", "collapsed") -IS_GRAPPELLI_INSTALLED = 'grappelli' in settings.INSTALLED_APPS +IS_GRAPPELLI_INSTALLED = "grappelli" in settings.INSTALLED_APPS diff --git a/categories/editor/static/editor/jquery.treeTable.css b/categories/editor/static/editor/jquery.treeTable.css index 9d9a263..07421f1 100644 --- a/categories/editor/static/editor/jquery.treeTable.css +++ b/categories/editor/static/editor/jquery.treeTable.css @@ -66,4 +66,4 @@ .treeTable .ui-draggable-dragging { color: #000; z-index: 1; -} \ No newline at end of file +} diff --git a/categories/editor/static/editor/jquery.treeTable.js b/categories/editor/static/editor/jquery.treeTable.js index 38f7bcb..ea2a88b 100644 --- a/categories/editor/static/editor/jquery.treeTable.js +++ b/categories/editor/static/editor/jquery.treeTable.js @@ -460,4 +460,4 @@ function parentOf(node) { return $(node).parentOf(); } -})(django.jQuery); \ No newline at end of file +})(django.jQuery); diff --git a/categories/editor/templates/admin/editor/grappelli_tree_list_results.html b/categories/editor/templates/admin/editor/grappelli_tree_list_results.html index 379471e..f5b5e5b 100644 --- a/categories/editor/templates/admin/editor/grappelli_tree_list_results.html +++ b/categories/editor/templates/admin/editor/grappelli_tree_list_results.html @@ -25,4 +25,4 @@ -{% endif %} \ No newline at end of file +{% endif %} diff --git a/categories/editor/templates/admin/editor/tree_editor.html b/categories/editor/templates/admin/editor/tree_editor.html index 9179640..337da05 100644 --- a/categories/editor/templates/admin/editor/tree_editor.html +++ b/categories/editor/templates/admin/editor/tree_editor.html @@ -36,4 +36,4 @@ {% if action_form and actions_on_top and cl.full_result_count %}{% admin_actions %}{% endif %} {% result_tree_list cl %} {% if action_form and actions_on_bottom and cl.full_result_count %}{% admin_actions %}{% endif %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/categories/editor/templatetags/admin_tree_list_tags.py b/categories/editor/templatetags/admin_tree_list_tags.py index 6ef6e95..160752b 100644 --- a/categories/editor/templatetags/admin_tree_list_tags.py +++ b/categories/editor/templatetags/admin_tree_list_tags.py @@ -1,29 +1,30 @@ import django +from django.contrib.admin.templatetags.admin_list import _boolean_icon, result_headers +from django.contrib.admin.utils import lookup_field +from django.core.exceptions import ObjectDoesNotExist from django.db import models from django.template import Library -from django.contrib.admin.templatetags.admin_list import result_headers, _boolean_icon -from django.contrib.admin.utils import lookup_field -from categories.editor.utils import display_for_field -from django.core.exceptions import ObjectDoesNotExist -from django.utils.encoding import smart_text, force_text -from django.utils.html import escape, conditional_escape, escapejs, format_html +from django.utils.encoding import force_text, smart_text +from django.utils.html import conditional_escape, escape, escapejs, format_html from django.utils.safestring import mark_safe from categories.editor import settings +from categories.editor.utils import display_for_field register = Library() -TREE_LIST_RESULTS_TEMPLATE = 'admin/editor/tree_list_results.html' +TREE_LIST_RESULTS_TEMPLATE = "admin/editor/tree_list_results.html" if settings.IS_GRAPPELLI_INSTALLED: - TREE_LIST_RESULTS_TEMPLATE = 'admin/editor/grappelli_tree_list_results.html' + TREE_LIST_RESULTS_TEMPLATE = "admin/editor/grappelli_tree_list_results.html" def get_empty_value_display(cl): - if hasattr(cl.model_admin, 'get_empty_value_display'): + if hasattr(cl.model_admin, "get_empty_value_display"): return cl.model_admin.get_empty_value_display() else: # Django < 1.9 from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE + return EMPTY_CHANGELIST_VALUE @@ -34,7 +35,7 @@ def items_for_tree_result(cl, result, form): first = True pk = cl.lookup_opts.pk.attname for field_name in cl.list_display: - row_class = '' + row_class = "" try: f, attr, value = lookup_field(field_name, result, cl.model_admin) except (AttributeError, ObjectDoesNotExist): @@ -42,10 +43,10 @@ def items_for_tree_result(cl, result, form): else: if f is None: if django.VERSION[0] == 1 and django.VERSION[1] == 4: - if field_name == 'action_checkbox': + if field_name == "action_checkbox": row_class = ' class="action-checkbox disclosure"' - allow_tags = getattr(attr, 'allow_tags', False) - boolean = getattr(attr, 'boolean', False) + allow_tags = getattr(attr, "allow_tags", False) + boolean = getattr(attr, "boolean", False) if boolean: allow_tags = True result_repr = _boolean_icon(value) @@ -60,16 +61,16 @@ def items_for_tree_result(cl, result, form): else: if value is None: result_repr = get_empty_value_display(cl) - if hasattr(f, 'rel') and isinstance(f.rel, models.ManyToOneRel): + if hasattr(f, "rel") and isinstance(f.rel, models.ManyToOneRel): result_repr = escape(getattr(result, f.name)) else: - result_repr = display_for_field(value, f, '') + result_repr = display_for_field(value, f, "") if isinstance(f, models.DateField) or isinstance(f, models.TimeField): row_class = ' class="nowrap"' if first: if django.VERSION[0] == 1 and django.VERSION[1] < 4: try: - f, attr, checkbox_value = lookup_field('action_checkbox', result, cl.model_admin) + f, attr, checkbox_value = lookup_field("action_checkbox", result, cl.model_admin) if row_class: row_class = "%s%s" % (row_class[:-1], ' disclosure"') else: @@ -77,14 +78,14 @@ def items_for_tree_result(cl, result, form): except (AttributeError, ObjectDoesNotExist): pass - if force_text(result_repr) == '': - result_repr = mark_safe(' ') + if force_text(result_repr) == "": + result_repr = mark_safe(" ") # If list_display_links not defined, add the link tag to the first field if (first and not cl.list_display_links) or field_name in cl.list_display_links: if django.VERSION[0] == 1 and django.VERSION[1] < 4: - table_tag = 'td' # {True:'th', False:'td'}[first] + table_tag = "td" # {True:'th', False:'td'}[first] else: - table_tag = {True: 'th', False: 'td'}[first] + table_tag = {True: "th", False: "td"}[first] url = cl.url_for_result(result) # Convert the pk to something that can be used in Javascript. @@ -104,9 +105,14 @@ def items_for_tree_result(cl, result, form): row_class, url, format_html( - ' onclick="opener.dismissRelatedLookupPopup(window, ' - ''{}'); return false;"', result_id - ) if cl.is_popup else '', result_repr, table_tag) + ' onclick="opener.dismissRelatedLookupPopup(window, ' ''{}'); return false;"', + result_id, + ) + if cl.is_popup + else "", + result_repr, + table_tag, + ) ) else: @@ -118,9 +124,9 @@ def items_for_tree_result(cl, result, form): result_repr = mark_safe(force_text(bf.errors) + force_text(bf)) else: result_repr = conditional_escape(result_repr) - yield mark_safe(smart_text('%s' % (row_class, result_repr))) + yield mark_safe(smart_text("%s" % (row_class, result_repr))) if form and not form[cl.model._meta.pk.name].is_hidden: - yield mark_safe(smart_text('%s' % force_text(form[cl.model._meta.pk.name]))) + yield mark_safe(smart_text("%s" % force_text(form[cl.model._meta.pk.name]))) class TreeList(list): @@ -131,7 +137,7 @@ def tree_results(cl): if cl.formset: for res, form in zip(cl.result_list, cl.formset.forms): result = TreeList(items_for_tree_result(cl, res, form)) - if hasattr(res, 'pk'): + if hasattr(res, "pk"): result.pk = res.pk if res.parent: result.parent_pk = res.parent.pk @@ -141,7 +147,7 @@ def tree_results(cl): else: for res in cl.result_list: result = TreeList(items_for_tree_result(cl, res, None)) - if hasattr(res, 'pk'): + if hasattr(res, "pk"): result.pk = res.pk if res.parent: result.parent_pk = res.parent.pk @@ -155,14 +161,12 @@ def result_tree_list(cl): Displays the headers and data list together """ import django - result = { - 'cl': cl, - 'result_headers': list(result_headers(cl)), - 'results': list(tree_results(cl)) - } + + result = {"cl": cl, "result_headers": list(result_headers(cl)), "results": list(tree_results(cl))} if django.VERSION[0] == 1 and django.VERSION[1] > 2: from django.contrib.admin.templatetags.admin_list import result_hidden_fields - result['result_hidden_fields'] = list(result_hidden_fields(cl)) + + result["result_hidden_fields"] = list(result_hidden_fields(cl)) return result diff --git a/categories/editor/tree_editor.py b/categories/editor/tree_editor.py index f832df5..45c70d1 100644 --- a/categories/editor/tree_editor.py +++ b/categories/editor/tree_editor.py @@ -1,12 +1,11 @@ -from django.contrib import admin -from django.db.models.query import QuerySet -from django.contrib.admin.views.main import ChangeList -from django.http import HttpResponseRedirect -from django.utils.translation import ugettext_lazy as _ -from django.contrib.admin.options import IncorrectLookupParameters -from django.shortcuts import render - import django +from django.contrib import admin +from django.contrib.admin.options import IncorrectLookupParameters +from django.contrib.admin.views.main import ChangeList +from django.db.models.query import QuerySet +from django.http import HttpResponseRedirect +from django.shortcuts import render +from django.utils.translation import ugettext_lazy as _ from . import settings @@ -24,6 +23,7 @@ class TreeEditorQuerySet(QuerySet): in the result set, so the resulting tree display actually makes sense. """ + def iterator(self): qs = self # Reaching into the bowels of query sets to find out whether the qs is @@ -36,9 +36,9 @@ class TreeEditorQuerySet(QuerySet): # this cuts down the number of queries considerably since all ancestors # will already be in include_pages when they are checked, thus not # trigger additional queries. - for p in super(TreeEditorQuerySet, self.order_by('rght')).iterator(): + for p in super(TreeEditorQuerySet, self.order_by("rght")).iterator(): if p.parent_id and p.parent_id not in include_pages and p.id not in include_pages: - ancestor_id_list = p.get_ancestors().values_list('id', flat=True) + ancestor_id_list = p.get_ancestors().values_list("id", flat=True) include_pages.update(ancestor_id_list) if include_pages: @@ -68,18 +68,18 @@ class TreeEditorQuerySet(QuerySet): class TreeChangeList(ChangeList): def _get_default_ordering(self): if django.VERSION[0] == 1 and django.VERSION[1] < 4: - return '', '' # ('tree_id', 'lft') + return "", "" # ('tree_id', 'lft') else: return [] def get_ordering(self, request=None, queryset=None): if django.VERSION[0] == 1 and django.VERSION[1] < 4: - return '', '' # ('tree_id', 'lft') + return "", "" # ('tree_id', 'lft') else: return [] def get_queryset(self, *args, **kwargs): - qs = super(TreeChangeList, self).get_queryset(*args, **kwargs).order_by('tree_id', 'lft') + qs = super(TreeChangeList, self).get_queryset(*args, **kwargs).order_by("tree_id", "lft") return qs @@ -88,18 +88,18 @@ class TreeEditor(admin.ModelAdmin): list_max_show_all = 200 # new in django 1.4 class Media: - css = {'all': (settings.MEDIA_PATH + "jquery.treeTable.css", )} + css = {"all": (settings.MEDIA_PATH + "jquery.treeTable.css",)} js = [] - js.extend((settings.MEDIA_PATH + "jquery.treeTable.js", )) + js.extend((settings.MEDIA_PATH + "jquery.treeTable.js",)) def __init__(self, *args, **kwargs): super(TreeEditor, self).__init__(*args, **kwargs) self.list_display = list(self.list_display) - if 'action_checkbox' in self.list_display: - self.list_display.remove('action_checkbox') + if "action_checkbox" in self.list_display: + self.list_display.remove("action_checkbox") opts = self.model._meta @@ -108,9 +108,9 @@ class TreeEditor(admin.ModelAdmin): grappelli_prefix = "grappelli_" self.change_list_template = [ - 'admin/%s/%s/editor/%stree_editor.html' % (opts.app_label, opts.object_name.lower(), grappelli_prefix), - 'admin/%s/editor/%stree_editor.html' % (opts.app_label, grappelli_prefix), - 'admin/editor/%stree_editor.html' % grappelli_prefix, + "admin/%s/%s/editor/%stree_editor.html" % (opts.app_label, opts.object_name.lower(), grappelli_prefix), + "admin/%s/editor/%stree_editor.html" % (opts.app_label, grappelli_prefix), + "admin/editor/%stree_editor.html" % grappelli_prefix, ] def get_changelist(self, request, **kwargs): @@ -125,6 +125,7 @@ class TreeEditor(admin.ModelAdmin): from django.core.exceptions import PermissionDenied from django.utils.encoding import force_text from django.utils.translation import ungettext + opts = self.model._meta app_label = opts.app_label if not self.has_change_permission(request, None): @@ -137,31 +138,56 @@ class TreeEditor(admin.ModelAdmin): list_display = list(self.list_display) if not actions: try: - list_display.remove('action_checkbox') + list_display.remove("action_checkbox") except ValueError: pass try: if django.VERSION[0] == 1 and django.VERSION[1] < 4: params = ( - request, self.model, list_display, - self.list_display_links, self.list_filter, self.date_hierarchy, - self.search_fields, self.list_select_related, - self.list_per_page, self.list_editable, self) + request, + self.model, + list_display, + self.list_display_links, + self.list_filter, + self.date_hierarchy, + self.search_fields, + self.list_select_related, + self.list_per_page, + self.list_editable, + self, + ) elif django.VERSION[0] == 1 or (django.VERSION[0] == 2 and django.VERSION[1] < 1): params = ( - request, self.model, list_display, - self.list_display_links, self.list_filter, self.date_hierarchy, - self.search_fields, self.list_select_related, - self.list_per_page, self.list_max_show_all, - self.list_editable, self) + request, + self.model, + list_display, + self.list_display_links, + self.list_filter, + self.date_hierarchy, + self.search_fields, + self.list_select_related, + self.list_per_page, + self.list_max_show_all, + self.list_editable, + self, + ) else: params = ( - request, self.model, list_display, - self.list_display_links, self.list_filter, self.date_hierarchy, - self.search_fields, self.list_select_related, - self.list_per_page, self.list_max_show_all, - self.list_editable, self, self.sortable_by) + request, + self.model, + list_display, + self.list_display_links, + self.list_filter, + self.date_hierarchy, + self.search_fields, + self.list_select_related, + self.list_per_page, + self.list_max_show_all, + self.list_editable, + self, + self.sortable_by, + ) cl = TreeChangeList(*params) except IncorrectLookupParameters: # Wacky lookup parameters were given, so redirect to the main @@ -170,15 +196,13 @@ class TreeEditor(admin.ModelAdmin): # the 'invalid=1' parameter was already in the query string, something # is screwed up with the database, so display an error page. if ERROR_FLAG in list(request.GET.keys()): - return render( - request, - 'admin/invalid_setup.html', {'title': _('Database error')}) - return HttpResponseRedirect(request.path + '?' + ERROR_FLAG + '=1') + return render(request, "admin/invalid_setup.html", {"title": _("Database error")}) + return HttpResponseRedirect(request.path + "?" + ERROR_FLAG + "=1") # If the request was POSTed, this might be a bulk action or a bulk edit. # Try to look up an action first, but if this isn't an action the POST # will fall through to the bulk edit check, below. - if actions and request.method == 'POST': + if actions and request.method == "POST": response = self.response_action(request, queryset=cl.get_queryset()) if response: return response @@ -191,9 +215,7 @@ class TreeEditor(admin.ModelAdmin): # Handle POSTed bulk-edit data. if request.method == "POST" and self.list_editable: FormSet = self.get_changelist_formset(request) - formset = cl.formset = FormSet( - request.POST, request.FILES, queryset=cl.result_list - ) + formset = cl.formset = FormSet(request.POST, request.FILES, queryset=cl.result_list) if formset.is_valid(): changecount = 0 for form in formset.forms: @@ -213,9 +235,8 @@ class TreeEditor(admin.ModelAdmin): msg = ungettext( "%(count)s %(name)s was changed successfully.", "%(count)s %(name)s were changed successfully.", - changecount) % {'count': changecount, - 'name': name, - 'obj': force_text(obj)} + changecount, + ) % {"count": changecount, "name": name, "obj": force_text(obj)} self.message_user(request, msg) return HttpResponseRedirect(request.get_full_path()) @@ -234,40 +255,47 @@ class TreeEditor(admin.ModelAdmin): # Build the action form and populate it with available actions. if actions: action_form = self.action_form(auto_id=None) - action_form.fields['action'].choices = self.get_action_choices(request) + action_form.fields["action"].choices = self.get_action_choices(request) else: action_form = None context = { - 'title': cl.title, - 'is_popup': cl.is_popup, - 'cl': cl, - 'media': media, - 'has_add_permission': self.has_add_permission(request), - 'app_label': app_label, - 'action_form': action_form, - 'actions_on_top': self.actions_on_top, - 'actions_on_bottom': self.actions_on_bottom, + "title": cl.title, + "is_popup": cl.is_popup, + "cl": cl, + "media": media, + "has_add_permission": self.has_add_permission(request), + "app_label": app_label, + "action_form": action_form, + "actions_on_top": self.actions_on_top, + "actions_on_bottom": self.actions_on_bottom, } if django.VERSION[0] == 1 and django.VERSION[1] < 4: - context['root_path'] = self.admin_site.root_path + context["root_path"] = self.admin_site.root_path elif django.VERSION[0] == 1 or (django.VERSION[0] == 2 and django.VERSION[1] < 1): - selection_note_all = ungettext('%(total_count)s selected', 'All %(total_count)s selected', cl.result_count) + selection_note_all = ungettext("%(total_count)s selected", "All %(total_count)s selected", cl.result_count) - context.update({ - 'module_name': force_text(opts.verbose_name_plural), - 'selection_note': _('0 of %(cnt)s selected') % {'cnt': len(cl.result_list)}, - 'selection_note_all': selection_note_all % {'total_count': cl.result_count}, - }) + context.update( + { + "module_name": force_text(opts.verbose_name_plural), + "selection_note": _("0 of %(cnt)s selected") % {"cnt": len(cl.result_list)}, + "selection_note_all": selection_note_all % {"total_count": cl.result_count}, + } + ) else: - context['opts'] = self.model._meta + context["opts"] = self.model._meta context.update(extra_context or {}) - return render(request, self.change_list_template or [ - 'admin/%s/%s/change_list.html' % (app_label, opts.object_name.lower()), - 'admin/%s/change_list.html' % app_label, - 'admin/change_list.html' - ], context=context) + return render( + request, + self.change_list_template + or [ + "admin/%s/%s/change_list.html" % (app_label, opts.object_name.lower()), + "admin/%s/change_list.html" % app_label, + "admin/change_list.html", + ], + context=context, + ) def changelist_view(self, request, extra_context=None, *args, **kwargs): """ @@ -275,8 +303,8 @@ class TreeEditor(admin.ModelAdmin): change list/actions page. """ extra_context = extra_context or {} - extra_context['EDITOR_MEDIA_PATH'] = settings.MEDIA_PATH - extra_context['EDITOR_TREE_INITIAL_STATE'] = settings.TREE_INITIAL_STATE + extra_context["EDITOR_MEDIA_PATH"] = settings.MEDIA_PATH + extra_context["EDITOR_TREE_INITIAL_STATE"] = settings.TREE_INITIAL_STATE # FIXME return self.old_changelist_view(request, extra_context) diff --git a/categories/fields.py b/categories/fields.py index 1926de9..719b72e 100644 --- a/categories/fields.py +++ b/categories/fields.py @@ -4,21 +4,24 @@ from django.db.models import ForeignKey, ManyToManyField class CategoryM2MField(ManyToManyField): def __init__(self, **kwargs): from .models import Category - if 'to' in kwargs: - kwargs.pop('to') + + if "to" in kwargs: + kwargs.pop("to") super(CategoryM2MField, self).__init__(to=Category, **kwargs) class CategoryFKField(ForeignKey): def __init__(self, **kwargs): from .models import Category - if 'to' in kwargs: - kwargs.pop('to') + + if "to" in kwargs: + kwargs.pop("to") super(CategoryFKField, self).__init__(to=Category, **kwargs) try: from south.modelsinspector import add_introspection_rules + add_introspection_rules([], [r"^categories\.fields\.CategoryFKField"]) add_introspection_rules([], [r"^categories\.fields\.CategoryM2MField"]) except ImportError: diff --git a/categories/fixtures/musicgenres.json b/categories/fixtures/musicgenres.json index b832884..3817510 100644 --- a/categories/fixtures/musicgenres.json +++ b/categories/fixtures/musicgenres.json @@ -4414,4 +4414,4 @@ } } -] \ No newline at end of file +] diff --git a/categories/fixtures/test_category_spaces.txt b/categories/fixtures/test_category_spaces.txt index 025edbe..85852b5 100644 --- a/categories/fixtures/test_category_spaces.txt +++ b/categories/fixtures/test_category_spaces.txt @@ -5,4 +5,4 @@ Category 2 Category 2-1 Category 2-1-1 Category 3 - Category 3-1 \ No newline at end of file + Category 3-1 diff --git a/categories/fixtures/test_category_tabs.txt b/categories/fixtures/test_category_tabs.txt index 207a634..8ded421 100644 --- a/categories/fixtures/test_category_tabs.txt +++ b/categories/fixtures/test_category_tabs.txt @@ -5,4 +5,4 @@ Category 2 Category 2-1 Category 2-1-1 Category 3 - Category 3-1 \ No newline at end of file + Category 3-1 diff --git a/categories/genericcollection.py b/categories/genericcollection.py index ffa01a0..1745914 100644 --- a/categories/genericcollection.py +++ b/categories/genericcollection.py @@ -1,7 +1,8 @@ +import json + from django.contrib import admin from django.contrib.contenttypes.models import ContentType -from django.urls import reverse, NoReverseMatch -import json +from django.urls import NoReverseMatch, reverse class GenericCollectionInlineModelAdmin(admin.options.InlineModelAdmin): @@ -9,7 +10,7 @@ class GenericCollectionInlineModelAdmin(admin.options.InlineModelAdmin): ct_fk_field = "object_id" def get_content_types(self): - ctypes = ContentType.objects.all().order_by('id').values_list('id', 'app_label', 'model') + ctypes = ContentType.objects.all().order_by("id").values_list("id", "app_label", "model") elements = {} for x, y, z in ctypes: try: @@ -25,12 +26,12 @@ class GenericCollectionInlineModelAdmin(admin.options.InlineModelAdmin): return result class Media: - js = ('contentrelations/js/genericlookup.js', ) + js = ("contentrelations/js/genericlookup.js",) class GenericCollectionTabularInline(GenericCollectionInlineModelAdmin): - template = 'admin/edit_inline/gen_coll_tabular.html' + template = "admin/edit_inline/gen_coll_tabular.html" class GenericCollectionStackedInline(GenericCollectionInlineModelAdmin): - template = 'admin/edit_inline/gen_coll_stacked.html' + template = "admin/edit_inline/gen_coll_stacked.html" diff --git a/categories/locale/it/LC_MESSAGES/django.po b/categories/locale/it/LC_MESSAGES/django.po index 1186eef..32f3f2d 100644 --- a/categories/locale/it/LC_MESSAGES/django.po +++ b/categories/locale/it/LC_MESSAGES/django.po @@ -181,4 +181,3 @@ msgstr "Cancella?" #: templates/admin/edit_inline/gen_coll_tabular.html:24 msgid "View on site" msgstr "Vedi sul sito" - diff --git a/categories/management/commands/add_category_fields.py b/categories/management/commands/add_category_fields.py index 4d44c4d..377f5e5 100644 --- a/categories/management/commands/add_category_fields.py +++ b/categories/management/commands/add_category_fields.py @@ -5,13 +5,14 @@ class Command(BaseCommand): """ Alter one or more models' tables with the registered attributes """ + help = "Alter the tables for all registered models, or just specified models" args = "[appname ...]" can_import_settings = True requires_system_checks = False def add_arguments(self, parser): - parser.add_argument('app_names', nargs='*') + parser.add_argument("app_names", nargs="*") def handle(self, *args, **options): """ @@ -20,8 +21,9 @@ class Command(BaseCommand): from categories.migration import migrate_app from categories.settings import MODEL_REGISTRY - if options['app_names']: - for app in options['app_names']: + + if options["app_names"]: + for app in options["app_names"]: migrate_app(None, app) else: for app in MODEL_REGISTRY: diff --git a/categories/management/commands/drop_category_field.py b/categories/management/commands/drop_category_field.py index cc4850e..f10a220 100644 --- a/categories/management/commands/drop_category_field.py +++ b/categories/management/commands/drop_category_field.py @@ -1,27 +1,28 @@ -from django.core.management.base import BaseCommand -from django.core.management.base import CommandError +from django.core.management.base import BaseCommand, CommandError class Command(BaseCommand): """ Alter one or more models' tables with the registered attributes """ + help = "Drop the given field from the given model's table" args = "appname modelname fieldname" can_import_settings = True requires_system_checks = False def add_arguments(self, parser): - parser.add_argument('app_name') - parser.add_argument('model_name') - parser.add_argument('field_name') + parser.add_argument("app_name") + parser.add_argument("model_name") + parser.add_argument("field_name") def handle(self, *args, **options): """ Alter the tables """ from categories.migration import drop_field - if 'app_name' not in options or 'model_name' not in options or 'field_name' not in options: + + if "app_name" not in options or "model_name" not in options or "field_name" not in options: raise CommandError("You must specify an Application name, a Model name and a Field name") - drop_field(options['app_name'], options['model_name'], options['field_name']) + drop_field(options["app_name"], options["model_name"], options["field_name"]) diff --git a/categories/management/commands/import_categories.py b/categories/management/commands/import_categories.py index a899e50..6009afb 100644 --- a/categories/management/commands/import_categories.py +++ b/categories/management/commands/import_categories.py @@ -1,6 +1,5 @@ from django.core.management.base import BaseCommand, CommandError from django.db import transaction - from slugify import slugify from categories.models import Category @@ -10,7 +9,9 @@ from categories.settings import SLUG_TRANSLITERATOR class Command(BaseCommand): """Import category trees from a file.""" - help = "Imports category tree(s) from a file. Sub categories must be indented by the same multiple of spaces or tabs." + help = ( + "Imports category tree(s) from a file. Sub categories must be indented by the same multiple of spaces or tabs." + ) args = "file_path [file_path ...]" def get_indent(self, string): @@ -19,13 +20,13 @@ class Command(BaseCommand): """ indent_amt = 0 - if string[0] == '\t': - return '\t' + if string[0] == "\t": + return "\t" for char in string: - if char == ' ': + if char == " ": indent_amt += 1 else: - return ' ' * indent_amt + return " " * indent_amt @transaction.atomic def make_category(self, string, parent=None, order=1): @@ -36,9 +37,9 @@ class Command(BaseCommand): name=string.strip(), slug=slugify(SLUG_TRANSLITERATOR(string.strip()))[:49], # arent=parent, - order=order + order=order, ) - cat._tree_manager.insert_node(cat, parent, 'last-child', True) + cat._tree_manager.insert_node(cat, parent, "last-child", True) cat.save() if parent: parent.rght = cat.rght + 1 @@ -49,10 +50,10 @@ class Command(BaseCommand): """ Do the work of parsing each line """ - indent = '' + indent = "" level = 0 - if lines[0][0] == ' ' or lines[0][0] == '\t': + if lines[0][0] == " " or lines[0][0] == "\t": raise CommandError("The first line in the file cannot start with a space or tab.") # This keeps track of the current parents at a given level @@ -61,8 +62,8 @@ class Command(BaseCommand): for line in lines: if len(line) == 0: continue - if line[0] == ' ' or line[0] == '\t': - if indent == '': + if line[0] == " " or line[0] == "\t": + if indent == "": indent = self.get_indent(line) elif not line[0] in indent: raise CommandError("You can't mix spaces and tabs for indents") @@ -83,7 +84,7 @@ class Command(BaseCommand): if not os.path.isfile(file_path): print("File %s not found." % file_path) continue - f = open(file_path, 'r') + f = open(file_path, "r") data = f.readlines() f.close() diff --git a/categories/migration.py b/categories/migration.py index 407a796..77358a5 100644 --- a/categories/migration.py +++ b/categories/migration.py @@ -1,8 +1,7 @@ -# -*- coding: utf-8 -*- -from django.db import connection, transaction from django.apps import apps +from django.db import connection, transaction from django.db.utils import ProgrammingError @@ -25,7 +24,7 @@ def field_exists(app_name, model_name, field_name): # Return True if the many to many table exists field = model._meta.get_field(field_name) - if hasattr(field, 'm2m_db_table'): + if hasattr(field, "m2m_db_table"): m2m_table_name = field.m2m_db_table() m2m_field_info = connection.introspection.get_table_description(cursor, m2m_table_name) if m2m_field_info: @@ -50,9 +49,10 @@ def migrate_app(sender, *args, **kwargs): Migrate all models of this app registered """ from .registration import registry - if 'app_config' not in kwargs: + + if "app_config" not in kwargs: return - app_config = kwargs['app_config'] + app_config = kwargs["app_config"] app_name = app_config.label @@ -60,7 +60,7 @@ def migrate_app(sender, *args, **kwargs): sid = transaction.savepoint() for fld in fields: - model_name, field_name = fld.split('.')[1:] + model_name, field_name = fld.split(".")[1:] if field_exists(app_name, model_name, field_name): continue model = app_config.get_model(model_name) diff --git a/categories/migrations/0001_initial.py b/categories/migrations/0001_initial.py index b58fabc..883fd62 100644 --- a/categories/migrations/0001_initial.py +++ b/categories/migrations/0001_initial.py @@ -1,59 +1,123 @@ -# -*- coding: utf-8 -*- -from django.db import models, migrations import django.core.files.storage import mptt.fields +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('contenttypes', '0001_initial'), + ("contenttypes", "0001_initial"), ] operations = [ migrations.CreateModel( - name='Category', + name="Category", fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('name', models.CharField(max_length=100, verbose_name='name')), - ('slug', models.SlugField(verbose_name='slug')), - ('active', models.BooleanField(default=True, verbose_name='active')), - ('thumbnail', models.FileField(storage=django.core.files.storage.FileSystemStorage(), null=True, upload_to='uploads/categories/thumbnails', blank=True)), - ('thumbnail_width', models.IntegerField(null=True, blank=True)), - ('thumbnail_height', models.IntegerField(null=True, blank=True)), - ('order', models.IntegerField(default=0)), - ('alternate_title', models.CharField(default='', help_text='An alternative title to use on pages with this category.', max_length=100, blank=True)), - ('alternate_url', models.CharField(help_text='An alternative URL to use instead of the one derived from the category hierarchy.', max_length=200, blank=True)), - ('description', models.TextField(null=True, blank=True)), - ('meta_keywords', models.CharField(default='', help_text='Comma-separated keywords for search engines.', max_length=255, blank=True)), - ('meta_extra', models.TextField(default='', help_text='(Advanced) Any additional HTML to be placed verbatim in the <head>', blank=True)), - ('lft', models.PositiveIntegerField(editable=False, db_index=True)), - ('rght', models.PositiveIntegerField(editable=False, db_index=True)), - ('tree_id', models.PositiveIntegerField(editable=False, db_index=True)), - ('level', models.PositiveIntegerField(editable=False, db_index=True)), - ('parent', mptt.fields.TreeForeignKey(related_name='children', verbose_name='parent', blank=True, to='categories.Category', on_delete=models.CASCADE, null=True)), + ("id", models.AutoField(verbose_name="ID", serialize=False, auto_created=True, primary_key=True)), + ("name", models.CharField(max_length=100, verbose_name="name")), + ("slug", models.SlugField(verbose_name="slug")), + ("active", models.BooleanField(default=True, verbose_name="active")), + ( + "thumbnail", + models.FileField( + storage=django.core.files.storage.FileSystemStorage(), + null=True, + upload_to="uploads/categories/thumbnails", + blank=True, + ), + ), + ("thumbnail_width", models.IntegerField(null=True, blank=True)), + ("thumbnail_height", models.IntegerField(null=True, blank=True)), + ("order", models.IntegerField(default=0)), + ( + "alternate_title", + models.CharField( + default="", + help_text="An alternative title to use on pages with this category.", + max_length=100, + blank=True, + ), + ), + ( + "alternate_url", + models.CharField( + help_text="An alternative URL to use instead of the one derived from the category hierarchy.", + max_length=200, + blank=True, + ), + ), + ("description", models.TextField(null=True, blank=True)), + ( + "meta_keywords", + models.CharField( + default="", + help_text="Comma-separated keywords for search engines.", + max_length=255, + blank=True, + ), + ), + ( + "meta_extra", + models.TextField( + default="", + help_text="(Advanced) Any additional HTML to be placed verbatim in the <head>", + blank=True, + ), + ), + ("lft", models.PositiveIntegerField(editable=False, db_index=True)), + ("rght", models.PositiveIntegerField(editable=False, db_index=True)), + ("tree_id", models.PositiveIntegerField(editable=False, db_index=True)), + ("level", models.PositiveIntegerField(editable=False, db_index=True)), + ( + "parent", + mptt.fields.TreeForeignKey( + related_name="children", + verbose_name="parent", + blank=True, + to="categories.Category", + on_delete=models.CASCADE, + null=True, + ), + ), ], options={ - 'ordering': ('tree_id', 'lft'), - 'abstract': False, - 'verbose_name': 'category', - 'verbose_name_plural': 'categories', + "ordering": ("tree_id", "lft"), + "abstract": False, + "verbose_name": "category", + "verbose_name_plural": "categories", }, ), migrations.CreateModel( - name='CategoryRelation', + name="CategoryRelation", fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('object_id', models.PositiveIntegerField(verbose_name='object id')), - ('relation_type', models.CharField(help_text="A generic text field to tag a relation, like 'leadphoto'.", max_length='200', null=True, verbose_name='relation type', blank=True)), - ('category', models.ForeignKey(verbose_name='category', to='categories.Category', on_delete=models.CASCADE)), - ('content_type', models.ForeignKey(verbose_name='content type', to='contenttypes.ContentType', on_delete=models.CASCADE)), + ("id", models.AutoField(verbose_name="ID", serialize=False, auto_created=True, primary_key=True)), + ("object_id", models.PositiveIntegerField(verbose_name="object id")), + ( + "relation_type", + models.CharField( + help_text="A generic text field to tag a relation, like 'leadphoto'.", + max_length="200", + null=True, + verbose_name="relation type", + blank=True, + ), + ), + ( + "category", + models.ForeignKey(verbose_name="category", to="categories.Category", on_delete=models.CASCADE), + ), + ( + "content_type", + models.ForeignKey( + verbose_name="content type", to="contenttypes.ContentType", on_delete=models.CASCADE + ), + ), ], ), migrations.AlterUniqueTogether( - name='category', - unique_together=set([('parent', 'name')]), + name="category", + unique_together=set([("parent", "name")]), ), ] diff --git a/categories/migrations/0002_auto_20170217_1111.py b/categories/migrations/0002_auto_20170217_1111.py index 27b77ed..38c1f4f 100644 --- a/categories/migrations/0002_auto_20170217_1111.py +++ b/categories/migrations/0002_auto_20170217_1111.py @@ -1,27 +1,32 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.10.5 on 2017-02-17 11:11 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.manager +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('categories', '0001_initial'), + ("categories", "0001_initial"), ] operations = [ migrations.AlterModelManagers( - name='category', + name="category", managers=[ - ('tree', django.db.models.manager.Manager()), + ("tree", django.db.models.manager.Manager()), ], ), migrations.AlterField( - model_name='categoryrelation', - name='relation_type', - field=models.CharField(blank=True, help_text="A generic text field to tag a relation, like 'leadphoto'.", max_length=200, null=True, verbose_name='relation type'), + model_name="categoryrelation", + name="relation_type", + field=models.CharField( + blank=True, + help_text="A generic text field to tag a relation, like 'leadphoto'.", + max_length=200, + null=True, + verbose_name="relation type", + ), ), ] diff --git a/categories/migrations/0003_auto_20200306_1050.py b/categories/migrations/0003_auto_20200306_1050.py index c725321..21d98a3 100644 --- a/categories/migrations/0003_auto_20200306_1050.py +++ b/categories/migrations/0003_auto_20200306_1050.py @@ -1,35 +1,44 @@ # Generated by Django 3.0.4 on 2020-03-06 10:50 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('contenttypes', '0002_remove_content_type_name'), - ('categories', '0002_auto_20170217_1111'), + ("contenttypes", "0002_remove_content_type_name"), + ("categories", "0002_auto_20170217_1111"), ] operations = [ migrations.AlterField( - model_name='category', - name='level', + model_name="category", + name="level", field=models.PositiveIntegerField(editable=False), ), migrations.AlterField( - model_name='category', - name='lft', + model_name="category", + name="lft", field=models.PositiveIntegerField(editable=False), ), migrations.AlterField( - model_name='category', - name='rght', + model_name="category", + name="rght", field=models.PositiveIntegerField(editable=False), ), migrations.AlterField( - model_name='categoryrelation', - name='content_type', - field=models.ForeignKey(limit_choices_to=models.Q(models.Q(('app_label', 'simpletext'), ('model', 'simpletext')), models.Q(('app_label', 'flatpages'), ('model', 'flatpage')), _connector='OR'), on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType', verbose_name='content type'), + model_name="categoryrelation", + name="content_type", + field=models.ForeignKey( + limit_choices_to=models.Q( + models.Q(("app_label", "simpletext"), ("model", "simpletext")), + models.Q(("app_label", "flatpages"), ("model", "flatpage")), + _connector="OR", + ), + on_delete=django.db.models.deletion.CASCADE, + to="contenttypes.ContentType", + verbose_name="content type", + ), ), ] diff --git a/categories/migrations/0004_auto_20200517_1832.py b/categories/migrations/0004_auto_20200517_1832.py index ec3f2a0..dcbde23 100644 --- a/categories/migrations/0004_auto_20200517_1832.py +++ b/categories/migrations/0004_auto_20200517_1832.py @@ -1,20 +1,22 @@ # Generated by Django 3.0.6 on 2020-05-17 18:32 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('contenttypes', '0002_remove_content_type_name'), - ('categories', '0003_auto_20200306_1050'), + ("contenttypes", "0002_remove_content_type_name"), + ("categories", "0003_auto_20200306_1050"), ] operations = [ migrations.AlterField( - model_name='categoryrelation', - name='content_type', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType', verbose_name='content type'), + model_name="categoryrelation", + name="content_type", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="contenttypes.ContentType", verbose_name="content type" + ), ), ] diff --git a/categories/models.py b/categories/models.py index 15ddecb..3789de6 100644 --- a/categories/models.py +++ b/categories/models.py @@ -1,20 +1,26 @@ -from django.core.files.images import get_image_dimensions -from django.urls import reverse -from django.db import models -from django.utils.encoding import force_text -from django.contrib.contenttypes.models import ContentType from functools import reduce + +from django.contrib.contenttypes.models import ContentType +from django.core.files.images import get_image_dimensions +from django.db import models +from django.urls import reverse +from django.utils.encoding import force_text + try: from django.contrib.contenttypes.fields import GenericForeignKey except ImportError: from django.contrib.contenttypes.generic import GenericForeignKey -from django.core.files.storage import get_storage_class +from django.core.files.storage import get_storage_class from django.utils.translation import ugettext_lazy as _ -from .settings import (RELATION_MODELS, RELATIONS, THUMBNAIL_UPLOAD_PATH, THUMBNAIL_STORAGE) - from .base import CategoryBase +from .settings import ( + RELATION_MODELS, + RELATIONS, + THUMBNAIL_STORAGE, + THUMBNAIL_UPLOAD_PATH, +) STORAGE = get_storage_class(THUMBNAIL_STORAGE) @@ -22,32 +28,28 @@ STORAGE = get_storage_class(THUMBNAIL_STORAGE) class Category(CategoryBase): thumbnail = models.FileField( upload_to=THUMBNAIL_UPLOAD_PATH, - null=True, blank=True, - storage=STORAGE(),) + null=True, + blank=True, + storage=STORAGE(), + ) thumbnail_width = models.IntegerField(blank=True, null=True) thumbnail_height = models.IntegerField(blank=True, null=True) order = models.IntegerField(default=0) alternate_title = models.CharField( - blank=True, - default="", - max_length=100, - help_text="An alternative title to use on pages with this category.") + blank=True, default="", max_length=100, help_text="An alternative title to use on pages with this category." + ) alternate_url = models.CharField( blank=True, max_length=200, - help_text="An alternative URL to use instead of the one derived from " - "the category hierarchy.") + help_text="An alternative URL to use instead of the one derived from " "the category hierarchy.", + ) description = models.TextField(blank=True, null=True) meta_keywords = models.CharField( - blank=True, - default="", - max_length=255, - help_text="Comma-separated keywords for search engines.") + blank=True, default="", max_length=255, help_text="Comma-separated keywords for search engines." + ) meta_extra = models.TextField( - blank=True, - default="", - help_text="(Advanced) Any additional HTML to be placed verbatim " - "in the <head>") + blank=True, default="", help_text="(Advanced) Any additional HTML to be placed verbatim " "in the <head>" + ) @property def short_title(self): @@ -60,19 +62,21 @@ class Category(CategoryBase): if self.alternate_url: return self.alternate_url try: - prefix = reverse('categories_tree_list') + prefix = reverse("categories_tree_list") except NoReverseMatch: - prefix = '/' - ancestors = list(self.get_ancestors()) + [self, ] - return prefix + '/'.join([force_text(i.slug) for i in ancestors]) + '/' + prefix = "/" + ancestors = list(self.get_ancestors()) + [ + self, + ] + return prefix + "/".join([force_text(i.slug) for i in ancestors]) + "/" if RELATION_MODELS: + def get_related_content_type(self, content_type): """ Get all related items of the specified content type """ - return self.categoryrelation_set.filter( - content_type__name=content_type) + return self.categoryrelation_set.filter(content_type__name=content_type) def get_relation_type(self, relation_type): """ @@ -92,11 +96,11 @@ class Category(CategoryBase): super(Category, self).save(*args, **kwargs) class Meta(CategoryBase.Meta): - verbose_name = _('category') - verbose_name_plural = _('categories') + verbose_name = _("category") + verbose_name_plural = _("categories") class MPTTMeta: - order_insertion_by = ('order', 'name') + order_insertion_by = ("order", "name") if RELATIONS: @@ -123,17 +127,23 @@ class CategoryRelationManager(models.Manager): class CategoryRelation(models.Model): """Related category item""" - category = models.ForeignKey(Category, verbose_name=_('category'), on_delete=models.CASCADE) + + category = models.ForeignKey(Category, verbose_name=_("category"), on_delete=models.CASCADE) content_type = models.ForeignKey( - ContentType, on_delete=models.CASCADE, limit_choices_to=CATEGORY_RELATION_LIMITS, verbose_name=_('content type')) - object_id = models.PositiveIntegerField(verbose_name=_('object id')) - content_object = GenericForeignKey('content_type', 'object_id') + ContentType, + on_delete=models.CASCADE, + limit_choices_to=CATEGORY_RELATION_LIMITS, + verbose_name=_("content type"), + ) + object_id = models.PositiveIntegerField(verbose_name=_("object id")) + content_object = GenericForeignKey("content_type", "object_id") relation_type = models.CharField( - verbose_name=_('relation type'), + verbose_name=_("relation type"), max_length=200, blank=True, null=True, - help_text=_("A generic text field to tag a relation, like 'leadphoto'.")) + help_text=_("A generic text field to tag a relation, like 'leadphoto'."), + ) objects = CategoryRelationManager() diff --git a/categories/registration.py b/categories/registration.py index e26bb12..d871e14 100644 --- a/categories/registration.py +++ b/categories/registration.py @@ -1,17 +1,17 @@ """ These functions handle the adding of fields to other models """ -from django.db.models import ForeignKey, ManyToManyField, CASCADE -from django.core.exceptions import FieldDoesNotExist -from . import fields +from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured +from django.db.models import CASCADE, ForeignKey, ManyToManyField + # from settings import self._field_registry, self._model_registry from django.utils.translation import ugettext_lazy as _ -from django.core.exceptions import ImproperlyConfigured +from . import fields FIELD_TYPES = { - 'ForeignKey': ForeignKey, - 'ManyToManyField': ManyToManyField, + "ForeignKey": ForeignKey, + "ManyToManyField": ManyToManyField, } @@ -28,17 +28,20 @@ class Registry(object): field_definitions: a string, tuple or list of field configurations field_type: either 'ForeignKey' or 'ManyToManyField' """ - from django.apps import apps import collections + from django.apps import apps + app_label = app if isinstance(field_definitions, str): field_definitions = [field_definitions] elif not isinstance(field_definitions, collections.Iterable): - raise ImproperlyConfigured(_('Field configuration for %(app)s should be a string or iterable') % {'app': app}) + raise ImproperlyConfigured( + _("Field configuration for %(app)s should be a string or iterable") % {"app": app} + ) - if field_type not in ('ForeignKey', 'ManyToManyField'): + if field_type not in ("ForeignKey", "ManyToManyField"): raise ImproperlyConfigured(_('`field_type` must be either `"ForeignKey"` or `"ManyToManyField"`.')) try: @@ -55,30 +58,31 @@ class Registry(object): if model not in self._model_registry[app_label]: self._model_registry[app_label].append(model) except LookupError: - raise ImproperlyConfigured('Model "%(model)s" doesn\'t exist in app "%(app)s".' % {'model': model_name, 'app': app}) + raise ImproperlyConfigured( + 'Model "%(model)s" doesn\'t exist in app "%(app)s".' % {"model": model_name, "app": app} + ) if not isinstance(field_definitions, (tuple, list)): field_definitions = [field_definitions] for fld in field_definitions: - extra_params = {'to': 'categories.Category', 'blank': True} - if field_type != 'ManyToManyField': - extra_params['on_delete'] = CASCADE - extra_params['null'] = True + extra_params = {"to": "categories.Category", "blank": True} + if field_type != "ManyToManyField": + extra_params["on_delete"] = CASCADE + extra_params["null"] = True if isinstance(fld, str): field_name = fld elif isinstance(fld, dict): - if 'name' in fld: - field_name = fld.pop('name') + if "name" in fld: + field_name = fld.pop("name") else: continue extra_params.update(fld) else: raise ImproperlyConfigured( - _("%(settings)s doesn't recognize the value of %(app)s.%(model)s") % { - 'settings': 'CATEGORY_SETTINGS', - 'app': app, - 'model': model_name}) + _("%(settings)s doesn't recognize the value of %(app)s.%(model)s") + % {"settings": "CATEGORY_SETTINGS", "app": app, "model": model_name} + ) registry_name = ".".join([app_label, model_name.lower(), field_name]) if registry_name in self._field_registry: continue @@ -89,10 +93,10 @@ class Registry(object): self._field_registry[registry_name] = FIELD_TYPES[field_type](**extra_params) self._field_registry[registry_name].contribute_to_class(model, field_name) - def register_m2m(self, model, field_name='categories', extra_params={}): + def register_m2m(self, model, field_name="categories", extra_params={}): return self._register(model, field_name, extra_params, fields.CategoryM2MField) - def register_fk(self, model, field_name='category', extra_params={}): + def register_fk(self, model, field_name="category", extra_params={}): return self._register(model, field_name, extra_params, fields.CategoryFKField) def _register(self, model, field_name, extra_params={}, field=fields.CategoryFKField): @@ -120,28 +124,32 @@ def _process_registry(registry, call_func): """ Given a dictionary, and a registration function, process the registry """ - from django.core.exceptions import ImproperlyConfigured from django.apps import apps + from django.core.exceptions import ImproperlyConfigured for key, value in list(registry.items()): - model = apps.get_model(*key.split('.')) + model = apps.get_model(*key.split(".")) if model is None: - raise ImproperlyConfigured(_('%(key)s is not a model') % {'key': key}) + raise ImproperlyConfigured(_("%(key)s is not a model") % {"key": key}) if isinstance(value, (tuple, list)): for item in value: if isinstance(item, str): call_func(model, item) elif isinstance(item, dict): - field_name = item.pop('name') + field_name = item.pop("name") call_func(model, field_name, extra_params=item) else: - raise ImproperlyConfigured(_("%(settings)s doesn't recognize the value of %(key)s") % - {'settings': 'CATEGORY_SETTINGS', 'key': key}) + raise ImproperlyConfigured( + _("%(settings)s doesn't recognize the value of %(key)s") + % {"settings": "CATEGORY_SETTINGS", "key": key} + ) elif isinstance(value, str): call_func(model, value) elif isinstance(value, dict): - field_name = value.pop('name') + field_name = value.pop("name") call_func(model, field_name, extra_params=value) else: - raise ImproperlyConfigured(_("%(settings)s doesn't recognize the value of %(key)s") % - {'settings': 'CATEGORY_SETTINGS', 'key': key}) + raise ImproperlyConfigured( + _("%(settings)s doesn't recognize the value of %(key)s") + % {"settings": "CATEGORY_SETTINGS", "key": key} + ) diff --git a/categories/settings.py b/categories/settings.py index bf77d66..2fedf6f 100644 --- a/categories/settings.py +++ b/categories/settings.py @@ -1,42 +1,46 @@ +import collections + from django.conf import settings from django.db.models import Q from django.utils.translation import ugettext_lazy as _ -import collections DEFAULT_SETTINGS = { - 'ALLOW_SLUG_CHANGE': False, - 'M2M_REGISTRY': {}, - 'FK_REGISTRY': {}, - 'THUMBNAIL_UPLOAD_PATH': 'uploads/categories/thumbnails', - 'THUMBNAIL_STORAGE': settings.DEFAULT_FILE_STORAGE, - 'JAVASCRIPT_URL': getattr(settings, 'STATIC_URL', settings.MEDIA_URL) + 'js/', - 'SLUG_TRANSLITERATOR': '', - 'REGISTER_ADMIN': True, - 'RELATION_MODELS': [], + "ALLOW_SLUG_CHANGE": False, + "M2M_REGISTRY": {}, + "FK_REGISTRY": {}, + "THUMBNAIL_UPLOAD_PATH": "uploads/categories/thumbnails", + "THUMBNAIL_STORAGE": settings.DEFAULT_FILE_STORAGE, + "JAVASCRIPT_URL": getattr(settings, "STATIC_URL", settings.MEDIA_URL) + "js/", + "SLUG_TRANSLITERATOR": "", + "REGISTER_ADMIN": True, + "RELATION_MODELS": [], } -DEFAULT_SETTINGS.update(getattr(settings, 'CATEGORIES_SETTINGS', {})) +DEFAULT_SETTINGS.update(getattr(settings, "CATEGORIES_SETTINGS", {})) -if DEFAULT_SETTINGS['SLUG_TRANSLITERATOR']: - if isinstance(DEFAULT_SETTINGS['SLUG_TRANSLITERATOR'], collections.Callable): +if DEFAULT_SETTINGS["SLUG_TRANSLITERATOR"]: + if isinstance(DEFAULT_SETTINGS["SLUG_TRANSLITERATOR"], collections.Callable): pass - elif isinstance(DEFAULT_SETTINGS['SLUG_TRANSLITERATOR'], str): + elif isinstance(DEFAULT_SETTINGS["SLUG_TRANSLITERATOR"], str): from django.utils.importlib import import_module - bits = DEFAULT_SETTINGS['SLUG_TRANSLITERATOR'].split(".") + + bits = DEFAULT_SETTINGS["SLUG_TRANSLITERATOR"].split(".") module = import_module(".".join(bits[:-1])) - DEFAULT_SETTINGS['SLUG_TRANSLITERATOR'] = getattr(module, bits[-1]) + DEFAULT_SETTINGS["SLUG_TRANSLITERATOR"] = getattr(module, bits[-1]) else: from django.core.exceptions import ImproperlyConfigured - raise ImproperlyConfigured(_('%(transliterator) must be a callable or a string.') % - {'transliterator': 'SLUG_TRANSLITERATOR'}) + + raise ImproperlyConfigured( + _("%(transliterator) must be a callable or a string.") % {"transliterator": "SLUG_TRANSLITERATOR"} + ) else: - DEFAULT_SETTINGS['SLUG_TRANSLITERATOR'] = lambda x: x + DEFAULT_SETTINGS["SLUG_TRANSLITERATOR"] = lambda x: x # Add all the keys/values to the module's namespace globals().update(DEFAULT_SETTINGS) -RELATIONS = [Q(app_label=al, model=m) for al, m in [x.split('.') for x in DEFAULT_SETTINGS['RELATION_MODELS']]] +RELATIONS = [Q(app_label=al, model=m) for al, m in [x.split(".") for x in DEFAULT_SETTINGS["RELATION_MODELS"]]] # The field registry keeps track of the individual fields created. # {'app.model.field': Field(**extra_params)} diff --git a/categories/static/js/genericcollections.js b/categories/static/js/genericcollections.js index 584208e..8081eb8 100644 --- a/categories/static/js/genericcollections.js +++ b/categories/static/js/genericcollections.js @@ -17,4 +17,4 @@ function showGenericRelatedObjectLookupPopup(triggeringLink, ctArray) { var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); win.focus(); return false; -} \ No newline at end of file +} diff --git a/categories/templates/categories/ancestors_ul.html b/categories/templates/categories/ancestors_ul.html index eb07cb2..d9173e2 100644 --- a/categories/templates/categories/ancestors_ul.html +++ b/categories/templates/categories/ancestors_ul.html @@ -8,4 +8,4 @@ {% else %}{{ node.name }} {% endifequal %} {% for level in structure.closed_levels %}{% endfor %} -{% endfor %} \ No newline at end of file +{% endfor %} diff --git a/categories/templates/categories/base.html b/categories/templates/categories/base.html index 385820f..245102a 100644 --- a/categories/templates/categories/base.html +++ b/categories/templates/categories/base.html @@ -1,3 +1,3 @@ {% extends 'base.html' %} {% block content %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/categories/templates/categories/breadcrumbs.html b/categories/templates/categories/breadcrumbs.html index d6ec117..9fac9e2 100644 --- a/categories/templates/categories/breadcrumbs.html +++ b/categories/templates/categories/breadcrumbs.html @@ -1,3 +1,3 @@ {% spaceless %}{% for item in category.get_ancestors %} {{ item.name }}{{ separator }}{% endfor %}{{ category.name }} -{% endspaceless %} \ No newline at end of file +{% endspaceless %} diff --git a/categories/templates/categories/category_detail.html b/categories/templates/categories/category_detail.html index 3865fa1..c43e371 100644 --- a/categories/templates/categories/category_detail.html +++ b/categories/templates/categories/category_detail.html @@ -14,4 +14,4 @@ {% if category.parent %}

Go up to {{ category.parent }}

{% endif %} {% if category.description %}

{{ category.description }}

{% endif %} {% if category.children.count %}

Subcategories

    {% for child in category.children.all %}
  • {{ child }}
  • {% endfor %}
{% endif %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/categories/templates/categories/category_list.html b/categories/templates/categories/category_list.html index ff87511..f9a2c26 100644 --- a/categories/templates/categories/category_list.html +++ b/categories/templates/categories/category_list.html @@ -2,4 +2,4 @@ {% block content %}

Categories

-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/categories/templates/categories/ul_tree.html b/categories/templates/categories/ul_tree.html index b6013de..891e298 100644 --- a/categories/templates/categories/ul_tree.html +++ b/categories/templates/categories/ul_tree.html @@ -8,4 +8,4 @@ {% else %}{{ node.name }} {% endifequal %} {% for level in structure.closed_levels %}{% endfor %} -{% endfor %}{% endspaceless %} \ No newline at end of file +{% endfor %}{% endspaceless %} diff --git a/categories/templatetags/category_tags.py b/categories/templatetags/category_tags.py index 69d2aad..a93f70e 100644 --- a/categories/templatetags/category_tags.py +++ b/categories/templatetags/category_tags.py @@ -1,13 +1,18 @@ from django import template from django.apps import apps -from django.template import (Node, TemplateSyntaxError, VariableDoesNotExist) +from django.template import Node, TemplateSyntaxError, VariableDoesNotExist from django.template.base import FilterExpression +from mptt.templatetags.mptt_tags import ( + RecurseTreeNode, + full_tree_for_model, + tree_info, + tree_path, +) +from mptt.utils import drilldown_tree_for_node from six import string_types + from categories.base import CategoryBase from categories.models import Category -from mptt.utils import drilldown_tree_for_node -from mptt.templatetags.mptt_tags import (tree_path, tree_info, RecurseTreeNode, - full_tree_for_model) register = template.Library() @@ -48,9 +53,9 @@ def get_category(category_string, model=Category): """ model_class = get_cat_model(model) category = str(category_string).strip("'\"") - category = category.strip('/') + category = category.strip("/") - cat_list = category.split('/') + cat_list = category.split("/") if len(cat_list) == 0: return None try: @@ -88,7 +93,7 @@ class CategoryDrillDownNode(template.Node): context[self.varname] = [] except Exception: context[self.varname] = [] - return '' + return "" @register.tag @@ -114,30 +119,32 @@ def get_category_drilldown(parser, token): Grandparent, Parent, Child 1, Child 2, Child n """ bits = token.split_contents() - error_str = '%(tagname)s tag should be in the format {%% %(tagname)s ' \ - '"category name" [using "app.Model"] as varname %%} or ' \ - '{%% %(tagname)s category_obj as varname %%}.' + error_str = ( + "%(tagname)s tag should be in the format {%% %(tagname)s " + '"category name" [using "app.Model"] as varname %%} or ' + "{%% %(tagname)s category_obj as varname %%}." + ) if len(bits) == 4: - if bits[2] != 'as': - raise template.TemplateSyntaxError(error_str % {'tagname': bits[0]}) - if bits[2] == 'as': + if bits[2] != "as": + raise template.TemplateSyntaxError(error_str % {"tagname": bits[0]}) + if bits[2] == "as": varname = bits[3].strip("'\"") model = "categories.category" if len(bits) == 6: - if bits[2] not in ('using', 'as') or bits[4] not in ('using', 'as'): - raise template.TemplateSyntaxError(error_str % {'tagname': bits[0]}) - if bits[2] == 'as': + if bits[2] not in ("using", "as") or bits[4] not in ("using", "as"): + raise template.TemplateSyntaxError(error_str % {"tagname": bits[0]}) + if bits[2] == "as": varname = bits[3].strip("'\"") model = bits[5].strip("'\"") - if bits[2] == 'using': + if bits[2] == "using": varname = bits[5].strip("'\"") model = bits[3].strip("'\"") category = FilterExpression(bits[1], parser) return CategoryDrillDownNode(category, varname, model) -@register.inclusion_tag('categories/breadcrumbs.html') -def breadcrumbs(category_string, separator=' > ', using='categories.category'): +@register.inclusion_tag("categories/breadcrumbs.html") +def breadcrumbs(category_string, separator=" > ", using="categories.category"): """ {% breadcrumbs category separator="::" using="categories.category" %} @@ -146,11 +153,11 @@ def breadcrumbs(category_string, separator=' > ', using='categories.category'): """ cat = get_category(category_string, using) - return {'category': cat, 'separator': separator} + return {"category": cat, "separator": separator} -@register.inclusion_tag('categories/ul_tree.html') -def display_drilldown_as_ul(category, using='categories.Category'): +@register.inclusion_tag("categories/ul_tree.html") +def display_drilldown_as_ul(category, using="categories.Category"): """ Render the category with ancestors and children using the ``categories/ul_tree.html`` template. @@ -185,13 +192,13 @@ def display_drilldown_as_ul(category, using='categories.Category'): """ cat = get_category(category, using) if cat is None: - return {'category': cat, 'path': []} + return {"category": cat, "path": []} else: - return {'category': cat, 'path': drilldown_tree_for_node(cat)} + return {"category": cat, "path": drilldown_tree_for_node(cat)} -@register.inclusion_tag('categories/ul_tree.html') -def display_path_as_ul(category, using='categories.Category'): +@register.inclusion_tag("categories/ul_tree.html") +def display_path_as_ul(category, using="categories.Category"): """ Render the category with ancestors, but no children using the ``categories/ul_tree.html`` template. @@ -219,7 +226,7 @@ def display_path_as_ul(category, using='categories.Category'): else: cat = get_category(category) - return {'category': cat, 'path': cat.get_ancestors() or []} + return {"category": cat, "path": cat.get_ancestors() or []} class TopLevelCategoriesNode(template.Node): @@ -229,8 +236,8 @@ class TopLevelCategoriesNode(template.Node): def render(self, context): model = get_cat_model(self.model) - context[self.varname] = model.objects.filter(parent=None).order_by('name') - return '' + context[self.varname] = model.objects.filter(parent=None).order_by("name") + return "" @register.tag @@ -247,14 +254,14 @@ def get_top_level_categories(parser, token): bits = token.split_contents() usage = 'Usage: {%% %s [using "app.Model"] as %%}' % bits[0] if len(bits) == 3: - if bits[1] != 'as': + if bits[1] != "as": raise template.TemplateSyntaxError(usage) varname = bits[2] model = "categories.category" elif len(bits) == 5: - if bits[1] not in ('as', 'using') and bits[3] not in ('as', 'using'): + if bits[1] not in ("as", "using") and bits[3] not in ("as", "using"): raise template.TemplateSyntaxError(usage) - if bits[1] == 'using': + if bits[1] == "using": model = bits[2].strip("'\"") varname = bits[4].strip("'\"") else: @@ -264,22 +271,21 @@ def get_top_level_categories(parser, token): return TopLevelCategoriesNode(varname, model) -def get_latest_objects_by_category(category, app_label, model_name, set_name, date_field='pub_date', num=15): +def get_latest_objects_by_category(category, app_label, model_name, set_name, date_field="pub_date", num=15): m = apps.get_model(app_label, model_name) if not isinstance(category, CategoryBase): category = Category.objects.get(slug=str(category)) children = category.children.all() ids = [] for cat in list(children) + [category]: - if hasattr(cat, '%s_set' % set_name): - ids.extend([x.pk for x in getattr(cat, '%s_set' % set_name).all()[:num]]) + if hasattr(cat, "%s_set" % set_name): + ids.extend([x.pk for x in getattr(cat, "%s_set" % set_name).all()[:num]]) - return m.objects.filter(pk__in=ids).order_by('-%s' % date_field)[:num] + return m.objects.filter(pk__in=ids).order_by("-%s" % date_field)[:num] class LatestObjectsNode(Node): - def __init__(self, var_name, category, app_label, model_name, set_name, - date_field='pub_date', num=15): + def __init__(self, var_name, category, app_label, model_name, set_name, date_field="pub_date", num=15): """ Get latest objects of app_label.model_name """ @@ -305,7 +311,7 @@ class LatestObjectsNode(Node): result = get_latest_objects_by_category(category, app_label, model_name, set_name, date_field, num) context[self.var_name] = result - return '' + return "" def do_get_latest_objects_by_category(parser, token): @@ -317,7 +323,7 @@ def do_get_latest_objects_by_category(parser, token): proper_form = "{% get_latest_objects_by_category category app_name model_name set_name [date_field] [number] as [var_name] %}" bits = token.split_contents() - if bits[-2] != 'as': + if bits[-2] != "as": raise TemplateSyntaxError("%s tag shoud be in the form: %s" % (bits[0], proper_form)) if len(bits) < 7: raise TemplateSyntaxError("%s tag shoud be in the form: %s" % (bits[0], proper_form)) @@ -328,11 +334,11 @@ def do_get_latest_objects_by_category(parser, token): model_name = FilterExpression(bits[3], parser) set_name = FilterExpression(bits[4], parser) var_name = bits[-1] - if bits[5] != 'as': + if bits[5] != "as": date_field = FilterExpression(bits[5], parser) else: date_field = FilterExpression(None, parser) - if bits[6] != 'as': + if bits[6] != "as": num = FilterExpression(bits[6], parser) else: num = FilterExpression(None, parser) @@ -348,8 +354,10 @@ def tree_queryset(value): Converts a normal queryset from an MPTT model to include all the ancestors so a filtered subset of items can be formatted correctly """ - from django.db.models.query import QuerySet from copy import deepcopy + + from django.db.models.query import QuerySet + if not isinstance(value, QuerySet): return value @@ -365,9 +373,9 @@ def tree_queryset(value): # this cuts down the number of queries considerably since all ancestors # will already be in include_pages when they are checked, thus not # trigger additional queries. - for p in qs2.order_by('rght').iterator(): + for p in qs2.order_by("rght").iterator(): if p.parent_id and p.parent_id not in include_pages and p.id not in include_pages: - ancestor_id_list = p.get_ancestors().values_list('id', flat=True) + ancestor_id_list = p.get_ancestors().values_list("id", flat=True) include_pages.update(ancestor_id_list) if include_pages: @@ -400,10 +408,10 @@ def recursetree(parser, token): """ bits = token.contents.split() if len(bits) != 2: - raise template.TemplateSyntaxError('%s tag requires a queryset' % bits[0]) + raise template.TemplateSyntaxError("%s tag requires a queryset" % bits[0]) queryset_var = FilterExpression(bits[1], parser) - template_nodes = parser.parse(('endrecursetree',)) + template_nodes = parser.parse(("endrecursetree",)) parser.delete_first_token() return RecurseTreeNode(template_nodes, queryset_var) diff --git a/categories/tests/test_admin.py b/categories/tests/test_admin.py index 20759c1..ce1c7a3 100644 --- a/categories/tests/test_admin.py +++ b/categories/tests/test_admin.py @@ -1,68 +1,68 @@ -# -*- coding: utf-8 -*- from django.contrib.auth.models import User -from django.urls import reverse from django.test import Client, TestCase +from django.urls import reverse from django.utils.encoding import smart_text from categories.models import Category class TestCategoryAdmin(TestCase): - def setUp(self): self.client = Client() def test_adding_parent_and_child(self): - User.objects.create_superuser('testuser', 'testuser@example.com', 'password') - self.client.login(username='testuser', password='password') - url = reverse('admin:categories_category_add') + User.objects.create_superuser("testuser", "testuser@example.com", "password") + self.client.login(username="testuser", password="password") + url = reverse("admin:categories_category_add") data = { - 'parent': '', - 'name': smart_text('Parent Catégory'), - 'thumbnail': '', - 'filename': '', - 'active': 'on', - 'alternate_title': '', - 'alternate_url': '', - 'description': '', - 'meta_keywords': '', - 'meta_extra': '', - 'order': 0, - 'slug': 'parent', - '_save': '_save', - 'categoryrelation_set-TOTAL_FORMS': '0', - 'categoryrelation_set-INITIAL_FORMS': '0', - 'categoryrelation_set-MIN_NUM_FORMS': '1000', - 'categoryrelation_set-MAX_NUM_FORMS': '1000', + "parent": "", + "name": smart_text("Parent Catégory"), + "thumbnail": "", + "filename": "", + "active": "on", + "alternate_title": "", + "alternate_url": "", + "description": "", + "meta_keywords": "", + "meta_extra": "", + "order": 0, + "slug": "parent", + "_save": "_save", + "categoryrelation_set-TOTAL_FORMS": "0", + "categoryrelation_set-INITIAL_FORMS": "0", + "categoryrelation_set-MIN_NUM_FORMS": "1000", + "categoryrelation_set-MAX_NUM_FORMS": "1000", } resp = self.client.post(url, data=data) self.assertEqual(resp.status_code, 302) self.assertEqual(1, Category.objects.count()) # update parent - data.update({'name': smart_text('Parent Catégory (Changed)')}) - resp = self.client.post(reverse('admin:categories_category_change', args=(1,)), data=data) + data.update({"name": smart_text("Parent Catégory (Changed)")}) + resp = self.client.post(reverse("admin:categories_category_change", args=(1,)), data=data) self.assertEqual(resp.status_code, 302) self.assertEqual(1, Category.objects.count()) # add a child - data.update({ - 'parent': '1', - 'name': smart_text('Child Catégory'), - 'slug': smart_text('child-category'), - }) + data.update( + { + "parent": "1", + "name": smart_text("Child Catégory"), + "slug": smart_text("child-category"), + } + ) resp = self.client.post(url, data=data) self.assertEqual(resp.status_code, 302) self.assertEqual(2, Category.objects.count()) # update child - data.update({'name': 'Child (Changed)'}) - resp = self.client.post(reverse('admin:categories_category_change', args=(2,)), data=data) + data.update({"name": "Child (Changed)"}) + resp = self.client.post(reverse("admin:categories_category_change", args=(2,)), data=data) self.assertEqual(resp.status_code, 302) self.assertEqual(2, Category.objects.count()) # test the admin list view - url = reverse('admin:categories_category_changelist') + url = reverse("admin:categories_category_changelist") resp = self.client.get(url) self.assertEqual(resp.status_code, 200) diff --git a/categories/tests/test_category_import.py b/categories/tests/test_category_import.py index 3db1be4..acd366f 100644 --- a/categories/tests/test_category_import.py +++ b/categories/tests/test_category_import.py @@ -4,20 +4,21 @@ import os from django.conf import settings -from django.test import TestCase, override_settings -from categories.models import Category -from categories.management.commands.import_categories import Command from django.core.management.base import CommandError +from django.test import TestCase, override_settings + +from categories.management.commands.import_categories import Command +from categories.models import Category -@override_settings(INSTALLED_APPS=(app for app in settings.INSTALLED_APPS if app != 'django.contrib.flatpages')) +@override_settings(INSTALLED_APPS=(app for app in settings.INSTALLED_APPS if app != "django.contrib.flatpages")) class CategoryImportTest(TestCase): def setUp(self): pass def _import_file(self, filename): - root_cats = ['Category 1', 'Category 2', 'Category 3'] - testfile = os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'fixtures', filename)) + root_cats = ["Category 1", "Category 2", "Category 3"] + testfile = os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), "fixtures", filename)) cmd = Command() cmd.handle(testfile) roots = Category.tree.root_nodes() @@ -26,31 +27,31 @@ class CategoryImportTest(TestCase): for item in roots: assert item.name in root_cats - cat2 = Category.objects.get(name='Category 2') + cat2 = Category.objects.get(name="Category 2") cat21 = cat2.children.all()[0] - self.assertEqual(cat21.name, 'Category 2-1') + self.assertEqual(cat21.name, "Category 2-1") cat211 = cat21.children.all()[0] - self.assertEqual(cat211.name, 'Category 2-1-1') + self.assertEqual(cat211.name, "Category 2-1-1") def testImportSpaceDelimited(self): Category.objects.all().delete() - self._import_file('test_category_spaces.txt') + self._import_file("test_category_spaces.txt") items = Category.objects.all() - self.assertEqual(items[0].name, 'Category 1') - self.assertEqual(items[1].name, 'Category 1-1') - self.assertEqual(items[2].name, 'Category 1-2') + self.assertEqual(items[0].name, "Category 1") + self.assertEqual(items[1].name, "Category 1-1") + self.assertEqual(items[2].name, "Category 1-2") def testImportTabDelimited(self): Category.objects.all().delete() - self._import_file('test_category_tabs.txt') + self._import_file("test_category_tabs.txt") items = Category.objects.all() - self.assertEqual(items[0].name, 'Category 1') - self.assertEqual(items[1].name, 'Category 1-1') - self.assertEqual(items[2].name, 'Category 1-2') + self.assertEqual(items[0].name, "Category 1") + self.assertEqual(items[1].name, "Category 1-1") + self.assertEqual(items[2].name, "Category 1-2") def testMixingTabsSpaces(self): """ diff --git a/categories/tests/test_manager.py b/categories/tests/test_manager.py index b2fb6c6..a9f2718 100644 --- a/categories/tests/test_manager.py +++ b/categories/tests/test_manager.py @@ -1,10 +1,11 @@ # test active returns only active items from django.test import TestCase + from categories.models import Category class CategoryManagerTest(TestCase): - fixtures = ['categories.json'] + fixtures = ["categories.json"] def setUp(self): pass @@ -16,7 +17,7 @@ class CategoryManagerTest(TestCase): all_count = Category.objects.all().count() self.assertEqual(Category.objects.active().count(), all_count) - cat1 = Category.objects.get(name='Category 1') + cat1 = Category.objects.get(name="Category 1") cat1.active = False cat1.save() diff --git a/categories/tests/test_mgmt_commands.py b/categories/tests/test_mgmt_commands.py index 7466910..b94c842 100644 --- a/categories/tests/test_mgmt_commands.py +++ b/categories/tests/test_mgmt_commands.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.core import management from django.core.management.base import CommandError from django.db import connection @@ -6,7 +5,6 @@ from django.test import TestCase class TestMgmtCommands(TestCase): - @classmethod def setUpClass(cls): connection.disable_constraint_checking() @@ -18,13 +16,13 @@ class TestMgmtCommands(TestCase): connection.enable_constraint_checking() def test_add_category_fields(self): - management.call_command('add_category_fields', verbosity=0) + management.call_command("add_category_fields", verbosity=0) def test_add_category_fields_app(self): - management.call_command('add_category_fields', 'flatpages', verbosity=0) + management.call_command("add_category_fields", "flatpages", verbosity=0) def test_drop_category_field(self): - management.call_command('drop_category_field', 'flatpages', 'flatpage', 'category', verbosity=0) + management.call_command("drop_category_field", "flatpages", "flatpage", "category", verbosity=0) def test_drop_category_field_error(self): - self.assertRaises(CommandError, management.call_command, 'drop_category_field', verbosity=0) + self.assertRaises(CommandError, management.call_command, "drop_category_field", verbosity=0) diff --git a/categories/tests/test_models.py b/categories/tests/test_models.py index 5649bee..5208baf 100644 --- a/categories/tests/test_models.py +++ b/categories/tests/test_models.py @@ -2,20 +2,19 @@ import os from django.core.files import File from django.core.files.uploadedfile import UploadedFile +from django.test import TestCase from categories.models import Category -from django.test import TestCase class TestCategoryThumbnail(TestCase): - def test_thumbnail(self): - file_name = 'test_image.jpg' + file_name = "test_image.jpg" - with open(os.path.join(os.path.dirname(__file__), file_name), 'rb') as f: - test_image = UploadedFile(File(f), content_type='image/jpeg') - category = Category.objects.create(name='Test Category', slug='test-category', thumbnail=test_image) + with open(os.path.join(os.path.dirname(__file__), file_name), "rb") as f: + test_image = UploadedFile(File(f), content_type="image/jpeg") + category = Category.objects.create(name="Test Category", slug="test-category", thumbnail=test_image) self.assertEqual(category.pk, 1) self.assertEqual(category.thumbnail_width, 640) self.assertEqual(category.thumbnail_height, 480) diff --git a/categories/tests/test_registration.py b/categories/tests/test_registration.py index 842baec..918d8c9 100644 --- a/categories/tests/test_registration.py +++ b/categories/tests/test_registration.py @@ -14,43 +14,39 @@ class CategoryRegistrationTest(TestCase): """ def test_foreignkey_string(self): - FK_REGISTRY = { - 'flatpages.flatpage': 'category' - } + FK_REGISTRY = {"flatpages.flatpage": "category"} _process_registry(FK_REGISTRY, registry.register_fk) from django.contrib.flatpages.models import FlatPage - self.assertTrue('category' in [f.name for f in FlatPage()._meta.get_fields()]) + + self.assertTrue("category" in [f.name for f in FlatPage()._meta.get_fields()]) def test_foreignkey_dict(self): - FK_REGISTRY = { - 'flatpages.flatpage': {'name': 'category'} - } + FK_REGISTRY = {"flatpages.flatpage": {"name": "category"}} _process_registry(FK_REGISTRY, registry.register_fk) from django.contrib.flatpages.models import FlatPage - self.assertTrue('category' in [f.name for f in FlatPage()._meta.get_fields()]) + + self.assertTrue("category" in [f.name for f in FlatPage()._meta.get_fields()]) def test_foreignkey_list(self): - FK_REGISTRY = { - 'flatpages.flatpage': ( - {'name': 'category', 'related_name': 'cats'}, - ) - } + FK_REGISTRY = {"flatpages.flatpage": ({"name": "category", "related_name": "cats"},)} _process_registry(FK_REGISTRY, registry.register_fk) from django.contrib.flatpages.models import FlatPage - self.assertTrue('category' in [f.name for f in FlatPage()._meta.get_fields()]) + + self.assertTrue("category" in [f.name for f in FlatPage()._meta.get_fields()]) if django.VERSION[1] >= 7: + def test_new_foreignkey_string(self): - registry.register_model('flatpages', 'flatpage', 'ForeignKey', 'category') + registry.register_model("flatpages", "flatpage", "ForeignKey", "category") from django.contrib.flatpages.models import FlatPage - self.assertTrue('category' in [f.name for f in FlatPage()._meta.get_fields()]) + + self.assertTrue("category" in [f.name for f in FlatPage()._meta.get_fields()]) class Categorym2mTest(TestCase): def test_m2m_string(self): - M2M_REGISTRY = { - 'flatpages.flatpage': 'categories' - } + M2M_REGISTRY = {"flatpages.flatpage": "categories"} _process_registry(M2M_REGISTRY, registry.register_m2m) from django.contrib.flatpages.models import FlatPage - self.assertTrue('category' in [f.name for f in FlatPage()._meta.get_fields()]) + + self.assertTrue("category" in [f.name for f in FlatPage()._meta.get_fields()]) diff --git a/categories/tests/test_templatetags.py b/categories/tests/test_templatetags.py index f099715..ffe967c 100644 --- a/categories/tests/test_templatetags.py +++ b/categories/tests/test_templatetags.py @@ -1,13 +1,14 @@ -from django.test import TestCase -from django import template import re +from django import template +from django.test import TestCase + from categories.models import Category class CategoryTagsTest(TestCase): - fixtures = ['musicgenres.json'] + fixtures = ["musicgenres.json"] def render_template(self, template_string, context={}): """ @@ -21,7 +22,9 @@ class CategoryTagsTest(TestCase): """ Ensure that get_category raises an exception if there aren't enough arguments. """ - self.assertRaises(template.TemplateSyntaxError, self.render_template, '{% load category_tags %}{% get_category %}') + self.assertRaises( + template.TemplateSyntaxError, self.render_template, "{% load category_tags %}{% get_category %}" + ) def testBasicUsage(self): """ @@ -30,46 +33,50 @@ class CategoryTagsTest(TestCase): # display_path_as_ul rock_resp = '' resp = self.render_template('{% load category_tags %}{% display_path_as_ul "/Rock" %}') - resp = re.sub(r'\n$', "", resp) + resp = re.sub(r"\n$", "", resp) self.assertEqual(resp, rock_resp) # display_drilldown_as_ul expected_resp = '' resp = self.render_template( - '{% load category_tags %}' - '{% display_drilldown_as_ul "/World/Worldbeat" "categories.category" %}') - resp = re.sub(r'\n$', "", resp) + "{% load category_tags %}" '{% display_drilldown_as_ul "/World/Worldbeat" "categories.category" %}' + ) + resp = re.sub(r"\n$", "", resp) self.assertEqual(resp, expected_resp) # breadcrumbs expected_resp = 'World > Worldbeat' resp = self.render_template( - '{% load category_tags %}' - '{% breadcrumbs "/World/Worldbeat" " > " "categories.category" %}') + "{% load category_tags %}" '{% breadcrumbs "/World/Worldbeat" " > " "categories.category" %}' + ) self.assertEqual(resp, expected_resp) # get_top_level_categories - expected_resp = 'Avant-garde|Blues|Country|Easy listening|Electronic|Hip hop/Rap music|Jazz|Latin|Modern folk|Pop|Reggae|Rhythm and blues|Rock|World|' + expected_resp = "Avant-garde|Blues|Country|Easy listening|Electronic|Hip hop/Rap music|Jazz|Latin|Modern folk|Pop|Reggae|Rhythm and blues|Rock|World|" resp = self.render_template( - '{% load category_tags %}' + "{% load category_tags %}" '{% get_top_level_categories using "categories.category" as varname %}' - '{% for item in varname %}{{ item }}|{% endfor %}') + "{% for item in varname %}{{ item }}|{% endfor %}" + ) self.assertEqual(resp, expected_resp) # get_category_drilldown expected_resp = "World|World > Worldbeat|" resp = self.render_template( - '{% load category_tags %}' + "{% load category_tags %}" '{% get_category_drilldown "/World" using "categories.category" as var %}' - '{% for item in var %}{{ item }}|{% endfor %}') + "{% for item in var %}{{ item }}|{% endfor %}" + ) self.assertEqual(resp, expected_resp) # recursetree - expected_resp = '
  • Country
    • Country pop
      • Urban Cowboy
  • World
    • Worldbeat
    ' - ctxt = {'nodes': Category.objects.filter(name__in=("Worldbeat", "Urban Cowboy"))} + expected_resp = "
    • Country
      • Country pop
        • Urban Cowboy
    • World
      • Worldbeat
      " + ctxt = {"nodes": Category.objects.filter(name__in=("Worldbeat", "Urban Cowboy"))} resp = self.render_template( - '{% load category_tags %}' - '
        {% recursetree nodes|tree_queryset %}
      • {{ node.name }}' - '{% if not node.is_leaf_node %}
          {{ children }}' - '
        {% endif %}
      • {% endrecursetree %}
      ', ctxt) + "{% load category_tags %}" + "
        {% recursetree nodes|tree_queryset %}
      • {{ node.name }}" + "{% if not node.is_leaf_node %}
          {{ children }}" + "
        {% endif %}
      • {% endrecursetree %}
      ", + ctxt, + ) self.assertEqual(resp, expected_resp) diff --git a/categories/tests/test_views.py b/categories/tests/test_views.py index d64435b..dac65f9 100644 --- a/categories/tests/test_views.py +++ b/categories/tests/test_views.py @@ -1,8 +1,9 @@ -from django.http import Http404 from django.contrib.auth.models import AnonymousUser -from django.test import Client, TestCase, RequestFactory -from categories.models import Category, CategoryRelation +from django.http import Http404 +from django.test import Client, RequestFactory, TestCase + from categories import views +from categories.models import Category, CategoryRelation class MyCategoryRelationView(views.CategoryRelatedDetail): @@ -10,16 +11,18 @@ class MyCategoryRelationView(views.CategoryRelatedDetail): class TestCategoryViews(TestCase): - fixtures = ['musicgenres.json', ] + fixtures = [ + "musicgenres.json", + ] def setUp(self): self.client = Client() self.factory = RequestFactory() def test_category_detail(self): - cat0 = Category.objects.get(slug='country', level=0) - cat1 = cat0.children.get(slug='country-pop') - cat2 = Category.objects.get(slug='urban-cowboy') + cat0 = Category.objects.get(slug="country", level=0) + cat1 = cat0.children.get(slug="country-pop") + cat2 = Category.objects.get(slug="urban-cowboy") url = cat0.get_absolute_url() response = self.client.get(url) self.assertEquals(response.status_code, 200) @@ -33,51 +36,48 @@ class TestCategoryViews(TestCase): self.assertEquals(response.status_code, 404) def test_get_category_for_path(self): - cat0 = Category.objects.get(slug='country', level=0) - cat1 = cat0.children.get(slug='country-pop') - cat2 = Category.objects.get(slug='urban-cowboy') + cat0 = Category.objects.get(slug="country", level=0) + cat1 = cat0.children.get(slug="country-pop") + cat2 = Category.objects.get(slug="urban-cowboy") - result = views.get_category_for_path('/country/country-pop/urban-cowboy/') + result = views.get_category_for_path("/country/country-pop/urban-cowboy/") self.assertEquals(result, cat2) - result = views.get_category_for_path('/country/country-pop/') + result = views.get_category_for_path("/country/country-pop/") self.assertEquals(result, cat1) - result = views.get_category_for_path('/country/') + result = views.get_category_for_path("/country/") self.assertEquals(result, cat0) def test_categorydetailview(self): - request = self.factory.get('') + request = self.factory.get("") request.user = AnonymousUser() self.assertRaises(AttributeError, views.CategoryDetailView.as_view(), request) - request = self.factory.get('') + request = self.factory.get("") request.user = AnonymousUser() - response = views.CategoryDetailView.as_view()(request, path='/country/country-pop/urban-cowboy/') + response = views.CategoryDetailView.as_view()(request, path="/country/country-pop/urban-cowboy/") self.assertEquals(response.status_code, 200) - request = self.factory.get('') + request = self.factory.get("") request.user = AnonymousUser() - self.assertRaises(Http404, views.CategoryDetailView.as_view(), request, path='/country/country-pop/foo/') + self.assertRaises(Http404, views.CategoryDetailView.as_view(), request, path="/country/country-pop/foo/") def test_categoryrelateddetailview(self): from simpletext.models import SimpleText - stext = SimpleText.objects.create( - name='Test', - description='test description' - ) - cat = Category.objects.get(slug='urban-cowboy') - cat_rel = CategoryRelation.objects.create( # NOQA - category=cat, - content_object=stext - ) - request = self.factory.get('') + + stext = SimpleText.objects.create(name="Test", description="test description") + cat = Category.objects.get(slug="urban-cowboy") + cat_rel = CategoryRelation.objects.create(category=cat, content_object=stext) # NOQA + request = self.factory.get("") request.user = AnonymousUser() self.assertRaises(AttributeError, MyCategoryRelationView.as_view(), request) - request = self.factory.get('') + request = self.factory.get("") request.user = AnonymousUser() - response = MyCategoryRelationView.as_view()(request, category_path='/country/country-pop/urban-cowboy/') + response = MyCategoryRelationView.as_view()(request, category_path="/country/country-pop/urban-cowboy/") self.assertEquals(response.status_code, 200) - request = self.factory.get('') + request = self.factory.get("") request.user = AnonymousUser() - self.assertRaises(Http404, MyCategoryRelationView.as_view(), request, category_path='/country/country-pop/foo/') + self.assertRaises( + Http404, MyCategoryRelationView.as_view(), request, category_path="/country/country-pop/foo/" + ) diff --git a/categories/urls.py b/categories/urls.py index 986df79..7160f61 100644 --- a/categories/urls.py +++ b/categories/urls.py @@ -1,19 +1,11 @@ from django.conf.urls import url from django.views.generic import ListView -from .models import Category + from . import views +from .models import Category +categorytree_dict = {"queryset": Category.objects.filter(level=0)} -categorytree_dict = { - 'queryset': Category.objects.filter(level=0) -} +urlpatterns = (url(r"^$", ListView.as_view(**categorytree_dict), name="categories_tree_list"),) -urlpatterns = ( - url( - r'^$', ListView.as_view(**categorytree_dict), name='categories_tree_list' - ), -) - -urlpatterns += ( - url(r'^(?P.+)/$', views.category_detail, name='categories_category'), -) +urlpatterns += (url(r"^(?P.+)/$", views.category_detail, name="categories_category"),) diff --git a/categories/views.py b/categories/views.py index 65584f6..c92752d 100644 --- a/categories/views.py +++ b/categories/views.py @@ -1,5 +1,5 @@ +from django.http import Http404, HttpResponse from django.shortcuts import get_object_or_404 -from django.http import HttpResponse, Http404 from django.template.loader import select_template from django.utils.translation import ugettext_lazy as _ from django.views.generic import DetailView, ListView @@ -7,139 +7,126 @@ from django.views.generic import DetailView, ListView from .models import Category -def category_detail(request, path, template_name='categories/category_detail.html', extra_context={}): - path_items = path.strip('/').split('/') +def category_detail(request, path, template_name="categories/category_detail.html", extra_context={}): + path_items = path.strip("/").split("/") if len(path_items) >= 2: category = get_object_or_404( - Category, - slug__iexact=path_items[-1], - level=len(path_items) - 1, - parent__slug__iexact=path_items[-2]) + Category, slug__iexact=path_items[-1], level=len(path_items) - 1, parent__slug__iexact=path_items[-2] + ) else: - category = get_object_or_404( - Category, - slug__iexact=path_items[-1], - level=len(path_items) - 1) + category = get_object_or_404(Category, slug__iexact=path_items[-1], level=len(path_items) - 1) templates = [] while path_items: - templates.append('categories/%s.html' % '_'.join(path_items)) + templates.append("categories/%s.html" % "_".join(path_items)) path_items.pop() templates.append(template_name) - context = {'category': category} + context = {"category": category} if extra_context: context.update(extra_context) return HttpResponse(select_template(templates).render(context)) def get_category_for_path(path, queryset=Category.objects.all()): - path_items = path.strip('/').split('/') + path_items = path.strip("/").split("/") if len(path_items) >= 2: queryset = queryset.filter( - slug__iexact=path_items[-1], - level=len(path_items) - 1, - parent__slug__iexact=path_items[-2]) + slug__iexact=path_items[-1], level=len(path_items) - 1, parent__slug__iexact=path_items[-2] + ) else: - queryset = queryset.filter( - slug__iexact=path_items[-1], - level=len(path_items) - 1) + queryset = queryset.filter(slug__iexact=path_items[-1], level=len(path_items) - 1) return queryset.get() class CategoryDetailView(DetailView): model = Category - path_field = 'path' + path_field = "path" def get_object(self, **kwargs): if self.path_field not in self.kwargs: - raise AttributeError("Category detail view %s must be called with " - "a %s." % (self.__class__.__name__, self.path_field)) + raise AttributeError( + "Category detail view %s must be called with " "a %s." % (self.__class__.__name__, self.path_field) + ) if self.queryset is None: queryset = self.get_queryset() try: return get_category_for_path(self.kwargs[self.path_field], self.model.objects.all()) except Category.DoesNotExist: - raise Http404(_("No %(verbose_name)s found matching the query") % - {'verbose_name': queryset.model._meta.verbose_name}) + raise Http404( + _("No %(verbose_name)s found matching the query") % {"verbose_name": queryset.model._meta.verbose_name} + ) def get_template_names(self): names = [] - path_items = self.kwargs[self.path_field].strip('/').split('/') + path_items = self.kwargs[self.path_field].strip("/").split("/") while path_items: - names.append('categories/%s.html' % '_'.join(path_items)) + names.append("categories/%s.html" % "_".join(path_items)) path_items.pop() names.extend(super(CategoryDetailView, self).get_template_names()) return names class CategoryRelatedDetail(DetailView): - path_field = 'category_path' + path_field = "category_path" object_name_field = None def get_object(self, **kwargs): if self.path_field not in self.kwargs: - raise AttributeError("Category detail view %s must be called with " - "a %s." % (self.__class__.__name__, self.path_field)) + raise AttributeError( + "Category detail view %s must be called with " "a %s." % (self.__class__.__name__, self.path_field) + ) queryset = super(CategoryRelatedDetail, self).get_queryset() try: category = get_category_for_path(self.kwargs[self.path_field]) except Category.DoesNotExist: - raise Http404(_("No %(verbose_name)s found matching the query") % - {'verbose_name': queryset.model._meta.verbose_name}) + raise Http404( + _("No %(verbose_name)s found matching the query") % {"verbose_name": queryset.model._meta.verbose_name} + ) return queryset.get(category=category) def get_template_names(self): names = [] opts = self.object._meta - path_items = self.kwargs[self.path_field].strip('/').split('/') + path_items = self.kwargs[self.path_field].strip("/").split("/") if self.object_name_field: path_items.append(getattr(self.object, self.object_name_field)) while path_items: - names.append('%s/category_%s_%s%s.html' % ( - opts.app_label, - '_'.join(path_items), - opts.object_name.lower(), - self.template_name_suffix) + names.append( + "%s/category_%s_%s%s.html" + % (opts.app_label, "_".join(path_items), opts.object_name.lower(), self.template_name_suffix) ) path_items.pop() - names.append('%s/category_%s%s.html' % ( - opts.app_label, - opts.object_name.lower(), - self.template_name_suffix) - ) + names.append("%s/category_%s%s.html" % (opts.app_label, opts.object_name.lower(), self.template_name_suffix)) names.extend(super(CategoryRelatedDetail, self).get_template_names()) return names class CategoryRelatedList(ListView): - path_field = 'category_path' + path_field = "category_path" def get_queryset(self): if self.path_field not in self.kwargs: - raise AttributeError("Category detail view %s must be called with " - "a %s." % (self.__class__.__name__, self.path_field)) + raise AttributeError( + "Category detail view %s must be called with " "a %s." % (self.__class__.__name__, self.path_field) + ) queryset = super(CategoryRelatedList, self).get_queryset() category = get_category_for_path(self.kwargs[self.path_field]) return queryset.filter(category=category) def get_template_names(self): names = [] - if hasattr(self.object_list, 'model'): + if hasattr(self.object_list, "model"): opts = self.object_list.model._meta - path_items = self.kwargs[self.path_field].strip('/').split('/') + path_items = self.kwargs[self.path_field].strip("/").split("/") while path_items: - names.append('%s/category_%s_%s%s.html' % ( - opts.app_label, - '_'.join(path_items), - opts.object_name.lower(), - self.template_name_suffix) + names.append( + "%s/category_%s_%s%s.html" + % (opts.app_label, "_".join(path_items), opts.object_name.lower(), self.template_name_suffix) ) path_items.pop() - names.append('%s/category_%s%s.html' % ( - opts.app_label, - opts.object_name.lower(), - self.template_name_suffix) + names.append( + "%s/category_%s%s.html" % (opts.app_label, opts.object_name.lower(), self.template_name_suffix) ) names.extend(super(CategoryRelatedList, self).get_template_names()) return names diff --git a/doc_src/_static/default.css b/doc_src/_static/default.css index c719235..a95ff54 100644 --- a/doc_src/_static/default.css +++ b/doc_src/_static/default.css @@ -770,4 +770,4 @@ display:inline; } li p { margin-top:8px; -} \ No newline at end of file +} diff --git a/doc_src/_static/toc.js b/doc_src/_static/toc.js index 7b70978..cc06ee8 100644 --- a/doc_src/_static/toc.js +++ b/doc_src/_static/toc.js @@ -17,4 +17,4 @@ var TOC = { $(document).ready(function () { TOC.load(); -}); \ No newline at end of file +}); diff --git a/doc_src/adding_the_fields.rst b/doc_src/adding_the_fields.rst index a6a920f..b40709b 100644 --- a/doc_src/adding_the_fields.rst +++ b/doc_src/adding_the_fields.rst @@ -20,4 +20,4 @@ Reconfiguring Fields You can make changes to the field configurations as long as they do not change the underlying database structure. For example, adding a ``related_name`` (see :ref:`registering_a_m2one_relationship`\ ) because it only affects Django code. Changing the name of the field, however, is a different matter. -Django Categories provides a complementary management command to drop a field from the database (the field must still be in the configuration to do so): ``python manage.py drop_category_field app_name model_name field_name`` \ No newline at end of file +Django Categories provides a complementary management command to drop a field from the database (the field must still be in the configuration to do so): ``python manage.py drop_category_field app_name model_name field_name`` diff --git a/doc_src/code_examples/custom_categories1.py b/doc_src/code_examples/custom_categories1.py index c8d4652..68a437e 100644 --- a/doc_src/code_examples/custom_categories1.py +++ b/doc_src/code_examples/custom_categories1.py @@ -7,4 +7,4 @@ class SimpleCategory(CategoryBase): """ class Meta: - verbose_name_plural = 'simple categories' + verbose_name_plural = "simple categories" diff --git a/doc_src/code_examples/custom_categories3.py b/doc_src/code_examples/custom_categories3.py index d2aaa6f..27babd9 100644 --- a/doc_src/code_examples/custom_categories3.py +++ b/doc_src/code_examples/custom_categories3.py @@ -5,29 +5,25 @@ from categories.base import CategoryBase class Category(CategoryBase): thumbnail = models.FileField( upload_to=settings.THUMBNAIL_UPLOAD_PATH, - null=True, blank=True, - storage=settings.THUMBNAIL_STORAGE,) + null=True, + blank=True, + storage=settings.THUMBNAIL_STORAGE, + ) thumbnail_width = models.IntegerField(blank=True, null=True) thumbnail_height = models.IntegerField(blank=True, null=True) order = models.IntegerField(default=0) alternate_title = models.CharField( - blank=True, - default="", - max_length=100, - help_text="An alternative title to use on pages with this category.") + blank=True, default="", max_length=100, help_text="An alternative title to use on pages with this category." + ) alternate_url = models.CharField( blank=True, max_length=200, - help_text="An alternative URL to use instead of the one derived from " - "the category hierarchy.") + help_text="An alternative URL to use instead of the one derived from " "the category hierarchy.", + ) description = models.TextField(blank=True, null=True) meta_keywords = models.CharField( - blank=True, - default="", - max_length=255, - help_text="Comma-separated keywords for search engines.") + blank=True, default="", max_length=255, help_text="Comma-separated keywords for search engines." + ) meta_extra = models.TextField( - blank=True, - default="", - help_text="(Advanced) Any additional HTML to be placed verbatim " - "in the <head>") + blank=True, default="", help_text="(Advanced) Any additional HTML to be placed verbatim " "in the <head>" + ) diff --git a/doc_src/code_examples/custom_categories4.py b/doc_src/code_examples/custom_categories4.py index 87e1d3a..9356e05 100644 --- a/doc_src/code_examples/custom_categories4.py +++ b/doc_src/code_examples/custom_categories4.py @@ -3,8 +3,9 @@ from categories.models import Category def save(self, *args, **kwargs): if self.thumbnail: - from django.core.files.images import get_image_dimensions import django + from django.core.files.images import get_image_dimensions + if django.VERSION[1] < 2: width, height = get_image_dimensions(self.thumbnail.file) else: diff --git a/doc_src/code_examples/custom_categories5.py b/doc_src/code_examples/custom_categories5.py index 67109c6..e2f48d4 100644 --- a/doc_src/code_examples/custom_categories5.py +++ b/doc_src/code_examples/custom_categories5.py @@ -2,8 +2,8 @@ from categories.base import CategoryBase class Meta(CategoryBase.Meta): - verbose_name_plural = 'categories' + verbose_name_plural = "categories" class MPTTMeta: - order_insertion_by = ('order', 'name') + order_insertion_by = ("order", "name") diff --git a/doc_src/code_examples/custom_categories6.py b/doc_src/code_examples/custom_categories6.py index 3c09f03..387aa72 100644 --- a/doc_src/code_examples/custom_categories6.py +++ b/doc_src/code_examples/custom_categories6.py @@ -7,7 +7,7 @@ class CategoryAdminForm(CategoryBaseAdminForm): model = Category def clean_alternate_title(self): - if self.instance is None or not self.cleaned_data['alternate_title']: - return self.cleaned_data['name'] + if self.instance is None or not self.cleaned_data["alternate_title"]: + return self.cleaned_data["name"] else: - return self.cleaned_data['alternate_title'] + return self.cleaned_data["alternate_title"] diff --git a/doc_src/code_examples/custom_categories7.py b/doc_src/code_examples/custom_categories7.py index 4fcc1a2..6ec7041 100644 --- a/doc_src/code_examples/custom_categories7.py +++ b/doc_src/code_examples/custom_categories7.py @@ -4,18 +4,21 @@ from categories.base import CategoryBaseAdmin class CategoryAdmin(CategoryBaseAdmin): form = CategoryAdminForm - list_display = ('name', 'alternate_title', 'active') + list_display = ("name", "alternate_title", "active") fieldsets = ( - (None, { - 'fields': ('parent', 'name', 'thumbnail', 'active') - }), - ('Meta Data', { - 'fields': ('alternate_title', 'alternate_url', 'description', - 'meta_keywords', 'meta_extra'), - 'classes': ('collapse',), - }), - ('Advanced', { - 'fields': ('order', 'slug'), - 'classes': ('collapse',), - }), + (None, {"fields": ("parent", "name", "thumbnail", "active")}), + ( + "Meta Data", + { + "fields": ("alternate_title", "alternate_url", "description", "meta_keywords", "meta_extra"), + "classes": ("collapse",), + }, + ), + ( + "Advanced", + { + "fields": ("order", "slug"), + "classes": ("collapse",), + }, + ), ) diff --git a/doc_src/conf.py b/doc_src/conf.py index 0ffb72f..f8400c6 100644 --- a/doc_src/conf.py +++ b/doc_src/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Django Categories documentation build configuration file, created by # sphinx-quickstart on Tue Oct 6 07:53:33 2009. @@ -11,14 +10,14 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys import os +import sys # 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.append(os.path.abspath('..')) -os.environ['DJANGO_SETTINGS_MODULE'] = 'example.settings' +sys.path.append(os.path.abspath("..")) +os.environ["DJANGO_SETTINGS_MODULE"] = "example.settings" import categories # noqa @@ -32,17 +31,17 @@ extensions = [] templates_path = ['_templates'] # The suffix of source filenames. -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. # ource_encoding = 'utf-8' # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = 'Django Categories' -copyright = '2010-2012, Corey Oordt' +project = "Django Categories" +copyright = "2010-2012, Corey Oordt" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -68,7 +67,7 @@ release = categories.get_version() # List of directories, relative to source directory, that shouldn't be searched # for source files. -exclude_trees = ['_build'] +exclude_trees = ["_build"] # The reST default role (used for this markup: `text`) to use for all documents. # efault_role = None @@ -85,7 +84,7 @@ exclude_trees = ['_build'] # how_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. # odindex_common_prefix = [] @@ -124,7 +123,7 @@ html_theme = 'default' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. @@ -162,7 +161,7 @@ html_static_path = ['_static'] # tml_file_suffix = '' # Output file base name for HTML help builder. -htmlhelp_basename = 'DjangoCategoriesdoc' +htmlhelp_basename = "DjangoCategoriesdoc" # -- Options for LaTeX output -------------------------------------------------- @@ -176,7 +175,7 @@ htmlhelp_basename = 'DjangoCategoriesdoc' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'DjangoCategories.tex', 'Django Categories Documentation', 'CoreyOordt', 'manual'), + ("index", "DjangoCategories.tex", "Django Categories Documentation", "CoreyOordt", "manual"), ] # The name of an image file (relative to this directory) to place at the top of diff --git a/doc_src/index.rst b/doc_src/index.rst index 9c330ed..093de5a 100644 --- a/doc_src/index.rst +++ b/doc_src/index.rst @@ -41,4 +41,3 @@ Indices and tables * :ref:`genindex` * :ref:`modindex` * :ref:`search` - diff --git a/doc_src/reference/management_commands.rst b/doc_src/reference/management_commands.rst index b090695..4818672 100644 --- a/doc_src/reference/management_commands.rst +++ b/doc_src/reference/management_commands.rst @@ -35,4 +35,4 @@ drop_category_field Drop the ``field_name`` field from the ``app_name_model_name`` table, if the field is currently registered in ``CATEGORIES_SETTINGS``\ . -Requires Django South. \ No newline at end of file +Requires Django South. diff --git a/doc_src/reference/settings.rst b/doc_src/reference/settings.rst index dd0ebee..96c542f 100644 --- a/doc_src/reference/settings.rst +++ b/doc_src/reference/settings.rst @@ -128,4 +128,4 @@ ADMIN_FIELDSETS **Default:** ``{}`` -**Description:** Allows for selective customization of the default behavior of adding the fields to the admin class. See :ref:`admin_settings` for more information. \ No newline at end of file +**Description:** Allows for selective customization of the default behavior of adding the fields to the admin class. See :ref:`admin_settings` for more information. diff --git a/doc_src/usage.rst b/doc_src/usage.rst index c54c3b2..83e9779 100644 --- a/doc_src/usage.rst +++ b/doc_src/usage.rst @@ -59,4 +59,3 @@ comma-separated list of feature names. The valid feature names are: Books -> [] Sci-fi -> [u'Books'] Dystopian Futures -> [u'Books', u'Sci-fi'] - diff --git a/doc_src/usage_example_template.html b/doc_src/usage_example_template.html index b0bee73..9428cf6 100644 --- a/doc_src/usage_example_template.html +++ b/doc_src/usage_example_template.html @@ -25,4 +25,4 @@

      No entries for {{ category }}

      {% endif %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/example/settings-testing.py b/example/settings-testing.py index 9d2c3f1..ba91a32 100644 --- a/example/settings-testing.py +++ b/example/settings-testing.py @@ -16,108 +16,105 @@ ADMINS = ( MANAGERS = ADMINS DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': 'dev.db', - 'USER': '', - 'PASSWORD': '', - 'HOST': '', - 'PORT': '', + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": "dev.db", + "USER": "", + "PASSWORD": "", + "HOST": "", + "PORT": "", } } INSTALLED_APPS = ( - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'django.contrib.flatpages', - 'categories', - 'categories.editor', - 'mptt', - 'simpletext', + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.sites", + "django.contrib.messages", + "django.contrib.staticfiles", + "django.contrib.flatpages", + "categories", + "categories.editor", + "mptt", + "simpletext", ) -TIME_ZONE = 'America/Chicago' +TIME_ZONE = "America/Chicago" -LANGUAGE_CODE = 'en-us' +LANGUAGE_CODE = "en-us" SITE_ID = 1 USE_I18N = True -MEDIA_ROOT = os.path.abspath(os.path.join(PROJ_ROOT, 'media', 'uploads')) +MEDIA_ROOT = os.path.abspath(os.path.join(PROJ_ROOT, "media", "uploads")) -MEDIA_URL = '/uploads/' +MEDIA_URL = "/uploads/" -STATIC_ROOT = os.path.abspath(os.path.join(PROJ_ROOT, 'media', 'static')) +STATIC_ROOT = os.path.abspath(os.path.join(PROJ_ROOT, "media", "static")) -STATIC_URL = '/static/' +STATIC_URL = "/static/" STATICFILES_DIRS = () STATICFILES_FINDERS = ( - 'django.contrib.staticfiles.finders.FileSystemFinder', - 'django.contrib.staticfiles.finders.AppDirectoriesFinder', + "django.contrib.staticfiles.finders.FileSystemFinder", + "django.contrib.staticfiles.finders.AppDirectoriesFinder", ) -SECRET_KEY = 'bwq#m)-zsey-fs)0#4*o=2z(v5g!ei=zytl9t-1hesh4b&-u^d' +SECRET_KEY = "bwq#m)-zsey-fs)0#4*o=2z(v5g!ei=zytl9t-1hesh4b&-u^d" MIDDLEWARE = ( - 'django.middleware.security.SecurityMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", ) -ROOT_URLCONF = 'urls' +ROOT_URLCONF = "urls" TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'APP_DIRS': True, - 'DIRS': [os.path.abspath(os.path.join(os.path.dirname(__file__), 'templates'))], - 'OPTIONS': { - 'debug': DEBUG, - 'context_processors': [ - 'django.contrib.auth.context_processors.auth', - 'django.template.context_processors.debug', - 'django.template.context_processors.i18n', - 'django.template.context_processors.media', - 'django.template.context_processors.static', - 'django.template.context_processors.tz', - 'django.contrib.messages.context_processors.messages', + "BACKEND": "django.template.backends.django.DjangoTemplates", + "APP_DIRS": True, + "DIRS": [os.path.abspath(os.path.join(os.path.dirname(__file__), "templates"))], + "OPTIONS": { + "debug": DEBUG, + "context_processors": [ + "django.contrib.auth.context_processors.auth", + "django.template.context_processors.debug", + "django.template.context_processors.i18n", + "django.template.context_processors.media", + "django.template.context_processors.static", + "django.template.context_processors.tz", + "django.contrib.messages.context_processors.messages", ], - } + }, }, ] CATEGORIES_SETTINGS = { - 'ALLOW_SLUG_CHANGE': True, - 'RELATION_MODELS': ['simpletext.simpletext', 'flatpages.flatpage'], - 'FK_REGISTRY': { - 'flatpages.flatpage': ( - 'category', - {'on_delete': models.CASCADE} - ), - 'simpletext.simpletext': ( - 'primary_category', - {'name': 'secondary_category', 'related_name': 'simpletext_sec_cat'}, + "ALLOW_SLUG_CHANGE": True, + "RELATION_MODELS": ["simpletext.simpletext", "flatpages.flatpage"], + "FK_REGISTRY": { + "flatpages.flatpage": ("category", {"on_delete": models.CASCADE}), + "simpletext.simpletext": ( + "primary_category", + {"name": "secondary_category", "related_name": "simpletext_sec_cat"}, ), }, - 'M2M_REGISTRY': { + "M2M_REGISTRY": { # 'simpletext.simpletext': {'name': 'categories', 'related_name': 'm2mcats'}, - 'flatpages.flatpage': ( - {'name': 'other_categories', 'related_name': 'other_cats'}, - {'name': 'more_categories', 'related_name': 'more_cats'}, + "flatpages.flatpage": ( + {"name": "other_categories", "related_name": "other_cats"}, + {"name": "more_categories", "related_name": "more_cats"}, ), }, } -TEST_RUNNER = 'django.test.runner.DiscoverRunner' +TEST_RUNNER = "django.test.runner.DiscoverRunner" diff --git a/example/settings.py b/example/settings.py index 6eab74a..c303377 100644 --- a/example/settings.py +++ b/example/settings.py @@ -1,6 +1,7 @@ # Django settings for sample project. import os import sys + import django from django.db import models @@ -16,109 +17,106 @@ ADMINS = ( MANAGERS = ADMINS DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': 'dev.db', - 'USER': '', - 'PASSWORD': '', - 'HOST': '', - 'PORT': '', + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": "dev.db", + "USER": "", + "PASSWORD": "", + "HOST": "", + "PORT": "", } } INSTALLED_APPS = ( - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'django.contrib.flatpages', - 'categories', - 'categories.editor', - 'mptt', - 'simpletext', + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.sites", + "django.contrib.messages", + "django.contrib.staticfiles", + "django.contrib.flatpages", + "categories", + "categories.editor", + "mptt", + "simpletext", ) -TIME_ZONE = 'America/Chicago' +TIME_ZONE = "America/Chicago" -LANGUAGE_CODE = 'en-us' +LANGUAGE_CODE = "en-us" SITE_ID = 1 USE_I18N = True -MEDIA_ROOT = os.path.abspath(os.path.join(PROJ_ROOT, 'media', 'uploads')) +MEDIA_ROOT = os.path.abspath(os.path.join(PROJ_ROOT, "media", "uploads")) -MEDIA_URL = '/uploads/' +MEDIA_URL = "/uploads/" -STATIC_ROOT = os.path.abspath(os.path.join(PROJ_ROOT, 'media', 'static')) +STATIC_ROOT = os.path.abspath(os.path.join(PROJ_ROOT, "media", "static")) -STATIC_URL = '/static/' +STATIC_URL = "/static/" STATICFILES_DIRS = () STATICFILES_FINDERS = ( - 'django.contrib.staticfiles.finders.FileSystemFinder', - 'django.contrib.staticfiles.finders.AppDirectoriesFinder', + "django.contrib.staticfiles.finders.FileSystemFinder", + "django.contrib.staticfiles.finders.AppDirectoriesFinder", ) -SECRET_KEY = 'bwq#m)-zsey-fs)0#4*o=2z(v5g!ei=zytl9t-1hesh4b&-u^d' +SECRET_KEY = "bwq#m)-zsey-fs)0#4*o=2z(v5g!ei=zytl9t-1hesh4b&-u^d" MIDDLEWARE = ( - 'django.middleware.security.SecurityMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", ) -ROOT_URLCONF = 'urls' +ROOT_URLCONF = "urls" TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'APP_DIRS': True, - 'DIRS': [os.path.abspath(os.path.join(os.path.dirname(__file__), 'templates'))], - 'OPTIONS': { - 'debug': DEBUG, - 'context_processors': [ - 'django.contrib.auth.context_processors.auth', - 'django.template.context_processors.debug', - 'django.template.context_processors.i18n', - 'django.template.context_processors.media', - 'django.template.context_processors.static', - 'django.template.context_processors.tz', - 'django.contrib.messages.context_processors.messages', + "BACKEND": "django.template.backends.django.DjangoTemplates", + "APP_DIRS": True, + "DIRS": [os.path.abspath(os.path.join(os.path.dirname(__file__), "templates"))], + "OPTIONS": { + "debug": DEBUG, + "context_processors": [ + "django.contrib.auth.context_processors.auth", + "django.template.context_processors.debug", + "django.template.context_processors.i18n", + "django.template.context_processors.media", + "django.template.context_processors.static", + "django.template.context_processors.tz", + "django.contrib.messages.context_processors.messages", ], - } + }, } ] CATEGORIES_SETTINGS = { - 'ALLOW_SLUG_CHANGE': True, - 'RELATION_MODELS': ['simpletext.simpletext', 'flatpages.flatpage'], - 'FK_REGISTRY': { - 'flatpages.flatpage': ( - 'category', - {'on_delete': models.CASCADE} - ), - 'simpletext.simpletext': ( - 'primary_category', - {'name': 'secondary_category', 'related_name': 'simpletext_sec_cat'}, + "ALLOW_SLUG_CHANGE": True, + "RELATION_MODELS": ["simpletext.simpletext", "flatpages.flatpage"], + "FK_REGISTRY": { + "flatpages.flatpage": ("category", {"on_delete": models.CASCADE}), + "simpletext.simpletext": ( + "primary_category", + {"name": "secondary_category", "related_name": "simpletext_sec_cat"}, ), }, - 'M2M_REGISTRY': { - 'simpletext.simpletext': {'name': 'categories', 'related_name': 'm2mcats'}, - 'flatpages.flatpage': ( - {'name': 'other_categories', 'related_name': 'other_cats'}, - {'name': 'more_categories', 'related_name': 'more_cats'}, + "M2M_REGISTRY": { + "simpletext.simpletext": {"name": "categories", "related_name": "m2mcats"}, + "flatpages.flatpage": ( + {"name": "other_categories", "related_name": "other_cats"}, + {"name": "more_categories", "related_name": "more_cats"}, ), }, } if django.VERSION[1] > 5: - TEST_RUNNER = 'django.test.runner.DiscoverRunner' + TEST_RUNNER = "django.test.runner.DiscoverRunner" diff --git a/example/simpletext/admin.py b/example/simpletext/admin.py index dcf1947..9539514 100644 --- a/example/simpletext/admin.py +++ b/example/simpletext/admin.py @@ -1,21 +1,28 @@ -from .models import SimpleText, SimpleCategory from django.contrib import admin from categories.admin import CategoryBaseAdmin, CategoryBaseAdminForm +from .models import SimpleCategory, SimpleText + class SimpleTextAdmin(admin.ModelAdmin): fieldsets = ( - (None, { - 'fields': ('name', 'description', ) - }), + ( + None, + { + "fields": ( + "name", + "description", + ) + }, + ), ) class SimpleCategoryAdminForm(CategoryBaseAdminForm): class Meta: model = SimpleCategory - fields = '__all__' + fields = "__all__" class SimpleCategoryAdmin(CategoryBaseAdmin): diff --git a/example/simpletext/migrations/0001_initial.py b/example/simpletext/migrations/0001_initial.py index d66db39..fe231e1 100644 --- a/example/simpletext/migrations/0001_initial.py +++ b/example/simpletext/migrations/0001_initial.py @@ -1,10 +1,9 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.9.13 on 2017-10-12 20:27 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion import mptt.fields +from django.db import migrations, models class Migration(migrations.Migration): @@ -15,35 +14,45 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='SimpleCategory', + name="SimpleCategory", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100, verbose_name='name')), - ('slug', models.SlugField(verbose_name='slug')), - ('active', models.BooleanField(default=True, verbose_name='active')), - ('lft', models.PositiveIntegerField(db_index=True, editable=False)), - ('rght', models.PositiveIntegerField(db_index=True, editable=False)), - ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)), - ('level', models.PositiveIntegerField(db_index=True, editable=False)), - ('parent', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='simpletext.SimpleCategory', verbose_name='parent')), + ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ("name", models.CharField(max_length=100, verbose_name="name")), + ("slug", models.SlugField(verbose_name="slug")), + ("active", models.BooleanField(default=True, verbose_name="active")), + ("lft", models.PositiveIntegerField(db_index=True, editable=False)), + ("rght", models.PositiveIntegerField(db_index=True, editable=False)), + ("tree_id", models.PositiveIntegerField(db_index=True, editable=False)), + ("level", models.PositiveIntegerField(db_index=True, editable=False)), + ( + "parent", + mptt.fields.TreeForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="children", + to="simpletext.SimpleCategory", + verbose_name="parent", + ), + ), ], options={ - 'verbose_name_plural': 'simple categories', + "verbose_name_plural": "simple categories", }, ), migrations.CreateModel( - name='SimpleText', + name="SimpleText", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255)), - ('description', models.TextField(blank=True)), - ('created', models.DateTimeField(auto_now_add=True)), - ('updated', models.DateTimeField(auto_now=True)), + ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ("name", models.CharField(max_length=255)), + ("description", models.TextField(blank=True)), + ("created", models.DateTimeField(auto_now_add=True)), + ("updated", models.DateTimeField(auto_now=True)), ], options={ - 'ordering': ('-created',), - 'get_latest_by': 'updated', - 'verbose_name_plural': 'Simple Text', + "ordering": ("-created",), + "get_latest_by": "updated", + "verbose_name_plural": "Simple Text", }, ), ] diff --git a/example/simpletext/migrations/0002_auto_20171204_0721.py b/example/simpletext/migrations/0002_auto_20171204_0721.py index 2205f4c..6ce4e0a 100644 --- a/example/simpletext/migrations/0002_auto_20171204_0721.py +++ b/example/simpletext/migrations/0002_auto_20171204_0721.py @@ -1,39 +1,46 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.10.5 on 2017-12-04 07:21 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion import django.db.models.manager +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('categories', '0002_auto_20170217_1111'), - ('simpletext', '0001_initial'), + ("categories", "0002_auto_20170217_1111"), + ("simpletext", "0001_initial"), ] operations = [ migrations.AlterModelManagers( - name='simplecategory', + name="simplecategory", managers=[ - ('tree', django.db.models.manager.Manager()), + ("tree", django.db.models.manager.Manager()), ], ), migrations.AddField( - model_name='simpletext', - name='categories', - field=models.ManyToManyField(blank=True, related_name='m2mcats', to='categories.Category'), + model_name="simpletext", + name="categories", + field=models.ManyToManyField(blank=True, related_name="m2mcats", to="categories.Category"), ), migrations.AddField( - model_name='simpletext', - name='primary_category', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='categories.Category'), + model_name="simpletext", + name="primary_category", + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to="categories.Category" + ), ), migrations.AddField( - model_name='simpletext', - name='secondary_category', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='simpletext_sec_cat', to='categories.Category'), + model_name="simpletext", + name="secondary_category", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="simpletext_sec_cat", + to="categories.Category", + ), ), ] diff --git a/example/simpletext/migrations/0003_auto_20200306_0928.py b/example/simpletext/migrations/0003_auto_20200306_0928.py index 0d786bc..a33be27 100644 --- a/example/simpletext/migrations/0003_auto_20200306_0928.py +++ b/example/simpletext/migrations/0003_auto_20200306_0928.py @@ -6,23 +6,23 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('simpletext', '0002_auto_20171204_0721'), + ("simpletext", "0002_auto_20171204_0721"), ] operations = [ migrations.AlterField( - model_name='simplecategory', - name='level', + model_name="simplecategory", + name="level", field=models.PositiveIntegerField(editable=False), ), migrations.AlterField( - model_name='simplecategory', - name='lft', + model_name="simplecategory", + name="lft", field=models.PositiveIntegerField(editable=False), ), migrations.AlterField( - model_name='simplecategory', - name='rght', + model_name="simplecategory", + name="rght", field=models.PositiveIntegerField(editable=False), ), ] diff --git a/example/simpletext/models.py b/example/simpletext/models.py index 0fe96d1..e7ccaed 100755 --- a/example/simpletext/models.py +++ b/example/simpletext/models.py @@ -14,9 +14,9 @@ class SimpleText(models.Model): updated = models.DateTimeField(auto_now=True) class Meta: - verbose_name_plural = 'Simple Text' - ordering = ('-created',) - get_latest_by = 'updated' + verbose_name_plural = "Simple Text" + ordering = ("-created",) + get_latest_by = "updated" def __unicode__(self): return self.name @@ -24,16 +24,19 @@ class SimpleText(models.Model): def get_absolute_url(self): try: from django.db.models import permalink - return permalink('simpletext_detail_view_name', [str(self.id)]) + + return permalink("simpletext_detail_view_name", [str(self.id)]) except ImportError: from django.urls import reverse - return reverse('simpletext_detail_view_name', args=[str(self.id)]) + + return reverse("simpletext_detail_view_name", args=[str(self.id)]) class SimpleCategory(CategoryBase): """A Test of catgorizing""" + class Meta: - verbose_name_plural = 'simple categories' + verbose_name_plural = "simple categories" # mport categories diff --git a/example/simpletext/tests.py b/example/simpletext/tests.py index 73d6465..f51d798 100755 --- a/example/simpletext/tests.py +++ b/example/simpletext/tests.py @@ -16,9 +16,11 @@ class SimpleTest(TestCase): self.assertEqual(1 + 1, 2) -__test__ = {"doctest": """ +__test__ = { + "doctest": """ Another way to test that 1 + 1 is equal to 2. >>> 1 + 1 == 2 True -"""} +""" +} diff --git a/example/static/editor/jquery.treeTable.css b/example/static/editor/jquery.treeTable.css index f9fccd9..26828b6 100644 --- a/example/static/editor/jquery.treeTable.css +++ b/example/static/editor/jquery.treeTable.css @@ -62,4 +62,4 @@ .treeTable .ui-draggable-dragging { color: #000; z-index: 1; -} \ No newline at end of file +} diff --git a/example/static/editor/jquery.treeTable.js b/example/static/editor/jquery.treeTable.js index 522b2c5..412bdaf 100644 --- a/example/static/editor/jquery.treeTable.js +++ b/example/static/editor/jquery.treeTable.js @@ -455,4 +455,4 @@ function parentOf(node) { return $(node).parentOf(); } -})(django.jQuery); \ No newline at end of file +})(django.jQuery); diff --git a/example/static/js/genericcollections.js b/example/static/js/genericcollections.js index 584208e..8081eb8 100644 --- a/example/static/js/genericcollections.js +++ b/example/static/js/genericcollections.js @@ -17,4 +17,4 @@ function showGenericRelatedObjectLookupPopup(triggeringLink, ctArray) { var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); win.focus(); return false; -} \ No newline at end of file +} diff --git a/example/urls.py b/example/urls.py index 4c34998..cab9d28 100644 --- a/example/urls.py +++ b/example/urls.py @@ -12,23 +12,16 @@ ROOT_PATH = os.path.dirname(os.path.dirname(__file__)) urlpatterns = ( # Example: # (r'^sample/', include('sample.foo.urls')), - # Uncomment the admin/doc line below and add 'django.contrib.admindocs' # to INSTALLED_APPS to enable admin documentation: # (r'^admin/doc/', include('django.contrib.admindocs.urls')), - # Uncomment the next line to enable the admin: - url(r'^admin/', admin.site.urls), - url(r'^categories/', include('categories.urls')), + url(r"^admin/", admin.site.urls), + url(r"^categories/", include("categories.urls")), # r'^cats/', include('categories.urls')), - - url(r'^static/categories/(?P.*)$', serve, - {'document_root': ROOT_PATH + '/categories/media/categories/'}), - + url(r"^static/categories/(?P.*)$", serve, {"document_root": ROOT_PATH + "/categories/media/categories/"}), # (r'^static/editor/(?P.*)$', 'django.views.static.serve', # {'document_root': ROOT_PATH + '/editor/media/editor/', # 'show_indexes':True}), - - url(r'^static/(?P.*)$', serve, {'document_root': os.path.join(ROOT_PATH, 'example', 'static')}), - + url(r"^static/(?P.*)$", serve, {"document_root": os.path.join(ROOT_PATH, "example", "static")}), ) From 01250045241b3e4aac9be146c9df11f1a3acccbd Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sun, 5 Dec 2021 10:13:19 -0600 Subject: [PATCH 14/51] Added a .editorconfig file. --- .editorconfig | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..585e2ab --- /dev/null +++ b/.editorconfig @@ -0,0 +1,23 @@ +# http://editorconfig.org + +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{py,rst,ini}] +indent_style = space +indent_size = 4 + +[*.{html,css,scss,json,yml}] +indent_style = space +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false + +[Makefile] +indent_style = tab From e377eccb8cbe3a60a74b2d304514d380d7fcfac6 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sun, 5 Dec 2021 10:14:31 -0600 Subject: [PATCH 15/51] Changed the requirements to use chained files. --- requirements.txt | 3 +-- requirements/dev.txt | 8 ++++++++ requirements/prod.txt | 2 ++ requirements/test.txt | 1 + 4 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 requirements/dev.txt create mode 100644 requirements/prod.txt create mode 100644 requirements/test.txt diff --git a/requirements.txt b/requirements.txt index b0a4601..5eaadb8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1 @@ -django-mptt -unicode-slugify +-r requirements/prod.txt diff --git a/requirements/dev.txt b/requirements/dev.txt new file mode 100644 index 0000000..1c3dcd1 --- /dev/null +++ b/requirements/dev.txt @@ -0,0 +1,8 @@ +--find-links https://github.com/PennyDreadfulMTG/pystache/releases/ +-r test.txt + +bump2version>=1.0.1 +git-fame>=1.12.2 +gitchangelog>=3.0.4 +pre-commit +pystache>=0.6.0 diff --git a/requirements/prod.txt b/requirements/prod.txt new file mode 100644 index 0000000..b0a4601 --- /dev/null +++ b/requirements/prod.txt @@ -0,0 +1,2 @@ +django-mptt +unicode-slugify diff --git a/requirements/test.txt b/requirements/test.txt new file mode 100644 index 0000000..ca0c6f8 --- /dev/null +++ b/requirements/test.txt @@ -0,0 +1 @@ +-r prod.txt From ebefa59f6eb34776af69e7653cc319d0e4ca1ec6 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sun, 5 Dec 2021 10:15:42 -0600 Subject: [PATCH 16/51] Added ability to generate a Changelog. --- .gitchangelog.rc | 311 ++++++++++++ CHANGELOG.md | 1228 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1539 insertions(+) create mode 100644 .gitchangelog.rc create mode 100644 CHANGELOG.md diff --git a/.gitchangelog.rc b/.gitchangelog.rc new file mode 100644 index 0000000..47ebf32 --- /dev/null +++ b/.gitchangelog.rc @@ -0,0 +1,311 @@ +# -*- coding: utf-8; mode: python -*- +# +# Format +# +# ACTION: [AUDIENCE:] COMMIT_MSG [!TAG ...] +# +# Description +# +# ACTION is one of 'chg', 'fix', 'new' +# +# Is WHAT the change is about. +# +# 'chg' is for refactor, small improvement, cosmetic changes... +# 'fix' is for bug fixes +# 'new' is for new features, big improvement +# +# AUDIENCE is optional and one of 'dev', 'usr', 'pkg', 'test', 'doc' +# +# Is WHO is concerned by the change. +# +# 'dev' is for developpers (API changes, refactors...) +# 'usr' is for final users (UI changes) +# 'pkg' is for packagers (packaging changes) +# 'test' is for testers (test only related changes) +# 'doc' is for doc guys (doc only changes) +# +# COMMIT_MSG is ... well ... the commit message itself. +# +# TAGs are additionnal adjective as 'refactor' 'minor' 'cosmetic' +# +# They are preceded with a '!' or a '@' (prefer the former, as the +# latter is wrongly interpreted in github.) Commonly used tags are: +# +# 'refactor' is obviously for refactoring code only +# 'minor' is for a very meaningless change (a typo, adding a comment) +# 'cosmetic' is for cosmetic driven change (re-indentation, 80-col...) +# 'wip' is for partial functionality but complete subfunctionality. +# +# Example: +# +# new: usr: support of bazaar implemented +# chg: re-indentend some lines !cosmetic +# new: dev: updated code to be compatible with last version of killer lib. +# fix: pkg: updated year of licence coverage. +# new: test: added a bunch of test around user usability of feature X. +# fix: typo in spelling my name in comment. !minor +# +# Please note that multi-line commit message are supported, and only the +# first line will be considered as the "summary" of the commit message. So +# tags, and other rules only applies to the summary. The body of the commit +# message will be displayed in the changelog without reformatting. + + +# +# ``ignore_regexps`` is a line of regexps +# +# Any commit having its full commit message matching any regexp listed here +# will be ignored and won't be reported in the changelog. +# +ignore_regexps = [ + r'@minor', r'!minor', + r'@cosmetic', r'!cosmetic', + r'@refactor', r'!refactor', + r'@wip', r'!wip', + r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[p|P]kg:', + r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[d|D]ev:', + r'^(.{3,3}\s*:)?\s*[fF]irst commit.?\s*$', + r'^Initial Commit.$', + r'^Version updated.+$', + r'^$', # ignore commits with empty messages + r'^Merge branch .+', + r'^Merge pull .+', +] + + +# ``section_regexps`` is a list of 2-tuples associating a string label and a +# list of regexp +# +# Commit messages will be classified in sections thanks to this. Section +# titles are the label, and a commit is classified under this section if any +# of the regexps associated is matching. +# +# Please note that ``section_regexps`` will only classify commits and won't +# make any changes to the contents. So you'll probably want to go check +# ``subject_process`` (or ``body_process``) to do some changes to the subject, +# whenever you are tweaking this variable. +# +section_regexps = [ + ('New', [ + r'^\[?[nN][eE][wW]\]?\s*:?\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', + r'^\[?[aA][dD][dD]\]?\s*:?\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', + ]), + ('Updates', [ + r'^\[?[uU][pP][dD][aA][tT][eE]\s*:?\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', + r'^\[?[cC][hH][aA][nN][gG][eE][dD]?\s*:?\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', + ]), + ('Fix', [ + r'^\[?[fF][iI][xX]\]?\s*:?\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', + ]), + + ('Other', None # Match all lines + ), + +] + + +# ``body_process`` is a callable +# +# This callable will be given the original body and result will +# be used in the changelog. +# +# Available constructs are: +# +# - any python callable that take one txt argument and return txt argument. +# +# - ReSub(pattern, replacement): will apply regexp substitution. +# +# - Indent(chars=" "): will indent the text with the prefix +# Please remember that template engines gets also to modify the text and +# will usually indent themselves the text if needed. +# +# - Wrap(regexp=r"\n\n"): re-wrap text in separate paragraph to fill 80-Columns +# +# - noop: do nothing +# +# - ucfirst: ensure the first letter is uppercase. +# (usually used in the ``subject_process`` pipeline) +# +# - final_dot: ensure text finishes with a dot +# (usually used in the ``subject_process`` pipeline) +# +# - strip: remove any spaces before or after the content of the string +# +# - SetIfEmpty(msg="No commit message."): will set the text to +# whatever given ``msg`` if the current text is empty. +# +# Additionally, you can `pipe` the provided filters, for instance: +# body_process = Wrap(regexp=r'\n(?=\w+\s*:)') | Indent(chars=" ") +# body_process = Wrap(regexp=r'\n(?=\w+\s*:)') +# body_process = noop +body_process = ReSub(r'((^|\n)[A-Z]\w+(-\w+)*: .*(\n\s+.*)*)+$', r'') | strip + + +# ``subject_process`` is a callable +# +# This callable will be given the original subject and result will +# be used in the changelog. +# +# Available constructs are those listed in ``body_process`` doc. +subject_process = (strip | + ReSub(r'^(\[\w+\])\s*:?\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n@]*)(@[a-z]+\s+)*$', r'\4') | + SetIfEmpty("No commit message.") | ucfirst | final_dot) + + +# ``tag_filter_regexp`` is a regexp +# +# Tags that will be used for the changelog must match this regexp. +# +tag_filter_regexp = r'^[0-9]+\.[0-9]+(\.[0-9]+)?$' + + +# ``unreleased_version_label`` is a string or a callable that outputs a string +# +# This label will be used as the changelog Title of the last set of changes +# between last valid tag and HEAD if any. +def unreleased_date(): + import datetime + return 'Unreleased ({})'.format(datetime.datetime.now().strftime('%Y-%m-%d')) +unreleased_version_label = unreleased_date + + +# ``output_engine`` is a callable +# +# This will change the output format of the generated changelog file +# +# Available choices are: +# +# - rest_py +# +# Legacy pure python engine, outputs ReSTructured text. +# This is the default. +# +# - mustache() +# +# Template name could be any of the available templates in +# ``templates/mustache/*.tpl``. +# Requires python package ``pystache``. +# Examples: +# - mustache("markdown") +# - mustache("restructuredtext") +# +# - makotemplate() +# +# Template name could be any of the available templates in +# ``templates/mako/*.tpl``. +# Requires python package ``mako``. +# Examples: +# - makotemplate("restructuredtext") +# +# output_engine = rest_py +# output_engine = mustache("restructuredtext") +output_engine = mustache("markdown") +# output_engine = makotemplate("restructuredtext") + + +# ``include_merge`` is a boolean +# +# This option tells git-log whether to include merge commits in the log. +# The default is to include them. +include_merge = True + + +# ``log_encoding`` is a string identifier +# +# This option tells gitchangelog what encoding is outputed by ``git log``. +# The default is to be clever about it: it checks ``git config`` for +# ``i18n.logOutputEncoding``, and if not found will default to git's own +# default: ``utf-8``. +log_encoding = 'utf-8' + +OUTPUT_FILE = "CHANGELOG.md" +INSERT_POINT_REGEX = r'''(?isxu) +^ +( + \s*\#\s+Changelog\s*(\n|\r\n|\r) ## ``Changelog`` line +) + +( ## Match all between changelog and release rev + ( + (?! + (?<=(\n|\r)) ## look back for newline + \#\#\s+%(rev)s ## revision + \s+ + \([0-9]+-[0-9]{2}-[0-9]{2}\)(\n|\r\n|\r) ## date + ) + . + )* +) + +(?P\#\#\s+(?P%(rev)s)) +''' % {'rev': r"[0-9]+\.[0-9]+(\.[0-9]+)?"} + + +# ``publish`` is a callable +# +# Sets what ``gitchangelog`` should do with the output generated by +# the output engine. ``publish`` is a callable taking one argument +# that is an interator on lines from the output engine. +# +# Some helper callable are provided: +# +# Available choices are: +# +# - stdout +# +# Outputs directly to standard output +# (This is the default) +# +# - FileInsertAtFirstRegexMatch(file, pattern, idx=lamda m: m.start()) +# +# Creates a callable that will parse given file for the given +# regex pattern and will insert the output in the file. +# ``idx`` is a callable that receive the matching object and +# must return a integer index point where to insert the +# the output in the file. Default is to return the position of +# the start of the matched string. +# +# - FileRegexSubst(file, pattern, replace, flags) +# +# Apply a replace inplace in the given file. Your regex pattern must +# take care of everything and might be more complex. Check the README +# for a complete copy-pastable example. +# +publish = FileRegexSubst(OUTPUT_FILE, INSERT_POINT_REGEX, r"\1\o\n\g") + + +# ``revs`` is a list of callable or a list of string +# +# callable will be called to resolve as strings and allow dynamical +# computation of these. The result will be used as revisions for +# gitchangelog (as if directly stated on the command line). This allows +# to filter exaclty which commits will be read by gitchangelog. +# +# To get a full documentation on the format of these strings, please +# refer to the ``git rev-list`` arguments. There are many examples. +# +# Using callables is especially useful, for instance, if you +# are using gitchangelog to generate incrementally your changelog. +# +# Some helpers are provided, you can use them:: +# +# - FileFirstRegexMatch(file, pattern): will return a callable that will +# return the first string match for the given pattern in the given file. +# If you use named sub-patterns in your regex pattern, it'll output only +# the string matching the regex pattern named "rev". +# +# - Caret(rev): will return the rev prefixed by a "^", which is a +# way to remove the given revision and all its ancestor. +# +# Please note that if you provide a rev-list on the command line, it'll +# replace this value (which will then be ignored). +# +# If empty, then ``gitchangelog`` will act as it had to generate a full +# changelog. +# +# The default is to use all commits to make the changelog. +# revs = ["^1.0.3", ] +revs = [ + Caret(FileFirstRegexMatch(OUTPUT_FILE, INSERT_POINT_REGEX)), + "HEAD" +] diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..6159a28 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,1228 @@ +# Changelog + + +## Unreleased (2021-12-05) + +### New + +* Added pre-commit configuration and configuration for the tools. [Corey Oordt] + +* Added XML reporting for code coverage. #164. [Corey Oordt] + +* Added codecov uploading to Tox. #164. [Corey Oordt] + +* Adds GitHub Actions to run Tox. #164. [Corey Oordt] + +* Added contributing documentation. #164. [Corey Oordt] + +* Added Jazzband badge to README. [Corey Oordt] + + Also changed it to Markdown. + +### Updates + +* Changed codecov uploading pattern. [Corey Oordt] + +* Updated tox to run coverage commands together. [Corey Oordt] + +* Updated references to Python 3.10. #164. [Corey Oordt] + +* Updated gitignore to be more ignorative. [Corey Oordt] + +* Updates URL of the project to Jazzband. #164. [Corey Oordt] + +### Other + +* Removed Python 3.10 testing until compatibility established. [Corey Oordt] + + +## 1.8.0 (2020-08-31) + +### New + +* Add support for Django 3.1. [gantonayde] + + In Django 3.1 the compatibility import of django.core.exceptions.FieldDoesNotExist in django.db.models.fields is removed. + + So we'd have to update the package by replacing: + from django.db.models.fields import FieldDoesNotExist + with + from django.core.exceptions import FieldDoesNotExist + +### Updates + +* Update the version to 1.8. [Brent O'Connor] + +* Update tox tests to run Django 3.1 and removed support for Python 2.7. [Brent O'Connor] + +### Other + +* Remove Python 2.7 from the Travis config. [Brent O'Connor] + +* Django-mptt 0.11 needed for Django 3.1. [gantonayde] + + In Django 3.1 the compatibility import of django.core.exceptions.FieldDoesNotExist in django.db.models.fields is removed. + django-mptt should be the latest version (0.11 as of now) + + +## 1.7.2 (2020-05-18) + +### Updates + +* Update publish make task. [Brent O'Connor] + +### Fix + +* Fix #152. [Petr Dlouhý] + +### Other + +* Include missing migration. [Carlos Cesar Caballero Díaz] + +* Ignore .python-version. [Brent O'Connor] + + +## 1.7.1 (2020-03-06) + +### New + +* Add missing migrations. [Brent O'Connor] + + +## 1.7.0 (2020-02-04) + +### New + +* Add newer Django versions to tox.ini. [Petr Dlouhý] + +### Updates + +* Update django-mptt. [Petr Dlouhý] + +* Update `make publish` [Brent O'Connor] + +### Fix + +* Fixes to Django 3.0. [Petr Dlouhý] + + +## 1.6.1 (2019-06-26) + +### New + +* Adding opts to context for Django version 2 and above. [Gagandeep Singh] + +* Django 2.0 support in Admin. [Gagandeep Singh] + + TypeError at /admin/categories/category/ + __init__() missing 1 required positional argument: 'sortable_by' + +### Updates + +* Update Travis. [Brent O'Connor] + + * travis.yml + * build badge + * Remove 3.7 from Travis config since it doesn't look like it's supported + * Switch to tox-travis. + +* Updated tree editor for typo. [Gagandeep Singh] + +* Upgrade build environment to Xenial. [Brent O'Connor] + + This makes it so Django 2.2 tests should pass + +### Fix + +* Fix Travis so it uses the correct python versions. [Brent O'Connor] + +* Fix Travis so it works with Python 3.7. [Brent O'Connor] + +* Fix 'Models aren't loaded yet' warning on import. [Frankie Dintino] + + categories.registration._process_registry was being called in + categories/__init__.py, but since Django 1.9 it hasn't been possible to + perform operations with models until the app registry is fully + loaded. Currently the `AppRegistryNotReady` exception is being caught + and printed, which means it is never actually executed on load. + + Since this code isn't currently doing anything (other than emitting a + print() of a warning), I've removed it. + +* Fix tests. [Brent O'Connor] + + Also dropped testing Django 1.10 since django-mptt requires Django>=1.11. + +* Fix for TOXENV=py27-lint. [Gagandeep Singh] + +* Fixing model for TOXENV=py36-django110. [Gagandeep Singh] + +* Py27-lint test fix. [Gagandeep Singh] + +* Test Cases fix. [Gagandeep Singh] + +* Bug Fix : sortable was last argument. [Gagandeep Singh] + + + +## 1.6.0 (2018-02-27) + +### Updates + +* Updated the Travis CI config. [Brent O'Connor] + +* Changed from using a string to importing the actual CASCADE function. [Brent O'Connor] + +### Other + +* Proposes changes based on 366ff74619811505ac73ac5ea2c0096ddab0ac51 and pull request #140 for Django 2.0 to pass CI tests. [goetzb] + +* Made updates to get everything working with Django 2. [Brent O'Connor] + + +## 1.5.4 (2017-10-13) + +### New + +* Django 1.11 compatibility. [Hodossy Szabolcs] + +* Support Django 1.11 testing environment. [Egor] + +* Add migrations for simpletext example app. [Corey Oordt] + +### Fix + +* Fix changlist TypeError. Return RequestContext as dict on changelist_view. [Egor] + + * Based on [changes in Django 1.11](https://docs.djangoproject.com/en/1.11/releases/1.11/#django-template-backends-django-template-render-prohibits-non-dict-context) + +* Get management commands compatible with Django 1.10+ [Corey Oordt] + +### Updates + +* Updated test settings to test generic relations. [Corey Oordt] + +* Updated tox and travis configurations to check py2.7 and 3.6 and django 1.8-1.11. [Corey Oordt] + + +### Other + +* Made sure example was excluded from packaging. [Corey Oordt] + +* Remove old django-cbv reference and adds better error checking in views. [Corey Oordt] + +* Retrieve content types lazily in Generic Relations admin. [Corey Oordt] + +* Check for a valid session id before trying to save or rollback a transaction. [Corey Oordt] + +* Added additional test coverage for management commands and views. [Corey Oordt] + +* Remove south migrations. [Corey Oordt] + +* Set decendent_ids to empty list if not saved. [Corey Oordt] + +* Removing every occurrence of Requestcontext and Context. [Hodossy Szabolcs] + + +## 1.5.3 (2017-03-31) + +### Fix + +* Fixed a ValueError that happened when trying to save a Category that has a thumbnail. [Brent O'Connor] + +### Other + +* Version bump. [Brent O'Connor] + + +## 1.5.2 (2017-03-29) + +### Fix + +* Fixed a unicode error that happens with Python 2.7. [Brent O'Connor] + + +## 1.5.1 (2017-02-17) + +### New + +* Added a missing migration. [Brent O'Connor] + +### Updates + +* Updated README.rst with svg badge. [Sobolev Nikita] + +### Fix + +* Close table tag in templatetag result. [Dheeraj Sayala] + + In items_for_tree_result, there's a format_html call which builds HTML via string interpolation. It missed back slash in the closing tag. This commit adds that. + +### Other + +* Just to be safe - pin it down. [Primož Verdnik] + + +## 1.5 (2016-11-14) + +### Updates + +* Updated the Travis config to test for Django 1.10. [Brent O'Connor] + +* Updated django-categories to work with Django 1.10. [Brent O'Connor] + + +## 1.4.3 (2016-10-21) + +### Fix + +* Fixes popup raw_id fields for django versions 8 or greater. [Jordan Roth] + + +## 1.4.2 (2016-04-19) + +### Fix + +* Fixed it so display_for_field works with Django 1.8 and 1.9. [Brent O'Connor] + + +## 1.4.1 (2016-03-31) + +### New + +* Added setup.cfg file for creating universal wheel distribution. [Brent O'Connor] + +* Added coverage to tox. [Brent O'Connor] + +* Added some tests to test the admin. [Brent O'Connor] + +* Added a makefile for common tasks. [Brent O'Connor] + +### Updates + +* Updated the new in 1.4 information. [Brent O'Connor] + +### Fix + +* Fixed an exception error that happens when saving a category in the admin. [msaelices] + +* Removed some RemovedInDjango110Warning warnings. [Brent O'Connor] + +### Other + +* Moved all template settings for the example app into the TEMPLATES Django setting. [Brent O'Connor] + +* Avoid the "Cannot call get_descendants on unsaved Category instances" ValueError when adding categories in admin interface. [msaelices] + +* Removed contributors from the README since that information is in CREDITS.md. No sense maintaining it two places. [Brent O'Connor] + + +## 1.4 (2016-02-15) + +### New + +* Added a tox.ini and updated the travis config to work with tox. [Brent O'Connor] + +### Updates + +* Updated admin_tree_list_tags so that EMPTY_CHANGELIST_VALUE has a compatible way of working with Django 1.9 and older versions. [Brent O'Connor] + +* Updated urls to work without patterns since patterns is being deprecated. [Brent O'Connor] + +* Updated settings to remove all the TEMPLATE_* settings and put them into the TEMPLATES dict for Django 1.9 compatibility. [Brent O'Connor] + +* Changed __unicode__ to __str__ on the CategoryBase class for Python 3 compatibility. [Brent O'Connor] + +* Upgraded to django-mptt 0.8. [Brent O'Connor] + +* Switched to using _meta.get_fields() instead of ._meta.get_all_field_names() for compatibility with Django 1.9. [Brent O'Connor] + +* Replaced django.db.models.get_model with django.apps.apps.get_model for future compatibility with Django. [Brent O'Connor] + +* Switched to importing the correct templatetags that got renamed. [Brent O'Connor] + +* Switched form using smart_unicode to smart_text and force_unicode to force_text. [Brent O'Connor] + +* Switched from using django.db.models.loading.get_model to using django.apps.apps.get_model. [Brent O'Connor] + +* Switched form using force_unicode to force_text. [Brent O'Connor] + +* Use singleton `registry` to import `register_fk` and `register_m2m` since they are members on `Registry` class. [Orestes Sanchez] + +### Fix + +* Fixed the max_length setting to use a int instead of a string. [Brent O'Connor] + +* Fixed a test: file() doesn't work in Python 3, used open() instead. [Brent O'Connor] + +* Made a bunch of flake8 fixes and also added flake8 testing to Travis and Tox. [Brent O'Connor] + +* Made a fix for backwards compatibility with Python 2. [Brent O'Connor] + +* B'' doesn't work under Python 3 in a migration file. [Brent O'Connor] + +### Other + +* Ran the 2to3 script `2to3 -w .` [Brent O'Connor] + +* Ugettext may cause circular import. [Basile LEGAL] + +* Run the test with a different configuration. [Orestes Sanchez] + + +## 1.3 (2015-06-09) + +### New + +* Added the fields property with it set to '__all__' in order to not get the RemovedInDjango18Warning. [Brent O'Connor] + +* Defaulting the url prefix to / if it can't find the category tree. [Corey Oordt] + +* I18n: add french translation. [Olivier Le Brouster] + +### Updates + +* Updates the existing migration to south_migrations. [Corey Oordt] + +* Renamed get_query_set to get_queryset to get Django categories to work in Django 1.7. I'm not sure of a good way to make this work in Django 1.6. [Brent O'Connor] + +* Migrations + + * Dramatically refactored how migrations are performed to work with Django 1.7. [Corey Oordt] + + * Missed some migrations. [Jose Soares] + + * Changing migration dependency of contenttypes to 0001_initial for support for Django 1.7. [Corey Oordt] + +### Fix + +* Fixes potential double imports in dev and test servers. [Corey Oordt] + +* Fixed a potential issue with double-loading of the dev server. [Corey Oordt] + +* Fixes a conflict with treebeard. They stole the name admin_tree_list. [Corey Oordt] + +* Fixed the RemovedInDjango19Warning deprecation warning. [Brent O'Connor] + +* Fixed tests so they run under Django 1.7. [Brent O'Connor] + +* fixes registration when there is no app config. [Corey Oordt] + +* [-] Fixed some tree editor and generic collection issues. [Jose Soares] + +### Other + +* Removing outdated settings and updating outdated files. [Corey Oordt] + +* [-] 1.6/1.7/1.8 compatiable changes (WIP) [Jose Soares] + + +## 1.2.3 (2015-05-05) + +### New + +* Added a new way to register models manually. [Corey Oordt] + +* Bootstrap class on table (important for django-suit) [Mirza Delic] + +### Updates + +* Update requirements. [Sina Samavati] + +* Using custom model in CategoryDetailView. [Enver Bisevac] + +### Fix + +* Fix unicode slug issue. [Sina Samavati] + + +## 1.2.2 (2013-07-07) + +### New + +* Italian localization. [Iacopo Spalletti] + +### Fix + +* Fixing migration script for adding fields. [Corey Oordt] + +* Fixed i18n and failing test in Django 1.4. [Corey Oordt] + +### Other + +* Load I18N templatetags. [Eugene] + + +## 1.2.1 (2013-03-22) + +### Fix + +* Fixed i18n and failing test in Django 1.4. [Corey Oordt] + + +## 1.2 (2013-03-20) + +### New + +* Added admin settings documentation. [Corey Oordt] + +* Added customization of admin fieldsets. [Corey Oordt] + +### Updates + +* Update categories/templatetags/category_tags.py. [Glen] + + * Added NoneType check to display_drilldown_as_ul on line 188 to fix NoneType error. + + * Added str() to line 49 to fix an error where .strip("'\"") in get_category is getting called on a non-string category_string. + +* Made updates so django-categories works with django-grappelli. [Brent O'Connor] + +* Updated the code so it will work with or without Grappelli installed. [Brent O'Connor] + +### Fix + +* Fixing a few minor Django 1.5 incompatibilities. [Corey Oordt] + +* Fix for Django 1.5: {% url %} parameter needs to be quoted. [Corey Oordt] + +* Fixed an exception error. [Brent O'Connor] + + Fixed an exception error that occurs when an empty form is submitted for apps that are created using categories.base.CategoryBase. + +### Other + +* Version bump 1.2. [Corey Oordt] + +* Updating the admin template to support the latest django admin code. [Corey Oordt] + +* I18n. [winniehell] + +* German translation. [winniehell] + +* 1.5 compat: remove adminmedia templatetag calls. [Yohan Boniface] + + See https://docs.djangoproject.com/en/1.5/releases/1.5/#miscellaneous + +* Made it so django-categories works with Django 1.5 and Grappelli 2.4.4. [Brent O'Connor] + +* Simplified the assignment of the IS_GRAPPELLI_INSTALLED variable. [Brent O'Connor] + + + +## 1.1.3 (2012-08-29) + +### Other + +* To satisfy a very demanding and owly jsoa, I removed an unused variable. :P. [Corey Oordt] + +* Updating the signal registration to check for south first and fail silently. [Corey Oordt] + +* Moved the registration of the signal to models.py where it will get executed. [Corey Oordt] + +* Refactored the migration script to use the syncdb signal. The post_migrate signal only fires for south-managed apps, so it isn't as useful. [Corey Oordt] + + +## 1.1.2 (2012-08-18) + +### New + +* Added travisci. [Jose Soares] + +### Fix + +* Fixed a bug in the compatibility layer. [Corey Oordt] + +* Minor tweak to tempatetag tests. [Jose Soares] + +### Other + +* Can't use the m2m tests because it conflicts with the fk tests. [Corey Oordt] + +* Placing some south imports into try blocks. [Corey Oordt] + +* Capitalizing the various REGISTRY settings. [Corey Oordt] + +* Refactored the registration of fields from __init__ to a new module. [Corey Oordt] + + It also makes it easier to test. + + +## 1.1 (2012-07-12) + +### New + +* Added Brad Jasper to the credits and updated Jonathan's github account. [Corey Oordt] + +* Added queryset parameter to ChangeList.get_ordering() [Brad Jasper] + +### Updates + +* Updated read me and version bump to 1.1. [Corey Oordt] + +* Updated and rendered docs. [Corey Oordt] + +* Update to template tags to include ways to retrieve an object from a model other than Category. [Corey Oordt] + +* Updated the credits to add Iacopo Spalletti. [Corey Oordt] + +* Updated CREDITS, docs. [Jose Soares] + +### Fix + +* Fixed an incorrect include in the example. [Corey Oordt] + +* Fixed some Django 1.4 cosmetic issues. [Corey Oordt] + +* Fixes Pull Request #37 Adds notification in the readme regarding issue with South version 0.7.4. [Corey Oordt] + +* Fixed format error. [Iacopo Spalletti] + +* Fixes issue #40 Checks for instance of CategoryBase instead of Category. [Corey Oordt] + + There are still some template tags that won't work with subclasses. Need a better solution for those tags. + +### Other + +* Template tags now work with any derivative of CategoryBase. Recognizes the "using" param to specify the model to use. [Corey Oordt] + +* Sorry, typo in documentation. [Iacopo Spalletti] + +* Documented the upgrade path from 1.0.2 and 1.0.3 plus a small migration to keep things in sync. [Iacopo Spalletti] + +* Stylistic fixes and docs. [Martin Matusiak] + +* Make it optional to register in admin. [Martin Matusiak] + +* Use ugettext_lazy. [Martin Matusiak] + +* Minor fix to example app. [Jose Soares] + + +## 1.0.3 (2012-03-28) + +### New + +* Adding additional migrations to fix potential data corruption when renaming the foreign key. [Corey Oordt] + +### Fix + +* Fixed another migration. [Corey Oordt] + +* Altering the #10 migration as it caused strange behavior with data. [Corey Oordt] + + +## 1.0.1 (2012-03-09) + +### Other + +* Importing get_model directly from the loading module appears to fix certain edge cases. [Corey Oordt] + + +## 1.0.2 (2012-03-06) + +### Fix + +* Fixed how the activate/deactivate methods in the admin fetched their models. [Corey Oordt] + +* Fix for django 1.4 compatibility. [Corey Oordt] + +### Other + +* Removed an errant print statement. [Corey Oordt] + + +## 1.0 (2012-02-15) + +### New + +* Added compatibility with Django 1.4. [Corey Oordt] + +* Allow the setting of a SLUG_TRANSLITERATOR to convert non-ASCII characters to ASCII characters. [Corey Oordt] + +### Updates + +* Updated documentation for 1.0b1. [Corey Oordt] + +* Updated migrations to include a data migration. [Corey Oordt] + +* Updated the default view caching to 600, which is the django default instead of forcing the views to NEVER cache at all. [Corey Oordt] + +* Updating docs to correct and simplify the simple custom categories instructions. [Corey Oordt] + +### Fix + +* Also fixes #30 by including the editor's media. [Corey Oordt] + +* Formally fixes #1 by adding the ability to specify a transliteration function. [Corey Oordt] + +* Addresses issue #27; updated musicgenres.json. [Jose Soares] + +* The admin prior to 1.4 requires a different result from get_ordering. [Corey Oordt] + +* This fixes #31. [Corey Oordt] + + * Uses the incorrect version segment. Although it works in 1.4a1, it is not perfect. + +### Other + +* Removed the __init__ method for the treechange list. Don't need it and it varies too much by django version. [Corey Oordt] + + +* Test of the CategoryBase class subclassed without extras. [Corey Oordt] + +* Moved the base models to base.py and did a few PEP8 cleanups. [Corey Oordt] + +* Moved the base classes to a new file to isolate them. [Corey Oordt] + +* Refactored the admin into a base class for subclasses. [Corey Oordt] + +* Extracted a base class for categories to allow other apps to make their own independent category-style models. [Corey Oordt] + + * Updated for django-mptt 0.5.2 + * Fixed typo in the CategoryRelation field in that the foreign key is called 'story' + * Made the order field non-null and default to 0 + * Changed the parent foreign key a TreeForeignKey (for 0.5.2) + * Changed requirements to mptt>=0.5.2 + * Added a migration for model changes. + + +## 0.8.9 (2012-02-06) + +### Updates + +* Updated the docs. [Jose Soares] + +### Fix + +* Fixes issue #30; includes static directory when packaged. [Jose Soares] + +### Other + +* Moved the editor app so it's inside the categories app. [Jose Soares] + + +## 0.8.7 (2012-01-05) + +### Updates + +* Changed behavior of (de)activating an item within the change form: [Corey Oordt] + + Instead of changing all descendants' active status to the current item's, it will only change the descendants' active status if the item is False. + + As it makes sense to have an item active, but its children inactive, it doesn't make sense that an item is inactive, but its descendants are active. + + This doesn't change the activate/deactivate admin actions. They will always affect an item and its descendants. + + +## 0.8.6 (2012-01-03) + +### New + +* Added a django/jQuery stub for previous versions of Django. [Corey Oordt] + +* Added David Charbonnier to the credits. [Corey Oordt] + +### Fix + +* Fixes #13 : Documented installation and re-rendered the docs. [Corey Oordt] + +* Fix missing imports. [David Charbonnier] + +### Other + +* Altered the field type of the alternate url field from URL to Char. This allows relative urls, instead of full urls. [Corey Oordt] + + Added a migration in case the database complains. Really doesn't do anything on that level + + +## 0.8.5 (2011-11-03) + +### Fix + +* Fixes issue #26 by limiting the slug to the first 50 characters. [Corey Oordt] + + +## 0.8.4 (2011-10-14) + +### New + +* Added a version check to support Django 1.1 in a core Django function. [Corey Oordt] + + +## 0.8.3 (2011-10-13) + +### Other + +* Activate and Deactivate of a child no longer (de)activates their parent. [Corey Oordt] + + The query set includes the entire hierarchy. So manually get the categories based on the selected items. Then do them and their children + +* Remove the delete action from the available actions. [Corey Oordt] + + +## 0.8.2 (2011-09-04) + +### Updates + +* Updated docs adding usage in templates and rendered. [Corey Oordt] + +### Fix + +* Fix Issue #25 : The override of __getitem__ was causing issues with analysis of query sets, [Corey Oordt] + + +## 0.8.1 (2011-08-29) + +### Fix + +* Fixes a bug trying to set active on decendants before object is saved. [Corey Oordt] + + +## 0.8 (2011-08-22) + +### New + +* Added to the README. [Corey Oordt] + +* Added an active flag for models. [Corey Oordt] + +### Other + +* Improved Category import. [Corey Oordt] + + +## 0.7.2 (2011-08-19) + +### New + +* Added a check in migrate_app to see if the app is a string or not. [Corey Oordt] + +### Updates + +* Updated the get_version function to be PEP 386 compliant. [Corey Oordt] + +* Changed the DatabaseError import to be more compatible. [Corey Oordt] + +* Updated the readme. [Corey Oordt] + +### Other + +* Pruning the example project. [Corey Oordt] + +* Refactored the editor to become Django 1.1.1 compatible and some PEP8 formatting. [Corey Oordt] + +* Ensure that the slug is always within the 50 characters it needs to be. [Corey Oordt] + + +## 0.7.1 (2011-08-03) + +### Other + +* Due to settings, the migration for the category relations table never would be created. This fixes it. [Corey Oordt] + + +## 0.7 (2011-08-02) + +### New + +* Added a setting for the JAVASCRIPT_URL to make placement of the genericcollections.js file easier. [Corey Oordt] + +* Added compatibility with Django 1.1 by adding missing methods for editor and bumped version to 0.7beta2. [Corey Oordt] + +* Added a get_latest_objects_by_category template tag. Might be useful. [Corey Oordt] + +* Added the ability to add the appropriate fields to a table if configured after an initial syncdb. [Corey Oordt] + +* Added an alternate url field to the model. [Corey Oordt] + +* Added the alternate_url to the admin. [Corey Oordt] + +### Updates + +* Updated and rendered docs. [Corey Oordt] + +* Updated the gitignore for venv file. [Corey Oordt] + +* Altered the inline template to display the content_object instead of the __unicode__ of the middle table. [Corey Oordt] + +* Updating the documentation. [Corey Oordt] + +### Fix + +* Fixed a typo in the docs. [Corey Oordt] + +* [Fixes issue #23] Changes the way the tree shows items when searched. Doesn't hide them in the template. [Corey Oordt] + +* Fixed a bug in the javascript. [Corey Oordt] + +### Other + +* Refactored the registry into a registry of models and fields. This will make it easier for migrations. [Corey Oordt] + +* Deleted old migration scripts since they were migrated to south. [Corey Oordt] + + +## 0.6 (2011-05-18) + +### New + +* Added a Deprecation warning for CATEGORIES_RELATION_MODELS. [Corey Oordt] + +* Adding South migrations. [Corey Oordt] + +* Added some specialized functions for relations. [Corey Oordt] + +* Added a class based view for the detail page of a model related to a category. [Erik Simmler] + +* Added a view that list items of specific model that are related to the current category. [Erik Simmler] + +* Added a class based CategoryDetailView that should be functionally identical to the original function based view. [Erik Simmler] + +* Add optional thumbnail model field. [Evan Culver] + +### Updates + +* Updated docs. [Corey Oordt] + +* Updated README. [Corey Oordt] + +* Updated some of the setup info. [Corey Oordt] + +### Fix + +* Fixed a problem in the new admin creation where it wouldn't properly filter out the category fields by model. [Corey Oordt] + +* [FIXED Issue #17] Refactored how the HTML is rendered, removing the checkbox from the tag and pulling the parent checkbox from the row class. [Corey Oordt] + +* Fixed the deprecated settings in the example app. [Corey Oordt] + +* Fixed small errors in templatetags documentation and docstrings. [Ramiro Morales] + +* Fixed wrong var name in import_categories command. [Andrzej Herok] + +* Fixed the homepage in the setup.py. [Corey Oordt] + +### Other + +* Final doc rendering. [Corey Oordt] + +* Enabled new registry in the example app for testing. [Corey Oordt] + +* The registry default settings needs to be an empty dict, not list. [Corey Oordt] + +* Enable registering of models in settings. [Corey Oordt] + +* Putting registry outside of the try block. [Corey Oordt] + +* Updating settings for Django 1.3. [Corey Oordt] + +* Refactored the thumbnail from imagefield to filefield. [Corey Oordt] + + Why? ImageField causes hits to storage to fill out certain fields. Added a storage class and width/height fields so it is possible to scale the thumbnails and store them somewhere besides the filesystem. + +* Allow for using django-cbv in Django 1.2.x. [Corey Oordt] + +* Slight refactor of the default settings to clean it up. [Corey Oordt] + +* Filled out all contributors. [Corey Oordt] + +* Moved path to category code into its own function to make reuse easier. [Erik Simmler] + +* Remove 'to' from kwargs in CategoryM2MField and CategoryFKField. 'to' is already specified, and causes errors when running unit tests. [Martin Ogden] + +* Make admin js relative to MEDIA_URL. [Evan Culver] + +* Make the initial state of the editor tree an app setting with collapsed as the default. [Erik Simmler] + + +## 0.5.2 (2011-02-14) + +### Other + +* Removed the raising of an exception when it finds a model that is already registered. [Corey Oordt] + + +## 0.5.1 (2011-02-14) + +### Updates + +* Updated the test to test a new template tag, not the old one. [Corey Oordt] + +* Changed the import to import from category_import. [Corey Oordt] + +### Other + +* The test for importing checks the first child. With two children either could be 1st, so remove one. [Corey Oordt] + +* Need to delete all the objects before each test because the import checks its work. [Corey Oordt] + +* Checking for raising the correct exception and moved the strings used in the test to a list of strings. [Corey Oordt] + +* Got rid of the debugging print statements. [Corey Oordt] + + +## 0.5 (2011-01-20) + +### New + +* Added contributors to the readme for proper recognition. [Corey Oordt] + +* Added logic to skip adding categories that are already defined for a modeladmin. [Erik Simmler] + +* Added additional fields to the display_list. [Corey Oordt] + +* Adding a new import and alphabetizing them (OCD, I know) [Corey Oordt] + +* Added a new template tag to override the painting of the admin rows. [Corey Oordt] + +* New template and media. [Corey Oordt] + +* Added a placeholder for Django. [Corey Oordt] + +* Adding a new version of TreeTable with a few minor changes to support row repainting. [Corey Oordt] + +### Updates + +* Updated the documentation! [Corey Oordt] + +* Updated the docstrings of the template tags and added breadcrumbs. [Corey Oordt] + +### Other + +* STATIC_URL seems to be returning as None even when not defined. [Erik Simmler] + +* Renamed 'media' directories to 'static' to work with the django 1.3 staticfiles app. [Erik Simmler] + +* Removed duplicate slash from EDITOR_MEDIA_PATH setting. [Erik Simmler] + +* ModelAdmin re-register now skips modeladmins without fieldsets already defined. [Erik Simmler] + + Was causing a "TypeError at /current/url/: unsupported operand type(s) for +: 'NoneType' and 'tuple'" + +* Got rid of the with_stories keyword for the category detail view. [Corey Oordt] + +* Revised the README to get it up-to-date. [Corey Oordt] + +* Refactored the templates to extend a categories/base.html. [Corey Oordt] + +* Renamed the README to indicate it is a reST file. [Corey Oordt] + +* Long trees cause a performance hit if the initial state is expanded. Changing to "collapsed" [Corey Oordt] + +* Getting rid of unused code in the treeeditor. [Corey Oordt] + +* Ignoring a few more things. [Corey Oordt] + +* Made the media delivery work. [Corey Oordt] + +* Removed some unused cruft from the TreeEditor class. [Corey Oordt] + +* What's that doing there? [Corey Oordt] + +* Now that Django has a getchangelist function, we don't need to hack anymore. [Corey Oordt] + +* Don't need to set that EDITOR_MEDIA_PATH any more. [Corey Oordt] + +* Reworked the template to initialize the correct javascript and use the result_tree_list. [Corey Oordt] + +* Deleted an unused template. [Corey Oordt] + +* Got rid of hotlinking settings and changed the EDITOR_MEDIA_PATH. [Corey Oordt] + +* Removed unused code files. [Corey Oordt] + +* Removed all the old, unused templates. [Corey Oordt] + +* Removed all the old media. [Corey Oordt] + + + +## 0.4.8 (2010-12-10) + +### New + +* Added a Meta class for proper plural naming. [Corey Oordt] + +### Updates + +* Updated the requirements to django-mptt 0.4.2. [Corey Oordt] +* Modified Category model to work with django-mptt 0.4. [Josh Ourisman] + +### Fix + +* Fixing bug #6 per primski. Adds the correct fields into the admin instead of both. [Corey Oordt] + +### Other + +* PyPI didn't like the license metadata. [Corey Oordt] + + +## 0.4.6 (2010-10-07) + +### Other + +* Bumped version to 0.4.6. [Corey Oordt] + + +## 0.4.5 (2010-10-07) + +### Fix + +* Fix fieldsets assignment, issue 3. [Justin Quick] + +* Category string, fixes issue 2. [Justin Quick] + +### Other + +* Checks for parent if given enough path bits. [Justin Quick] + + +## 0.4.4 (2010-05-28) + +### New + +* Added the extra templates. [Corey Oordt] + +* Added extra context to view func. [Justin Quick] + +### Other + +* Redid docs with new template. [Corey Oordt] + +* Refactoring docs into doc_src and docs. [Corey Oordt] + +* Require a trailing slash at the end of urls. [Corey Oordt] + +* Safe mptt registration. [Justin Quick] + + +## 0.4.2 (2010-04-28) + +### Updates + +* Updated the version number. [Corey Oordt] + +### Fix + +* Fixing jquery issues. [Corey Oordt] + +### Other + +* Fied my typo for settings url. [Web Development] + + +## 0.4 (2010-04-23) + +### New + +* Added the necessary files to test the generic relations. [Corey Oordt] + +* Added generic relation stuff into categories. [Corey Oordt] + +### Other + +* Renamed sample to example because that is what every other one is called, damnit. [Corey Oordt] + + +## 0.3 (2010-04-23) + +### New + +* Added metadata to the model for seo stuff. [Corey Oordt] + +### Updates + +* Changed the requirements from mptt in our repository to mptt-2 in pypi. [Corey Oordt] + + +## 0.2.2 (2010-04-08) + +### New + +* Added better setup.py pieces. Getting ready to push to our PyPi. [Corey Oordt] + +### Updates + +* Changed the requirements to have mptt just greater than 0.2. [Corey Oordt] + +### Other + +* Switched to setuptools/distribute. [Corey Oordt] + +* Deleted code referencing something I deleted earlier. [Corey Oordt] + +* Removing docs for piece I deleted previously. [Corey Oordt] + + + +## 0.2.1 (2010-04-06) + +### New + +- Added some docs and testing apps. [Corey Oordt] +- Added a caching setting to vary the amount of time the view is cached. + [Corey Oordt] +- Added missing templates for category traversal. [Justin Quick] +- Added an app to test categories against. [Corey Oordt] +- Added some registration notes to start the docs. [Corey Oordt] +- Added registry, hacked admin w/ new templates for category editor. + [Justin Quick] +- Added ability to register fields to models. [Jose Soares] +- Added registry, hacked admin w/ new templates for category editor. + [Justin Quick] +- Added an optional setting to allow the slug to be changed. [Corey + Oordt] +- Added a new templatetag to retrieve the top level categories. [Jose + Soares] +- Added views. [Jonathan Hensley] +- Added new documentation. [Corey Oordt] +- Added a description field. [Corey Oordt] +- Added some sample config to see it work. [Corey Oordt] +- Added a template for the template tags. [Corey Oordt] +- Added a demo file of music genres. [Corey Oordt] +- Added tests for templatetags. [Corey Oordt] +- Upped the version and separated the editor. [Corey Oordt] +- Added some testing fixtures. [Corey Oordt] +- Added some tests for category importing. [Corey Oordt] +- Started the docs. [Corey Oordt] +- Added a command to import categories from a file. [Corey Oordt] +- Added the editor templates. [Corey Oordt] +- Added to the gitignore. [Corey Oordt] +- Added template for category detail. [Jose Soares] +- Added urls and views for category detail. [Jose Soares] +- Getting the admin interface working. [Corey Oordt] + +### Fix + +- Fixed a typo in the setup.py and wrapped the other django import in + __init__.py so you could call get_version without having django + installed. Also increased the version number to 0.2.1. [Corey Oordt] +- Fixed the get_absolute_url for the Categories model and fixed up the + view as well. [Corey Oordt] +- Fixing up and updating the usage. [Corey Oordt] +- Fixed up the readme to include some goals. [Corey Oordt] +- Tweaked the description and example of the template tag. [Corey Oordt] +- Fixed a wrong relative path with the jsi18n admin script. [Corey + Oordt] + +### Updates + +- Modified the setup.py to get the latest version from the code and the + long_description fro the README.txt file. [Corey Oordt] +- Altered the registration naming so more than one field could be + registered for a model. [Corey Oordt] +- Changed the disclosure triangle to be a unicode character instead of + the images. [Corey Oordt] +- Updated tree editor view. [jhensley] + +### Other + +- Tiered template heirarchy. [Justin Quick] +- Removed the special many2many models. The user interface was just too + odd to implement. [Corey Oordt] +- Removed the permalink decorator to make the absoluteurl work. [Corey + Oordt] +- Fixed most of the tests. [Corey Oordt] +- Moving media files around. [Corey Oordt] +- Split the editor into a separate app. [Corey Oordt] From 035fdf693e2304cc48fc2d96170f60706041f400 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sun, 5 Dec 2021 10:33:50 -0600 Subject: [PATCH 17/51] Changed version management to bump2version --- categories/__init__.py | 17 ++--------------- setup.cfg | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/categories/__init__.py b/categories/__init__.py index 0dad974..1eb3387 100644 --- a/categories/__init__.py +++ b/categories/__init__.py @@ -1,19 +1,6 @@ -__version_info__ = {"major": 1, "minor": 8, "micro": 0, "releaselevel": "final", "serial": 1} +"""Django categories.""" +__version__ = "1.8.0" -def get_version(short=False): - assert __version_info__["releaselevel"] in ("alpha", "beta", "final") - vers = [ - "%(major)i.%(minor)i" % __version_info__, - ] - if __version_info__["micro"] and not short: - vers.append(".%(micro)i" % __version_info__) - if __version_info__["releaselevel"] != "final" and not short: - vers.append("%s%i" % (__version_info__["releaselevel"][0], __version_info__["serial"])) - return "".join(vers) - - -__version__ = get_version() - default_app_config = "categories.apps.CategoriesConfig" diff --git a/setup.cfg b/setup.cfg index bfc227d..70fb57f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,6 @@ [metadata] name = django-categories +version = 1.8.0 description = A way to handle one or more hierarchical category trees in django. long_description = file:README.md long_description_content_type = "text/markdown" @@ -36,3 +37,23 @@ ignore=DAR402 [bdist_wheel] universal = 1 + +[bumpversion] +current_version = 1.8.0 +commit = True +tag = False +tag_name = {new_version} +parse = (?P\d+)\.(?P\d+)\.(?P\d+)(\+\w+-(?P\d+))? +serialize = + {major}.{minor}.{patch}+{$USER}-{dev} + {major}.{minor}.{patch} +message = Version updated from {current_version} to {new_version} + +[bumpversion:part:dev] + +[bumpversion:file:setup.cfg] + +[bumpversion:file:categories/__init__.py] + +[bumpversion:file:CHANGELOG.md] +search = Unreleased From 90d154b7435daa3a3946ceb57eeb1bf11e254239 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sun, 5 Dec 2021 10:34:36 -0600 Subject: [PATCH 18/51] Uodated Makefile to automate the versioning process. --- Makefile | 87 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 76 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 90bd027..b197358 100644 --- a/Makefile +++ b/Makefile @@ -1,20 +1,85 @@ -help: - @echo "" - @echo "Available make commands:" - @echo "" - @echo "deps Install development dependencies" - @echo "test Run tests" - @echo "publish Publish a release to PyPi (requires permissions)" - @echo "" +.DEFAULT_GOAL := help -deps: +RELEASE_KIND := patch +SOURCE_DIR := categories + +BRANCH_NAME := $(shell echo $$(git rev-parse --abbrev-ref HEAD)) +SHORT_BRANCH_NAME := $(shell echo $(BRANCH_NAME) | cut -c 1-20) +PRIMARY_BRANCH_NAME := master + +EDIT_CHANGELOG_IF_EDITOR_SET := @bash -c "$(shell if [[ -n $$EDITOR ]] ; then echo "$$EDITOR CHANGELOG.md" ; else echo "" ; fi)" + +help: + @grep '^[a-zA-Z]' $(MAKEFILE_LIST) | sort | awk -F ':.*?## ' 'NF==2 {printf "\033[36m %-25s\033[0m %s\n", $$1, $$2}' + +clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts + +clean-build: ## remove build artifacts + rm -fr build/ + rm -fr dist/ + rm -fr .eggs/ + find . -name '*.egg-info' -exec rm -fr {} + + find . -name '*.egg' -exec rm -f {} + + +clean-pyc: ## remove Python file artifacts + find . -name '*.pyc' -exec rm -f {} + + find . -name '*.pyo' -exec rm -f {} + + find . -name '*~' -exec rm -f {} + + find . -name '__pycache__' -exec rm -fr {} + + +clean-test: ## remove test and coverage artifacts + rm -fr .tox/ + rm -f .coverage + rm -fr htmlcov/ + rm -fr .pytest_cache + +deps: ## Install development dependencies pip install -r requirements.txt pip install tox sphinx sphinx-autobuild twine -test: +test: ## Run tests tox -publish: +publish: ## Publish a release to PyPi (requires permissions) rm -fr build dist python setup.py sdist bdist_wheel twine upload dist/* + +release-helper: + ## DO NOT CALL DIRECTLY. It is used by release-{patch,major,minor,dev} + @echo "Branch In Use: $(BRANCH_NAME) $(SHORT_BRANCH_NAME)" +ifeq ($(BRANCH_NAME), $(PRIMARY_BRANCH_NAME)) + ifeq ($(RELEASE_KIND), dev) + @echo "Error! Can't bump $(RELEASE_KIND) while on the $(PRIMARY_BRANCH_NAME) branch." + exit +else ifneq ($(RELEASE_KIND), dev) + @echo "Error! Must be on the $(PRIMARY_BRANCH_NAME) branch to bump $(RELEASE_KIND)." + exit +endif + + git fetch -p --all + gitchangelog + $(EDIT_CHANGELOG_IF_EDITOR_SET) + export BRANCH_NAME=$(SHORT_BRANCH_NAME);bumpversion $(RELEASE_KIND) --allow-dirty --tag + git push origin $(BRANCH_NAME) + git push --tags + +set-release-major-env-var: + $(eval RELEASE_KIND := major) + +set-release-minor-env-var: + $(eval RELEASE_KIND := minor) + +set-release-patch-env-var: + $(eval RELEASE_KIND := patch) + +set-release-dev-env-var: + $(eval RELEASE_KIND := dev) + +release-dev: set-release-dev-env-var release-helper ## Release a new development version: 1.1.1 -> 1.1.1+branchname-0 + +release-patch: set-release-patch-env-var release-helper ## Release a new patch version: 1.1.1 -> 1.1.2 + +release-minor: set-release-minor-env-var release-helper ## Release a new minor version: 1.1.1 -> 1.2.0 + +release-major: set-release-major-env-var release-helper ## release a new major version: 1.1.1 -> 2.0.0 From 4e8002ecf543cefe37f380768b2d6bd53e317435 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sat, 11 Dec 2021 07:27:18 -0600 Subject: [PATCH 19/51] Removed the unused get_version call. --- setup.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/setup.py b/setup.py index da41c03..d67a743 100644 --- a/setup.py +++ b/setup.py @@ -4,8 +4,6 @@ from pathlib import Path from setuptools import setup -import categories - def parse_reqs(filepath: str) -> list: """ @@ -48,6 +46,5 @@ def parse_reqs(filepath: str) -> list: requirements = parse_reqs("requirements.txt") setup( - version=categories.get_version(), install_requires=requirements, ) From 1d7654e5e138815beb39c62ad14257a57f61b23c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 11 Dec 2021 13:29:35 +0000 Subject: [PATCH 20/51] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- categories/__init__.py | 1 - categories/editor/tree_editor.py | 13 ++++++++----- categories/migration.py | 2 -- categories/migrations/0001_initial.py | 2 -- categories/tests/test_admin.py | 1 - 5 files changed, 8 insertions(+), 11 deletions(-) diff --git a/categories/__init__.py b/categories/__init__.py index 1eb3387..509879e 100644 --- a/categories/__init__.py +++ b/categories/__init__.py @@ -2,5 +2,4 @@ __version__ = "1.8.0" - default_app_config = "categories.apps.CategoriesConfig" diff --git a/categories/editor/tree_editor.py b/categories/editor/tree_editor.py index 45c70d1..2d64b51 100644 --- a/categories/editor/tree_editor.py +++ b/categories/editor/tree_editor.py @@ -232,11 +232,14 @@ class TreeEditor(admin.ModelAdmin): name = force_text(opts.verbose_name) else: name = force_text(opts.verbose_name_plural) - msg = ungettext( - "%(count)s %(name)s was changed successfully.", - "%(count)s %(name)s were changed successfully.", - changecount, - ) % {"count": changecount, "name": name, "obj": force_text(obj)} + msg = ( + ungettext( + "%(count)s %(name)s was changed successfully.", + "%(count)s %(name)s were changed successfully.", + changecount, + ) + % {"count": changecount, "name": name, "obj": force_text(obj)} + ) self.message_user(request, msg) return HttpResponseRedirect(request.get_full_path()) diff --git a/categories/migration.py b/categories/migration.py index 77358a5..ac4f36c 100644 --- a/categories/migration.py +++ b/categories/migration.py @@ -1,5 +1,3 @@ - - from django.apps import apps from django.db import connection, transaction from django.db.utils import ProgrammingError diff --git a/categories/migrations/0001_initial.py b/categories/migrations/0001_initial.py index 883fd62..23afb6a 100644 --- a/categories/migrations/0001_initial.py +++ b/categories/migrations/0001_initial.py @@ -1,5 +1,3 @@ - - import django.core.files.storage import mptt.fields from django.db import migrations, models diff --git a/categories/tests/test_admin.py b/categories/tests/test_admin.py index ce1c7a3..4875889 100644 --- a/categories/tests/test_admin.py +++ b/categories/tests/test_admin.py @@ -1,4 +1,3 @@ - from django.contrib.auth.models import User from django.test import Client, TestCase from django.urls import reverse From 8c0c4ebf6ae22c2467dfbc8c1dcdf3f3537a27a3 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sun, 12 Dec 2021 08:05:58 -0600 Subject: [PATCH 21/51] Refactored documentation. --- .gitignore | 4 + Makefile | 7 + doc_src/Makefile | 6 +- doc_src/_static/breadcrumb_background.png | Bin 136 -> 0 bytes doc_src/_static/css/custom.css | 32 + doc_src/_static/default.css | 773 ----------------- doc_src/_static/documentation.png | Bin 412 -> 0 bytes doc_src/_static/header_sm_mid.png | Bin 159 -> 0 bytes doc_src/_static/scrn1.png | Bin 108046 -> 0 bytes doc_src/_static/scrn2.png | Bin 121395 -> 0 bytes doc_src/_static/searchfield_leftcap.png | Bin 855 -> 0 bytes doc_src/_static/searchfield_repeat.png | Bin 158 -> 0 bytes doc_src/_static/searchfield_rightcap.png | Bin 530 -> 0 bytes doc_src/_static/title_background.png | Bin 132 -> 0 bytes doc_src/_static/toc.js | 20 - doc_src/_static/triangle_closed.png | Bin 181 -> 0 bytes doc_src/_static/triangle_left.png | Bin 195 -> 0 bytes doc_src/_static/triangle_open.png | Bin 191 -> 0 bytes doc_src/_templates/autosummary/base.rst | 10 + doc_src/_templates/autosummary/class.rst | 34 + doc_src/_templates/autosummary/module.rst | 70 ++ doc_src/_templates/layout.html | 144 ---- doc_src/api/index.rst | 8 + doc_src/changelog.md | 2 + doc_src/conf.py | 241 ++---- doc_src/index.rst | 20 +- doc_src/user_guide/index.md | 12 + docs/.buildinfo | 4 - docs/_sources/getting_started.txt | 74 -- docs/_sources/index.txt | 43 - docs/_sources/installation.txt | 43 - docs/_sources/reference/index.txt | 12 - .../reference/management_commands.txt | 38 - docs/_sources/reference/models.txt | 115 --- docs/_sources/reference/settings.txt | 121 --- docs/_sources/reference/templatetags.txt | 348 -------- docs/_sources/templatetags.txt | 146 ---- docs/_static/ajax-loader.gif | Bin 673 -> 0 bytes docs/_static/basic.css | 528 ------------ docs/_static/breadcrumb_background.png | Bin 136 -> 0 bytes docs/_static/comment-bright.png | Bin 3500 -> 0 bytes docs/_static/comment-close.png | Bin 3578 -> 0 bytes docs/_static/comment.png | Bin 3445 -> 0 bytes docs/_static/default.css | 773 ----------------- docs/_static/doctools.js | 247 ------ docs/_static/documentation.png | Bin 412 -> 0 bytes docs/_static/down-pressed.png | Bin 368 -> 0 bytes docs/_static/down.png | Bin 363 -> 0 bytes docs/_static/file.png | Bin 392 -> 0 bytes docs/_static/header_sm_mid.png | Bin 159 -> 0 bytes docs/_static/jquery.js | 154 ---- docs/_static/minus.png | Bin 199 -> 0 bytes docs/_static/plus.png | Bin 199 -> 0 bytes docs/_static/pygments.css | 62 -- docs/_static/scrn1.png | Bin 108046 -> 0 bytes docs/_static/scrn2.png | Bin 121395 -> 0 bytes docs/_static/searchfield_leftcap.png | Bin 855 -> 0 bytes docs/_static/searchfield_repeat.png | Bin 158 -> 0 bytes docs/_static/searchfield_rightcap.png | Bin 530 -> 0 bytes docs/_static/searchtools.js | 518 ----------- docs/_static/sidebar.js | 148 ---- docs/_static/title_background.png | Bin 132 -> 0 bytes docs/_static/toc.js | 20 - docs/_static/triangle_closed.png | Bin 181 -> 0 bytes docs/_static/triangle_left.png | Bin 195 -> 0 bytes docs/_static/triangle_open.png | Bin 191 -> 0 bytes docs/_static/underscore.js | 16 - docs/_static/up-pressed.png | Bin 372 -> 0 bytes docs/_static/up.png | Bin 363 -> 0 bytes docs/_static/websupport.js | 808 ------------------ docs/adding_the_fields.html | 127 --- docs/custom_categories.html | 341 -------- docs/genindex.html | 199 ----- docs/getting_started.html | 166 ---- docs/index.html | 172 ---- docs/installation.html | 155 ---- docs/objects.inv | Bin 982 -> 0 bytes docs/reference/index.html | 151 ---- docs/reference/management_commands.html | 136 --- docs/reference/models.html | 252 ------ docs/reference/settings.html | 198 ----- docs/reference/templatetags.html | 393 --------- docs/registering_models.html | 249 ------ docs/search.html | 110 --- docs/searchindex.js | 1 - docs/templatetags.html | 221 ----- docs/usage.html | 221 ----- requirements/test.txt | 7 + 88 files changed, 257 insertions(+), 8443 deletions(-) delete mode 100644 doc_src/_static/breadcrumb_background.png create mode 100644 doc_src/_static/css/custom.css delete mode 100644 doc_src/_static/default.css delete mode 100644 doc_src/_static/documentation.png delete mode 100644 doc_src/_static/header_sm_mid.png delete mode 100644 doc_src/_static/scrn1.png delete mode 100644 doc_src/_static/scrn2.png delete mode 100644 doc_src/_static/searchfield_leftcap.png delete mode 100644 doc_src/_static/searchfield_repeat.png delete mode 100644 doc_src/_static/searchfield_rightcap.png delete mode 100644 doc_src/_static/title_background.png delete mode 100644 doc_src/_static/toc.js delete mode 100644 doc_src/_static/triangle_closed.png delete mode 100644 doc_src/_static/triangle_left.png delete mode 100644 doc_src/_static/triangle_open.png create mode 100644 doc_src/_templates/autosummary/base.rst create mode 100644 doc_src/_templates/autosummary/class.rst create mode 100644 doc_src/_templates/autosummary/module.rst delete mode 100644 doc_src/_templates/layout.html create mode 100644 doc_src/api/index.rst create mode 100644 doc_src/changelog.md create mode 100644 doc_src/user_guide/index.md delete mode 100644 docs/.buildinfo delete mode 100644 docs/_sources/getting_started.txt delete mode 100644 docs/_sources/index.txt delete mode 100644 docs/_sources/installation.txt delete mode 100644 docs/_sources/reference/index.txt delete mode 100644 docs/_sources/reference/management_commands.txt delete mode 100644 docs/_sources/reference/models.txt delete mode 100644 docs/_sources/reference/settings.txt delete mode 100644 docs/_sources/reference/templatetags.txt delete mode 100644 docs/_sources/templatetags.txt delete mode 100644 docs/_static/ajax-loader.gif delete mode 100644 docs/_static/basic.css delete mode 100644 docs/_static/breadcrumb_background.png delete mode 100644 docs/_static/comment-bright.png delete mode 100644 docs/_static/comment-close.png delete mode 100644 docs/_static/comment.png delete mode 100644 docs/_static/default.css delete mode 100644 docs/_static/doctools.js delete mode 100644 docs/_static/documentation.png delete mode 100644 docs/_static/down-pressed.png delete mode 100644 docs/_static/down.png delete mode 100644 docs/_static/file.png delete mode 100644 docs/_static/header_sm_mid.png delete mode 100644 docs/_static/jquery.js delete mode 100644 docs/_static/minus.png delete mode 100644 docs/_static/plus.png delete mode 100644 docs/_static/pygments.css delete mode 100644 docs/_static/scrn1.png delete mode 100644 docs/_static/scrn2.png delete mode 100644 docs/_static/searchfield_leftcap.png delete mode 100644 docs/_static/searchfield_repeat.png delete mode 100644 docs/_static/searchfield_rightcap.png delete mode 100644 docs/_static/searchtools.js delete mode 100644 docs/_static/sidebar.js delete mode 100644 docs/_static/title_background.png delete mode 100644 docs/_static/toc.js delete mode 100644 docs/_static/triangle_closed.png delete mode 100644 docs/_static/triangle_left.png delete mode 100644 docs/_static/triangle_open.png delete mode 100644 docs/_static/underscore.js delete mode 100644 docs/_static/up-pressed.png delete mode 100644 docs/_static/up.png delete mode 100644 docs/_static/websupport.js delete mode 100644 docs/adding_the_fields.html delete mode 100644 docs/custom_categories.html delete mode 100644 docs/genindex.html delete mode 100644 docs/getting_started.html delete mode 100644 docs/index.html delete mode 100644 docs/installation.html delete mode 100644 docs/objects.inv delete mode 100644 docs/reference/index.html delete mode 100644 docs/reference/management_commands.html delete mode 100644 docs/reference/models.html delete mode 100644 docs/reference/settings.html delete mode 100644 docs/reference/templatetags.html delete mode 100644 docs/registering_models.html delete mode 100644 docs/search.html delete mode 100644 docs/searchindex.js delete mode 100644 docs/templatetags.html delete mode 100644 docs/usage.html diff --git a/.gitignore b/.gitignore index bf5515f..f13af1c 100644 --- a/.gitignore +++ b/.gitignore @@ -168,6 +168,10 @@ output/*/index.html junit-*.xml flake8-errors.txt +# Documentation building +_build +doc_src/api/categories*.rst + RELEASE.txt site-packages reports diff --git a/Makefile b/Makefile index b197358..ac0575b 100644 --- a/Makefile +++ b/Makefile @@ -83,3 +83,10 @@ release-patch: set-release-patch-env-var release-helper ## Release a new patch release-minor: set-release-minor-env-var release-helper ## Release a new minor version: 1.1.1 -> 1.2.0 release-major: set-release-major-env-var release-helper ## release a new major version: 1.1.1 -> 2.0.0 + +documentation: + mkdir -p docs + rm -f doc_src/api/$(SOURCE_DIR)*.rst + ls -A1 docs | xargs -I {} rm -rf docs/{} + $(MAKE) -C doc_src clean html + cp -a doc_src/_build/html/. docs diff --git a/doc_src/Makefile b/doc_src/Makefile index d34da38..7c75b9a 100644 --- a/doc_src/Makefile +++ b/doc_src/Makefile @@ -6,7 +6,7 @@ SPHINXOPTS = -a SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build -DESTDIR = .. +DESTDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 @@ -32,9 +32,9 @@ clean: -rm -rf $(BUILDDIR)/* html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(DESTDIR)/docs + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(DESTDIR)/html @echo - @echo "Build finished. The HTML pages are in $(DESTDIR)/docs." + @echo "Build finished. The HTML pages are in $(DESTDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml diff --git a/doc_src/_static/breadcrumb_background.png b/doc_src/_static/breadcrumb_background.png deleted file mode 100644 index 9b45910e0b984604c5e8b913f431bad172bdef53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 136 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{R!3HD)xzimdKI;Vst0CaOHKL7v# diff --git a/doc_src/_static/css/custom.css b/doc_src/_static/css/custom.css new file mode 100644 index 0000000..59a7390 --- /dev/null +++ b/doc_src/_static/css/custom.css @@ -0,0 +1,32 @@ +.sig-prename.descclassname { + display: none; +} +dl.attribute { + margin-bottom: 30px; +} +dl.field-list { + display: block; +} +dl.field-list > dt { + padding-left: 0; +} +dl.field-list > dd { + padding-left: 1em; + border-left: 0; +} +dl.field-list > dd > ul.simple { + list-style-type: none; + padding-left: 0; +} +dl.field-list > dd + dt { + margin-top: 0.5em; +} +dd { + margin-left: 0; + padding-left: 30px; + border-left: 1px solid #c9c9c9; +} +.table.autosummary td { + border-top: 0; + border-bottom: 1px solid #dee2e6; +} diff --git a/doc_src/_static/default.css b/doc_src/_static/default.css deleted file mode 100644 index a95ff54..0000000 --- a/doc_src/_static/default.css +++ /dev/null @@ -1,773 +0,0 @@ -/** - * Sphinx stylesheet -- basic theme - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - h3 { - color:#000000; - font-size: 17px; - margin-bottom:0.5em; - margin-top:2em; - } -/* -- main layout ----------------------------------------------------------- */ - -div.clearer { - clear: both; -} - -/* -- header ---------------------------------------------------------------- */ - -#header #title { - background:#29334F url(title_background.png) repeat-x scroll 0 0; - border-bottom:1px solid #B6B6B6; - height:25px; - overflow:hidden; -} -#headerButtons { - position: absolute; - list-style: none outside; - top: 26px; - left: 0px; - right: 0px; - margin: 0px; - padding: 0px; - border-top: 1px solid #2B334F; - border-bottom: 1px solid #EDEDED; - height: 20px; - font-size: 8pt; - overflow: hidden; - background-color: #D8D8D8; -} - -#headerButtons li { - background-repeat:no-repeat; - display:inline; - margin-top:0; - padding:0; -} - -.headerButton { - display: inline; - height:20px; -} - -.headerButton a { - text-decoration: none; - float: right; - height: 20px; - padding: 4px 15px; - border-left: 1px solid #ACACAC; - font-family:'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; - color: black; -} -.headerButton a:hover { - color: white; - background-color: #787878; - -} - -li#toc_button { - text-align:left; -} - -li#toc_button .headerButton a { - width:198px; - padding-top: 4px; - font-family:'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; - color: black; - float: left; - padding-left:15px; - border-right:1px solid #ACACAC; - background:transparent url(triangle_open.png) no-repeat scroll 4px 6px; -} - -li#toc_button .headerButton a:hover { - background-color: #787878; - color: white; -} - -li#page_buttons { -position:absolute; -right:0; -} - -#breadcrumbs { - color: black; - background-image:url(breadcrumb_background.png); - border-top:1px solid #2B334F; - bottom:0; - font-size:10px; - height:15px; - left:0; - overflow:hidden; - padding:3px 10px 0; - position:absolute; - right:0; - white-space:nowrap; - z-index:901; -} -#breadcrumbs a { - color: black; - text-decoration: none; -} -#breadcrumbs a:hover { - text-decoration: underline; -} -#breadcrumbs img { - padding-left: 3px; -} -/* -- sidebar --------------------------------------------------------------- */ -#sphinxsidebar { - position: absolute; - top: 84px; - bottom: 19px; - left: 0px; - width: 229px; - background-color: #E4EBF7; - border-right: 1px solid #ACACAC; - border-top: 1px solid #2B334F; - overflow-x: hidden; - overflow-y: auto; - padding: 0px 0px 0px 0px; - font-size:11px; -} - -div.sphinxsidebarwrapper { - padding: 10px 5px 0 10px; -} - -#sphinxsidebar li { - margin: 0px; - padding: 0px; - font-weight: normal; - margin: 0px 0px 7px 0px; - overflow: hidden; - text-overflow: ellipsis; - font-size: 11px; -} - -#sphinxsidebar ul { - list-style: none; - margin: 0px 0px 0px 0px; - padding: 0px 5px 0px 5px; -} - -#sphinxsidebar ul ul, -#sphinxsidebar ul.want-points { - list-style: square; -} - -#sphinxsidebar ul ul { - margin-top: 0; - margin-bottom: 0; -} - -#sphinxsidebar form { - margin-top: 10px; -} - -#sphinxsidebar input { - border: 1px solid #787878; - font-family: sans-serif; - font-size: 1em; -} - -img { - border: 0; -} - -#sphinxsidebar li.toctree-l1 a { - font-weight: bold; - color: #000; - text-decoration: none; -} - -#sphinxsidebar li.toctree-l2 a { - font-weight: bold; - color: #4f4f4f; - text-decoration: none; -} - -/* -- search page ----------------------------------------------------------- */ - -ul.search { - margin: 10px 0 0 20px; - padding: 0; -} - -ul.search li { - padding: 5px 0 5px 20px; - background-image: url(file.png); - background-repeat: no-repeat; - background-position: 0 7px; -} - -ul.search li a { - font-weight: bold; -} - -ul.search li div.context { - color: #888; - margin: 2px 0 0 30px; - text-align: left; -} - -ul.keywordmatches li.goodmatch a { - font-weight: bold; -} -#sphinxsidebar input.prettysearch {border:none;} -input.searchbutton { - float: right; -} -.search-wrapper {width: 100%; height: 25px;} -.search-wrapper input.prettysearch { border: none; width:200px; height: 16px; background: url(searchfield_repeat.png) center top repeat-x; border: 0px; margin: 0; padding: 3px 0 0 0; font: 11px "Lucida Grande", "Lucida Sans Unicode", Arial, sans-serif; } -.search-wrapper input.prettysearch { width: 184px; margin-left: 20px; *margin-top:-1px; *margin-right:-2px; *margin-left:10px; } -.search-wrapper .search-left { display: block; position: absolute; width: 20px; height: 19px; background: url(searchfield_leftcap.png) left top no-repeat; } -.search-wrapper .search-right { display: block; position: relative; left: 204px; top: -19px; width: 10px; height: 19px; background: url(searchfield_rightcap.png) right top no-repeat; } - -/* -- index page ------------------------------------------------------------ */ - -table.contentstable { - width: 90%; -} - -table.contentstable p.biglink { - line-height: 150%; -} - -a.biglink { - font-size: 1.3em; -} - -span.linkdescr { - font-style: italic; - padding-top: 5px; - font-size: 90%; -} - -/* -- general index --------------------------------------------------------- */ - -table.indextable td { - text-align: left; - vertical-align: top; -} - -table.indextable dl, table.indextable dd { - margin-top: 0; - margin-bottom: 0; -} - -table.indextable tr.pcap { - height: 10px; -} - -table.indextable tr.cap { - margin-top: 10px; - background-color: #f2f2f2; -} - -img.toggler { - margin-right: 3px; - margin-top: 3px; - cursor: pointer; -} - -/* -- general body styles --------------------------------------------------- */ -.document { - border-top:1px solid #2B334F; - overflow:auto; - padding-left:2em; - padding-right:2em; - position:absolute; - z-index:1; - top:84px; - bottom:19px; - right:0; - left:230px; -} - -a.headerlink { - visibility: hidden; -} - -h1:hover > a.headerlink, -h2:hover > a.headerlink, -h3:hover > a.headerlink, -h4:hover > a.headerlink, -h5:hover > a.headerlink, -h6:hover > a.headerlink, -dt:hover > a.headerlink { - visibility: visible; -} - -div.body p.caption { - text-align: inherit; -} - -div.body td { - text-align: left; -} - -.field-list ul { - padding-left: 1em; -} - -.first { - margin-top: 0 !important; -} - -p.rubric { - margin-top: 30px; - font-weight: bold; -} - -/* -- sidebars -------------------------------------------------------------- */ - -/*div.sidebar { - margin: 0 0 0.5em 1em; - border: 1px solid #ddb; - padding: 7px 7px 0 7px; - background-color: #ffe; - width: 40%; - float: right; -} - -p.sidebar-title { - font-weight: bold; -} -*/ -/* -- topics ---------------------------------------------------------------- */ - -div.topic { - border: 1px solid #ccc; - padding: 7px 7px 0 7px; - margin: 10px 0 10px 0; -} - -p.topic-title { - font-size: 1.1em; - font-weight: bold; - margin-top: 10px; -} - -/* -- admonitions ----------------------------------------------------------- */ -.admonition { - border: 1px solid #a1a5a9; - background-color: #f7f7f7; - margin: 20px; - padding: 0px 8px 7px 9px; - text-align: left; -} -.warning { - background-color:#E8E8E8; - border:1px solid #111111; - margin:30px; -} -.admonition p { - font: 12px 'Lucida Grande', Geneva, Helvetica, Arial, sans-serif; - margin-top: 7px; - margin-bottom: 0px; -} - -div.admonition dt { - font-weight: bold; -} - -div.admonition dl { - margin-bottom: 0; -} - -p.admonition-title { - margin: 0px 10px 5px 0px; - font-weight: bold; - padding-top: 3px; -} - -div.body p.centered { - text-align: center; - margin-top: 25px; -} - -/* -- tables ---------------------------------------------------------------- */ - -table.docutils { - border-collapse: collapse; - border-top: 1px solid #919699; - border-left: 1px solid #919699; - border-right: 1px solid #919699; - font-size:12px; - padding:8px; - text-align:left; - vertical-align:top; -} - -table.docutils td, table.docutils th { - padding: 8px; - font-size: 12px; - text-align: left; - vertical-align: top; - border-bottom: 1px solid #919699; -} - -table.docutils th { - font-weight: bold; -} -/* This alternates colors in up to six table rows (light blue for odd, white for even)*/ -.docutils tr { - background: #F0F5F9; -} - -.docutils tr + tr { - background: #FFFFFF; -} - -.docutils tr + tr + tr { - background: #F0F5F9; -} - -.docutils tr + tr + tr + tr { - background: #FFFFFF; -} - -.docutils tr + tr + tr +tr + tr { - background: #F0F5F9; -} - -.docutils tr + tr + tr + tr + tr + tr { - background: #FFFFFF; -} - -.docutils tr + tr + tr + tr + tr + tr + tr { - background: #F0F5F9; -} - -table.footnote td, table.footnote th { - border: 0 !important; -} - -th { - text-align: left; - padding-right: 5px; -} - -/* -- other body styles ----------------------------------------------------- */ - -dl { - margin-bottom: 15px; - font-size: 12px; -} - -dd p { - margin-top: 0px; - font-size: 12px; -} - -dd ul, dd table { - margin-bottom: 10px; -} - -dd { - margin-top: 3px; - margin-bottom: 10px; - margin-left: 30px; - font-size: 12px; -} - -dt:target, .highlight { - background-color: #fbe54e; -} - -dl.glossary dt { - font-weight: bold; - font-size: 0.8em; -} - -dl.glossary dd { - font-size:12px; -} -.field-list ul { - vertical-align: top; - margin: 0; - padding-bottom: 0; - list-style: none inside; -} - -.field-list ul li { - margin-top: 0; -} - -.field-list p { - margin: 0; -} - -.refcount { - color: #060; -} - -.optional { - font-size: 1.3em; -} - -.versionmodified { - font-style: italic; -} - -.system-message { - background-color: #fda; - padding: 5px; - border: 3px solid red; -} - -.footnote:target { - background-color: #ffa -} - -/* -- code displays --------------------------------------------------------- */ - -pre { - overflow: auto; - background-color:#F1F5F9; - border:1px solid #C9D1D7; - border-spacing:0; - font-family:"Bitstream Vera Sans Mono",Monaco,"Lucida Console",Courier,Consolas,monospace; - font-size:11px; - padding: 10px; -} - -td.linenos { - width: 2em; -} - -td.linenos pre { - padding: 5px 0px; - border: 0; - background-color: transparent; - color: #aaa; -} - -td.code { - -} - -table.highlighttable { - margin-left: 0.5em; - width: 100%; -} - -table.highlighttable td { - padding: 0 0.5em 0 0.5em; -} -table.highlighttable td.linenos { - text-align: right; - width: 1.5em; - padding-right: 0; -} -tt { - font-family:"Bitstream Vera Sans Mono",Monaco,"Lucida Console",Courier,Consolas,monospace; -} - -tt.descname { - background-color: transparent; - font-weight: bold; - font-size: 1em; -} - -tt.descclassname { - background-color: transparent; -} - -tt.xref, a tt { - background-color: transparent; - font-weight: bold; -} - -h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { - background-color: transparent; -} - -/* -- math display ---------------------------------------------------------- */ - -img.math { - vertical-align: middle; -} - -div.body div.math p { - text-align: center; -} - -span.eqno { - float: right; -} - -/* -- printout stylesheet --------------------------------------------------- */ - -@media print { - div.document, - div.documentwrapper, - div.bodywrapper { - margin: 0; - width: 100%; - } - - div.sphinxsidebar, - div.related, - div.footer, - #top-link { - display: none; - } -} - -body { - font-family:'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; -} - -dl.class dt { - padding: 3px; -/* border-top: 2px solid #999;*/ -} - -em.property { - font-style: normal; -} - -dl.class dd p { - margin-top: 6px; -} - -dl.class dd dl.exception dt { - padding: 3px; - background-color: #FFD6D6; - border-top: none; -} - -dl.class dd dl.method dt { - padding: 3px; - background-color: #e9e9e9; - border-top: none; - -} - -dl.function dt { - padding: 3px; - border-top: 2px solid #999; -} - -ul { -list-style-image:none; -list-style-position:outside; -list-style-type:square; -margin:0 0 0 30px; -padding:0 0 12px 6px; -} -#docstitle { - height: 36px; - background-image: url(header_sm_mid.png); - left: 0; - top: 0; - position: absolute; - width: 100%; -} -#docstitle p { - padding:7px 0 0 45px; - margin: 0; - color: white; - text-shadow:0 1px 0 #787878; - background: transparent url(documentation.png) no-repeat scroll 10px 3px; - height: 36px; - font-size: 15px; -} -#header { -height:45px; -left:0; -position:absolute; -right:0; -top:36px; -z-index:900; -} - -#header h1 { -font-size:10pt; -margin:0; -padding:5px 0 0 10px; -text-shadow:0 1px 0 #D5D5D5; -white-space:nowrap; -} - -h1 { --x-system-font:none; -color:#000000; -font-family:'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; -font-size:30px; -font-size-adjust:none; -font-stretch:normal; -font-style:normal; -font-variant:normal; -font-weight:bold; -line-height:normal; -margin-bottom:25px; -margin-top:1em; -} - -.footer { -border-top:1px solid #DDDDDD; -clear:both; -padding-top:9px; -width:100%; -font-size:10px; -} - -p { --x-system-font:none; -font-family:'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; -font-size:12px; -font-size-adjust:none; -font-stretch:normal; -font-style:normal; -font-variant:normal; -font-weight:normal; -line-height:normal; -margin-bottom:10px; -margin-top:0; -} - -h2 { -border-bottom:1px solid #919699; -color:#000000; -font-size:24px; -margin-top:2.5em; -padding-bottom:2px; -} - -a:link:hover { -color:#093D92; -text-decoration:underline; -} - -a:link { -color:#093D92; -text-decoration:none; -} - - -ol { -list-style-position:outside; -list-style-type:decimal; -margin:0 0 0 30px; -padding:0 0 12px 6px; -} -li { -margin-top:7px; -font-family:'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; -font-size:12px; -font-size-adjust:none; -font-stretch:normal; -font-style:normal; -font-variant:normal; -font-weight:normal; -line-height:normal; -} -li > p { -display:inline; -} -li p { -margin-top:8px; -} diff --git a/doc_src/_static/documentation.png b/doc_src/_static/documentation.png deleted file mode 100644 index f0d334b57a69d1c49ce833d2d3536ececbf31c2c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 412 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�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 ZGnh*?r5D zK?F?^1PO^?Wsw#|C6=?-W^S0-j0f&L_uPHXI&1H}_EzfkIyH{f)m7!>^Kb(vi>SKQho4r_&jBxm=pvZl})9PBIt_?E_{q z8Rhi!G*BoMepoD)w<9AXn%nIro6RO*nx+X@JAfKq7Z(@yVzKz$>-D}L9UUc)$3tCR zUDVOhL2$KQcLi`|Wko$YI{Ltj-i1OT>h0|%W=ZTmEiW(A?(Qye7|8GU6YP;lgnD{< zUIsirKXhlgU1Mx%0h^H4ePZyXK>X88d?&bEAykB5T^5)*LGsP|MCH)U&5g`hV+;=uzbGS( zZ^~4w)sTK8m`+Sg5SJcpZEZ<1ng?PyGc!XRs%JLC{QUeYHpIHSyH#DpX0ut6V6|F_ zlSbFq*ThPo$;nCL+9s|l(I?i3?~~F?rBbh1Q&~=c4FGTjY?-yVdUtn6wOUPLh%9qe zQ8JmNrGMRELr%h4@nWTM!3_ZyKtc-)G|T1avEu822WQ%mvv4FO#qs` BFGc_W diff --git a/doc_src/_static/searchfield_rightcap.png b/doc_src/_static/searchfield_rightcap.png deleted file mode 100644 index 8e13620ecbc56b3464c48d6cd09bf1337e1c33a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 530 zcmV+t0`2{YP)`}SW{%?kjooesx~_vP%P<%W?AdJgh{{)$N=4@w2Hn_CKTAY65m^iR+I*Mbk6^ z``^NHsdV!wP>EqmHX4oOX0v%l>il0RsWXek!jL5C0oS5;;H%I;7qQ7?Vs$#5r$(c3 zLKkVc?jhG;Dl&tEW>67q;r<#eHuX!@@AqBfuGeb~jqr-VJ=U*XtycBJC;bR809Q3H UB&DjC!~g&Q07*qoM6N<$f;HIhQUCw| diff --git a/doc_src/_static/title_background.png b/doc_src/_static/title_background.png deleted file mode 100644 index 6fcd1cda8799b2dcd85a5d2fe05f70983c7ab454..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 132 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{K!3HGDSj;X0Db50q$YKTtt`8v0=(NUU22jw< z)5S4_LpIr>`rDiOW#8>*O3wKA_cy!JKj+B$z?~eCD_FXcHoS@75!aHmf+fPRjgKui c`Tu{0jtkz)WtP=g15IG?boFyt=akR{0Lc(3VgLXD diff --git a/doc_src/_static/toc.js b/doc_src/_static/toc.js deleted file mode 100644 index cc06ee8..0000000 --- a/doc_src/_static/toc.js +++ /dev/null @@ -1,20 +0,0 @@ -var TOC = { - load: function () { - $('#toc_button').click(TOC.toggle); - }, - - toggle: function () { - if ($('#sphinxsidebar').toggle().is(':hidden')) { - $('div.document').css('left', "0px"); - $('toc_button').removeClass("open"); - } else { - $('div.document').css('left', "230px"); - $('#toc_button').addClass("open"); - } - return $('#sphinxsidebar'); - } -}; - -$(document).ready(function () { - TOC.load(); -}); diff --git a/doc_src/_static/triangle_closed.png b/doc_src/_static/triangle_closed.png deleted file mode 100644 index 1e7f7bba20bdc6e6692a936b37b912c562361001..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 181 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{Vk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5X!aZFaLn>}1B`nZRU=uud?%X#oFE8$fABX<_{vN+bJIN`@ zn&Bhsg0`OyXZpPbc~lraGA}q(Rnz70fZ0Q_=Wvs25fjJzySu+Do4Il~>|oURDR4KU cfq|LfmbCbnryJ{vfmSehy85}Sb4q9e0C?d(yZ`_I diff --git a/doc_src/_static/triangle_left.png b/doc_src/_static/triangle_left.png deleted file mode 100644 index 2d86be7dfedc80dcd80b8ac087a5a485924c41dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 195 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{!3Opi<85p>QL70(Y)*K0-V5z5z zV~B)ga>4@bgkx#57cXACZ_}nvT&%3E><%9$utrYYxY5vFz$YOk#m7OcUAw5LXcfDc z2!kkxf;Pj(nF&n)|NX6INU3l5I5Bg_B4&0zoj*T5EYSJrU;qFB diff --git a/doc_src/_static/triangle_open.png b/doc_src/_static/triangle_open.png deleted file mode 100644 index e5d3bfdad1ba43a89157643de68a50ae4ebb43d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 191 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{Vk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5X5}1B`nZRU=cib?%cN=dY@& m%BN7wd|}Gu6I~2UJPdwUB%hf5&L{&~#^CAd=d#Wzp$PyP{61&^ diff --git a/doc_src/_templates/autosummary/base.rst b/doc_src/_templates/autosummary/base.rst new file mode 100644 index 0000000..90e3521 --- /dev/null +++ b/doc_src/_templates/autosummary/base.rst @@ -0,0 +1,10 @@ +.. rst-class:: h4 text-secondary + +{{ fullname }} + +{{ objname | escape | underline}} + +.. currentmodule:: {{ module }} +{%- if not objname.startswith("test") %} +.. auto{{ objtype }}:: {{ objname }} +{%- endif %} diff --git a/doc_src/_templates/autosummary/class.rst b/doc_src/_templates/autosummary/class.rst new file mode 100644 index 0000000..fb5557b --- /dev/null +++ b/doc_src/_templates/autosummary/class.rst @@ -0,0 +1,34 @@ +.. rst-class:: h4 text-secondary + +{{ fullname }} + +{{ objname | escape | underline}} + +.. currentmodule:: {{ module }} + +.. autoclass:: {{ objname }} + + {% block methods %} + {% if methods %} + .. rubric:: {{ _('Methods') }} + + .. autosummary:: + {% for item in methods %} + {%- if "__" not in item %} + ~{{ name }}.{{ item }} + {% endif -%} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block attributes %} + {% if attributes %} + .. rubric:: {{ _('Attributes') }} + + .. autosummary:: + {% for item in attributes %} + {%- if "__" not in item %} + ~{{ name }}.{{ item }}{% endif %} + {% endfor -%} + {% endif %} + {% endblock %} diff --git a/doc_src/_templates/autosummary/module.rst b/doc_src/_templates/autosummary/module.rst new file mode 100644 index 0000000..d664d28 --- /dev/null +++ b/doc_src/_templates/autosummary/module.rst @@ -0,0 +1,70 @@ +.. rst-class:: h4 text-secondary + +{{ fullname }} + +{{ objname | escape | underline}} +.. currentmodule:: {{ fullname }} + + +.. automodule:: {{ fullname }} + + {% block modules -%} + {% if modules %} + + .. rubric:: Submodules + + .. autosummary:: + :toctree: + :recursive: + {% for item in modules %} + {% if "migrations" not in item and "tests" not in item%}{{ item }}{% endif %} + {%- endfor %} + {% endif %} + {% endblock %} + {% block attributes -%} + {%- if attributes -%} + .. rubric:: {{ _('Module Attributes') }} + + .. autosummary:: + :toctree: + {% for item in attributes %} + {{ item }} + {%- endfor -%} + {%- endif -%} + {% endblock attributes -%} + {%- block functions -%} + {%- if functions %} + + .. rubric:: {{ _('Functions') }} + + .. autosummary:: + :toctree: + {% for item in functions %} + {{ item }} + {%- endfor -%} + {%- endif -%} + {% endblock functions -%} + {% block classes -%} + {% if classes %} + + .. rubric:: {{ _('Classes') }} + + .. autosummary:: + :toctree: + {% for item in classes %} + {{ item }} + {%- endfor -%} + {%- endif -%} + {% endblock classes -%} + {% block exceptions -%} + {% if exceptions %} + + .. rubric:: {{ _('Exceptions') }} + + .. autosummary:: + :toctree: + {% for item in exceptions %} + {{ item }} + {%- endfor -%} + {%- endif -%} + {% endblock exceptions -%} diff --git a/doc_src/_templates/layout.html b/doc_src/_templates/layout.html deleted file mode 100644 index 4e302db..0000000 --- a/doc_src/_templates/layout.html +++ /dev/null @@ -1,144 +0,0 @@ -{% extends "basic/layout.html" %} -{%- block doctype -%} - -{%- endblock %} -{%- set reldelim1 = reldelim1 is not defined and ' »' or reldelim1 %} -{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %} -{%- block linktags %} - {%- if hasdoc('about') %} - - {%- endif %} - {%- if hasdoc('genindex') %} - - {%- endif %} - {%- if hasdoc('search') %} - - {%- endif %} - {%- if hasdoc('copyright') %} - - {%- endif %} - - {%- if parents %} - - {%- endif %} - {%- if next %} - - {%- endif %} - {%- if prev %} - - {%- endif %} -{%- endblock %} -{%- block extrahead %} {% endblock %} -{%- block header %}{% endblock %} -{%- block relbar1 %} -
      -

      {{docstitle}}

      -
      -
      -{% endblock %} - -{%- block sidebar1 %} -{%- if not embedded %}{% if not theme_nosidebar|tobool %} -
      -
      - {%- block sidebarlogo %} - {%- if logo %} - - {%- endif %} - {%- endblock %} - {%- block sidebartoc %} - - {{ toctree() }} - {%- endblock %} - {%- block sidebarrel %} - {%- endblock %} - {%- block sidebarsourcelink %} - {%- if show_source and has_source and sourcename %} -

      {{ _('This Page') }}

      - - {%- endif %} - {%- endblock %} - {%- if customsidebar %} - {% include customsidebar %} - {%- endif %} - {%- block sidebarsearch %} - {%- if pagename != "search" %} - - - {%- endif %} - {%- endblock %} -
      -
      -{%- endif %}{% endif %} - -{% endblock %} -{%- block document %} -
      - {%- if not embedded %}{% if not theme_nosidebar|tobool %} -
      - {%- endif %}{% endif %} -
      - {% block body %} {% endblock %} -
      - {%- if not embedded %}{% if not theme_nosidebar|tobool %} -
      - {%- endif %}{% endif %} -
      - -{%- endblock %} -{%- block sidebar2 %}{% endblock %} -{%- block relbar2 %}{% endblock %} -{%- block footer %} - - -{%- endblock %} diff --git a/doc_src/api/index.rst b/doc_src/api/index.rst new file mode 100644 index 0000000..7f95b37 --- /dev/null +++ b/doc_src/api/index.rst @@ -0,0 +1,8 @@ +API +=== + +.. autosummary:: + :toctree: + :recursive: + + categories diff --git a/doc_src/changelog.md b/doc_src/changelog.md new file mode 100644 index 0000000..66efc0f --- /dev/null +++ b/doc_src/changelog.md @@ -0,0 +1,2 @@ +```{include} ../CHANGELOG.md +``` diff --git a/doc_src/conf.py b/doc_src/conf.py index f8400c6..e2cab65 100644 --- a/doc_src/conf.py +++ b/doc_src/conf.py @@ -1,196 +1,85 @@ -# -# Django Categories documentation build configuration file, created by -# sphinx-quickstart on Tue Oct 6 07:53:33 2009. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. +""" +Sphinx configuration. +""" import os import sys +from datetime import date +from pathlib import Path -# 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.append(os.path.abspath("..")) +project_root = Path("..").resolve() +sys.path.insert(0, str(project_root / "example")) +sys.path.insert(0, str(project_root)) os.environ["DJANGO_SETTINGS_MODULE"] = "example.settings" +# Setup Django +import django # NOQA + +django.setup() + import categories # noqa +import categories.urls # noqa + +project = "Django Categories" +copyright = f"2010-{date.today():%Y}, Corey Oordt" + +version = categories.__version__ +release = categories.__version__ # -- General configuration ----------------------------------------------------- -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = [] +extensions = [ + "myst_parser", + "sphinx.ext.autodoc", + "sphinx.ext.viewcode", + "sphinx.ext.autosummary", + "sphinx.ext.intersphinx", + "sphinx.ext.autosectionlabel", + "sphinx.ext.napoleon", + "sphinx_autodoc_typehints", + "sphinx.ext.coverage", + "sphinx.ext.githubpages", + "sphinxcontrib_django2", +] +autosectionlabel_prefix_document = True +autosectionlabel_maxdepth = 2 +autosummary_generate = True +napoleon_attr_annotations = True +napoleon_include_special_with_doc = False +napoleon_include_private_with_doc = True +napoleon_include_init_with_doc = True +myst_enable_extensions = [ + "amsmath", + "colon_fence", + "deflist", + "dollarmath", + "linkify", + "replacements", + "smartquotes", + "substitution", + "tasklist", +] +intersphinx_mapping = { + "python": ("https://docs.python.org/3", None), + "django": ( + "https://docs.djangoproject.com/en/stable", + "https://docs.djangoproject.com/en/stable/_objects", + ), +} -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = ".rst" - -# The encoding of source files. -# ource_encoding = 'utf-8' - -# The master toctree document. +templates_path = ["_templates"] +source_suffix = [".rst", ".md"] master_doc = "index" -# General information about the project. -project = "Django Categories" -copyright = "2010-2012, Corey Oordt" - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = categories.get_version(short=True) -# The full version, including alpha/beta/rc tags. -release = categories.get_version() - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# anguage = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# oday = '' -# Else, today_fmt is used as the format for a strftime call. -# oday_fmt = '%B %d, %Y' - -# List of documents that shouldn't be included in the build. -# nused_docs = [] - -# List of directories, relative to source directory, that shouldn't be searched -# for source files. -exclude_trees = ["_build"] - -# The reST default role (used for this markup: `text`) to use for all documents. -# efault_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -# dd_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# dd_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# how_authors = False - -# The name of the Pygments (syntax highlighting) style to use. +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] pygments_style = "sphinx" - -# A list of ignored prefixes for module index sorting. -# odindex_common_prefix = [] +todo_include_todos = False # -- Options for HTML output --------------------------------------------------- -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -html_theme = 'default' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# tml_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -# tml_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -# tml_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -# tml_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# tml_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. -# tml_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_theme = "pydata_sphinx_theme" html_static_path = ["_static"] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# tml_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# tml_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# tml_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# tml_additional_pages = {} - -# If false, no module index is generated. -# tml_use_modindex = True - -# If false, no index is generated. -# tml_use_index = True - -# If true, the index is split into individual pages for each letter. -# tml_split_index = False - -# If true, links to the reST sources are added to the pages. -# tml_show_sourcelink = 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. -# tml_use_opensearch = '' - -# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -# tml_file_suffix = '' - -# Output file base name for HTML help builder. -htmlhelp_basename = "DjangoCategoriesdoc" - - -# -- Options for LaTeX output -------------------------------------------------- - -# The paper size ('letter' or 'a4'). -# atex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -# atex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ("index", "DjangoCategories.tex", "Django Categories Documentation", "CoreyOordt", "manual"), +html_css_files = [ + "css/custom.css", ] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# atex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# atex_use_parts = False - -# Additional stuff for the LaTeX preamble. -# atex_preamble = '' - -# Documents to append as an appendix to all manuals. -# atex_appendices = [] - -# If false, no module index is generated. -# atex_use_modindex = True diff --git a/doc_src/index.rst b/doc_src/index.rst index 093de5a..22be8a7 100644 --- a/doc_src/index.rst +++ b/doc_src/index.rst @@ -6,18 +6,6 @@ Django Categories grew out of our need to provide a basic hierarchical taxonomy As a news site, our stories, photos, and other content get divided into "sections" and we wanted all the apps to use the same set of sections. As our needs grew, the Django Categories grew in the functionality it gave to category handling within web pages. -New in 1.1 -========== - -* Fixed a cosmetic bug in the Django 1.4 admin. Action checkboxes now only appear once. - -* Template tags are refactored to allow easy use of any model derived from ``CategoryBase``. - -* Improved test suite. - -* Improved some of the documentation. - - Contents ======== @@ -28,12 +16,10 @@ Contents installation getting_started - usage - registering_models - adding_the_fields - admin_settings - custom_categories + user_guide/index reference/index + api/index + changelog Indices and tables ================== diff --git a/doc_src/user_guide/index.md b/doc_src/user_guide/index.md new file mode 100644 index 0000000..fb4062b --- /dev/null +++ b/doc_src/user_guide/index.md @@ -0,0 +1,12 @@ +# User Guide + +```{toctree} +--- +maxdepth: 2 +--- +usage +registering_models +adding_the_fields +admin_settings +custom_categories +``` diff --git a/docs/.buildinfo b/docs/.buildinfo deleted file mode 100644 index 0885fbe..0000000 --- a/docs/.buildinfo +++ /dev/null @@ -1,4 +0,0 @@ -# Sphinx build info version 1 -# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: -tags: diff --git a/docs/_sources/getting_started.txt b/docs/_sources/getting_started.txt deleted file mode 100644 index 4885628..0000000 --- a/docs/_sources/getting_started.txt +++ /dev/null @@ -1,74 +0,0 @@ -=============== -Getting Started -=============== - -You can use Django Categories in two ways: - -1. As storage for one tree of categories, using the :py:class:`Category` model:: - - Top Category 1 - Subcategory 1-1 - Subcategory 1-2 - subcategory 1-2-1 - Top Category 2 - Subcategory 2-1 - -2. As the basis for several custom categories (see :ref:`creating_custom_categories`), e.g. a **MusicGenre** model - - :: - - MusicGenre 1 - MusicSubGenre 1-1 - MusicSubGenre 1-2 - MusicSubGenre 1-2-1 - MusicGenre 2 - MusicSubGenre 2-1 - - and a **Subject** model - - :: - - Subject 1 - Discipline 1-1 - Discipline 1-2 - SubDiscipline 1-2-1 - Subject 2 - Discipline 2-1 - - - -Connecting your model with Django-Categories -============================================ - -There are two ways to add Category fields to an application. If you are in control of the code (it's your application) or you are willing to take control of the code (fork someone else's app) you can make a :ref:`hard_coded_connection`\ . - -For 3rd-party apps or even your own apps that you don't wish to add Django-Categories as a dependency, you can configure a :ref:`lazy_connection`\ . - -.. _hard_coded_connection: - -Hard Coded Connection ---------------------- - -Hard coded connections are done in the exact same way you handle any other foreign key or many-to-many relations to a model. - -.. code-block:: python - - from django.db import models - - class MyModel(models.Model): - name = models.CharField(max_length=100) - category = models.ForeignKey('categories.Category') - -Don't forget to add the field or fields to your ``ModelAdmin`` class as well. - - -.. _lazy_connection: - -Lazy Connection ---------------- - -Lazy connections are done through configuring Django Categories in the project's ``settings.py`` file. When the project starts up, the configured fields are dynamically added to the configured models and admin. - -If you do this before you have created the database (before you ran ``manage.py syncdb``), the fields will also be in the tables. If you do this after you have already created all the tables, you can run ``manage.py add_category_fields`` to create the fields (this requires Django South to be installed). - -You add a many-to-one or many-to-many relationship with Django Categories using the :ref:`FK_REGISTRY` and :ref:`M2M_REGISTRY` settings respectively. For more information see :ref:`registering_models`\ . diff --git a/docs/_sources/index.txt b/docs/_sources/index.txt deleted file mode 100644 index 33705cd..0000000 --- a/docs/_sources/index.txt +++ /dev/null @@ -1,43 +0,0 @@ -============================= -Django Categories v |version| -============================= - -Django Categories grew out of our need to provide a basic hierarchical taxonomy management system that multiple applications could use independently or in concert. - -As a news site, our stories, photos, and other content get divided into "sections" and we wanted all the apps to use the same set of sections. As our needs grew, the Django Categories grew in the functionality it gave to category handling within web pages. - -New in 1.1 -========== - -* Fixed a cosmetic bug in the Django 1.4 admin. Action checkboxes now only appear once. - -* Template tags are refactored to allow easy use of any model derived from ``CategoryBase``. - -* Improved test suite. - -* Improved some of the documentation. - - - -Contents -======== - -.. toctree:: - :maxdepth: 2 - :glob: - - installation - getting_started - usage - registering_models - adding_the_fields - custom_categories - reference/index - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` - diff --git a/docs/_sources/installation.txt b/docs/_sources/installation.txt deleted file mode 100644 index 1cff18a..0000000 --- a/docs/_sources/installation.txt +++ /dev/null @@ -1,43 +0,0 @@ -============ -Installation -============ - -To use the Category model -========================= - -1. Install django-categories:: - - pip install django-categories - -2. Add ``"categories"`` and ``"categories.editor"`` to your ``INSTALLED_APPS`` list in your project's ``settings.py`` file. - - .. code-block:: python - - INSTALLED_APPS = [ - # ... - "categories", - "categories.editor", - ] - -3. Run ``./manage.py syncdb`` (or ``./manage.py migrate categories`` if you are using `South `_) - - -To only subclass CategoryBase -============================= - -If you are going to create your own models using :py:class:`CategoryBase`, (see :ref:`creating_custom_categories`) you'll need a few different steps. - -1. Install django-categories:: - - pip install django-categories - -2. Add ``"categories.editor"`` to your ``INSTALLED_APPS`` list in your project's ``settings.py`` file. - - .. code-block:: python - - INSTALLED_APPS = [ - # ... - "categories.editor", - ] - -3. Create your own models. diff --git a/docs/_sources/reference/index.txt b/docs/_sources/reference/index.txt deleted file mode 100644 index 9bca020..0000000 --- a/docs/_sources/reference/index.txt +++ /dev/null @@ -1,12 +0,0 @@ -========= -Reference -========= - -.. toctree:: - :maxdepth: 2 - :glob: - - management_commands - models - settings - templatetags diff --git a/docs/_sources/reference/management_commands.txt b/docs/_sources/reference/management_commands.txt deleted file mode 100644 index b090695..0000000 --- a/docs/_sources/reference/management_commands.txt +++ /dev/null @@ -1,38 +0,0 @@ -.. _management-commands: - -=================== -Management Commands -=================== - -.. _import_categories: - -import_categories -================= - -**Usage:** ``./manage.py import_categories /path/to/file.txt [/path/to/file2.txt]`` - -Imports category tree(s) from a file. Sub categories must be indented by the same multiple of spaces or tabs. The first line in the file cannot start with a space or tab and you can't mix spaces and tabs. - - -.. _add_category_fields: - -add_category_fields -=================== - -**Usage:** ``./manage.py add_category_fields [app1 app2 ...]`` - -Add missing registered category fields to the database table of a specified application or all registered applications. - -Requires Django South. - - -.. _drop_category_field: - -drop_category_field -=================== - -**Usage:** ``./manage.py drop_category_field app_name model_name field_name`` - -Drop the ``field_name`` field from the ``app_name_model_name`` table, if the field is currently registered in ``CATEGORIES_SETTINGS``\ . - -Requires Django South. \ No newline at end of file diff --git a/docs/_sources/reference/models.txt b/docs/_sources/reference/models.txt deleted file mode 100644 index 2ec5444..0000000 --- a/docs/_sources/reference/models.txt +++ /dev/null @@ -1,115 +0,0 @@ -====== -Models -====== - -CategoryBase -============ - -.. py:class:: CategoryBase - - .. py:attribute:: parent - - :py:class:`TreeForeignKey` ``(self)`` - - The category's parent category. Leave this blank for an root category. - - .. py:attribute:: name - - **Required** ``CharField(100)`` - - The name of the category. - - .. py:attribute:: slug - - **Required** ``SlugField`` - - URL-friendly title. It is automatically generated from the title. - - .. py:attribute:: active - - **Required** ``BooleanField`` *default:* ``True`` - - Is this item active. If it is inactive, all children are set to inactive as well. - - .. py:attribute:: objects - - ``CategoryManager`` - - An object manager that adds an ``active`` method for only selecting items whose ``active`` attribute is ``True``. - - .. py:attribute:: tree - - ``TreeManager`` - - A Django-MPTT `TreeManager `_ instance. - -Category -======== - -.. py:class:: Category - - Category is a subclass of :py:class:`CategoryBase` and includes all its attributes. - - .. py:attribute:: thumbnail - - ``FileField`` - - An optional thumbnail, that is uploaded to :ref:`thumbnail_upload_path` via :ref:`THUMBNAIL_STORAGE`. - - .. note:: Why isn't this an ``ImageField``? - - For ``ImageField``\ s, Django checks the file system for the existance of the files to handle the height and width. In many cases this can lead to problems and impact performance. - - For these reasons, a ``FileField`` that manually manages the width and height was chosen. - - .. py:attribute:: thumbnail_width - - ``IntegerField`` - - The thumbnail width. Automatically set on save if a thumbnail is uploaded. - - .. py:attribute:: thumbnail_height - - ``IntegerField`` - - The thumbnail height. Automatically set on save if a thumbnail is uploaded. - - .. py:attribute:: order - - **Required** ``IntegerField`` *default:* 0 - - A manually-managed order of this category in the listing. Items with the same order are sorted alphabetically. - - .. py:attribute:: alternate_title - - ``CharField(100)`` - - An alternative title to use on pages with this category. - - .. py:attribute:: alternate_url - - ``CharField(200)`` - - An alternative URL to use instead of the one derived from the category hierarchy. - - .. note:: Why isn't this a ``URLField``? - - For ``URLField``\ s, Django checks that the URL includes ``http://`` and the site name. This makes it impossible to use relative URLs in that field. - - .. py:attribute:: description - - ``TextField`` - - An optional longer description of the category. Very useful on category landing pages. - - .. py:attribute:: meta_keywords - - ``CharField(255)`` - - Comma-separated keywords for search engines. - - .. py:attribute:: meta_extra - - ``TextField`` - - (Advanced) Any additional HTML to be placed verbatim in the ```` of the page. diff --git a/docs/_sources/reference/settings.txt b/docs/_sources/reference/settings.txt deleted file mode 100644 index 78df52d..0000000 --- a/docs/_sources/reference/settings.txt +++ /dev/null @@ -1,121 +0,0 @@ -.. _reference_settings: - -======== -Settings -======== - -The ``CATEGORIES_SETTINGS`` dictionary is where you can override the default settings. You don't have to include all the settings; only the ones which you want to override. - -.. contents:: - :local: - - -The default settings are: - -.. code-block:: python - - CATEGORIES_SETTINGS = { - 'ALLOW_SLUG_CHANGE': False, - 'CACHE_VIEW_LENGTH': 0, - 'RELATION_MODELS': [], - 'M2M_REGISTRY': {}, - 'FK_REGISTRY': {}, - 'THUMBNAIL_UPLOAD_PATH': 'uploads/categories/thumbnails', - 'THUMBNAIL_STORAGE': settings.DEFAULT_FILE_STORAGE, - 'SLUG_TRANSLITERATOR': lambda x: x, - } - - -.. _ALLOW_SLUG_CHANGE: - -ALLOW_SLUG_CHANGE -================= - -**Default:** ``False`` - -**Description:** Changing the slug for a category can have serious consequences if it is used as part of a URL. Setting this to ``True`` will allow users to change the slug of a category. - -.. _SLUG_TRANSLITERATOR: - -SLUG_TRANSLITERATOR -=================== - -**Default:** ``lambda x: x`` - -**Description:** Allows the specification of a function to convert non-ASCII characters in the potential slug to ASCII characters. Allows specifying a ``callable()`` or a string in the form of ``'path.to.module.function'``. - -A great tool for this is `Unidecode `_. Use it by setting ``SLUG_TRANSLITERATOR`` to ``'unidecode.unidecode``. - - -.. _CACHE_VIEW_LENGTH: - -CACHE_VIEW_LENGTH -================= - -**Default:** ``0`` - -**Description:** This setting will be deprecated soon, but in the mean time, it allows you to specify the amount of time each view result is cached. - -.. _RELATION_MODELS: - -RELATION_MODELS -=============== - -**Default:** ``[]`` - -**Description:** Relation models is a set of models that a user can associate with this category. You specify models using ``'app_name.modelname'`` syntax. - -.. _M2M_REGISTRY: - -M2M_REGISTRY -============ - -**Default:** {} - -**Description:** A dictionary where the keys are in ``'app_name.model_name'`` syntax, and the values are a string, dict, or tuple of dicts. See :ref:`registering_models`\ . - -.. _FK_REGISTRY: - -FK_REGISTRY -============ - -**Default:** {} - -**Description:** A dictionary where the keys are in ``'app_name.model_name'`` syntax, and the values are a string, dict, or tuple of dicts. See :ref:`registering_models`\ . - -.. _THUMBNAIL_UPLOAD_PATH: - -.. _REGISTER_ADMIN: - -REGISTER_ADMIN -============== - -**Default:** ``True`` - -**Description:** If you write your own category class by subclassing ``CategoryBase`` then you probably have no use for registering the default ``Category`` class in the admin. - - -THUMBNAIL_UPLOAD_PATH -===================== - -**Default:** ``'uploads/categories/thumbnails'`` - -**Description:** Where thumbnails for the categories will be saved. - -.. _THUMBNAIL_STORAGE: - -THUMBNAIL_STORAGE -================= - -**Default:** ``settings.DEFAULT_FILE_STORAGE`` - -**Description:** How to store the thumbnails. Allows for external storage engines like S3. - -.. _JAVASCRIPT_URL: - -JAVASCRIPT_URL -============== - -**Default:** ``STATIC_URL or MEDIA_URL + 'js/'`` - -**Description:** Allows for customization of javascript placement. diff --git a/docs/_sources/reference/templatetags.txt b/docs/_sources/reference/templatetags.txt deleted file mode 100644 index 9f846fd..0000000 --- a/docs/_sources/reference/templatetags.txt +++ /dev/null @@ -1,348 +0,0 @@ -========================= -Template tags and filters -========================= - -.. contents:: - :depth: 2 - :local: - :backlinks: top - - -Filters -======= - - -``category_path`` ------------------ - -**Optional Parameter:** separator string. *Default:* ``" :: "`` - -Creates a path represented by a categories by joining the items with a separator. - -Each path item will be coerced to unicode, so you can pass a list of category instances, if required. - -**Example using a list of categories:** - -.. code-block:: django - - {{ some_list|category_path }} - -If ``some_list`` is ``[ , , ]`` the result will be:: - - Country :: Country pop :: Urban Cowboy - -**Example using a category node and optional separator parameter:** - -.. code-block:: django - - {{ some_node.get_ancestors|category_path:" > " }} - -If ``some_node`` was category "Urban Cowboy", the result will be:: - - Country > Country pop > Urban Cowboy - -.. _tree_info: - -``tree_info`` -------------- - -**Optional Parameter:** ``"ancestors"`` - -Given a list of categories, it iterates over the list, generating a tuple of the current category and a dict containing information about the tree structure around it, with the following keys: - -``'new_level'`` - ``True`` if the current item is the start of a new level in the tree, ``False`` otherwise. - -``'closed_levels'`` - A list of levels which end after the current item. This will be an empty list if the next category's level is the same as or greater than the level of the current item. - -Provide the optional argument, ``"ancestors"``, to add a list of unicode representations of the ancestors of the current category, in descending order (root node first, immediate parent last), under the key 'ancestors'. - -For example: given the sample tree below, the contents of the list which would be available under the 'ancestors' key are given on the right:: - - Country -> [] - Country pop -> [u'Country pop'] - Urban Cowboy -> [u'Country', u'Country pop'] - -Using this filter with unpacking in a {% for %} tag, you should have enough information about the tree structure to create a hierarchical representation of the tree. - -.. code-block:: django - - {% for node,structure in objects|tree_info %} - {% if structure.new_level %}
      • {% else %}
      • {% endif %} - {{ node.name }} - {% for level in structure.closed_levels %}
      {% endfor %} - {% endfor %} - -``tree_queryset`` ------------------ - -Convert a regular category :py:class:`QuerySet` into a new, ordered :py:class:`QuerySet` that includes the categories selected and their ancestors. - -This is especially helpful when you have a subset of categories and want to show the hierarchy for all the items. - -For example, if we add it to the example for :ref:`tree_info`: - -.. code-block:: django - - {% for node,structure in objects|tree_queryset|tree_info %} - {% if structure.new_level %}
      • {% else %}
      • {% endif %} - {{ node.name }} - {% for level in structure.closed_levels %}
      {% endfor %} - {% endfor %} - -A list of unrelated categories such as ``[, ]``, the above template example will output the two categories and their ancestors: - -.. code-block:: html - -
      • - Country -
        • - Country pop -
          • - Urban cowboy -
      -
      • - Rhythm and blues -
        • - Urban contemporary -
      - -.. note:: - Categories that have similar ancestors are grouped accordingly. There is no duplication of the ancestor tree. - - -Inclusion tags -============== - -``display_path_as_ul`` ----------------------- - -**Template Rendered:** ``categories/ul_tree.html`` - -**Syntax 1:** ``{% display_path_as_ul %}`` - -**Syntax 2:** ``{% display_path_as_ul [ using="app.Model"] %}`` - -Render the category with ancestors, but no children. - -Pass either an object that subclasses :py:class:`CategoryBase` or a path string for the category. Add ``using="app.Model"`` to specify which model when using a path string. The default model used is :py:class:`Category`. - -**Example, using Category model:** - -.. code-block:: django - - {% display_path_as_ul "/Grandparent/Parent" %} - -**Example, using custom model:** - -.. code-block:: django - - {% display_path_as_ul "/Grandparent/Parent" using="coolapp.MusicGenre" %} - -**Example, using an object:** - -.. code-block:: django - - {% display_path_as_ul category_obj %} - -Returns: - -.. code-block:: html - - - - -``display_drilldown_as_ul`` ---------------------------- - -**Template rendered:** ``categories/ul_tree.html`` - -**Syntax 1:** ``{% display_drilldown_as_ul category_obj %}`` - -**Syntax 2:** ``{% display_drilldown_as_ul "/Grandparent/Parent" [using="app.Model"] %}`` - -Render the category with ancestors and children. - -**Example, using Category model:** - -.. code-block:: django - - {% display_drilldown_as_ul "/Grandparent/Parent" %} - -**Example, using custom model:** - -.. code-block:: django - - {% display_drilldown_as_ul "/Grandparent/Parent" using="coolapp.MusicGenre" %} - -**Example, using an object:** - -.. code-block:: django - - {% display_drilldown_as_ul category_obj %} - -Returns: - -.. code-block:: html - - - - -``breadcrumbs tag`` -------------------- - -**Template rendered:** ``categories/breadcrumbs.html`` - -**Syntax 1:** ``{% breadcrumbs category_obj [separator=" :: "] %}`` - -**Syntax 2:** ``{% breadcrumbs "/Grandparent/Parent" [separator=" :: "] [using="app.Model"] %}`` - -Render breadcrumbs for the given path using ``::`` or the given separator. - -**Example using Category model:** - -.. code-block:: django - - {% breadcrumbs "/Grandparent/Parent" %} - -**Example using a custom model:** - -.. code-block:: django - - {% breadcrumbs "/Grandparent/Parent" using="coolapp.MusicGenre" %} - -**Example using an object:** - -.. code-block:: django - - {% breadcrumbs category_obj %} - -Returns: - -.. code-block:: html - - Grandparent / Parent - -You can alter the separator used in the template by adding a separator argument: - -.. code-block:: django - - {% breadcrumbs category_obj separator=" > " %} - -Returns: - -.. code-block:: html - - Grandparent > Parent - - -Template Tags -============= - -``get_top_level_categories`` ----------------------------- - -Retrieves an alphabetical list of all the categories that have no parents. - -Syntax: - -.. code-block:: django - - {% get_top_level_categories [using "app.Model"] as categories %} - -Returns an list of categories ``[, , [using "app.Model"] as %}`` - -**Syntax 2:** ``{% get_category_drilldown as %}`` - -Retrieves the specified category, its ancestors and its immediate children as an iterable. Syntax 1 allows for the retrieval of the category object via a slash-delimited path. The optional ``using "app.Model"`` allows you to specify from which model to retrieve the object. - -Example: - -.. code-block:: django - - {% get_category_drilldown "/Grandparent/Parent" using "family.Member" as family %} - -The second syntax uses an instance of any object that subclasses :py:class:`CategoryBase` - -.. code-block:: django - - {% get_category_drilldown category_obj as family %} - -Both examples sets ``family`` to:: - - [Grandparent, Parent, Child 1, Child 2, Child n] - -``recursetree`` ---------------- - -This tag renders a section of your template recursively for each node in your -tree. - -For example: - -.. code-block:: django - -
        - {% recursetree nodes %} -
      • - {{ node.name }} - {% if not node.is_leaf_node %} -
          - {{ children }} -
        - {% endif %} -
      • - {% endrecursetree %} -
      - -Note the special variables ``node`` and ``children``. -These are magically inserted into your context while you're inside the -``recursetree`` tag. - - ``node`` is an instance of your MPTT model. - - ``children`` : This variable holds the rendered HTML for the children of - ``node``. - -.. note:: - If you already have variables called ``node`` or ``children`` in your - template, and you need to access them inside the ``recursetree`` block, - you'll need to alias them to some other name first: - - .. code-block:: django - - {% with node as friendly_node %} - {% recursetree nodes %} - {{ node.name }} is friends with {{ friendly_node.name }} - {{ children }} - {% endrecursetree %} - {% endwith %} diff --git a/docs/_sources/templatetags.txt b/docs/_sources/templatetags.txt deleted file mode 100644 index b5463f4..0000000 --- a/docs/_sources/templatetags.txt +++ /dev/null @@ -1,146 +0,0 @@ -============= -Template Tags -============= - -get_top_level_categories -======================== - -Retrieves an alphabetical list of all the categories that have no parents. - -Syntax: - -.. code-block:: django - - {% get_top_level_categories as categories %} - -Returns an list of categories ``[, , -
    • Top - -
    • - - - -get_category_drilldown -====================== - -Retrieves the specified category, its ancestors and its immediate children -as an iterable. - -Example: - -.. code-block:: django - - {% get_category_drilldown "/Grandparent/Parent" as family %} - -or - -.. code-block:: django - - {% get_category_drilldown category_obj as family %} - -Sets ``family`` to:: - - [Grandparent, Parent, Child 1, Child 2, Child n] - - -display_drilldown_as_ul -======================= - -Render the category with ancestors and children using the -``categories/ul_tree.html`` template. - -Example: - -.. code-block:: django - - {% display_drilldown_as_ul "/Grandparent/Parent" %} - -or: - -.. code-block:: django - - {% display_drilldown_as_ul category_obj %} - -Returns: - -.. code-block:: html - - - - -breadcrumbs tag -=============== - -Render breadcrumbs, using the ``categories/breadcrumbs.html`` template, using the optional ``separator`` argument. - -Example: - -.. code-block:: django - - {% breadcrumbs "/Grandparent/Parent" %} - -or: - -.. code-block:: django - - {% breadcrumbs category_obj %} - -Returns: - -.. code-block:: html - - Grandparent / Parent - -You can alter the separator used in the template by adding a string argument to be the separator: - -.. code-block:: django - - {% breadcrumbs category_obj "::" %} - -Returns: - -.. code-block:: html - - Grandparent :: Parent diff --git a/docs/_static/ajax-loader.gif b/docs/_static/ajax-loader.gif deleted file mode 100644 index 61faf8cab23993bd3e1560bff0668bd628642330..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 673 zcmZ?wbhEHb6krfw_{6~Q|Nno%(3)e{?)x>&1u}A`t?OF7Z|1gRivOgXi&7IyQd1Pl zGfOfQ60;I3a`F>X^fL3(@);C=vM_KlFfb_o=k{|A33hf2a5d61U}gjg=>Rd%XaNQW zW@Cw{|b%Y*pl8F?4B9 zlo4Fz*0kZGJabY|>}Okf0}CCg{u4`zEPY^pV?j2@h+|igy0+Kz6p;@SpM4s6)XEMg z#3Y4GX>Hjlml5ftdH$4x0JGdn8~MX(U~_^d!Hi)=HU{V%g+mi8#UGbE-*ao8f#h+S z2a0-5+vc7MU$e-NhmBjLIC1v|)9+Im8x1yacJ7{^tLX(ZhYi^rpmXm0`@ku9b53aN zEXH@Y3JaztblgpxbJt{AtE1ad1Ca>{v$rwwvK(>{m~Gf_=-Ro7Fk{#;i~+{{>QtvI yb2P8Zac~?~=sRA>$6{!(^3;ZP0TPFR(G_-UDU(8Jl0?(IXu$~#4A!880|o%~Al1tN diff --git a/docs/_static/basic.css b/docs/_static/basic.css deleted file mode 100644 index 32630d5..0000000 --- a/docs/_static/basic.css +++ /dev/null @@ -1,528 +0,0 @@ -/* - * basic.css - * ~~~~~~~~~ - * - * Sphinx stylesheet -- basic theme. - * - * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - -/* -- main layout ----------------------------------------------------------- */ - -div.clearer { - clear: both; -} - -/* -- relbar ---------------------------------------------------------------- */ - -div.related { - width: 100%; - font-size: 90%; -} - -div.related h3 { - display: none; -} - -div.related ul { - margin: 0; - padding: 0 0 0 10px; - list-style: none; -} - -div.related li { - display: inline; -} - -div.related li.right { - float: right; - margin-right: 5px; -} - -/* -- sidebar --------------------------------------------------------------- */ - -div.sphinxsidebarwrapper { - padding: 10px 5px 0 10px; -} - -div.sphinxsidebar { - float: left; - width: 230px; - margin-left: -100%; - font-size: 90%; -} - -div.sphinxsidebar ul { - list-style: none; -} - -div.sphinxsidebar ul ul, -div.sphinxsidebar ul.want-points { - margin-left: 20px; - list-style: square; -} - -div.sphinxsidebar ul ul { - margin-top: 0; - margin-bottom: 0; -} - -div.sphinxsidebar form { - margin-top: 10px; -} - -div.sphinxsidebar input { - border: 1px solid #98dbcc; - font-family: sans-serif; - font-size: 1em; -} - -img { - border: 0; -} - -/* -- search page ----------------------------------------------------------- */ - -ul.search { - margin: 10px 0 0 20px; - padding: 0; -} - -ul.search li { - padding: 5px 0 5px 20px; - background-image: url(file.png); - background-repeat: no-repeat; - background-position: 0 7px; -} - -ul.search li a { - font-weight: bold; -} - -ul.search li div.context { - color: #888; - margin: 2px 0 0 30px; - text-align: left; -} - -ul.keywordmatches li.goodmatch a { - font-weight: bold; -} - -/* -- index page ------------------------------------------------------------ */ - -table.contentstable { - width: 90%; -} - -table.contentstable p.biglink { - line-height: 150%; -} - -a.biglink { - font-size: 1.3em; -} - -span.linkdescr { - font-style: italic; - padding-top: 5px; - font-size: 90%; -} - -/* -- general index --------------------------------------------------------- */ - -table.indextable { - width: 100%; -} - -table.indextable td { - text-align: left; - vertical-align: top; -} - -table.indextable dl, table.indextable dd { - margin-top: 0; - margin-bottom: 0; -} - -table.indextable tr.pcap { - height: 10px; -} - -table.indextable tr.cap { - margin-top: 10px; - background-color: #f2f2f2; -} - -img.toggler { - margin-right: 3px; - margin-top: 3px; - cursor: pointer; -} - -div.modindex-jumpbox { - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 1em 0 1em 0; - padding: 0.4em; -} - -div.genindex-jumpbox { - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 1em 0 1em 0; - padding: 0.4em; -} - -/* -- general body styles --------------------------------------------------- */ - -a.headerlink { - visibility: hidden; -} - -h1:hover > a.headerlink, -h2:hover > a.headerlink, -h3:hover > a.headerlink, -h4:hover > a.headerlink, -h5:hover > a.headerlink, -h6:hover > a.headerlink, -dt:hover > a.headerlink { - visibility: visible; -} - -div.body p.caption { - text-align: inherit; -} - -div.body td { - text-align: left; -} - -.field-list ul { - padding-left: 1em; -} - -.first { - margin-top: 0 !important; -} - -p.rubric { - margin-top: 30px; - font-weight: bold; -} - -img.align-left, .figure.align-left, object.align-left { - clear: left; - float: left; - margin-right: 1em; -} - -img.align-right, .figure.align-right, object.align-right { - clear: right; - float: right; - margin-left: 1em; -} - -img.align-center, .figure.align-center, object.align-center { - display: block; - margin-left: auto; - margin-right: auto; -} - -.align-left { - text-align: left; -} - -.align-center { - clear: both; - text-align: center; -} - -.align-right { - text-align: right; -} - -/* -- sidebars -------------------------------------------------------------- */ - -div.sidebar { - margin: 0 0 0.5em 1em; - border: 1px solid #ddb; - padding: 7px 7px 0 7px; - background-color: #ffe; - width: 40%; - float: right; -} - -p.sidebar-title { - font-weight: bold; -} - -/* -- topics ---------------------------------------------------------------- */ - -div.topic { - border: 1px solid #ccc; - padding: 7px 7px 0 7px; - margin: 10px 0 10px 0; -} - -p.topic-title { - font-size: 1.1em; - font-weight: bold; - margin-top: 10px; -} - -/* -- admonitions ----------------------------------------------------------- */ - -div.admonition { - margin-top: 10px; - margin-bottom: 10px; - padding: 7px; -} - -div.admonition dt { - font-weight: bold; -} - -div.admonition dl { - margin-bottom: 0; -} - -p.admonition-title { - margin: 0px 10px 5px 0px; - font-weight: bold; -} - -div.body p.centered { - text-align: center; - margin-top: 25px; -} - -/* -- tables ---------------------------------------------------------------- */ - -table.docutils { - border: 0; - border-collapse: collapse; -} - -table.docutils td, table.docutils th { - padding: 1px 8px 1px 5px; - border-top: 0; - border-left: 0; - border-right: 0; - border-bottom: 1px solid #aaa; -} - -table.field-list td, table.field-list th { - border: 0 !important; -} - -table.footnote td, table.footnote th { - border: 0 !important; -} - -th { - text-align: left; - padding-right: 5px; -} - -table.citation { - border-left: solid 1px gray; - margin-left: 1px; -} - -table.citation td { - border-bottom: none; -} - -/* -- other body styles ----------------------------------------------------- */ - -ol.arabic { - list-style: decimal; -} - -ol.loweralpha { - list-style: lower-alpha; -} - -ol.upperalpha { - list-style: upper-alpha; -} - -ol.lowerroman { - list-style: lower-roman; -} - -ol.upperroman { - list-style: upper-roman; -} - -dl { - margin-bottom: 15px; -} - -dd p { - margin-top: 0px; -} - -dd ul, dd table { - margin-bottom: 10px; -} - -dd { - margin-top: 3px; - margin-bottom: 10px; - margin-left: 30px; -} - -dt:target, .highlighted { - background-color: #fbe54e; -} - -dl.glossary dt { - font-weight: bold; - font-size: 1.1em; -} - -.field-list ul { - margin: 0; - padding-left: 1em; -} - -.field-list p { - margin: 0; -} - -.refcount { - color: #060; -} - -.optional { - font-size: 1.3em; -} - -.versionmodified { - font-style: italic; -} - -.system-message { - background-color: #fda; - padding: 5px; - border: 3px solid red; -} - -.footnote:target { - background-color: #ffa; -} - -.line-block { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} - -.line-block .line-block { - margin-top: 0; - margin-bottom: 0; - margin-left: 1.5em; -} - -.guilabel, .menuselection { - font-family: sans-serif; -} - -.accelerator { - text-decoration: underline; -} - -.classifier { - font-style: oblique; -} - -/* -- code displays --------------------------------------------------------- */ - -pre { - overflow: auto; - overflow-y: hidden; /* fixes display issues on Chrome browsers */ -} - -td.linenos pre { - padding: 5px 0px; - border: 0; - background-color: transparent; - color: #aaa; -} - -table.highlighttable { - margin-left: 0.5em; -} - -table.highlighttable td { - padding: 0 0.5em 0 0.5em; -} - -tt.descname { - background-color: transparent; - font-weight: bold; - font-size: 1.2em; -} - -tt.descclassname { - background-color: transparent; -} - -tt.xref, a tt { - background-color: transparent; - font-weight: bold; -} - -h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { - background-color: transparent; -} - -.viewcode-link { - float: right; -} - -.viewcode-back { - float: right; - font-family: sans-serif; -} - -div.viewcode-block:target { - margin: -1px -10px; - padding: 0 10px; -} - -/* -- math display ---------------------------------------------------------- */ - -img.math { - vertical-align: middle; -} - -div.body div.math p { - text-align: center; -} - -span.eqno { - float: right; -} - -/* -- printout stylesheet --------------------------------------------------- */ - -@media print { - div.document, - div.documentwrapper, - div.bodywrapper { - margin: 0 !important; - width: 100%; - } - - div.sphinxsidebar, - div.related, - div.footer, - #top-link { - display: none; - } -} diff --git a/docs/_static/breadcrumb_background.png b/docs/_static/breadcrumb_background.png deleted file mode 100644 index 9b45910e0b984604c5e8b913f431bad172bdef53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 136 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{R!3HD)xzimdKI;Vst0CaOHKL7v# diff --git a/docs/_static/comment-bright.png b/docs/_static/comment-bright.png deleted file mode 100644 index 551517b8c83b76f734ff791f847829a760ad1903..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3500 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 A2LJ#7 diff --git a/docs/_static/comment.png b/docs/_static/comment.png deleted file mode 100644 index 92feb52b8824c6b0f59b658b1196c61de9162a95..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3445 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 Xn!ZpXD%P(H00000NkvXXu0mjf a.headerlink, -h2:hover > a.headerlink, -h3:hover > a.headerlink, -h4:hover > a.headerlink, -h5:hover > a.headerlink, -h6:hover > a.headerlink, -dt:hover > a.headerlink { - visibility: visible; -} - -div.body p.caption { - text-align: inherit; -} - -div.body td { - text-align: left; -} - -.field-list ul { - padding-left: 1em; -} - -.first { - margin-top: 0 !important; -} - -p.rubric { - margin-top: 30px; - font-weight: bold; -} - -/* -- sidebars -------------------------------------------------------------- */ - -/*div.sidebar { - margin: 0 0 0.5em 1em; - border: 1px solid #ddb; - padding: 7px 7px 0 7px; - background-color: #ffe; - width: 40%; - float: right; -} - -p.sidebar-title { - font-weight: bold; -} -*/ -/* -- topics ---------------------------------------------------------------- */ - -div.topic { - border: 1px solid #ccc; - padding: 7px 7px 0 7px; - margin: 10px 0 10px 0; -} - -p.topic-title { - font-size: 1.1em; - font-weight: bold; - margin-top: 10px; -} - -/* -- admonitions ----------------------------------------------------------- */ -.admonition { - border: 1px solid #a1a5a9; - background-color: #f7f7f7; - margin: 20px; - padding: 0px 8px 7px 9px; - text-align: left; -} -.warning { - background-color:#E8E8E8; - border:1px solid #111111; - margin:30px; -} -.admonition p { - font: 12px 'Lucida Grande', Geneva, Helvetica, Arial, sans-serif; - margin-top: 7px; - margin-bottom: 0px; -} - -div.admonition dt { - font-weight: bold; -} - -div.admonition dl { - margin-bottom: 0; -} - -p.admonition-title { - margin: 0px 10px 5px 0px; - font-weight: bold; - padding-top: 3px; -} - -div.body p.centered { - text-align: center; - margin-top: 25px; -} - -/* -- tables ---------------------------------------------------------------- */ - -table.docutils { - border-collapse: collapse; - border-top: 1px solid #919699; - border-left: 1px solid #919699; - border-right: 1px solid #919699; - font-size:12px; - padding:8px; - text-align:left; - vertical-align:top; -} - -table.docutils td, table.docutils th { - padding: 8px; - font-size: 12px; - text-align: left; - vertical-align: top; - border-bottom: 1px solid #919699; -} - -table.docutils th { - font-weight: bold; -} -/* This alternates colors in up to six table rows (light blue for odd, white for even)*/ -.docutils tr { - background: #F0F5F9; -} - -.docutils tr + tr { - background: #FFFFFF; -} - -.docutils tr + tr + tr { - background: #F0F5F9; -} - -.docutils tr + tr + tr + tr { - background: #FFFFFF; -} - -.docutils tr + tr + tr +tr + tr { - background: #F0F5F9; -} - -.docutils tr + tr + tr + tr + tr + tr { - background: #FFFFFF; -} - -.docutils tr + tr + tr + tr + tr + tr + tr { - background: #F0F5F9; -} - -table.footnote td, table.footnote th { - border: 0 !important; -} - -th { - text-align: left; - padding-right: 5px; -} - -/* -- other body styles ----------------------------------------------------- */ - -dl { - margin-bottom: 15px; - font-size: 12px; -} - -dd p { - margin-top: 0px; - font-size: 12px; -} - -dd ul, dd table { - margin-bottom: 10px; -} - -dd { - margin-top: 3px; - margin-bottom: 10px; - margin-left: 30px; - font-size: 12px; -} - -dt:target, .highlight { - background-color: #fbe54e; -} - -dl.glossary dt { - font-weight: bold; - font-size: 0.8em; -} - -dl.glossary dd { - font-size:12px; -} -.field-list ul { - vertical-align: top; - margin: 0; - padding-bottom: 0; - list-style: none inside; -} - -.field-list ul li { - margin-top: 0; -} - -.field-list p { - margin: 0; -} - -.refcount { - color: #060; -} - -.optional { - font-size: 1.3em; -} - -.versionmodified { - font-style: italic; -} - -.system-message { - background-color: #fda; - padding: 5px; - border: 3px solid red; -} - -.footnote:target { - background-color: #ffa -} - -/* -- code displays --------------------------------------------------------- */ - -pre { - overflow: auto; - background-color:#F1F5F9; - border:1px solid #C9D1D7; - border-spacing:0; - font-family:"Bitstream Vera Sans Mono",Monaco,"Lucida Console",Courier,Consolas,monospace; - font-size:11px; - padding: 10px; -} - -td.linenos { - width: 2em; -} - -td.linenos pre { - padding: 5px 0px; - border: 0; - background-color: transparent; - color: #aaa; -} - -td.code { - -} - -table.highlighttable { - margin-left: 0.5em; - width: 100%; -} - -table.highlighttable td { - padding: 0 0.5em 0 0.5em; -} -table.highlighttable td.linenos { - text-align: right; - width: 1.5em; - padding-right: 0; -} -tt { - font-family:"Bitstream Vera Sans Mono",Monaco,"Lucida Console",Courier,Consolas,monospace; -} - -tt.descname { - background-color: transparent; - font-weight: bold; - font-size: 1em; -} - -tt.descclassname { - background-color: transparent; -} - -tt.xref, a tt { - background-color: transparent; - font-weight: bold; -} - -h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { - background-color: transparent; -} - -/* -- math display ---------------------------------------------------------- */ - -img.math { - vertical-align: middle; -} - -div.body div.math p { - text-align: center; -} - -span.eqno { - float: right; -} - -/* -- printout stylesheet --------------------------------------------------- */ - -@media print { - div.document, - div.documentwrapper, - div.bodywrapper { - margin: 0; - width: 100%; - } - - div.sphinxsidebar, - div.related, - div.footer, - #top-link { - display: none; - } -} - -body { - font-family:'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; -} - -dl.class dt { - padding: 3px; -/* border-top: 2px solid #999;*/ -} - -em.property { - font-style: normal; -} - -dl.class dd p { - margin-top: 6px; -} - -dl.class dd dl.exception dt { - padding: 3px; - background-color: #FFD6D6; - border-top: none; -} - -dl.class dd dl.method dt { - padding: 3px; - background-color: #e9e9e9; - border-top: none; - -} - -dl.function dt { - padding: 3px; - border-top: 2px solid #999; -} - -ul { -list-style-image:none; -list-style-position:outside; -list-style-type:square; -margin:0 0 0 30px; -padding:0 0 12px 6px; -} -#docstitle { - height: 36px; - background-image: url(header_sm_mid.png); - left: 0; - top: 0; - position: absolute; - width: 100%; -} -#docstitle p { - padding:7px 0 0 45px; - margin: 0; - color: white; - text-shadow:0 1px 0 #787878; - background: transparent url(documentation.png) no-repeat scroll 10px 3px; - height: 36px; - font-size: 15px; -} -#header { -height:45px; -left:0; -position:absolute; -right:0; -top:36px; -z-index:900; -} - -#header h1 { -font-size:10pt; -margin:0; -padding:5px 0 0 10px; -text-shadow:0 1px 0 #D5D5D5; -white-space:nowrap; -} - -h1 { --x-system-font:none; -color:#000000; -font-family:'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; -font-size:30px; -font-size-adjust:none; -font-stretch:normal; -font-style:normal; -font-variant:normal; -font-weight:bold; -line-height:normal; -margin-bottom:25px; -margin-top:1em; -} - -.footer { -border-top:1px solid #DDDDDD; -clear:both; -padding-top:9px; -width:100%; -font-size:10px; -} - -p { --x-system-font:none; -font-family:'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; -font-size:12px; -font-size-adjust:none; -font-stretch:normal; -font-style:normal; -font-variant:normal; -font-weight:normal; -line-height:normal; -margin-bottom:10px; -margin-top:0; -} - -h2 { -border-bottom:1px solid #919699; -color:#000000; -font-size:24px; -margin-top:2.5em; -padding-bottom:2px; -} - -a:link:hover { -color:#093D92; -text-decoration:underline; -} - -a:link { -color:#093D92; -text-decoration:none; -} - - -ol { -list-style-position:outside; -list-style-type:decimal; -margin:0 0 0 30px; -padding:0 0 12px 6px; -} -li { -margin-top:7px; -font-family:'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; -font-size:12px; -font-size-adjust:none; -font-stretch:normal; -font-style:normal; -font-variant:normal; -font-weight:normal; -line-height:normal; -} -li > p { -display:inline; -} -li p { -margin-top:8px; -} \ No newline at end of file diff --git a/docs/_static/doctools.js b/docs/_static/doctools.js deleted file mode 100644 index 8b9bd2c..0000000 --- a/docs/_static/doctools.js +++ /dev/null @@ -1,247 +0,0 @@ -/* - * doctools.js - * ~~~~~~~~~~~ - * - * Sphinx JavaScript utilties for all documentation. - * - * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - -/** - * select a different prefix for underscore - */ -$u = _.noConflict(); - -/** - * make the code below compatible with browsers without - * an installed firebug like debugger -if (!window.console || !console.firebug) { - var names = ["log", "debug", "info", "warn", "error", "assert", "dir", - "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", - "profile", "profileEnd"]; - window.console = {}; - for (var i = 0; i < names.length; ++i) - window.console[names[i]] = function() {}; -} - */ - -/** - * small helper function to urldecode strings - */ -jQuery.urldecode = function(x) { - return decodeURIComponent(x).replace(/\+/g, ' '); -} - -/** - * small helper function to urlencode strings - */ -jQuery.urlencode = encodeURIComponent; - -/** - * This function returns the parsed url parameters of the - * current request. Multiple values per key are supported, - * it will always return arrays of strings for the value parts. - */ -jQuery.getQueryParameters = function(s) { - if (typeof s == 'undefined') - s = document.location.search; - var parts = s.substr(s.indexOf('?') + 1).split('&'); - var result = {}; - for (var i = 0; i < parts.length; i++) { - var tmp = parts[i].split('=', 2); - var key = jQuery.urldecode(tmp[0]); - var value = jQuery.urldecode(tmp[1]); - if (key in result) - result[key].push(value); - else - result[key] = [value]; - } - return result; -}; - -/** - * small function to check if an array contains - * a given item. - */ -jQuery.contains = function(arr, item) { - for (var i = 0; i < arr.length; i++) { - if (arr[i] == item) - return true; - } - return false; -}; - -/** - * highlight a given string on a jquery object by wrapping it in - * span elements with the given class name. - */ -jQuery.fn.highlightText = function(text, className) { - function highlight(node) { - if (node.nodeType == 3) { - var val = node.nodeValue; - var pos = val.toLowerCase().indexOf(text); - if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) { - var span = document.createElement("span"); - span.className = className; - span.appendChild(document.createTextNode(val.substr(pos, text.length))); - node.parentNode.insertBefore(span, node.parentNode.insertBefore( - document.createTextNode(val.substr(pos + text.length)), - node.nextSibling)); - node.nodeValue = val.substr(0, pos); - } - } - else if (!jQuery(node).is("button, select, textarea")) { - jQuery.each(node.childNodes, function() { - highlight(this); - }); - } - } - return this.each(function() { - highlight(this); - }); -}; - -/** - * Small JavaScript module for the documentation. - */ -var Documentation = { - - init : function() { - this.fixFirefoxAnchorBug(); - this.highlightSearchWords(); - this.initIndexTable(); - }, - - /** - * i18n support - */ - TRANSLATIONS : {}, - PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; }, - LOCALE : 'unknown', - - // gettext and ngettext don't access this so that the functions - // can safely bound to a different name (_ = Documentation.gettext) - gettext : function(string) { - var translated = Documentation.TRANSLATIONS[string]; - if (typeof translated == 'undefined') - return string; - return (typeof translated == 'string') ? translated : translated[0]; - }, - - ngettext : function(singular, plural, n) { - var translated = Documentation.TRANSLATIONS[singular]; - if (typeof translated == 'undefined') - return (n == 1) ? singular : plural; - return translated[Documentation.PLURALEXPR(n)]; - }, - - addTranslations : function(catalog) { - for (var key in catalog.messages) - this.TRANSLATIONS[key] = catalog.messages[key]; - this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); - this.LOCALE = catalog.locale; - }, - - /** - * add context elements like header anchor links - */ - addContextElements : function() { - $('div[id] > :header:first').each(function() { - $('\u00B6'). - attr('href', '#' + this.id). - attr('title', _('Permalink to this headline')). - appendTo(this); - }); - $('dt[id]').each(function() { - $('\u00B6'). - attr('href', '#' + this.id). - attr('title', _('Permalink to this definition')). - appendTo(this); - }); - }, - - /** - * workaround a firefox stupidity - */ - fixFirefoxAnchorBug : function() { - if (document.location.hash && $.browser.mozilla) - window.setTimeout(function() { - document.location.href += ''; - }, 10); - }, - - /** - * highlight the search words provided in the url in the text - */ - highlightSearchWords : function() { - var params = $.getQueryParameters(); - var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; - if (terms.length) { - var body = $('div.body'); - window.setTimeout(function() { - $.each(terms, function() { - body.highlightText(this.toLowerCase(), 'highlighted'); - }); - }, 10); - $('') - .appendTo($('.sidebar .this-page-menu')); - } - }, - - /** - * init the domain index toggle buttons - */ - initIndexTable : function() { - var togglers = $('img.toggler').click(function() { - var src = $(this).attr('src'); - var idnum = $(this).attr('id').substr(7); - $('tr.cg-' + idnum).toggle(); - if (src.substr(-9) == 'minus.png') - $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); - else - $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); - }).css('display', ''); - if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { - togglers.click(); - } - }, - - /** - * helper function to hide the search marks again - */ - hideSearchWords : function() { - $('.sidebar .this-page-menu li.highlight-link').fadeOut(300); - $('span.highlighted').removeClass('highlighted'); - }, - - /** - * make the url absolute - */ - makeURL : function(relativeURL) { - return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; - }, - - /** - * get the current relative url - */ - getCurrentURL : function() { - var path = document.location.pathname; - var parts = path.split(/\//); - $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { - if (this == '..') - parts.pop(); - }); - var url = parts.join('/'); - return path.substring(url.lastIndexOf('/') + 1, path.length - 1); - } -}; - -// quick alias for translations -_ = Documentation.gettext; - -$(document).ready(function() { - Documentation.init(); -}); diff --git a/docs/_static/documentation.png b/docs/_static/documentation.png deleted file mode 100644 index f0d334b57a69d1c49ce833d2d3536ececbf31c2c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 412 zcmV;N0b~A&P)V|5Xcvp(%M!Kgji)eD=qwh zg{)PY6mE9sSonm;^7iSXc>&$i3^Q|Q&b@P+33{MD0iFXj;0!p8h+n&qyCPF6JQV6iHPIexmn;9Fb7Nl<3Jl|0!P3BP>+aqQH5_(N#jt7nHQ%jqyU$Fz7$7E>_1_sYph)S z-zvU;;z5rq6AzyH?u!RKu1s9{Qx9ijQN?HKDbR|DG2kh;m|&6k2-pJlBccKP<>HGw z4ZH?E0E=DsG=W{94m5xVzyvT4ECVxzcJ)j45&Nn>F3VIMR^O(SeyAPwyZWLeeq8;O zQaa2W-}0Lq>ROqwM*>TI#Mji%>SliNQ9sg~pgye1RmeF;a#_fxJ%6YG0000}Z23@f-Ava~9&<9T!#}JFtXD=!G zGdl{fK6ro2OGiOl+hKvH6i=D3%%Y^j`yIkRn!8O>@bG)IQR0{Kf+mxNd=_WScA8u_ z3;8(7x2){m9`nt+U(Nab&1G)!{`SPVpDX$w8McLTzAJ39wprG3p4XLq$06M`%}2Yk zRPPsbES*dnYm1wkGL;iioAUB*Or2kz6(-M_r_#Me-`{mj$Z%( diff --git a/docs/_static/down.png b/docs/_static/down.png deleted file mode 100644 index 3003a88770de3977d47a2ba69893436a2860f9e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 363 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|*pj^6U4S$Y z{B+)352QE?JR*yM+OLB!qm#z$3ZNi+iKnkC`z>}xaV3tUZ$qnrLa#kt978NlpS`ru z&)HFc^}^>{UOEce+71h5nn>6&w6A!ieNbu1wh)UGh{8~et^#oZ1# z>T7oM=FZ~xXWnTo{qnXm$ZLOlqGswI_m2{XwVK)IJmBjW{J3-B3x@C=M{ShWt#fYS9M?R;8K$~YwlIqwf>VA7q=YKcwf2DS4Zj5inDKXXB1zl=(YO3ST6~rDq)&z z*o>z)=hxrfG-cDBW0G$!?6{M<$@{_4{m1o%Ub!naEtn|@^frU1tDnm{r-UW|!^@B8 diff --git a/docs/_static/file.png b/docs/_static/file.png deleted file mode 100644 index d18082e397e7e54f20721af768c4c2983258f1b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 392 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP$HyOL$D9)yc9|lc|nKf<9@eUiWd>3GuTC!a5vdfWYEazjncPj5ZQX%+1 zt8B*4=d)!cdDz4wr^#OMYfqGz$1LDFF>|#>*O?AGil(WEs?wLLy{Gj2J_@opDm%`dlax3yA*@*N$G&*ukFv>P8+2CBWO(qz zD0k1@kN>hhb1_6`&wrCswzINE(evt-5C1B^STi2@PmdKI;Vst0PQB6!2kdN diff --git a/docs/_static/header_sm_mid.png b/docs/_static/header_sm_mid.png deleted file mode 100644 index dce5a40e98bc982ba4733bb0797230cc98a69f01..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^>_Du-!2~2vacq|XQj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>JiX1&%978H@CGnhJm3n|dhv)zQWWm4R-|L56tdDT{|2W{c z`088rM^^v!-XmRb(=9yy&tL0^Shqb)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, -Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& -(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, -a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== -"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, -function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
      a"; -var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, -parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= -false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= -s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, -applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; -else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, -a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== -w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, -cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= -c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); -a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, -function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); -k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), -C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= -e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& -f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; -if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", -e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, -"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, -d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, -e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); -t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| -g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, -CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, -g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, -text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, -setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= -h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== -"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, -h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& -q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; -if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

      ";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); -(function(){var g=s.createElement("div");g.innerHTML="
      ";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: -function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= -{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== -"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", -d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? -a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== -1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
      ","
      "],thead:[1,"","
      "],tr:[2,"","
      "],td:[3,"","
      "],col:[2,"","
      "],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
      ","
      "];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= -c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, -wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, -prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, -this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); -return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, -""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); -return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", -""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= -c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? -c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= -function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= -Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, -"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= -a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= -a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== -"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
      ").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, -serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), -function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, -global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& -e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? -"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== -false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= -false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", -c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| -d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); -g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== -1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== -"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; -if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== -"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| -c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; -this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= -this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, -e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
      "; -a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); -c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, -d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- -f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": -"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in -e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); diff --git a/docs/_static/minus.png b/docs/_static/minus.png deleted file mode 100644 index da1c5620d10c047525a467a425abe9ff5269cfc2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 199 zcmeAS@N?(olHy`uVBq!ia0vp^+#t-s1SHkYJtzcHoCO|{#XvD(5N2eUHAey{$X?>< z>&kweokM_|(Po{+Q=kw>iEBiObAE1aYF-J$w=>iB1I2R$WLpMkF=>bh=@O1TaS?83{1OVknK< z>&kweokM`jkU7Va11Q8%;u=xnoS&PUnpeW`?aZ|OK(QcC7sn8Z%gHvy&v=;Q4jejg zV8NnAO`-4Z@2~&zopr02WF_WB>pF diff --git a/docs/_static/pygments.css b/docs/_static/pygments.css deleted file mode 100644 index 1a14f2a..0000000 --- a/docs/_static/pygments.css +++ /dev/null @@ -1,62 +0,0 @@ -.highlight .hll { background-color: #ffffcc } -.highlight { background: #eeffcc; } -.highlight .c { color: #408090; font-style: italic } /* Comment */ -.highlight .err { border: 1px solid #FF0000 } /* Error */ -.highlight .k { color: #007020; font-weight: bold } /* Keyword */ -.highlight .o { color: #666666 } /* Operator */ -.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ -.highlight .cp { color: #007020 } /* Comment.Preproc */ -.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ -.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ -.highlight .gd { color: #A00000 } /* Generic.Deleted */ -.highlight .ge { font-style: italic } /* Generic.Emph */ -.highlight .gr { color: #FF0000 } /* Generic.Error */ -.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ -.highlight .gi { color: #00A000 } /* Generic.Inserted */ -.highlight .go { color: #303030 } /* Generic.Output */ -.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ -.highlight .gs { font-weight: bold } /* Generic.Strong */ -.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ -.highlight .gt { color: #0040D0 } /* Generic.Traceback */ -.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ -.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ -.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ -.highlight .kp { color: #007020 } /* Keyword.Pseudo */ -.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ -.highlight .kt { color: #902000 } /* Keyword.Type */ -.highlight .m { color: #208050 } /* Literal.Number */ -.highlight .s { color: #4070a0 } /* Literal.String */ -.highlight .na { color: #4070a0 } /* Name.Attribute */ -.highlight .nb { color: #007020 } /* Name.Builtin */ -.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ -.highlight .no { color: #60add5 } /* Name.Constant */ -.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ -.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ -.highlight .ne { color: #007020 } /* Name.Exception */ -.highlight .nf { color: #06287e } /* Name.Function */ -.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ -.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ -.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ -.highlight .nv { color: #bb60d5 } /* Name.Variable */ -.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ -.highlight .w { color: #bbbbbb } /* Text.Whitespace */ -.highlight .mf { color: #208050 } /* Literal.Number.Float */ -.highlight .mh { color: #208050 } /* Literal.Number.Hex */ -.highlight .mi { color: #208050 } /* Literal.Number.Integer */ -.highlight .mo { color: #208050 } /* Literal.Number.Oct */ -.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ -.highlight .sc { color: #4070a0 } /* Literal.String.Char */ -.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ -.highlight .s2 { color: #4070a0 } /* Literal.String.Double */ -.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ -.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ -.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ -.highlight .sx { color: #c65d09 } /* Literal.String.Other */ -.highlight .sr { color: #235388 } /* Literal.String.Regex */ -.highlight .s1 { color: #4070a0 } /* Literal.String.Single */ -.highlight .ss { color: #517918 } /* Literal.String.Symbol */ -.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ -.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ -.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ -.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ -.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/docs/_static/scrn1.png b/docs/_static/scrn1.png deleted file mode 100644 index 6499b3cf760c9d065408842221161d014fb7a073..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108046 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�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 ZGnh*?r5D zK?F?^1PO^?Wsw#|C6=?-W^S0-j0f&L_uPHXI&1H}_EzfkIyH{f)m7!>^Kb(vi>SKQho4r_&jBxm=pvZl})9PBIt_?E_{q z8Rhi!G*BoMepoD)w<9AXn%nIro6RO*nx+X@JAfKq7Z(@yVzKz$>-D}L9UUc)$3tCR zUDVOhL2$KQcLi`|Wko$YI{Ltj-i1OT>h0|%W=ZTmEiW(A?(Qye7|8GU6YP;lgnD{< zUIsirKXhlgU1Mx%0h^H4ePZyXK>X88d?&bEAykB5T^5)*LGsP|MCH)U&5g`hV+;=uzbGS( zZ^~4w)sTK8m`+Sg5SJcpZEZ<1ng?PyGc!XRs%JLC{QUeYHpIHSyH#DpX0ut6V6|F_ zlSbFq*ThPo$;nCL+9s|l(I?i3?~~F?rBbh1Q&~=c4FGTjY?-yVdUtn6wOUPLh%9qe zQ8JmNrGMRELr%h4@nWTM!3_ZyKtc-)G|T1avEu822WQ%mvv4FO#qs` BFGc_W diff --git a/docs/_static/searchfield_rightcap.png b/docs/_static/searchfield_rightcap.png deleted file mode 100644 index 8e13620ecbc56b3464c48d6cd09bf1337e1c33a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 530 zcmV+t0`2{YP)`}SW{%?kjooesx~_vP%P<%W?AdJgh{{)$N=4@w2Hn_CKTAY65m^iR+I*Mbk6^ z``^NHsdV!wP>EqmHX4oOX0v%l>il0RsWXek!jL5C0oS5;;H%I;7qQ7?Vs$#5r$(c3 zLKkVc?jhG;Dl&tEW>67q;r<#eHuX!@@AqBfuGeb~jqr-VJ=U*XtycBJC;bR809Q3H UB&DjC!~g&Q07*qoM6N<$f;HIhQUCw| diff --git a/docs/_static/searchtools.js b/docs/_static/searchtools.js deleted file mode 100644 index dae92b5..0000000 --- a/docs/_static/searchtools.js +++ /dev/null @@ -1,518 +0,0 @@ -/* - * searchtools.js - * ~~~~~~~~~~~~~~ - * - * Sphinx JavaScript utilties for the full-text search. - * - * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - -/** - * helper function to return a node containing the - * search summary for a given text. keywords is a list - * of stemmed words, hlwords is the list of normal, unstemmed - * words. the first one is used to find the occurance, the - * latter for highlighting it. - */ - -jQuery.makeSearchSummary = function(text, keywords, hlwords) { - var textLower = text.toLowerCase(); - var start = 0; - $.each(keywords, function() { - var i = textLower.indexOf(this.toLowerCase()); - if (i > -1) - start = i; - }); - start = Math.max(start - 120, 0); - var excerpt = ((start > 0) ? '...' : '') + - $.trim(text.substr(start, 240)) + - ((start + 240 - text.length) ? '...' : ''); - var rv = $('
      ').text(excerpt); - $.each(hlwords, function() { - rv = rv.highlightText(this, 'highlighted'); - }); - return rv; -} - -/** - * Porter Stemmer - */ -var PorterStemmer = function() { - - var step2list = { - ational: 'ate', - tional: 'tion', - enci: 'ence', - anci: 'ance', - izer: 'ize', - bli: 'ble', - alli: 'al', - entli: 'ent', - eli: 'e', - ousli: 'ous', - ization: 'ize', - ation: 'ate', - ator: 'ate', - alism: 'al', - iveness: 'ive', - fulness: 'ful', - ousness: 'ous', - aliti: 'al', - iviti: 'ive', - biliti: 'ble', - logi: 'log' - }; - - var step3list = { - icate: 'ic', - ative: '', - alize: 'al', - iciti: 'ic', - ical: 'ic', - ful: '', - ness: '' - }; - - var c = "[^aeiou]"; // consonant - var v = "[aeiouy]"; // vowel - var C = c + "[^aeiouy]*"; // consonant sequence - var V = v + "[aeiou]*"; // vowel sequence - - var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 - var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 - var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 - var s_v = "^(" + C + ")?" + v; // vowel in stem - - this.stemWord = function (w) { - var stem; - var suffix; - var firstch; - var origword = w; - - if (w.length < 3) - return w; - - var re; - var re2; - var re3; - var re4; - - firstch = w.substr(0,1); - if (firstch == "y") - w = firstch.toUpperCase() + w.substr(1); - - // Step 1a - re = /^(.+?)(ss|i)es$/; - re2 = /^(.+?)([^s])s$/; - - if (re.test(w)) - w = w.replace(re,"$1$2"); - else if (re2.test(w)) - w = w.replace(re2,"$1$2"); - - // Step 1b - re = /^(.+?)eed$/; - re2 = /^(.+?)(ed|ing)$/; - if (re.test(w)) { - var fp = re.exec(w); - re = new RegExp(mgr0); - if (re.test(fp[1])) { - re = /.$/; - w = w.replace(re,""); - } - } - else if (re2.test(w)) { - var fp = re2.exec(w); - stem = fp[1]; - re2 = new RegExp(s_v); - if (re2.test(stem)) { - w = stem; - re2 = /(at|bl|iz)$/; - re3 = new RegExp("([^aeiouylsz])\\1$"); - re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); - if (re2.test(w)) - w = w + "e"; - else if (re3.test(w)) { - re = /.$/; - w = w.replace(re,""); - } - else if (re4.test(w)) - w = w + "e"; - } - } - - // Step 1c - re = /^(.+?)y$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(s_v); - if (re.test(stem)) - w = stem + "i"; - } - - // Step 2 - re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - suffix = fp[2]; - re = new RegExp(mgr0); - if (re.test(stem)) - w = stem + step2list[suffix]; - } - - // Step 3 - re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - suffix = fp[2]; - re = new RegExp(mgr0); - if (re.test(stem)) - w = stem + step3list[suffix]; - } - - // Step 4 - re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; - re2 = /^(.+?)(s|t)(ion)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(mgr1); - if (re.test(stem)) - w = stem; - } - else if (re2.test(w)) { - var fp = re2.exec(w); - stem = fp[1] + fp[2]; - re2 = new RegExp(mgr1); - if (re2.test(stem)) - w = stem; - } - - // Step 5 - re = /^(.+?)e$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(mgr1); - re2 = new RegExp(meq1); - re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); - if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) - w = stem; - } - re = /ll$/; - re2 = new RegExp(mgr1); - if (re.test(w) && re2.test(w)) { - re = /.$/; - w = w.replace(re,""); - } - - // and turn initial Y back to y - if (firstch == "y") - w = firstch.toLowerCase() + w.substr(1); - return w; - } -} - - -/** - * Search Module - */ -var Search = { - - _index : null, - _queued_query : null, - _pulse_status : -1, - - init : function() { - var params = $.getQueryParameters(); - if (params.q) { - var query = params.q[0]; - $('input[name="q"]')[0].value = query; - this.performSearch(query); - } - }, - - loadIndex : function(url) { - $.ajax({type: "GET", url: url, data: null, success: null, - dataType: "script", cache: true}); - }, - - setIndex : function(index) { - var q; - this._index = index; - if ((q = this._queued_query) !== null) { - this._queued_query = null; - Search.query(q); - } - }, - - hasIndex : function() { - return this._index !== null; - }, - - deferQuery : function(query) { - this._queued_query = query; - }, - - stopPulse : function() { - this._pulse_status = 0; - }, - - startPulse : function() { - if (this._pulse_status >= 0) - return; - function pulse() { - Search._pulse_status = (Search._pulse_status + 1) % 4; - var dotString = ''; - for (var i = 0; i < Search._pulse_status; i++) - dotString += '.'; - Search.dots.text(dotString); - if (Search._pulse_status > -1) - window.setTimeout(pulse, 500); - }; - pulse(); - }, - - /** - * perform a search for something - */ - performSearch : function(query) { - // create the required interface elements - this.out = $('#search-results'); - this.title = $('

      ' + _('Searching') + '

      ').appendTo(this.out); - this.dots = $('').appendTo(this.title); - this.status = $('

      ').appendTo(this.out); - this.output = $('
      - - - - \ No newline at end of file diff --git a/docs/custom_categories.html b/docs/custom_categories.html deleted file mode 100644 index 34726a3..0000000 --- a/docs/custom_categories.html +++ /dev/null @@ -1,341 +0,0 @@ - - - - - - - - Creating Custom Categories — Django Categories v1.1 documentation - - - - - - - - - - - -
      -

      Django Categories v1.1 documentation

      -
      - - -
      -
      - - - -

      This Page

      - - - -
      -
      - - - -
      -
      -
      -
      - -
      -

      Creating Custom Categories¶

      -

      Django Categories isn’t just for using a single category model. It allows you to create your own custom category-like models with as little or much customization as you need.

      -
      -

      Name only¶

      -

      For many cases, you want a simple user-managed lookup table. You can do this with just a little bit of code. The resulting model will include name, slug and active fields and a hierarchical admin.

      -
        -
      1. Create a model that subclasses CategoryBase

        -
        1
        -2
        -3
        -4
        -5
        -6
        -7
        -8
        -9
        from categories.models import CategoryBase
        -
        -class SimpleCategory(CategoryBase):
        -    """
        -    A simple of catgorizing example
        -    """
        -    
        -    class Meta:
        -        verbose_name_plural = 'simple categories'
        -
        -
        -
      2. -
      3. Create a subclass of CategoryBaseAdmin.

        -
         1
        - 2
        - 3
        - 4
        - 5
        - 6
        - 7
        - 8
        - 9
        -10
        from django.contrib import admin
        -
        -from categories.admin import CategoryBaseAdmin
        -
        -from .models import SimpleCategory
        -
        -class SimpleCategoryAdmin(CategoryBaseAdmin):
        -    pass
        -
        -admin.site.register(SimpleCategory, SimpleCategoryAdmin)
        -
        -
        -
      4. -
      5. Register your model and custom model admin class.

        -
      6. -
      -
      -
      -

      Name and other data¶

      -

      Sometimes you need more functionality, such as extra metadata and custom functions. The Category model in this package does this.

      -
        -
      1. Create a model that subclasses CategoryBase as above.

        -
      2. -
      3. Add new fields to the model. The Category model adds these extra fields.

        -
         1
        - 2
        - 3
        - 4
        - 5
        - 6
        - 7
        - 8
        - 9
        -10
        -11
        -12
        -13
        -14
        -15
        -16
        -17
        -18
        -19
        -20
        -21
        -22
        -23
        -24
        -25
        -26
        -27
        -28
        -29
        class Category(CategoryBase):
        -    thumbnail = models.FileField(
        -        upload_to=THUMBNAIL_UPLOAD_PATH, 
        -        null=True, blank=True,
        -        storage=STORAGE(),)
        -    thumbnail_width = models.IntegerField(blank=True, null=True)
        -    thumbnail_height = models.IntegerField(blank=True, null=True)
        -    order = models.IntegerField(default=0)
        -    alternate_title = models.CharField(
        -        blank=True,
        -        default="",
        -        max_length=100,
        -        help_text="An alternative title to use on pages with this category.")
        -    alternate_url = models.CharField(
        -        blank=True, 
        -        max_length=200, 
        -        help_text="An alternative URL to use instead of the one derived from "
        -                  "the category hierarchy.")
        -    description = models.TextField(blank=True, null=True)
        -    meta_keywords = models.CharField(
        -        blank=True,
        -        default="",
        -        max_length=255,
        -        help_text="Comma-separated keywords for search engines.")
        -    meta_extra = models.TextField(
        -        blank=True,
        -        default="",
        -        help_text="(Advanced) Any additional HTML to be placed verbatim "
        -                  "in the &lt;head&gt;")
        -
        -
        -
      4. -
      5. Add new methods to the model. For example, the Category model adds several new methods, including overriding the save() method.

        -
         1
        - 2
        - 3
        - 4
        - 5
        - 6
        - 7
        - 8
        - 9
        -10
        -11
        -12
        -13
        -14
        -15
        def save(self, *args, **kwargs):
        -    if self.thumbnail:
        -        from django.core.files.images import get_image_dimensions
        -        import django
        -        if django.VERSION[1] < 2:
        -            width, height = get_image_dimensions(self.thumbnail.file)
        -        else:
        -            width, height = get_image_dimensions(self.thumbnail.file, close=True)
        -    else:
        -        width, height = None, None
        -    
        -    self.thumbnail_width = width
        -    self.thumbnail_height = height
        -    
        -    super(Category, self).save(*args, **kwargs)
        -
        -
        -
      6. -
      7. Alter Meta or MPTTMeta class. Either of these inner classes can be overridden, however your Meta class should inherit CategoryBase.Meta. Options for Meta are in the Django-MPTT docs.

        -
        1
        -2
        -3
        -4
        -5
        class Meta(CategoryBase.Meta):
        -    verbose_name_plural = 'categories'
        -
        -class MPTTMeta:
        -    order_insertion_by = ('order', 'name')
        -
        -
        -
      8. -
      9. For the admin, you must create a form that subclasses CategoryBaseAdminForm and at least sets the Meta.model attribute. You can also alter the form fields and cleaning methods, as Category does.

        -
        1
        -2
        -3
        -4
        -5
        -6
        -7
        -8
        -9
        class CategoryAdminForm(CategoryBaseAdminForm):
        -    class Meta:
        -        model = Category
        -    
        -    def clean_alternate_title(self):
        -        if self.instance is None or not self.cleaned_data['alternate_title']:
        -            return self.cleaned_data['name']
        -        else:
        -            return self.cleaned_data['alternate_title']
        -
        -
        -
      10. -
      11. Next you must subclass CategoryBaseAdmin and assign the form attribute the form class created above. You can alter any other attributes as necessary.

        -
         1
        - 2
        - 3
        - 4
        - 5
        - 6
        - 7
        - 8
        - 9
        -10
        -11
        -12
        -13
        -14
        -15
        -16
        -17
        class CategoryAdmin(CategoryBaseAdmin):
        -    form = CategoryAdminForm
        -    list_display = ('name', 'alternate_title', 'active')
        -    fieldsets = (
        -        (None, {
        -            'fields': ('parent', 'name', 'thumbnail', 'active')
        -        }),
        -        ('Meta Data', {
        -            'fields': ('alternate_title', 'alternate_url', 'description', 
        -                        'meta_keywords', 'meta_extra'),
        -            'classes': ('collapse',),
        -        }),
        -        ('Advanced', {
        -            'fields': ('order', 'slug'),
        -            'classes': ('collapse',),
        -        }),
        -    )
        -
        -
        -
      12. -
      -
      -
      - - -
      -
      -
      - -
      -
      - - - - \ No newline at end of file diff --git a/docs/genindex.html b/docs/genindex.html deleted file mode 100644 index a0f5ab9..0000000 --- a/docs/genindex.html +++ /dev/null @@ -1,199 +0,0 @@ - - - - - - - - Index — Django Categories v1.1 documentation - - - - - - - - - -
      -

      Django Categories v1.1 documentation

      -
      - - -
      -
      - - - - - - - - -
      -
      - - - - - - - - \ No newline at end of file diff --git a/docs/getting_started.html b/docs/getting_started.html deleted file mode 100644 index bb2ac50..0000000 --- a/docs/getting_started.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - - - Getting Started — Django Categories v1.1 documentation - - - - - - - - - - - -
      -

      Django Categories v1.1 documentation

      -
      - - -
      -
      - - - -

      This Page

      - - - -
      -
      - - - -
      -
      -
      -
      - -
      -

      Getting Started¶

      -

      You can use Django Categories in two ways:

      -
        -
      1. As storage for one tree of categories, using the Category model:

        -
        Top Category 1
        -  Subcategory 1-1
        -    Subcategory 1-2
        -      subcategory 1-2-1
        -Top Category 2
        -  Subcategory 2-1
        -
        -
      2. -
      3. As the basis for several custom categories (see Creating Custom Categories), e.g. a MusicGenre model

        -
        MusicGenre 1
        -  MusicSubGenre 1-1
        -  MusicSubGenre 1-2
        -    MusicSubGenre 1-2-1
        -MusicGenre 2
        -  MusicSubGenre 2-1
        -
        -

        and a Subject model

        -
        Subject 1
        -  Discipline 1-1
        -  Discipline 1-2
        -    SubDiscipline 1-2-1
        -Subject 2
        -  Discipline 2-1
        -
        -
      4. -
      -
      -

      Connecting your model with Django-Categories¶

      -

      There are two ways to add Category fields to an application. If you are in control of the code (it’s your application) or you are willing to take control of the code (fork someone else’s app) you can make a Hard Coded Connection.

      -

      For 3rd-party apps or even your own apps that you don’t wish to add Django-Categories as a dependency, you can configure a Lazy Connection.

      -
      -

      Hard Coded Connection¶

      -

      Hard coded connections are done in the exact same way you handle any other foreign key or many-to-many relations to a model.

      -
      from django.db import models
      -
      -class MyModel(models.Model):
      -    name = models.CharField(max_length=100)
      -    category = models.ForeignKey('categories.Category')
      -
      -
      -

      Don’t forget to add the field or fields to your ModelAdmin class as well.

      -
      -
      -

      Lazy Connection¶

      -

      Lazy connections are done through configuring Django Categories in the project’s settings.py file. When the project starts up, the configured fields are dynamically added to the configured models and admin.

      -

      If you do this before you have created the database (before you ran manage.py syncdb), the fields will also be in the tables. If you do this after you have already created all the tables, you can run manage.py add_category_fields to create the fields (this requires Django South to be installed).

      -

      You add a many-to-one or many-to-many relationship with Django Categories using the FK_REGISTRY and M2M_REGISTRY settings respectively. For more information see Registering Models.

      -
      -
      -
      - - -
      -
      -
      - -
      -
      - - - - \ No newline at end of file diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 092b98f..0000000 --- a/docs/index.html +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - Django Categories v 1.1 — Django Categories v1.1 documentation - - - - - - - - - - -
      -

      Django Categories v1.1 documentation

      -
      - - -
      -
      - - - -

      This Page

      - - - -
      -
      - - - -
      -
      -
      -
      - -
      -

      Django Categories v 1.1¶

      -

      Django Categories grew out of our need to provide a basic hierarchical taxonomy management system that multiple applications could use independently or in concert.

      -

      As a news site, our stories, photos, and other content get divided into “sections” and we wanted all the apps to use the same set of sections. As our needs grew, the Django Categories grew in the functionality it gave to category handling within web pages.

      -
      -

      New in 1.1¶

      -
        -
      • Fixed a cosmetic bug in the Django 1.4 admin. Action checkboxes now only appear once.
      • -
      • Template tags are refactored to allow easy use of any model derived from CategoryBase.
      • -
      • Improved test suite.
      • -
      • Improved some of the documentation.
      • -
      -
      - -
      -

      Indices and tables¶

      - -
      -
      - - -
      -
      -
      - -
      -
      - - - - \ No newline at end of file diff --git a/docs/installation.html b/docs/installation.html deleted file mode 100644 index b97eb78..0000000 --- a/docs/installation.html +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - - - Installation — Django Categories v1.1 documentation - - - - - - - - - - - -
      -

      Django Categories v1.1 documentation

      -
      - - -
      -
      - - - -

      This Page

      - - - -
      -
      - - - -
      -
      -
      -
      - -
      -

      Installation¶

      -
      -

      To use the Category model¶

      -
        -
      1. Install django-categories:

        -
        pip install django-categories
        -
        -
      2. -
      3. Add "categories" and "categories.editor" to your INSTALLED_APPS list in your project’s settings.py file.

        -
        INSTALLED_APPS = [
        -    # ...
        -    "categories",
        -    "categories.editor",
        -]
        -
        -
        -
      4. -
      5. Run ./manage.py syncdb (or ./manage.py migrate categories if you are using South)

        -
      6. -
      -
      -
      -

      To only subclass CategoryBase¶

      -

      If you are going to create your own models using CategoryBase, (see Creating Custom Categories) you’ll need a few different steps.

      -
        -
      1. Install django-categories:

        -
        pip install django-categories
        -
        -
      2. -
      3. Add "categories.editor" to your INSTALLED_APPS list in your project’s settings.py file.

        -
        INSTALLED_APPS = [
        -    # ...
        -    "categories.editor",
        -]
        -
        -
        -
      4. -
      5. Create your own models.

        -
      6. -
      -
      -
      - - -
      -
      -
      - -
      -
      - - - - \ No newline at end of file diff --git a/docs/objects.inv b/docs/objects.inv deleted file mode 100644 index faaf6d663a6534c614d72ad39ae07057eeed00a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 982 zcmV;{11bC?AX9K?X>NERX>N99Zgg*Qc_4OWa&u{KZXhxWBOp+6Z)#;@bUGkJYGH0? zZy-ZqbY*96a%p9A3L_v^WpZ_Ab7^j8AbM>if58Ky94UINHqbmV9ydbsDdOJ?eLE z(pc+jROdg!Gn9#uh2;mMh8^Ewn8SRJensoaYW{P>?^kiqm76u?9<7Xz;i7egliC%O z>age5fG(A!ssdGF*o7UCodDPI{Vm_DqUAcCZ>Fn=iWra}ovLh#?@IcOyOpui9GM#t zN8S>WC9Ewr_bUMwwoqb_f}#GQ>bYO7F>&QQEte00bPC3zsLpaY=5eftn~{~$L{|E3 ztZgH45Si3Nl~rL_g;`B+=WEIikG?ME%OJbXc(ubEhw%}DwTQ*_f>(^I-$4QiRo=0(qdLn2cdG zInh;RtDnGiwc#g`1`7Tj$MvE^^t&*ob-(|*QFAC%4uTgjROQ{csi4e5Pr9)`2!UtU zxklbhhBB4K_^}Dhv#?hz{UHh=CH=^3&S+cM-xjo?@FtX@FHUV|EpA=^32FfzX^7q= z3d%BkrG{PQc%{%Gi3CzaQs69=K`?6 zYP32<{m13UV}06yr2C8)f;D6#pzV0tJvq?spsO}IFV!~(7GT^5!uT}hMxePY%5hq} z0!4vnTKUhb3$^rw#}~TtC2H=@x6&&7uYO2T?o)fAINXH2KpgY|aj81o*cpD}KS*Y* E0ADQTCIA2c diff --git a/docs/reference/index.html b/docs/reference/index.html deleted file mode 100644 index 90a267b..0000000 --- a/docs/reference/index.html +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - Reference — Django Categories v1.1 documentation - - - - - - - - - - - -
      -

      Django Categories v1.1 documentation

      -
      - - -
      -
      - - - -

      This Page

      - - - -
      -
      - - - - - - - - \ No newline at end of file diff --git a/docs/reference/management_commands.html b/docs/reference/management_commands.html deleted file mode 100644 index be65f11..0000000 --- a/docs/reference/management_commands.html +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - - - Management Commands — Django Categories v1.1 documentation - - - - - - - - - - - - -
      -

      Django Categories v1.1 documentation

      -
      - - -
      -
      - - - -

      This Page

      - - - -
      -
      - - - -
      -
      -
      -
      - -
      -

      Management Commands¶

      -
      -

      import_categories¶

      -

      Usage: ./manage.py import_categories /path/to/file.txt [/path/to/file2.txt]

      -

      Imports category tree(s) from a file. Sub categories must be indented by the same multiple of spaces or tabs. The first line in the file cannot start with a space or tab and you can’t mix spaces and tabs.

      -
      -
      -

      add_category_fields¶

      -

      Usage: ./manage.py add_category_fields [app1 app2 ...]

      -

      Add missing registered category fields to the database table of a specified application or all registered applications.

      -

      Requires Django South.

      -
      -
      -

      drop_category_field¶

      -

      Usage: ./manage.py drop_category_field app_name model_name field_name

      -

      Drop the field_name field from the app_name_model_name table, if the field is currently registered in CATEGORIES_SETTINGS.

      -

      Requires Django South.

      -
      -
      - - -
      -
      -
      - -
      -
      - - - - \ No newline at end of file diff --git a/docs/reference/models.html b/docs/reference/models.html deleted file mode 100644 index 639b4be..0000000 --- a/docs/reference/models.html +++ /dev/null @@ -1,252 +0,0 @@ - - - - - - - - Models — Django Categories v1.1 documentation - - - - - - - - - - - - -
      -

      Django Categories v1.1 documentation

      -
      - - -
      -
      - - - -

      This Page

      - - - -
      -
      - - - -
      -
      -
      -
      - -
      -

      Models¶

      -
      -

      CategoryBase¶

      -
      -
      -class CategoryBase¶
      -
      -
      -parent¶
      -

      TreeForeignKey (self)

      -

      The category’s parent category. Leave this blank for an root category.

      -
      - -
      -
      -name¶
      -

      Required CharField(100)

      -

      The name of the category.

      -
      - -
      -
      -slug¶
      -

      Required SlugField

      -

      URL-friendly title. It is automatically generated from the title.

      -
      - -
      -
      -active¶
      -

      Required BooleanField default: True

      -

      Is this item active. If it is inactive, all children are set to inactive as well.

      -
      - -
      -
      -objects¶
      -

      CategoryManager

      -

      An object manager that adds an active method for only selecting items whose active attribute is True.

      -
      - -
      -
      -tree¶
      -

      TreeManager

      -

      A Django-MPTT TreeManager instance.

      -
      - -
      - -
      -
      -

      Category¶

      -
      -
      -class Category¶
      -

      Category is a subclass of CategoryBase and includes all its attributes.

      -
      -
      -thumbnail¶
      -

      FileField

      -

      An optional thumbnail, that is uploaded to REGISTER_ADMIN via THUMBNAIL_STORAGE.

      -
      -

      Note

      -

      Why isn’t this an ImageField?

      -

      For ImageFields, Django checks the file system for the existance of the files to handle the height and width. In many cases this can lead to problems and impact performance.

      -

      For these reasons, a FileField that manually manages the width and height was chosen.

      -
      -
      - -
      -
      -thumbnail_width¶
      -

      IntegerField

      -

      The thumbnail width. Automatically set on save if a thumbnail is uploaded.

      -
      - -
      -
      -thumbnail_height¶
      -

      IntegerField

      -

      The thumbnail height. Automatically set on save if a thumbnail is uploaded.

      -
      - -
      -
      -order¶
      -

      Required IntegerField default: 0

      -

      A manually-managed order of this category in the listing. Items with the same order are sorted alphabetically.

      -
      - -
      -
      -alternate_title¶
      -

      CharField(100)

      -

      An alternative title to use on pages with this category.

      -
      - -
      -
      -alternate_url¶
      -

      CharField(200)

      -

      An alternative URL to use instead of the one derived from the category hierarchy.

      -
      -

      Note

      -

      Why isn’t this a URLField?

      -

      For URLFields, Django checks that the URL includes http:// and the site name. This makes it impossible to use relative URLs in that field.

      -
      -
      - -
      -
      -description¶
      -

      TextField

      -

      An optional longer description of the category. Very useful on category landing pages.

      -
      - -
      -
      -meta_keywords¶
      -

      CharField(255)

      -

      Comma-separated keywords for search engines.

      -
      - -
      -
      -meta_extra¶
      -

      TextField

      -

      (Advanced) Any additional HTML to be placed verbatim in the <head> of the page.

      -
      - -
      - -
      -
      - - -
      -
      -
      - -
      -
      - - - - \ No newline at end of file diff --git a/docs/reference/settings.html b/docs/reference/settings.html deleted file mode 100644 index 17693b9..0000000 --- a/docs/reference/settings.html +++ /dev/null @@ -1,198 +0,0 @@ - - - - - - - - Settings — Django Categories v1.1 documentation - - - - - - - - - - - - -
      -

      Django Categories v1.1 documentation

      -
      - - -
      -
      - - - -

      This Page

      - - - -
      -
      - - - -
      -
      -
      -
      - -
      -

      Settings¶

      -

      The CATEGORIES_SETTINGS dictionary is where you can override the default settings. You don’t have to include all the settings; only the ones which you want to override.

      - -

      The default settings are:

      -
      CATEGORIES_SETTINGS = {
      -    'ALLOW_SLUG_CHANGE': False,
      -    'CACHE_VIEW_LENGTH': 0,
      -    'RELATION_MODELS': [],
      -    'M2M_REGISTRY': {},
      -    'FK_REGISTRY': {},
      -    'THUMBNAIL_UPLOAD_PATH': 'uploads/categories/thumbnails',
      -    'THUMBNAIL_STORAGE': settings.DEFAULT_FILE_STORAGE,
      -    'SLUG_TRANSLITERATOR': lambda x: x,
      -}
      -
      -
      -
      -

      ALLOW_SLUG_CHANGE¶

      -

      Default: False

      -

      Description: Changing the slug for a category can have serious consequences if it is used as part of a URL. Setting this to True will allow users to change the slug of a category.

      -
      -
      -

      SLUG_TRANSLITERATOR¶

      -

      Default: lambda x: x

      -

      Description: Allows the specification of a function to convert non-ASCII characters in the potential slug to ASCII characters. Allows specifying a callable() or a string in the form of 'path.to.module.function'.

      -

      A great tool for this is Unidecode. Use it by setting SLUG_TRANSLITERATOR to 'unidecode.unidecode.

      -
      -
      -

      CACHE_VIEW_LENGTH¶

      -

      Default: 0

      -

      Description: This setting will be deprecated soon, but in the mean time, it allows you to specify the amount of time each view result is cached.

      -
      -
      -

      RELATION_MODELS¶

      -

      Default: []

      -

      Description: Relation models is a set of models that a user can associate with this category. You specify models using 'app_name.modelname' syntax.

      -
      -
      -

      M2M_REGISTRY¶

      -

      Default: {}

      -

      Description: A dictionary where the keys are in 'app_name.model_name' syntax, and the values are a string, dict, or tuple of dicts. See Registering Models.

      -
      -
      -

      FK_REGISTRY¶

      -

      Default: {}

      -

      Description: A dictionary where the keys are in 'app_name.model_name' syntax, and the values are a string, dict, or tuple of dicts. See Registering Models.

      -
      -
      -

      REGISTER_ADMIN¶

      -

      Default: True

      -

      Description: If you write your own category class by subclassing CategoryBase then you probably have no use for registering the default Category class in the admin.

      -
      -
      -

      THUMBNAIL_UPLOAD_PATH¶

      -

      Default: 'uploads/categories/thumbnails'

      -

      Description: Where thumbnails for the categories will be saved.

      -
      -
      -

      THUMBNAIL_STORAGE¶

      -

      Default: settings.DEFAULT_FILE_STORAGE

      -

      Description: How to store the thumbnails. Allows for external storage engines like S3.

      -
      -
      -

      JAVASCRIPT_URL¶

      -

      Default: STATIC_URL or MEDIA_URL + 'js/'

      -

      Description: Allows for customization of javascript placement.

      -
      -
      - - -
      -
      -
      - -
      -
      - - - - \ No newline at end of file diff --git a/docs/reference/templatetags.html b/docs/reference/templatetags.html deleted file mode 100644 index 024a499..0000000 --- a/docs/reference/templatetags.html +++ /dev/null @@ -1,393 +0,0 @@ - - - - - - - - Template tags and filters — Django Categories v1.1 documentation - - - - - - - - - - - -
      -

      Django Categories v1.1 documentation

      -
      - - -
      -
      - - - -

      This Page

      - - - -
      -
      - - - -
      -
      -
      -
      - -
      -

      Template tags and filters¶

      - -
      -

      Filters¶

      -
      -

      category_path¶

      -

      Optional Parameter: separator string. Default: " :: "

      -

      Creates a path represented by a categories by joining the items with a separator.

      -

      Each path item will be coerced to unicode, so you can pass a list of category instances, if required.

      -

      Example using a list of categories:

      -
      {{ some_list|category_path }}
      -
      -
      -

      If some_list is [ <Category: Country>, <Category: Country pop>, <Category: Urban Cowboy>] the result will be:

      -
      Country :: Country pop :: Urban Cowboy
      -
      -

      Example using a category node and optional separator parameter:

      -
      {{ some_node.get_ancestors|category_path:" > " }}
      -
      -
      -

      If some_node was category “Urban Cowboy”, the result will be:

      -
      Country > Country pop > Urban Cowboy
      -
      -
      -
      -

      tree_info¶

      -

      Optional Parameter: "ancestors"

      -

      Given a list of categories, it iterates over the list, generating a tuple of the current category and a dict containing information about the tree structure around it, with the following keys:

      -
      -
      'new_level'
      -
      True if the current item is the start of a new level in the tree, False otherwise.
      -
      'closed_levels'
      -
      A list of levels which end after the current item. This will be an empty list if the next category’s level is the same as or greater than the level of the current item.
      -
      -

      Provide the optional argument, "ancestors", to add a list of unicode representations of the ancestors of the current category, in descending order (root node first, immediate parent last), under the key ‘ancestors’.

      -

      For example: given the sample tree below, the contents of the list which would be available under the ‘ancestors’ key are given on the right:

      -
      Country             ->  []
      -   Country pop      ->  [u'Country pop']
      -      Urban Cowboy  ->  [u'Country', u'Country pop']
      -
      -

      Using this filter with unpacking in a {% for %} tag, you should have enough information about the tree structure to create a hierarchical representation of the tree.

      -
      {% for node,structure in objects|tree_info %}
      -    {% if structure.new_level %}<ul><li>{% else %}</li><li>{% endif %}
      -    {{ node.name }}
      -    {% for level in structure.closed_levels %}</li></ul>{% endfor %}
      -{% endfor %}
      -
      -
      -
      -
      -

      tree_queryset¶

      -

      Convert a regular category QuerySet into a new, ordered QuerySet that includes the categories selected and their ancestors.

      -

      This is especially helpful when you have a subset of categories and want to show the hierarchy for all the items.

      -

      For example, if we add it to the example for tree_info:

      -
      {% for node,structure in objects|tree_queryset|tree_info %}
      -    {% if structure.new_level %}<ul><li>{% else %}</li><li>{% endif %}
      -    {{ node.name }}
      -    {% for level in structure.closed_levels %}</li></ul>{% endfor %}
      -{% endfor %}
      -
      -
      -

      A list of unrelated categories such as [<Category: Urban cowboy>, <Category: Urban comtemporary>], the above template example will output the two categories and their ancestors:

      -
      <ul><li>
      -Country
      -<ul><li>
      -Country pop
      -<ul><li>
      -Urban cowboy
      -</li></ul></li></ul></li></ul>
      -<ul><li>
      -Rhythm and blues
      -<ul><li>
      -Urban contemporary
      -</li></ul></li></ul>
      -
      -
      -
      -

      Note

      -

      Categories that have similar ancestors are grouped accordingly. There is no duplication of the ancestor tree.

      -
      -
      -
      -
      -

      Inclusion tags¶

      -
      -

      display_path_as_ul¶

      -

      Template Rendered: categories/ul_tree.html

      -

      Syntax 1: {% display_path_as_ul <category_obj> %}

      -

      Syntax 2: {% display_path_as_ul <path_string>[ using="app.Model"] %}

      -

      Render the category with ancestors, but no children.

      -

      Pass either an object that subclasses CategoryBase or a path string for the category. Add using="app.Model" to specify which model when using a path string. The default model used is Category.

      -

      Example, using Category model:

      -
      {% display_path_as_ul "/Grandparent/Parent" %}
      -
      -
      -

      Example, using custom model:

      -
      {% display_path_as_ul "/Grandparent/Parent" using="coolapp.MusicGenre" %}
      -
      -
      -

      Example, using an object:

      -
      {% display_path_as_ul category_obj %}
      -
      -
      -

      Returns:

      -
      <ul>
      -  <li><a href="/categories/">Top</a>
      -  <ul>
      -    <li><a href="/categories/grandparent/">Grandparent</a></li>
      -  </ul>
      -  </li>
      -</ul>
      -
      -
      -
      -
      -

      display_drilldown_as_ul¶

      -

      Template rendered: categories/ul_tree.html

      -

      Syntax 1: {% display_drilldown_as_ul category_obj %}

      -

      Syntax 2: {% display_drilldown_as_ul "/Grandparent/Parent" [using="app.Model"] %}

      -

      Render the category with ancestors and children.

      -

      Example, using Category model:

      -
      {% display_drilldown_as_ul "/Grandparent/Parent" %}
      -
      -
      -

      Example, using custom model:

      -
      {% display_drilldown_as_ul "/Grandparent/Parent" using="coolapp.MusicGenre" %}
      -
      -
      -

      Example, using an object:

      -
      {% display_drilldown_as_ul category_obj %}
      -
      -
      -

      Returns:

      -
      <ul>
      -  <li><a href="/categories/">Top</a>
      -  <ul>
      -    <li><a href="/categories/grandparent/">Grandparent</a>
      -    <ul>
      -      <li><a href="/categories/grandparent/parent/">Parent</a>
      -      <ul>
      -        <li><a href="/categories/grandparent/parent/child1">Child1</a></li>
      -        <li><a href="/categories/grandparent/parent/child2">Child2</a></li>
      -        <li><a href="/categories/grandparent/parent/child3">Child3</a></li>
      -      </ul>
      -      </li>
      -    </ul>
      -    </li>
      -  </ul>
      -  </li>
      -</ul>
      -
      -
      -
      - -
      -
      -

      Template Tags¶

      -
      -

      get_top_level_categories¶

      -

      Retrieves an alphabetical list of all the categories that have no parents.

      -

      Syntax:

      -
      {% get_top_level_categories [using "app.Model"] as categories %}
      -
      -
      -

      Returns an list of categories [<category>, <category>, <category, ...]

      -
      -
      -

      get_category_drilldown¶

      -

      Syntax 1: {% get_category_drilldown <path_string> [using "app.Model"] as <varname> %}

      -

      Syntax 2: {% get_category_drilldown <object> as <varname> %}

      -

      Retrieves the specified category, its ancestors and its immediate children as an iterable. Syntax 1 allows for the retrieval of the category object via a slash-delimited path. The optional using "app.Model" allows you to specify from which model to retrieve the object.

      -

      Example:

      -
      {% get_category_drilldown "/Grandparent/Parent" using "family.Member" as family %}
      -
      -
      -

      The second syntax uses an instance of any object that subclasses CategoryBase

      -
      {% get_category_drilldown category_obj as family %}
      -
      -
      -

      Both examples sets family to:

      -
      [Grandparent, Parent, Child 1, Child 2, Child n]
      -
      -
      -
      -

      recursetree¶

      -

      This tag renders a section of your template recursively for each node in your -tree.

      -

      For example:

      -
      <ul class="root">
      -    {% recursetree nodes %}
      -        <li>
      -            {{ node.name }}
      -            {% if not node.is_leaf_node %}
      -                <ul class="children">
      -                    {{ children }}
      -                </ul>
      -            {% endif %}
      -        </li>
      -    {% endrecursetree %}
      -</ul>
      -
      -
      -

      Note the special variables node and children. -These are magically inserted into your context while you’re inside the -recursetree tag.

      -
      -

      node is an instance of your MPTT model.

      -

      children : This variable holds the rendered HTML for the children of -node.

      -
      -
      -

      Note

      -

      If you already have variables called node or children in your -template, and you need to access them inside the recursetree block, -you’ll need to alias them to some other name first:

      -
      {% with node as friendly_node %}
      -    {% recursetree nodes %}
      -        {{ node.name }} is friends with {{ friendly_node.name }}
      -        {{ children }}
      -    {% endrecursetree %}
      -{% endwith %}
      -
      -
      -
      -
      -
      -
      - - -
      -
      -
      - -
      -
      - - - - \ No newline at end of file diff --git a/docs/registering_models.html b/docs/registering_models.html deleted file mode 100644 index 5397a5e..0000000 --- a/docs/registering_models.html +++ /dev/null @@ -1,249 +0,0 @@ - - - - - - - - Registering Models — Django Categories v1.1 documentation - - - - - - - - - - - -
      -

      Django Categories v1.1 documentation

      -
      - - - - - - -
      -
      -
      -
      - -
      -

      Registering Models¶

      -
      -

      Registering models in settings.py¶

      -

      It is nice to not have to modify the code of applications to add a relation to categories. You can therefore do all the registering in settings.py. For example:

      -
      CATEGORIES_SETTINGS = {
      -    'FK_REGISTRY': {
      -        'app.AModel': 'category',
      -        'app.MyModel': (
      -            'primary_category',
      -            {'name': 'secondary_category', 'related_name': 'mymodel_sec_cat'}, )
      -    },
      -    'M2M_REGISTRY': {
      -        'app.BModel': 'categories',
      -        'app.MyModel': ('other_categories', 'more_categories', ),
      -    }
      -}
      -
      -
      -

      The FK_REGISTRY is a dictionary whose keys are the model to which to add the new field(s). The value is a string or tuple of strings or dictionaries specifying the necessary information for each field.

      -

      The M2M_REGISTRY is a dictionary whose keys are the model to which to add the new field(s). The value is a string or tuple of strings specifying the necessary information for each field.

      -
      -

      Registering one Category field to model¶

      -

      The simplest way is to specify the name of the field, such as:

      -
      CATEGORIES_SETTINGS = {
      -    'FK_REGISTRY': {
      -        'app.AModel': 'category'
      -    }
      -}
      -
      -
      -

      This is equivalent to adding the following the AModel of app:

      -
      category = models.ForeignKey(Category)
      -
      -
      -

      If you want more control over the new field, you can use a dictionary and pass other ForeignKey options. The name key is required:

      -
      CATEGORIES_SETTINGS = {
      -    'FK_REGISTRY': {
      -        'app.AModel': {'name': 'category', 'related_name': 'amodel_cats'}
      -    }
      -}
      -
      -
      -

      This is equivalent to adding the following the AModel of app:

      -
      category = models.ForeignKey(Category, related_name='amodel_cats')
      -
      -
      -
      -
      -

      Registering two or more Category fields to a Model¶

      -

      When you want more than one relation to Category, all but one of the fields must specify a related_name to avoid conflicts, like so:

      -
      CATEGORIES_SETTINGS = {
      -    'FK_REGISTRY': {
      -        'app.MyModel': (
      -            'primary_category',
      -            {'name': 'secondary_category', 'related_name': 'mymodel_sec_cat'}, )
      -    },
      -
      -
      -
      -

      Registering one or more Many-to-Many Category fields to a Model¶

      -
      CATEGORIES_SETTINGS = {
      -    'M2M_REGISTRY': {
      -        'app.AModel': 'categories',
      -        'app.MyModel': (
      -            {'name': 'other_categories', 'related_name': 'other_cats'},
      -            {'name': 'more_categories', 'related_name': 'more_cats'},
      -        ),
      -    }
      -}
      -
      -
      -
      -
      -
      -

      Registering a many-to-one relationship¶

      -

      To create a many-to-one relationship (foreign key) between a model and Django Categories, you register your model with the register_fk function.

      -
      -
      -register_fk(model, field_name='category', extra_params={}])¶
      -
      --- - - - -
      Parameters:
        -
      • model – The Django Model to link to Django Categories
      • -
      • field_name – Optional name for the field default: category
      • -
      • extra_params – Optional dictionary of extra parameters passed to the ForeignKey class.
      • -
      -
      -
      - -

      Example, in your models.py:

      -
      import categories
      -categories.register_fk(MyModel)
      -
      -
      -

      If you want more than one field on a model you have to have some extra arguments:

      -
      import categories
      -categories.register_fk(MyModel, 'primary_category')
      -categories.register_fk(MyModel, 'secondary_category', {'related_name':'mymodel_sec_cat'})
      -
      -
      -

      The extra_args allows you to specify the related_name of one of the fields so it doesn’t clash.

      -
      -
      -

      Registering a many-to-many relationship¶

      -

      To create a many-to-many relationship between a model and Django Categories, you register your model with the register_m2m function.

      -
      -
      -register_m2m(model, field_name='categories', extra_params={}])¶
      -
      --- - - - -
      Parameters:
        -
      • model – The Django Model to link to Django Categories
      • -
      • field_name – Optional name for the field default: categories
      • -
      • extra_params – Optional dictionary of extra parameters passed to the ManyToManyField class.
      • -
      -
      -
      - -

      Example, in your models.py:

      -
      import categories
      -categories.register_m2m(MyModel)
      -
      -
      -
      -
      - - -
      -
      -
      - -
      -
      - - - - \ No newline at end of file diff --git a/docs/search.html b/docs/search.html deleted file mode 100644 index 394cb8c..0000000 --- a/docs/search.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - Search — Django Categories v1.1 documentation - - - - - - - - - - - - - -
      -

      Django Categories v1.1 documentation

      -
      - - - - - - -
      -
      -
      -
      - -

      Search

      -
      - -

      - Please activate JavaScript to enable the search - functionality. -

      -
      -

      - From here you can search these documents. Enter your search - words into the box below and click "search". Note that the search - function will automatically search for all of the words. Pages - containing fewer words won't appear in the result list. -

      -
      - - - -
      - -
      - -
      - -
      -
      -
      - -
      -
      - - - - \ No newline at end of file diff --git a/docs/searchindex.js b/docs/searchindex.js deleted file mode 100644 index 94c7fe9..0000000 --- a/docs/searchindex.js +++ /dev/null @@ -1 +0,0 @@ -Search.setIndex({objects:{"":{Category:[0,0,1],register_m2m:[8,2,1],CategoryBase:[0,0,1],register_fk:[8,2,1]},Category:{meta_keywords:[0,1,1],description:[0,1,1],meta_extra:[0,1,1],thumbnail_width:[0,1,1],order:[0,1,1],alternate_title:[0,1,1],alternate_url:[0,1,1],thumbnail_height:[0,1,1],thumbnail:[0,1,1]},CategoryBase:{name:[0,1,1],parent:[0,1,1],tree:[0,1,1],objects:[0,1,1],active:[0,1,1],slug:[0,1,1]}},terms:{represent:[5,6],all:[0,1,2,8,6,5,9,10,11],code:[9,7,8,11],sci:5,forget:11,is_leaf_nod:6,follow:[5,8,6],children:[0,5,6],hard_coded_connect:[],hierarch:[1,6,7],whose:[0,8],depend:11,upload_to:7,friendli:0,categorymanag:0,rhythm:6,under:[5,6],cache_view_length:[4,2],child1:6,child2:6,child3:6,fieldset:7,string:[2,8,6],bmodel:8,fals:[5,2,6],mechan:[],parti:11,coolapp:6,veri:0,affect:9,syntax:[2,6],exact:11,magic:6,level:[5,6],list:[0,5,3,6],upload:[0,2],iter:[5,6],item:[0,1,6,5],categories_set:[10,2,8],endrecursetre:6,consequ:2,second:6,treemanag:0,alternate_url:[0,7],treeforeignkei:0,full_tree_for_categori:[],even:11,index:1,what:[],appear:[5,1],section:[1,6],current:[5,10,6],version:7,"new":[5,1,8,6,7],varnam:6,method:[0,7],metadata:7,full:[],deriv:[0,1,7],gener:[0,5,6],never:[],fk_registri:[4,2,8,11],path:[10,2,6],full_tree_for_model:[],modifi:8,valu:[2,8],treeleaf:[],search:[0,1,7],genr:[],thumbnail_upload_path:[7,2,4],amount:2,related_nam:[9,5,8],action:1,chang:[9,2],control:[8,11],via:[0,6],dictionari:[2,8],extra:[5,7,8],appli:[],app:[9,1,8,6,11],disciplin:11,deprec:2,api:9,subcategori:[5,11],famili:6,simplecategoryadmin:7,instal:[1,3,11],txt:10,select:[0,6],from:[0,1,5,6,7,9,10,11],would:[9,5,6],regist:[1,2,8,7,5,9,10,11],two:[5,8,6,11],next:[5,7,6],few:3,call:6,type:[],tell:[],more:[7,8,11],sort:0,clean_alternate_titl:7,relat:[5,2,8,11],hurt:9,indic:1,hold:6,unpack:6,cach:2,must:[9,7,8,10],none:7,join:6,alia:6,work:9,recursetre:6,treelevel:[],can:[0,2,8,5,6,7,9,10,11],root:[0,5,6],def:7,overrid:[7,2],want:[1,2,8,6,7,9],fragment:[],get_top_level_categori:6,templat:[5,1,6,4],manytomanyfield:8,tag:[5,1,6,4],tab:10,multipl:[1,10],divid:1,anoth:9,write:2,allow_slug_chang:[4,2],more_cat:8,meta_keyword:[0,7],default_file_storag:2,instead:[0,7,5],ancestor:[5,6],app_name_model_nam:10,updat:[],overridden:7,after:[5,6,11],befor:11,extra_param:8,end:[5,6],data:[9,1,7],ul_tre:6,attempt:9,get_latest_objects_by_categori:[],seriou:2,django:[0,1,3,7,8,9,10,11],caus:9,inform:[5,8,6,11],allow:[1,2,8,6,7,5],enter:[9,1],callabl:2,first:[9,10,6,5],order:[0,7,6,5],category_detail:5,help:6,slugif:[],over:[5,8,6],becaus:9,comma:[0,7,5],hierarchi:[0,7,6],taxonomi:1,secondary_categori:8,dynam:[9,11],paramet:[5,8,6],group:6,catgor:7,other_categori:8,chosen:0,fix:1,therefor:8,alter:[5,7,6],them:6,categorybaseadminform:7,"return":[7,6],greater:[5,6],thei:9,handl:[0,1,11],extra_arg:8,var_nam:[],initi:[],mymodel_sec_set:[],now:1,document:1,name:[0,1,8,7,6,9,5,11],unidecod:2,simpl:[9,7],drop:[9,10],separ:[0,7,6,5],easili:[],each:[2,8,6],categoryadmin:7,unicod:[5,6],collaps:7,mean:2,subset:6,hard:11,"7beta1":[],urlfield:0,"7beta3":[],meta:7,connect:[1,11],our:1,happen:[],special:6,out:1,variabl:6,"3rd":11,space:10,categori:[0,1,2,3,4,5,6,7,8,9,10,11],verbatim:[0,7],import_categori:[4,10],rel:0,insid:6,advanc:[0,7],migrat:3,given:[5,6],get_image_dimens:7,headlin:5,reason:0,base:5,transliter:[],drop_category_field:[9,4,10],basi:11,reconfigur:[9,1],indent:10,meta_extra:[0,7],appnam:[],could:[9,1,5],static_url:2,filter:[1,6,4],musicgenr:[6,11],perman:9,charfield:[0,7,11],assign:7,south:[9,1,3,11,10],lambda:2,render:6,onc:1,independ:1,number:[],sometim:7,mymodel_sec_cat:8,alreadi:[6,11],done:11,blank:[0,7],installed_app:3,miss:[9,10],differ:[9,3],lazy_connect:[],width:[0,7],associ:2,top:[6,11],system:[0,1],least:7,stori:1,max_length:[7,11],accordingli:6,store:2,schema:9,urban:6,option:[0,7,8,6,5],relationship:[9,1,8,11,5],especi:6,get_absolute_url:5,specifi:[5,10,2,8,6],part:2,textfield:[0,7],than:[5,8,6],category_path:6,grew:1,keyword:[0,7],provid:[9,1,6,5],tree:[0,10,11,6,5],structur:[9,5,6],charact:2,project:[3,11],matter:9,endspaceless:[],friend:6,imagefield:0,browser:[],"function":[1,2,8,7],behavior:9,ran:11,pass:[7,8,6],queryset:6,argument:[5,8,6],packag:7,mptt:[0,7,6],have:[5,2,8,6,11],tabl:[9,1,11,10,7],need:[1,3,6,7],"null":7,engin:[0,7,2],categorybas:[0,1,2,3,4,6,7],equival:8,self:[0,7],register_fk:8,note:[0,6],also:[9,7,11],exampl:[9,7,8,6,5],take:11,which:[5,2,8,6],tupl:[5,2,8,6],tool:2,singl:7,compat:[],endfor:[5,6],clash:8,though:[],object:[0,5,6],regular:6,relation_model:[4,2],"class":[0,2,8,6,7,11],sub:10,don:[9,2,11],url:[0,7,2],doc:7,mymodel:[8,11],doe:7,place:[0,7],clean:7,register_m2m:8,show:6,model_nam:[9,10,2],checkbox:1,breadcrumbs_tag:[],contemporari:6,filefield:[0,7],impact:0,access:[5,6],onli:[0,1,2,3,5,7,9],coerc:6,configur:[9,5,11],activ:[0,7],should:[5,7,6],dict:[5,2,6],tree_info:[5,6],media_url:2,count:5,get:[5,1,11],simplest:8,soon:2,cannot:10,increas:[],requir:[0,8,6,9,10,11],amodel_cat:8,get_ancestor:6,contain:[5,6],through:11,cache_middleware_second:[],where:2,view:[5,2],set:[0,1,2,3,4,6,7,8,11],concert:1,thumbnail_width:[0,7],displai:[],javascript_url:[4,2],see:[9,5,2,3,11],result:[7,2,6],arg:7,close:7,subject:11,still:9,kei:[5,2,8,6,11],databas:[9,1,11,10],enough:6,between:8,"import":[5,7,8,11,10],thumbnail:[0,7,2],modeladmin:11,attribut:[0,7],altern:[0,7],grandpar:6,extend:5,javascript:2,treebranch:[],complementari:9,come:[],popul:[],both:6,last:[5,6],delimit:6,admin:[1,2,11,7],similar:6,howev:[9,7],lazi:11,foreign:[8,11],instanc:[0,7,6],context:6,new_level:[5,6],mani:[0,1,8,7,9,11],display_path_as_ul:6,thumbnail_storag:[0,4,2],simpli:[],slugfield:0,height:[0,7],mpttmeta:7,respect:11,duplic:6,empti:[5,6],much:7,basic:1,addit:[0,7],imag:7,convert:[2,6],ani:[0,1,7,6,9,5,11],child:[5,6],closed_level:[5,6],"case":[0,7,9],display_drilldown_as_ul:6,look:5,modelnam:2,"while":[9,6],abov:[7,6],error:9,some_list:6,loos:9,endblock:5,categorybaseadmin:7,non:2,kwarg:7,ascii:2,sever:[9,7,11],parent:[0,7,6,5],welcom:[],perform:0,alphabet:[0,6],make:[0,9,11],more_categori:8,same:[0,1,6,5,10,11],member:6,python:9,html:[0,7,6,5],descend:[5,6],m2m_registri:[4,2,8,11],eventu:[],conflict:8,http:0,categoryadminform:7,blue:6,someon:11,user:[7,2],countri:6,extern:2,cosmet:1,appropri:9,dystopian:5,entri:5,well:[0,11],inherit:7,without:5,command:[9,1,10,4],thi:[0,2,8,5,6,7,9,11],endif:[5,6],model:[0,1,2,3,4,5,6,7,9,8,11],latest:[],relatedmodel_set:5,just:7,photo:1,simplecategoryadminform:[],endwith:6,alternate_titl:[0,7],thumbnail_height:[0,7],forloop:[],web:1,entries_set:5,register_admin:[0,4,2],easi:1,mix:10,had:5,littl:7,add:[0,3,6,7,8,5,10,11],book:5,inner:7,tweak:[],els:[5,7,6,11],save:[0,7,2],modul:[1,2],gave:1,applic:[9,1,8,11,10],around:[5,6],amodel:8,format:[],pop:6,field_nam:[9,10,8],bit:7,recurs:6,insert:6,like:[5,7,2,8],specif:2,other_cat:8,manual:0,href:[5,6],necessari:[7,8],either:[7,6],output:6,list_displai:7,page:[0,1,7],underli:9,revers:5,simplecategori:7,some:[1,8,6],intern:[],sampl:[5,6],syncdb:[3,11],inact:0,category_set:[],tree_path:[],integerfield:[0,7],lead:0,slug_transliter:[4,2],avoid:8,subclass:[0,1,2,3,6,7],add_category_field:[9,4,11,10],leav:0,tree_queryset:6,content:[5,1,6],refer:[1,4],core:7,set_nam:[],run:[9,3,11],imposs:0,usag:10,comtemporari:6,how:2,step:3,isn:[0,7],"super":7,slug:[0,7,2],about:[5,6],column:9,verbose_name_plur:7,date_field:[],includ:[0,7,2,6,9],cowboi:6,category_obj:6,other:[1,8,6,7,5,11],block:[5,6],file2:10,own:[7,2,3,11],within:[5,1],automat:[0,5],slash:6,right:[5,6],subdisciplin:11,contrib:7,storag:[7,2,11],your:[1,2,3,6,7,5,8,11],manag:[0,1,3,7,4,9,10,11],inclus:[4,6],wai:[9,8,11],musicsubgenr:11,"long":9,custom:[1,2,3,6,7,11],avail:[5,6],start:[5,1,11,6,10],editor:3,suit:1,fork:11,head:[0,7],cleaned_data:7,form:[7,2],great:2,category_tag:5,link:8,placement:2,line:10,"true":[0,7,2,6,5],bug:1,reset:9,immedi:[5,6],path_str:6,possibl:9,"default":[0,2,8,6,7,9],wish:11,app2:10,app1:10,below:[5,6],foreignkei:[8,11],site:[0,1,7],otherwis:[5,6],problem:0,unrel:6,booleanfield:0,app_nam:[9,10,2],featur:5,creat:[1,3,6,7,9,8,11],retriev:6,"abstract":[],primary_categori:8,doesn:[9,8],repres:6,exist:0,file:[0,7,3,11,10],pip:3,improv:1,check:0,probabl:[9,2],titl:[0,7],when:[8,6,11],detail:5,refactor:1,field:[0,1,8,7,9,10,11],valid:5,lookup:7,futur:5,test:1,you:[2,3,5,6,7,8,9,10,11],nice:8,node:[5,6],some_nod:6,friendly_nod:6,order_insertion_bi:7,why:0,breadcrumb:6,land:0,longer:0,help_text:7,get_category_drilldown:6,descript:[0,7,2,5],"6b1":[],potenti:2,time:[9,2]},objtypes:{"0":"py:class","1":"py:attribute","2":"py:function"},titles:["Models","Django Categories v 1.1","Settings","Installation","Reference","Using categories in templates","Template tags and filters","Creating Custom Categories","Registering Models","Adding the fields to the database","Management Commands","Getting Started"],objnames:{"0":"Python class","1":"Python attribute","2":"Python function"},filenames:["reference/models","index","reference/settings","installation","reference/index","usage","reference/templatetags","custom_categories","registering_models","adding_the_fields","reference/management_commands","getting_started"]}) \ No newline at end of file diff --git a/docs/templatetags.html b/docs/templatetags.html deleted file mode 100644 index 6b4a500..0000000 --- a/docs/templatetags.html +++ /dev/null @@ -1,221 +0,0 @@ - - - - - - - - Template Tags — Django Categories v0.7beta1 documentation - - - - - - - - - - - -
      -

      Django Categories v0.7beta1 documentation

      -
      - - -
      -
      - - - -

      This Page

      - - - -
      -
      - - - -
      -
      -
      -
      - -
      -

      Template Tags¶

      -
      -

      get_top_level_categories¶

      -

      Retrieves an alphabetical list of all the categories that have no parents.

      -

      Syntax:

      -
      {% get_top_level_categories as categories %}
      -
      -
      -

      Returns an list of categories [<category>, <category>, <category, ...]

      -
      -
      -

      display_path_as_ul¶

      -

      Render the category with ancestors, but no children using the categories/ul_tree.html template.

      -

      Example:

      -
      {% display_path_as_ul "/Grandparent/Parent" %}
      -
      -
      -

      or

      -
      {% display_path_as_ul category_obj %}
      -
      -
      -

      Returns:

      -
      <ul>
      -  <li><a href="/categories/">Top</a>
      -  <ul>
      -    <li><a href="/categories/grandparent/">Grandparent</a></li>
      -  </ul>
      -  </li>
      -</ul>
      -
      -
      -
      -
      -

      get_category_drilldown¶

      -

      Retrieves the specified category, its ancestors and its immediate children -as an iterable.

      -

      Example:

      -
      {% get_category_drilldown "/Grandparent/Parent" as family %}
      -
      -
      -

      or

      -
      {% get_category_drilldown category_obj as family %}
      -
      -
      -

      Sets family to:

      -
      [Grandparent, Parent, Child 1, Child 2, Child n]
      -
      -
      -
      -

      display_drilldown_as_ul¶

      -

      Render the category with ancestors and children using the -categories/ul_tree.html template.

      -

      Example:

      -
      {% display_drilldown_as_ul "/Grandparent/Parent" %}
      -
      -
      -

      or:

      -
      {% display_drilldown_as_ul category_obj %}
      -
      -
      -

      Returns:

      -
      <ul>
      -  <li><a href="/categories/">Top</a>
      -  <ul>
      -    <li><a href="/categories/grandparent/">Grandparent</a>
      -    <ul>
      -      <li><a href="/categories/grandparent/parent/">Parent</a>
      -      <ul>
      -        <li><a href="/categories/grandparent/parent/child1">Child1</a></li>
      -        <li><a href="/categories/grandparent/parent/child2">Child2</a></li>
      -        <li><a href="/categories/grandparent/parent/child3">Child3</a></li>
      -      </ul>
      -      </li>
      -    </ul>
      -    </li>
      -  </ul>
      -  </li>
      -</ul>
      -
      -
      -
      - -
      - - -
      -
      -
      - -
      -
      - - - - \ No newline at end of file diff --git a/docs/usage.html b/docs/usage.html deleted file mode 100644 index 2fb9c25..0000000 --- a/docs/usage.html +++ /dev/null @@ -1,221 +0,0 @@ - - - - - - - - Using categories in templates — Django Categories v1.1 documentation - - - - - - - - - - - -
      -

      Django Categories v1.1 documentation

      -
      - - -
      -
      - - - -

      This Page

      - - - -
      -
      - - - -
      -
      -
      -
      - -
      -

      Using categories in templates¶

      -
      -

      Getting all items within a category¶

      -

      The Category model automatically gets reverse relationships with all other models related to it.

      -

      This allows you access to the related objects from the template without altering any views. For example, if you only had Entry models related to Category, your categories/category_detail.html template could look like

      -
       1
      - 2
      - 3
      - 4
      - 5
      - 6
      - 7
      - 8
      - 9
      -10
      -11
      -12
      -13
      -14
      -15
      -16
      -17
      -18
      -19
      -20
      -21
      -22
      -23
      -24
      -25
      -26
      -27
      -28
      {% extends 'categories/base.html' %}
      -{% block content %}
      -<h1>{{ category }}</h1>
      -{% if category.parent %}
      -    <h2>Go up to 
      -        <a href="{{ category.parent.get_absolute_url }}">
      -            {{ category.parent }}
      -        </a></h2>
      -{% endif %}
      -{% if category.description %}<p>{{ category.description }}</p>{% endif %}
      -{% if category.children.count %}
      -    <h2>Subcategories</h2>
      -    <ul>
      -        {% for child in category.children.all %}
      -        <li><a href="{{ child.get_absolute_url }}">{{ child }}</a></li>
      -        {% endfor %}
      -    </ul>
      -{% endif %}
      -<h2>Entries</h2>
      -{% if category.entries_set.all %}
      -    {% for entry in category.entries_set.all %}
      -        <p><a href="{{ entry.get_absolute_url }}">{{ entry.headline }}</a></p>
      -    {% endfor %}
      -{% else %}
      -    <p><em>No entries for {{ category }}</em></p>
      -{% endif %}
      -
      -{% endblock %}
      -
      -
      -

      If you have related_name parameters to the configuration (see Registering Models), then you would use category.related_name.all instead of category.relatedmodel_set.all.

      -
      -
      -

      Template Tags¶

      -

      To use the template tags:

      -
      {% import category_tags %}
      -
      -
      -

      tree_info¶

      -

      Given a list of categories, iterates over the list, generating -two-tuples of the current tree item and a dict containing -information about the tree structure around the item, with the following -keys:

      -
      -
      -
      'new_level'
      -
      True if the current item is the start of a new level in -the tree, False otherwise.
      -
      'closed_levels'
      -
      A list of levels which end after the current item. This will -be an empty list if the next item’s level is the same as or -greater than the level of the current item.
      -
      -
      -

      An optional argument can be provided to specify extra details about the -structure which should appear in the dict. This should be a -comma-separated list of feature names. The valid feature names are:

      -
      -
      -
      ancestors
      -

      Adds a list of unicode representations of the ancestors of the -current node, in descending order (root node first, immediate -parent last), under the key 'ancestors'.

      -

      For example: given the sample tree below, the contents of the list -which would be available under the 'ancestors' key are given -on the right:

      -
      Books                    ->  []
      -   Sci-fi                ->  [u'Books']
      -      Dystopian Futures  ->  [u'Books', u'Sci-fi']
      -
      -
      -
      -
      -
      -
      -
      - - -
      -
      -
      - -
      -
      - - - - \ No newline at end of file diff --git a/requirements/test.txt b/requirements/test.txt index ca0c6f8..203af8e 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -1 +1,8 @@ -r prod.txt +linkify-it-py +myst-parser + +pydata-sphinx-theme +Sphinx>=4.3.0 +sphinx-autodoc-typehints +sphinxcontrib-django2 From 8a7f22618de6822863c6a95e5f055f10e6cd9acd Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sun, 12 Dec 2021 08:07:36 -0600 Subject: [PATCH 22/51] Moved some documentation to new places --- .../{ => user_guide}/adding_the_fields.rst | 0 doc_src/{ => user_guide}/admin_settings.rst | 0 .../code_examples/custom_categories1.py | 0 .../code_examples/custom_categories2.py | 0 .../code_examples/custom_categories3.py | 0 .../code_examples/custom_categories4.py | 0 .../code_examples/custom_categories5.py | 0 .../code_examples/custom_categories6.py | 0 .../code_examples/custom_categories7.py | 0 .../{ => user_guide}/custom_categories.rst | 0 .../{ => user_guide}/registering_models.rst | 0 doc_src/{ => user_guide}/usage.rst | 0 .../usage_example_template.html | 0 docs/_sources/adding_the_fields.txt | 23 --- docs/_sources/custom_categories.txt | 56 ------- docs/_sources/registering_models.txt | 139 ------------------ docs/_sources/usage.txt | 62 -------- 17 files changed, 280 deletions(-) rename doc_src/{ => user_guide}/adding_the_fields.rst (100%) rename doc_src/{ => user_guide}/admin_settings.rst (100%) rename doc_src/{ => user_guide}/code_examples/custom_categories1.py (100%) rename doc_src/{ => user_guide}/code_examples/custom_categories2.py (100%) rename doc_src/{ => user_guide}/code_examples/custom_categories3.py (100%) rename doc_src/{ => user_guide}/code_examples/custom_categories4.py (100%) rename doc_src/{ => user_guide}/code_examples/custom_categories5.py (100%) rename doc_src/{ => user_guide}/code_examples/custom_categories6.py (100%) rename doc_src/{ => user_guide}/code_examples/custom_categories7.py (100%) rename doc_src/{ => user_guide}/custom_categories.rst (100%) rename doc_src/{ => user_guide}/registering_models.rst (100%) rename doc_src/{ => user_guide}/usage.rst (100%) rename doc_src/{ => user_guide}/usage_example_template.html (100%) delete mode 100644 docs/_sources/adding_the_fields.txt delete mode 100644 docs/_sources/custom_categories.txt delete mode 100644 docs/_sources/registering_models.txt delete mode 100644 docs/_sources/usage.txt diff --git a/doc_src/adding_the_fields.rst b/doc_src/user_guide/adding_the_fields.rst similarity index 100% rename from doc_src/adding_the_fields.rst rename to doc_src/user_guide/adding_the_fields.rst diff --git a/doc_src/admin_settings.rst b/doc_src/user_guide/admin_settings.rst similarity index 100% rename from doc_src/admin_settings.rst rename to doc_src/user_guide/admin_settings.rst diff --git a/doc_src/code_examples/custom_categories1.py b/doc_src/user_guide/code_examples/custom_categories1.py similarity index 100% rename from doc_src/code_examples/custom_categories1.py rename to doc_src/user_guide/code_examples/custom_categories1.py diff --git a/doc_src/code_examples/custom_categories2.py b/doc_src/user_guide/code_examples/custom_categories2.py similarity index 100% rename from doc_src/code_examples/custom_categories2.py rename to doc_src/user_guide/code_examples/custom_categories2.py diff --git a/doc_src/code_examples/custom_categories3.py b/doc_src/user_guide/code_examples/custom_categories3.py similarity index 100% rename from doc_src/code_examples/custom_categories3.py rename to doc_src/user_guide/code_examples/custom_categories3.py diff --git a/doc_src/code_examples/custom_categories4.py b/doc_src/user_guide/code_examples/custom_categories4.py similarity index 100% rename from doc_src/code_examples/custom_categories4.py rename to doc_src/user_guide/code_examples/custom_categories4.py diff --git a/doc_src/code_examples/custom_categories5.py b/doc_src/user_guide/code_examples/custom_categories5.py similarity index 100% rename from doc_src/code_examples/custom_categories5.py rename to doc_src/user_guide/code_examples/custom_categories5.py diff --git a/doc_src/code_examples/custom_categories6.py b/doc_src/user_guide/code_examples/custom_categories6.py similarity index 100% rename from doc_src/code_examples/custom_categories6.py rename to doc_src/user_guide/code_examples/custom_categories6.py diff --git a/doc_src/code_examples/custom_categories7.py b/doc_src/user_guide/code_examples/custom_categories7.py similarity index 100% rename from doc_src/code_examples/custom_categories7.py rename to doc_src/user_guide/code_examples/custom_categories7.py diff --git a/doc_src/custom_categories.rst b/doc_src/user_guide/custom_categories.rst similarity index 100% rename from doc_src/custom_categories.rst rename to doc_src/user_guide/custom_categories.rst diff --git a/doc_src/registering_models.rst b/doc_src/user_guide/registering_models.rst similarity index 100% rename from doc_src/registering_models.rst rename to doc_src/user_guide/registering_models.rst diff --git a/doc_src/usage.rst b/doc_src/user_guide/usage.rst similarity index 100% rename from doc_src/usage.rst rename to doc_src/user_guide/usage.rst diff --git a/doc_src/usage_example_template.html b/doc_src/user_guide/usage_example_template.html similarity index 100% rename from doc_src/usage_example_template.html rename to doc_src/user_guide/usage_example_template.html diff --git a/docs/_sources/adding_the_fields.txt b/docs/_sources/adding_the_fields.txt deleted file mode 100644 index a6a920f..0000000 --- a/docs/_sources/adding_the_fields.txt +++ /dev/null @@ -1,23 +0,0 @@ -.. _adding_the_fields: - -================================= -Adding the fields to the database -================================= - -While Django will create the appropriate columns and tables if you configure Django Categories first, many times that is not possible. You could also reset the table, but you would loose all data in it. There is another way. - -Enter South -*********** - -`South `_ is a Django application for managing database schema changes. South's default behavior is for managing permanent changes to a model's structure. In the case of dynamically adding a field or fields to a model, this doesn't work because you are not making the change permanent. And probably don't want to. - -Django Categories has a management command to create any missing fields. It requires South because it uses the South's API for making changes to databases. The management command is simple: ``python manage.py add_category_fields [app]``\ . If you do not include an app name, it will attempt to do all applications configured. - -Running this command several times will not hurt any data or cause any errors. - -Reconfiguring Fields -******************** - -You can make changes to the field configurations as long as they do not change the underlying database structure. For example, adding a ``related_name`` (see :ref:`registering_a_m2one_relationship`\ ) because it only affects Django code. Changing the name of the field, however, is a different matter. - -Django Categories provides a complementary management command to drop a field from the database (the field must still be in the configuration to do so): ``python manage.py drop_category_field app_name model_name field_name`` \ No newline at end of file diff --git a/docs/_sources/custom_categories.txt b/docs/_sources/custom_categories.txt deleted file mode 100644 index f4ce71e..0000000 --- a/docs/_sources/custom_categories.txt +++ /dev/null @@ -1,56 +0,0 @@ -.. _creating_custom_categories: - -========================== -Creating Custom Categories -========================== - -Django Categories isn't just for using a single category model. It allows you to create your own custom category-like models with as little or much customization as you need. - -Name only -========= - -For many cases, you want a simple user-managed lookup table. You can do this with just a little bit of code. The resulting model will include name, slug and active fields and a hierarchical admin. - -#. Create a model that subclasses :py:class:`CategoryBase` - - .. literalinclude:: code_examples/custom_categories1.py - :linenos: - -#. Create a subclass of CategoryBaseAdmin. - - .. literalinclude:: code_examples/custom_categories2.py - :linenos: - -#. Register your model and custom model admin class. - -Name and other data -=================== - -Sometimes you need more functionality, such as extra metadata and custom functions. The :py:class:`Category` model in this package does this. - -#. Create a model that subclasses :py:class:`CategoryBase` as above. - -#. Add new fields to the model. The :py:class:`Category` model adds these extra fields. - - .. literalinclude:: code_examples/custom_categories3.py - :linenos: - -#. Add new methods to the model. For example, the :py:class:`Category` model adds several new methods, including overriding the :py:meth:`save` method. - - .. literalinclude:: code_examples/custom_categories4.py - :linenos: - -#. Alter :py:class:`Meta` or :py:class:`MPTTMeta` class. Either of these inner classes can be overridden, however your :py:class:`Meta` class should inherit :py:class:`CategoryBase.Meta`. Options for :py:class:`Meta` are in the `Django-MPTT docs `_. - - .. literalinclude:: code_examples/custom_categories5.py - :linenos: - -#. For the admin, you must create a form that subclasses :py:class:`CategoryBaseAdminForm` and at least sets the ``Meta.model`` attribute. You can also alter the form fields and cleaning methods, as :py:class:`Category` does. - - .. literalinclude:: code_examples/custom_categories6.py - :linenos: - -#. Next you must subclass :py:class:`CategoryBaseAdmin` and assign the ``form`` attribute the form class created above. You can alter any other attributes as necessary. - - .. literalinclude:: code_examples/custom_categories7.py - :linenos: diff --git a/docs/_sources/registering_models.txt b/docs/_sources/registering_models.txt deleted file mode 100644 index e44f652..0000000 --- a/docs/_sources/registering_models.txt +++ /dev/null @@ -1,139 +0,0 @@ -.. _registering_models: - -================== -Registering Models -================== - - -Registering models in settings.py -================================= - -It is nice to not have to modify the code of applications to add a relation to categories. You can therefore do all the registering in ``settings.py``\ . For example: - -.. code-block:: python - - CATEGORIES_SETTINGS = { - 'FK_REGISTRY': { - 'app.AModel': 'category', - 'app.MyModel': ( - 'primary_category', - {'name': 'secondary_category', 'related_name': 'mymodel_sec_cat'}, ) - }, - 'M2M_REGISTRY': { - 'app.BModel': 'categories', - 'app.MyModel': ('other_categories', 'more_categories', ), - } - } - -The ``FK_REGISTRY`` is a dictionary whose keys are the model to which to add the new field(s). The value is a string or tuple of strings or dictionaries specifying the necessary information for each field. - -The ``M2M_REGISTRY`` is a dictionary whose keys are the model to which to add the new field(s). The value is a string or tuple of strings specifying the necessary information for each field. - - -Registering one Category field to model -*************************************** - -The simplest way is to specify the name of the field, such as: - -.. code-block:: python - - CATEGORIES_SETTINGS = { - 'FK_REGISTRY': { - 'app.AModel': 'category' - } - } - -This is equivalent to adding the following the ``AModel`` of ``app``\ : - -.. code-block:: python - - category = models.ForeignKey(Category) - - -If you want more control over the new field, you can use a dictionary and pass other ``ForeignKey`` options. The ``name`` key is required: - -.. code-block:: python - - CATEGORIES_SETTINGS = { - 'FK_REGISTRY': { - 'app.AModel': {'name': 'category', 'related_name': 'amodel_cats'} - } - } - -This is equivalent to adding the following the ``AModel`` of ``app``\ : - -.. code-block:: python - - category = models.ForeignKey(Category, related_name='amodel_cats') - -Registering two or more Category fields to a Model -************************************************** - -When you want more than one relation to ``Category``\ , all but one of the fields must specify a ``related_name`` to avoid conflicts, like so: - -.. code-block:: python - - CATEGORIES_SETTINGS = { - 'FK_REGISTRY': { - 'app.MyModel': ( - 'primary_category', - {'name': 'secondary_category', 'related_name': 'mymodel_sec_cat'}, ) - }, - -Registering one or more Many-to-Many Category fields to a Model -*************************************************************** - -.. code-block:: python - - CATEGORIES_SETTINGS = { - 'M2M_REGISTRY': { - 'app.AModel': 'categories', - 'app.MyModel': ( - {'name': 'other_categories', 'related_name': 'other_cats'}, - {'name': 'more_categories', 'related_name': 'more_cats'}, - ), - } - } - -.. _registering_a_m2one_relationship: - -Registering a many-to-one relationship -====================================== - -To create a many-to-one relationship (foreign key) between a model and Django Categories, you register your model with the ``register_fk`` function. - -.. py:function:: register_fk(model, field_name='category', extra_params={}]) - - :param model: The Django Model to link to Django Categories - :param field_name: Optional name for the field **default:** category - :param extra_params: Optional dictionary of extra parameters passed to the ``ForeignKey`` class. - -Example, in your ``models.py``:: - - import categories - categories.register_fk(MyModel) - -If you want more than one field on a model you have to have some extra arguments:: - - import categories - categories.register_fk(MyModel, 'primary_category') - categories.register_fk(MyModel, 'secondary_category', {'related_name':'mymodel_sec_cat'}) - -The ``extra_args`` allows you to specify the related_name of one of the fields so it doesn't clash. - - -Registering a many-to-many relationship -======================================= - -To create a many-to-many relationship between a model and Django Categories, you register your model with the ``register_m2m`` function. - -.. py:function:: register_m2m(model, field_name='categories', extra_params={}]) - - :param model: The Django Model to link to Django Categories - :param field_name: Optional name for the field **default:** categories - :param extra_params: Optional dictionary of extra parameters passed to the ``ManyToManyField`` class. - -Example, in your ``models.py``:: - - import categories - categories.register_m2m(MyModel) diff --git a/docs/_sources/usage.txt b/docs/_sources/usage.txt deleted file mode 100644 index c54c3b2..0000000 --- a/docs/_sources/usage.txt +++ /dev/null @@ -1,62 +0,0 @@ -============================= -Using categories in templates -============================= - - -Getting all items within a category -=================================== - -The :py:class:`Category` model automatically gets `reverse relationships `_ with all other models related to it. - -This allows you access to the related objects from the template without altering any views. For example, if you only had ``Entry`` models related to :py:class:`Category`, your ``categories/category_detail.html`` template could look like - -.. literalinclude:: usage_example_template.html - :language: django - :linenos: - - -If you have ``related_name`` parameters to the configuration (see :ref:`registering_models`), then you would use ``category.related_name.all`` instead of ``category.relatedmodel_set.all``\ . - - -Template Tags -============= - -To use the template tags:: - - {% import category_tags %} - - -``tree_info`` -------------- - -Given a list of categories, iterates over the list, generating -two-tuples of the current tree item and a ``dict`` containing -information about the tree structure around the item, with the following -keys: - - ``'new_level'`` - ``True`` if the current item is the start of a new level in - the tree, ``False`` otherwise. - - ``'closed_levels'`` - A list of levels which end after the current item. This will - be an empty list if the next item's level is the same as or - greater than the level of the current item. - -An optional argument can be provided to specify extra details about the -structure which should appear in the ``dict``. This should be a -comma-separated list of feature names. The valid feature names are: - - ancestors - Adds a list of unicode representations of the ancestors of the - current node, in descending order (root node first, immediate - parent last), under the key ``'ancestors'``. - - For example: given the sample tree below, the contents of the list - which would be available under the ``'ancestors'`` key are given - on the right:: - - Books -> [] - Sci-fi -> [u'Books'] - Dystopian Futures -> [u'Books', u'Sci-fi'] - From 510b21ee93946b05799766b30c75370e0c4ed1f2 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sun, 12 Dec 2021 08:19:38 -0600 Subject: [PATCH 23/51] Added requirements to MANIFEST.in --- MANIFEST.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index 26b3af9..bc24de9 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -14,5 +14,5 @@ include doc_src/make.bat recursive-include categories/locale *.mo *.po recursive-include categories/editor/locale *.mo *.po - +recursive-include requirements/*.txt prune example From f470e38cc218ac6eab56ede0de859f9b0ff35060 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sun, 12 Dec 2021 08:31:36 -0600 Subject: [PATCH 24/51] Fixed the MANIFEST.in file. --- MANIFEST.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index bc24de9..e6535cf 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -9,10 +9,11 @@ recursive-include categories/static *.html *.gif *.png *.css *.txt *.js recursive-include categories/editor *.html *.gif *.png *.css *.js recursive-include doc_src *.rst *.txt *.png *.css *.html *.js +recursive-exclude doc_src/_build *.* include doc_src/Makefile include doc_src/make.bat recursive-include categories/locale *.mo *.po recursive-include categories/editor/locale *.mo *.po -recursive-include requirements/*.txt +recursive-include requirements *.txt prune example From acdae7b1d4b78ff36bcd3ca07c6b8c251fb23488 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sun, 12 Dec 2021 08:33:53 -0600 Subject: [PATCH 25/51] Added TOML support for coverage --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 075aaf2..333d5a4 100644 --- a/tox.ini +++ b/tox.ini @@ -22,7 +22,7 @@ deps= django3: Django>=3.0,<3.1 django31: Django>=3.1,<3.2 django111: Django>=1.11,<1.12 - coverage + coverage[toml] pillow ipdb codecov From 45d47ab6463b5a7deb9392d1cea6df91831c9fc4 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sun, 12 Dec 2021 08:45:41 -0600 Subject: [PATCH 26/51] Fixed the tests --- .gitignore | 2 +- categories/tests/test_templatetags.py | 2 +- example/settings-testing.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index f13af1c..a8acde2 100644 --- a/.gitignore +++ b/.gitignore @@ -167,7 +167,7 @@ output/*/index.html # Testing artifacts junit-*.xml flake8-errors.txt - +example/media/ # Documentation building _build doc_src/api/categories*.rst diff --git a/categories/tests/test_templatetags.py b/categories/tests/test_templatetags.py index ffe967c..2d419a3 100644 --- a/categories/tests/test_templatetags.py +++ b/categories/tests/test_templatetags.py @@ -45,7 +45,7 @@ class CategoryTagsTest(TestCase): self.assertEqual(resp, expected_resp) # breadcrumbs - expected_resp = 'World > Worldbeat' + expected_resp = 'World > Worldbeat\n' resp = self.render_template( "{% load category_tags %}" '{% breadcrumbs "/World/Worldbeat" " > " "categories.category" %}' ) diff --git a/example/settings-testing.py b/example/settings-testing.py index ba91a32..2105458 100644 --- a/example/settings-testing.py +++ b/example/settings-testing.py @@ -42,7 +42,7 @@ INSTALLED_APPS = ( ) TIME_ZONE = "America/Chicago" - +DEFAULT_AUTO_FIELD = "django.db.models.AutoField" LANGUAGE_CODE = "en-us" SITE_ID = 1 From 2d6905486d0c39e27c270df19e540399d1de6781 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Sun, 12 Dec 2021 08:52:22 -0600 Subject: [PATCH 27/51] Changed flake8 to use config files --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 333d5a4..53dd214 100644 --- a/tox.ini +++ b/tox.ini @@ -48,7 +48,7 @@ deps= flake8 commands= - flake8 . --ignore=E501 --exclude=build/,dist/,.tox/,doc_src + flake8 [testenv:coverage-report] commands = From f9a46848b23b571826f3592ad94031ca60e9e837 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Wed, 22 Dec 2021 12:02:54 -0600 Subject: [PATCH 28/51] Updated project configurations - pre-commit to ignore certain files - ignore some documentation errors --- .pre-commit-config.yaml | 4 +++- pyproject.toml | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9e54b49..5da5536 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,7 @@ repos: rev: 6.1.1 hooks: - id: pydocstyle - exclude: test.* + exclude: test.*|custom_.*|\d\d\d\d_.* additional_dependencies: [toml] - repo: https://github.com/terrencepreilly/darglint rev: v1.8.1 @@ -45,6 +45,8 @@ repos: - -v 2 - "--message-template={path}:{line} in `{obj}`:\n {msg_id}: {msg}" - --strictness=short + exclude: test.*|custom_.*|\d\d\d\d_.* + - repo: https://github.com/econchick/interrogate rev: 1.5.0 # or master if you're bold hooks: diff --git a/pyproject.toml b/pyproject.toml index 126de67..1cb253a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,7 +32,7 @@ ignore-module = false ignore-nested-functions = true ignore-nested-classes = true ignore-setters = false -fail-under = 95 +fail-under = 60 exclude = ["setup.py", "docs", "build", "test"] ignore-regex = ["^get$", "^mock_.*", ".*BaseClass.*"] verbose = 0 @@ -55,7 +55,7 @@ color_output = true [tool.pydocstyle] convention = "google" -add-ignore = ["D107", "D200", "D212"] +add-ignore = ["D104", "D105", "D106", "D107", "D200", "D212"] match = "(?!test_).*\\.py" [tool.black] From 076debb44d6426f05fa804746046b1b0678e7162 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Wed, 22 Dec 2021 12:03:21 -0600 Subject: [PATCH 29/51] Adds doc strings for lots of functions. --- categories/admin.py | 15 +- categories/apps.py | 6 +- categories/base.py | 51 +++-- categories/editor/models.py | 2 +- categories/editor/settings.py | 1 + .../templatetags/admin_tree_list_tags.py | 15 +- categories/editor/tree_editor.py | 67 ++++-- categories/editor/utils.py | 3 +- categories/fields.py | 14 +- categories/genericcollection.py | 9 + .../commands/add_category_fields.py | 7 +- .../commands/drop_category_field.py | 6 +- .../management/commands/import_categories.py | 22 +- categories/migration.py | 7 +- categories/models.py | 15 +- categories/registration.py | 47 +++- categories/settings.py | 1 + categories/templatetags/category_tags.py | 205 +++++++++++++----- categories/urls.py | 1 + categories/views.py | 22 +- example/manage.py | 1 + example/settings.py | 2 +- example/simpletext/admin.py | 7 + example/simpletext/models.py | 6 +- example/simpletext/views.py | 2 +- example/urls.py | 1 + 26 files changed, 380 insertions(+), 155 deletions(-) mode change 100755 => 100644 example/simpletext/models.py mode change 100755 => 100644 example/simpletext/views.py diff --git a/categories/admin.py b/categories/admin.py index 5c11755..abf3f72 100644 --- a/categories/admin.py +++ b/categories/admin.py @@ -1,3 +1,4 @@ +"""Admin interface classes.""" from django import forms from django.contrib import admin from django.utils.translation import ugettext_lazy as _ @@ -15,10 +16,9 @@ class NullTreeNodeChoiceField(forms.ModelChoiceField): self.level_indicator = level_indicator super(NullTreeNodeChoiceField, self).__init__(*args, **kwargs) - def label_from_instance(self, obj): + def label_from_instance(self, obj) -> str: """ - Creates labels which represent the tree level of each node when - generating option labels. + Creates labels which represent the tree level of each node when generating option labels. """ return "%s %s" % (self.level_indicator * getattr(obj, obj._mptt_meta.level_attr), obj) @@ -27,15 +27,20 @@ if RELATION_MODELS: from .models import CategoryRelation class InlineCategoryRelation(GenericCollectionTabularInline): + """The inline admin panel for category relations.""" + model = CategoryRelation class CategoryAdminForm(CategoryBaseAdminForm): + """The form for a category in the admin.""" + class Meta: model = Category fields = "__all__" - def clean_alternate_title(self): + def clean_alternate_title(self) -> str: + """Return either the name or alternate title for the category.""" if self.instance is None or not self.cleaned_data["alternate_title"]: return self.cleaned_data["name"] else: @@ -43,6 +48,8 @@ class CategoryAdminForm(CategoryBaseAdminForm): class CategoryAdmin(CategoryBaseAdmin): + """Admin for categories.""" + form = CategoryAdminForm list_display = ("name", "alternate_title", "active") fieldsets = ( diff --git a/categories/apps.py b/categories/apps.py index 1bc058e..5f58385 100644 --- a/categories/apps.py +++ b/categories/apps.py @@ -1,7 +1,10 @@ +"""Django application setup.""" from django.apps import AppConfig class CategoriesConfig(AppConfig): + """Application configuration for categories.""" + name = "categories" verbose_name = "Categories" @@ -12,6 +15,7 @@ class CategoriesConfig(AppConfig): class_prepared.connect(handle_class_prepared) def ready(self): + """Migrate the app after it is ready.""" from django.db.models.signals import post_migrate from .migration import migrate_app @@ -21,7 +25,7 @@ class CategoriesConfig(AppConfig): def handle_class_prepared(sender, **kwargs): """ - See if this class needs registering of fields + See if this class needs registering of fields. """ from .registration import registry from .settings import FK_REGISTRY, M2M_REGISTRY diff --git a/categories/base.py b/categories/base.py index 9517565..f2e5521 100644 --- a/categories/base.py +++ b/categories/base.py @@ -1,9 +1,8 @@ """ -This is the base class on which to build a hierarchical category-like model -with customizable metadata and its own name space. -""" -import sys +This is the base class on which to build a hierarchical category-like model. +It provides customizable metadata and its own name space. +""" from django import forms from django.contrib import admin from django.db import models @@ -17,31 +16,24 @@ from slugify import slugify from .editor.tree_editor import TreeEditor from .settings import ALLOW_SLUG_CHANGE, SLUG_TRANSLITERATOR -if sys.version_info[0] < 3: # Remove this after dropping support of Python 2 - from django.utils.encoding import python_2_unicode_compatible -else: - - def python_2_unicode_compatible(x): - return x - class CategoryManager(models.Manager): """ - A manager that adds an "active()" method for all active categories + A manager that adds an "active()" method for all active categories. """ def active(self): """ - Only categories that are active + Only categories that are active. """ return self.get_queryset().filter(active=True) -@python_2_unicode_compatible class CategoryBase(MPTTModel): """ - This base model includes the absolute bare bones fields and methods. One - could simply subclass this model and do nothing else and it should work. + This base model includes the absolute bare-bones fields and methods. + + One could simply subclass this model, do nothing else, and it should work. """ parent = TreeForeignKey( @@ -61,9 +53,15 @@ class CategoryBase(MPTTModel): def save(self, *args, **kwargs): """ + Save the category. + While you can activate an item without activating its descendants, It doesn't make sense that you can deactivate an item and have its decendants remain active. + + Args: + args: generic args + kwargs: generic keyword arguments """ if not self.slug: self.slug = slugify(SLUG_TRANSLITERATOR(self.name))[:50] @@ -95,14 +93,16 @@ class CategoryBase(MPTTModel): class CategoryBaseAdminForm(forms.ModelForm): + """Base admin form for categories.""" + def clean_slug(self): - if not self.cleaned_data.get("slug", None): - if self.instance is None or not ALLOW_SLUG_CHANGE: - self.cleaned_data["slug"] = slugify(SLUG_TRANSLITERATOR(self.cleaned_data["name"])) + """Prune and transliterate the slug.""" + if not self.cleaned_data.get("slug", None) and (self.instance is None or not ALLOW_SLUG_CHANGE): + self.cleaned_data["slug"] = slugify(SLUG_TRANSLITERATOR(self.cleaned_data["name"])) return self.cleaned_data["slug"][:50] def clean(self): - + """Clean the data passed from the admin interface.""" super(CategoryBaseAdminForm, self).clean() if not self.is_valid(): @@ -141,6 +141,8 @@ class CategoryBaseAdminForm(forms.ModelForm): class CategoryBaseAdmin(TreeEditor, admin.ModelAdmin): + """Base admin class for categories.""" + form = CategoryBaseAdminForm list_display = ("name", "active") search_fields = ("name",) @@ -149,14 +151,15 @@ class CategoryBaseAdmin(TreeEditor, admin.ModelAdmin): actions = ["activate", "deactivate"] def get_actions(self, request): + """Get available actions for the admin interface.""" actions = super(CategoryBaseAdmin, self).get_actions(request) if "delete_selected" in actions: del actions["delete_selected"] return actions - def deactivate(self, request, queryset): + def deactivate(self, request, queryset): # NOQA: queryset is not used. """ - Set active to False for selected items + Set active to False for selected items. """ selected_cats = self.model.objects.filter(pk__in=[int(x) for x in request.POST.getlist("_selected_action")]) @@ -168,9 +171,9 @@ class CategoryBaseAdmin(TreeEditor, admin.ModelAdmin): deactivate.short_description = _("Deactivate selected categories and their children") - def activate(self, request, queryset): + def activate(self, request, queryset): # NOQA: queryset is not used. """ - Set active to True for selected items + Set active to True for selected items. """ selected_cats = self.model.objects.filter(pk__in=[int(x) for x in request.POST.getlist("_selected_action")]) diff --git a/categories/editor/models.py b/categories/editor/models.py index 3542496..8c35c95 100644 --- a/categories/editor/models.py +++ b/categories/editor/models.py @@ -1 +1 @@ -# Placeholder for Django +"""Placeholder for Django.""" diff --git a/categories/editor/settings.py b/categories/editor/settings.py index 5ea2e61..164cf21 100644 --- a/categories/editor/settings.py +++ b/categories/editor/settings.py @@ -1,3 +1,4 @@ +"""Settings management for the editor.""" import django from django.conf import settings diff --git a/categories/editor/templatetags/admin_tree_list_tags.py b/categories/editor/templatetags/admin_tree_list_tags.py index 160752b..11088c4 100644 --- a/categories/editor/templatetags/admin_tree_list_tags.py +++ b/categories/editor/templatetags/admin_tree_list_tags.py @@ -1,3 +1,4 @@ +"""Template tags used to render the tree editor.""" import django from django.contrib.admin.templatetags.admin_list import _boolean_icon, result_headers from django.contrib.admin.utils import lookup_field @@ -19,13 +20,14 @@ if settings.IS_GRAPPELLI_INSTALLED: def get_empty_value_display(cl): + """Get the value to display when empty.""" if hasattr(cl.model_admin, "get_empty_value_display"): return cl.model_admin.get_empty_value_display() - else: - # Django < 1.9 - from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE - return EMPTY_CHANGELIST_VALUE + # Django < 1.9 + from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE + + return EMPTY_CHANGELIST_VALUE def items_for_tree_result(cl, result, form): @@ -130,10 +132,13 @@ def items_for_tree_result(cl, result, form): class TreeList(list): + """A list subclass for tree result.""" + pass def tree_results(cl): + """Generates a list of results for the tree.""" if cl.formset: for res, form in zip(cl.result_list, cl.formset.forms): result = TreeList(items_for_tree_result(cl, res, form)) @@ -158,7 +163,7 @@ def tree_results(cl): def result_tree_list(cl): """ - Displays the headers and data list together + Displays the headers and data list together. """ import django diff --git a/categories/editor/tree_editor.py b/categories/editor/tree_editor.py index 2d64b51..d528c95 100644 --- a/categories/editor/tree_editor.py +++ b/categories/editor/tree_editor.py @@ -1,3 +1,6 @@ +"""Classes for representing tree structures in Django's admin.""" +from typing import Any + import django from django.contrib import admin from django.contrib.admin.options import IncorrectLookupParameters @@ -12,9 +15,9 @@ from . import settings class TreeEditorQuerySet(QuerySet): """ - The TreeEditorQuerySet is a special query set used only in the TreeEditor - ChangeList page. The only difference to a regular QuerySet is that it - will enforce: + A special query set used only in the TreeEditor ChangeList page. + + The only difference to a regular QuerySet is that it will enforce: (a) The result is ordered in correct tree order so that the TreeAdmin works all right. @@ -25,6 +28,7 @@ class TreeEditorQuerySet(QuerySet): """ def iterator(self): + """Iterates through the items in thee query set.""" qs = self # Reaching into the bowels of query sets to find out whether the qs is # actually filtered and we need to do the INCLUDE_ANCESTORS dance at all. @@ -54,18 +58,27 @@ class TreeEditorQuerySet(QuerySet): # def __getitem__(self, index): # return self # Don't even try to slice - def get(self, *args, **kwargs): + def get(self, *args, **kwargs) -> Any: """ - Quick and dirty hack to fix change_view and delete_view; they use - self.queryset(request).get(...) to get the object they should work - with. Our modifications to the queryset when INCLUDE_ANCESTORS is - enabled make get() fail often with a MultipleObjectsReturned - exception. + Quick and dirty hack to fix change_view and delete_view. + + They use ``self.queryset(request).get(...)`` to get the object they should work + with. Our modifications to the queryset when ``INCLUDE_ANCESTORS`` is enabled make ``get()`` + fail often with a ``MultipleObjectsReturned`` exception. + + Args: + args: generic arguments + kwargs: generic keyword arguments + + Returns: + The object they should work with. """ return self.model._default_manager.get(*args, **kwargs) class TreeChangeList(ChangeList): + """A change list for a tree.""" + def _get_default_ordering(self): if django.VERSION[0] == 1 and django.VERSION[1] < 4: return "", "" # ('tree_id', 'lft') @@ -73,17 +86,31 @@ class TreeChangeList(ChangeList): return [] def get_ordering(self, request=None, queryset=None): + """ + Return ordering information for the change list. + + Always returns empty/default ordering. + + Args: + request: The incoming request. + queryset: The current queryset + + Returns: + Either a tuple of empty strings or an empty list. + """ if django.VERSION[0] == 1 and django.VERSION[1] < 4: return "", "" # ('tree_id', 'lft') else: return [] def get_queryset(self, *args, **kwargs): - qs = super(TreeChangeList, self).get_queryset(*args, **kwargs).order_by("tree_id", "lft") - return qs + """Return a queryset.""" + return super(TreeChangeList, self).get_queryset(*args, **kwargs).order_by("tree_id", "lft") class TreeEditor(admin.ModelAdmin): + """A tree editor view for Django's admin.""" + list_per_page = 999999999 # We can't have pagination list_max_show_all = 200 # new in django 1.4 @@ -120,7 +147,7 @@ class TreeEditor(admin.ModelAdmin): return TreeChangeList def old_changelist_view(self, request, extra_context=None): - "The 'change list' admin view for this model." + """The 'change list' admin view for this model.""" from django.contrib.admin.views.main import ERROR_FLAG from django.core.exceptions import PermissionDenied from django.utils.encoding import force_text @@ -302,8 +329,7 @@ class TreeEditor(admin.ModelAdmin): def changelist_view(self, request, extra_context=None, *args, **kwargs): """ - Handle the changelist view, the django view for the model instances - change list/actions page. + Handle the changelist view, the django view for the model instances change list/actions page. """ extra_context = extra_context or {} extra_context["EDITOR_MEDIA_PATH"] = settings.MEDIA_PATH @@ -312,10 +338,17 @@ class TreeEditor(admin.ModelAdmin): # FIXME return self.old_changelist_view(request, extra_context) - def get_queryset(self, request): + def get_queryset(self, request) -> TreeEditorQuerySet: """ - Returns a QuerySet of all model instances that can be edited by the - admin site. This is used by changelist_view. + Returns a QuerySet of all model instances that can be edited by the admin site. + + This is used by changelist_view. + + Args: + request: the incoming request. + + Returns: + A QuerySet of editable model instances """ qs = self.model._default_manager.get_queryset() qs.__class__ = TreeEditorQuerySet diff --git a/categories/editor/utils.py b/categories/editor/utils.py index dab0511..3ce0165 100644 --- a/categories/editor/utils.py +++ b/categories/editor/utils.py @@ -1,10 +1,11 @@ """ -Provides compatibility with Django 1.8 +Provides compatibility with Django 1.8. """ from django.contrib.admin.utils import display_for_field as _display_for_field def display_for_field(value, field, empty_value_display=None): + """Compatility for displaying a field in Django 1.8.""" try: return _display_for_field(value, field, empty_value_display) except TypeError: diff --git a/categories/fields.py b/categories/fields.py index 719b72e..12f254e 100644 --- a/categories/fields.py +++ b/categories/fields.py @@ -1,7 +1,10 @@ +"""Custom category fields for other models.""" from django.db.models import ForeignKey, ManyToManyField class CategoryM2MField(ManyToManyField): + """A many to many field to a Category model.""" + def __init__(self, **kwargs): from .models import Category @@ -11,18 +14,11 @@ class CategoryM2MField(ManyToManyField): class CategoryFKField(ForeignKey): + """A foreign key to the Category model.""" + def __init__(self, **kwargs): from .models import Category if "to" in kwargs: kwargs.pop("to") super(CategoryFKField, self).__init__(to=Category, **kwargs) - - -try: - from south.modelsinspector import add_introspection_rules - - add_introspection_rules([], [r"^categories\.fields\.CategoryFKField"]) - add_introspection_rules([], [r"^categories\.fields\.CategoryM2MField"]) -except ImportError: - pass diff --git a/categories/genericcollection.py b/categories/genericcollection.py index 1745914..7eab863 100644 --- a/categories/genericcollection.py +++ b/categories/genericcollection.py @@ -1,3 +1,4 @@ +"""Special helpers for generic collections.""" import json from django.contrib import admin @@ -6,10 +7,13 @@ from django.urls import NoReverseMatch, reverse class GenericCollectionInlineModelAdmin(admin.options.InlineModelAdmin): + """Inline admin for generic model collections.""" + ct_field = "content_type" ct_fk_field = "object_id" def get_content_types(self): + """Get the content types supported by this collection.""" ctypes = ContentType.objects.all().order_by("id").values_list("id", "app_label", "model") elements = {} for x, y, z in ctypes: @@ -20,6 +24,7 @@ class GenericCollectionInlineModelAdmin(admin.options.InlineModelAdmin): return json.dumps(elements) def get_formset(self, request, obj=None, **kwargs): + """Get the formset for the generic collection.""" result = super(GenericCollectionInlineModelAdmin, self).get_formset(request, obj, **kwargs) result.content_types = self.get_content_types() result.ct_fk_field = self.ct_fk_field @@ -30,8 +35,12 @@ class GenericCollectionInlineModelAdmin(admin.options.InlineModelAdmin): class GenericCollectionTabularInline(GenericCollectionInlineModelAdmin): + """Tabular model admin for a generic collection.""" + template = "admin/edit_inline/gen_coll_tabular.html" class GenericCollectionStackedInline(GenericCollectionInlineModelAdmin): + """Stacked model admin for a generic collection.""" + template = "admin/edit_inline/gen_coll_stacked.html" diff --git a/categories/management/commands/add_category_fields.py b/categories/management/commands/add_category_fields.py index 377f5e5..de315a4 100644 --- a/categories/management/commands/add_category_fields.py +++ b/categories/management/commands/add_category_fields.py @@ -1,9 +1,10 @@ +"""The add_category_fields command.""" from django.core.management.base import BaseCommand class Command(BaseCommand): """ - Alter one or more models' tables with the registered attributes + Alter one or more models' tables with the registered attributes. """ help = "Alter the tables for all registered models, or just specified models" @@ -12,13 +13,13 @@ class Command(BaseCommand): requires_system_checks = False def add_arguments(self, parser): + """Add app_names argument to the command.""" parser.add_argument("app_names", nargs="*") def handle(self, *args, **options): """ - Alter the tables + Alter the tables. """ - from categories.migration import migrate_app from categories.settings import MODEL_REGISTRY diff --git a/categories/management/commands/drop_category_field.py b/categories/management/commands/drop_category_field.py index f10a220..ca48b39 100644 --- a/categories/management/commands/drop_category_field.py +++ b/categories/management/commands/drop_category_field.py @@ -1,9 +1,10 @@ +"""Alter one or more models' tables with the registered attributes.""" from django.core.management.base import BaseCommand, CommandError class Command(BaseCommand): """ - Alter one or more models' tables with the registered attributes + Alter one or more models' tables with the registered attributes. """ help = "Drop the given field from the given model's table" @@ -12,13 +13,14 @@ class Command(BaseCommand): requires_system_checks = False def add_arguments(self, parser): + """Add app_name, model_name, and field_name arguments to the command.""" parser.add_argument("app_name") parser.add_argument("model_name") parser.add_argument("field_name") def handle(self, *args, **options): """ - Alter the tables + Alter the tables. """ from categories.migration import drop_field diff --git a/categories/management/commands/import_categories.py b/categories/management/commands/import_categories.py index 6009afb..b41469e 100644 --- a/categories/management/commands/import_categories.py +++ b/categories/management/commands/import_categories.py @@ -1,3 +1,5 @@ +"""Import category trees from a file.""" + from django.core.management.base import BaseCommand, CommandError from django.db import transaction from slugify import slugify @@ -16,7 +18,7 @@ class Command(BaseCommand): def get_indent(self, string): """ - Look through the string and count the spaces + Look through the string and count the spaces. """ indent_amt = 0 @@ -31,7 +33,7 @@ class Command(BaseCommand): @transaction.atomic def make_category(self, string, parent=None, order=1): """ - Make and save a category object from a string + Make and save a category object from a string. """ cat = Category( name=string.strip(), @@ -48,12 +50,12 @@ class Command(BaseCommand): def parse_lines(self, lines): """ - Do the work of parsing each line + Do the work of parsing each line. """ indent = "" level = 0 - if lines[0][0] == " " or lines[0][0] == "\t": + if lines[0][0] in [" ", "\t"]: raise CommandError("The first line in the file cannot start with a space or tab.") # This keeps track of the current parents at a given level @@ -62,10 +64,10 @@ class Command(BaseCommand): for line in lines: if len(line) == 0: continue - if line[0] == " " or line[0] == "\t": + if line[0] in [" ", "\t"]: if indent == "": indent = self.get_indent(line) - elif not line[0] in indent: + elif line[0] not in indent: raise CommandError("You can't mix spaces and tabs for indents") level = line.count(indent) current_parents[level] = self.make_category(line, parent=current_parents[level - 1]) @@ -76,7 +78,7 @@ class Command(BaseCommand): def handle(self, *file_paths, **options): """ - Handle the basic import + Handle the basic import. """ import os @@ -84,8 +86,6 @@ class Command(BaseCommand): if not os.path.isfile(file_path): print("File %s not found." % file_path) continue - f = open(file_path, "r") - data = f.readlines() - f.close() - + with open(file_path, "r") as f: + data = f.readlines() self.parse_lines(data) diff --git a/categories/migration.py b/categories/migration.py index ac4f36c..13ff0c5 100644 --- a/categories/migration.py +++ b/categories/migration.py @@ -1,3 +1,4 @@ +"""Adds and removes category relations on the database.""" from django.apps import apps from django.db import connection, transaction from django.db.utils import ProgrammingError @@ -5,7 +6,7 @@ from django.db.utils import ProgrammingError def table_exists(table_name): """ - Check if a table exists in the database + Check if a table exists in the database. """ pass @@ -33,7 +34,7 @@ def field_exists(app_name, model_name, field_name): def drop_field(app_name, model_name, field_name): """ - Drop the given field from the app's model + Drop the given field from the app's model. """ app_config = apps.get_app_config(app_name) model = app_config.get_model(model_name) @@ -44,7 +45,7 @@ def drop_field(app_name, model_name, field_name): def migrate_app(sender, *args, **kwargs): """ - Migrate all models of this app registered + Migrate all models of this app registered. """ from .registration import registry diff --git a/categories/models.py b/categories/models.py index 3789de6..0cba3fb 100644 --- a/categories/models.py +++ b/categories/models.py @@ -1,3 +1,4 @@ +"""Category models.""" from functools import reduce from django.contrib.contenttypes.models import ContentType @@ -26,6 +27,8 @@ STORAGE = get_storage_class(THUMBNAIL_STORAGE) class Category(CategoryBase): + """A basic category model.""" + thumbnail = models.FileField( upload_to=THUMBNAIL_UPLOAD_PATH, null=True, @@ -53,10 +56,11 @@ class Category(CategoryBase): @property def short_title(self): + """Return the name.""" return self.name def get_absolute_url(self): - """Return a path""" + """Return a path.""" from django.urls import NoReverseMatch if self.alternate_url: @@ -74,17 +78,18 @@ class Category(CategoryBase): def get_related_content_type(self, content_type): """ - Get all related items of the specified content type + Get all related items of the specified content type. """ return self.categoryrelation_set.filter(content_type__name=content_type) def get_relation_type(self, relation_type): """ - Get all relations of the specified relation type + Get all relations of the specified relation type. """ return self.categoryrelation_set.filter(relation_type=relation_type) def save(self, *args, **kwargs): + """Save the category.""" if self.thumbnail: width, height = get_image_dimensions(self.thumbnail.file) else: @@ -110,6 +115,8 @@ else: class CategoryRelationManager(models.Manager): + """Custom access functions for category relations.""" + def get_content_type(self, content_type): """ Get all the items of the given content type related to this item. @@ -126,7 +133,7 @@ class CategoryRelationManager(models.Manager): class CategoryRelation(models.Model): - """Related category item""" + """Related category item.""" category = models.ForeignKey(Category, verbose_name=_("category"), on_delete=models.CASCADE) content_type = models.ForeignKey( diff --git a/categories/registration.py b/categories/registration.py index d871e14..793c908 100644 --- a/categories/registration.py +++ b/categories/registration.py @@ -1,6 +1,10 @@ """ -These functions handle the adding of fields to other models +These functions handle the adding of fields to other models. """ +from typing import Optional, Type, Union + +import collections + from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured from django.db.models import CASCADE, ForeignKey, ManyToManyField @@ -16,17 +20,26 @@ FIELD_TYPES = { class Registry(object): + """Keeps track of fields and models registered.""" + def __init__(self): self._field_registry = {} self._model_registry = {} - def register_model(self, app, model_name, field_type, field_definitions): + def register_model( + self, app: str, model_name, field_type: str, field_definitions: Union[str, collections.Iterable] + ): """ - Process for Django 1.7 + - app: app name/label - model_name: name of the model - field_definitions: a string, tuple or list of field configurations - field_type: either 'ForeignKey' or 'ManyToManyField' + Registration process for Django 1.7+. + + Args: + app: app name/label + model_name: name of the model + field_definitions: a string, tuple or list of field configurations + field_type: either 'ForeignKey' or 'ManyToManyField' + + Raises: + ImproperlyConfigured: For incorrect parameter types or missing model. """ import collections @@ -93,14 +106,26 @@ class Registry(object): self._field_registry[registry_name] = FIELD_TYPES[field_type](**extra_params) self._field_registry[registry_name].contribute_to_class(model, field_name) - def register_m2m(self, model, field_name="categories", extra_params={}): + def register_m2m(self, model, field_name: str = "categories", extra_params: Optional[dict] = None): + """Register a field name to the model as a many to many field.""" + extra_params = extra_params or {} return self._register(model, field_name, extra_params, fields.CategoryM2MField) - def register_fk(self, model, field_name="category", extra_params={}): + def register_fk(self, model, field_name: str = "category", extra_params: Optional[dict] = None): + """Register a field name to the model as a foreign key.""" + extra_params = extra_params or {} return self._register(model, field_name, extra_params, fields.CategoryFKField) - def _register(self, model, field_name, extra_params={}, field=fields.CategoryFKField): + def _register( + self, + model, + field_name: str, + extra_params: Optional[dict] = None, + field: Type = fields.CategoryFKField, + ): + """Does the heavy lifting for registering a field to a model.""" app_label = model._meta.app_label + extra_params = extra_params or {} registry_name = ".".join((app_label, model.__name__, field_name)).lower() if registry_name in self._field_registry: @@ -122,7 +147,7 @@ registry = Registry() def _process_registry(registry, call_func): """ - Given a dictionary, and a registration function, process the registry + Given a dictionary, and a registration function, process the registry. """ from django.apps import apps from django.core.exceptions import ImproperlyConfigured diff --git a/categories/settings.py b/categories/settings.py index 2fedf6f..03519fe 100644 --- a/categories/settings.py +++ b/categories/settings.py @@ -1,3 +1,4 @@ +"""Manages settings for the categories application.""" import collections from django.conf import settings diff --git a/categories/templatetags/category_tags.py b/categories/templatetags/category_tags.py index a93f70e..460509a 100644 --- a/categories/templatetags/category_tags.py +++ b/categories/templatetags/category_tags.py @@ -1,3 +1,6 @@ +"""Template tags for categories.""" +from typing import Any, Type, Union + from django import template from django.apps import apps from django.template import Node, TemplateSyntaxError, VariableDoesNotExist @@ -9,7 +12,6 @@ from mptt.templatetags.mptt_tags import ( tree_path, ) from mptt.utils import drilldown_tree_for_node -from six import string_types from categories.base import CategoryBase from categories.models import Category @@ -21,7 +23,8 @@ register.filter(tree_info) register.tag("full_tree_for_category", full_tree_for_model) -def resolve(var, context): +def resolve(var: Any, context: dict) -> Any: + """Aggressively resolve a variable.""" try: return var.resolve(context) except VariableDoesNotExist: @@ -33,10 +36,11 @@ def resolve(var, context): def get_cat_model(model): """ - Return a class from a string or class + Return a class from a string or class. """ + model_class = None try: - if isinstance(model, string_types): + if isinstance(model, str): model_class = apps.get_model(*model.split(".")) elif issubclass(model, CategoryBase): model_class = model @@ -47,9 +51,16 @@ def get_cat_model(model): return model_class -def get_category(category_string, model=Category): +def get_category(category_string, model: Union[str, Type] = Category) -> Any: """ - Convert a string, including a path, and return the Category object + Convert a string, including a path, and return the Category object. + + Args: + category_string: The name or path of the category + model: The name of or Category model to search in + + Returns: + The found category object or None if no category was found """ model_class = get_cat_model(model) category = str(category_string).strip("'\"") @@ -66,31 +77,31 @@ def get_category(category_string, model=Category): # if the parent matches the parent passed in the string if len(categories) == 1: return categories[0] - else: - for item in categories: - if item.parent.name == cat_list[-2]: - return item + + for item in categories: + if item.parent.name == cat_list[-2]: + return item except model_class.DoesNotExist: return None class CategoryDrillDownNode(template.Node): + """A category drill down template node.""" + def __init__(self, category, varname, model): self.category = category self.varname = varname self.model = model def render(self, context): + """Render this node.""" category = resolve(self.category, context) if isinstance(category, CategoryBase): cat = category else: cat = get_category(category, self.model) try: - if cat is not None: - context[self.varname] = drilldown_tree_for_node(cat) - else: - context[self.varname] = [] + context[self.varname] = drilldown_tree_for_node(cat) if cat is not None else [] except Exception: context[self.varname] = [] return "" @@ -99,8 +110,7 @@ class CategoryDrillDownNode(template.Node): @register.tag def get_category_drilldown(parser, token): """ - Retrieves the specified category, its ancestors and its immediate children - as an iterable. + Retrieves the specified category, its ancestors and its immediate children as an Iterable. Syntax:: @@ -117,6 +127,16 @@ def get_category_drilldown(parser, token): Sets family to:: Grandparent, Parent, Child 1, Child 2, Child n + + Args: + parser: The Django template parser. + token: The tag contents + + Returns: + The recursive tree node. + + Raises: + TemplateSyntaxError: If the tag is malformed. """ bits = token.split_contents() error_str = ( @@ -124,13 +144,14 @@ def get_category_drilldown(parser, token): '"category name" [using "app.Model"] as varname %%} or ' "{%% %(tagname)s category_obj as varname %%}." ) + varname = model = "" if len(bits) == 4: if bits[2] != "as": raise template.TemplateSyntaxError(error_str % {"tagname": bits[0]}) if bits[2] == "as": varname = bits[3].strip("'\"") model = "categories.category" - if len(bits) == 6: + elif len(bits) == 6: if bits[2] not in ("using", "as") or bits[4] not in ("using", "as"): raise template.TemplateSyntaxError(error_str % {"tagname": bits[0]}) if bits[2] == "as": @@ -139,6 +160,8 @@ def get_category_drilldown(parser, token): if bits[2] == "using": varname = bits[5].strip("'\"") model = bits[3].strip("'\"") + else: + raise template.TemplateSyntaxError(error_str % {"tagname": bits[0]}) category = FilterExpression(bits[1], parser) return CategoryDrillDownNode(category, varname, model) @@ -146,10 +169,17 @@ def get_category_drilldown(parser, token): @register.inclusion_tag("categories/breadcrumbs.html") def breadcrumbs(category_string, separator=" > ", using="categories.category"): """ + Render breadcrumbs, using the ``categories/breadcrumbs.html`` template. + {% breadcrumbs category separator="::" using="categories.category" %} - Render breadcrumbs, using the ``categories/breadcrumbs.html`` template, - using the optional ``separator`` argument. + Args: + category_string: A variable reference to or the name of the category to display + separator: The string to separate the categories + using: A variable reference to or the name of the category model to search for. + + Returns: + The inclusion template """ cat = get_category(category_string, using) @@ -159,8 +189,7 @@ def breadcrumbs(category_string, separator=" > ", using="categories.category"): @register.inclusion_tag("categories/ul_tree.html") def display_drilldown_as_ul(category, using="categories.Category"): """ - Render the category with ancestors and children using the - ``categories/ul_tree.html`` template. + Render the category with ancestors and children using the ``categories/ul_tree.html`` template. Example:: @@ -189,6 +218,13 @@ def display_drilldown_as_ul(category, using="categories.Category"): + + Args: + category: A variable reference to or the name of the category to display + using: A variable reference to or the name of the category model to search for. + + Returns: + The inclusion template """ cat = get_category(category, using) if cat is None: @@ -200,19 +236,18 @@ def display_drilldown_as_ul(category, using="categories.Category"): @register.inclusion_tag("categories/ul_tree.html") def display_path_as_ul(category, using="categories.Category"): """ - Render the category with ancestors, but no children using the - ``categories/ul_tree.html`` template. - - Example:: + Render the category with ancestors, but no children using the ``categories/ul_tree.html`` template. + Examples: + ``` {% display_path_as_ul "/Grandparent/Parent" %} - - or :: - + ``` + ``` {% display_path_as_ul category_obj %} + ``` - Returns:: - + Output: + ```
      • Top
          @@ -220,21 +255,32 @@ def display_path_as_ul(category, using="categories.Category"):
      + ``` + + Args: + category: A variable reference to or the name of the category to display + using: A variable reference to or the name of the category model to search for. + + Returns: + The inclusion template """ if isinstance(category, CategoryBase): cat = category else: - cat = get_category(category) + cat = get_category(category, using) return {"category": cat, "path": cat.get_ancestors() or []} class TopLevelCategoriesNode(template.Node): + """Template node for the top level categories.""" + def __init__(self, varname, model): self.varname = varname self.model = model def render(self, context): + """Render this node.""" model = get_cat_model(self.model) context[self.varname] = model.objects.filter(parent=None).order_by("name") return "" @@ -245,14 +291,25 @@ def get_top_level_categories(parser, token): """ Retrieves an alphabetical list of all the categories that have no parents. - Syntax:: + Usage: + ``` {% get_top_level_categories [using "app.Model"] as categories %} + ``` - Returns an list of categories [, , , , - {% recursetree nodes %} -
    • - {{ node.name }} - {% if not node.is_leaf_node %} -
        - {{ children }} -
      - {% endif %} -
    • - {% endrecursetree %} - + ``` +
        + {% recursetree nodes %} +
      • + {{ node.name }} + {% if not node.is_leaf_node %} +
          + {{ children }} +
        + {% endif %} +
      • + {% endrecursetree %} +
      + ``` + + Args: + parser: The Django template parser. + token: The tag contents + + Returns: + The recursive tree node. + + Raises: + TemplateSyntaxError: If a queryset isn't provided. """ bits = token.contents.split() if len(bits) != 2: diff --git a/categories/urls.py b/categories/urls.py index 7160f61..ecb9649 100644 --- a/categories/urls.py +++ b/categories/urls.py @@ -1,3 +1,4 @@ +"""URL patterns for the categories app.""" from django.conf.urls import url from django.views.generic import ListView diff --git a/categories/views.py b/categories/views.py index c92752d..cb81054 100644 --- a/categories/views.py +++ b/categories/views.py @@ -1,3 +1,6 @@ +"""View functions for categories.""" +from typing import Optional + from django.http import Http404, HttpResponse from django.shortcuts import get_object_or_404 from django.template.loader import select_template @@ -7,7 +10,11 @@ from django.views.generic import DetailView, ListView from .models import Category -def category_detail(request, path, template_name="categories/category_detail.html", extra_context={}): +def category_detail( + request, path, template_name="categories/category_detail.html", extra_context: Optional[dict] = None +): + """Render the detail page for a category.""" + extra_context = extra_context or {} path_items = path.strip("/").split("/") if len(path_items) >= 2: category = get_object_or_404( @@ -29,6 +36,7 @@ def category_detail(request, path, template_name="categories/category_detail.htm def get_category_for_path(path, queryset=Category.objects.all()): + """Return the category for a path.""" path_items = path.strip("/").split("/") if len(path_items) >= 2: queryset = queryset.filter( @@ -40,10 +48,13 @@ def get_category_for_path(path, queryset=Category.objects.all()): class CategoryDetailView(DetailView): + """Detail view for a category.""" + model = Category path_field = "path" def get_object(self, **kwargs): + """Get the category.""" if self.path_field not in self.kwargs: raise AttributeError( "Category detail view %s must be called with " "a %s." % (self.__class__.__name__, self.path_field) @@ -58,6 +69,7 @@ class CategoryDetailView(DetailView): ) def get_template_names(self): + """Get the potential template names.""" names = [] path_items = self.kwargs[self.path_field].strip("/").split("/") while path_items: @@ -68,10 +80,13 @@ class CategoryDetailView(DetailView): class CategoryRelatedDetail(DetailView): + """Detailed view for a category relation.""" + path_field = "category_path" object_name_field = None def get_object(self, **kwargs): + """Get the object to render.""" if self.path_field not in self.kwargs: raise AttributeError( "Category detail view %s must be called with " "a %s." % (self.__class__.__name__, self.path_field) @@ -86,6 +101,7 @@ class CategoryRelatedDetail(DetailView): return queryset.get(category=category) def get_template_names(self): + """Get all template names.""" names = [] opts = self.object._meta path_items = self.kwargs[self.path_field].strip("/").split("/") @@ -103,9 +119,12 @@ class CategoryRelatedDetail(DetailView): class CategoryRelatedList(ListView): + """List related category items.""" + path_field = "category_path" def get_queryset(self): + """Get the list of items.""" if self.path_field not in self.kwargs: raise AttributeError( "Category detail view %s must be called with " "a %s." % (self.__class__.__name__, self.path_field) @@ -115,6 +134,7 @@ class CategoryRelatedList(ListView): return queryset.filter(category=category) def get_template_names(self): + """Get the template names.""" names = [] if hasattr(self.object_list, "model"): opts = self.object_list.model._meta diff --git a/example/manage.py b/example/manage.py index f9726f9..195f6b9 100755 --- a/example/manage.py +++ b/example/manage.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +"""Entrypoint for custom django functions.""" import os import sys diff --git a/example/settings.py b/example/settings.py index c303377..ababf90 100644 --- a/example/settings.py +++ b/example/settings.py @@ -1,4 +1,4 @@ -# Django settings for sample project. +"""Django settings for sample project.""" import os import sys diff --git a/example/simpletext/admin.py b/example/simpletext/admin.py index 9539514..2d12815 100644 --- a/example/simpletext/admin.py +++ b/example/simpletext/admin.py @@ -1,3 +1,4 @@ +"""Admin interface for simple text.""" from django.contrib import admin from categories.admin import CategoryBaseAdmin, CategoryBaseAdminForm @@ -6,6 +7,8 @@ from .models import SimpleCategory, SimpleText class SimpleTextAdmin(admin.ModelAdmin): + """Admin for simple text model.""" + fieldsets = ( ( None, @@ -20,12 +23,16 @@ class SimpleTextAdmin(admin.ModelAdmin): class SimpleCategoryAdminForm(CategoryBaseAdminForm): + """Admin form for simple category.""" + class Meta: model = SimpleCategory fields = "__all__" class SimpleCategoryAdmin(CategoryBaseAdmin): + """Admin for simple category.""" + form = SimpleCategoryAdminForm diff --git a/example/simpletext/models.py b/example/simpletext/models.py old mode 100755 new mode 100644 index e7ccaed..7d01720 --- a/example/simpletext/models.py +++ b/example/simpletext/models.py @@ -1,3 +1,4 @@ +"""Example model.""" from django.db import models from categories.base import CategoryBase @@ -5,7 +6,7 @@ from categories.base import CategoryBase class SimpleText(models.Model): """ - (SimpleText description) + (SimpleText description). """ name = models.CharField(max_length=255) @@ -22,6 +23,7 @@ class SimpleText(models.Model): return self.name def get_absolute_url(self): + """Get the absolute URL for this object.""" try: from django.db.models import permalink @@ -33,7 +35,7 @@ class SimpleText(models.Model): class SimpleCategory(CategoryBase): - """A Test of catgorizing""" + """A Test of catgorizing.""" class Meta: verbose_name_plural = "simple categories" diff --git a/example/simpletext/views.py b/example/simpletext/views.py old mode 100755 new mode 100644 index 60f00ef..8a89169 --- a/example/simpletext/views.py +++ b/example/simpletext/views.py @@ -1 +1 @@ -# Create your views here. +"""Create your views here.""" diff --git a/example/urls.py b/example/urls.py index cab9d28..b20f351 100644 --- a/example/urls.py +++ b/example/urls.py @@ -1,3 +1,4 @@ +"""URL patterns for the example project.""" import os from django.conf.urls import include, url From 30258ac456baf1d245dbb483ceca1c633893eaa5 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Wed, 22 Dec 2021 12:10:13 -0600 Subject: [PATCH 30/51] Marked several files as not executable --- example/simpletext/__init__.py | 0 example/simpletext/tests.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 example/simpletext/__init__.py mode change 100755 => 100644 example/simpletext/tests.py diff --git a/example/simpletext/__init__.py b/example/simpletext/__init__.py old mode 100755 new mode 100644 diff --git a/example/simpletext/tests.py b/example/simpletext/tests.py old mode 100755 new mode 100644 From 56a9b4f756d948bd0cc40b333b7af13539ff8362 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Wed, 22 Dec 2021 12:14:04 -0600 Subject: [PATCH 31/51] Added Django to the dev dependencies and docs build. --- .github/workflows/python-package.yml | 4 ++-- requirements/dev.txt | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index c4d1b54..27d591a 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -26,8 +26,8 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install flake8 pytest - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + pip install django + if [ -f requirements/test.txt ]; then pip install -r requirements/test.txt; fi - name: Sphinx Pages # You may pin to the exact commit or the version. # uses: seanzhengw/sphinx-pages@70dd0557fc226cfcd41c617aec5e9ee4fce4afe2 diff --git a/requirements/dev.txt b/requirements/dev.txt index 1c3dcd1..c764852 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -2,6 +2,7 @@ -r test.txt bump2version>=1.0.1 +django git-fame>=1.12.2 gitchangelog>=3.0.4 pre-commit From 82298af6bc6683b8a6ae353d5a9e1ce9c626b874 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Wed, 22 Dec 2021 12:23:13 -0600 Subject: [PATCH 32/51] Updated the workflow. --- .github/workflows/python-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 27d591a..b79b96d 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -26,7 +26,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install django + python -m pip install django if [ -f requirements/test.txt ]; then pip install -r requirements/test.txt; fi - name: Sphinx Pages # You may pin to the exact commit or the version. From 55be640d7aa429e93685548ebf84f39a54893b15 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Wed, 22 Dec 2021 12:27:26 -0600 Subject: [PATCH 33/51] Installing the dev requirements for doc building. --- .github/workflows/python-package.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index b79b96d..aa13e2b 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -26,8 +26,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install django - if [ -f requirements/test.txt ]; then pip install -r requirements/test.txt; fi + if [ -f requirements/test.txt ]; then pip install -r requirements/dev.txt; fi - name: Sphinx Pages # You may pin to the exact commit or the version. # uses: seanzhengw/sphinx-pages@70dd0557fc226cfcd41c617aec5e9ee4fce4afe2 From cd43f6e4396ed9604236c7078fa27063425e0fe7 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Wed, 22 Dec 2021 12:30:49 -0600 Subject: [PATCH 34/51] Set the django requirement to less than 4. --- requirements/dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/dev.txt b/requirements/dev.txt index c764852..5e28f72 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -2,7 +2,7 @@ -r test.txt bump2version>=1.0.1 -django +django<4.0.0 git-fame>=1.12.2 gitchangelog>=3.0.4 pre-commit From 4d19a7a0678965702205f91768d32536b8fa47fe Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Thu, 23 Dec 2021 15:40:04 -0600 Subject: [PATCH 35/51] Debugging the doc generation process --- .github/workflows/python-package.yml | 21 ++-- .github/workflows/run-tests.yaml | 6 +- .gitignore | 3 + Makefile | 6 +- categories/templatetags/category_tags.py | 124 ++++++++++++----------- 5 files changed, 85 insertions(+), 75 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index aa13e2b..4852979 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -26,13 +26,14 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - if [ -f requirements/test.txt ]; then pip install -r requirements/dev.txt; fi - - name: Sphinx Pages - # You may pin to the exact commit or the version. - # uses: seanzhengw/sphinx-pages@70dd0557fc226cfcd41c617aec5e9ee4fce4afe2 - uses: seanzhengw/sphinx-pages@d29427677b3b89c1b5311d9eb135fb4168f4ba4a - with: - # Token for the repo. Can be passed in using $\{{ secrets.GITHUB_TOKEN }} - github_token: ${{ secrets.GITHUB_TOKEN }} - # Auto create a README.md file at branch gh-pages root with repo/branch/commit links - source_dir: "doc_src" + pip install -r requirements/dev.txt + make pubdocs +# - name: Sphinx Pages +# # You may pin to the exact commit or the version. +# # uses: seanzhengw/sphinx-pages@70dd0557fc226cfcd41c617aec5e9ee4fce4afe2 +# uses: seanzhengw/sphinx-pages@d29427677b3b89c1b5311d9eb135fb4168f4ba4a +# with: +# # Token for the repo. Can be passed in using $\{{ secrets.GITHUB_TOKEN }} +# github_token: ${{ secrets.GITHUB_TOKEN }} +# # Auto create a README.md file at branch gh-pages root with repo/branch/commit links +# source_dir: "doc_src" diff --git a/.github/workflows/run-tests.yaml b/.github/workflows/run-tests.yaml index 5d979a8..ed93a00 100644 --- a/.github/workflows/run-tests.yaml +++ b/.github/workflows/run-tests.yaml @@ -1,7 +1,7 @@ name: Run Tox tests -on: - - push - - pull_request +#on: +# - push +# - pull_request jobs: build: diff --git a/.gitignore b/.gitignore index a8acde2..2948063 100644 --- a/.gitignore +++ b/.gitignore @@ -67,6 +67,7 @@ cover/ local_settings.py db.sqlite3 db.sqlite3-journal +dev.db # Flask stuff: instance/ @@ -168,9 +169,11 @@ output/*/index.html junit-*.xml flake8-errors.txt example/media/ + # Documentation building _build doc_src/api/categories*.rst +docs RELEASE.txt site-packages diff --git a/Makefile b/Makefile index ac0575b..b630b5f 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,4 @@ +.PHONY: clean clean-test clean-pyc clean-build docs help .DEFAULT_GOAL := help RELEASE_KIND := patch @@ -84,9 +85,12 @@ release-minor: set-release-minor-env-var release-helper ## Release a new minor release-major: set-release-major-env-var release-helper ## release a new major version: 1.1.1 -> 2.0.0 -documentation: +docs: ## generate Sphinx HTML documentation, including API docs mkdir -p docs rm -f doc_src/api/$(SOURCE_DIR)*.rst ls -A1 docs | xargs -I {} rm -rf docs/{} $(MAKE) -C doc_src clean html cp -a doc_src/_build/html/. docs + +pubdocs: docs ## Publish the documentation to GitHub + ghp-import -op docs diff --git a/categories/templatetags/category_tags.py b/categories/templatetags/category_tags.py index 460509a..cc4a579 100644 --- a/categories/templatetags/category_tags.py +++ b/categories/templatetags/category_tags.py @@ -112,21 +112,22 @@ def get_category_drilldown(parser, token): """ Retrieves the specified category, its ancestors and its immediate children as an Iterable. - Syntax:: + The basic syntax:: {% get_category_drilldown "category name" [using "app.Model"] as varname %} - Example:: + Example: + Using a string for the category name:: - {% get_category_drilldown "/Grandparent/Parent" [using "app.Model"] as family %} + {% get_category_drilldown "/Grandparent/Parent" as family %} - or :: + or using a variable for the category:: - {% get_category_drilldown category_obj as family %} + {% get_category_drilldown category_obj as family %} - Sets family to:: + Sets family to:: - Grandparent, Parent, Child 1, Child 2, Child n + Grandparent, Parent, Child 1, Child 2, Child n Args: parser: The Django template parser. @@ -171,7 +172,9 @@ def breadcrumbs(category_string, separator=" > ", using="categories.category"): """ Render breadcrumbs, using the ``categories/breadcrumbs.html`` template. - {% breadcrumbs category separator="::" using="categories.category" %} + The basic syntax:: + + {% breadcrumbs "category" [separator=" > "] [using="categories.category"] %} Args: category_string: A variable reference to or the name of the category to display @@ -191,33 +194,34 @@ def display_drilldown_as_ul(category, using="categories.Category"): """ Render the category with ancestors and children using the ``categories/ul_tree.html`` template. - Example:: + Example: + The template code of:: - {% display_drilldown_as_ul "/Grandparent/Parent" %} + {% display_drilldown_as_ul "/Grandparent/Parent" %} - or :: + or:: - {% display_drilldown_as_ul category_obj %} + {% display_drilldown_as_ul category_obj %} - Returns:: + might render as:: - Args: category: A variable reference to or the name of the category to display @@ -239,23 +243,23 @@ def display_path_as_ul(category, using="categories.Category"): Render the category with ancestors, but no children using the ``categories/ul_tree.html`` template. Examples: - ``` - {% display_path_as_ul "/Grandparent/Parent" %} - ``` - ``` - {% display_path_as_ul category_obj %} - ``` + The template code of:: + + {% display_path_as_ul "/Grandparent/Parent" %} + + or:: + + {% display_path_as_ul category_obj %} + + might render as:: - Output: - ``` - - ``` Args: category: A variable reference to or the name of the category to display @@ -291,18 +295,16 @@ def get_top_level_categories(parser, token): """ Retrieves an alphabetical list of all the categories that have no parents. - Usage: + The basic syntax is:: - ``` {% get_top_level_categories [using "app.Model"] as categories %} - ``` Args: parser: The Django template parser. token: The tag contents Returns: - Returns an list of categories [, , , , - {% recursetree nodes %} -
    • - {{ node.name }} - {% if not node.is_leaf_node %} -
        - {{ children }} -
      - {% endif %} -
    • - {% endrecursetree %} - - ``` + Example: + Basic usage example:: + +
        + {% recursetree nodes %} +
      • + {{ node.name }} + {% if not node.is_leaf_node %} +
          + {{ children }} +
        + {% endif %} +
      • + {% endrecursetree %} +
      Args: parser: The Django template parser. From adf7c78268520b691085b3b1bd7d6d56e4b04d91 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Thu, 23 Dec 2021 15:47:12 -0600 Subject: [PATCH 36/51] Added ghp-import to requirements. --- requirements/dev.txt | 1 - requirements/test.txt | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements/dev.txt b/requirements/dev.txt index 5e28f72..1c3dcd1 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -2,7 +2,6 @@ -r test.txt bump2version>=1.0.1 -django<4.0.0 git-fame>=1.12.2 gitchangelog>=3.0.4 pre-commit diff --git a/requirements/test.txt b/requirements/test.txt index 203af8e..4f858b5 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -1,7 +1,8 @@ -r prod.txt +django<4.0.0 +ghp-import linkify-it-py myst-parser - pydata-sphinx-theme Sphinx>=4.3.0 sphinx-autodoc-typehints From e3bed16a9f5527f2850f5f984d04e177faedb468 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Thu, 23 Dec 2021 15:54:30 -0600 Subject: [PATCH 37/51] Added configuration for git user --- .github/workflows/python-package.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 4852979..99b6517 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -27,6 +27,8 @@ jobs: run: | python -m pip install --upgrade pip pip install -r requirements/dev.txt + git config user.name github-actions + git config user.email github-actions@github.com make pubdocs # - name: Sphinx Pages # # You may pin to the exact commit or the version. From 13b4cdc981fe762d4f44d924b089d18f169d6e61 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Thu, 23 Dec 2021 15:57:25 -0600 Subject: [PATCH 38/51] Adjusted makefile for github action commit --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b630b5f..20a62b0 100644 --- a/Makefile +++ b/Makefile @@ -93,4 +93,5 @@ docs: ## generate Sphinx HTML documentation, including API docs cp -a doc_src/_build/html/. docs pubdocs: docs ## Publish the documentation to GitHub - ghp-import -op docs + ghp-import -o docs + git push origin gh-pages --force From ed5aa6573646c07a5d4e99ad45bd760bdd337799 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Thu, 23 Dec 2021 16:14:03 -0600 Subject: [PATCH 39/51] Redo the doc publishing @minor --- .github/workflows/python-package.yml | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 99b6517..eaebc6e 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -27,9 +27,22 @@ jobs: run: | python -m pip install --upgrade pip pip install -r requirements/dev.txt - git config user.name github-actions - git config user.email github-actions@github.com - make pubdocs + - name: Build documentation + run: | + make docs + - name: Publish documentation + run: | + author_name="$(git show --format=%an -s)" + author_email="$(git show --format=%ae -s)" + echo "git config user.name $author_name" + git config user.name $author_name + echo "git config user.email $author_email" + git config user.email $author_email + echo "git remote add origin https://github.com/$GITHUB_REPOSITORY.git" + git remote add origin https://$GITHUB_ACTOR:$INPUT_GITHUB_TOKEN@github.com/$GITHUB_REPOSITORY.git + echo "git fetch origin +refs/heads/gh-pages:refs/remotes/origin/gh-pages" + git fetch origin +refs/heads/gh-pages:refs/remotes/origin/gh-pages + ghp-import -op docs # - name: Sphinx Pages # # You may pin to the exact commit or the version. # # uses: seanzhengw/sphinx-pages@70dd0557fc226cfcd41c617aec5e9ee4fce4afe2 From 7d81843a9aa3f2ef809bfdb936c5993e1acdfcf0 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Thu, 23 Dec 2021 16:16:06 -0600 Subject: [PATCH 40/51] Fixing the publish documentation @minor --- .github/workflows/python-package.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index eaebc6e..9f0ad05 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -38,8 +38,6 @@ jobs: git config user.name $author_name echo "git config user.email $author_email" git config user.email $author_email - echo "git remote add origin https://github.com/$GITHUB_REPOSITORY.git" - git remote add origin https://$GITHUB_ACTOR:$INPUT_GITHUB_TOKEN@github.com/$GITHUB_REPOSITORY.git echo "git fetch origin +refs/heads/gh-pages:refs/remotes/origin/gh-pages" git fetch origin +refs/heads/gh-pages:refs/remotes/origin/gh-pages ghp-import -op docs From 247575daacc494783ce44fa39cb7bd702b0773f8 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Thu, 23 Dec 2021 16:18:27 -0600 Subject: [PATCH 41/51] Fixing docs pub again @minor --- .github/workflows/python-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 9f0ad05..3ed9c64 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -38,8 +38,8 @@ jobs: git config user.name $author_name echo "git config user.email $author_email" git config user.email $author_email - echo "git fetch origin +refs/heads/gh-pages:refs/remotes/origin/gh-pages" - git fetch origin +refs/heads/gh-pages:refs/remotes/origin/gh-pages + echo "git fetch origin gh-pages" + git fetch origin gh-pages ghp-import -op docs # - name: Sphinx Pages # # You may pin to the exact commit or the version. From 2da01b8bc650573560b8a88a01d0d77cdfd6d41d Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Thu, 23 Dec 2021 16:26:25 -0600 Subject: [PATCH 42/51] Making ghp-import use a shell @minor --- .github/workflows/python-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 3ed9c64..41f9218 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -40,7 +40,7 @@ jobs: git config user.email $author_email echo "git fetch origin gh-pages" git fetch origin gh-pages - ghp-import -op docs + ghp-import -ops docs # - name: Sphinx Pages # # You may pin to the exact commit or the version. # # uses: seanzhengw/sphinx-pages@70dd0557fc226cfcd41c617aec5e9ee4fce4afe2 From 3b189e968e222e3e9a051057f9f60cc5a1fd38f1 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Thu, 23 Dec 2021 16:45:51 -0600 Subject: [PATCH 43/51] New attempt to fix doc publishing @minor --- .github/workflows/python-package.yml | 45 +++++++++++++++------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 41f9218..775bdb6 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -27,26 +27,29 @@ jobs: run: | python -m pip install --upgrade pip pip install -r requirements/dev.txt - - name: Build documentation + - name: Prepare documentation build run: | - make docs - - name: Publish documentation - run: | - author_name="$(git show --format=%an -s)" - author_email="$(git show --format=%ae -s)" - echo "git config user.name $author_name" - git config user.name $author_name - echo "git config user.email $author_email" - git config user.email $author_email - echo "git fetch origin gh-pages" + mkdir -p docs + rm -f doc_src/api/categories*.rst + ls -A1 docs | xargs -I {} rm -rf docs/{} git fetch origin gh-pages - ghp-import -ops docs -# - name: Sphinx Pages -# # You may pin to the exact commit or the version. -# # uses: seanzhengw/sphinx-pages@70dd0557fc226cfcd41c617aec5e9ee4fce4afe2 -# uses: seanzhengw/sphinx-pages@d29427677b3b89c1b5311d9eb135fb4168f4ba4a -# with: -# # Token for the repo. Can be passed in using $\{{ secrets.GITHUB_TOKEN }} -# github_token: ${{ secrets.GITHUB_TOKEN }} -# # Auto create a README.md file at branch gh-pages root with repo/branch/commit links -# source_dir: "doc_src" + git update-ref -d refs/heads/gh-pages +# - name: Publish documentation +# run: | +# author_name="$(git show --format=%an -s)" +# author_email="$(git show --format=%ae -s)" +# echo "git config user.name $author_name" +# git config user.name $author_name +# echo "git config user.email $author_email" +# git config user.email $author_email +# echo "git fetch origin gh-pages" +# git fetch origin gh-pages +# git update-ref -d refs/heads/gh-pages + - name: Sphinx Pages + # You may pin to the exact commit or the version. + # uses: seanzhengw/sphinx-pages@70dd0557fc226cfcd41c617aec5e9ee4fce4afe2 + uses: seanzhengw/sphinx-pages@d29427677b3b89c1b5311d9eb135fb4168f4ba4a + with: + # Token for the repo. Can be passed in using $\{{ secrets.GITHUB_TOKEN }} + github_token: ${{ secrets.GITHUB_TOKEN }} + source_dir: "doc_src" From 249d3c95c25593fd142efd5bfdfcf5a9c93ec89b Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Thu, 23 Dec 2021 16:48:15 -0600 Subject: [PATCH 44/51] Making sure docs directory doesn't exist @minor --- .github/workflows/python-package.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 775bdb6..9509300 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -29,9 +29,8 @@ jobs: pip install -r requirements/dev.txt - name: Prepare documentation build run: | - mkdir -p docs rm -f doc_src/api/categories*.rst - ls -A1 docs | xargs -I {} rm -rf docs/{} + rm -rf docs/ git fetch origin gh-pages git update-ref -d refs/heads/gh-pages # - name: Publish documentation From 7fbbbe030dc8b8afb0e5496df6886bc1ef277772 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Thu, 23 Dec 2021 17:17:50 -0600 Subject: [PATCH 45/51] Another try at the documentation publishing @minor --- .github/workflows/python-package.yml | 30 +++++++--------------------- Makefile | 3 +-- 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 9509300..1fa005b 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -27,28 +27,12 @@ jobs: run: | python -m pip install --upgrade pip pip install -r requirements/dev.txt - - name: Prepare documentation build + - name: Build documentation run: | - rm -f doc_src/api/categories*.rst - rm -rf docs/ - git fetch origin gh-pages - git update-ref -d refs/heads/gh-pages -# - name: Publish documentation -# run: | -# author_name="$(git show --format=%an -s)" -# author_email="$(git show --format=%ae -s)" -# echo "git config user.name $author_name" -# git config user.name $author_name -# echo "git config user.email $author_email" -# git config user.email $author_email -# echo "git fetch origin gh-pages" -# git fetch origin gh-pages -# git update-ref -d refs/heads/gh-pages - - name: Sphinx Pages - # You may pin to the exact commit or the version. - # uses: seanzhengw/sphinx-pages@70dd0557fc226cfcd41c617aec5e9ee4fce4afe2 - uses: seanzhengw/sphinx-pages@d29427677b3b89c1b5311d9eb135fb4168f4ba4a - with: - # Token for the repo. Can be passed in using $\{{ secrets.GITHUB_TOKEN }} + make docs + - name: github pages deploy + uses: peaceiris/actions-gh-pages@v2.3.1 + env: github_token: ${{ secrets.GITHUB_TOKEN }} - source_dir: "doc_src" + publish_branch: gh-pages + publish_dir: docs diff --git a/Makefile b/Makefile index 20a62b0..b630b5f 100644 --- a/Makefile +++ b/Makefile @@ -93,5 +93,4 @@ docs: ## generate Sphinx HTML documentation, including API docs cp -a doc_src/_build/html/. docs pubdocs: docs ## Publish the documentation to GitHub - ghp-import -o docs - git push origin gh-pages --force + ghp-import -op docs From 797ae50c8ace866422a6362701ee2381c657cc8a Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Thu, 23 Dec 2021 17:25:53 -0600 Subject: [PATCH 46/51] Updates the gh-pages action to 3.8.0 @minor --- .github/workflows/python-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 1fa005b..e0ccf18 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -31,7 +31,7 @@ jobs: run: | make docs - name: github pages deploy - uses: peaceiris/actions-gh-pages@v2.3.1 + uses: peaceiris/actions-gh-pages@v3.8.0 env: github_token: ${{ secrets.GITHUB_TOKEN }} publish_branch: gh-pages From 87143a8fe27531a1725fca7cd0e1334683b84ea0 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Thu, 23 Dec 2021 17:32:51 -0600 Subject: [PATCH 47/51] Trying a different token variable. @minor --- .github/workflows/python-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index e0ccf18..4a7ecf9 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -33,6 +33,6 @@ jobs: - name: github pages deploy uses: peaceiris/actions-gh-pages@v3.8.0 env: - github_token: ${{ secrets.GITHUB_TOKEN }} + github_token: ${{ github.token }} publish_branch: gh-pages publish_dir: docs From da9ba4a4f57199b3a7383d7fb4e7e64410f1642b Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Thu, 23 Dec 2021 17:44:17 -0600 Subject: [PATCH 48/51] Added GITHUB TOKEN permissions @minor --- .github/workflows/python-package.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 4a7ecf9..5fd32dc 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -9,6 +9,10 @@ on: pull_request: branches: [ master ] +permissions: + contents: write + pull-requests: write + jobs: build: @@ -36,3 +40,4 @@ jobs: github_token: ${{ github.token }} publish_branch: gh-pages publish_dir: docs + force_orphan: true From 75f2f570839698655bc9e64cf6d5b1013ffaf3fd Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Thu, 23 Dec 2021 17:46:50 -0600 Subject: [PATCH 49/51] Trying a different token again @minor --- .github/workflows/python-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 5fd32dc..7ac64a4 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -37,7 +37,7 @@ jobs: - name: github pages deploy uses: peaceiris/actions-gh-pages@v3.8.0 env: - github_token: ${{ github.token }} + github_token: ${{ secrets.GITHUB_TOKEN }} publish_branch: gh-pages publish_dir: docs force_orphan: true From e8e9fa3b93236d798d58c569bd685724d08a9c5e Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Thu, 23 Dec 2021 17:49:37 -0600 Subject: [PATCH 50/51] Switched env with with @minor --- .github/workflows/python-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 7ac64a4..fd501df 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -36,7 +36,7 @@ jobs: make docs - name: github pages deploy uses: peaceiris/actions-gh-pages@v3.8.0 - env: + with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_branch: gh-pages publish_dir: docs From 7300efed19532ac222c099477db3f5ff6e47b5d4 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Thu, 23 Dec 2021 18:30:53 -0600 Subject: [PATCH 51/51] Updated all github actions. @minor --- .../{python-package.yml => publish-docs.yml} | 14 +++--- .github/workflows/publish-package.yml | 48 +++++++++++++++++++ .github/workflows/run-tests.yaml | 6 +-- 3 files changed, 57 insertions(+), 11 deletions(-) rename .github/workflows/{python-package.yml => publish-docs.yml} (71%) create mode 100644 .github/workflows/publish-package.yml diff --git a/.github/workflows/python-package.yml b/.github/workflows/publish-docs.yml similarity index 71% rename from .github/workflows/python-package.yml rename to .github/workflows/publish-docs.yml index fd501df..778d218 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/publish-docs.yml @@ -1,13 +1,8 @@ -# This workflow will install Python dependencies, run tests and lint with a variety of Python versions -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions - -name: Python package +name: Build and publish documentation on: push: - branches: [ master ] - pull_request: - branches: [ master ] + tags: [ "*" ] permissions: contents: write @@ -15,7 +10,6 @@ permissions: jobs: build: - runs-on: ubuntu-latest strategy: matrix: @@ -23,17 +17,21 @@ jobs: steps: - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} + - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements/dev.txt + - name: Build documentation run: | make docs + - name: github pages deploy uses: peaceiris/actions-gh-pages@v3.8.0 with: diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml new file mode 100644 index 0000000..bc6333c --- /dev/null +++ b/.github/workflows/publish-package.yml @@ -0,0 +1,48 @@ +name: Release package on PyPI + +on: + push: + tags: [ "*" ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + build-n-publish: + name: Build package and publish to TestPyPI and PyPI + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-python@v2 + name: Use Python 3.9 + with: + python-version: 3.9 + + - name: Install pypa/build + run: >- + python -m + pip install + build + --user + + - name: Build a binary wheel and a source tarball + run: >- + python -m + build + --sdist + --wheel + --outdir dist/ + + - name: Publish package to Test PyPI + uses: pypa/gh-action-pypi-publish@master + with: + password: ${{ secrets.TEST_PYPI_API_TOKEN }} + repository_url: https://test.pypi.org/legacy/ + + - name: Publish package + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') + uses: pypa/gh-action-pypi-publish@master + with: + password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.github/workflows/run-tests.yaml b/.github/workflows/run-tests.yaml index ed93a00..5d979a8 100644 --- a/.github/workflows/run-tests.yaml +++ b/.github/workflows/run-tests.yaml @@ -1,7 +1,7 @@ name: Run Tox tests -#on: -# - push -# - pull_request +on: + - push + - pull_request jobs: build: