diff --git a/lib/_gomodulehacks.py b/lib/_gomodulehacks.py new file mode 100644 index 00000000..3412e485 --- /dev/null +++ b/lib/_gomodulehacks.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +from __go__.grumpy import SysModules +import errno + +# For some reason, importing and extending grumpy.Module does not work. +Module = type(errno) + + +def hybrid_module(modulename, modulefile, moduledict, all_attrs, globals_): + """ + Augment native 'moduledict' with Python-sourced parts + + Allows 'modulename' to use 'moduledict' from outside, + for example a Grumpy dict from native module. + + And does include the resulting module on sys.modules at the end. + + Should be called as: + hybrid_module(__name__, __file__, YourmoduleDict, __all__, globals()) + On the last line of the Python-part of the module + """ + class HybridModule(Module): + def __init__(self): + moduledict['__name__'] = modulename + moduledict['__file__'] = modulefile + for k in all_attrs: + moduledict[k] = globals_[k] + def __setattr__(self, name, value): + moduledict[name] = value + def __getattribute__(self, name): # TODO: replace w/ __getattr__ when implemented + resp = moduledict.get(name) + if resp is None and name not in moduledict: + return super(HybridModule, self).__getattribute__(name) + return resp + + finalmodule = HybridModule() + SysModules[modulename] = finalmodule + return finalmodule diff --git a/lib/sys.py b/lib/sys.py index e59ca69c..45bcb299 100644 --- a/lib/sys.py +++ b/lib/sys.py @@ -15,43 +15,57 @@ """System-specific parameters and functions.""" from __go__.os import Args -from __go__.grumpy import SysModules, MaxInt, Stdin as stdin, Stdout as stdout, Stderr as stderr # pylint: disable=g-multiple-import +from __go__.grumpy import SysmoduleDict, SysModules, MaxInt # pylint: disable=g-multiple-import from __go__.runtime import (GOOS as platform, Version) from __go__.unicode import MaxRune +import _gomodulehacks + + +__all__ = ('stdin', 'stdout', 'stderr', 'argv', 'goversion', + 'maxint', 'maxsize', 'maxunicode', 'modules', 'platform', 'py3kwarning', + 'warnoptions', 'byteorder', 'flags', 'exc_info', 'exit') + argv = [] for arg in Args: - argv.append(arg) + argv.append(arg) goversion = Version() + +stdin = SysmoduleDict['stdin'] +stdout = SysmoduleDict['stdout'] +stderr = SysmoduleDict['stderr'] + maxint = MaxInt maxsize = maxint maxunicode = MaxRune modules = SysModules + py3kwarning = False warnoptions = [] # TODO: Support actual byteorder byteorder = 'little' version = '2.7.13' + class _Flags(object): - """Container class for sys.flags.""" - debug = 0 - py3k_warning = 0 - division_warning = 0 - division_new = 0 - inspect = 0 - interactive = 0 - optimize = 0 - dont_write_bytecode = 0 - no_user_site = 0 - no_site = 0 - ignore_environment = 0 - tabcheck = 0 - verbose = 0 - unicode = 0 - bytes_warning = 0 - hash_randomization = 0 + """Container class for sys.flags.""" + debug = 0 + py3k_warning = 0 + division_warning = 0 + division_new = 0 + inspect = 0 + interactive = 0 + optimize = 0 + dont_write_bytecode = 0 + no_user_site = 0 + no_site = 0 + ignore_environment = 0 + tabcheck = 0 + verbose = 0 + unicode = 0 + bytes_warning = 0 + hash_randomization = 0 flags = _Flags() @@ -62,12 +76,16 @@ def exc_clear(): def exc_info(): - e, tb = __frame__().__exc_info__() # pylint: disable=undefined-variable - t = None - if e: - t = type(e) - return t, e, tb + e, tb = __frame__().__exc_info__() # pylint: disable=undefined-variable + t = None + if e: + t = type(e) + return t, e, tb def exit(code=None): # pylint: disable=redefined-builtin - raise SystemExit(code) + raise SystemExit(code) + + +# Should be the last line of the python part of hybrid stuff +_gomodulehacks.hybrid_module(__name__, __file__, SysmoduleDict, __all__, globals()) diff --git a/runtime/sysmodule.go b/runtime/sysmodule.go new file mode 100644 index 00000000..a3622336 --- /dev/null +++ b/runtime/sysmodule.go @@ -0,0 +1,26 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package grumpy + +var ( + // SysmoduleDict is the __dict__ of the native part of sys.py. + SysmoduleDict = newStringDict(map[string]*Object{ + "__file__": NewStr("").ToObject(), + "__name__": NewStr("_sys").ToObject(), + "stdin": Stdin.ToObject(), + "stdout": Stdout.ToObject(), + "stderr": Stderr.ToObject(), + }) +) diff --git a/testing/sysmodule_test.py b/testing/sysmodule_test.py new file mode 100644 index 00000000..6d4bc3a1 --- /dev/null +++ b/testing/sysmodule_test.py @@ -0,0 +1,15 @@ +from StringIO import StringIO +import sys + +print 'To sys.stdout' + +old_stdout = sys.stdout +sio = StringIO() +sys.stdout = sio + +print 'To replaced sys.stdout' + +sys.stdout = old_stdout +print 'To original sys.stdout' + +assert sio.tell() == len('To replaced sys.stdout')+1, 'Should had printed to StringIO, not STDOUT' \ No newline at end of file