Creating a menu, adding the input to a list or csv file and display - csv

I am trying to create a programme that allows me to add, remove, amend and display details. I have created a general class and an additional class, that allowed me to hold an empty list and add/remove details.
I am now struggling with my menu and how to add further details and display these. Can anyone help, please?
from AircraftInspection_2 import AircraftInspection_2
from RoutineInspection import RoutineInspection
inspection = RoutineInspection()
end_of_add_String = "X to return to main menu\n"
def display_inspection_inventory():
#if inspection.number_of_aircrafts == 0
#return
print (f'{"SN":>3} {"TN":<7} {"AFhrs":<7} {"Zone":<3} {"Corrosion":<3} {"Component":<8} {"Fault":<8} {"Actionalbe":<5}')
for count aircraft in enumerate(inspection.aircrafts):
print(f'{count + 1:>3} {aircraft.Serial_Number:>3} {aircraft.Tail_No:<7} {aircraft.AF_hrs:<7} {aircraft.Zone:<3} {aircraft.Corrosion:<3} {aircraft.Component:<8} {aircraft.Fault:<8} {aircraft.Actionable:<5}')
def menu_options():
print("Menu: ")
print("Key A - Add details.")
print("Key R - Remove details.")
print("Key C - Change details.")
print("Key D - Display details.")
print("Key X - Exit the programme")
print(" ")
menu_options()
def menu_choice():
letters = {"a", "r", "c", "d", "x"}
select = input()
while any(letter in letters for letter in select) and len(select) == 1:
pass
return select
#menu_choice()
def add_aircraft():
aircraft = get_aircraft_details()
try:
routineinspection.add(aircraft)
except ValueError as e:
print(f"{str(e)}")
def get_aircraft_details():
Tail_No = input("Please enter tailnumber: ")
AF_hours = int(input("Enter airframe hours: "))
Zone = input("Enter inspected zone: ")
Corrosion = int(input("Enter corrosion level: "))
Component = input("Enter inspected component: ")
Fault = input("Enter type of fault: ")
Actionable = bool(input("Enter 1 if actionable, 0 if not: "))
aircraft = Aircraft(Tail_No = Tail_No, AF_hours = AF_hours, Zone = Zone, Corrosion = Corrosion, Component = Component, Fault = Fault, Actionable = Actionable)
return aircraft
def remove_aircraft():
routineinspection.remove(aircraft)
while True:
display_inspection_inventory()
menu_options()
menu_choice()
option = menu_choice().upper()
if option == "A":
add_aircraft()
elif option == "R":
remove_aircraft()
#elif option =="C":
#amend_aircraft()
elif option == "X":
confirm = input("Do you want to quit the programme, y or n?").lower()
if confirm == "y":
break
else:
pass
print("See you again soon.")

Related

Tkinter and requests: Can fetch weather using zipcode

from tkinter import *
import requests
import json
root = Tk()
root.geometry('400x400')
def searchbyzip():
try:
zipcode=zipentry.get()
api_request = requests.get("http://www.airnowapi.org/aq/observation/zipCode/current/?format=application/json&zipCode="+zipcode+"10001&distance=5&API_KEY=2FF97EFB-2391-4403-9001-EA249EEDACDB")
api = json.loads(api_request.content)
city = api[0]['ReportingArea']
quality=api[0]['AQI']
category=api[0]['Category']['Name']
if category == "Good":
weather_color='"#0C0"'
elif category == "Moderate":
weather_color="#FFFF00"
elif category == "Unhealthy for Sensitive Groups":
weather_color="#FFFF00"
elif category == "Unhealthy":
weather_color="#FF0000"
elif category == "Very Unhealthy":
weather_color="#990066"
elif category == "Hazardous":
weather_color="#660000"
root.config(bg=weather_color)
apilabel = Label(root, text="City: "+city+'\n'+'Quality: '+str(quality)+"\n"+'Category: '+category, font=("Helvetica",20),bg=weather_color)
apilabel.grid(row=2,column=0,columnspan=2)
except Exception:
api="No internet connection"
errorlabel = Label(root,text=api)
errorlabel.grid(row=0,column=0)
zipentry = Entry(root)
zipentry.grid(row=0,column=1,columnspan=2,pady=5)
zipbutton = Button(root, text="Search By Zip",command=searchbyzip)
zipbutton.grid(row=1,column=0,columnspan=2)
root.mainloop()
It works for the default zipcode but it throws the exception block when I enter a custom zipcode. Really can't identify the problem here. Also I am new to tkinter and kinda exploring right now.

