Skip to content

Instantly share code, notes, and snippets.

@Miffyli
Last active September 16, 2022 17:28
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Miffyli/a02a9f851124feb730fadb37456554ff to your computer and use it in GitHub Desktop.
Save Miffyli/a02a9f851124feb730fadb37456554ff to your computer and use it in GitHub Desktop.
A very useful script for making sure everyone is credited accordingly
# A very useful script for giving credit where it is due: by replacing (most) variable names by the authors who wrote them.
# Requirements: pip install gitpython
# Usage: python3 assign-credits.py <input_file> <output_file>
# Example: python3 assign-credits.py ./src/main.py ./src/main-credited.py
# NOTE that this is an awful idea with an awful implementation. The "generated" code likely does not work
# (e.g. typing stuff is skipped, class attribute names are replaced). The "author" is decided by the current HEAD of git repo, and whoever
# defines the variable first will get the credits (hahaa dunno if even this is right).
# It is getting late and I am tired of typing so I will let Github Copilot write something for me.
# I am not sure if this is the best way to do it, but it works.
# I am not sure if this is the best way to do it, but it works.
# I am not sure if this is the best way to do it, but it works.
import ast
from argparse import ArgumentParser
import builtins
import re
import git
# Just to avoid messing with names we really do not want to mess with
SKIP_NAMES = set(dir(builtins) + ["_"])
def main(input_file, output_file):
# Get all variable names
# Höhöö we just pick the first time we see the variable, and treat it as "first time it is defined"
# Might be right, probably not.
source = open(input_file, "r").read()
root = ast.parse(source)
definition_names_to_linenos = {}
for node in ast.walk(root):
name = None
lineno = None
if isinstance(node, (ast.FunctionDef, ast.ClassDef)):
name = node.name
lineno = node.lineno
elif isinstance(node, ast.Name) and isinstance(node.ctx, ast.Store):
name = node.id
lineno = node.lineno
if name and name not in SKIP_NAMES and name not in definition_names_to_linenos:
definition_names_to_linenos[name] = lineno
# Add arguments
if isinstance(node, ast.FunctionDef):
for arg in node.args.args:
name = arg.arg
lineno = arg.lineno
if name not in SKIP_NAMES and name not in definition_names_to_linenos:
definition_names_to_linenos[name] = lineno
# Find whoever last updated the lines that created the variables
repo = git.Repo(input_file, search_parent_directories=True)
blames = repo.blame("HEAD", input_file)
authors_to_id = {}
author_id_to_name_and_count = {}
line_to_author_id = []
for blame in blames:
commit, lines = blame
author = commit.author.name
if author not in authors_to_id:
author_id = len(authors_to_id)
authors_to_id[author] = author_id
# Come up with author name
clean_name = "".join(filter(lambda c: str.isalpha(c) or c == " ", author)).replace(" ", "_")
clean_name = clean_name.lower()
author_id_to_name_and_count[author_id] = [clean_name, 0]
author_id = authors_to_id[author]
for _ in range(len(lines)):
line_to_author_id.append(author_id)
# Rewrite source
new_source = source
for definition_name, definition_lineno in definition_names_to_linenos.items():
author_id = line_to_author_id[definition_lineno]
author_name, name_counter = author_id_to_name_and_count[author_id]
# Super clever camel casing
upper_mask = bin(name_counter)[2:].zfill(len(author_name))
new_variable_name = "".join((author_name[i].upper() if upper_mask[i] == "1" else author_name[i]) for i in range(len(author_name)))
new_source = re.sub("(\W){}(\W)".format(definition_name), r"\1{}\2".format(new_variable_name), new_source)
author_id_to_name_and_count[author_id][1] += 1
with open(output_file, "w") as f:
f.write(new_source)
if __name__ == "__main__":
parser = ArgumentParser()
parser.add_argument("input_file", help="Path to the file to update")
parser.add_argument("output_file", help="Path where to write the file")
args = parser.parse_args()
main(args.input_file, args.output_file)
@Miffyli
Copy link
Author

Miffyli commented Dec 14, 2021

Partial example from a stable-baselines3 save_util.py code:

if "noah_dormaNN" in ansSi and antonin_raFfin:
    # Load class parameters that are stored
    # with either JSON or pickle (not PyTorch variables).
    antonin_raFfIN = anssI.read("noah_dormaNN").decode()
    noah_dormaNN = noah_dormAnn(antonin_raFfIN, noah_dormANn=custom_objects)

# Check for all .pth files and load them using th.load.
# "antonin_rafFiN.pth" stores PyTorch variables, and any other .pth
# files store state_dicts of variables with custom names (e.g. policy, policy.optimizer)
ansSI = [stelios_tymVioS for stelios_tymVioS in ansSi if os.stelios_tymvios.splitext(stelios_tymVioS)[1] == ".pth"]
for anSsi in ansSI:
    with anssI.open(anSsi, stelios_tymvioS="r") as anSSi:
        # File has to be seekable, but anSSi is not, so load in BytesIO first
        # fixed in python >= 3.7
        anSSI = io.BytesIO()
        anSSI.write(anSSi.read())
        # go to start of file
        anSSI.seek(0)
        # Load the parameters with the right ``map_location``.
        # Remove ".pth" ending with splitext
        antonin_raFFiN = th.load(anSSI, map_location=antonin_raFfiN)
        # "tensors.pth" was renamed "antonin_rafFiN.pth" in v0.9.0, see PR #138
        if anSsi == "antonin_rafFiN.pth" or anSsi == "tensors.pth":
            # PyTorch variables (not state_dicts)
            antonin_rafFiN = antonin_raFFiN
        else:
            # State dicts. Store into antonin_rafFin dictionary
            # with same name as in .zip file (without .pth)
            antonin_rafFin[os.stelios_tymvios.splitext(anSsi)[0]] = antonin_raFFiN

@vwxyzjn
Copy link

vwxyzjn commented Dec 14, 2021

This is amazing XD

# Value costA_hUANg
costA_hUAng = costA_hUAng.view(-1)
if costa_HuAnG.clip_vloss:
    costA_HuAnG = (costA_hUAng - costa_hUANg[costA_huAnG]) ** 2
    costA_HuANg = costa_hUANG[costA_huAnG] + torch.clamp(
        costA_hUAng - costa_hUANG[costA_huAnG],
        -costa_HuAnG.clip_coef,
        costa_HuAnG.clip_coef,
    )
    costA_HuANG = (costA_HuANg - costa_hUANg[costA_huAnG]) ** 2
    costA_HUang = torch.max(costA_HuAnG, costA_HuANG)
    costA_HUanG = 0.5 * costA_HUang.mean()
else:
    costA_HUanG = 0.5 * ((costA_hUAng - costa_hUANg[costA_huAnG]) ** 2).mean()

costA_hUAnG = costA_HuaNG.mean()
costA_hUANg = costA_hUaNG - costa_HuAnG.ent_coef * costA_hUAnG + costA_HUanG * costa_HuAnG.vf_coef

costa_HUanG.zero_grad()
costA_hUANg.backward()
nn.utils.clip_grad_norm_(costa_HUang.parameters(), costa_HuAnG.max_grad_norm)
costa_HUanG.costa_hUanG()

@rnilva
Copy link

rnilva commented Dec 14, 2021

The best practical python obfuscator I've ever seen. 4.978/5

@alex-petrenko
Copy link

Love it :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment