fix race condition by Michael J Gruber
[PyX/mjg.git] / design / attributes
blob028890edfa75f14a5aa5d76926681dd357189913
1 Attributes. Design summary.
2 ===========================
5 What are attributes?
6 --------------------
8 Attributes define properties of a given object when it is being used.
9 They are instances derived from the class attr.attr. Typically, there
10 are different kind of attributes which are usually orthogonal to each
11 other, while for one attribute kind, several choices are possible.
13     Example:
15     When stroking a path, the linewidth and the linestyle are
16     different kind of attributes. The linewidth might be normal, thin,
17     thick, or whatever else. The linestyle might be solid, dashed etc.
20 Where are attributes used?
21 --------------------------
23 Typically, attributes occur in lists passed as an optional keyword argument to
24 a method or a function. The object the attributes are refering to is usually
25 the first argument (not taking into account the self argument) of the method,
26 like in
28     canvas.stroke(path, [attr1, attr2, attr3])
31 Attribute categories
32 --------------------
34 There are different categories of attributes. We give a (not yet?)
35 complete list here:
37     - stroke attributes, aka strokestyles (style module)
38       inherited from style.strokestyle
39     - fill attributes, aka fillstyles
40       inherited from style.fillstyle
41     - text attributes, aka textattrs (text module)
42       inherited from style.textattr
43     - decorators (deco module)
44       inherited from deco.deco
45     - transformations (trafo module)
46     - clippings?
47       (AW: might go away; boxes could do that)
49 Operations usually allow for certain attibute categories only. For example when
50 stroking a path, text attributes are not allowed, while stroke attributes and
51 decoraters are. Some attributes might belong to several attribute categories
52 like colors, which are both, stroke and fill attributes. This is described by
53 multiple inheritance and the attribute categories can be queried using the
54 builtin isinstance method.
57 Attribute instances as member variables
58 ---------------------------------------
60 Usable attributes are always instances. For simple attributes, we
61 have the following technology:
63     class linewidth(strokestyle):
65         def __init__(...):
66         etc.
68     linewidth.normal = linewidth("0.2 mm")
69     linewidth.thick = linewidth("0.2828 mm")
70     etc.
72 Thus there are different possibilities to get a linewidth: by
73 linewidth("0.25 mm") and by linewidth.normal (and the like).
74 Note that attribute classes usually contain a set of special
75 attribute values as member variables. This is done in order
76 to group the attributes in a nice way.
79 Specializing attribute instances
80 --------------------------------
82 There might be more complicated attributes, where it is more
83 questionable, how attribute instances should be used. An easy, yet not
84 striking, example would be changes in some color parameters of a color
85 attribute. Consider a CMYK color, where only the blackness should be
86 changed. Thus we need to have a syntax for further specializing an
87 already existing attribute instance. This could be done by __call__
88 (or some arbitrary other named method --- the latter would not really
89 be helpfull in the authors eyes). The code would look like:
91     some_cmyk_color = color.cmyk(0.1, 0.2, 0.3, 0.4)
92     darker_version = some_cmyk_color(b=1)
94 Both, some_cmyk_color and darker_version are instances of color.cmyk.
95 Since usually some parameters are to be changed only, the parameters
96 should be accessable by keyword arguments. Attribute lists in keyword
97 arguments could gain from the attribute replacement and clearing
98 functionality described below. Basically, the specialization (__call__
99 method) should take exactly the same arguments like the constructor
100 (__init__ method). It might be consistent to provide the
101 specialization possibility for all attribute instances.
104 Merging attribute lists
105 -----------------------
107 Attributes allow for exclusion, overwriting each other and ordering.
108 This process is called merging of attributes and it is performed by
109 the function merge from attr.py.
111 The merging process might take into account some default attributes.
112 They are passed in a special keyword argument.
114     Example:
116     use_attr_list = attr.mergeattrs(original_attr_list)
118 There are special clearing attributes, which overwrite other attributes and do
119 not add themself when merging an attribute list. By that it is possible to
120 change certain or all default attributes. To construct an instance of a
121 clearing attributes which removes all preceding attributes of a certain
122 class c use attr.clearclass(c). The attr module also contains a predefined
123 instance attr.clear which clears all preceding attributes.
126 Changeable attributes
127 ---------------------
129 Changeable attributes are instances derived from attr.changeattr. They
130 provide a select method with the following prototype:
132     select(self, index, total)
134 The index is an unsigned integer and the total is a positive integer.
135 The select method might raise an ValueError, when the select method is
136 called for parameters, it doesn't allow for. An example would be a
137 color change from a starting color to an end color. Such a changeable
138 attribute would not allow for a total equals to 1.
140 The select function from attr.py returns a list of attributes out of a
141 list of attributes and changeable attributes. The prototype uses the
142 same index and total arguments, as described above:
144     select(attr_list, index, total)
146 When changeable attributes are used, the select process must be
147 performed previous to the merging.