Use hashable references to update the hash object and dequeue them. NB. "Hashable" types are primitives, data primitives, and pure functions. With modules being "hashed" by version number, or ignored. The current "hashables" are: - module (with pin by version)
(
self,
refs: set[Name],
scope: dict[Name, Any],
ctx: RuntimeContext | None = None,
)
| 661 | return SerialRefs(refs, {}, stateful_refs) |
| 662 | |
| 663 | def serialize_and_dequeue_content_refs( |
| 664 | self, |
| 665 | refs: set[Name], |
| 666 | scope: dict[Name, Any], |
| 667 | ctx: RuntimeContext | None = None, |
| 668 | ) -> SerialRefs: |
| 669 | """Use hashable references to update the hash object and dequeue them. |
| 670 | |
| 671 | NB. "Hashable" types are primitives, data primitives, and pure |
| 672 | functions. With modules being "hashed" by version number, or ignored. |
| 673 | |
| 674 | The current "hashables" are: |
| 675 | - module (with pin by version) |
| 676 | - primitive (bytes, str, numbers.Number, type(None)) |
| 677 | - data primitive (e.g. numpy array, torch tensor) |
| 678 | - external module definitions (imported anything) |
| 679 | - pure functions (no state, no external dependencies) |
| 680 | - pure containers of the above (list, dict, set, tuple) |
| 681 | - custom types defined in CUSTOM_STUBS |
| 682 | |
| 683 | Args: |
| 684 | refs: A set of reference names unaccounted for. |
| 685 | scope: A dictionary representing the current scope. |
| 686 | ctx: Optional runtime context for memoization. |
| 687 | |
| 688 | Returns a filtered list of remaining references that were not utilized |
| 689 | in updating the hash, and a dictionary of the content serialization. |
| 690 | """ |
| 691 | self._hash = None |
| 692 | |
| 693 | content_serialization = {} |
| 694 | refs = set(refs) |
| 695 | defining_cells: set[CellId_t] = set() |
| 696 | # Content addressed hash is valid if every reference is accounted for |
| 697 | # and can be shown to be a primitive value. |
| 698 | imports = get_imports(scope) |
| 699 | for local_ref in sorted(refs): |
| 700 | ref = if_local_then_mangle(local_ref, self.cell_id) |
| 701 | if ref in imports: |
| 702 | # TODO: There may be a way to tie this in with module watching. |
| 703 | # e.g. module watcher could mutate the version number based |
| 704 | # last updated timestamp. |
| 705 | version = "" |
| 706 | module = None |
| 707 | if self.pin_modules: |
| 708 | # `.get`: a cached module def restored as a missing- |
| 709 | # module placeholder is in scope but not sys.modules. |
| 710 | module = sys.modules.get(imports[ref].module) |
| 711 | version = getattr(module, "__version__", "") or "" |
| 712 | if not version: |
| 713 | module = sys.modules.get(imports[ref].namespace) |
| 714 | version = getattr(module, "__version__", "") or "" |
| 715 | |
| 716 | content_serialization[ref] = type_sign( |
| 717 | bytes(f"module:{ref}:{version}", "utf-8"), "module" |
| 718 | ) |
| 719 | # No need to watch the module otherwise. If the block depends |
| 720 | # on it then it should be caught when hashing the block. |
no test coverage detected