/usr/share/pyshared/gtkmvc/support/metaclasses.py is in python-gtkmvc 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 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 | # Author: Roberto Cavada <roboogle@gmail.com>
#
# Copyright (c) 2005 by Roberto Cavada
#
# pygtkmvc is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# pygtkmvc is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110, USA.
#
# For more information on pygtkmvc see <http://pygtkmvc.sourceforge.net>
# or email to the author Roberto Cavada <roboogle@gmail.com>.
# Please report bugs to <roboogle@gmail.com>.
import new
import re
import types
import inspect
import sys
import fnmatch
import itertools
import gtkmvc.support.wrappers as wrappers
from gtkmvc.support.utils import getmembers
from gtkmvc.support.log import logger
from gtkmvc.support.exceptions import DecoratorError, TooManyCandidatesError
# ----------------------------------------------------------------------
OBS_TUPLE_NAME = "__observables__"
# old name, supported only for backward compatilibity, do not use it
# anymore in new code
PROPS_MAP_NAME = "__properties__"
# This keeps the names of all observable properties (old and new)
ALL_OBS_SET = "__all_observables__"
# name of the variable that hold a property value
PROP_NAME = "_prop_%(prop_name)s"
# these are the names of the internal maps associating logical
# properties names to their getters/setters
LOGICAL_GETTERS_MAP_NAME = "_getdict"
LOGICAL_SETTERS_MAP_NAME = "_setdict"
# WARNING! These variables and code using them is deprecated These are
# the names for property getter/setter methods that depend on property
# name
GET_PROP_NAME = "get_%(prop_name)s_value"
SET_PROP_NAME = "set_%(prop_name)s_value"
# There are the names for generic property getter/setter methods
GET_GENERIC_NAME = "get__value"
SET_GENERIC_NAME = "set__value"
# this used for pattern matching
WILDCARDS = frozenset("[]!*?")
class PropertyMeta (type):
"""This is a meta-class that provides auto-property support.
The idea is to allow programmers to define some properties which
will be automatically connected to auto-generated code which handles
access to those properties.
How can you use this meta-class?
First, '__metaclass__ = PropertyMeta' must be class member of the class
you want to make the automatic properties handling.
Second, '__properties__' must be a map containing the properties names
as keys, values will be initial values for properties.
That's all: after the instantiation, your class will contain all properties
you named inside '__properties__'. Each of them will be also associated
to a couple of automatically-generated functions which get and set the
property value inside a generated member variable.
About names: suppose the property is called 'x'. The generated variable
(which keeps the real value of the property x) is called _prop_x.
The getter is called get_prop_x(self), and the setter is called
'set_prop_x(self, value)'.
Customization:
The base implementation of getter is to return the value stored in the
variable associated to the property. The setter simply sets its value.
Programmers can override basic behaviour for getters or setters simply by
defining their getters and setters (see at the names convention above).
The customized function can lie everywhere in the user classes hierarchy.
Every overridden function will not be generated by the metaclass.
To supply your own methods is good for few methods, but can result in a
very unconfortable way for many methods. In this case you can extend
the meta-class, and override methods get_[gs]etter_source with your
implementation (this can be probably made better).
An example is provided in meta-class PropertyMetaVerbose below.
"""
def __init__(cls, name, bases, _dict):
"""class constructor"""
type.__init__(cls, name, bases, _dict)
# the set of all obs (it is calculated and stored below)
obs = set()
# processes now all names in __observables__
conc_props, log_props = type(cls).__get_observables_sets__(cls)
# processes all concrete properties
for prop in conc_props:
val = _dict[prop] # must exist if concrete
type(cls).__create_conc_prop_accessors__(cls, prop, val)
obs.add(prop)
pass
# processes all logical properties, and adds the actual log
# properties to the list of all observables
_getdict = getattr(cls, LOGICAL_GETTERS_MAP_NAME, dict())
_setdict = getattr(cls, LOGICAL_SETTERS_MAP_NAME, dict())
real_log_props = type(cls).__create_log_props(cls, log_props,
_getdict, _setdict)
obs |= real_log_props
# after using the maps, it is time to clear them to make
# them available to the next class in the mro.
_getdict.clear()
_setdict.clear()
# processes all names in __properties__ (deprecated,
# overloaded by __observables__)
props = getattr(cls, PROPS_MAP_NAME, {})
if len(props) > 0:
import warnings
warnings.warn("In class %s.%s the use of attribute '%s' in "
"models is deprecated."
" Use the tuple '%s' instead (see the manual)" \
% (cls.__module__, cls.__name__,
PROPS_MAP_NAME, OBS_TUPLE_NAME),
DeprecationWarning)
pass
for prop in (x for x in props.iterkeys() if x not in obs):
type(cls).__create_conc_prop_accessors__(cls, prop, props[prop])
obs.add(prop)
pass
# generates the list of _all_ properties available for this
# class (also from bases)
for base in bases: obs |= getattr(base, ALL_OBS_SET, set())
setattr(cls, ALL_OBS_SET, frozenset(obs))
logger.debug("class %s.%s has observables: %s" \
% (cls.__module__, cls.__name__, obs))
return
def __get_observables_sets__(cls):
"""Returns a pair of frozensets. First set of strings is the set
of concrete properties, obtained by expanding wildcards
found in class field __observables__. Expansion works only
with names not prefixed with __.
Second set of strings contains the names of the logical
properties. This set may still contain logical properties
which have not been associated with a getter (and
optionally with a setter).
"""
conc_prop_set = set()
log_prop_set = set()
not_found = []
names = cls.__dict__.get(OBS_TUPLE_NAME, tuple())
if not isinstance(names, types.ListType) and \
not isinstance(names, types.TupleType):
raise TypeError("In class %s.%s attribute '%s' must be a list or tuple" %
(cls.__module__, cls.__name__, OBS_TUPLE_NAME))
for name in names:
if type(name) != types.StringType:
raise TypeError("In class %s.%s attribute '%s' must contain"\
" only strings (found %s)" %
(cls.__module__, cls.__name__, OBS_TUPLE_NAME,
type(name)))
if (cls.__dict__.has_key(name) and not
isinstance(getattr(cls, name), types.MethodType)):
conc_prop_set.add(name)
else: not_found.append(name)
pass
# now searches all possible matches for those that have not
# been found, and collects all logical properties as well
# (those which do not match, and do not contain patterns)
concrete_members = [x for x,v in cls.__dict__.iteritems()
if (not x.startswith("__") and
not isinstance(v, types.FunctionType) and
not isinstance(v, types.MethodType) and
type(v) is not classmethod and
x not in conc_prop_set)]
for pat in not_found:
if frozenset(pat) & WILDCARDS:
matches = fnmatch.filter(concrete_members, pat)
if 0 == len(matches):
logger.warning("In class %s.%s observable pattern '%s' " \
"did not match any existing attribute." % \
(cls.__module__, cls.__name__, pat))
else: conc_prop_set |= set(matches)
else: # here pat has to be a logical property
log_prop_set.add(pat)
pass
pass
return (frozenset(conc_prop_set), frozenset(log_prop_set))
def __create_log_props(cls, log_props, _getdict, _setdict):
"""Creates all the logical property.
The list of names of properties to be created is passed
with frozenset log_props. The getter/setter information is
taken from _{get,set}dict.
This method resolves also wildcards in names, and performs
all checks to ensure correctness.
Returns the frozen set of the actually created properties
(as not log_props may be really created, e.g. when no
getter is provided, and a warning is issued).
"""
real_log_props = set()
resolved_getdict = {}
resolved_setdict = {}
for _dict_name, _dict, _resolved_dict in (("getter",
_getdict, resolved_getdict),
("setter",
_setdict, resolved_setdict)):
# first resolve all wildcards
for pat, ai in ((pat, ai)
for pat, ai in _dict.iteritems()
if frozenset(pat) & WILDCARDS):
matches = fnmatch.filter(log_props, pat)
for match in matches:
if match in _resolved_dict:
raise NameError("In class %s.%s %s property '%s' "
"is matched multiple times by patterns" % \
(cls.__module__, cls.__name__, _dict_name, match))
_resolved_dict[match] = ai
pass
if not matches:
logger.warning("In class %s.%s %s pattern '%s' "
"did not match any existing logical property." % \
(cls.__module__, cls.__name__, _dict_name, pat))
pass
pass
# now adds the exact matches (no wilcards) which override
# the pattern-matches
_resolved_dict.update((name, ai)
for name, ai in _dict.iteritems()
if name in log_props)
# checks that all getter/setter have a corresponding logical property
not_found = [name for name in _resolved_dict
if name not in log_props]
if not_found:
logger.warning("In class %s.%s logical %s were declared for"\
"non-existant observables: %s" % \
(cls.__module__, cls.__name__, _dict_name, str(not_found)))
pass
pass
# creates the properties
for name in log_props:
# finds the getter
ai_get = resolved_getdict.get(name, None)
if ai_get:
# decorator-based
_getter = type(cls).get_getter(cls, name, ai_get.func,
ai_get.has_args)
else:
# old style
_getter = type(cls).get_getter(cls, name)
if _getter is None:
raise RuntimeError("In class %s.%s logical observable '%s' "\
"has no getter method" % \
(cls.__module__, cls.__name__, name))
pass
# finds the setter
ai_set = resolved_setdict.get(name, None)
if ai_set:
# decorator-based
if ai_get:
_setter = type(cls).get_setter(cls, name,
ai_set.func, ai_set.has_args,
ai_get.func, ai_get.has_args)
else:
# the getter is old style. _getter is already
# resolved wrt the name it may take, so
# getter_takes_name is False
_setter = type(cls).get_setter(cls, name,
ai_set.func, ai_set.has_args,
_getter, False)
pass
else:
# old style setter
if ai_get:
_setter = type(cls).get_setter(cls, name,
None, None,
ai_get.func,
ai_get.has_args)
else: _setter = type(cls).get_setter(cls, name)
pass
# here _setter can be None
prop = property(_getter, _setter)
setattr(cls, name, prop)
real_log_props.add(name)
pass
# checks that all setters have a getter
setters_no_getters = (set(resolved_setdict) - real_log_props) & log_props
if setters_no_getters:
logger.warning("In class %s.%s logical setters have no "
"getters: %s" % \
(cls.__module__, cls.__name__,
", ".join(setters_no_getters)))
pass
return frozenset(real_log_props)
def __create_conc_prop_accessors__(cls, prop_name, default_val):
"""Private method that creates getter and setter, and the
corresponding property. This is used for concrete
properties."""
getter_name = "get_prop_%s" % prop_name
setter_name = "set_prop_%s" % prop_name
members_names = cls.__dict__.keys()
# checks if accessors are already defined:
if getter_name not in members_names:
_getter = type(cls).get_getter(cls, prop_name)
setattr(cls, getter_name, _getter)
else:
logger.debug("Custom member '%s' overloads generated getter of property '%s'" \
% (getter_name, prop_name))
pass
if setter_name not in members_names:
_setter = type(cls).get_setter(cls, prop_name)
setattr(cls, setter_name, _setter)
else:
logger.warning("Custom member '%s' overloads generated setter of property '%s'" \
% (setter_name, prop_name))
pass
# creates the property
prop = property(getattr(cls, getter_name), getattr(cls, setter_name))
setattr(cls, prop_name, prop)
# creates the underlaying variable if needed
varname = PROP_NAME % {'prop_name' : prop_name}
if varname not in members_names:
setattr(cls, varname, cls.create_value(varname, default_val))
else: logger.warning("In class %s.%s automatic property builder found a "
"possible clashing with attribute '%s'" \
% (cls.__module__, cls.__name__, varname))
return
def has_prop_attribute(cls, prop_name):
"""This methods returns True if there exists a class attribute
for the given property. The attribute is searched locally
only"""
props = getattr(cls, PROPS_MAP_NAME, {})
return (cls.__dict__.has_key(prop_name) and
type(cls.__dict__[prop_name]) != types.FunctionType)
def check_value_change(cls, old, new):
"""Checks whether the value of the property changed in type
or if the instance has been changed to a different instance.
If true, a call to model._reset_property_notification should
be called in order to re-register the new property instance
or type"""
return type(old) != type(new) or \
isinstance(old, wrappers.ObsWrapperBase) and (old != new)
def create_value(cls, prop_name, val, model=None):
"""This is used to create a value to be assigned to a
property. Depending on the type of the value, different values
are created and returned. For example, for a list, a
ListWrapper is created to wrap it, and returned for the
assignment. model is different from None when the value is
changed (a model exists). Otherwise, during property creation
model is None"""
if isinstance(val, tuple):
# this might be a class instance to be wrapped
# (thanks to Tobias Weber for
# providing a bug fix to avoid TypeError (in 1.99.1)
if len(val) == 3:
try:
wrap_instance = isinstance(val[1], val[0]) and \
(isinstance(val[2], tuple) or
isinstance(val[2], list))
except TypeError:
pass # not recognized, it must be another type of tuple
else:
if wrap_instance:
res = wrappers.ObsUserClassWrapper(val[1], val[2])
if model: res.__add_model__(model, prop_name)
return res
pass
pass
pass
elif isinstance(val, list):
res = wrappers.ObsListWrapper(val)
if model: res.__add_model__(model, prop_name)
return res
elif isinstance(val, dict):
res = wrappers.ObsMapWrapper(val)
if model: res.__add_model__(model, prop_name)
return res
return val
# ------------------------------------------------------------
# Services
# ------------------------------------------------------------
# Override these:
def get_getter(cls, prop_name,
user_getter=None, getter_takes_name=False):
"""Returns a function wich is a getter for a property.
prop_name is the name off the property.
user_getter is an optional function doing the work. If
specified, that function will be called instead of getting
the attribute whose name is in 'prop_name'.
If user_getter is specified with a False value for
getter_takes_name (default), than the method is used to get
the value of the property. If True is specified for
getter_takes_name, then the user_getter is called by
passing the property name (i.e. it is considered a general
method which receive the property name whose value has to
be returned.)
"""
if user_getter:
if getter_takes_name: # wraps the property name
def _getter(self): return user_getter(self, prop_name)
else: _getter = user_getter
return _getter
def _getter(self): return getattr(self,
PROP_NAME % {'prop_name' : prop_name})
return _getter
def get_setter(cls, prop_name,
user_setter=None, setter_takes_name=False,
user_getter=None, getter_takes_name=False):
"""Similar to get_getter, but for setting property
values. If user_getter is specified, that it may be used to
get the old value of the property before setting it (this
is the case in some derived classes' implementation). if
getter_takes_name is True and user_getter is not None, than
the property name is passed to the given getter to retrieve
the property value."""
if user_setter:
if setter_takes_name:
# wraps the property name
def _setter(self, val): return user_setter(self, prop_name, val)
else: _setter = user_setter
return _setter
def _setter(self, val): setattr(self,
PROP_NAME % {'prop_name' : prop_name},
val)
return _setter
pass # end of class
# ----------------------------------------------------------------------
class ObservablePropertyMeta (PropertyMeta):
"""Classes instantiated by this meta-class must provide a method named
notify_property_change(self, prop_name, old, new)"""
def __init__(cls, name, bases, dict):
PropertyMeta.__init__(cls, name, bases, dict)
return
def get_getter(cls, prop_name,
user_getter=None, getter_takes_name=False):
"""This implementation returns the PROP_NAME value if there
exists such property. Otherwise there must exist a logical
getter (user_getter) which the value is taken from. If no
getter is found, None is returned (i.e. the property cannot
be created)"""
has_prop_variable = cls.has_prop_attribute(prop_name)
# WARNING! Deprecated
has_specific_getter = hasattr(cls, GET_PROP_NAME % {'prop_name' : prop_name})
has_general_getter = hasattr(cls, GET_GENERIC_NAME)
if not (has_prop_variable or
has_specific_getter or has_general_getter or user_getter):
return None
# when property variable is given, it overrides all the getters
if has_prop_variable:
if has_specific_getter or user_getter:
logger.warning("In class %s.%s ignoring custom logical getter "
"for property '%s' as a corresponding "
"attribute exists" \
% (cls.__module__, cls.__name__, prop_name))
pass
# user_getter is ignored here, so it has not to be passed up
user_getter = None; getter_takes_name = False
else:
# uses logical getter. Sees if the getter needs to receive
# the property name (i.e. if the getter is used for multiple
# properties)
if user_getter: pass
else:
if has_specific_getter:
# this is done to delay getter call, to have
# bound methods to allow overloading of getter in
# derived classes
def __getter(self):
_getter = getattr(self, GET_PROP_NAME % {'prop_name' : prop_name})
return _getter()
#previously it was simply:
#user_getter = getattr(cls, GET_PROP_NAME % {'prop_name' : prop_name})
user_getter = __getter
getter_takes_name = False
else:
assert has_general_getter
def __getter(self, name):
_getter = getattr(self, GET_GENERIC_NAME)
return _getter(name)
#user_getter = getattr(cls, GET_GENERIC_NAME)
user_getter = __getter
getter_takes_name = True
pass
pass
pass
return PropertyMeta.get_getter(cls, prop_name, user_getter, getter_takes_name)
def get_setter(cls, prop_name,
user_setter=None, setter_takes_name=False,
user_getter=None, getter_takes_name=False):
"""The setter follows the rules of the getter. First search
for property variable, then logical custom setter. If no
setter is found, None is returned (i.e. the property is
read-only.)"""
has_prop_variable = cls.has_prop_attribute(prop_name)
# WARNING! These are deprecated
has_specific_setter = hasattr(cls, SET_PROP_NAME % {'prop_name' : prop_name})
has_general_setter = hasattr(cls, SET_GENERIC_NAME)
if not (has_prop_variable or
has_specific_setter or has_general_setter or user_setter):
return None
if has_prop_variable:
if has_specific_setter or user_setter:
logger.warning("In class %s.%s ignoring custom logical setter "
"for property '%s' as a corresponding "
"attribute exists" \
% (cls.__module__, cls.__name__, prop_name))
pass
user_setter = user_getter = None
setter_takes_name = getter_takes_name = False
else:
if user_setter: pass
else:
if has_specific_setter:
def __setter(self, val):
_setter = getattr(self, SET_PROP_NAME % {'prop_name' : prop_name})
_setter(val)
pass
user_setter = __setter
#user_setter = getattr(cls, SET_PROP_NAME % {'prop_name' : prop_name})
setter_takes_name = False
else:
assert has_general_setter
def __setter(self, name, val):
_setter = getattr(self, SET_GENERIC_NAME)
_setter(name, val)
pass
user_setter = __setter
#user_setter = getattr(cls, SET_GENERIC_NAME)
setter_takes_name = True
pass
pass
pass
# the final setter is a combination of a basic setter, and
# the getter (see how inner_{getter,setter} are used in
# _setter below)
_inner_setter = PropertyMeta.get_setter(cls, prop_name,
user_setter, setter_takes_name,
user_getter, getter_takes_name)
_inner_getter = type(cls).get_getter(cls, prop_name, user_getter, getter_takes_name)
def _setter(self, val):
old = _inner_getter(self)
new = type(self).create_value(prop_name, val, self)
_inner_setter(self, new)
if type(self).check_value_change(old, new):
self._reset_property_notification(prop_name, old)
pass
self.notify_property_value_change(prop_name, old, val)
return
return _setter
pass #end of class
# ----------------------------------------------------------------------
class ObservablePropertyMetaMT (ObservablePropertyMeta):
"""This class provides multithreading support for accesing
properties, through a locking mechanism. It is assumed a lock is
owned by the class that uses it. A Lock object called _prop_lock
is assumed to be a member of the using class. see for example class
ModelMT"""
def __init__(cls, name, bases, dict):
ObservablePropertyMeta.__init__(cls, name, bases, dict)
return
def get_setter(cls, prop_name,
user_setter=None, setter_takes_name=False,
user_getter=None, getter_takes_name=False):
"""The setter follows the rules of the getter. First search
for property variable, then logical custom getter/seter pair
methods"""
_inner_setter = ObservablePropertyMeta.get_setter(cls, prop_name,
user_setter, setter_takes_name,
user_getter, getter_takes_name)
def _setter(self, val):
self._prop_lock.acquire()
_inner_setter(self, val)
self._prop_lock.release()
return
return _setter
pass #end of class
try:
from sqlobject import Col
from sqlobject.inheritance import InheritableSQLObject
from sqlobject.events import listen, RowUpdateSignal
class ObservablePropertyMetaSQL (InheritableSQLObject.__metaclass__,
ObservablePropertyMeta):
"""Classes instantiated by this meta-class must provide a method
named notify_property_change(self, prop_name, old, new)"""
def __init__(cls, name, bases, dict):
InheritableSQLObject.__metaclass__.__init__(cls, name, bases, dict)
ObservablePropertyMeta.__init__(cls, name, bases, dict)
listen(cls.update_listener, cls, RowUpdateSignal)
return
def __create_conc_prop_accessors__(cls, prop_name, default_val):
if not isinstance(default_val, Col):
# this is not a SQLObject column (likely a normal concrete
# observable property)
ObservablePropertyMeta.__create_conc_prop_accessors__(cls,
prop_name,
default_val)
pass
return
def update_listener(cls, instance, kwargs):
conc_pnames, _ = type(cls).__get_observables_sets__(cls)
for k in kwargs:
if k in conc_pnames:
_old = getattr(instance, k)
_new = kwargs[k]
instance.notify_property_value_change(k, _old, _new)
pass
pass
return
pass #end of class
except: pass
try:
from gobject import GObjectMeta
class ObservablePropertyGObjectMeta (ObservablePropertyMeta, GObjectMeta): pass
class ObservablePropertyGObjectMetaMT (ObservablePropertyMetaMT, GObjectMeta): pass
except:
class ObservablePropertyGObjectMeta (ObservablePropertyMeta): pass
class ObservablePropertyGObjectMetaMT (ObservablePropertyMetaMT): pass
pass
|