PEAK-rules : possible improvements to @when and use case for peak rules

Sébastien de Menten <[email protected]> Sat, 31 Aug 2013 08:19:25 +0200
Newsgroups gmane.comp.python.peak
Message-ID <CAB2pxDv5XbNxR=RBzer_V-AQQFwZb76uR4RO17ozvZCPG5aCSw@mail.gmail.com>
--===============0880106705==
Content-Type: multipart/alternative; boundary=047d7bfe97e018e9c104e5385201

--047d7bfe97e018e9c104e5385201
Content-Type: text/plain; charset=windows-1252
Content-Transfer-Encoding: quoted-printable

Hello,

I have two questions on PEAK-rules where I would more than happy to have
your opinion/advice.

First the simple one: when using the @when(multimethod_function, "condition
in a string") decorator, i find the "condition in string" syntax slightly
annoying as it is not recognised by the IDE or other code inspector (flake,
etc). For the IDE point, it is not very readable as there is not syntax
coloring and the autocompletion feature (and other refactoring features)
does not work ideally. For the code inspector, it detects falsely that some
imports are unused as they are in fact only used in the string.

 Could there be an alternative? I was thinking along in the lines of a
when_inside decorator working in the following spirit:

 from peak.rules import when, abstract

@abstract
def foo(a, b):
    pass

@when(foo, "a>4 and b<56")
def foo(a, b):
    "This function does blabla"

    for i in range(5):
        print i


@*when_inside*(foo)  # this would be equivalent to the previous definition
def foo(a, b):
    "This function does blabla"
    *a>5 and b<56*     # the condition that normally is the 2nd argument of
when is the first line of code (maybe with an "assert a>5 and b<56" if it
helps)

    for i in range(5):
        print i

*@foo.when*     # this would be even simpler and still equivalent to the
previous definition
def foo(a, b):
    "This function does blabla"
    *a>5 and b<56*     # the condition that normally is the 2nd argument of
when is the first line of code (maybe with an "assert a>5 and b<56" if it
helps)
     for i in range(5):
        print i

The decorator would thus extract and analyse the first code line of the
function (maybe using the meta package (https://pypi.python.org/pypi/meta)
with meta.dump_python_source(meta.decompile(foo.func_code)).split("\n")[1]
to get it)) to get the condition.
In your opinion, is this meaningful/useful ? but also doable ?

My second question is related to the use case for peak rules.
I am using peak-rules in a project essentially to replace standard object
methods in a system with a lot of composition of objects with inheritance.
So I have a class Operation which instances have two attributes which are
instances of two other classes Source and Destination. So the "abstract"
class looks like:
Class Operation:
            source =3D None (but should be an instance of Source)
            destination =3D None (but should be an instance of Destination)
then I can subclass Operation to add new attributes/meaning for the class
and the same for Source and Destination.
After that, I have an engine that must interpret (=3Ddo calculation on) the
Operation with its Source and Destination and the interpretation is
dependent on the 3 objects (operation, source and destination).
I use peak.rules to dispatch to the correct algorithm in function of the
conditions like:
@abstract
def interpret(operation):
    pass

@when(interpret, =93isinstance(operation, SubOperationOfTypeZ) and
isinstance(operation.source, SubTypeWOfSource) and
operation.source.date_of_creation.month < 5=94)
def interpret(operation):
    return =93blabla=94

Is this usage of peak.rules OK ? would you use a different pattern ? My
feeling it is that it is one of the use of generic functions methods ...
but i have no practical experience with them.

Sebastien

--047d7bfe97e018e9c104e5385201
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: quoted-printable

<span style=3D"font-family:arial,helvetica,sans-serif">Hello,</span><br>
<div><font face=3D"arial,helvetica,sans-serif">=A0</font></div>
<div><font face=3D"arial,helvetica,sans-serif">I have two questions on=A0PE=
AK-rules=A0where I would more than happy to have your opinion/advice.</font=
></div>
<p><font face=3D"arial,helvetica,sans-serif">First the simple one: when=A0u=
sing the @when(multimethod_function, &quot;condition in a string&quot;) dec=
orator, i find the &quot;condition in string&quot; syntax slightly annoying=
 as it is not recognised by the IDE or other code inspector (flake, etc). F=
or the IDE=A0point, it is not very readable as there is not syntax coloring=
 and the autocompletion feature (and other refactoring features) does not w=
ork ideally. For the code inspector, it detects falsely that some imports a=
re unused as they are in fact only used in the string. </font></p>


<p><font face=3D"arial,helvetica,sans-serif">=A0Could=A0there be=A0an alter=
native? I was thinking along in the lines of a when_inside decorator workin=
g in the following spirit:</font></p>
<blockquote style=3D"MARGIN-RIGHT:0px" dir=3D"ltr">
<blockquote style=3D"MARGIN-RIGHT:0px" dir=3D"ltr">
<p><font face=3D"arial,helvetica,sans-serif">from peak.rules import when, a=
bstract</font></p>
<p><font face=3D"arial,helvetica,sans-serif">@abstract </font>
</p><div><font face=3D"arial,helvetica,sans-serif">def foo(a, b):</font></d=
iv>
<div><font face=3D"arial,helvetica,sans-serif">=A0=A0=A0 pass</font></div>
<p><font face=3D"arial,helvetica,sans-serif">@when(foo, &quot;a&gt;4 and b&=
lt;56&quot;) </font>
</p><div><font face=3D"arial,helvetica,sans-serif">def foo(a, b):</font></d=
iv>
<div><font face=3D"arial,helvetica,sans-serif">=A0=A0=A0 &quot;This functio=
n does blabla&quot;</font></div>
<div><font face=3D"arial,helvetica,sans-serif">=A0=A0=A0 =A0</font></div>
<div><font face=3D"arial,helvetica,sans-serif">=A0=A0=A0 for i in range(5):=
</font></div>
<div><font face=3D"arial,helvetica,sans-serif">=A0=A0=A0=A0=A0=A0=A0 print =
i</font></div>
<div><font face=3D"arial,helvetica,sans-serif">=A0=A0=A0=A0=A0=A0=A0 =A0</f=
ont></div>
<p><font face=3D"arial,helvetica,sans-serif">@<strong>when_inside</strong>(=
foo)=A0 # this would be equivalent to the previous definition </font>
</p><div><font face=3D"arial,helvetica,sans-serif">def foo(a, b):</font></d=
iv>
<div><font face=3D"arial,helvetica,sans-serif">=A0=A0=A0 &quot;This functio=
n does blabla&quot;</font></div>
<div><font face=3D"arial,helvetica,sans-serif">=A0=A0=A0 <strong>a&gt;5 and=
 b&lt;56</strong>=A0=A0=A0=A0 # the condition that normally is the 2nd argu=
ment of when is the first line of code (maybe with an &quot;assert a&gt;5 a=
nd b&lt;56&quot; if it helps)</font></div>


<div><font face=3D"arial,helvetica,sans-serif">=A0=A0=A0 =A0</font></div>
<div><font face=3D"arial,helvetica,sans-serif">=A0=A0=A0 for i in range(5):=
</font></div>
<div><font face=3D"arial,helvetica,sans-serif">=A0=A0=A0=A0=A0=A0=A0 print =
i </font>
<div><font face=3D"arial,helvetica,sans-serif">=A0</font></div>
<div><font face=3D"arial,helvetica,sans-serif"><strong>@foo.when</strong>=
=A0=A0=A0=A0 # this would be even simpler and still equivalent to the previ=
ous definition</font></div>
<div><font face=3D"arial,helvetica,sans-serif">def foo(a, b):</font></div>
<div><font face=3D"arial,helvetica,sans-serif">=A0=A0=A0 &quot;This functio=
n does blabla&quot;</font></div>
<div><font face=3D"arial,helvetica,sans-serif">=A0=A0=A0 <strong>a&gt;5 and=
 b&lt;56</strong>=A0=A0=A0=A0 # the condition that normally is the 2nd argu=
ment of when is the first line of code (maybe with an &quot;assert a&gt;5 a=
nd b&lt;56&quot; if it helps)</font></div>

</div>
<div><font face=3D"arial,helvetica,sans-serif">=A0=A0=A0 for i in range(5):=
 </font>
<div><font face=3D"arial,helvetica,sans-serif">=A0=A0=A0=A0=A0=A0=A0 print =
i</font></div></div><p></p><p></p><p></p></blockquote></blockquote>
<div dir=3D"ltr"><font face=3D"arial,helvetica,sans-serif">The decorator wo=
uld thus extract and=A0analyse the first code line of the function (maybe u=
sing the meta package (</font><a href=3D"https://pypi.python.org/pypi/meta"=
 target=3D"_blank"><font face=3D"arial,helvetica,sans-serif">https://pypi.p=
ython.org/pypi/meta</font></a><font face=3D"arial,helvetica,sans-serif">) w=
ith meta.dump_python_source(meta.decompile(foo.func_code)).split(&quot;\n&q=
uot;)[1] to get it)) to get the condition.</font></div>


