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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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_ */