I am trying to add a timestamp column to the table shown in this Python Dash Example:
https://github.com/plotly/dash-sample-apps/blob/main/apps/dash-image-annotation/app.py
The aim is to have a timestamp for each of the created objects.
So far, I managed to:
Create a new column in the output table (Line 48 of the Github code)
Trying to append a timestamp by adding this to the "modify_table_entries" function (line 466 in the Github code):
annotations_table_data[0]["timestamp"] = time_passed(annotations_store_data["starttime"])
This gives me a timestamp only for the first entry in the output table:
I tried now however for several days now. I believe I have to somehow append the timestamp to each created object in this function of the code:
def modify_table_entries(
previous_n_clicks,
next_n_clicks,
graph_relayoutData,
annotations_table_data,
image_files_data,
annotations_store_data,
annotation_type,
):
cbcontext = [p["prop_id"] for p in dash.callback_context.triggered][0]
if cbcontext == "graph.relayoutData":
#debug_print("graph_relayoutData:", graph_relayoutData)
#debug_print("annotations_table_data before:", annotations_table_data)
if "shapes" in graph_relayoutData.keys():
# this means all the shapes have been passed to this function via
# graph_relayoutData, so we store them
annotations_table_data = [
shape_to_table_row(sh) for sh in graph_relayoutData["shapes"]
]
elif re.match("shapes\[[0-9]+\].x0", list(graph_relayoutData.keys())[0]):
# this means a shape was updated (e.g., by clicking and dragging its
# vertices), so we just update the specific shape
annotations_table_data = annotations_table_shape_resize(
annotations_table_data, graph_relayoutData
)
if annotations_table_data is None:
return dash.no_update
else:
debug_print("annotations_table_data after:", annotations_table_data)
annotations_table_data[0]["timestamp"] = time_passed(annotations_store_data["starttime"])
return (annotations_table_data, image_files_data)
image_index_change = 0
if cbcontext == "previous.n_clicks":
image_index_change = -1
if cbcontext == "next.n_clicks":
image_index_change = 1
image_files_data["current"] += image_index_change
image_files_data["current"] %= len(image_files_data["files"])
if image_index_change != 0:
# image changed, update annotations_table_data with new data
annotations_table_data = []
filename = image_files_data["files"][image_files_data["current"]]
#debug_print(annotations_store_data[filename])
for sh in annotations_store_data[filename]["shapes"]:
annotations_table_data.append(shape_to_table_row(sh))
return (annotations_table_data, image_files_data)
else:
return dash.no_update
Any help is much appreciated!
I am currently having an issue where I am trying to store data in a list (using dataclasses). When I print the data inside the list in the function (PullIncursionData()) it responded with a certain amount of numbers (never the same, not possible due to it's nature). When printing it after it being called to store it's return in a Var it somehow prints only the same number.
I cannot share the numbers, as they update with EVE Online's API, so the only way is to run it locally and read the first list yourself.
The repository is Here: https://github.com/AtherActive/EVEAPI-Demo
Heads up! Inside the main.py (the file with issues) (a snippet of code is down below) are more functions. All functions from line 90 and forward are important, the rest can be ignored for this question, as they do not interact with the other functions.
def PullIncursionData():
#Pulls data from URL and converts it into JSON
url = 'https://esi.evetech.net/latest/incursions/?datasource=tranquility'
data = rq.get(url)
jsData = data.json()
#Init var to store incursions
incursions = []
#Set lenght for loop. yay
length = len(jsData)
# Every loop incursion data will be read by __parseIncursionData(). It then gets added to var Incursions.
for i in range(length):
# Add data to var Incursion.
incursions.append(__parseIncursionData(jsData, i))
# If Dev mode, print some debug. Can be toggled in settings.py
if settings.developerMode == 1:
print(incursions[i].constellation_id)
return incursions
# Basically parses the input data in a decent manner. No comments needed really.
def __parseIncursionData(jsData, i):
icstruct = stru.Incursion
icstruct.constellation_id = jsData[i]['constellation_id']
icstruct.constellation_name = 'none'
icstruct.staging = jsData[i]['staging_solar_system_id']
icstruct.region_name = ResolveSystemNames(icstruct.constellation_id, 'con-reg')
icstruct.status = jsData[i]['state']
icstruct.systems_id = jsData[i]['infested_solar_systems']
icstruct.systems_names = ResolveSystemNames(jsData[i]['infested_solar_systems'], 'system')
return icstruct
# Resolves names for systems, regions and constellations. Still WIP.
def ResolveSystemNames(id, mode='constellation'):
#init value
output_name = 'none'
# If constellation, pull data and find region name.
if mode == 'con-reg':
url = 'https://www.fuzzwork.co.uk/api/mapdata.php?constellationid={}&format=json'.format(id)
data = rq.get(url)
jsData = data.json()
output_name = jsData[0]['regionname']
# Pulls system name form Fuzzwork.co.uk.
elif mode == 'system':
#Convert output to a list.
output_name = []
lenght = len(id)
# Pulls system name from Fuzzwork. Not that hard.
for i in range(lenght):
url = 'https://www.fuzzwork.co.uk/api/mapdata.php?solarsystemid={}&format=json'.format(id[i])
data = rq.get(url)
jsData = data.json()
output_name.append(jsData[i]['solarsystemname'])
return output_name
icdata = PullIncursionData()
print('external data check:')
length = len(icdata)
for i in range(length):
print(icdata[i].constellation_id)
structures.py (custom file)
#dataclass
class Incursion:
constellation_id = int
constellation_name = str
staging = int
staging_name = str
systems_id = list
systems_names = list
region_name = str
status = str
def ___init___(self):
self.constellation_id = -1
self.constellation_name = 'undefined'
self.staging = -1
self.staging_name = 'undefined'
self.systems_id = []
self.systems_names = []
self.region_name = 'undefined'
self.status = 'unknown'
I was playing around with pygtk to build my little project, that uses gtk, basically there is a window, in this window I have a treeview, inside the treeview a gtk.liststore.
Here is a image with the window and its values
Everything was cool until I realized that I was needing some tags, saw a lot of examples using pango, and it's work, at least until the row selected is changed.
I got around the problem with something not much elegant, and
here a link to the complete code:
def on_toolbar_button_clicked(self, widget, tag):
bounds_front = self.text_buffer_front.get_selection_bounds()
bounds_back = self.text_buffer_back.get_selection_bounds()
if len(bounds_front) != 0:
(start, end) = bounds_front
selection_front = self.text_buffer_front.get_text(start, end, True)
get_insert_front = self.text_buffer_front.get_insert()
self.text_buffer_front.delete(start, end)
iter_front = self.text_buffer_front.get_iter_at_mark(get_insert_front)
self.text_buffer_front.insert(iter_front, tag[0] + selection_front + tag[1])
Basically this method will put <u></u> around a word when I click at the toolbar underline button, and it's value will be placed at liststore, and also display that value with textview. This would be perfect if at least set_text detected these syntaxes.
So, what I'm trying to achieve is something that display the word tagged at textview and when I change the row and get back at the previous tagged row that it still display words tagged, like, if I underline a word, that it still underline when I get back, and in case the solution involves using pango, how can I get the values from it to use later.
What I tried so far was messing around textbuffer.serialize and textbuffer.deserialized, but it didn't worked as I want.
Edit
Like here I had applied underline tag to 'paper', serialized the textbuffer, put it inside a variable, but how can I pass it back to the buffer?
exported = self.text_buffer_front.serialize( self.text_buffer_front, format, start_iter_front, end_iter_front )
Printing the variable 'exported' I get a byte value:
b'GTKTEXTBUFFERCONTENTS-0001\x00\x00\x00w <text_view_markup>\n <tags>\n </tags>\n<text>A
At the first comes rock! Rock, <apply_tag name="underline">paper</apply_tag>, scissors!
Edit 2
This was probably obvious but not for me, if I have a serialized something all that I'll need to do next is just 'deserialize' it, and for that there is gtk.TextBuffer.deserialize.
The syntaxes should be something like this:
self.dict_any_tags = {str(key): value[1] for key, value in enumerate(self.sub_list_store)}
def item_selected(self, *args):
try:
iter_start_front = self.text_buffer_front.get_start_iter()
iter_end_front = self.text_buffer_front.get_end_iter()
path = self.selected_row.get_selected_rows()[1][0]
try:
self.text_buffer_front.deserialize(self.text_buffer_front, self.text_buffer_front.register_deserialize_tagset(), self.text_buffer_front.get_start_iter(), self.dict_any_tags[str(path)])
except:
self.text_buffer_front.set_text(self.sub_list_store[path][1])
except IndexError:
pass
def on_toolbar_button_clicked(self, widget, tag):
bounds_front = self.text_buffer_front.get_selection_bounds()
bounds_back = self.text_buffer_back.get_selection_bounds()
path = self.selected_row.get_selected_rows()[1][0]
if len(bounds_front) != 0:
(start, end) = bounds_front
selection_front = self.text_buffer_front.get_text(start, end, True)
get_insert_front = self.text_buffer_front.get_insert()
self.text_buffer_front.apply_tag(tag, start, end)
start_iter_front = self.text_buffer_front.get_start_iter()
end_iter_front = self.text_buffer_front.get_end_iter()
format = self.text_buffer_front.register_serialize_tagset()
exported = self.text_buffer_front.serialize( self.text_buffer_front,
format,
start_iter_front,
end_iter_front)
self.dict_any_tags[str(path)] = exported
The thing is that when I tried it before I was probably putting the deserialize at wrong place and with that it did nothing. Now I can track more easily where are the tags, etc. I just need run some more tests.
The key was create another iterator (I used a dictionary) to track the serialized text, then when I click in a row it tries to use deserialize function if the value is byte, caso is not it will simply set a text normally with set_text.
Also is important set the text to nothing set_text('') before deserialize, otherwise the previous value of the buffer will be placed in front of the current value at the buffer.
As for the changes on text, I used the method connect to connect the 'changed' signal and serialized the changes and passed the serialized value to the dictionary. And this is what I got:
# dictionary to track the tags
self.dict_any_change_front = {str(key): value[1] for key, value in enumerate(self.sub_list_store)}
self.dict_any_change_back = {str(key): value[1] for key, value in enumerate(self.sub_list_store_back)}
def deserialize(self, text_buffer, exported):
text_buffer.set_text('')
text_buffer.deserialize( text_buffer,
text_buffer.register_deserialize_tagset(),
text_buffer.get_start_iter(),
exported )
def item_selected(self, *args):
# Need this try/except to silent a indexerror that will occur case the second window close and if opened again,
# merely cosmetic as it will always occur, just select any row and all good.
# The get_selected_rows()[1] will return a empty list at first try when reopening the second window, I just don't know why
try:
path = self.selected_row.get_selected_rows()[1][0]
exported_front = self.dict_any_change_front[str(path)]
exported_back = self.dict_any_change_back[str(path)]
try:
if isinstance(exported_front, bytes):
self.deserialize(self.text_buffer_front, exported_front)
else:
self.text_buffer_front.set_text(self.sub_list_store[path][1])
if isinstance(exported_back, bytes):
self.deserialize(self.text_buffer_back, exported_back)
else:
self.text_buffer_back.set_text(self.sub_list_store_back[path][1])
except:
self.text_buffer_front.set_text(self.sub_list_store[path][1])
self.text_buffer_back.set_text(self.sub_list_store_back[path][1])
self.text_buffer_front.connect('changed', self.editingCard)
self.text_buffer_back.connect('changed', self.editingCardBack)
except IndexError:
pass
def editingCard(self, text_buffer):
path = self.selected_row.get_selected_rows()[1][0]
start_iter_front = text_buffer.get_start_iter()
end_iter_front = text_buffer.get_end_iter()
self.sub_list_store[path][1] = text_buffer.get_text(start_iter_front, end_iter_front, True)
format = text_buffer.register_serialize_tagset()
exported = text_buffer.serialize( text_buffer,
format,
start_iter_front,
end_iter_front )
self.dict_any_change_front[str(path)] = exported
def editingCardBack(self, text_buffer):
path = self.selected_row.get_selected_rows()[1][0]
start_iter_back = text_buffer.get_start_iter()
end_iter_back = text_buffer.get_end_iter()
self.sub_list_store_back[path][1] = text_buffer.get_text(start_iter_back, end_iter_back, True)
format = text_buffer.register_serialize_tagset()
exported = text_buffer.serialize( text_buffer,
format,
start_iter_back,
end_iter_back )
self.dict_any_change_back[str(path)] = exported
def on_toolbar_button_clicked(self, widget, tag_front, tag_back):
bounds_front = self.text_buffer_front.get_selection_bounds()
bounds_back = self.text_buffer_back.get_selection_bounds()
path = self.selected_row.get_selected_rows()[1][0]
##### FRONT
if len(bounds_front) != 0:
(start, end) = bounds_front
selection_front = self.text_buffer_front.get_text(start, end, True)
get_insert_front = self.text_buffer_front.get_insert()
self.text_buffer_front.apply_tag(tag_front, start, end)
start_iter_front = self.text_buffer_front.get_start_iter()
end_iter_front = self.text_buffer_front.get_end_iter()
format = self.text_buffer_front.register_serialize_tagset()
exported = self.text_buffer_front.serialize( self.text_buffer_front,
format,
start_iter_front,
end_iter_front )
self.dict_any_change_front[str(path)] = exported
###### BACK
if len(bounds_back) != 0:
(start, end) = bounds_back
selection_back = self.text_buffer_back.get_text(start, end, True)
get_insert_back = self.text_buffer_back.get_insert()
self.text_buffer_back.apply_tag(tag_back, start, end)
start_iter_back = self.text_buffer_back.get_start_iter()
end_iter_back = self.text_buffer_back.get_end_iter()
format = self.text_buffer_back.register_serialize_tagset()
exported = self.text_buffer_back.serialize( self.text_buffer_back,
format,
start_iter_back,
end_iter_back )
self.dict_any_change_back[str(path)] = exported
Working as I wanted :).
Edit
I adjusted my code to serialize everything at start and putting at the dictionary, instead of putting strings in the dictionary and as was editing the texts serializing the text and putting it the dictionary, with this was possible remove some if/else's and try/except's.
Also I created functions to serialize and deserialize thing, and put these functions in another file, I think this way is better.
myhandlerfile.py:
...
from myfuncfile import serializeIt, deserializeIt
...
# dictionary to track the tags
self.dict_any_change_front = {str(key): serializeIt(text_buffer=self.text_buffer_front, tmp_string=value[1]) \
for key, value in enumerate(self.sub_list_store)}
self.dict_any_change_back = {str(key): serializeIt(text_buffer=self.text_buffer_back, tmp_string=value[1]) \
for key, value in enumerate(self.sub_list_store_back)}
def item_selected(self, *args):
# Silencing a indexerror that will occur in case the window was hided and rised again
# it is not important, can be ignored
try:
path = self.selected_row.get_selected_rows()[1][0]
exported_front = self.dict_any_change_front[str(path)]
exported_back = self.dict_any_change_back[str(path)]
deserializeIt(self.text_buffer_front, exported_front)
deserializeIt(self.text_buffer_back, exported_back)
self.text_buffer_front.connect('changed', self.editingCard)
self.text_buffer_back.connect('changed', self.editingCardBack)
except IndexError:
pass
def editingCard(self, text_buffer_front):
# Silencing a indexerror that will occur in case the window was hided and rised again
# it is not important, can be ignored
try:
path = self.selected_row.get_selected_rows()[1][0]
start_iter_front = text_buffer_front.get_start_iter()
end_iter_front = text_buffer_front.get_end_iter()
self.sub_list_store[path][1] = text_buffer_front.get_text(start_iter_front, end_iter_front, True)
exported = serializeIt(text_buffer=text_buffer_front)
self.dict_any_change_front[str(path)] = exported
except IndexError:
pass
def editingCardBack(self, text_buffer_back):
# Silencing a indexerror that will occur in case the window was hided and rised again
# it is not important, can be ignored
try:
path = self.selected_row.get_selected_rows()[1][0]
start_iter_back = text_buffer_back.get_start_iter()
end_iter_back = text_buffer_back.get_end_iter()
self.sub_list_store_back[path][1] = text_buffer_back.get_text(start_iter_back, end_iter_back, True)
exported = serializeIt(text_buffer=text_buffer_back)
self.dict_any_change_back[str(path)] = exported
except IndexError:
pass
def on_toolbar_button_clicked(self, widget, tag_front, tag_back):
bounds_front = self.text_buffer_front.get_selection_bounds()
bounds_back = self.text_buffer_back.get_selection_bounds()
path = self.selected_row.get_selected_rows()[1][0]
##### FRONT
if len(bounds_front) != 0:
(start, end) = bounds_front
selection_front = self.text_buffer_front.get_text(start, end, True)
get_insert_front = self.text_buffer_front.get_insert()
self.text_buffer_front.apply_tag(tag_front, start, end)
exported = serializeIt(text_buffer=self.text_buffer_front)
self.dict_any_change_front[str(path)] = exported
###### BACK
if len(bounds_back) != 0:
(start, end) = bounds_back
selection_back = self.text_buffer_back.get_text(start, end, True)
get_insert_back = self.text_buffer_back.get_insert()
self.text_buffer_back.apply_tag(tag_back, start, end)
exported = serializeIt(text_buffer=self.text_buffer_back)
self.dict_any_change_back[str(path)] = exported
...
myfuncfile.py:
...
def serializeIt(text_buffer, tmp_string=None):
if tmp_string:
text_buffer.set_text(tmp_string)
tmp_start_iter = text_buffer.get_start_iter()
tmp_end_iter = text_buffer.get_end_iter()
tmp_format = text_buffer.register_serialize_tagset()
tmp_exported = text_buffer.serialize( text_buffer,
tmp_format,
tmp_start_iter,
tmp_end_iter )
return tmp_exported
else:
start_iter = text_buffer.get_start_iter()
end_iter = text_buffer.get_end_iter()
format = text_buffer.register_serialize_tagset()
exported = text_buffer.serialize( text_buffer,
format,
start_iter,
end_iter )
return exported
def deserializeIt(text_buffer, exported):
text_buffer.set_text('')
text_buffer.deserialize(text_buffer,
text_buffer.register_deserialize_tagset(),
text_buffer.get_start_iter(),
exported )
...
I'm trying to request a json object and run through the object with a for loop and take out the data I need and save it to a model in django.
I only want the first two attributes of runner_1_name and runner_2_name but in my json object the amount or runners varies inside each list. I keep getting list index out of range error. I have tried to use try and accept but when I try save to the model it's showing my save variables is referenced before assignment What's the best way of ignoring list index out or range error or fixing the list so the indexes are correct? I also want the code to run really fast as I will using this function as a background task to poll every two seconds.
#shared_task()
def mb_get_events():
mb = APIClient('username' , 'pass')
tennis_events = mb.market_data.get_events()
for data in tennis_events:
id = data['id']
event_name = data['name']
sport_id = data['sport-id']
start_time = data['start']
is_ip = data['in-running-flag']
par = data['event-participants']
event_id = par[0]['event-id']
cat_id = data['meta-tags'][0]['id']
cat_name = data['meta-tags'][0]['name']
cat_type = data['meta-tags'][0]['type']
url_name = data['meta-tags'][0]['type']
try:
runner_1_name = data['markets'][0]['runners'][0]['name']
except IndexError:
pass
try:
runner_2_name = data['markets'][0]['runners'][1]['name']
except IndexError:
pass
run1_par_id = data['markets'][0]['runners'][0]['id']
run2_par_id = data['markets'][0]['runners'][1]['id']
run1_back_odds = data['markets'][0]['runners'][0]['prices'][0]['odds']
run2_back_odds = data['markets'][0]['runners'][1]['prices'][0]['odds']
run1_lay_odds = data['markets'][0]['runners'][0]['prices'][3]['odds']
run2_lay_odds = data['markets'][0]['runners'][1]['prices'][3]['odds']
te, created = MBEvent.objects.update_or_create(id=id)
te.id = id
te.event_name = event_name
te.sport_id = sport_id
te.start_time = start_time
te.is_ip = is_ip
te.event_id = event_id
te.runner_1_name = runner_1_name
te.runner_2_name = runner_2_name
te.run1_back_odds = run1_back_odds
te.run2_back_odds = run2_back_odds
te.run1_lay_odds = run1_lay_odds
te.run2_lay_odds = run2_lay_odds
te.run1_par_id = run1_par_id
te.run2_par_id = run2_par_id
te.cat_id = cat_id
te.cat_name = cat_name
te.cat_type = cat_type
te.url_name = url_name
te.save()
Quick Fix:
try:
runner_1_name = data['markets'][0]['runners'][0]['name']
except IndexError:
runner_1_name = '' # don't just pass here
try:
runner_2_name = data['markets'][0]['runners'][1]['name']
except IndexError:
runner_2_name = ''
It giving you variables is referenced before assignment because in expect block you are just passing, so if try fails runner_1_name or runner_2_name is never defined. You when you try to use those variables you get an error because they were never defined. So in except block either set the value to a blank string or some other string like 'Runner Does not Exists'.
Now if you want to totally avoid try/except and IndexError you can use if statements to check the length of markets and runners. Something like this:
runner_1_name = ''
runner_2_name = ''
# Make sure markets exists in data and its length is greater than 0 and runners exists in first market
if 'markets' in data and len(data['markets']) > 0 and 'runners' in data['market'][0]:
runners = data['markets'][0]['runners']
# get runner 1
if len(runners) > 0 and `name` in runners[0]:
runner_1_name = runners[0]['name']
else:
runner_1_name = 'Runner 1 does not exists'
# get runner 2
if len(runners) > 1 and `name` in runners[1]:
runner_2_name = runners[1]['name']
else:
runner_2_name = 'Runner 2 does not exists'
As you can see this gets too long and its not the recommended way to do things.
You should just assume data is alright and try to get the names and use try/except to catch any errors as suggested above in my first code snippet.
I had the issue with a list of comments that can be empty or filled by an unknown number of comments
My solution is to initialize a counting variable at 0 and have a while loop on a boolean
In the loop I try to get comment[count] if it fails on except IndexError I set the boolean to False to stop the infinite loop
count = 0
condition_continue = True
while condition_continue :
try:
detailsCommentDict = comments[count]
....
except IndexError:
# no comment at all or no more comment
condition_continue = False
Is it possible to get the associated FbxNode from the enum ENodeId ?
for example if i want to get the FbxNode from the Character::eLeftHand
I tried to use Character::GetCharacterLink(ENodeId, FbxCharacterLink)
then extracting the FbxNode from FbxCharacterLink simply by calling FbxCharacterLink::mNode
However this function returns for most ENodeIds False, so no FbxCharacterLink is created.
character = myScene.GetCharacter(0)
lefthand = character.eLeftHand
lefthand_node = FbxCharacterLink()
character.GetCharacterLink(lefthand, lefthand_node) # False
lefthand_node = lefthand_node.mNode
when I was scripting inside Motionbuilder using Python and Pyfbxsdk, it was very easy, no matter how the skeleton objects are named, I can get the FBXObject of it
m = character.GetModel(self.BodyNodeObject[o])
and BodyNodeObject is generated with
def BodyNodes(self):
for i in dir(FBBodyNodeId):
if i[0] == 'k':
try:
self.BodyNodeObject[BodyNodesId[i]] = getattr(FBBodyNodeId, i)
except:
pass
BodyNodesId is simply a dictionary
BodyNodesId = OrderedDict({
'kFBChestNodeId':'Spine1',
'kFBHeadNodeId':'Head',
'kFBHipsNodeId':'Hips',
'kFBLeftAnkleNodeId':'LeftFoot',
'kFBLeftCollarNodeId':'LeftShoulder',
'kFBLeftElbowNodeId':'LeftForeArm',
...
})
this worked for me
from fbx import *
for i in range(myscene.GetCharacterCount()):
character = myscene.GetCharacter(i)
node = character.eHips
link = FbxCharacterLink()
while (character.GetCharacterLink(node, link)):
print node, link.mNode.GetName()
node = character.ENodeId(int(node+1))