GeezerVison is showing github.com — Merge pull request #33 from bdkearns/master · ntworld/java2python@5b7f514
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboard +3Lines changed: 3 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +*.class | | 2 | +*.egg-info | | 3 | +*.pyc |
Collapse file Copy file name to clipboardExpand all lines: java2python/compiler/template.py +2-1Lines changed: 2 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -119,6 +119,7 @@ def __init__(self, config, name=None, type=None, parent=None): | 119 | 119 | self.children = [] | 120 | 120 | self.config = config | 121 | 121 | self.decorators = [] | | 122 | + self.overloaded = None | 122 | 123 | self.factory = Factory(config) | 123 | 124 | self.modifiers = [] | 124 | 125 | self.name = name | @@ -172,7 +173,7 @@ def configHandler(self, part, suffix='Handler', default=None): | 172 | 173 | def configHandlers(self, part, suffix='Handlers'): | 173 | 174 | """ Returns config handlers for this type of template """ | 174 | 175 | name = '{0}{1}{2}'.format(self.typeName, part, suffix) | 175 | | - return imap(self.toIter, self.config.last(name, ())) | | 176 | + return imap(self.toIter, chain(*self.config.every(name, []))) | 176 | 177 |
| 177 | 178 | def dump(self, fd, level=0): | 178 | 179 | """ Writes the Python source code for this template to the given file. """ | |
Collapse file Copy file name to clipboardExpand all lines: java2python/compiler/visitor.py +18-6Lines changed: 18 additions & 6 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -129,7 +129,12 @@ def acceptType(self, node, memo): | 129 | 129 | acceptAt = makeAcceptType('at') | 130 | 130 | acceptClass = makeAcceptType('klass') | 131 | 131 | acceptEnum = makeAcceptType('enum') | 132 | | - acceptInterface = makeAcceptType('interface') | | 132 | + _acceptInterface = makeAcceptType('interface') | | 133 | + | | 134 | + def acceptInterface(self, node, memo): | | 135 | + module = self.parents(lambda x:x.isModule).next() | | 136 | + module.needsAbstractHelpers = True | | 137 | + return self._acceptInterface(node, memo) | 133 | 138 |
| 134 | 139 |
| 135 | 140 | class Module(TypeAcceptor, Base): | @@ -228,7 +233,10 @@ def acceptVarDeclaration(self, node, memo): | 228 | 233 | if node.firstChildOfType(tokens.TYPE).firstChildOfType(tokens.ARRAY_DECLARATOR_LIST): | 229 | 234 | val = assgnExp.pushRight('[]') | 230 | 235 | else: | 231 | | - val = assgnExp.pushRight('{0}()'.format(identExp.type)) | | 236 | + if node.firstChildOfType(tokens.TYPE).firstChild().type != tokens.QUALIFIED_TYPE_IDENT: | | 237 | + val = assgnExp.pushRight('{0}()'.format(identExp.type)) | | 238 | + else: | | 239 | + val = assgnExp.pushRight('None') | 232 | 240 | return self | 233 | 241 |
| 234 | 242 |
| @@ -358,7 +366,7 @@ class Interface(Class): | 358 | 366 | """ Interface -> accepts AST branches for Java interfaces. """ | 359 | 367 |
| 360 | 368 |
| 361 | | -class MethodContent(Base): | | 369 | +class MethodContent(VarAcceptor, Base): | 362 | 370 | """ MethodContent -> accepts trees for blocks within methods. """ | 363 | 371 |
| 364 | 372 | def acceptAssert(self, node, memo): | @@ -399,6 +407,10 @@ def acceptCatch(self, node, memo): | 399 | 407 |
| 400 | 408 | def acceptContinue(self, node, memo): | 401 | 409 | """ Accept and process a continue statement. """ | | 410 | + parent = node.parents(lambda x: x.type in {tokens.FOR, tokens.FOR_EACH, tokens.DO, tokens.WHILE}).next() | | 411 | + if parent.type == tokens.FOR: | | 412 | + updateStat = self.factory.expr(parent=self) | | 413 | + updateStat.walk(parent.firstChildOfType(tokens.FOR_UPDATE), memo) | 402 | 414 | contStat = self.factory.statement('continue', fs=FS.lsr, parent=self) | 403 | 415 | if len(node.children): | 404 | 416 | warn('Detected unhandled continue statement with label; generated code incorrect.') | @@ -517,7 +529,7 @@ def acceptSwitch(self, node, memo): | 517 | 529 | # we have at least one node... | 518 | 530 | parExpr = self.factory.expr(parent=self) | 519 | 531 | parExpr.walk(parNode, memo) | 520 | | - eqFs = FS.l + '==' + FS.r | | 532 | + eqFs = FS.l + ' == ' + FS.r | 521 | 533 | for caseIdx, caseNode in enumerate(caseNodes): | 522 | 534 | isDefault, isFirst = caseNode.type==tokens.DEFAULT, caseIdx==0 | 523 | 535 |
| @@ -613,7 +625,7 @@ def acceptWhile(self, node, memo): | 613 | 625 | whileStat.walk(blkNode, memo) | 614 | 626 |
| 615 | 627 |
| 616 | | -class Method(VarAcceptor, ModifiersAcceptor, MethodContent): | | 628 | +class Method(ModifiersAcceptor, MethodContent): | 617 | 629 | """ Method -> accepts AST branches for method-level objects. """ | 618 | 630 |
| 619 | 631 | def acceptFormalParamStdDecl(self, node, memo): | @@ -835,7 +847,7 @@ def acceptThisConstructorCall(self, node, memo): | 835 | 847 |
| 836 | 848 | def acceptStaticArrayCreator(self, node, memo): | 837 | 849 | """ Accept and process a static array expression. """ | 838 | | - self.right = self.factory.expr(fs='[None]*{left}') | | 850 | + self.right = self.factory.expr(fs='[None] * {left}') | 839 | 851 | self.right.left = self.factory.expr() | 840 | 852 | self.right.left.walk(node.firstChildOfType(tokens.EXPR), memo) | 841 | 853 |
| |
Collapse file Copy file name to clipboardExpand all lines: java2python/config/__init__.py +1-1Lines changed: 1 addition & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -27,7 +27,7 @@ def last(self, key, default=None): | 27 | 27 | @staticmethod | 28 | 28 | def load(name): | 29 | 29 | """ Imports and returns a module from dotted form or filename. """ | 30 | | - if path.exists(name): | | 30 | + if path.exists(name) and path.isfile(name): | 31 | 31 | mod = load_source(str(hash(name)), name) | 32 | 32 | else: | 33 | 33 | mod = reduce(getattr, name.split('.')[1:], __import__(name)) | |
Collapse file Copy file name to clipboardExpand all lines: java2python/config/default.py +11-5Lines changed: 11 additions & 5 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 24 | 24 | modulePrologueHandlers = [ | 25 | 25 | basic.shebangLine, | 26 | 26 | basic.simpleDocString, | | 27 | + 'from __future__ import print_function', | 27 | 28 | basic.maybeBsr, | | 29 | + basic.maybeAbstractHelpers, | 28 | 30 | basic.maybeSyncHelpers, | 29 | 31 | ] | 30 | 32 |
| | 97 | 99 | methodPrologueHandlers = [ | 98 | 100 | basic.maybeAbstractMethod, | 99 | 101 | basic.maybeClassMethod, | | 102 | + basic.overloadedClassMethods, | 100 | 103 | # NB: synchronized should come after classmethod | 101 | 104 | basic.maybeSynchronizedMethod, | 102 | | - basic.overloadedClassMethods, | 103 | 105 | ] | 104 | 106 |
| 105 | 107 |
| | 131 | 133 |
| 132 | 134 | # This handler is turns java imports into python imports. No mapping | 133 | 135 | # of packages is performed: | 134 | | -moduleImportDeclarationHandler = basic.simpleImports | | 136 | +# moduleImportDeclarationHandler = basic.simpleImports | 135 | 137 |
| 136 | 138 | # This import decl. handler can be used instead to produce comments | 137 | 139 | # instead of import statements: | | 148 | 150 | (Type('TRUE'), transform.true2True), | 149 | 151 | (Type('IDENT'), transform.keywordSafeIdent), | 150 | 152 |
| | 153 | + (Type('DECIMAL_LITERAL'), transform.syntaxSafeDecimalLiteral), | 151 | 154 | (Type('FLOATING_POINT_LITERAL'), transform.syntaxSafeFloatLiteral), | 152 | 155 |
| 153 | 156 | (Type('TYPE') > Type('BOOLEAN'), transform.typeSub), | | 193 | 196 |
| 194 | 197 | # module output subs. | 195 | 198 | moduleOutputSubs = [ | 196 | | - (r'System\.out\.println\((.*)\)', r'print \1'), | 197 | | - (r'System\.out\.print_\((.*?)\)', r'print \1,'), | | 199 | + (r'System\.out\.println\((.*)\)', r'print(\1)'), | | 200 | + (r'System\.out\.print_\((.*?)\)', r'print(\1, end="")'), | 198 | 201 | (r'(.*?)\.equals\((.*?)\)', r'\1 == \2'), | 199 | 202 | (r'(.*?)\.equalsIgnoreCase\((.*?)\)', r'\1.lower() == \2.lower()'), | 200 | 203 | (r'([\w.]+)\.size\(\)', r'len(\1)'), | | 207 | 210 | (r'\.getClass\(\)', '.__class__'), | 208 | 211 | (r'\.getName\(\)', '.__name__'), | 209 | 212 | (r'\.getInterfaces\(\)', '.__bases__'), | 210 | | - #(r'String\.valueOf\((.*?)\)', r'str(\1)'), | | 213 | + (r'String\.valueOf\((.*?)\)', r'str(\1)'), | 211 | 214 | #(r'(\s)(\S*?)(\.toString\(\))', r'\1str(\2)'), | | 215 | + (r'Math\.', ''), | 212 | 216 | ] | 213 | 217 |
| 214 | 218 |
| | 241 | 245 | 'java.lang.String' : 'str', | 242 | 246 |
| 243 | 247 | 'Object' : 'object', | | 248 | + | 244 | 249 | 'IndexOutOfBoundsException' : 'IndexError', | | 250 | + 'IOException': 'IOError', | 245 | 251 | } |
Collapse file Copy file name to clipboardExpand all lines: java2python/mod/basic.py +9-4Lines changed: 9 additions & 4 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -36,7 +36,7 @@ def simpleDocString(obj): | 36 | 36 |
| 37 | 37 |
| 38 | 38 | def commentedImports(module, expr): | 39 | | - module.factory.comment(parent=module, left=expr, fs='import: {left}') | | 39 | + module.factory.comment(parent=module, left=expr, fs='#import {left}') | 40 | 40 |
| 41 | 41 |
| 42 | 42 | def simpleImports(module, expr): | @@ -109,11 +109,13 @@ def overloadedClassMethods(method): | 109 | 109 | cls = method.parent | 110 | 110 | methods = [o for o in cls.children if o.isMethod and o.name==method.name] | 111 | 111 | if len(methods) == 1: | | 112 | + if methods[0].overloaded: | | 113 | + yield methods[0].overloaded | 112 | 114 | return | 113 | 115 | for i, m in enumerate(methods[1:]): | 114 | 116 | args = [p['type'] for p in m.parameters] | 115 | 117 | args = ', '.join(args) | 116 | | - m.decorators.append('@{0}.register({1})'.format(method.name, args)) | | 118 | + m.overloaded = '@{0}.register({1})'.format(method.name, args) | 117 | 119 | m.name = '{0}_{1}'.format(method.name, i) | 118 | 120 | # for this one only: | 119 | 121 | yield '@overloaded' | @@ -131,8 +133,6 @@ def maybeAbstractMethod(method): | 131 | 133 |
| 132 | 134 | def maybeSynchronizedMethod(method): | 133 | 135 | if 'synchronized' in method.modifiers: | 134 | | - module = method.parents(lambda x:x.isModule).next() | 135 | | - module.needsSyncHelpers = True | 136 | 136 | yield '@synchronized' | 137 | 137 |
| 138 | 138 |
| @@ -158,6 +158,11 @@ def maybeBsr(module): | 158 | 158 | yield line | 159 | 159 |
| 160 | 160 |
| | 161 | +def maybeAbstractHelpers(module): | | 162 | + if getattr(module, 'needsAbstractHelpers', False): | | 163 | + yield 'from abc import ABCMeta, abstractmethod' | | 164 | + | | 165 | + | 161 | 166 | def maybeSyncHelpers(module): | 162 | 167 | if getattr(module, 'needsSyncHelpers', False): | 163 | 168 | for line in getSyncHelpersSrc().split('\n'): | |
Collapse file Copy file name to clipboard +6Lines changed: 6 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +class classmethod_(classmethod): | | 2 | + """ Classmethod that provides attribute delegation. | | 3 | +
| | 4 | + """ | | 5 | + def __getattr__(self, name): | | 6 | + return getattr(self.__func__, name) |
Collapse file Copy file name to clipboardExpand all lines: java2python/mod/include/overloading.py +7-5Lines changed: 7 additions & 5 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 36 | 36 |
| 37 | 37 | """ | 38 | 38 |
| 39 | | -import new | | 39 | +from types import MethodType as instancemethod | 40 | 40 |
| 41 | | -# Make the environment more like Python 3.0 | 42 | | -__metaclass__ = type | 43 | | -from itertools import izip as zip | | 41 | +import sys | | 42 | +if sys.version_info[0] < 3: | | 43 | + # Make the environment more like Python 3.0 | | 44 | + __metaclass__ = type | | 45 | + from itertools import izip as zip | 44 | 46 |
| 45 | 47 |
| 46 | 48 | class overloaded: | @@ -55,7 +57,7 @@ def __init__(self, default_func): | 55 | 57 | def __get__(self, obj, type=None): | 56 | 58 | if obj is None: | 57 | 59 | return self | 58 | | - return new.instancemethod(self, obj) | | 60 | + return instancemethod(self, obj) | 59 | 61 |
| 60 | 62 | def register(self, *types): | 61 | 63 | """Decorator to register an implementation for a specific set of types. | |
Collapse file Copy file name to clipboard +5-4Lines changed: 5 additions & 4 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +from functools import wraps | 1 | 2 | from threading import RLock | 2 | 3 |
| 3 | | -_locks = {} | 4 | | -def lock_for_object(obj, locks=_locks): | | 4 | +def lock_for_object(obj, locks={}): | 5 | 5 | return locks.setdefault(id(obj), RLock()) | 6 | 6 |
| 7 | | - | 8 | 7 | def synchronized(call): | | 8 | + assert call.__code__.co_varnames[0] in ['self', 'cls'] | | 9 | + @wraps(call) | 9 | 10 | def inner(*args, **kwds): | 10 | | - with lock_for_object(call): | | 11 | + with lock_for_object(args[0]): | 11 | 12 | return call(*args, **kwds) | 12 | 13 | return inner |
Collapse file Copy file name to clipboardExpand all lines: java2python/mod/transform.py +12-5Lines changed: 12 additions & 5 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -48,15 +48,21 @@ def xform(node, config): | 48 | 48 | true2True = makeConst('True') | 49 | 49 |
| 50 | 50 |
| | 51 | +def syntaxSafeDecimalLiteral(node, config): | | 52 | + """ Ensures a Java decimal literal is a valid Python decimal literal. """ | | 53 | + value = node.token.text | | 54 | + if value.endswith(('l', 'L')): | | 55 | + value = value[:-1] | | 56 | + node.token.text = value | | 57 | + | | 58 | + | 51 | 59 | def syntaxSafeFloatLiteral(node, config): | 52 | 60 | """ Ensures a Java float literal is a valid Python float literal. """ | 53 | 61 | value = node.token.text | 54 | 62 | if value.startswith('.'): | 55 | 63 | value = '0' + value | 56 | 64 | if value.lower().endswith(('f', 'd')): | 57 | 65 | value = value[:-1] | 58 | | - elif value.endswith(('l', 'L')): | 59 | | - value = value[:-1] + 'L' | 60 | 66 | node.token.text = value | 61 | 67 |
| 62 | 68 |
| @@ -184,6 +190,7 @@ def typeSub(node, config): | 184 | 190 | mapping and further discussion. | 185 | 191 | """ | 186 | 192 | ident = node.token.text | 187 | | - subs = config.last('typeSubs') | 188 | | - if ident in subs: | 189 | | - node.token.text = subs[ident] | | 193 | + for subs in reversed(config.every('typeSubs', {})): | | 194 | + if ident in subs: | | 195 | + node.token.text = subs[ident] | | 196 | + return |
|