Google Cloud Functions - How to set up a function (trading bot)

I would like to set up a trading bot via Google Cloud to run around the clock.
In Google Cloud Functions I use the Inline editor with runtime Python 3.7.
I have two questions:
1) Main.py section: Here I copied the full code of my Python script (Trading Bot) - see code below for reference (which works well when run as a script in my IDE Spyder).
However, below Google asks to provide a function to execute. However, my code is just a script with no main function. Can I just put at the top of the code e.g.: "def trading_bot(self):" and indent the remaining part below?
While the code as a script copied below works well, if I add the "def trading_bot(self):" at the top in my IDE (Spyder), the code doesnt seem to work properly...How can I make sure the code within the function runs properly, when I call the function from Google Cloud (or from my IDE).
2) Requirements.txt section: Can you provide guidance what exactly I need to put there, i.e. can I look up the dependencies used in my code somewhere? I use Anaconda for distribution, the classes imported for the script are at the top of the script provided below.
Thanks for any help. Glad also for your advice if you think Google Cloud Functions is not the best approach to run a trading bot but it seemed to me to be the simplest solution.
import bitmex
import json
from time import sleep
from bitmex_websocket import BitMEXWebsocket
import logging, time, requests
import numpy as np
import pandas as pd
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
from datetime import datetime
import math
from statistics import mean
#-------------------------
#variable
symbol = "XBTUSD"
#standard API connection
api_key = "XXX"
api_secret = "XXX"
#True for testnet
client = bitmex.bitmex(test=False, api_key=api_key, api_secret=api_secret)
#------------------
# Trading algorithm
symbol = "XBTUSD"
ordType = 'Stop'
#starting order quantity
orderQty = 1
leftBars = 6
rightBars = 2
#round to 0.5
def round_to_BTC(n):
result = round(n*2)/2
return result
t=1
while t < 1000000:
time_now = (time.strftime('%H:%M:%S', time.localtime(int(time.time()))))
t_now = time_now[6:8]
t1 = "00"
t2 = "59"
FMT = '%S'
def days_hours_minutes_seconds(td):
return td.days, td.seconds//3600, (td.seconds//60)%60, td.seconds
if t_now == str('00'):
#give 1 second to candlestick to properly close
sleep(1)
elif t_now > str('00') and t_now <= str('59'):
s1 = datetime.strptime(t2, FMT) - datetime.strptime(t_now, FMT)
s1_seconds = days_hours_minutes_seconds(s1)[3]+2
sleep(s1_seconds)
else:
pass
time_now = (time.strftime('%H:%M:%S', time.localtime(int(time.time()))))
print("The time is now: " + time_now)
#most recent swing candles, get highs and lows / #binsizes = {"1m": 1, "5m": 5, "1h": 60, "1d": 1440}
#+1 is the middle bar
totalBars = leftBars + rightBars + 1
swing_candles = client.Trade.Trade_getBucketed(symbol=symbol, binSize="1m", count=totalBars, reverse=True).result()[0]
last_highs = []
last_lows = []
i=0
while i <= (len(swing_candles)-1):
last_highs.append(swing_candles[i]["high"])
last_lows.append(swing_candles[i]["low"])
i += 1
#get the highest high and the lowest low
highest_high = max(last_highs)
lowest_low = min(last_lows)
#check if there are existing positions & orders
if client.Position.Position_get().result()[0] != []:
positions_quantity = client.Position.Position_get().result()[0][0]["currentQty"]
else:
positions_quantity = 0
#check existing orders
buy_orders_quantity = []
sell_orders_quantity = []
orders_quantity = client.Order.Order_getOrders(filter=json.dumps({"open": True})).result()[0]
h=0
while h <= len(orders_quantity)-1:
if orders_quantity[h]["side"] == "Sell":
sell_orders_quantity.append(orders_quantity[h])
elif orders_quantity[h]["side"] == "Buy":
buy_orders_quantity.append(orders_quantity[h])
h += 1
if highest_high == last_highs[rightBars] and positions_quantity == 0:
if buy_orders_quantity == []:
client.Order.Order_new(symbol = symbol, orderQty = orderQty*1, side = "Buy", ordType = 'Stop', stopPx = (highest_high+0.5), execInst ='LastPrice' ).result()
elif buy_orders_quantity != []:
orderID = buy_orders_quantity[0]["orderID"]
client.Order.Order_amend(orderID=orderID, orderQty=orderQty*1, stopPx = (highest_high+0.5)).result()
else:
pass
elif highest_high == last_highs[rightBars] and positions_quantity > 0:
#dont place any additional long
pass
elif highest_high == last_highs[rightBars] and positions_quantity < 0:
if buy_orders_quantity != []:
orderID = buy_orders_quantity[0]["orderID"]
client.Order.Order_amend(orderID=orderID, orderQty=orderQty*2, stopPx = (highest_high+0.5)).result()
else:
client.Order.Order_new(symbol = symbol, orderQty = (orderQty)*2, side = "Buy", ordType = 'Stop', stopPx = (highest_high+0.5), execInst ='LastPrice' ).result()
elif lowest_low == last_lows[rightBars] and positions_quantity == 0:
if sell_orders_quantity == []:
client.Order.Order_new(symbol = symbol, orderQty = (orderQty)*-1, side = "Sell", ordType = 'Stop', stopPx = (lowest_low-0.5), execInst ='LastPrice' ).result()
elif sell_orders_quantity != []:
orderID = sell_orders_quantity[0]["orderID"]
client.Order.Order_amend(orderID=orderID, orderQty=orderQty*-1, stopPx = (lowest_low-0.5)).result()
else:
pass
elif lowest_low == last_lows[rightBars] and positions_quantity < 0:
#dont place any additional shorts
pass
elif lowest_low == last_lows[rightBars] and positions_quantity > 0:
if sell_orders_quantity != []:
orderID = sell_orders_quantity[0]["orderID"]
client.Order.Order_amend(orderID=orderID, orderQty=orderQty*-2, stopPx = (lowest_low-0.5)).result()
else:
client.Order.Order_new(symbol = symbol, orderQty = (orderQty)*-2, side = "Sell", ordType = 'Stop', stopPx = (lowest_low-0.5), execInst ='LastPrice' ).result()
positions_quantity = client.Position.Position_get().result()[0][0]["currentQty"]
buy_orders_quantity = []
sell_orders_quantity = []
orders_quantity = client.Order.Order_getOrders(filter=json.dumps({"open": True})).result()[0]
h=0
while h <= len(orders_quantity)-1:
if orders_quantity[h]["side"] == "Sell":
sell_orders_quantity.append(orders_quantity[h])
elif orders_quantity[h]["side"] == "Buy":
buy_orders_quantity.append(orders_quantity[h])
h += 1
if positions_quantity > 0:
if sell_orders_quantity != []:
orderID = sell_orders_quantity[0]["orderID"]
client.Order.Order_amend(orderID=orderID, orderQty=orderQty*-2).result()
elif positions_quantity < 0:
if buy_orders_quantity != []:
orderID = buy_orders_quantity[0]["orderID"]
client.Order.Order_amend(orderID=orderID, orderQty=orderQty*2).result()
print("Your current position is " + str(positions_quantity))
print("This is iteration: " + str(t))
t += 1
As concerns my second question, I solved it in the following way:
In the command terminal, type: pip freeze > requirements.txt
The file contains all dependencies.
As concerns question 1 I still dont understand what code exactly needs to be put in the section main.py.
Thanks!
Cloud Functions is not an adequate product for your use case. They are mostly used for lightweight calculations or not high resource consuming methods.
The magic of CF consists in that they execute your code whenever you hit the URL that belongs to it. This is important to understand for your question number 1. If you want your function to work, you need to always create a method that accepts the "request" parameter. As it is the information from the HTTP request made when the URL is hit.
You can take a look at this document for reference.
You function should always start like this
from flask #import your dependencies
def my_awesome_function(request):
#Your logic
In this case you should write "my_awesome_function" on the Function to Execute textbox.
You also have to be careful with your resources, as CF have 5 presentations. They differ in CPU and Memory you can read more about this here.
This, among many reasons, you should not use Cloud Functions for your bot. I could recommend you to use a virtual machine, but activities related to use of the Services for cryptocurrency mining without Google's prior written approval are frowned upon and may result in the deactivation of your product as stated in the terms of service.

