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