-
Notifications
You must be signed in to change notification settings - Fork 4
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
Human readable choice labels #5
base: dev
Are you sure you want to change the base?
Conversation
Extended IndexableField schema to have list of human readable choice labels alongside the actual choice values. Added few tests for choice labels and brief documentation for field choices.
choices (list|tuple = None) | ||
Predefined list of possible values for the field. ValidationError will be raised if field value doesn't | ||
match any of the defined values. | ||
choice_labels (list|tuple = None) |
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.
I like the idea with human readable labels. But make it a dict then - not two list parameters. Cause I already foresee the situation when someone adds a choice somewhere in the middle of the list and forgets to add the label exactly at the same spot of another list - and WOOOHA! a month passes and no one has a clue why the data that was coming from the UI is so inappropriate.
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.
However, for the primitive cases it would also make sense to have just a list of choices that would internally be transformed from [val1, val2, val3] into {val1:val1, val2:val2, val3:val3}
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.
I see your point and actually I had thought about it myself. My concern regarding the dict is the correct ordering of the choices: how can we guarantee correct ordering of the items? For some use cases like UI automation the correct ordering of choices could be crucial.
Order of items in python dict seems to be implementation specific. I see two options to address this issue:
- choices with labels defined as list of key-value pair tuples
- choices defined as enums
In both cases choices and labels would be split to separate lists in schema output, in order to preserve correct ordering (also on client side) and especially to maintain backward compatibility.
Somehow I dislike the idea of interpreting the contents of the choice list to guess whether it should include labels or not. Enum would support ordering and also deal with duplicate values.
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.
Then again, enum name as a label may be quite limiting. These values could be extended with extra label field, but meh..
Using OrderedDict would solve ordering but allow e.g. spaces in the label.
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.
I gave your idea another thought.
Human labels just do not make sense with respect to Resource API. The choices that are mentioned in the current "choices" field must be the values that make sense for the client (including a human client).
The only scenario where you would hypothetically need both: short values and human readable title is in case if you want to "optimize bandwidth" so to say. If performance is to be kept in mind - Resource API is not an option. That has never been its design goal.
In case if you want to implement something like:
number_of_group_members = IntegerFIeld(
choices=[12, 57, 187],
choice_labels=["Small group count", "Medium group count", "Big group count"])
Please don't.
Do like:
group_type = StringField(choices=["Small", "Medium", "Big"])
And internally - i.e. in the implementation (not definition) of the individual resource do the mapping from the string values to the integers.
On the other hand, if in the example above you really need to expose both the size and a corresponding group type as human readable string - it is a clear indication that you should use a read-only Resource with a Link field.
Sth like:
class GroupType(Resource):
count_name_map = {
12: "Small",
57: "Medium",
187: "Big"
}
class Schema:
count = IntegerField(description="Number of people in a group", pk=True)
name = StringField(description="Human readable definition of a group")
def exists(self, user, pk):
return pk in self.count_name_map
def get_data(self, user, pk):
return self.count_name_map.get(pk)
def get_uris(self, user, params=None):
return self.count_name_map.keys()
def get_count(self, user, params=None):
return len(self.count_name_map)
...
# Somewhere in another resource
Links
class group_type(Link):
target = "Teacher"
one_way = True
cardinality = Link.cardinalities.ONE
master = True
Thus I do not approve this commit :)
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.
I gave your idea another thought.
Human labels just do not make sense with respect to Resource API. The choices that are mentioned in the current "choices" field must be the values that make sense for the client (including a human client).
The only scenario where you would hypothetically need both: short values and human readable title is in case if you want to "optimize bandwidth" so to say. If performance is to be kept in mind - Resource API is not an option. That has never been its design goal.
In case if you want to implement something like:
number_of_group_members = IntegerFIeld(
choices=[12, 57, 187],
choice_labels=["Small group count", "Medium group count", "Big group count"])
Please don't.
Do like:
group_type = StringField(choices=["Small", "Medium", "Big"])
And internally - i.e. in the implementation (not definition) of the individual resource do the mapping from the string values to the integers.
On the other hand, if in the example above you really need to expose both the size and a corresponding group type as human readable string - it is a clear indication that you should use a read-only Resource with a Link field.
Sth like:
class GroupType(Resource):
count_name_map = {
12: "Small",
57: "Medium",
187: "Big"
}
class Schema:
count = IntegerField(description="Number of people in a group", pk=True)
name = StringField(description="Human readable definition of a group")
def exists(self, user, pk):
return pk in self.count_name_map
def get_data(self, user, pk):
return self.count_name_map.get(pk)
def get_uris(self, user, params=None):
return self.count_name_map.keys()
def get_count(self, user, params=None):
return len(self.count_name_map)
...
# Somewhere in another resource
class Links:
class group_type(Link):
target = "GroupType"
one_way = True
cardinality = Link.cardinalities.ONE
master = True
Thus I do not approve this commit :)
Extended IndexableField schema to have list of human readable choice labels alongside
the actual choice values. Added few tests for choice labels and brief documentation
for field choices.