KeyError: 'data' - python

I am currently on a Discord Bot interacting with the Controlpanel API. (https://documenter.getpostman.com/view/9044962/TzY69ub2#02b8da43-ab01-487d-b2f5-5f8699b509cd)
Now, I am getting an KeyError when listing a specific user.
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer <censored>'
}
url = "https://<censored>"
endpoint = f"/api/users/{user}"
if __name__ == '__main__':
data = requests.get(f'{url}{endpoint}', headers=headers).text
for user in json.loads(data)['data']:
embed = discord.Embed(title="Users")
embed.add_field(name=user['id'], value=user['name'])
await ctx.send(embed=embed)
^That's python.
Error:
for user in json.loads(data)['data']:
KeyError: 'data'
How can I fix this?
Thank you!

This KeyError happens usually when the Key doesn't exist(not exist or even a typo). in your case I think you dont have the 'data' key in your response and your should use something like:
data.json()
if you can post the complete response it would be more convinient to give you some hints.

The endpoint you're hitting does not return a list but a single object.
You should use the generic endpoint : {{url}}/api/users
Also I don't think you want to recreate your embed object for each user.
headers = {
'Authorization': 'Bearer <censored>'
}
url = 'https://<censored>'
endpoint = '/api/users'
if __name__ == '__main__':
embed = discord.Embed(title="Users")
for user in requests.get(
f'{url}{endpoint}', headers=headers
).json()['data']:
embed.add_field(name=user['id'], value=user['name'])
await ctx.send(embed=embed)
Also I'm pretty sure you can't just await like that in __main__.

Related

401 From MWAA Airflow Environment When Attempting To Run A DAG

Description
When attempting to make calls to a Managed Amazon Airflow instance I was not able to make API calls to the airflow environment despite being able to generate a CLI token from aws mwaa create-cli-token. Why am I getting a FORBIDDEN error here?
Console and Code
Code
#pytest.fixture(scope="function")
def run_dag(
environment_name: str,
airflow_conn_info: AirflowConnectionInfo,
dag_to_run: str,
target_date: datetime) -> Callable:
headers = {
'accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': airflow_conn_info.cli_token,
}
trigger_body = {
"conf": {},
"execution_date": target_date.isoformat(),
}
if not dag_to_run:
dag_to_run = f"{carrier_name}_dag"
base_url = f"https://{airflow_conn_info.hostname}/api/v1/dags/{dag_to_run}"
trigger_dag_url = f"{base_url}/dagRuns"
# TODO: Add some sort of check to ensure a DAG isn't disabled OR add a call
# to enable the DAG. For now we're just going to assume it's enabled.
trigger_response = requests.post(
trigger_dag_url,
headers=headers,
data=json.dumps(trigger_body))
if trigger_response.status_code != 200:
raise ValueError(f"{trigger_response}")
dag_run_status_url = f"{base_url}/{trigger_response.json()['dag_id']}"
status_body = {}
task_instances_status_url = f"{base_url}/dagRuns/{trigger_response.json()['dag_id']/taskInstances}"
task_instances_body = {}
status_response = requests.get(
dag_run_status_url,
headers=headers,
data=json.dumps(status_body))
if status_response.status_code != 200:
raise ValueError(f"{trigger_response}")
# Derived from
# https://github.com/apache/airflow/blob/main/airflow/utils/state.py
terminal_states: List[str] = ["success", "failed"]
# TODO: Add a timeout to this while loop.
while (trigger_response.status_code == 200
and trigger_response.json()["state"] not in terminal_states):
# TODO: Add some sort of console output to show what task instance we're
# on and the state of that current task instance.
status_response = requests.get(
dag_run_status_url,
headers=headers,
data=json.dumps(status_body))
task_instances_response = requests.get(
task_instances_status_url,
headers=headers,
data=json.dumps(task_instances_body))
breakpoint()
Failing Run PDB
(Pdb) base_url
'https://{a_string}.c46.us-east-1.airflow.amazonaws.com/api/v1/dags/fedex_dag'
(Pdb) trigger_response.json()
{'detail': None, 'status': 401, 'title': 'Unauthorized', 'type': 'https://airflow.apache.org/docs/2.0.2/stable-rest-api-ref.html#section/Errors/Unauthenticated'}
(Pdb) headers
{'accept': 'application/json', 'Content-Type': 'application/json', 'Authorization': '{secret}'}
TLDR: The API is turned off by default. This is not explicitly stated anywhere. You should use the https://YOUR_HOST_NAME/aws_mwaa/cli endpoint unless you want to enable the full API.
When I was reading the AWS documentation around generating a CLI token what was not clear to me is that the aws_mwaa/cli endpoint that AWS adds to the MWAA is the endpoint that they want you to use. This is explained in the user guide but not in any of the website documentation making it very unclear to me.
There is a AmazonMWAAFullApiAccess which sounds like it grants access to the full API if you have access to a role with the policy but i have not tested this yet.

how can make a liktervise discord.py?

Can someone help me to make a linktervise bypass bot for discord.py I have this code that I found on github but I can't understand it
import requests
def bypass(url):
payload = {
"url": url,
}
r = requests.post("https://api.bypass.vip/", data=payload)
return r.json()
if __name__ == '__main__':
result = bypass("https://...") # include url to bypass
print(result)
You have to try and make it yourself, the people here won't spoonfeed you.
You could make a command that uses
def bypass(url):
payload = {
"url": url,
}
r = requests.post("https://api.bypass.vip/", data=payload)
return r.json()
and then check what the value is that it returns and send that back to the user

How to trigger pipeline API in AzureDevOps from Python (urllib3)

