Getting specific keys from dictionaries - python-3.x

I am developing an API service for my website. The website is about Recipes, where a user is supposed to register on his first visit, then log in. When he logs in he gets an access token, which he uses to do REST services on categories and recipes.
So coming to Recipes, he can give a title, ingredients, and directions. Example:
{
"title" : "api recipe",
"directions" : "Testing api recipe directions",
"ingredient1" : "postman",
"ingredient2" : "ing2",
"ingredient3" : "me",
"ingredient4" : "ingredient4",
"ingredient5" : "ingredient5"
}
Now, I am facing a problem when it comes to PUT method. I want to enable a user to edit a recipe giving only that which he wants to edit. Example:
{
"title" : "PUT"
}
Using PUT method, if a user provides an ingredient as such:
{
"ingredient2" : "Potatoes",
"ingredient5" : "stackexchange"
}
I would like to only change the ingredients that he provided me with and leave the rest the way it is.
Before coming to my question, when a user provides the above, I get a dictionary with the keys and values he/she has provided. My question is, how can I get all the ingredients he wants to edit plus their number?
my code:
data = request.get_json()
category = Category.query.filter_by(user_id=user_id).filter_by(id=category_id).first()
if not category:
return jsonify({'message' : 'category does not exists'})
category.edit_recipe(data, id=recipe_id)
return jsonify({'message' : 'Edited successfully'})
def edit_recipe(self, data, *args, **kwargs):
edit_this = None
if 'id' in kwargs:
edit_this = Recipe.query.filter_by(id=kwargs['id']).filter_by(category_id=self.id).first()
else:
edit_this = Recipe.query.filter_by(title=kwargs['prev_title']).filter_by(category_id=self.id).first()
"""TODO: Get ingredient from data followed by its number.
if data == {'title' = 'change title', 'ingredient2' = 'change ing 2', 'ingredient5' = 'change ing 5'}
then I want to get keys that start with ingredient followed by their number and its value
"""
if 'title' in data:
edit_this.title = data['title']
if 'directions' in data:
edit_this.directions = data['directions']
if 'filename' in data:
edit_this.filename = data['filename']
db.session.commit()

To get only the ingredients, the following below should
keyValue = {
"title" : "api recipe",
"directions" : "Testing api recipe directions",
"ingredient1" : "postman",
"ingredient2" : "ing2",
"ingredient3" : "me",
"ingredient4" : "ingredient4",
"ingredient5" : "ingredient5"
}
oldListOfKeys = keyValue.keys()
ingredientsList = filter(lambda x: x not in ["directions", "title"], oldListOfKeys)
newDict = {key: keyValue[key] for key in keyValue if key in ingredientsList}
print newDict # {'ingredient4': 'ingredient4', 'ingredient5': 'ingredient5', 'ingredient1': 'postman', 'ingredient2': 'ing2', 'ingredient3': 'me'}

(Am using this in a flask app with sqlAlchemy- hope it helps)
In your put method, first query of a specific recipe for example
recipe = Recipe.query.filter_by(recipe_id=id).first()
Then you can access the specific keys like this
data = request.get_json()
recipe.title = data['title']
recipe.directions = data['directions']
recipe.ingredient1 = data['ingredient1']
recipe.ingredient2 = data['ingredient2']

Related

Terraform iterate over nested data

