edouard@3501: #!/usr/bin/env python
edouard@3501: # -*- coding: utf-8 -*-
edouard@3501: 
edouard@3501: import sys
edouard@3501: from types import ModuleType
edouard@3501: 
edouard@3501: # TODO use gettext instead
edouard@3501: def get_translation(txt):
edouard@3501:     return txt
edouard@3501: 
edouard@3501: 
edouard@3501: class FakeObject:
edouard@3501:     def __init__(self, *args, **kwargs):
kinsamanka@3790:         if "__classname__" in kwargs:
kinsamanka@3790:             self.__classname__ = kwargs["__classname__"]
edouard@3501: 
edouard@3501:     def __getattr__(self,name):
edouard@3501:         if name.startswith('__'):
kinsamanka@3767:             raise AttributeError(name)
edouard@3501:         return FakeObject(__classname__=self.__classname__+"."+name)
edouard@3501: 
edouard@3501:     def __call__(self, *args, **kwargs):
edouard@3501:         return FakeObject(__classname__=self.__classname__+"()")
edouard@3501: 
edouard@3501:     def __getitem__(self, key):
edouard@3809:         return FakeObject(__classname__=self.__classname__+"["+repr(key)+"]")
edouard@3501: 
edouard@3501:     def __str__(self):
edouard@3501:         return self.__classname__
edouard@3501: 
edouard@3501:     def __or__(self, other):
edouard@3501:         return FakeObject(__classname__=self.__classname__+"|"+other.__classname__)
edouard@3809:     
edouard@3809:     def __hash__(self) -> int:
edouard@3809:         return id(self)
edouard@3501: 
edouard@3809:     def __cmp__(self,other):
edouard@3809:         return True
edouard@3809:     __lt__=__cmp__
edouard@3809:     __le__=__cmp__
edouard@3809:     __eq__=__cmp__
edouard@3809:     __ne__=__cmp__
edouard@3809:     __gt__=__cmp__
edouard@3809:     __ge__=__cmp__
edouard@3501: 
edouard@3501: class FakeClass:
edouard@3501:     def __init__(self, *args, **kwargs):
kinsamanka@3767:         print(("DUMMY Class __init__ !",self.__name__,args,kwargs))
edouard@3501: 
edouard@3501: 
edouard@3501: class FakeModule(ModuleType):
edouard@3501:     def __init__(self, name, classes):
edouard@3501:         self.__modname__ = name
kinsamanka@3767:         self.__objects__ = dict([(desc, type(desc, (FakeClass,), {}))
kinsamanka@3767:             if type(desc)==str else desc for desc in classes])
edouard@3501:         ModuleType(name)
edouard@3501: 
edouard@3501:     def __getattr__(self,name):
edouard@3501:         if name.startswith('__'):
kinsamanka@3767:             raise AttributeError(name)
edouard@3501:   
kinsamanka@3767:         if name in self.__objects__:
edouard@3501:             return self.__objects__[name]
edouard@3501:   
edouard@3501:         obj = FakeObject(__classname__=self.__modname__+"."+name)
edouard@3501:         self.__objects__[name] = obj
edouard@3501:         return obj
edouard@3501: 
edouard@3501: 
edouard@3501: # Keep track of already faked modules to catch those
edouard@3501: # that are already present in sys.modules from start
edouard@3501: # (i.e. mpl_toolkits for exemple)
edouard@3501: already_patched = {}
edouard@3501: 
edouard@3501: for name, classes in [
edouard@3501:     # list given for each module name contains name string for a FakeClass,
edouard@3501:     # otherwise a tuple (name, object) for arbitrary object/function/class
edouard@3501:     ('wx',[
edouard@3501:         'Panel', 'PyCommandEvent', 'Dialog', 'PopupWindow', 'TextEntryDialog',
edouard@3501:         'Notebook', 'ListCtrl', 'TextDropTarget', 'PyControl', 'TextCtrl', 
edouard@3549:         'SplitterWindow', 'Frame', 'Printout', 'StaticBitmap', 'DropTarget',
edouard@3501:         ('GetTranslation', get_translation)]),
edouard@3501:     ('wx.lib.agw.advancedsplash',[]),
edouard@3549:     ('wx.dataview',['DataViewIndexListModel', 'PyDataViewIndexListModel']),
edouard@3501:     ('wx.lib.buttons',['GenBitmapTextButton']),
edouard@3501:     ('wx.adv',['EditableListBox']),
edouard@3501:     ('wx.grid',[
edouard@3931:         'Grid', 'GridTableBase', 'GridCellEditor', 'GridCellTextEditor',
edouard@3501:         'GridCellChoiceEditor']),
edouard@3501:     ('wx.lib.agw.customtreectrl',['CustomTreeCtrl']),
edouard@3549:     ('wx.lib.gizmos',[]),
edouard@3501:     ('wx.lib.intctrl',['IntCtrl']),
edouard@3501:     ('matplotlib.pyplot',[]),
edouard@3501:     ('matplotlib.backends.backend_wxagg',['FigureCanvasWxAgg']),
edouard@3501:     ('wx.stc',['StyledTextCtrl']),
edouard@3501:     ('wx.lib.scrolledpanel',[]),
edouard@3501:     ('wx.lib.mixins.listctrl',['ColumnSorterMixin', 'ListCtrlAutoWidthMixin']),
edouard@3501:     ('wx.dataview',['PyDataViewIndexListModel']),
edouard@3501:     ('matplotlib.backends.backend_agg',[]),
edouard@3501:     ('wx.aui',[]),
edouard@3817:     ('wx.html',['HtmlWindow']),
edouard@3501:     ('mpl_toolkits.mplot3d',[])]:
edouard@3501:     modpath = None
edouard@3501:     parentmod = None
edouard@3501:     for identifier in name.split("."):
edouard@3501:         modpath = (modpath + "." + identifier) if modpath else identifier
edouard@3501:         mod = sys.modules.get(modpath, None)
edouard@3501: 
edouard@3501:         if mod is None or modpath not in already_patched:
edouard@3501:             mod = FakeModule(modpath, classes)
edouard@3501:             sys.modules[modpath] = mod
edouard@3501:             already_patched[modpath] = True
edouard@3501: 
edouard@3501:         if parentmod is not None:
edouard@3501:             parentmod.__objects__[identifier] = mod
edouard@3501: 
edouard@3501:         parentmod = mod
edouard@3501: 
kinsamanka@3752: import builtins
edouard@3501: 
edouard@3501: builtins.__dict__['_'] = get_translation
edouard@3501: