Repository: pinetr2e/napkin

Issue:
group
How to group set of req and resp using python code in napkin?

Discussion:

Patch:
diff --git a/DEMO_EXAMPLES.md b/DEMO_EXAMPLES.md
index b8da20a..0b763ac 100644
--- a/DEMO_EXAMPLES.md
+++ b/DEMO_EXAMPLES.md
@@ -96,6 +96,34 @@ def ex_loop(c):
             with c.loop('until done'):
                 foo.func_other()
 
+```
+## Opt
+![UML result image](images/Opt.png)
+```python
+@napkin.seq_diagram('Opt')
+def ex_opt(c):
+    foo = c.object('Foo')
+    bar = c.object('Bar')
+    with c.opt():
+        with foo:
+            bar.func()
+            with c.opt('some condition'):
+                bar.func_other()
+
+```
+## Message grouping
+![UML result image](images/Message%20grouping.png)
+```python
+@napkin.seq_diagram('Message grouping')
+def ex_group(c):
+    foo = c.object('Foo')
+    bar = c.object('Bar')
+    with foo:
+        with c.group():
+            bar.func()
+        with c.group('own label'):
+            bar.func()
+
 ```
 ## Alt
 ![UML result image](images/Alt.png)
diff --git a/demo/demo_examples.py b/demo/demo_examples.py
index b79ab35..85b2750 100644
--- a/demo/demo_examples.py
+++ b/demo/demo_examples.py
@@ -81,6 +81,28 @@ def ex_loop(c):
                 foo.func_other()
 
 
+@napkin.seq_diagram('Opt')
+def ex_opt(c):
+    foo = c.object('Foo')
+    bar = c.object('Bar')
+    with c.opt():
+        with foo:
+            bar.func()
+            with c.opt('some condition'):
+                bar.func_other()
+
+
+@napkin.seq_diagram('Message grouping')
+def ex_group(c):
+    foo = c.object('Foo')
+    bar = c.object('Bar')
+    with foo:
+        with c.group():
+            bar.func()
+        with c.group('own label'):
+            bar.func()
+
+
 @napkin.seq_diagram('Alt')
 def ex_alt(c):
     foo = c.object('Foo')
diff --git a/napkin/sd.py b/napkin/sd.py
index 5b4b429..b230c51 100644
--- a/napkin/sd.py
+++ b/napkin/sd.py
@@ -345,6 +345,9 @@ class Context(object):
     def choice(self, condition=None):
         return Frag(self, 'choice', condition)
 
+    def group(self, label=None):
+        return Frag(self, 'group', label)
+
     def enter_frag(self, frag):
         if self._current_call and self._current_call.ret_params:
             raise FragError('Current function already returned')


Test patch:
diff --git a/tests/test_gen_plantuml.py b/tests/test_gen_plantuml.py
index d50e12a..cdf07ed 100644
--- a/tests/test_gen_plantuml.py
+++ b/tests/test_gen_plantuml.py
@@ -338,4 +338,38 @@ participant bar
 
 foo -> bar : func()
 ... hello ...
+""")
+
+    def test_group(self, check):
+        def f(c):
+            foo = c.object('foo')
+            baz = c.object('baz')
+            with foo:
+                with c.group():
+                    baz.func()
+
+        check(f, """
+participant foo
+participant baz
+
+group
+foo -> baz : func()
+end
+""")
+
+    def test_group_with_label(self, check):
+        def f(c):
+            foo = c.object('foo')
+            baz = c.object('baz')
+            with foo:
+                with c.group('label'):
+                    baz.func()
+
+        check(f, """
+participant foo
+participant baz
+
+group label
+foo -> baz : func()
+end
 """)
diff --git a/tests/test_sd_frag.py b/tests/test_sd_frag.py
index 20105dc..865f656 100644
--- a/tests/test_sd_frag.py
+++ b/tests/test_sd_frag.py
@@ -292,3 +292,22 @@ class TestAlt(TestBase):
             sd_action.FragEnd('choice'),
             sd_action.FragEnd('alt'),
         ])
+
+
+class TestGroup(TestBase):
+    def test_top_level(self):
+        c = sd.Context()
+
+        foo = c.object('foo')
+        bar = c.object('bar')
+
+        with c.group():
+            with foo:
+                bar.func()
+
+        self.check(c, [
+            sd_action.FragBegin('group'),
+            sd_action.Call(foo, bar, 'func', sd.Params()),
+            sd_action.ImplicitReturn(),
+            sd_action.FragEnd('group'),
+        ])