Install pip

If you end up on a system without pip, you can install it from a script.

wget https://bootstrap.pypa.io/get-pip.py # Download installation script
python3 get-pip.py # Run installation script

Read file line-by-line and print each line

def print_lines(file):
    with open(file) as f:
        for line in f:
            print(line)

Read file into list

def return_list(file):
    with open(file) as f:
        list = f.readlines()
        return list

Remove line from a file containing a specified string

def remove_line_containing_string(file):
    f = open(file, 'r')
    contents = f.readlines()
    f.close()

    f = open(file, 'w')
    for line in contents:
        if not 'some string' in line:
            f.write(line)
    f.close()

Check if file exists

def file_exists(file):
    if os.path.isfile(file):
        return True
    else:
        return False

Find and replace line in a file

def find_and_replace_in_file(inp_file, old, new):
    new_output = ''
    with open(inp_file, 'U') as f:
        new_output = f.read()

        while old in new_output:
            new_output = new_output.replace(old, new)

    with open(inp_file, 'w') as f:
        f.write(new_output)

Resource: https://bhagat.blog/2017/01/06/replacing-string-in-a-file-using-python/

Run command and get output

This can be found as part of mypyutils

import subprocess

def run_cmd(cmd):
    p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)x
    output, err = p.communicate()
    return output.decode().strip()

# Example:
print(run_cmd("uname -a"))

Python3 Simple HTTP Server

python3 -m http.server <port>

IPv6 server

web_server.py:

from http.server import HTTPServer, SimpleHTTPRequestHandler
import socket

class HTTPServerV6(HTTPServer):
    address_family = socket.AF_INET6

server = HTTPServerV6(('::', 8080), SimpleHTTPRequestHandler)
server.serve_forever()

Resource: https://stackoverflow.com/questions/25817848/python-3-does-http-server-support-ipv6

Python2 Simple HTTP Server

python -m SimpleHTTPServer <port>

Get password as input

import getpass

try:
    password = getpass.getpass()
except Exception as error:
    print('ERROR', error)

Resource: https://www.geeksforgeeks.org/getpass-and-getuser-in-python-password-without-echo/


Regex

Group matching

>>> import re
>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
>>> m.group(0)
'Isaac Newton'
>>> m.group(1)
'Isaac'
>>> m.group(2)
'Newton'
>>> m.group(1,2)
('Isaac', 'Newton')

Resource: https://docs.python.org/2/library/re.html

Regex testers

Regex to match a line in a file

# input could be something like:
# dog 2
pattern = re.compile("\w+(\d+)")
with open(file) as f:
    for line in f:
      m = pattern.match(line)
      if m:
        print(f"Found this item: {m.group(1)}")

List operations

Reverse list

>>> l = [1,2,3,4]
>>> rl = l[::-1]
>>> rl
[4, 3, 2, 1]

Resource: https://stackoverflow.com/questions/47025356/reverse-index-in-a-list

Count elements in a list

len(list)

Resource: https://stackoverflow.com/questions/4130027/python-count-elements-in-list

String to list

string.split()

Resource: https://stackoverflow.com/questions/8266529/python-convert-string-to-list

List to comma-separated string

a_list = ["a", "b", "c"]
joined_string = ",".join(a_list)

Resource: https://www.kite.com/python/answers/how-to-make-a-list-into-a-comma-separated-string-in-python

Check if list is empty

if not a:
  print("List is empty")

Resource: https://stackoverflow.com/questions/53513/how-do-i-check-if-a-list-is-empty

Get first two characters of a string

<string var>[2:]

Resource: https://stackoverflow.com/questions/1270990/how-to-remove-two-chars-from-the-beginning-of-a-line


File operations

List only files in a directory

from os import listdir
from os.path import isfile, join
onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]

Remove file

os.remove('path/to/file')

Change directory

os.chdir('/etc/')

Remove directory if it exists

if os.path.isdir(self.repo_name):
    shutil.rmtree(self.repo_name)

Remove all jpg files from current folder (python 2)

import glob, os
for f in glob.glob("*.jpg"):
    os.remove(f)

Remove all jpg files from current folder (python 3)

from pathlib import Path
for p in Path(".").glob("*.jpg"):
    p.unlink()

