Dictonary persistance weirdness

  • Thread starter =?iso-8859-1?q?Gonzalo_Sainz-Tr=E1paga_=28GomoX=29
  • Start date
?

=?iso-8859-1?q?Gonzalo_Sainz-Tr=E1paga_=28GomoX=29

Hi, I've posted this to (e-mail address removed) and got no answers, so
i'm reposting it here, I really hope someone can help me out.

------

Hi,
I'm building my first application with mod_python. I am using Ian
Bicking's SQLObject, validators and HTMLfill among other tools.
I built a custom handler that parses the url and loads an external
module, passing it a request object and eventually, an ID integer that
is extracted from the URI.

Example:
http://site.com/race.py/4/signup will trigger "import race;
race.signup(4,req)" and that function will provide a form in order for
people to sign themselves up for race 4.

Form handling and data parsing (for POST or GET data) is done in
separate modules that are imported when needed, so race.py actually
imports formgen.py and formgen.py imports VarsWrapper (from wrappers.py)
in order to parse data for his form and tell whether he needs to print
an error message, or the input is valid.

The process works fine up to races.py: it gets the POSTed data fine, but
then if I try to pass the variables received to the form handler, the
handler will only receive them correctly on the first call to it after a
server restart. For later calls, the form handler sticks to the values
received on his first request.

Code snippets:

-- race.py -------------------------
def signup(id,req):
from formgen import FormInscripcion

v = VarsWrapper(req)
c = v.get_vars()

f = FormInscripcion(id)

tpl.locals.contenido = f.handle(c)
return tpl.get_html()


-- formgen.py -------------------------

class FormInscripcion:
(...)
def handle(self,vars):
# check for sent data
if ('id_regata',str(self.id_regata)) in vars.items():
return self._post(vars) # triggers a data handler
else:
return self._form() # shows the clean form
(...)


-- wrappers.py -------------------------
class VarsWrapper:
def __init__(self,req):
self.fs = util.FieldStorage(req)

def get_vars():
d = {}
for each in self.fs.list:
self.d[x.name] = x.value
return d


So again, the problem arises when calling FormInscripcion.handle() for
the 2nd time or more: it will stick to the data received on the 1st
request passed to it. If i print the variable dictionary (c in race.py,
vars in formgen.py) after the form, c will change with new POST data, as
vars will stay constant after the 1st request.
The weird thing is that i'm passing data from pyhandler.py to race.py in
the same way that i'm passing it from race.py to formgen.py, and it
refuses to work correctly in the latter.
I have already tried pretty much every single possible cause for this
oddity with no consistent results, so i'm pretty confident that there's
something i'm missing that's not inherent to my app's logic, but to my
app's login combined with some mod_python specific complication.
In short: i'm going nuts!
Sorry for all the writing, but I really hope somebody can help me.
Thanks in advance,

Gonzalo Sainz-Trápaga (GomoX)
 
J

John Machin

-- wrappers.py -------------------------
class VarsWrapper:
def __init__(self,req):
self.fs = util.FieldStorage(req)

def get_vars():
d = {}
for each in self.fs.list:
self.d[x.name] = x.value
return d

Are you sure that is the code that you are executing? What is "x"?
What is "self.d"? "each" is not used. Even if "x" and "self.d" do
exist, the for loop will do nothing, and the method will return an
empty dictionary.

You weren't trying to "optimise" the references to self.d inside the
loop, were you?

Making the charitable assumptions that d and self.d are the same thing
and so are "x" and "each":

Assuming self.d does exist, why does it exist? I.e for what reason do
you want the data to persist? Could its persistence be the cause of
your problem? Are you sure you are not accidentally always referring
to the same VarsWrapper instance?

Is that all that VarsWrapper contains? Seems to me like an unnecessary
and possibly confusing convolution. If you "own" util.FieldStorage,
then giving it an as_dictionary() method might be a good idea.
Otherwise a simple wrapper *function* that replaces your two-step
__init__ and get_vars would be a not unreasonable idea; there's no law
that says that everything must be a class.

Are you sure you don't have a dict as a default arg somewhere, like in
def handle(self, vars={}) ??

HTH,

John
 
?

=?iso-8859-1?q?Gonzalo_Sainz-Tr=E1paga_=28GomoX=29

Hi John,
Thanks for your reply, I was feeling pretty desperate already with no one
talking to me :(

Are you sure that is the code that you are executing? What is "x"? What is
"self.d"? "each" is not used. Even if "x" and "self.d" do exist, the for
loop will do nothing, and the method will return an empty dictionary.

You are right, I'm sorry, my code has comments and variable names in
Spanish, so i made a translation of it. Obviously i was more stressed out
than i can remember and i came up with that nasty mess. The actual code is:


def get_vars(self):
if self.d == {}:
for x in self.fs.list:
self.d[x.name] = x.value
return self.d
Assuming self.d does exist, why does it exist? I.e for what reason do you
want the data to persist? Could its persistence be the cause of your
problem? Are you sure you are not accidentally always referring to the
same VarsWrapper instance?

self.d is initialized as "{}" on __init__(), and i'm using self.d this way
so that the parsing is done only once, upon get_vars() first call. After
this, self.d will be different than {} and i will just get the values.

Referring to the same VarsWrapper instance (or the same instance of some
other object) sounds like a plausible cause for my problem, since it works
the first time (upon the first instantiation) and keeps the same values
later. The problem is, I really don't see any way this could be happening.
I've checked the corresponding parts of the code a few hundred times rigth
now and I've made sure that every object is new and not reused. This is,
of course, unless there's some unexpected behaviour in mod_python (thing
like variables staying "alive" between executions of a script, or
something like this).
Is that all that VarsWrapper contains? Seems to me like an unnecessary and
possibly confusing convolution. If you "own" util.FieldStorage, then
giving it an as_dictionary() method might be a good idea. Otherwise a
simple wrapper *function* that replaces your two-step __init__ and
get_vars would be a not unreasonable idea; there's no law that says that
everything must be a class.

I guess you are right on this, actually the util.FieldStorage
implementation just replaced an older util.parse_qs() one that provided
with separated get_getvars() and get_postvars() methods, aside from the
get_vars() one. I went back to util.FieldStorage when I found this issue,
in order to reduce the possible origins for this behaviour.
Are you sure you don't have a dict as a default arg somewhere, like
in def handle(self, vars={}) ??

I'm positive about this: my code works fine right after a restart of the
server, but keeps seeing the same data after the first request, so the
bug is about unwanted persistence of the first request data, not about
defaults.

Anyway, I will try replacing VarsWrapper with a simple function in order
to avoid yet another possible bug cause.

Thanks again for your help, and if something else comes to your mind I
would really appreciate to hear about it, since i've pretty much ran out
of ideas by now. Anyhow, I will work on it some more tomorrow afternoon,
I'm taking a well deserved break now :D

Gonzalo
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,169
Latest member
ArturoOlne
Top