4
4
# --- BEGIN_HEADER ---
5
5
#
6
6
# serial - object serialization operations using pickle, json or yaml
7
- # Copyright (C) 2003-2024 The MiG Project lead by Brian Vinter
7
+ # Copyright (C) 2003-2025 The MiG Project by the Science HPC Center at UCPH
8
8
#
9
9
# This file is part of MiG.
10
10
#
37
37
print ("ERROR: failed to init compatibility setup" )
38
38
exit (1 )
39
39
40
- import json
41
- import yaml
42
-
43
- # Python 2 requires explicit cPickle where as python 3 defaults to it
40
+ # Python 2 requires explicit cPickle whereas python 3 defaults to it
44
41
try :
45
42
import cPickle as pickle
46
43
except ImportError :
47
44
import pickle
45
+ # IMPORTANT: lazy-load json and yaml mainly in order to work around PAM crashes
46
+ # seen in sshd+sftpsubsys sessions. Apparently there's a bug / C-API
47
+ # incompatibility when using yaml in embedded python interpreters,
48
+ # due to yaml using its own nested C-extensions. In practice it
49
+ # results in a metaclass conflict TypeError upon yaml re-init there
50
+ # like described in
51
+ # https://github.com/ros-drivers/rosserial/issues/450
52
+ try :
53
+ import json
54
+ except ImportError :
55
+ json = None
56
+ try :
57
+ import yaml
58
+ except ImportError :
59
+ yaml = None
60
+ except TypeError :
61
+ # NOTE: this should not really happen but it does with sshd+sftpsubsys in
62
+ # our PAM module hooking into this code as described above. We don't
63
+ # actually need yaml in that case so just silently ignore it here and
64
+ # only raise an assertion error if used below.
65
+ yaml = None
48
66
49
67
from mig .shared .base import force_native_str_rec , force_utf8_rec
50
68
@@ -65,10 +83,12 @@ def dumps(data, protocol=0, serializer='pickle', **kwargs):
65
83
# pickle dumps already returns bytes - skip post conversion
66
84
postprocess_helper = None
67
85
if serializer == 'json' :
86
+ assert json is not None , "JSON module must be loaded for actual use"
68
87
serial_helper = json .dumps
69
88
# json dumps expects and returns native string - skip pre conversion
70
89
preprocess_helper = None
71
90
if serializer == 'yaml' :
91
+ assert yaml is not None , "YAML module must be loaded for actual use"
72
92
serial_helper = yaml .dump
73
93
if not serial_helper :
74
94
raise ValueError ("invalid serializer %r provided" % serializer )
@@ -104,8 +124,10 @@ def loads(data, serializer='pickle', **kwargs):
104
124
if serializer == 'pickle' :
105
125
serial_helper = pickle .loads
106
126
if serializer == 'json' :
127
+ assert json is not None , "JSON module must be loaded for actual use"
107
128
serial_helper = json .loads
108
129
if serializer == 'yaml' :
130
+ assert yaml is not None , "YAML module must be loaded for actual use"
109
131
# NOTE: yaml load supports both string and file-like obj
110
132
serial_helper = yaml .load
111
133
kwargs ['Loader' ] = yaml .SafeLoader
0 commit comments