Session 7

Published

October 19, 2023

Topics Covered
  • Working with APIs

Questions

import argparse
p = argparse.ArgumentParser()
p.add_argument("-i", "--ignore-case", action="store_true", default=False)
_StoreTrueAction(option_strings=['-i', '--ignore-case'], dest='ignore_case', nargs=0, const=True, default=False, type=None, choices=None, required=False, help=None, metavar=None)
p.parse_args(args=["-i"])
Namespace(ignore_case=True)
print(p.format_help())
usage: ipykernel_launcher.py [-h] [-i]

options:
  -h, --help         show this help message and exit
  -i, --ignore-case

Working with Web & APIs

The third-party library requests is the most popular choice for working with web & APIs.

import requests
!curl https://anandology.com/tmp/hello.txt
Hello, world!

Let’s see how to do that with Python.

url = "https://anandology.com/tmp/hello.txt"
response = requests.get(url)
response
<Response [200]>
response.status_code
200
response.headers
{'Server': 'nginx/1.10.3 (Ubuntu)', 'Date': 'Thu, 19 Oct 2023 04:13:18 GMT', 'Content-Type': 'text/plain', 'Content-Length': '14', 'Last-Modified': 'Sat, 30 Nov 2019 10:26:32 GMT', 'Connection': 'keep-alive', 'ETag': '"5de243d8-e"', 'Access-Control-Allow-Origin': '*', 'Accept-Ranges': 'bytes'}
response.text
'Hello, world!\n'
print(requests.get(url).text)
Hello, world!

Example: figlet

API URL: https://figlet.apps.pipal.in/api/figlet

The API takes two query parameters - text and font.

!curl 'https://figlet.apps.pipal.in/api/figlet?text=Python'
 ____        _   _                 
|  _ \ _   _| |_| |__   ___  _ __  
| |_) | | | | __| '_ \ / _ \| '_ \ 
|  __/| |_| | |_| | | | (_) | | | |
|_|    \__, |\__|_| |_|\___/|_| |_|
       |___/                       
!curl 'https://figlet.apps.pipal.in/api/figlet?text=Python&font=slant'
    ____        __  __              
   / __ \__  __/ /_/ /_  ____  ____ 
  / /_/ / / / / __/ __ \/ __ \/ __ \
 / ____/ /_/ / /_/ / / / /_/ / / / /
/_/    \__, /\__/_/ /_/\____/_/ /_/ 
      /____/                        
!curl 'https://figlet.apps.pipal.in/api/figlet?text=Python&font=lean'
                                                               
    _/_/_/                _/      _/                           
   _/    _/  _/    _/  _/_/_/_/  _/_/_/      _/_/    _/_/_/    
  _/_/_/    _/    _/    _/      _/    _/  _/    _/  _/    _/   
 _/        _/    _/    _/      _/    _/  _/    _/  _/    _/    
_/          _/_/_/      _/_/  _/    _/    _/_/    _/    _/     
               _/                                              
          _/_/                                                 
url = "https://figlet.apps.pipal.in/api/figlet"
params = {"text": "Python", "font": "slant"}
text = requests.get(url, params=params).text
text
'    ____        __  __              \n   / __ \\__  __/ /_/ /_  ____  ____ \n  / /_/ / / / / __/ __ \\/ __ \\/ __ \\\n / ____/ /_/ / /_/ / / / /_/ / / / /\n/_/    \\__, /\\__/_/ /_/\\____/_/ /_/ \n      /____/                        \n'
print(text)
    ____        __  __              
   / __ \__  __/ /_/ /_  ____  ____ 
  / /_/ / / / / __/ __ \/ __ \/ __ \
 / ____/ /_/ / /_/ / / / /_/ / / / /
/_/    \__, /\__/_/ /_/\____/_/ /_/ 
      /____/                        
def figlet(text, font=None):
    url = "https://figlet.apps.pipal.in/api/figlet"
    params = {"text": text}
    if font:
        params['font'] = font
    text = requests.get(url, params=params).text
    print(text)
figlet("Python")
 ____        _   _                 
|  _ \ _   _| |_| |__   ___  _ __  
| |_) | | | | __| '_ \ / _ \| '_ \ 
|  __/| |_| | |_| | | | (_) | | | |
|_|    \__, |\__|_| |_|\___/|_| |_|
       |___/                       
figlet("Python", font="slant")
    ____        __  __              
   / __ \__  __/ /_/ /_  ____  ____ 
  / /_/ / / / / __/ __ \/ __ \/ __ \
 / ____/ /_/ / /_/ / / / /_/ / / / /
/_/    \__, /\__/_/ /_/\____/_/ /_/ 
      /____/                        
for i in range(5):
    figlet(i)
  ___  
 / _ \ 
| | | |
| |_| |
 \___/ 
       

 _ 
/ |
| |
| |
|_|
   

 ____  
|___ \ 
  __) |
 / __/ 
|_____|
       

 _____ 
|___ / 
  |_ \ 
 ___) |
|____/ 
       

 _  _   
