Mercurial > hg
annotate mercurial/cext/util.h @ 45095:8e04607023e5
procutil: ensure that procutil.std{out,err}.write() writes all bytes
Python 3 offers different kind of streams and it’s not guaranteed for all of
them that calling write() writes all bytes.
When Python is started in unbuffered mode, sys.std{out,err}.buffer are
instances of io.FileIO, whose write() can write less bytes for
platform-specific reasons (e.g. Linux has a 0x7ffff000 bytes maximum and could
write less if interrupted by a signal; when writing to Windows consoles, it’s
limited to 32767 bytes to avoid the "not enough space" error). This can lead to
silent loss of data, both when using sys.std{out,err}.buffer (which may in fact
not be a buffered stream) and when using the text streams sys.std{out,err}
(I’ve created a CPython bug report for that:
https://bugs.python.org/issue41221).
Python may fix the problem at some point. For now, we implement our own wrapper
for procutil.std{out,err} that calls the raw stream’s write() method until all
bytes have been written. We don’t use sys.std{out,err} for larger writes, so I
think it’s not worth the effort to patch them.
author | Manuel Jacob <me@manueljacob.de> |
---|---|
date | Fri, 10 Jul 2020 12:27:58 +0200 |
parents | fa33196088c4 |
children | 84391ddf4c78 |
rev | line source |
---|---|
11358
4494fb02d549
util.h: Utility macros for handling different Python APIs.
Renato Cunha <renatoc@gmail.com>
parents:
diff
changeset
|
1 /* |
4494fb02d549
util.h: Utility macros for handling different Python APIs.
Renato Cunha <renatoc@gmail.com>
parents:
diff
changeset
|
2 util.h - utility functions for interfacing with the various python APIs. |
4494fb02d549
util.h: Utility macros for handling different Python APIs.
Renato Cunha <renatoc@gmail.com>
parents:
diff
changeset
|
3 |
4494fb02d549
util.h: Utility macros for handling different Python APIs.
Renato Cunha <renatoc@gmail.com>
parents:
diff
changeset
|
4 This software may be used and distributed according to the terms of |
4494fb02d549
util.h: Utility macros for handling different Python APIs.
Renato Cunha <renatoc@gmail.com>
parents:
diff
changeset
|
5 the GNU General Public License, incorporated herein by reference. |
4494fb02d549
util.h: Utility macros for handling different Python APIs.
Renato Cunha <renatoc@gmail.com>
parents:
diff
changeset
|
6 */ |
4494fb02d549
util.h: Utility macros for handling different Python APIs.
Renato Cunha <renatoc@gmail.com>
parents:
diff
changeset
|
7 |
4494fb02d549
util.h: Utility macros for handling different Python APIs.
Renato Cunha <renatoc@gmail.com>
parents:
diff
changeset
|
8 #ifndef _HG_UTIL_H_ |
4494fb02d549
util.h: Utility macros for handling different Python APIs.
Renato Cunha <renatoc@gmail.com>
parents:
diff
changeset
|
9 #define _HG_UTIL_H_ |
4494fb02d549
util.h: Utility macros for handling different Python APIs.
Renato Cunha <renatoc@gmail.com>
parents:
diff
changeset
|
10 |
29444
284d742e5611
internals: move the bitmanipulation routines into its own file
Maciej Fijalkowski <fijall@gmail.com>
parents:
25076
diff
changeset
|
11 #include "compat.h" |
284d742e5611
internals: move the bitmanipulation routines into its own file
Maciej Fijalkowski <fijall@gmail.com>
parents:
25076
diff
changeset
|
12 |
11358
4494fb02d549
util.h: Utility macros for handling different Python APIs.
Renato Cunha <renatoc@gmail.com>
parents:
diff
changeset
|
13 #if PY_MAJOR_VERSION >= 3 |
4494fb02d549
util.h: Utility macros for handling different Python APIs.
Renato Cunha <renatoc@gmail.com>
parents:
diff
changeset
|
14 #define IS_PY3K |
30112
9b6ff0f940ed
parsers: move PyInt aliasing out of util.h
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30101
diff
changeset
|
15 #endif |
11358
4494fb02d549
util.h: Utility macros for handling different Python APIs.
Renato Cunha <renatoc@gmail.com>
parents:
diff
changeset
|
16 |
36618
9a639a33ad1f
py3: add PY23() macro to switch string literal depending on python version
Yuya Nishihara <yuya@tcha.org>
parents:
35775
diff
changeset
|
17 /* helper to switch things like string literal depending on Python version */ |
9a639a33ad1f
py3: add PY23() macro to switch string literal depending on python version
Yuya Nishihara <yuya@tcha.org>
parents:
35775
diff
changeset
|
18 #ifdef IS_PY3K |
9a639a33ad1f
py3: add PY23() macro to switch string literal depending on python version
Yuya Nishihara <yuya@tcha.org>
parents:
35775
diff
changeset
|
19 #define PY23(py2, py3) py3 |
9a639a33ad1f
py3: add PY23() macro to switch string literal depending on python version
Yuya Nishihara <yuya@tcha.org>
parents:
35775
diff
changeset
|
20 #else |
9a639a33ad1f
py3: add PY23() macro to switch string literal depending on python version
Yuya Nishihara <yuya@tcha.org>
parents:
35775
diff
changeset
|
21 #define PY23(py2, py3) py2 |
9a639a33ad1f
py3: add PY23() macro to switch string literal depending on python version
Yuya Nishihara <yuya@tcha.org>
parents:
35775
diff
changeset
|
22 #endif |
9a639a33ad1f
py3: add PY23() macro to switch string literal depending on python version
Yuya Nishihara <yuya@tcha.org>
parents:
35775
diff
changeset
|
23 |
34635
3455e2e2ce9b
util: add clang-format control comment around struct and format macro
Augie Fackler <augie@google.com>
parents:
33758
diff
changeset
|
24 /* clang-format off */ |
21809
e250b8300e6e
parsers: inline fields of dirstate values in C version
Siddharth Agarwal <sid0@fb.com>
parents:
19833
diff
changeset
|
25 typedef struct { |
e250b8300e6e
parsers: inline fields of dirstate values in C version
Siddharth Agarwal <sid0@fb.com>
parents:
19833
diff
changeset
|
26 PyObject_HEAD |
e250b8300e6e
parsers: inline fields of dirstate values in C version
Siddharth Agarwal <sid0@fb.com>
parents:
19833
diff
changeset
|
27 char state; |
e250b8300e6e
parsers: inline fields of dirstate values in C version
Siddharth Agarwal <sid0@fb.com>
parents:
19833
diff
changeset
|
28 int mode; |
e250b8300e6e
parsers: inline fields of dirstate values in C version
Siddharth Agarwal <sid0@fb.com>
parents:
19833
diff
changeset
|
29 int size; |
e250b8300e6e
parsers: inline fields of dirstate values in C version
Siddharth Agarwal <sid0@fb.com>
parents:
19833
diff
changeset
|
30 int mtime; |
e250b8300e6e
parsers: inline fields of dirstate values in C version
Siddharth Agarwal <sid0@fb.com>
parents:
19833
diff
changeset
|
31 } dirstateTupleObject; |
34635
3455e2e2ce9b
util: add clang-format control comment around struct and format macro
Augie Fackler <augie@google.com>
parents:
33758
diff
changeset
|
32 /* clang-format on */ |
21809
e250b8300e6e
parsers: inline fields of dirstate values in C version
Siddharth Agarwal <sid0@fb.com>
parents:
19833
diff
changeset
|
33 |
21838
0022ee690446
util.h: declare dirstateTupleType variable instead of defining it
André Sintzoff <andre.sintzoff@gmail.com>
parents:
21809
diff
changeset
|
34 extern PyTypeObject dirstateTupleType; |
21809
e250b8300e6e
parsers: inline fields of dirstate values in C version
Siddharth Agarwal <sid0@fb.com>
parents:
19833
diff
changeset
|
35 #define dirstate_tuple_check(op) (Py_TYPE(op) == &dirstateTupleType) |
e250b8300e6e
parsers: inline fields of dirstate values in C version
Siddharth Agarwal <sid0@fb.com>
parents:
19833
diff
changeset
|
36 |
35775
440e8fce29e7
cext: define MIN macro only if it is not yet defined
André Sintzoff <andre.sintzoff@gmail.com>
parents:
34635
diff
changeset
|
37 #ifndef MIN |
34635
3455e2e2ce9b
util: add clang-format control comment around struct and format macro
Augie Fackler <augie@google.com>
parents:
33758
diff
changeset
|
38 #define MIN(a, b) (((a) < (b)) ? (a) : (b)) |
35775
440e8fce29e7
cext: define MIN macro only if it is not yet defined
André Sintzoff <andre.sintzoff@gmail.com>
parents:
34635
diff
changeset
|
39 #endif |
24442
98042b0e19f9
manifest: move C bool polyfill into util.h
Matt Mackall <mpm@selenic.com>
parents:
24016
diff
changeset
|
40 /* VC9 doesn't include bool and lacks stdbool.h based on my searching */ |
24829
8e9f8d2a2c0c
util: fix the check for non-C99 compilers (issue4605)
Kevin Bullock <kbullock@ringworld.org>
parents:
24823
diff
changeset
|
41 #if defined(_MSC_VER) || __STDC_VERSION__ < 199901L |
24442
98042b0e19f9
manifest: move C bool polyfill into util.h
Matt Mackall <mpm@selenic.com>
parents:
24016
diff
changeset
|
42 #define true 1 |
98042b0e19f9
manifest: move C bool polyfill into util.h
Matt Mackall <mpm@selenic.com>
parents:
24016
diff
changeset
|
43 #define false 0 |
98042b0e19f9
manifest: move C bool polyfill into util.h
Matt Mackall <mpm@selenic.com>
parents:
24016
diff
changeset
|
44 typedef unsigned char bool; |
98042b0e19f9
manifest: move C bool polyfill into util.h
Matt Mackall <mpm@selenic.com>
parents:
24016
diff
changeset
|
45 #else |
98042b0e19f9
manifest: move C bool polyfill into util.h
Matt Mackall <mpm@selenic.com>
parents:
24016
diff
changeset
|
46 #include <stdbool.h> |
98042b0e19f9
manifest: move C bool polyfill into util.h
Matt Mackall <mpm@selenic.com>
parents:
24016
diff
changeset
|
47 #endif |
98042b0e19f9
manifest: move C bool polyfill into util.h
Matt Mackall <mpm@selenic.com>
parents:
24016
diff
changeset
|
48 |
33756
5866ba5e9c48
cext: move _dict_new_presized() to header
Yuya Nishihara <yuya@tcha.org>
parents:
32386
diff
changeset
|
49 static inline PyObject *_dict_new_presized(Py_ssize_t expected_size) |
5866ba5e9c48
cext: move _dict_new_presized() to header
Yuya Nishihara <yuya@tcha.org>
parents:
32386
diff
changeset
|
50 { |
5866ba5e9c48
cext: move _dict_new_presized() to header
Yuya Nishihara <yuya@tcha.org>
parents:
32386
diff
changeset
|
51 /* _PyDict_NewPresized expects a minused parameter, but it actually |
5866ba5e9c48
cext: move _dict_new_presized() to header
Yuya Nishihara <yuya@tcha.org>
parents:
32386
diff
changeset
|
52 creates a dictionary that's the nearest power of two bigger than the |
5866ba5e9c48
cext: move _dict_new_presized() to header
Yuya Nishihara <yuya@tcha.org>
parents:
32386
diff
changeset
|
53 parameter. For example, with the initial minused = 1000, the |
5866ba5e9c48
cext: move _dict_new_presized() to header
Yuya Nishihara <yuya@tcha.org>
parents:
32386
diff
changeset
|
54 dictionary created has size 1024. Of course in a lot of cases that |
5866ba5e9c48
cext: move _dict_new_presized() to header
Yuya Nishihara <yuya@tcha.org>
parents:
32386
diff
changeset
|
55 can be greater than the maximum load factor Python's dict object |
5866ba5e9c48
cext: move _dict_new_presized() to header
Yuya Nishihara <yuya@tcha.org>
parents:
32386
diff
changeset
|
56 expects (= 2/3), so as soon as we cross the threshold we'll resize |
5866ba5e9c48
cext: move _dict_new_presized() to header
Yuya Nishihara <yuya@tcha.org>
parents:
32386
diff
changeset
|
57 anyway. So create a dictionary that's at least 3/2 the size. */ |
5866ba5e9c48
cext: move _dict_new_presized() to header
Yuya Nishihara <yuya@tcha.org>
parents:
32386
diff
changeset
|
58 return _PyDict_NewPresized(((1 + expected_size) / 2) * 3); |
5866ba5e9c48
cext: move _dict_new_presized() to header
Yuya Nishihara <yuya@tcha.org>
parents:
32386
diff
changeset
|
59 } |
5866ba5e9c48
cext: move _dict_new_presized() to header
Yuya Nishihara <yuya@tcha.org>
parents:
32386
diff
changeset
|
60 |
40598
fa33196088c4
revlog: replace PyInt_AS_LONG with a more portable helper function
Augie Fackler <augie@google.com>
parents:
36618
diff
changeset
|
61 /* Convert a PyInt or PyLong to a long. Returns false if there is an |
fa33196088c4
revlog: replace PyInt_AS_LONG with a more portable helper function
Augie Fackler <augie@google.com>
parents:
36618
diff
changeset
|
62 error, in which case an exception will already have been set. */ |
fa33196088c4
revlog: replace PyInt_AS_LONG with a more portable helper function
Augie Fackler <augie@google.com>
parents:
36618
diff
changeset
|
63 static inline bool pylong_to_long(PyObject *pylong, long *out) |
fa33196088c4
revlog: replace PyInt_AS_LONG with a more portable helper function
Augie Fackler <augie@google.com>
parents:
36618
diff
changeset
|
64 { |
fa33196088c4
revlog: replace PyInt_AS_LONG with a more portable helper function
Augie Fackler <augie@google.com>
parents:
36618
diff
changeset
|
65 *out = PyLong_AsLong(pylong); |
fa33196088c4
revlog: replace PyInt_AS_LONG with a more portable helper function
Augie Fackler <augie@google.com>
parents:
36618
diff
changeset
|
66 /* Fast path to avoid hitting PyErr_Occurred if the value was obviously |
fa33196088c4
revlog: replace PyInt_AS_LONG with a more portable helper function
Augie Fackler <augie@google.com>
parents:
36618
diff
changeset
|
67 * not an error. */ |
fa33196088c4
revlog: replace PyInt_AS_LONG with a more portable helper function
Augie Fackler <augie@google.com>
parents:
36618
diff
changeset
|
68 if (*out != -1) { |
fa33196088c4
revlog: replace PyInt_AS_LONG with a more portable helper function
Augie Fackler <augie@google.com>
parents:
36618
diff
changeset
|
69 return true; |
fa33196088c4
revlog: replace PyInt_AS_LONG with a more portable helper function
Augie Fackler <augie@google.com>
parents:
36618
diff
changeset
|
70 } |
fa33196088c4
revlog: replace PyInt_AS_LONG with a more portable helper function
Augie Fackler <augie@google.com>
parents:
36618
diff
changeset
|
71 return PyErr_Occurred() == NULL; |
fa33196088c4
revlog: replace PyInt_AS_LONG with a more portable helper function
Augie Fackler <augie@google.com>
parents:
36618
diff
changeset
|
72 } |
fa33196088c4
revlog: replace PyInt_AS_LONG with a more portable helper function
Augie Fackler <augie@google.com>
parents:
36618
diff
changeset
|
73 |
11358
4494fb02d549
util.h: Utility macros for handling different Python APIs.
Renato Cunha <renatoc@gmail.com>
parents:
diff
changeset
|
74 #endif /* _HG_UTIL_H_ */ |