Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No application singleton #262

Merged
merged 10 commits into from Feb 5, 2020
4 changes: 2 additions & 2 deletions examples/list_classes.py
Expand Up @@ -8,7 +8,7 @@
import sys

import gaphor.UML as UML
from gaphor.application import Application
from gaphor.application import Session

# Setup command line options.
usage = "usage: %prog [options] file.gaphor"
Expand All @@ -33,7 +33,7 @@
model = args[0]

# Create the Gaphor application object.
session = Application.new_session()
session = Session()

# Get services we need.
element_factory = session.get_service("element_factory")
Expand Down
27 changes: 12 additions & 15 deletions gaphor/UML/properties.py
Expand Up @@ -743,21 +743,18 @@ def _union(self, obj, exclude=None):
"""
Returns a union of all values as a set.
"""
if self.single:
return next(iter(self.subsets)).__get__(obj)
else:
u: Set[T] = set()
for s in self.subsets:
if s is exclude:
continue
tmp = s.__get__(obj)
if tmp:
try:
u.update(tmp)
except TypeError:
# [0..1] property
u.add(tmp)
return collectionlist(u)
u: Set[T] = set()
for s in self.subsets:
if s is exclude:
continue
tmp = s.__get__(obj)
if tmp:
try:
u.update(tmp)
except TypeError:
# [0..1] property
u.add(tmp)
return collectionlist(u)

