Tuesday, April 10, 2012

Possible to Unpickle class instances after being converted from old to new style?

In python, is it possible to unpickle objects that were pickled as old-style python classes after being converted to new-style ones? (Ie, objects with different "class signatures"). *


For example, imagine some instances were saved as:


class foo: # old style
 


and then a few more objects were pickled after the class was changed to inherit from object:


class foo(object): # new style
 


Objects that are pickle.dump'ed with one can be pickle.load'ed by the same style class, but neither one will load both. I think that the strategy used by pickle changes based on the inheritance (the class that inherits from object has a __reduce__ method automatically defined, but the one without inheritance doesn't). When trying to load a with-inheritance old-style pickle from code without inheritance (old-style definition), I get the same argument error as seen in this SO question; even though the second argument is redundant, it still changes the "class signature" and expected arguments, and prevents loading. To solve this, I'd be happy to write an unpickler, although I'm afraid it may involve two separate sub-classed unpicklers a la the docs... If I knew how to correctly unpickle each one I'd be fine doing that.


A little background on my situation... I'm using a TrialHandler class to save and reload button presses and reaction times for behavioral psychology experiments. We refactored the TrialHandler class to inherit from a more abstract, baseTrialHandler, but in doing so temporarily changed the class signature to inherit from object. However, we couldn't unpickle older trial_handler files, so it was changed back. I'd like to look at data from the same experiment that was run with both versions of the trial handler, and so want to unpickle both types of saved log file in the same script.


Alternatively, if I can't write a custom unpickler that will unpickle both objects, is there another way to serialize them? I tried dumping straight to yaml, but it looks like I'll have to register the class as something that can be yaml'ized, anyway.


A full description of the problem with specific errors is on the PsychoPy mailing list. Any blog posts explaining the details intermediate pickling, or even python inheritance, would be most welcome; the closest I found was a good explanation of why pickling is insecure describing pickling as a "simple stack-based virtual machine", which is nice, but doesn't get me enough to figure out even the basics of unpicking myself.


Answer:

Going for parts: 1) there is no thing called "class signature" in Python, although I got the idea from your question 2) Not inheriting from "object" in a Python 2 program should be considered an error. Classes that do not inherit from object - also called "old style" classes wher just kept on the language for backwards compatibility, when new style classes where introduced in Python 2.2 (circa year 2000/2001) - old style classes are a lot less consistent and lack many features that make today's python such a nice language.
With that out of the way: unpickle will try to unpickle objects based on the class qualified name - as in ., as seem on the object's __class__.__name__ attribute at pickling time. So it is possible to have a naive way that on an unpickle exception (it raises TypeError), swap the available class with the same name, and retry the unpickle operation Again: your classes should inherit from "object"(more specifically, have a "type" based metaclass)
As for the example I mentioned, juust write something along:
try:
    new_obj = pickle.load(data_stream)
except TypeError: # if you know this was caused due to the new version of "Foo" class:
    current_foo = foomodule.Foo
    foomodule.Foo = foomodule.OldFoo
    new_obj = pickle.load(data_stream)
    foomodule.Foo = current_foo

Why is my specific page tpl.php not being used?

I can't seem to use a unique page--xxxxxxx.tpl.php for a specific page.



I created a "page" content, filled it in, and gave it a path alias. Let's say: "mypage/mycontent". Then I created a page--mypage--mycontent.tpl.php file in my theme's root. Instead of using it, my page.tpl.php is being used. I was under the impression that Drupal 7 automatically searches for template suggestions using the format of page--path.tpl.php, is this incorrect? Do I need to include specific code in my template.php file first? I did try clearing the theme cache, btw and that didn't make a difference.





MVC model with sorting and filtering logic

I was wondering where I should put logic for sorting and filtering a Qt tables in a MVC model. I'm working with a QAbstractTableModel.



  • My tables are handling anywhere from 20 items to 100,000.

  • I need to handle multiple views of the same data with different sort and filter criteria.



I'm relatively new to the MVC model so bear with me.
Thanks in advance.



Answer:

If the sorting/filtering is specific to a view, then the filtering/sorting logic belongs in the View.
Edit: I suppose I should add that the logic itself doesn't necessarily belong in the view -- depending on the situation, you might (for example) have a back-end that uses something like SQL, in which case the query that specifies the filtering/sorting goes in the view, but the implementation of the sorting/filtering itself would end up in SQL implementation. Even if you use something less elaborate than SQL, you can still have a generic implementation of the logic in the back-end, and only a specification of what to do in the view itself.

How to print a boost graph in graphviz with one of the properties displayed?

I see examples of this when using property maps, but not when using structs to handle the vertices and edges (I think this is called 'bundles').


I have vertices and edges defined as such, in an adjacency list graph.


struct Vertex
 {
     string name;
     int some_int;
 };
 
 struct Edge
 {
     double weight;
 };
 


The graph is constructed as follows:


typedef boost::adjacency_list<boost::listS, boost::vecS, boost::directedS, Vertex, Edge> boost_graph;
 


I want to print my graph of these objects in Graphviz format, so I can view it as an image. However, I don't only want the nodes and edges. I also want the attribute name on vertices and weight on edges to appear in the image. How can I do this?


Answer:

I gave bad info the first time. Here is the correct answer.
#include <boost/graph/graphviz.hpp>
using namespace boost;
// Graph type
typedef adjacency_list<vecS, vecS, directedS, VertexProperties, EdgeProperty> Graph;
Graph g;
std::vector<std::string> NameVec; // for dot file names

// write the dot file
std::ofstream dotfile (strDotFile.c_str ());
write_graphviz (dotfile, g, make_label_writer(&NameVec[0]));

tsql conditions vs c# conditions performance

I would like to know what performs faster and its preferable a condition in a tsql query like this:



select case 'color' when 'red' then 1 when 'blue' then 2 else 3 end



or performing the same switch in c# code after getting the value from the db?



switch(color):
{
case "red":
return 1;
case "blue":
return 2;
default:
return 3;
}


Thanks beforehand





Insert into Multiple Tables using PHP with LAST_INSERT_ID()

Below is the code that I've tried but I can't seem to make the right tweaks to get the script to run properly.


$sql = 'INSERT INTO clients (first_name, last_name, email) VALUES('.$_POST['first_name'].', '.$_POST['last_name'].', '.$_POST['email'].')
 INSERT INTO client_data (client_id, phone, zip, note) VALUES(LAST_INSERT_ID(), '.$_POST['phone'].', '.$_POST['zip'].', '.$_POST['message'].')';
 
 mysql_query($sql) or die (mysql_error());
 


Any help is much appreciated.



Answer:

You cannot execute two sql statements with mysql_query();
Use something like this:
$sql = 'INSERT INTO clients (first_name, last_name, email) VALUES('.$_POST['first_name'].', '.$_POST['last_name'].', '.$_POST['email'].')';
mysql_query($sql);

$clientId = mysql_insert_id();

$sql = 'INSERT INTO client_data (client_id, phone, zip, note) VALUES('.$clientId.', '.$_POST['phone'].', '.$_POST['zip'].', '.$_POST['message'].')';

mysql_query($sql) or die (mysql_error());