Skip to content

Commit

Permalink
Use bytecode for hashes in *some* cases
Browse files Browse the repository at this point in the history
This is guaranteed to be *not* stable across python versions (and
probably other implementation details), but without this stuff just
crashes

Fixes pangeo-forge#427
  • Loading branch information
yuvipanda committed Oct 26, 2022
1 parent a9bba04 commit 3cd15ff
Showing 1 changed file with 21 additions and 1 deletion.
22 changes: 21 additions & 1 deletion pangeo_forge_recipes/serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
from enum import Enum
from hashlib import sha256
from json import dumps
import dis
import io
from contextlib import redirect_stdout
from typing import Any, List, Sequence


Expand All @@ -19,7 +22,24 @@ def either_encode_or_hash(obj: Any):
elif hasattr(obj, "sha256"):
return obj.sha256().hex()
elif inspect.isfunction(obj):
return inspect.getsource(obj)
try:
return inspect.getsource(obj)
except OSError as e:
# If the function is coming from something that was `exec`d (as pangeo-forge-runner is)
# or a lambda, inspect.getsource doesn't work. In that case, we construct something as
# stable as possible. However, this is *not* guaranteed to be stable across major
# python versions. But I *think* that is fine?
if e.args == ('could not get source code',):
codeobj = obj.__code__
# Name of
name = codeobj.co_name
args = codeobj.co_varnames[:codeobj.co_argcount]
# This is not guaranteed to be stable across python versions unfortunately
body = codeobj.co_code
return f"{name}({', '.join(args)}): {body}"
with redirect_stdout(io.StringIO()) as f:
dis.dis(obj)
return obj.__name__ + "-n" + f.getvalue()
raise TypeError(f"object of type {type(obj).__name__} not serializable")


Expand Down

0 comments on commit 3cd15ff

Please sign in to comment.