#!/usr/bin/env python
# -*- coding: utf-8 -*-
# java2python.mod.basic -> functions to revise generated source strings.
from itertools import count
from logging import info, warn
from os import path
from re import sub as rxsub
def shebangLine(module):
""" yields the canonical python shebang line. """
yield '#!/usr/bin/env python'
def encodingLine(encoding='utf-8'):
""" returns a function to yield the specified encoding line.
Note that this function isn't wired up because the encoding is
specified for the source directly, and adding this line produces a
syntax error when the compile function is used.
"""
def line(module):
yield '# -*- coding: {0} -*-'.format(encoding)
return line
def simpleDocString(obj):
""" yields multiple lines for a default docstring.
This generator works for modules, classes, and functions.
"""
yield '""" generated source for {0} {1} """'.format(obj.typeName, obj.name)
def commentedImports(module, expr):
module.factory.comment(parent=module, left=expr, fs='import: {left}')
def simpleImports(module, expr):
module.factory.expr(parent=module, left=expr, fs='import {left}')
def commentedPackages(module, expr):
module.factory.comment(parent=module, left=expr, fs='# package: {left}')
def namespacePackages(module, expr):
source = module.sourceFilename
if not source:
warn('namespace package not created; source input not named.')
return
initname = path.join(path.dirname(source), '__init__.py')
if path.exists(initname):
warn('namespace package not created; __init__.py exists.')
return
with open(initname, 'w') as initfile:
initfile.write('from pkgutil import extend_path\n')
initfile.write('__path__ = extend_path(__path__, __name__)\n')
# wrong
initfile.write('\nfrom {0} import {0}\n'.format(module.name))
info('created __init__.py file for package %s.', expr)
def enumConstInts(enum, index, name):
return str(index)
def enumConstStrings(enum, index, name):
return repr(name)
scriptTemplate = """\n
if __name__ == '__main__':
{indent}import sys
{indent}{name}.main(sys.argv)"""
def scriptMainStanza(module):
def filterClass(x):
return x.isClass and x.name==module.name
def filterMethod(x):
return x.isMethod and x.isPublic and x.isStatic and \
x.isVoid and x.name=='main'
for cls in [c for c in module.children if filterClass(c)]:
if [m for m in cls.children if filterMethod(m)]:
yield scriptTemplate.format(indent=module.indent, name=module.name)
break
def outputSubs(obj, text):
subsname = '{0}OutputSubs'.format(obj.typeName)
subs = obj.config.every(subsname, [])
for sub in subs:
for pattern, repl in sub:
text = rxsub(pattern, repl, text)
return text
def overloadedClassMethods(method):
"""
NB: this implementation does not handle overloaded static (or
class) methods, only instance methods.
"""
cls = method.parent
methods = [o for o in cls.children if o.isMethod and o.name==method.name]
if len(methods) == 1:
return
for i, m in enumerate(methods[1:]):
args = [p['type'] for p in m.parameters]
args = ', '.join(args)
m.decorators.append('@{0}.register({1})'.format(method.name, args))
m.name = '{0}_{1}'.format(method.name, i)
# for this one only:
yield '@overloaded'
def maybeClassMethod(method):
if method.isStatic and 'classmethod' not in method.decorators:
yield '@classmethod'
def maybeAbstractMethod(method):
if method.parent and method.parent.isInterface:
yield '@abstractmethod'
def maybeSynchronizedMethod(method):
if 'synchronized' in method.modifiers:
module = method.parents(lambda x:x.isModule).next()
module.needsSyncHelpers = True
yield '@synchronized'
def globalNameCounter(original, counter=count()):
return '__{0}_{1}'.format(original, counter.next())
def getBsrSrc():
from inspect import getsource
from java2python.mod.include.bsr import bsr
return getsource(bsr)
def getSyncHelpersSrc():
from inspect import getsource
from java2python.mod.include import sync
return getsource(sync)
def maybeBsr(module):
if getattr(module, 'needsBsrFunc', False):
for line in getBsrSrc().split('\n'):
yield line
def maybeSyncHelpers(module):
if getattr(module, 'needsSyncHelpers', False):
for line in getSyncHelpersSrc().split('\n'):
yield line
def classContentSort(obj):
isMethod = lambda x:x and x.isMethod
def iterBody(body):
group = []
for value in body:
if isMethod(value):
group.append(value)
yield group
group = []
else:
group.append(value)
yield group
def sortBody(group):
methods = [item for item in group if isMethod(item)]
return methods[0].name if methods else -1
grp = list(iterBody(obj.children))
grpsrt = sorted(grp, key=sortBody)
obj.children = [item for grp in grpsrt for item in grp]
def defaultParams(obj):
return iter(obj.parameters)
def zopeInterfaceMethodParams(obj):
if not obj.parent.isInterface:
for param in obj.parameters:
yield param
else:
for index, param in enumerate(obj.parameters):
if index != 0 and param['name'] != 'self':
yield param
normalBases = ('object', )
def defaultBases(obj):
return iter(obj.bases or normalBases)
def zopeInterfaceBases(obj):
return iter(obj.bases or ['zope.interface.Interface'])
def implAny(obj):
for module in obj.parents(lambda x:x.isModule):
for name in obj.bases:
if any(module.find(lambda v:v.name == name)):
return True
def zopeImplementsClassBases(obj):
return iter(normalBases) if implAny(obj) else defaultBases(obj)
def zopeImplementsClassHead(obj):
if implAny(obj):
for cls in obj.bases:
yield 'zope.interface.implements({})'.format(cls)
def moveStaticExpressions(cls):
name = '{}.'.format(cls.name) # notice the dot
exprs = [child for child in cls.children if child.isExpression and name in str(child)]
module = cls.parents(lambda x:x.isModule).next()
for expr in exprs:
cls.children.remove(expr)
newExpr = module.factory.expr(fs=name + '{right}', right=expr)
module.adopt(newExpr, index=len(module.children))