Example #1
0
//============================================================================
// FUNCTION:    SPELLutils::dumpFrameInfo()
//============================================================================
void SPELLutils::dumpFrameInfo( const std::string& id, PyFrameObject* frame, int iStateId, int TStateId, int FrameId )
{
	LOG_INFO("Dump information for frame " + ISTR(iStateId) + "." + ISTR(TStateId) + "." + ISTR(FrameId));

	std::string dataDir = getSPELL_DATA() + PATH_SEPARATOR + "Runtime" + PATH_SEPARATOR;
	std::string filename = dataDir + id + "_frame_state_" + ISTR(iStateId) + "." + ISTR(TStateId) + "." + ISTR(FrameId) + ".dump";
	std::ofstream dumpFile;
	dumpFile.open( filename.c_str() , std::ios::out );

	dumpFile << "FRAME STATE " << TStateId << " DATA" << std::endl;
	dumpFile << "--------------------------------------" << std::endl;
	dumpFile << "Address              : " << PSTR(frame) << std::endl;
	dumpFile << "Next address         : " << PSTR(frame->f_back) << std::endl;
	dumpFile << "Thread state address : " << PSTR(frame->f_tstate) << std::endl;
	dumpFile << "Last instruction     : " << frame->f_lasti << std::endl;
	dumpFile << "Last line            : " << frame->f_lineno << std::endl;
	dumpFile << "Try blocks count     : " << frame->f_iblock << std::endl;
	dumpFile << "Try blocks           : " << PSTR(frame->f_blockstack) << std::endl;
	dumpFile << "Value stack          : " << PSTR(frame->f_valuestack) << std::endl;
	dumpFile << "Stack top            : " << PSTR(frame->f_stacktop) << std::endl;
	dumpFile << "Stack count          : " << (frame->f_stacktop - frame->f_valuestack) << std::endl;
	dumpFile << "Fast locals          : " << (frame->f_code->co_nlocals-1) << std::endl;
	dumpFile << "Exception type       : " << PYREPR(frame->f_exc_type) << std::endl;
	dumpFile << "Exception value      : " << PYREPR(frame->f_exc_value) << std::endl;
	dumpFile << "Exception traceback  : " << PYREPR(frame->f_exc_traceback) << std::endl;
	dumpFile << "Trace function       : " << PYREPR(frame->f_trace) << std::endl;
	dumpFile << "Builtins             : " << PYSIZE(frame->f_builtins) << std::endl;
	dumpFile << "Globals              : " << PYSIZE(frame->f_globals) << std::endl;
	dumpFile << "Locals               : " << PYSIZE(frame->f_locals) << std::endl;
	dumpFile << "Code                 : " << PYCREPR(frame->f_code) << std::endl;

	// Close the frame state dump, no more to add
	dumpFile.flush();
	dumpFile.close();
}
//=============================================================================
// METHOD    : SPELLwsClassDataHandler::read()
//=============================================================================
void SPELLwsClassDataHandler::read()
{
	// Store the class name
	SPELLwsObjectDataHandler nameHandler( NULL );
	nameHandler.setStorage(getStorage());
	SPELLwsDictDataHandler dictHandler( NULL );
	dictHandler.setStorage(getStorage());

	// Read the data
	DEBUG("[CDH] Reading name");
	nameHandler.read();
	DEBUG("[CDH] Name read: " + PYREPR(nameHandler.getObject()));

	PyObject* classObject = NULL;
	if ( PYSTR(nameHandler.getObject()) == "__FAILED_WS_CLASS__" )
	{
		classObject = PyClass_New( NULL, PyDict_New(), nameHandler.getObject() );
		std::string msg = "Detected failed WS class, assuming error during marshal process";
		LOG_ERROR(msg);
		std::cerr << msg << std::endl;
	}
	else
	{
		DEBUG("[CDH] Reading dictionary");
		dictHandler.read();
		DEBUG("[CDH] Dictionary read: " + PYREPR(dictHandler.getObject()));
		// Create the class object
		classObject = PyClass_New( NULL, dictHandler.getObject(), nameHandler.getObject() );
	}
	// Set it as associated object
	setObject( classObject );
}
//=============================================================================
// METHOD: SPELLvariableMonitor::retrieveNames()
//=============================================================================
std::vector<std::string> SPELLvariableMonitor::retrieveNames()
{
	std::vector<std::string> varNames;

	PyObject* varList = m_frame->f_code->co_names;
	DEBUG("[VM] CO_NAMES   : " + PYREPR(varList));
	unsigned int numVars = PyTuple_Size(varList);

	/*
	 * co_varnames contains the names of the local variables
	 * (starting with the argument names)
	 */
	varList = m_frame->f_code->co_varnames;
	DEBUG("[VM] CO_VARNAMES: " + PYREPR(varList));
	numVars = PyTuple_Size(varList);
	for( unsigned int index = 0; index<numVars; index++)
	{
		PyObject* varName = PyTuple_GetItem( varList, index );
		varNames.push_back( PYSSTR( varName ) );
	}

	varList = m_frame->f_code->co_freevars;
	DEBUG("[VM] CO_FREEVARS : " + PYREPR(varList));

	varList = m_frame->f_code->co_cellvars;
	DEBUG("[VM] CO_CELLVARS : " + PYREPR(varList));

	return varNames;
}
//=============================================================================
// METHOD: SPELLvariableMonitor::changeVariable()
//=============================================================================
void SPELLvariableMonitor::changeVariable( SPELLvarInfo& var )
{
	SPELLsafePythonOperations ops("SPELLvariableMonitor::changeVariable()");

	DEBUG("[VM] Request changing variable " + var.varName);

	// Evaluate the value for the variable
	PyObject* value = NULL;
	// If varValue is '<empty>' or empty string, do not try to evaluate it,
	// directly assign Python empty string
	if ((var.varValue == EMPTY_STRING)||(var.varValue == ""))
	{
		value = STRPY("");
	}
	else
	{
		// Build assignment expression. We need to check first, if there
		// are double quotes, convert them to single quotes
		SPELLutils::replace(var.varValue, "\"", "'");
		DEBUG("[VM] Evaluating value expression: " + var.varValue );
		// Check value correctness and evaluate it
		value = SPELLpythonHelper::instance().eval(var.varValue, false);
	}

	if ((m_frame->f_globals)&&(var.isGlobal))
	{
		DEBUG("[VM] Setting " + var.varName + " to " + PYREPR(value) + " in globals");
		PyDict_SetItemString( m_frame->f_globals, var.varName.c_str(), value );
	}
	else if ((m_frame->f_locals)&&(!var.isGlobal))
	{
		DEBUG("[VM] Setting " + var.varName + " to " + PYREPR(value) + " in locals");
		// Update locals from fast locals first
		PyFrame_FastToLocals(m_frame);
		PyDict_SetItemString( m_frame->f_locals, var.varName.c_str(), value );
		PyFrame_LocalsToFast(m_frame,0);
	}
	var.varValue = PYSSTR(value);
	if (var.varValue == "") var.varValue = EMPTY_STRING;

	// Update the variable if it is registered, and notify to listeners
	VarMap::iterator it = m_variables.find(var.varName);
	if (it != m_variables.end())
	{
		std::vector<SPELLvarInfo> changed;
		it->second.varValue = var.varValue;
		DEBUG("[VM] Variable changed by user: "******", current value: " + var.varValue );
		changed.push_back(it->second);
		m_listener->variableChanged( changed );
	}
}
Example #5
0
//============================================================================
// FUNCTION:    SPELLutils::dumpThreadStateInfo()
//============================================================================
void SPELLutils::dumpThreadStateInfo( const std::string& id, PyThreadState* ts, int iStateId, int TStateId  )
{
	LOG_INFO("Dump information for thread state " + ISTR(iStateId) + "." + ISTR(TStateId));
	std::string dataDir = getSPELL_DATA() + PATH_SEPARATOR + "Runtime" + PATH_SEPARATOR;
	std::string filename = dataDir + id + "_thread_state_" + ISTR(iStateId) + "." + ISTR(TStateId) + ".dump";
	std::ofstream dumpFile;
	dumpFile.open( filename.c_str() , std::ios::out );

	dumpFile << "THREAD STATE " << TStateId << " DATA" << std::endl;
	dumpFile << "--------------------------------------" << std::endl;
	dumpFile << "Address           : " << PSTR(ts) << std::endl;
	dumpFile << "Next address      : " << PSTR(ts->next) << std::endl;
	dumpFile << "IState address    : " << PSTR(ts->interp) << std::endl;
	dumpFile << "Recursion depth   : " << ts->recursion_depth << std::endl;
	dumpFile << "Tracing flag      : " << ts->tracing << std::endl;
	dumpFile << "Use tracing flg   : " << ts->use_tracing << std::endl;
	dumpFile << "Profile function  : " << ts->c_profilefunc << std::endl;
	dumpFile << "Trace function    : " << ts->c_tracefunc << std::endl;
	dumpFile << "Profile object    : " << PYREPR(ts->c_profileobj) << std::endl;
	dumpFile << "Trace object      : " << PYREPR(ts->c_traceobj) << std::endl;
	dumpFile << "Current exc. type : " << PYREPR(ts->curexc_type) << std::endl;
	dumpFile << "Current exc. value: " << PYREPR(ts->curexc_value) << std::endl;
	dumpFile << "Current exc. tback: " << PYREPR(ts->curexc_traceback) << std::endl;
	dumpFile << "Exception type    : " << PYREPR(ts->exc_type) << std::endl;
	dumpFile << "Exception value   : " << PYREPR(ts->exc_value) << std::endl;
	dumpFile << "Exception tback   : " << PYREPR(ts->exc_traceback) << std::endl;
	dumpFile << "Main dict         : " << PYSIZE(ts->dict) << " items." << std::endl;
	dumpFile << "Tick counter      : " << ts->tick_counter << std::endl;
	dumpFile << "GIL state counter : " << ts->gilstate_counter << std::endl;
	dumpFile << "Async. exception  : " << PYREPR(ts->async_exc) << std::endl;
	dumpFile << "Thread id         : " << ts->thread_id << std::endl;

	// Count frames
	int numFR = 0;
	PyFrameObject* currFR = ts->frame;
	while( currFR != NULL )
	{
		dumpFrameInfo( id, currFR, iStateId, TStateId, numFR );
		numFR++;
		currFR = currFR->f_back;
	}
	dumpFile << "Number of frames  : " << numFR << std::endl;

	// Close the thread state dump, no more to add
	dumpFile.flush();
	dumpFile.close();
}
//=============================================================================
// METHOD    : SPELLwsClassDataHandler::write()
//=============================================================================
void SPELLwsClassDataHandler::write()
{
	assert( PyClass_Check(getObject()) );

	PyClassObject* classObject = reinterpret_cast<PyClassObject*>(getObject());

	DEBUG("[CDH] Storing name: " + PYREPR(classObject->cl_name) );
	SPELLwsObjectDataHandler nameHandler( classObject->cl_name );
	nameHandler.setStorage(getStorage());

	DEBUG("[CDH] Storing dictionary: " + PYREPR(classObject->cl_dict));
	SPELLwsDictDataHandler dictHandler( classObject->cl_dict );
	dictHandler.setStorage(getStorage());

	// Store the class name, We dont need a data code, we know what is there
	nameHandler.write();
	// Store the class dictionary
	dictHandler.write();
	DEBUG("[CDH] Storing class done" );
}
//=============================================================================
// METHOD: SPELLvariableMonitor::retrieveLocalVariables()
//=============================================================================
void SPELLvariableMonitor::retrieveLocalVariables(std::vector<SPELLvarInfo>& vars)
{
	DEBUG("[VM] Retrieve Locals");

	/*
	 * Bottom stack frame is discarded,
	 * as globals and locals are the same dictionary
	 */
	if (m_frame->f_back == NULL) return;

	/*
	 * Get the names defined in the current code, including arguments
	 */
	std::vector<std::string> varNames = retrieveNames();

	/*
	 * Iterate over the locals dictionary, retrieving the names contained in
	 * varNames
	 */
	PyFrame_FastToLocals(m_frame);
	PyObject* dict = m_frame->f_locals;
	DEBUG("[VM] Frame: " + PYCREPR(m_frame));
	for( unsigned int index = 0; index< varNames.size(); index++)
	{
		std::string varName = varNames[index];
		PyObject* pyVarName = SSTRPY(varName);
		if (PyDict_Contains( dict, pyVarName ))
		{
			PyObject* object = PyDict_GetItem( dict, pyVarName );

			if (!SPELLpythonHelper::instance().isInstance(object, "Database", "spell.lib.adapter.databases.database"))
			{
				if (PyCallable_Check(object)) continue;
				if (PyClass_Check(object)) continue;
				if (PyModule_Check(object)) continue;
				if (PyInstance_Check(object)) continue;
			}
			DEBUG("[VM] Processing " + varName);
			std::string type = PYSSTR( PyObject_Type(object) );
			DEBUG("[VM] Type      : " + type);
			std::string value = PYREPR( object );
			DEBUG("[VM] Value     : " + value);
			DEBUG("[VM] Global    : " + BSTR(false));
			DEBUG("[VM] Registered: " + BSTR(isRegistered(varName)));

			// Mark empty values (empty strings) as "<empty>"
			if (value == "") value = EMPTY_STRING;

			vars.push_back( SPELLvarInfo(varName, type, value, false, isRegistered(varName)) );
		}
	}
	PyFrame_LocalsToFast(m_frame,0);
}
//=============================================================================
// STATIC : SPELLwsWarmStartImpl::shouldFilter()
//=============================================================================
bool SPELLwsWarmStartImpl::shouldFilter( PyObject* key, PyObject* item )
{
	bool doFilter = false;
	// Do not consider modules
	if (PyModule_Check(item))
	{
		doFilter = true;
	}
	// Do not consider callables
	else if (PyCallable_Check(item))
	{
		doFilter = true;
	}
	// Do not consider functions
	else if (PyFunction_Check(item))
	{
		doFilter = true;
	}
	else if ( PYREPR(key) == DatabaseConstants::SCDB )
	{
		doFilter = true;
	}
	else if ( PYREPR(key) == DatabaseConstants::GDB )
	{
		doFilter = true;
	}
	else if ( PYREPR(key) == DatabaseConstants::PROC )
	{
		doFilter = true;
	}
	if ((!doFilter) && (s_filterKeys != NULL))
	{
		// If the set contains the key, must filter it
		int contains = PySet_Contains( s_filterKeys, key );
		doFilter = (contains!=0);
	}
	return doFilter;
}
Example #9
0
//=============================================================================
// METHOD    : SPELLwsStorage::storeObject
//=============================================================================
void SPELLwsStorage::storeObject( PyObject* object )
{
	if (!m_file.is_open()) return;
    if (object == NULL)
    {
        THROW_EXCEPTION("Unable to store object", "Null reference given", SPELL_ERROR_WSTART);
    }
    if (m_mode == MODE_READ)
    {
        THROW_EXCEPTION("Unable to store object", "Initialized in read mode", SPELL_ERROR_WSTART);
    }

    std::string ptype = PYREPR(PyObject_Type(object));
	DEBUG("Encoding object " + PYREPR(object) + " of type " + ptype);
	// Marshal the object to the persistent storage file
	PyObject* marshal = PyMarshal_WriteObjectToString( object, LATEST_MARSHAL_VERSION );
	// Ensure there is no internal Python error
	SPELLpythonHelper::instance().checkError();
	int marshal_len = PyObject_Length(marshal);
	DEBUG("Marshal length: " + ISTR(marshal_len));
	char* encoded = PyString_AsString(marshal);

    // FORMAT IN FILE:
    // COUNT \1 PTYPE \1 MARSHAL LENGTH
    // MARSHAL

    // If the marshal was OK, continue and store in file: OP,TYPE,MARSHALLED
    m_opCounter++;
    m_file << m_opCounter << "\1" << ptype << "\1" << marshal_len << std::endl;
    m_file.write(encoded,marshal_len); m_file << std::endl;

    std::flush(m_file);

    m_trace << "[" << m_opCounter << "] STORE (" << m_filename << ") " + PYREPR(object) << " [ Type=" + ptype << ", Marhsal length=" + ISTR(marshal_len) + " ]" << std::endl;
    std::flush(m_trace);

}
Example #10
0
//=============================================================================
// METHOD    : SPELLwsStorage::loadObject
//=============================================================================
PyObject* SPELLwsStorage::loadObject()
{
	if (!m_file.is_open()) return NULL;
    if (m_mode == MODE_WRITE)
    {
        THROW_EXCEPTION("Unable to load object", "Initialized in write mode", SPELL_ERROR_WSTART);
    }

    // FORMAT IN FILE:
    // COUNT \1 PTYPE \1 MARSHAL LENGTH
    // MARSHAL

    std::string line = "";
    // Get first the line with the info
    while(!m_file.eof() && (line == ""))
    {
    	std::getline(m_file,line);
        DEBUG("Obtained line [" + line + "]");
    }

    DEBUG("Load object from line [" + line + "]");

    std::vector<std::string> elements = SPELLutils::tokenize(line,"\1");

    PyObject* obj = NULL;
    std::string ptype = elements[1];
	int marshal_len = STRI(elements[2]);
	DEBUG("Decoding object of type " + elements[1] + ", marshal length " + elements[2]);
	// Get the line with the marshal
	char buffer[4512];
	m_file.read(buffer,marshal_len);
	obj = (PyObject*) PyMarshal_ReadObjectFromString( buffer, marshal_len );
	DEBUG("Decoded: " + PYCREPR(obj));
	// Check that the unmarshal was ok
	SPELLpythonHelper::instance().checkError();

    m_opCounter++;
    m_trace << "[" << m_opCounter << "] LOAD (" << m_filename << ") " << PYREPR(obj) << " [ Type=" << PYREPR(PyObject_Type(obj)) << ", Marshal length=" + ISTR(marshal_len) + " ]" << std::endl;
    std::flush(m_trace);


    if (obj != NULL) Py_INCREF(obj);

    return obj;
}
//=============================================================================
// STATIC : SPELLwsDataHandlerFactory::createDataHandler()
//=============================================================================
SPELLwsDataHandler* SPELLwsDataHandlerFactory::createDataHandler( PyObject* object )
{
	assert(object != NULL);

	SPELLwsDataHandler* handler = NULL;

	DEBUG("[DHF] Creating handler for object of type " + PYREPR( PyObject_Type(object) ));

	if (PyDict_Check(object))
	{
		DEBUG("[DHF] Object is a dictionary");
		handler = new SPELLwsDictDataHandler(object);
	}
	else if (PyList_Check(object))
	{
		DEBUG("[DHF] Object is a list");
		handler = new SPELLwsListDataHandler(object);
	}
	else if ( Py_None == object )
	{
		DEBUG("[DHF] Object is None");
		handler = new SPELLwsNoneDataHandler();
	}
	else if (SPELLpythonHelper::instance().isDatabase(object))
	{
		DEBUG("[DHF] Object is database");
		handler = new SPELLwsDbDataHandler(object);
	}
	else if (SPELLpythonHelper::instance().isTime(object))
	{
		DEBUG("[DHF] Object is TIME");
		handler = new SPELLwsTimeDataHandler(object);
	}
	else if (PyClass_Check(object))
	{
		DEBUG("[DHF] Object is a class: " + PYCREPR(object));
		handler = new SPELLwsClassDataHandler(object);
	}
	else if (PyInstance_Check(object))
	{
		DEBUG("[DHF] Object is a instance: " + PYCREPR(object));
		handler = new SPELLwsInstanceDataHandler(object);
	}
	else if (SPELLpythonHelper::instance().isSubclassInstance(object, "TmItemClass", "spell.lib.adapter.tm_item"))
	{
		DEBUG("[DHF] Object is a TM item: " + PYCREPR(object));
		handler = new SPELLwsTmItemDataHandler(object);
	}
	// Look discussion at mail.python.org/pipermail/python-dev/2004-July/046074.html
	else if ((object->ob_type->tp_flags & Py_TPFLAGS_HEAPTYPE)>0)
	{
		DEBUG("[DHF] Object is a custom type: " + PYCREPR(object));
		handler = new SPELLwsCustomTypeDataHandler(object);
	}
	else
	{
		DEBUG("[DHF] Default to object handler: " + PYCREPR(object));
		handler = new SPELLwsObjectDataHandler(object);
	}
	return handler;
}
Example #12
0
//============================================================================
// METHOD: SPELLpyValue::set
//============================================================================
void SPELLpyValue::set( PyObject* pyValue )
{
	m_type = NONE;
	m_intValue = 0;
	m_boolValue = false;
	m_floatValue = 0.0;
	m_timeValue.set(0,0);
	m_stringValue = "";

	if (pyValue == NULL) return;

	DEBUG("[PYVAL] Set value from " + PYREPR(pyValue));
	if (pyValue != Py_None)
	{
		if (PyBool_Check(pyValue))
		{
			m_type = BOOLEAN;
			m_boolValue = pyValue == Py_True;
		}
		else if (PyLong_Check(pyValue))
		{
			DEBUG("[PYVAL] Long check");
			m_type = LONG;
			m_intValue = PyLong_AsLongLong(pyValue);
		}
		else if (PyInt_Check(pyValue))
		{
			DEBUG("[PYVAL] Int check");
			m_type = LONG;
			m_intValue = PyInt_AsLong(pyValue);
		}
		else if (PyFloat_Check(pyValue))
		{
			m_type = DOUBLE;
			m_floatValue = PyFloat_AsDouble(pyValue);
		}
		else if (SPELLpythonHelper::instance().isTime(pyValue))
		{
			m_timeValue = SPELLpythonHelper::instance().evalTime(PYSSTR(pyValue));
			if (m_timeValue.isDelta())
			{
				m_type = RELTIME;
			}
			else
			{
				m_type = ABSTIME;
			}
		}
		else if (PyString_Check(pyValue))
		{
			m_type = STRING;
			m_stringValue = PYSTR(pyValue);
		}
		else if (PyList_Check(pyValue))
		{
			m_type = LIST;
			m_listValue.clear();
			unsigned int numItems = PyList_Size(pyValue);
			for(unsigned int idx = 0; idx < numItems; idx++)
			{
				m_listValue.push_back( SPELLpyValue( PyList_GetItem( pyValue, idx) ));
			}
		}
		else if (PyDict_Check(pyValue))
		{
			m_type = DICT;
			m_dictValue.clear();
			PyObject* keys = PyDict_Keys(pyValue);
			unsigned int numItems = PyList_Size(keys);
			for(unsigned int idx = 0; idx < numItems; idx++)
			{
				PyObject* key = PyList_GetItem(keys,idx);
				PyObject* value = PyDict_GetItem( pyValue, key );
				m_dictValue.insert( std::make_pair( PYSSTR(key), SPELLpyValue(value) ) );
			}
		}
		else
		{
			THROW_EXCEPTION("Cannot create variable value",
					        "Cannot infer type from value (" + PYREPR(pyValue) + ")",
					        SPELL_ERROR_LANGUAGE);
		}
		SPELLpythonHelper::instance().checkError();
	}
}
//=============================================================================
// METHOD: SPELLvariableMonitor::retrieveGlobalVariables()
//=============================================================================
void SPELLvariableMonitor::retrieveGlobalVariables(std::vector<SPELLvarInfo>& vars,
												   std::set<std::string> locals)
{
	DEBUG("[VM] Retrieve Globals");

	/*
	 * Once we get the bottom stack frame, we have to iterate over all the keys
	 * in the globals dictionary, and filter them agains the m_initialVariables
	 */
	PyObject* dict = m_frame->f_globals;
	PyObject* itemList = PyDict_Keys(dict);
	unsigned int numItems = PyList_Size(itemList);
	for( unsigned int index = 0; index<numItems; index++)
	{
		PyObject* key = PyList_GetItem( itemList, index );
		std::string varName = PYSSTR(key);

		// Do the following check just when the considered variables are not internal databases
		if ( (varName != DatabaseConstants::SCDB) &&
			 (varName != DatabaseConstants::GDB)  &&
			 (varName != DatabaseConstants::PROC) &&
			 (varName != DatabaseConstants::ARGS) &&
			 (varName != DatabaseConstants::IVARS))
		{
			/* If they key is contained in the initial variables set, then ignore it */
			if (m_initialVariables.find(varName) != m_initialVariables.end())
			{
				continue;
			}
		}
		/* If a variable with the same name has been retrieved in the local scope
		 * then it must be ignored */
		if (locals.find(varName) != locals.end())
		{
			continue;
		}

		// Ignore internal flags
		if (varName == "__USERLIB__") continue;

		PyObject* object = PyDict_GetItem( dict, key );

		if (!SPELLpythonHelper::instance().isInstance(object, "Database", "spell.lib.adapter.databases.database"))
		{
			if (PyCallable_Check(object)) continue;
			if (PyClass_Check(object)) continue;
			if (PyModule_Check(object)) continue;
			if (PyInstance_Check(object)) continue;
		}
		DEBUG("[VM] Processing " + varName);

		std::string type = PYSSTR( PyObject_Type(object) );
		std::string value = PYREPR( object );

		DEBUG("[VM] Type      : " + type);
		DEBUG("[VM] Value     : " + value);
		DEBUG("[VM] Global    : " + BSTR(true));
		DEBUG("[VM] Registered: " + BSTR(isRegistered(PYSSTR(key))));

		// Mark empty values (empty strings) as "<empty>"
		if (value == "") value = EMPTY_STRING;

		vars.push_back( SPELLvarInfo(varName, type, value, true, isRegistered(PYSSTR(key))) );
	}
}
//=============================================================================
// METHOD    : SPELLwsDictDataHandler::write()
//=============================================================================
void SPELLwsDictDataHandler::write()
{
	if (getObject() == NULL)
	{
		getStorage()->storeLong( -1 );
		return;
	}

	assert( PyDict_Check(getObject()));

	SPELLpyHandle keys = PyDict_Keys( getObject() );
	unsigned int numItems = PyList_Size( keys.get() );

	DEBUG("[DDH] Storing dictionary items (total " + ISTR(numItems) + ") address " + PSTR(getObject()));

	PyObject* key = NULL;
	PyObject* item = NULL;

	long toStore = 0;
	// Calculate the number of items to store
	// Store each list item
	DEBUG("[DDH] Keys of the dictionary:");
	for( unsigned int index = 0; index < numItems; index++)
	{
		key = PyList_GetItem( keys.get(), index );
		item = PyDict_GetItem( getObject(), key );
		if (SPELLwsWarmStartImpl::shouldFilter(key,item))
		{
			continue;
		}
		else
		{
			DEBUG("     - " + PYSSTR(key));
		}
		toStore++;
	}

	DEBUG("[DDH] Will store " + ISTR(toStore) + " keys");
	// Store the number of items
	getStorage()->storeLong( (long) toStore );

	DEBUG("[DDH] Start checking items");
	if (toStore>0)
	{
		// Store each list item
		for( unsigned int index = 0; index < numItems; index++)
		{
			key = PyList_GetItem( keys.get(), index );
			item = PyDict_GetItem( getObject(), key );

			DEBUG("[DDH] Checking item " + PYCREPR(key));

			// Do not consider filtered values
			if (SPELLwsWarmStartImpl::shouldFilter(key,item)) continue;

			SPELLpythonHelper::instance().checkError();

			DEBUG("		[DDH] Key index " + ISTR(index));
			DEBUG("		[DDH] Key to use" + PYREPR(key));
			DEBUG("		[DDH] Item type:" + PYREPR(PyObject_Type(item)));

			// Handler for the key
			SPELLwsObjectDataHandler keyHandler(key);
			keyHandler.setStorage(getStorage());

			DEBUG("		[DDH] Creating handler");

			// Create a handler for the item
			SPELLwsDataHandler* handler = SPELLwsDataHandlerFactory::createDataHandler(item);
			handler->setStorage(getStorage());

			// Store the key
			DEBUG("		[DDH] Storing key: " + PYREPR(key));
			keyHandler.write();

			// Store the item data code in order to recognise it later
			DEBUG("		[DDH] Storing data code: " + SPELLwsData::codeStr(handler->getCode()));
			handler->storeDataCode();

			// IMPORTANT in the case of lists and dictionaries, we want to be able to continue
			// the storage even if there is a problem in the handler processing at this point.
			// If that is the case, a fake empty object will be replaced by the object being
			// processed by the handler, and the dumping of this collection will continue.
			try
			{
				if (handler->getCode() == SPELLwsData::DATA_CUSTOM_TYPE )
				{
					std::string msg = "WARNING! warm start not supported for custom Python types (" + PYREPR(key) + "=" + PYREPR(item) + ")";
					LOG_WARN(msg);
					SPELLexecutor::instance().getCIF().warning(msg);
					storeFakeObject( SPELLwsData::DATA_NONE );
				}
				else
				{
					// Store the value
					DEBUG("		[DDH] Storing value: " + PYREPR(item));
					handler->write();
					DEBUG("		[DDH] Storing value done");
				}
			}
			catch(SPELLcoreException& ex)
			{
				std::string msg = "WARNING! WS storage of element " + ISTR(index) + " failed: " + ex.what();
				LOG_WARN(msg);
				SPELLexecutor::instance().getCIF().warning(msg);
				storeFakeObject( handler->getCode() );
			}
			delete handler;
		}
	}

	DEBUG("[DDH] Storing dictionary done");
}
//=============================================================================
// METHOD    : SPELLwsDictDataHandler::read()
//=============================================================================
void SPELLwsDictDataHandler::read()
{
	DEBUG("[DDH] Loading dictionary items");
	// Load the number of items
	int numItems = getStorage()->loadLong();
	DEBUG("[DDH] Number of items " + ISTR(numItems));

	if (numItems == -1)
	{
		setObject(NULL);
		return;
	}

	// Create a dictionary
	PyObject* dictObject = PyDict_New();

	for( unsigned int index = 0; index < (unsigned) numItems; index++)
	{
		// We know that first an Object comes, as the key. So make the handler directly.
		SPELLwsObjectDataHandler keyHandler(NULL);
		keyHandler.setStorage(getStorage());
		DEBUG("		[DDH] Loading key");
		keyHandler.read();
		PyObject* key = keyHandler.getObject();
		DEBUG("		[DDH] Loaded key " + PYREPR(key));

		// Load the item code
		DEBUG("		[DDH] Loading data code");
		SPELLwsData::Code code = loadDataCode();
		DEBUG("		[DDH] Loaded data code " + SPELLwsData::codeStr(code));

		if (code == SPELLwsData::DATA_CUSTOM_TYPE )
		{
			std::string msg = "WARNING! warm start not supported for custom Python types (" + PYREPR(key) + ")";
			LOG_WARN(msg);
			SPELLexecutor::instance().getCIF().warning(msg);
			getStorage()->loadObject(); // Load none
			PyDict_SetItem(dictObject, key, Py_None);
		}
		else
		{
			// Create an appropriate handler
			SPELLwsDataHandler* handler = SPELLwsDataHandlerFactory::createDataHandler(code);
			handler->setStorage(getStorage());
			try
			{
				// Read the data
				DEBUG("		[DDH] Loading value");
				handler->read();
				DEBUG("		[DDH] Value loaded " + PYREPR(handler->getObject()));
				// Add the item to the dictionary
				PyDict_SetItem(dictObject, key, handler->getObject());
			}
			catch(SPELLcoreException& ex)
			{
				std::string msg = "Failed to recover dictionary item " + PYREPR(key) + ": " + ex.what();
				LOG_WARN(msg);
				SPELLexecutor::instance().getCIF().warning(msg);
				PyDict_SetItem(dictObject, key, Py_None);
			}
			delete handler;
			DEBUG("     [DDH] ");
		}
	}

	DEBUG("[DDH] Dictionary loaded");

	// Set it as associated object
	setObject( dictObject );
}