yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #02467
[Branch ~yade-dev/yade/trunk] Rev 1845: 1. Add yade.system module containing most startup things
------------------------------------------------------------
revno: 1845
committer: Václav Šmilauer <eudoxos@xxxxxxxx>
branch nick: trunk
timestamp: Thu 2009-12-03 00:01:36 +0100
message:
1. Add yade.system module containing most startup things
2. yade-trunk-py usable now; startup is _much_ faster than the c++ main :-) (lazy linkage?). If everything works well, the c++ main will be deprecated soon (though still functional)
added:
py/system.py
modified:
core/main/main.py.in
core/main/pyboot.cpp
gui/py/PythonUI_rc.py
py/SConscript
py/yadeWrapper/yadeWrapper.cpp
--
lp:yade
https://code.launchpad.net/~yade-dev/yade/trunk
Your team Yade developers is subscribed to branch lp:yade.
To unsubscribe from this branch go to https://code.launchpad.net/~yade-dev/yade/trunk/+edit-subscription.
=== modified file 'core/main/main.py.in'
--- core/main/main.py.in 2009-12-01 22:24:00 +0000
+++ core/main/main.py.in 2009-12-02 23:01:36 +0000
@@ -1,4 +1,5 @@
#!/usr/bin/python
+# encoding: utf-8
# syntax:python
import sys,ctypes
@@ -22,7 +23,7 @@
# find what is our version, based on argv[0]
# should be improved
-import sys,re,os.path
+import sys,re,os,os.path
m=re.match('(.*)/bin/yade(-.*)-py',sys.argv[0])
if not m: raise RuntimeError("Unable to find prefix and yade version from argv[0]=='%s'."%sys.argv[0])
prefix,suffix=m.group(1),m.group(2)
@@ -30,6 +31,9 @@
pluginDirs=[libDir+dir for dir in ('','/plugins','/gui','/extra') if os.path.exists(libDir+dir)]
sys.path.append(libDir+'/py')
+# this works, cool!
+## os.environ['OMP_NUM_THREADS']=str(1)
+
# now we can import yade's c++ modules just fine
import yade.boot
yade.boot.initialize(pluginDirs,True)
@@ -57,15 +61,15 @@
if arg.endswith('.xml') or arg.endswith('.xml.bz2'): runtime.simulation=arg
elif arg.endswith('.py'): runtime.script=arg
-#
-# this fills __builtins__ with wrapped types and proxy classes; it could be factored out, though
-#
-execfile(prefix+'/lib/yade'+suffix+'/gui/PythonUI_rc.py')
-
try:
import yade.qt
yade.qt.Controller()
except ImportError: pass
+#
+# this fills __builtins__ with wrapped types and proxy classes; it could be factored out, though
+#
+execfile(prefix+'/lib/yade'+suffix+'/gui/PythonUI_rc.py')
+
#setupPythonRuntime()
=== modified file 'core/main/pyboot.cpp'
--- core/main/pyboot.cpp 2009-12-01 11:02:55 +0000
+++ core/main/pyboot.cpp 2009-12-02 23:01:36 +0000
@@ -42,20 +42,11 @@
localLogger->setLevel(getenv("YADE_DEBUG")?debugLevel:warnLevel);
#endif
- #if defined(YADE_OPENMP) || defined(YADE_OPENGL)
- #ifdef LOG4CXX
- LOG_ERROR("Yade compiled with openmp/opengl. Using python main will likely crash as soone as an ostream is used.")
- #else
- // avoid log4cxx-less LOG_ERROR, since it uses cerr, which crashes due to libsctc++ (?) issue.
- fprintf(stderr,"ERROR: Yade compiled with openmp/opengl. Using python main will likely crash as soone as an ostream is used.\n");
- #endif
- #endif
-
PyEval_InitThreads();
Omega& O(Omega::instance());
O.init();
- O.origArgv=NULL; O.origArgc=0;
+ O.origArgv=NULL; O.origArgc=0; // not needed, anyway
O.initTemps();
#ifdef YADE_DEBUG
if(gdb){
=== modified file 'gui/py/PythonUI_rc.py'
--- gui/py/PythonUI_rc.py 2009-12-01 14:56:39 +0000
+++ gui/py/PythonUI_rc.py 2009-12-02 23:01:36 +0000
@@ -4,125 +4,17 @@
yade.runtime must have already been populated from within c++."""
import sys
-sys.excepthook=sys.__excepthook__ # apport on ubuntu overrides this, we don't need it
-# sys.path.insert(0,runtime.prefix+'/lib/yade'+runtime.suffix+'/extra')
-
from math import *
from miniWm3Wrap import *
from yade.wrapper import *
from yade._customConverters import *
from yade import runtime
from yade import utils
-__builtins__.O=Omega()
-sys.exit=O.exitNoBacktrace
-
-### direct object creation through automatic wrapper functions
-def listChildClassesRecursive(base):
- ret=set(O.childClasses(base)); ret2=set()
- for bb in ret:
- ret2|=listChildClassesRecursive(bb)
- return ret | ret2
-
-# not sure whether __builtins__ is the right place?
-_proxyNamespace=__builtins__.__dict__
-# all classes that we want to handle at this point
-_allSerializables=set(listChildClassesRecursive('Serializable'))
-# classes that cannot be instantiated in python directly, and will have no properties generated for them
-_noPropsClasses=set(['InteractionContainer','BodyContainer','Functor','Engine','Dispatcher'])
-# classes that have special wrappers; only the most-bottom ones, with their names as it is in c++
-_pyRootClasses=set([
- 'StandAloneEngine','DeusExMachina','InteractingGeometry','BoundingVolume','InteractionGeometry','InteractionPhysics','FileGenerator',
- 'BoundingVolumeFunctor','InteractionGeometryFunctor','InteractionPhysicsFunctor','ConstitutiveLaw']+
- (['GeometricalModelEngineUnit','InteractingGeometryEngineUnit','GeometricalModel'] if 'shape' in runtime.features else [])+(['PhysicalParameters','PhysicalActionApplierUnit','PhysicalActionDamperUnit','StateEngineUnit'] if 'physpar' in runtime.features else ['Material','State'])
- # childless classes
- +['BoundingVolumeDispatcher','InteractionGeometryDispatcher','InteractionPhysicsDispatcher','ConstitutiveLawDispatcher','InteractionDispatchers','ParallelEngine']
-)
-
-_proxiedClasses=set()
-
-
-if 1:
- # create types for all classes that yade defines: first those deriving from some root classes
- for root in _pyRootClasses:
- try:
- rootType=yade.wrapper.__dict__[root]
- except KeyError:
- print 'WARNING: class %s not defined'%root
- for p in listChildClassesRecursive(root):
- _proxyNamespace[p]=type(p,(rootType,),{'__init__': lambda self,__subType_=p,*args,**kw: super(type(self),self).__init__(__subType_,*args,**kw)})
- _proxiedClasses.add(p)
- # inject wrapped class itself into _proxyNamespace
- _proxyNamespace[root]=rootType
- # create types for classes that derive just from Serializable
- for p in _allSerializables-_proxiedClasses-_pyRootClasses:
- _proxyNamespace[p]=type(p,(Serializable,),{'__init__': lambda self,__subType_=p,*args,**kw: super(type(self),self).__init__(__subType_,*args,**kw)})
- ## NOTE: this will not work if the object is returned from c++; seems to be more confusing than doing any good; disabling for now.
- if 0:
- # create class properties for yade serializable attributes, i.e. access object['attribute'] as object.attribute
- for c in _allSerializables-_noPropsClasses:
- cls=eval(c) # ugly: create instance; better lookup some namespace (builtins? globals?)
- for k in cls().keys(): # must be instantiated so that attributes can be retrieved
- setattr(cls,k,property(lambda self,__k_=k:self.__getitem__(__k_),lambda self,val,__k_=k:self.__setitem__(__k_,val)))
-else:
- # old code, can be removed at some point
- for root in _pyRootClasses:
- for p in listChildClassesRecursive(root):
- _proxyNamespace[p]=lambda __r_=root,__p_=p,**kw : yade.wrapper.__dict__[__r_](__p_,**kw)
- _proxiedClasses.add(p)
- # wrap classes that don't derive from any specific root class, have no proxy and need it
- for p in _allSerializables-_proxiedClasses-_pyRootClasses:
- _proxyNamespace[p]=lambda __p_=p,**kw: yade.wrapper.Serializable(__p_,**kw)
-### end wrappers
-
-#### HANDLE RENAMED CLASSES ####
-# if old class name is used, the new object is constructed and a warning is issued about old name being used
-# keep chronologically ordered, oldest first; script/rename-class.py appends at the end
-renamed={
- 'CpmPhysDamageColorizer':'CpmStateUpdater', # renamed 10.10.2009
- 'GLDraw_Dem3DofGeom_FacetSphere':'Gl1_Dem3DofGeom_FacetSphere', # renamed 15.11.2009
- 'PeriodicInsertionSortCollider':'InsertionSortCollider', # integrated 25.11.2009
- 'BoundingVolumeMetaEngine':'BoundingVolumeDispatcher', # Tue Dec 1 14:28:29 2009, vaclav@flux
- 'BoundingVolumeEngineUnit':'BoundingVolumeFunctor', # Tue Dec 1 14:39:53 2009, vaclav@flux
- 'InteractionGeometryMetaEngine':'InteractionGeometryDispatcher', # Tue Dec 1 14:40:36 2009, vaclav@flux
- 'InteractionPhysicsMetaEngine':'InteractionPhysicsDispatcher', # Tue Dec 1 14:40:53 2009, vaclav@flux
- 'InteractionPhysicsEngineUnit':'InteractionPhysicsFunctor', # Tue Dec 1 14:41:19 2009, vaclav@flux
- 'InteractionGeometryEngineUnit':'InteractionGeometryFunctor', # Tue Dec 1 14:41:56 2009, vaclav@flux
- ### END_RENAMED_CLASSES_LIST ### (do not delete this line; scripts/rename-class.py uses it
-}
-
-for oldName in renamed.keys():
- class warnWrap:
- def __init__(self,_old,_new):
- # assert(_proxyNamespace.has_key(_new))
- self.old,self.new=_old,_new
- def __call__(self,*args,**kw):
- import warnings; warnings.warn("Class `%s' was renamed to (or replaced by) `%s', update your code!"%(self.old,self.new),DeprecationWarning,stacklevel=3);
- return _proxyNamespace[self.new](*args,**kw)
- _proxyNamespace[oldName]=warnWrap(oldName,renamed[oldName])
-
-
-
-# python2.4 workaround (so that quit() works as it does in 2.5)
-if not callable(__builtins__.quit):
- def _quit(): import sys; sys.exit(0)
- __builtins__.quit=_quit
-
-def cleanup():
- try:
- #import yade.qt, time
- import yade._qt
- if yade._qt.isActive(): yade._qt.close();
- #yade.qt.close()
- #while True: time.sleep(.1) # wait to be killed
- except ImportError: pass
-
-
-## run the TCP server
-import yade.PythonTCPServer
-srv=yade.PythonTCPServer.GenericTCPServer(handler=yade.PythonTCPServer.PythonConsoleSocketEmulator,title='TCP python prompt',cookie=True,minPort=9000)
-yade.runtime.cookie=srv.server.cookie
-info=yade.PythonTCPServer.GenericTCPServer(handler=yade.PythonTCPServer.InfoSocketProvider,title='TCP info provider',cookie=False,minPort=21000)
-sys.stdout.flush()
+
+import yade.system
+yade.system.setExitHandlers()
+yade.system.injectCtors()
+yade.system.runServers()
if not runtime.__dict__.has_key('noSession'):
@@ -175,9 +67,10 @@
# http://lists.ipython.scipy.org/pipermail/ipython-user/2008-September/005839.html
import IPython.ipapi
IPython.ipapi.get().IP.atexit_operations()
- except SystemExit:
- cleanup()
- finally:
- cleanup()
+ O.exitNoBacktrace()
+ except SystemExit: pass
+ #cleanup()
+ finally: pass
+ #cleanup()
=== modified file 'py/SConscript'
--- py/SConscript 2009-12-01 14:22:18 +0000
+++ py/SConscript 2009-12-02 23:01:36 +0000
@@ -27,6 +27,7 @@
env.File('linterpolation.py'),
env.File('timing.py'),
env.File('pack.py'),
+ env.File('system.py'),
env.File('export.py'),
env.File('post2d.py'),
env.SharedLibrary('wrapper',['yadeWrapper/yadeWrapper.cpp'],SHLIBPREFIX='',LIBS=['PythonUI']+linkPlugins(['Shop','BoundingVolumeDispatcher','InteractionGeometryDispatcher','InteractionPhysicsDispatcher','ConstitutiveLawDispatcher','InteractionDispatchers','ParallelEngine','Clump','STLImporter',]+(['GeometricalModelMetaEngine','InteractingGeometryMetaEngine',] if 'shape' in env['features'] else [])+(['StateMetaEngine',] if 'physpar' in env['features'] else []))),
=== added file 'py/system.py'
--- py/system.py 1970-01-01 00:00:00 +0000
+++ py/system.py 2009-12-02 23:01:36 +0000
@@ -0,0 +1,112 @@
+# coding: utf-8
+# 2009 © Václav Šmilauer <eudoxos@xxxxxxxx>
+
+"""
+Functions for accessing yade's internals; only used internally.
+"""
+import sys
+from yade import wrapper
+from yade._customConverters import *
+from yade import runtime
+__builtins__['O']=wrapper.Omega()
+
+def childClasses(base):
+ """Recursively enumerate classes deriving from given base (as string). Returns set."""
+ ret=set(O.childClassesNonrecursive(base)); ret2=set()
+ for bb in ret:
+ ret2|=childClasses(bb)
+ return ret | ret2
+
+_allSerializables=childClasses('Serializable')
+# classes that cannot be instantiated in python directly, and will have no properties generated for them
+_noPropsClasses=set(['InteractionContainer','BodyContainer','Functor','Engine','Dispatcher'])
+# classes that have special wrappers; only the most-bottom ones, with their names as it is in c++
+_pyRootClasses=set([
+ 'StandAloneEngine','DeusExMachina','InteractingGeometry','BoundingVolume','InteractionGeometry','InteractionPhysics','FileGenerator',
+ 'BoundingVolumeFunctor','InteractionGeometryFunctor','InteractionPhysicsFunctor','ConstitutiveLaw','Material','State']
+ # childless classes
+ +['BoundingVolumeDispatcher','InteractionGeometryDispatcher','InteractionPhysicsDispatcher','ConstitutiveLawDispatcher','InteractionDispatchers','ParallelEngine']
+)
+## set of classes for which the proxies were created
+_proxiedClasses=set()
+
+## deprecated classes
+# if old class name is used, the new object is constructed and a warning is issued about old name being used
+# keep chronologically ordered, oldest first; script/rename-class.py appends at the end
+_deprecated={
+ 'CpmPhysDamageColorizer':'CpmStateUpdater', # renamed 10.10.2009
+ 'GLDraw_Dem3DofGeom_FacetSphere':'Gl1_Dem3DofGeom_FacetSphere', # renamed 15.11.2009
+ 'PeriodicInsertionSortCollider':'InsertionSortCollider', # integrated 25.11.2009
+ 'BoundingVolumeMetaEngine':'BoundingVolumeDispatcher', # Tue Dec 1 14:28:29 2009, vaclav@flux
+ 'BoundingVolumeEngineUnit':'BoundingVolumeFunctor', # Tue Dec 1 14:39:53 2009, vaclav@flux
+ 'InteractionGeometryMetaEngine':'InteractionGeometryDispatcher', # Tue Dec 1 14:40:36 2009, vaclav@flux
+ 'InteractionPhysicsMetaEngine':'InteractionPhysicsDispatcher', # Tue Dec 1 14:40:53 2009, vaclav@flux
+ 'InteractionPhysicsEngineUnit':'InteractionPhysicsFunctor', # Tue Dec 1 14:41:19 2009, vaclav@flux
+ 'InteractionGeometryEngineUnit':'InteractionGeometryFunctor', # Tue Dec 1 14:41:56 2009, vaclav@flux
+ ### END_RENAMED_CLASSES_LIST ### (do not delete this line; scripts/rename-class.py uses it
+}
+
+
+def injectCtors(proxyNamespace=__builtins__):
+ """Input wrapped classes as well as proxies for their derived types into the __builtins__ namespace. Should be invoked at yade startup.
+
+ Root classes are those that are directly wrapped by boost::python. These are only imported to proxyNamespace.
+
+ Derived classes (from these root classes) are faked by creating a callable which invokes appropriate root class constructor with the derived class parameter and passes remaining arguments to it.
+
+ Classes that are neither root nor derived are exposed via callable object that constructs a Serializable of given type and passes the parameters.
+ """
+ # classes derived from wrappers (but not from Serializable directly)
+ for root in _pyRootClasses:
+ try:
+ rootType=wrapper.__dict__[root]
+ except KeyError:
+ print 'WARNING: class %s not defined'%root
+ for p in childClasses(root):
+ proxyNamespace[p]=type(p,(rootType,),{'__init__': lambda self,__subType_=p,*args,**kw: super(type(self),self).__init__(__subType_,*args,**kw)})
+ _proxiedClasses.add(p)
+ # inject wrapped class itself into proxyNamespace
+ proxyNamespace[root]=rootType
+ # classes that derive just from Serializable: the remaining ones
+ for p in _allSerializables-_proxiedClasses-_pyRootClasses:
+ proxyNamespace[p]=type(p,(wrapper.Serializable,),{'__init__': lambda self,__subType_=p,*args,**kw: super(type(self),self).__init__(__subType_,*args,**kw)})
+ # deprecated names
+ for oldName in _deprecated.keys():
+ class warnWrap:
+ def __init__(self,_old,_new):
+ # assert(proxyNamespace.has_key(_new))
+ self.old,self.new=_old,_new
+ def __call__(self,*args,**kw):
+ import warnings; warnings.warn("Class `%s' was renamed to (or replaced by) `%s', update your code!"%(self.old,self.new),DeprecationWarning,stacklevel=2);
+ return proxyNamespace[self.new](*args,**kw)
+ proxyNamespace[oldName]=warnWrap(oldName,_deprecated[oldName])
+
+def setExitHandlers():
+ """Set exit handler to avoid gdb run if log4cxx crashes at exit.
+ Remove excepthook."""
+ #import sys
+ # python2.4 workaround (so that quit() works as it does in 2.5)
+ if not callable(__builtins__['quit']):
+ def _quit(): import sys; sys.exit(0)
+ __builtins__['quit']=_quit
+ # avoid backtrace at regular exit, even if we crash
+ sys.exit=O.exitNoBacktrace
+ #sys.excepthook=sys.__excepthook__ # apport on ubuntu overrides this, we don't need it
+
+def runServers():
+ """Run python telnet server and info socket. They will be run at localhost on ports 9000 (or higher if used)Â and 21000 (or higer if used) respectively.
+
+ The python telnet server accepts only connection from localhost,
+ after authentication by random cookie, which is printed on stdout
+ at server startup.
+
+ The info socket provides read-only access to several simulation parameters
+ at runtime. Each connection receives pickled dictionary with those values.
+ This socket is primarily used by yade-multi batch scheduler.
+ """
+ import yade.PythonTCPServer
+ srv=yade.PythonTCPServer.GenericTCPServer(handler=yade.PythonTCPServer.PythonConsoleSocketEmulator,title='TCP python prompt',cookie=True,minPort=9000)
+ yade.runtime.cookie=srv.server.cookie
+ info=yade.PythonTCPServer.GenericTCPServer(handler=yade.PythonTCPServer.InfoSocketProvider,title='TCP info provider',cookie=False,minPort=21000)
+ sys.stdout.flush()
+
=== modified file 'py/yadeWrapper/yadeWrapper.cpp'
--- py/yadeWrapper/yadeWrapper.cpp 2009-12-01 14:56:39 +0000
+++ py/yadeWrapper/yadeWrapper.cpp 2009-12-02 23:01:36 +0000
@@ -468,7 +468,7 @@
pyMaterialContainer materials_get(void){return pyMaterialContainer();}
- python::list listChildClasses(const string& base){
+ python::list listChildClassesNonrecursive(const string& base){
python::list ret;
for(map<string,DynlibDescriptor>::const_iterator di=Omega::instance().getDynlibsDescriptor().begin();di!=Omega::instance().getDynlibsDescriptor().end();++di) if (Omega::instance().isInheritingFrom((*di).first,base)) ret.append(di->first);
return ret;
@@ -713,7 +713,7 @@
.add_property("actions",&pyOmega::bex_get,"Deprecated alias for Omega().bex")
.add_property("bex",&pyOmega::bex_get,"BodyExternalVariables (forces, torques, ..) in the current simulation.")
.add_property("tags",&pyOmega::tags_get,"Tags (string=string dictionary) of the current simulation (container supporting string-index access/assignment)")
- .def("childClasses",&pyOmega::listChildClasses,"Return list of all classes deriving from given class, as registered in the class factory")
+ .def("childClassesNonrecursive",&pyOmega::listChildClassesNonrecursive,"Return list of all classes deriving from given class, as registered in the class factory")
.def("isChildClassOf",&pyOmega::isChildClassOf,"Tells whether the first class derives from the second one (both given as strings).")
.add_property("bodyContainer",&pyOmega::bodyContainer_get,&pyOmega::bodyContainer_set,"Get/set type of body container (as string); there must be no bodies.")
.add_property("interactionContainer",&pyOmega::interactionContainer_get,&pyOmega::interactionContainer_set,"Get/set type of interaction container (as string); there must be no interactions.")