SmartSheet API python extended object - python

There are several objects in the SmartSheet SDK API which are extensions of objects. For instance, CellLink and ObjectValue are an extensions of the Cell object. I've done some reading and understand that these are parent/child classes and involve inheritance. However, this concept still escapes me and I cannot figure out the syntax for creating a CellLink object.
new_cell = ss.models.Cell()
linked_cell = ss.models.Cell()
linked_cell.column_id = int(columnid)
linked_cell.sheet_id = int(sheetid)
linked_cell.row_id = int(rowid)
new_cell.link_in_from_cell = linked_cell
The example above gives me the most informative error message therefore, I assume it is the closest to the correct syntax of all the variations I have tried. Any help with this example and possibly the underlying concept would be greatly appreciated.
raise ValueError("`{0}` invalid type for {1} value".format(value,
self.object_type))
ValueError: `{"columnId": 2068210422966148}` invalid type for <class
'smartsheet.models.cell_link.CellLink'> value
I believe I have found the answer to this question. It seems as though you just need to create a dictionary of the attributes like:
ex_dict = {sheet_id: 0974792938, column_id: 07263839242, row_id:
2632938474839}
new_cell.link_in_from_cell = ex_dict
The trick is later in the code. Instead of creating a new row like:
row = ss.models.Row()
You need to update an existing row like:
row = ss.Sheets.get_row(sheet_id, row_id)
However, I am still having a weird error of:
Field \"createdAt\" was of unexpected type.