<div dir=3D"ltr"><font face=3D"arial,helvetica,sans-serif">In your opinion,=
 is this meaningful/useful ? but also doable ?</font></div>
<div style=3D"LINE-HEIGHT:normal;MARGIN:0cm 0cm 10pt" class=3D"MsoNormal"><=
span style=3D"FONT-FAMILY:&#39;Times New Roman&#39;,&#39;serif&#39;"><font =
face=3D"arial,helvetica,sans-serif"></font></span>=A0</div>
<div style=3D"LINE-HEIGHT:normal;MARGIN:0cm 0cm 10pt" class=3D"MsoNormal"><=
span style=3D"FONT-FAMILY:&#39;Times New Roman&#39;,&#39;serif&#39;"><font =
face=3D"arial,helvetica,sans-serif">My second question is related to the us=
e case for peak rules.</font></span></div>


<div style=3D"LINE-HEIGHT:normal;MARGIN:0cm 0cm 10pt" class=3D"MsoNormal"><=
span style=3D"FONT-FAMILY:&#39;Times New Roman&#39;,&#39;serif&#39;"><font =
face=3D"arial,helvetica,sans-serif">I am using peak-rules in a project esse=
ntially to replace standard object methods in a system with a lot of compos=
ition of objects with inheritance. So I have a class Operation which instan=
ces have two attributes which are instances of two other classes Source and=
 Destination. So the &quot;abstract&quot; class looks like:</font></span></=