I cannot access dropdown widget output in a loop

I have been going in circles for hours.
I am trying to get the dropdown output to loop, to ensure the result is correct.
I get the dropdown list, but the "output" is none.
If I select 'DEV' or "DEV", it prints DEV. The output (w) is none and the loop exits at else not if??
The python code (jypter):
source = ["Select Source", "DEV", "TEMP", "PROD"]
source_ = widgets.Dropdown(
options=source,
value=source[0],
description='Select variable:',
disabled=False,
button_style=''
)
def sourceURL(b):
clear_output()
print(source_.value)
### Drop Down
print("Drop Down")
display(source_)
w = source_.observe(sourceURL)
## print("output: ")
print(w) ### output is None
#### LOOP
if w == 'DEV':
print("This is Dev")
elif w == "TEST":
print("This is TEST")
else:
print("This is PROD")
When you do source_.observe(sourceURL), there is no return value from this call. Hence this is equivalent to w = None.
To get the behaviour you want, I think you would need to move the code at the end of your script into your sourceURL function.
import ipywidgets as widgets
from IPython.display import clear_output
source = ["DEV", "TEMP", "PROD"]
source_ = widgets.Dropdown(
options=source,
value=source[0],
description='Select variable:',
disabled=False,
button_style=''
)
def sourceURL(b):
# clear_output()
w = b['new']
if w == 'DEV':
print("This is Dev")
elif w == "TEMP":
print("This is TEMP")
else:
print("This is PROD")
### Drop Down
print("Drop Down")
display(source_)
w = source_.observe(sourceURL, names='value')