You should be sending Row and Cell objects with only the properties that you wish to change. You do not want to attempt to modify an existing Row object (e.g. with the createdAt property, but rather allocate a new one with appropriate row id and cells to update.
See https://github.com/smartsheet-samples/python-snippets/blob/04951c2ca8ae1a97386bdd3fa6e010f2845e1421/samples.py#L45 for a complete example of creating a cell link.

Related

Writing values to new field, Python GDAL OGR, not sure how to commit the changes, why are my fields still empty?

Im reading in some s-57 from 2 sources using gdal/ogr and writing it to a memory datasourse.
The data is loading sucessfully and I can see layers and values etc.
encdriver = ogr.GetDriverByName("S57")
new_enc = encdriver.Open(new_enc_path)
old_enc = encdriver.Open(new_enc_path)
memdriver=ogr.GetDriverByName('MEMORY')
memsource=memdriver.CreateDataSource('memData')
tmp=memdriver.Open('memData',1)
memsource.CopyLayer(new_enc.GetLayerByName('lights'), 'new_lights',['OVERWRITE=YES'])
memsource.CopyLayer(old_enc.GetLayerByName('lights'), 'old_lights',['OVERWRITE=YES'])
new_lights = memsource.GetLayerByName('new_lights')
old_lights = memsource.GetLayerByName('old_lights')
I am then defining a new field (boolean) and adding it to the layer then setting it to true or false in each layer.
new_field = ogr.FieldDefn('NEW', ogr.OFSTBoolean)
new_lights.CreateField(new_field)
old_lights.CreateField(new_field)
layerDefinition = new_lights.GetLayerDefn()
print(layerDefinition.GetFieldCount())
new_lights.ResetReading()
old_lights.ResetReading()
print('NEW')
for feat in new_lights:
feat.SetField('NEW', True)
new_lights.CommitTransaction()
print(feat.GetField('NEW'))
print('OLD')
for feat in old_lights:
feat.SetField('NEW', False)
old_lights.CommitTransaction()
print(feat.GetField('NEW'))
In both the loops above the field is printed with the new value [0] or [1]
print('OLD2')
old_lights.ResetReading()
for feat in old_lights:
print(feat.GetField('NEW'))
but when I try and read these layers after the above loop, the new field is 'None', has no values, I tried adding datasource.CommitTransaction() but it doesnt seem to have helped. Could someone help explain what Im missing here, Im not sure why the values are not being written to the field but I can see the field does now exist.
I should of continued reading, found this, seems I was a bit early posting a question.
This function is the same as the C++ method OGRFeature::SetField().
This method has only an effect on the in-memory feature object. If
this object comes from a layer and the modifications must be
serialized back to the datasource, OGR_L_SetFeature() must be used
afterwards. Or if this is a new feature, OGR_L_CreateFeature() must be
used afterwards.

Python- Insert new values into 'nested' list?

What I'm trying to do isn't a huge problem in php, but I can't find much assistance for Python.
In simple terms, from a list which produces output as follows:
{"marketId":"1.130856098","totalAvailable":null,"isMarketDataDelayed":null,"lastMatchTime":null,"betDelay":0,"version":2576584033,"complete":true,"runnersVoidable":false,"totalMatched":null,"status":"OPEN","bspReconciled":false,"crossMatching":false,"inplay":false,"numberOfWinners":1,"numberOfRunners":10,"numberOfActiveRunners":8,"runners":[{"status":"ACTIVE","ex":{"tradedVolume":[],"availableToBack":[{"price":2.8,"size":34.16},{"price":2.76,"size":200},{"price":2.5,"size":237.85}],"availableToLay":[{"price":2.94,"size":6.03},{"price":2.96,"size":10.82},{"price":3,"size":33.45}]},"sp":{"nearPrice":null,"farPrice":null,"backStakeTaken":[],"layLiabilityTaken":[],"actualSP":null},"adjustmentFactor":null,"removalDate":null,"lastPriceTraded":null,"handicap":0,"totalMatched":null,"selectionId":12832765}...
All I want to do is add in an extra field, containing the 'runner name' in the data set below, into each of the 'runners' sub lists from the initial data set, based on selection_id=selectionId.
So initially I iterate through the full dataset, and then create a separate list to get the runner name from the runner id (I should point out that runnerId===selectionId===selection_id, no idea why there are multiple names are used), this works fine and the code is shown below:
for market_book in market_books:
market_catalogues = trading.betting.list_market_catalogue(
market_projection=["RUNNER_DESCRIPTION", "RUNNER_METADATA", "COMPETITION", "EVENT", "EVENT_TYPE", "MARKET_DESCRIPTION", "MARKET_START_TIME"],
filter=betfairlightweight.filters.market_filter(
market_ids=[market_book.market_id],
),
max_results=100)
data = []
for market_catalogue in market_catalogues:
for runner in market_catalogue.runners:
data.append(
(runner.selection_id, runner.runner_name)
)
So as you can see I have the data in data[], but what I need to do is add it to the initial data set, based on the selection_id.
I'm more comfortable with Php or Javascript, so apologies if this seems a bit simplistic, but the code snippets I've found on-line only seem to assist with very simple Python lists and nothing 'nested' (to me the structure seems similar to a nested array).
As per the request below, here is the full list:
{"marketId":"1.130856098","totalAvailable":null,"isMarketDataDelayed":null,"lastMatchTime":null,"betDelay":0,"version":2576584033,"complete":true,"runnersVoidable":false,"totalMatched":null,"status":"OPEN","bspReconciled":false,"crossMatching":false,"inplay":false,"numberOfWinners":1,"numberOfRunners":10,"numberOfActiveRunners":8,"runners":[{"status":"ACTIVE","ex":{"tradedVolume":[],"availableToBack":[{"price":2.8,"size":34.16},{"price":2.76,"size":200},{"price":2.5,"size":237.85}],"availableToLay":[{"price":2.94,"size":6.03},{"price":2.96,"size":10.82},{"price":3,"size":33.45}]},"sp":{"nearPrice":null,"farPrice":null,"backStakeTaken":[],"layLiabilityTaken":[],"actualSP":null},"adjustmentFactor":null,"removalDate":null,"lastPriceTraded":null,"handicap":0,"totalMatched":null,"selectionId":12832765},{"status":"ACTIVE","ex":{"tradedVolume":[],"availableToBack":[{"price":20,"size":3},{"price":19.5,"size":26.36},{"price":19,"size":2}],"availableToLay":[{"price":21,"size":13},{"price":22,"size":2},{"price":23,"size":2}]},"sp":{"nearPrice":null,"farPrice":null,"backStakeTaken":[],"layLiabilityTaken":[],"actualSP":null},"adjustmentFactor":null,"removalDate":null,"lastPriceTraded":null,"handicap":0,"totalMatched":null,"selectionId":12832767},{"status":"ACTIVE","ex":{"tradedVolume":[],"availableToBack":[{"price":11,"size":9.75},{"price":10.5,"size":3},{"price":10,"size":28.18}],"availableToLay":[{"price":11.5,"size":12},{"price":13.5,"size":2},{"price":14,"size":7.75}]},"sp":{"nearPrice":null,"farPrice":null,"backStakeTaken":[],"layLiabilityTaken":[],"actualSP":null},"adjustmentFactor":null,"removalDate":null,"lastPriceTraded":null,"handicap":0,"totalMatched":null,"selectionId":12832766},{"status":"ACTIVE","ex":{"tradedVolume":[],"availableToBack":[{"price":48,"size":2},{"price":46,"size":5},{"price":42,"size":5}],"availableToLay":[{"price":60,"size":7},{"price":70,"size":5},{"price":75,"size":10}]},"sp":{"nearPrice":null,"farPrice":null,"backStakeTaken":[],"layLiabilityTaken":[],"actualSP":null},"adjustmentFactor":null,"removalDate":null,"lastPriceTraded":null,"handicap":0,"totalMatched":null,"selectionId":12832769},{"status":"ACTIVE","ex":{"tradedVolume":[],"availableToBack":[{"price":18.5,"size":28.94},{"price":18,"size":5},{"price":17.5,"size":3}],"availableToLay":[{"price":21,"size":20},{"price":23,"size":2},{"price":24,"size":2}]},"sp":{"nearPrice":null,"farPrice":null,"backStakeTaken":[],"layLiabilityTaken":[],"actualSP":null},"adjustmentFactor":null,"removalDate":null,"lastPriceTraded":null,"handicap":0,"totalMatched":null,"selectionId":12832768},{"status":"ACTIVE","ex":{"tradedVolume":[],"availableToBack":[{"price":4.3,"size":9},{"price":4.2,"size":257.98},{"price":4.1,"size":51.1}],"availableToLay":[{"price":4.4,"size":20.97},{"price":4.5,"size":30},{"price":4.6,"size":16}]},"sp":{"nearPrice":null,"farPrice":null,"backStakeTaken":[],"layLiabilityTaken":[],"actualSP":null},"adjustmentFactor":null,"removalDate":null,"lastPriceTraded":null,"handicap":0,"totalMatched":null,"selectionId":12832771},{"status":"ACTIVE","ex":{"tradedVolume":[],"availableToBack":[{"price":24,"size":6.75},{"price":23,"size":2},{"price":22,"size":2}],"availableToLay":[{"price":26,"size":2},{"price":27,"size":2},{"price":28,"size":2}]},"sp":{"nearPrice":null,"farPrice":null,"backStakeTaken":[],"layLiabilityTaken":[],"actualSP":null},"adjustmentFactor":null,"removalDate":null,"lastPriceTraded":null,"handicap":0,"totalMatched":null,"selectionId":12832770},{"status":"ACTIVE","ex":{"tradedVolume":[],"availableToBack":[{"price":5.7,"size":149.33},{"price":5.5,"size":29.41},{"price":5.4,"size":5}],"availableToLay":[{"price":6,"size":85},{"price":6.6,"size":5},{"price":6.8,"size":5}]},"sp":{"nearPrice":null,"farPrice":null,"backStakeTaken":[],"layLiabilityTaken":[],"actualSP":null},"adjustmentFactor":null,"removalDate":null,"lastPriceTraded":null,"handicap":0,"totalMatched":null,"selectionId":10064909}],"publishTime":1551612312125,"priceLadderDefinition":{"type":"CLASSIC"},"keyLineDescription":null,"marketDefinition":{"bspMarket":false,"turnInPlayEnabled":false,"persistenceEnabled":false,"marketBaseRate":5,"eventId":"28180290","eventTypeId":"2378961","numberOfWinners":1,"bettingType":"ODDS","marketType":"NONSPORT","marketTime":"2019-03-29T00:00:00.000Z","suspendTime":"2019-03-29T00:00:00.000Z","bspReconciled":false,"complete":true,"inPlay":false,"crossMatching":false,"runnersVoidable":false,"numberOfActiveRunners":8,"betDelay":0,"status":"OPEN","runners":[{"status":"ACTIVE","sortPriority":1,"id":10064909},{"status":"ACTIVE","sortPriority":2,"id":12832765},{"status":"ACTIVE","sortPriority":3,"id":12832766},{"status":"ACTIVE","sortPriority":4,"id":12832767},{"status":"ACTIVE","sortPriority":5,"id":12832768},{"status":"ACTIVE","sortPriority":6,"id":12832770},{"status":"ACTIVE","sortPriority":7,"id":12832769},{"status":"ACTIVE","sortPriority":8,"id":12832771},{"status":"LOSER","sortPriority":9,"id":10317013},{"status":"LOSER","sortPriority":10,"id":10317010}],"regulators":["MR_INT"],"countryCode":"GB","discountAllowed":true,"timezone":"Europe\/London","openDate":"2019-03-29T00:00:00.000Z","version":2576584033,"priceLadderDefinition":{"type":"CLASSIC"}}}
i think i understand what you are trying to do now
first hold your data as a python object (you gave us a json object)
import json
my_data = json.loads(my_json_string)
for item in my_data['runners']:
item['selectionId'] = [item['selectionId'], my_name_here]
the thing is that my_data['runners'][i]['selectionId'] is a string, unless you want to concat the name and the id together, you should turn it into a list or even a dictionary
each item is a dicitonary so you can always also a new keys to it
item['new_key'] = my_value
So, essentially this works...with one exception...I can see from the print(...) in the loop that the attribute is updated, however what I can't seem to do is then see this update outside the loop.
mkt_runners = []
for market_catalogue in market_catalogues:
for r in market_catalogue.runners:
mkt_runners.append((r.selection_id, r.runner_name))
for market_book in market_books:
for runner in market_book.runners:
for x in mkt_runners:
if runner.selection_id in x:
setattr(runner, 'x', x[1])
print(market_book.market_id, runner.x, runner.selection_id)
print(market_book.json())
So the print(market_book.market_id.... displays as expected, but when I print the whole list it shows the un-updated version. I can't seem to find an obvious solution, which is odd, as it seems like a really simple thing (I tried messing around with indents, in case that was the problem, but it doesn't seem to be, its like its not refreshing the market_book list post update of the runners sub list)!

How to use dynamic variable in python mongodb script

I want to update records in the collection books.
I want to create new field whose name and value are the values from variables.
for book in db.books.find():
title = book['title']
author, value = getAuthor(title)
db.dataset.update({"_id": book['_id']}, {"$set": {author: value}})
When I did this I got the error: WriteError: The update path contains an empty field name. It is not allowed which is not true because both variables have values. I googled and resolved this issue by enclosing author into []. So the code looks like this:
for book in db.books.find():
title = book['title']
author, value = getAuthor(title)
db.dataset.update({"_id": book['_id']}, {"$set": {[author]: value}})
But now I am getting this error which I am not able to resolve:
TypeError: unhashable type: 'list'
Does anyone have encountered such problem? How can I resolve it?
It sounds like getAuthor() is returning back nothing for it's first value, so author is getting set to nothing. From what I can see you did not resolve the error, you just changed it to a different error. By making it say [author] (though it's been a while since I've been in Python) I believe you're just trying to set the key to be an empty list, or a list with an empty string as the only value, depending on what author is.
If I were you, I would print out what author is, or do some debugging and figure out what you're getting back from getAuthor(). Since I can't see that code, nor the data in your database, I'm not sure how to help further without more information.

Error in the coding : TypeError : list indices must be integer, not str

Code is importing another file, which is working perfectly.
But, there is a problem in the line where I try to import the csv file, with a column called 'account key', returning the TypeError above.
import file_import as fi
Function for collectively finding data necessary from a csv file.
def unique_students(csv_file):
unique_students_list = set()
for information in csv_file:
unique_students_list.add(csv_file["account_key"])
return len(unique_students_list)
#enrollment_num_rows = len(fi.enrollments)
#engagement_num_rows = len(fi.daily_engagement)
#submission_num_rows = len(fi.project_submissions)
#enrollment_num_unique_students = unique_students(fi.enrollments)
#engagement_num_unique_students = unique_students(fi.daily_engagement)
#submission_num_unique_students = unique_students(fi.project_submissions)
csv_file["account_key"]
Lists expect a numeric index. As far as I know, only dictionaries accept String indices.
I'm not entirely sure what this is supposed to do; I think your logic is flawed. You bind information in the for loop, then never use it. Even if the list did accept a string index, all it would do is populate the Set with the same information over and over since the for loop body remains the same same every loop. This would only work if you were expecting csv_file to be a custom container type that had side effects when indexed (like advancing some internal counter).

Using Strings to Name Hash Keys?

I'm working through a book called "Head First Programming," and there's a particular part where I'm confused as to why they're doing this.
There doesn't appear to be any reasoning for it, nor any explanation anywhere in the text.
The issue in question is in using multiple-assignment to assign split data from a string into a hash (which doesn't make sense as to why they're using a hash, if you ask me, but that's a separate issue). Here's the example code:
line = "101;Johnny 'wave-boy' Jones;USA;8.32;Fish;21"
s = {}
(s['id'], s['name'], s['country'], s['average'], s['board'], s['age']) = line.split(";")
I understand that this will take the string line and split it up into each named part, but I don't understand why what I think are keys are being named by using a string, when just a few pages prior, they were named like any other variable, without single quotes.
The purpose of the individual parts is to be searched based on an individual element and then printed on screen. For example, being able to search by ID number and then return the entire thing.
The language in question is Python, if that makes any difference. This is rather confusing for me, since I'm trying to learn this stuff on my own.
My personal best guess is that it doesn't make any difference and that it was personal preference on part of the authors, but it bewilders me that they would suddenly change form like that without it having any meaning, and further bothers me that they don't explain it.
EDIT: So I tried printing the id key both with and without single quotes around the name, and it worked perfectly fine, either way. Therefore, I'd have to assume it's a matter of personal preference, but I still would like some info from someone who actually knows what they're doing as to whether it actually makes a difference, in the long run.
EDIT 2: Apparently, it doesn't make any sense as to how my Python interpreter is actually working with what I've given it, so I made a screen capture of it working https://www.youtube.com/watch?v=52GQJEeSwUA
I don't understand why what I think are keys are being named by using a string, when just a few pages prior, they were named like any other variable, without single quotes
The answer is right there. If there's no quote, mydict[s], then s is a variable, and you look up the key in the dict based on what the value of s is.
If it's a string, then you look up literally that key.
So, in your example s[name] won't work as that would try to access the variable name, which is probably not set.
EDIT: So I tried printing the id key both with and without single
quotes around the name, and it worked perfectly fine, either way.
That's just pure luck... There's a built-in function called id:
>>> id
<built-in function id>
Try another name, and you'll see that it won't work.
Actually, as it turns out, for dictionaries (Python's term for hashes) there is a semantic difference between having the quotes there and not.
For example:
s = {}
s['test'] = 1
s['othertest'] = 2
defines a dictionary called s with two keys, 'test' and 'othertest.' However, if I tried to do this instead:
s = {}
s[test] = 1
I'd get a NameError exception, because this would be looking for an undefined variable called test whose value would be used as the key.
If, then, I were to type this into the Python interpreter:
>>> s = {}
>>> s['test'] = 1
>>> s['othertest'] = 2
>>> test = 'othertest'
>>> print s[test]
2
>>> print s['test']
1
you'll see that using test as a key with no quotes uses the value of that variable to look up the associated entry in the dictionary s.
Edit: Now, the REALLY interesting question is why using s[id] gave you what you expected. The keyword "id" is actually a built-in function in Python that gives you a unique id for an object passed as its argument. What in the world the Python interpreter is doing with the expression s[id] is a total mystery to me.
Edit 2: Watching the OP's Youtube video, it's clear that he's staying consistent when assigning and reading the hash about using id or 'id', so there's no issue with the function id as a hash key somehow magically lining up with 'id' as a hash key. That had me kind of worried for a while.

Categories