Skip to content

Commit 0c1941f

Browse files
authored
Merge pull request #95 from KennyMcSimpson/fix/cli-utf8-input-files
Read CLI JSON and pointer files as UTF-8
2 parents bb428e5 + 12eb2cb commit 0c1941f

3 files changed

Lines changed: 27 additions & 5 deletions

File tree

‎bin/jsonpointer‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ parser = argparse.ArgumentParser(
1313
# Accept pointer as option, as file or as first positional argument
1414
ptr_group = parser.add_mutually_exclusive_group()
1515

16-
ptr_group.add_argument('-f', '--pointer-file', type=argparse.FileType('r'),
16+
ptr_group.add_argument('-f', '--pointer-file', type=argparse.FileType('r', encoding='utf-8'),
1717
help='File containing a JSON pointer expression')
1818

1919
ptr_group.add_argument('-p', '--pointer', type=str,
@@ -88,7 +88,7 @@ def resolve_files():
8888

8989
for name in files:
9090
try:
91-
f = argparse.FileType('r')(name)
91+
f = argparse.FileType('r', encoding='utf-8')(name)
9292
except argparse.ArgumentTypeError as e:
9393
parser.error(str(e))
9494

‎doc/commandline.rst‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ The program has the following usage ::
3131
The pointer can be passed as the first positional argument, with ``-p``, or
3232
read from a file with ``-f``.
3333

34+
JSON input files and pointer files are read as UTF-8.
35+
3436
The exit status is 0 if the pointer could be resolved on all files, 1 if it
3537
could not be resolved on at least one file (the remaining files are still
3638
processed) and 2 on usage errors, such as an invalid pointer or a missing

‎tests.py‎

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import copy
44
import doctest
5+
import json
56
import os
67
import subprocess
78
import sys
@@ -566,14 +567,33 @@ def setUp(self):
566567
self._write('ptr.txt', '/a\n')
567568

568569
def _write(self, name, content):
569-
with open(os.path.join(self.dir, name), 'w') as f:
570+
with open(os.path.join(self.dir, name), 'w', encoding='utf-8') as f:
570571
f.write(content)
571572

572-
def _run(self, *args):
573+
def _run(self, *args, utf8=True):
573574
env = dict(os.environ, PYTHONPATH=self.ROOT, PYTHONUTF8='1')
575+
if not utf8:
576+
# Keep pipes in UTF-8 while exercising locale-dependent file I/O.
577+
env.update(PYTHONUTF8='0', PYTHONIOENCODING='utf-8',
578+
LC_ALL='C', PYTHONCOERCECLOCALE='0')
574579
return subprocess.run([sys.executable, self.SCRIPT] + list(args),
575580
cwd=self.dir, env=env, capture_output=True,
576-
text=True)
581+
encoding='utf-8')
582+
583+
def test_utf8_json_file_without_utf8_mode(self):
584+
self._write('unicode.json', '{"value": "🚀"}')
585+
proc = self._run('/value', 'unicode.json', utf8=False)
586+
self.assertEqual(proc.returncode, 0, proc.stderr)
587+
self.assertEqual(json.loads(proc.stdout), '🚀')
588+
self.assertEqual(proc.stderr, '')
589+
590+
def test_utf8_pointer_file_without_utf8_mode(self):
591+
self._write('unicode.json', json.dumps({'ä': 'expected'}))
592+
self._write('unicode.txt', '/ä\n')
593+
proc = self._run('-f', 'unicode.txt', 'unicode.json', utf8=False)
594+
self.assertEqual(proc.returncode, 0, proc.stderr)
595+
self.assertEqual(json.loads(proc.stdout), 'expected')
596+
self.assertEqual(proc.stderr, '')
577597

578598
def test_positional_pointer(self):
579599
proc = self._run('/a', 'a.json', 'b.json')

0 commit comments

Comments
 (0)