div>


<div style=3D"LINE-HEIGHT:normal;MARGIN:0cm 0cm 10pt" class=3D"MsoNormal"><=
span style=3D"FONT-FAMILY:&#39;Times New Roman&#39;,&#39;serif&#39;"><font =
face=3D"arial,helvetica,sans-serif">Class Operation:</font></span></div>
<div style=3D"LINE-HEIGHT:normal;MARGIN:0cm 0cm 10pt" class=3D"MsoNormal"><=
span style=3D"FONT-FAMILY:&#39;Times New Roman&#39;,&#39;serif&#39;"><font =
face=3D"arial,helvetica,sans-serif"><span>=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=
 </span>source =3D None (but should be an instance of Source)</font></span>=
</div>


<div style=3D"LINE-HEIGHT:normal;MARGIN:0cm 0cm 10pt" class=3D"MsoNormal"><=
span style=3D"FONT-FAMILY:&#39;Times New Roman&#39;,&#39;serif&#39;"><font =
face=3D"arial,helvetica,sans-serif"><span>=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=
 </span>destination =3D None (but should be an instance of Destination)</fo=
nt></span></div>


<div style=3D"LINE-HEIGHT:normal;MARGIN:0cm 0cm 10pt" class=3D"MsoNormal"><=
span style=3D"FONT-FAMILY:&#39;Times New Roman&#39;,&#39;serif&#39;"><font =
face=3D"arial,helvetica,sans-serif">then I can subclass Operation to add ne=
w attributes/meaning for the class and the same for Source and Destination.=
</font></span></div>


<div style=3D"LINE-HEIGHT:normal;MARGIN:0cm 0cm 10pt" class=3D"MsoNormal"><=
span style=3D"FONT-FAMILY:&#39;Times New Roman&#39;,&#39;serif&#39;"><font =
face=3D"arial,helvetica,sans-serif">After that, I have an engine that must =
interpret (=3Ddo calculation on) the Operation with its Source and Destinat=
ion and the interpretation is dependent on the 3 objects (operation, source=
 and destination).</font></span></div>