I'm trying to create New Relic's service-level objects based on a yaml config file that provides the relevant configuration.
My yaml configuration:
slo:
targets:
- first_slo:
name: "My First SLO"
endpoints:
- path: /api/method1
method: GET
- path: /api/method2
method: PUT
objectives:
availability:
threshold: 99.9
- first_slo:
name: "My Second SLO"
endpoints:
- path: /api/method12
method: GET
- path: /api/method23
method: PUT
objectives:
availability:
threshold: 99.99
I want to iterate over this example configuration to build the object, but I'm struggling to form the right NRQL query using a nested iteration.
My terraform file:
resource "newrelic_service_level" "availability" {
for_each = var.config.slo.targets
guid = var.guid
name = "${each.value.name} - Availability"
description = "Proportion of requests that are served successfully."
events {
account_id = var.account_id
valid_events {
from = "Transaction"
where = "transactionType='Web' AND entityGuid = '${var.guid}' AND (OR_CONDITION_BETWEEN_ALL_THE_METHODS_AND_URIS)"
}
bad_events {
from = "Transaction"
where = "transactionType= 'Web' AND entityGuid = '${var.guid}' AND numeric(response.status) >= 500 AND (OR_CONDITION_BETWEEN_ALL_THE_METHODS_AND_URIS)"
}
}
objective {
target = each.value.objectives.availability.threshold
time_window {
rolling {
count = 7
unit = "DAY"
}
}
}
}
So basically what I'm trying to do here, is create a service level with an NRQL query that filters only for the specific combination of URI and method that are relevant for this specific target - the URI and methods that I have in my config file.
So for the first SLO, OR_CONDITION_BETWEEN_ALL_THE_METHODS_AND_URIS should translate to something like this:
(request.uri = '/api/method1' AND request.method = 'GET') OR (request.uri = '/api/method2' AND request.method = 'PUT')
My current solution would be to build the query manually and add it to the configurations for each SLO, but it is not readable and hard to maintain.
I would highly appreciate any suggestions on how to build the query dynamically.
You can certainly build that query with Terraform. Here's a wee .tf file that shows how you could do it:
locals {
config = yamldecode(file("${path.root}/vars.yaml"))
parsed = [for d in local.config.slo.targets : {
name : d["name"]
condition : join(" OR ", [for e in d["endpoints"] : "(request.uri = '${e["path"]}' AND request.method = '${e["method"]}')"])
}]
}
output "parsed" {
value = local.parsed
}
This expects your yaml file to be sitting next to it with name vars.yaml, and produces:
$ terraform plan
Changes to Outputs:
+ parsed = [
+ {
+ condition = "(request.uri = '/api/method1' AND request.method = 'GET') OR (request.uri = '/api/method2' AND request.method = 'PUT')"
+ name = "My First SLO"
},
+ {
+ condition = "(request.uri = '/api/method12' AND request.method = 'GET') OR (request.uri = '/api/method23' AND request.method = 'PUT')"
+ name = "My Second SLO"
},
]
For your module, you can just use the join(...) part in place of OR_CONDITION_BETWEEN_ALL_THE_METHODS_AND_URIS. Having it repeated should be fine (as long as you document it, naturally), but if you don't like the big long line, you can create a sub-module to encapsulate it. Or you could build the query string in a pre-processing locals block, possibly using the merge function to just add the query string alongside the rest of each target's config.

How do I pass a variable into a payload

So I have an endpoint that I am trying to integrate in Python which accepts a POST request and according to the API documentation, the payload is to be formatted this way:
payload = "{\r\n\"serviceCode\" : \"V-TV\",\r\n\"type\" : \"DSTV\",\r\n\"smartCardNo\" : \"10441003943\"\r\n}\r\n\r\n\r\n\r\n\r\n"
I want the values of type and smartCardNo to be dynamic, i.e I am going to get the values from a form in the frontend and pass it to the backend but I am finding it difficult to do so.
If I format the payload this way(which of course allows ease of passing variable):
{
"serviceCode": "V-TV",
"type": "DSTV",
"smartCardNo" : "10441003943"
}
I get this error:
{'required_fields': ['The service code field is required.'], 'message': 'Service Code is not supplied', 'status': '301'}
Could anyone tell me how I can pass the values for type and smartCardNo dynamically in the fist format(the format specified in the documentation)....any help will be greatly appreciated.
you can simply use the .format()
dict_values = {
"serviceCode": "V-TV",
"type": "DSTV",
"smartCardNo" : "10441003943"
}
payload = """{{"serviceCode":"{serviceCode}","type":"{mytype}","smartCardNo":"{smartCardNo}"}}""".format(
serviceCode = dict_values["serviceCode"],
mytype = dict_values["type"],
smartCardNo = dict_values["smartCardNo"]
)
output:
'{"serviceCode":"V-TV","type":"DSTV","smartCardNo":"10441003943"}'
If you really need the same format as in your payload example, simple use:
payload = "{{\r\n\"serviceCode\" : \"{serviceCode}\",\r\n\"type\" : \"{mytype}\",\r\n\"smartCardNo\" : \"{smartCardNo}\"\r\n}}\r\n\r\n\r\n\r\n\r\n".format(
serviceCode = dict_values["serviceCode"],
mytype = dict_values["type"],
smartCardNo = dict_values["smartCardNo"]
)
and your output will be:
'{\r\n"serviceCode" : "V-TV",\r\n"type" : "DSTV",\r\n"smartCardNo" : "10441003943"\r\n}\r\n\r\n\r\n\r\n\r\n'

