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