pystache: render context inside lambda - python

This is very similar to https://github.com/defunkt/pystache/issues/157, however in the mentioned post didn't really answer...
My target: print the following lines:
Al,John,Jack
Tim,Tom,Todd
without a final comma.
I tried this way:
ctx = {
'gangs': [
{'gangsters': [ {'name': 'Al' }, {'name': 'John'}, {'name': 'Jack'}]},
{'gangsters': [ {'name': 'Tim'}, {'name': 'Tom'} , {'name': 'Todd'}]},
]
}
class Lambdas(object):
def __init__(self, renderer):
self.renderer = renderer
def rstrip(self):
"Remove last character"
print self.renderer.context
return lambda s: self.renderer.render(s, self.renderer.context)[:-1]
renderer = pystache.Renderer(missing_tags='strict')
print renderer.render("""
{{#gangs}}
{{#rstrip}}{{#gangsters}}{{name}},{{/gangsters}}{{/rstrip}}
{{/gangs}}
""", ctx, Lambdas(renderer))
The output:
ContextStack({'gangs': [{'gangsters': [{'name': 'Al'}, {'name': 'John'}, {'name': 'Jack'}]}, {'gangsters': [{'name': 'Tim'}, {'name': 'Tom'}, {'name': 'Todd'}]}]}, <__main__.Lambdas object at 0x15cadb10>, {'gangsters': [{'name': 'Al'}, {'name': 'John'}, {'name': 'Jack'}]})
ContextStack({'gangs': [{'gangsters': [{'name': 'Al'}, {'name': 'John'}, {'name': 'Jack'}]}, {'gangsters': [{'name': 'Tim'}, {'name': 'Tom'}, {'name': 'Todd'}]}]}, <__main__.Lambdas object at 0x15cadb10>, {'gangsters': [{'name': 'Al'}, {'name': 'John'}, {'name': 'Jack'}]})
Al,John,Jack
Al,John,Jack
The culprit is the invocation to render() inside rstrip. Notice how, during the second call, the 3d element of the ContextStack is exactly identical to the previous call.
Is this a bug, or am I missing something?!?

Answered upstream: https://github.com/defunkt/pystache/issues/158
def rstrip(self):
"Remove last character"
return lambda s: copy.deepcopy(self.renderer).render(s, self.renderer.context)[:-1]

Related

Apply function to specific element's value of a list of dictionaries [duplicate]

This question already has answers here:
Getting a map() to return a list in Python 3.x
(11 answers)
Closed last month.
tbl_headers = db_admin.execute("SELECT name, type FROM PRAGMA_TABLE_INFO(?);", table_name)
tbl_headers is same below:
[{'name': 'id', 'type': 'INTEGER'}, {'name': 'abasdfasd', 'type': 'TEXT'}, {'name': 'sx', 'type': 'TEXT'}, {'name': 'password', 'type': 'NULL'}, {'name': 'asdf', 'type': 'TEXT'}]
I need apply hash_in() function on the 'name' values are in dictionary elements of above list.
Have tried these:
tbl_headers = [hash_in(i['name']) for i in tbl_headers]
suppresses dictionaries and return only a list of 'name' values:
['sxtw001c001h', 'sxtw001c001r001Z001e001c001r001Z001a001Z', 'sxtw001w001r', 'sxtw001c001q001n001v001r001r001Z001o', 'sxtw001e001c001r001Z']
OR
tbl_headers = map(hash_in, tbl_headers)
Returns error.
Update
The Output result I have seek is same:
[{'name': hash_in('id'), 'type': 'INTEGER'}, {'name': hash_in('abasdfasd'), 'type': 'TEXT'}, {'name': hash_in('sx'), 'type': 'TEXT'}, {'name': ('password'), 'type': 'NULL'}, {'name': ('asdf'), 'type': 'TEXT'}]
Appreciate you.
Try this list comprehension:
tbl_headers = [{'name': hash_in(i['name']), 'type': i['type']} for i in tbl_headers]

How do I get my Jupyter Notebook to stop repeating the code into the output?

