#!/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
from java2python.lib import FS
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:
if methods[0].overloaded:
yield methods[0].overloaded
return
for i, m in enumerate(methods[1:]):
args = [p['type'] for p in m.parameters]
args = ', '.join(args)
m.overloaded = '@{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:
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 maybeAbstractHelpers(module):
if getattr(module, 'needsAbstractHelpers', False):
yield 'from abc import ABCMeta, abstractmethod'
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))
def castCtor(expr, node):
expr.fs = FS.l + '(' + FS.r + ')'
def castDrop(expr, node):
expr.fs = FS.r