Showing preview only (1,285K chars total). Download the full file or copy to clipboard to get everything.
Repository: hovel/pybbm
Branch: master
Commit: 9def6595c7ed
Files: 256
Total size: 1.2 MB
Directory structure:
gitextract_xr1bgpyb/
├── .coveragerc
├── .gitignore
├── .hgignore
├── .travis.yml
├── AUTHORS
├── CHANGELOG
├── LICENSE
├── MANIFEST.in
├── README.rst
├── docs/
│ ├── Makefile
│ ├── anonymous.rst
│ ├── conf.py
│ ├── contributing.rst
│ ├── customuser.rst
│ ├── example.rst
│ ├── filters.rst
│ ├── index.rst
│ ├── install.rst
│ ├── javascript.rst
│ ├── make.bat
│ ├── markup.rst
│ ├── notifications.rst
│ ├── originalpybb.rst
│ ├── permissions.rst
│ ├── premoderation.rst
│ ├── problems.rst
│ ├── pybbmigrate.rst
│ ├── settings.rst
│ ├── templatetags.rst
│ ├── testing.rst
│ └── updates.rst
├── pybb/
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── compat.py
│ ├── context_processors.py
│ ├── defaults.py
│ ├── feeds.py
│ ├── forms.py
│ ├── locale/
│ │ ├── de/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── django.mo
│ │ │ └── django.po
│ │ ├── es/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── django.mo
│ │ │ └── django.po
│ │ ├── fr/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── django.mo
│ │ │ └── django.po
│ │ ├── he/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── django.mo
│ │ │ └── django.po
│ │ ├── it/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── django.mo
│ │ │ └── django.po
│ │ ├── ja/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── django.mo
│ │ │ └── django.po
│ │ ├── pl/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── django.mo
│ │ │ └── django.po
│ │ ├── pt_BR/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── django.mo
│ │ │ └── django.po
│ │ ├── ru/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── django.mo
│ │ │ └── django.po
│ │ ├── sk/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── django.mo
│ │ │ └── django.po
│ │ ├── sv/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── django.mo
│ │ │ └── django.po
│ │ ├── uk/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── django.mo
│ │ │ └── django.po
│ │ └── zh/
│ │ └── LC_MESSAGES/
│ │ ├── django.mo
│ │ └── django.po
│ ├── management/
│ │ ├── __init__.py
│ │ └── commands/
│ │ ├── __init__.py
│ │ ├── dump_topics.py
│ │ ├── migrate_profile.py
│ │ ├── pybb_delete_invalid_topics.py
│ │ ├── pybb_update_counters.py
│ │ └── supermoderator.py
│ ├── markup/
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── bbcode.py
│ │ └── markdown.py
│ ├── middleware.py
│ ├── migrations/
│ │ ├── 0001_initial.py
│ │ ├── 0002_slugs_optional.py
│ │ ├── 0003_slugs_fill.py
│ │ ├── 0004_slugs_required.py
│ │ ├── 0005_auto_20151108_1528.py
│ │ ├── 0006_forum_subscriptions.py
│ │ ├── 0007_auto_20170111_1504.py
│ │ └── __init__.py
│ ├── models.py
│ ├── permissions.py
│ ├── profiles.py
│ ├── signals.py
│ ├── static/
│ │ ├── markitup/
│ │ │ ├── ajax_csrf.js
│ │ │ ├── jquery.markitup.js
│ │ │ ├── preview.css
│ │ │ ├── sets/
│ │ │ │ ├── bbcode/
│ │ │ │ │ ├── readme.txt
│ │ │ │ │ ├── set.js
│ │ │ │ │ └── style.css
│ │ │ │ ├── default/
│ │ │ │ │ ├── set.js
│ │ │ │ │ └── style.css
│ │ │ │ └── markdown/
│ │ │ │ ├── readme.txt
│ │ │ │ ├── set.js
│ │ │ │ └── style.css
│ │ │ ├── skins/
│ │ │ │ ├── markitup/
│ │ │ │ │ └── style.css
│ │ │ │ └── simple/
│ │ │ │ └── style.css
│ │ │ └── templates/
│ │ │ ├── preview.css
│ │ │ └── preview.html
│ │ └── pybb/
│ │ ├── forum.less
│ │ ├── forum3.less
│ │ ├── js/
│ │ │ ├── markitup.js
│ │ │ └── pybbjs.js
│ │ ├── posts.less
│ │ ├── posts3.less
│ │ ├── visual.less
│ │ └── visual3.less
│ ├── subscription.py
│ ├── templates/
│ │ └── pybb/
│ │ ├── _button_forum_subscription.html
│ │ ├── _button_new_topic.html
│ │ ├── _button_save.html
│ │ ├── _button_submit.html
│ │ ├── _easy_thumbnail_avatar.html
│ │ ├── _markitup.html
│ │ ├── _markitup_preview.html
│ │ ├── _need_to_login_message.html
│ │ ├── _select_radio.html
│ │ ├── _sorl_thumbnail_avatar.html
│ │ ├── add_post.html
│ │ ├── attachments_formset.html
│ │ ├── avatar.html
│ │ ├── base.html
│ │ ├── breadcrumb.html
│ │ ├── breadcrumb_top_extra_crumb.html
│ │ ├── category.html
│ │ ├── delete_post.html
│ │ ├── edit_post.html
│ │ ├── edit_privileges.html
│ │ ├── edit_profile.html
│ │ ├── feeds/
│ │ │ ├── posts_description.html
│ │ │ ├── posts_title.html
│ │ │ ├── topics_description.html
│ │ │ └── topics_title.html
│ │ ├── form.html
│ │ ├── form_errors.html
│ │ ├── form_field.html
│ │ ├── forum.html
│ │ ├── forum_last_update_info.html
│ │ ├── forum_list.html
│ │ ├── forum_subscription.html
│ │ ├── index.html
│ │ ├── latest_topics.html
│ │ ├── mail_templates/
│ │ │ ├── base-html.html
│ │ │ ├── base.html
│ │ │ ├── forum_subscription_email_body.html
│ │ │ ├── forum_subscription_email_subject.html
│ │ │ ├── subscription_email_body-html.html
│ │ │ ├── subscription_email_body.html
│ │ │ └── subscription_email_subject.html
│ │ ├── markup/
│ │ │ ├── bbcode_widget.html
│ │ │ └── markdown_widget.html
│ │ ├── move_post.html
│ │ ├── pagination.html
│ │ ├── poll.html
│ │ ├── poll_edit_form.html
│ │ ├── post_form.html
│ │ ├── post_template.html
│ │ ├── topic.html
│ │ ├── topic_last_message_info.html
│ │ ├── topic_list.html
│ │ ├── user.html
│ │ ├── user_posts.html
│ │ ├── user_topics.html
│ │ └── users.html
│ ├── templatetags/
│ │ ├── __init__.py
│ │ └── pybb_tags.py
│ ├── tests.py
│ ├── urls.py
│ ├── util.py
│ └── views.py
├── runtests.py
├── setup.py
├── test/
│ ├── example_bootstrap/
│ │ ├── example_bootstrap/
│ │ │ ├── __init__.py
│ │ │ ├── settings.py
│ │ │ ├── urls.py
│ │ │ └── wsgi.py
│ │ ├── fixtures/
│ │ │ └── demo_data.json
│ │ ├── manage.py
│ │ ├── requirements.txt
│ │ ├── static/
│ │ │ ├── bootstrap/
│ │ │ │ ├── alerts.less
│ │ │ │ ├── bootstrap.less
│ │ │ │ ├── breadcrumbs.less
│ │ │ │ ├── button-groups.less
│ │ │ │ ├── buttons.less
│ │ │ │ ├── carousel.less
│ │ │ │ ├── close.less
│ │ │ │ ├── code.less
│ │ │ │ ├── component-animations.less
│ │ │ │ ├── dropdowns.less
│ │ │ │ ├── forms.less
│ │ │ │ ├── grid.less
│ │ │ │ ├── mixins.less
│ │ │ │ ├── modals.less
│ │ │ │ ├── navbar.less
│ │ │ │ ├── navs.less
│ │ │ │ ├── pager.less
│ │ │ │ ├── pagination.less
│ │ │ │ ├── popovers.less
│ │ │ │ ├── progress-bars.less
│ │ │ │ ├── responsive-utilities.less
│ │ │ │ ├── scaffolding.less
│ │ │ │ ├── tables.less
│ │ │ │ ├── thumbnails.less
│ │ │ │ ├── tooltip.less
│ │ │ │ ├── type.less
│ │ │ │ ├── utilities.less
│ │ │ │ ├── variables.less
│ │ │ │ └── wells.less
│ │ │ ├── csrf.js
│ │ │ ├── example_bootstrap.css
│ │ │ └── example_bootstrap.less
│ │ └── templates/
│ │ ├── 404.html
│ │ ├── base.html
│ │ ├── bootstrap_base.html
│ │ ├── pybb/
│ │ │ ├── breadcrumb.html
│ │ │ └── form_field.html
│ │ └── registration/
│ │ ├── activate.html
│ │ ├── activation_complete.html
│ │ ├── activation_email.txt
│ │ ├── activation_email_subject.txt
│ │ ├── login.html
│ │ ├── logout.html
│ │ ├── registration_complete.html
│ │ └── registration_form.html
│ ├── example_thirdparty/
│ │ ├── example_thirdparty/
│ │ │ ├── __init__.py
│ │ │ ├── forms.py
│ │ │ ├── settings.py
│ │ │ ├── urls.py
│ │ │ └── wsgi.py
│ │ ├── manage.py
│ │ ├── requirements.txt
│ │ └── templates/
│ │ ├── pybb/
│ │ │ ├── breadcrumb.html
│ │ │ ├── form.html
│ │ │ └── form_field.html
│ │ └── site_base.html
│ └── test_project/
│ ├── manage.py
│ ├── requirements_test.txt
│ ├── templates/
│ │ ├── 404.html
│ │ ├── base.html
│ │ └── pybb/
│ │ ├── _need_to_login_message.html
│ │ └── edit_profile.html
│ ├── test_app/
│ │ ├── __init__.py
│ │ ├── apps.py
│ │ ├── migrations/
│ │ │ ├── 0001_initial.py
│ │ │ └── __init__.py
│ │ └── models.py
│ └── test_project/
│ ├── __init__.py
│ ├── markup_parsers.py
│ ├── settings.py
│ └── urls.py
└── tox.ini
================================================
FILE CONTENTS
================================================
================================================
FILE: .coveragerc
================================================
[run]
source = pybb
[report]
exclude_lines =
pragma: no cover
raise ImproperlyConfigured
================================================
FILE: .gitignore
================================================
.idea
*.pyc
local_path.py
settings_local.py
dist
*.egg-info
testdb.sqlite
test/example/media/pybb_upload
docs/_build/
env/
#After a tox test run, some folders are created. Ignore these
.tox/
.coverage
htmlcov/
pybb_upload/
================================================
FILE: .hgignore
================================================
syntax: glob
# Global
*.pyc
*.swp
*.swo
# Distutils
pybb.egg-info/
dist/
# Sphinx
docs/_build/
================================================
FILE: .travis.yml
================================================
language: python
python:
- "2.7"
- "3.4"
- "3.5"
env:
- DJANGO="Django>=1.8,<1.9" DB=sqlite
- DJANGO="Django>=1.8,<1.9" DB=postgres
- DJANGO="Django>=1.8,<1.9" DB=mysql
- DJANGO="Django>=1.11,<2.0" DB=sqlite DJANGO_LTS=true
- DJANGO="Django>=1.11,<2.0" DB=postgres DJANGO_LTS=true
- DJANGO="Django>=1.11,<2.0" DB=mysql DJANGO_LTS=true
- DJANGO="Django>=2.0,<2.1" DB=sqlite
- DJANGO="Django>=2.0,<2.1" DB=postgres
- DJANGO="Django>=2.0,<2.1" DB=mysql
matrix:
exclude:
- python: "2.7"
env: DJANGO="Django>=2.0,<2.1" DB=sqlite
- python: "2.7"
env: DJANGO="Django>=2.0,<2.1" DB=postgres
- python: "2.7"
env: DJANGO="Django>=2.0,<2.1" DB=mysql
install:
- if [[ $DB == mysql ]]; then pip install -qU mysqlclient; fi
- if [[ $DB == postgres ]]; then pip install -qU psycopg2; fi
- pip install -qU $DJANGO
- if [[ $DB == postgres && $TRAVIS_PYTHON_VERSION == '3.5' && $DJANGO_LTS == true ]] ; then export WITH_COVERALL=true ; fi
- if [[ $WITH_COVERALL == true ]]; then pip install -qU coveralls ; fi
- CFLAGS="-O0" pip install -qU -r test/test_project/requirements_test.txt
before_script:
- if [[ $DB == mysql ]]; then mysql -e 'SET GLOBAL wait_timeout = 36000 ; create database pybbm;'; fi
- if [[ $DB == postgres ]]; then psql -c 'create database pybbm;' -U postgres; fi
script:
- if [[ $WITH_COVERALL == true ]]; then coverage run setup.py test; else python setup.py test ; fi
after_success:
- if [[ $WITH_COVERALL == true ]]; then coveralls ; fi
================================================
FILE: AUTHORS
================================================
Pavel Zhukov <gelios@gmail.com>
Grigory Petukhov
Nikolai Sevostjanov <nikolai.sevostjanov@gmail.com>
Denis Burij <denger@footter.com>
Alexander Solovyov <piranha@piranha.org.ua>
William Grzybowski <william88@gmail.com>
Nikolai Zamkovoi <nickzam@gmail.com>
Luke Petre
Filip Wasilewski (en@ig.ma)
Sergey Fursov <geyser85@gmail.com>
Dylann Cordel <cordel.d@free.fr>
Maksim Iakovlev <lampslave@gmail.com>
================================================
FILE: CHANGELOG
================================================
1.0.0
* PyBBM is now compatible with Django 3.2 (older versions not supported anymore)
* PyBBM is now compatible with Python 3.7+ (older versions not supported anymore)
0.19.0
* PyBBM is now compatible with Django 1.8, 1.11, 2.0
* Fix permissions and add documentation for default permissions
* Allow moderators to move a topic or split posts
* Update translations
* Multiple other fixes, refactoring
0.18.4
* Fix misspelling in Swedish translation
0.18.3
* Fix 0005 and 0006 migrations (changes will not affect db, so it's ok if this migrations were already executed)
0.18.2
* Minor fixes.
0.18.1
* Minor fixes.
0.18
* PyBBM is now compatible with Django>=1.8,<1.11
* Allow non-moderators to delete their own posts.
* Add setting to enable or disable admin post form.
* Add Swedish translation.
* Use FileField instead of ImageField when pillow is not available to make pillow depencency optional.
* Use staticfiles in all templates.
* Improve permission checking.
* Allow users to subscribe to a forum.
* Add a form to grant users moderator privileges.
* Add notification's emails HTML alternative.
* Add the ability to the user to use their attachments inside their posts to render it as link, image etc.
* Multiple fixes and improvements.
0.17.3
* Fast fix for migrations for Posgres database.
If you already get and applied migrations from 0.17 version (for example on MySQL DB) you can skip new
migrations with `manage.py migrate pybb --fake`
0.17
* Topic and post creation wrapped in transaction
* All topic/post/poll related forms can be overrided when custom view inherites pybbm view
* Demo data for example projects
* Using active markup engine when quoting posts via javascript
* Functionality to support disabling default pybbm subscriptions and notifications and
new settings: `PYBB_DISABLE_SUBSCRIPTIONS` and `PYBB_DISABLE_NOTIFICATIONS`
* Fixed sorl.thumbnail/easy_thumbnail compatibility in standard `pybb/avatar.html` template
* Improved example projects
* Removed applying `urlize` filter over html produced by markdown parser
(it doesn't play nicely with html markup as noted in django's docs)
* django 1.8 compatibility
* common django layout for test project
* use mysqlclient package for testing installation with mysql database backend on python 3
* optional enabling "nice urls" for entire forum,
that looks like '<forum prefix>/c/<category slug>/<forum slug>/<topic slug>/'
0.16.1
* Fast fixes
0.16
* Django 1.7 compatibility.
* Fixed creating custom profile model of any class defined in settings with right related name to user model.
*Migration note*: If you have workaround for creating profile in your code, you should remove it for
preventing possible dubplicate unique key error on user creating.
* New get_display_name method for profile model used to unification displaying username through forum
* New markup processing. See `markup`
0.15.6
* Make all migrations compatible with custom user model. Break dependency on sorl.thumbnail in migrations
* Compatibility functions moved to compat.py module
* Email notifications optimization
* Example_bootstrap projects now based on bootstrap 3
* Fixes and improvements
0.15.5
* Fixed bug when user can vote (or cancel vote) when topic was closed.
* Added `may_vote_in_topic` method to permission handler.
* Fixed blocking user view
0.15.4
* Hot fixes to bbcode transform
0.15.3
* bbcode engine simplified
0.15.2
* Pybbm specific forms moved to views' attributes, added new functions to views to get such forms dynamically.
This makes overriding pybbm forms much easier
* Moving from unmaintained postmarkup package to bbcode project as default bbcode render engine
Changed output html for [code] tag. It will be <code></code> tags instead of <div class="code"></div>.
So you should duplicate styles applied to div.code for code html tag.
* Japanese translation
0.15.1
* Hot fixes for Python 3 support
* Fixes for Chinese translation
0.15
* Python 3 support
* Chinese translation
0.14.9
* Two new methods added to permission handler: `may_attach_files` and `may_create_poll`. First method used for
restrict attaching files to post by user. By default it depends on `PYBB_ATTACHMENT_ENABLE` setting.
Second may be used to restrict some users to create/edit polls. By default it always return `True`.
For disabling polls on your forum, just write custom permission handler and return from this method `False`
0.14.8
* Improved javascript functionality: quote selected text, qoute full original message via ajax,
insert nickname in post body. For enabling this functionality you should satisfy `some requirements</javascript>`
in your templates
* Support for nested forums
* `PybbProfile` abstract model moved to `pybb.profiles` module to avoid circular imports when checking models.
0.14.7
* Django 1.6 compatibility
* unblock user functionality added
0.14.6
* Cache anonymous views count for topic and save it in database only when some count reached (100 by default).
This value can be changed by setting `PYBB_ANONYMOUS_VIEWS_CACHE_BUFFER`. Also added custom filter
`pybbm_calc_topic_views` that calc actual views count for topic
* Fix for migration that may fails on clean mysql installation
* Fixed perfomance issue with feed views
* Using custom permissions handler in feed views
0.14.5
* Minor fixes
0.14.4
* Fix for migration that may fails on clean mysql installation (not fixed really, filxed after 0.14.5)
* Make example_thirdparty project bootstrap3 compatible
0.14.3
* Show only available topics (by permission handler) in ForumView
0.14.2
* Fixed MultipleObjectReturned when topic has more than one moderator
0.14.1
* Fixed circular import issue
0.14
* Restored views for rendering user's posts and topics and link to that views from profile info page
* Broken hard dependency from EditProfileView and EditProfileForm classes in forum
* Ability for users to cancel their poll vote
* Block user view accepts only POST requests
* If `block_and_delete_messages` passed to request.POST for block user view,
then all user's messages will be deleted
0.13.1
* Hotfix for rendering avatars
0.13
* You can add first-unread get parameter to the topic url to provide link to first unread post from topic
* Removed django-mailer, pytils, sorl-thumbnail, south, django-pure-pagination from hard dependencies
* Support Custom User model introduced in django 1.5. Do not forget to define `PYBB_PROFILE_RELATED_NAME`
in settings, if you don't use predefined `pybb.PybbProfile` model See `how to use custom user model
with pybbm</customuser>`
* Dropped support for django 1.3
* Experimental support for python 3
* Removed django-mailer from hard dependencies, you have to manually install it for using it's functionality
0.12.5
* More flexible forms/forms fields rendering in templates
Strongly recommended to check rendering of pybbm forms on your site (edit profile, poll/topic create/edit)
* Additional template for markitup preview
You can override `pybb/_markitup_preview.html` to provide your styling for <code>, <pre> and other markitup tags
* Improved permissions handling see `PYBB_PERMISSION_HANDLER` setting in `settings</settings>`
* Fixed bugs and improved performance
0.12.4
* `PYBB_USE_DJANGO_MAILER` setting
0.12.3
* German translation
0.12
* Fixed bug when the answers to poll unexpectedly deleted. Strongly recommendet to update to this version, if using polls subsystem
* Polish translation
0.11.0
* Polls (by Geyser)
0.10.0
* Bootstrap 2 (by nigma and Geyser) (WARNING!! - BACKWARD INCOMPATIBLE TEMPLATES)
0.9.0
* Button in templates restyling (by nigma)
* Code cleanup (by nigma)
0.8.2
* Docs touchup
* Fix links to project
* Fix read/unread tracking (by lpetre)
0.8.1
* Support for django 1.4 timezones
0.8.0
* Django 1.4 support (by djw)
* Fix misspellings (by djw)
0.7.0
* Code cleanup
* Add post cleaners
* Rename BODY_CLEANER settings to PYBB_BODY_VALIDATOR
0.6.3
* Changed pybbTimeNode to use get_profile # (thanks Shon)
* Disable admin for 'pybb.Profile' if different AUTH_PROFILE_MODULE is set
* Disable editing of 'user' field in Profile admin
* French translation (thanks Eric)
0.6.1
* Russian translation updated
0.6.0
* CSS file is now build with less
* You can disable default css inclusion in templates with PYBB_DISABLE_CSS settings
and manually include pybb.less file or build pybb.less to your styles.
* Default style and templates revisied, new templates system
is cleaned and fully compatible with twitter bootstrap
Be aware of next changes:
* pagination template moved from `templates/pybb/pagination/` to `templates/pybb`
* pagination template changed from plain links to ul/li list
* breadcrumb now live in separated template and changed from plain links to ul/li list
* `add_post_form.html` template renamed to `post_form.html`
* PYBB_FORUM_PAGE_SIZE default value changed from 10 to 20
0.5.1
* Attachment system now fully worked and ready for usage
0.5.0
* Add anonymous posting (disabled by default)
* Add pre-moderation system (disabled by default)
0.4.1
* Fix category view context
* Add test for category view
0.4.0
* Most views are now class-based
* Tests code cleanup
* Django versions prior 1.3 supported via django-cbv
* django-pure-pagination is now are requirement as a pagination system for class based list views
* Provide inline pagination for topic
* Add read/unread blue/gray indicator (customized via css3)
0.3.6
* Fix migration issue on innodb tables
* Fix permission does not exists issue on first syncdb
================================================
FILE: LICENSE
================================================
Copyright (c) 2014-today, Maksim Iakovlev, Pavel Zhukov
Copyright (c) 2012-2014, Sergey Fursov, Pavel Zhukov
Copyright (c) 2009-2012, Pavel Zhukov
Copyright (c) 2008-2009, Grigoriy Petukhov (project forked)
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: MANIFEST.in
================================================
recursive-include pybb/static *
recursive-include pybb/templates *
recursive-include pybb/locale *
include README.rst
================================================
FILE: README.rst
================================================
PyBBM - Django forum solution
=============================
.. |travis| image:: https://travis-ci.org/hovel/pybbm.png?branch=master
.. |coveralls| image:: https://coveralls.io/repos/github/hovel/pybbm/badge.svg?branch=master
|travis| |coveralls|
PyBBM is a full-featured django forum solution with these features:
* Avatars
* Custom profiles and support of Custom User Model (since django 1.5)
* Post editing
* Pre-moderation
* Custom sanitization
* Anonymous posting
* Subscriptions
* Polls
* ...
All features is based on:
* +94% tests covered code
* Twitter bootstrap compatible default theme
* Ready to use example project
The main point in development of pybb is to build it so it could be
*easily* integrated to existing django based site. This mean that pybb does not provide features like user registration, password restoring. It does not provide authentication page. (But example project provides ;))
PyBBM includes ready to use `example/test project with instructions <http://readthedocs.org/docs/pybbm/en/latest/example.html>`_
i18n support
============
PYBB support English, Russian, Slovak, Ukrainian, Brazilian Portuguese, Polish, Hebrew, French, Chinese, Japanese,
German, Spanish, Italian, Swedish translations now. Feel free to contribute translation for another language or to correct existing.
You should enable django.middleware.locale.LocaleMiddleware to activate
django locale autodetecting.
More links
==========
* Support Forum and DEMO: http://pybbm.org/
* PyPi: http://pypi.python.org/pypi/pybbm/
* Sourcecode: https://github.com/hovel/pybbm/
* Documentation: http://pybbm.readthedocs.org/en/latest/
* Page on djangopackages.com: http://www.djangopackages.com/packages/p/pybbm/
================================================
FILE: docs/Makefile
================================================
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/PyBBM.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PyBBM.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/PyBBM"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PyBBM"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
make -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
================================================
FILE: docs/anonymous.rst
================================================
Anonymous posting
=================
PyBBM allow you to enable anonymous posting on forum.
Be very carefull by enabling anonymous posting, it is better to enable
`BODY_CLEANER` setting to cleanup spam links from posts.
Enable :ref:`PYBB_ENABLE_ANONYMOUS_POST` and set :ref:`PYBB_ANONYMOUS_USERNAME` for enabling anonymous posting::
PYBB_ENABLE_ANONYMOUS_POST = True
PYBB_ANONYMOUS_USERNAME = 'Anonymous'
Carefully set :ref:`PYBB_ANONYMOUS_USERNAME`. It is better to create user with this username yourself rather than left
it to autoregister on first anonymous post, somemone may want to use this username and register before first
anonymous post will be posted, in that case anonymous post will share same account with this user.
Anonymous topic views count cached for each topic. The reason to do this is not update database on each anonymous
request. Default value that will be cached is 100, this values controlled by :ref:`PYBB_ANONYMOUS_VIEWS_CACHE_BUFFER`
setting and can be disabled by this setting too.
================================================
FILE: docs/conf.py
================================================
#
# PyBBM documentation build configuration file, created by
# sphinx-quickstart on Mon Aug 22 16:28:25 2011.
#
# 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.
import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = []
# 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.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'PyBBM'
copyright = u'2011, Pavel Zukov'
# 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 = '0.3.1'
# The full version, including alpha/beta/rc tags.
release = 'rc'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = '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.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# 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']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'PyBBMdoc'
# -- Options for LaTeX output --------------------------------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_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', 'PyBBM.tex', u'PyBBM Documentation',
u'Pavel Zukov', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'pybbm', u'PyBBM Documentation',
[u'Pavel Zukov'], 1)
]
================================================
FILE: docs/contributing.rst
================================================
Contributing
============
Development happens on github, with main repo: https://github.com/hovel/pybbm
Issues, forks, patches and pull requests live here ;)
There are many ways to contribute to pybbm and you do not need to be a developper to do it:
1) Find a bug and submit an issue. You should:
* explain what was expected
* explain what was really done
* explain how to reproduce (environment, steps etc.)
2) Improve documentation
* you can correct typos or "bad english"
* add a new documentation part (for example, a "how to" than could help people when using pybb in
some use-case. eg: how to add news fields to `Topic` model).
3) Fix a bug. You should:
* write a test which should fail because of this bug
* write your bug fix
* run all pybbm tests
* be sure that code coverage does not decrease
* create the pull request
4) Add a new feature:
* quick-document it
* open an issue and discuss about it
* document it completely
* add tests for all parts of this new feature
* write your new feature
* run all pybbm tests
* be sure that code coverage does not decrease
* create the pull request
================================================
FILE: docs/customuser.rst
================================================
How to integrate custom user model in pybbm forum
=================================================
`Custom user model <https://docs.djangoproject.com/en/1.5/topics/auth/customizing/#substituting-a-custom-user-model>`_
is a great feature introduced in django framework since version 1.5. This topic describes how
to integrate your custom user model in pybbm forum application.
First of all pybbm uses some fields from standard User model and permission system.
The simplest way to make your custom model compatible with pybbm is to inherit from
`django.contrib.auth.models.AbstractUser`
Second way is to meet next requirements:
* define USERNAME_FIELD constant, which point to unique field on your model
* define email, is_staff, is_superuser fields or properties
* inherit from `django.contib.auth.models.PermissionsMixin` or reproduce django's
default permission system
Next step is to decide which model will store all fields for pybb forum profiles.
This model should be referenced to current User model (custom or default) in OneToOne
relationship. To easily setup such model you can use predefined `pybb.profiles.PybbProfile`
class. If profile model is custom user model itself then you can use `PybbProfile` class
as mixin for adding required fields. For more granunal control of fields in your forum
profile model you may not rely on `PybbProfile` and define all fields from
this model manually. You can use fields from another app (such as `avatar` or `language`),
but you have to define proxy properties in forum profile model and build custom
edit profile view, which will be override default pybb profile edit view in urls.py.
Next define `get_display_name` method for your profile model if you want custom username
rendering everywhere in forum. Default `pybb.Profile` model return user's username field
as display name, base `pybb.profiles.PybbProfile` class trying to return `self.user.get_username()`
or `self.get_username()`.
Last step is to correctly set `PYBB_PROFILE_RELATED_NAME` setting. You have to set this
setting to related_name parameter from profile's model from OneToOne relation to User model.
If you use custom user model and this model is profile model itself, then you have to set
this setting to `None`
================================================
FILE: docs/example.rst
================================================
Example projects
================
The PyBBM source code contains two example projects under the ``test/example_bootstrap`` and ``test/example_thirdparty`` directories.
Both are fully deployed and ready to use forum applications.
There is only one difference between these projects:
* ``example_bootstrap`` includes the LESS (a CSS preprocessor) files from Twitter Bootstrap.
* ``example_thirdparty`` leaves this to the thirdparty app ``pinax-theme-bootstrap``.
We recommend to use ``example_thirdparty`` to start with. If you starting from scratch it's probaly the best way to begin.
Running the example projects
----------------------------
Each example directory contains requirements.txt file, you can run::
pip install -r requirements.txt
to install all dependencies.
Also `example_bootstrap/fixtures` directory contains `demo_data.json` file with some example data.
So, you can run::
python manage.py loaddata <path to example_bootstrap>/fixtures/demo_data.json
from root directory to load some models in you database.
================================================
FILE: docs/filters.rst
================================================
Filtering spam, urls and other 'bad' stuff
==========================================
PyBBM contains two settings :ref:`PYBB_BODY_VALIDATOR` and :ref:`PYBB_BODY_CLEANERS` that create
very flexible system for filtering posts. Read this settings description for more information.
================================================
FILE: docs/index.rst
================================================
PyBBM - Django forum solution
=============================
PyBBM is a complete Django forum solution with the following features:
* Avatars
* Custom profiles and support of Custom User Model (since Django 1.5)
* Editable posts
* Pre-moderation
* Custom sanitization
* Anonymous posting
* Subscriptions
* Polls
* ...
All features are based on:
* 95% test code coverage
* Twitter Bootstrap compatible default theme
* Ready to use example projects
The main focus in the development of PyBMM is to build it in a way that allows *easy* integration in existing Django-based sites. This means that PyBMM does not provide features like user registration, password restoring or the user login page. (But the example projects show how to do these tasks ;))
Contents:
.. toctree::
:maxdepth: 2
install
settings
customuser
premoderation
permissions
anonymous
templatetags
example
filters
markup
javascript
contributing
testing
updates
pybbmigrate
originalpybb
problems
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
================================================
FILE: docs/install.rst
================================================
Installation
============
Mandatory dependencies
----------------------
PyBBM requires the following packages:
* django
* django-annoying
* unidecode (for slugifying instances for nicer urls)
By installing PyBBM with ``pip`` or ``easy_install``, all the above dependencies will be installed automatically::
pip install pybbm
Optional dependencies
---------------------
The following dependencies are optional. You can install them with ``pip install``:
* For better performance and easy images thumbnailing you can use any thumbnail django application.
PyBBM by default uses ``sorl.thumbnail`` if it is installed and included in your ``INSTALLED_APPS`` setting.
It is used for defining the `avatar` field in the `PybbProfile` model and for resizing the avatar
in the ``pybb/avatar.html`` template. If you decide to install ``sorl.thumbnail`` with django 1.7 you
have to install at least 11.12.1b version with::
pip install "sorl-thumbnail>=11.12.1b"
* ``PIL`` (Python Imaging Library) or its more up-to-date fork ``Pillow`` is optional if you configure ``sorl.thumbnail``
to use different backend or don't use ``sorl.thumbnail`` in general, but remember that using an ImageField in forms
requires the Python Imaging Library to be installed (i.e. you should install it if you use the built-in profile).
* PyBBM emulates the behavior and functionality of ``django-pure-pagination``, but we recommend to install it in your
project.
* Choose from ``bbcode`` and ``markdown`` libraries if you use one of the attached to pybbm markup engines.
For more information see :doc:`markup`
Fresh project
-------------
If you start a new project based on pybbm, checkout pybbm.org website codebase from https://github.com/hovel/pybbm_org
and skip the next steps.
Enable applications and edit settings
-------------------------------------
* Add the following apps to your ``INSTALLED_APPS`` to enable pybbm and required applications:
* pybb
::
INSTALLED_APPS = (
....
'pybb',
...
)
* Add ``pybb.context_processors.processor`` to your ``settings.TEMPLATE_CONTEXT_PROCESSORS``::
TEMPLATE_CONTEXT_PROCESSORS = (
...
'pybb.context_processors.processor',
...
)
* Add ``pybb.middleware.PybbMiddleware`` to your ``settings.MIDDLEWARE``::
MIDDLEWARE = (
...
'pybb.middleware.PybbMiddleware',
...
)
Enable PyBBM urlconf
--------------------
Put ``include('pybb.urls', namespace='pybb'))`` into main project ``urls.py`` file::
urlpatterns = [
....
(r'^forum/', include('pybb.urls', namespace='pybb')),
....
]
Enable your site profile
------------------------
Setup forum's profile model and ``PYBB_PROFILE_RELATED_NAME`` setting.
If you have no site profile, default settings will satisfy your needs.
If you have a custom user model, which stores all profile fields itself, or if you have custom site profile model, then check that it inherits from ``pybb.profiles.PybbProfile`` or contains all fields and properties from this class.
Then set ``PYBB_PROFILE_RELATED_NAME`` to ``None`` for custom user model, or to related_name
from OneToOne field related to User from custom site profile model.
For more information see :doc:`how to use custom user model with pybbm</customuser>`
Migrate database
----------------
Since django 1.7 release you have several combinations of installed packages that affect database migrations:
* **django >= 1.7**
Django since 1.7 version has it's own `migration engine <https://docs.djangoproject.com/en/1.7/topics/migrations/>`_.
Pybbm fully supports django 1.7 migrations, so just run::
python manage.py migrate pybb
* We recommend to use database engine that supports transaction management (all django backends except sqlite).
Otherwise you have small chance to face some inconsistency in DB after failed post/topic creation.
Templates
---------
Check that:
* Your templates directory contains the "base.html" template. Otherwise, set a custom base template with :ref:`PYBB_TEMPLATE`.
* Basic template contains at least a ``content`` block.
================================================
FILE: docs/javascript.rst
================================================
Javascript functionality
========================
Pybb does not depend on any javascript code. But javascript can provide more rich user experience
when interacting with forum.
For enabling javascript features your installation should meet some requirements:
* include in your templates link to `pybbjs.js` file, for example with ``{% static 'pybb/js/pybbjs.js' %}`` tag
* to enable deleting posts via ajax, add to your delete link inline onclick handler
with calling pybb_delete_post(url, post_id, confirm_text)
* to enable quoting selected text in post, add in each post link with `quote-selected-link` class
* to enable quoting full message via ajax, add in each post link with `quote-link` class and href
attribute pointed to view that return text to quote
* to enable insert in post body user's nickname by clicking with shift pressed, just wrap each post
with tag with `post-row` class and place inside it nickname wrapped by tag with `post-username` class
All of this features enabled in standard templates shipped with pybbm app.
================================================
FILE: docs/make.bat
================================================
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. changes to make an overview over all changed/added/deprecated items
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\PyBBM.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\PyBBM.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
:end
================================================
FILE: docs/markup.rst
================================================
Markup
======
How it works
------------
Every time user save new post, message parsed by markup parser to it's html representation.
It will include only allowed by engine html tags, html tags should be html-encoded and rendered
as simple text to prevent XSS attacks.
Pybbm includes two default engines. Actions needed to use these engines:
- bbcode engine: install required package with ``pip install bbcode`` command and set :ref:`PYBB_MARKUP` to ``'bbcode'``
- markdown engine: install required package with ``pip install markdown`` command and set :ref:`PYBB_MARKUP` to ``'markdown'``
Engine classes must inherit from `pybb.markup.base.BaseParser`
which defines three required methods:
- ``def format(self, text)`` method receives post's text as parameter and returns parsed message as html fragment
- ``def quote(self, text, username='')`` method receives quoted post's text and username and returns quoted string
in terms of markup engine
- ``def get_widget_cls(cls)`` class method which return the class to use as the widget
for the body field
How to change
-------------
If you want to write your custom engine you can write a new class which extends ``pybb.markup.base.BaseParser``
To change behavior of one of the default parsers you can override ``pybb.markup.bbcode.BBCodeParser`` or
``pybb.markup.markdown.MarkdownParser``.
For example, for adding additional formatter to bbcode parser you can write your own class in myproject.markup_engines.py::
from pybb.markup.bbcode import BBCodeParser
class CustomBBCodeParser(BBCodeParser):
def __init__(self):
super(CustomBBCodeParser, self).__init__()
self._parser.add_simple_formatter('ul', '<ul>%(value)s</ul>', transform_newlines=False, strip=True)
self._parser.add_simple_formatter('li', '<li>%(value)s</li>', transform_newlines=False, strip=True)
include it in :ref:`PYBB_MARKUP_ENGINES_PATHS` setting dict and point pybbm to use it by :ref:`PYBB_MARKUP` setting::
PYBB_MARKUP_ENGINES_PATHS = {'custom_bbcode': 'myproject.markup_engines.CustomBBCodeParser'}
PYBB_MARKUP = 'custom_bbcode'
or you can override default bbcode engine in settings.py::
PYBB_MARKUP_ENGINES_PATHS = {'bbcode': 'myproject.markup_engines.CustomBBCodeParser'}
PYBB_MARKUP = 'bbcode' # don't required because 'bbcode' is default value
Using different media assets
----------------------------
When you define your custom markup parser you may want to control how it will be rendered.
For that purpose pybbm uses django's concept of `widgets <https://docs.djangoproject.com/en/1.7/ref/forms/widgets/>`_
and their `media assets <https://docs.djangoproject.com/en/1.7/topics/forms/media/>`_.
Widget class used by markup engine controlled by ``get_widget_cls`` class method of engine class.
By default it returns ``widget_class`` attribute value. Pybbm default parsers use next widgets:
- pybb.base.BaseParser - django.forms.Textarea
- pybb.bbcode.BBCodeParser - pybb.bbcode.BBCodeWidget
- pybb.bbcode.MarkdownParser - pybb.markdown.MarkdownWidget
To get it working in your templates include ``{{ form.media }}`` or ``{{ form.media.css }}`` / ``{{ form.media.js }}``
in proper place in every template where you use post form.
================================================
FILE: docs/notifications.rst
================================================
Notifications
=============
Configure notifications
-----------------------
See those settings:
* :ref:`PYBB_DISABLE_SUBSCRIPTIONS`
* :ref:`PYBB_DEFAULT_AUTOSUBSCRIBE`
* :ref:`PYBB_DISABLE_NOTIFICATIONS`
* :ref:`PYBB_USE_DJANGO_MAILER`
When notifications are sent
---------------------------
Each time a post is saved (created or updated), subscribers will receive an email.
If you configure PYBB to use django-mailer (see :ref:`PYBB_USE_DJANGO_MAILER`), emails
will be sent when your cron job will run. Else, emails will be sent when post is saved.
Overwrite emails templates
--------------------------
You can overwrite three templates:
* `pybb/mail_templates/subscription_email_subject.html`: will be used to render the subject of the email
* `pybb/mail_templates/subscription_email_body.html`: will be used to render the text version's body of the email
* `pybb/mail_templates/subscription_email_body-html.html`: will be used to render the html version's body of the email
My test user is not receiving emails ?!
---------------------------------------
Emails matching this rules are not sent: <username>@example.com
================================================
FILE: docs/originalpybb.rst
================================================
PyBB Modified (PyBBM) and original PyBB
=======================================
PyBB originally developed by lorien in 2008-2010 has ben dropped from development in mid 2010.
This is a list of differences between PyBB and PyBBM as of mid 2011.
* All settings of pybbm have default values, see default.py file for detailed list.
* pybbm templates fill *content*, *head*, *title* and *breadcrumb* blocks for template defined in settings as :ref:`PYBB_TEMPLATE` ("base.html" by default).
* Markup engines can be configured as an ordinary settings.
* PyBBM designed to fit django-staticfiles (django <= 1.2) or django.contrib.staticfiles (django >= 1.3).
* Default pybbm templates and css files include only layout, minimal design and no coloring, so it's easy to fit any existed site colorscheme.
* PyBBM code covered with tests more than 80%
* PyBBM provides completely rewritten unread tracking with big performance improvement on large database
* Views rewritten to use as many generics as possible
* Number of external dependencies significantly reduced
* `PyBBM well documented <http://readthedocs.org/projects/pybbm/>`_
* PyBBM included two example projects for fast start.
================================================
FILE: docs/permissions.rst
================================================
Permissions
===========
Pybb allow you to manage permissions by overwriting a Permission handler.
See ``PYBB_PERMISSION_HANDLER`` setting.
Below are the current pybb permissions managed by the default Permission handler for each type of
"user".
Permissions for anonymous:
+----------------------------------+---------------------+---------------------+
| action | can do with | can do with |
| | PREMODERATION False | PREMODERATION True |
+==================================+=====================+=====================+
| view normal forum | yes | yes |
+----------------------------------+---------------------+---------------------+
| view hidden forum | no | no |
+----------------------------------+---------------------+---------------------+
| view other topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| view other post | yes | yes |
+----------------------------------+---------------------+---------------------+
| view own on moderation topic | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| view own on moderation post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| view other on moderation topic | no | no |
+----------------------------------+---------------------+---------------------+
| view other on moderation post | yes | no |
+----------------------------------+---------------------+---------------------+
| add post in normal topic | no | no |
+----------------------------------+---------------------+---------------------+
| add post in on moderation topic | no | no |
+----------------------------------+---------------------+---------------------+
| add post in closed topic | no | no |
+----------------------------------+---------------------+---------------------+
| edit own normal post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| edit own on moderation post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| edit other post | no | no |
+----------------------------------+---------------------+---------------------+
| delete own normal post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| delete own on moderation post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| delete other post | no | no |
+----------------------------------+---------------------+---------------------+
| close and unclose topic | no | no |
+----------------------------------+---------------------+---------------------+
| stick and unstick topic | no | no |
+----------------------------------+---------------------+---------------------+
| manage moderators | no | no |
+----------------------------------+---------------------+---------------------+
Permissions for a logged-in user:
+----------------------------------+---------------------+---------------------+
| action | can do with | can do with |
| | PREMODERATION False | PREMODERATION True |
+==================================+=====================+=====================+
| view normal forum | yes | yes |
+----------------------------------+---------------------+---------------------+
| view hidden forum | no | no |
+----------------------------------+---------------------+---------------------+
| view other topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| view other post | yes | yes |
+----------------------------------+---------------------+---------------------+
| view own on moderation topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| view own on moderation post | yes | yes |
+----------------------------------+---------------------+---------------------+
| view other on moderation topic | no | no |
+----------------------------------+---------------------+---------------------+
| view other on moderation post | yes | no |
+----------------------------------+---------------------+---------------------+
| add post in normal topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| add post in on moderation topic | no | no |
+----------------------------------+---------------------+---------------------+
| add post in closed topic | no | no |
+----------------------------------+---------------------+---------------------+
| edit own normal post | yes | yes |
+----------------------------------+---------------------+---------------------+
| edit own on moderation post | yes | yes |
+----------------------------------+---------------------+---------------------+
| edit other post | no | no |
+----------------------------------+---------------------+---------------------+
| delete own normal post | yes | yes |
+----------------------------------+---------------------+---------------------+
| delete own on moderation post | yes | yes |
+----------------------------------+---------------------+---------------------+
| delete other post | no | no |
+----------------------------------+---------------------+---------------------+
| close and unclose topic | no | no |
+----------------------------------+---------------------+---------------------+
| stick and unstick topic | no | no |
+----------------------------------+---------------------+---------------------+
| manage moderators | no | no |
+----------------------------------+---------------------+---------------------+
Permissions for a moderator of the current forum:
+----------------------------------+---------------------+---------------------+
| action | can do with | can do with |
| | PREMODERATION False | PREMODERATION True |
+==================================+=====================+=====================+
| view normal forum | yes | yes |
+----------------------------------+---------------------+---------------------+
| view hidden forum | no | no |
+----------------------------------+---------------------+---------------------+
| view other topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| view other post | yes | yes |
+----------------------------------+---------------------+---------------------+
| view own on moderation topic | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| view own on moderation post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| view other on moderation topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| view other on moderation post | yes | yes |
+----------------------------------+---------------------+---------------------+
| add post in normal topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| add post in on moderation topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| add post in closed topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| edit own normal post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| edit own on moderation post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| edit other post | yes | yes |
+----------------------------------+---------------------+---------------------+
| delete own normal post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| delete own on moderation post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| delete other post | yes | yes |
+----------------------------------+---------------------+---------------------+
| close and unclose topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| stick and unstick topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| manage moderators | no | no |
+----------------------------------+---------------------+---------------------+
Permissions for a "is_staff" user without pybb permissions:
+----------------------------------+---------------------+---------------------+
| action | can do with | can do with |
| | PREMODERATION False | PREMODERATION True |
+==================================+=====================+=====================+
| view normal forum | yes | yes |
+----------------------------------+---------------------+---------------------+
| view hidden forum | yes | yes |
+----------------------------------+---------------------+---------------------+
| view other topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| view other post | yes | yes |
+----------------------------------+---------------------+---------------------+
| view own on moderation topic | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| view own on moderation post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| view other on moderation topic | no | no |
+----------------------------------+---------------------+---------------------+
| view other on moderation post | yes | no |
+----------------------------------+---------------------+---------------------+
| add post in normal topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| add post in on moderation topic | no | no |
+----------------------------------+---------------------+---------------------+
| add post in closed topic | no | no |
+----------------------------------+---------------------+---------------------+
| edit own normal post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| edit own on moderation post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| edit other post | no | no |
+----------------------------------+---------------------+---------------------+
| delete own normal post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| delete own on moderation post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| delete other post | no | no |
+----------------------------------+---------------------+---------------------+
| close and unclose topic | no | no |
+----------------------------------+---------------------+---------------------+
| stick and unstick topic | no | no |
+----------------------------------+---------------------+---------------------+
| manage moderators | yes | yes |
+----------------------------------+---------------------+---------------------+
Permissions for a "is_staff" user with pybb permissions:
+----------------------------------+---------------------+---------------------+
| action | can do with | can do with |
| | PREMODERATION False | PREMODERATION True |
+==================================+=====================+=====================+
| view normal forum | yes | yes |
+----------------------------------+---------------------+---------------------+
| view hidden forum | yes | yes |
+----------------------------------+---------------------+---------------------+
| view other topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| view other post | yes | yes |
+----------------------------------+---------------------+---------------------+
| view own on moderation topic | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| view own on moderation post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| view other on moderation topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| view other on moderation post | yes | yes |
+----------------------------------+---------------------+---------------------+
| add post in normal topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| add post in on moderation topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| add post in closed topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| edit own normal post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| edit own on moderation post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| edit other post | yes | yes |
+----------------------------------+---------------------+---------------------+
| delete own normal post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| delete own on moderation post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| delete other post | yes | yes |
+----------------------------------+---------------------+---------------------+
| close and unclose topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| stick and unstick topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| manage moderators | yes | yes |
+----------------------------------+---------------------+---------------------+
Permissions for superuser:
+----------------------------------+---------------------+---------------------+
| action | can do with | can do with |
| | PREMODERATION False | PREMODERATION True |
+==================================+=====================+=====================+
| view normal forum | yes | yes |
+----------------------------------+---------------------+---------------------+
| view hidden forum | yes | yes |
+----------------------------------+---------------------+---------------------+
| view other topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| view other post | yes | yes |
+----------------------------------+---------------------+---------------------+
| view own on moderation topic | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| view own on moderation post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| view other on moderation topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| view other on moderation post | yes | yes |
+----------------------------------+---------------------+---------------------+
| add post in normal topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| add post in on moderation topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| add post in closed topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| edit own normal post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| edit own on moderation post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| edit other post | yes | yes |
+----------------------------------+---------------------+---------------------+
| delete own normal post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| delete own on moderation post | see logged-in user | see logged-in user |
+----------------------------------+---------------------+---------------------+
| delete other post | yes | yes |
+----------------------------------+---------------------+---------------------+
| close and unclose topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| stick and unstick topic | yes | yes |
+----------------------------------+---------------------+---------------------+
| manage moderators | yes | yes |
+----------------------------------+---------------------+---------------------+
================================================
FILE: docs/premoderation.rst
================================================
Pre-moderation
==============
PyBBM shipped with fully customizable pre-moderation system.
Because in different circumstances you may need different pre-moderation conditions,
pybbm gives you ability to create custom filter for messages that require pre-moderation.
All you need is to provide function from two arguments: `user` and `body`. This function
should return `True` if message pass filter and `False` if message require pre-moderation.
For example, next filter allow to post without pre-moderation only for superusers::
def check_superuser(user, post):
if user.is_superuser:
return True
return False
Told pybbm to use this function by setting :ref:`PYBB_PREMODERATION` in settings::
PYBB_PREMODERATION = check_superuser
================================================
FILE: docs/problems.rst
================================================
Known problems
==============
Using with a database that doest not support microseconds
---------------------------------------------------------
If you are using a database which does not support microseconds (MySQL before v5.7 for eg.), a
forum can be wrongly marked read. It can happens if a user who read the only unread topic from
a forum in the same time an other user create / update an other topic on the same forum.
================================================
FILE: docs/pybbmigrate.rst
================================================
Migrating from pybb (lorien package)
====================================
PyBBM was drop-in replacement for pybb in 2010, but current
replacing current version was not checked.
You can try to:
* Replace `pybb` package with `pybbm`
* Migrate forward
* Set AUTH_PROFILE
* Migrate old profiles with `manage.py migrate_profile` command
================================================
FILE: docs/settings.rst
================================================
Settings
========
Basic settings
--------------
.. _PYBB_TOPIC_PAGE_SIZE:
PYBB_TOPIC_PAGE_SIZE
....................
Number of posts in topic page
Default: 10
.. _PYBB_FORUM_PAGE_SIZE:
PYBB_FORUM_PAGE_SIZE
....................
Number of topics in forum page
Default: 10
.. _PYBB_FREEZE_FIRST_POST:
PYBB_FREEZE_FIRST_POST
......................
Freeze first post in topics (show on every page)
Default: False
.. _PYBB_DEFAULT_TITLE:
PYBB_DEFAULT_TITLE
..................
Default title for forum index page
Default: 'PYBB Powered Forum'
.. _PYBB_DEFAULT_AUTOSUBSCRIBE:
PYBB_DEFAULT_AUTOSUBSCRIBE
..........................
Users will be automatically subscribed to topic when create post in it.
Default: True
.. _PYBB_DISABLE_SUBSCRIPTIONS:
PYBB_DISABLE_SUBSCRIPTIONS
..........................
Users won't be able to subscribe to topic.
If you want to have a more advanced mode than enable / disable (for example, use model permissions),
you just have to overwrite the "may_subscribe_topic" method of the Permission handler.
If you disabled topic subscriptions, already subscribed users will still receive notifications:
see ``PYBB_DISABLE_NOTIFICATIONS`` to stop notifications sending.
Default: False
.. _PYBB_DISABLE_NOTIFICATIONS:
PYBB_DISABLE_NOTIFICATIONS
..........................
Users which have subscribed to a topic won't receive notifications but still be able to subscribe
to topics. See ``PYBB_DISABLE_NOTIFICATIONS`` to disable topic subscription too.
This is usefull if you want to to use your own notification system. Additionally, if your custom
user model has a ``receive_emails`` field, it will be used to determine whether to send notification
emails to each user.
Default: False
.. _PYBB_USE_DJANGO_MAILER:
PYBB_USE_DJANGO_MAILER
......................
When True and django-mailer app installed, then for sending email pybbm will use this app. With django-mailer you can
manage emails from your site in queue. But in this case you have to periodically actually
send emails from queue. For more information see `app home page <https://github.com/pinax/django-mailer/>`_.
Default: False
Emoticons
---------
.. _PYBB_SMILES_PREFIX:
PYBB_SMILES_PREFIX
..................
Prefix for emoticons images set, related to STATIC_URL.
Default: 'pybb/emoticons'
.. _PYBB_SMILES:
PYBB_SMILES
...........
Dict for emoticon replacement.
Key - text to be replaced, value - image name.
Default::
{
'>_<': 'angry.png',
':.(': 'cry.png',
'o_O': 'eyes.png',
'[]_[]': 'geek.png',
'8)': 'glasses.png',
':D': 'lol.png',
':(': 'sad.png',
':O': 'shok.png',
'-_-': 'shy.png',
':)': 'smile.png',
':P': 'tongue.png',
';)': 'wink.png'
}
e.g. text ";)" in post will be replaced to::
<img src="{{ STATIC_URL }}{{ PYBB_SMILES_PREFIX }}wink.png">
with default setting.
User profile settings
---------------------
Next settings used only if you don't customize user profile model,
user profile creation form or templates.
.. _PYBB_PROFILE_RELATED_NAME:
PYBB_PROFILE_RELATED_NAME
.........................
Related name from profile's OneToOne relationship to User model. If profile model is User
model itself then set it to `None`.
Default: 'pybb_profile'
For more information see :doc:`how to use custom user model with pybbm</customuser>`
.. _PYBB_AVATAR_WIDTH:
PYBB_AVATAR_WIDTH
.................
Avatar width to use in templates (avatars scaled using sorl.thumbnail
if it installed and included in project).
Default: 80
.. _PYBB_AVATAR_HEIGHT:
PYBB_AVATAR_HEIGHT
..................
Avatar height to use in templates (avatars scaled using sorl.thumbnail
if it installed and included in project)
Default: 80
.. _PYBB_MAX_AVATAR_SIZE:
PYBB_MAX_AVATAR_SIZE
....................
Maximum avatar size, in bytes
Default: 51200 (50 Kb)
.. _PYBB_DEFAULT_TIME_ZONE:
PYBB_DEFAULT_TIME_ZONE
......................
Default time zone for forum as integer. E.g. setting to 1 means GMT+1 zone.
Default: 3 (Moscow)
.. _PYBB_SIGNATURE_MAX_LENGTH:
PYBB_SIGNATURE_MAX_LENGTH
.........................
Limit of symbols in user signature
Default: 1024
.. _PYBB_SIGNATURE_MAX_LINES:
PYBB_SIGNATURE_MAX_LINES
........................
Limit of lines in user signature
Default: 3
.. _PYBB_DEFAULT_AVATAR_URL:
PYBB_DEFAULT_AVATAR_URL
.......................
Will be used if user doesn't upload avatar
Default: settings.STATIC_URL + 'pybb/img/default_avatar.jpg'
Style
-----
You can use builtin templates with custom basic template.
.. _PYBB_TEMPLATE:
PYBB_TEMPLATE
.............
Builtin templates will inherit this template
Default: 'base.html
.. _PYBB_TEMPLATE_MAIL_TXT:
PYBB_TEMPLATE_MAIL_TXT
.............
Builtin `txt` emails templates will inherit this template
Default: 'pybb/mail_templates/base.html
.. _PYBB_TEMPLATE_MAIL_HTML:
PYBB_TEMPLATE_MAIL_HTML
.............
Builtin `html` emails templates will inherit this template
Default: 'pybb/mail_templates/base-html.html
Markup engines
--------------
.. _PYBB_MARKUP:
PYBB_MARKUP
...........
Markup engine used in forum. Also see :ref:`PYBB_MARKUP_ENGINES` below
Default: 'bbcode`
.. _PYBB_MARKUP_ENGINES_PATHS:
PYBB_MARKUP_ENGINES_PATHS
.........................
Dict with avaiable markup engines path. One of them should be selected with PYBB_MARKUP
Markup engine should be a path to a class, that inherits from `pybb.markup.base.BaseParser`.
Markup engine should take care of replacing smiles in body with related emoticons.
by default PyBBM support `bbcode` and `markdown` markup::
{
'bbcode': 'pybb.markup.bbcode.BBCodeParser',
'markdown': 'pybb.markup.markdown.MarkdownParser'
}
Please note, that previous version of pybb used two different settings :
`PYBB_MARKUP_ENGINES` and `PYBB_QUOTE_ENGINES` which were callables.
This is still supported, but is deprecated.
.. _PYBB_MARKUP_ENGINES:
PYBB_MARKUP_ENGINES (deprecated)
................................
Should be the same dict with paths to markup engine classes as `PYBB_MARKUP_ENGINES_PATH` setting
Default: `PYBB_MARKUP_ENGINES_PATHS`.
For more information see :doc:`markup`
.. _PYBB_QUOTE_ENGINES:
PYBB_QUOTE_ENGINES (deprecated)
...............................
**Deprecation note: Every markup class must inherit from** `pybb.markup.base.BaseParser`
**For more information see** :doc:`markup`
Should be the same dict with paths to markup engine classes as `PYBB_MARKUP_ENGINES_PATH` setting
Default: `PYBB_MARKUP_ENGINES_PATHS`.
Post cleaning/validation
------------------------
.. _PYBB_BODY_CLEANERS:
PYBB_BODY_CLEANERS
..................
List of paths to 'cleaner' functions for body post to automatically remove undesirable content from posts.
Cleaners are user-aware, so you can disable them for some types of users.
Each function in list should accept `auth.User` instance as first argument and `string` instance as second, returned value will be sended to next function on list or saved and rendered as post body.
For example this is enabled by default `rstrip_str` cleaner::
def rstrip_str(user, str):
if user.is_staff:
return str
return '\n'.join([s.rstrip() for s in str.splitlines()])
Default::
PYBB_BODY_CLEANERS = ['pybb.markup.base.rstrip_str', 'pybb.markup.base.filter_blanks']
.. _PYBB_BODY_VALIDATOR:
PYBB_BODY_VALIDATOR
...................
Extra form validation for body of post.
Called as::
PYBB_BODY_VALIDATOR(user, body)
at `clean_body` method of `PostForm` Here you can do various checks based on user stats.
E.g. allow moderators to post links and don't allow others. By raising::
forms.ValidationError('Here Error Message')
You can show user what is going wrong during validation.
You can use it for example for time limit between posts, preventing URLs, etc.
Default: None
Anonymous/guest posting
-----------------------
.. _PYBB_ENABLE_ANONYMOUS_POST:
PYBB_ENABLE_ANONYMOUS_POST
..........................
Allow post for not-authenticated users.
Default: False
See :doc:`anonymous posting</anonymous>` for details.
.. _PYBB_ANONYMOUS_USERNAME:
PYBB_ANONYMOUS_USERNAME
.......................
Username for anonymous posts. If no user with this username exists it will be created on first anonymous post.
Default: 'Anonymous'
.. _PYBB_ANONYMOUS_VIEWS_CACHE_BUFFER:
PYBB_ANONYMOUS_VIEWS_CACHE_BUFFER
.................................
Number of anonymous views for each topic, that will be cached. For disabling caching anonymous views
just set it to `None`.
Default: 100
Premoderation
-------------
.. _PYBB_PREMODERATION:
PYBB_PREMODERATION
..................
Filter for messages that require pre-moderation.
Default: False
See :doc:`Pre-moderation</premoderation>` for details.
Attachments
-----------
.. _PYBB_ATTACHMENT_ENABLE:
PYBB_ATTACHMENT_ENABLE
......................
Enable attahcments for all users.
Default: False
.. _PYBB_ATTACHMENT_SIZE_LIMIT:
PYBB_ATTACHMENT_SIZE_LIMIT
..........................
Maximum attachment limit (in bytes).
Default: 1048576 (1Mb)
.. _PYBB_ATTACHMENT_UPLOAD_TO:
PYBB_ATTACHMENT_UPLOAD_TO
.........................
Directory in your media path for uploaded attacments.
Default: 'pybb_upload/attachments'
Polls
-----
Note: For disabling polls on your forum, write custom permission handler and return from `may_create_poll` method `False`
See `PYBB_PERMISSION_HANDLER` setting.
.. _PYBB_POLL_MAX_ANSWERS:
PYBB_POLL_MAX_ANSWERS
.....................
Max count of answers, that user can add to topic.
Default: 10
Permissions
-----------
.. _PYBB_AUTO_USER_PERMISSIONS:
PYBB_AUTO_USER_PERMISSIONS
..........................
Automatically adds add post and add topic permissions to users on user.save().
Default: True
.. _PYBB_PERMISSION_HANDLER:
PYBB_PERMISSION_HANDLER
.......................
If you need custom permissions (for example, private forums based on application-specific
user groups), you can set :ref:`PYBB_PERMISSION_HANDLER` to a class which inherits from
`pybb.permissions.DefaultPermissionHandler` (default), and override any of the `filter_*` and
`may_*` method. For details, look at the source of `pybb.permissions.DefaultPermissionHandler`.
All methods from permission handler (custom or default) can be used in templates as filters,
if loaded pybb_tags. In template will be loaded methods which start with 'may' or 'filter'
and with three or two arguments (include 'self' argument)
Default: 'pybb.permissions.DefaultPermissionHandler'
Urls
----
.. _PYBB_NICE_URL:
PYBB_NICE_URL
.............
Changes old/classics URLs to more semantic URLs using Category/Forum/Topic's slug.
For example www.yourforum.com/forum/1 becomes www.yourforum.com/c/category_slug/forum_slug.
Old URLs will have a permanent redirections to new ones.
Default: False
.. _PYBB_NICE_URL_PERMANENT_REDIRECT:
PYBB_NICE_URL_PERMANENT_REDIRECT
................................
When PYBB is set to use PYBB_NICE_URL, this setting changes the HTTP response code used
to redirect old style URL to new one. True (default) use 301 (permantent) redirect. If set to False,
it uses 302 (temporary) redirect. `False` value is usefull for testing period to not loose SEO related
to old URLs, then, once testing period is over, setting this to True will ensure that your old URLs will
be updated to the new ones next time the Search Engine will check it.
Default: True
.. _PYBB_NICE_URL_SLUG_DUPLICATE_LIMIT:
PYBB_NICE_URL_SLUG_DUPLICATE_LIMIT
..................................
Limit for checking duplicate slugs.
After reaching this limit while trying to find unique slug ValidationError will be raised.
Default: 100
.. PYBB_ENABLE_ADMIN_POST_FORM:
PYBB_ENABLE_ADMIN_POST_FORM
...........................
Enable admin post form that allowed staff to post with any username automagically creating it if it did not exist.
Default: True
.. PYBB_ALLOW_DELETE_OWN_POST:
PYBB_ALLOW_DELETE_OWN_POST
..........................
Allow non-superusers to delete their own posts.
Default: True
================================================
FILE: docs/templatetags.rst
================================================
Useful template tags and filters
================================
Next filters and tags can be used when `pybb_tags` loaded in template:
* PyBBM passes all filter_* and may_* methods from current permission handler
to templates as filters with pybb_ prefix. So you can use they as::
{% if user|may_view_topic:topic %}
you can view {{ topic }}
{% endif %}
or::
{% with queryset=user|filter_topics:topic_queryset %}
{# operations on queryset there #}
{% endwith %}
* `pybb_get_latest_topic` and `pybb_get_latest_posts` assignment tags you can use on
every page for getting latest topics ans posts, for example for rendering in side block.
Also you can pass `user` parameter (default to user from template context) for geting topics
or posts available for specific user and `cnt` parameter for get specific count of topics
or posts::
{% pybb_get_latest_topic cnt=30 as topics %}
{# operation on topics list there #}
* `pybb_get_profile` assignment tag can be used to get forum profile instance for any user
passed as `user` argument::
{% pybb_get_profile user=post.user as post_user_profile %}
{# use profile fields there #}
================================================
FILE: docs/testing.rst
================================================
Testing
=======
PyBBM has good unittest coverage. There is two way to test pybbm: a "multi-env way" via tox
(multiple versions of Django, Python...), and a "local env way" with your
version of python and locally installed python packages.
Testing with tox (recommended)
------------------------------
This is the recommended way to test pybbm if you want to contribute.
You must have tox installed on your system. (eg: `sudo pip install tox`)
1) Clone your github pybbm fork and go in its directory::
git clone git@github.com:yourGithubUsername/pybbm.git
cd pybbm
2) run tox::
tox
That's all ;-). Tox will tests pybbm in multiple environnements configured in the pybbm's tox.ini.
If you want to test only a specific environment from that list, you can run tox with the "-e"
option. For example, this command will test pybbm only with python 2.7 and Django 1.8::
tox -e py27-django18
There is a special tox env to check code coverage called `coverage`. By running it, it will output
a summary of code coverage and will generate a HTML rapport (in `htmlcov/index.html`) to see which
part of code is not yet tested.
**If you add new features to pybbm, ensure that lines you add are covered by tests** ;-)
Testing in your local environment
-----------------------------------
If you want to contribute, you should use the "tox way" to test your contributions before
creating a pull-request ! This testing way will allow you to test pybbm in your current local
environment. It is usefull if you have a specific environment which is not covered by tox.ini.
If you already have a working pybb in your environment, you can go to the step 4.
Else, steps 1-3 will allow you to have a minimal environment to run pybb test project.
1) Your environment must be ready to use pip and install Pillow and lxml python packages.
For Debian, the simplest way is to install debian python packages with their dependencies::
sudo apt-get install python-pip python-lxml python-pillow
2) Now, your environment is ready to install python packages via pip. Install pybbm from your
github fork with the "-e" option to be able to contribute, and install the test requirements::
mkdir -p ~/tests/ && cd ~/tests/
pip install --user -e git+git@github.com:yourGithubUsername/pybbm.git#egg=pybbm
pip install --user -r src/pybbm/test/test_project/requirements_test.txt
3) Now, add your user-local pip install directory and the pybbm directory to your PYTHONPATH::
export PYTHONPATH=$PYTHONPATH:~/.local/lib/python3.7/site-packages/:~/tests/src/pybbm
4) Now, you have an editable version of pybbm and you can run tests from the "test_project"::
cd ~/tests/src/pybbm/test/test_project/
python manage.py test pybb
5) If you want to display a coverage summary and create a coverage HTML report::
pip install --user coveralls
PATH=$PATH:~/.local/bin/
cd ~/tests/src/pybbm/test/test_project/
coverage run --rcfile ../../.coveragerc manage.py test pybb
coverage report
coverage html
Index HTML report is created in `htmlcov/index.html`
================================================
FILE: docs/updates.rst
================================================
PyBBM Changelog
===============
0.18.4 -> 0.19.0
----------------
* PyBBM is now compatible with Django 1.8, 1.11, 2.0
* Fix permissions and add documentation for default permissions
* Allow moderators to move a topic or split posts
* Update translations
* Multiple other fixes, refactoring
0.18.3 -> 0.18.4
----------------
* Fix misspelling in Swedish translation
0.18.2 -> 0.18.3
----------------
* Fix 0005 and 0006 migrations (changes will not affect db, so it's ok if this migrations were already executed)
0.18.1 -> 0.18.2
----------------
* Minor fixes.
0.18 -> 0.18.1
--------------
* Minor fixes.
0.17.3 -> 0.18
--------------
* PyBBM is now compatible with Django>=1.8,<1.11
* Allow non-moderators to delete their own posts.
* Add setting to enable or disable admin post form.
* Add Swedish translation.
* Use FileField instead of ImageField when pillow is not available to make pillow depencency optional.
* Use staticfiles in all templates.
* Improve permission checking.
* Allow users to subscribe to a forum.
* Add a form to grant users moderator privileges.
* Add notification's emails HTML alternative.
* Add the ability to the user to use their attachments inside their posts to render it as link, image etc.
* Multiple fixes and improvements.
0.17 -> 0.17.3
--------------
* Fast fix for migrations for Posgres database.
If you already get and applied migrations from 0.17 version (for example on MySQL DB) you can skip new
migrations with `manage.py migrate pybb --fake`
0.16.1 -> 0.17
--------------
* Topic and post creation wrapped in transaction
* All topic/post/poll related forms can be overridden when custom view inherites pybbm view
* Demo data for example projects
* Using active markup engine when quoting posts via javascript
* Functionality to support disabling default pybbm subscriptions and notifications and
new settings: :ref:`PYBB_DISABLE_SUBSCRIPTIONS` and :ref:`PYBB_DISABLE_NOTIFICATIONS`
* Fixed sorl.thumbnail/easy_thumbnail compatibility in standard `pybb/avatar.html` template
* Improved example projects
* Removed applying `urlize` filter over html produced by markdown parser
(it doesn't play nicely with html markup as noted in django's docs)
* django 1.8 compatibility
* common django layout for test project
* use mysqlclient package for testing installation with mysql database backend on python 3
* optional enabling "nice urls" for entire forum,
that looks like '<forum prefix>/c/<category slug>/<forum slug>/<topic slug>/'
0.16 -> 0.16.1
--------------
* Fast fixes
0.15.6 -> 0.16
--------------
* Django 1.7 compatibility.
* Fixed creating custom profile model of any class defined in settings with right related name to user model.
*Migration note*: If you have workaround for creating profile in your code, you should remove it for
preventing possible dubplicate unique key error on user creating.
* New get_display_name method for profile model used to unification displaying username through forum
* New markup processing. See :doc:`markup`
0.15.5 -> 0.15.6
----------------
* Make all migrations compatible with custom user model. Break dependency on sorl.thumbnail in migrations
* Compatibility functions moved to compat.py module
* Email notifications optimization
* Example_bootstrap projects now based on bootstrap 3
* Fixes and improvements
0.15.4 -> 0.15.5
----------------
* Fixed bug when user can vote (or cancel vote) when topic was closed.
* Added `may_vote_in_topic` method to permission handler.
* Fixed blocking user view
0.15.3 -> 0.15.4
----------------
* Hot fixes to bbcode transform
0.15.2 -> 0.15.3
----------------
* bbcode engine simplified
0.15.1 -> 0.15.2
----------------
* Pybbm specific forms moved to views' attributes, added new functions to views to get such forms dynamically.
This makes overriding pybbm forms much easier
* Moving from unmaintained postmarkup package to bbcode project as default bbcode render engine
Changed output html for [code] tag. It will be <code></code> tags instead of <div class="code"></div>.
So you should duplicate styles applied to div.code for code html tag.
* Japanese translation
0.15 -> 0.15.1
--------------
* Hot fixes for Python 3 support
* Fixes for Chinese translation
0.14.9 -> 0.15
--------------
* Python 3 support
* Chinese translation
0.14.8 -> 0.14.9
----------------
* Two new methods added to permission handler: `may_attach_files` and `may_create_poll`. First method used for
restrict attaching files to post by user. By default it depends on :ref:`PYBB_ATTACHMENT_ENABLE` setting.
Second may be used to restrict some users to create/edit polls. By default it always return `True`.
For disabling polls on your forum, just write custom permission handler and return from this method `False`
0.14.7 -> 0.14.8
----------------
* Improved javascript functionality: quote selected text, qoute full original message via ajax,
insert nickname in post body. For enabling this functionality you should satisfy :doc:`some requirements</javascript>`
in your templates
* Support for nested forums
* `PybbProfile` abstract model moved to `pybb.profiles` module to avoid circular imports when checking models.
0.14.6 -> 0.14.7
----------------
* Django 1.6 compatibility
* unblock user functionality added
0.14.5 -> 0.14.6
----------------
* Cache anonymous views count for topic and save it in database only when some count reached (100 by default).
This value can be changed by setting :ref:`PYBB_ANONYMOUS_VIEWS_CACHE_BUFFER`. Also added custom filter
`pybbm_calc_topic_views` that calc actual views count for topic
* Fix for migration that may fails on clean mysql installation
* Fixed performance issue with feed views
* Using custom permissions handler in feed views
0.14.4 -> 0.14.5
----------------
* Minor fixes
0.14.3 -> 0.14.4
----------------
* Fix for migration that may fails on clean mysql installation (not fixed really, filxed after 0.14.5)
* Make example_thirdparty project bootstrap3 compatible
0.14.2 -> 0.14.3
----------------
* Show only available topics (by permission handler) in ForumView
0.14.1 -> 0.14.2
----------------
* Fixed MultipleObjectReturned when topic has more than one moderator
0.14 -> 0.14.1
--------------
* Fixed circular import issue
0.13.1 -> 0.14
--------------
* Restored views for rendering user's posts and topics and link to that views from profile info page
* Broken hard dependency from EditProfileView and EditProfileForm classes in forum
* Ability for users to cancel their poll vote
* Block user view accepts only POST requests
* If `block_and_delete_messages` passed to request.POST for block user view,
then all user's messages will be deleted
0.13 -> 0.13.1
--------------
* Hotfix for rendering avatars
0.12.5 -> 0.13
--------------
* You can add first-unread get parameter to the topic url to provide link to first unread post from topic
* Removed django-mailer, pytils, sorl-thumbnail, south, django-pure-pagination from hard dependencies
* Support Custom User model introduced in django 1.5. Do not forget to define :ref:`PYBB_PROFILE_RELATED_NAME`
in settings, if you don't use predefined `pybb.PybbProfile` model See :doc:`how to use custom user model
with pybbm</customuser>`
* Dropped support for django 1.3
* Experimental support for python 3
* Removed django-mailer from hard dependencies, you have to manually install it for using it's functionality
0.12.4 -> 0.12.5
----------------
* More flexible forms/forms fields rendering in templates
Strongly recommended to check rendering of pybbm forms on your site (edit profile, poll/topic create/edit)
* Additional template for markitup preview
You can override `pybb/_markitup_preview.html` to provide your styling for <code>, <pre> and other markitup tags
* Improved permissions handling see :ref:`PYBB_PERMISSION_HANDLER` setting in :doc:`settings</settings>`
* Fixed bugs and improved performance
0.12.3 -> 0.12.4
----------------
* :ref:`PYBB_USE_DJANGO_MAILER` setting
0.12.2 -> 0.12.3
----------------
* German translation
0.11 -> 0.12
------------
* Fixed bug when the answers to poll unexpectedly deleted. Strongly recommended to update to this version, if using
polls subsystem
* Polish translation
0.10 -> 0.11
------------
* Ability to override standard message when user doesn't login and not alowed anonymous posts by
:ref:`PYBB_ENABLE_ANONYMOUS_POST` setting. It may be useful when project doesn't have ``registration_register``
and/or ``auth_login`` url names in ``urls.py``
* Content in each ``topic.html`` and ``forum.html`` is wrapped in ``<div>`` tag with ``topic`` and ``forum`` classes
accordingly
0.9 -> 0.10
-----------
* Templates are updated for 2nd version of twitter bootstrap
* Bootstrap less files removed from pybb.
* Refactored example projects. `test` folder now contains two examples:
* `example_bootstrap` shows how to include bootstrap files in your project
* `example_thirdparty` shows how to use another project like `pinax-theme-bootstrap <https://github.com/pinax/pinax-theme-bootstrap>`_ to style forum
* New poll feature added. When user creates new topic he can add poll question and some answers. Answers count
can vary from 2 to :ref:`PYBB_POLL_MAX_ANSWERS` setting (10 by default)
* Dropped support for self containing CSS in pybb.css file and PYBB_ENABLE_SELF_CSS setting.
0.8 -> 0.9
----------
The PYBB_BUTTONS setting is removed and overridable `pybb/_button_*.html`
templates for `save`, `new topic` and `submit` buttons are provided in case
css styling methods are not enough.
0.6 -> 0.7
----------
If you use custom BODY_CLEANER in your settings, rename this setting to :ref:`PYBB_BODY_VALIDATOR`
0.5 -> 0.6
----------
Version 0.6 has significant changes in template subsystem, with main goal to make them more configurable and simple.
* CSS now not included with project.
* For a limited time legacy `pybb.css` can be enabled by activating :ref:`PYBB_ENABLE_SELF_CSS` settings (just set it for True).
* Twitter bootstrap now included in project tree
* Default templates now provide fine theme with twitter bootstrap, corresponded .less file 'pybb_bootstrap.less'
and builded `pybb_bootstrap.css` can be located in static. You can find example of usage in test directory.
* Pagination and breadcrumb templates changed:
* pagination template moved from `templates/pybb/pagination/` to `templates/pybb`
* pagination template changed from plain links to ul/li list
* breadcrumb now live in separated template and changed from plain links to ul/li list
* `add_post_form.html` template renamed to `post_form.html`
* :ref:`PYBB_FORUM_PAGE_SIZE` default value changed from 10 to 20
================================================
FILE: pybb/__init__.py
================================================
default_app_config = 'pybb.apps.PybbConfig'
================================================
FILE: pybb/admin.py
================================================
# -*- coding: utf-8
from copy import deepcopy
from django.utils.translation import gettext_lazy as _
from django.contrib import admin
from django.urls import reverse
from pybb import permissions
from pybb.models import Category, Forum, Topic, Post, Profile, Attachment, PollAnswer
from pybb import compat, util
username_field = compat.get_username_field()
class ForumInlineAdmin(admin.TabularInline):
model = Forum
fields = ['name', 'hidden', 'position']
extra = 0
class CategoryAdmin(admin.ModelAdmin):
prepopulated_fields = {'slug': ('name',)}
list_display = ['name', 'position', 'hidden', 'forum_count']
list_per_page = 20
ordering = ['position']
search_fields = ['name']
list_editable = ['position']
inlines = [ForumInlineAdmin]
class ForumAdmin(admin.ModelAdmin):
prepopulated_fields = {'slug': ('name',)}
list_display = ['name', 'category', 'hidden', 'position', 'topic_count', ]
list_per_page = 20
raw_id_fields = ['moderators']
ordering = ['-category']
search_fields = ['name', 'category__name']
list_editable = ['position', 'hidden']
fieldsets = (
(None, {
'fields': ('category', 'parent', 'name', 'hidden', 'position', )
}
),
(_('Additional options'), {
'classes': ('collapse',),
'fields': ('updated', 'description', 'headline', 'post_count', 'slug')
}
),
)
def get_fieldsets(self, request, obj=None):
"""
adds moderators field to Additionnal options fieldset only if
the request user has permission to manage moderators
"""
fieldsets = super(ForumAdmin, self).get_fieldsets(request, obj)
if permissions.perms.may_manage_moderators(request.user):
fieldsets = deepcopy(fieldsets)
fieldsets[-1][1]['fields'] += ('moderators',)
return fieldsets
class PollAnswerAdmin(admin.TabularInline):
model = PollAnswer
fields = ['text', ]
extra = 0
class TopicAdmin(admin.ModelAdmin):
prepopulated_fields = {'slug': ('name',)}
list_display = ['name', 'forum', 'created', 'head', 'post_count', 'poll_type',]
list_per_page = 20
raw_id_fields = ['user', 'subscribers']
ordering = ['-created']
date_hierarchy = 'created'
search_fields = ['name']
fieldsets = (
(None, {
'fields': ('forum', 'name', 'user', ('created', 'updated'), 'poll_type',)
}
),
(_('Additional options'), {
'classes': ('collapse',),
'fields': (('views', 'post_count'), ('sticky', 'closed'), 'subscribers', 'slug')
}
),
)
inlines = [PollAnswerAdmin, ]
class TopicReadTrackerAdmin(admin.ModelAdmin):
list_display = ['topic', 'user', 'time_stamp']
search_fields = ['user__%s' % username_field]
class ForumReadTrackerAdmin(admin.ModelAdmin):
list_display = ['forum', 'user', 'time_stamp']
search_fields = ['user__%s' % username_field]
class PostAdmin(admin.ModelAdmin):
list_display = ['topic', 'user', 'created', 'updated', 'summary']
list_per_page = 20
raw_id_fields = ['user', 'topic']
ordering = ['-created']
date_hierarchy = 'created'
search_fields = ['body']
fieldsets = (
(None, {
'fields': ('topic', 'user')
}
),
(_('Additional options'), {
'classes': ('collapse',),
'fields' : (('created', 'updated'), 'user_ip')
}
),
(_('Message'), {
'fields': ('body', 'body_html', 'body_text')
}
),
)
class ProfileAdmin(admin.ModelAdmin):
list_display = ['user', 'time_zone', 'language', 'post_count']
list_per_page = 20
ordering = ['-user']
search_fields = ['user__%s' % username_field]
fieldsets = (
(None, {
'fields': ('time_zone', 'language')
}
),
(_('Additional options'), {
'classes': ('collapse',),
'fields' : ('avatar', 'signature', 'show_signatures')
}
),
)
class AttachmentAdmin(admin.ModelAdmin):
list_display = ['file', 'size', 'admin_view_post', 'admin_edit_post']
def admin_view_post(self, obj):
return '<a href="%s">view</a>' % obj.post.get_absolute_url()
admin_view_post.allow_tags = True
admin_view_post.short_description = _('View post')
def admin_edit_post(self, obj):
return '<a href="%s">edit</a>' % reverse('admin:pybb_post_change', args=[obj.post.pk])
admin_edit_post.allow_tags = True
admin_edit_post.short_description = _('Edit post')
admin.site.register(Category, CategoryAdmin)
admin.site.register(Forum, ForumAdmin)
admin.site.register(Topic, TopicAdmin)
admin.site.register(Post, PostAdmin)
admin.site.register(Attachment, AttachmentAdmin)
if util.get_pybb_profile_model() == Profile:
admin.site.register(Profile, ProfileAdmin)
# This can be used to debug read/unread trackers
#admin.site.register(TopicReadTracker, TopicReadTrackerAdmin)
#admin.site.register(ForumReadTracker, ForumReadTrackerAdmin)
================================================
FILE: pybb/apps.py
================================================
from django.apps import AppConfig
from django.utils.translation import gettext_lazy as _
class PybbConfig(AppConfig):
name = 'pybb'
verbose_name = _('Pybbm forum solution')
default_auto_field = 'django.db.models.AutoField'
def ready(self):
from pybb import signals
signals.setup()
================================================
FILE: pybb/compat.py
================================================
import django
from django.conf import settings
from django.utils.encoding import force_str
from django.utils.text import slugify as django_slugify
from unidecode import unidecode
from pybb import defaults
if defaults.PYBB_USE_DJANGO_MAILER:
from mailer import send_html_mail, send_mail
else:
from django.core.mail import send_mail, get_connection
from django.core.mail.message import EmailMultiAlternatives
def send_html_mail(subject, text_msg, html_msg, sender, recipient,
fail_silently=False, auth_user=None, auth_password=None, connection=None):
"""Sends an email with HTML alternative."""
connection = connection or get_connection(username=auth_user,
password=auth_password,
fail_silently=fail_silently)
msg = EmailMultiAlternatives(subject, text_msg, sender, recipient, connection=connection)
msg.attach_alternative(html_msg, "text/html")
msg.send()
def send_mass_html_mail(emails, *args, **kwargs):
"""
Sends emails with html alternative if email item has html content.
Email item is a tuple with an optional html message version :
(subject, text_msg, sender, recipient, [html_msg])
"""
for email in emails:
subject, text_msg, sender, recipient = email[0:4]
html_msg = email[4] if len(email) > 4 else ''
if html_msg:
send_html_mail(subject, text_msg, html_msg, sender, recipient, *args, **kwargs)
else:
send_mail(subject, text_msg, sender, recipient, *args, **kwargs)
def get_image_field_class():
try:
from PIL import Image
except ImportError:
from django.db.models import FileField
return FileField
try:
from sorl.thumbnail import ImageField
except ImportError:
from django.db.models import ImageField
return ImageField
def get_image_field_full_name():
try:
from PIL import Image
except ImportError:
return 'django.db.models.fields.files.FileField'
try:
from sorl.thumbnail import ImageField
name = 'sorl.thumbnail.fields.ImageField'
except ImportError:
from django.db.models import ImageField
name = 'django.db.models.fields.files.ImageField'
return name
def get_user_model():
from django.contrib.auth import get_user_model
return get_user_model()
def get_user_model_path():
return getattr(settings, 'AUTH_USER_MODEL', 'auth.User')
def get_username_field():
return get_user_model().USERNAME_FIELD
def get_atomic_func():
from django.db.transaction import atomic as atomic_func
return atomic_func
def get_paginator_class():
try:
from pure_pagination import Paginator
pure_pagination = True
except ImportError:
# the simplest emulation of django-pure-pagination behavior
from django.core.paginator import Paginator, Page
class PageRepr(int):
def querystring(self):
return 'page=%s' % self
Page.pages = lambda self: [PageRepr(i) for i in range(1, self.paginator.num_pages + 1)]
pure_pagination = False
return Paginator, pure_pagination
def is_installed(app_name):
from django.apps import apps
return apps.is_installed(app_name)
def get_related_model_class(parent_model, field_name):
return parent_model._meta.get_field(field_name).related_model
def slugify(text):
"""
Slugify function that supports unicode symbols
:param text: any unicode text
:return: slugified version of passed text
"""
return django_slugify(force_str(unidecode(text)))
================================================
FILE: pybb/context_processors.py
================================================
from pybb import defaults
__author__ = 'zeus'
def processor(request):
context = {}
for i in (
'PYBB_TEMPLATE',
'PYBB_TEMPLATE_MAIL_HTML',
'PYBB_TEMPLATE_MAIL_TXT',
'PYBB_DEFAULT_AVATAR_URL',
'PYBB_MARKUP',
'PYBB_DEFAULT_TITLE',
'PYBB_ENABLE_ANONYMOUS_POST',
'PYBB_ATTACHMENT_ENABLE', # deprecated, should be used pybb_may_attach_files filter, will be removed
'PYBB_AVATAR_WIDTH',
'PYBB_AVATAR_HEIGHT'
):
context[i] = getattr(defaults, i, None)
context['PYBB_AVATAR_DIMENSIONS'] = '%sx%s' % (defaults.PYBB_AVATAR_WIDTH, defaults.PYBB_AVATAR_WIDTH)
return context
================================================
FILE: pybb/defaults.py
================================================
import os.path
import warnings
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
PYBB_TOPIC_PAGE_SIZE = getattr(settings, 'PYBB_TOPIC_PAGE_SIZE', 10)
PYBB_FORUM_PAGE_SIZE = getattr(settings, 'PYBB_FORUM_PAGE_SIZE', 20)
PYBB_AVATAR_WIDTH = getattr(settings, 'PYBB_AVATAR_WIDTH', 80)
PYBB_AVATAR_HEIGHT = getattr(settings, 'PYBB_AVATAR_HEIGHT', 80)
PYBB_MAX_AVATAR_SIZE = getattr(settings, 'PYBB_MAX_AVATAR_SIZE', 1024 * 50)
PYBB_DEFAULT_TIME_ZONE = getattr(settings, 'PYBB_DEFAULT_TIME_ZONE', 3)
PYBB_SIGNATURE_MAX_LENGTH = getattr(settings, 'PYBB_SIGNATURE_MAX_LENGTH', 1024)
PYBB_SIGNATURE_MAX_LINES = getattr(settings, 'PYBB_SIGNATURE_MAX_LINES', 3)
PYBB_DEFAULT_MARKUP = getattr(settings, 'PYBB_DEFAULT_MARKUP', 'bbcode')
PYBB_FREEZE_FIRST_POST = getattr(settings, 'PYBB_FREEZE_FIRST_POST', False)
PYBB_ATTACHMENT_SIZE_LIMIT = getattr(settings, 'PYBB_ATTACHMENT_SIZE_LIMIT', 1024 * 1024)
PYBB_ATTACHMENT_ENABLE = getattr(settings, 'PYBB_ATTACHMENT_ENABLE', False)
PYBB_ATTACHMENT_UPLOAD_TO = getattr(settings, 'PYBB_ATTACHMENT_UPLOAD_TO', os.path.join('pybb_upload', 'attachments'))
PYBB_DEFAULT_AVATAR_URL = getattr(settings, 'PYBB_DEFAULT_AVATAR_URL',
getattr(settings, 'STATIC_URL', '') + 'pybb/img/default_avatar.jpg')
PYBB_DEFAULT_TITLE = getattr(settings, 'PYBB_DEFAULT_TITLE', 'PYBB Powered Forum')
PYBB_SMILES_PREFIX = getattr(settings, 'PYBB_SMILES_PREFIX', 'pybb/emoticons/')
PYBB_SMILES = getattr(settings, 'PYBB_SMILES', {
'>_<': 'angry.png',
':.(': 'cry.png',
'o_O': 'eyes.png',
'[]_[]': 'geek.png',
'8)': 'glasses.png',
':D': 'lol.png',
':(': 'sad.png',
':O': 'shok.png',
'-_-': 'shy.png',
':)': 'smile.png',
':P': 'tongue.png',
';)': 'wink.png'
})
PYBB_NICE_URL = getattr(settings, 'PYBB_NICE_URL', False)
PYBB_NICE_URL_PERMANENT_REDIRECT = getattr(settings, 'PYBB_NICE_URL_PERMANENT_REDIRECT', True)
PYBB_NICE_URL_SLUG_DUPLICATE_LIMIT = getattr(settings, 'PYBB_NICE_URL_SLUG_DUPLICATE_LIMIT', 100)
# TODO In a near future, this code will be deleted when callable settings will not supported anymore.
callable_warning = ('%(setting_name)s should not be a callable anymore but a path to the parser classes.'
'ex : myproject.markup.CustomBBCodeParser. It will stop working in next pybbm release.')
wrong_setting_warning = ('%s setting will be removed in next pybbm version. '
'Place your custom quote functions in markup class and override '
'PYBB_MARKUP_ENGINES_PATHS/PYBB_MARKUP settings')
bad_function_warning = '%(bad)s function is deprecated. Use %(good)s instead.'
def getsetting_with_deprecation_check(all_settings, setting_name): # pragma: no cover
setting_value = getattr(all_settings, setting_name)
values = setting_value if type(setting_value) is not dict else setting_value.values()
for value in values:
if isinstance(value, str):
continue
warnings.warn(
callable_warning % {'setting_name': setting_name, },
DeprecationWarning
)
return setting_value
PYBB_MARKUP_ENGINES_PATHS = getattr(settings, 'PYBB_MARKUP_ENGINES_PATHS', {
'bbcode': 'pybb.markup.bbcode.BBCodeParser',
'markdown': 'pybb.markup.markdown.MarkdownParser'})
# TODO in the next major release : delete PYBB_MARKUP_ENGINES and PYBB_QUOTE_ENGINES settings
if not hasattr(settings, 'PYBB_MARKUP_ENGINES'):
PYBB_MARKUP_ENGINES = PYBB_MARKUP_ENGINES_PATHS
else: # pragma: no cover
warnings.warn(wrong_setting_warning % 'PYBB_MARKUP_ENGINES', DeprecationWarning)
PYBB_MARKUP_ENGINES = getsetting_with_deprecation_check(settings, 'PYBB_MARKUP_ENGINES')
if not hasattr(settings, 'PYBB_QUOTE_ENGINES'):
PYBB_QUOTE_ENGINES = PYBB_MARKUP_ENGINES_PATHS
else: # pragma: no cover
warnings.warn(wrong_setting_warning % 'PYBB_QUOTE_ENGINES', DeprecationWarning)
PYBB_QUOTE_ENGINES = getsetting_with_deprecation_check(settings, 'PYBB_QUOTE_ENGINES')
PYBB_MARKUP = getattr(settings, 'PYBB_MARKUP', None)
if not PYBB_MARKUP or PYBB_MARKUP not in PYBB_MARKUP_ENGINES:
if not PYBB_MARKUP_ENGINES: # pragma: no cover
warnings.warn('There is no markup engines defined in your settings. '
'Default pybb.base.BaseParser will be used.'
'Please set correct PYBB_MARKUP_ENGINES_PATHS and PYBB_MARKUP settings.',
DeprecationWarning)
PYBB_MARKUP = None
elif 'bbcode' in PYBB_MARKUP_ENGINES:
# Backward compatibility. bbcode is the default markup
PYBB_MARKUP = 'bbcode'
else:
raise ImproperlyConfigured('PYBB_MARKUP must be defined to an existing key of '
'PYBB_MARKUP_ENGINES_PATHS')
PYBB_TEMPLATE = getattr(settings, 'PYBB_TEMPLATE', "base.html")
PYBB_TEMPLATE_MAIL_TXT = getattr(settings,
'PYBB_TEMPLATE_MAIL_TXT',
'pybb/mail_templates/base.html')
PYBB_TEMPLATE_MAIL_HTML = getattr(settings,
'PYBB_TEMPLATE_MAIL_HTML',
'pybb/mail_templates/base-html.html')
PYBB_DEFAULT_AUTOSUBSCRIBE = getattr(settings, 'PYBB_DEFAULT_AUTOSUBSCRIBE', True)
PYBB_ENABLE_ANONYMOUS_POST = getattr(settings, 'PYBB_ENABLE_ANONYMOUS_POST', False)
PYBB_ANONYMOUS_USERNAME = getattr(settings, 'PYBB_ANONYMOUS_USERNAME', 'Anonymous')
PYBB_ANONYMOUS_VIEWS_CACHE_BUFFER = getattr(settings, 'PYBB_ANONYMOUS_VIEWS_CACHE_BUFFER', 100)
PYBB_DISABLE_SUBSCRIPTIONS = getattr(settings, 'PYBB_DISABLE_SUBSCRIPTIONS', False)
PYBB_DISABLE_NOTIFICATIONS = getattr(settings, 'PYBB_DISABLE_NOTIFICATIONS', False)
PYBB_PREMODERATION = getattr(settings, 'PYBB_PREMODERATION', False)
if not hasattr(settings, 'PYBB_BODY_CLEANERS'):
PYBB_BODY_CLEANERS = ['pybb.markup.base.rstrip_str', 'pybb.markup.base.filter_blanks']
else: # pragma: no cover
PYBB_BODY_CLEANERS = getsetting_with_deprecation_check(settings, 'PYBB_BODY_CLEANERS')
PYBB_BODY_VALIDATOR = getattr(settings, 'PYBB_BODY_VALIDATOR', None)
PYBB_POLL_MAX_ANSWERS = getattr(settings, 'PYBB_POLL_MAX_ANSWERS', 10)
PYBB_AUTO_USER_PERMISSIONS = getattr(settings, 'PYBB_AUTO_USER_PERMISSIONS', True)
PYBB_USE_DJANGO_MAILER = getattr(settings, 'PYBB_USE_DJANGO_MAILER', False)
PYBB_PERMISSION_HANDLER = getattr(settings, 'PYBB_PERMISSION_HANDLER', 'pybb.permissions.DefaultPermissionHandler')
PYBB_PROFILE_RELATED_NAME = getattr(settings, 'PYBB_PROFILE_RELATED_NAME', 'pybb_profile')
PYBB_ENABLE_ADMIN_POST_FORM = getattr(settings, 'PYBB_ENABLE_ADMIN_POST_FORM', True)
PYBB_ALLOW_DELETE_OWN_POST = getattr(settings, 'PYBB_ALLOW_DELETE_OWN_POST', True)
# Backward compatibility : define old functions which was defined here if some devs did used it
# TODO in a near future : delete those functions
def bbcode(s): # pragma: no cover
warnings.warn(
bad_function_warning % {
'bad': 'pybb.defaults.bbcode',
'good': 'pybb.markup.bbcode.BBCodeParser',
},
DeprecationWarning)
from pybb.markup.bbcode import BBCodeParser
return BBCodeParser().format(s)
def markdown(s): # pragma: no cover
warnings.warn(
bad_function_warning % {
'bad': 'pybb.defaults.markdown',
'good': 'pybb.markup.markdown.MarkdownParser',
},
DeprecationWarning)
from pybb.markup.markdown import MarkdownParser
return MarkdownParser().format(s)
def _render_quote(name, value, options, parent, context): # pragma: no cover
warnings.warn('pybb.defaults._render_quote function is deprecated. '
'This function is internal of new pybb.markup.bbcode.BBCodeParser class.',
DeprecationWarning)
from pybb.markup.bbcode import BBCodeParser
return BBCodeParser()._render_quote(name, value, options, parent, context)
def smile_it(s): # pragma: no cover
warnings.warn(
bad_function_warning % {
'bad': 'pybb.defaults.smile_it',
'good': 'pybb.markup.base.smile_it',
},
DeprecationWarning)
from pybb.markup.base import smile_it as real_smile_it
return real_smile_it(s)
================================================
FILE: pybb/feeds.py
================================================
from django.contrib.syndication.views import Feed
from django.urls import reverse
from django.utils.feedgenerator import Atom1Feed
from django.utils.translation import gettext_lazy as _
from pybb.models import Post, Topic
from pybb.permissions import perms
class PybbFeed(Feed):
feed_type = Atom1Feed
def link(self):
return reverse('pybb:index')
def item_guid(self, obj):
return str(obj.id)
def item_pubdate(self, obj):
return obj.created
class LastPosts(PybbFeed):
title = _('Latest posts on forum')
description = _('Latest posts on forum')
title_template = 'pybb/feeds/posts_title.html'
description_template = 'pybb/feeds/posts_description.html'
def get_object(self, request, *args, **kwargs):
return request.user
def items(self, user):
ids = [p.id for p in perms.filter_posts(user, Post.objects.only('id')).order_by('-created', '-id')[:15]]
return Post.objects.filter(id__in=ids).select_related('topic', 'topic__forum', 'user')
class LastTopics(PybbFeed):
title = _('Latest topics on forum')
description = _('Latest topics on forum')
title_template = 'pybb/feeds/topics_title.html'
description_template = 'pybb/feeds/topics_description.html'
def get_object(self, request, *args, **kwargs):
return request.user
def items(self, user):
return perms.filter_topics(user, Topic.objects.all()).select_related('forum').order_by('-created', '-id')[:15]
================================================
FILE: pybb/forms.py
================================================
import re
import inspect
import django
from django import forms
from django.core.exceptions import FieldError, PermissionDenied
from django.forms.models import inlineformset_factory, BaseInlineFormSet
from django.utils.decorators import method_decorator
from django.utils.text import Truncator
from django.utils.translation import gettext, gettext_lazy
from django.utils.timezone import now as tznow
from django.utils.translation import gettext as _
from pybb import compat, defaults, util, permissions
from pybb.models import Topic, Post, Attachment, PollAnswer, \
ForumSubscription, Category, Forum, create_or_check_slug
User = compat.get_user_model()
username_field = compat.get_username_field()
class AttachmentForm(forms.ModelForm):
class Meta(object):
model = Attachment
fields = ('file', )
def clean_file(self):
if self.cleaned_data['file'].size > defaults.PYBB_ATTACHMENT_SIZE_LIMIT:
raise forms.ValidationError(gettext('Attachment is too big'))
return self.cleaned_data['file']
AttachmentFormSet = inlineformset_factory(Post, Attachment, extra=1, form=AttachmentForm)
class PollAnswerForm(forms.ModelForm):
class Meta:
model = PollAnswer
fields = ('text', )
class BasePollAnswerFormset(BaseInlineFormSet):
def clean(self):
forms_cnt = (len(self.initial_forms) + len([form for form in self.extra_forms if form.has_changed()]) -
len(self.deleted_forms))
if forms_cnt > defaults.PYBB_POLL_MAX_ANSWERS:
raise forms.ValidationError(
gettext('You can''t add more than %s answers for poll' % defaults.PYBB_POLL_MAX_ANSWERS))
if forms_cnt < 2:
raise forms.ValidationError(gettext('Add two or more answers for this poll'))
PollAnswerFormSet = inlineformset_factory(Topic, PollAnswer, extra=2, max_num=defaults.PYBB_POLL_MAX_ANSWERS,
form=PollAnswerForm, formset=BasePollAnswerFormset)
class PostForm(forms.ModelForm):
name = forms.CharField(label=gettext_lazy('Subject'))
poll_type = forms.TypedChoiceField(label=gettext_lazy('Poll type'), choices=Topic.POLL_TYPE_CHOICES, coerce=int)
poll_question = forms.CharField(
label=gettext_lazy('Poll question'),
required=False,
widget=forms.Textarea(attrs={'class': 'no-markitup'}))
slug = forms.CharField(label=gettext_lazy('Topic slug'), required=False)
class Meta(object):
model = Post
fields = ('body',)
widgets = {
'body': util.get_markup_engine().get_widget_cls(),
}
def __init__(self, *args, **kwargs):
# Move args to kwargs
if args:
kwargs.update(dict(zip(inspect.getargspec(super(PostForm, self).__init__)[0][1:], args)))
self.user = kwargs.pop('user', None)
self.ip = kwargs.pop('ip', None)
self.topic = kwargs.pop('topic', None)
self.forum = kwargs.pop('forum', None)
self.may_create_poll = kwargs.pop('may_create_poll', True)
self.may_edit_topic_slug = kwargs.pop('may_edit_topic_slug', False)
if not (self.topic or self.forum or ('instance' in kwargs)):
raise ValueError('You should provide topic, forum or instance')
# Handle topic subject, poll type and question if editing topic head
if kwargs.get('instance', None) and (kwargs['instance'].topic.head == kwargs['instance']):
kwargs.setdefault('initial', {})['name'] = kwargs['instance'].topic.name
kwargs.setdefault('initial', {})['poll_type'] = kwargs['instance'].topic.poll_type
kwargs.setdefault('initial', {})['poll_question'] = kwargs['instance'].topic.poll_question
super(PostForm, self).__init__(**kwargs)
# remove topic specific fields
if not (self.forum or (self.instance.pk and (self.instance.topic.head == self.instance))):
del self.fields['name']
del self.fields['poll_type']
del self.fields['poll_question']
del self.fields['slug']
else:
if not self.may_create_poll:
del self.fields['poll_type']
del self.fields['poll_question']
if not self.may_edit_topic_slug:
del self.fields['slug']
self.available_smiles = defaults.PYBB_SMILES
self.smiles_prefix = defaults.PYBB_SMILES_PREFIX
def clean_body(self):
body = self.cleaned_data['body']
user = self.user or self.instance.user
if defaults.PYBB_BODY_VALIDATOR:
defaults.PYBB_BODY_VALIDATOR(user, body)
for cleaner in defaults.PYBB_BODY_CLEANERS:
body = util.get_body_cleaner(cleaner)(user, body)
return body
def clean(self):
poll_type = self.cleaned_data.get('poll_type', None)
poll_question = self.cleaned_data.get('poll_question', None)
if poll_type is not None and poll_type != Topic.POLL_TYPE_NONE and not poll_question:
raise forms.ValidationError(gettext('Poll''s question is required when adding a poll'))
return self.cleaned_data
def save(self, commit=True):
if self.instance.pk:
post = super(PostForm, self).save(commit=False)
if self.user:
post.user = self.user
if post.topic.head == post:
post.topic.name = self.cleaned_data['name']
if self.may_create_poll:
post.topic.poll_type = self.cleaned_data['poll_type']
post.topic.poll_question = self.cleaned_data['poll_question']
post.topic.updated = tznow()
if commit:
post.topic.save()
post.updated = tznow()
if commit:
post.save()
return post, post.topic
allow_post = True
if defaults.PYBB_PREMODERATION:
allow_post = defaults.PYBB_PREMODERATION(self.user, self.cleaned_data['body'])
if self.forum:
topic = Topic(
forum=self.forum,
user=self.user,
name=self.cleaned_data['name'],
poll_type=self.cleaned_data.get('poll_type', Topic.POLL_TYPE_NONE),
poll_question=self.cleaned_data.get('poll_question', None),
slug=self.cleaned_data.get('slug', None),
)
if not allow_post:
topic.on_moderation = True
else:
topic = self.topic
post = Post(user=self.user, user_ip=self.ip, body=self.cleaned_data['body'])
if not allow_post:
post.on_moderation = True
if commit:
topic.save()
post.topic = topic
post.save()
return post, topic
class MovePostForm(forms.Form):
def __init__(self, instance, user, *args, **kwargs):
super(MovePostForm, self).__init__(*args, **kwargs)
self.instance = instance
self.user = user
self.post = self.instance
self.category, self.forum, self.topic = self.post.get_parents()
if not self.post.is_topic_head:
# we do not move an entire topic but a part of it's posts. Let's select those posts.
self.posts_to_move = Post.objects.filter(created__gte=self.post.created,
topic=self.topic).order_by('created', 'pk')
# if multiple posts exists with the same created datetime, it's important to keep the
# same order and do not move some posts which could be "before" our post.
# We can not just filter by adding `pk__gt=self.post.pk` because we could exclude
# some posts if for some reasons, a lesser pk has a greater "created" datetime
# Most of the time, we just do one extra request to be sure the first post is
# the wanted one
first_pk = self.posts_to_move.values_list('pk', flat=True)[0]
while first_pk != self.post.pk:
self.posts_to_move = self.posts_to_move.exclude(pk=first_pk)
first_pk = self.posts_to_move.values_list('pk', flat=True)[0]
i = 0
choices = []
for post in self.posts_to_move[1:]: # all except the current one
i += 1
bvars = {'author': util.get_pybb_profile(post.user).get_display_name(),
'abstract': Truncator(post.body_text).words(8),
'i': i}
label = _('%(i)d (%(author)s: "%(abstract)s")') % bvars
choices.append((i, label))
choices.insert(0, (0, _('None')))
choices.insert(0, (-1, _('All')))
self.fields['number'] = forms.TypedChoiceField(
label=gettext_lazy('Number of following posts to move with'),
choices=choices, required=True, coerce=int,
)
# we move the entire topic, so we want to change it's forum.
# So, let's exclude the current one
# get all forum where we can move this post (and the others)
move_to_forums = permissions.perms.filter_forums(self.user, Forum.objects.all())
if self.post.is_topic_head:
# we move the entire topic, so we want to change it's forum.
# So, let's exclude the current one
move_to_forums = move_to_forums.exclude(pk=self.forum.pk)
last_cat_pk = None
choices = []
for forum in move_to_forums.order_by('category__position', 'position', 'name'):
if not permissions.perms.may_create_topic(self.user, forum):
continue
if last_cat_pk != forum.category.pk:
last_cat_pk = forum.category.pk
choices.append(('%s' % forum.category, []))
if self.forum.pk == forum.pk:
name = '%(forum)s (forum of the current post)' % {'forum': self.forum}
else:
name = '%s' % forum
choices[-1][1].append((forum.pk, name))
self.fields['move_to'] = forms.ChoiceField(label=gettext_lazy('Move to forum'),
initial=self.forum.pk,
choices=choices, required=True,)
self.fields['name'] = forms.CharField(label=_('New subject'),
initial=self.topic.name,
max_length=255, required=True)
if permissions.perms.may_edit_topic_slug(self.user):
self.fields['slug'] = forms.CharField(label=_('New topic slug'),
initial=self.topic.slug,
max_length=255, required=False)
def get_new_topic(self):
if hasattr(self, '_new_topic'):
return self._new_topic
if self.post.is_topic_head:
topic = self.topic
else:
topic = Topic(user=self.post.user)
if topic.name != self.cleaned_data['name']:
topic.name = self.cleaned_data['name']
# force slug auto-rebuild if slug is not speficied and topic is renamed
topic.slug = self.cleaned_data.get('slug', None)
elif self.cleaned_data.get('slug', None):
topic.slug = self.cleaned_data['slug']
topic.forum = Forum.objects.get(pk=self.cleaned_data['move_to'])
topic.slug = create_or_check_slug(topic, Topic, forum=topic.forum)
topic.save()
return topic
@method_decorator(compat.get_atomic_func())
def save(self):
data = self.cleaned_data
topic = self.get_new_topic()
if not self.post.is_topic_head:
# we move some posts
posts = self.posts_to_move
if data['number'] != -1:
number = data['number'] + 1 # we want to move at least the current post ;-)
posts = posts[0:number]
# update posts
# we can not update with subqueries on same table with mysql 5.5
# it raises: You can't specify target table 'pybb_post' for update in FROM clause
# so we need to get all pks... It's bad for perfs, but posts are not often splitted...
posts_pks = [p.pk for p in posts]
Post.objects.filter(pk__in=posts_pks).update(topic_id=topic.pk)
topic.update_counters()
topic.forum.update_counters()
if topic.pk != self.topic.pk:
# we just created a new topic. let's update the counters
self.topic.update_counters()
if self.forum.pk != topic.forum.pk:
self.forum.update_counters()
return Post.objects.get(pk=self.post.pk)
class AdminPostForm(PostForm):
"""
Superusers can post messages from any user and from any time
If no user with specified name - new user will be created
"""
login = forms.CharField(label=gettext_lazy('User'))
def __init__(self, *args, **kwargs):
if args:
kwargs.update(dict(zip(inspect.getargspec(forms.ModelForm.__init__)[0][1:], args)))
if 'instance' in kwargs and kwargs['instance']:
kwargs.setdefault('initial', {}).update({'login': getattr(kwargs['instance'].user, username_field)})
super(AdminPostForm, self).__init__(**kwargs)
def save(self, *args, **kwargs):
try:
self.user = User.objects.filter(**{username_field: self.cleaned_data['login']}).get()
except User.DoesNotExist:
if username_field != 'email':
create_data = {username_field: self.cleaned_data['login'],
'email': '%s@example.com' % self.cleaned_data['login'],
'is_staff': False}
else:
create_data = {'email': '%s@example.com' % self.cleaned_data['login'],
'is_staff': False}
self.user = User.objects.create(**create_data)
return super(AdminPostForm, self).save(*args, **kwargs)
try:
class EditProfileForm(forms.ModelForm):
class Meta(object):
model = util.get_pybb_profile_model()
fields = ['signature', 'time_zone', 'language', 'show_signatures', 'avatar']
def __init__(self, *args, **kwargs):
super(EditProfileForm, self).__init__(*args, **kwargs)
self.fields['signature'].widget = forms.Textarea(attrs={'rows': 2, 'cols:': 60})
def clean_avatar(self):
if self.cleaned_data['avatar'] and (self.cleaned_data['avatar'].size > defaults.PYBB_MAX_AVATAR_SIZE):
forms.ValidationError(gettext('Avatar is too large, max size: %s bytes' %
defaults.PYBB_MAX_AVATAR_SIZE))
return self.cleaned_data['avatar']
def clean_signature(self):
value = self.cleaned_data['signature'].strip()
if len(re.findall(r'\n', value)) > defaults.PYBB_SIGNATURE_MAX_LINES:
raise forms.ValidationError('Number of lines is limited to %d' % defaults.PYBB_SIGNATURE_MAX_LINES)
if len(value) > defaults.PYBB_SIGNATURE_MAX_LENGTH:
raise forms.ValidationError('Length of signature is limited to %d' % defaults.PYBB_SIGNATURE_MAX_LENGTH)
return value
except FieldError:
pass
class UserSearchForm(forms.Form):
query = forms.CharField(required=False, label='')
def filter(self, qs):
if self.is_valid():
query = self.cleaned_data['query']
return qs.filter(**{'%s__contains' % username_field: query})
else:
return qs
class PollForm(forms.Form):
def __init__(self, topic, *args, **kwargs):
self.topic = topic
super(PollForm, self).__init__(*args, **kwargs)
qs = PollAnswer.objects.filter(topic=topic)
if topic.poll_type == Topic.POLL_TYPE_SINGLE:
self.fields['answers'] = forms.ModelChoiceField(
label='', queryset=qs, empty_label=None,
widget=forms.RadioSelect())
elif topic.poll_type == Topic.POLL_TYPE_MULTIPLE:
self.fields['answers'] = forms.ModelMultipleChoiceField(
label='', queryset=qs,
widget=forms.CheckboxSelectMultiple())
def clean_answers(self):
answers = self.cleaned_data['answers']
if self.topic.poll_type == Topic.POLL_TYPE_SINGLE:
return [answers]
else:
return answers
class ForumSubscriptionForm(forms.Form):
def __init__(self, user, forum, instance=None, *args, **kwargs):
super(ForumSubscriptionForm, self).__init__(*args, **kwargs)
self.user = user
self.forum = forum
self.instance = instance
type_choices = list(ForumSubscription.TYPE_CHOICES)
if instance :
type_choices.append(
('unsubscribe', _('be unsubscribe from this forum')))
type_initial = instance.type
else:
type_initial = ForumSubscription.TYPE_NOTIFY
self.fields['type'] = forms.ChoiceField(
label=_('You want to'), choices=type_choices, initial=type_initial,
widget=forms.RadioSelect())
topic_choices = (
('new', _('only new topics')),
('all', _('all topics of the forum')),
)
self.fields['topics'] = forms.ChoiceField(
label=_('Concerned topics'), choices=topic_choices,
initial=topic_choices[0][0], widget=forms.RadioSelect())
def process(self):
"""
saves or deletes the ForumSubscription's instance
"""
action = self.cleaned_data.get('type')
all_topics = self.cleaned_data.get('topics') == 'all'
if action == 'unsubscribe':
self.instance.delete(all_topics=all_topics)
return 'delete-all' if all_topics else 'delete'
else:
if not self.instance:
self.instance = ForumSubscription()
self.instance.user = self.user
self.instance.forum = self.forum
self.instance.type = int(self.cleaned_data.get('type'))
self.instance.save(all_topics=all_topics)
return 'subscribe-all' if all_topics else 'subscribe'
class ModeratorForm(forms.Form):
def __init__(self, user, *args, **kwargs):
"""
Creates the form to grant moderator privileges, checking if the request user has the
permission to do so.
:param user: request user
"""
super(ModeratorForm, self).__init__(*args, **kwargs)
categories = Category.objects.all()
self.authorized_forums = []
if not permissions.perms.may_manage_moderators(user):
raise PermissionDenied()
for category in categories:
forums = [forum.pk for forum in category.forums.all() if permissions.perms.may_change_forum(user, forum)]
if forums:
self.authorized_forums += forums
self.fields['cat_%d' % category.pk] = forms.ModelMultipleChoiceField(
label=category.name,
queryset=category.forums.filter(pk__in=forums),
widget=forms.CheckboxSelectMultiple(),
required=False
)
def process(self, target_user):
"""
Updates the target user moderator privileges
:param target_user: user to update
"""
cleaned_forums = self.cleaned_data.values()
initial_forum_set = target_user.forum_set.all()
# concatenation of the lists into one
checked_forums = [forum for queryset in cleaned_forums for forum in queryset]
# keep all the forums, the request user does't have the permission to change
untouchable_forums = [forum for forum in initial_forum_set if forum.pk not in self.authorized_forums]
if django.VERSION < (1, 9):
target_user.forum_set = checked_forums + untouchable_forums
else:
target_user.forum_set.set(checked_forums + untouchable_forums)
================================================
FILE: pybb/locale/de/LC_MESSAGES/django.po
================================================
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: pybbm\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-01-11 14:06+0100\n"
"PO-Revision-Date: 2017-01-11 14:11+0100\n"
"Last-Translator: DylannCordel <d.cordel@webu.coop>\n"
"Language-Team: \n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.6.10\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-Basepath: ../../..\n"
#: admin.py:45 admin.py:84 admin.py:112 admin.py:134
msgid "Additional options"
msgstr "Zusätzliche Einstellungen"
#: admin.py:117 models.py:280
msgid "Message"
msgstr "Nachricht"
#: admin.py:148
msgid "View post"
msgstr "Beitrag anzeigen"
#: admin.py:153
msgid "Edit post"
msgstr "Beitrag bearbeiten"
#: apps.py:9
msgid "Pybbm forum solution"
msgstr ""
#: feeds.py:27 feeds.py:28 templates/pybb/base.html:10
msgid "Latest posts on forum"
msgstr "Neueste Antworten in Forum"
#: feeds.py:41 feeds.py:42 templates/pybb/base.html:11
msgid "Latest topics on forum"
msgstr "Neueste Beiträge in Forum"
#: forms.py:30
msgid "Attachment is too big"
msgstr "Anhang ist zu groß"
#: forms.py:48
#, python-format
msgid "You cant add more than %s answers for poll"
msgstr "Sie können nicht mehr als %s Antworten pro Umfrage hinzufügen"
#: forms.py:50
msgid "Add two or more answers for this poll"
msgstr "Fügen Sie eine oder mehrere Antworten zu dieser Umfrage hinzu"
#: forms.py:58 models.py:183
msgid "Subject"
msgstr "Betreff"
#: forms.py:59 models.py:195
msgid "Poll type"
msgstr "Umfrage Typ"
#: forms.py:61 models.py:196
msgid "Poll question"
msgstr "Frage"
#: forms.py:64
#, fuzzy
#| msgid "Topics"
msgid "Topic slug"
msgstr "Themen"
#: forms.py:123
msgid "Polls question is required when adding a poll"
msgstr "Zu jeder Umfrage muss eine Frage eingegeben werden"
#: forms.py:176 models.py:186 models.py:295 models.py:368 models.py:507
msgid "User"
msgstr "Benutzer"
#: forms.py:212
#, python-format
msgid "Avatar is too large, max size: %s bytes"
msgstr "Avatar ist zu groß (maximal %s Byte)"
#: forms.py:272
msgid "be unsubscribe from this forum"
msgstr "sich von diesem Forum abmelden."
#: forms.py:277
msgid "You want to"
msgstr "Sie möchten"
#: forms.py:281
#, fuzzy
#| msgid "New topic"
msgid "only new topics"
msgstr "Neuer Beitrag"
#: forms.py:282
#, fuzzy
#| msgid "Latest topics on forum"
msgid "all topics of the forum"
msgstr "Neueste Beiträge in Forum"
#: forms.py:285
#, fuzzy
#| msgid "Close topic"
msgid "Concerned topics"
msgstr "Thema schließen"
#: models.py:23 models.py:59
msgid "Name"
msgstr "Name"
#: models.py:24 models.py:60
msgid "Position"
msgstr "Position"
#: models.py:25 models.py:66 templates/pybb/category.html:4
#: templates/pybb/forum_list.html:26
msgid "Hidden"
msgstr "Versteckt"
#: models.py:26
msgid "If checked, this category will be visible only for staff"
msgstr ""
"Versteckte Kategorien sind nur für Administratoren und Redakteure sichtbar"
#: models.py:27 models.py:69 models.py:197
msgid "Slug"
msgstr ""
#: models.py:31 models.py:56
msgid "Category"
msgstr "Kategorie"
#: models.py:32
msgid "Categories"
msgstr "Kategorien"
#: models.py:57
msgid "Parent forum"
msgstr ""
#: models.py:61
msgid "Description"
msgstr "Beschreibung"
#: models.py:62
msgid "Moderators"
msgstr "Moderatoren"
#: models.py:63 models.py:185 models.py:297
msgid "Updated"
msgstr "Aktualisiert"
#: models.py:64 models.py:192 profiles.py:41
msgid "Post count"
msgstr "Anzahl Antworten"
#: models.py:65
msgid "Topic count"
msgstr "Anzahl Beiträge"
#: models.py:68
msgid "Headline"
msgstr "Titel"
#: models.py:73 models.py:136 models.py:182 templates/pybb/forum_list.html:8
msgid "Forum"
msgstr "Forum"
#: models.py:74
msgid "Forums"
msgstr "Foren"
#: models.py:129
msgid "be notified only when a new topic is added"
msgstr "nur benachrichtigt werden, wenn ein neues Thema hinzugefügt wird"
#: models.py:130
msgid "be auto-subscribed to topics"
msgstr "Themen automatisch abonnieren"
#: models.py:134
#, fuzzy
#| msgid "Subscribers"
msgid "Subscriber"
msgstr "Abonnenten"
#: models.py:138
#, fuzzy
#| msgid "Subscriptions on topics"
msgid "Subscription type"
msgstr "Themen-Abonnements"
#: models.py:148
#, fuzzy
#| msgid "Subscriptions on topics"
msgid "Subscription to forum"
msgstr "Themen-Abonnements"
#: models.py:149
#, fuzzy
#| msgid "Subscriptions on topics"
msgid "Subscriptions to forums"
msgstr "Themen-Abonnements"
#: models.py:177
msgid "None"
msgstr "Nichts"
#: models.py:178
msgid "Single answer"
msgstr "Eine Antwort"
#: models.py:179
msgid "Multiple answers"
msgstr "Mehrere Antworten"
#: models.py:184 models.py:296
msgid "Created"
msgstr "Angelegt"
#: models.py:187
msgid "Views count"
msgstr "angezeigt"
#: models.py:188 templates/pybb/topic_list.html:27
msgid "Sticky"
msgstr "Sticky"
#: models.py:189 templates/pybb/topic_list.html:28
msgid "Closed"
msgstr "Geschlossen"
#: models.py:191 templates/pybb/topic.html:88
msgid "Subscribers"
msgstr "Abonnenten"
#: models.py:194 models.py:299
msgid "On moderation"
msgstr "wird moderiert"
#: models.py:201 models.py:294 models.py:483 templates/pybb/topic_list.html:7
msgid "Topic"
msgstr "Thema"
#: models.py:202 templates/pybb/forum_list.html:11
#: templates/pybb/user_topics.html:7
msgid "Topics"
msgstr "Themen"
#: models.py:281
msgid "HTML version"
msgstr "HTML Version"
#: models.py:282
msgid "Text version"
msgstr "Text Version"
#: models.py:298
msgid "User IP"
msgstr "Benutzer IP"
#: models.py:303 models.py:386
msgid "Post"
msgstr "Beitrag"
#: models.py:304 templates/pybb/forum_list.html:14
#: templates/pybb/topic.html:42 templates/pybb/topic_list.html:10
#: templates/pybb/user_posts.html:7
msgid "Posts"
msgstr "Beiträge"
#: models.py:371
msgid "Profile"
msgstr "Profil"
#: models.py:372
msgid "Profiles"
msgstr "Profile"
#: models.py:383
msgid "Attachment"
msgstr "Anhang"
#: models.py:384
msgid "Attachments"
msgstr "Anhänge"
#: models.py:387
msgid "Size"
msgstr "Größe"
#: models.py:388
msgid "File"
msgstr "Datei"
#: models.py:438
msgid "Topic read tracker"
msgstr "'Beitrag gelesen' Tracker"
#: models.py:439
msgid "Topic read trackers"
msgstr "'Beitrag gelesen' Tracker"
#: models.py:476
msgid "Forum read tracker"
msgstr "'Forum gelesen' Tracker"
#: models.py:477
msgid "Forum read trackers"
msgstr "'Beitrag gelesen' Tracker"
#: models.py:484
msgid "Text"
msgstr "Text"
#: models.py:487 models.py:506
msgid "Poll answer"
msgstr "Umfrageantwort"
#: models.py:488
msgid "Polls answers"
msgstr "Umfrageantworten"
#: models.py:511
msgid "Poll answer user"
msgstr "Umfrageantwort Benutzer"
#: models.py:512
msgid "Polls answers users"
msgstr "Umfrageantworten Benutzer"
#: models.py:535
#, python-format
msgid ""
"After %(limit)s attemps, there is not any unique slug value for \"%(slug)s\""
msgstr ""
#: profiles.py:34
msgid "Signature"
msgstr "Signatur"
#: profiles.py:35
msgid "Signature HTML Version"
msgstr "Signatur HTML Version"
#: profiles.py:37
msgid "Time zone"
msgstr "Zeitzone"
#: profiles.py:38
msgid "Language"
msgstr "Sprache"
#: profiles.py:40
msgid "Show signatures"
msgstr "Signatur anzeigen"
#: profiles.py:42
msgid "Avatar"
msgstr "Avatar"
#: profiles.py:44
msgid "Automatically subscribe"
msgstr "Automatisch abonnieren"
#: profiles.py:45
msgid "Automatically subscribe to topics that you answer"
msgstr "Themen, auf die geantwortet wurde, automatisch abonnieren"
#: templates/pybb/_button_forum_subscription.html:1
#, fuzzy
#| msgid "Description"
msgid "Manage subscription"
msgstr "Beschreibung"
#: templates/pybb/_button_forum_subscription.html:1
#: templates/pybb/topic.html:72
msgid "Subscribe"
msgstr "Abonnieren"
#: templates/pybb/_button_new_topic.html:1 templates/pybb/add_post.html:5
#: templates/pybb/add_post.html.py:32
msgid "New topic"
msgstr "Neuer Beitrag"
#: templates/pybb/_button_save.html:1
msgid "Save"
msgstr "Speichern"
#: templates/pybb/_button_submit.html:1
#: templates/pybb/forum_subscription.html:33
msgid "Submit"
msgstr "Absenden"
#: templates/pybb/_markitup.html:25
#: templates/pybb/markup/bbcode_widget.html:16
#: templates/pybb/markup/markdown_widget.html:24
msgid "Bold"
msgstr ""
#: templates/pybb/_markitup.html:26
#: templates/pybb/markup/bbcode_widget.html:17
#: templates/pybb/markup/markdown_widget.html:25
msgid "Italic"
msgstr ""
#: templates/pybb/_markitup.html:27
#: templates/pybb/markup/bbcode_widget.html:18
msgid "Underline"
msgstr ""
#: templates/pybb/_markitup.html:28
#: templates/pybb/markup/bbcode_widget.html:19
msgid "Stroke"
msgstr ""
#: templates/pybb/_markitup.html:30
#: templates/pybb/markup/bbcode_widget.html:21
#: templates/pybb/markup/markdown_widget.html:32
#, fuzzy
#| msgid "Signature"
msgid "Picture"
msgstr "Signatur"
#: templates/pybb/_markitup.html:31
#: templates/pybb/markup/bbcode_widget.html:22
#: templates/pybb/markup/markdown_widget.html:33
msgid "Link"
msgstr ""
#: templates/pybb/_markitup.html:33
#: templates/pybb/markup/bbcode_widget.html:24
msgid "Bulleted list"
msgstr ""
#: templates/pybb/_markitup.html:34
#: templates/pybb/markup/bbcode_widget.html:25
msgid "Numeric list"
msgstr ""
#: templates/pybb/_markitup.html:35
#: templates/pybb/markup/bbcode_widget.html:26
msgid "List item"
msgstr ""
#: templates/pybb/_markitup.html:37
#: templates/pybb/markup/bbcode_widget.html:28
#: templates/pybb/markup/markdown_widget.html:35
#, fuzzy
#| msgid "quote"
msgid "Quotes"
msgstr "zitieren"
#: templates/pybb/_markitup.html:38
#: templates/pybb/markup/bbcode_widget.html:29
msgid "Code"
msgstr ""
#: templates/pybb/_markitup.html:40
#: templates/pybb/markup/bbcode_widget.html:31
msgid "Clean"
msgstr ""
#: templates/pybb/_markitup.html:41
#: templates/pybb/markup/bbcode_widget.html:32
#: templates/pybb/markup/markdown_widget.html:38
msgid "Preview"
msgstr ""
#: templates/pybb/_need_to_login_message.html:2
msgid "Register"
msgstr "Registrieren"
#: templates/pybb/_need_to_login_message.html:2
msgid "or"
msgstr "oder"
#: templates/pybb/_need_to_login_message.html:2
msgid "login"
msgstr "Einloggen"
#: templates/pybb/_need_to_login_message.html:2
msgid "to create to post a reply"
msgstr "Um einen Beitrag oder eine Antwort zu schreiben"
#: templates/pybb/add_post.html:5 templates/pybb/add_post.html.py:32
msgid "New reply"
msgstr "Neue Antwort"
#: templates/pybb/attachments_formset.html:6
msgid "Add attachments"
msgstr "Anhang hinzufügen"
#: templates/pybb/attachments_formset.html:14
msgid ""
"If you need to upload larger files, please use an external storage website."
msgstr ""
#: templates/pybb/attachments_formset.html:14
#, python-format
msgid "(max size: %(max_size)s)"
msgstr ""
#: templates/pybb/attachments_formset.html:17
#: templates/pybb/edit_profile.html:25
msgid "delete"
msgstr "löschen"
#: templates/pybb/attachments_formset.html:20
msgid "Reference to your file"
msgstr ""
#: templates/pybb/attachments_formset.html:20
msgid "Ref"
msgstr ""
#: templates/pybb/attachments_formset.html:20
#: templates/pybb/mail_templates/forum_subscription_email_body.html:5
#: templates/pybb/mail_templates/forum_subscription_email_body.html:6
#: templates/pybb/mail_templates/forum_subscription_email_body.html:9
#: templates/pybb/mail_templates/subscription_email_body.html:4
#: templates/pybb/mail_templates/subscription_email_body.html:5
#: templates/pybb/topic.html:88 templates/pybb/topic_list.html:32
msgid ":"
msgstr ""
#: templates/pybb/attachments_formset.html:22
msgid "link"
msgstr "Link"
#: templates/pybb/attachments_formset.html:22
msgid "Insert a link to your file inside your post."
msgstr "Fügen Sie einen Link zu Ihrer Datei in Ihrem Beitrag."
#: templates/pybb/attachments_formset.html:23
msgid "image"
msgstr "Image"
#: templates/pybb/attachments_formset.html:23
msgid "Insert your image inside your post."
msgstr "Fügen Sie Ihr Bild in Ihrem Beitrag."
#: templates/pybb/breadcrumb.html:4
msgid "Home"
msgstr "Home"
#: templates/pybb/delete_post.html:5
msgid "Are you sure you want to delete this message?"
msgstr "Möchten Sie diese Nachricht wirklich löschen"
#: templates/pybb/delete_post.html:12
msgid "No, take me back"
msgstr "Nein, Abbruch"
#: templates/pybb/delete_post.html:13
msgid "Yes, I am sure"
msgstr "Ja, ich bin sicher"
#: templates/pybb/edit_post.html:4 templates/pybb/edit_post.html.py:17
msgid "Editing the post"
msgstr "Beitrag bearbeiten"
#: templates/pybb/edit_privileges.html:5 templates/pybb/edit_privileges.html:8
msgid "Grant moderator privileges"
msgstr "Moderatorrechte gewähren"
#: templates/pybb/edit_profile.html:5 templates/pybb/edit_profile.html.py:8
#: templates/pybb/edit_profile.html:13
msgid "Profile editing"
msgstr "Profil bearbeiten"
#: templates/pybb/edit_profile.html:18
msgid "Subscriptions on topics"
msgstr "Themen-Abonnements"
#: templates/pybb/forum_list.html:17
msgid "Last posts"
msgstr "Letzte Beiträge"
#: templates/pybb/forum_list.html:43
msgid "No forums created"
msgstr "Keine Foren angelegt"
#: templates/pybb/forum_list.html:44
msgid "Add forum now"
msgstr "Forum anlegen"
#: templates/pybb/forum_subscription.html:4
#, python-format
msgctxt "page title"
msgid "%(forum)s - Subscription"
msgstr "%(forum)s - Abonnement"
#: templates/pybb/forum_subscription.html:14
#, python-format
msgctxt "content heading"
msgid "%(forum)s - Subscription"
msgstr "%(forum)s - Abonnement"
#: templates/pybb/forum_subscription.html:32
msgid "Cancel"
msgstr "Stornieren"
#: templates/pybb/index.html:17
msgid "Forum categories are not created"
msgstr "Keine Kategorien angelegt"
#: templates/pybb/index.html:18
msgid "Add a category now"
msgstr "Jetzt Kategorie anlegen"
#: templates/pybb/index.html:22 templates/pybb/latest_topics.html:5
#: templates/pybb/latest_topics.html:8 templates/pybb/latest_topics.html:15
msgid "Last updates in topics"
msgstr "Letzte Updates in den Themen"
#: templates/pybb/index.html:23
msgid "Mark all forums as read"
msgstr "Alles als gelesen markieren"
#: templates/pybb/latest_topics.html:31
#, fuzzy
#| msgid "Mark all forums as read"
msgid "Mark all topics as read"
msgstr "Alles als gelesen markieren"
#: templates/pybb/mail_templates/forum_subscription_email_body.html:4
#, python-format
msgid ""
"User %(username)s post a new topic in forum to which you are subscribed "
"(%(forum_name)s)."
msgstr ""
"Benutzer %(username)s hat in einem Thema geantwortet, das Sie abonniert "
"haben (%(forum_name)s)."
#: templates/pybb/mail_templates/forum_subscription_email_body.html:5
#: templates/pybb/mail_templates/subscription_email_body.html:5
#, fuzzy
#| msgid "Link to topic:"
msgid "Link to topic"
msgstr "Link zum Thema"
#: templates/pybb/mail_templates/forum_subscription_email_body.html:6
#, fuzzy
#| msgid "Link to forum:"
msgid "Link to forum"
msgstr "Link zum Forum:"
#: templates/pybb/mail_templates/forum_subscription_email_body.html:9
#, fuzzy
#| msgid ""
#| "If you don't want to recive notifications on new messages in this topic "
#| "visit following link:"
msgid ""
"If you don't want to receive notifications on new topics in this forum visit "
"following link"
msgstr ""
"Wenn Sie keine E-Mails zu diesem Thema mehr erhalten möchten,klicken Sie den "
"folgenden Link"
#: templates/pybb/mail_templates/forum_subscription_email_subject.html:2
#, fuzzy
#| msgid "New answer in topic that you subscribed."
msgid "New topic in forum that you subscribed."
msgstr "Neue Antwort im Forum"
#: templates/pybb/mail_templates/subscription_email_body-html.html:7
#: templates/pybb/mail_templates/subscription_email_body.html:3
#, python-format
msgid "User %(username)s replied in topic to which you are subscribed."
msgstr ""
"Benutzer %(username)s hat in einem Thema geantwortet, das Sie abonniert haben"
#: templates/pybb/mail_templates/subscription_email_body-html.html:10
#, python-format
msgid ""
"Follow %(link_post_start)sthis link%(link_end)s to see the new post on the "
"topic %(link_topic_start)s%(topic_name)s%(link_end)s."
msgstr ""
#: templates/pybb/mail_templates/subscription_email_body-html.html:14
#, fuzzy, python-format
#| msgid ""
#| "If you don't want to recive notifications on new messages in this topic "
#| "visit following link:"
msgid ""
"If you don't want to receive notifications on new posts in this topic visit "
"%(link_start)sthis link%(link_end)s."
msgstr ""
"Wenn Sie keine E-Mails zu diesem Thema mehr erhalten möchten,klicken Sie den "
"folgenden Link"
#: templates/pybb/mail_templates/subscription_email_body.html:4
#, fuzzy
#| msgid "Link to post:"
msgid "Link to post"
msgstr "Link zum Beitrag"
#: templates/pybb/mail_templates/subscription_email_body.html:8
#, fuzzy, python-format
#| msgid ""
#| "If you don't want to recive notifications on new messages in this topic "
#| "visit following link:"
msgid ""
"If you don't want to receive notifications on new messages in this topic "
"visit following link: %(delete_url_full)s"
msgstr ""
"Wenn Sie keine E-Mails zu diesem Thema mehr erhalten möchten,klicken Sie den "
"folgenden Link"
#: templates/pybb/mail_templates/subscription_email_subject.html:2
msgid "New answer in topic that you subscribed."
msgstr "Neue Antwort im Forum"
#: templates/pybb/markup/bbcode_widget.html:22
#: templates/pybb/markup/markdown_widget.html:33
msgid "Your text to link here..."
msgstr ""
#: templates/pybb/markup/markdown_widget.html:17
msgid "First Level Heading"
msgstr "Titel 1"
#: templates/pybb/markup/markdown_widget.html:17
#: templates/pybb/markup/markdown_widget.html:18
#: templates/pybb/markup/markdown_widget.html:19
#: templates/pybb/markup/markdown_widget.html:20
#: templates/pybb/markup/markdown_widget.html:21
#: templates/pybb/markup/markdown_widget.html:22
msgid "Your title here..."
msgstr ""
#: templates/pybb/markup/markdown_widget.html:18
msgid "Second Level Heading"
msgstr "Titel 2"
#: templates/pybb/markup/markdown_widget.html:19
msgid "Heading 3"
msgstr "Titel 3"
#: templates/pybb/markup/markdown_widget.html:20
msgid "Heading 4"
msgstr "Titel 4"
#: templates/pybb/markup/markdown_widget.html:21
msgid "Heading 5"
msgstr "Titel 5"
#: templates/pybb/markup/markdown_widget.html:22
msgid "Heading 6"
msgstr "Titel 6"
#: templates/pybb/markup/markdown_widget.html:27
msgid "Bulleted List"
msgstr ""
#: templates/pybb/markup/markdown_widget.html:28
msgid "Numeric List"
msgstr ""
#: templates/pybb/markup/markdown_widget.html:36
msgid "Code Block / Code"
msgstr ""
#: templates/pybb/pagination.html:7
msgid "previous page"
msgstr "vorherige Seite"
#: templates/pybb/pagination.html:21
msgid "next page"
msgstr "nächste Seite"
#: templates/pybb/poll.html:4
msgid "Poll"
msgstr "Umfrage"
#: templates/pybb/poll.html:36
msgid "Cancel my poll vote"
msgstr ""
#: templates/pybb/poll_edit_form.html:7
msgid "Poll answers"
msgstr "Antworten zu Umfrage"
#: templates/pybb/poll_edit_form.html:20
msgid "remove answer"
msgstr "Antwort löschen"
#: templates/pybb/poll_edit_form.html:21
msgid "add answer"
msgstr "Antwort hinzufügen"
#: templates/pybb/post_template.html:28
#, python-format
msgid "Rank: %(rank)s"
msgstr "Rang: %(rank)s"
#: templates/pybb/post_template.html:41 templates/pybb/user.html:51
msgid "Edit"
msgstr "bearbeiten"
#: templates/pybb/post_template.html:45
msgid "Delete post?"
msgstr "Beitrag löschen?"
#: templates/pybb/post_template.html:46
msgid "Delete"
msgstr "löschen"
#: templates/pybb/post_template.html:49
msgid "Approve post"
msgstr "Beitrag genehmigen"
#: templates/pybb/post_template.html:53 templates/pybb/topic.html:62
msgid "Admin"
msgstr "Administrator"
#: templates/pybb/post_template.html:69
msgid "Edited"
msgstr "Bearbeitet"
#: templates/pybb/post_template.html:83
msgid "quote"
msgstr "zitieren"
#: templates/pybb/post_template.html:84
msgid "quote selected"
msgstr ""
#: templates/pybb/topic.html:51
msgid "Unstick topic"
msgstr "'Sticky' aufheben"
#: templates/pybb/topic.html:53
msgid "Stick topic"
msgstr "'Sticky' setzen"
#: templates/pybb/topic.html:57
msgid "Open topic"
msgstr "Thema öffnen"
#: templates/pybb/topic.html:59
msgid "Close topic"
msgstr "Thema schließen"
#: templates/pybb/topic.html:70
msgid "Unsubscribe"
msgstr "Abbestellen"
#: templates/pybb/topic_list.html:13
msgid "Views"
msgstr "Ansichten"
#: templates/pybb/topic_list.html:16
msgid "Last post"
msgstr "Letzter Beitrag"
#: templates/pybb/topic_list.html:26
msgid "Go to first unread post"
msgstr ""
#: templates/pybb/topic_list.html:32
msgid "pages"
msgstr "Seiten"
#: templates/pybb/user.html:16
msgid "Statistics"
msgstr "Statistik"
#: templates/pybb/user.html:19
#, python-format
msgid "Number of topics: %(count)s"
msgstr "Anzahl Themen: %(count)s"
#: templates/pybb/user.html:24
#, python-format
msgid "Number of posts: %(count)s"
msgstr "Anzahl Beiträge: %(count)s"
#: templates/pybb/user.html:29
#, python-format
msgid "Date of registration: %(date_joined)s "
msgstr "Registrierungsdatum: %(date_joined)s "
#: templates/pybb/user.html:36
msgid "Moderator"
msgstr "Moderator"
#: templates/pybb/user.html:41
msgid "Block"
msgstr "Block"
#: templates/pybb/user.html:42
msgid "Block and delete all messages"
msgstr ""
#: templates/pybb/user.html:46
#, fuzzy
#| msgid "Block"
msgid "Unblock"
msgstr "Block"
#: templates/pybb/user_posts.html:12 templates/pybb/user_posts.html.py:17
#, fuzzy
#| msgid "All topics created by"
msgid "All posts created by"
msgstr "Alle Beiträge von"
#: templates/pybb/user_topics.html:12 templates/pybb/user_topics.html.py:17
msgid "All topics created by"
msgstr "Alle Beiträge von"
#: templates/pybb/users.html:8 templates/pybb/users.html.py:24
msgid "Users"
msgstr "Benutzer"
#: templates/pybb/users.html:12
msgid "Search"
msgstr "Suche"
#: templatetags/pybb_tags.py:61
#, fuzzy, python-format
#| msgid "seconds ago"
msgid "%d second ago"
msgid_plural "%d seconds ago"
msgstr[0] "vor Sekunden"
msgstr[1] "vor Sekunden"
#: templatetags/pybb_tags.py:65
#, fuzzy, python-format
#| msgid "minutes ago"
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "vor Minuten"
msgstr[1] "vor Minuten"
#: templatetags/pybb_tags.py:75
#, python-format
msgid "today, %s"
msgstr "Heute, %s"
#: templatetags/pybb_tags.py:77
#, python-format
msgid "yesterday, %s"
msgstr "Gestern, %s"
#: util.py:140
msgid "Can't get profile for anonymous user"
msgstr ""
#: views.py:156
#, fuzzy
#| msgid "Forum categories are not created"
msgid "Forum does not exist"
msgstr "Keine Kategorien angelegt"
#: views.py:388
msgid "This topic does not exists"
msgstr ""
#: views.py:826
msgid ""
"Subscription removed. You will not receive emails from this topic unless you "
"subscribe or post again."
msgstr ""
#: views.py:837
msgid ""
"Subscription added. You will receive email notifications for replies to this "
"topic."
msgstr ""
#: views.py:855
msgid "All forums marked as read"
msgstr "Alle Foren wurden als gelesen markiert"
#: views.py:888
msgid "User successfuly blocked"
msgstr "Benutzer wurde erfolgreich gesperrt"
#: views.py:901
#, fuzzy
#| msgid "User successfuly blocked"
msgid "User successfuly unblocked"
msgstr "Benutzer wurde erfolgreich gesperrt"
#: views.py:939
msgid "Privileges updated"
msgstr ""
#~ msgid "Subscribers:"
#~ msgstr "Abonnenten:"
#~ msgid "Change the password"
#~ msgstr "Passwort ändern"
#~ msgid "Rank"
#~ msgstr "Rang"
#~ msgid "seconds ago,seconds ago,seconds ago"
#~ msgstr "vor Sekunden, vor Sekunden, vor Sekunden"
#~ msgid "minutes ago,minutes ago,minutes ago"
#~ msgstr "vor Minuten, vor Minuten, vor Minuten"
================================================
FILE: pybb/locale/es/LC_MESSAGES/django.po
================================================
# Spanish translation for the pybbm form.
# Copyright (C) 2013 Jose Antonio Martin
# This file is distributed under the same license as the pybbm package.
# Jose Antonio Martin <jantonio.martin@gmail.com>, 2013.
#
msgid ""
msgstr ""
"Project-Id-Version: pybbm\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-01-11 14:06+0100\n"
"PO-Revision-Date: 2017-01-11 14:13+0100\n"
"Last-Translator: DylannCordel <d.cordel@webu.coop>\n"
"Language-Team: \n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.6.10\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-Basepath: ../../..\n"
#: admin.py:45 admin.py:84 admin.py:112 admin.py:134
msgid "Additional options"
msgstr "Opciones adicionales"
#: admin.py:117 models.py:280
msgid "Message"
msgstr "Mensaje"
#: admin.py:148
msgid "View post"
msgstr "Ver mensaje"
#: admin.py:153
msgid "Edit post"
msgstr "Editar mensaje"
#: apps.py:9
msgid "Pybbm forum solution"
msgstr ""
#: feeds.py:27 feeds.py:28 templates/pybb/base.html:10
msgid "Latest posts on forum"
msgstr "Últimos mensajes en el foro"
#: feeds.py:41 feeds.py:42 templates/pybb/base.html:11
msgid "Latest topics on forum"
msgstr "Últimos temas en el foro"
#: forms.py:30
msgid "Attachment is too big"
msgstr "El adjunto es demasiado grande"
#: forms.py:48
#, python-format
msgid "You cant add more than %s answers for poll"
msgstr "No puedes añadir más de %s respuestas por encuesta"
#: forms.py:50
msgid "Add two or more answers for this poll"
msgstr "Añade dos o más respuestas a la encuesta"
#: forms.py:58 models.py:183
msgid "Subject"
msgstr "Asunto"
#: forms.py:59 models.py:195
msgid "Poll type"
msgstr "Tipo de encuesta"
#: forms.py:61 models.py:196
msgid "Poll question"
msgstr "Pregunta de la encuesta"
#: forms.py:64
#, fuzzy
#| msgid "Topics"
msgid "Topic slug"
msgstr "Temas"
#: forms.py:123
msgid "Polls question is required when adding a poll"
msgstr "Se requiere una pregunta para añadir una encuesta"
#: forms.py:176 models.py:186 models.py:295 models.py:368 models.py:507
msgid "User"
msgstr "Usuario"
#: forms.py:212
#, python-format
msgid "Avatar is too large, max size: %s bytes"
msgstr "El avatar es demasiado grande, máximo tamaño: %s bytes"
#: forms.py:272
msgid "be unsubscribe from this forum"
msgstr "darse de baja de este foro"
#: forms.py:277
msgid "You want to"
msgstr "Desea ser "
#: forms.py:281
#, fuzzy
#| msgid "New topic"
msgid "only new topics"
msgstr "Nuevo tema"
#: forms.py:282
#, fuzzy
#| msgid "Latest topics on forum"
msgid "all topics of the forum"
msgstr "Últimos temas en el foro"
#: forms.py:285
#, fuzzy
#| msgid "Close topic"
msgid "Concerned topics"
msgstr "Cerrar tema"
#: models.py:23 models.py:59
msgid "Name"
msgstr "Nombre"
#: models.py:24 models.py:60
msgid "Position"
msgstr "Posición"
#: models.py:25 models.py:66 templates/pybb/category.html:4
#: templates/pybb/forum_list.html:26
msgid "Hidden"
msgstr "Oculto"
#: models.py:26
msgid "If checked, this category will be visible only for staff"
msgstr "Marcado, esta categoría será visible solo para administradores"
#: models.py:27 models.py:69 models.py:197
msgid "Slug"
msgstr ""
#: models.py:31 models.py:56
msgid "Category"
msgstr "Categoría"
#: models.py:32
msgid "Categories"
msgstr "Categorías"
#: models.py:57
msgid "Parent forum"
msgstr ""
#: models.py:61
msgid "Description"
msgstr "Descripción"
#: models.py:62
msgid "Moderators"
msgstr "Moderadores"
#: models.py:63 models.py:185 models.py:297
msgid "Updated"
msgstr "Actualizado"
#: models.py:64 models.py:192 profiles.py:41
msgid "Post count"
msgstr "Número de mensajes"
#: models.py:65
msgid "Topic count"
msgstr "Número de temas"
#: models.py:68
msgid "Headline"
msgstr "Titular"
#: models.py:73 models.py:136 models.py:182 templates/pybb/forum_list.html:8
msgid "Forum"
msgstr "Foro"
#: models.py:74
msgid "Forums"
msgstr "Foros"
#: models.py:129
msgid "be notified only when a new topic is added"
msgstr "notificado solo cuando se agrega un nuevo tema"
#: models.py:130
msgid "be auto-subscribed to topics"
msgstr "suscribirse automáticamente a los temas"
#: models.py:134
#, fuzzy
#| msgid "Subscribers"
msgid "Subscriber"
msgstr "Suscriptores"
#: models.py:138
#, fuzzy
#| msgid "Subscriptions on topics"
msgid "Subscription type"
msgstr "Subscripciones a temas"
#: models.py:148
#, fuzzy
#| msgid "Subscriptions on topics"
msgid "Subscription to forum"
msgstr "Subscripciones a temas"
#: models.py:149
#, fuzzy
#| msgid "Subscriptions on topics"
msgid "Subscriptions to forums"
msgstr "Subscripciones a temas"
#: models.py:177
msgid "None"
msgstr "Ninguna"
#: models.py:178
msgid "Single answer"
msgstr "Respuesta única"
#: models.py:179
msgid "Multiple answers"
msgstr "Respuestas múltiples"
#: models.py:184 models.py:296
msgid "Created"
msgstr "Creado"
#: models.py:187
msgid "Views count"
msgstr "Lecturas"
#: models.py:188 templates/pybb/topic_list.html:27
msgid "Sticky"
msgstr "Pegajoso"
#: models.py:189 templates/pybb/topic_list.html:28
msgid "Closed"
msgstr "Cerrado"
#: models.py:191 templates/pybb/topic.html:88
msgid "Subscribers"
msgstr "Suscriptores"
#: models.py:194 models.py:299
msgid "On moderation"
msgstr "En moderación"
#: models.py:201 models.py:294 models.py:483 templates/pybb/topic_list.html:7
msgid "Topic"
msgstr "Tema"
#: models.py:202 templates/pybb/forum_list.html:11
#: templates/pybb/user_topics.html:7
msgid "Topics"
msgstr "Temas"
#: models.py:281
msgid "HTML version"
msgstr "Versión HTML"
#: models.py:282
msgid "Text version"
msgstr "Versión de texto"
#: models.py:298
msgid "User IP"
msgstr "IP de usuario"
#: models.py:303 models.py:386
msgid "Post"
msgstr "Mensaje"
#: models.py:304 templates/pybb/forum_list.html:14
#: templates/pybb/topic.html:42 templates/pybb/topic_list.html:10
#: templates/pybb/user_posts.html:7
msgid "Posts"
msgstr "Mensajes"
#: models.py:371
msgid "Profile"
msgstr "Perfil"
#: models.py:372
msgid "Profiles"
msgstr "Perfiles"
#: models.py:383
msgid "Attachment"
msgstr "Adjunto"
#: models.py:384
msgid "Attachments"
msgstr "Adjuntos"
#: models.py:387
msgid "Size"
msgstr "Tamaño"
#: models.py:388
msgid "File"
msgstr "Archivo"
#: models.py:438
msgid "Topic read tracker"
msgstr "Seguidor de temas leídos"
#: models.py:439
msgid "Topic read trackers"
msgstr "Seguidores de temas leídos"
#: models.py:476
msgid "Forum read tracker"
msgstr "Seguidor de foros leídos"
#: models.py:477
msgid "Forum read trackers"
msgstr "Seguidores de foros leídos"
#: models.py:484
msgid "Text"
msgstr "Texto"
#: models.py:487 models.py:506
msgid "Poll answer"
msgstr "Respuesta de encuesta"
#: models.py:488
msgid "Polls answers"
msgstr "Respuestas de encuestas"
#: models.py:511
msgid "Poll answer user"
msgstr "Usuario de respuesta de encuesta"
#: models.py:512
msgid "Polls answers users"
msgstr "Usuarios de respuestas de encuestas"
#: models.py:535
#, python-format
msgid ""
"After %(limit)s attemps, there is not any unique slug value for \"%(slug)s\""
msgstr ""
#: profiles.py:34
msgid "Signature"
msgstr "Firma"
#: profiles.py:35
msgid "Signature HTML Version"
msgstr "Versión HTML de la firma"
#: profiles.py:37
msgid "Time zone"
msgstr "Huso horario"
#: profiles.py:38
msgid "Language"
msgstr "Idioma"
#: profiles.py:40
msgid "Show signatures"
msgstr "Mostrar firmas"
#: profiles.py:42
msgid "Avatar"
msgstr "Avatar"
#: profiles.py:44
msgid "Automatically subscribe"
msgstr "Suscribir automáticamente"
#: profiles.py:45
msgid "Automatically subscribe to topics that you answer"
msgstr "Te suscribe automáticamente a los temas a los que respondas"
#: templates/pybb/_button_forum_subscription.html:1
#, fuzzy
#| msgid "Description"
msgid "Manage subscription"
msgstr "Descripción"
#: templates/pybb/_button_forum_subscription.html:1
#: templates/pybb/topic.html:72
msgid "Subscribe"
msgstr "Subscribir"
#: templates/pybb/_button_new_topic.html:1 templates/pybb/add_post.html:5
#: templates/pybb/add_post.html.py:32
msgid "New topic"
msgstr "Nuevo tema"
#: templates/pybb/_button_save.html:1
msgid "Save"
msgstr "Guardar"
#: templates/pybb/_button_submit.html:1
#: templates/pybb/forum_subscription.html:33
msgid "Submit"
msgstr "Enviar"
#: templates/pybb/_markitup.html:25
#: templates/pybb/markup/bbcode_widget.html:16
#: templates/pybb/markup/markdown_widget.html:24
msgid "Bold"
msgstr ""
#: templates/pybb/_markitup.html:26
#: templates/pybb/markup/bbcode_widget.html:17
#: templates/pybb/markup/markdown_widget.html:25
msgid "Italic"
msgstr ""
#: templates/pybb/_markitup.html:27
#: templates/pybb/markup/bbcode_widget.html:18
msgid "Underline"
msgstr ""
#: templates/pybb/_markitup.html:28
#: templates/pybb/markup/bbcode_widget.html:19
msgid "Stroke"
msgstr ""
#: templates/pybb/_markitup.html:30
#: templates/pybb/markup/bbcode_widget.html:21
#: templates/pybb/markup/markdown_widget.html:32
#, fuzzy
#| msgid "Signature"
msgid "Picture"
msgstr "Firma"
#: templates/pybb/_markitup.html:31
#: templates/pybb/markup/bbcode_widget.html:22
#: templates/pybb/markup/markdown_widget.html:33
msgid "Link"
msgstr ""
#: templates/pybb/_markitup.html:33
#: templates/pybb/markup/bbcode_widget.html:24
msgid "Bulleted list"
msgstr ""
#: templates/pybb/_markitup.html:34
#: templates/pybb/markup/bbcode_widget.html:25
msgid "Numeric list"
msgstr ""
#: templates/pybb/_markitup.html:35
#: templates/pybb/markup/bbcode_widget.html:26
msgid "List item"
msgstr ""
#: templates/pybb/_markitup.html:37
#: templates/pybb/markup/bbcode_widget.html:28
#: templates/pybb/markup/markdown_widget.html:35
#, fuzzy
#| msgid "quote"
msgid "Quotes"
msgstr "citar"
#: templates/pybb/_markitup.html:38
#: templates/pybb/markup/bbcode_widget.html:29
msgid "Code"
msgstr ""
#: templates/pybb/_markitup.html:40
#: templates/pybb/markup/bbcode_widget.html:31
msgid "Clean"
msgstr ""
#: templates/pybb/_markitup.html:41
#: templates/pybb/markup/bbcode_widget.html:32
#: templates/pybb/markup/markdown_widget.html:38
msgid "Preview"
msgstr ""
#: templates/pybb/_need_to_login_message.html:2
msgid "Register"
msgstr "Registrar"
#: templates/pybb/_need_to_login_message.html:2
msgid "or"
msgstr "o"
#: templates/pybb/_need_to_login_message.html:2
msgid "login"
msgstr "entrar"
#: templates/pybb/_need_to_login_message.html:2
msgid "to create to post a reply"
msgstr "para crear o responder a un tema"
#: templates/pybb/add_post.html:5 templates/pybb/add_post.html.py:32
msgid "New reply"
msgstr "Nueva respuesta"
#: templates/pybb/attachments_formset.html:6
msgid "Add attachments"
msgstr "Añadir adjuntos"
#: templates/pybb/attachments_formset.html:14
msgid ""
"If you need to upload larger files, please use an external storage website."
msgstr ""
#: templates/pybb/attachments_formset.html:14
#, python-format
msgid "(max size: %(max_size)s)"
msgstr ""
#: templates/pybb/attachments_formset.html:17
#: templates/pybb/edit_profile.html:25
msgid "delete"
msgstr "borrar"
#: templates/pybb/attachments_formset.html:20
msgid "Reference to your file"
msgstr ""
#: templates/pybb/attachments_formset.html:20
msgid "Ref"
msgstr ""
#: templates/pybb/attachments_formset.html:20
#: templates/pybb/mail_templates/forum_subscription_email_body.html:5
#: templates/pybb/mail_templates/forum_subscription_email_body.html:6
#: templates/pybb/mail_templates/forum_subscription_email_body.html:9
#: templates/pybb/mail_templates/subscription_email_body.html:4
#: templates/pybb/mail_templates/subscription_email_body.html:5
#: templates/pybb/topic.html:88 templates/pybb/topic_list.html:32
msgid ":"
msgstr ""
#: templates/pybb/attachments_formset.html:22
msgid "link"
msgstr ""
#: templates/pybb/attachments_formset.html:22
msgid "Insert a link to your file inside your post."
msgstr ""
#: templates/pybb/attachments_formset.html:23
msgid "image"
msgstr ""
#: templates/pybb/attachments_formset.html:23
msgid "Insert your image inside your post."
msgstr ""
#: templates/pybb/breadcrumb.html:4
msgid "Home"
msgstr "Inicio"
#: templates/pybb/delete_post.html:5
msgid "Are you sure you want to delete this message?"
msgstr "¿Estás seguro de que deseas borrar este mensaje?"
#: templates/pybb/delete_post.html:12
msgid "No, take me back"
msgstr "No, cancelar"
#: templates/pybb/delete_post.html:13
msgid "Yes, I am sure"
msgstr "Sí, estoy seguro"
#: templates/pybb/edit_post.html:4 templates/pybb/edit_post.html.py:17
msgid "Editing the post"
msgstr "Editando el mensaje"
#: templates/pybb/edit_privileges.html:5 templates/pybb/edit_privileges.html:8
msgid "Grant moderator privileges"
msgstr ""
#: templates/pybb/edit_profile.html:5 templates/pybb/edit_profile.html.py:8
#: templates/pybb/edit_profile.html:13
msgid "Profile editing"
msgstr "Editando perfil"
#: templates/pybb/edit_profile.html:18
msgid "Subscriptions on topics"
msgstr "Subscripciones a temas"
#: templates/pybb/forum_list.html:17
msgid "Last posts"
msgstr "Últimos mensajes"
#: templates/pybb/forum_list.html:43
msgid "No forums created"
msgstr "No hay foros creados"
#: templates/pybb/forum_list.html:44
msgid "Add forum now"
msgstr "Añadir foro ahora"
#: templates/pybb/forum_subscription.html:4
#, python-format
msgctxt "page title"
msgid "%(forum)s - Subscription"
msgstr "%(forum)s - Subscripciones"
#: templates/pybb/forum_subscription.html:14
#, python-format
msgctxt "content heading"
msgid "%(forum)s - Subscription"
msgstr "%(forum)s - Subscripciones"
#: templates/pybb/forum_subscription.html:32
msgid "Cancel"
msgstr ""
#: templates/pybb/index.html:17
msgid "Forum categories are not created"
msgstr "Las categorías del foro no están creadas"
#: templates/pybb/index.html:18
msgid "Add a category now"
msgstr "Añadir categoría ahora"
#: templates/pybb/index.html:22 templates/pybb/latest_topics.html:5
#: templates/pybb/latest_topics.html:8 templates/pybb/latest_topics.html:15
msgid "Last updates in topics"
msgstr "Últimas acutalizaciones de temas"
#: templates/pybb/index.html:23
msgid "Mark all forums as read"
msgstr "Marcar todos los foros como leídos"
#: templates/pybb/latest_topics.html:31
msgid "Mark all topics as read"
msgstr "Marcar todos los temas como leídos"
#: templates/pybb/mail_templates/forum_subscription_email_body.html:4
#, python-format
msgid ""
"User %(username)s post a new topic in forum to which you are subscribed "
"(%(forum_name)s)."
msgstr ""
"Usuario %(username)s respondió a un tema al que estás suscrito "
"(%(forum_name)s)."
#: templates/pybb/mail_templates/forum_subscription_email_body.html:5
#: templates/pybb/mail_templates/subscription_email_body.html:5
msgid "Link to topic"
msgstr "Enlace al tema"
#: templates/pybb/mail_templates/forum_subscription_email_body.html:6
msgid "Link to forum"
msgstr "Enlace al foro"
#: templates/pybb/mail_templates/forum_subscription_email_body.html:9
msgid ""
"If you don't want to receive notifications on new topics in this forum visit "
"following link"
msgstr ""
"Si no deseas recibir notificaciones de nuevos mensajes sobre este tema pulsa "
"el siguiente enlace"
#: templates/pybb/mail_templates/forum_subscription_email_subject.html:2
#, fuzzy
#| msgid "New answer in topic that you subscribed."
msgid "New topic in forum that you subscribed."
msgstr "Nueva respuesta a un tema de tu interés."
#: templates/pybb/mail_templates/subscription_email_body-html.html:7
#: templates/pybb/mail_templates/subscription_email_body.html:3
#, python-format
msgid "User %(username)s replied in topic to which you are subscribed."
msgstr "Usuario %(username)s respondió a un tema al que estás suscrito."
#: templates/pybb/mail_templates/subscription_email_body-html.html:10
#, python-format
msgid ""
"Follow %(link_post_start)sthis link%(link_end)s to see the new post on the "
"topic %(link_topic_start)s%(topic_name)s%(link_end)s."
msgstr ""
#: templates/pybb/mail_templates/subscription_email_body-html.html:14
#, python-format
msgid ""
"If you don't want to receive notifications on new posts in this topic visit "
"%(link_start)sthis link%(link_end)s."
msgstr ""
"Si no deseas recibir notificaciones de nuevos mensajes sobre este tema pulsa "
"%(link_start)sel siguiente enlace%(link_end)s."
#: templates/pybb/mail_templates/subscription_email_body.html:4
msgid "Link to post"
msgstr "Enlace al mensaje"
#: templates/pybb/mail_templates/subscription_email_body.html:8
#, python-format
msgid ""
"If you don't want to receive notifications on new messages in this topic "
"visit following link: %(delete_url_full)s"
msgstr ""
"Si no deseas recibir notificaciones de nuevos mensajes sobre este tema pulsa "
"el siguiente enlace: %(delete_url_full)s"
#: templates/pybb/mail_templates/subscription_email_subject.html:2
msgid "New answer in topic that you subscribed."
msgstr "Nueva respuesta a un tema de tu interés."
#: templates/pybb/markup/bbcode_widget.html:22
#: templates/pybb/markup/markdown_widget.html:33
msgid "Your text to link here..."
msgstr ""
#: templates/pybb/markup/markdown_widget.html:17
msgid "First Level Heading"
msgstr "Titular 1"
#: templates/pybb/markup/markdown_widget.html:17
#: templates/pybb/markup/markdown_widget.html:18
#: templates/pybb/markup/markdown_widget.html:19
#: templates/pybb/markup/markdown_widget.html:20
#: templates/pybb/markup/markdown_widget.html:21
#: templates/pybb/markup/markdown_widget.html:22
msgid "Your title here..."
msgstr ""
#: templates/pybb/markup/markdown_widget.html:18
msgid "Second Level Heading"
msgstr "Titular 2"
#: templates/pybb/markup/markdown_widget.html:19
msgid "Heading 3"
msgstr "Titular 3"
#: templates/pybb/markup/markdown_widget.html:20
msgid "Heading 4"
msgstr "Titular 4"
#: templates/pybb/markup/markdown_widget.html:21
msgid "Heading 5"
msgstr "Titular 5"
#: templates/pybb/markup/markdown_widget.html:22
msgid "Heading 6"
msgstr "Titular 6"
#: templates/pybb/markup/markdown_widget.html:27
msgid "Bulleted List"
msgstr ""
#: templates/pybb/markup/markdown_widget.html:28
msgid "Numeric List"
msgstr ""
#: templates/pybb/markup/markdown_widget.html:36
msgid "Code Block / Code"
msgstr ""
#: templates/pybb/pagination.html:7
msgid "previous page"
msgstr "página anterior"
#: templates/pybb/pagination.html:21
msgid "next page"
msgstr "página siguiente"
#: templates/pybb/poll.html:4
msgid "Poll"
msgstr "Encuesta"
#: templates/pybb/poll.html:36
msgid "Cancel my poll vote"
msgstr ""
#: templates/pybb/poll_edit_form.html:7
msgid "Poll answers"
msgstr "Respuestas a encuesta"
#: templates/pybb/poll_edit_form.html:20
msgid "remove answer"
msgstr "eliminar respuesta"
#: templates/pybb/poll_edit_form.html:21
msgid "add answer"
msgstr "añadir respuesta"
#: templates/pybb/post_template.html:28
#, python-format
msgid "Rank: %(rank)s"
msgstr "Rango: %(rank)s"
#: templates/pybb/post_template.html:41 templates/pybb/user.html:51
msgid "Edit"
msgstr "Editar"
#: templates/pybb/post_template.html:45
msgid "Delete post?"
msgstr "¿Borrar mensaje?"
#: templates/pybb/post_template.html:46
msgid "Delete"
msgstr "Borrar"
#: templates/pybb/post_template.html:49
msgid "Approve post"
msgstr "Aprobar mensaje"
#: templates/pybb/post_template.html:53 templates/pybb/topic.html:62
msgid "Admin"
msgstr "Admin"
#: templates/pybb/post_template.html:69
msgid "Edited"
msgstr "Editado"
#: templates/pybb/post_template.html:83
msgid "quote"
msgstr "citar"
#: templates/pybb/post_template.html:84
msgid "quote selected"
msgstr ""
#: templates/pybb/topic.html:51
msgid "Unstick topic"
msgstr "Desanclar tema"
#: templates/pybb/topic.html:53
msgid "Stick topic"
msgstr "Anclar tema"
#: templates/pybb/topic.html:57
msgid "Open topic"
msgstr "Abrir tema"
#: templates/pybb/topic.html:59
msgid "Close topic"
msgstr "Cerrar tema"
#: templates/pybb/topic.html:70
msgid "Unsubscribe"
msgstr "Anular subscripción"
#: templates/pybb/topic_list.html:13
msgid "Views"
msgstr "Vistas"
#: templates/pybb/topic_list.html:16
msgid "Last post"
msgstr "Último mensaje"
#: templates/pybb/topic_list.html:26
msgid "Go to first unread post"
msgstr "Ir al primer mensaje no leído"
#: templates/pybb/topic_list.html:32
msgid "pages"
msgstr "páginas"
#: templates/pybb/user.html:16
msgid "Statistics"
msgstr "Estadísticas"
#: templates/pybb/user.html:19
#, python-format
msgid "Number of topics: %(count)s"
msgstr "Número de temas: %(count)s"
#: templates/pybb/user.html:24
#, python-format
msgid "Number of posts: %(count)s"
msgstr "Número de mensajes: %(count)s"
#: templates/pybb/user.html:29
#, python-format
msgid "Date of registration: %(date_joined)s "
msgstr "Fecha de registro: %(date_joined)s "
#: templates/pybb/user.html:36
#, fuzzy
#| msgid "Moderators"
msgid "Moderator"
msgstr "Moderadores"
#: templates/pybb/user.html:41
msgid "Block"
msgstr "Bloquear"
#: templates/pybb/user.html:42
msgid "Block and delete all messages"
msgstr ""
#: templates/pybb/user.html:46
#, fuzzy
#| msgid "Block"
msgid "Unblock"
msgstr "Bloquear"
#: templates/pybb/user_posts.html:12 templates/pybb/user_posts.html.py:17
msgid "All posts created by"
msgstr "Todos los mensajes creados por"
#: templates/pybb/user_topics.html:12 templates/pybb/user_topics.html.py:17
msgid "All topics created by"
msgstr "Todos los temas creados por"
#: templates/pybb/users.html:8 templates/pybb/users.html.py:24
msgid "Users"
msgstr "Usuarios"
#: templates/pybb/users.html:12
msgid "Search"
msgstr "Buscar"
#: templatetags/pybb_tags.py:61
#, fuzzy, python-format
#| msgid "seconds ago"
msgid "%d second ago"
msgid_plural "%d seconds ago"
msgstr[0] "segundos"
msgstr[1] "segundos"
#: templatetags/pybb_tags.py:65
#, fuzzy, python-format
#| msgid "minutes ago"
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "minutos"
msgstr[1] "minutos"
#: templatetags/pybb_tags.py:75
#, python-format
msgid "today, %s"
msgstr "hoy, %s"
#: templatetags/pybb_tags.py:77
#, python-format
msgid "yesterday, %s"
msgstr "ayer, %s"
#: util.py:140
msgid "Can't get profile for anonymous user"
msgstr "No se pude obtener el perfil del usuario anónimo"
#: views.py:156
#, fuzzy
#| msgid "Forum categories are not created"
msgid "Forum does not exist"
msgstr "Las categorías del foro no están creadas"
#: views.py:388
msgid "This topic does not exists"
msgstr ""
#: views.py:826
msgid ""
"Subscription removed. You will not receive emails from this topic unless you "
"subscribe or post again."
msgstr ""
#: views.py:837
msgid ""
"Subscription added. You will receive email notifications for replies to this "
"topic."
msgstr ""
#: views.py:855
msgid "All forums marked as read"
msgstr "Todos los foros marcados como leídos"
#: views.py:888
msgid "User successfuly blocked"
msgstr "Usuario bloqueado con éxito"
#: views.py:901
#, fuzzy
#| msgid "User successfuly blocked"
msgid "User successfuly unblocked"
msgstr "Usuario bloqueado con éxito"
#: views.py:939
msgid "Privileges updated"
msgstr ""
#~ msgid "Subscribers:"
#~ msgstr "Suscriptores:"
#~ msgid "Rank"
#~ msgstr "Rango"
================================================
FILE: pybb/locale/fr/LC_MESSAGES/django.po
================================================
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <frederique.castagnac@makina-corpus.com>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: pybbm\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-01-11 14:06+0100\n"
"PO-Revision-Date: 2017-01-11 14:10+0100\n"
"Last-Translator: DylannCordel <d.cordel@webu.coop>\n"
"Language-Team: \n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-Basepath: ../../..\n"
"X-Generator: Poedit 1.6.10\n"
#: admin.py:45 admin.py:84 admin.py:112 admin.py:134
msgid "Additional options"
msgstr "Options supplémentaires"
#: admin.py:117 models.py:280
msgid "Message"
msgstr "Message"
#: admin.py:148
msgid "View post"
msgstr "Voir le message"
#: admin.py:153
msgid "Edit post"
msgstr "Modifier le message"
#: apps.py:9
msgid "Pybbm forum solution"
msgstr "Solution de forum Pybbm"
#: feeds.py:27 feeds.py:28 templates/pybb/base.html:10
msgid "Latest posts on forum"
msgstr "Derniers messages sur le forum"
#: feeds.py:41 feeds.py:42 templates/pybb/base.html:11
msgid "Latest topics on forum"
msgstr "Derniers sujets sur le forum"
#: forms.py:30
msgid "Attachment is too big"
msgstr "Le fichier joint est trop lourd"
#: forms.py:48
#, python-format
msgid "You cant add more than %s answers for poll"
msgstr "Vous ne pouvez ajouter plus de %s réponses pour un sondage"
#: forms.py:50
msgid "Add two or more answers for this poll"
msgstr "Ajouter au moins 2 réponses pour ce sondage"
#: forms.py:58 models.py:183
msgid "Subject"
msgstr "Thème"
#: forms.py:59 models.py:195
msgid "Poll type"
msgstr "Type de sondage"
#: forms.py:61 models.py:196
msgid "Poll question"
msgstr "Question de sondage"
#: forms.py:64
msgid "Topic slug"
msgstr "Slug du sujet"
#: forms.py:123
msgid "Polls question is required when adding a poll"
msgstr "Vous devez spécifier une question lorsque vous ajoutez un sondage"
#: forms.py:176 models.py:186 models.py:295 models.py:368 models.py:507
msgid "User"
msgstr "Utilisateur"
#: forms.py:212
#, python-format
msgid "Avatar is too large, max size: %s bytes"
msgstr "Avatar trop grand, taille max : %s octets"
#: forms.py:272
msgid "be unsubscribe from this forum"
msgstr "être désinscrit de ce forum"
#: forms.py:277
msgid "You want to"
msgstr "Vous souhaitez"
#: forms.py:281
msgid "only new topics"
msgstr "seulement les nouveaux sujets"
#: forms.py:282
msgid "all topics of the forum"
msgstr "tous les sujets du forum"
#: forms.py:285
msgid "Concerned topics"
msgstr "Sujets concernés"
#: models.py:23 models.py:59
msgid "Name"
msgstr "Nom"
#: models.py:24 models.py:60
msgid "Position"
msgstr "Position"
#: models.py:25 models.py:66 templates/pybb/category.html:4
#: templates/pybb/forum_list.html:26
msgid "Hidden"
msgstr "Caché"
#: models.py:26
msgid "If checked, this category will be visible only for staff"
msgstr "Si coché, cette catégorie sera visible par l'équipe uniquement"
#: models.py:27 models.py:69 models.py:197
msgid "Slug"
msgstr "Slug"
#: models.py:31 models.py:56
msgid "Category"
msgstr "Catégorie"
#: models.py:32
msgid "Categories"
msgstr "Catégories"
#: models.py:57
msgid "Parent forum"
msgstr "Forum parent"
#: models.py:61
msgid "Description"
msgstr "Description"
#: models.py:62
msgid "Moderators"
msgstr "Modérateurs"
#: models.py:63 models.py:185 models.py:297
msgid "Updated"
msgstr "Mis à jour"
#: models.py:64 models.py:192 profiles.py:41
msgid "Post count"
msgstr "Nombre de messages"
#: models.py:65
msgid "Topic count"
msgstr "Nombre de sujets"
#: models.py:68
msgid "Headline"
msgstr "Titre "
#: models.py:73 models.py:136 models.py:182 templates/pybb/forum_list.html:8
msgid "Forum"
msgstr "Forum"
#: models.py:74
msgid "Forums"
msgstr "Forums"
#: models.py:129
msgid "be notified only when a new topic is added"
msgstr "être notifié seulement lorsqu'un nouveau sujet est ajouté"
#: models.py:130
msgid "be auto-subscribed to topics"
msgstr "être automatiquement inscrit aux sujets"
#: models.py:134
msgid "Subscriber"
msgstr "Abonné"
#: models.py:138
msgid "Subscription type"
msgstr "Type d'abonnement"
#: models.py:148
msgid "Subscription to forum"
msgstr "Abonnement au forum"
#: models.py:149
msgid "Subscriptions to forums"
msgstr "Abonnements aux forums"
#: models.py:177
msgid "None"
msgstr "Aucun(e)"
#: models.py:178
msgid "Single answer"
msgstr "Réponse simple"
#: models.py:179
msgid "Multiple answers"
msgstr "Réponses multiples"
#: models.py:184 models.py:296
msgid "Created"
msgstr "Créé"
#: models.py:187
msgid "Views count"
msgstr "Nombre de vues"
#: models.py:188 templates/pybb/topic_list.html:27
msgid "Sticky"
msgstr "Épinglé"
#: models.py:189 templates/pybb/topic_list.html:28
msgid "Closed"
msgstr "Fermé"
#: models.py:191 templates/pybb/topic.html:88
msgid "Subscribers"
msgstr "Abonnés"
#: models.py:194 models.py:299
msgid "On moderation"
msgstr "En modération"
#: models.py:201 models.py:294 models.py:483 templates/pybb/topic_list.html:7
msgid "Topic"
msgstr "Sujet"
#: models.py:202 templates/pybb/forum_list.html:11
#: templates/pybb/user_topics.html:7
msgid "Topics"
msgstr "Sujets"
#: models.py:281
msgid "HTML version"
msgstr "Version HTML"
#: models.py:282
msgid "Text version"
msgstr "Version texte"
#: models.py:298
msgid "User IP"
msgstr "IP de l'utilisateur"
#: models.py:303 models.py:386
msgid "Post"
msgstr "Message"
#: models.py:304 templates/pybb/forum_list.html:14
#: templates/pybb/topic.html:42 templates/pybb/topic_list.html:10
#: templates/pybb/user_posts.html:7
msgid "Posts"
msgstr "Messages"
#: models.py:371
msgid "Profile"
msgstr "Profil"
#: models.py:372
msgid "Profiles"
msgstr "Profils"
#: models.py:383
msgid "Attachment"
msgstr "Fichier joint"
#: models.py:384
msgid "Attachments"
msgstr "Fichiers joints"
#: models.py:387
msgid "Size"
msgstr "Taille"
#: models.py:388
msgid "File"
msgstr "Fichier"
#: models.py:438
msgid "Topic read tracker"
msgstr "Suivi des sujets lus"
#: models.py:439
msgid "Topic read trackers"
msgstr "Suivis des sujets lus"
#: models.py:476
msgid "Forum read tracker"
msgstr "Suivi des forums lus"
#: models.py:477
msgid "Forum read trackers"
msgstr "Suivis des forums lus"
#: models.py:484
msgid "Text"
msgstr "Texte"
#: models.py:487 models.py:506
msgid "Poll answer"
msgstr "Réponse de sondage"
#: models.py:488
msgid "Polls answers"
msgstr "Réponses de sondage"
#: models.py:511
msgid "Poll answer user"
msgstr "Réponse au sondage"
#: models.py:512
msgid "Polls answers users"
msgstr "Réponses aux sondages"
#: models.py:535
#, python-format
msgid ""
"After %(limit)s attemps, there is not any unique slug value for \"%(slug)s\""
msgstr ""
"Après %(limit)s essais, il n'y a aucune valeur de slug unique pour \"%(slug)s"
"\""
#: profiles.py:34
msgid "Signature"
msgstr "Signature"
#: profiles.py:35
msgid "Signature HTML Version"
msgstr "Version HTML de la signature"
#: profiles.py:37
msgid "Time zone"
msgstr "Fuseau horaire"
#: profiles.py:38
msgid "Language"
msgstr "Langue"
#: profiles.py:40
msgid "Show signatures"
msgstr "Afficher les signatures"
#: profiles.py:42
msgid "Avatar"
msgstr "Avatar"
#: profiles.py:44
msgid "Automatically subscribe"
msgstr "S'abonner automatiquement"
#: profiles.py:45
msgid "Automatically subscribe to topics that you answer"
msgstr "S'abonner automatiquement aux sujets auxquels vous répondez"
#: templates/pybb/_button_forum_subscription.html:1
msgid "Manage subscription"
msgstr "Gérer vos abonnements"
#: templates/pybb/_button_forum_subscription.html:1
#: templates/pybb/topic.html:72
msgid "Subscribe"
msgstr "S'abonner"
#: templates/pybb/_button_new_topic.html:1 templates/pybb/add_post.html:5
#: templates/pybb/add_post.html.py:32
msgid "New topic"
msgstr "Nouveau sujet"
#: templates/pybb/_button_save.html:1
msgid "Save"
msgstr "Enregistrer"
#: templates/pybb/_button_submit.html:1
#: templates/pybb/forum_subscription.html:33
msgid "S
gitextract_xr1bgpyb/ ├── .coveragerc ├── .gitignore ├── .hgignore ├── .travis.yml ├── AUTHORS ├── CHANGELOG ├── LICENSE ├── MANIFEST.in ├── README.rst ├── docs/ │ ├── Makefile │ ├── anonymous.rst │ ├── conf.py │ ├── contributing.rst │ ├── customuser.rst │ ├── example.rst │ ├── filters.rst │ ├── index.rst │ ├── install.rst │ ├── javascript.rst │ ├── make.bat │ ├── markup.rst │ ├── notifications.rst │ ├── originalpybb.rst │ ├── permissions.rst │ ├── premoderation.rst │ ├── problems.rst │ ├── pybbmigrate.rst │ ├── settings.rst │ ├── templatetags.rst │ ├── testing.rst │ └── updates.rst ├── pybb/ │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── compat.py │ ├── context_processors.py │ ├── defaults.py │ ├── feeds.py │ ├── forms.py │ ├── locale/ │ │ ├── de/ │ │ │ └── LC_MESSAGES/ │ │ │ ├── django.mo │ │ │ └── django.po │ │ ├── es/ │ │ │ └── LC_MESSAGES/ │ │ │ ├── django.mo │ │ │ └── django.po │ │ ├── fr/ │ │ │ └── LC_MESSAGES/ │ │ │ ├── django.mo │ │ │ └── django.po │ │ ├── he/ │ │ │ └── LC_MESSAGES/ │ │ │ ├── django.mo │ │ │ └── django.po │ │ ├── it/ │ │ │ └── LC_MESSAGES/ │ │ │ ├── django.mo │ │ │ └── django.po │ │ ├── ja/ │ │ │ └── LC_MESSAGES/ │ │ │ ├── django.mo │ │ │ └── django.po │ │ ├── pl/ │ │ │ └── LC_MESSAGES/ │ │ │ ├── django.mo │ │ │ └── django.po │ │ ├── pt_BR/ │ │ │ └── LC_MESSAGES/ │ │ │ ├── django.mo │ │ │ └── django.po │ │ ├── ru/ │ │ │ └── LC_MESSAGES/ │ │ │ ├── django.mo │ │ │ └── django.po │ │ ├── sk/ │ │ │ └── LC_MESSAGES/ │ │ │ ├── django.mo │ │ │ └── django.po │ │ ├── sv/ │ │ │ └── LC_MESSAGES/ │ │ │ ├── django.mo │ │ │ └── django.po │ │ ├── uk/ │ │ │ └── LC_MESSAGES/ │ │ │ ├── django.mo │ │ │ └── django.po │ │ └── zh/ │ │ └── LC_MESSAGES/ │ │ ├── django.mo │ │ └── django.po │ ├── management/ │ │ ├── __init__.py │ │ └── commands/ │ │ ├── __init__.py │ │ ├── dump_topics.py │ │ ├── migrate_profile.py │ │ ├── pybb_delete_invalid_topics.py │ │ ├── pybb_update_counters.py │ │ └── supermoderator.py │ ├── markup/ │ │ ├── __init__.py │ │ ├── base.py │ │ ├── bbcode.py │ │ └── markdown.py │ ├── middleware.py │ ├── migrations/ │ │ ├── 0001_initial.py │ │ ├── 0002_slugs_optional.py │ │ ├── 0003_slugs_fill.py │ │ ├── 0004_slugs_required.py │ │ ├── 0005_auto_20151108_1528.py │ │ ├── 0006_forum_subscriptions.py │ │ ├── 0007_auto_20170111_1504.py │ │ └── __init__.py │ ├── models.py │ ├── permissions.py │ ├── profiles.py │ ├── signals.py │ ├── static/ │ │ ├── markitup/ │ │ │ ├── ajax_csrf.js │ │ │ ├── jquery.markitup.js │ │ │ ├── preview.css │ │ │ ├── sets/ │ │ │ │ ├── bbcode/ │ │ │ │ │ ├── readme.txt │ │ │ │ │ ├── set.js │ │ │ │ │ └── style.css │ │ │ │ ├── default/ │ │ │ │ │ ├── set.js │ │ │ │ │ └── style.css │ │ │ │ └── markdown/ │ │ │ │ ├── readme.txt │ │ │ │ ├── set.js │ │ │ │ └── style.css │ │ │ ├── skins/ │ │ │ │ ├── markitup/ │ │ │ │ │ └── style.css │ │ │ │ └── simple/ │ │ │ │ └── style.css │ │ │ └── templates/ │ │ │ ├── preview.css │ │ │ └── preview.html │ │ └── pybb/ │ │ ├── forum.less │ │ ├── forum3.less │ │ ├── js/ │ │ │ ├── markitup.js │ │ │ └── pybbjs.js │ │ ├── posts.less │ │ ├── posts3.less │ │ ├── visual.less │ │ └── visual3.less │ ├── subscription.py │ ├── templates/ │ │ └── pybb/ │ │ ├── _button_forum_subscription.html │ │ ├── _button_new_topic.html │ │ ├── _button_save.html │ │ ├── _button_submit.html │ │ ├── _easy_thumbnail_avatar.html │ │ ├── _markitup.html │ │ ├── _markitup_preview.html │ │ ├── _need_to_login_message.html │ │ ├── _select_radio.html │ │ ├── _sorl_thumbnail_avatar.html │ │ ├── add_post.html │ │ ├── attachments_formset.html │ │ ├── avatar.html │ │ ├── base.html │ │ ├── breadcrumb.html │ │ ├── breadcrumb_top_extra_crumb.html │ │ ├── category.html │ │ ├── delete_post.html │ │ ├── edit_post.html │ │ ├── edit_privileges.html │ │ ├── edit_profile.html │ │ ├── feeds/ │ │ │ ├── posts_description.html │ │ │ ├── posts_title.html │ │ │ ├── topics_description.html │ │ │ └── topics_title.html │ │ ├── form.html │ │ ├── form_errors.html │ │ ├── form_field.html │ │ ├── forum.html │ │ ├── forum_last_update_info.html │ │ ├── forum_list.html │ │ ├── forum_subscription.html │ │ ├── index.html │ │ ├── latest_topics.html │ │ ├── mail_templates/ │ │ │ ├── base-html.html │ │ │ ├── base.html │ │ │ ├── forum_subscription_email_body.html │ │ │ ├── forum_subscription_email_subject.html │ │ │ ├── subscription_email_body-html.html │ │ │ ├── subscription_email_body.html │ │ │ └── subscription_email_subject.html │ │ ├── markup/ │ │ │ ├── bbcode_widget.html │ │ │ └── markdown_widget.html │ │ ├── move_post.html │ │ ├── pagination.html │ │ ├── poll.html │ │ ├── poll_edit_form.html │ │ ├── post_form.html │ │ ├── post_template.html │ │ ├── topic.html │ │ ├── topic_last_message_info.html │ │ ├── topic_list.html │ │ ├── user.html │ │ ├── user_posts.html │ │ ├── user_topics.html │ │ └── users.html │ ├── templatetags/ │ │ ├── __init__.py │ │ └── pybb_tags.py │ ├── tests.py │ ├── urls.py │ ├── util.py │ └── views.py ├── runtests.py ├── setup.py ├── test/ │ ├── example_bootstrap/ │ │ ├── example_bootstrap/ │ │ │ ├── __init__.py │ │ │ ├── settings.py │ │ │ ├── urls.py │ │ │ └── wsgi.py │ │ ├── fixtures/ │ │ │ └── demo_data.json │ │ ├── manage.py │ │ ├── requirements.txt │ │ ├── static/ │ │ │ ├── bootstrap/ │ │ │ │ ├── alerts.less │ │ │ │ ├── bootstrap.less │ │ │ │ ├── breadcrumbs.less │ │ │ │ ├── button-groups.less │ │ │ │ ├── buttons.less │ │ │ │ ├── carousel.less │ │ │ │ ├── close.less │ │ │ │ ├── code.less │ │ │ │ ├── component-animations.less │ │ │ │ ├── dropdowns.less │ │ │ │ ├── forms.less │ │ │ │ ├── grid.less │ │ │ │ ├── mixins.less │ │ │ │ ├── modals.less │ │ │ │ ├── navbar.less │ │ │ │ ├── navs.less │ │ │ │ ├── pager.less │ │ │ │ ├── pagination.less │ │ │ │ ├── popovers.less │ │ │ │ ├── progress-bars.less │ │ │ │ ├── responsive-utilities.less │ │ │ │ ├── scaffolding.less │ │ │ │ ├── tables.less │ │ │ │ ├── thumbnails.less │ │ │ │ ├── tooltip.less │ │ │ │ ├── type.less │ │ │ │ ├── utilities.less │ │ │ │ ├── variables.less │ │ │ │ └── wells.less │ │ │ ├── csrf.js │ │ │ ├── example_bootstrap.css │ │ │ └── example_bootstrap.less │ │ └── templates/ │ │ ├── 404.html │ │ ├── base.html │ │ ├── bootstrap_base.html │ │ ├── pybb/ │ │ │ ├── breadcrumb.html │ │ │ └── form_field.html │ │ └── registration/ │ │ ├── activate.html │ │ ├── activation_complete.html │ │ ├── activation_email.txt │ │ ├── activation_email_subject.txt │ │ ├── login.html │ │ ├── logout.html │ │ ├── registration_complete.html │ │ └── registration_form.html │ ├── example_thirdparty/ │ │ ├── example_thirdparty/ │ │ │ ├── __init__.py │ │ │ ├── forms.py │ │ │ ├── settings.py │ │ │ ├── urls.py │ │ │ └── wsgi.py │ │ ├── manage.py │ │ ├── requirements.txt │ │ └── templates/ │ │ ├── pybb/ │ │ │ ├── breadcrumb.html │ │ │ ├── form.html │ │ │ └── form_field.html │ │ └── site_base.html │ └── test_project/ │ ├── manage.py │ ├── requirements_test.txt │ ├── templates/ │ │ ├── 404.html │ │ ├── base.html │ │ └── pybb/ │ │ ├── _need_to_login_message.html │ │ └── edit_profile.html │ ├── test_app/ │ │ ├── __init__.py │ │ ├── apps.py │ │ ├── migrations/ │ │ │ ├── 0001_initial.py │ │ │ └── __init__.py │ │ └── models.py │ └── test_project/ │ ├── __init__.py │ ├── markup_parsers.py │ ├── settings.py │ └── urls.py └── tox.ini
SYMBOL INDEX (628 symbols across 42 files)
FILE: pybb/admin.py
class ForumInlineAdmin (line 14) | class ForumInlineAdmin(admin.TabularInline):
class CategoryAdmin (line 20) | class CategoryAdmin(admin.ModelAdmin):
class ForumAdmin (line 31) | class ForumAdmin(admin.ModelAdmin):
method get_fieldsets (line 51) | def get_fieldsets(self, request, obj=None):
class PollAnswerAdmin (line 64) | class PollAnswerAdmin(admin.TabularInline):
class TopicAdmin (line 70) | class TopicAdmin(admin.ModelAdmin):
class TopicReadTrackerAdmin (line 91) | class TopicReadTrackerAdmin(admin.ModelAdmin):
class ForumReadTrackerAdmin (line 95) | class ForumReadTrackerAdmin(admin.ModelAdmin):
class PostAdmin (line 99) | class PostAdmin(admin.ModelAdmin):
class ProfileAdmin (line 123) | class ProfileAdmin(admin.ModelAdmin):
class AttachmentAdmin (line 141) | class AttachmentAdmin(admin.ModelAdmin):
method admin_view_post (line 144) | def admin_view_post(self, obj):
method admin_edit_post (line 149) | def admin_edit_post(self, obj):
FILE: pybb/apps.py
class PybbConfig (line 5) | class PybbConfig(AppConfig):
method ready (line 10) | def ready(self):
FILE: pybb/compat.py
function send_html_mail (line 14) | def send_html_mail(subject, text_msg, html_msg, sender, recipient,
function send_mass_html_mail (line 25) | def send_mass_html_mail(emails, *args, **kwargs):
function get_image_field_class (line 39) | def get_image_field_class():
function get_image_field_full_name (line 52) | def get_image_field_full_name():
function get_user_model (line 66) | def get_user_model():
function get_user_model_path (line 71) | def get_user_model_path():
function get_username_field (line 75) | def get_username_field():
function get_atomic_func (line 79) | def get_atomic_func():
function get_paginator_class (line 84) | def get_paginator_class():
function is_installed (line 100) | def is_installed(app_name):
function get_related_model_class (line 105) | def get_related_model_class(parent_model, field_name):
function slugify (line 109) | def slugify(text):
FILE: pybb/context_processors.py
function processor (line 7) | def processor(request):
FILE: pybb/defaults.py
function getsetting_with_deprecation_check (line 58) | def getsetting_with_deprecation_check(all_settings, setting_name): # pr...
function bbcode (line 143) | def bbcode(s): # pragma: no cover
function markdown (line 155) | def markdown(s): # pragma: no cover
function _render_quote (line 167) | def _render_quote(name, value, options, parent, context): # pragma: no ...
function smile_it (line 176) | def smile_it(s): # pragma: no cover
FILE: pybb/feeds.py
class PybbFeed (line 11) | class PybbFeed(Feed):
method link (line 14) | def link(self):
method item_guid (line 17) | def item_guid(self, obj):
method item_pubdate (line 20) | def item_pubdate(self, obj):
class LastPosts (line 24) | class LastPosts(PybbFeed):
method get_object (line 30) | def get_object(self, request, *args, **kwargs):
method items (line 33) | def items(self, user):
class LastTopics (line 38) | class LastTopics(PybbFeed):
method get_object (line 44) | def get_object(self, request, *args, **kwargs):
method items (line 47) | def items(self, user):
FILE: pybb/forms.py
class AttachmentForm (line 24) | class AttachmentForm(forms.ModelForm):
class Meta (line 25) | class Meta(object):
method clean_file (line 29) | def clean_file(self):
class PollAnswerForm (line 37) | class PollAnswerForm(forms.ModelForm):
class Meta (line 38) | class Meta:
class BasePollAnswerFormset (line 43) | class BasePollAnswerFormset(BaseInlineFormSet):
method clean (line 44) | def clean(self):
class PostForm (line 58) | class PostForm(forms.ModelForm):
class Meta (line 67) | class Meta(object):
method __init__ (line 74) | def __init__(self, *args, **kwargs):
method clean_body (line 110) | def clean_body(self):
method clean (line 120) | def clean(self):
method save (line 128) | def save(self, commit=True):
class MovePostForm (line 172) | class MovePostForm(forms.Form):
method __init__ (line 174) | def __init__(self, instance, user, *args, **kwargs):
method get_new_topic (line 245) | def get_new_topic(self):
method save (line 266) | def save(self):
class AdminPostForm (line 294) | class AdminPostForm(PostForm):
method __init__ (line 301) | def __init__(self, *args, **kwargs):
method save (line 308) | def save(self, *args, **kwargs):
class EditProfileForm (line 324) | class EditProfileForm(forms.ModelForm):
class Meta (line 325) | class Meta(object):
method __init__ (line 329) | def __init__(self, *args, **kwargs):
method clean_avatar (line 333) | def clean_avatar(self):
method clean_signature (line 339) | def clean_signature(self):
class UserSearchForm (line 350) | class UserSearchForm(forms.Form):
method filter (line 353) | def filter(self, qs):
class PollForm (line 361) | class PollForm(forms.Form):
method __init__ (line 362) | def __init__(self, topic, *args, **kwargs):
method clean_answers (line 377) | def clean_answers(self):
class ForumSubscriptionForm (line 385) | class ForumSubscriptionForm(forms.Form):
method __init__ (line 386) | def __init__(self, user, forum, instance=None, *args, **kwargs):
method process (line 411) | def process(self):
class ModeratorForm (line 430) | class ModeratorForm(forms.Form):
method __init__ (line 432) | def __init__(self, user, *args, **kwargs):
method process (line 457) | def process(self, target_user):
FILE: pybb/management/commands/dump_topics.py
class Command (line 10) | class Command(BaseCommand):
method handle (line 14) | def handle(self, *args, **options):
FILE: pybb/management/commands/migrate_profile.py
class Command (line 12) | class Command(BaseCommand):
method handle (line 16) | def handle(self, *args, **options):
FILE: pybb/management/commands/pybb_delete_invalid_topics.py
class Command (line 7) | class Command(BaseCommand):
method handle (line 10) | def handle(self, *args, **kwargs):
FILE: pybb/management/commands/pybb_update_counters.py
class Command (line 9) | class Command(BaseCommand):
method handle (line 12) | def handle(self, *args, **options):
FILE: pybb/management/commands/supermoderator.py
class Command (line 8) | class Command(BaseCommand):
method handle (line 12) | def handle(self, *args, **kwargs):
FILE: pybb/markup/base.py
function smile_it (line 9) | def smile_it(s):
function filter_blanks (line 15) | def filter_blanks(user, str):
function rstrip_str (line 22) | def rstrip_str(user, str):
class BaseParser (line 30) | class BaseParser(object):
method format_attachments (line 33) | def format_attachments(self, text, attachments):
method format (line 59) | def format(self, text, instance=None):
method quote (line 64) | def quote(self, text, username=''):
method get_widget_cls (line 68) | def get_widget_cls(cls, **kwargs):
FILE: pybb/markup/bbcode.py
class BBCodeWidget (line 10) | class BBCodeWidget(Textarea):
class Media (line 11) | class Media:
method render (line 25) | def render(self, *args, **kwargs):
class BBCodeParser (line 31) | class BBCodeParser(BaseParser):
method __init__ (line 34) | def __init__(self):
method _render_quote (line 42) | def _render_quote(self, name, value, options, parent, context):
method format (line 49) | def format(self, text, instance=None):
method quote (line 54) | def quote(self, text, username=''):
FILE: pybb/markup/markdown.py
class MarkdownWidget (line 10) | class MarkdownWidget(Textarea):
class Media (line 11) | class Media:
method render (line 25) | def render(self, *args, **kwargs):
class MarkdownParser (line 31) | class MarkdownParser(BaseParser):
method __init__ (line 34) | def __init__(self):
method format (line 37) | def format(self, text, instance=None):
method quote (line 42) | def quote(self, text, username=''):
FILE: pybb/middleware.py
class PybbMiddleware (line 15) | class PybbMiddleware(MiddlewareParentClass):
method process_request (line 16) | def process_request(self, request):
FILE: pybb/migrations/0001_initial.py
class Migration (line 9) | class Migration(migrations.Migration):
FILE: pybb/migrations/0002_slugs_optional.py
class Migration (line 5) | class Migration(migrations.Migration):
FILE: pybb/migrations/0003_slugs_fill.py
function fill_slugs (line 6) | def fill_slugs(apps, schema_editor):
function clear_slugs (line 25) | def clear_slugs(apps, schema_editor):
class Migration (line 35) | class Migration(migrations.Migration):
FILE: pybb/migrations/0004_slugs_required.py
class Migration (line 5) | class Migration(migrations.Migration):
FILE: pybb/migrations/0005_auto_20151108_1528.py
class Migration (line 11) | class Migration(migrations.Migration):
FILE: pybb/migrations/0006_forum_subscriptions.py
class Migration (line 7) | class Migration(migrations.Migration):
FILE: pybb/migrations/0007_auto_20170111_1504.py
class Migration (line 5) | class Migration(migrations.Migration):
FILE: pybb/models.py
class Category (line 18) | class Category(models.Model):
class Meta (line 25) | class Meta(object):
method __str__ (line 30) | def __str__(self):
method forum_count (line 33) | def forum_count(self):
method get_absolute_url (line 36) | def get_absolute_url(self):
method topics (line 42) | def topics(self):
method posts (line 46) | def posts(self):
class Forum (line 50) | class Forum(models.Model):
class Meta (line 66) | class Meta(object):
method __str__ (line 72) | def __str__(self):
method update_counters (line 75) | def update_counters(self):
method get_absolute_url (line 90) | def get_absolute_url(self):
method posts (line 96) | def posts(self):
method last_post (line 100) | def last_post(self):
method get_parents (line 106) | def get_parents(self):
class ForumSubscription (line 118) | class ForumSubscription(models.Model):
class Meta (line 141) | class Meta(object):
method __str__ (line 146) | def __str__(self):
method save (line 150) | def save(self, all_topics=False, **kwargs):
method delete (line 158) | def delete(self, all_topics=False, **kwargs):
class Topic (line 164) | class Topic(models.Model):
class Meta (line 192) | class Meta(object):
method __str__ (line 198) | def __str__(self):
method head (line 202) | def head(self):
method last_post (line 209) | def last_post(self):
method get_absolute_url (line 215) | def get_absolute_url(self):
method save (line 220) | def save(self, *args, **kwargs):
method delete (line 237) | def delete(self, using=None):
method update_counters (line 241) | def update_counters(self):
method get_parents (line 250) | def get_parents(self):
method poll_votes (line 258) | def poll_votes(self):
class RenderableItem (line 265) | class RenderableItem(models.Model):
class Meta (line 270) | class Meta(object):
method render (line 277) | def render(self):
class Post (line 285) | class Post(RenderableItem):
class Meta (line 293) | class Meta(object):
method summary (line 298) | def summary(self):
method __str__ (line 303) | def __str__(self):
method is_topic_head (line 307) | def is_topic_head(self):
method save (line 310) | def save(self, *args, **kwargs):
method get_absolute_url (line 338) | def get_absolute_url(self):
method delete (line 341) | def delete(self, *args, **kwargs):
method get_parents (line 352) | def get_parents(self):
class Profile (line 359) | class Profile(PybbProfile):
class Meta (line 368) | class Meta(object):
method get_absolute_url (line 372) | def get_absolute_url(self):
method get_display_name (line 375) | def get_display_name(self):
class Attachment (line 379) | class Attachment(models.Model):
class Meta (line 380) | class Meta(object):
method save (line 389) | def save(self, *args, **kwargs):
method size_display (line 393) | def size_display(self):
class TopicReadTrackerManager (line 403) | class TopicReadTrackerManager(models.Manager):
method get_or_create_tracker (line 404) | def get_or_create_tracker(self, user, topic):
class TopicReadTracker (line 425) | class TopicReadTracker(models.Model):
class Meta (line 435) | class Meta(object):
class ForumReadTrackerManager (line 441) | class ForumReadTrackerManager(models.Manager):
method get_or_create_tracker (line 442) | def get_or_create_tracker(self, user, forum):
class ForumReadTracker (line 463) | class ForumReadTracker(models.Model):
class Meta (line 473) | class Meta(object):
class PollAnswer (line 479) | class PollAnswer(models.Model):
class Meta (line 483) | class Meta:
method __str__ (line 487) | def __str__(self):
method votes (line 490) | def votes(self):
method votes_percent (line 493) | def votes_percent(self):
class PollAnswerUser (line 501) | class PollAnswerUser(models.Model):
class Meta (line 506) | class Meta:
method __str__ (line 511) | def __str__(self):
function create_or_check_slug (line 515) | def create_or_check_slug(instance, model, **extra_filters):
FILE: pybb/permissions.py
class DefaultPermissionHandler (line 10) | class DefaultPermissionHandler(object):
method filter_categories (line 25) | def filter_categories(self, user, qs):
method may_view_category (line 33) | def may_view_category(self, user, category):
method filter_forums (line 44) | def filter_forums(self, user, qs):
method may_view_forum (line 52) | def may_view_forum(self, user, forum):
method may_create_topic (line 60) | def may_create_topic(self, user, forum):
method filter_topics (line 69) | def filter_topics(self, user, qs):
method may_view_topic (line 94) | def may_view_topic(self, user, topic):
method may_moderate_topic (line 112) | def may_moderate_topic(self, user, topic):
method may_close_topic (line 119) | def may_close_topic(self, user, topic):
method may_open_topic (line 123) | def may_open_topic(self, user, topic):
method may_stick_topic (line 127) | def may_stick_topic(self, user, topic):
method may_unstick_topic (line 131) | def may_unstick_topic(self, user, topic):
method may_vote_in_topic (line 135) | def may_vote_in_topic(self, user, topic):
method may_create_post (line 145) | def may_create_post(self, user, topic):
method may_post_as_admin (line 161) | def may_post_as_admin(self, user):
method may_subscribe_topic (line 169) | def may_subscribe_topic(self, user, topic):
method filter_posts (line 176) | def filter_posts(self, user, qs):
method may_view_post (line 198) | def may_view_post(self, user, post):
method may_moderate_post (line 212) | def may_moderate_post(self, user, post):
method may_edit_post (line 217) | def may_edit_post(self, user, post):
method may_delete_post (line 223) | def may_delete_post(self, user, post):
method may_admin_post (line 237) | def may_admin_post(self, user, post):
method may_block_user (line 246) | def may_block_user(self, user, user_to_block):
method may_attach_files (line 252) | def may_attach_files(self, user):
method may_create_poll (line 259) | def may_create_poll(self, user):
method may_edit_topic_slug (line 266) | def may_edit_topic_slug(self, user):
method may_change_forum (line 274) | def may_change_forum(self, user, forum):
method may_manage_moderators (line 283) | def may_manage_moderators(self, user):
FILE: pybb/profiles.py
class PybbProfile (line 22) | class PybbProfile(models.Model):
class Meta (line 27) | class Meta(object):
method save (line 47) | def save(self, *args, **kwargs):
method avatar_url (line 52) | def avatar_url(self):
method get_display_name (line 58) | def get_display_name(self):
FILE: pybb/signals.py
function topic_saved (line 10) | def topic_saved(instance, **kwargs):
function post_saved (line 14) | def post_saved(instance, **kwargs):
function post_deleted (line 38) | def post_deleted(instance, **kwargs):
function user_saved (line 51) | def user_saved(instance, created, **kwargs):
function get_save_slug (line 74) | def get_save_slug(extra_field=None):
function setup (line 95) | def setup():
FILE: pybb/static/markitup/ajax_csrf.js
function getCookie (line 2) | function getCookie(name) {
function csrfSafeMethod (line 19) | function csrfSafeMethod(method) {
FILE: pybb/static/markitup/jquery.markitup.js
function localize (line 126) | function localize(data, inText) {
function init (line 134) | function init() {
function dropMenus (line 200) | function dropMenus(markupSet) {
function magicMarkups (line 247) | function magicMarkups(string) {
function prepare (line 280) | function prepare(action) {
function build (line 288) | function build(string) {
function markup (line 336) | function markup(button) {
function fixOperaBug (line 427) | function fixOperaBug(string) {
function fixIeBug (line 434) | function fixIeBug(string) {
function insert (line 442) | function insert(block) {
function set (line 452) | function set(start, len) {
function get (line 471) | function get() {
function preview (line 497) | function preview() {
function refreshPreview (line 534) | function refreshPreview() {
function renderPreview (line 538) | function renderPreview() {
function writeInPreview (line 571) | function writeInPreview(data) {
function keyPressed (line 588) | function keyPressed(e) {
function remove (line 636) | function remove() {
FILE: pybb/static/pybb/js/pybbjs.js
function pybb_delete_post (line 1) | function pybb_delete_post(url, post_id, confirm_text) {
function getSelectedText (line 19) | function getSelectedText() {
function add_pybb_attachment_item (line 138) | function add_pybb_attachment_item() {
FILE: pybb/subscription.py
function notify_forum_subscribers (line 16) | def notify_forum_subscribers(topic):
function notify_topic_subscribers (line 33) | def notify_topic_subscribers(post):
function send_notification (line 54) | def send_notification(users, template, context=None):
FILE: pybb/templatetags/pybb_tags.py
function pybb_time (line 30) | def pybb_time(parser, token):
function pybb_get_time (line 40) | def pybb_get_time(context, context_time):
class PybbTimeNode (line 44) | class PybbTimeNode(template.Node):
method __init__ (line 45) | def __init__(self, time):
method render (line 49) | def render(self, context):
function pybb_user_time (line 54) | def pybb_user_time(context_time, user):
function pybb_link (line 84) | def pybb_link(object, anchor=''):
function pybb_topic_moderated_by (line 96) | def pybb_topic_moderated_by(topic, user): # pragma: no cover
function pybb_editable_by (line 106) | def pybb_editable_by(post, user): # pragma: no cover
function pybb_posted_by (line 117) | def pybb_posted_by(post, user):
function pybb_is_topic_unread (line 125) | def pybb_is_topic_unread(topic, user):
function pybb_topic_unread (line 143) | def pybb_topic_unread(topics, user):
function pybb_forum_unread (line 173) | def pybb_forum_unread(forums, user):
function pybb_topic_inline_pagination (line 195) | def pybb_topic_inline_pagination(topic):
function pybb_topic_poll_not_voted (line 203) | def pybb_topic_poll_not_voted(topic, user):
function endswith (line 210) | def endswith(str, substr):
function pybb_get_profile (line 215) | def pybb_get_profile(*args, **kwargs):
function pybb_get_latest_topics (line 223) | def pybb_get_latest_topics(context, cnt=5, user=None):
function pybb_get_latest_posts (line 232) | def pybb_get_latest_posts(context, cnt=5, user=None):
function load_perms_filters (line 240) | def load_perms_filters():
function check_app_installed (line 270) | def check_app_installed(app_name):
function pybbm_calc_topic_views (line 275) | def pybbm_calc_topic_views(topic):
FILE: pybb/tests.py
function sleep_only_if_required (line 46) | def sleep_only_if_required(s):
class SharedTestModule (line 56) | class SharedTestModule(object):
method create_user (line 58) | def create_user(self):
method login_client (line 61) | def login_client(self, username='zeus', password='zeus'):
method create_post (line 64) | def create_post(self, _sleep=False, **kwargs):
method create_post_via_http (line 77) | def create_post_via_http(self, client, forum_id=None, topic_id=None, _...
method create_initial (line 102) | def create_initial(self, post=True):
method get_form_values (line 109) | def get_form_values(self, response, form="post-form"):
method get_with_user (line 112) | def get_with_user(self, url, username=None, password=None):
class FeaturesTest (line 120) | class FeaturesTest(TestCase, SharedTestModule):
method setUp (line 121) | def setUp(self):
method test_base (line 130) | def test_base(self):
method test_forum_page (line 143) | def test_forum_page(self):
method test_category_page (line 153) | def test_category_page(self):
method test_profile_language_default (line 160) | def test_profile_language_default(self):
method test_profile_edit (line 166) | def test_profile_edit(self):
method test_pagination_and_topic_addition (line 182) | def test_pagination_and_topic_addition(self):
method test_bbcode_and_topic_title (line 193) | def test_bbcode_and_topic_title(self):
method test_topic_addition (line 200) | def test_topic_addition(self):
method test_topic_read_before_post_addition (line 212) | def test_topic_read_before_post_addition(self):
method test_post_deletion (line 254) | def test_post_deletion(self):
method test_topic_deletion (line 259) | def test_topic_deletion(self):
method test_forum_updated (line 270) | def test_forum_updated(self):
method test_read_tracking (line 277) | def test_read_tracking(self):
method test_read_tracking_multi_user (line 323) | def test_read_tracking_multi_user(self):
method test_read_tracking_multi_forum (line 409) | def test_read_tracking_multi_forum(self):
method test_read_tracker_after_posting (line 441) | def test_read_tracker_after_posting(self):
method test_pybb_is_topic_unread_filter (line 450) | def test_pybb_is_topic_unread_filter(self):
method test_is_forum_unread_filter (line 507) | def test_is_forum_unread_filter(self):
method test_read_tracker_when_topics_forum_changed (line 555) | def test_read_tracker_when_topics_forum_changed(self):
method test_open_first_unread_post (line 609) | def test_open_first_unread_post(self):
method test_latest_topics (line 640) | def test_latest_topics(self):
method test_hidden (line 699) | def test_hidden(self):
method test_inactive (line 760) | def test_inactive(self):
method get_csrf (line 774) | def get_csrf(self, form):
method test_csrf (line 777) | def test_csrf(self):
method test_user_blocking (line 785) | def test_user_blocking(self):
method test_user_unblocking (line 813) | def test_user_unblocking(self):
method test_ajax_preview (line 827) | def test_ajax_preview(self):
method test_headline (line 832) | def test_headline(self):
method test_quote (line 838) | def test_quote(self):
method test_edit_post (line 845) | def test_edit_post(self):
method test_admin_post_add (line 895) | def test_admin_post_add(self):
method test_stick (line 904) | def test_stick(self):
method test_delete_view (line 913) | def test_delete_view(self):
method test_open_close (line 940) | def test_open_close(self):
method test_subscription (line 957) | def test_subscription(self):
method test_subscription_disabled (line 994) | def test_subscription_disabled(self):
method _test_notification_emails_init (line 1027) | def _test_notification_emails_init(self):
method test_notification_emails_alternative (line 1051) | def test_notification_emails_alternative(self):
method test_notification_emails_content (line 1062) | def test_notification_emails_content(self):
method test_notification_emails_translation (line 1091) | def test_notification_emails_translation(self):
method test_notifications_disabled (line 1104) | def test_notifications_disabled(self):
method test_forum_subscription (line 1134) | def test_forum_subscription(self):
method test_topic_updated (line 1262) | def test_topic_updated(self):
method test_topic_deleted (line 1274) | def test_topic_deleted(self):
method test_user_views (line 1302) | def test_user_views(self):
method test_post_count (line 1325) | def test_post_count(self):
method test_latest_topics_tag (line 1336) | def test_latest_topics_tag(self):
method test_latest_posts_tag (line 1345) | def test_latest_posts_tag(self):
method test_multiple_objects_returned (line 1354) | def test_multiple_objects_returned(self):
method tearDown (line 1370) | def tearDown(self):
method test_managing_forums (line 1374) | def test_managing_forums(self):
class MoveAndSplitPostTest (line 1441) | class MoveAndSplitPostTest(TestCase, SharedTestModule):
method create_initial (line 1443) | def create_initial(self):
method test_move_topic (line 1464) | def test_move_topic(self):
method test_split_posts_all (line 1503) | def test_split_posts_all(self):
method test_split_posts_last (line 1566) | def test_split_posts_last(self):
method test_split_posts_some_same_forum (line 1591) | def test_split_posts_some_same_forum(self):
method test_split_posts_some_other_forum (line 1624) | def test_split_posts_some_other_forum(self):
class AnonymousTest (line 1656) | class AnonymousTest(TestCase, SharedTestModule):
method setUp (line 1657) | def setUp(self):
method tearDown (line 1672) | def tearDown(self):
method test_anonymous_posting (line 1677) | def test_anonymous_posting(self):
method test_anonymous_cache_topic_views (line 1684) | def test_anonymous_cache_topic_views(self):
function premoderate_test (line 1705) | def premoderate_test(user, post):
class PreModerationTest (line 1715) | class PreModerationTest(TestCase, SharedTestModule):
method setUp (line 1716) | def setUp(self):
method test_premoderation (line 1723) | def test_premoderation(self):
method tearDown (line 1811) | def tearDown(self):
class AttachmentTest (line 1815) | class AttachmentTest(TestCase, SharedTestModule):
method setUp (line 1816) | def setUp(self):
method test_attachment (line 1825) | def test_attachment(self):
method test_attachment_usage (line 1836) | def test_attachment_usage(self):
method tearDown (line 1867) | def tearDown(self):
class PollTest (line 1872) | class PollTest(TestCase, SharedTestModule):
method setUp (line 1873) | def setUp(self):
method test_poll_add (line 1879) | def test_poll_add(self):
method test_regression_adding_poll_with_removed_answers (line 1923) | def test_regression_adding_poll_with_removed_answers(self):
method test_regression_poll_deletion_after_second_post (line 1939) | def test_regression_poll_deletion_after_second_post(self):
method test_poll_edit (line 1959) | def test_poll_edit(self):
method test_poll_voting (line 2000) | def test_poll_voting(self):
method test_poll_voting_on_closed_topic (line 2044) | def test_poll_voting_on_closed_topic(self):
method tearDown (line 2059) | def tearDown(self):
class FiltersTest (line 2063) | class FiltersTest(TestCase, SharedTestModule):
method setUp (line 2064) | def setUp(self):
method test_filters (line 2068) | def test_filters(self):
class CustomPermissionHandler (line 2079) | class CustomPermissionHandler(permissions.DefaultPermissionHandler):
method filter_categories (line 2085) | def filter_categories(self, user, qs):
method may_view_category (line 2088) | def may_view_category(self, user, category):
method filter_forums (line 2091) | def filter_forums(self, user, qs):
method may_view_forum (line 2096) | def may_view_forum(self, user, forum):
method filter_topics (line 2099) | def filter_topics(self, user, qs):
method may_view_topic (line 2105) | def may_view_topic(self, user, topic):
method filter_posts (line 2108) | def filter_posts(self, user, qs):
method may_view_post (line 2113) | def may_view_post(self, user, post):
method may_create_poll (line 2116) | def may_create_poll(self, user):
method may_edit_topic_slug (line 2119) | def may_edit_topic_slug(self, user):
method may_change_forum (line 2122) | def may_change_forum(self, user, forum):
class MarkupParserTest (line 2125) | class MarkupParserTest(TestCase, SharedTestModule):
method setUp (line 2127) | def setUp(self):
method tearDown (line 2147) | def tearDown(self):
method test_markup_engines (line 2153) | def test_markup_engines(self):
method test_quote_engines (line 2234) | def test_quote_engines(self):
method test_body_cleaners (line 2263) | def test_body_cleaners(self):
function _attach_perms_class (line 2279) | def _attach_perms_class(class_name):
function _detach_perms_class (line 2288) | def _detach_perms_class():
class ControlsAndPermissionsTest (line 2295) | class ControlsAndPermissionsTest(TestCase, SharedTestModule):
method create_initial (line 2297) | def create_initial(self, on_moderation=False, closed=False, sticky=Fal...
method test_permission_documentation (line 2365) | def test_permission_documentation(self):
method test_may_create_post (line 2558) | def test_may_create_post(self):
method test_filter_topics_anonymous_and_other (line 2633) | def test_filter_topics_anonymous_and_other(self):
method test_filter_posts_anonymous_and_other (line 2665) | def test_filter_posts_anonymous_and_other(self):
method test_filter_topics_author (line 2726) | def test_filter_topics_author(self):
method test_filter_posts_author (line 2754) | def test_filter_posts_author(self):
method test_filter_topics_staff_without_perms (line 2794) | def test_filter_topics_staff_without_perms(self):
method test_filter_posts_staff_without_perms (line 2824) | def test_filter_posts_staff_without_perms(self):
method test_filter_topics_staff_with_perms (line 2869) | def test_filter_topics_staff_with_perms(self):
method test_filter_posts_staff_with_perms (line 2890) | def test_filter_posts_staff_with_perms(self):
method test_filter_topics_superuser (line 2922) | def test_filter_topics_superuser(self):
method test_filter_posts_superuser (line 2940) | def test_filter_posts_superuser(self):
method test_post_actions_anonymous (line 2969) | def test_post_actions_anonymous(self):
method test_post_actions_own_post (line 2980) | def test_post_actions_own_post(self):
method test_post_actions_other_post (line 3011) | def test_post_actions_other_post(self):
method test_post_actions_staff_no_perms (line 3023) | def test_post_actions_staff_no_perms(self):
method test_post_actions_staff_with_perms (line 3037) | def test_post_actions_staff_with_perms(self):
method test_post_actions_superuser (line 3085) | def test_post_actions_superuser(self):
method test_post_actions_moderator (line 3113) | def test_post_actions_moderator(self):
class CustomPermissionHandlerTest (line 3180) | class CustomPermissionHandlerTest(TestCase, SharedTestModule):
method setUp (line 3183) | def setUp(self):
method tearDown (line 3203) | def tearDown(self):
method test_category_permission (line 3206) | def test_category_permission(self):
method test_forum_permission (line 3218) | def test_forum_permission(self):
method test_topic_permission (line 3226) | def test_topic_permission(self):
method test_post_permission (line 3233) | def test_post_permission(self):
method test_poll_add (line 3240) | def test_poll_add(self):
class RestrictEditingHandler (line 3256) | class RestrictEditingHandler(permissions.DefaultPermissionHandler):
method may_create_topic (line 3257) | def may_create_topic(self, user, forum):
method may_create_post (line 3260) | def may_create_post(self, user, topic):
method may_edit_post (line 3263) | def may_edit_post(self, user, post):
class LogonRedirectTest (line 3267) | class LogonRedirectTest(TestCase, SharedTestModule):
method setUp (line 3270) | def setUp(self):
method test_redirect_category (line 3288) | def test_redirect_category(self):
method test_redirect_forum (line 3299) | def test_redirect_forum(self):
method test_redirect_topic (line 3310) | def test_redirect_topic(self):
method test_redirect_post (line 3321) | def test_redirect_post(self):
method test_redirect_topic_add (line 3333) | def test_redirect_topic_add(self):
method test_redirect_post_edit (line 3351) | def test_redirect_post_edit(self):
method test_profile_autocreation_signal_on (line 3369) | def test_profile_autocreation_signal_on(self):
method test_profile_autocreation_middleware (line 3376) | def test_profile_autocreation_middleware(self):
method test_user_delete_cascade (line 3387) | def test_user_delete_cascade(self):
class NiceUrlsTest (line 3402) | class NiceUrlsTest(TestCase, SharedTestModule):
method __init__ (line 3403) | def __init__(self, *args, **kwargs):
method setUp (line 3409) | def setUp(self):
method test_unicode_slugify (line 3416) | def test_unicode_slugify(self):
method test_automatique_slug (line 3420) | def test_automatique_slug(self):
method test_no_duplicate_slug (line 3425) | def test_no_duplicate_slug(self):
method test_fail_on_too_many_duplicate_slug (line 3455) | def test_fail_on_too_many_duplicate_slug(self):
method test_long_duplicate_slug (line 3471) | def test_long_duplicate_slug(self):
method test_absolute_url (line 3480) | def test_absolute_url(self):
method test_add_topic (line 3500) | def test_add_topic(self):
method test_old_url_redirection (line 3522) | def test_old_url_redirection(self):
method tearDown (line 3540) | def tearDown(self):
class TestTemplateTags (line 3544) | class TestTemplateTags(TestCase, SharedTestModule):
method test_pybb_time_anonymous (line 3551) | def test_pybb_time_anonymous(self):
method test_pybb_time_authenticated (line 3575) | def test_pybb_time_authenticated(self):
method test_pybb_get_time (line 3590) | def test_pybb_get_time(self):
method test_pybb_link (line 3598) | def test_pybb_link(self):
method test_pybb_posted_by (line 3616) | def test_pybb_posted_by(self):
method test_pybb_is_topic_unread (line 3629) | def test_pybb_is_topic_unread(self):
method test_pybb_topic_unread (line 3646) | def test_pybb_topic_unread(self):
method test_pybb_forum_unread (line 3722) | def test_pybb_forum_unread(self):
method test_pybb_topic_inline_pagination (line 3791) | def test_pybb_topic_inline_pagination(self):
method test_pybb_topic_poll_not_voted (line 3812) | def test_pybb_topic_poll_not_voted(self):
method test_endswith (line 3836) | def test_endswith(self):
method test_pybb_get_profile (line 3844) | def test_pybb_get_profile(self):
method test_pybb_get_latest_topics (line 3859) | def test_pybb_get_latest_topics(self):
method test_pybb_get_latest_posts (line 3892) | def test_pybb_get_latest_posts(self):
method test_perms_check_app_installed (line 3949) | def test_perms_check_app_installed(self):
method test_pybbm_calc_topic_views (line 3955) | def test_pybbm_calc_topic_views(self):
function build_dynamic_test_for_templatetags_perms (line 3975) | def build_dynamic_test_for_templatetags_perms():
class MiscTest (line 4056) | class MiscTest(TestCase, SharedTestModule):
method test_profile_avatar_url_property (line 4058) | def test_profile_avatar_url_property(self):
method test_profile_get_display_name (line 4075) | def test_profile_get_display_name(self):
FILE: pybb/util.py
function resolve_class (line 27) | def resolve_class(name):
function resolve_function (line 35) | def resolve_function(path):
function get_markup_engine (line 45) | def get_markup_engine(name=None):
function _get_markup_formatter (line 68) | def _get_markup_formatter(name=None):
function _get_markup_quoter (line 92) | def _get_markup_quoter(name=None):
function get_body_cleaner (line 116) | def get_body_cleaner(name):
function unescape (line 120) | def unescape(text):
function get_pybb_profile (line 130) | def get_pybb_profile(user):
function get_pybb_profile_model (line 145) | def get_pybb_profile_model():
function build_cache_key (line 154) | def build_cache_key(key_name, **kwargs):
class FilePathGenerator (line 161) | class FilePathGenerator(object):
method __init__ (line 167) | def __init__(self, to, *args, **kwargs):
method deconstruct (line 170) | def deconstruct(self, *args, **kwargs):
method __call__ (line 173) | def __call__(self, instance, filename):
FILE: pybb/views.py
class PaginatorMixin (line 35) | class PaginatorMixin(object):
method get_paginator (line 36) | def get_paginator(self, queryset, per_page, orphans=0, allow_empty_fir...
class RedirectToLoginMixin (line 43) | class RedirectToLoginMixin(object):
method dispatch (line 48) | def dispatch(self, request, *args, **kwargs):
method get_login_redirect_url (line 58) | def get_login_redirect_url(self):
class IndexView (line 63) | class IndexView(generic.ListView):
method get_context_data (line 68) | def get_context_data(self, **kwargs):
method get_queryset (line 76) | def get_queryset(self):
class CategoryView (line 80) | class CategoryView(RedirectToLoginMixin, generic.DetailView):
method get_login_redirect_url (line 85) | def get_login_redirect_url(self):
method get_queryset (line 90) | def get_queryset(self):
method get_object (line 93) | def get_object(self, queryset=None):
method get_context_data (line 99) | def get_context_data(self, **kwargs):
method get (line 105) | def get(self, *args, **kwargs):
class ForumView (line 111) | class ForumView(RedirectToLoginMixin, PaginatorMixin, generic.ListView):
method dispatch (line 117) | def dispatch(self, request, *args, **kwargs):
method get_login_redirect_url (line 121) | def get_login_redirect_url(self):
method get_context_data (line 124) | def get_context_data(self, **kwargs):
method get_queryset (line 140) | def get_queryset(self):
method get_forum (line 148) | def get_forum(self, **kwargs):
method get (line 157) | def get(self, *args, **kwargs):
class ForumSubscriptionView (line 163) | class ForumSubscriptionView(RedirectToLoginMixin, generic.FormView):
method get_login_redirect_url (line 167) | def get_login_redirect_url(self):
method get_success_url (line 170) | def get_success_url(self):
method get_form_kwargs (line 173) | def get_form_kwargs(self):
method get_context_data (line 181) | def get_context_data(self, **kwargs):
method form_valid (line 187) | def form_valid(self, form):
method get_objects (line 211) | def get_objects(self):
class LatestTopicsView (line 223) | class LatestTopicsView(PaginatorMixin, generic.ListView):
method get_queryset (line 229) | def get_queryset(self):
class PybbFormsMixin (line 235) | class PybbFormsMixin(object):
method get_post_form_class (line 243) | def get_post_form_class(self):
method get_admin_post_form_class (line 246) | def get_admin_post_form_class(self):
method get_attachment_formset_class (line 249) | def get_attachment_formset_class(self):
method get_poll_form_class (line 252) | def get_poll_form_class(self):
method get_poll_answer_formset_class (line 255) | def get_poll_answer_formset_class(self):
class TopicView (line 259) | class TopicView(RedirectToLoginMixin, PaginatorMixin, PybbFormsMixin, ge...
method get (line 264) | def get(self, request, *args, **kwargs):
method get_login_redirect_url (line 271) | def get_login_redirect_url(self):
method dispatch (line 275) | def dispatch(self, request, *args, **kwargs):
method get_queryset (line 302) | def get_queryset(self):
method get_context_data (line 321) | def get_context_data(self, **kwargs):
method mark_read (line 356) | def mark_read(self):
method get_topic (line 386) | def get_topic(self, **kwargs):
class PostEditMixin (line 402) | class PostEditMixin(PybbFormsMixin):
method post (line 405) | def post(self, request, *args, **kwargs):
method get_form_class (line 408) | def get_form_class(self):
method get_context_data (line 415) | def get_context_data(self, **kwargs):
method form_valid (line 431) | def form_valid(self, form):
class AddPostView (line 489) | class AddPostView(PostEditMixin, generic.CreateView):
method dispatch (line 494) | def dispatch(self, request, *args, **kwargs):
method get_form_kwargs (line 532) | def get_form_kwargs(self):
method get_context_data (line 546) | def get_context_data(self, **kwargs):
method get_success_url (line 552) | def get_success_url(self):
class EditPostView (line 558) | class EditPostView(PostEditMixin, generic.UpdateView):
method dispatch (line 567) | def dispatch(self, request, *args, **kwargs):
method get_form_kwargs (line 570) | def get_form_kwargs(self):
method get_object (line 575) | def get_object(self, queryset=None):
class MovePostView (line 582) | class MovePostView(RedirectToLoginMixin, generic.UpdateView):
method dispatch (line 591) | def dispatch(self, request, *args, **kwargs):
method get_form_kwargs (line 594) | def get_form_kwargs(self):
method get_object (line 599) | def get_object(self, queryset=None):
method form_valid (line 605) | def form_valid(self, *args, **kwargs):
method get_success_url (line 615) | def get_success_url(self):
class UserView (line 619) | class UserView(generic.DetailView):
method get_object (line 624) | def get_object(self, queryset=None):
method get_context_data (line 629) | def get_context_data(self, **kwargs):
class UserPosts (line 635) | class UserPosts(PaginatorMixin, generic.ListView):
method dispatch (line 640) | def dispatch(self, request, *args, **kwargs):
method get_queryset (line 645) | def get_queryset(self):
method get_context_data (line 652) | def get_context_data(self, **kwargs):
class UserTopics (line 658) | class UserTopics(PaginatorMixin, generic.ListView):
method dispatch (line 663) | def dispatch(self, request, *args, **kwargs):
method get_queryset (line 668) | def get_queryset(self):
method get_context_data (line 675) | def get_context_data(self, **kwargs):
class PostView (line 681) | class PostView(RedirectToLoginMixin, generic.RedirectView):
method dispatch (line 685) | def dispatch(self, request, *args, **kwargs):
method get_login_redirect_url (line 689) | def get_login_redirect_url(self):
method get_redirect_url (line 692) | def get_redirect_url(self, **kwargs):
method get_post (line 699) | def get_post(self, **kwargs):
class ModeratePost (line 703) | class ModeratePost(generic.RedirectView):
method get_redirect_url (line 707) | def get_redirect_url(self, **kwargs):
class ProfileEditView (line 716) | class ProfileEditView(generic.UpdateView):
method get_object (line 720) | def get_object(self, queryset=None):
method get_form_class (line 723) | def get_form_class(self):
method dispatch (line 732) | def dispatch(self, request, *args, **kwargs):
method get_success_url (line 735) | def get_success_url(self):
class DeletePostView (line 739) | class DeletePostView(generic.DeleteView):
method get_object (line 744) | def get_object(self, queryset=None):
method form_valid (line 752) | def form_valid(self, form):
method get_success_url (line 763) | def get_success_url(self):
class TopicActionBaseView (line 775) | class TopicActionBaseView(generic.View):
method get_topic (line 777) | def get_topic(self):
method get (line 781) | def get(self, *args, **kwargs):
class StickTopicView (line 787) | class StickTopicView(TopicActionBaseView):
method action (line 789) | def action(self, topic):
class UnstickTopicView (line 796) | class UnstickTopicView(TopicActionBaseView):
method action (line 798) | def action(self, topic):
class CloseTopicView (line 805) | class CloseTopicView(TopicActionBaseView):
method action (line 807) | def action(self, topic):
class OpenTopicView (line 814) | class OpenTopicView(TopicActionBaseView):
method action (line 815) | def action(self, topic):
class TopicPollVoteView (line 822) | class TopicPollVoteView(PybbFormsMixin, generic.UpdateView):
method dispatch (line 827) | def dispatch(self, request, *args, **kwargs):
method get_form_class (line 830) | def get_form_class(self):
method get_form_kwargs (line 833) | def get_form_kwargs(self):
method form_valid (line 838) | def form_valid(self, form):
method form_invalid (line 853) | def form_invalid(self, form):
method get_success_url (line 856) | def get_success_url(self):
function topic_cancel_poll_vote (line 861) | def topic_cancel_poll_vote(request, pk):
function delete_subscription (line 868) | def delete_subscription(request, topic_id):
function add_subscription (line 877) | def add_subscription(request, topic_id):
function post_ajax_preview (line 888) | def post_ajax_preview(request):
function mark_all_as_read (line 895) | def mark_all_as_read(request):
function block_user (line 907) | def block_user(request, username):
function unblock_user (line 938) | def unblock_user(request, username):
class UserEditPrivilegesView (line 949) | class UserEditPrivilegesView(generic.edit.FormMixin, generic.edit.Proces...
method get_success_url (line 957) | def get_success_url(self):
method get_initial (line 960) | def get_initial(self):
method get_form_kwargs (line 967) | def get_form_kwargs(self):
method get (line 972) | def get(self, request, *args, **kwargs):
method post (line 976) | def post(self, request, *args, **kwargs):
method form_valid (line 980) | def form_valid(self, form):
FILE: runtests.py
function runtests (line 15) | def runtests(*test_args, **kwargs):
FILE: test/example_bootstrap/static/csrf.js
function getCookie (line 2) | function getCookie(name) {
FILE: test/example_thirdparty/example_thirdparty/forms.py
class SignupFormWithCaptcha (line 5) | class SignupFormWithCaptcha(SignupForm):
FILE: test/test_project/test_app/apps.py
class TestApp (line 5) | class TestApp(AppConfig):
FILE: test/test_project/test_app/migrations/0001_initial.py
class Migration (line 9) | class Migration(migrations.Migration):
FILE: test/test_project/test_app/models.py
class CustomUserManager (line 11) | class CustomUserManager(BaseUserManager):
method create_user (line 12) | def create_user(self, username, email=None, password=None, **extra_fie...
class CustomUser (line 23) | class CustomUser(AbstractBaseUser, PermissionsMixin):
class Meta (line 34) | class Meta:
class CustomProfile (line 38) | class CustomProfile(PybbProfile):
class Meta (line 47) | class Meta(object):
method get_absolute_url (line 51) | def get_absolute_url(self):
method get_display_name (line 54) | def get_display_name(self):
FILE: test/test_project/test_project/markup_parsers.py
class CustomBBCodeParser (line 6) | class CustomBBCodeParser(BBCodeParser):
method __init__ (line 7) | def __init__(self):
class LiberatorParser (line 20) | class LiberatorParser(BaseParser):
method format (line 28) | def format(self, text):
method quote (line 33) | def quote(self, text, username=''):
Condensed preview — 256 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,318K chars).
[
{
"path": ".coveragerc",
"chars": 98,
"preview": "[run]\nsource = pybb\n\n[report]\nexclude_lines =\n pragma: no cover\n raise ImproperlyConfigured\n"
},
{
"path": ".gitignore",
"chars": 224,
"preview": ".idea\n*.pyc\nlocal_path.py\nsettings_local.py\ndist\n*.egg-info\ntestdb.sqlite\ntest/example/media/pybb_upload\ndocs/_build/\nen"
},
{
"path": ".hgignore",
"chars": 97,
"preview": "syntax: glob\n# Global\n*.pyc\n*.swp\n*.swo\n\n# Distutils\npybb.egg-info/\ndist/\n\n# Sphinx\ndocs/_build/\n"
},
{
"path": ".travis.yml",
"chars": 1519,
"preview": "language: python\npython:\n - \"2.7\"\n - \"3.4\"\n - \"3.5\"\nenv:\n - DJANGO=\"Django>=1.8,<1.9\" DB=sqlite\n - DJANGO=\"Django>="
},
{
"path": "AUTHORS",
"chars": 401,
"preview": "Pavel Zhukov <gelios@gmail.com>\nGrigory Petukhov\nNikolai Sevostjanov <nikolai.sevostjanov@gmail.com>\nDenis Burij <denger"
},
{
"path": "CHANGELOG",
"chars": 10156,
"preview": "1.0.0\n * PyBBM is now compatible with Django 3.2 (older versions not supported anymore)\n * PyBBM is now compatible"
},
{
"path": "LICENSE",
"chars": 1465,
"preview": "Copyright (c) 2014-today, Maksim Iakovlev, Pavel Zhukov\nCopyright (c) 2012-2014, Sergey Fursov, Pavel Zhukov\nCopyright ("
},
{
"path": "MANIFEST.in",
"chars": 118,
"preview": "recursive-include pybb/static *\nrecursive-include pybb/templates *\nrecursive-include pybb/locale *\ninclude README.rst\n"
},
{
"path": "README.rst",
"chars": 1715,
"preview": "PyBBM - Django forum solution\n=============================\n\n.. |travis| image:: https://travis-ci.org/hovel/pybbm.png?b"
},
{
"path": "docs/Makefile",
"chars": 4587,
"preview": "# Makefile for Sphinx documentation\n# \n\n# You can set these variables from the command line.\nSPHINXOPTS =\nSPHINXBUILD"
},
{
"path": "docs/anonymous.rst",
"chars": 1024,
"preview": "Anonymous posting\n=================\n\nPyBBM allow you to enable anonymous posting on forum.\n\nBe very carefull by enabling"
},
{
"path": "docs/conf.py",
"chars": 6933,
"preview": "#\n# PyBBM documentation build configuration file, created by\n# sphinx-quickstart on Mon Aug 22 16:28:25 2011.\n#\n# This f"
},
{
"path": "docs/contributing.rst",
"chars": 1109,
"preview": "Contributing\n============\n\nDevelopment happens on github, with main repo: https://github.com/hovel/pybbm\n\nIssues, forks,"
},
{
"path": "docs/customuser.rst",
"chars": 2246,
"preview": "How to integrate custom user model in pybbm forum\n=================================================\n\n`Custom user model "
},
{
"path": "docs/example.rst",
"chars": 1043,
"preview": "Example projects\n================\n\nThe PyBBM source code contains two example projects under the ``test/example_bootstra"
},
{
"path": "docs/filters.rst",
"chars": 278,
"preview": "Filtering spam, urls and other 'bad' stuff\n==========================================\n\nPyBBM contains two settings :ref:"
},
{
"path": "docs/index.rst",
"chars": 1114,
"preview": "PyBBM - Django forum solution\n=============================\n\nPyBBM is a complete Django forum solution with the followin"
},
{
"path": "docs/install.rst",
"chars": 4163,
"preview": "Installation\n============\n\nMandatory dependencies\n----------------------\n\nPyBBM requires the following packages:\n\n* djan"
},
{
"path": "docs/javascript.rst",
"chars": 1063,
"preview": "Javascript functionality\n========================\n\nPybb does not depend on any javascript code. But javascript can provi"
},
{
"path": "docs/make.bat",
"chars": 4509,
"preview": "@ECHO OFF\n\nREM Command file for Sphinx documentation\n\nif \"%SPHINXBUILD%\" == \"\" (\n\tset SPHINXBUILD=sphinx-build\n)\nset BUI"
},
{
"path": "docs/markup.rst",
"chars": 3289,
"preview": "Markup\n======\n\nHow it works\n------------\n\nEvery time user save new post, message parsed by markup parser to it's html re"
},
{
"path": "docs/notifications.rst",
"chars": 1131,
"preview": "Notifications\n=============\n\nConfigure notifications\n-----------------------\n\nSee those settings:\n* :ref:`PYBB_DISABLE_S"
},
{
"path": "docs/originalpybb.rst",
"chars": 1179,
"preview": "PyBB Modified (PyBBM) and original PyBB\n=======================================\n\nPyBB originally developed by lorien in "
},
{
"path": "docs/permissions.rst",
"chars": 21904,
"preview": "Permissions\n===========\n\nPybb allow you to manage permissions by overwriting a Permission handler.\nSee ``PYBB_PERMISSION"
},
{
"path": "docs/premoderation.rst",
"chars": 774,
"preview": "Pre-moderation\n==============\n\nPyBBM shipped with fully customizable pre-moderation system.\n\nBecause in different circum"
},
{
"path": "docs/problems.rst",
"chars": 426,
"preview": "Known problems\n==============\n\nUsing with a database that doest not support microseconds\n-------------------------------"
},
{
"path": "docs/pybbmigrate.rst",
"chars": 335,
"preview": "Migrating from pybb (lorien package)\n====================================\n\nPyBBM was drop-in replacement for pybb in 201"
},
{
"path": "docs/settings.rst",
"chars": 12101,
"preview": "Settings\n========\n\nBasic settings\n--------------\n\n.. _PYBB_TOPIC_PAGE_SIZE:\n\nPYBB_TOPIC_PAGE_SIZE\n....................\n\n"
},
{
"path": "docs/templatetags.rst",
"chars": 1189,
"preview": "Useful template tags and filters\n================================\n\nNext filters and tags can be used when `pybb_tags` lo"
},
{
"path": "docs/testing.rst",
"chars": 3098,
"preview": "Testing\n=======\n\nPyBBM has good unittest coverage. There is two way to test pybbm: a \"multi-env way\" via tox\n(multiple v"
},
{
"path": "docs/updates.rst",
"chars": 10709,
"preview": "PyBBM Changelog\n===============\n\n0.18.4 -> 0.19.0\n----------------\n* PyBBM is now compatible with Django 1.8, 1.11, 2.0\n"
},
{
"path": "pybb/__init__.py",
"chars": 44,
"preview": "default_app_config = 'pybb.apps.PybbConfig'\n"
},
{
"path": "pybb/admin.py",
"chars": 5267,
"preview": "# -*- coding: utf-8\nfrom copy import deepcopy\nfrom django.utils.translation import gettext_lazy as _\nfrom django.contrib"
},
{
"path": "pybb/apps.py",
"chars": 316,
"preview": "from django.apps import AppConfig\nfrom django.utils.translation import gettext_lazy as _\n\n\nclass PybbConfig(AppConfig):\n"
},
{
"path": "pybb/compat.py",
"chars": 3677,
"preview": "import django\nfrom django.conf import settings\nfrom django.utils.encoding import force_str\nfrom django.utils.text import"
},
{
"path": "pybb/context_processors.py",
"chars": 674,
"preview": "\nfrom pybb import defaults\n\n__author__ = 'zeus'\n\n\ndef processor(request):\n context = {}\n for i in (\n 'PYBB_"
},
{
"path": "pybb/defaults.py",
"chars": 8263,
"preview": "import os.path\nimport warnings\nfrom django.conf import settings\nfrom django.core.exceptions import ImproperlyConfigured\n"
},
{
"path": "pybb/feeds.py",
"chars": 1490,
"preview": "\nfrom django.contrib.syndication.views import Feed\nfrom django.urls import reverse\nfrom django.utils.feedgenerator impor"
},
{
"path": "pybb/forms.py",
"chars": 20281,
"preview": "\nimport re\nimport inspect\n\nimport django\nfrom django import forms\nfrom django.core.exceptions import FieldError, Permiss"
},
{
"path": "pybb/locale/de/LC_MESSAGES/django.po",
"chars": 23683,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER\n# This file is distributed under the same "
},
{
"path": "pybb/locale/es/LC_MESSAGES/django.po",
"chars": 22978,
"preview": "# Spanish translation for the pybbm form.\n# Copyright (C) 2013 Jose Antonio Martin\n# This file is distributed under the "
},
{
"path": "pybb/locale/fr/LC_MESSAGES/django.po",
"chars": 23759,
"preview": "# SOME DESCRIPTIVE TITLE. \n# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER\n# This file is distributed under the same"
},
{
"path": "pybb/locale/he/LC_MESSAGES/django.po",
"chars": 25107,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER\n# This file is distributed under the same "
},
{
"path": "pybb/locale/it/LC_MESSAGES/django.po",
"chars": 23245,
"preview": "# Italian translation for the pybbm form.\n# Copyright (C) 2014 Andrea Magatti\n# This file is distributed under the same "
},
{
"path": "pybb/locale/ja/LC_MESSAGES/django.po",
"chars": 21620,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER\n# This file is distributed under the same "
},
{
"path": "pybb/locale/pl/LC_MESSAGES/django.po",
"chars": 23924,
"preview": "# Russian translation for pybbm forum\n# Copyright (C) 2012 Adrian Gruntkowski\n# This file is distributed under the same "
},
{
"path": "pybb/locale/pt_BR/LC_MESSAGES/django.po",
"chars": 25011,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER\n# This file is distributed under the same "
},
{
"path": "pybb/locale/ru/LC_MESSAGES/django.po",
"chars": 24769,
"preview": "# Russian translation for pybbm forum\n# Copyright (C) 2011 Zhukov Pavel\n# This file is distributed under the same licens"
},
{
"path": "pybb/locale/sk/LC_MESSAGES/django.po",
"chars": 26047,
"preview": "# Russian translation for pybb forum\n# Copyright (C) 2008 Grigoriy Petukhov\n# This file is distributed under the same li"
},
{
"path": "pybb/locale/sv/LC_MESSAGES/django.po",
"chars": 23040,
"preview": "# Swedish messages for Django pybbm app.\n# Copyright © 2016, 2017 Göran Uddeborg\n# This file is distributed under the sa"
},
{
"path": "pybb/locale/uk/LC_MESSAGES/django.po",
"chars": 26633,
"preview": "# Ukrainian translation for pybb forum\n# Copyright (C) 2009 Mykola Zamkovoi\n# This file is distributed under the same li"
},
{
"path": "pybb/locale/zh/LC_MESSAGES/django.po",
"chars": 20745,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER\n# This file is distributed under the same "
},
{
"path": "pybb/management/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "pybb/management/commands/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "pybb/management/commands/dump_topics.py",
"chars": 576,
"preview": "#!/usr/bin/env python\n# vim:fileencoding=utf-8\n__author__ = 'zeus'\n\nfrom django.core.management.base import BaseCommand\n"
},
{
"path": "pybb/management/commands/migrate_profile.py",
"chars": 1482,
"preview": "#!/usr/bin/env python\n# vim:fileencoding=utf-8\n\n__author__ = 'zeus'\n\nfrom django.core.management.base import BaseCommand"
},
{
"path": "pybb/management/commands/pybb_delete_invalid_topics.py",
"chars": 871,
"preview": "from django.utils.timezone import now, timedelta\nfrom django.core.management.base import BaseCommand, CommandError\nfrom "
},
{
"path": "pybb/management/commands/pybb_update_counters.py",
"chars": 606,
"preview": "#!/usr/bin/env python\n# vim:fileencoding=utf-8\n\n__author__ = 'zeus'\n\nfrom django.core.management.base import BaseCommand"
},
{
"path": "pybb/management/commands/supermoderator.py",
"chars": 722,
"preview": "\nfrom django.core.management.base import BaseCommand, CommandError\nfrom pybb import compat\n\nfrom pybb.models import Foru"
},
{
"path": "pybb/markup/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "pybb/markup/base.py",
"chars": 2407,
"preview": "\nimport re\nfrom django.conf import settings\nfrom django.utils.html import escape\nfrom pybb.defaults import PYBB_SMILES, "
},
{
"path": "pybb/markup/bbcode.py",
"chars": 2094,
"preview": "from __future__ import unicode_literals, absolute_import\n\nfrom bbcode import Parser\nfrom django.forms import Textarea\nfr"
},
{
"path": "pybb/markup/markdown.py",
"chars": 1361,
"preview": "from __future__ import unicode_literals, absolute_import\n\nfrom markdown import Markdown\nfrom django.forms import Textare"
},
{
"path": "pybb/middleware.py",
"chars": 1514,
"preview": "\n\nimport django\nfrom django.utils import translation\nfrom django.db.models import ObjectDoesNotExist\nfrom pybb import ut"
},
{
"path": "pybb/migrations/0001_initial.py",
"chars": 15324,
"preview": "\nfrom django.db import models, migrations\nfrom django.conf import settings\nfrom pybb.compat import get_image_field_class"
},
{
"path": "pybb/migrations/0002_slugs_optional.py",
"chars": 720,
"preview": "\nfrom django.db import models, migrations\n\n\nclass Migration(migrations.Migration):\n\n dependencies = [\n ('pybb'"
},
{
"path": "pybb/migrations/0003_slugs_fill.py",
"chars": 1301,
"preview": "\nfrom django.db import models, migrations\nfrom pybb.models import create_or_check_slug\n\n\ndef fill_slugs(apps, schema_edi"
},
{
"path": "pybb/migrations/0004_slugs_required.py",
"chars": 971,
"preview": "\nfrom django.db import models, migrations\n\n\nclass Migration(migrations.Migration):\n\n dependencies = [\n ('pybb'"
},
{
"path": "pybb/migrations/0005_auto_20151108_1528.py",
"chars": 1950,
"preview": "# Generated by Django 1.9b1 on 2015-11-08 23:28\n\nfrom django.conf import settings\nfrom django.db import migrations, mode"
},
{
"path": "pybb/migrations/0006_forum_subscriptions.py",
"chars": 1810,
"preview": "\nimport django\nfrom django.db import models, migrations\nfrom django.conf import settings\n\n\nclass Migration(migrations.Mi"
},
{
"path": "pybb/migrations/0007_auto_20170111_1504.py",
"chars": 770,
"preview": "\nfrom django.db import migrations, models\n\n\nclass Migration(migrations.Migration):\n\n dependencies = [\n ('pybb'"
},
{
"path": "pybb/migrations/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "pybb/models.py",
"chars": 20540,
"preview": "\nfrom django.core.exceptions import ValidationError\nfrom django.urls import reverse\nfrom django.db import models, transa"
},
{
"path": "pybb/permissions.py",
"chars": 12051,
"preview": "\"\"\"\nExtensible permission system for pybbm\n\"\"\"\n\nfrom django.db.models import Q\n\nfrom pybb import defaults, util\n\n\nclass "
},
{
"path": "pybb/profiles.py",
"chars": 3095,
"preview": "from django.conf import settings\nfrom django.db import models\nfrom django.utils.encoding import force_str\nfrom django.ut"
},
{
"path": "pybb/signals.py",
"chars": 3760,
"preview": "from django.contrib.auth.models import Permission\nfrom django.contrib.contenttypes.models import ContentType\nfrom django"
},
{
"path": "pybb/static/markitup/ajax_csrf.js",
"chars": 1018,
"preview": "// https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/#ajax\nfunction getCookie(name) {\n var cookieValue = null;\n "
},
{
"path": "pybb/static/markitup/jquery.markitup.js",
"chars": 20472,
"preview": "// ----------------------------------------------------------------------------\n// markItUp! Universal MarkUp Engine, JQ"
},
{
"path": "pybb/static/markitup/preview.css",
"chars": 113,
"preview": "/* preview style examples */\nbody {\n\tbackground-color:#EFEFEF;\n\tfont:70% Verdana, Arial, Helvetica, sans-serif;\n}"
},
{
"path": "pybb/static/markitup/sets/bbcode/readme.txt",
"chars": 336,
"preview": "Markup language: \nBBCode\n\nDescription:\nA basic BBCode markup set with Bold, Italic, Underline, Picture, Link, Size, List"
},
{
"path": "pybb/static/markitup/sets/bbcode/set.js",
"chars": 1989,
"preview": "// ----------------------------------------------------------------------------\n// markItUp!\n// ------------------------"
},
{
"path": "pybb/static/markitup/sets/bbcode/style.css",
"chars": 1268,
"preview": "/* -------------------------------------------------------------------\n// markItUp!\n// By Jay Salvat - http://markitup.j"
},
{
"path": "pybb/static/markitup/sets/default/set.js",
"chars": 1572,
"preview": "// ----------------------------------------------------------------------------\n// markItUp!\n// ------------------------"
},
{
"path": "pybb/static/markitup/sets/default/style.css",
"chars": 722,
"preview": "/* -------------------------------------------------------------------\n// markItUp!\n// By Jay Salvat - http://markitup.j"
},
{
"path": "pybb/static/markitup/sets/markdown/readme.txt",
"chars": 319,
"preview": "Markup language: \nMarkdown\n\nDescription:\nA basic Markdown markup set with Headings, Bold, Italic, Picture, Link, List, Q"
},
{
"path": "pybb/static/markitup/sets/markdown/set.js",
"chars": 2527,
"preview": "// -------------------------------------------------------------------\n// markItUp!\n// ---------------------------------"
},
{
"path": "pybb/static/markitup/sets/markdown/style.css",
"chars": 1322,
"preview": "/* -------------------------------------------------------------------\n// markItUp!\n// By Jay Salvat - http://markitup.j"
},
{
"path": "pybb/static/markitup/skins/markitup/style.css",
"chars": 3337,
"preview": "/* -------------------------------------------------------------------\n// markItUp! Universal MarkUp Engine, JQuery plug"
},
{
"path": "pybb/static/markitup/skins/simple/style.css",
"chars": 2475,
"preview": "/* -------------------------------------------------------------------\n// markItUp! Universal MarkUp Engine, JQuery plug"
},
{
"path": "pybb/static/markitup/templates/preview.css",
"chars": 113,
"preview": "/* preview style examples */\nbody {\n\tbackground-color:#EFEFEF;\n\tfont:70% Verdana, Arial, Helvetica, sans-serif;\n}"
},
{
"path": "pybb/static/markitup/templates/preview.html",
"chars": 406,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\""
},
{
"path": "pybb/static/pybb/forum.less",
"chars": 483,
"preview": "/* --- Topic/Forum table --- */\n.forum-description {\n margin: 5px;\n font-size: @baseFontSize - 2;\n}\n\n.forum-row, ."
},
{
"path": "pybb/static/pybb/forum3.less",
"chars": 486,
"preview": "/* --- Topic/Forum table --- */\n.forum-description {\n margin: 5px;\n font-size: @font-size-base - 2;\n}\n\n.forum-row,"
},
{
"path": "pybb/static/pybb/js/markitup.js",
"chars": 398,
"preview": "$(function() {\n if(window.pybb && window.pybb.get_markitup_settings){\n var mySettings = window.pybb.get_markit"
},
{
"path": "pybb/static/pybb/js/pybbjs.js",
"chars": 8077,
"preview": "function pybb_delete_post(url, post_id, confirm_text) {\n if (!confirm(confirm_text))\n return false;\n $.ajax"
},
{
"path": "pybb/static/pybb/posts.less",
"chars": 812,
"preview": ".posts {\n}\n\n.post {\n margin: 3px 0 5px 0;\n}\n\n.post-header {\n padding: 3px 0 3px 20px;\n font-size: @baseFontSize -"
},
{
"path": "pybb/static/pybb/posts3.less",
"chars": 815,
"preview": ".posts {\n}\n\n.post {\n margin: 3px 0 5px 0;\n}\n\n.post-header {\n padding: 3px 0 3px 20px;\n font-size: @font-size-base"
},
{
"path": "pybb/static/pybb/visual.less",
"chars": 668,
"preview": ".forum-headline {\n margin-top: 10px;\n}\n\n.attachments-form {\n padding-bottom: 15px;\n}\n\n.attachment-link {\n borde"
},
{
"path": "pybb/static/pybb/visual3.less",
"chars": 688,
"preview": ".forum-headline {\n margin-top: 10px;\n}\n\n.attachments-form {\n padding-bottom: 15px;\n}\n\n.attachment-link {\n borde"
},
{
"path": "pybb/subscription.py",
"chars": 3646,
"preview": "\nfrom django.conf import settings\nfrom django.urls import reverse\nfrom django.core.validators import validate_email\nfrom"
},
{
"path": "pybb/templates/pybb/_button_forum_subscription.html",
"chars": 219,
"preview": "{% load i18n %}<a href=\"{% url 'pybb:forum_subscription' pk=forum.id %}\" class=\"forum-subscription btn btn-primary\">{% i"
},
{
"path": "pybb/templates/pybb/_button_new_topic.html",
"chars": 123,
"preview": "{% load i18n %}<a href=\"{% url 'pybb:add_topic' forum.id %}\" class=\"new-topic btn btn-primary\">{% trans 'New topic' %}</"
},
{
"path": "pybb/templates/pybb/_button_save.html",
"chars": 89,
"preview": "{% load i18n %}<input type=\"submit\" class=\"btn btn-primary\" value=\"{% trans 'Save' %}\" />"
},
{
"path": "pybb/templates/pybb/_button_submit.html",
"chars": 149,
"preview": "{% load i18n %}<input type=\"submit\" class=\"btn btn-primary\" value=\"{% if submit_text %}{{ submit_text }}{% else %}{% tra"
},
{
"path": "pybb/templates/pybb/_easy_thumbnail_avatar.html",
"chars": 201,
"preview": "{% load thumbnail %}\n{% thumbnail user_profile.avatar|default:PYBB_DEFAULT_AVATAR_URL PYBB_AVATAR_DIMENSIONS as avatar %"
},
{
"path": "pybb/templates/pybb/_markitup.html",
"chars": 3018,
"preview": "{% load i18n %}\n\n{% comment %}\nTODO : delete this template in the next major release\nThis template will not exist anymor"
},
{
"path": "pybb/templates/pybb/_markitup_preview.html",
"chars": 776,
"preview": "<html>\n<head>\n <style type=\"text/css\">\n blockquote {\n padding: 0 0 0 15px;\n margin: 0 0 20px"
},
{
"path": "pybb/templates/pybb/_need_to_login_message.html",
"chars": 218,
"preview": "{% load i18n %}\n<a href=\"{% url 'registration_register' %}\">{% trans 'Register' %}</a> {% trans 'or' %} <a href=\"{% url "
},
{
"path": "pybb/templates/pybb/_select_radio.html",
"chars": 770,
"preview": "<div class=\"form-group\">\n {% if field.auto_id %}\n <label class=\"control-label {% if field.field.required %}{{ "
},
{
"path": "pybb/templates/pybb/_sorl_thumbnail_avatar.html",
"chars": 192,
"preview": "{% load thumbnail %}\n{% thumbnail user_profile.avatar PYBB_AVATAR_DIMENSIONS as avatar %}\n <img src=\"{{ avatar.url }}"
},
{
"path": "pybb/templates/pybb/add_post.html",
"chars": 964,
"preview": "{% extends 'pybb/base.html' %}\n{% load i18n pybb_tags static %}\n\n{% block title %}\n{% if forum %}{% trans 'New topic' %}"
},
{
"path": "pybb/templates/pybb/attachments_formset.html",
"chars": 1925,
"preview": "{% load pybb_tags static %}\n\n{% if request.user|pybb_may_attach_files %}\n {% load i18n %}\n <div class=\"attachments"
},
{
"path": "pybb/templates/pybb/avatar.html",
"chars": 850,
"preview": "{% load pybb_tags %}\n<div class=\"avatar\">\n {% pybb_get_profile user=user as user_profile %}\n <a href=\"{{ user_prof"
},
{
"path": "pybb/templates/pybb/base.html",
"chars": 614,
"preview": "{% extends PYBB_TEMPLATE|default:\"base.html\" %}\n\n{% load i18n pybb_tags %}\n\n{% block title %}{{ PYBB_DEFAULT_TITLE }}{% "
},
{
"path": "pybb/templates/pybb/breadcrumb.html",
"chars": 713,
"preview": "{% load i18n pybb_tags %}\n<ul class=\"breadcrumb\">\n {% include \"pybb/breadcrumb_top_extra_crumb.html\" %}\n <li><a hr"
},
{
"path": "pybb/templates/pybb/breadcrumb_top_extra_crumb.html",
"chars": 0,
"preview": ""
},
{
"path": "pybb/templates/pybb/category.html",
"chars": 264,
"preview": "{% load i18n pybb_tags %}\n\n<div class=\"category\">\n <h1>{{ category.name }} {% if category.hidden %}[{% trans 'Hidden'"
},
{
"path": "pybb/templates/pybb/delete_post.html",
"chars": 548,
"preview": "{% extends 'pybb/base.html' %}\n{% load i18n pybb_tags %}\n\n{% block content %}\n <h1>{% trans 'Are you sure you want to"
},
{
"path": "pybb/templates/pybb/edit_post.html",
"chars": 671,
"preview": "{% extends 'pybb/base.html' %}\n{% load pybb_tags i18n static %}\n\n{% block title %}{% trans 'Editing the post' %}{% endbl"
},
{
"path": "pybb/templates/pybb/edit_privileges.html",
"chars": 1475,
"preview": "{% extends 'pybb/base.html' %}\n\n{% load i18n pybb_tags %}\n\n{% block title %}{% trans 'Grant moderator privileges' %}{% e"
},
{
"path": "pybb/templates/pybb/edit_profile.html",
"chars": 961,
"preview": "{% extends 'pybb/base.html' %}\n\n{% load i18n pybb_tags %}\n\n{% block title %}{% trans 'Profile editing' %}{% endblock tit"
},
{
"path": "pybb/templates/pybb/feeds/posts_description.html",
"chars": 25,
"preview": "{{ obj.body_html|safe }}\n"
},
{
"path": "pybb/templates/pybb/feeds/posts_title.html",
"chars": 151,
"preview": "{% load pybb_tags %}\n{% pybb_get_profile user=obj.user as profile %}\n{{ profile.get_display_name }}: {{ obj.topic.name }"
},
{
"path": "pybb/templates/pybb/feeds/topics_description.html",
"chars": 30,
"preview": "{{ obj.head.body_html|safe }}\n"
},
{
"path": "pybb/templates/pybb/feeds/topics_title.html",
"chars": 132,
"preview": "{% load pybb_tags %}\n{% pybb_get_profile user=obj.head.user as profile %}\n{{ profile.user }}: {{ obj.name }} @ {{ obj.fo"
},
{
"path": "pybb/templates/pybb/form.html",
"chars": 395,
"preview": "{% load pybb_tags %}\n{% csrf_token %}\n\n{% include \"pybb/form_errors.html\" %}\n\n{% for field in form.visible_fields %}\n "
},
{
"path": "pybb/templates/pybb/form_errors.html",
"chars": 147,
"preview": "{% if form.non_field_errors %}\n {{ form.non_field_errors }}\n{% endif %}\n{% if form.non_form_errors %}\n {{ form.non"
},
{
"path": "pybb/templates/pybb/form_field.html",
"chars": 474,
"preview": "{% load pybb_tags %}\n\n<div class=\"{% if field.is_required %}required{% endif %} {% if field.errors %}error{% endif %}\">\n"
},
{
"path": "pybb/templates/pybb/forum.html",
"chars": 1033,
"preview": "{% extends 'pybb/base.html' %}\n{% load pybb_tags i18n %}\n\n{% block title %}{{ forum.name }}{% endblock title %}\n\n{% bloc"
},
{
"path": "pybb/templates/pybb/forum_last_update_info.html",
"chars": 91,
"preview": "{% load pybb_tags %}\n\n{% if forum.updated %}\n {% pybb_time forum.updated %}\n{% endif %}\n"
},
{
"path": "pybb/templates/pybb/forum_list.html",
"chars": 1890,
"preview": "{% load pybb_tags i18n %}\n\n{% if forum_list %}\n <table class=\"table {% if category %}category-table{% elif parent_for"
},
{
"path": "pybb/templates/pybb/forum_subscription.html",
"chars": 1454,
"preview": "{% extends 'pybb/base.html' %}\n{% load pybb_tags i18n %}\n\n{% block title %}{% blocktrans with forum=forum.name context '"
},
{
"path": "pybb/templates/pybb/index.html",
"chars": 893,
"preview": "{% extends 'pybb/base.html' %}\n\n{% load i18n %}\n\n{% block title %}{{ PYBB_DEFAULT_TITLE }}{% endblock title %}\n\n{% block"
},
{
"path": "pybb/templates/pybb/latest_topics.html",
"chars": 993,
"preview": "{% extends 'pybb/base.html' %}\n\n{% load pybb_tags i18n %}\n\n{% block title %}{% trans 'Last updates in topics' %}{% endbl"
},
{
"path": "pybb/templates/pybb/mail_templates/base-html.html",
"chars": 468,
"preview": "{% load i18n pybb_tags %}\n{% pybb_get_profile user=post.user as profile %}\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD XHTML 1.0 "
},
{
"path": "pybb/templates/pybb/mail_templates/base.html",
"chars": 34,
"preview": "{% block content %}{% endblock %}\n"
},
{
"path": "pybb/templates/pybb/mail_templates/forum_subscription_email_body.html",
"chars": 634,
"preview": "{% load i18n pybb_tags %}\n{% pybb_get_profile user=topic.user as profile %}\n\n{% blocktrans with username=profile.get_dis"
},
{
"path": "pybb/templates/pybb/mail_templates/forum_subscription_email_subject.html",
"chars": 70,
"preview": "{% load i18n %}\n{% trans 'New topic in forum that you subscribed.' %}\n"
},
{
"path": "pybb/templates/pybb/mail_templates/subscription_email_body-html.html",
"chars": 1018,
"preview": "{% extends PYBB_TEMPLATE_MAIL_HTML|default:\"pybb/mail_templates/base-html.html\" %}\n{% load i18n pybb_tags %}\n{% block co"
},
{
"path": "pybb/templates/pybb/mail_templates/subscription_email_body.html",
"chars": 640,
"preview": "{% extends PYBB_TEMPLATE_MAIL_TXT|default:\"pybb/mail_templates/base.html\" %}\n{% load i18n pybb_tags %}\n{% block content "
},
{
"path": "pybb/templates/pybb/mail_templates/subscription_email_subject.html",
"chars": 71,
"preview": "{% load i18n %}\n{% trans 'New answer in topic that you subscribed.' %}\n"
},
{
"path": "pybb/templates/pybb/markup/bbcode_widget.html",
"chars": 2980,
"preview": "{% load i18n %}\n\n{{ widget_output }}\n\n<script type=\"text/javascript\">\nif(!window.pybb){\n window.pybb = {};\n}\nif(!wind"
},
{
"path": "pybb/templates/pybb/markup/markdown_widget.html",
"chars": 3776,
"preview": "{% load i18n %}\n\n{{ widget_output }}\n\n\n<script type=\"text/javascript\">\nif(!window.pybb){\n window.pybb = {};\n}\nif(!win"
},
{
"path": "pybb/templates/pybb/move_post.html",
"chars": 1716,
"preview": "{% extends 'pybb/base.html' %}\n{% load i18n pybb_tags %}\n\n{% block content %}\n\n {% if post.is_topic_head %}\n <"
},
{
"path": "pybb/templates/pybb/pagination.html",
"chars": 1055,
"preview": "{% load i18n %}\n\n{% if is_paginated %}\n <div class=\"pagination\">\n <ul>\n <li class=\"prev {% if not p"
},
{
"path": "pybb/templates/pybb/poll.html",
"chars": 1695,
"preview": "{% load i18n pybb_tags %}\n\n<div class=\"poll\">\n <h2>{% trans 'Poll' %}</h2>\n <table class=\"table table-bordered poll\">\n"
},
{
"path": "pybb/templates/pybb/poll_edit_form.html",
"chars": 1359,
"preview": "{% load i18n %}\n{% include \"pybb/form_field.html\" with field=form.poll_type %}\n<div id=\"poll-question\">\n {% include \"py"
},
{
"path": "pybb/templates/pybb/post_form.html",
"chars": 1372,
"preview": "{% load i18n pybb_tags static %}\n<form class=\"post-form\" action=\"\n {% if forum %}\n {% url 'pybb:add_topic' for"
},
{
"path": "pybb/templates/pybb/post_template.html",
"chars": 4548,
"preview": "{% load i18n pybb_tags static %}\n\n{% pybb_get_profile user=post.user as post_user_profile %}\n{% pybb_get_profile user=us"
},
{
"path": "pybb/templates/pybb/topic.html",
"chars": 3940,
"preview": "{% extends 'pybb/base.html' %}\n\n{% load pybb_tags i18n static %}\n\n{% block title %}{{ topic }}{% endblock %}\n\n{% block e"
},
{
"path": "pybb/templates/pybb/topic_last_message_info.html",
"chars": 91,
"preview": "{% load pybb_tags %}\n\n{% if topic.updated %}\n {% pybb_time topic.updated %}\n{% endif %}\n"
},
{
"path": "pybb/templates/pybb/topic_list.html",
"chars": 2485,
"preview": "{% load i18n pybb_tags %}\n\n<table class=\"table topic-list\">\n <thead>\n <tr class=\"topic-row head-row\">\n "
},
{
"path": "pybb/templates/pybb/user.html",
"chars": 2360,
"preview": "{% extends 'pybb/base.html' %}\n\n{% load pybb_tags i18n %}\n\n{% block title %}\n {% pybb_get_profile target_user as targ"
},
{
"path": "pybb/templates/pybb/user_posts.html",
"chars": 965,
"preview": "{% extends 'pybb/base.html' %}\n\n{% load pybb_tags i18n %}\n\n{% block breadcrumb %}\n {% pybb_get_profile target_user as"
},
{
"path": "pybb/templates/pybb/user_topics.html",
"chars": 802,
"preview": "{% extends 'pybb/base.html' %}\n\n{% load pybb_tags i18n %}\n\n{% block breadcrumb %}\n {% pybb_get_profile target_user as"
},
{
"path": "pybb/templates/pybb/users.html",
"chars": 851,
"preview": "{% extends 'pybb/base.html' %}\n\n{# DEPRECATED AND WILL BE REMOVED IN NEXT VERSION #}\n\n{% load pybb_tags i18n %}\n\n{% bloc"
},
{
"path": "pybb/templatetags/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "pybb/templatetags/pybb_tags.py",
"chars": 9341,
"preview": "import inspect\n\nimport math\nimport time\nimport warnings\n\nimport django\nfrom django import template\nfrom django.core.cach"
},
{
"path": "pybb/tests.py",
"chars": 200157,
"preview": "\nimport datetime, time\nimport logging\nimport inspect\nimport math\nimport os\nfrom unittest import skip\nfrom django.contrib"
},
{
"path": "pybb/urls.py",
"chars": 4237,
"preview": "\n\nfrom django.urls import re_path\n\nfrom pybb.defaults import PYBB_NICE_URL\nfrom pybb.feeds import LastPosts, LastTopics\n"
},
{
"path": "pybb/util.py",
"chars": 5666,
"preview": "\nimport os\nimport warnings\nimport uuid\n\nfrom importlib import import_module\nfrom django.utils.translation import gettext"
},
{
"path": "pybb/views.py",
"chars": 38136,
"preview": "\nimport math\n\nfrom django.contrib.auth.decorators import login_required\nfrom django.core.cache import cache\nfrom django."
},
{
"path": "runtests.py",
"chars": 931,
"preview": "#!/usr/bin/env python\nimport django\nimport sys\nimport os\nfrom optparse import OptionParser\n\nproject_dir = os.path.join(o"
},
{
"path": "setup.py",
"chars": 1329,
"preview": "from setuptools import setup, find_packages\n\nsetup(\n name='pybbm',\n version='0.19.0',\n description='PyBB Modifi"
},
{
"path": "test/example_bootstrap/example_bootstrap/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "test/example_bootstrap/example_bootstrap/settings.py",
"chars": 2733,
"preview": "# Django settings for example_bootstrap project.\nimport os\n\nBASE_DIR = os.path.dirname(os.path.dirname(__file__))\n\nDEBUG"
},
{
"path": "test/example_bootstrap/example_bootstrap/urls.py",
"chars": 325,
"preview": "\nimport django\nfrom django.urls import include, re_path\nfrom django.contrib import admin\n\nurlpatterns = [\n re_path(r'"
},
{
"path": "test/example_bootstrap/example_bootstrap/wsgi.py",
"chars": 177,
"preview": "import os\nos.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"example_bootstrap.settings\")\n\nfrom django.core.wsgi import ge"
},
{
"path": "test/example_bootstrap/fixtures/demo_data.json",
"chars": 34119,
"preview": "[\n{\n \"pk\": 1, \n \"model\": \"auth.user\", \n \"fields\": {\n \"username\": \"admin\", \n \"first_name\": \"\", \n "
},
{
"path": "test/example_bootstrap/manage.py",
"chars": 260,
"preview": "#!/usr/bin/env python\nimport os\nimport sys\n\nif __name__ == \"__main__\":\n os.environ.setdefault(\"DJANGO_SETTINGS_MODULE"
},
{
"path": "test/example_bootstrap/requirements.txt",
"chars": 184,
"preview": "django>=1.8,<1.11\n\n#example_bootstrap dependencies\ndjango-registration-redux\n\n#pybb strong dependencies\ndjango-annoying\n"
},
{
"path": "test/example_bootstrap/static/bootstrap/alerts.less",
"chars": 1430,
"preview": "//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert"
},
{
"path": "test/example_bootstrap/static/bootstrap/bootstrap.less",
"chars": 1071,
"preview": "// Core variables and mixins\n@import \"variables.less\";\n@import \"mixins.less\";\n\n// Reset\n@import \"normalize.less\";\n@impor"
},
{
"path": "test/example_bootstrap/static/bootstrap/breadcrumbs.less",
"chars": 594,
"preview": "//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n padding: @breadcrumb-padding-v"
},
{
"path": "test/example_bootstrap/static/bootstrap/button-groups.less",
"chars": 5014,
"preview": "//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-gro"
},
{
"path": "test/example_bootstrap/static/bootstrap/buttons.less",
"chars": 3539,
"preview": "//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------"
},
{
"path": "test/example_bootstrap/static/bootstrap/carousel.less",
"chars": 4598,
"preview": "//\n// Carousel\n// --------------------------------------------------\n\n\n// Wrapper for the slide container and indicators"
},
{
"path": "test/example_bootstrap/static/bootstrap/close.less",
"chars": 683,
"preview": "//\n// Close icons\n// --------------------------------------------------\n\n\n.close {\n float: right;\n font-size: (@font-s"
},
{
"path": "test/example_bootstrap/static/bootstrap/code.less",
"chars": 1329,
"preview": "//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\nco"
},
{
"path": "test/example_bootstrap/static/bootstrap/component-animations.less",
"chars": 509,
"preview": "//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `."
},
{
"path": "test/example_bootstrap/static/bootstrap/dropdowns.less",
"chars": 4645,
"preview": "//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n display:"
},
{
"path": "test/example_bootstrap/static/bootstrap/forms.less",
"chars": 11022,
"preview": "//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline"
},
{
"path": "test/example_bootstrap/static/bootstrap/grid.less",
"chars": 1387,
"preview": "//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container wi"
},
{
"path": "test/example_bootstrap/static/bootstrap/mixins.less",
"chars": 26570,
"preview": "//\n// Mixins\n// --------------------------------------------------\n\n\n// Utilities\n// -------------------------\n\n// Clear"
},
{
"path": "test/example_bootstrap/static/bootstrap/modals.less",
"chars": 3404,
"preview": "//\n// Modals\n// --------------------------------------------------\n\n// .modal-open - body class for killing the scr"
},
{
"path": "test/example_bootstrap/static/bootstrap/navbar.less",
"chars": 13936,
"preview": "//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static n"
},
{
"path": "test/example_bootstrap/static/bootstrap/navs.less",
"chars": 4926,
"preview": "//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// ------------------------------------"
},
{
"path": "test/example_bootstrap/static/bootstrap/pager.less",
"chars": 857,
"preview": "//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n padding-left: 0;\n margin: @li"
},
{
"path": "test/example_bootstrap/static/bootstrap/pagination.less",
"chars": 1996,
"preview": "//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n display: inline-"
},
{
"path": "test/example_bootstrap/static/bootstrap/popovers.less",
"chars": 3360,
"preview": "//\n// Popovers\n// --------------------------------------------------\n\n\n.popover {\n position: absolute;\n top: 0;\n left"
},
{
"path": "test/example_bootstrap/static/bootstrap/progress-bars.less",
"chars": 1589,
"preview": "//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -----------------------"
},
{
"path": "test/example_bootstrap/static/bootstrap/responsive-utilities.less",
"chars": 2005,
"preview": "//\n// Responsive: Utility classes\n// --------------------------------------------------\n\n\n// IE10 in Windows (Phone) 8\n/"
},
{
"path": "test/example_bootstrap/static/bootstrap/scaffolding.less",
"chars": 2268,
"preview": "//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This r"
},
{
"path": "test/example_bootstrap/static/bootstrap/tables.less",
"chars": 4470,
"preview": "//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n max-width: 100%;\n background-color: @tab"
},
{
"path": "test/example_bootstrap/static/bootstrap/thumbnails.less",
"chars": 750,
"preview": "//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.th"
},
{
"path": "test/example_bootstrap/static/bootstrap/tooltip.less",
"chars": 2590,
"preview": "//\n// Tooltips\n// --------------------------------------------------\n\n\n// Base class\n.tooltip {\n position: absolute;\n "
},
{
"path": "test/example_bootstrap/static/bootstrap/type.less",
"chars": 5734,
"preview": "//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h"
},
{
"path": "test/example_bootstrap/static/bootstrap/utilities.less",
"chars": 780,
"preview": "//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.c"
},
{
"path": "test/example_bootstrap/static/bootstrap/variables.less",
"chars": 25388,
"preview": "//\n// Variables\n// --------------------------------------------------\n\n\n//== Colors\n//\n//## Gray and brand colors for us"
},
{
"path": "test/example_bootstrap/static/bootstrap/wells.less",
"chars": 527,
"preview": "//\n// Wells\n// --------------------------------------------------\n\n\n// Base class\n.well {\n min-height: 20px;\n padding:"
}
]
// ... and 56 more files (download for full content)
About this extraction
This page contains the full source code of the hovel/pybbm GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 256 files (1.2 MB), approximately 332.3k tokens, and a symbol index with 628 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.