| || |  
| || |_ 
|__   _|
   |_|  
        

Problem: Add API

%load_problem add-api
Problem: Add API

Use Add API to add two numbers.

$ curl https://numbers.apps.pipal.in/add?a=3&b=4
7

Write a function add that takes two numbers as arguments and adds them using the Add API and returns the result.

>>> add(3, 4)
7

You can verify your solution using:

%verify_problem add-api

# your code here


Problem: Fibs API

%load_problem fibs-api
Problem: Fibs API

Write a function fibs to generate fibonacci numbers using fibs API at https://numbers.apps.pipal.in/.

The API takes 3 query parameters a, b and n and generates n fibonacci numbers starting with a and b.

$ curl 'https://numbers.apps.pipal.in/fibs?a=3&b=4&n=10
3
4
7
11
18
29
47
76
123
199

Write a function fibs that takes three numbers a, b and n as arguments and returns a list of fibonacci numbers given by the API.

>>> fibs(3, 4, 10)
[3, 4, 7, 11, 18, 29, 47, 76, 123, 199]

>>> sum(fibs(3, 4, 10))
517

You can verify your solution using:

%verify_problem fibs-api

!curl 'https://numbers.apps.pipal.in/fibs?a=3&b=4&n=5'
3
4
7
11
18
url = "https://numbers.apps.pipal.in/fibs"
params = {"a": 3, "b": 4, "n": 5}
text = requests.get(url, params=params).text
text
'3\n4\n7\n11\n18\n'
text.splitlines()
['3', '4', '7', '11', '18']
[int(line) for line in text.splitlines()]
[3, 4, 7, 11, 18]
def fibs(a, b, n):
    url = "https://numbers.apps.pipal.in/fibs"
    params = {"a": a, "b": b, "n": n}
    text = requests.get(url, params=params).text.strip()
    # print(repr(text))
    return [int(line) for line in text.splitlines()]
fibs(3, 4, 5)
[3, 4, 7, 11, 18]
fibs(3, 4, 0)
[]
%verify_problem fibs-api
✓ fibs(3, 4, 10)
✓ sum(fibs(3, 4, 10))
✓ fibs(3, 4, 0)
✓ fibs(3, 4, 1)
✓ fibs(3, 4, 2)
✓ fibs(3, 4, 3)
✓ fibs(1, 1, 6)
🎉 Congratulations! You have successfully solved problem fibs-api!!
!curl 'https://numbers.apps.pipal.in/fibs?a=3&b=4&n=10'
3
4
7
11
18
29
47
76
123
199
x = 100
a = print(x)
100
print(a)
None
"".split("\n")
['']
"".split()
[]
"1\n2\n3\n".splitlines()
['1', '2', '3']
"\n".splitlines()
['']
"\n".strip().splitlines()
[]

JSON APIs

import json
person = {
    "name": "Alice", 
    "email": "alice@example.com",
    "verified": True,
    "numbers": [1, 2, 3, 4]
}
json.dumps(person)
'{"name": "Alice", "email": "alice@example.com", "verified": true, "numbers": [1, 2, 3, 4]}'
jsontext = json.dumps(person)
json.loads(jsontext)
{'name': 'Alice',
 'email': 'alice@example.com',
 'verified': True,
 'numbers': [1, 2, 3, 4]}
url = "https://numbers.apps.pipal.in/fibs"
params = {"a": 3, "b": 4, "n": 5, "format": "json"}
text = requests.get(url, params).text
text
'{"result":[3,4,7,11,18]}\n'
json.loads(text)
{'result': [3, 4, 7, 11, 18]}
json.loads(text)['result']
[3, 4, 7, 11, 18]
requests.get(url, params).json()
{'result': [3, 4, 7, 11, 18]}
requests.get(url, params).json()['result']
[3, 4, 7, 11, 18]
def fibs(a, b, n):
    url = "https://numbers.apps.pipal.in/fibs"
    params = {"a": a, "b": b, "n": n, "format": "json"}
    data = requests.get(url, params).json()    
    return data['result']
fibs(3, 4, 5)
[3, 4, 7, 11, 18]

HTTP Methods

Every HTTP request is made with one of the HTTP methods. The common ones are GET, POST, PUT and DELETE.

