Skip to content

Instantly share code, notes, and snippets.

@Toliak
Last active February 14, 2023 10:16
Show Gist options
  • Select an option

  • Save Toliak/773bb957693fdbde84c71d39cc9d384c to your computer and use it in GitHub Desktop.

Select an option

Save Toliak/773bb957693fdbde84c71d39cc9d384c to your computer and use it in GitHub Desktop.

Revisions

  1. Toliak revised this gist Apr 9, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion shame.py
    Original file line number Diff line number Diff line change
    @@ -66,7 +66,7 @@ def with_shame(func_or_code):


    def print_shame():
    print('ахахахах')
    print('it works lmao bottom text')


    @with_shame
  2. Toliak revised this gist Apr 9, 2022. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions shame.py
    Original file line number Diff line number Diff line change
    @@ -12,7 +12,7 @@ def _patch_code(code: types.CodeType):
    names_list = list(code.co_names)

    # I believe each python bytecode command has 2 bytes
    # Range решил не работать с 3мя аргументами....
    # Range is not working successfully with 3 arguments (what)
    for i in range(0, len(code.co_code) // 2):
    i *= 2
    opcode, oparg = struct.unpack_from('BB', code_bytarray, i)
    @@ -31,7 +31,7 @@ def _patch_code(code: types.CodeType):


    def _make_code(code, codestring, names):
    # Благополучно спер отсюда
    # Successfully snatched from
    # https://github.com/snoack/python-goto/blob/master/goto.py#L45
    args = [
    code.co_argcount, code.co_nlocals, code.co_stacksize,
  3. Toliak revised this gist Apr 9, 2022. 1 changed file with 3 additions and 0 deletions.
    3 changes: 3 additions & 0 deletions shame.py
    Original file line number Diff line number Diff line change
    @@ -71,6 +71,9 @@ def print_shame():

    @with_shame
    def test():
    """
    Will be compiled and executed successfully
    """
    print('> Ok')
    shame
    return 1
  4. Toliak revised this gist Apr 9, 2022. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion shame.py
    Original file line number Diff line number Diff line change
    @@ -78,4 +78,3 @@ def test():

    if __name__ == '__main__':
    test()
    pass
  5. Toliak created this gist Apr 5, 2022.
    81 changes: 81 additions & 0 deletions shame.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,81 @@
    import functools
    import struct
    import types
    import dis


    def _patch_code(code: types.CodeType):
    # Call function with 0 arguments
    function_call_bytearray = bytearray(dis.opmap['CALL_FUNCTION'].to_bytes(1, byteorder='little') + b'\x00')

    code_bytarray = bytearray(code.co_code)
    names_list = list(code.co_names)

    # I believe each python bytecode command has 2 bytes
    # Range решил не работать с 3мя аргументами....
    for i in range(0, len(code.co_code) // 2):
    i *= 2
    opcode, oparg = struct.unpack_from('BB', code_bytarray, i)
    if dis.opname[opcode] != 'LOAD_GLOBAL':
    continue

    global_name = names_list[oparg]
    if global_name != 'shame':
    continue

    names_list[oparg] = 'print_shame'
    # Insert CALL_FUNCTION after LOAD_GLOBAL 'shame'
    code_bytarray[i + 2:i + 2] = function_call_bytearray

    return _make_code(code, bytes(code_bytarray), tuple(names_list))


    def _make_code(code, codestring, names):
    # Благополучно спер отсюда
    # https://github.com/snoack/python-goto/blob/master/goto.py#L45
    args = [
    code.co_argcount, code.co_nlocals, code.co_stacksize,
    code.co_flags, codestring, code.co_consts,
    names, code.co_varnames, code.co_filename,
    code.co_name, code.co_firstlineno, code.co_lnotab,
    code.co_freevars, code.co_cellvars
    ]

    try:
    args.insert(1, code.co_kwonlyargcount) # PY3
    except AttributeError:
    pass

    return types.CodeType(*args)


    def with_shame(func_or_code):
    if isinstance(func_or_code, types.CodeType):
    return _patch_code(func_or_code)

    return functools.update_wrapper(
    types.FunctionType(
    _patch_code(func_or_code.__code__),
    func_or_code.__globals__,
    func_or_code.__name__,
    func_or_code.__defaults__,
    func_or_code.__closure__,
    ),
    func_or_code
    )


    def print_shame():
    print('ахахахах')


    @with_shame
    def test():
    print('> Ok')
    shame
    return 1


    if __name__ == '__main__':
    test()
    pass