I defined two ResourceContainer.
But echov1openapi.json is generated by endpointscfg.py has only one Container.
such as:
class TestRequest(messages.Message):
foo = messages.StringField(1)
bar = messages.StringField(2)
class EchoRequest(messages.Message):
aaa = messages.StringField(1)
bbb = messages.StringField(2)
ECHO_RESOURCE = endpoints.ResourceContainer(
EchoRequest,
n=messages.IntegerField(3))
TEST_RESOURCE = endpoints.ResourceContainer(
TestRequest,
test=messages.IntegerField(3))
...
#endpoints.method(
ECHO_RESOURCE,
EchoResponse,
path='echo',
http_method='POST',
name='echoTest')
def echo(self, request):
...
#endpoints.method(
TEST_RESOURCE,
EchoResponse,
path='echo2',
http_method='POST',
name='echo2')
def echo2(self, request):
....
then, I execute endpointscfg.py. But TEST_RESOURCE is not appears.
"definitions": {
...
"ProtorpcMessagesCombinedContainer": { ★ECHO_RESOURCE
"properties": {
"aaa": {
"type": "string"
},
"bbb": {
"type": "string"
},
"n": {
"format": "int64",
"type": "string"
}
},
"type": "object"
}
},
...
"paths": {
"/echo/v1/echo": {
"post": {
"operationId": "EchoApi_echo",
"parameters": [
{
"in": "body",
"name": "body",
"schema": {
"$ref": "#/definitions/ProtorpcMessagesCombinedContainer"★refer ECHO_RESOURCE
}
}
],
...
"/echo/v1/echo2": {
"post": {
"operationId": "EchoApi_echo2",
"parameters": [
{
"in": "body",
"name": "body",
"schema": {
"$ref": "#/definitions/ProtorpcMessagesCombinedContainer"★not TEST_RESOURCE but ECHO_RESOURCE!
}
}
],
Is it specification or BUG?
ResourceContainer can be defined once each API?
and I could not found API reference about ResourceContainer.
Where is the reference page?
It's difficult to say without seeing your full example, but I suspect the cause is that you never use the 'test' attribute in any of the requests; you don't accept a 'test' url parameter.
returns
"messages": [
{
"text": "testing",
"ts": "1479967441.000004",
"user": "ray",
"type": "message",
"bot_id": "B379PT5AT"
},
{
"text": "SWAT start",
"type": "message",
"user": "john",
"ts": "1479967379.000003"
},
{
"text": "SWAT close",
"type": "message",
"user": "ray",
"ts": "1479967379.000003"
},
I would like to add another parameter
"messages": [
{
"text": "testing",
"ts": "1479967441.000004",
"user": "ray",
"type": "message",
"bot_id": "B379PT5AT"
"icon": "URL...."
},
{
"text": "SWAT start",
"type": "message",
"user": "john",
"ts": "1479967379.000003"
"icon": "URL...."
},
{
"text": "SWAT close",
"type": "message",
"user": "ray",
"ts": "1479967379.000003"
"icon": "URL...."
},
Code:
import simplejson
with open ('automation.json')as json_data:
data = simplejson.loads(json_data)
for r in data['messages']:
key = messages['icon']
messages["icon"] = ("testing")
outdata = simplejson.dumps(data)
You almost had it. Looping over data['messages'] accesses a list of dictionaries, which is why your assignment didn't quite work. You have to access the dictionary first, and then assign.
import json
with open('automation.json') as data_file:
data = json.load(data_file)['messages'] # you now have a the json as a python object.
# If you want to always add the same value to each dictionary
data = {d['icon'] = 'A Value you want' for d in data} # d represents a dictionary in data['messages']
# other wise, lets say the icon is linked to the user:
icon_urls = {'john': 'http://someurl.com', 'ray': 'http://someotherurl.com'}
data = {d['icon'] = icon_urls[d['user']] for d in data}
I am a new python user, and I have just been getting familiar with restructuring data with the zip function, however I am now faced with a challenging data set that i have to restructure. I have 3 json responses that I have to merge from my end, the data sets are identical in design and would have the same length, they just differ from environments they ran on.
Let 3 files be the same values for brevity: qa.json | dev.json | prod.json
Note: This outer object is array/list of object, I just put one object for brevity
[
{
"elements": [
{
"keyword": "Scenario",
"name": "valid user can login site",
"steps": [
{
"name": "a valid user name and password",
"result": {
"status": "passed"
}
},
{
"name": "a valid user clicking on the login button after typing in user name and password",
"result": {
"status": "passed"
}
},
{
"name": "map should display",
"result": {
"status": "passed"
}
}
]
}
],
"keyword": "Feature",
"name": "login",
"status": "passed"
}
]
What I want to achieve:
Note: i want to merge them in one set with different environments reflecting the status
[
{
"elements": [
{
"keyword": "Scenario",
"name": "valid user can login site",
"steps": [
{
"name": "a valid user name and password",
"result": {
"qa": "passed",
"prod": "passed",
"dev": "passed"
}
},
{
"name": "a valid user clicking on the login button after typing in user name and password",
"result": {
"qa": "passed",
"prod": "passed",
"dev": "passed"
}
},
{
"name": "map should display",
"result": {
"qa": "passed",
"prod": "passed",
"dev": "passed"
}
}
]
}
],
"keyword": "Feature",
"name": "login",
"qa": "passed",
"prod": "passed",
"dev": "passed"
}
]
What i have done so far:
I come from a javascript background so i im still getting familiar with python logic
import json
with open('qa.json') as data_file:
qa = json.load(data_file)
with open('dev.json') as data_file:
dev = json.load(data_file)
with open('prod.json') as data_file:
prod = json.load(data_file)
json_list = [{SOME STRUCT} for q, d, p in zip(qa, dev, prod)]
I don't have a lot of time so I'm posting what I believe is a working solution to your problem even if it's slightly messy. If I have time I'll edit it.
Code
import json
data = """
[
{
"elements": [{
"keyword": "Scenario",
"name": "valid user can login site",
"steps": [{
"name": "a valid user name and password",
"result": {
"status": "passed"
}
}, {
"name": "a valid user clicking on the login button after typing in user name and password",
"result": {
"status": "passed"
}
}, {
"name": "map should display",
"result": {
"status": "passed"
}
}]
}],
"keyword": "Feature",
"name": "login",
"status": "passed"
},
{
"elements": [{
"keyword": "Scenario",
"name": "valid user can login site",
"steps": [{
"name": "a valid user name and password",
"result": {
"status": "passed"
}
}, {
"name": "a valid user clicking on the login button after typing in user name and password",
"result": {
"status": "failed"
}
}, {
"name": "map should display",
"result": {
"status": "passed"
}
}]
}],
"keyword": "Feature",
"name": "login",
"status": "passed"
}
]
"""
def get_result(envData, objIndex, elementIndex, stepIndex):
return envData[objIndex]['elements'][elementIndex]['steps'][stepIndex]['result']['status']
def set_combined_results(combinedData, objIndex, elementIndex, stepIndex, results):
resultNode = combinedData[objIndex]['elements'][elementIndex]['steps'][stepIndex]['result']
resultNode.update({ 'qa': results[0], 'prod': results[1], 'dev': results[2] })
if __name__ == '__main__':
qAData = json.loads(data)
prodData = json.loads(data)
devData = json.loads(data)
combinedData = json.loads(data)
for objIndex, obj in enumerate(combinedData):
for elementIndex, element in enumerate(obj['elements']):
for stepIndex, _ in enumerate(element['steps']):
qAResult = get_result(qAData, objIndex, elementIndex, stepIndex)
prodResult = get_result(prodData, objIndex, elementIndex, stepIndex)
devResult = get_result(devData, objIndex, elementIndex, stepIndex)
combinedResults = (qAResult, prodResult, devResult)
set_combined_results(combinedData, objIndex, elementIndex, stepIndex, combinedResults)
qAAggregateResult = qAData[objIndex]['status']
prodAggregateResult = prodData[objIndex]['status']
devAggregateResult = devData[objIndex]['status']
del combinedData[objIndex]['status']
combinedData[objIndex]['qa'] = qAAggregateResult
combinedData[objIndex]['prod'] = prodAggregateResult
combinedData[objIndex]['dev'] = devAggregateResult
print(json.dumps(combinedData, indent=True))
Output
[
{
"keyword": "Feature",
"name": "login",
"elements": [
{
"keyword": "Scenario",
"name": "valid user can login site",
"steps": [
{
"result": {
"qa": "passed",
"status": "passed",
"dev": "passed",
"prod": "passed"
},
"name": "a valid user name and password"
},
{
"result": {
"qa": "passed",
"status": "passed",
"dev": "passed",
"prod": "passed"
},
"name": "a valid user clicking on the login button after typing in user name and password"
},
{
"result": {
"qa": "passed",
"status": "passed",
"dev": "passed",
"prod": "passed"
},
"name": "map should display"
}
]
}
],
"dev": "passed",
"prod": "passed",
"qa": "passed"
},
{
"keyword": "Feature",
"name": "login",
"elements": [
{
"keyword": "Scenario",
"name": "valid user can login site",
"steps": [
{
"result": {
"qa": "passed",
"status": "passed",
"dev": "passed",
"prod": "passed"
},
"name": "a valid user name and password"
},
{
"result": {
"qa": "failed",
"status": "failed",
"dev": "failed",
"prod": "failed"
},
"name": "a valid user clicking on the login button after typing in user name and password"
},
{
"result": {
"qa": "passed",
"status": "passed",
"dev": "passed",
"prod": "passed"
},
"name": "map should display"
}
]
}
],
"dev": "failed",
"prod": "failed",
"qa": "failed"
}
]
This is a recursive merge implementation. It will merge arbitrary types of Python objects, such that anything but dicts must be equal when merged.
For dicts, it will allow merging if the same keys are associated with mergable values in those where the key is present. Any dict keys equalling the parameter fieldname will be suffixed with an index before merging:
from copy import deepcopy
from itertools import chain
def merge(field_name, *objs):
# Make sure all objs are of same type
types = list(set(map(type, objs)))
if not len(set(map(type, objs))) == 1:
raise Exception('Cannot merge objects of different types: {types}'.format(types=types))
first = objs[0]
# for any random objects, make sure they are equal!
if not isinstance(first, (list, tuple, dict)):
if not len(set(objs)) == 1:
raise Exception("Cannot merge non-equal objects that aren't dicts: {objs}".format(objs=objs))
return deepcopy(first)
# for lists, tuples: zip 'em and merge the zipped elements
if isinstance(first, (list, tuple)):
return [merge(field_name, *zipped) for zipped in zip(*objs)]
# dicts
result_dict = {}
keys = list(set(chain.from_iterable(d.keys() for d in objs)))
try:
keys.remove(field_name)
except ValueError:
pass
for k in keys:
# merge values from all dicts where key is present
result_dict[k] = merge(field_name, *(d[k] for d in objs if k in d))
for i, d in enumerate(objs):
if field_name in d:
result_dict['{f}_{i}'.format(f=field_name, i=i)] = d[field_name]
return result_dict
This can now be used on dev, qa, prod that are dicts of the structure given by th OP:
>>> from pprint import pprint
>>> pprint(merge('status', qa, dev, prod))
[{'elements': [{'keyword': 'Scenario',
'name': 'valid user can login site',
'steps': [{'name': 'a valid user name and password',
'result': {'status_0': 'passed',
'status_1': 'passed',
'status_2': 'passed'}},
{'name': 'a valid user clicking on the login button after typing in user name and password',
'result': {'status_0': 'passed',
'status_1': 'passed',
'status_2': 'passed'}},
{'name': 'map should display',
'result': {'status_0': 'passed',
'status_1': 'passed',
'status_2': 'passed'}}]}],
'keyword': 'Feature',
'name': 'login',
'status_0': 'passed',
'status_1': 'passed',
'status_2': 'passed'}]
This is, of course, not fully generic, e.g. it only "deep" merges sequences when they are lists or tuples, but it should be decent enough for data structures loaded from json. I hope it helps you find a solution.
Because each object in the list is a dict you can use dict.update mehthod to update a dict.
f.e.
a = [{'one': 1}, {'three': 3}]
b = [{'one': 1}, {'two': 2}] # {'one': 1} is duplicate with same value
c = [{'a': 'aaa'}, {'two': 22}] # {'two': 22} is duplicate with different value
for x, y, z in zip(a, b, c):
x.update(y)
x.update(z)
Now x would be [{'a': 'aaa', 'one': 1}, {'three': 3, 'two': 22}]
For those json files you mentioned, it would be;
import json
from pprint import pprint
qa = '''
[
{
"elements": [
{
"keyword": "Scenario",
"name": "valid user can login site",
"steps": [
{
"name": "a valid user name and password",
"result": {
"qa": "passed"
}
},
{
"name": "a valid user clicking on the login button after typing in user name and password",
"result": {
"qa": "passed"
}
},
{
"name": "map should display",
"result": {
"qa": "passed"
}
}
]
}
],
"keyword": "Feature",
"name": "login",
"qa": "passed"
}
]
'''
dev = '''
[
{
"elements": [
{
"keyword": "Scenario",
"name": "valid user can login site",
"steps": [
{
"name": "a valid user name and password",
"result": {
"dev": "passed"
}
},
{
"name": "a valid user clicking on the login button after typing in user name and password",
"result": {
"dev": "passed"
}
},
{
"name": "map should display",
"result": {
"dev": "passed"
}
}
]
}
],
"keyword": "Feature",
"name": "login",
"dev": "passed"
}
]
'''
prod = '''
[
{
"elements": [
{
"keyword": "Scenario",
"name": "valid user can login site",
"steps": [
{
"name": "a valid user name and password",
"result": {
"prod": "passed"
}
},
{
"name": "a valid user clicking on the login button after typing in user name and password",
"result": {
"prod": "passed"
}
},
{
"name": "map should display",
"result": {
"prod": "passed"
}
}
]
}
],
"keyword": "Feature",
"name": "login",
"prod": "passed"
}
]
'''
qa = json.loads(qa)
dev = json.loads(dev)
prod = json.loads(prod)
for q, p, d in zip(qa, dev, prod):
# update all keys but 'elements'
q.update({k: v for k, v in p.items() if k != 'elements'})
q.update({k: v for k, v in d.items() if k != 'elements'})
# update the three 'result' dict
for i in range(3):
q['elements'][0]['steps'][i]['result'].update(p['elements'][0]['steps'][i]['result'])
q['elements'][0]['steps'][i]['result'].update(d['elements'][0]['steps'][i]['result'])
pprint(qa)
Output;
[{'dev': 'passed',
'elements': [{'keyword': 'Scenario',
'name': 'valid user can login site',
'steps': [{'name': 'a valid user name and password',
'result': {'dev': 'passed',
'prod': 'passed',
'qa': 'passed'}},
{'name': 'a valid user clicking on the login button '
'after typing in user name and password',
'result': {'dev': 'passed',
'prod': 'passed',
'qa': 'passed'}},
{'name': 'map should display',
'result': {'dev': 'passed',
'prod': 'passed',
'qa': 'passed'}}]}],
'keyword': 'Feature',
'name': 'login',
'prod': 'passed',
'qa': 'passed'}]