!curl -v https://anandology.com/tmp/hello.txt
*   Trying 139.59.87.96:443...
* Connected to anandology.com (139.59.87.96) port 443 (#0)
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN: server accepted http/1.1
* Server certificate:
*  subject: CN=anandology.com
*  start date: Oct 15 11:52:59 2023 GMT
*  expire date: Jan 13 11:52:58 2024 GMT
*  subjectAltName: host "anandology.com" matched cert's "anandology.com"
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
* using HTTP/1.1
> GET /tmp/hello.txt HTTP/1.1
> Host: anandology.com
> User-Agent: curl/7.88.1
> Accept: */*
> 
< HTTP/1.1 200 OK
< Server: nginx/1.10.3 (Ubuntu)
< Date: Thu, 19 Oct 2023 05:14:37 GMT
< Content-Type: text/plain
< Content-Length: 14
< Last-Modified: Sat, 30 Nov 2019 10:26:32 GMT
< Connection: keep-alive
< ETag: "5de243d8-e"
< Access-Control-Allow-Origin: *
< Accept-Ranges: bytes
< 
Hello, world!
* Connection #0 to host anandology.com left intact

Example: range

!curl -i -H 'Content-type: application/json' -d '{"start": 1, "stop": 10}' https://numbers.apps.pipal.in/range
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Thu, 19 Oct 2023 05:16:57 GMT
Content-Type: application/json
Content-Length: 31
Connection: keep-alive

{"result":[1,2,3,4,5,6,7,8,9]}
!curl -v -H 'Content-type: application/json' -d '{"start": 1, "stop": 10}' https://numbers.apps.pipal.in/range
*   Trying 157.245.98.225:443...
* Connected to numbers.apps.pipal.in (157.245.98.225) port 443 (#0)
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN: server accepted http/1.1
* Server certificate:
*  subject: CN=numbers.apps.pipal.in
*  start date: Oct 19 01:46:56 2023 GMT
*  expire date: Jan 17 01:46:55 2024 GMT
*  subjectAltName: host "numbers.apps.pipal.in" matched cert's "numbers.apps.pipal.in"
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
* using HTTP/1.1
> POST /range HTTP/1.1
> Host: numbers.apps.pipal.in
> User-Agent: curl/7.88.1
> Accept: */*
> Content-type: application/json
> Content-Length: 24
> 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
< HTTP/1.1 200 OK
< Server: nginx/1.18.0 (Ubuntu)
< Date: Thu, 19 Oct 2023 05:19:28 GMT
< Content-Type: application/json
< Content-Length: 31
< Connection: keep-alive
< 
{"result":[1,2,3,4,5,6,7,8,9]}
* Connection #0 to host numbers.apps.pipal.in left intact
url = "https://numbers.apps.pipal.in/range"
data = {"start": 1, "stop": 10, "step": 3}
requests.post(url, json=data).json()
{'result': [1, 4, 7]}
def api_range(start, stop, step=1):
    url = "https://numbers.apps.pipal.in/range"
    data = {"start": start, "stop": stop, "step": step}
    result = requests.post(url, json=data).json()
    return result['result']
api_range(2, 5)
[2, 3, 4]
!curl https://numbers.apps.pipal.in/range
<!doctype html>
<html lang=en>
<title>405 Method Not Allowed</title>
<h1>Method Not Allowed</h1>
<p>The method is not allowed for the requested URL.</p>

Problem: product API

%load_problem product-api
Problem: Product API

Write a function product to compute the product of a list of numbers using the product API.

$ curl -H 'Content-type: application/json' -d '{"numbers": [1, 2, 3, 4, 5]}' https://numbers.apps.pipal.in/product
{"result": 120}

Write a function product that takes a list of numbers as argument and computes their product using the product API.

>>> product([1, 2, 3, 4])
24
>>> product([10, 2, 50])
1000

You can verify your solution using:

%verify_problem product-api

# your code here


Authorization

!curl 'https://numbers.apps.pipal.in/store'
{}
!curl -X PUT \
    -H 'content-type: application/json' \
    -H 'Authorization: Bearer abcd1234' \
    -d '{"value": 50}' 'https://numbers.apps.pipal.in/store/x'
{"ok":true}
!curl -X PUT \
    -H 'content-type: application/json' \
    -H 'Authorization: Bearer abcd1234' \
    -d '{"value": 37}' 'https://numbers.apps.pipal.in/store/y'
{"ok":true}
!curl 'https://numbers.apps.pipal.in/store'
{"x":50,"y":37}
!curl 'https://numbers.apps.pipal.in/store/x'
{"value":50}
!curl -X DELETE 'https://numbers.apps.pipal.in/store/y'
{"error":"forbidden"}
!curl -X DELETE -H 'Authorization: Bearer abcd1234' 'https://numbers.apps.pipal.in/store/y'
{"ok":true}
!curl 'https://numbers.apps.pipal.in/store'
{"x":50}
headers = {"Authorization": "Bearer abcd1234"}
def put(name, value):
    url = f"https://numbers.apps.pipal.in/store/{name}"
    data = {"value": value}
    response = requests.put(url, json=data, headers=headers).json()
    print(response)
def get_store():
    url = f"https://numbers.apps.pipal.in/store"
    return requests.get(url).json()
get_store()
{'x': 150}
put("x", 150)
{'ok': True}
for i in range(10):
    put(f"x{i}", i)
{'ok': True}
{'ok': True}
{'ok': True}
{'ok': True}
{'ok': True}
{'ok': True}
{'ok': True}
{'ok': True}
{'ok': True}
{'ok': True}
get_store()
{'x': 150,
 'x0': 0,
 'x1': 1,
 'x2': 2,
 'x3': 3,
 'x4': 4,
 'x5': 5,
 'x6': 6,
 'x7': 7,
 'x8': 8,
 'x9': 9}