On 4/4/06, Joel Hedlund <[EMAIL PROTECTED]> wrote:
You can do the same things with jython. You can in your script (as it reloads automatically at runtime) do something as dir(editor) to see the PyEdit methods. Another option would be checking the code itself... I still don't have a good developers guide to explain how to download the code and make the project (altough there is a very 'simple' comment at http://pydev.sourceforge.net/roadmap.html on how to do it).
The 'catch' is that in jython not all things behave exactly as you'd expect, so, you have to make dir(editor.__class__)
Well, if you download the code for pydev and create the project you should be able to grab all. So, now that I put all in place, I realized that I have not generated the javadocs for Pydev, so, there is still no default place for it. I'll try to set the developers guide and put the javadocs for it (I'm currently fixing some other bugs, so, if someone else was able to do it, it would be great, otherwise, in about 2-3 weeks I'll try to set it up).
Well, actually you'd do something such as editor.getDocument() and change things in the returned document (the PySelection is a wrapper to help on many things, as the document interface is kind of 'raw') .
Hope that too!
Yeah, Jython support to inspect is kind of poor...
So, you'd do dir(editor.__class__), but it might not get all, just for the class, and not superclasses.
I'm attaching 2 examples that should how you'd get all the members (that's actually taken from the pydev code-completion stuff).
-- just copy and paste in a clean example to see how it would get all the members for the editor.
Cheers,
Fabio
Hi!
I'm trying learn Jython scripting for PyDev in order to implement feature
request #1450378 (mine :-).
http://sourceforge.net/tracker/index.php?func=detail&aid=1450378&group_id=85796&atid=577332
Fabio gave me a neat starter guide and a code example from the cvs java source
(see feature request page above), but I've got a few questions before I can
start getting productive.
1) How do I find out PyEdit object methods and data members?
What is the best way of finding out the available members and data methods of
an object in Jython scripts for PyDev? I'm a CPython programmer and I'm used to
having dir(), help() and the inspect module for peeking into strange objects,
but none of them seems to do me any good here. Afaik the help() function is not
implemented in Jython 2.1, but why can't I import the inspect module? Also, why
does dir(editor) return an empty list? (example at the end) What's the
recommended way of finding out information on object methods and data members
in Jython?
You can do the same things with jython. You can in your script (as it reloads automatically at runtime) do something as dir(editor) to see the PyEdit methods. Another option would be checking the code itself... I still don't have a good developers guide to explain how to download the code and make the project (altough there is a very 'simple' comment at http://pydev.sourceforge.net/roadmap.html on how to do it).
The 'catch' is that in jython not all things behave exactly as you'd expect, so, you have to make dir(editor.__class__)
2) Where do I find the source for the relevant superclasses?
I tried browsing the PyDev source cvs for the answer to my previous question,
but as I'm not a java black belt I feel a little disoriented. PyEdit objects
apparently have a .getSite() method (line 32 in pyedit_example2.py in the
starter guide), but the org.python.pydev.editor.PyEdit class does not define it.
http://cvs.sourceforge.net/viewcvs.py/pydev/org.python.pydev/src/org/python/pydev/editor/PyEdit.java?rev=1.91&view=markup
PyEdit implements IPyEdit, but how do I get to the source for it (or some docs)?
Well, if you download the code for pydev and create the project you should be able to grab all. So, now that I put all in place, I realized that I have not generated the javadocs for Pydev, so, there is still no default place for it. I'll try to set the developers guide and put the javadocs for it (I'm currently fixing some other bugs, so, if someone else was able to do it, it would be great, otherwise, in about 2-3 weeks I'll try to set it up).
3) How do I affect code in the editor with only a PyEdit object?
From the starter guide I understand that Pydev scripts communicate with PyDev
using an editor object, but the code example I got from Fabio apparently does
not. Instead it uses a PySelection object that it gets as its first argument.
The PyEdit argument is apparently not used.
Well, actually you'd do something such as editor.getDocument() and change things in the returned document (the PySelection is a wrapper to help on many things, as the document interface is kind of 'raw') .
This Jython scripting thing seems really powerful and I hope I'll be able to
produce some nifty things with it once I'm up to speed.
Hope that too!
Example:
$PYEDIT_SCRIPTS/pyedit_test.py:
---------------------------------------------------------------------
assert cmd is not None
assert editor is not None
dir(editor)
import inspect
---------------------------------------------------------------------
Yeah, Jython support to inspect is kind of poor...
So, you'd do dir(editor.__class__), but it might not get all, just for the class, and not superclasses.
I'm attaching 2 examples that should how you'd get all the members (that's actually taken from the pydev code-completion stuff).
-- just copy and paste in a clean example to see how it would get all the members for the editor.
Cheers,
Fabio
import java
def dirObj(obj):
ret = []
found = java.util.HashMap()
original = obj
if hasattr(obj, '__class__') and obj.__class__ == java.lang.Class:
#get info about superclasses
classes = []
classes.append(obj)
c = obj.getSuperclass()
while c != None:
classes.append(c)
c = c.getSuperclass()
#get info about interfaces
interfs = []
for obj in classes:
interfs.extend(obj.getInterfaces())
classes.extend(interfs)
#now is the time when we actually get info on the declared methods and
fields
for obj in classes:
declaredMethods = obj.getDeclaredMethods()
declaredFields = obj.getDeclaredFields()
for i in range(len(declaredMethods)):
name = declaredMethods[i].getName()
ret.append(name)
found.put(name, 1)
for i in range(len(declaredFields)):
name = declaredFields[i].getName()
ret.append(name)
found.put(name, 1)
#this simple dir does not always get all the info, that's why we have the
part before
#(e.g.: if we do a dir on String, some methods that are from other
interfaces such as
#charAt don't appear)
d = dir(original)
for name in d:
if found.get(name) is not 1:
ret.append(name)
return ret
for p in dirObj(editor.__class__):
print p
import StringIO
import traceback
from java.lang import StringBuffer
from java.lang import String
import java.lang
import sys
from org.python.core import PyReflectedFunction
from org.python import core
#completion types.
TYPE_UNKNOWN = -1
TYPE_IMPORT = 0
TYPE_CLASS = 1
TYPE_FUNCTION = 2
TYPE_ATTR = 3
TYPE_BUILTIN = 4
TYPE_PARAM = 5
TYPE_BUILTIN_AS_STR = '4'
def _imp(name):
try:
return __import__(name)
except:
if '.' in name:
sub = name[0:name.rfind('.')]
return _imp(sub)
else:
s = 'Unable to import module: %s - sys.path: %s' % (str(name),
sys.path)
raise RuntimeError(s)
def Find( name ):
f = None
if name.startswith('__builtin__'):
if name == '__builtin__.str':
name = 'org.python.core.PyString'
elif name == '__builtin__.dict':
name = 'org.python.core.PyDictionary'
mod = _imp(name)
if hasattr(mod, '__file__'):
f = mod.__file__
components = name.split('.')
for comp in components[1:]:
mod = getattr(mod, comp)
if hasattr(mod, '__file__'):
f = mod.__file__
return f, mod
def formatParamClassName(paramClassName):
if paramClassName.startswith('['):
if paramClassName == '[C':
paramClassName = 'char[]'
elif paramClassName == '[B':
paramClassName = 'byte[]'
elif paramClassName == '[I':
paramClassName = 'int[]'
elif paramClassName.startswith('[L') and paramClassName.endswith(';'):
paramClassName = paramClassName[2:-1]
paramClassName += '[]'
return paramClassName
def GenerateTip( data ):
data = data.replace( '\n', '' )
if data.endswith( '.' ):
data = data.rstrip( '.' )
f, mod = Find( data )
tips = GenerateImportsTipForModule( mod )
return f, tips
class Info:
def __init__(self, name, **kwargs):
self.name = name
self.doc = kwargs.get('doc', None)
self.args = kwargs.get('args', ()) #tuple of strings
self.varargs = kwargs.get('varargs', None) #string
self.kwargs = kwargs.get('kwargs', None) #string
self.ret = kwargs.get('ret', None) #string
def basicAsStr(self):
'''@returns this class information as a string (just basic format)
'''
s = 'function:%s args=%s, varargs=%s, kwargs=%s, docs:%s' % \
(str(self.name), str( self.args), str( self.varargs), str(
self.kwargs), str( self.doc))
return s
def getAsDoc(self):
s = str(self.name)
if self.doc:
s+='[EMAIL PROTECTED] %s\n' % str(self.doc)
if self.args:
s+='[EMAIL PROTECTED] '
for arg in self.args:
s+=str(formatParamClassName(arg))
s+=' '
if self.varargs:
s+='[EMAIL PROTECTED] '
s+=str(self.varargs)
if self.kwargs:
s+='[EMAIL PROTECTED] '
s+=str(self.kwargs)
if self.ret:
s+='[EMAIL PROTECTED] '
s+=str(formatParamClassName(str(self.ret)))
return str(s)
def isclass(cls):
return isinstance(cls, core.PyClass)
def ismethod(func):
'''this function should return the information gathered on a function
@param func: this is the function we want to get info on
@return a tuple where:
0 = indicates whether the parameter passed is a method or not
1 = a list of classes 'Info', with the info gathered from the function
this is a list because when we have methods from java with the same
name and different signatures,
we actually have many methods, each with its own set of arguments
'''
try:
if isinstance(func, core.PyFunction):
#ok, this is from python, created by jython
#print ' PyFunction'
def getargs(func_code):
"""Get information about the arguments accepted by a code
object.
Three things are returned: (args, varargs, varkw), where 'args'
is
a list of argument names (possibly containing nested lists), and
'varargs' and 'varkw' are the names of the * and ** arguments
or None."""
nargs = func_code.co_argcount
names = func_code.co_varnames
args = list(names[:nargs])
step = 0
varargs = None
if func_code.co_flags & func_code.CO_VARARGS:
varargs = func_code.co_varnames[nargs]
nargs = nargs + 1
varkw = None
if func_code.co_flags & func_code.CO_VARKEYWORDS:
varkw = func_code.co_varnames[nargs]
return args, varargs, varkw
args = getargs(func.func_code)
return 1, [Info(func.func_name, args = args[0], varargs = args[1],
kwargs = args[2], doc = func.func_doc)]
if isinstance(func, core.PyMethod):
#this is something from java itself, and jython just wrapped it...
#things to play in func:
#['__call__', '__class__', '__cmp__', '__delattr__', '__dir__',
'__doc__', '__findattr__', '__name__', '_doget', 'im_class',
#'im_func', 'im_self', 'toString']
#print ' PyMethod'
#that's the PyReflectedFunction... keep going to get it
func = func.im_func
if isinstance(func, PyReflectedFunction):
#this is something from java itself, and jython just wrapped it...
#print ' PyReflectedFunction'
infos = []
for i in range(len(func.argslist)):
#things to play in func.argslist[i]:
#'PyArgsCall', 'PyArgsKeywordsCall', 'REPLACE', 'StandardCall',
'args', 'compare', 'compareTo', 'data', 'declaringClass'
#'flags', 'isStatic', 'matches', 'precedence']
#print ' ', func.argslist[i].data.__class__
#func.argslist[i].data.__class__ == java.lang.reflect.Method
if func.argslist[i]:
met = func.argslist[i].data
name = met.getName()
try:
ret = met.getReturnType()
except AttributeError:
ret = ''
parameterTypes = met.getParameterTypes()
args = []
for j in range(len(parameterTypes)):
paramTypesClass = parameterTypes[j]
try:
try:
paramClassName = paramTypesClass.getName()
except:
paramClassName =
paramTypesClass.getName(paramTypesClass)
except AttributeError:
try:
paramClassName = repr(paramTypesClass) #should
be something like <type 'object'>
paramClassName = paramClassName.split('\'')[1]
except:
paramClassName = repr(paramTypesClass) #just in
case something else happens... it will at least be visible
#if the parameter equals [C, it means it it a char
array, so, let's change it
a = formatParamClassName(paramClassName)
#a = a.replace('[]','Array')
#a = a.replace('Object', 'obj')
#a = a.replace('String', 's')
#a = a.replace('Integer', 'i')
#a = a.replace('Char', 'c')
#a = a.replace('Double', 'd')
args.append(a) #so we don't leave invalid code
info = Info(name, args = args, ret = ret)
#print info.basicAsStr()
infos.append(info)
return 1, infos
except Exception, e:
s = StringIO.StringIO()
traceback.print_exc(file=s)
return 1, [Info(str('ERROR'), doc = s.getvalue())]
return 0, None
def ismodule(mod):
#java modules... do we have other way to know that?
if not hasattr(mod, 'getClass') and not hasattr(mod, '__class__') \
and hasattr(mod, '__name__'):
return 1
return isinstance(mod, core.PyModule)
def dirObj(obj):
ret = []
found = java.util.HashMap()
original = obj
if hasattr(obj, '__class__') and obj.__class__ == java.lang.Class:
#get info about superclasses
classes = []
classes.append(obj)
c = obj.getSuperclass()
while c != None:
classes.append(c)
c = c.getSuperclass()
#get info about interfaces
interfs = []
for obj in classes:
interfs.extend(obj.getInterfaces())
classes.extend(interfs)
#now is the time when we actually get info on the declared methods and
fields
for obj in classes:
declaredMethods = obj.getDeclaredMethods()
declaredFields = obj.getDeclaredFields()
for i in range(len(declaredMethods)):
name = declaredMethods[i].getName()
ret.append(name)
found.put(name, 1)
for i in range(len(declaredFields)):
name = declaredFields[i].getName()
ret.append(name)
found.put(name, 1)
#this simple dir does not always get all the info, that's why we have the
part before
#(e.g.: if we do a dir on String, some methods that are from other
interfaces such as
#charAt don't appear)
d = dir(original)
for name in d:
if found.get(name) is not 1:
ret.append(name)
return ret
def formatArg(arg):
'''formats an argument to be shown
'''
s = str( arg )
dot = s.rfind('.')
if dot >= 0:
s = s[dot+1:]
s = s.replace(';','')
s = s.replace('[]','Array')
if len(s) > 0:
c = s[0].lower()
s = c + s[1:]
return s
def GenerateImportsTipForModule( mod ):
'''
@param mod: the module from where we should get the completions
'''
ret = []
dirComps = dirObj( mod )
dontGetDocsOn = (float, int, str, tuple, list, type)
for d in dirComps:
args = ''
doc = ''
retType = TYPE_BUILTIN
try:
obj = getattr(mod, d)
except AttributeError:
#jython has a bug in its custom classloader that prevents some
things from working correctly, so, let's see if
#we can fix that... (maybe fixing it in jython itself would be a
better idea, as this is clearly a bug)
#for that we need a custom classloader... we have references from
it in the below places:
#
#http://mindprod.com/jgloss/classloader.html
#http://www.javaworld.com/javaworld/jw-03-2000/jw-03-classload-p2.html
#http://freshmeat.net/articles/view/1643/
#
#note: this only happens when we add things to the sys.path at
runtime, if they are added to the classpath
#before the run, everything goes fine.
#
#The code below ilustrates what I mean...
#
#import sys
#sys.path.insert(1,
r"C:\bin\eclipse310\plugins\org.junit_3.8.1\junit.jar" )
#
#import junit.framework
#print dir(junit.framework) #shows the TestCase class here
#
#import junit.framework.TestCase
#
#raises the error:
#Traceback (innermost last):
# File "<console>", line 1, in ?
#ImportError: No module named TestCase
#
#whereas if we had added the jar to the classpath before,
everything would be fine by now...
ret.append( (d, '', '', str(retType)) )
#that's ok, private things cannot be gotten...
continue
else:
isMet = ismethod(obj)
if isMet[0]:
info = isMet[1][0]
try:
args, vargs, kwargs = info.args, info.varargs, info.kwargs
doc = info.getAsDoc()
r = ''
for a in ( args ):
if len( r ) > 0:
r += ', '
r += formatArg(a)
args = '(%s)' % (r)
except TypeError:
print traceback.print_exc()
args = '()'
retType = TYPE_FUNCTION
elif isclass(obj):
retType = TYPE_CLASS
elif ismodule(obj):
retType = TYPE_IMPORT
#add token and doc to return - assure only strings.
ret.append( (d, doc, args, str(retType)) )
return ret
for p in GenerateImportsTipForModule(editor.__class__):
print p
