Merge tag 'upstream/1.4.9' into debian/master
Upstream version 1.4.9
Brian May
6 years ago
46 | 46 | |
47 | 47 | matrix: |
48 | 48 | fast_finish: true |
49 | exclude: | |
50 | - python: 2.7 | |
51 | env: DJANGO_VERSION=master DATABASE_URL=postgres://postgres@/django_guardian | |
52 | - python: 2.7 | |
53 | env: DJANGO_VERSION=master DATABASE_URL=mysql://root:@localhost/django_guardian | |
54 | - python: 2.7 | |
55 | env: DJANGO_VERSION=master DATABASE_URL=sqlite:// | |
56 | - python: 3.4 | |
57 | env: DJANGO_VERSION=master DATABASE_URL=postgres://postgres@/django_guardian | |
58 | - python: 3.4 | |
59 | env: DJANGO_VERSION=master DATABASE_URL=mysql://root:@localhost/django_guardian | |
60 | - python: 3.4 | |
61 | env: DJANGO_VERSION=master DATABASE_URL=sqlite:// | |
49 | 62 | allow_failures: |
50 | 63 | - env: DJANGO_VERSION=master DATABASE_URL=postgres://postgres@/django_guardian |
51 | 64 | - env: DJANGO_VERSION=master DATABASE_URL=mysql://root:@localhost/django_guardian |
0 | Release 1.4.9 (Jul 01, 2017) | |
1 | ============================ | |
2 | ||
3 | * Drop ``django_guardian.compat.OrderedDict`` as a consequence of drop Python 1.6 | |
4 | earlier. | |
5 | * Fix django admin 1.11 not showing selected permissions | |
6 | * Add a optional checker variable to get_obj_perms | |
7 | * Add missing classifiers in setup.py | |
8 | ||
9 | ||
0 | 10 | Release 1.4.8 (Apr 04, 2017) |
1 | 11 | ============================ |
2 | 12 |
0 | 0 | Metadata-Version: 1.1 |
1 | 1 | Name: django-guardian |
2 | Version: 1.4.8 | |
2 | Version: 1.4.9 | |
3 | 3 | Summary: Implementation of per object permissions for Django. |
4 | 4 | Home-page: http://github.com/django-guardian/django-guardian |
5 | 5 | Author: Lukasz Balcerzak |
125 | 125 | Classifier: Development Status :: 5 - Production/Stable |
126 | 126 | Classifier: Environment :: Web Environment |
127 | 127 | Classifier: Framework :: Django |
128 | Classifier: Framework :: Django :: 1.8 | |
129 | Classifier: Framework :: Django :: 1.9 | |
130 | Classifier: Framework :: Django :: 1.10 | |
131 | Classifier: Framework :: Django :: 1.11 | |
128 | 132 | Classifier: Intended Audience :: Developers |
129 | 133 | Classifier: License :: OSI Approved :: BSD License |
130 | 134 | Classifier: Operating System :: OS Independent |
0 | 0 | Metadata-Version: 1.1 |
1 | 1 | Name: django-guardian |
2 | Version: 1.4.8 | |
2 | Version: 1.4.9 | |
3 | 3 | Summary: Implementation of per object permissions for Django. |
4 | 4 | Home-page: http://github.com/django-guardian/django-guardian |
5 | 5 | Author: Lukasz Balcerzak |
125 | 125 | Classifier: Development Status :: 5 - Production/Stable |
126 | 126 | Classifier: Environment :: Web Environment |
127 | 127 | Classifier: Framework :: Django |
128 | Classifier: Framework :: Django :: 1.8 | |
129 | Classifier: Framework :: Django :: 1.9 | |
130 | Classifier: Framework :: Django :: 1.10 | |
131 | Classifier: Framework :: Django :: 1.11 | |
128 | 132 | Classifier: Intended Audience :: Developers |
129 | 133 | Classifier: License :: OSI Approved :: BSD License |
130 | 134 | Classifier: Operating System :: OS Independent |
73 | 73 | various reasons, i.e. there were no reply for over a month after our last |
74 | 74 | comment, there were no tests for the changes etc. |
75 | 75 | |
76 | ||
77 | How to do a new release? | |
78 | ---------------------------- | |
79 | ||
80 | To enroll a new relase you should perform the following task: | |
81 | ||
82 | * Ensure file ``CHANGES`` reflects all important changes. | |
83 | * Ensure file ``CHANGES`` includes a new version identifier and current release date. | |
84 | * Execute ``bumpversion patch`` (or accordinly - see `Semantic Versioning 2.0 <http://semver.org/>`_ ) to reflects changes in codebase. | |
85 | * Commit changes of codebase, e.g. ``git commit -m "Release 1.4.8" -a``. | |
86 | * Tag a new release, e.g. ``git tag "v1.4.8"``. | |
87 | * Push new tag to repo - ``git push origin --tags``. | |
88 | * Push a new release to PyPI - ``python setup.py sdist bdist_wheel upload``. |
3 | 3 | ======== |
4 | 4 | |
5 | 5 | ``django-guardian`` is an implementation of object permissions for Django_ |
6 | providing extra *authentication backend*. | |
6 | providing an extra *authentication backend*. | |
7 | 7 | |
8 | 8 | Features |
9 | 9 | -------- |
28 | 28 | Alternate projects |
29 | 29 | ------------------ |
30 | 30 | |
31 | Django_ still has *only* foundation for object permissions [1]_ and | |
32 | ``django-guardian`` make use of new facilities and it is based on them. There | |
33 | are some other pluggable applications which does *NOT* require 1.2+ | |
34 | version of Django_. For instance, there are great `django-authority`_ or | |
35 | `django-permissions`_ available out there. | |
31 | Django_ still *only* has the foundation for object permissions [1]_ and | |
32 | ``django-guardian`` makes use of new facilities and it is based on them. There | |
33 | are some other pluggable applications which do *NOT* require Django_ version 1.2+. | |
34 | For instance, `django-authority`_ or | |
35 | `django-permissions`_ are great options available. | |
36 | 36 | |
37 | 37 | .. _django: http://www.djangoproject.com/ |
38 | .. _django-authority: http://bitbucket.org/jezdez/django-authority/ | |
39 | .. _django-permissions: http://bitbucket.org/diefenbach/django-permissions/ | |
38 | .. _django-authority: https://github.com/jazzband/django-authority | |
39 | .. _django-permissions: https://github.com/lambdalisue/django-permission | |
40 | 40 | .. _issue-tracker: http://github.com/lukaszb/django-guardian |
41 | 41 | .. _grappelli: https://github.com/sehmaschine/django-grappelli |
42 | 42 |
3 | 3 | from django.conf.urls import url |
4 | 4 | from . import views |
5 | 5 | |
6 | ||
7 | app_name = 'articles' | |
6 | 8 | urlpatterns = [ |
7 | 9 | url(r'^$', views.ArticleListView.as_view(), |
8 | 10 | name="list"), |
8 | 8 | admin.autodiscover() |
9 | 9 | |
10 | 10 | urlpatterns = [ |
11 | url(r'^admin/', include(admin.site.urls)), | |
11 | url(r'^admin/', admin.site.urls), | |
12 | 12 | url(r'^logout/$', logout, {'next_page': '/'}, name='logout'), |
13 | 13 | url(r'^article/', include('articles.urls', namespace='articles')), |
14 | 14 | url(r'^', include('posts.urls')), |
6 | 6 | default_app_config = 'guardian.apps.GuardianConfig' |
7 | 7 | |
8 | 8 | # PEP 396: The __version__ attribute's value SHOULD be a string. |
9 | __version__ = '1.4.8' | |
9 | __version__ = '1.4.9' | |
10 | 10 | |
11 | 11 | # Compatibility to eg. django-rest-framework |
12 | 12 | VERSION = tuple(int(x) for x in __version__.split('.')[:3]) |
0 | 0 | from __future__ import unicode_literals |
1 | ||
2 | from collections import OrderedDict | |
3 | ||
1 | 4 | from django import forms |
2 | 5 | from django.conf import settings |
3 | 6 | from django.contrib import admin, messages |
6 | 9 | from django.template import RequestContext |
7 | 10 | from django.utils.translation import ugettext_lazy as _ |
8 | 11 | from django.utils.translation import ugettext |
9 | from guardian.compat import get_model_name, get_user_model, OrderedDict, url, reverse | |
12 | from guardian.compat import get_model_name, get_user_model, url, reverse | |
10 | 13 | from guardian.forms import GroupObjectPermissionsForm, UserObjectPermissionsForm |
11 | 14 | from guardian.models import Group |
12 | 15 | from guardian.shortcuts import (get_group_perms, get_groups_with_perms, get_perms_for_model, get_user_perms, |
0 | 0 | from __future__ import unicode_literals |
1 | # OrderedDict only available in Python 2.7. | |
2 | # This will always be the case in Django 1.7 and above, as these versions | |
3 | # no longer support Python 2.6. | |
4 | 1 | |
5 | from collections import OrderedDict | |
6 | 2 | from django.conf import settings |
7 | 3 | from django.conf.urls import handler404, handler500, include, url |
8 | 4 | from django.contrib.auth.models import AnonymousUser, Group, Permission |
30 | 30 | field = field_class( |
31 | 31 | label=self.get_obj_perms_field_label(), |
32 | 32 | choices=self.get_obj_perms_field_choices(), |
33 | initial=self.get_obj_perms_field_initial(), | |
33 | initial=list(self.get_obj_perms_field_initial()), | |
34 | 34 | widget=self.get_obj_perms_field_widget(), |
35 | 35 | required=self.are_obj_perms_required(), |
36 | 36 | ) |
18 | 18 | |
19 | 19 | class ObjectPermissionsNode(template.Node): |
20 | 20 | |
21 | def __init__(self, for_whom, obj, context_var): | |
21 | def __init__(self, for_whom, obj, context_var, checker=None): | |
22 | 22 | self.for_whom = template.Variable(for_whom) |
23 | 23 | self.obj = template.Variable(obj) |
24 | 24 | self.context_var = context_var |
25 | self.checker = template.Variable(checker) if checker else None | |
25 | 26 | |
26 | 27 | def render(self, context): |
27 | 28 | for_whom = self.for_whom.resolve(context) |
40 | 41 | obj = self.obj.resolve(context) |
41 | 42 | if not obj: |
42 | 43 | return '' |
43 | ||
44 | check = ObjectPermissionChecker(for_whom) | |
44 | ||
45 | check = self.checker.resolve(context) if self.checker else ObjectPermissionChecker(for_whom) | |
45 | 46 | perms = check.get_perms(obj) |
46 | 47 | |
47 | 48 | context[self.context_var] = perms |
82 | 83 | |
83 | 84 | """ |
84 | 85 | bits = token.split_contents() |
85 | format = '{% get_obj_perms user/group for obj as "context_var" %}' | |
86 | if len(bits) != 6 or bits[2] != 'for' or bits[4] != 'as': | |
86 | format = '{% get_obj_perms user/group for obj as "context_var" perm_checker %}' | |
87 | if not (6 <= len(bits) <= 7) or bits[2] != 'for' or bits[4] != 'as': | |
87 | 88 | raise template.TemplateSyntaxError("get_obj_perms tag should be in " |
88 | 89 | "format: %s" % format) |
89 | 90 | |
94 | 95 | raise template.TemplateSyntaxError("get_obj_perms tag's context_var " |
95 | 96 | "argument should be in quotes") |
96 | 97 | context_var = context_var[1:-1] |
97 | return ObjectPermissionsNode(for_whom, obj, context_var) | |
98 | checker = bits[6] if len(bits) == 7 else None | |
99 | return ObjectPermissionsNode(for_whom, obj, context_var, checker) |
161 | 161 | response = self.client.post(url, data, follow=True) |
162 | 162 | self.assertEqual(len(response.redirect_chain), 1) |
163 | 163 | self.assertEqual(response.redirect_chain[0][1], 302) |
164 | ||
164 | self.assertIn('selected', str(response.context['form'])) | |
165 | 165 | self.assertEqual( |
166 | 166 | set(get_perms(self.user, self.obj)), |
167 | 167 | set(perms), |
5 | 5 | from django.test import TestCase |
6 | 6 | |
7 | 7 | from guardian.compat import get_user_model, template_debug_getter, template_debug_setter |
8 | from guardian.core import ObjectPermissionChecker | |
8 | 9 | from guardian.exceptions import NotUserNorGroup |
9 | 10 | from guardian.models import UserObjectPermission, GroupObjectPermission |
10 | 11 | |
130 | 131 | output = render(template, context) |
131 | 132 | |
132 | 133 | self.assertEqual(output, 'delete_contenttype') |
134 | ||
135 | def test_checker(self): | |
136 | GroupObjectPermission.objects.assign_perm("delete_contenttype", self.group, | |
137 | self.ctype) | |
138 | ||
139 | checker = ObjectPermissionChecker(self.user) | |
140 | checker.prefetch_perms(Group.objects.all()) | |
141 | ||
142 | template = ''.join(( | |
143 | '{% load guardian_tags %}', | |
144 | '{% get_obj_perms group for contenttype as "obj_perms" checker %}', | |
145 | '{{ obj_perms|join:" " }}', | |
146 | )) | |
147 | context = {'group': self.group, 'contenttype': self.ctype, 'checker': checker} | |
148 | output = render(template, context) | |
149 | ||
150 | self.assertEqual(output, 'delete_contenttype') |
0 | 0 | [bumpversion] |
1 | current_version = 1.4.8 | |
1 | current_version = 1.4.9 | |
2 | 2 | |
3 | 3 | [build_sphinx] |
4 | 4 | source-dir = docs/ |
2 | 2 | from extras import RunFlakesCommand |
3 | 3 | |
4 | 4 | |
5 | version = '1.4.8' | |
5 | version = '1.4.9' | |
6 | 6 | |
7 | 7 | readme_file = os.path.join(os.path.dirname(__file__), 'README.rst') |
8 | 8 | with open(readme_file, 'r') as f: |
34 | 34 | classifiers=['Development Status :: 5 - Production/Stable', |
35 | 35 | 'Environment :: Web Environment', |
36 | 36 | 'Framework :: Django', |
37 | 'Framework :: Django :: 1.8', | |
38 | 'Framework :: Django :: 1.9', | |
39 | 'Framework :: Django :: 1.10', | |
40 | 'Framework :: Django :: 1.11', | |
37 | 41 | 'Intended Audience :: Developers', |
38 | 42 | 'License :: OSI Approved :: BSD License', |
39 | 43 | 'Operating System :: OS Independent', |