I have to trigger a pipeline in Azure DevOps from a python script. I have already found out that i need a private access token and that part is fine. I can, however, not get the script to work. I am trying something like this:
data = [
{
}
]
http = urllib3.PoolManager()
r = http.request('POST', api_url, headers={'Content-Type': 'application/json-patch+json', "Authorization": private_access_token}, body=data)
print(r.status)
print(r.data)
Its a requirement that i have to use urllib3 because I cant use the requests package
data is empty, because looking at the parameters here https://learn.microsoft.com/en-us/rest/api/azure/devops/pipelines/runs/run%20pipeline?view=azure-devops-rest-6.0. Then i dont need any input data? I just want to trigger a pipeline, nothing else
Error message is not very helpful. I get error message 203.
I solved it by using:
authorization = str(base64.b64encode(bytes(':'+private_access_token, 'ascii')), 'ascii')
data = {}
a = json.dumps(data)
http = urllib3.PoolManager()
r = http.request('POST', api_url, headers = {'Content-Type': 'application/json', 'Authorization': 'Basic '+authorization}, body=a)

How to write clean pytest chain api tests

New-ish to python and I'm stumped on this. I literally cannot seem to find a clear and correct answer anywhere online. I honestly feel stupid because this is a pretty basic python skill.
My issue:
I've been tasked with writing a python test suite of asyncronous api requests chained together. I need to fire the requests, save values from the response json, then pass those values into subsequent requests.
Below is a list of what I WANT the test to do, and what I would expect it to do based on how I've written the test file:
Send GET to /users endpoint
Save first customerId from response payload as customer_id
Send POST to /customer/{customer_id}/addresses endpoint to create new customer address
Save addressId from response payload as address_id
Send PUT to /orders/{customer_id} endpoint to update order with the address_id from step #3.
Example Code:
(This is the same code I have on my machine, but I've sanitized the file with fake info.
import requests
import json
def first_request_get(self):
url = 'https://api.example.net/users'
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer asdfasdfasdfasdfasdfasdfasdf'
}
payload = {}
resp = requests.get(url, headers=headers, data=json.dumps(payload))
json_str = json.dumps(payload)
resp_body = resp.json()
customer_id = resp_body['customer'][0]['id']
assert resp_body['customer'][0]['id'] is not None
assert resp.status_code == 200
return customer_id
def second_request_post(self):
customer_id = self.first_request_get()
url = 'https://api.example.net/customers/{}/addresses'.format(customer_id)
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer asdfasdfasdfasdfasdfasdfasdf'
}
payload = {"address1": "285 Beandip Ln",
"city": "Lincoln",
"province": "Nebraska",
"zip": "68510",
}
resp = requests.post(url, headers=headers, data=json.dumps(payload))
resp_body = resp.json()
address_id = resp_body['address']['id']
print('address_id == ')
print(address_id)
assert resp.status_code == 200
assert resp_body['address']['id'] is not None
return address_id
def third_request_put(self):
address_id = self.second_request_post()
customer_id = self.first_request_get()
url = 'https://api.example.net/orders/{}'.format(customer_id)
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer asdfasdfasdfasdfasdfasdfasdf'
}
payload = {"address_id": address_id,
"next_charge_scheduled_at": "2022-01-31T00:00:00",
"price": 6.85,
"quantity": 2,
}
resp = requests.put(url, headers=headers, data=json.dumps(payload))
resp_body = resp.json()
subscription_id = resp_body['order']['id']
print('order_id == ')
print(subscription_id)
assert resp_body['order']['id'] is not None
assert resp.status_code == 200
return subscription_id
The result of executing this test file ends up looping through the file in a weird order rather than doing what I would expect it to do. Why do I have to call an earlier function just to access the variable I've already extracted from the json and assigned to a variable in an earlier function?
Unfortunately, it's not advised to design your tests this way.
Testcases should be completely independent of one another and have no side effects. The order of execution should not matter. The Pytest documentation among other sources makes reference to this (and takes steps to disallow violating this principle).
I can also recommend the book "The Art of Software Testing" by Glenford J Myers.
As such, to make this test work, you're going to have to place it all in one method...
If you'd like to be more explicit about the point of failure (even though pytest does a pretty good job already), you'll want to break this test up into multiple cases, but mock the data you're not explicitly testing at each stage.

Keep getting a 401 error when trying to pull data

I'm fairly new to using web APIs and pulling data and i'm also pretty new with python. My goal is to make a stat-tracker app but I keep getting a 401 when I try and pull the data.
I've printed out the entire url just to make sure I didn't get it wrong. I copied and pasted the API key exactly so that shouldn't be a problem
api_token = 'api key in python file'
api_url_base = 'https://public-api.tracker.gg/v2/apex/standard/'
headers = {'Content-Type' : 'application/json',
'Authorization' : 'Bearer {}'.format(api_token)}
def get_player_profile():
api_url = '{}profile/psn/Daltoosh'.format(api_url_base)
response = requests.get(api_url, headers=headers)
if response.status_code == 200:
return json.loads(response.content.decode('utf-8'))
else:
return response.status_code, api_url
print(get_player_profile())
#player_profile = get_player_profile()
#if player_profile is not None:
# print("Career Stats:")
# for k, v in player_profile['profile/psn/Daltoosh'].items():
# print('{0}:{1}.format(k, v)')
#else:
# print('[!] Data Request Failed [!]')
I expected a status code of 200 but there seems to be a problem authenticating.
I'm not too well versed in the web API that you are using, but I think you might be using the API token incorrectly. I don't think that specific API requires a Bearer token, but instead a separate header called TRN-Api-Key.
So maybe write something like this:
headers = {'Content-Type' : 'application/json', 'TRN-Api-Key' : api_token}
If you look here, you should be able to read up on how to set up authentication.

Categories