How do I fix my Jupyter Notebook to stop running the code so many times? I should only be getting three outputs but instead I am getting more than that and idk how to fix it!? It is running data from a previous code as well and I am not sure why?
The AnimalShelter.py code
import pymongo
from pymongo import MongoClient
from bson.objectid import ObjectId
class AnimalShelter(object):
""" CRUD operations for Animal collection in MongoDB """
def __init__(self, username, password):
#Initializing the MongoClient. This helps to access the MongoDB databases and collections.
self.client = MongoClient('mongodb://%s:%s#localhost:45344' % (username, password))
#where xxxx is your unique port number
self.database = self.client['AAC']
#Complete this create method to implement the C in CRUD.
def create(self, data):
if data is not None:
insert = self.database.animals.insert(data) #data should be dictionary
else:
raise Exception("Nothing to save, because data parameter is empty")
#Create method to implement the R in CRUD.
def read(self, searchData):
if searchData:
data = self.database.animals.find(searchData, {"_id": False})
else:
data = self.database.animals.find({}, {"_id": False})
return data
#Create method to implement U in CRUD.
def update(self, searchData, updateData):
if searchData is not None:
result = self.database.animals.update_many(searchData, {"$set": updateData})
else:
return "{}"
return result.raw_result
#Create method to implement D in CRUD.
def delete(self, deleteData):
if deleteData is not None:
result = self.database.animals.delete_many(deleteData)
else:
return "{}"
return result.raw_result
My ipnyb code:
from AnimalShelter import AnimalShelter
a = AnimalShelter("aacuser","French")
animal_data = [
{
"name":"Hades",
"type":"dog"
},
{
"name":"Fable",
"type":"cat"
},
{
"name":"Buddy",
"type":"dog"
}
]
for i in animal_data:
a.create(i)
dogs = a.read( {"type":"dog"} )
for dog in dogs:
print(dog)
cats = a.read( {"type":"cat"} )
for cat in cats:
print(cat)
The output:
{'name': 'bruno', 'type': 'dog'}
{'name': 'sticky', 'type': 'dog'}
{'name': 'bruno', 'type': 'dog'}
{'name': 'sticky', 'type': 'dog'}
{'name': 'bruno', 'type': 'dog'}
{'name': 'sticky', 'type': 'dog'}
{'name': 'bruno', 'type': 'dog'}
{'name': 'sticky', 'type': 'dog'}
{'name': 'bruno', 'type': 'dog'}
{'name': 'sticky', 'type': 'dog'}
{'name': 'bruno', 'type': 'dog'}
{'name': 'sticky', 'type': 'dog'}
{'name': 'bruno', 'type': 'dog'}
{'name': 'sticky', 'type': 'dog'}
{'name': 'bruno', 'type': 'dog'}
{'name': 'sticky', 'type': 'dog'}
{'name': 'bruno', 'type': 'dog'}
{'name': 'sticky', 'type': 'dog'}
{'name': 'bruno', 'type': 'dog'}
{'name': 'sticky', 'type': 'dog'}
{'name': 'bruno', 'type': 'dog'}
{'name': 'sticky', 'type': 'dog'}
{'name': 'Hades', 'type': 'dog'}
{'name': 'Buddy', 'type': 'dog'}
{'name': 'Hades', 'type': 'dog'}
{'name': 'Buddy', 'type': 'dog'}
{'name': 'Hades', 'type': 'dog'}
{'name': 'Buddy', 'type': 'dog'}
{'name': 'missy', 'type': 'cat'}
{'name': 'missy', 'type': 'cat'}
{'name': 'missy', 'type': 'cat'}
{'name': 'missy', 'type': 'cat'}
{'name': 'missy', 'type': 'cat'}
{'name': 'missy', 'type': 'cat'}
{'name': 'missy', 'type': 'cat'}
{'name': 'missy', 'type': 'cat'}
{'name': 'missy', 'type': 'cat'}
{'name': 'missy', 'type': 'cat'}
{'name': 'missy', 'type': 'cat'}
{'name': 'Fable', 'type': 'cat'}
{'name': 'Fable', 'type': 'cat'}
{'name': 'Fable', 'type': 'cat'}
I have tried to restart the entire thing, made a new notebook to work out of, and cleared the outputs/reset the kernel/ran the program again and each time it adds another listing instead of it showing the three listings. Is this a bug or did I do something wrong?
MongoDB is a persistent database; so each create() adds more data in to the database.
You already have a delete method so you could add something like:
a = AnimalShelter("aacuser","French")
a.delete({"type":"dog"})
a.delete({"type":"cat"})
near the start of your code to delete any existing data before you start.