<div style=3D"LINE-HEIGHT:normal;MARGIN:0cm 0cm 10pt" class=3D"MsoNormal"><=
span style=3D"FONT-FAMILY:&#39;Times New Roman&#39;,&#39;serif&#39;"><font =
face=3D"arial,helvetica,sans-serif">I use peak.rules to dispatch to the cor=
rect algorithm in function of the conditions like:</font></span></div>


<div style=3D"LINE-HEIGHT:normal;MARGIN:0cm 0cm 10pt" class=3D"MsoNormal"><=
span style=3D"FONT-FAMILY:&#39;Courier New&#39;"><font face=3D"arial,helvet=
ica,sans-serif">@abstract</font></span></div>
<div style=3D"LINE-HEIGHT:normal;MARGIN:0cm 0cm 10pt" class=3D"MsoNormal"><=
span style=3D"FONT-FAMILY:&#39;Courier New&#39;"><font face=3D"arial,helvet=
ica,sans-serif">def interpret(operation):</font></span></div>
<div style=3D"LINE-HEIGHT:normal;MARGIN:0cm 0cm 10pt" class=3D"MsoNormal"><=
span style=3D"FONT-FAMILY:&#39;Courier New&#39;"><font face=3D"arial,helvet=
ica,sans-serif">=A0=A0=A0 pass</font></span></div>
<div style=3D"LINE-HEIGHT:normal;MARGIN:0cm 0cm 10pt" class=3D"MsoNormal"><=
span style=3D"FONT-FAMILY:&#39;Courier New&#39;"><font face=3D"arial,helvet=
ica,sans-serif"></font></span>=A0</div>
<div style=3D"LINE-HEIGHT:normal;MARGIN:0cm 0cm 10pt" class=3D"MsoNormal"><=
span style=3D"FONT-FAMILY:&#39;Courier New&#39;"><font face=3D"arial,helvet=
ica,sans-serif">@when(interpret, =93isinstance(operation, SubOperationOfTyp=
eZ) and isinstance(operation.source, SubTypeWOfSource) and operation.source=
.date_of_creation.month &lt; 5=94)</font></span></div>


<div style=3D"LINE-HEIGHT:normal;MARGIN:0cm 0cm 10pt" class=3D"MsoNormal"><=
span style=3D"FONT-FAMILY:&#39;Courier New&#39;"><font face=3D"arial,helvet=
ica,sans-serif">def interpret(operation):</font></span></div>
<div style=3D"LINE-HEIGHT:normal;MARGIN:0cm 0cm 10pt" class=3D"MsoNormal"><=
span style=3D"FONT-FAMILY:&#39;Courier New&#39;"><font face=3D"arial,helvet=
ica,sans-serif">=A0=A0=A0 return =93blabla=94</font></span></div>
<div style=3D"LINE-HEIGHT:normal;MARGIN:0cm 0cm 10pt" class=3D"MsoNormal"><=
span style=3D"FONT-FAMILY:&#39;Courier New&#39;"><font face=3D"Arial"></fon=
t></span>=A0</div>
<div style=3D"LINE-HEIGHT:normal;MARGIN:0cm 0cm 10pt" class=3D"MsoNormal"><=
span style=3D"FONT-FAMILY:&#39;Courier New&#39;"><font face=3D"Arial">Is th=
is usage of peak.rules OK ? would you use a different pattern=A0? My feelin=
g it is that it is one of the use of generic functions=A0methods ... but i =
have no practical experience with them.=A0</font></span></div>
<div style=3D"LINE-HEIGHT:normal;MARGIN:0cm 0cm 10pt" class=3D"MsoNormal"><=
br></div><div style=3D"LINE-HEIGHT:normal;MARGIN:0cm 0cm 10pt" class=3D"Mso=
Normal"><span style=3D"FONT-FAMILY:&#39;Courier New&#39;"><font face=3D"Ari=
al">Sebastien</font></span></div>

<br>

--047d7bfe97e018e9c104e5385201--

--===============0880106705==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
PEAK mailing list
[email protected]
http://www.eby-sarna.com/mailman/listinfo/peak
--===============0880106705==--