mirror of
https://github.com/facebook/sapling.git
synced 2024-10-13 02:07:31 +03:00
9dc21f8d0b
Summary: D13853115 adds `edenscm/` to `sys.path` and code still uses `import mercurial`. That has nasty problems if both `import mercurial` and `import edenscm.mercurial` are used, because Python would think `mercurial.foo` and `edenscm.mercurial.foo` are different modules so code like `try: ... except mercurial.error.Foo: ...`, or `isinstance(x, mercurial.foo.Bar)` would fail to handle the `edenscm.mercurial` version. There are also some module-level states (ex. `extensions._extensions`) that would cause trouble if they have multiple versions in a single process. Change imports to use the `edenscm` so ideally the `mercurial` is no longer imported at all. Add checks in extensions.py to catch unexpected extensions importing modules from the old (wrong) locations when running tests. Reviewed By: phillco Differential Revision: D13868981 fbshipit-source-id: f4e2513766957fd81d85407994f7521a08e4de48
73 lines
2.3 KiB
Python
73 lines
2.3 KiB
Python
# json.py - json encoding
|
|
#
|
|
# Copyright 2018 Facebook, Inc.
|
|
#
|
|
# This software may be used and distributed according to the terms of the
|
|
# GNU General Public License version 2 or any later version.
|
|
|
|
from __future__ import absolute_import
|
|
|
|
import json as _sysjson
|
|
|
|
from edenscm.mercurial import encoding, error, pycompat, util
|
|
|
|
|
|
try:
|
|
long
|
|
except NameError:
|
|
long = int
|
|
|
|
|
|
def dumps(obj, paranoid=True):
|
|
if obj is None:
|
|
return "null"
|
|
elif obj is False:
|
|
return "false"
|
|
elif obj is True:
|
|
return "true"
|
|
elif isinstance(obj, (int, long, float)):
|
|
return pycompat.bytestr(obj)
|
|
elif isinstance(obj, bytes):
|
|
return '"%s"' % encoding.jsonescape(obj, paranoid=paranoid)
|
|
elif isinstance(obj, str):
|
|
# This branch is unreachable on Python 2, because bytes == str
|
|
# and we'll return in the next-earlier block in the elif
|
|
# ladder. On Python 3, this helps us catch bugs before they
|
|
# hurt someone.
|
|
raise error.ProgrammingError(
|
|
"Mercurial only does output with bytes on Python 3: %r" % obj
|
|
)
|
|
elif util.safehasattr(obj, "keys"):
|
|
out = [
|
|
'"%s": %s' % (encoding.jsonescape(k, paranoid=paranoid), dumps(v, paranoid))
|
|
for k, v in sorted(obj.iteritems())
|
|
]
|
|
return "{" + ", ".join(out) + "}"
|
|
elif util.safehasattr(obj, "__iter__"):
|
|
out = [dumps(i, paranoid) for i in obj]
|
|
return "[" + ", ".join(out) + "]"
|
|
else:
|
|
raise TypeError("cannot encode type %s" % obj.__class__.__name__)
|
|
|
|
|
|
def _rapply(f, xs):
|
|
if xs is None:
|
|
# assume None means non-value of optional data
|
|
return xs
|
|
if isinstance(xs, (list, set, tuple)):
|
|
return type(xs)(_rapply(f, x) for x in xs)
|
|
if isinstance(xs, dict):
|
|
return type(xs)((_rapply(f, k), _rapply(f, v)) for k, v in xs.items())
|
|
return f(xs)
|
|
|
|
|
|
def loads(string):
|
|
"""Like stdlib json.loads, but results are bytes instead of unicode
|
|
|
|
Warning: this does not round-trip with "dumps". "dumps" supports non-utf8
|
|
binary content that is unsupported by this function.
|
|
"""
|
|
# XXX: This should round-trip with "dumps". But it might be non-trivial to
|
|
# do so.
|
|
return _rapply(lambda s: bytes(s.encode("utf-8")), _sysjson.loads(string))
|