mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Merge pull request #3917 from youknowone/update-unittest
Update more tests
This commit is contained in:
186
Lib/datetime.py
vendored
186
Lib/datetime.py
vendored
@@ -4,9 +4,14 @@ See http://www.iana.org/time-zones/repository/tz-link.html for
|
||||
time zone and DST data sources.
|
||||
"""
|
||||
|
||||
__all__ = ("date", "datetime", "time", "timedelta", "timezone", "tzinfo",
|
||||
"MINYEAR", "MAXYEAR")
|
||||
|
||||
|
||||
import time as _time
|
||||
import math as _math
|
||||
import sys
|
||||
from operator import index as _index
|
||||
|
||||
def _cmp(x, y):
|
||||
return 0 if x == y else 1 if x > y else -1
|
||||
@@ -376,27 +381,10 @@ def _check_utc_offset(name, offset):
|
||||
"-timedelta(hours=24) and timedelta(hours=24)" %
|
||||
(name, offset))
|
||||
|
||||
def _check_int_field(value):
|
||||
if isinstance(value, int):
|
||||
return value
|
||||
if not isinstance(value, float):
|
||||
try:
|
||||
value = value.__int__()
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
if isinstance(value, int):
|
||||
return value
|
||||
raise TypeError('__int__ returned non-int (type %s)' %
|
||||
type(value).__name__)
|
||||
raise TypeError('an integer is required (got type %s)' %
|
||||
type(value).__name__)
|
||||
raise TypeError('integer argument expected, got float')
|
||||
|
||||
def _check_date_fields(year, month, day):
|
||||
year = _check_int_field(year)
|
||||
month = _check_int_field(month)
|
||||
day = _check_int_field(day)
|
||||
year = _index(year)
|
||||
month = _index(month)
|
||||
day = _index(day)
|
||||
if not MINYEAR <= year <= MAXYEAR:
|
||||
raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), year)
|
||||
if not 1 <= month <= 12:
|
||||
@@ -407,10 +395,10 @@ def _check_date_fields(year, month, day):
|
||||
return year, month, day
|
||||
|
||||
def _check_time_fields(hour, minute, second, microsecond, fold):
|
||||
hour = _check_int_field(hour)
|
||||
minute = _check_int_field(minute)
|
||||
second = _check_int_field(second)
|
||||
microsecond = _check_int_field(microsecond)
|
||||
hour = _index(hour)
|
||||
minute = _index(minute)
|
||||
second = _index(second)
|
||||
microsecond = _index(microsecond)
|
||||
if not 0 <= hour <= 23:
|
||||
raise ValueError('hour must be in 0..23', hour)
|
||||
if not 0 <= minute <= 59:
|
||||
@@ -718,31 +706,31 @@ class timedelta:
|
||||
if isinstance(other, timedelta):
|
||||
return self._cmp(other) == 0
|
||||
else:
|
||||
return False
|
||||
return NotImplemented
|
||||
|
||||
def __le__(self, other):
|
||||
if isinstance(other, timedelta):
|
||||
return self._cmp(other) <= 0
|
||||
else:
|
||||
_cmperror(self, other)
|
||||
return NotImplemented
|
||||
|
||||
def __lt__(self, other):
|
||||
if isinstance(other, timedelta):
|
||||
return self._cmp(other) < 0
|
||||
else:
|
||||
_cmperror(self, other)
|
||||
return NotImplemented
|
||||
|
||||
def __ge__(self, other):
|
||||
if isinstance(other, timedelta):
|
||||
return self._cmp(other) >= 0
|
||||
else:
|
||||
_cmperror(self, other)
|
||||
return NotImplemented
|
||||
|
||||
def __gt__(self, other):
|
||||
if isinstance(other, timedelta):
|
||||
return self._cmp(other) > 0
|
||||
else:
|
||||
_cmperror(self, other)
|
||||
return NotImplemented
|
||||
|
||||
def _cmp(self, other):
|
||||
assert isinstance(other, timedelta)
|
||||
@@ -869,6 +857,40 @@ class date:
|
||||
except Exception:
|
||||
raise ValueError(f'Invalid isoformat string: {date_string!r}')
|
||||
|
||||
@classmethod
|
||||
def fromisocalendar(cls, year, week, day):
|
||||
"""Construct a date from the ISO year, week number and weekday.
|
||||
|
||||
This is the inverse of the date.isocalendar() function"""
|
||||
# Year is bounded this way because 9999-12-31 is (9999, 52, 5)
|
||||
if not MINYEAR <= year <= MAXYEAR:
|
||||
raise ValueError(f"Year is out of range: {year}")
|
||||
|
||||
if not 0 < week < 53:
|
||||
out_of_range = True
|
||||
|
||||
if week == 53:
|
||||
# ISO years have 53 weeks in them on years starting with a
|
||||
# Thursday and leap years starting on a Wednesday
|
||||
first_weekday = _ymd2ord(year, 1, 1) % 7
|
||||
if (first_weekday == 4 or (first_weekday == 3 and
|
||||
_is_leap(year))):
|
||||
out_of_range = False
|
||||
|
||||
if out_of_range:
|
||||
raise ValueError(f"Invalid week: {week}")
|
||||
|
||||
if not 0 < day < 8:
|
||||
raise ValueError(f"Invalid weekday: {day} (range is [1, 7])")
|
||||
|
||||
# Now compute the offset from (Y, 1, 1) in days:
|
||||
day_offset = (week - 1) * 7 + (day - 1)
|
||||
|
||||
# Calculate the ordinal day for monday, week 1
|
||||
day_1 = _isoweek1monday(year)
|
||||
ord_day = day_1 + day_offset
|
||||
|
||||
return cls(*_ord2ymd(ord_day))
|
||||
|
||||
# Conversions to string
|
||||
|
||||
@@ -1014,7 +1036,7 @@ class date:
|
||||
if isinstance(other, timedelta):
|
||||
o = self.toordinal() + other.days
|
||||
if 0 < o <= _MAXORDINAL:
|
||||
return date.fromordinal(o)
|
||||
return type(self).fromordinal(o)
|
||||
raise OverflowError("result out of range")
|
||||
return NotImplemented
|
||||
|
||||
@@ -1042,7 +1064,7 @@ class date:
|
||||
return self.toordinal() % 7 or 7
|
||||
|
||||
def isocalendar(self):
|
||||
"""Return a 3-tuple containing ISO year, week number, and weekday.
|
||||
"""Return a named tuple containing ISO year, week number, and weekday.
|
||||
|
||||
The first ISO week of the year is the (Mon-Sun) week
|
||||
containing the year's first Thursday; everything else derives
|
||||
@@ -1067,7 +1089,7 @@ class date:
|
||||
if today >= _isoweek1monday(year+1):
|
||||
year += 1
|
||||
week = 0
|
||||
return year, week+1, day+1
|
||||
return _IsoCalendarDate(year, week+1, day+1)
|
||||
|
||||
# Pickle support.
|
||||
|
||||
@@ -1157,6 +1179,36 @@ class tzinfo:
|
||||
else:
|
||||
return (self.__class__, args, state)
|
||||
|
||||
|
||||
class IsoCalendarDate(tuple):
|
||||
|
||||
def __new__(cls, year, week, weekday, /):
|
||||
return super().__new__(cls, (year, week, weekday))
|
||||
|
||||
@property
|
||||
def year(self):
|
||||
return self[0]
|
||||
|
||||
@property
|
||||
def week(self):
|
||||
return self[1]
|
||||
|
||||
@property
|
||||
def weekday(self):
|
||||
return self[2]
|
||||
|
||||
def __reduce__(self):
|
||||
# This code is intended to pickle the object without making the
|
||||
# class public. See https://bugs.python.org/msg352381
|
||||
return (tuple, (tuple(self),))
|
||||
|
||||
def __repr__(self):
|
||||
return (f'{self.__class__.__name__}'
|
||||
f'(year={self[0]}, week={self[1]}, weekday={self[2]})')
|
||||
|
||||
|
||||
_IsoCalendarDate = IsoCalendarDate
|
||||
del IsoCalendarDate
|
||||
_tzinfo_class = tzinfo
|
||||
|
||||
class time:
|
||||
@@ -1261,31 +1313,31 @@ class time:
|
||||
if isinstance(other, time):
|
||||
return self._cmp(other, allow_mixed=True) == 0
|
||||
else:
|
||||
return False
|
||||
return NotImplemented
|
||||
|
||||
def __le__(self, other):
|
||||
if isinstance(other, time):
|
||||
return self._cmp(other) <= 0
|
||||
else:
|
||||
_cmperror(self, other)
|
||||
return NotImplemented
|
||||
|
||||
def __lt__(self, other):
|
||||
if isinstance(other, time):
|
||||
return self._cmp(other) < 0
|
||||
else:
|
||||
_cmperror(self, other)
|
||||
return NotImplemented
|
||||
|
||||
def __ge__(self, other):
|
||||
if isinstance(other, time):
|
||||
return self._cmp(other) >= 0
|
||||
else:
|
||||
_cmperror(self, other)
|
||||
return NotImplemented
|
||||
|
||||
def __gt__(self, other):
|
||||
if isinstance(other, time):
|
||||
return self._cmp(other) > 0
|
||||
else:
|
||||
_cmperror(self, other)
|
||||
return NotImplemented
|
||||
|
||||
def _cmp(self, other, allow_mixed=False):
|
||||
assert isinstance(other, time)
|
||||
@@ -1369,7 +1421,8 @@ class time:
|
||||
part is omitted if self.microsecond == 0.
|
||||
|
||||
The optional argument timespec specifies the number of additional
|
||||
terms of the time to include.
|
||||
terms of the time to include. Valid options are 'auto', 'hours',
|
||||
'minutes', 'seconds', 'milliseconds' and 'microseconds'.
|
||||
"""
|
||||
s = _format_time(self._hour, self._minute, self._second,
|
||||
self._microsecond, timespec)
|
||||
@@ -1495,7 +1548,7 @@ class time:
|
||||
self._tzinfo = tzinfo
|
||||
|
||||
def __reduce_ex__(self, protocol):
|
||||
return (time, self._getstate(protocol))
|
||||
return (self.__class__, self._getstate(protocol))
|
||||
|
||||
def __reduce__(self):
|
||||
return self.__reduce_ex__(2)
|
||||
@@ -1506,6 +1559,7 @@ time.min = time(0, 0, 0)
|
||||
time.max = time(23, 59, 59, 999999)
|
||||
time.resolution = timedelta(microseconds=1)
|
||||
|
||||
|
||||
class datetime(date):
|
||||
"""datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])
|
||||
|
||||
@@ -1598,7 +1652,7 @@ class datetime(date):
|
||||
y, m, d, hh, mm, ss, weekday, jday, dst = converter(t)
|
||||
ss = min(ss, 59) # clamp out leap seconds if the platform has them
|
||||
result = cls(y, m, d, hh, mm, ss, us, tz)
|
||||
if tz is None:
|
||||
if tz is None and not utc:
|
||||
# As of version 2015f max fold in IANA database is
|
||||
# 23 hours at 1969-09-30 13:00:00 in Kwajalein.
|
||||
# Let's probe 24 hours in the past to detect a transition:
|
||||
@@ -1619,7 +1673,7 @@ class datetime(date):
|
||||
probe2 = cls(y, m, d, hh, mm, ss, us, tz)
|
||||
if probe2 == result:
|
||||
result._fold = 1
|
||||
else:
|
||||
elif tz is not None:
|
||||
result = tz.fromutc(result)
|
||||
return result
|
||||
|
||||
@@ -1798,17 +1852,10 @@ class datetime(date):
|
||||
ts = (self - _EPOCH) // timedelta(seconds=1)
|
||||
localtm = _time.localtime(ts)
|
||||
local = datetime(*localtm[:6])
|
||||
try:
|
||||
# Extract TZ data if available
|
||||
gmtoff = localtm.tm_gmtoff
|
||||
zone = localtm.tm_zone
|
||||
except AttributeError:
|
||||
delta = local - datetime(*_time.gmtime(ts)[:6])
|
||||
zone = _time.strftime('%Z', localtm)
|
||||
tz = timezone(delta, zone)
|
||||
else:
|
||||
tz = timezone(timedelta(seconds=gmtoff), zone)
|
||||
return tz
|
||||
# Extract TZ data
|
||||
gmtoff = localtm.tm_gmtoff
|
||||
zone = localtm.tm_zone
|
||||
return timezone(timedelta(seconds=gmtoff), zone)
|
||||
|
||||
def astimezone(self, tz=None):
|
||||
if tz is None:
|
||||
@@ -1860,7 +1907,8 @@ class datetime(date):
|
||||
time, default 'T'.
|
||||
|
||||
The optional argument timespec specifies the number of additional
|
||||
terms of the time to include.
|
||||
terms of the time to include. Valid options are 'auto', 'hours',
|
||||
'minutes', 'seconds', 'milliseconds' and 'microseconds'.
|
||||
"""
|
||||
s = ("%04d-%02d-%02d%c" % (self._year, self._month, self._day, sep) +
|
||||
_format_time(self._hour, self._minute, self._second,
|
||||
@@ -2031,10 +2079,10 @@ class datetime(date):
|
||||
hour, rem = divmod(delta.seconds, 3600)
|
||||
minute, second = divmod(rem, 60)
|
||||
if 0 < delta.days <= _MAXORDINAL:
|
||||
return datetime.combine(date.fromordinal(delta.days),
|
||||
time(hour, minute, second,
|
||||
delta.microseconds,
|
||||
tzinfo=self._tzinfo))
|
||||
return type(self).combine(date.fromordinal(delta.days),
|
||||
time(hour, minute, second,
|
||||
delta.microseconds,
|
||||
tzinfo=self._tzinfo))
|
||||
raise OverflowError("result out of range")
|
||||
|
||||
__radd__ = __add__
|
||||
@@ -2133,6 +2181,7 @@ def _isoweek1monday(year):
|
||||
week1monday += 7
|
||||
return week1monday
|
||||
|
||||
|
||||
class timezone(tzinfo):
|
||||
__slots__ = '_offset', '_name'
|
||||
|
||||
@@ -2167,9 +2216,9 @@ class timezone(tzinfo):
|
||||
return (self._offset, self._name)
|
||||
|
||||
def __eq__(self, other):
|
||||
if type(other) != timezone:
|
||||
return False
|
||||
return self._offset == other._offset
|
||||
if isinstance(other, timezone):
|
||||
return self._offset == other._offset
|
||||
return NotImplemented
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self._offset)
|
||||
@@ -2226,7 +2275,7 @@ class timezone(tzinfo):
|
||||
raise TypeError("fromutc() argument must be a datetime instance"
|
||||
" or None")
|
||||
|
||||
_maxoffset = timedelta(hours=23, minutes=59)
|
||||
_maxoffset = timedelta(hours=24, microseconds=-1)
|
||||
_minoffset = -_maxoffset
|
||||
|
||||
@staticmethod
|
||||
@@ -2250,8 +2299,11 @@ class timezone(tzinfo):
|
||||
return f'UTC{sign}{hours:02d}:{minutes:02d}'
|
||||
|
||||
timezone.utc = timezone._create(timedelta(0))
|
||||
timezone.min = timezone._create(timezone._minoffset)
|
||||
timezone.max = timezone._create(timezone._maxoffset)
|
||||
# bpo-37642: These attributes are rounded to the nearest minute for backwards
|
||||
# compatibility, even though the constructor will accept a wider range of
|
||||
# values. This may change in the future.
|
||||
timezone.min = timezone._create(-timedelta(hours=23, minutes=59))
|
||||
timezone.max = timezone._create(timedelta(hours=23, minutes=59))
|
||||
_EPOCH = datetime(1970, 1, 1, tzinfo=timezone.utc)
|
||||
|
||||
# Some time zone algebra. For a datetime x, let
|
||||
@@ -2275,7 +2327,7 @@ _EPOCH = datetime(1970, 1, 1, tzinfo=timezone.utc)
|
||||
# This is again a requirement for a sane tzinfo class.
|
||||
#
|
||||
# 4. (x+k).s = x.s
|
||||
# This follows from #2, and that datimetimetz+timedelta preserves tzinfo.
|
||||
# This follows from #2, and that datetime.timetz+timedelta preserves tzinfo.
|
||||
#
|
||||
# 5. (x+k).n = x.n + k
|
||||
# Again follows from how arithmetic is defined.
|
||||
@@ -2458,13 +2510,13 @@ else:
|
||||
# Clean up unused names
|
||||
del (_DAYNAMES, _DAYS_BEFORE_MONTH, _DAYS_IN_MONTH, _DI100Y, _DI400Y,
|
||||
_DI4Y, _EPOCH, _MAXORDINAL, _MONTHNAMES, _build_struct_time,
|
||||
_check_date_fields, _check_int_field, _check_time_fields,
|
||||
_check_date_fields, _check_time_fields,
|
||||
_check_tzinfo_arg, _check_tzname, _check_utc_offset, _cmp, _cmperror,
|
||||
_date_class, _days_before_month, _days_before_year, _days_in_month,
|
||||
_format_time, _format_offset, _is_leap, _isoweek1monday, _math,
|
||||
_format_time, _format_offset, _index, _is_leap, _isoweek1monday, _math,
|
||||
_ord2ymd, _time, _time_class, _tzinfo_class, _wrap_strftime, _ymd2ord,
|
||||
_divide_and_round, _parse_isoformat_date, _parse_isoformat_time,
|
||||
_parse_hh_mm_ss_ff)
|
||||
_parse_hh_mm_ss_ff, _IsoCalendarDate)
|
||||
# XXX Since import * above excludes names that start with _,
|
||||
# docstring does not get overwritten. In the future, it may be
|
||||
# appropriate to maintain a single module level docstring and
|
||||
|
||||
15
Lib/json/__init__.py
vendored
15
Lib/json/__init__.py
vendored
@@ -133,7 +133,7 @@ def dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True,
|
||||
|
||||
If ``check_circular`` is false, then the circular reference check
|
||||
for container types will be skipped and a circular reference will
|
||||
result in an ``OverflowError`` (or worse).
|
||||
result in an ``RecursionError`` (or worse).
|
||||
|
||||
If ``allow_nan`` is false, then it will be a ``ValueError`` to
|
||||
serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``)
|
||||
@@ -195,7 +195,7 @@ def dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True,
|
||||
|
||||
If ``check_circular`` is false, then the circular reference check
|
||||
for container types will be skipped and a circular reference will
|
||||
result in an ``OverflowError`` (or worse).
|
||||
result in an ``RecursionError`` (or worse).
|
||||
|
||||
If ``allow_nan`` is false, then it will be a ``ValueError`` to
|
||||
serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in
|
||||
@@ -329,8 +329,6 @@ def loads(s, *, cls=None, object_hook=None, parse_float=None,
|
||||
|
||||
To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
|
||||
kwarg; otherwise ``JSONDecoder`` is used.
|
||||
|
||||
The ``encoding`` argument is ignored and deprecated since Python 3.1.
|
||||
"""
|
||||
if isinstance(s, str):
|
||||
if s.startswith('\ufeff'):
|
||||
@@ -342,15 +340,6 @@ def loads(s, *, cls=None, object_hook=None, parse_float=None,
|
||||
f'not {s.__class__.__name__}')
|
||||
s = s.decode(detect_encoding(s), 'surrogatepass')
|
||||
|
||||
if "encoding" in kw:
|
||||
import warnings
|
||||
warnings.warn(
|
||||
"'encoding' is ignored and deprecated. It will be removed in Python 3.9",
|
||||
DeprecationWarning,
|
||||
stacklevel=2
|
||||
)
|
||||
del kw['encoding']
|
||||
|
||||
if (cls is None and object_hook is None and
|
||||
parse_int is None and parse_float is None and
|
||||
parse_constant is None and object_pairs_hook is None and not kw):
|
||||
|
||||
2
Lib/json/encoder.py
vendored
2
Lib/json/encoder.py
vendored
@@ -116,7 +116,7 @@ class JSONEncoder(object):
|
||||
|
||||
If check_circular is true, then lists, dicts, and custom encoded
|
||||
objects will be checked for circular references during encoding to
|
||||
prevent an infinite recursion (which would cause an OverflowError).
|
||||
prevent an infinite recursion (which would cause an RecursionError).
|
||||
Otherwise, no such check takes place.
|
||||
|
||||
If allow_nan is true, then NaN, Infinity, and -Infinity will be
|
||||
|
||||
58
Lib/json/tool.py
vendored
58
Lib/json/tool.py
vendored
@@ -13,6 +13,7 @@ Usage::
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def main():
|
||||
@@ -25,31 +26,60 @@ def main():
|
||||
help='a JSON file to be validated or pretty-printed',
|
||||
default=sys.stdin)
|
||||
parser.add_argument('outfile', nargs='?',
|
||||
type=argparse.FileType('w', encoding="utf-8"),
|
||||
type=Path,
|
||||
help='write the output of infile to outfile',
|
||||
default=sys.stdout)
|
||||
default=None)
|
||||
parser.add_argument('--sort-keys', action='store_true', default=False,
|
||||
help='sort the output of dictionaries alphabetically by key')
|
||||
parser.add_argument('--no-ensure-ascii', dest='ensure_ascii', action='store_false',
|
||||
help='disable escaping of non-ASCII characters')
|
||||
parser.add_argument('--json-lines', action='store_true', default=False,
|
||||
help='parse input using the jsonlines format')
|
||||
help='parse input using the JSON Lines format. '
|
||||
'Use with --no-indent or --compact to produce valid JSON Lines output.')
|
||||
group = parser.add_mutually_exclusive_group()
|
||||
group.add_argument('--indent', default=4, type=int,
|
||||
help='separate items with newlines and use this number '
|
||||
'of spaces for indentation')
|
||||
group.add_argument('--tab', action='store_const', dest='indent',
|
||||
const='\t', help='separate items with newlines and use '
|
||||
'tabs for indentation')
|
||||
group.add_argument('--no-indent', action='store_const', dest='indent',
|
||||
const=None,
|
||||
help='separate items with spaces rather than newlines')
|
||||
group.add_argument('--compact', action='store_true',
|
||||
help='suppress all whitespace separation (most compact)')
|
||||
options = parser.parse_args()
|
||||
|
||||
infile = options.infile
|
||||
outfile = options.outfile
|
||||
sort_keys = options.sort_keys
|
||||
json_lines = options.json_lines
|
||||
with infile, outfile:
|
||||
dump_args = {
|
||||
'sort_keys': options.sort_keys,
|
||||
'indent': options.indent,
|
||||
'ensure_ascii': options.ensure_ascii,
|
||||
}
|
||||
if options.compact:
|
||||
dump_args['indent'] = None
|
||||
dump_args['separators'] = ',', ':'
|
||||
|
||||
with options.infile as infile:
|
||||
try:
|
||||
if json_lines:
|
||||
if options.json_lines:
|
||||
objs = (json.loads(line) for line in infile)
|
||||
else:
|
||||
objs = (json.load(infile), )
|
||||
for obj in objs:
|
||||
json.dump(obj, outfile, sort_keys=sort_keys, indent=4)
|
||||
outfile.write('\n')
|
||||
objs = (json.load(infile),)
|
||||
|
||||
if options.outfile is None:
|
||||
out = sys.stdout
|
||||
else:
|
||||
out = options.outfile.open('w', encoding='utf-8')
|
||||
with out as outfile:
|
||||
for obj in objs:
|
||||
json.dump(obj, outfile, **dump_args)
|
||||
outfile.write('\n')
|
||||
except ValueError as e:
|
||||
raise SystemExit(e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
try:
|
||||
main()
|
||||
except BrokenPipeError as exc:
|
||||
sys.exit(exc.errno)
|
||||
|
||||
2
Lib/test/test_json/__init__.py
vendored
2
Lib/test/test_json/__init__.py
vendored
@@ -6,6 +6,7 @@ import unittest
|
||||
from test import support
|
||||
from test.support import import_helper
|
||||
|
||||
|
||||
# import json with and without accelerations
|
||||
# XXX RUSTPYTHON: we don't import _json as fresh since the fresh module isn't placed
|
||||
# into the sys.modules cache, and therefore the vm can't recognize the _json.Scanner class
|
||||
@@ -40,6 +41,7 @@ class TestPyTest(PyTest):
|
||||
'json.encoder')
|
||||
|
||||
class TestCTest(CTest):
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_cjson(self):
|
||||
self.assertEqual(self.json.scanner.make_scanner.__module__, '_json')
|
||||
|
||||
4
Lib/test/test_json/test_decode.py
vendored
4
Lib/test/test_json/test_decode.py
vendored
@@ -97,10 +97,6 @@ class TestDecode:
|
||||
d = self.json.JSONDecoder()
|
||||
self.assertRaises(ValueError, d.raw_decode, 'a'*42, -50000)
|
||||
|
||||
def test_deprecated_encode(self):
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.loads('{}', encoding='fake')
|
||||
|
||||
class TestPyDecode(TestDecode, PyTest): pass
|
||||
# TODO: RUSTPYTHON
|
||||
class TestCDecode(TestDecode, CTest): # pass
|
||||
|
||||
21
Lib/test/test_json/test_recursion.py
vendored
21
Lib/test/test_json/test_recursion.py
vendored
@@ -1,3 +1,4 @@
|
||||
from test import support
|
||||
from test.test_json import PyTest, CTest
|
||||
|
||||
|
||||
@@ -52,7 +53,7 @@ class TestRecursion:
|
||||
return [JSONTestObject]
|
||||
else:
|
||||
return 'JSONTestObject'
|
||||
return pyjson.JSONEncoder.default(o)
|
||||
return self.json.JSONEncoder.default(o)
|
||||
|
||||
enc = RecursiveJSONEncoder()
|
||||
self.assertEqual(enc.encode(JSONTestObject), '"JSONTestObject"')
|
||||
@@ -69,11 +70,14 @@ class TestRecursion:
|
||||
# test that loading highly-nested objects doesn't segfault when C
|
||||
# accelerations are used. See #12017
|
||||
with self.assertRaises(RecursionError):
|
||||
self.loads('{"a":' * 100000 + '1' + '}' * 100000)
|
||||
with support.infinite_recursion():
|
||||
self.loads('{"a":' * 100000 + '1' + '}' * 100000)
|
||||
with self.assertRaises(RecursionError):
|
||||
self.loads('{"a":' * 100000 + '[1]' + '}' * 100000)
|
||||
with support.infinite_recursion():
|
||||
self.loads('{"a":' * 100000 + '[1]' + '}' * 100000)
|
||||
with self.assertRaises(RecursionError):
|
||||
self.loads('[' * 100000 + '1' + ']' * 100000)
|
||||
with support.infinite_recursion():
|
||||
self.loads('[' * 100000 + '1' + ']' * 100000)
|
||||
|
||||
def test_highly_nested_objects_encoding(self):
|
||||
# See #12051
|
||||
@@ -81,9 +85,11 @@ class TestRecursion:
|
||||
for x in range(100000):
|
||||
l, d = [l], {'k':d}
|
||||
with self.assertRaises(RecursionError):
|
||||
self.dumps(l)
|
||||
with support.infinite_recursion():
|
||||
self.dumps(l)
|
||||
with self.assertRaises(RecursionError):
|
||||
self.dumps(d)
|
||||
with support.infinite_recursion():
|
||||
self.dumps(d)
|
||||
|
||||
def test_endless_recursion(self):
|
||||
# See #12051
|
||||
@@ -93,7 +99,8 @@ class TestRecursion:
|
||||
return [o]
|
||||
|
||||
with self.assertRaises(RecursionError):
|
||||
EndlessJSONEncoder(check_circular=False).encode(5j)
|
||||
with support.infinite_recursion():
|
||||
EndlessJSONEncoder(check_circular=False).encode(5j)
|
||||
|
||||
|
||||
class TestPyRecursion(TestRecursion, PyTest): pass
|
||||
|
||||
11
Lib/test/test_json/test_speedups.py
vendored
11
Lib/test/test_json/test_speedups.py
vendored
@@ -62,6 +62,17 @@ class TestEncode(CTest):
|
||||
with self.assertRaises(ZeroDivisionError):
|
||||
enc('spam', 4)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_bad_markers_argument_to_encoder(self):
|
||||
# https://bugs.python.org/issue45269
|
||||
with self.assertRaisesRegex(
|
||||
TypeError,
|
||||
r'make_encoder\(\) argument 1 must be dict or None, not int',
|
||||
):
|
||||
self.json.encoder.c_make_encoder(1, None, None, None, ': ', ', ',
|
||||
False, False, False)
|
||||
|
||||
# TODO: RUSTPYTHON, translate the encoder to Rust
|
||||
@unittest.expectedFailure
|
||||
def test_bad_bool_args(self):
|
||||
|
||||
99
Lib/test/test_json/test_tool.py
vendored
99
Lib/test/test_json/test_tool.py
vendored
@@ -1,8 +1,10 @@
|
||||
import errno
|
||||
import os
|
||||
import sys
|
||||
import textwrap
|
||||
import unittest
|
||||
from subprocess import Popen, PIPE
|
||||
import subprocess
|
||||
|
||||
from test import support
|
||||
from test.support import os_helper
|
||||
from test.support.script_helper import assert_python_ok
|
||||
@@ -85,10 +87,9 @@ class TestTool(unittest.TestCase):
|
||||
|
||||
def test_stdin_stdout(self):
|
||||
args = sys.executable, '-m', 'json.tool'
|
||||
with Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) as proc:
|
||||
out, err = proc.communicate(self.data.encode())
|
||||
self.assertEqual(out.splitlines(), self.expect.encode().splitlines())
|
||||
self.assertEqual(err, b'')
|
||||
process = subprocess.run(args, input=self.data, capture_output=True, text=True, check=True)
|
||||
self.assertEqual(process.stdout, self.expect)
|
||||
self.assertEqual(process.stderr, '')
|
||||
|
||||
def _create_infile(self, data=None):
|
||||
infile = os_helper.TESTFN
|
||||
@@ -124,7 +125,16 @@ class TestTool(unittest.TestCase):
|
||||
outfile = os_helper.TESTFN + '.out'
|
||||
rc, out, err = assert_python_ok('-m', 'json.tool', infile, outfile)
|
||||
self.addCleanup(os.remove, outfile)
|
||||
with open(outfile, "r") as fp:
|
||||
with open(outfile, "r", encoding="utf-8") as fp:
|
||||
self.assertEqual(fp.read(), self.expect)
|
||||
self.assertEqual(rc, 0)
|
||||
self.assertEqual(out, b'')
|
||||
self.assertEqual(err, b'')
|
||||
|
||||
def test_writing_in_place(self):
|
||||
infile = self._create_infile()
|
||||
rc, out, err = assert_python_ok('-m', 'json.tool', infile, infile)
|
||||
with open(infile, "r", encoding="utf-8") as fp:
|
||||
self.assertEqual(fp.read(), self.expect)
|
||||
self.assertEqual(rc, 0)
|
||||
self.assertEqual(out, b'')
|
||||
@@ -132,10 +142,9 @@ class TestTool(unittest.TestCase):
|
||||
|
||||
def test_jsonlines(self):
|
||||
args = sys.executable, '-m', 'json.tool', '--json-lines'
|
||||
with Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) as proc:
|
||||
out, err = proc.communicate(self.jsonlines_raw.encode())
|
||||
self.assertEqual(out.splitlines(), self.jsonlines_expect.encode().splitlines())
|
||||
self.assertEqual(err, b'')
|
||||
process = subprocess.run(args, input=self.jsonlines_raw, capture_output=True, text=True, check=True)
|
||||
self.assertEqual(process.stdout, self.jsonlines_expect)
|
||||
self.assertEqual(process.stderr, '')
|
||||
|
||||
def test_help_flag(self):
|
||||
rc, out, err = assert_python_ok('-m', 'json.tool', '-h')
|
||||
@@ -150,3 +159,73 @@ class TestTool(unittest.TestCase):
|
||||
self.assertEqual(out.splitlines(),
|
||||
self.expect_without_sort_keys.encode().splitlines())
|
||||
self.assertEqual(err, b'')
|
||||
|
||||
def test_indent(self):
|
||||
input_ = '[1, 2]'
|
||||
expect = textwrap.dedent('''\
|
||||
[
|
||||
1,
|
||||
2
|
||||
]
|
||||
''')
|
||||
args = sys.executable, '-m', 'json.tool', '--indent', '2'
|
||||
process = subprocess.run(args, input=input_, capture_output=True, text=True, check=True)
|
||||
self.assertEqual(process.stdout, expect)
|
||||
self.assertEqual(process.stderr, '')
|
||||
|
||||
def test_no_indent(self):
|
||||
input_ = '[1,\n2]'
|
||||
expect = '[1, 2]\n'
|
||||
args = sys.executable, '-m', 'json.tool', '--no-indent'
|
||||
process = subprocess.run(args, input=input_, capture_output=True, text=True, check=True)
|
||||
self.assertEqual(process.stdout, expect)
|
||||
self.assertEqual(process.stderr, '')
|
||||
|
||||
def test_tab(self):
|
||||
input_ = '[1, 2]'
|
||||
expect = '[\n\t1,\n\t2\n]\n'
|
||||
args = sys.executable, '-m', 'json.tool', '--tab'
|
||||
process = subprocess.run(args, input=input_, capture_output=True, text=True, check=True)
|
||||
self.assertEqual(process.stdout, expect)
|
||||
self.assertEqual(process.stderr, '')
|
||||
|
||||
def test_compact(self):
|
||||
input_ = '[ 1 ,\n 2]'
|
||||
expect = '[1,2]\n'
|
||||
args = sys.executable, '-m', 'json.tool', '--compact'
|
||||
process = subprocess.run(args, input=input_, capture_output=True, text=True, check=True)
|
||||
self.assertEqual(process.stdout, expect)
|
||||
self.assertEqual(process.stderr, '')
|
||||
|
||||
def test_no_ensure_ascii_flag(self):
|
||||
infile = self._create_infile('{"key":"💩"}')
|
||||
outfile = os_helper.TESTFN + '.out'
|
||||
self.addCleanup(os.remove, outfile)
|
||||
assert_python_ok('-m', 'json.tool', '--no-ensure-ascii', infile, outfile)
|
||||
with open(outfile, "rb") as f:
|
||||
lines = f.read().splitlines()
|
||||
# asserting utf-8 encoded output file
|
||||
expected = [b'{', b' "key": "\xf0\x9f\x92\xa9"', b"}"]
|
||||
self.assertEqual(lines, expected)
|
||||
|
||||
def test_ensure_ascii_default(self):
|
||||
infile = self._create_infile('{"key":"💩"}')
|
||||
outfile = os_helper.TESTFN + '.out'
|
||||
self.addCleanup(os.remove, outfile)
|
||||
assert_python_ok('-m', 'json.tool', infile, outfile)
|
||||
with open(outfile, "rb") as f:
|
||||
lines = f.read().splitlines()
|
||||
# asserting an ascii encoded output file
|
||||
expected = [b'{', rb' "key": "\ud83d\udca9"', b"}"]
|
||||
self.assertEqual(lines, expected)
|
||||
|
||||
@unittest.skipIf(sys.platform =="win32", "The test is failed with ValueError on Windows")
|
||||
def test_broken_pipe_error(self):
|
||||
cmd = [sys.executable, '-m', 'json.tool']
|
||||
proc = subprocess.Popen(cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stdin=subprocess.PIPE)
|
||||
# bpo-39828: Closing before json.tool attempts to write into stdout.
|
||||
proc.stdout.close()
|
||||
proc.communicate(b'"{}"')
|
||||
self.assertEqual(proc.returncode, errno.EPIPE)
|
||||
|
||||
Reference in New Issue
Block a user