/usr/share/doc/python-gtkmvc-doc/userman/_sources/op_logical.txt is in python-gtkmvc-doc 1.99.1-1build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | =============================
Logical Observable Properties
=============================
*Logical* OPs are properties whose values are not necessarily
stored in the model, but which are read and written by a pair of
getter/setter methods.
This make logical OPs ideal for:
* Values calculated out of other OPs (which can be either logical
or concrete).
* Values living outside the model, like e.g. in a database, or in a
remote server.
Logical OPs are declared like concrete OPs, but no correspoding
attributes have to appear in the class. Their name have to appear
only within the special member ``__observables__``.
For example: ::
from gtkmvc import Model
# ----------------------------
class MyModel (Model):
name = "Roberto"
__observables__ = ("name", "happiness")
pass # end of class
# ----------------------------
In the example, ``name`` is a concrete property, whereas
``happiness`` is a logical property, as no corresponding attribute
exists in class ``MyModel``.
.. Note::
Notice that names of logical OPs occurring within the
special member ``__observables__`` cannot contain wildcards like
concrete properties.
The reasons for this limitation is obvious, as wildcards
can be used to match only class attributes.)
However, a logical OP's value is taken from a getter method, and
for a read/write OP the values are stored through a setter
method. Defining a getter is mandatory, while defining a setter is
required only for writable logical OPs.
getter/setter methods can be defined by exploiting decorators, or
by exploiting a naming convention.
Use of decorators for defining getters and/or setters
-----------------------------------------------------
Decorators ``@Model.getter`` and ``@Model.setter`` can be used for
defining logical OPs getter and setter respectively. The syntax and
semantics are very similar to the python ``@property``
decorator.
E.g. for logical OP ``happiness`` in the previous example: ::
from gtkmvc import Model
# ----------------------------
class MyModel (Model):
name = "Roberto"
__observables__ = ("name", "happiness")
_a_value = 1.0 # support for happiness
@Model.getter
def happiness(self): return self._a_value
@Model.setter
def happiness(self, value): self._a_value = max(1.0, value)
pass # end of class
# ----------------------------
It is possible to define getter/setter methods which serve multiple
logical OPs.
For example: ::
from gtkmvc import Model
# ----------------------------
class MyModel (Model):
name = "Roberto"
__observables__ = ("name", "happiness", "energy")
_a_value = 1.0 # support for happiness
@Model.getter("happiness", "energy")
def a_getter_for_several_ops(self, name):
if "energy" == name: return 0.1 # constantly need holidays!
return self._a_value
@Model.setter
def happiness(self, value): self._a_value = max(1.0, value)
pass # end of class
# ----------------------------
In the example, the decorator ``@Model.getter`` is used with
arguments, which have to be the string names of all properties
which have to be handled by the decorated method. The method (the
getter in this case) will receive the name of the property along
with its other arguments.
Use of wildcards is allowed in decorators names, and will match all
logical OPs not exactly matched by other decorators. It is an error
condition if multiple matches are found when matching logical OPs
specified with wildcards. For example this is perfectly legal: ::
from gtkmvc import Model
# ----------------------------
class MyModel (Model):
name = "Roberto"
__observables__ = ("name", "energy", "entropy", "enology")
@Model.getter
def energy(self): return 0.1 # constantly need holidays!
@Model.getter("enology")
def getter1(self, name): return "good science!"
@Model.getter("en*") # matches only remaining 'entropy'
def getter2(self, name):
assert "entropy" == name
return 0
@Model.setter("*") # matches "energy", "entropy", "enology"
def happiness(self, name, value):
print "setter for", name, value
...
return
pass # end of class
# ----------------------------
However, this example is not legal: ::
from gtkmvc import Model
# ----------------------------
class MyModel (Model):
__observables__ = ("energy", "entropy", "enology")
@Model.getter("en*") # matches energy, entropy, and enology
def getter1(self, name): ...
@Model.getter("*") # matches energy, entropy, and enology
def getter2(self, name): ...
pass # end of class
# ----------------------------
The example does not work as ambiguity is found when resolving
wilcards.
Use of naming convention for defining getters and/or setters
------------------------------------------------------------
In some cases, the use of decorators for defining getters/setters
can be a limitation. For example, when the model is built
dynamically, like when generating proxy classes.
In these and other cases, the framework supports a *naming
convention* which can be used to define implicitly getters and/or
setters for logical OPs.
The naming convention applies to Model's method names which are
implicitly declared as getters or setters.
* `get_<prop_name>_value(self)`: A specific getter for OP `<prop_name>`.
* `set_<prop_name>_value(self, value)`: A specific setter for OP `<prop_name>`.
* `get__value(self, name)`: A generic getter receiving the name of
the property to be get.
* `set__value(self, name, value)`: A generic setter receiving the name of
the property to be set.
As you see getters/setters can be either *specific* or
*generic*. In the former case, the getter/setter is specific for
one OP. In the latter case, getter/setter is general and will
receive the name of the property.
Generic getter/setter will not be called for OPs which have
specific getter/setter defined. For example: ::
from gtkmvc import Model
# ----------------------------
class MyModel (Model):
__observables__ = ("energy", "entropy", "enology")
def get_energy_value(self): return 0.1 # constantly need holidays!
# getter for entropy and enology only, as energy has a specific getter
def get__value(self, name): ...
# setter for all properties
def set_value(self, name, value): ...
pass # end of class
# ----------------------------
The first example we presented for decorators could be rewritten
as: ::
from gtkmvc import Model
# ----------------------------
class MyModel (Model):
name = "Roberto"
__observables__ = ("name", "energy", "entropy", "enology")
def get_energy_value(self): return 0.1 # constantly need holidays!
def get_enology_value(self): return "good science!"
def get__value(self, name):
assert "entropy" == name
return 0
def set__value(self, name, value):
print "setter for", name, value
...
return
pass # end of class
# ----------------------------
Of course, since in naming conventions names *matters*, some names
in the example had to be adapted.
|