Using integers with dictionary to create text menu (Switch/Case alternative)

I am working my way through the book Core Python Programming. Exercise 2_11 instructed to build a menu system that had allowed users to select and option which would run an earlier simple program. the menu system would stay open until the user selected the option to quit. Here is my first working program.
programList = {1:"menu system",
2:"for loop count 0 to 10",
3:"positive or negative",
4:"print a string, one character at a time",
5:"sum of a fixed tuple",
"x":"quit()",
"menu":"refresh the menu"}
import os
for x in programList:
print(x,":",programList[x])
while True:
selection = input("select a program: ")
if selection == "1":
os.startfile("cpp2_11.py")
elif selection == "2":
os.startfile("cpp2_5b.py")
elif selection == "3":
os.startfile("cpp2_6.py")
elif selection == "4":
os.startfile("cpp2_7.py")
elif selection == "5":
os.startfile("cpp2_8.py")
elif selection == "menu":
for x in range(8): print(" ")
for x in programList:print(x,":",programList[x])
elif selection == "X":
break
elif selection == "x":
break
else:
print("not sure what you want")
input()
quit()
This version worked fine, but I wanted to use the a dictionary as a case/switch statement to clean up the ugly if/elif/else lines.
Now I'm stuck. I'm using Eclipse with PyDev and my new code is throwing an error:
Duplicated signature:!!
Here's a copy of my current code:
import os
def '1'():
os.startfile("cpp2_11.py")
def '2'():
os.startfile("cpp2_5b.py")
def '3'():
os.startfile("cpp2_6.py")
def '4'():
os.startfile("cpp2_7.py")
def '5'():
os.startfile("cpp2_8.py")
def 'm'():
for x in range(8): print(" ")
for x in actions:print(x,":",actions[x])
def 'x'():
quit()
def errhandler():
else:
print("not sure what you want")
actions = {1:"menu system",
2:"for loop count 0 to 10",
3:"positive or negative",
4:"print a string, one character at a time",
5:"sum of a fixed tuple",
"X":"quit()",
"menu":"refresh the menu"}
for x in actions:
print(x,":",actions[x])
selectedaction = input("please select an option from the list")
while True:
actions.get(selectedaction,errhandler)()
input()
quit()
I'm pretty sure that my current problem (the error codes) are related to the way I'm trying to use the os.startfile() in the functions. Maybe I'm way off. Any help is appreciated.
EDIT: I am changing the title to make it more useful for future reference. After a helpful comment from Ryan pointing out the simple error in function naming, I was able to piece together a script that works. sort of...Here it is:
import os
def menu_system():
os.startfile("cpp2_11alt.py")
def loopCount_zero_to_ten():
os.startfile("cpp2_5b.py")
def positive_or_negative():
os.startfile("cpp2_6.py")
def print_a_string_one_character_at_a_time():
os.startfile("cpp2_7.py")
def sum_of_a_tuples_values():
os.startfile("cpp2_8.py")
def refresh_the_menu():
for x in range(4): print(" ")
for y in actions:print(y,":",actions[y])
for z in range(2): print(" ")
def exit_the_program():
quit()
def errhandler():
print("not sure what you want")
actions = {'1':menu_system,
'2':loopCount_zero_to_ten,
'3':positive_or_negative,
'4':print_a_string_one_character_at_a_time,
'5':sum_of_a_tuples_values,
'x':exit_the_program,
'm':refresh_the_menu}
for item in actions:
print(item,":",actions[item])
for z in range(2): print(" ")
selectedaction = input("please select an option from the list: ")
while True:
actions.get(selectedaction,errhandler)()
selectedaction = input("please select an option from the list: ")
quit()
There were many problems with the second attempt. I was referencing the dictionary key instead of the value when calling functions. I also had some bugs in the way the menu printed and handled input values. Now all I need to do is figure out how to get the dictionary values to print without all of the extra information:
This is the output when I print the menu:
2 : <function loopCount_zero_to_ten at 0x027FDA08>
3 : <function positive_or_negative at 0x027FD810>
1 : <function menu_system at 0x027FD978>
4 : <function print_a_string_one_character_at_a_time at 0x027FD930>
5 : <function sum_of_a_tuples_values at 0x027FD780>
x : <function exit_the_program at 0x027FD858>
m : <function refresh_the_menu at 0x027FD7C8>
AND how to get the menu to print in numeric order.
Once again, any help is appreciated.
I finally found a solution to the problem of sorting a dictionary and printing the function names as a string. In the last part of the edited question (3rd code section), I had the fixed code for the question that started this post: how to use integers in a dictionary to create a menu - with the intention of creating a switch/case style alternative and avoiding the ugly if/elif/else problems in the first code section.
Here's the final version of the working code:
import os
def menu_system():
os.startfile("cpp2_11alt.py")
def loopCount_zero_to_ten():
os.startfile("cpp2_5b.py")
def positive_or_negative():
os.startfile("cpp2_6.py")
def print_a_string_one_character_at_a_time():
os.startfile("cpp2_7.py")
def sum_of_a_tuples_values():
os.startfile("cpp2_8.py")
def refresh_the_menu():
for x in range(4): print(" ")
for key in sorted(actions):
print (key, '=>', actions[key].__name__)
for z in range(2): print(" ")
def exit_the_program():
quit()
def errhandler():
print("not sure what you want")
actions = {'1':menu_system,
'2':loopCount_zero_to_ten,
'3':positive_or_negative,
'4':print_a_string_one_character_at_a_time,
'5':sum_of_a_tuples_values,
'x':exit_the_program,
'm':refresh_the_menu}
for key in sorted(actions):
print (key, '=>', actions[key].__name__)
selectedaction = input("please select an option from the list: ")
while True:
actions.get(selectedaction,errhandler)()
selectedaction = input("please select an option from the list: ")
quit()
adding the .__name__ method allowed me to print the function names as a string.
Using the for loop:
for key in sorted(actions):
print (key, '=>', actions[key].__name__)
created the ability to sort the dictionary.

