-
Notifications
You must be signed in to change notification settings - Fork 148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add verbose_name
for rules and permissions
#154
base: master
Are you sure you want to change the base?
Conversation
Great stuff! 👍 My only concern is we're changing the structure of the items stored in rule sets -- RuleSets used to be a map of strings to predicates, whereas now it is going to be a map of strings to dicts. This is technically a breaking change and can catch users by surprise. Maybe override Otherwise this looks like a great addition, thank you for that! |
Glad this is seen as something beneficial, and thanks for the advice/direction. I updated the code, returning the I figured following a similar approach as Django's If that sounds sensible, I'll add tests and docs this week to finish this out. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jacklinke apologies for the delayed review. Great stuff 👍
I left a few comments. There also seem to be a few lint/formatting issues highlighted by the checks -- can you please take a look at those too?
@@ -36,7 +36,10 @@ def __new__(cls, name, bases, attrs, **kwargs): | |||
new_class._meta.rules_permissions = perms | |||
new_class.preprocess_rules_permissions(perms) | |||
for perm_type, predicate in perms.items(): | |||
add_perm(new_class.get_perm(perm_type), predicate) | |||
if isinstance(predicate, dict): | |||
add_perm(new_class.get_perm(perm_type), predicate['pred'], verbose_name=predicate['verbose_name']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please rename the pred
attribute to predicate
?
return name in self and self[name].test(*args, **kwargs) | ||
|
||
def rule_exists(self, name): | ||
return name in self | ||
|
||
def add_rule(self, name, pred): | ||
def rule_verbose_name(self, name): | ||
return self["get_%s_display" % name] or name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return self["get_%s_display" % name] or name | |
return self["get_%s_display" % name] |
This must return None if no verbose name has been provided for the rule and callers can choose whether to fallback to name
.
if isfunction(pred): | ||
# If a function as passed in (as might be done with legacy django-rules) | ||
# convert the value to the dictionary form | ||
pred = {'pred': predicate(pred), 'verbose_name': verbose_name} | ||
|
||
if isinstance(pred, dict): | ||
# Check if internal pred is already a Predicate, or an basic | ||
# unwrapped function. Wrap as a Predicate if needed | ||
if not isinstance(pred['pred'], Predicate): | ||
pred['pred'] = predicate(pred['pred']) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All this can just be:
if isfunction(pred): | |
# If a function as passed in (as might be done with legacy django-rules) | |
# convert the value to the dictionary form | |
pred = {'pred': predicate(pred), 'verbose_name': verbose_name} | |
if isinstance(pred, dict): | |
# Check if internal pred is already a Predicate, or an basic | |
# unwrapped function. Wrap as a Predicate if needed | |
if not isinstance(pred['pred'], Predicate): | |
pred['pred'] = predicate(pred['pred']) | |
if isinstance(pred, dict): | |
pred['pred'] = predicate(pred['pred']) | |
else: | |
pred = {'pred': predicate(pred), 'verbose_name': None} |
Or even:
if isfunction(pred): | |
# If a function as passed in (as might be done with legacy django-rules) | |
# convert the value to the dictionary form | |
pred = {'pred': predicate(pred), 'verbose_name': verbose_name} | |
if isinstance(pred, dict): | |
# Check if internal pred is already a Predicate, or an basic | |
# unwrapped function. Wrap as a Predicate if needed | |
if not isinstance(pred['pred'], Predicate): | |
pred['pred'] = predicate(pred['pred']) | |
if not isinstance(pred, dict): | |
pred = {'pred': predicate(pred), 'verbose_name': None} |
if we assume anyone passing a dict know what they're doing.
def _check_name(_name): | ||
if (not super(RuleSet, self).__contains__(_name)): | ||
raise KeyError("Provided name '`%s`' not found" % _name) | ||
|
||
if name[0] != '_': | ||
prefix = "get_" | ||
suffix = "_display" | ||
if name.startswith(prefix) and name.endswith(suffix): | ||
_name = name[len(prefix):-len(suffix)] | ||
_check_name(_name) | ||
return super(RuleSet, self).__getitem__(_name)['verbose_name'] | ||
|
||
_check_name(name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All this can just be:
def _check_name(_name): | |
if (not super(RuleSet, self).__contains__(_name)): | |
raise KeyError("Provided name '`%s`' not found" % _name) | |
if name[0] != '_': | |
prefix = "get_" | |
suffix = "_display" | |
if name.startswith(prefix) and name.endswith(suffix): | |
_name = name[len(prefix):-len(suffix)] | |
_check_name(_name) | |
return super(RuleSet, self).__getitem__(_name)['verbose_name'] | |
_check_name(name) | |
prefix = "get_" | |
suffix = "_display" | |
if name.startswith(prefix) and name.endswith(suffix): | |
_name = name[len(prefix):-len(suffix)] | |
return super(RuleSet, self).__getitem__(_name)['verbose_name'] |
Right?
Adds
verbose_name
for rules and permissions, resolving #59.This change should be transparent to any existing users of django-rules, but adds the new capability to add and display verbose names for rules & permissions through the use of new/updated RuleSet instance methods and shortcuts for shared and permissions rule sets.
add_rule(name, predicate, verbose_name=None)
: Updated to allow optionalverbose_name
.set_rule(name, predicate, verbose_name=None)
: Updated to allow optionalverbose_name
rule_verbose_name(name)
: A new method which returns theverbose_name
if it was supplied when adding or setting the rule. Defaults toname
if noverbose_name
was supplied.permissions
)Models can now also optionally add verbose names to permissions using the following conventions:
This would be equivalent to the following calls::
Tasks:
I welcome any feedback.