Re: Annotation support

"Caleb P. Burns" <[email protected]>
Newsgroups gmane.comp.lang.jython.devel
Message-ID <CAOxVj+TkRXpBSZF3g76V=_9VNv2dAKvZK6fQZu3_7GYcTcEFCg@mail.gmail.com>
Jim,

Thank you for the direction.

I have another question for you or the other Jython developers.

An overload for `org.python.compiler.ProxyMaker#addMethod` is documented as
follows:

    /**
     * Adds a method of the given name to the class being implemented. If
     * <code>declaringClass</code> is null, the generated method will
expect to find an object of
     * the method's name in the Python object and call it. If it isn't
null, if an object is found
     * in the Python object, it'll be called. Otherwise the superclass will
be called. No checking
     * is done to guarantee that the superclass has a method with the same
signature.
     */
    public void addMethod(String name,
                          Class<?> ret,
                          Class<?>[] parameters,
                          Class<?>[] exceptions,
                          int access,
                          Class<?> declaringClass) throws Exception {
        addMethod(name, name, ret, parameters, exceptions, access,
declaringClass, null, null);
    }

My understanding is this indicates *declaringClass* can be null so long as
the name exists on the Python object. This directly passes the arguments
(with null annotations) to:

    /**
     * Generates and adds a proxy method to the proxy class
     *
     * @param name: name of the java method
     * @param pyName: name of the python method to which the java method
     * proxies (useful for clamped objects)
     *
     * @param ret: return type
     * @param parameters: parameter types
     * @param exceptions: throwable exception types
     * @param access
     * @param declaringClass
     * @param methodAnnotations: method annotations
     * @param parameterAnnotations: parameter annotations
     * @throws Exception
     */
    public void addMethod(String name,
                          String pyName,
                          Class<?> ret,
                          Class<?>[] parameters,
                          Class<?>[] exceptions,
                          int access,
                          Class<?> declaringClass,
                          AnnotationDescr[] methodAnnotations,
                          AnnotationDescr[][]parameterAnnotations) throws