Easier way to create a JSON object from an SQLObject

EDIT -- took the code from below and made it so it can handle ForiegnKeys, Decimal numbers (although i'm doing a very forced float conversion). It returns a dict now so it can be recursive.
from sqlobject import SQLObject
from decimal import Decimal
def sqlobject_to_dict(obj):
json_dict = {}
cls_name = type(obj)
for attr in vars(cls_name):
if isinstance(getattr(cls_name, attr), property):
attr_value = getattr(obj, attr)
attr_class = type(attr_value)
attr_parent = attr_class.__bases__[0]
if isinstance(getattr(obj, attr), Decimal):
json_dict[attr] = float(getattr(obj, attr))
elif attr_parent == SQLObject:
json_dict[attr] = sqlobject_to_dict(getattr(obj, attr))
else:
json_dict[attr] = getattr(obj, attr)
return json_dict
EDIT -- changed to add the actual data model -- there are generated values that need to be accessed and Decimal() columns that need dealing with as well.
So I've seen this: return SQL table as JSON in python but it's not really what I'm looking for -- that's "brute force" -- you need to know the names of the attributes of the object in order to generate the JSON response.
What I'd like to do is something like this (the name of the class and it's attributes are not-important)
class BJCPStyle(SQLObject):
name = UnicodeCol(length=128, default=None)
beer_type = UnicodeCol(length=5, default=None)
category = ForeignKey('BJCPCategory')
subcategory = UnicodeCol(length=1, default=None)
aroma = UnicodeCol(default=None)
appearance = UnicodeCol(default=None)
flavor = UnicodeCol(default=None)
mouthfeel = UnicodeCol(default=None)
impression = UnicodeCol(default=None)
comments = UnicodeCol(default=None)
examples = UnicodeCol(default=None)
og_low = SGCol(default=None)
og_high = SGCol(default=None)
fg_low = SGCol(default=None)
fg_high = SGCol(default=None)
ibu_low = IBUCol(default=None)
ibu_high = IBUCol(default=None)
srm_low = SRMCol(default=None)
srm_high = SRMCol(default=None)
abv_low = DecimalCol(size=3, precision=1, default=None)
abv_high = DecimalCol(size=3, precision=1, default=None)
versions = Versioning()
def _get_combined_category_id(self):
return "%s%s" % (self.category.category_id, self.subcategory)
def _get_og_range(self):
low = self._SO_get_og_low()
high = self._SO_get_og_high()
if low == 0 and high == 0:
return "varies"
else:
return "%.3f - %.3f" % (low, high)
def _get_fg_range(self):
low = self._SO_get_fg_low()
high = self._SO_get_fg_high()
if low == 0 and high == 0:
return "varies"
else:
return "%.3f - %.3f" % (low, high)
def _get_srm_range(self):
low = self._SO_get_srm_low()
high = self._SO_get_srm_high()
if low == 0 and high == 0:
return "varies"
else:
return "%.1f - %.1f" % (low, high)
def _get_abv_range(self):
low = self._SO_get_abv_low()
high = self._SO_get_abv_high()
if low == 0 and high == 0:
return "varies"
else:
return "%.2f%% - %.2f%%" % (low, high)
def _get_ibu_range(self):
low = self._SO_get_ibu_low()
high = self._SO_get_ibu_high()
if low == 0 and high == 0:
return "varies"
else:
return "%i - %i" % (low, high)
Is there an easy way, pythonic way to write that magic to_json() function?
You can use the python json module with the SQLObject sqlmeta class. Like this:
def to_json(obj):
return json.dumps(dict((c, getattr(obj, c)) for c in obj.sqlmeta.columns))
When I run this with your class Foo I get:
>>> print to_json(f)
{"bar": "test", "lulz": "only for the", "baz": true}
Edit: if you want to include magic attributes in your json string and you don't mind using something of a hack, you could abuse the fact that the attributes of your object are python properties. For example, if I add a magic attribute foo to your original sample class:
class Foo(SQLObject):
bar = UnicodeCol(length=128)
baz = BoolCol(default=True)
lulz = UnicodeCol(length=256)
def _get_foo(self):
return "foo"
Then I can define the to_json() function like this:
def to_json(obj):
cls = type(obj)
d = dict((c, getattr(obj, c)) for c in vars(cls) if isinstance(getattr(cls, c), property))
return json.dumps(d)
Now, if I do this:
f = Foo(bar = "test", lulz = "only for the")
print to_json(f)
I get the following result:
{"baz": true, "lulz": "only for the", "bar": "test", "foo": "foo"}
import json
json.dumps(obj_instance.sqlmeta.asDict())
In my case this object contained datetimes which json doesn't serialize, so I did something like this:
json.dumps(dict((k, str(v)) for (k,v) in obj_instance.sqlmeta.asDict().items()))
Something like this ...
class MyTable( sqlobject.SQLObject ):
# ... your columns ...
json.dumps({
'MyTable': [row.sqlmeta.asDict() for row in MyTable.select()]
}, indent=4, sort_keys=True )
Suppose you have a list of sqlobject.SQLObject derived classes called
'Tables'
Tables = [MyTable, ...]
def dump():
r={}
for t in Tables:
r[t.__name__] = [row.sqlmeta.asDict() for row in t.select()]
return json.dumps(r, indent=4, sort_keys=True)