chef 17.0.242 → 17.1.35

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -12
  3. data/Rakefile +2 -2
  4. data/chef.gemspec +9 -20
  5. data/lib/chef/chef_fs/file_pattern.rb +2 -2
  6. data/lib/chef/compliance/default_attributes.rb +1 -1
  7. data/lib/chef/compliance/reporter/automate.rb +1 -1
  8. data/lib/chef/compliance/runner.rb +2 -2
  9. data/lib/chef/cookbook/cookbook_version_loader.rb +3 -3
  10. data/lib/chef/cookbook/gem_installer.rb +5 -1
  11. data/lib/chef/dsl/declare_resource.rb +5 -10
  12. data/lib/chef/formatters/doc.rb +2 -1
  13. data/lib/chef/node.rb +1 -1
  14. data/lib/chef/provider/directory.rb +6 -6
  15. data/lib/chef/provider/link.rb +1 -1
  16. data/lib/chef/provider/package/dnf/dnf_helper.py +11 -10
  17. data/lib/chef/provider/package/dnf/python_helper.rb +9 -8
  18. data/lib/chef/provider/package/yum.rb +1 -4
  19. data/lib/chef/provider/package/yum/python_helper.rb +15 -10
  20. data/lib/chef/provider/package/yum/yum_helper.py +46 -62
  21. data/lib/chef/provider/registry_key.rb +1 -1
  22. data/lib/chef/provider/service/systemd.rb +1 -1
  23. data/lib/chef/provider/systemd_unit.rb +1 -1
  24. data/lib/chef/provider/template/content.rb +1 -1
  25. data/lib/chef/provider/windows_script.rb +1 -1
  26. data/lib/chef/resource.rb +6 -7
  27. data/lib/chef/resource/execute.rb +2 -2
  28. data/lib/chef/resource/inspec_waiver_file_entry.rb +155 -0
  29. data/lib/chef/resource/lwrp_base.rb +17 -2
  30. data/lib/chef/resource/remote_file.rb +2 -2
  31. data/lib/chef/resource/windows_env.rb +1 -1
  32. data/lib/chef/resource/windows_font.rb +1 -1
  33. data/lib/chef/resource/windows_pagefile.rb +2 -2
  34. data/lib/chef/resource/windows_path.rb +2 -2
  35. data/lib/chef/resource/windows_security_policy.rb +5 -2
  36. data/lib/chef/resource/windows_task.rb +1 -1
  37. data/lib/chef/resource_builder.rb +8 -2
  38. data/lib/chef/resources.rb +1 -0
  39. data/lib/chef/run_lock.rb +1 -1
  40. data/lib/chef/runner.rb +1 -1
  41. data/lib/chef/shell/ext.rb +3 -3
  42. data/lib/chef/version.rb +1 -1
  43. data/lib/chef/win32/api.rb +9 -2
  44. data/spec/data/knife-home/.chef/plugins/knife/example_home_subcommand.rb +0 -0
  45. data/spec/data/knife-site-subcommands/plugins/knife/example_subcommand.rb +0 -0
  46. data/spec/data/knife_subcommand/test_explicit_category.rb +7 -0
  47. data/spec/data/knife_subcommand/test_name_mapping.rb +4 -0
  48. data/spec/data/knife_subcommand/test_yourself.rb +21 -0
  49. data/spec/functional/resource/dnf_package_spec.rb +857 -537
  50. data/spec/functional/resource/group_spec.rb +1 -1
  51. data/spec/functional/resource/link_spec.rb +1 -1
  52. data/spec/functional/resource/remote_file_spec.rb +1 -1
  53. data/spec/functional/resource/windows_env_spec.rb +2 -2
  54. data/spec/functional/resource/yum_package_spec.rb +495 -428
  55. data/spec/integration/client/client_spec.rb +0 -20
  56. data/spec/integration/recipes/unified_mode_spec.rb +70 -0
  57. data/spec/spec_helper.rb +3 -0
  58. data/spec/support/chef_helpers.rb +1 -1
  59. data/spec/support/shared/functional/execute_resource.rb +1 -1
  60. data/spec/support/shared/functional/knife.rb +37 -0
  61. data/spec/support/shared/integration/knife_support.rb +192 -0
  62. data/spec/support/shared/unit/knife_shared.rb +39 -0
  63. data/spec/support/shared/unit/provider/file.rb +1 -1
  64. data/spec/unit/chef_fs/file_system/repository/directory_spec.rb +1 -1
  65. data/spec/unit/compliance/runner_spec.rb +1 -1
  66. data/spec/unit/provider/link_spec.rb +1 -1
  67. data/spec/unit/provider/package/dnf/python_helper_spec.rb +1 -0
  68. data/spec/unit/provider/package/yum/python_helper_spec.rb +1 -0
  69. data/spec/unit/provider/service/systemd_service_spec.rb +2 -2
  70. data/spec/unit/provider/systemd_unit_spec.rb +2 -2
  71. data/spec/unit/resource/inspec_waiver_file_entry_spec.rb +80 -0
  72. data/tasks/rspec.rb +4 -9
  73. metadata +16 -160
  74. data/lib/chef/provider/package/yum/simplejson/LICENSE.txt +0 -79
  75. data/lib/chef/provider/package/yum/simplejson/__init__.py +0 -318
  76. data/lib/chef/provider/package/yum/simplejson/__init__.pyc +0 -0
  77. data/lib/chef/provider/package/yum/simplejson/decoder.py +0 -354
  78. data/lib/chef/provider/package/yum/simplejson/decoder.pyc +0 -0
  79. data/lib/chef/provider/package/yum/simplejson/encoder.py +0 -440
  80. data/lib/chef/provider/package/yum/simplejson/encoder.pyc +0 -0
  81. data/lib/chef/provider/package/yum/simplejson/scanner.py +0 -65
  82. data/lib/chef/provider/package/yum/simplejson/scanner.pyc +0 -0
  83. data/lib/chef/provider/package/yum/simplejson/tool.py +0 -37
