summaryrefslogtreecommitdiff
path: root/Objects/clinic
diff options
context:
space:
mode:
authorGregory P. Smith <greg@krypto.org>2019-05-29 11:46:58 -0700
committerGitHub <noreply@github.com>2019-05-29 11:46:58 -0700
commit0c2f9305640f7655ba0cd5f478948b2763b376b3 (patch)
treeeb5b39614be93083e883f7aeb6f3397d8d8b89c2 /Objects/clinic
parentaacc77fbd77640a8f03638216fa09372cc21673d (diff)
downloadcpython-git-0c2f9305640f7655ba0cd5f478948b2763b376b3.tar.gz
bpo-22385: Support output separators in hex methods. (#13578)
* bpo-22385: Support output separators in hex methods. Also in binascii.hexlify aka b2a_hex. The underlying implementation behind all hex generation in CPython uses the same pystrhex.c implementation. This adds support to bytes, bytearray, and memoryview objects. The binascii module functions exist rather than being slated for deprecation because they return bytes rather than requiring an intermediate step through a str object. This change was inspired by MicroPython which supports sep in its binascii implementation (and does not yet support the .hex methods). https://bugs.python.org/issue22385
Diffstat (limited to 'Objects/clinic')
-rw-r--r--Objects/clinic/bytearrayobject.c.h71
-rw-r--r--Objects/clinic/bytesobject.c.h71
-rw-r--r--Objects/clinic/memoryobject.c.h74
3 files changed, 214 insertions, 2 deletions
diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h
index da1dc6a40a..08c6eb53f5 100644
--- a/Objects/clinic/bytearrayobject.c.h
+++ b/Objects/clinic/bytearrayobject.c.h
@@ -867,6 +867,75 @@ exit:
return return_value;
}
+PyDoc_STRVAR(bytearray_hex__doc__,
+"hex($self, /, sep=None, bytes_per_sep=1)\n"
+"--\n"
+"\n"
+"Create a str of hexadecimal numbers from a bytearray object.\n"
+"\n"
+" sep\n"
+" An optional single character or byte to separate hex bytes.\n"
+" bytes_per_sep\n"
+" How many bytes between separators. Positive values count from the\n"
+" right, negative values count from the left.\n"
+"\n"
+"Example:\n"
+">>> value = bytearray([0xb9, 0x01, 0xef])\n"
+">>> value.hex()\n"
+"\'b901ef\'\n"
+">>> value.hex(\':\')\n"
+"\'b9:01:ef\'\n"
+">>> value.hex(\':\', 2)\n"
+"\'b9:01ef\'\n"
+">>> value.hex(\':\', -2)\n"
+"\'b901:ef\'");
+
+#define BYTEARRAY_HEX_METHODDEF \
+ {"hex", (PyCFunction)(void(*)(void))bytearray_hex, METH_FASTCALL|METH_KEYWORDS, bytearray_hex__doc__},
+
+static PyObject *
+bytearray_hex_impl(PyByteArrayObject *self, PyObject *sep, int bytes_per_sep);
+
+static PyObject *
+bytearray_hex(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"sep", "bytes_per_sep", NULL};
+ static _PyArg_Parser _parser = {NULL, _keywords, "hex", 0};
+ PyObject *argsbuf[2];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+ PyObject *sep = NULL;
+ int bytes_per_sep = 1;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 2, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[0]) {
+ sep = args[0];
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+ if (PyFloat_Check(args[1])) {
+ PyErr_SetString(PyExc_TypeError,
+ "integer argument expected, got float" );
+ goto exit;
+ }
+ bytes_per_sep = _PyLong_AsInt(args[1]);
+ if (bytes_per_sep == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+skip_optional_pos:
+ return_value = bytearray_hex_impl(self, sep, bytes_per_sep);
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(bytearray_reduce__doc__,
"__reduce__($self, /)\n"
"--\n"
@@ -942,4 +1011,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored))
{
return bytearray_sizeof_impl(self);
}
-/*[clinic end generated code: output=272fcb836b92da32 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=7848247e5469ba1b input=a9049054013a1b77]*/
diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h
index b03078305a..69c35063c6 100644
--- a/Objects/clinic/bytesobject.c.h
+++ b/Objects/clinic/bytesobject.c.h
@@ -686,4 +686,73 @@ bytes_fromhex(PyTypeObject *type, PyObject *arg)
exit:
return return_value;
}
-/*[clinic end generated code: output=af9f51b9b185567d input=a9049054013a1b77]*/
+
+PyDoc_STRVAR(bytes_hex__doc__,
+"hex($self, /, sep=None, bytes_per_sep=1)\n"
+"--\n"
+"\n"
+"Create a str of hexadecimal numbers from a bytes object.\n"
+"\n"
+" sep\n"
+" An optional single character or byte to separate hex bytes.\n"
+" bytes_per_sep\n"
+" How many bytes between separators. Positive values count from the\n"
+" right, negative values count from the left.\n"
+"\n"
+"Example:\n"
+">>> value = b\'\\xb9\\x01\\xef\'\n"
+">>> value.hex()\n"
+"\'b901ef\'\n"
+">>> value.hex(\':\')\n"
+"\'b9:01:ef\'\n"
+">>> value.hex(\':\', 2)\n"
+"\'b9:01ef\'\n"
+">>> value.hex(\':\', -2)\n"
+"\'b901:ef\'");
+
+#define BYTES_HEX_METHODDEF \
+ {"hex", (PyCFunction)(void(*)(void))bytes_hex, METH_FASTCALL|METH_KEYWORDS, bytes_hex__doc__},
+
+static PyObject *
+bytes_hex_impl(PyBytesObject *self, PyObject *sep, int bytes_per_sep);
+
+static PyObject *
+bytes_hex(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"sep", "bytes_per_sep", NULL};
+ static _PyArg_Parser _parser = {NULL, _keywords, "hex", 0};
+ PyObject *argsbuf[2];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+ PyObject *sep = NULL;
+ int bytes_per_sep = 1;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 2, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[0]) {
+ sep = args[0];
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+ if (PyFloat_Check(args[1])) {
+ PyErr_SetString(PyExc_TypeError,
+ "integer argument expected, got float" );
+ goto exit;
+ }
+ bytes_per_sep = _PyLong_AsInt(args[1]);
+ if (bytes_per_sep == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+skip_optional_pos:
+ return_value = bytes_hex_impl(self, sep, bytes_per_sep);
+
+exit:
+ return return_value;
+}
+/*[clinic end generated code: output=2d0a3733e13e753a input=a9049054013a1b77]*/
diff --git a/Objects/clinic/memoryobject.c.h b/Objects/clinic/memoryobject.c.h
new file mode 100644
index 0000000000..64fce10acb
--- /dev/null
+++ b/Objects/clinic/memoryobject.c.h
@@ -0,0 +1,74 @@
+/*[clinic input]
+preserve
+[clinic start generated code]*/
+
+PyDoc_STRVAR(memoryview_hex__doc__,
+"hex($self, /, sep=None, bytes_per_sep=1)\n"
+"--\n"
+"\n"
+"Return the data in the buffer as a str of hexadecimal numbers.\n"
+"\n"
+" sep\n"
+" An optional single character or byte to separate hex bytes.\n"
+" bytes_per_sep\n"
+" How many bytes between separators. Positive values count from the\n"
+" right, negative values count from the left.\n"
+"\n"
+"Example:\n"
+">>> value = memoryview(b\'\\xb9\\x01\\xef\')\n"
+">>> value.hex()\n"
+"\'b901ef\'\n"
+">>> value.hex(\':\')\n"
+"\'b9:01:ef\'\n"
+">>> value.hex(\':\', 2)\n"
+"\'b9:01ef\'\n"
+">>> value.hex(\':\', -2)\n"
+"\'b901:ef\'");
+
+#define MEMORYVIEW_HEX_METHODDEF \
+ {"hex", (PyCFunction)(void(*)(void))memoryview_hex, METH_FASTCALL|METH_KEYWORDS, memoryview_hex__doc__},
+
+static PyObject *
+memoryview_hex_impl(PyMemoryViewObject *self, PyObject *sep,
+ int bytes_per_sep);
+
+static PyObject *
+memoryview_hex(PyMemoryViewObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"sep", "bytes_per_sep", NULL};
+ static _PyArg_Parser _parser = {NULL, _keywords, "hex", 0};
+ PyObject *argsbuf[2];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+ PyObject *sep = NULL;
+ int bytes_per_sep = 1;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 2, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[0]) {
+ sep = args[0];
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+ if (PyFloat_Check(args[1])) {
+ PyErr_SetString(PyExc_TypeError,
+ "integer argument expected, got float" );
+ goto exit;
+ }
+ bytes_per_sep = _PyLong_AsInt(args[1]);
+ if (bytes_per_sep == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+skip_optional_pos:
+ return_value = memoryview_hex_impl(self, sep, bytes_per_sep);
+
+exit:
+ return return_value;
+}
+/*[clinic end generated code: output=5e44e2bcf01057b5 input=a9049054013a1b77]*/