def propagate(self, event):
"""
Expand Down
11 changes: 3 additions & 8 deletions gaphor/UML/tests/test_elementfactory.py
Expand Up @@ -2,7 +2,7 @@

import pytest

from gaphor.application import Application
from gaphor.application import Session
from gaphor.core import event_handler
from gaphor.services.eventmanager import EventManager
from gaphor.UML import Parameter
Expand Down Expand Up @@ -96,17 +96,12 @@ def clear_events():

@pytest.fixture
def element_factory():
session = Application.new_session(
services=["event_manager", "component_registry", "element_factory"]
)
event_manager = session.get_service("event_manager")
event_manager = EventManager()
event_manager.subscribe(handler)
clear_events()
factory = session.get_service("element_factory")
factory = ElementFactory(event_manager)
yield factory
del factory
clear_events()
session.shutdown()


def test_create_event(element_factory):
Expand Down
250 changes: 25 additions & 225 deletions gaphor/UML/tests/test_properties.py
@@ -1,6 +1,3 @@
import pytest

from gaphor.application import Application
from gaphor.core import event_handler
from gaphor.UML.element import Element
from gaphor.UML.event import AssociationUpdated
Expand Down Expand Up @@ -398,31 +395,6 @@ class A(Element):
assert a.a == "one"


@pytest.mark.skip
def test_notify():
class A(Element):
notified = None

def notify(self, name, pspec):
self.notified = name

A.assoc = association("assoc", A)
A.attr = attribute("attr", bytes, "default")
A.enum = enumeration("enum", ("one", "two"), "one")

a = A()
assert a.notified is None
a.assoc = A()
assert a.notified == "assoc", a.notified
a.attr = "newval"
assert a.notified == "attr", a.notified
a.enum = "two"
assert a.notified == "enum", a.notified
a.notified = None
a.enum = "two" # should not notify since value hasn't changed.
assert a.notified is None


def test_derivedunion():
class A(Element):
pass
Expand Down Expand Up @@ -454,24 +426,44 @@ class A(Element):
assert d in a.u


@pytest.mark.skip
def test_derivedunion_notify():
def test_derivedunion_notify_for_single_derived_property():
class A(Element):
pass

class E(Element):
notified = False

def notify(self, name, pspec):
if name == "u":
def handle(self, event):
if event.property is E.u:
self.notified = True

E.a = association("a", A)
E.u = derivedunion(E, "u", A, 0, "*", E.a)

e = E()
assert e.notified is False
e.a = A()

assert e.notified is True


def test_derivedunion_notify_for_multiple_derived_properties():
class A(Element):
pass

class E(Element):
notified = False

def handle(self, event):
if event.property is E.u:
self.notified = True

E.a = association("a", A)
E.aa = association("aa", A)
E.u = derivedunion(E, "u", A, 0, "*", E.a, E.aa)

e = E()
e.a = A()

assert e.notified is True


Expand Down Expand Up @@ -518,195 +510,3 @@ def unlink(self):
a.unlink()
assert a.is_unlinked
assert b.is_unlinked


@pytest.mark.skip
def test_derivedunion_events():
from gaphor.UML.event import DerivedAdded, DerivedDeleted

class A(Element):
is_unlinked = False

def unlink(self):
self.is_unlinked = True
Element.unlink(self)

A.a1 = association("a1", A, upper=1)
A.a2 = association("a2", A, upper=1)
A.b1 = association("b1", A, upper="*")
A.b2 = association("b2", A, upper="*")
A.b3 = association("b3", A, upper=1)

A.derived_a = derivedunion(A, "derived_a", object, 0, 1, A.a1, A.a2)
A.derived_b = derivedunion(A, "derived_b", object, 0, "*", A.b1, A.b2, A.b3)

events = []

@event_handler(AssociationUpdated)
def handler(event, events=events):
events.append(event)

Application.register_handler(handler)
try:
a = A()
a.a1 = A()
assert len(events) == 2
assert events[0].property is A.derived_a
assert events[1].property is A.a1
assert a.derived_a is a.a1
a.a1 = A()
assert len(events) == 4, len(events)
assert a.derived_a is a.a1

a.a2 = A()
# Should not emit DerivedSet
assert len(events) == 5, len(events)
assert events[4].property is A.a2

del events[:]
old_a1 = a.a1
del a.a1
assert len(events) == 2, len(events)
assert events[0].property is A.derived_a
assert events[0].new_value is a.a2, "{} {} {}".format(
a.a1, a.a2, events[3].new_value
)
assert events[0].old_value is old_a1, "{} {} {}".format(
a.a1, a.a2, events[3].old_value
)
assert events[1].property is A.a1

del events[:]
old_a2 = a.a2
del a.a2
assert len(events) == 2, len(events)
assert events[0].property is A.derived_a
assert events[0].new_value is None, "{} {} {}".format(
a.a1, a.a2, events[5].new_value
)
assert events[0].old_value is old_a2, "{} {} {}".format(
a.a1, a.a2, events[5].old_value
)
assert events[1].property is A.a2

del events[:]
assert len(events) == 0, len(events)

a.b1 = A()
assert len(events) == 2
assert events[0].property is A.derived_b
assert events[1].property is A.b1

a.b2 = A()
assert len(events) == 4
assert events[2].property is A.derived_b
assert events[3].property is A.b2

a.b2 = A()
assert len(events) == 6
assert events[4].property is A.derived_b
assert events[5].property is A.b2

a.b3 = A()
assert len(events) == 8, len(events)
assert events[6].property is A.derived_b
assert events[7].property is A.b3

# Add b3's value to b2, should not emit derived union event
a.b2 = a.b3
assert len(events) == 9, len(events)
assert events[8].property is A.b2

# Remove b3's value to b2
del a.b2[a.b3]
assert len(events) == 10, len(events)
assert events[9].property is A.b2

a.b3 = A()
assert len(events) == 13, len(events)
assert events[10].property is A.derived_b
assert isinstance(events[10], DerivedDeleted), type(events[10])
assert events[11].property is A.derived_b
assert isinstance(events[11], DerivedAdded), type(events[11])
assert events[12].property is A.b3

del a.b3
assert len(events) == 15, len(events)
assert events[13].property is A.derived_b
assert isinstance(events[13], DerivedDeleted), type(events[10])
assert events[14].property is A.b3
finally:
Application.unregister_handler(handler)


@pytest.mark.skip
def test_redefine():
from gaphor.application import Application

class A(Element):
is_unlinked = False

def unlink(self):
self.is_unlinked = True
super().unlink()

A.a = association("a", A, upper=1)

A.a = redefine(A, "a", A, A.a)
events = []

@event_handler(AssociationUpdated)
def handler(event, events=events):
events.append(event)

Application.register_handler(handler)
try:
a = A()
a.a = A()
assert len(events) == 2
assert events[0].property is A.a, events[0].property
assert events[1].property is A.a.original, events[1].property
finally:
Application.unregister_handler(handler)


@pytest.mark.skip
def test_redefine_subclass():
class A(Element):
is_unlinked = False

def unlink(self):
self.is_unlinked = True
Element.unlink()

A.a = association("a", A, upper=1)

class B(A):
pass

B.b = redefine(B, "b", A, A.a)

events = []

@event_handler(AssociationUpdated)
def handler(event, events=events):
events.append(event)

Application.register_handler(handler)
try:
a = A()
a.a = A()
# Only a.a changes, no B class involved
assert len(events) == 1
assert events[0].property is A.a, events[0].property
# assert events[1].property is A.a.original, events[1].property
del events[:]

a = B()
a.a = A()
# Now events are sent for both association and redefine
assert len(events) == 2
assert events[0].property is B.b, events[0].property
assert events[1].property is B.b.original, events[1].property
finally:
Application.unregister_handler(handler)