better-dsh 0.3.0 → 0.3.1-a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -177
- package/cordis.patch.yml +5 -36
- package/docs/20_specs/kernel-provisioning/spec.md +2 -0
- package/docs/adr/0015-independent-bundles-agent-remote.md +40 -0
- package/docs/remote-tools.md +56 -0
- package/docs/specs/kernel-provisioning/spec.md +12 -40
- package/docs/specs/omp-python-repl-port/runtime-guide.md +35 -0
- package/docs/specs/omp-python-repl-port/spec.md +68 -0
- package/docs/specs/remote-tool-enhancement/spec.md +203 -0
- package/dsh-docs/baseline.md +13 -0
- package/dsh-docs/subsystems/invariants.md +3 -0
- package/dsh-docs/subsystems/invariants.zh.md +3 -0
- package/eval-description.md +7 -3
- package/lib/LaunchOptions-0Mr6meJc.js +4 -0
- package/lib/{LaunchOptions-kGXcZOe0.js → LaunchOptions-iE9M-STS.js} +1 -1
- package/lib/{bidi-BalpKaJc.js → bidi-CaQeBZHY.js} +1 -1
- package/lib/client/index.js +30 -6
- package/lib/failover/index.js +1 -1
- package/lib/fs-aware/sandbox-plugin.js +3 -3
- package/lib/{index-browser-CysrjMyM.js → index-browser-CJzxT9Vi.js} +4 -4
- package/lib/index.d.ts +16 -50
- package/lib/index.js +482 -1720
- package/lib/kernel-env-x_WkG6Fr.js +76 -0
- package/lib/kernel-env.d.ts +5 -69
- package/lib/kernel-env.js +2 -2
- package/lib/{lsp-server-registry-BXvUTBY7.js → lsp-server-registry-BcdkHROD.js} +1 -1
- package/lib/{lsp-server-registry-CH9WNFFt.js → lsp-server-registry-D4VLs1Sm.js} +1 -1
- package/lib/{main-BQeFrBM1.js → main-taSMz1KX.js} +1 -1
- package/lib/{main-CupOhMp5.js → main-uqGqYYnA.js} +7 -5
- package/lib/mobile/plugin.d.ts +1 -1
- package/lib/omp-python/DILL-LICENSE +35 -0
- package/lib/omp-python/OMP-LICENSE +23 -0
- package/lib/omp-python/better_snapshot.py +391 -0
- package/lib/omp-python/better_support.py +425 -0
- package/lib/omp-python/dill-provenance.json +55 -0
- package/lib/omp-python/provenance.json +13 -0
- package/lib/omp-python/runner.py +2499 -0
- package/lib/omp-python/vendor/dill/__diff.py +234 -0
- package/lib/omp-python/vendor/dill/__info__.py +291 -0
- package/lib/omp-python/vendor/dill/__init__.py +119 -0
- package/lib/omp-python/vendor/dill/_dill.py +2265 -0
- package/lib/omp-python/vendor/dill/_objects.py +545 -0
- package/lib/omp-python/vendor/dill/_shims.py +193 -0
- package/lib/omp-python/vendor/dill/detect.py +287 -0
- package/lib/omp-python/vendor/dill/logger.py +285 -0
- package/lib/omp-python/vendor/dill/objtypes.py +24 -0
- package/lib/omp-python/vendor/dill/pointers.py +122 -0
- package/lib/omp-python/vendor/dill/session.py +612 -0
- package/lib/omp-python/vendor/dill/settings.py +25 -0
- package/lib/omp-python/vendor/dill/source.py +1025 -0
- package/lib/omp-python/vendor/dill/temp.py +252 -0
- package/lib/{puppeteer-core-CSk2PtSm.js → puppeteer-core-C-4NyOpY.js} +8 -8
- package/lib/remote/plugin.d.ts +459 -5
- package/lib/remote/plugin.js +2389 -210
- package/lib/url-schemes/index.d.ts +11 -11
- package/lib/url-schemes/index.js +11 -11
- package/lib/web-password.d.ts +8 -8
- package/lib/web-password.js +5 -1
- package/lib/{web-trust-Dej_RI2B.d.ts → web-trust-C_Y6o8Z2.d.ts} +11 -11
- package/lib/web-trust.d.ts +1 -2
- package/lib/welcome-notice.d.ts +5 -7
- package/lib/welcome-notice.js +9 -48
- package/lib/{wrap-T4I0nfPM.js → wrap-0VA0uFx8.js} +1 -1
- package/package.json +7 -24
- package/scripts/kernel-check.mjs +5 -0
- package/lib/LaunchOptions-B874eBu2.js +0 -4
- package/lib/bundle-delivery.d.ts +0 -20
- package/lib/bundle-delivery.js +0 -209
- package/lib/hmr.d.ts +0 -32
- package/lib/hmr.js +0 -49
- package/lib/kernel-bridge.py +0 -172
- package/lib/kernel-env-D8UOWeji.js +0 -195
- package/lib/webserver.d.ts +0 -10
- package/lib/webserver.js +0 -19
- package/scripts/kernel-provision.mjs +0 -35
- package/scripts/register-bundle.mjs +0 -80
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
#
|
|
3
|
+
# Author: Mike McKerns (mmckerns @caltech and @uqfoundation)
|
|
4
|
+
# Copyright (c) 2008-2016 California Institute of Technology.
|
|
5
|
+
# Copyright (c) 2016-2026 The Uncertainty Quantification Foundation.
|
|
6
|
+
# License: 3-clause BSD. The full license text is available at:
|
|
7
|
+
# - https://github.com/uqfoundation/dill/blob/master/LICENSE
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
Module to show if an object has changed since it was memorised
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import builtins
|
|
14
|
+
import os
|
|
15
|
+
import sys
|
|
16
|
+
import types
|
|
17
|
+
try:
|
|
18
|
+
import numpy.ma
|
|
19
|
+
HAS_NUMPY = True
|
|
20
|
+
except ImportError:
|
|
21
|
+
HAS_NUMPY = False
|
|
22
|
+
|
|
23
|
+
# pypy doesn't use reference counting
|
|
24
|
+
getrefcount = getattr(sys, 'getrefcount', lambda x:0)
|
|
25
|
+
|
|
26
|
+
# memo of objects indexed by id to a tuple (attributes, sequence items)
|
|
27
|
+
# attributes is a dict indexed by attribute name to attribute id
|
|
28
|
+
# sequence items is either a list of ids, of a dictionary of keys to ids
|
|
29
|
+
memo = {}
|
|
30
|
+
id_to_obj = {}
|
|
31
|
+
# types that cannot have changing attributes
|
|
32
|
+
builtins_types = set((str, list, dict, set, frozenset, int))
|
|
33
|
+
dont_memo = set(id(i) for i in (memo, sys.modules, sys.path_importer_cache,
|
|
34
|
+
os.environ, id_to_obj))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def get_attrs(obj):
|
|
38
|
+
"""
|
|
39
|
+
Gets all the attributes of an object though its __dict__ or return None
|
|
40
|
+
"""
|
|
41
|
+
if type(obj) in builtins_types \
|
|
42
|
+
or type(obj) is type and obj in builtins_types:
|
|
43
|
+
return
|
|
44
|
+
return getattr(obj, '__dict__', None)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def get_seq(obj, cache={str: False, frozenset: False, list: True, set: True,
|
|
48
|
+
dict: True, tuple: True, type: False,
|
|
49
|
+
types.ModuleType: False, types.FunctionType: False,
|
|
50
|
+
types.BuiltinFunctionType: False}):
|
|
51
|
+
"""
|
|
52
|
+
Gets all the items in a sequence or return None
|
|
53
|
+
"""
|
|
54
|
+
try:
|
|
55
|
+
o_type = obj.__class__
|
|
56
|
+
except AttributeError:
|
|
57
|
+
o_type = type(obj)
|
|
58
|
+
hsattr = hasattr
|
|
59
|
+
if o_type in cache:
|
|
60
|
+
if cache[o_type]:
|
|
61
|
+
if hsattr(obj, "copy"):
|
|
62
|
+
return obj.copy()
|
|
63
|
+
return obj
|
|
64
|
+
elif HAS_NUMPY and o_type in (numpy.ndarray, numpy.ma.core.MaskedConstant):
|
|
65
|
+
if obj.shape and obj.size:
|
|
66
|
+
return obj
|
|
67
|
+
else:
|
|
68
|
+
return []
|
|
69
|
+
elif hsattr(obj, "__contains__") and hsattr(obj, "__iter__") \
|
|
70
|
+
and hsattr(obj, "__len__") and hsattr(o_type, "__contains__") \
|
|
71
|
+
and hsattr(o_type, "__iter__") and hsattr(o_type, "__len__"):
|
|
72
|
+
cache[o_type] = True
|
|
73
|
+
if hsattr(obj, "copy"):
|
|
74
|
+
return obj.copy()
|
|
75
|
+
return obj
|
|
76
|
+
else:
|
|
77
|
+
cache[o_type] = False
|
|
78
|
+
return None
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def memorise(obj, force=False):
|
|
82
|
+
"""
|
|
83
|
+
Adds an object to the memo, and recursively adds all the objects
|
|
84
|
+
attributes, and if it is a container, its items. Use force=True to update
|
|
85
|
+
an object already in the memo. Updating is not recursively done.
|
|
86
|
+
"""
|
|
87
|
+
obj_id = id(obj)
|
|
88
|
+
if obj_id in memo and not force or obj_id in dont_memo:
|
|
89
|
+
return
|
|
90
|
+
id_ = id
|
|
91
|
+
g = get_attrs(obj)
|
|
92
|
+
if g is None:
|
|
93
|
+
attrs_id = None
|
|
94
|
+
else:
|
|
95
|
+
attrs_id = dict((key,id_(value)) for key, value in g.items())
|
|
96
|
+
|
|
97
|
+
s = get_seq(obj)
|
|
98
|
+
if s is None:
|
|
99
|
+
seq_id = None
|
|
100
|
+
elif hasattr(s, "items"):
|
|
101
|
+
seq_id = dict((id_(key),id_(value)) for key, value in s.items())
|
|
102
|
+
elif not hasattr(s, "__len__"): #XXX: avoid TypeError from unexpected case
|
|
103
|
+
seq_id = None
|
|
104
|
+
else:
|
|
105
|
+
seq_id = [id_(i) for i in s]
|
|
106
|
+
|
|
107
|
+
memo[obj_id] = attrs_id, seq_id
|
|
108
|
+
id_to_obj[obj_id] = obj
|
|
109
|
+
mem = memorise
|
|
110
|
+
if g is not None:
|
|
111
|
+
[mem(value) for key, value in g.items()]
|
|
112
|
+
|
|
113
|
+
if s is not None:
|
|
114
|
+
if hasattr(s, "items"):
|
|
115
|
+
[(mem(key), mem(item))
|
|
116
|
+
for key, item in s.items()]
|
|
117
|
+
else:
|
|
118
|
+
if hasattr(s, '__len__'):
|
|
119
|
+
[mem(item) for item in s]
|
|
120
|
+
else: mem(s)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def release_gone():
|
|
124
|
+
itop, mp, src = id_to_obj.pop, memo.pop, getrefcount
|
|
125
|
+
[(itop(id_), mp(id_)) for id_, obj in list(id_to_obj.items())
|
|
126
|
+
if src(obj) < 4] #XXX: correct for pypy?
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def whats_changed(obj, seen=None, simple=False, first=True):
|
|
130
|
+
"""
|
|
131
|
+
Check an object against the memo. Returns a list in the form
|
|
132
|
+
(attribute changes, container changed). Attribute changes is a dict of
|
|
133
|
+
attribute name to attribute value. container changed is a boolean.
|
|
134
|
+
If simple is true, just returns a boolean. None for either item means
|
|
135
|
+
that it has not been checked yet
|
|
136
|
+
"""
|
|
137
|
+
# Special cases
|
|
138
|
+
if first:
|
|
139
|
+
# ignore the _ variable, which only appears in interactive sessions
|
|
140
|
+
if "_" in builtins.__dict__:
|
|
141
|
+
del builtins._
|
|
142
|
+
if seen is None:
|
|
143
|
+
seen = {}
|
|
144
|
+
|
|
145
|
+
obj_id = id(obj)
|
|
146
|
+
|
|
147
|
+
if obj_id in seen:
|
|
148
|
+
if simple:
|
|
149
|
+
return any(seen[obj_id])
|
|
150
|
+
return seen[obj_id]
|
|
151
|
+
|
|
152
|
+
# Safety checks
|
|
153
|
+
if obj_id in dont_memo:
|
|
154
|
+
seen[obj_id] = [{}, False]
|
|
155
|
+
if simple:
|
|
156
|
+
return False
|
|
157
|
+
return seen[obj_id]
|
|
158
|
+
elif obj_id not in memo:
|
|
159
|
+
if simple:
|
|
160
|
+
return True
|
|
161
|
+
else:
|
|
162
|
+
raise RuntimeError("Object not memorised " + str(obj))
|
|
163
|
+
|
|
164
|
+
seen[obj_id] = ({}, False)
|
|
165
|
+
|
|
166
|
+
chngd = whats_changed
|
|
167
|
+
id_ = id
|
|
168
|
+
|
|
169
|
+
# compare attributes
|
|
170
|
+
attrs = get_attrs(obj)
|
|
171
|
+
if attrs is None:
|
|
172
|
+
changed = {}
|
|
173
|
+
else:
|
|
174
|
+
obj_attrs = memo[obj_id][0]
|
|
175
|
+
obj_get = obj_attrs.get
|
|
176
|
+
changed = dict((key,None) for key in obj_attrs if key not in attrs)
|
|
177
|
+
for key, o in attrs.items():
|
|
178
|
+
if id_(o) != obj_get(key, None) or chngd(o, seen, True, False):
|
|
179
|
+
changed[key] = o
|
|
180
|
+
|
|
181
|
+
# compare sequence
|
|
182
|
+
items = get_seq(obj)
|
|
183
|
+
seq_diff = False
|
|
184
|
+
if (items is not None) and (hasattr(items, '__len__')):
|
|
185
|
+
obj_seq = memo[obj_id][1]
|
|
186
|
+
if (len(items) != len(obj_seq)):
|
|
187
|
+
seq_diff = True
|
|
188
|
+
elif hasattr(obj, "items"): # dict type obj
|
|
189
|
+
obj_get = obj_seq.get
|
|
190
|
+
for key, item in items.items():
|
|
191
|
+
if id_(item) != obj_get(id_(key)) \
|
|
192
|
+
or chngd(key, seen, True, False) \
|
|
193
|
+
or chngd(item, seen, True, False):
|
|
194
|
+
seq_diff = True
|
|
195
|
+
break
|
|
196
|
+
else:
|
|
197
|
+
for i, j in zip(items, obj_seq): # list type obj
|
|
198
|
+
if id_(i) != j or chngd(i, seen, True, False):
|
|
199
|
+
seq_diff = True
|
|
200
|
+
break
|
|
201
|
+
seen[obj_id] = changed, seq_diff
|
|
202
|
+
if simple:
|
|
203
|
+
return changed or seq_diff
|
|
204
|
+
return changed, seq_diff
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def has_changed(*args, **kwds):
|
|
208
|
+
kwds['simple'] = True # ignore simple if passed in
|
|
209
|
+
return whats_changed(*args, **kwds)
|
|
210
|
+
|
|
211
|
+
__import__ = __import__
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def _imp(*args, **kwds):
|
|
215
|
+
"""
|
|
216
|
+
Replaces the default __import__, to allow a module to be memorised
|
|
217
|
+
before the user can change it
|
|
218
|
+
"""
|
|
219
|
+
before = set(sys.modules.keys())
|
|
220
|
+
mod = __import__(*args, **kwds)
|
|
221
|
+
after = set(sys.modules.keys()).difference(before)
|
|
222
|
+
for m in after:
|
|
223
|
+
memorise(sys.modules[m])
|
|
224
|
+
return mod
|
|
225
|
+
|
|
226
|
+
builtins.__import__ = _imp
|
|
227
|
+
if hasattr(builtins, "_"):
|
|
228
|
+
del builtins._
|
|
229
|
+
|
|
230
|
+
# memorise all already imported modules. This implies that this must be
|
|
231
|
+
# imported first for any changes to be recorded
|
|
232
|
+
for mod in list(sys.modules.values()):
|
|
233
|
+
memorise(mod)
|
|
234
|
+
release_gone()
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
#
|
|
3
|
+
# Author: Mike McKerns (mmckerns @caltech and @uqfoundation)
|
|
4
|
+
# Copyright (c) 2026 The Uncertainty Quantification Foundation.
|
|
5
|
+
# License: 3-clause BSD. The full license text is available at:
|
|
6
|
+
# - https://github.com/uqfoundation/dill/blob/master/LICENSE
|
|
7
|
+
'''
|
|
8
|
+
-----------------------------
|
|
9
|
+
dill: serialize all of Python
|
|
10
|
+
-----------------------------
|
|
11
|
+
|
|
12
|
+
About Dill
|
|
13
|
+
==========
|
|
14
|
+
|
|
15
|
+
``dill`` extends Python's ``pickle`` module for serializing and de-serializing
|
|
16
|
+
Python objects to the majority of the built-in Python types. Serialization
|
|
17
|
+
is the process of converting an object to a byte stream, and the inverse
|
|
18
|
+
of which is converting a byte stream back to a Python object hierarchy.
|
|
19
|
+
|
|
20
|
+
``dill`` provides the user the same interface as the ``pickle`` module, and
|
|
21
|
+
also includes some additional features. In addition to pickling Python
|
|
22
|
+
objects, ``dill`` provides the ability to save the state of an interpreter
|
|
23
|
+
session in a single command. Hence, it would be feasible to save an
|
|
24
|
+
interpreter session, close the interpreter, ship the pickled file to
|
|
25
|
+
another computer, open a new interpreter, unpickle the session and
|
|
26
|
+
thus continue from the 'saved' state of the original interpreter
|
|
27
|
+
session.
|
|
28
|
+
|
|
29
|
+
``dill`` can be used to store Python objects to a file, but the primary
|
|
30
|
+
usage is to send Python objects across the network as a byte stream.
|
|
31
|
+
``dill`` is quite flexible, and allows arbitrary user defined classes
|
|
32
|
+
and functions to be serialized. Thus ``dill`` is not intended to be
|
|
33
|
+
secure against erroneously or maliciously constructed data. It is
|
|
34
|
+
left to the user to decide whether the data they unpickle is from
|
|
35
|
+
a trustworthy source.
|
|
36
|
+
|
|
37
|
+
``dill`` is part of ``pathos``, a Python framework for heterogeneous computing.
|
|
38
|
+
``dill`` is in active development, so any user feedback, bug reports, comments,
|
|
39
|
+
or suggestions are highly appreciated. A list of issues is located at
|
|
40
|
+
https://github.com/uqfoundation/dill/issues, with a legacy list maintained at
|
|
41
|
+
https://uqfoundation.github.io/project/pathos/query.
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
Major Features
|
|
45
|
+
==============
|
|
46
|
+
|
|
47
|
+
``dill`` can pickle the following standard types:
|
|
48
|
+
|
|
49
|
+
- none, type, bool, int, float, complex, bytes, str,
|
|
50
|
+
- tuple, list, dict, file, buffer, builtin,
|
|
51
|
+
- Python classes, namedtuples, dataclasses, metaclasses,
|
|
52
|
+
- instances of classes,
|
|
53
|
+
- set, frozenset, array, functions, exceptions
|
|
54
|
+
|
|
55
|
+
``dill`` can also pickle more 'exotic' standard types:
|
|
56
|
+
|
|
57
|
+
- functions with yields, nested functions, lambdas,
|
|
58
|
+
- cell, method, unboundmethod, module, code, methodwrapper,
|
|
59
|
+
- methoddescriptor, getsetdescriptor, memberdescriptor, wrapperdescriptor,
|
|
60
|
+
- dictproxy, slice, notimplemented, ellipsis, quit
|
|
61
|
+
|
|
62
|
+
``dill`` cannot yet pickle these standard types:
|
|
63
|
+
|
|
64
|
+
- frame, generator, traceback
|
|
65
|
+
|
|
66
|
+
``dill`` also provides the capability to:
|
|
67
|
+
|
|
68
|
+
- save and load Python interpreter sessions
|
|
69
|
+
- save and extract the source code from functions and classes
|
|
70
|
+
- interactively diagnose pickling errors
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
Current Release
|
|
74
|
+
===============
|
|
75
|
+
|
|
76
|
+
The latest released version of ``dill`` is available from:
|
|
77
|
+
|
|
78
|
+
https://pypi.org/project/dill
|
|
79
|
+
|
|
80
|
+
``dill`` is distributed under a 3-clause BSD license.
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
Development Version
|
|
84
|
+
===================
|
|
85
|
+
|
|
86
|
+
You can get the latest development version with all the shiny new features at:
|
|
87
|
+
|
|
88
|
+
https://github.com/uqfoundation
|
|
89
|
+
|
|
90
|
+
If you have a new contribution, please submit a pull request.
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
Installation
|
|
94
|
+
============
|
|
95
|
+
|
|
96
|
+
``dill`` can be installed with ``pip``::
|
|
97
|
+
|
|
98
|
+
$ pip install dill
|
|
99
|
+
|
|
100
|
+
To optionally include the ``objgraph`` diagnostic tool in the install::
|
|
101
|
+
|
|
102
|
+
$ pip install dill[graph]
|
|
103
|
+
|
|
104
|
+
To optionally include the ``gprof2dot`` diagnostic tool in the install::
|
|
105
|
+
|
|
106
|
+
$ pip install dill[profile]
|
|
107
|
+
|
|
108
|
+
For windows users, to optionally install session history tools::
|
|
109
|
+
|
|
110
|
+
$ pip install dill[readline]
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
Requirements
|
|
114
|
+
============
|
|
115
|
+
|
|
116
|
+
``dill`` requires:
|
|
117
|
+
|
|
118
|
+
- ``python`` (or ``pypy``), **>=3.9**
|
|
119
|
+
- ``setuptools``, **>=42**
|
|
120
|
+
|
|
121
|
+
Optional requirements:
|
|
122
|
+
|
|
123
|
+
- ``objgraph``, **>=1.7.2**
|
|
124
|
+
- ``gprof2dot``, **>=2022.7.29**
|
|
125
|
+
- ``pyreadline``, **>=1.7.1** (on windows)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
Basic Usage
|
|
129
|
+
===========
|
|
130
|
+
|
|
131
|
+
``dill`` is a drop-in replacement for ``pickle``. Existing code can be
|
|
132
|
+
updated to allow complete pickling using::
|
|
133
|
+
|
|
134
|
+
>>> import dill as pickle
|
|
135
|
+
|
|
136
|
+
or::
|
|
137
|
+
|
|
138
|
+
>>> from dill import dumps, loads
|
|
139
|
+
|
|
140
|
+
``dumps`` converts the object to a unique byte string, and ``loads`` performs
|
|
141
|
+
the inverse operation::
|
|
142
|
+
|
|
143
|
+
>>> squared = lambda x: x**2
|
|
144
|
+
>>> loads(dumps(squared))(3)
|
|
145
|
+
9
|
|
146
|
+
|
|
147
|
+
There are a number of options to control serialization which are provided
|
|
148
|
+
as keyword arguments to several ``dill`` functions:
|
|
149
|
+
|
|
150
|
+
* with *protocol*, the pickle protocol level can be set. This uses the
|
|
151
|
+
same value as the ``pickle`` module, *DEFAULT_PROTOCOL*.
|
|
152
|
+
* with *byref=True*, ``dill`` to behave a lot more like pickle with
|
|
153
|
+
certain objects (like modules) pickled by reference as opposed to
|
|
154
|
+
attempting to pickle the object itself.
|
|
155
|
+
* with *recurse=True*, objects referred to in the global dictionary are
|
|
156
|
+
recursively traced and pickled, instead of the default behavior of
|
|
157
|
+
attempting to store the entire global dictionary.
|
|
158
|
+
* with *fmode*, the contents of the file can be pickled along with the file
|
|
159
|
+
handle, which is useful if the object is being sent over the wire to a
|
|
160
|
+
remote system which does not have the original file on disk. Options are
|
|
161
|
+
*HANDLE_FMODE* for just the handle, *CONTENTS_FMODE* for the file content
|
|
162
|
+
and *FILE_FMODE* for content and handle.
|
|
163
|
+
* with *ignore=False*, objects reconstructed with types defined in the
|
|
164
|
+
top-level script environment use the existing type in the environment
|
|
165
|
+
rather than a possibly different reconstructed type.
|
|
166
|
+
|
|
167
|
+
The default serialization can also be set globally in *dill.settings*.
|
|
168
|
+
Thus, we can modify how ``dill`` handles references to the global dictionary
|
|
169
|
+
locally or globally::
|
|
170
|
+
|
|
171
|
+
>>> import dill.settings
|
|
172
|
+
>>> dumps(absolute) == dumps(absolute, recurse=True)
|
|
173
|
+
False
|
|
174
|
+
>>> dill.settings['recurse'] = True
|
|
175
|
+
>>> dumps(absolute) == dumps(absolute, recurse=True)
|
|
176
|
+
True
|
|
177
|
+
|
|
178
|
+
``dill`` also includes source code inspection, as an alternate to pickling::
|
|
179
|
+
|
|
180
|
+
>>> import dill.source
|
|
181
|
+
>>> print(dill.source.getsource(squared))
|
|
182
|
+
squared = lambda x:x**2
|
|
183
|
+
|
|
184
|
+
To aid in debugging pickling issues, use *dill.detect* which provides
|
|
185
|
+
tools like pickle tracing::
|
|
186
|
+
|
|
187
|
+
>>> import dill.detect
|
|
188
|
+
>>> with dill.detect.trace():
|
|
189
|
+
>>> dumps(squared)
|
|
190
|
+
┬ F1: <function <lambda> at 0x7fe074f8c280>
|
|
191
|
+
├┬ F2: <function _create_function at 0x7fe074c49c10>
|
|
192
|
+
│└ # F2 [34 B]
|
|
193
|
+
├┬ Co: <code object <lambda> at 0x7fe07501eb30, file "<stdin>", line 1>
|
|
194
|
+
│├┬ F2: <function _create_code at 0x7fe074c49ca0>
|
|
195
|
+
││└ # F2 [19 B]
|
|
196
|
+
│└ # Co [87 B]
|
|
197
|
+
├┬ D1: <dict object at 0x7fe0750d4680>
|
|
198
|
+
│└ # D1 [22 B]
|
|
199
|
+
├┬ D2: <dict object at 0x7fe074c5a1c0>
|
|
200
|
+
│└ # D2 [2 B]
|
|
201
|
+
├┬ D2: <dict object at 0x7fe074f903c0>
|
|
202
|
+
│├┬ D2: <dict object at 0x7fe074f8ebc0>
|
|
203
|
+
││└ # D2 [2 B]
|
|
204
|
+
│└ # D2 [23 B]
|
|
205
|
+
└ # F1 [180 B]
|
|
206
|
+
|
|
207
|
+
With trace, we see how ``dill`` stored the lambda (``F1``) by first storing
|
|
208
|
+
``_create_function``, the underlying code object (``Co``) and ``_create_code``
|
|
209
|
+
(which is used to handle code objects), then we handle the reference to
|
|
210
|
+
the global dict (``D2``) plus other dictionaries (``D1`` and ``D2``) that
|
|
211
|
+
save the lambda object's state. A ``#`` marks when the object is actually stored.
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
More Information
|
|
215
|
+
================
|
|
216
|
+
|
|
217
|
+
Probably the best way to get started is to look at the documentation at
|
|
218
|
+
http://dill.rtfd.io. Also see ``dill.tests`` for a set of scripts that
|
|
219
|
+
demonstrate how ``dill`` can serialize different Python objects. You can
|
|
220
|
+
run the test suite with ``python -m dill.tests``. The contents of any
|
|
221
|
+
pickle file can be examined with ``undill``. As ``dill`` conforms to
|
|
222
|
+
the ``pickle`` interface, the examples and documentation found at
|
|
223
|
+
http://docs.python.org/library/pickle.html also apply to ``dill``
|
|
224
|
+
if one will ``import dill as pickle``. The source code is also generally
|
|
225
|
+
well documented, so further questions may be resolved by inspecting the
|
|
226
|
+
code itself. Please feel free to submit a ticket on github, or ask a
|
|
227
|
+
question on stackoverflow (**@Mike McKerns**).
|
|
228
|
+
If you would like to share how you use ``dill`` in your work, please send
|
|
229
|
+
an email (to **mmckerns at uqfoundation dot org**).
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
Citation
|
|
233
|
+
========
|
|
234
|
+
|
|
235
|
+
If you use ``dill`` to do research that leads to publication, we ask that you
|
|
236
|
+
acknowledge use of ``dill`` by citing the following in your publication::
|
|
237
|
+
|
|
238
|
+
M.M. McKerns, L. Strand, T. Sullivan, A. Fang, M.A.G. Aivazis,
|
|
239
|
+
"Building a framework for predictive science", Proceedings of
|
|
240
|
+
the 10th Python in Science Conference, 2011;
|
|
241
|
+
http://arxiv.org/pdf/1202.1056
|
|
242
|
+
|
|
243
|
+
Michael McKerns and Michael Aivazis,
|
|
244
|
+
"pathos: a framework for heterogeneous computing", 2010- ;
|
|
245
|
+
https://uqfoundation.github.io/project/pathos
|
|
246
|
+
|
|
247
|
+
Please see https://uqfoundation.github.io/project/pathos or
|
|
248
|
+
http://arxiv.org/pdf/1202.1056 for further information.
|
|
249
|
+
|
|
250
|
+
'''
|
|
251
|
+
|
|
252
|
+
__version__ = '0.4.1'
|
|
253
|
+
__author__ = 'Mike McKerns'
|
|
254
|
+
|
|
255
|
+
__license__ = '''
|
|
256
|
+
Copyright (c) 2004-2016 California Institute of Technology.
|
|
257
|
+
Copyright (c) 2016-2026 The Uncertainty Quantification Foundation.
|
|
258
|
+
All rights reserved.
|
|
259
|
+
|
|
260
|
+
This software is available subject to the conditions and terms laid
|
|
261
|
+
out below. By downloading and using this software you are agreeing
|
|
262
|
+
to the following conditions.
|
|
263
|
+
|
|
264
|
+
Redistribution and use in source and binary forms, with or without
|
|
265
|
+
modification, are permitted provided that the following conditions
|
|
266
|
+
are met:
|
|
267
|
+
|
|
268
|
+
- Redistributions of source code must retain the above copyright
|
|
269
|
+
notice, this list of conditions and the following disclaimer.
|
|
270
|
+
|
|
271
|
+
- Redistributions in binary form must reproduce the above copyright
|
|
272
|
+
notice, this list of conditions and the following disclaimer in the
|
|
273
|
+
documentation and/or other materials provided with the distribution.
|
|
274
|
+
|
|
275
|
+
- Neither the names of the copyright holders nor the names of any of
|
|
276
|
+
the contributors may be used to endorse or promote products derived
|
|
277
|
+
from this software without specific prior written permission.
|
|
278
|
+
|
|
279
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
280
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
281
|
+
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
282
|
+
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
283
|
+
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
284
|
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
285
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
286
|
+
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
287
|
+
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
288
|
+
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
289
|
+
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
290
|
+
|
|
291
|
+
'''
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
#
|
|
3
|
+
# Author: Mike McKerns (mmckerns @caltech and @uqfoundation)
|
|
4
|
+
# Copyright (c) 2008-2016 California Institute of Technology.
|
|
5
|
+
# Copyright (c) 2016-2026 The Uncertainty Quantification Foundation.
|
|
6
|
+
# License: 3-clause BSD. The full license text is available at:
|
|
7
|
+
# - https://github.com/uqfoundation/dill/blob/master/LICENSE
|
|
8
|
+
|
|
9
|
+
# author, version, license, and long description
|
|
10
|
+
try: # the package is installed
|
|
11
|
+
from .__info__ import __version__, __author__, __doc__, __license__
|
|
12
|
+
except: # pragma: no cover
|
|
13
|
+
import os
|
|
14
|
+
import sys
|
|
15
|
+
parent = os.path.dirname(os.path.abspath(os.path.dirname(__file__)))
|
|
16
|
+
sys.path.append(parent)
|
|
17
|
+
# get distribution meta info
|
|
18
|
+
from version import (__version__, __author__,
|
|
19
|
+
get_license_text, get_readme_as_rst)
|
|
20
|
+
__license__ = get_license_text(os.path.join(parent, 'LICENSE'))
|
|
21
|
+
__license__ = "\n%s" % __license__
|
|
22
|
+
__doc__ = get_readme_as_rst(os.path.join(parent, 'README.md'))
|
|
23
|
+
del os, sys, parent, get_license_text, get_readme_as_rst
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
from ._dill import (
|
|
27
|
+
dump, dumps, load, loads, copy,
|
|
28
|
+
Pickler, Unpickler, register, pickle, pickles, check,
|
|
29
|
+
DEFAULT_PROTOCOL, HIGHEST_PROTOCOL, HANDLE_FMODE, CONTENTS_FMODE, FILE_FMODE,
|
|
30
|
+
PickleError, PickleWarning, PicklingError, PicklingWarning, UnpicklingError,
|
|
31
|
+
UnpicklingWarning,
|
|
32
|
+
)
|
|
33
|
+
from .session import (
|
|
34
|
+
dump_module, load_module, load_module_asdict,
|
|
35
|
+
dump_session, load_session # backward compatibility
|
|
36
|
+
)
|
|
37
|
+
from . import detect, logger, session, source, temp
|
|
38
|
+
|
|
39
|
+
# get global settings
|
|
40
|
+
from .settings import settings
|
|
41
|
+
|
|
42
|
+
# make sure "trace" is turned off
|
|
43
|
+
logger.trace(False)
|
|
44
|
+
|
|
45
|
+
objects = {}
|
|
46
|
+
# local import of dill._objects
|
|
47
|
+
#from . import _objects
|
|
48
|
+
#objects.update(_objects.succeeds)
|
|
49
|
+
#del _objects
|
|
50
|
+
|
|
51
|
+
# local import of dill.objtypes
|
|
52
|
+
from . import objtypes as types
|
|
53
|
+
|
|
54
|
+
def load_types(pickleable=True, unpickleable=True):
|
|
55
|
+
"""load pickleable and/or unpickleable types to ``dill.types``
|
|
56
|
+
|
|
57
|
+
``dill.types`` is meant to mimic the ``types`` module, providing a
|
|
58
|
+
registry of object types. By default, the module is empty (for import
|
|
59
|
+
speed purposes). Use the ``load_types`` function to load selected object
|
|
60
|
+
types to the ``dill.types`` module.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
pickleable (bool, default=True): if True, load pickleable types.
|
|
64
|
+
unpickleable (bool, default=True): if True, load unpickleable types.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
None
|
|
68
|
+
"""
|
|
69
|
+
from importlib import reload
|
|
70
|
+
# local import of dill.objects
|
|
71
|
+
from . import _objects
|
|
72
|
+
if pickleable:
|
|
73
|
+
objects.update(_objects.succeeds)
|
|
74
|
+
else:
|
|
75
|
+
[objects.pop(obj,None) for obj in _objects.succeeds]
|
|
76
|
+
if unpickleable:
|
|
77
|
+
objects.update(_objects.failures)
|
|
78
|
+
else:
|
|
79
|
+
[objects.pop(obj,None) for obj in _objects.failures]
|
|
80
|
+
objects.update(_objects.registered)
|
|
81
|
+
del _objects
|
|
82
|
+
# reset contents of types to 'empty'
|
|
83
|
+
[types.__dict__.pop(obj) for obj in list(types.__dict__.keys()) \
|
|
84
|
+
if obj.find('Type') != -1]
|
|
85
|
+
# add corresponding types from objects to types
|
|
86
|
+
reload(types)
|
|
87
|
+
|
|
88
|
+
def extend(use_dill=True):
|
|
89
|
+
'''add (or remove) dill types to/from the pickle registry
|
|
90
|
+
|
|
91
|
+
by default, ``dill`` populates its types to ``pickle.Pickler.dispatch``.
|
|
92
|
+
Thus, all ``dill`` types are available upon calling ``'import pickle'``.
|
|
93
|
+
To drop all ``dill`` types from the ``pickle`` dispatch, *use_dill=False*.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
use_dill (bool, default=True): if True, extend the dispatch table.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
None
|
|
100
|
+
'''
|
|
101
|
+
from ._dill import _revert_extension, _extend
|
|
102
|
+
if use_dill: _extend()
|
|
103
|
+
else: _revert_extension()
|
|
104
|
+
return
|
|
105
|
+
|
|
106
|
+
extend()
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def license():
|
|
110
|
+
"""print license"""
|
|
111
|
+
print (__license__)
|
|
112
|
+
return
|
|
113
|
+
|
|
114
|
+
def citation():
|
|
115
|
+
"""print citation"""
|
|
116
|
+
print (__doc__[-491:-118])
|
|
117
|
+
return
|
|
118
|
+
|
|
119
|
+
# end of file
|