How to obtain virtual user id/details in gatling?

I am new to Gatling and Scala and I need your advice.
I would like to obtain load test for n-users. Each user have to send request for creating different accounts. This is obtained by sending json file with appropriate array of objects ('entries' in our case).
Each single user must send different login as our backend system is checking if username is unique. Somehow we have to be sure that gatling is sending different data for each virtual user and also for each entries as well.
We noticed that there us session element which represents virtual user's state. Problem is that code showed below will not work as Exec structure used with expression function does not send any request.
There is section that could work but I do not know how to determine third parameter to distinguish virtual user id. Please find below simple json file structure used for this test
{
"entries": [
{
"userName": "some user name",
"password": "some password"
}
}
and scala code with my comments
import io.gatling.core.Predef._
import io.gatling.http.Predef._
class UserCreationTest extends Simulation {
val profilesNumber = 2
val virtualUsers = 2
val httpConf = http
.baseURL("some url")
.acceptHeader("application/json")
.basicAuth("username", "password")
// This method will multiply 'entries' section in JSON 'entriesNumber' times
def createJsonUserEntries(entriesNumber: Int, users: List[String], userId : Long): String = {
val header = """{"entries": ["""
val footer = """]}"""
val builder = StringBuilder.newBuilder
for (i <- 0 until entriesNumber) {
val userIndex = (userId.toInt - 1) * entriesNumber + i
val userName = users(userIndex).get
val apiString =
s"""{
"userName": "${userName}"
"password": "password"
}"""
builder.append(apiString)
if (i != entriesNumber) {
builder.append(",")
}
}
header + builder.toString() + footer
}
// We do have method for generating user names based on profilesNumber and virtualUsers variables
// but for sake of this example lets hardcode 4 (profilesNumber * virtualUsers) user names
val usersList = List("user-1", "user-2", "user-3", "user-4")
//This will throw exception as no request was send. According to documentation function block is used to debugging/editing session
val scn = scenario("Create WiFi User Profile")
.exec(session => {
http("CreateUserProfile")
.post("/userProfiles/create/")
.body(StringBody(
createJsonUserEntries(profilesNumber, userslList, session.userId).toString
)
).asJSON
session})
// This exec block will send a request but I do not know how to determine third param that should be virtual user Id
// To run this section please comment previous whole scenario block
/*
val scn = scenario("")
.exec(http("CreateUserProfile")
.post("/userProfiles/create/")
.body(StringBody(
createJsonUserEntries(profilesNumber, emailList, ???).toString
)
).asJSON
)
*/
setUp(scn.inject(atOnceUsers(virtualUsers)).protocols(httpConf))
}
Can you help me on that please? Is there any other way to do that in gatling? Thank you very much in advance
so you are trying to have each user have a unique userId?
you could create a feeder that does this
var userIdFeeder = (1 to 999999).toStream.map(i => Map("userId" -> i)).toIterator
val scn = scenario("")
.feed(userIdFeeder)
.exec(http("CreateUserProfile")
.post("/userProfiles/create/")
.body(StringBody(
createJsonUserEntries(profilesNumber, emailList, "${userId}").toString
)
).asJSON
)

setting context with list of objects as prameters in dialogflow

I have a list of values each having another KEY value corresponding to it, when i present this list to user, user has to select a value and agent has to call an external api with selected value's KEY. how can i achieve this in dialogflow?
I tried to send the entire key value pair in the context and access it in the next intent but for some reason when i set a list(array) to context parameters dialogflow simply ignoring the fulfillment response.
What is happening here and is there any good way to achieve this? I am trying to develop a food ordering chatbot where the category of items in menu is presented and list items in that menu will fetched when user selects a category, this menu is not static thats why i am using api calls to get the dynamic menu.
function newOrder(agent)
{
var categories = []
var cat_parameters = {}
var catarray = []
const conv = agent.conv();
//conv.ask('sure, select a category to order');
agent.add('select a category to order');
return getAllCategories().then((result)=>{
for(let i=0; i< result.restuarantMenuList.length; i++)
{
try{
var name = result.restuarantMenuList[i].Name;
var catid = result.restuarantMenuList[i].Id;
categories.push(name)
//categories.name = catid
cat_parameters['id'] = catid;
cat_parameters['name'] = name
catarray.push(cat_parameters)
}catch(ex)
{
agent.add('trouble getting the list please try again later')
}
}
agent.context.set({
name: 'categorynames',
lifespan: 5,
parameters: catarray, // if i omit this line, the reponse is the fultillment response with categories names, if i keep this line the reponse is fetching from default static console one.
})
return agent.add('\n'+categories.toString())
})
function selectedCategory(agent)
{
//agent.add('category items should be fetched and displayed here');
var cat = agent.parameters.category
const categories = agent.context.get('categorynames')
const cat_ob = categories.parameters.cat_parameters
// use the key in the catarray with the parameter cat to call the external API
agent.add('you have selected '+ cat );
}
}
The primary issue is that the context parameters must be an object, it cannot be an array.
So when you save it, you can do something like
parameters: {
"cat_parameters": catarray
}
and when you deal with it when you get the reply, you can get the array back with
let catarray = categories.parameters.cat_parameters;
(There are some other syntax and scoping issues with your code, but this seems like it is the data availability issue you're having.)

populate a comboBox in Griffon App dynamically

I have 2 comboBoxes in my View of Griffon App (or groovy swingBuilder)
country = comboBox(items:country(), selectedItem: bind(target:model, 'country',
value:model.country), actionPerformed: controller.getStates)
state = comboBox(items:bind(source:model, sourceProperty:'states'),
selectedItem: bind(target:model, 'state', value:model.state))
The getStates() in the controller, populates #Bindable List states = [] in the model based on the country selected.
The above code doesn't give any errors, but the states are never populated.
I changed the states from being List to a range object(dummy), it gives me an error MissingPropertyException No such property items for class java.swing.JComboBox.
Am I missing something here? There are a couple of entries related to this on Nabble but nothing is clear. The above code works if I had a label instead of a second comboBox.
I believe that the items: property is not observable and it's only used while the node is being built. You may have better results by setting the binding on the model or by using GlazedLists' EventList.
Model:
#Bindable String country = ""
EventList statesList = new BasicEventList()
Controller:
def showStates = { evt = null ->
model.statesList.clear()
def states = []
if(model.country == "US")
states = ["CA","TX", "CO", "VA"]
else if(model.country == "Canada")
states = ["BC", "AL"]
else
states = ["None"]
edt {model.statesList.addAll(states.collect{it})}
}
View:
def createComboBoxStatesModel() {
new EventComboBoxModel(model.daysList) }
comboBox( items:["USA","Canada","other"], selectedItem: bind(target:model, 'country', value: model.country), actionPerformed : controller.showStates)
comboBox( model: createComboBoxStatesModel(), selectedItem: bind(target:model, 'state', value:model.state))

Resources