obfuscate.py - For obfuscating Python code

A collection of functions for obfuscating code.

pyminifier.obfuscate.apply_obfuscation(source)[source]

Returns ‘source’ all obfuscated.

pyminifier.obfuscate.find_obfuscatables(tokens, obfunc, ignore_length=False)[source]

Iterates over tokens, which must be an equivalent output to what tokenize.generate_tokens() produces, calling obfunc on each with the following parameters:

  • tokens: The current list of tokens.
  • index: The current position in the list.

obfunc is expected to return the token string if that token can be safely obfuscated or one of the following optional values which will instruct find_obfuscatables() how to proceed:

  • ‘__skipline__’ Keep skipping tokens until a newline is reached.
  • ‘__skipnext__’ Skip the next token in the sequence.

If ignore_length is True then single-character obfuscatables will be obfuscated anyway (even though it wouldn’t save any space).

pyminifier.obfuscate.insert_in_next_line(tokens, index, string)[source]

Inserts the given string after the next newline inside tokens starting at tokens[index]. Indents must be a list of indentation tokens that will preceeed the insert (can be an empty list).

pyminifier.obfuscate.obfuscatable_class(tokens, index, **kwargs)[source]

Given a list of tokens and an index (representing the current position), returns the token string if it is a class name that can be safely obfuscated.

pyminifier.obfuscate.obfuscatable_function(tokens, index, **kwargs)[source]

Given a list of tokens and an index (representing the current position), returns the token string if it is a function or method name that can be safely obfuscated.

pyminifier.obfuscate.obfuscatable_variable(tokens, index, ignore_length=False)[source]

Given a list of tokens and an index (representing the current position), returns the token string if it is a variable name that can be safely obfuscated.

Returns ‘__skipline__’ if the rest of the tokens on this line should be skipped. Returns ‘__skipnext__’ if the next token should be skipped.

If ignore_length is True, even variables that are already a single character will be obfuscated (typically only used with the --nonlatin option).

pyminifier.obfuscate.obfuscate(module, tokens, options, name_generator=None, table=None)[source]

Obfuscates tokens in-place. options is expected to be the options variable passed through from pyminifier.py.

module must be the name of the module we’re currently obfuscating

If name_generator is provided it will be used to obtain replacement values for identifiers. If not, a new instance of

If table is given (should be a list containing a single dictionary), it will be used to perform lookups of replacements and any new replacements will be added to it.

pyminifier.obfuscate.obfuscate_builtins(module, tokens, name_generator, table=None)[source]

Inserts an assignment, ‘<obfuscated identifier> = <builtin function>’ at the beginning of tokens (after the shebang and encoding if present) for every Python built-in function that is used inside tokens. Also, replaces all of said builti-in functions in tokens with each respective obfuscated identifer.

Obfuscated identifier names are pulled out of name_generator via next().

If table is provided, replacements will be looked up there before generating a new unique name.

pyminifier.obfuscate.obfuscate_class(tokens, index, replace, replacement, *args)[source]

If the token string (a class) inside tokens[index] matches replace, return replacement.

pyminifier.obfuscate.obfuscate_function(tokens, index, replace, replacement, *args)[source]

If the token string (a function) inside tokens[index] matches replace, return replacement.

pyminifier.obfuscate.obfuscate_global_import_methods(module, tokens, name_generator, table=None)[source]

Replaces the used methods of globally-imported modules with obfuscated equivalents. Updates tokens in-place.

module must be the name of the module we’re currently obfuscating

If table is provided, replacements for import methods will be attempted to be looked up there before generating a new unique name.

pyminifier.obfuscate.obfuscate_unique(tokens, index, replace, replacement, *args)[source]

If the token string (a unique value anywhere) inside tokens[index] matches replace, return replacement.

Note

This function is only for replacing absolutely unique ocurrences of replace (where we don’t have to worry about their position).

pyminifier.obfuscate.obfuscate_variable(tokens, index, replace, replacement, right_of_equal, inside_parens, inside_function)[source]

If the token string inside tokens[index] matches replace, return replacement. right_of_equal, and inside_parens are used to determine whether or not this token is safe to obfuscate.

pyminifier.obfuscate.obfuscation_machine(use_unicode=False, identifier_length=1)[source]

A generator that returns short sequential combinations of lower and upper-case letters that will never repeat.

If use_unicode is True, use nonlatin cryllic, arabic, and syriac letters instead of the usual ABCs.

The identifier_length represents the length of the string to return using the aforementioned characters.

pyminifier.obfuscate.remap_name(name_generator, names, table=None)[source]

Produces a series of variable assignments in the form of:

<obfuscated name> = <some identifier>

for each item in names using name_generator to come up with the replacement names.

If table is provided, replacements will be looked up there before generating a new unique name.

pyminifier.obfuscate.replace_obfuscatables(module, tokens, obfunc, replace, name_generator, table=None)[source]

Iterates over tokens, which must be an equivalent output to what tokenize.generate_tokens() produces, replacing the given identifier name (replace) by calling obfunc on each token with the following parameters:

  • module: The name of the script we’re currently obfuscating.
  • tokens: The current list of all tokens.
  • index: The current position.
  • replace: The token string that we’re replacing.
  • replacement: A randomly generated, unique value that will be used to replace, replace.
  • right_of_equal: A True or False value representing whether or not the token is to the right of an equal sign. Note: This gets reset to False if a comma or open paren are encountered.
  • inside_parens: An integer that is incremented whenever an open paren is encountered and decremented when a close paren is encountered.
  • inside_function: If not False, the name of the function definition we’re inside of (used in conjunction with keyword_args to determine if a safe replacement can be made).

obfunc is expected to return the token string if that token can be safely obfuscated or one of the following optional values which will instruct find_obfuscatables() how to proceed:

  • ‘__open_paren__’ Increment the inside_parens value
  • ‘__close_paren__’ Decrement the inside_parens value
  • ‘__comma__’ Reset the right_of_equal value to False
  • ‘__right_of_equal__’ Sets the right_of_equal value to True

Note: The right_of_equal and the inside_parens values are reset whenever a NEWLINE is encountered.

When obfuscating a list of files, table is used to keep track of which obfuscatable identifiers are which inside each resulting file. It must be an empty dictionary that will be populated like so:

{orig_name: obfuscated_name}

This table of “what is what” will be used to ensure that references from one script/module that call another are kept in sync when they are replaced with obfuscated values.