@@ -1,318 +0,0 @@
1
- r"""JSON (JavaScript Object Notation) <http://json.org> is a subset of
2
- JavaScript syntax (ECMA-262 3rd edition) used as a lightweight data
3
- interchange format.
4
-
5
- :mod:`simplejson` exposes an API familiar to users of the standard library
6
- :mod:`marshal` and :mod:`pickle` modules. It is the externally maintained
7
- version of the :mod:`json` library contained in Python 2.6, but maintains
8
- compatibility with Python 2.4 and Python 2.5 and (currently) has
9
- significant performance advantages, even without using the optional C
10
- extension for speedups.
11
-
12
- Encoding basic Python object hierarchies::
13
-
14
- >>> import simplejson as json
15
- >>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
16
- '["foo", {"bar": ["baz", null, 1.0, 2]}]'
17
- >>> print json.dumps("\"foo\bar")
18
- "\"foo\bar"
19
- >>> print json.dumps(u'\u1234')
20
- "\u1234"
21
- >>> print json.dumps('\\')
22
- "\\"
23
- >>> print json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True)
24
- {"a": 0, "b": 0, "c": 0}
25
- >>> from StringIO import StringIO
26
- >>> io = StringIO()
27
- >>> json.dump(['streaming API'], io)
28
- >>> io.getvalue()
29
- '["streaming API"]'
30
-
31
- Compact encoding::
32
-
33
- >>> import simplejson as json
34
- >>> json.dumps([1,2,3,{'4': 5, '6': 7}], separators=(',',':'))
35
- '[1,2,3,{"4":5,"6":7}]'
36
-
37
- Pretty printing::
38
-
39
- >>> import simplejson as json
40
- >>> s = json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4)
41
- >>> print '\n'.join([l.rstrip() for l in s.splitlines()])
42
- {
43
- "4": 5,
44
- "6": 7
45
- }
46
-
47
- Decoding JSON::
48
-
49
- >>> import simplejson as json
50
- >>> obj = [u'foo', {u'bar': [u'baz', None, 1.0, 2]}]
51
- >>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]') == obj
52
- True
53
- >>> json.loads('"\\"foo\\bar"') == u'"foo\x08ar'
54
- True
55
- >>> from StringIO import StringIO
56
- >>> io = StringIO('["streaming API"]')
57
- >>> json.load(io)[0] == 'streaming API'
58
- True
59
-
60
- Specializing JSON object decoding::
61
-
62
- >>> import simplejson as json
63
- >>> def as_complex(dct):
64
- ... if '__complex__' in dct:
65
- ... return complex(dct['real'], dct['imag'])
66
- ... return dct
67
- ...
68
- >>> json.loads('{"__complex__": true, "real": 1, "imag": 2}',
69
- ... object_hook=as_complex)
70
- (1+2j)
71
- >>> import decimal
72
- >>> json.loads('1.1', parse_float=decimal.Decimal) == decimal.Decimal('1.1')
73
- True
74
-
75
- Specializing JSON object encoding::
76
-
77
- >>> import simplejson as json
78
- >>> def encode_complex(obj):
79
- ... if isinstance(obj, complex):
80
- ... return [obj.real, obj.imag]
81
- ... raise TypeError(repr(o) + " is not JSON serializable")
82
- ...
83
- >>> json.dumps(2 + 1j, default=encode_complex)
84
- '[2.0, 1.0]'
85
- >>> json.JSONEncoder(default=encode_complex).encode(2 + 1j)
86
- '[2.0, 1.0]'
87
- >>> ''.join(json.JSONEncoder(default=encode_complex).iterencode(2 + 1j))
88
- '[2.0, 1.0]'
89
-
90
-
91
- Using simplejson.tool from the shell to validate and pretty-print::
92
-
93
- $ echo '{"json":"obj"}' | python -m simplejson.tool
94
- {
95
- "json": "obj"
96
- }
97
- $ echo '{ 1.2:3.4}' | python -m simplejson.tool
98
- Expecting property name: line 1 column 2 (char 2)
99
- """
100
- __version__ = '2.0.9'
101
- __all__ = [
102
- 'dump', 'dumps', 'load', 'loads',
103
- 'JSONDecoder', 'JSONEncoder',
104
- ]
105
-
106
- __author__ = 'Bob Ippolito <bob@redivi.com>'
107
-
108
- from decoder import JSONDecoder
109
- from encoder import JSONEncoder
110
-
111
- _default_encoder = JSONEncoder(
112
- skipkeys=False,
113
- ensure_ascii=True,
114
- check_circular=True,
115
- allow_nan=True,
116
- indent=None,
117
- separators=None,
118
- encoding='utf-8',
119
- default=None,
120
- )
121
-
122
- def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
123
- allow_nan=True, cls=None, indent=None, separators=None,
124
- encoding='utf-8', default=None, **kw):
125
- """Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
126
- ``.write()``-supporting file-like object).
127
-
128
- If ``skipkeys`` is true then ``dict`` keys that are not basic types
129
- (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``)
130
- will be skipped instead of raising a ``TypeError``.
131
-
132
- If ``ensure_ascii`` is false, then the some chunks written to ``fp``
133
- may be ``unicode`` instances, subject to normal Python ``str`` to
134
- ``unicode`` coercion rules. Unless ``fp.write()`` explicitly
135
- understands ``unicode`` (as in ``codecs.getwriter()``) this is likely
136
- to cause an error.
137
-
138
- If ``check_circular`` is false, then the circular reference check
139
- for container types will be skipped and a circular reference will
140
- result in an ``OverflowError`` (or worse).
141
-
142
- If ``allow_nan`` is false, then it will be a ``ValueError`` to
143
- serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``)
144
- in strict compliance of the JSON specification, instead of using the
145
- JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
146
-
147
- If ``indent`` is a non-negative integer, then JSON array elements and object
148
- members will be pretty-printed with that indent level. An indent level
149
- of 0 will only insert newlines. ``None`` is the most compact representation.
150
-
151
- If ``separators`` is an ``(item_separator, dict_separator)`` tuple
152
- then it will be used instead of the default ``(', ', ': ')`` separators.
153
- ``(',', ':')`` is the most compact JSON representation.
154
-
155
- ``encoding`` is the character encoding for str instances, default is UTF-8.
156
-
157
- ``default(obj)`` is a function that should return a serializable version
158
- of obj or raise TypeError. The default simply raises TypeError.
159
-
160
- To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
161
- ``.default()`` method to serialize additional types), specify it with
162
- the ``cls`` kwarg.
163
-
164
- """
165
- # cached encoder
166
- if (not skipkeys and ensure_ascii and
167
- check_circular and allow_nan and
168
- cls is None and indent is None and separators is None and
169
- encoding == 'utf-8' and default is None and not kw):
170
- iterable = _default_encoder.iterencode(obj)
171
- else:
172
- if cls is None:
173
- cls = JSONEncoder
174
- iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii,
175
- check_circular=check_circular, allow_nan=allow_nan, indent=indent,
176
- separators=separators, encoding=encoding,
177
- default=default, **kw).iterencode(obj)
178
- # could accelerate with writelines in some versions of Python, at
179
- # a debuggability cost
180
- for chunk in iterable:
181
- fp.write(chunk)
182
-
183
-
184
- def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
185
- allow_nan=True, cls=None, indent=None, separators=None,
186
- encoding='utf-8', default=None, **kw):
187
- """Serialize ``obj`` to a JSON formatted ``str``.
188
-
189
- If ``skipkeys`` is false then ``dict`` keys that are not basic types
190
- (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``)
191
- will be skipped instead of raising a ``TypeError``.
192
-
193
- If ``ensure_ascii`` is false, then the return value will be a
194
- ``unicode`` instance subject to normal Python ``str`` to ``unicode``
195
- coercion rules instead of being escaped to an ASCII ``str``.
196
-
197
- If ``check_circular`` is false, then the circular reference check
198
- for container types will be skipped and a circular reference will
199
- result in an ``OverflowError`` (or worse).
200
-
201
- If ``allow_nan`` is false, then it will be a ``ValueError`` to
202
- serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in
203
- strict compliance of the JSON specification, instead of using the
204
- JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
205
-
206
- If ``indent`` is a non-negative integer, then JSON array elements and
207
- object members will be pretty-printed with that indent level. An indent
208
- level of 0 will only insert newlines. ``None`` is the most compact
209
- representation.
210
-
211
- If ``separators`` is an ``(item_separator, dict_separator)`` tuple
212
- then it will be used instead of the default ``(', ', ': ')`` separators.
213
- ``(',', ':')`` is the most compact JSON representation.
214
-
215
- ``encoding`` is the character encoding for str instances, default is UTF-8.
216
-
217
- ``default(obj)`` is a function that should return a serializable version
218
- of obj or raise TypeError. The default simply raises TypeError.
219
-
220
- To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
221
- ``.default()`` method to serialize additional types), specify it with
222
- the ``cls`` kwarg.
223
-
224
- """
225
- # cached encoder
226
- if (not skipkeys and ensure_ascii and
227
- check_circular and allow_nan and
228
- cls is None and indent is None and separators is None and
229
- encoding == 'utf-8' and default is None and not kw):
230
- return _default_encoder.encode(obj)
231
- if cls is None:
232
- cls = JSONEncoder
233
- return cls(
234
- skipkeys=skipkeys, ensure_ascii=ensure_ascii,
235
- check_circular=check_circular, allow_nan=allow_nan, indent=indent,
236
- separators=separators, encoding=encoding, default=default,
237
- **kw).encode(obj)
238
-
239
-
240
- _default_decoder = JSONDecoder(encoding=None, object_hook=None)
241
-
242
-
243
- def load(fp, encoding=None, cls=None, object_hook=None, parse_float=None,
244
- parse_int=None, parse_constant=None, **kw):
245
- """Deserialize ``fp`` (a ``.read()``-supporting file-like object containing
246
- a JSON document) to a Python object.
247
-
248
- If the contents of ``fp`` is encoded with an ASCII based encoding other
249
- than utf-8 (e.g. latin-1), then an appropriate ``encoding`` name must
250
- be specified. Encodings that are not ASCII based (such as UCS-2) are
251
- not allowed, and should be wrapped with
252
- ``codecs.getreader(fp)(encoding)``, or simply decoded to a ``unicode``
253
- object and passed to ``loads()``
254
-
255
- ``object_hook`` is an optional function that will be called with the
256
- result of any object literal decode (a ``dict``). The return value of
257
- ``object_hook`` will be used instead of the ``dict``. This feature
258
- can be used to implement custom decoders (e.g. JSON-RPC class hinting).
259
-
260
- To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
261
- kwarg.
262
-
263
- """
264
- return loads(fp.read(),
265
- encoding=encoding, cls=cls, object_hook=object_hook,
266
- parse_float=parse_float, parse_int=parse_int,
267
- parse_constant=parse_constant, **kw)
268
-
269
-
270
- def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None,
271
- parse_int=None, parse_constant=None, **kw):
272
- """Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a JSON
273
- document) to a Python object.
274
-
275
- If ``s`` is a ``str`` instance and is encoded with an ASCII based encoding
276
- other than utf-8 (e.g. latin-1) then an appropriate ``encoding`` name
277
- must be specified. Encodings that are not ASCII based (such as UCS-2)
278
- are not allowed and should be decoded to ``unicode`` first.
279
-
280
- ``object_hook`` is an optional function that will be called with the
281
- result of any object literal decode (a ``dict``). The return value of
282
- ``object_hook`` will be used instead of the ``dict``. This feature
283
- can be used to implement custom decoders (e.g. JSON-RPC class hinting).
284
-
285
- ``parse_float``, if specified, will be called with the string
286
- of every JSON float to be decoded. By default this is equivalent to
287
- float(num_str). This can be used to use another datatype or parser
288
- for JSON floats (e.g. decimal.Decimal).
289
-
290
- ``parse_int``, if specified, will be called with the string
291
- of every JSON int to be decoded. By default this is equivalent to
292
- int(num_str). This can be used to use another datatype or parser
293
- for JSON integers (e.g. float).
294
-
295
- ``parse_constant``, if specified, will be called with one of the
296
- following strings: -Infinity, Infinity, NaN, null, true, false.
297
- This can be used to raise an exception if invalid JSON numbers
298
- are encountered.
299
-
300
- To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
301
- kwarg.
302
-
303
- """
304
- if (cls is None and encoding is None and object_hook is None and
305
- parse_int is None and parse_float is None and
306
- parse_constant is None and not kw):
307
- return _default_decoder.decode(s)
308
- if cls is None:
309
- cls = JSONDecoder
310
- if object_hook is not None:
311
- kw['object_hook'] = object_hook
312
- if parse_float is not None:
313
- kw['parse_float'] = parse_float
314
- if parse_int is not None:
315
- kw['parse_int'] = parse_int
316
- if parse_constant is not None:
317
- kw['parse_constant'] = parse_constant
318
- return cls(encoding=encoding, **kw).decode(s)
@@ -1,354 +0,0 @@
1
- """Implementation of JSONDecoder
2
- """
3
- import re
4
- import sys
5
- import struct
6
-
7
- from simplejson.scanner import make_scanner
8
- try:
9
- from simplejson._speedups import scanstring as c_scanstring
10
- except ImportError:
11
- c_scanstring = None
12
-
13
- __all__ = ['JSONDecoder']
14
-
15
- FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL
16
-
17
- def _floatconstants():
18
- _BYTES = '7FF80000000000007FF0000000000000'.decode('hex')
19
- if sys.byteorder != 'big':
20
- _BYTES = _BYTES[:8][::-1] + _BYTES[8:][::-1]
21
- nan, inf = struct.unpack('dd', _BYTES)
22
- return nan, inf, -inf
23
-
24
- NaN, PosInf, NegInf = _floatconstants()
25
-
26
-
27
- def linecol(doc, pos):
28
- lineno = doc.count('\n', 0, pos) + 1
29
- if lineno == 1:
30
- colno = pos
31
- else:
32
- colno = pos - doc.rindex('\n', 0, pos)
33
- return lineno, colno
34
-
35
-
36
- def errmsg(msg, doc, pos, end=None):
37
- # Note that this function is called from _speedups
38
- lineno, colno = linecol(doc, pos)
39
- if end is None:
40
- #fmt = '{0}: line {1} column {2} (char {3})'
41
- #return fmt.format(msg, lineno, colno, pos)
42
- fmt = '%s: line %d column %d (char %d)'
43
- return fmt % (msg, lineno, colno, pos)
44
- endlineno, endcolno = linecol(doc, end)
45
- #fmt = '{0}: line {1} column {2} - line {3} column {4} (char {5} - {6})'
46
- #return fmt.format(msg, lineno, colno, endlineno, endcolno, pos, end)
47
- fmt = '%s: line %d column %d - line %d column %d (char %d - %d)'
48
- return fmt % (msg, lineno, colno, endlineno, endcolno, pos, end)
49
-
50
-
51
- _CONSTANTS = {
52
- '-Infinity': NegInf,
53
- 'Infinity': PosInf,
54
- 'NaN': NaN,
55
- }
56
-
57
- STRINGCHUNK = re.compile(r'(.*?)(["\\\x00-\x1f])', FLAGS)
58
- BACKSLASH = {
59
- '"': u'"', '\\': u'\\', '/': u'/',
60
- 'b': u'\b', 'f': u'\f', 'n': u'\n', 'r': u'\r', 't': u'\t',
61
- }
62
-
63
- DEFAULT_ENCODING = "utf-8"
64
-
65
- def py_scanstring(s, end, encoding=None, strict=True, _b=BACKSLASH, _m=STRINGCHUNK.match):
66
- """Scan the string s for a JSON string. End is the index of the
67
- character in s after the quote that started the JSON string.
68
- Unescapes all valid JSON string escape sequences and raises ValueError
69
- on attempt to decode an invalid string. If strict is False then literal
70
- control characters are allowed in the string.
71
-
72
- Returns a tuple of the decoded string and the index of the character in s
73
- after the end quote."""
74
- if encoding is None:
75
- encoding = DEFAULT_ENCODING
76
- chunks = []
77
- _append = chunks.append
78
- begin = end - 1
79
- while 1:
80
- chunk = _m(s, end)
81
- if chunk is None:
82
- raise ValueError(
83
- errmsg("Unterminated string starting at", s, begin))
84
- end = chunk.end()
85
- content, terminator = chunk.groups()
86
- # Content is contains zero or more unescaped string characters
87
- if content:
88
- if not isinstance(content, unicode):
89
- content = unicode(content, encoding)
90
- _append(content)
91
- # Terminator is the end of string, a literal control character,
92
- # or a backslash denoting that an escape sequence follows
93
- if terminator == '"':
94
- break
95
- elif terminator != '\\':
96
- if strict:
97
- msg = "Invalid control character %r at" % (terminator,)
98
- #msg = "Invalid control character {0!r} at".format(terminator)
99
- raise ValueError(errmsg(msg, s, end))
100
- else:
101
- _append(terminator)
102
- continue
103
- try:
104
- esc = s[end]
105
- except IndexError:
106
- raise ValueError(
107
- errmsg("Unterminated string starting at", s, begin))
108
- # If not a unicode escape sequence, must be in the lookup table
109
- if esc != 'u':
110
- try:
111
- char = _b[esc]
112
- except KeyError:
113
- msg = "Invalid \\escape: " + repr(esc)
114
- raise ValueError(errmsg(msg, s, end))
115
- end += 1
116
- else:
117
- # Unicode escape sequence
118
- esc = s[end + 1:end + 5]
119
- next_end = end + 5
120
- if len(esc) != 4:
121
- msg = "Invalid \\uXXXX escape"
122
- raise ValueError(errmsg(msg, s, end))
123
- uni = int(esc, 16)
124
- # Check for surrogate pair on UCS-4 systems
125
- if 0xd800 <= uni <= 0xdbff and sys.maxunicode > 65535:
126
- msg = "Invalid \\uXXXX\\uXXXX surrogate pair"
127
- if not s[end + 5:end + 7] == '\\u':
128
- raise ValueError(errmsg(msg, s, end))
129
- esc2 = s[end + 7:end + 11]
130
- if len(esc2) != 4:
131
- raise ValueError(errmsg(msg, s, end))
132
- uni2 = int(esc2, 16)
133
- uni = 0x10000 + (((uni - 0xd800) << 10) | (uni2 - 0xdc00))
134
- next_end += 6
135
- char = unichr(uni)
136
- end = next_end
137
- # Append the unescaped character
138
- _append(char)
139
- return u''.join(chunks), end
140
-
141
-
142
- # Use speedup if available
143
- scanstring = c_scanstring or py_scanstring
144
-
145
- WHITESPACE = re.compile(r'[ \t\n\r]*', FLAGS)
146
- WHITESPACE_STR = ' \t\n\r'
147
-
148
- def JSONObject((s, end), encoding, strict, scan_once, object_hook, _w=WHITESPACE.match, _ws=WHITESPACE_STR):
149
- pairs = {}
150
- # Use a slice to prevent IndexError from being raised, the following
151
- # check will raise a more specific ValueError if the string is empty
152
- nextchar = s[end:end + 1]
153
- # Normally we expect nextchar == '"'
154
- if nextchar != '"':
155
- if nextchar in _ws:
156
- end = _w(s, end).end()
157
- nextchar = s[end:end + 1]
158
- # Trivial empty object
159
- if nextchar == '}':
160
- return pairs, end + 1
161
- elif nextchar != '"':
162
- raise ValueError(errmsg("Expecting property name", s, end))
163
- end += 1
164
- while True:
165
- key, end = scanstring(s, end, encoding, strict)
166
-
167
- # To skip some function call overhead we optimize the fast paths where
168
- # the JSON key separator is ": " or just ":".
169
- if s[end:end + 1] != ':':
170
- end = _w(s, end).end()
171
- if s[end:end + 1] != ':':
172
- raise ValueError(errmsg("Expecting : delimiter", s, end))
173
-
174
- end += 1
175
-
176
- try:
177
- if s[end] in _ws:
178
- end += 1
179
- if s[end] in _ws:
180
- end = _w(s, end + 1).end()
181
- except IndexError:
182
- pass
183
-
184
- try:
185
- value, end = scan_once(s, end)
186
- except StopIteration:
187
- raise ValueError(errmsg("Expecting object", s, end))
188
- pairs[key] = value
189
-
190
- try:
191
- nextchar = s[end]
192
- if nextchar in _ws:
193
- end = _w(s, end + 1).end()
194
- nextchar = s[end]
195
- except IndexError:
196
- nextchar = ''
197
- end += 1
198
-
199
- if nextchar == '}':
200
- break
201
- elif nextchar != ',':
202
- raise ValueError(errmsg("Expecting , delimiter", s, end - 1))
203
-
204
- try:
205
- nextchar = s[end]
206
- if nextchar in _ws:
207
- end += 1
208
- nextchar = s[end]
209
- if nextchar in _ws:
210
- end = _w(s, end + 1).end()
211
- nextchar = s[end]
212
- except IndexError:
213
- nextchar = ''
214
-
215
- end += 1
216
- if nextchar != '"':
217
- raise ValueError(errmsg("Expecting property name", s, end - 1))
218
-
219
- if object_hook is not None:
220
- pairs = object_hook(pairs)
221
- return pairs, end
222
-
223
- def JSONArray((s, end), scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR):
224
- values = []
225
- nextchar = s[end:end + 1]
226
- if nextchar in _ws:
227
- end = _w(s, end + 1).end()
228
- nextchar = s[end:end + 1]
229
- # Look-ahead for trivial empty array
230
- if nextchar == ']':
231
- return values, end + 1
232
- _append = values.append
233
- while True:
234
- try:
235
- value, end = scan_once(s, end)
236
- except StopIteration:
237
- raise ValueError(errmsg("Expecting object", s, end))
238
- _append(value)
239
- nextchar = s[end:end + 1]
240
- if nextchar in _ws:
241
- end = _w(s, end + 1).end()
242
- nextchar = s[end:end + 1]
243
- end += 1
244
- if nextchar == ']':
245
- break
246
- elif nextchar != ',':
247
- raise ValueError(errmsg("Expecting , delimiter", s, end))
248
-
249
- try:
250
- if s[end] in _ws:
251
- end += 1
252
- if s[end] in _ws:
253
- end = _w(s, end + 1).end()
254
- except IndexError:
255
- pass
256
-
257
- return values, end
258
-
259
- class JSONDecoder(object):
260
- """Simple JSON <http://json.org> decoder
261
-
262
- Performs the following translations in decoding by default:
263
-
264
- +---------------+-------------------+
265
- | JSON | Python |
266
- +===============+===================+
267
- | object | dict |
268
- +---------------+-------------------+
269
- | array | list |
270
- +---------------+-------------------+
271
- | string | unicode |
272
- +---------------+-------------------+
273
- | number (int) | int, long |
274
- +---------------+-------------------+
275
- | number (real) | float |
276
- +---------------+-------------------+
277
- | true | True |
278
- +---------------+-------------------+
279
- | false | False |
280
- +---------------+-------------------+
281
- | null | None |
282
- +---------------+-------------------+
283
-
284
- It also understands ``NaN``, ``Infinity``, and ``-Infinity`` as
285
- their corresponding ``float`` values, which is outside the JSON spec.
286
-
287
- """
288
-
289
- def __init__(self, encoding=None, object_hook=None, parse_float=None,
290
- parse_int=None, parse_constant=None, strict=True):
291
- """``encoding`` determines the encoding used to interpret any ``str``
292
- objects decoded by this instance (utf-8 by default). It has no
293
- effect when decoding ``unicode`` objects.
294
-
295
- Note that currently only encodings that are a superset of ASCII work,
296
- strings of other encodings should be passed in as ``unicode``.
297
-
298
- ``object_hook``, if specified, will be called with the result
299
- of every JSON object decoded and its return value will be used in
300
- place of the given ``dict``. This can be used to provide custom
301
- deserializations (e.g. to support JSON-RPC class hinting).
302
-
303
- ``parse_float``, if specified, will be called with the string
304
- of every JSON float to be decoded. By default this is equivalent to
305
- float(num_str). This can be used to use another datatype or parser
306
- for JSON floats (e.g. decimal.Decimal).
307
-
308
- ``parse_int``, if specified, will be called with the string
309
- of every JSON int to be decoded. By default this is equivalent to
310
- int(num_str). This can be used to use another datatype or parser
311
- for JSON integers (e.g. float).
312
-
313
- ``parse_constant``, if specified, will be called with one of the
314
- following strings: -Infinity, Infinity, NaN.
315
- This can be used to raise an exception if invalid JSON numbers
316
- are encountered.
317
-
318
- """
319
- self.encoding = encoding
320
- self.object_hook = object_hook
321
- self.parse_float = parse_float or float
322
- self.parse_int = parse_int or int
323
- self.parse_constant = parse_constant or _CONSTANTS.__getitem__
324
- self.strict = strict
325
- self.parse_object = JSONObject
326
- self.parse_array = JSONArray
327
- self.parse_string = scanstring
328
- self.scan_once = make_scanner(self)
329
-
330
- def decode(self, s, _w=WHITESPACE.match):
331
- """Return the Python representation of ``s`` (a ``str`` or ``unicode``
332
- instance containing a JSON document)
333
-
334
- """
335
- obj, end = self.raw_decode(s, idx=_w(s, 0).end())
336
- end = _w(s, end).end()
337
- if end != len(s):
338
- raise ValueError(errmsg("Extra data", s, end, len(s)))
339
- return obj
340
-
341
- def raw_decode(self, s, idx=0):
342
- """Decode a JSON document from ``s`` (a ``str`` or ``unicode`` beginning
343
- with a JSON document) and return a 2-tuple of the Python
344
- representation and the index in ``s`` where the document ended.
345
-
346
- This can be used to decode a JSON document from a string that may
347
- have extraneous data at the end.
348
-
349
- """
350
- try:
351
- obj, end = self.scan_once(s, idx)
352
- except StopIteration:
353
- raise ValueError("No JSON object could be decoded")
354
- return obj, end