Exception {

So, if I have a Python class similar to the following:

    @clamp.clamp_class('org.example')
    class Test(java.lang.Object):

        @clamp.method(java.lang.Integer)
        def foo(self):
            return 42

`ProxyMaker#addMethod` will end up being called for `foo`:

    # self is an instance of a subclass of ProxyMaker.
    self.addMethod('foo', # String name
                   'foo', # String pyName
                   java.lang.Integer, # Class<?> ret
                   [], # Class<?>[] parameters
                   [], # Class<?>[] exceptions
                   java.lang.reflect.Modifier.PUBLIC, # int access
                   None, # Class<?> declaringClass
                   None, # AnnotationDescr[] methodAnnotations
                   None) # AnnotationDescr[][] parameterAnnotations

However, this raises a `NullPointerException` because *declaringClass*:

    Traceback (most recent call last):
      File "test_setup.py", line 83, in <module>
        setup(
      File "/usr/local/lib/jython2.7b3/Lib/distutils/core.py", line 152, in
setup
        dist.run_commands()
      File "/usr/local/lib/jython2.7b3/Lib/distutils/core.py", line 152, in
setup
        dist.run_commands()
      File "/usr/local/lib/jython2.7b3/Lib/distutils/dist.py", line 953, in
run_commands
        self.run_command(cmd)
      File "/usr/local/lib/jython2.7b3/Lib/distutils/dist.py", line 972, in
run_command
        cmd_obj.run()
      File "../clamp/commands.py", line 84, in run
        build_jar(self.distribution.metadata.get_name(),
      File "../clamp/build.py", line 393, in build_jar
        __import__(module)
      File
"/home/caleb/Dropbox/Projects/jython-clamp/cpburnz/test/org/python/__init__.py",
line 33, in <module>
        @clamp.clamp_class('org.example')
      File "../clamp/declarative.py", line 118, in class_decorator
        return ClampProxyMakerMeta(target.__name__, tuple(bases),
dict(vars(target)))
      File "../clamp/declarative.py", line 115, in __new__
        return type.__new__(mcs, name, bases, newdct)
            at
org.python.compiler.ProxyCodeHelpers.mapClass(ProxyCodeHelpers.java:89)
            at org.python.compiler.ProxyMaker.addMethod(ProxyMaker.java:367)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
            at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:606)

    java.lang.NullPointerException: java.lang.NullPointerException

Upon examination of `ProxyMaker#addMethod`, so long as the method is not
abstract, then it will call `org.python.compiler.ProxyCodeHelpers#mapClass`
as:

    String superClass = mapClass(declaringClass);

Is this an error in the documentation about *declaringClass*? Or with the
implementation or my understanding of `ProxyMaker#addMethod`?

Thanks,
Caleb Burns

On Tue, Sep 23, 2014 at 9:34 PM, Jim Baker <[email protected]> wrote:

> Caleb,
>
> This is a great question! So there are two annotation/decorator scenarios
> to consider:
>
> *Clamp-specific Python decorators. *This is what you mentioned in
> http://clamp.readthedocs.org/en/latest/clamp.html; they are not yet
> supported in Clamp! Darjus Loktevic (cc-ed) has been playing with this
> approach, so I will let him speak to any specifics in terms of what
> progress he has made. However, the basic idea is that we can generate the
> Java method type signatures based on these decorators, without requiring
> that the Python class implements Java interface(s) and/or extends a Java
> class.
>
> In terms of implementation, presumably this should start with
> ClampProxyMakerMeta as defined in clamp.declarative. This metaclass, which
> has a construction inspired by SQLAlchemy, could be further refined such
> that it can access any metadata that the Clamp-specific decorators record
> for a class to be constructed (code that would need to be written!), then
> generating appropriate type signatures via
> org.python.compiler.ProxyMaker#addMethod
>
> *Java annotations as Python decorators*. This is the idea that I describe
> in some detail
> https://github.com/jythontools/clamp#supporting-java-annotations
> for ensuring that Python classes/methods have appropriate Java annotation
> metadata.
>
>
> Pull requests are certainly welcome. But perhaps even more important, we
> really need to first add unit tests to Clamp, beyond some simple functional
> testing provided by the Clamped companion project. (The current
> implementation of Clamp started out as a very useful spike... sorry about
> that!)
>
> - Jim
>
> On Tue, Sep 23, 2014 at 7:03 AM, Caleb P. Burns <[email protected]> wrote:
>
>> Jython developers,
>>
>> How relevant are the docs for v0.1 of Clamp over at <
>> http://clamp.readthedocs.org/en/latest/clamp.html>? It describes
>> decorators such as `clamp.method` and `clamp.annotated`. The current
>> version of Clamp (0.4) has no mention to these decorators.
>>
>> I am working on adding basic support for Java annotations into Clamp. At
>> the moment I have annotations for classes working with a decorator
>> (`clamp.annotated`). However, I am stuck on how to approach implementing
>> them for Python methods. Arbitrary python methods don't get exported. And
>> before one can export a python method, it needs to have a useful Java
>> return type and parameter types. Is it desired to have a decorator such as
>> `clamp.method` to specify its signature?
>>
>> Any help or advice would be greatly appreciated.
>>
>> Caleb Burns
>>
>>
>> ------------------------------------------------------------------------------
>> Meet PCI DSS 3.0 Compliance Requirements with EventLog Analyzer
>> Achieve PCI DSS 3.0 Compliant Status with Out-of-the-box PCI DSS Reports
>> Are you Audit-Ready for PCI DSS 3.0 Compliance? Download White paper
>> Comply to PCI DSS 3.0 Requirement 10 and 11.5 with EventLog Analyzer
>>
>> http://pubads.g.doubleclick.net/gampad/clk?id=154622311&iu=/4140/ostg.clktrk
>> _______________________________________________
>> Jython-dev mailing list
>> [email protected]
>> https://lists.sourceforge.net/lists/listinfo/jython-dev
>>
>>
>
>
> --
> - Jim
>
> jim.baker@{colorado.edu|python.org|rackspace.com|zyasoft.com}
> twitter.com/jimbaker
> github.com/jimbaker
> bitbucket.com/jimbaker
>

------------------------------------------------------------------------------
Meet PCI DSS 3.0 Compliance Requirements with EventLog Analyzer
Achieve PCI DSS 3.0 Compliant Status with Out-of-the-box PCI DSS Reports
Are you Audit-Ready for PCI DSS 3.0 Compliance? Download White paper
Comply to PCI DSS 3.0 Requirement 10 and 11.5 with EventLog Analyzer
http://pubads.g.doubleclick.net/gampad/clk?id=154622311&iu=/4140/ostg.clktrk

_______________________________________________
Jython-dev mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jython-dev
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.