Flat json to nested json python

I want to convert input json to nested json defined, I am not able to think of any json library which help me achieve this
Input json
[{'Name': 'John', 'state': 'Boston', 'currency': 'USD', 'marks': 100},
{'Name': 'Rohan', 'state': 'Paris', 'currency': 'EUR', 'marks': 20},
{'Name': 'Rohan', 'state': 'Lyon', 'currency': 'EUR', 'marks': 11.4},
{'Name': 'Messi', 'state': 'Madrid', 'currency': 'EUR', 'marks': 9.9},
{'Name': 'Lampard', 'state': 'London', 'currency': 'GBP', 'marks': 12.2},
{'Name': 'Lampard', 'state': 'London', 'currency': 'FBP', 'marks': 10.9}]
output json
{
"USD": {
"John": {
"Boston": [
{
"Marks": 100
}
]
},
Current scenario based on value Currency,Name,state,marks
The nested json can be put upto n level if required such as Name and state and marks or it can be Name , curreny , state and marks or Name,curreny and marks
So you want currency > name > state > list of marks.
One solution would be to create the structure using defaultdicts, and then just add to it.
from collections import defaultdict
from functools import wraps
data = [...]
def ddmaker(type_):
#wraps(dict)
def caller():
return defaultdict(type_)
return caller
# create the structure of the output
output = defaultdict(ddmaker(ddmaker(list)))
# add to it
for item in data:
currency = item["currency"]
name = item["Name"]
state = item["state"]
mark = item["marks"]
output[currency][name][state].append({'Marks': mark})

How to rename keys in a dictionary and make a dataframe of it?

I have a complex situation which I hope to solve and which might profit us all. I collected data from my API, added a pagination and inserted the complete data package in a tuple named q1 and finally I have made a dictionary named dict_1of that tuple which looks like this:
dict_1 = {100: {'ID': 100, 'DKSTGFase': None, 'DK': False, 'KM': None,
'Country: {'Name': GE', 'City': {'Name': 'Berlin'}},
'Type': {'Name': '219'}, 'DKObject': {'Name': '8555', 'Object': {'Name': 'Car'}},
'Order': {'OrderId': 101, 'CreatedOn': '2018-07-06T16:54:36.783+02:00',
'ModifiedOn': '2018-07-06T16:54:36.783+02:00',
'Name': Audi, 'Client': {‘1’ }}, 'DKComponent': {'Name': ‘John’}},
{200: {'ID': 200, 'DKSTGFase': None, 'DK': False, ' KM ': None,
'Country: {'Name': ES', 'City': {'Name': 'Madrid'}}, 'Type': {'Name': '220'},
'DKObject': {'Name': '8556', 'Object': {'Name': 'Car'}},
'Order': {'OrderId': 102, 'CreatedOn': '2018-07-06T16:54:36.783+02:00',
'ModifiedOn': '2018-07-06T16:54:36.783+02:00',
'Name': Mercedes, 'Client': {‘2’ }}, 'DKComponent': {'Name': ‘Sergio’}},
Please note that in the above dictionary I have just stated 2 records. The actual dictionary has 1400 records till it reaches ID 1500.
Now I want to 2 things:
I want to change some keys for all the records. key DK has to become DK1. Key Name in Country has to become Name1 and Name in Object has to become 'Name2'
The second thing I want is to make a dataFrame of the whole bunch of data. My expected outcome is:
This is my code:
q1 = response_2.json()
next_link = q1['#odata.nextLink']
q1 = [tuple(q1.values())]
while next_link:
new_response = requests.get(next_link, headers=headers, proxies=proxies)
new_data = new_response.json()
q1.append(tuple(new_data.values()))
next_link = new_data.get('#odata.nextLink', None)
dict_1 = {
record['ID']: record
for tup in q1
for record in tup[2]
}
#print(dict_1)
for x in dict_1.values():
x['DK1'] = x['DK']
x['Country']['Name1'] = x['Country']['Name']
x['Object']['Name2'] = x['Object']['Name']
df = pd.DataFrame(dict_1)
When i run this I receive the following Error:
Traceback (most recent call last):
File "c:\data\FF\Desktop\Python\PythongMySQL\Talky.py", line 57, in <module>
x['Country']['Name1'] = x['Country']['Name']
TypeError: 'NoneType' object is not subscriptable
working code
lists=[]
alldict=[{100: {'ID': 100, 'DKSTGFase': None, 'DK': False, 'KM': None,
'Country': {'Name': 'GE', 'City': {'Name': 'Berlin'}},
'Type': {'Name': '219'}, 'DKObject': {'Name': '8555', 'Object': {'Name': 'Car'}},
'Order': {'OrderId': 101, 'CreatedOn': '2018-07-06T16:54:36.783+02:00',
'ModifiedOn': '2018-07-06T16:54:36.783+02:00',
'Name': 'Audi', 'Client': {'1' }}, 'DKComponent': {'Name': 'John'}}}]
for eachdict in alldict:
key=list(eachdict.keys())[0]
eachdict[key]['DK1']=eachdict[key]['DK']
del eachdict[key]['DK']
eachdict[key]['Country']['Name1']=eachdict[key]['Country']['Name']
del eachdict[key]['Country']['Name']
eachdict[key]['DKObject']['Object']['Name2']=eachdict[key]['DKObject']['Object']['Name']
del eachdict[key]['DKObject']['Object']['Name']
lists.append([key, eachdict[key]['DK1'], eachdict[key]['KM'], eachdict[key]['Country']['Name1'],
eachdict[key]['Country']['City']['Name'], eachdict[key]['DKObject']['Object']['Name2'], eachdict[key]['Order']['Client']])
pd.DataFrame(lists, columns=[<columnNamesHere>])
Output:
{100: {'ID': 100,
'DKSTGFase': None,
'KM': None,
'Country': {'City': {'Name': 'Berlin'}, 'Name1': 'GE'},
'Type': {'Name': '219'},
'DKObject': {'Name': '8555', 'Object': {'Name2': 'Car'}},
'Order': {'OrderId': 101,
'CreatedOn': '2018-07-06T16:54:36.783+02:00',
'ModifiedOn': '2018-07-06T16:54:36.783+02:00',
'Name': 'Audi',
'Client': {'1'}},
'DKComponent': {'Name': 'John'},
'DK1': False}}

Appending/Merging in Python

I have the following structure:
[
{
u'123456': {'name': "Bill"},
u'234567': {'name': "Dave"},
u'345678': {'name': "Tom"}
},
]
During a for loop new items are added to the list using the extend function. Unfortunately this results in the following structure:
[
{
u'123456': {'name': "Bill"},
u'234567': {'name': "Dave"},
u'345678': {'name': "Tom"}
},
{
u'555555': {'name': "Steve"},
u'666666': {'name': "Michael"},
u'777777': {'name': "George"}
}
]
The intended result is actually a flat structure such in the following:
[
{
u'123456': {'name': "Bill"},
u'234567': {'name': "Dave"},
u'345678': {'name': "Tom"},
u'555555': {'name': "Steve"},
u'666666': {'name': "Michael"},
u'777777': {'name': "George"}
}
]
Is it possible to append to the list so that the structure gets built in a flat way.
or
Is it possible to flatten after the loop has finished?
If your list is named l you could use l[0].update(new_dict).
Example:
l = [{u'123456': {'name': "Bill"}}]
l[0].update({u'234567': {'name': "Dave"}})
print(l)
Nice formatted output is:
[
{
u'123456': {'name': 'Bill'},
u'234567': {'name': 'Dave'}
}
]
Where you currently have something like this:
mylist.extend(newdict)
You should use this:
mylist[0].update(newdict)
You can add the items of both dictionaries together:
>>> mylist = [
{
u'123456': {'name': "Bill"},
u'234567': {'name': "Dave"},
u'345678': {'name': "Tom"}
},
]
>>> mydict = {
u'555555': {'name': "Steve"},
u'666666': {'name': "Michael"},
u'777777': {'name': "George"}
}
>>> [dict(mylist[0].items() + mydict.items())]
[{u'123456': {'name': 'Bill'}, u'555555': {'name': 'Steve'}, u'777777': {'name': 'George'}, u'666666': {'name': 'Michael'}, u'345678': {'name': 'Tom'}, u'234567': {'name': 'Dave'}}]
Although it's more clean to just do .update():
>>> mylist[0].update(mydict)
You can use .update(), however this will overwrite values if you'll have duplicated keys.
def flatten(results):
newresult = {}
for subdict : results:
newresult.update(subdict)
return [newresult]

Categories

Resources