save and recover Storage as string

67 views
Skip to first unread message

lucas

unread,
Apr 23, 2021, 12:43:19 PM4/23/21
to web2py-users
hello one and all,

i'd like to save and recover Storage instances to a text blob field in a database.  converting to the string is not hard to store it in the field.  recovering it back to a Storage instance is other issue, especially when they're embedded Storage objects in the main Storage object.  i've tried from a script file not under a web2py application as:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from sys import path, argv
path.append('/opt/web2py_apps/web2py/')
from gluon import *
from gluon.storage import Storage
if 1:
    ss = Storage(s='main')
    ss.happy = 'yes happy'
    #ss.status = Storage(s1="1status1", s2="2status2")
    print("1:::", ss, type(ss))
    ss = repr(ss)
    print("2:::", ss, type(ss))
    #xglobal, xlocal = globals(), { }
    #eval(ss, xglobal, xlocal)
    ss = eval(ss)
    print("3:::", ss, type(ss))
exit()

with output:
1::: <Storage {'s': 'main', 'happy': 'yes happy'}> <class 'gluon.storage.Storage'>
2::: <Storage {'s': 'main', 'happy': 'yes happy'}> <class 'str'>
Traceback (most recent call last):
  File "./web2py_Storage.py", line 17, in <module>
    ss = eval(ss)
  File "<string>", line 1
    <Storage {'s': 'main', 'happy': 'yes happy'}>
    ^
SyntaxError: invalid syntax

any ideas how to make this work smoothly?  thank you in advance, lucas

Dave S

unread,
Apr 25, 2021, 3:07:29 AM4/25/21
to web2py-users
When you convert the storage to string (via the repr() call), don't use the same name.

/dps

 

lucas

unread,
Apr 25, 2021, 3:52:24 PM4/25/21
to web2py-users
i'm sorry that doesn't make sense to me.  nonetheless, i tried it with different variable names, as:

if 1:
    ss = Storage(s='main')
    ss.happy = 'yes happy'
    print("1:::", ss, type(ss))
    s1 = repr(ss)
    print("2:::", s1, type(s1))
    s2 = eval(s1)
    print("3:::", s2, type(s2))

and i still got the same error:
1::: <Storage {'s': 'main', 'happy': 'yes happy'}> <class 'gluon.storage.Storage'>
2::: <Storage {'s': 'main', 'happy': 'yes happy'}> <class 'str'>
Traceback (most recent call last):
  File "./web2py_Storage.py", line 17, in <module>
    s2 = eval(s1)
  File "<string>", line 1
    <Storage {'s': 'main', 'happy': 'yes happy'}>
    ^
SyntaxError: invalid syntax

there are so many convertors like to and from json, wouldn't it make sense to and from string for storage?  thank you again, lucas

Dave S

unread,
Apr 28, 2021, 3:14:59 AM4/28/21
to web2py-users
On Sunday, April 25, 2021 at 12:52:24 PM UTC-7 lucas wrote:
i'm sorry that doesn't make sense to me.  nonetheless, i tried it with different variable names, as:

My thought was that using the same name was getting into type problems,. 

if 1:
    ss = Storage(s='main')
    ss.happy = 'yes happy'
    print("1:::", ss, type(ss))
    s1 = repr(ss)
    print("2:::", s1, type(s1))
    s2 = eval(s1)
    print("3:::", s2, type(s2))

and i still got the same error:
1::: <Storage {'s': 'main', 'happy': 'yes happy'}> <class 'gluon.storage.Storage'>
2::: <Storage {'s': 'main', 'happy': 'yes happy'}> <class 'str'>
Traceback (most recent call last):
  File "./web2py_Storage.py", line 17, in <module>
    s2 = eval(s1)
  File "<string>", line 1
    <Storage {'s': 'main', 'happy': 'yes happy'}>
    ^
SyntaxError: invalid syntax

there are so many convertors like to and from json, wouldn't it make sense to and from string for storage?  thank you again, lucas


Storage is a special version of dictionary (er, dict), and I don't recognize eval() as a way to initialize a dictionary.   Storage is also pretty simple as a child of dict; gluon/storage.py isn't many lines, and Storage isn't the only class defined there.

This does work:

s1 = "<Storage {'s': 'main', 'happy': 'yes happy'}>"
s2 = Storage()
for sub in s1.replace("<Storage {'",'').replace("'}>",'').split(','):
    key, val = sub.replace("'", "").split(':')
    key = key.strip().rstrip()
    val = val.strip().rstrip()
    s2[key] = val

print(s1, type(s1))
print(s2, type(s2))

Most of the mess in the code comes from de-formatting s1

lucas

unread,
Apr 30, 2021, 10:02:49 AM4/30/21
to web2py-users
yes, your method works.

changing the __repr__ line under gluon/storage.py to "__repr__ = lambda self: 'Storage(%s)' % dict.__repr__(self)" will also allow eval(s1) to create the proper and filled Storage instance, or without changing storage.py:

if 1:
    ss = Storage(s='main')
    ss.happy = 'yes happy'
    #ss.status = Storage(s1="1status1", s2="2status2")
    print("1:::", ss, type(ss))
    s1 = repr(ss)
    print("2:::", s1, type(s1))
    s2 = 'Storage('+s1[9:-1]+')'
    print('"%s"' % s2)
    s2 = eval(s2)
    print("3:::", s2, type(s2))
    print(s2.happy)
exit()

where we replace the "<Storage " with "Storage(" at the beginning and ">" with ")" at the end and eval does the rest.

thank you for your help.  i think __repr__ should be updated to my suggestion above so its easier to convert to and from string for easier db storage of python data.  lucas
Reply all
Reply to author
Forward
0 new messages