category module
Classes and functions for defining categories.
Category
- class category.Category(cls, bases, classdict)[source]
Bases:
enum.EnumMetaMetaClass for Categorized (not for public use).
References
Categorized
- class category.Categorized(value)[source]
Bases:
enum.EnumDerive from this class to define a new category. e.g.:
class _BoardOption(NamedTuple): STR: str AX: Callable[[matplotlib.figure.Figure, tuple], matplotlib.axes.Axes] VERSIONS: Iterable = ALL class BoardOption(Categorized): HASH = _BoardOption(STR = _("a hash"), AX = hash_board) SQUARES = _BoardOption( STR = _("squares"), AX = squares_board, VERSIONS = from_version("1.5.0"), )
- Raises
AttributeError – Upon attempt to add, delete or change member.
The above example assumes the existence of functions named
hash_boardandsquares_board. It creates a Category namedBoardOptionwith two members,BoardOption.HASHandBoardOption.SQUARES, each of which has three attributes:STR,AXandVERSIONS.>>> isinstance(BoardOption, Category) True >>> isinstance(BoardOption.HASH, Categorized) True
A dropdown is a classic example of a category because different values should be available in different versions and all values typically should display differently in different languages. A member with an attribute named “VERSIONS”, will appear only for those versions. If a member has an attribute named “STR”, then that’s how that member will print (use functions from babelwrap module). For example, the following would yield a dropdown that contains only the local language translation of “a hash” in version 1.0.0, but translations of both “a hash” and “squares” in version 1.5.0 and above:
ipywidgets.Dropdown(options=BoardOption)
This will work even if the dropdown is declared before calling setvers() and setlang(). A member evaluates to False if not in the set version:
>>> setvers("1.0.0") (1,0,0) >>> bool(BoardOption.HASH) True >>> bool(BoardOption.SQUARES) False
If a member has an attribute named “CALL”, then the value of that attribute will be invoked when that member is called. If the CALL is a tuple-class (e.g.
NamedTuple), then that member is a “factory member”, and calling it will return a new Categorized with the attributes of that tuple-class (initialized with the called parameters). For example:class _Jump(NamedTuple): FROM: Tuple[int, ...] TO: Tuple[int, ...] VERSIONS: Iterable = ALL def __str__(self) -> str: return _("{origin} to {destination}").format( origin=self.FROM, destination=self.TO ) class _Move(NamedTuple): STR: str CALL: Optional[Callable] = None VERSIONS: Iterable = ALL class Move(Categorized): PASS = _Move(STR=_("Pass")) JUMP = _Move(STR=_("Reposition"), CALL=_Jump) jumps = (Move.JUMP(FROM=(1,2), TO=dest) for dest in ((3,1), (3,3), (2,4))) CurrentLegal = ctg(*jumps, name="CurentLegal", uniquify=True) | Move.PASS
In this example, the
MoveCategory has two members,Move.PASSandMove.JUMP, both of which haveSTR,CALL, andVERSIONSattributes.>>> str(Move) 'Pass and Reposition'
Move.JUMPis a factory member used in the second-to-last line to create three new instances of Categorized. They do not become members of any category until the last line which creates theCurrentLegalcategory from them unioned withMove.PASS. Then the members ofCurrentLegalareCurrentLegal.JUMP,CurrentLegal.JUMP1,CurrentLegal.JUMP2, andCurrentLegal.PASS(the names “JUMP1” and “JUMP2” are constructed byctg()to avoid name-collision).>>> str(CurrentLegal) '(1,2) to (3,1), (1,2) to (3,3), (1,2) to (2,4) and Pass'
Each of the “JUMP” members of
CurrentLegalhasFROM,TO, andVERSIONSattributes, butCurrentLegal.PASShas the same attributes asMove.PASS. It is the same entity, so it evaluates as==and isinboth categories:>>> CurrentLegal.PASS == Move.PASS True >>> CurrentLegal.PASS in Move True >>> Move.PASS in CurrentLegal True >>> CurrentLegal.JUMP in Move False
The only difference between the entities is context:
>>> str(type(Move.PASS)) 'Pass and Reposition' >>> str(type(CurrentLegal.PASS)) '(1,2) to (3,1), (1,2) to (3,3), (1,2) to (2,4) and Pass'
Categories support set operations, so you can get a new category containing all members that are in both categories (i.e. the set intersection):
>>> str(CurrentLegal & Move) 'Pass'
…set difference:
>>> str(CurrentLegal - Move) '(1,2) to (3,1), (1,2) to (3,3) and (1,2) to (2,4)'
…set union:
>>> str(CurrentLegal | Move) '(1,2) to (3,1), (1,2) to (3,3), (1,2) to (2,4), Pass and Reposition'
…and set symmetric difference:
>>> str(CurrentLegal ^ Move) '(1,2) to (3,1), (1,2) to (3,3), (1,2) to (2,4) and Reposition'
You can also test for containment of entire categories:
>>> CurrentLegal >= (Move - Move.JUMP) True
…and for proper superset (or subset):
>>> CurrentLegal > (Move - Move.JUMP) True
Tip
The
_()function should be used in categories to designate messages that need to be translated, and that function will be applied when categories are being initialized. To permit changing language after initialization, keep the initialized messages in the original language (the one for which you have translations) by setting this before setting the categories:def _(message: str) -> str: return message
… then set
_()to the actual translation function after setting the categories.References
ctg()
- category.ctg(*members: Iterable, name: str = 'Categorized', uniquify: bool = False) type[source]
Generate a new Category from one or more Categorized. E.g.:
ctg(Color.BLACK, Marker.CIRCLE)
- Parameters
- Returns
The new Category.
- Raises
TypeError – If attempt to combine non-equal members having the same name without setting
uniquifytoTrue.
setvers()
- category.setvers(name: Optional[str] = None) Tuple[Union[int, str], ...][source]
Get or set the version. E.g.:
setvers() # to get the currenty set version setlang("1.1.0") # to set a version (e.g. for testing) setlang("") # to restore the default from pyproject.toml
- Parameters
name (
str) – The name of the version to set. Default toNone.- Returns
The currently set version as a tuple.
parse_version()
- category.parse_version(name: Optional[str] = None, min_parts: int = 3) Tuple[Union[int, str], ...][source]
Yields sortable tuples for a version name. E.g.:
>>> parse_version("1.0.1-alpha") (1, 0, 1, 'alpha')
- Parameters
name (
str) – dot/hyphen-delimited version namemin_parts (
int) – The minimum parts in the tuple. Default is 3.
- Returns
A tuple with one member per part of the name padded with as many zeros as necessary to achieve min_parts. The numeric parts are integers, so the tuples sort correctly.
To support semantic versioning, omits any leading “v”, and appends an extra “~” part to versions with no “-”. E.g.:
>>> parse_version("v1.0.0-alpha") < parse_version("1.0") True
from_version()
- category.from_version(start: str, to: Optional[str] = None) Iterable[source]
The simple interval starting with a certain version. E.g.:
>>> from_version("1.5.0") [(1, 5, 0, '~'),+inf)
- Parameters
start (
str) – The starting versionto (
str) – If set, the (excluded) last version. If None, there is no end version. Default to None.
- Returns
ALL
- category.ALL = (-inf,+inf)
A shortcut for the portion.interval.Interval that contains all (e.g. versions)