]> arthur.barton.de Git - bup.git/blob - lib/bup/compat.py
Drop vestigial compat.input
[bup.git] / lib / bup / compat.py
1
2 import os, sys
3
4 py_maj = sys.version_info.major
5 assert py_maj >= 3
6
7 # pylint: disable=unused-import
8 from contextlib import ExitStack, nullcontext
9 from os import environb as environ
10 from os import fsdecode, fsencode
11 from shlex import quote
12
13 range = range
14 str_type = str
15 int_types = (int,)
16
17 def hexstr(b):
18     """Return hex string (not bytes as with hexlify) representation of b."""
19     return b.hex()
20
21 def reraise(ex):
22     raise ex.with_traceback(sys.exc_info()[2])
23
24 # These three functions (add_ex_tb, add_ex_ctx, and pending_raise) are
25 # vestigial, and code that uses them can probably be rewritten more
26 # simply now that we require Python versions that automatically
27 # populate the tracebacks and automatically chain pending exceptions.
28
29 def add_ex_tb(ex):
30     """Do nothing (already handled by Python 3 infrastructure)."""
31     return ex
32
33 def add_ex_ctx(ex, context_ex):
34     """Do nothing (already handled by Python 3 infrastructure)."""
35     return ex
36
37 class pending_raise:
38     """If rethrow is true, rethrow ex (if any), unless the body throws.
39
40     (Supports Python 2 compatibility.)
41
42     """
43     # This is completely vestigial, and should be removed
44     def __init__(self, ex, rethrow=True):
45         self.closed = False
46         self.ex = ex
47         self.rethrow = rethrow
48     def __enter__(self):
49         return None
50     def __exit__(self, exc_type, exc_value, traceback):
51         self.closed = True
52         if not exc_type and self.ex and self.rethrow:
53             raise self.ex
54     def __del__(self):
55         assert self.closed
56
57 def items(x):
58     return x.items()
59
60 def argv_bytes(x):
61     """Return the original bytes passed to main() for an argv argument."""
62     return fsencode(x)
63
64 def bytes_from_uint(i):
65     return bytes((i,))
66
67 def bytes_from_byte(b):  # python > 2: b[3] returns ord('x'), not b'x'
68     return bytes((b,))
69
70 byte_int = lambda x: x
71
72 def buffer(object, offset=None, size=None):
73     if size:
74         assert offset is not None
75         return memoryview(object)[offset:offset + size]
76     if offset:
77         return memoryview(object)[offset:]
78     return memoryview(object)
79
80 def getcwd():
81     return fsencode(os.getcwd())
82
83
84 try:
85     import bup_main
86 except ModuleNotFoundError:
87     bup_main = None
88
89 if bup_main:
90     def get_argvb():
91         "Return a new list containing the current process argv bytes."
92         return bup_main.argv()
93     def get_argv():
94         "Return a new list containing the current process argv strings."
95         return [x.decode(errors='surrogateescape') for x in bup_main.argv()]
96 else:
97     def get_argvb():
98         raise Exception('get_argvb requires the bup_main module');
99     def get_argv():
100         raise Exception('get_argv requires the bup_main module');
101
102 def wrap_main(main):
103     """Run main() and raise a SystemExit with the return value if it
104     returns, pass along any SystemExit it raises, convert
105     KeyboardInterrupts into exit(130), and print a Python 3 style
106     contextual backtrace for other exceptions in both Python 2 and
107     3)."""
108     try:
109         sys.exit(main())
110     except KeyboardInterrupt as ex:
111         sys.exit(130)