Skip to content

Commit f247e1d

Browse files
donBarbospicnixz
andauthored
gh-131178: Add tests for pickle command-line interface (#131275)
Co-authored-by: Bénédikt Tran <[email protected]>
1 parent dbfc6a4 commit f247e1d

File tree

2 files changed

+64
-5
lines changed

2 files changed

+64
-5
lines changed

Lib/pickle.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -1907,19 +1907,23 @@ def _loads(s, /, *, fix_imports=True, encoding="ASCII", errors="strict",
19071907
dump, dumps, load, loads = _dump, _dumps, _load, _loads
19081908

19091909

1910-
if __name__ == "__main__":
1910+
def _main(args=None):
19111911
import argparse
19121912
import pprint
19131913
parser = argparse.ArgumentParser(
19141914
description='display contents of the pickle files')
19151915
parser.add_argument(
19161916
'pickle_file',
19171917
nargs='+', help='the pickle file')
1918-
args = parser.parse_args()
1918+
args = parser.parse_args(args)
19191919
for fn in args.pickle_file:
19201920
if fn == '-':
19211921
obj = load(sys.stdin.buffer)
19221922
else:
19231923
with open(fn, 'rb') as f:
19241924
obj = load(f)
19251925
pprint.pprint(obj)
1926+
1927+
1928+
if __name__ == "__main__":
1929+
_main()

Lib/test/test_pickle.py

+58-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
from _compat_pickle import (IMPORT_MAPPING, REVERSE_IMPORT_MAPPING,
22
NAME_MAPPING, REVERSE_NAME_MAPPING)
33
import builtins
4-
import pickle
5-
import io
64
import collections
5+
import contextlib
6+
import io
7+
import pickle
78
import struct
89
import sys
10+
import tempfile
911
import warnings
1012
import weakref
13+
from textwrap import dedent
1114

1215
import doctest
1316
import unittest
1417
from test import support
15-
from test.support import import_helper
18+
from test.support import import_helper, os_helper
1619

1720
from test.pickletester import AbstractHookTests
1821
from test.pickletester import AbstractUnpickleTests
@@ -699,6 +702,58 @@ def test_multiprocessing_exceptions(self):
699702
('multiprocessing.context', name))
700703

701704

705+
class CommandLineTest(unittest.TestCase):
706+
def setUp(self):
707+
self.filename = tempfile.mktemp()
708+
self.addCleanup(os_helper.unlink, self.filename)
709+
710+
@staticmethod
711+
def text_normalize(string):
712+
"""Dedent *string* and strip it from its surrounding whitespaces.
713+
714+
This method is used by the other utility functions so that any
715+
string to write or to match against can be freely indented.
716+
"""
717+
return dedent(string).strip()
718+
719+
def set_pickle_data(self, data):
720+
with open(self.filename, 'wb') as f:
721+
pickle.dump(data, f)
722+
723+
def invoke_pickle(self, *flags):
724+
output = io.StringIO()
725+
with contextlib.redirect_stdout(output):
726+
pickle._main(args=[*flags, self.filename])
727+
return self.text_normalize(output.getvalue())
728+
729+
def test_invocation(self):
730+
# test 'python -m pickle pickle_file'
731+
data = {
732+
'a': [1, 2.0, 3+4j],
733+
'b': ('character string', b'byte string'),
734+
'c': 'string'
735+
}
736+
expect = '''
737+
{'a': [1, 2.0, (3+4j)],
738+
'b': ('character string', b'byte string'),
739+
'c': 'string'}
740+
'''
741+
self.set_pickle_data(data)
742+
743+
with self.subTest(data=data):
744+
res = self.invoke_pickle()
745+
expect = self.text_normalize(expect)
746+
self.assertListEqual(res.splitlines(), expect.splitlines())
747+
748+
def test_unknown_flag(self):
749+
stderr = io.StringIO()
750+
with self.assertRaises(SystemExit):
751+
# check that the parser help is shown
752+
with contextlib.redirect_stderr(stderr):
753+
_ = self.invoke_pickle('--unknown')
754+
self.assertStartsWith(stderr.getvalue(), 'usage: ')
755+
756+
702757
def load_tests(loader, tests, pattern):
703758
tests.addTest(doctest.DocTestSuite(pickle))
704759
return tests

0 commit comments

Comments
 (0)