| 322 | | getattr(type(value), self.opposite)._set(value, obj, from_opposite=True, do_notify=do_notify) |
|---|
| | 323 | opposite = getattr(type(value), self.opposite) |
|---|
| | 324 | if not opposite.opposite: |
|---|
| | 325 | opposite.stub = self |
|---|
| | 326 | opposite._set(value, obj, from_opposite=True, do_notify=do_notify) |
|---|
| | 327 | elif not self.opposite: |
|---|
| | 328 | if not self.stub: |
|---|
| | 329 | self.stub = associationstub(self) |
|---|
| | 330 | setattr(self.type, 'UML_associationstub_%x' % id(self), self.stub) |
|---|
| | 331 | self.stub._set(value, obj) |
|---|
| 390 | | def __on_unlink(self, value, pspec, obj): |
|---|
| 391 | | """ |
|---|
| 392 | | Disconnect when the element on the other end of the association |
|---|
| 393 | | (value) sends the '__unlink__' signal. This is especially important |
|---|
| 394 | | for uni-directional associations. |
|---|
| 395 | | """ |
|---|
| 396 | | #print '__on_unlink', name, obj, value |
|---|
| 397 | | if pspec == '__unlink__': |
|---|
| 398 | | self.__delete__(obj, value) |
|---|
| 399 | | # re-establish unlink handler: |
|---|
| 400 | | value.connect('__unlink__', self.__on_unlink, obj) |
|---|
| | 402 | # def __on_unlink(self, value, pspec, obj): |
|---|
| | 403 | # """ |
|---|
| | 404 | # Disconnect when the element on the other end of the association |
|---|
| | 405 | # (value) sends the '__unlink__' signal. This is especially important |
|---|
| | 406 | # for uni-directional associations. |
|---|
| | 407 | # """ |
|---|
| | 408 | # #print '__on_unlink', name, obj, value |
|---|
| | 409 | # if pspec == '__unlink__': |
|---|
| | 410 | # self.__delete__(obj, value) |
|---|
| | 411 | # # re-establish unlink handler: |
|---|
| | 412 | # value.connect('__unlink__', self.__on_unlink, obj) |
|---|
| | 413 | # |
|---|
| | 414 | |
|---|
| | 415 | class AssociationStubError(Exception): |
|---|
| | 416 | pass |
|---|
| | 417 | |
|---|
| | 418 | |
|---|
| | 419 | class associationstub(umlproperty): |
|---|
| | 420 | |
|---|
| | 421 | def __init__(self, association): |
|---|
| | 422 | self.association = association |
|---|
| | 423 | self._name = intern('_stub_%x' % id(self)) |
|---|
| | 424 | |
|---|
| | 425 | def __get__(self, obj, class_=None): |
|---|
| | 426 | if obj: |
|---|
| | 427 | raise AssociationStubError, 'getting values not allowed' |
|---|
| | 428 | return self |
|---|
| | 429 | |
|---|
| | 430 | def __set__(self, obj, value): |
|---|
| | 431 | raise AssociationStubError, 'setting values not allowed' |
|---|
| | 432 | |
|---|
| | 433 | def __delete__(self, obj, value=None): |
|---|
| | 434 | raise AssociationStubError, 'deleting values not allowed' |
|---|
| | 435 | |
|---|
| | 436 | def save(self, obj, save_func): |
|---|
| | 437 | pass |
|---|
| | 438 | |
|---|
| | 439 | def load(self, obj, value): |
|---|
| | 440 | pass |
|---|
| | 441 | |
|---|
| | 442 | def unlink(self, obj): |
|---|
| | 443 | try: |
|---|
| | 444 | values = getattr(obj, self._name) |
|---|
| | 445 | except AttributeError: |
|---|
| | 446 | pass |
|---|
| | 447 | else: |
|---|
| | 448 | for value in set(values): |
|---|
| | 449 | self.association.__delete__(value, obj) |
|---|
| | 450 | |
|---|
| | 451 | def _set(self, obj, value): |
|---|
| | 452 | try: |
|---|
| | 453 | getattr(obj, self._name).add(value) |
|---|
| | 454 | except AttributeError: |
|---|
| | 455 | setattr(obj, self._name, set([value])) |
|---|
| | 456 | |
|---|
| | 457 | def _del(self, obj, value, from_opposite=False): |
|---|
| | 458 | getattr(obj, self._name).discard(value) |
|---|