Skip to content

Commit 5da18e2

Browse files
committed
document/export pybytes
1 parent 30469a1 commit 5da18e2

File tree

4 files changed

+21
-5
lines changed

4 files changed

+21
-5
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ A macro exists for mimicking Python's "with statement". For example:
143143
The type of `f` can be specified with `f::T` (for example, to override automatic
144144
conversion, use `f::PyObject`). Similarly, if the context manager returns a type
145145
which is automatically converted to a Julia type, you will have override this
146-
via `@pywith EXPR::PyObject ...`.
146+
via `@pywith EXPR::PyObject ...`.
147147

148148

149149
**Important:** The biggest difference from Python is that object attributes/members are
@@ -230,6 +230,10 @@ and since NumPy supports column-major arrays this is not a problem.
230230

231231
However, the *default* ordering of NumPy arrays created in *Python* is row-major, and some Python packages will throw an error if you try to pass them column-major NumPy arrays. To deal with this, you can use `PyReverseDims(a)` to pass a Julia array as a row-major NumPy array with the dimensions *reversed*. For example, if `a` is a 3x4x5 Julia array, then `PyReverseDims(a)` passes it as a 5x4x3 NumPy row-major array (without making a copy of the underlying data).
232232

233+
A `Vector{UInt8}` object in Julia, by default, is converted to a Python
234+
`bytearray` object. If you want a `bytes` object instead, you can use
235+
the function `pybytes(a)`.
236+
233237
##### From Python to Julia
234238

235239
Multidimensional NumPy arrays (`ndarray`) are supported and can be

src/PyCall.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export pycall, pyimport, pybuiltin, PyObject, PyReverseDims,
88
pyisinstance, pywrap, pytypeof, pyeval, PyVector, pystring,
99
pyraise, pytype_mapping, pygui, pygui_start, pygui_stop,
1010
pygui_stop_all, @pylab, set!, PyTextIO, @pysym, PyNULL, @pydef,
11-
pyimport_conda, @py_str, @pywith, @pycall
11+
pyimport_conda, @py_str, @pywith, @pycall, pybytes
1212

1313
import Base: size, ndims, similar, copy, getindex, setindex!, stride,
1414
convert, pointer, summary, convert, show, haskey, keys, values,

src/serialize.jl

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,17 @@ function Base.serialize(s::AbstractSerializer, pyo::PyObject)
1212
end
1313
end
1414

15-
pybytes(b) = PyObject(@pycheckn ccall(@pysym(PyString_FromStringAndSize),
16-
PyPtr, (Ptr{UInt8}, Int),
17-
b, sizeof(b)))
15+
"""
16+
pybytes(b::Union{String,Vector{UInt8}})
17+
18+
Convert `b` to a Python `bytes` object. This differs from the default
19+
`PyObject(b)` conversion of `String` to a Python string (which may fail if `b`
20+
does not contain valid Unicode), or from the default conversion of a
21+
`Vector{UInt8}` to a `bytearray` object (which is mutable, unlike `bytes`).
22+
"""
23+
pybytes(b::Union{String,Array{UInt8}}) = PyObject(@pycheckn ccall(@pysym(PyString_FromStringAndSize),
24+
PyPtr, (Ptr{UInt8}, Int),
25+
b, sizeof(b)))
1826

1927
function Base.deserialize(s::AbstractSerializer, t::Type{PyObject})
2028
b = deserialize(s)

test/runtests.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,3 +430,7 @@ end
430430

431431
@test contains(Base.Docs.doc(PyObject(1)).content, "integer")
432432
@test contains(Base.Docs.doc(PyObject(py"lambda x: x+1")).content, "no docstring")
433+
434+
let b = rand(UInt8, 1000)
435+
@test Vector{UInt8}(pybytes(b)) == b == Vector{UInt8}(pybytes(String(b)))
436+
end

0 commit comments

Comments
 (0)