March 27-31, 2017
Anand Chitipothu
These notes are available online at https://notes.pipal.in/2017/symantec
© Pipal Academy LLP
Let us look at an example of class inheritance.
class Formatter:
def format_text(self, text):
return text
def format_file(self, filename):
text = open(filename).read()
return self.format_text(text)
class UpperCaseFormatter(Formatter):
def format_text(self, text):
return text.upper()
f = UpperCaseFormatter()
f.format_text("Hello World!")
print(f.format_file("words.txt"))
class LineFormatter(Formatter):
def format_text(self, text):
lines = text.splitlines()
lines = [self.format_line(line) for line in lines]
return "\n".join(lines)
def format_line(self, line):
"""Method to format a line.
The sub classes can override this method to
specify how to format indidual lines.
"""
return line
class PrefixFormatter(LineFormatter):
def __init__(self, prefix):
self.prefix = prefix
def format_line(self, line):
return self.prefix + line
f = PrefixFormatter("[INFO] ")
print(f.format_text("Hello"))
print(f.format_text("a\nb\nc\n"))
print(f.format_file("words.txt"))
Please see exceptions notebook.
from urllib.request import urlopen
url = "http://anandology.com/tmp/hello.txt"
contents = urlopen(url).read()
print(contents)
Notice that urlopen always gives bytes. We need to convert that into string if required.
print(contents.decode('utf-8'))
response = urlopen(url)
response
print(response.headers)
There is a third-party library called requests that is very popular.
import requests
r = requests.get("http://anandology.com/tmp/hello.txt")
r
r.text
response = urlopen("http://google.com/")
print(response.headers)
r = requests.get("http://google.com/")
r.status_code
print(r.text[:500])
import json
person = {"name": "Alice", "email": "alice@example.com"}
print(person)
jsontext = json.dumps(person)
jsontext
person = {
"name": "Alice",
"email": "alice@example.com",
"active": True,
"n": 87,
"tags": ["a", "b"],
"comment": "comment with a single 'quote'"
}
print(person)
jsontext = json.dumps(person)
jsontext
print(jsontext)
Let us try a simple example.
There is a service called http://httpbin.org. It just echos back our request as JSON.
url = "http://httpbin.org/get"
print(requests.get(url).text)
requests.get(url).text
The requests library provides a handy way to work with JSON.
d = requests.get(url).json()
d
d['origin']
def get_my_ip():
url = "http://httpbin.org/get"
d = requests.get(url).json()
return d['origin']
get_my_ip()
Github has very beautiful API.
url = "https://api.github.com/search/repositories"
params = {
"q": "language:python",
"sort": "stars",
"order": "desc"
}
d = requests.get(url, params=params).json()
type(d)
d.keys()
d['total_count']
d['items'][0].keys()
for repo in d['items'][:10]:
print(repo['full_name'])
%%file popular-repos.py
import requests
url = "https://api.github.com/search/repositories"
params = {
"q": "language:python",
"sort": "stars",
"order": "desc"
}
d = requests.get(url, params=params).json()
for repo in d['items'][:10]:
print(repo['full_name'])
!python popular-repos.py
import requests
url = "http://httpbin.org/post"
data = {"x": 1, "y": 2}
response = requests.post(url, data=data)
response.json()
response = requests.post(url, json=data)
response.json()
Setup an incoming webbook for your slack channel. That gives a webhook URL.
# given by slack - this posts to #hack on pipalacademy's slack
url ="https://hooks.slack.com/services/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"
payload={
"text": "This is a message sent from Python.\n" +
"And this is another line of text."
}
requests.post(url, data={"payload": json.dumps(payload)})
def post_to_slack(message):
payload={
"text": message
}
requests.post(url, data={"payload": json.dumps(payload)})
post_to_slack("Hello everyone")
for i in range(10):
post_to_slack("Hello " + str(i))
def post_to_slack(message, username=None, icon=None):
payload={
"text": message
}
if username:
payload["username"] = username
if icon:
payload["icon_emoji"] = icon
requests.post(url, data={"payload": json.dumps(payload)})
post_to_slack("banana banana banana", username="monkey-bot", icon=":monkey_face:")
Generete ansible dynamic inventory.
It looks something like this:
{
"_meta": {
"hostvars": {
"host1": {},
"host2": {}
}
},
"group1": [
"host1",
"host2"
]
}
%%file hosts.txt
mail-1.example.com
mail-2.example.com
web-1.example.com
web-2.example.com
%%file generate-dyn-inventory.py
"""Takes a plain text hosts file and generates
dynamic inventory for ansible.
"""
import sys
import json
def read_hosts(filename):
return [line.strip() for line in open(filename)]
def get_host_vars(hostname):
return {}
def generate_inventory(hosts):
d = {
"_meta": {
"hostvars": {h: get_host_vars(h) for h in hosts}
},
"testgroup": hosts
}
return d
def main():
hostsfile = sys.argv[1]
hosts = read_hosts(hostsfile)
inventory = generate_inventory(hosts)
print(json.dumps(inventory, indent=4))
if __name__ == "__main__":
main()
!python generate-dyn-inventory.py hosts.txt
%%file generate-dyn-inventory.py
"""Takes a plain text hosts file and generates
dynamic inventory for ansible.
version 2
"""
import sys
import json
def read_hosts(filename):
return [line.strip() for line in open(filename)]
def get_host_vars(hostname):
return {"g": find_group(hostname)}
def find_group(hostname):
basename = hostname.split(".")[0]
group = basename.split("-")[0]
return group
def generate_inventory(hosts):
d = {
"_meta": {
"hostvars": {h: get_host_vars(h) for h in hosts}
},
}
# for each host, identify the group and add to that
for h in hosts:
group = find_group(h)
d.setdefault(group, []).append(h)
return d
def main():
hostsfile = sys.argv[1]
hosts = read_hosts(hostsfile)
inventory = generate_inventory(hosts)
print(json.dumps(inventory, indent=4))
if __name__ == "__main__":
main()
!python generate-dyn-inventory.py hosts.txt
Please look at regular-expressions notebook.
Professional command-line applciations usually takes various flags and display nice help.
For example, let us look at the grep command in unix.
!grep --help
Let us understand different kinds of arguments that are commonly used:
-i, --ignore-case
Perform case insensitive matching.
By default, grep is case sensitive.
-c, --count
Only a count of selected lines is written to
standard output.
-C[num, --context=num]
Print num lines of leading and trailing context
surrounding each match.
-f file, --file=file
Read one or more newline separated patterns from file.
pattern
Pattern to look for
[file ...]
zero or more filenames to search
argparse module¶%%file echo.py
"""Simple echo program that takes command-line flags.
"""
import argparse
def parse_args():
p = argparse.ArgumentParser()
p.add_argument("message", help="message to display")
p.add_argument("-r", "--repeats",
type=int,
default=1,
help="number of times to repeat the message")
return p.parse_args()
def main():
args = parse_args()
print(args)
for i in range(args.repeats):
print(args.message)
if __name__ == "__main__":
main()
!python echo.py --help
!python echo.py -r 4 hello
!python echo.py -r x hello
%%file echo2.py
"""Simple echo program that takes command-line flags.
version 2 with boolean flags and multiple arguments.
"""
import argparse
def parse_args():
p = argparse.ArgumentParser()
p.add_argument("message", nargs="+", help="message to display")
p.add_argument("-r", "--repeats",
type=int,
default=1,
help="number of times to repeat the message")
p.add_argument("-u", "--upper-case",
default=False,
action="store_true",
help="convert the message to upper case")
return p.parse_args()
def main():
args = parse_args()
print(args)
message = " ".join(args.message)
if args.upper_case:
message = message.upper()
for i in range(args.repeats):
print(message)
if __name__ == "__main__":
main()
!python echo2.py --help
!python echo2.py -u -r 3 hello
!python echo2.py -r 3 hello world
%%file resolve-ip.py
import argparse
import re
def ipaddress(value):
# if value.count(".") != 3:
# raise ValueError("Invalid IP address: " + repr(value))
m = re.match("^(\d+)\.(\d+)\.(\d+)\.(\d+)$", value)
if not m:
raise ValueError("Invalid IP address: " + repr(value))
return tuple([int(x) for x in m.groups()])
def parse_args():
p = argparse.ArgumentParser()
p.add_argument("ip", nargs="+",
type=ipaddress,
help="IP address to resolve")
return p.parse_args()
def main():
args = parse_args()
print(args)
if __name__ == "__main__":
main()
!python resolve-ip.py --help
!python resolve-ip.py hello
!python resolve-ip.py 1.2.3.4