Underlying class changes between serialisation and deserialisation - python-2.7

There is an object of testclass created at some point in the life of program and then it is serialized in file system using pickle or h5py. Now during this period the definition of testclass is updated. The update is always about adding new fields (and not removing existing ones).
Does deserializing the stored class back and referencing it using updated testclass definition a right approach?
Before Serialization: Class is defined
class testclass:
__fieldA = None
__fieldB = None
__fieldC = 'Hello'
def __init__(self, A, B):
self.__fieldA = A
self.__fieldB = B
def setA(self, A):
self.__fieldA = A
def getA(self):
return self.__fieldA
def setB(self, B):
self.__fieldB = B
def getB(self):
return self.__fieldB
def setC(self, C):
self.__fieldC = C
def getC(self):
return self.__fieldC
>>>orig_obj = testclass('testA', 'testB')
>>>isinstance(orig_obj, testclass)
>>>True
>>>with open('test', 'wb') as handle:
pickle.dump(orig_obj, handle, protocol=pickle.HIGHEST_PROTOCOL)
After Serialization: Class definition is changed
class testclass:
__fieldA = None
__fieldB = None
__fieldC = 'Hello'
__fieldD = 10
def __init__(self, A, B):
self.__fieldA = A
self.__fieldB = B
def setA(self, A):
self.__fieldA = A
def getA(self):
return self.__fieldA
def setB(self, B):
self.__fieldB = B
def getB(self):
return self.__fieldB
def setC(self, C):
self.__fieldC = C
def getC(self):
return self.__fieldC
def setD(self, D):
self.__fieldD = D
def getD(self):
return self.__fieldD
>>>with open('test', 'rb') as handle:
loaded_obj = pickle.load(handle)
>>>isinstance(loaded_obj, testclass)
>>>False
Now loaded_obj is not an instance of testclass. This makes sense and has nothing to do with the fact whether new field __fieldD is introduced or not.
In this scenario, what is the best way to ensure that loaded_obj is an instance of testclass?

Related

Python - Overriding a parent variable with a getter/setter

So I have a parent class BaseAdd that I'm trying to subclass. The BaseAdd uses self.left and self.right, I want to use self.nodes to make it easier to access both left and right at once:
class BaseAdd():
def __init__(self, leftright):
self.left = leftright[0]
self.right = leftright[1]
class Add(BaseAdd):
def __init__(self, leftright):
self.nodes = leftright
#property
def left(self):
return self.nodes[0]
#left.setter
def left(self, value):
self.nodes[0] = value
foo = Add(('L', 'R'))
foo.left = "new"
print(foo.left, foo.nodes[0])
>>> ('new', 'L')
The problem is that the setter is never getting called, my hunch is that it's using the BaseAdd.left somehow instead. How can I make the setter properly set the list element?

Django - passing a dict to form constructor and having it available globally in the class

I'm making a big mess trying to access the object that I passed from the view to the form.
class PrenotaForm(forms.ModelForm):
ORARI_CHOICES = ()
def __init__(self, *args, **kwargs):
DICT_ORARI_CHOICES = kwargs.pop('ORARI_CHOICES_NEW', {})
ORARI_CHOICES_NEW = []
for key, value in DICT_ORARI_CHOICES.items():
temp = [key,value]
ORARI_CHOICES_NEW.append(temp)
super(PrenotaForm, self).__init__(*args, **kwargs)
self.ORARI_CHOICES = ORARI_CHOICES_NEW
print("EEEEEEEEEEEEEEE" + str(self.ORARI_CHOICES))
print(ORARI_CHOICES)
I don't understand why inside the init the ORARI_CHOICES is populated as shown in console output:
EEEEEEEEEEEEEEE[['è uguale', 'Indifferente'], ['845', '08:45'], ['900', '09:00'], ['915', {'label': '09:15', 'disabled': 'disabled'}], ['930', {'label': '09:30', 'disabled': 'disabled'}], ['945', '09:45'], ['1000', '10:00'], ['1015', '10:15'], ['1030', '10:30'], ['1045', '10:45'], ['1100', '11:00'], ['1115', '11:15'], ['1130', '11:30'], ['1145', '11:45']]
but outside the init the ORARI_CHOICE is still empty:
print(ORARI_CHOICES)
since the print does not output nothing.
How can I override the ORARI_CHOICES = () and make it avalable globally in the class after every GET request performed in the view?
if request.method == 'GET':
size_gruppi = 30
print("gruppi size is : " + str(size_gruppi))
ORARI_CHOICES = (
('è uguale', "Indifferente"),
('845', "08:45"),
('900', "09:00"),
('915', "09:15"),
('930', "09:30"),
('945', "09:45"),
('1000', "10:00"),
('1015', "10:15"),
('1030', "10:30"),
('1045', "10:45"),
('1100', "11:00"),
('1115', "11:15"),
('1130', "11:30"),
('1145', "11:45"),
)
orari_map = map(list,ORARI_CHOICES)
orari_dict = dict(ORARI_CHOICES)
print(orari_dict)
counter = 0
for key in orari_map:
if key[0] != 'è uguale':
tot_in_fascia = sum(filter(None, Iscritto.objects.filter(fasce_orarie=key[0]).aggregate(Sum('size_adulti'), Sum('size_giovani')).values()))
print(tot_in_fascia)
if tot_in_fascia >= size_gruppi:
print("fascia " + key[0] + " è al completo ")
orari_dict.update({key[0]: {'label': key[1], 'disabled': 'disabled'}})
form = PrenotaForm(ORARI_CHOICES_NEW = orari_dict)
return render(request, "prenota.html", {'form': form, 'posti_liberi': posti_disponibili, 'giovani_iscritti': giovani_iscritti})
You should set ORARI_CHOICES as a class/static attribute.
class PrenotaForm(forms.ModelForm):
ORARI_CHOICES = []
def __init__(self, *args, **kwargs):
DICT_ORARI_CHOICES = kwargs.pop('ORARI_CHOICES_NEW', {})
# ORARI_CHOICES_NEW = []
for key, value in DICT_ORARI_CHOICES.items():
temp = [key,value]
self.__class__.ORARI_CHOICES.append(temp)
super(PrenotaForm, self).__init__(*args, **kwargs)
print("EEEEEEEEEEEEEEE" + str(self.ORARI_CHOICES))
Now, PrenotaForm.ORARI_CHOICES is already accessible. PrenotaForm.ORARI_CHOICES will always be accessible, but it returns empty list, untill you do not create instance of PrenotaForm. After instance creation of PrenotaForm, __init__ method will be called and data will be added inside ORARI_CHOICES.

