Skip to content

Instantly share code, notes, and snippets.

@SqrtRyan
Created April 25, 2025 05:37
Show Gist options
  • Save SqrtRyan/acc4f69a43cab309e45607bd31e5a418 to your computer and use it in GitHub Desktop.
Save SqrtRyan/acc4f69a43cab309e45607bd31e5a418 to your computer and use it in GitHub Desktop.
import requests
import os
import PIL
def rebind_globals_to_module(module, *, monkey_patch=False):
"""
Decorator to change the global environment of functions and classes to another module's namespace.
If monkey_patch is True, the function or class is also added to the module.
The result: the decorated function is as good as if it were created in that module's source code,
allowing it to both read and write from that module's globals. As a consequence, it can no longer
read or write from the module where this decorator is called.
Args:
module: The target module to bind the globals to.
monkey_patch: If True, adds the object to the module.
Returns:
An object with its globals rebound to the target module's namespace.
EXAMPLE:
import rp.r as r
@rebind_globals_to_module(r)
def f():
#returns r._BundledPath
return _BundledPath
some_var=123
@rebind_globals_to_module(r)
def g():
#This crashes as it can no longer see names from the current module.
return some_var
"""
import types
import functools
def decorator(obj):
original_module = obj.__module__
if isinstance(obj, types.FunctionType):
if hasattr(obj, "__module__") and obj.__module__ == original_module:
bound_func = types.FunctionType(
obj.__code__,
module.__dict__,
obj.__name__,
obj.__defaults__,
obj.__closure__,
)
return bound_func
return obj
elif isinstance(obj, type): # It's a class
raise NotImplementedError("rebind_globals_to_module has not been tested/verified on classes yet")
# Create a new class with all attributes copied over
new_class_dict = {}
for attr_name, attr_value in obj.__dict__.items():
try:
new_attr_value = decorator(attr_value)
except TypeError:
new_attr_value = attr_value
new_class_dict[attr_name] = attr_value
# Construct the new class type in the module's namespace
new_class = type(obj.__name__, obj.__bases__, new_class_dict)
# Monkey patch if requested
if monkey_patch:
print('patching....')
setattr(module, obj.__name__, new_class)
return new_class
else:
raise TypeError("rebind_globals_to_module can only be applied to functions or classes.")
return decorator
if 'old_open' not in vars():
from PIL.Image import open as old_open
@rebind_globals_to_module(PIL.Image)
def image_open(fp, mode: r='r', formats: None=None,old_open=old_open):
print('Jiggle puffins')
if fp.startswith('https'):
#You'd better use a png >:O
image_path = download_url(fp, "image_input_blarglepuff.png")
else:
image_path = fp
return old_open(image_path, mode, formats)
@rebind_globals_to_module(PIL.Image)
def download_url(url, path):
"""
Download content from a URL and save it to the specified path.
Args:
url (str): The URL to download from.
path (str): The local path where the downloaded content should be saved.
Returns:
bool: True if download was successful, False otherwise.
"""
import requests
import os
import PIL
from builtins import open
# Make a GET request to the URL
response = requests.get(url, stream=True)
response.raise_for_status() # Raise an exception for HTTP errors
# Write the content to the specified file
with open(path,mode='wb') as f:
for chunk in response.iter_content(chunk_size=8192):
if chunk: # Filter out keep-alive new chunks
f.write(chunk)
print('returning ',path)
return path
PIL.Image.open=image_open
PIL.Image.download_url=download_url
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment