File: test_2106_pickle_class.py

package info (click to toggle)
python-awkward 2.6.5-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 23,088 kB
  • sloc: python: 148,689; cpp: 33,562; sh: 432; makefile: 21; javascript: 8
file content (103 lines) | stat: -rw-r--r-- 2,748 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# BSD 3-Clause License; see https://github.com/scikit-hep/awkward/blob/main/LICENSE

from __future__ import annotations

import contextlib
import pickle
import sys
import types
import uuid

import pytest

import awkward as ak


@contextlib.contextmanager
def temporary_module():
    name = str(uuid.uuid1()).replace("-", "_")
    module = types.ModuleType(name)
    sys.modules[name] = module
    yield module
    del sys.modules[name]


def impl():
    with temporary_module() as module:
        exec(
            """
import awkward as ak

behavior = {}
@ak.mixin_class(behavior, "my_array")
class MyArray:
    @property
    def meaning_of_life(self):
        return 42
        """,
            module.__dict__,
        )

        array = ak.Array(
            [None, [{"x": [None, 1, "hi"]}]],
            with_name="my_array",
            behavior=module.behavior,
        )
        record = ak.Array(
            [None, [{"x": [None, 1, "hi"]}]],
            with_name="my_array",
            behavior=module.behavior,
        )[1, 0]
        return pickle.dumps(array), pickle.dumps(record)


def global_impl():
    with temporary_module() as module:
        exec(
            """
import awkward as ak

@ak.mixin_class(ak.behavior, "my_array")
class MyArray:
    @property
    def meaning_of_life(self):
        return 42
        """,
            module.__dict__,
        )

        array = ak.Array([None, [{"x": [None, 1, "hi"]}]], with_name="my_array")
        record = ak.Array([None, [{"x": [None, 1, "hi"]}]], with_name="my_array")[1, 0]
        return pickle.dumps(array), pickle.dumps(record)


def test():
    array_data, record_data = impl()

    # Using a custom behavior dictionary will always break unpickling if
    # the objects in the dictionary can't be resolved
    with pytest.raises(ModuleNotFoundError):
        pickle.loads(array_data)

    with pytest.raises(ModuleNotFoundError):
        pickle.loads(record_data)


def test_global(monkeypatch):
    with monkeypatch.context() as m:
        m.setattr(ak, "behavior", {})
        array_data, record_data = global_impl()

    # The global ak.behavior is not written to the pickle
    # Awkward can create arrays with missing behavior classes
    other_array = pickle.loads(array_data)
    assert other_array.to_list() == [None, [{"x": [None, 1, "hi"]}]]
    # But it won't have their methods / properties when asked for
    with pytest.raises(AttributeError):
        assert other_array.meaning_of_life == 42

    other_record = pickle.loads(record_data)
    assert other_record.to_list() == {"x": [None, 1, "hi"]}
    # But it won't have their methods / properties when asked for
    with pytest.raises(AttributeError):
        assert other_record.meaning_of_life == 42