Replacement for django `render_options`

So I am implementing this answer: Country/State/City dropdown menus inside the Django admin inline, but the def render piece of code needs to be redone.... I have managed to redo it, but I am struggling to find a replacement (or the correct code) for the self.render_options method (which was deprecated on 1.11) of the Widget class.
I am on Django 2.1.
What should I change?
Here is my code:
class StateChoiceWidget(widgets.Select):
def render(self, name, value, attrs=None, renderer=None):
self.choices = [(u"", u"---------")]
if value is None:
value = ''
model_obj = self.form_instance.instance
if model_obj and model_obj.country:
for m in model_obj.country.state_set.all():
self.choices.append((m.id, smart_text(m)))
else:
obj = State.objects.get(id=value)
for m in State.objects.filter(country=obj.country):
self.choices.append((m.id, smart_text(m)))
final_attrs = self.build_attrs(attrs)
output = ['<select%s>' % flatatt(final_attrs)]
for option in self.choices:
output.append('<option value="%s">%s</option>' % (option[0], option[1]))
output.append('</select>')
return mark_safe(''.join(output))
Original poster updated the sample code, so now it doesn't show the code in the question: see previous revision https://stackoverflow.com/revisions/52174508/1
So I figured out the answer. Will post it here in case someone runs into the same issue.
class StateChoiceWidget(widgets.Select):
def render(self, name, value, attrs=None, renderer=None):
self.choices = [(u"", u"---------")]
if value is None or value == '':
value = ''
model_obj = self.form_instance.instance
if model_obj and model_obj.country:
for m in model_obj.country.state_set.all():
self.choices.append((m.id, smart_text(m)))
else:
obj = State.objects.get(id=value)
for m in State.objects.filter(country=obj.country):
self.choices.append((m.id, smart_text(m)))
final_attrs = self.build_attrs(attrs)
s = widgets.Select(choices=self.choices)
select_html = s.render(name=name,value=value,attrs=attrs)
return mark_safe(''.join(select_html))

object inheritance arugment input error

Playing around with inheritance and came across an error stating that I am inputing too many arguments. What could I be doing wrong?
This first file is called media.py
class Video():
def __init__(self, title, duration):
self.title = title
self.duration = duration
class Movie(Video):
def __init__(self, movie_story, movie_poster, trailer_youtube):
Video.__init__(self, title, duration)
self.storyline = movie_story
self.poster_image_url = movie_poster
self.trailer_youtube_url = trailer_youtube
def show_trailer(self):
webbrowser.open(self.trailer_youtube_url)
class TvShow(Video):
def __init__(self, season, episode, tv_station):
Video.__init__(self, title, duration)
self.season = season
self.episode = episode
self.tv_station = tv_station
This second file creates the objects.
import fresh_tomatoes
import media
family_guy = media.TvShow("Family Guy",
"2000-Present",
"Fifteen Seasons",
"Twenty-Eight",
"Fox")
print family_guy.title
The terminal output states I'm passing 6 arguments when only 4 may be accepted. Why is that?
Calling the parent __init__ will only invoke it , but you still need to pass in the arguments to it.
So when you invoke __init__ method for TvShow it only expects 3 +1(self) arguments , while you were trying to send more than that. So to solve the issue you just need to increase the number of arguments excepted by the __init__.
class Video():
def __init__(self, title, duration):
self.title = title
self.duration = duration
class Movie(Video):
def __init__(self, movie_story, movie_poster, trailer_youtube):
Video.__init__(self, title, duration)
self.storyline = movie_story
self.poster_image_url = movie_poster
self.trailer_youtube_url = trailer_youtube
def show_trailer(self):
webbrowser.open(self.trailer_youtube_url)
class TvShow(Video):
def __init__(self, season, episode, tv_station, title, duration):
Video.__init__(self, title, duration)
self.season = season
self.episode = episode
self.tv_station = tv_station

I don't know how to interact between classes

If I have this two classes:
class bandido:
def __init__(self, vida, ataque):
self.vida = random.randint(40,81)
self.ataque = random.randint(15,46)
class xiaoling:
def __init__(self, vida, ataque):
self.vida = 100
self.ataque = 100
How can I make a fight? and see who wins?