Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/nbconvert/utils/io.py: 25%
56 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-01 06:54 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-01 06:54 +0000
1"""io-related utilities"""
3# Copyright (c) Jupyter Development Team.
4# Distributed under the terms of the Modified BSD License.
6import codecs
7import errno
8import os
9import random
10import shutil
11import sys
14def unicode_std_stream(stream="stdout"):
15 """Get a wrapper to write unicode to stdout/stderr as UTF-8.
17 This ignores environment variables and default encodings, to reliably write
18 unicode to stdout or stderr.
20 ::
22 unicode_std_stream().write(u'ł@e¶ŧ←')
23 """
24 assert stream in ("stdout", "stderr") # noqa
25 stream = getattr(sys, stream)
27 try:
28 stream_b = stream.buffer
29 except AttributeError:
30 # sys.stdout has been replaced - use it directly
31 return stream
33 return codecs.getwriter("utf-8")(stream_b)
36def unicode_stdin_stream():
37 """Get a wrapper to read unicode from stdin as UTF-8.
39 This ignores environment variables and default encodings, to reliably read unicode from stdin.
41 ::
43 totreat = unicode_stdin_stream().read()
44 """
45 stream = sys.stdin
46 try:
47 stream_b = stream.buffer
48 except AttributeError:
49 return stream
51 return codecs.getreader("utf-8")(stream_b)
54class FormatSafeDict(dict):
55 """Format a dictionary safely."""
57 def __missing__(self, key):
58 """Handle missing value."""
59 return "{" + key + "}"
62try:
63 ENOLINK = errno.ENOLINK
64except AttributeError:
65 ENOLINK = 1998
68def link(src, dst):
69 """Hard links ``src`` to ``dst``, returning 0 or errno.
71 Note that the special errno ``ENOLINK`` will be returned if ``os.link`` isn't
72 supported by the operating system.
73 """
75 if not hasattr(os, "link"):
76 return ENOLINK
77 link_errno = 0
78 try:
79 os.link(src, dst)
80 except OSError as e:
81 link_errno = e.errno
82 return link_errno
85def link_or_copy(src, dst):
86 """Attempts to hardlink ``src`` to ``dst``, copying if the link fails.
88 Attempts to maintain the semantics of ``shutil.copy``.
90 Because ``os.link`` does not overwrite files, a unique temporary file
91 will be used if the target already exists, then that file will be moved
92 into place.
93 """
95 if os.path.isdir(dst):
96 dst = os.path.join(dst, os.path.basename(src))
98 link_errno = link(src, dst)
99 if link_errno == errno.EEXIST:
100 if os.stat(src).st_ino == os.stat(dst).st_ino:
101 # dst is already a hard link to the correct file, so we don't need
102 # to do anything else. If we try to link and rename the file
103 # anyway, we get duplicate files - see http://bugs.python.org/issue21876
104 return
106 new_dst = dst + f"-temp-{random.randint(1, 16**4):04X}" # noqa
107 try:
108 link_or_copy(src, new_dst)
109 except BaseException:
110 try:
111 os.remove(new_dst)
112 except OSError:
113 pass
114 raise
115 os.rename(new_dst, dst)
116 elif link_errno != 0:
117 # Either link isn't supported, or the filesystem doesn't support
118 # linking, or 'src' and 'dst' are on different filesystems.
119 shutil.copy(src, dst)