Run command

os.system('ls')

Break up long command

from mypyutils import sysutils

output = sysutils.run_cmd('aws ec2 describe-images --filters \
            "Name=name,Values=Kali-X2Go" --output json')

List comprehension

This for loop:

for x in range(int(sp),int(ep)+1):
    port_scan(site,int(x))

can also be represented as this list comprehension: [port_scan(site, int(x)) for x in range(int(sp), int(ep)+1)]

Dictionary comprehension

Similar concept to a list comprehension.

This will create a dictionary that maps an idea to the number of times someone has had it if the idea is greater than 4 characters:

all_my_ideas = {idea:ideas.count(idea) for idea in ideas if len(idea) > 4}

Resource: https://stackoverflow.com/questions/3496518/using-a-dictionary-to-count-the-items-in-a-list

print(list[0])

String interpolation with Python 3.6.x

import os
site = 'https://google.com'
os.system(f"open -a /Applications/Google\ Chrome.app {site}")

Escape fstring

In the event you need to have a ‘{’ in your string, use ‘{{’ to escape it

>>> foo = 'test'
>>> f'{foo} {{bar}}'
'test {bar}'

Resource: https://stackoverflow.com/questions/42521230/how-to-escape-f-strings-in-python-3-6

String interpolation with older Python

import os
site = 'https://google.com'
os.system("open -a /Applications/Google\ Chrome.app %s" % site)

The newer way with older Python

with open(file) as f:
    for line in f:
        print(run_cmd("nmap --open -Pn -top-ports 1000 -T4 -sS -g80 -sC -sV {target}".format(target=line)))

Resource: https://realpython.com/python-string-formatting/

Multiline list

list = [
    'item1',
    'item2',
]

Create requirements.txt with pip

pip freeze > requirements.txt

Debug one-liner

import pdb; pdb.set_trace()

Show global vars in pdb

globals()

Loop in pdb

If you want to be able to test an if statement (for example) in pdb, you’ll need to run this first:

!import code; code.interact(local=vars())

Resource: https://stackoverflow.com/questions/5967241/how-to-execute-multi-line-statements-within-pythons-own-debugger-pdb

Code Introspection

The ability to examine classes, functions and keywords to get a better sense for what they do.

Show available methods for an object

dir(object)

Show object type

type(object)

Resource: https://jobtensor.com/Tutorial/Python/en/Code-Introspection

Remove \n and extra quotes from an object

obj.rstrip().replace('"', '')

Remove newlines and carriage returns

'blablabla\r\n'.strip()

Check if current user is root, exit if not

def check_root():
    if not os.geteuid() == 0:
        sys.exit('This script must be run as root!')

Run remote command using ssh on an aws instance

import paramiko

k = paramiko.RSAKey.from_private_key_file("/path/to/pem/file")
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect( hostname = "<ec2 hostname>", username = "<username>", pkey = k )

stdin , stdout, stderr = c.exec_command("<command to run>")
print("stdout: " + stdout.read().decode('utf-8'))
print("stderr" + stderr.read().decode('utf-8'))
c.close()

Resource: http://diego-pacheco.blogspot.com/2016/05/having-fun-with-boto-3.html

Auto enable virtualenv for a directory

Use https://github.com/kennethreitz/autoenv, which can be installed via brew, pip, etc.

Once it’s installed, add this line to your bash_rc or zshrc or whatever (the path will vary based on which installation method you used): source /usr/local/opt/autoenv/activate.sh

Once this is done, you simply drop a .env file into the directory which has a virtualenv, that should look like this: source .venv/bin/activate

Now whenever you cd into this directory, virtualenv will automatically be activated. You will have to deactivate manually when you leave though.


Standards

This is a great guide for writing python code in general.

The Google guide is also quite helpful.

Commenting

A nice example can be found here for google style.


Pipenv

Install pipenv

pip3 install -U pipenv

Resource: https://github.com/pypa/pipenv/issues/1781

Set up pipenv for a project with python version 3.6.5

pipenv --python 3.6.5

Install a dependency

pipenv install <package>

Lock the dependencies

You want to do this before a release:

pipenv lock

Run a command from the virtualenv for a project

pipenv run python -V
pipenv run python -c 'print("A" * 32)'

Activate the virtualenv

pipenv shell

Deactivate the virtualenv

CTRL-d or type exit

Remove the virtualenv

pipenv --rm

Import from requirements.txt

pipenv install -r requirements.txt

Resources:


Pyenv

Install pyenv on macOS

brew install pyenv
echo 'PATH=$(pyenv root)/shims:$PATH' >> ~/.zshrc

Install version of python

PY_VER=3.8.12
pyenv install "${PY_VER}"

Set version of python for a directory

PY_VER=3.8.12
pyenv local "${PY_VER}"

Show versions of python on the system

pyenv versions

Set global python version

PY_VER=3.8.12
pyenv global "${PY_VER}"

Resource: https://opensource.com/article/20/4/pyenv


List licenses of dependencies

pip install pip-licenses

Get first occurrence of a char in a string

The index() function gets the index of the first occurrence of a char starting from the beginning of a string and returns it.

The rindex() function gets the index of the first occurrence of a char starting from the end of a string and returns it.

>>> s = "dedjdedl"
>>> s.index('d')
0
>>> s.rindex('d')
6

Combine two lists with zip

>>> l1 = ['a','b','c']
>>> l2 = [1,2,3]
>>> print(list(zip(l1,l2)))
[('a', 1), ('b', 2), ('c', 3)]

Combine two lists together and iterate over them

combined = zip(list1, list2)
for list1, list2 in combined:
    print(list1)
>>> a = [[1,2],[3,4],[5,6]]
>>> print(list(zip(*a)))
[(1, 3, 5), (2, 4, 6)]

Data types and examples

Complexity chart

set

Store unordered collections of unique elements

>>> items = [1,5,2,2,3,5,1]
>>> set(items)
{1, 2, 3, 5}

Iterate through list with idx and value

for idx, val in enumerate(list_of_stuff):
    print(idx)
    print(val)

Iterate through range with an incrementor of 100

for i in range(start, end, 100):

Resource: https://stackoverflow.com/questions/4930404/how-do-get-more-control-over-loop-increments-in-python

Random number in a range

import random
print(random.randint(1,101))

Search and replace text inline in a file

with fileinput.FileInput("file.txt", inplace=True) as file:
        for line in file:
            print(line.replace('stringtoreplace', 'replacementstring'), end='')

https://stackoverflow.com/questions/17140886/how-to-search-and-replace-text-in-a-file-using-python

Generate random id w/ lowercase letters and numbers

def id_generator(size=20, chars=string.ascii_lowercase + string.digits):
    return ''.join(random.choice(chars) for _ in range(size))

Open new tab and run ls with above run_cmd()

run_cmd(f"gnome-terminal --tab --active -- bash -c 'ls ; exec bash'")

Resource: https://askubuntu.com/questions/968032/option-e-is-deprecated-and-might-be-removed-in-a-later-version-of-gnome-termi

Break up long string

print('This is a really long string' \
        'and it should be broken up')

Run simple http webserver from code

web_lport = 8000

def start_webserver():
    url = f"localhost:{web_lport}"

    handler = http.server.SimpleHTTPRequestHandler
    httpd = socketserver.TCPServer(("", web_lport), handler)
    print(f"Web server starting on port {web_lport}")

    server_process = multiprocessing.Process(target=httpd.serve_forever)
    server_process.daemon = True
    server_process.start()

    return server_process

server_process = start_webserver()
# Do stuff
print(f"Closing web server running on port {web_lport}")
server_process.terminate()

Run SimpleHTTPServer as a background job

if [[ "$(pgrep tmux)" ]]; then
  kill -9 `top -n 1 | pgrep tmux`
fi

tmux new -s web_server -d 'python -m SimpleHTTPServer'

sleep 1
python do_things.py

Resources: https://superuser.com/questions/927544/run-command-in-detached-tmux-session-and-log-console-output-to-file https://gist.github.com/pwittchen/531c0bed8a20c1f06231

Append to file

with open("test.txt", "a") as myfile:
    myfile.write("appended text")

Resource: https://stackoverflow.com/questions/4706499/how-do-you-append-to-a-file-in-python

Multi-line string

s = """ this is a very
        long string if I had the
        energy to type more and more ..."""

Resource: https://stackoverflow.com/questions/10660435/pythonic-way-to-create-a-long-multi-line-string


Requests

Include hex chars

A hex character can be included by doing the following (observe the \x09):

headers = {
 'Host': host+':'+port,
 'Content-Length': '85',
 'Transfer\x09-Encoding': 'chunked',
}

Another example:

data = '0\x0d\x0a\x0d\x0a' \
    'GET /' \
    '/ HTTP/1.1\x0d\x0aHost: ' + host + ':' + port'

Override the content-length

This is done by using a prepared request. In this example, the content-length will be set to 85, no matter what:

s = requests.Session()
req = requests.Request("POST", protocol+'://'+host+':'+port,
                       headers=headers, data=data)
prepped = req.prepare()
prepped.headers['Content-Length'] = 85
s.send(prepped)

Intercept request with a proxy

This is useful for intercepting requests coming from a piece of malware that’s python-based.

proxies = {"http": "http://127.0.0.1:8090", "https": "http://127.0.0.1:8090"}

response = requests.post(target_url, headers=headers, json=data, verify=False, timeout=15,
proxies=proxies)

Resource: https://www.th3r3p0.com/random/python-requests-and-burp-suite.html

Run a command from the command line

python -c 'print "A" * 32'

Copy output using pbcopy in OSX:

python -c "print('b'*64)" | pbcopy

Dictionary Notes

Add value to list in dictionary if it doesn’t exist; otherwise append the value to the existing list.

if not dict.has_key(key):
    dict[key] = [value]
else:
    dict[key].append(value)

Create empty dict

dict = {}

Assign incrementor to key

In this instance, we’ll say that c is a random character, and we’re currently counting the number of instances of this character in a string.

dict[c] = 1

Increment incrementor

dict[c] += 1

Just use https://pypi.python.org/pypi/PrettyTable and save yourself a headache.

from prettytable import PrettyTable
def output_dict_to_table(in_dict):
        """
        Print an input dictionary as a table

        Usage:
        output_dict_to_table({'Key': ['Value'], 'Key2': ['Value2', 'Value3']})
        """
        t = PrettyTable(['Key', 'Value'])
        for k, v in in_dict.items():
            t.add_row([k, v])
        print t

JSON from output of running a program to dict

This example uses the run_cmd function above.

# Output is bytes; convert to string with the .decode('utf-8')
output = run_cmd('terraform output -json').decode('utf-8')
tf_json = json.loads(output)

The tf_json object will be properly set up as a python dictionary.

Resources:

List of chars or string to dict with counter

This dictionary will have counters for each letter. If there are duplicate letters, the counter will increment, i.e.

['h','e','l','l','o']

will return the following:

{'l': 2, 'h': 1, 'e': 1, 'o': 1}

The code to do this is as follows:

from collections import Counter
print(Counter(['h','e','l','l','o']))

Note that you can also use this with a string, i.e.

from collections import Counter
print(Counter('hello'))

Dictionary that has a dictionary as its value

This particular example will output a dictionary that has a word as its key and a dictionary as the value that maps each letter of the word to the number of times it appears.

from collections import Counter
words = ['hi', 'bye', 'toodles']
word_to_chars = {}
for word in words:
    word_to_chars[word] = Counter(word)
print(word_to_chars)

# {'bye': Counter({'y': 1, 'b': 1, 'e': 1}), 'hi': Counter({'i': 1, 'h': 1}), 'toodles':
Counter({'o': 2, 'e': 1, 'd': 1, 'l': 1, 's': 1, 't': 1})}

Check if value in a list of dictionaries

def check_if_in_list_of_dict(sample_dict, value):
    """Check if given value exists in list of dictionaries """
    for elem in sample_dict:
        if value in elem.values():
            return True
    return False

if check_if_in_list_of_dict(dict_name, 'value'):
    print('yep')

Resource: https://thispointer.com/python-check-if-value-exists-in-list-of-dictionaries/


Selenium

Open new tab

# Open new tab
driver.execute_script("window.open('');")
# Switch to new tab
driver.switch_to.window(driver.window_handles[1])
# Load stackoverflow
driver.get("http://stackoverflow.com")
# Wait for page to load
time.sleep(3)
# Close the new tab
driver.close()

Switch back to the first tab

driver.switch_to.window(driver.window_handles[0])

Resource: https://stackoverflow.com/questions/28431765/open-web-in-new-tab-selenium-python

Get page source

driver.page_source

Resource: https://pythonbasics.org/selenium-get-html/

Get all cookies

driver.get_cookies()

Get a particular cookie’s value

driver.get_cookie('cookie_name')['value']

Integrate with browsermob and Chrome

In the event you need to be able to get request and/or response data, you’ll probably want to look at using a proxy like browsermob.

A fully working example can be found here.

Integrate with browsermob and Firefox

from selenium import webdriver
from browsermobproxy import Server
import time

server = Server(
    path="./assets/browsermob-proxy-2.1.4/bin/browsermob-proxy", options={'port':
8095})
server.start()
proxy = server.create_proxy()

profile = webdriver.FirefoxProfile()
selenium_proxy = proxy.selenium_proxy()
profile.set_proxy(selenium_proxy)
driver = webdriver.Firefox(firefox_profile=profile)

proxy.new_har('req', options={'captureHeaders': True, 'captureContent': True})
driver.get("https://www.google.com")
print(proxy.har)

server.stop()
driver.quit()

Resources:

Click XPath Element

Using Chrome, I do the following to get the information I need to trigger an event-driven dropdown and then click one of the listed items:

  1. Get to the point where the menu is presented, stop with pdb
  2. Right click the element we want to click, Inspect
  3. Right click that element, click Copy and then Copy XPath
  4. Trigger the click event with selenium:
driver.find_element_by_xpath('<copied xpath>').click()

Continue on in this manner until you have the desired behavior.

Parse table from page

import pandas as pd
table = pd.read_html(driver.page_source)
# Print all values associated with a particular column
df = table
print(df.<column_name>)
# for example:
# print(df.IP)

Resources: https://beenje.github.io/blog/posts/parsing-html-tables-in-python-with-pandas/ https://stackoverflow.com/questions/6325216/parse-html-table-to-python-list

Click element based on text

This is one option:

driver.find_element_by_xpath(
      "//*[contains(text(), 'text to match')]")

This is another (specifically for a button):

driver.find_element_by_xpath(
      "//button[normalize-space()='text to match']").click()

Resources: https://www.guru99.com/using-contains-sbiling-ancestor-to-find-element-in-selenium.html https://stackoverflow.com/questions/12323403/how-do-i-find-an-element-that-contains-specific-text-in-selenium-webdriver-pyth https://stackoverflow.com/questions/49906237/how-to-find-button-with-selenium-by-its-text-inside-python

Send Backspace to an element

from selenium.webdriver.common.keys import Keys
driver.find_element_by_name('elementName').send_keys(Keys.BACK_SPACE)

Wait for element in page to load

from selenium.webdriver.support import expected_conditions as EC
# wait for 10 seconds for the page to load
delay = 10
try:
    WebDriverWait(driver, delay).until(
       EC.presence_of_element_located((By.ID, 'name of id associated with element
you want')))
except TimeoutException:
    sys.exit("Loading the page took too much time, exiting!")

Argparse

Argparse is great for when you need to use CLI arguments - it’s clean and can be implemented with minimal fuss.

import argparse

def parse_arg():
    parser = argparse.ArgumentParser(description='Do stuff')
    parser.add_argument("-a", '--argument', required=True, help='description of what
your awesome code does')
    return parser.parse_args()
    # Return value of a single argument if you don't have multiple ones:
    #return parser.parse_args().arg

For an example of how I’ve used this previously, check this page out: https://github.com/l50/base64_rot13_decoder

Resource: https://stackoverflow.com/questions/4188467/how-to-check-if-an-argument-from-commandline-has-been-set

Mutually exclusive options

import argparse

def __parse_args__():
    parser = argparse.ArgumentParser(
        description='Do stuff.')
    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument('-f', action=.....)
    group.add_argument('-d', type=bool, help='do a boolean thing')
    return parser.parse_args()

Resource: https://stackoverflow.com/questions/11154946/require-either-of-two-arguments-using-argparse

Add a debug mode

If you want to have a flag that defaults to true (so you don’t have to specify it as an argument), do the following:

parser.add_argument('-d', dest="debug", action='store_true',
   help='debug mode')

Resource: https://docs.python.org/3/library/argparse.html

Check if port is open

import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = sock.connect_ex(('127.0.0.1',80))
if result == 0:
   print "Port is open"
else:
   print "Port is not open"
sock.close()

Resource: https://stackoverflow.com/questions/19196105/how-to-check-if-a-network-port-is-open-on-linux

Show output as command runs

status_code = subprocess.call(
    ['ansible-playbook', 'site.yml', '-i', 'hosts'])
# status_code = 0 is an indicator of running the command successfully

Resource: https://www.cyberciti.biz/faq/python-run-external-command-and-get-output/

Send email to multiple recipients

import smtplib

from email.mime.text import MIMEText

smtp_user = 'youruser@yourdomain.com'
smtp_pw = 'YEP PUT THAT HERE'

sender = ['yoursender@domain.com']
recipients = ['person1@gmail.com', 'person2@gmail.com']

msg = MIMEText('Sweet text br0')
msg['Subject'] = "Awesome Subject
msg['From']    = ','.join(sender)
msg['To']      = ','.join(recipients)

s = smtplib.SMTP('smtp.mailgun.org', 587)

s.login(smtp_user, smtp_pw)
s.sendmail(sender, recipients, msg.as_string())
s.quit()

Resource: https://stackoverflow.com/questions/8856117/how-to-send-email-to-multiple-recipients-using-python-smtplib

Send email with CC

import smtplib

from email.mime.text import MIMEText

smtp_user = 'youruser@yourdomain.com'
smtp_pw = 'YEP PUT THAT HERE'

sender = ['yoursender@domain.com']
recipient = ['person1@gmail.com']
cc_emails = ['person2@gmail.com', 'person3@gmail.com']

msg = MIMEText('Sweet text br0')
msg['Subject'] = "Awesome Subject
msg['From']    = ','.join(sender)
msg['To']      = ','.join(recipient)
msg['Cc']      = ','.join(cc_emails)

s = smtplib.SMTP('smtp.mailgun.org', 587)

s.login(smtp_user, smtp_pw)
s.sendmail(sender, recipient+cc_emails, msg.as_string())
s.quit()

Resources: https://stackoverflow.com/questions/49062924/send-e-mail-to-multiple-cc-and-multiple-to-recipients-simultaneously-using-pytho https://stackoverflow.com/questions/1546367/python-how-to-send-mail-with-to-cc-and-bcc

Git

Clone

git.Repo.clone_from(f"https://github.com/{self.user_name}/{self.repo_name}.git",
f"./{self.repo_name}")

Add/commit/push via http git

os.environ['GIT_USERNAME'] = config.username
os.environ['GIT_PASSWORD'] = config.passwordrepo_path = 'repo_name'
try:
    repo = git.Repo(repo_path)
    repo.git.add(update=True)
    repo.index.commit('Commit Message')
    origin = repo.remote(name='origin')
    origin.push()
    print("Pushed the latest commit to the repo!")
except Exception as e:
    print(f"Failed to push the new commit due to {e}")
os.unsetenv('GIT_USERNAME')
os.unsetenv('GIT_PASSWORD')

Resources:


Generate hashed password w/ salt

from typing import Dict
import binascii
import hashlib
import hmac
import secrets
import string
import uuid

def gen_pw(size: str) -> str:
    return ''.join((secrets.choice(string.ascii_letters + string.digits + string.punctuation)
for i in range(size)))

def create_pw_hash(size: int) -> Dict[bytes, bytes]:
    """
    Hash the provided password with a randomly-generated salt and return the
    salt and hash to store in the database.
    """
    salt = secrets.token_bytes(32).hex().upper()
    password = gen_pw(size)
    key = hashlib.sha256(password.encode('utf-8') + salt.encode('utf-8'))
    return { 'salt': salt, 'key': key.hexdigest(), 'pw': password }

def is_correct_password(salt: str, pw_hash: str, password: str) -> bool:
    """
    Given a previously-stored salt and hash, and a password provided by a user
    trying to log in, check whether the password is correct.
    """
    return hmac.compare_digest(
        pw_hash,
        hashlib.sha256(password.encode('utf-8') + salt.encode('utf-8')).hexdigest()
    )

output = create_pw_hash(32)
assert(is_correct_password(output['salt'], output['key'], output['pw']))

Resources:

Get words from a web page into a list

strings_from_html = ' '.join(BeautifulSoup(html_code, "html.parser").stripped_strings)
words = strings_from_html.split()

Resource: https://stackoverflow.com/questions/328356/extracting-text-from-html-file-using-python

Get top three most common strings in a dictionary

from collections import Counter
stuff = {'bla':4,'hey':6,'chicken':2,'bob':10}
counter = Counter(stuff)
print(counter.most_common(3))

Resource: https://www.geeksforgeeks.org/python-program-to-find-the-highest-3-values-in-a-dictionary/

String to byte string

# Random string
a = '6f8FGlE(u'
str.encode(a)

Byte string to string

# Random string
a = b'6f8FGlE(u'
a.decode('utf-8')

Resource: https://stackoverflow.com/questions/606191/convert-bytes-to-a-string

Hex string to byte string

hex_string = '6465616462656566'
bytes.fromhex(hex_string)
# b'deadbeef'

Byte string to hex

byte_string = b"deadbeef"
byte_string.hex()
# '6465616462656566'

Resource: https://stackoverflow.com/questions/5649407/hexadecimal-string-to-byte-array-in-python

Get hrefs in a site

from bs4 import BeautifulSoup

soup = BeautifulSoup(input, 'html.parser')
for a in soup.find_all('a', href=True):
    if a.text:
        print(a['href'])

Resources: https://stackoverflow.com/questions/43814754/python-beautifulsoup-how-to-get-href-attribute-of-a-element/43814994

Get home dir

Python 3.5+:

from pathlib import Path
home = str(Path.home())

Alternative:

from os.path import expanduser
home = expanduser("~")

Resource: https://stackoverflow.com/questions/4028904/how-to-get-the-home-directory-in-python

Simple CLI

import argparse
# Initialize parser
parser = argparse.ArgumentParser()
# Adding optional argument
parser.add_argument('--foo', type=str, help='foo help')
# Read arguments from command line
args = parser.parse_args()

Reference your input in your code with:

print(args.foo)

Resources:

Get path of home directory

import os
print(os.path.expanduser('~')

Resource: https://www.kite.com/python/examples/4284/os-get-the-path-of-the-home-directory

Copy file

import shutil

# Source path
source = "/home/User/Documents/file.txt"

# Destination path
destination = "/home/User/Documents"

try:
    shutil.copyfile(source, destination)
    print("File copied successfully.")

# If source and destination are same
except shutil.SameFileError:
    print("Source and destination represents the same file.")

# If destination is a directory.
except IsADirectoryError:
    print("Destination is a directory.")

# If there is any permission issue
except PermissionError:
    print("Permission denied.")

# For other errors
except:
    print("Error occurred while copying file.")

Resource: https://www.geeksforgeeks.org/python-shutil-copyfile-method/

Change CWD without absolute path

import os

abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
os.chdir(dname)

Resource: https://stackoverflow.com/questions/1432924/python-change-the-scripts-working-directory-to-the-scripts-own-directory

Create file and any parent directories

This will do the same thing as mkdir -p:

import os, os.path

def safe_open_w(path):
    ''' Open "path" for writing, creating any parent directories as needed.
    '''
    os.makedirs(os.path.dirname(path), exist_ok=True)
    return open(path, 'w')

with safe_open_w('/Users/bill/output/output-text.txt') as f:
    f.write(...)

Resource: https://stackoverflow.com/questions/23793987/write-file-to-a-directory-that-doesnt-exist

Create a salted password hash for /etc/shadow

Run the following to generate the hash on your linux machine:

python3 -c 'import crypt; print(crypt.crypt("sickpasswordbro!", crypt.mksalt(crypt.METHOD_SHA512)))'

Resource: https://serverfault.com/questions/330069/how-to-create-an-sha-512-hashed-password-for-shadow