From d74d5142da7c700f149e90662bdccb53fbc5502f Mon Sep 17 00:00:00 2001 From: Alex Pearce Date: Mon, 10 Apr 2017 16:37:22 +0200 Subject: [PATCH 1/4] Python 3 support in C interface. --- bindings/python/src/ChunkIterator.hh | 7 +-- bindings/python/src/PyXRootD.hh | 22 ++++++-- bindings/python/src/PyXRootDCopyProcess.hh | 5 +- bindings/python/src/PyXRootDFile.cc | 6 +- bindings/python/src/PyXRootDFile.hh | 7 +-- bindings/python/src/PyXRootDFileSystem.cc | 2 +- bindings/python/src/PyXRootDFileSystem.hh | 4 +- bindings/python/src/PyXRootDModule.cc | 65 ++++++++++++++++++++-- bindings/python/src/PyXRootDURL.cc | 32 +++++++---- bindings/python/src/PyXRootDURL.hh | 5 +- bindings/python/src/Utils.cc | 12 ++++ 11 files changed, 127 insertions(+), 40 deletions(-) diff --git a/bindings/python/src/ChunkIterator.hh b/bindings/python/src/ChunkIterator.hh index e72f38bb8f1..7fbe931bffd 100644 --- a/bindings/python/src/ChunkIterator.hh +++ b/bindings/python/src/ChunkIterator.hh @@ -98,8 +98,8 @@ namespace PyXRootD else { self->currentOffset += self->chunksize; - pychunk = PyString_FromStringAndSize( (const char*) chunk->GetBuffer(), - chunk->GetSize() ); + pychunk = PyBytes_FromStringAndSize( (const char*) chunk->GetBuffer(), + chunk->GetSize() ); } delete chunk; @@ -110,8 +110,7 @@ namespace PyXRootD //! ChunkIterator type structure //---------------------------------------------------------------------------- static PyTypeObject ChunkIteratorType = { - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ + PyVarObject_HEAD_INIT(NULL, 0) "client.File.ChunkIterator", /* tp_name */ sizeof(ChunkIterator), /* tp_basicsize */ 0, /* tp_itemsize */ diff --git a/bindings/python/src/PyXRootD.hh b/bindings/python/src/PyXRootD.hh index 886185b51a3..78e6645f394 100644 --- a/bindings/python/src/PyXRootD.hh +++ b/bindings/python/src/PyXRootD.hh @@ -25,16 +25,12 @@ #ifndef PYXROOTD_HH_ #define PYXROOTD_HH_ -#if PY_MAJOR_VERSION >= 3 -#define IS_PY3K -#endif - #include #include #include "structmember.h" -#if PY_MINOR_VERSION <= 5 -#define PyUnicode_FromString PyString_FromString +#if PY_MAJOR_VERSION >= 3 +#define IS_PY3K #endif #define async( func ) \ @@ -42,4 +38,18 @@ func; \ Py_END_ALLOW_THREADS \ +#ifdef IS_PY3K +#define Py_TPFLAGS_HAVE_ITER 0 +/* TODO don't use this hack */ +#define METH_KEYWORDS 0x0003 +#else +#if PY_MINOR_VERSION <= 5 +#define PyUnicode_FromString PyString_FromString +#endif +#define PyBytes_Size PyString_Size +#define PyBytes_Check PyString_Check +#define PyBytes_FromString PyString_FromString +#define PyBytes_FromStringAndSize PyString_FromStringAndSize +#endif + #endif /* PYXROOTD_HH_ */ diff --git a/bindings/python/src/PyXRootDCopyProcess.hh b/bindings/python/src/PyXRootDCopyProcess.hh index 01b195c9123..89569507cd8 100644 --- a/bindings/python/src/PyXRootDCopyProcess.hh +++ b/bindings/python/src/PyXRootDCopyProcess.hh @@ -67,7 +67,7 @@ namespace PyXRootD { delete self->process; delete self->results; - self->ob_type->tp_free( (PyObject*) self ); + Py_TYPE(self)->tp_free( (PyObject*) self ); } //---------------------------------------------------------------------------- @@ -97,8 +97,7 @@ namespace PyXRootD //! CopyProcess binding type object //---------------------------------------------------------------------------- static PyTypeObject CopyProcessType = { - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ + PyVarObject_HEAD_INIT(NULL, 0) "pyxrootd.CopyProcess", /* tp_name */ sizeof(CopyProcess), /* tp_basicsize */ 0, /* tp_itemsize */ diff --git a/bindings/python/src/PyXRootDFile.cc b/bindings/python/src/PyXRootDFile.cc index 6544b58534d..889a048495f 100644 --- a/bindings/python/src/PyXRootDFile.cc +++ b/bindings/python/src/PyXRootDFile.cc @@ -295,10 +295,10 @@ namespace PyXRootD if ( off_init == 0 ) self->currentOffset += line->GetSize(); - pyline = PyString_FromStringAndSize( line->GetBuffer(), line->GetSize() ); + pyline = PyBytes_FromStringAndSize( line->GetBuffer(), line->GetSize() ); } else - pyline = PyString_FromString( "" ); + pyline = PyBytes_FromString( "" ); delete line; delete chunk; @@ -346,7 +346,7 @@ namespace PyXRootD { line = self->ReadLine( self, args, kwds ); - if ( !line || PyString_Size( line ) == 0 ) + if ( !line || PyBytes_Size( line ) == 0 ) break; PyList_Append( lines, line ); diff --git a/bindings/python/src/PyXRootDFile.hh b/bindings/python/src/PyXRootDFile.hh index 21bd3464689..f87af7e9ef1 100644 --- a/bindings/python/src/PyXRootDFile.hh +++ b/bindings/python/src/PyXRootDFile.hh @@ -91,7 +91,7 @@ namespace PyXRootD static void File_dealloc( File *self ) { delete self->file; - self->ob_type->tp_free( (PyObject*) self ); + Py_TYPE(self)->tp_free( (PyObject*) self ); } //---------------------------------------------------------------------------- @@ -121,7 +121,7 @@ namespace PyXRootD //-------------------------------------------------------------------------- // Raise StopIteration if the line we just read is empty //-------------------------------------------------------------------------- - if ( PyString_Size( line ) == 0 ) { + if ( PyBytes_Size( line ) == 0 ) { PyErr_SetNone( PyExc_StopIteration ); return NULL; } @@ -207,8 +207,7 @@ namespace PyXRootD //! File binding type object //---------------------------------------------------------------------------- static PyTypeObject FileType = { - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ + PyVarObject_HEAD_INIT(NULL, 0) "pyxrootd.File", /* tp_name */ sizeof(File), /* tp_basicsize */ 0, /* tp_itemsize */ diff --git a/bindings/python/src/PyXRootDFileSystem.cc b/bindings/python/src/PyXRootDFileSystem.cc index 22203d89ab4..8452e6fc832 100644 --- a/bindings/python/src/PyXRootDFileSystem.cc +++ b/bindings/python/src/PyXRootDFileSystem.cc @@ -624,7 +624,7 @@ namespace PyXRootD for ( int i = 0; i < PyList_Size( pyfiles ); ++i ) { pyfile = PyList_GetItem( pyfiles, i ); if ( !pyfile ) return NULL; - file = PyString_AsString( pyfile ); + file = PyBytes_AsString( pyfile ); files.push_back( std::string( file ) ); } diff --git a/bindings/python/src/PyXRootDFileSystem.hh b/bindings/python/src/PyXRootDFileSystem.hh index caee834a3a1..dbb5b4cb06d 100644 --- a/bindings/python/src/PyXRootDFileSystem.hh +++ b/bindings/python/src/PyXRootDFileSystem.hh @@ -134,7 +134,7 @@ namespace PyXRootD { delete self->filesystem; Py_XDECREF( self->url ); - self->ob_type->tp_free( (PyObject*) self ); + Py_TYPE(self)->tp_free( (PyObject*) self ); } //---------------------------------------------------------------------------- @@ -151,7 +151,7 @@ namespace PyXRootD //! FileSystem binding type object //---------------------------------------------------------------------------- static PyTypeObject FileSystemType = - { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ + { PyVarObject_HEAD_INIT(NULL, 0) "pyxrootd.FileSystem", /* tp_name */ sizeof(FileSystem), /* tp_basicsize */ 0, /* tp_itemsize */ diff --git a/bindings/python/src/PyXRootDModule.cc b/bindings/python/src/PyXRootDModule.cc index 4497b7b1ffa..52626792f8d 100644 --- a/bindings/python/src/PyXRootDModule.cc +++ b/bindings/python/src/PyXRootDModule.cc @@ -43,10 +43,31 @@ namespace PyXRootD { NULL } /* Sentinel */ }; +#if PY_MAJOR_VERSION >= 3 + //---------------------------------------------------------------------------- + //! Module properties + //---------------------------------------------------------------------------- + static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "client", /* m_name */ + client_module_doc, /* m_doc */ + -1, /* m_size */ + module_methods, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ + }; +#endif + //---------------------------------------------------------------------------- //! Module initialization function //---------------------------------------------------------------------------- +#ifdef IS_PY3K + PyMODINIT_FUNC PyInit_client( void ) +#else PyMODINIT_FUNC initclient( void ) +#endif { // Ensure GIL state is initialized Py_Initialize(); @@ -55,30 +76,66 @@ namespace PyXRootD } FileSystemType.tp_new = PyType_GenericNew; - if ( PyType_Ready( &FileSystemType ) < 0 ) return; + if ( PyType_Ready( &FileSystemType ) < 0 ) { +#ifdef IS_PY3K + return NULL; +#else + return; +#endif + } Py_INCREF( &FileSystemType ); FileType.tp_new = PyType_GenericNew; - if ( PyType_Ready( &FileType ) < 0 ) return; + if ( PyType_Ready( &FileType ) < 0 ) { +#ifdef IS_PY3K + return NULL; +#else + return; +#endif + } Py_INCREF( &FileType ); URLType.tp_new = PyType_GenericNew; - if ( PyType_Ready( &URLType ) < 0 ) return; + if ( PyType_Ready( &URLType ) < 0 ) { +#ifdef IS_PY3K + return NULL; +#else + return; +#endif + } Py_INCREF( &URLType ); CopyProcessType.tp_new = PyType_GenericNew; - if ( PyType_Ready( &CopyProcessType ) < 0 ) return; + if ( PyType_Ready( &CopyProcessType ) < 0 ) { +#ifdef IS_PY3K + return NULL; +#else + return; +#endif + } Py_INCREF( &CopyProcessType ); +#ifdef IS_PY3K + ClientModule = PyModule_Create(&moduledef); +#else ClientModule = Py_InitModule3("client", module_methods, client_module_doc); +#endif if (ClientModule == NULL) { +#ifdef IS_PY3K + return NULL; +#else return; +#endif } PyModule_AddObject( ClientModule, "FileSystem", (PyObject *) &FileSystemType ); PyModule_AddObject( ClientModule, "File", (PyObject *) &FileType ); PyModule_AddObject( ClientModule, "URL", (PyObject *) &URLType ); PyModule_AddObject( ClientModule, "CopyProcess", (PyObject *) &CopyProcessType ); + +#ifdef IS_PY3K + return ClientModule; +#endif } } diff --git a/bindings/python/src/PyXRootDURL.cc b/bindings/python/src/PyXRootDURL.cc index d4e385f4d0f..ee957258087 100644 --- a/bindings/python/src/PyXRootDURL.cc +++ b/bindings/python/src/PyXRootDURL.cc @@ -56,12 +56,12 @@ namespace PyXRootD //---------------------------------------------------------------------------- int URL::SetProtocol( URL *self, PyObject *protocol, void *closure ) { - if ( !PyString_Check( protocol ) ) { + if ( !PyBytes_Check( protocol ) ) { PyErr_SetString( PyExc_TypeError, "protocol must be string" ); return -1; } - self->url->SetProtocol( std::string ( PyString_AsString( protocol ) ) ); + self->url->SetProtocol( std::string ( PyBytes_AsString( protocol ) ) ); return 0; } @@ -78,12 +78,12 @@ namespace PyXRootD //---------------------------------------------------------------------------- int URL::SetUserName( URL *self, PyObject *username, void *closure ) { - if ( !PyString_Check( username ) ) { + if ( !PyBytes_Check( username ) ) { PyErr_SetString( PyExc_TypeError, "username must be string" ); return -1; } - self->url->SetUserName( std::string( PyString_AsString( username ) ) ); + self->url->SetUserName( std::string( PyBytes_AsString( username ) ) ); return 0; } @@ -100,12 +100,12 @@ namespace PyXRootD //---------------------------------------------------------------------------- int URL::SetPassword( URL *self, PyObject *password, void *closure ) { - if ( !PyString_Check( password ) ) { + if ( !PyBytes_Check( password ) ) { PyErr_SetString( PyExc_TypeError, "password must be string" ); return -1; } - self->url->SetPassword( std::string( PyString_AsString( password ) ) ); + self->url->SetPassword( std::string( PyBytes_AsString( password ) ) ); return 0; } @@ -122,12 +122,12 @@ namespace PyXRootD //---------------------------------------------------------------------------- int URL::SetHostName( URL *self, PyObject *hostname, void *closure ) { - if ( !PyString_Check( hostname ) ) { + if ( !PyBytes_Check( hostname ) ) { PyErr_SetString( PyExc_TypeError, "hostname must be string" ); return -1; } - self->url->SetHostName( std::string( PyString_AsString( hostname ) ) ); + self->url->SetHostName( std::string( PyBytes_AsString( hostname ) ) ); return 0; } @@ -136,7 +136,11 @@ namespace PyXRootD //---------------------------------------------------------------------------- PyObject* URL::GetPort( URL *self, void *closure ) { +#ifdef IS_PY3K + return PyLong_FromLong( self->url->GetPort() ); +#else return PyInt_FromLong( self->url->GetPort() ); +#endif } //---------------------------------------------------------------------------- @@ -144,12 +148,20 @@ namespace PyXRootD //---------------------------------------------------------------------------- int URL::SetPort( URL *self, PyObject *port, void *closure ) { +#ifdef IS_PY3K + if ( !PyLong_Check( port ) ) { +#else if ( !PyInt_Check( port ) ) { +#endif PyErr_SetString( PyExc_TypeError, "port must be int" ); return -1; } +#ifdef IS_PY3K + self->url->SetPort( PyLong_AsLong( port ) ); +#else self->url->SetPort( PyInt_AsLong( port ) ); +#endif return 0; } @@ -166,12 +178,12 @@ namespace PyXRootD //---------------------------------------------------------------------------- int URL::SetPath( URL *self, PyObject *path, void *closure ) { - if ( !PyString_Check( path ) ) { + if ( !PyBytes_Check( path ) ) { PyErr_SetString( PyExc_TypeError, "path must be string" ); return -1; } - self->url->SetPath( std::string( PyString_AsString( path ) ) ); + self->url->SetPath( std::string( PyBytes_AsString( path ) ) ); return 0; } diff --git a/bindings/python/src/PyXRootDURL.hh b/bindings/python/src/PyXRootDURL.hh index bf4383f71bd..47a7385e994 100644 --- a/bindings/python/src/PyXRootDURL.hh +++ b/bindings/python/src/PyXRootDURL.hh @@ -81,7 +81,7 @@ namespace PyXRootD static void URL_dealloc( URL *self ) { delete self->url; - self->ob_type->tp_free( (PyObject*) self ); + Py_TYPE(self)->tp_free( (PyObject*) self ); } //---------------------------------------------------------------------------- @@ -134,8 +134,7 @@ namespace PyXRootD //! URL binding type object //---------------------------------------------------------------------------- static PyTypeObject URLType = { - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ + PyVarObject_HEAD_INIT(NULL, 0) "pyxrootd.URL", /* tp_name */ sizeof(URL), /* tp_basicsize */ 0, /* tp_itemsize */ diff --git a/bindings/python/src/Utils.cc b/bindings/python/src/Utils.cc index ccd61d13995..5240ac48957 100644 --- a/bindings/python/src/Utils.cc +++ b/bindings/python/src/Utils.cc @@ -59,7 +59,11 @@ namespace PyXRootD //---------------------------------------------------------------------------- int PyIntToUlong(PyObject *py_val, unsigned long *val, const char *name) { +#ifdef IS_PY3K + const long tmp = PyLong_AsLong(py_val); +#else const long tmp = PyInt_AsLong(py_val); +#endif if (tmp == -1 && PyErr_Occurred()) { @@ -84,7 +88,11 @@ namespace PyXRootD //---------------------------------------------------------------------------- int PyObjToUlong(PyObject *py_val, unsigned long *val, const char *name) { +#ifdef IS_PY3K + if (PyLong_Check(py_val)) +#else if (PyInt_Check(py_val)) +#endif return PyIntToUlong(py_val, val, name); if (!PyLong_Check(py_val)) @@ -154,7 +162,11 @@ namespace PyXRootD int PyObjToUllong(PyObject *py_val, unsigned PY_LONG_LONG *val, const char *name) { +#ifdef IS_PY3K + if (PyLong_Check(py_val)) +#else if (PyInt_Check(py_val)) +#endif { unsigned long tmp; From 9fca3d402635635b2777f9a8bdc9bb95a3dc21cb Mon Sep 17 00:00:00 2001 From: Alex Pearce Date: Mon, 10 Apr 2017 16:37:36 +0200 Subject: [PATCH 2/4] Python 3 support in Python interface. --- bindings/python/libs/client/__init__.py | 10 ++++++---- bindings/python/libs/client/copyprocess.py | 5 +++-- bindings/python/libs/client/file.py | 3 ++- bindings/python/libs/client/filesystem.py | 1 + bindings/python/libs/client/flags.py | 3 ++- bindings/python/libs/client/responses.py | 4 +++- bindings/python/libs/client/url.py | 1 + bindings/python/libs/client/utils.py | 1 + bindings/python/setup.py.in | 10 ++++++---- 9 files changed, 25 insertions(+), 13 deletions(-) diff --git a/bindings/python/libs/client/__init__.py b/bindings/python/libs/client/__init__.py index 8567684e3ec..10c6646fbfe 100644 --- a/bindings/python/libs/client/__init__.py +++ b/bindings/python/libs/client/__init__.py @@ -1,4 +1,6 @@ -from filesystem import FileSystem as FileSystem -from file import File as File -from url import URL as URL -from copyprocess import CopyProcess as CopyProcess +from __future__ import absolute_import, division, print_function + +from .filesystem import FileSystem as FileSystem +from .file import File as File +from .url import URL as URL +from .copyprocess import CopyProcess as CopyProcess diff --git a/bindings/python/libs/client/copyprocess.py b/bindings/python/libs/client/copyprocess.py index 7636c6e3e32..a34262d2b85 100644 --- a/bindings/python/libs/client/copyprocess.py +++ b/bindings/python/libs/client/copyprocess.py @@ -21,6 +21,7 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. #------------------------------------------------------------------------------- +from __future__ import absolute_import, division, print_function from pyxrootd import client from XRootD.client.url import URL @@ -37,7 +38,7 @@ def begin(self, jobId, total, source, target): self.handler.begin(jobId, total, URL(source), URL(target)) def end(self, jobId, results): - if results.has_key('status'): + if 'success' in results: results['status'] = XRootDStatus(results['status']) if self.handler: self.handler.end(jobId, results) @@ -134,6 +135,6 @@ def run(self, handler=None): """ status, results = self.__process.run(ProgressHandlerWrapper(handler)) for x in results: - if x.has_key('status'): + if 'status' in x: x['status'] = XRootDStatus(x['status']) return XRootDStatus(status), results diff --git a/bindings/python/libs/client/file.py b/bindings/python/libs/client/file.py index e593edcef9f..9cefc1d1c44 100644 --- a/bindings/python/libs/client/file.py +++ b/bindings/python/libs/client/file.py @@ -21,6 +21,7 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. #------------------------------------------------------------------------------- +from __future__ import absolute_import, division, print_function from pyxrootd import client from XRootD.client.responses import XRootDStatus, StatInfo, VectorReadInfo @@ -42,7 +43,7 @@ def __exit__(self, type, value, traceback): def __iter__(self): return self - def next(self): + def __next__(self): return self.__file.next() def open(self, url, flags=0, mode=0, timeout=0, callback=None): diff --git a/bindings/python/libs/client/filesystem.py b/bindings/python/libs/client/filesystem.py index fd0f0f31f72..5f9bb0b59c9 100644 --- a/bindings/python/libs/client/filesystem.py +++ b/bindings/python/libs/client/filesystem.py @@ -21,6 +21,7 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. #------------------------------------------------------------------------------- +from __future__ import absolute_import, division, print_function from pyxrootd import client from XRootD.client.responses import XRootDStatus, StatInfo, StatInfoVFS diff --git a/bindings/python/libs/client/flags.py b/bindings/python/libs/client/flags.py index d4852956fce..232edb0a0ca 100644 --- a/bindings/python/libs/client/flags.py +++ b/bindings/python/libs/client/flags.py @@ -15,10 +15,11 @@ # You should have received a copy of the GNU Lesser General Public License # along with XRootD. If not, see . #------------------------------------------------------------------------------- +from __future__ import absolute_import, division, print_function def enum(**enums): """Build the equivalent of a C++ enum""" - reverse = dict((value, key) for key, value in enums.iteritems()) + reverse = dict((value, key) for key, value in enums.items()) enums['reverse_mapping'] = reverse return type('Enum', (), enums) diff --git a/bindings/python/libs/client/responses.py b/bindings/python/libs/client/responses.py index 0da392834a6..c47863b8593 100644 --- a/bindings/python/libs/client/responses.py +++ b/bindings/python/libs/client/responses.py @@ -15,6 +15,8 @@ # You should have received a copy of the GNU Lesser General Public License # along with XRootD. If not, see . #------------------------------------------------------------------------------- +from __future__ import absolute_import, division, print_function + from XRootD.client.url import URL class Struct(object): @@ -23,7 +25,7 @@ def __init__(self, entries): self.__dict__.update(**entries) def __repr__(self): return '<%s>' % str(', '.join('%s: %s' % (k, repr(v)) - for (k, v) in self.__dict__.iteritems())) + for (k, v) in self.__dict__.items())) class LocationInfo(Struct): """Path location information (a list of discovered file locations). diff --git a/bindings/python/libs/client/url.py b/bindings/python/libs/client/url.py index 64fc0f29413..0a3fd249939 100644 --- a/bindings/python/libs/client/url.py +++ b/bindings/python/libs/client/url.py @@ -15,6 +15,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with XRootD. If not, see . #------------------------------------------------------------------------------- +from __future__ import absolute_import, division, print_function from pyxrootd import client diff --git a/bindings/python/libs/client/utils.py b/bindings/python/libs/client/utils.py index acd10d32533..31ae0dbbeea 100644 --- a/bindings/python/libs/client/utils.py +++ b/bindings/python/libs/client/utils.py @@ -15,6 +15,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with XRootD. If not, see . #------------------------------------------------------------------------------- +from __future__ import absolute_import, division, print_function from threading import Lock from XRootD.client.responses import XRootDStatus, HostList diff --git a/bindings/python/setup.py.in b/bindings/python/setup.py.in index f8ba79ca53e..457ce7bcf43 100644 --- a/bindings/python/setup.py.in +++ b/bindings/python/setup.py.in @@ -1,3 +1,5 @@ +from __future__ import print_function + from distutils.core import setup, Extension from distutils import sysconfig from os import getenv, walk, path @@ -25,10 +27,10 @@ xrdsrcincdir = "${XRD_SRCINCDIR}" xrdbinincdir = "${XRD_BININCDIR}" version = "${XROOTD_VERSION}" -print 'XRootD library dir: ', xrdlibdir -print 'XRootD src include dir:', xrdsrcincdir -print 'XRootD bin include dir:', xrdbinincdir -print 'Version: ', version +print('XRootD library dir: ', xrdlibdir) +print('XRootD src include dir:', xrdsrcincdir) +print('XRootD bin include dir:', xrdbinincdir) +print('Version: ', version) setup( name = 'pyxrootd', version = version, From 6188d4922284546d4f27f7a2d7f0b371476d991e Mon Sep 17 00:00:00 2001 From: Alex Pearce Date: Tue, 11 Apr 2017 21:50:13 +0200 Subject: [PATCH 3/4] Iterator compatibility for Python 2. --- bindings/python/libs/client/file.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bindings/python/libs/client/file.py b/bindings/python/libs/client/file.py index 9cefc1d1c44..cf7ed3cdf45 100644 --- a/bindings/python/libs/client/file.py +++ b/bindings/python/libs/client/file.py @@ -46,6 +46,9 @@ def __iter__(self): def __next__(self): return self.__file.next() + # Python 2 compatibility + next = __next__ + def open(self, url, flags=0, mode=0, timeout=0, callback=None): """Open the file pointed to by the given URL. From d0cf72791789babfad327013a36c1fea3e3ef82f Mon Sep 17 00:00:00 2001 From: Alex Pearce Date: Wed, 31 May 2017 18:09:04 +0200 Subject: [PATCH 4/4] Typo. --- bindings/python/libs/client/copyprocess.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/libs/client/copyprocess.py b/bindings/python/libs/client/copyprocess.py index a34262d2b85..a8c88fbf4ec 100644 --- a/bindings/python/libs/client/copyprocess.py +++ b/bindings/python/libs/client/copyprocess.py @@ -38,7 +38,7 @@ def begin(self, jobId, total, source, target): self.handler.begin(jobId, total, URL(source), URL(target)) def end(self, jobId, results): - if 'success' in results: + if 'status' in results: results['status'] = XRootDStatus(results['status']) if self.handler: self.handler.end(jobId, results)