[SSSD] [patch] Python 3 support for sssd

Jakub Hrozek jhrozek at redhat.com
Fri Dec 12 15:25:43 UTC 2014


On Fri, Jul 18, 2014 at 11:28:21AM -0400, Bohuslav Kabrda wrote:
> ----- Original Message -----
> > On Fri, Jul 18, 2014 at 10:34:00AM -0400, Bohuslav Kabrda wrote:
> > > I'd highly appreciate if you could do the build changes yourself, I
> > > probably won't be able to get to any coding next week or two and I think
> > > it's better to get this merged and tested sooner than later.
> > 
> > OK:
> > https://fedorahosted.org/sssd/ticket/2386
> > 
> > Out of curiosity, is there some Fedora Feature or a bug that tracks
> > converting packages to Python 3? Do we need to hit some particular
> > deadline?
> 
> There is no hard deadline yet, doing this ASAP would however be appreciated, since there are other libraries depending on sssd that can't start porting without having sssd built with python3.
> We try to keep the progress tracked at [1], but it's not complete and up-to-date. We're working on a simple tool that would automate the checking for us, but it's not ready yet.
>  
> > > > Right, but on some distributions (ArchLinux comes to mind),
> > > > /usr/bin/python points to python3 already.
> > > 
> > > Yes, and I think it's Arch only. And they actually were the reason why
> > > Python upstream created this recommendation for other distros - Fedora,
> > > for one, is going to adhere to it, so we'll keep /usr/bin/python pointing
> > > to python2 even if we'll pronounce python3 "the default" Python
> > > interpreter.
> > 
> > Thanks for the clarification. 
> 
> YW!
> Slavek

After Slavek's nag ping on IRC I rebased the patch, fixed some minor
issues and made sure the patch passed make check on all platforms:
    http://sssd-ci.idm.lab.eng.brq.redhat.com:8080/job/ci/515/

I think we should merge it as-is when we split master and sssd-1-12.
-------------- next part --------------
>From 6aee3df7c45ceb253bb9b39e1f5d72b187032983 Mon Sep 17 00:00:00 2001
From: Bohuslav Kabrda <bkabrda at redhat.com>
Date: Fri, 12 Dec 2014 11:04:40 +0100
Subject: [PATCH] Python3 support in SSSD

---
 contrib/rhel/update_debug_levels.py          |  12 +--
 src/config/SSSDConfig/ipachangeconf.py       |  33 ++++----
 src/config/SSSDConfig/sssd_upgrade_config.py |  33 ++++----
 src/config/SSSDConfigTest.py                 |   8 +-
 src/external/python.m4                       |  19 ++---
 src/python/pyhbac.c                          | 117 +++++++++++++++++----------
 src/python/pysss.c                           |  68 +++++++++++++---
 src/python/pysss_murmur.c                    |  28 ++++++-
 src/python/pysss_nss_idmap.c                 |  62 ++++++++++----
 src/tests/pyhbac-test.py                     |   9 ++-
 src/tests/pysss_murmur-test.py               |   7 +-
 src/tests/python-test.py                     |  33 ++++----
 src/util/sss_python.h                        |  16 +++-
 13 files changed, 299 insertions(+), 146 deletions(-)

diff --git a/contrib/rhel/update_debug_levels.py b/contrib/rhel/update_debug_levels.py
index a9462625fac3a0d064a396d7834b980b1920f26f..a260ec1e82ba8eb17d70d8e13d9858fbbd289b6c 100644
--- a/contrib/rhel/update_debug_levels.py
+++ b/contrib/rhel/update_debug_levels.py
@@ -1,3 +1,5 @@
+from __future__ import print_function
+
 import os
 import sys
 import shutil
@@ -27,19 +29,19 @@ by default""")
                       help="Be verbose")
     (options, args) = parser.parse_args()
     if len(args) > 0:
-        print >>sys.stderr, "Stray arguments: %s" % ' '.join([a for a in args])
+        print("Stray arguments: %s" % ' '.join([a for a in args]), file=sys.stderr)
         return None
 
     return options
 
 def verbose(msg, verbosity):
     if verbosity:
-        print msg
+        print(msg)
 
 def main():
     options = parse_options()
     if not options:
-        print >> sys.stderr, "Cannot parse options"
+        print("Cannot parse options", file=sys.stderr)
         return 1
 
     # Import the current config file
@@ -47,8 +49,8 @@ def main():
         sssdconfig = SSSDConfig.SSSDConfig()
         sssdconfig.import_config()
 
-    except Exception, e:
-        print "Error: %s" % e
+    except Exception as e:
+        print("Error: %s" % e)
         verbose(traceback.format_exc(), options.verbose)
         return 2
 
diff --git a/src/config/SSSDConfig/ipachangeconf.py b/src/config/SSSDConfig/ipachangeconf.py
index 49394f20e352952e0a833e8f0578671ed1fbe269..257c0f46dcfd1cc24c22df1648f58cc6d97490f3 100644
--- a/src/config/SSSDConfig/ipachangeconf.py
+++ b/src/config/SSSDConfig/ipachangeconf.py
@@ -34,7 +34,8 @@ def openLocked(filename, perms, create = True):
     try:
         fd = os.open(filename, flags, perms)
         fcntl.lockf(fd, fcntl.LOCK_EX)
-    except OSError, (errno, strerr):
+    except OSError as err:
+        errno, strerr = err.args
         if fd != -1:
             try:
                 os.close(fd)
@@ -73,7 +74,7 @@ class IPAChangeConf:
         elif type(indent) is str:
             self.indent = (indent, )
         else:
-           raise ValueError, 'Indent must be a list of strings'
+           raise ValueError('Indent must be a list of strings')
 
     def setOptionAssignment(self, assign):
         if type(assign) is tuple:
@@ -174,7 +175,7 @@ class IPAChangeConf:
             if o['type'] == "empty":
                 output += self.deol
                 continue
-            raise SyntaxError, 'Unknown type: ['+o['type']+']'
+            raise SyntaxError('Unknown type: ['+o['type']+']')
 
         return output
 
@@ -189,7 +190,7 @@ class IPAChangeConf:
 
         parts = line.split(self.dassign, 1)
         if len(parts) < 2:
-            raise SyntaxError, 'Syntax Error: Unknown line format'
+            raise SyntaxError('Syntax Error: Unknown line format')
 
         return {'name':parts[0].strip(), 'type':'option', 'value':parts[1].rstrip()}
 
@@ -238,7 +239,7 @@ class IPAChangeConf:
             if o['type'] == 'empty':
                 opts.append({'name':'comment', 'type':'comment', 'value':''})
                 continue
-            raise SyntaxError, 'Unknown type: ['+o['type']+']'
+            raise SyntaxError('Unknown type: ['+o['type']+']')
 
         return opts
 
@@ -263,7 +264,7 @@ class IPAChangeConf:
                     continue
                 if no['action'] == "remove":
                     continue
-                raise SyntaxError, 'Unknown action: ['+no['action']+']'
+                raise SyntaxError('Unknown action: ['+no['action']+']')
 
             if o['type'] == "comment" or o['type'] == "empty":
                  opts.append(o)
@@ -285,9 +286,9 @@ class IPAChangeConf:
                 if no['action'] == 'set':
                     opts.append(no)
                     continue
-                raise SyntaxError, 'Unknown action: ['+o['action']+']'
+                raise SyntaxError('Unknown action: ['+o['action']+']')
 
-            raise SyntaxError, 'Unknown type: ['+o['type']+']'
+            raise SyntaxError('Unknown type: ['+o['type']+']')
 
         return opts
 
@@ -323,7 +324,7 @@ class IPAChangeConf:
                 cline += 1
                 continue
 
-            raise SyntaxError, 'Unknown type: ['+no['type']+']'
+            raise SyntaxError('Unknown type: ['+no['type']+']')
 
 
     def merge(self, oldopts, newopts):
@@ -368,7 +369,7 @@ class IPAChangeConf:
             value = self.matchSubSection(line)
             if value:
                 if subsection is not None:
-                    raise SyntaxError, 'nested subsections are not supported yet'
+                    raise SyntaxError('nested subsections are not supported yet')
                 subsectopts = []
                 curopts = subsectopts
                 subsection = value
@@ -377,7 +378,7 @@ class IPAChangeConf:
             value = self.matchSubSectionEnd(line)
             if value:
                 if subsection is None:
-                    raise SyntaxError, 'Unmatched end subsection terminator found'
+                    raise SyntaxError('Unmatched end subsection terminator found')
                 fatheropts.append({'name':subsection, 'type':'subsection', 'value':subsectopts})
                 subsection = None
                 curopts = fatheropts
@@ -407,7 +408,7 @@ class IPAChangeConf:
             #Do not catch an unexisting file error, we want to fail in that case
             shutil.copy2(file, file+self.backup_suffix)
 
-            f = openLocked(file, 0644)
+            f = openLocked(file, 0o644)
 
             oldopts = self.parse(f)
 
@@ -441,12 +442,12 @@ class IPAChangeConf:
         try:
             try:
                 shutil.copy2(file, file+self.backup_suffix)
-            except IOError, err:
+            except IOError as err:
                 if err.errno == 2:
                     # The orign file did not exist
                     pass
 
-            f = openLocked(file, 0644)
+            f = openLocked(file, 0o644)
 
             # Trunkate
             f.seek(0)
@@ -494,12 +495,12 @@ class SSSDChangeConf(IPAChangeConf):
 
         mo = self.OPTCRE.match(line)
         if not mo:
-            raise SyntaxError, 'Syntax Error: Unknown line format'
+            raise SyntaxError('Syntax Error: Unknown line format')
 
         try:
             name, value = mo.group('option', 'value')
         except IndexError:
-            raise SyntaxError, 'Syntax Error: Unknown line format'
+            raise SyntaxError('Syntax Error: Unknown line format')
 
         return {'name':name.strip(), 'type':'option', 'value':value.strip()}
 
diff --git a/src/config/SSSDConfig/sssd_upgrade_config.py b/src/config/SSSDConfig/sssd_upgrade_config.py
index 33d9fed74424a7d3ee28e888aaed724d0a8a94ff..282d6c46f46fb3ec0be78b87aa474e271bf3325f 100644
--- a/src/config/SSSDConfig/sssd_upgrade_config.py
+++ b/src/config/SSSDConfig/sssd_upgrade_config.py
@@ -18,6 +18,7 @@
 #
 #  You should have received a copy of the GNU General Public License
 #  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+from __future__ import print_function
 
 import os
 import sys
@@ -25,15 +26,15 @@ import shutil
 import traceback
 from optparse import OptionParser
 
-from ipachangeconf import openLocked
-from ipachangeconf import SSSDChangeConf
+from .ipachangeconf import openLocked
+from .ipachangeconf import SSSDChangeConf
 
 class SSSDConfigFile(SSSDChangeConf):
     def __init__(self, filename):
         SSSDChangeConf.__init__(self)
         self.filename = filename
 
-        f = openLocked(self.filename, 0600, False)
+        f = openLocked(self.filename, 0o600, False)
         self.opts = self.parse(f)
         f.close()
 
@@ -41,7 +42,7 @@ class SSSDConfigFile(SSSDChangeConf):
         " Copy the file we operate on to a backup location "
         shutil.copy(file_name, file_name + self.backup_suffix)
         # make sure we don't leak data, force permissions on the backup
-        os.chmod(file_name + self.backup_suffix, 0600)
+        os.chmod(file_name + self.backup_suffix, 0o600)
 
     def get_version(self):
         ver = self.get_option_index('sssd', 'config_file_version')[1]
@@ -50,7 +51,7 @@ class SSSDConfigFile(SSSDChangeConf):
         try:
             return int(ver['value'])
         except ValueError:
-            raise SyntaxError, 'config_file_version not an integer'
+            raise SyntaxError('config_file_version not an integer')
 
     def rename_opts(self, parent_name, rename_kw, type='option'):
         for new_name, old_name in rename_kw.items():
@@ -332,7 +333,7 @@ class SSSDConfigFile(SSSDChangeConf):
         of.write(output)
         of.close()
         # make sure it has the right permissions too
-        os.chmod(out_file_name, 0600)
+        os.chmod(out_file_name, 0o600)
 
     def upgrade_v2(self, out_file_name, backup=True):
         # read in the old file, make backup if needed
@@ -352,7 +353,7 @@ class SSSDConfigFile(SSSDChangeConf):
         of.write(output)
         of.close()
         # make sure it has the right permissions too
-        os.chmod(out_file_name, 0600)
+        os.chmod(out_file_name, 0o600)
 
 def parse_options():
     parser = OptionParser()
@@ -383,7 +384,7 @@ by default""")
 
 def verbose(msg, verbose):
     if verbose:
-        print msg
+        print(msg)
 
 def main():
     options = parse_options()
@@ -397,33 +398,33 @@ def main():
         verbose(traceback.format_exc(), options.verbose)
         print >>sys.stderr, "Cannot parse config file %s" % options.filename
         return 1
-    except Exception, e:
-        print "ERROR: %s" % e
+    except Exception as e:
+        print("ERROR: %s" % e)
         verbose(traceback.format_exc(), options.verbose)
         return 1
 
     # make sure we keep strict settings when creating new files
-    os.umask(0077)
+    os.umask(0o077)
 
     version = config.get_version()
     if version == 2:
         verbose("Looks like v2, only checking changes", options.verbose)
         try:
             config.v2_changes(options.outfile, options.backup)
-        except Exception, e:
-            print "ERROR: %s" % e
+        except Exception as e:
+            print("ERROR: %s" % e)
             verbose(traceback.format_exc(), options.verbose)
             return 1
     elif version == 1:
         verbose("Looks like v1, performing full upgrade", options.verbose)
         try:
             config.upgrade_v2(options.outfile, options.backup)
-        except Exception, e:
-            print "ERROR: %s" % e
+        except Exception as e:
+            print("ERROR: %s" % e)
             verbose(traceback.format_exc(), options.verbose)
             return 1
     else:
-        print >>sys.stderr, "Can only upgrade from v1 to v2, file %s looks like version %d" % (options.filename, config.get_version())
+        print("Can only upgrade from v1 to v2, file %s looks like version %d" % (options.filename, config.get_version()), file=sys.stderr)
         return 1
 
     return 0
diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py
index 78e22f6eff19aac8289d769dc9f565b2d548f4b3..bdca8517dedd793af88fdcc0712f7ab620feb228 100755
--- a/src/config/SSSDConfigTest.py
+++ b/src/config/SSSDConfigTest.py
@@ -148,7 +148,7 @@ class SSSDConfigTestValid(unittest.TestCase):
 
         #Output files should not be readable or writable by
         #non-owners, and should not be executable by anyone
-        self.assertFalse(S_IMODE(mode) & 0177)
+        self.assertFalse(S_IMODE(mode) & 0o177)
 
         #Remove the output file
         os.unlink(of)
@@ -182,7 +182,7 @@ class SSSDConfigTestValid(unittest.TestCase):
 
         #Output files should not be readable or writable by
         #non-owners, and should not be executable by anyone
-        self.assertFalse(S_IMODE(mode) & 0177)
+        self.assertFalse(S_IMODE(mode) & 0o177)
 
         #Remove the output file
         os.unlink(of)
@@ -216,7 +216,7 @@ class SSSDConfigTestValid(unittest.TestCase):
 
         #Output files should not be readable or writable by
         #non-owners, and should not be executable by anyone
-        self.assertFalse(S_IMODE(mode) & 0177)
+        self.assertFalse(S_IMODE(mode) & 0o177)
 
         #Remove the output file
         os.unlink(of)
@@ -1767,7 +1767,7 @@ class SSSDConfigTestSSSDConfig(unittest.TestCase):
 
         #Output files should not be readable or writable by
         #non-owners, and should not be executable by anyone
-        self.assertFalse(S_IMODE(mode) & 0177)
+        self.assertFalse(S_IMODE(mode) & 0o177)
 
         #Remove the output file
         os.unlink(of)
diff --git a/src/external/python.m4 b/src/external/python.m4
index b5d05e49e94a2364531d0014ab68a6526540d29a..25fc7f3972a0f3e13b78160af20a7bde32ab9aec 100644
--- a/src/external/python.m4
+++ b/src/external/python.m4
@@ -13,14 +13,14 @@ dnl versions of python
     AC_MSG_CHECKING([for working python])
     if test -x "$PYTHON"; then
         PYTHON_CFLAGS="`$PYTHON -c \"from distutils import sysconfig; \
-            print '-I' + sysconfig.get_python_inc() + \
+            print('-I' + sysconfig.get_python_inc() + \
             ' -I' + sysconfig.get_python_inc(plat_specific=True) + ' ' + \
-            sysconfig.get_config_var('BASECFLAGS')\"`"
+            sysconfig.get_config_var('BASECFLAGS'))\"`"
         PYTHON_LIBS="`$PYTHON -c \"from distutils import sysconfig; \
-            print \\\" \\\".join(sysconfig.get_config_var('LIBS').split() + \
+            print(' '.join(sysconfig.get_config_var('LIBS').split() + \
             sysconfig.get_config_var('SYSLIBS').split()) + \
-            ' -lpython' + sysconfig.get_config_var('VERSION') + \
-            ' -L' + sysconfig.get_config_var('LIBDIR')\"`"
+            ' ' + sysconfig.get_config_var('BLDLIBRARY') + ' ' + \
+            ' -L' + sysconfig.get_config_var('LIBDIR'))\"`"
             AC_MSG_RESULT([yes])
     else
         AC_MSG_RESULT([no])
@@ -37,12 +37,9 @@ AC_DEFUN([AM_CHECK_PYTHON_HEADERS],
     AC_MSG_CHECKING(for headers required to compile python extensions)
 
     dnl deduce PYTHON_INCLUDES
-    py_prefix=`$PYTHON -c "import sys; print sys.prefix"`
-    py_exec_prefix=`$PYTHON -c "import sys; print sys.exec_prefix"`
-    PYTHON_INCLUDES="-I${py_prefix}/include/python${PYTHON_VERSION}"
-    if test "$py_prefix" != "$py_exec_prefix"; then
-        PYTHON_INCLUDES="$PYTHON_INCLUDES -I${py_exec_prefix}/include/python${PYTHON_VERSION}"
-    fi
+    py_prefix=`$PYTHON -c "import sys; print(sys.prefix)"`
+    py_exec_prefix=`$PYTHON -c "import sys; print(sys.exec_prefix)"`
+    PYTHON_INCLUDES=-I`$PYTHON -c "from distutils import sysconfig; print(sysconfig.get_config_var('INCLUDEPY'))"`
 
     AC_SUBST(PYTHON_INCLUDES)
 
diff --git a/src/python/pyhbac.c b/src/python/pyhbac.c
index dd345a6eb4db8ac6104251d5b9c8f11a160e280d..c46f7c6b300df9eb82fa411673da3d77504080cd 100644
--- a/src/python/pyhbac.c
+++ b/src/python/pyhbac.c
@@ -78,7 +78,7 @@ get_utf8_string(PyObject *obj, const char *attrname)
     const char *a = attrname ? attrname : "attribute";
     PyObject *obj_utf8 = NULL;
 
-    if (PyString_Check(obj)) {
+    if (PyBytes_Check(obj)) {
         obj_utf8 = obj;
         Py_INCREF(obj_utf8); /* Make sure we can DECREF later */
     } else if (PyUnicode_Check(obj)) {
@@ -143,7 +143,7 @@ sequence_as_string_list(PyObject *seq, const char *paramname)
             return NULL;
         }
 
-        ret[i] = py_strdup(PyString_AsString(utf_item));
+        ret[i] = py_strdup(PyBytes_AsString(utf_item));
         Py_DECREF(utf_item);
         if (!ret[i]) {
             Py_DECREF(item);
@@ -172,9 +172,9 @@ verify_sequence(PyObject *seq, const char *attrname)
 static int
 pyobject_to_category(PyObject *o)
 {
-    int c;
+    long c;
 
-    c = PyInt_AsLong(o);
+    c = PYNUMBER_ASLONG(o);
     if (c == -1 && PyErr_Occurred()) {
         PyErr_Format(PyExc_TypeError,
                      "Invalid type for category element - must be an int\n");
@@ -187,7 +187,7 @@ pyobject_to_category(PyObject *o)
             return c;
     }
 
-    PyErr_Format(PyExc_ValueError, "Invalid value %d for category\n", c);
+    PyErr_Format(PyExc_ValueError, "Invalid value %ld for category\n", c);
     return -1;
 }
 
@@ -244,8 +244,11 @@ str_concat_sequence(PyObject *seq, const char *delim)
         item = PySequence_GetItem(seq, i);
         if (item == NULL) goto fail;
 
+#ifdef IS_PY3K
+        part = PyUnicode_AsUTF8(item);
+#else
         part = PyString_AsString(item);
-        if (part == NULL) goto fail;
+#endif
 
         if (s) {
             s = py_strcat_realloc(s, delim);
@@ -325,7 +328,7 @@ static void
 HbacRuleElement_dealloc(HbacRuleElement *self)
 {
     HbacRuleElement_clear(self);
-    self->ob_type->tp_free((PyObject*) self);
+    Py_TYPE(self)->tp_free((PyObject*) self);
 }
 
 static int
@@ -380,7 +383,7 @@ HbacRuleElement_init(HbacRuleElement *self, PyObject *args, PyObject *kwargs)
             return -1;
         }
     } else {
-        tmp = PyInt_FromLong(HBAC_CATEGORY_NULL);
+        tmp = PYNUMBER_FROMLONG(HBAC_CATEGORY_NULL);
         if (!tmp) {
             return -1;
         }
@@ -561,7 +564,7 @@ PyDoc_STRVAR(HbacRuleElement__doc__,
 "names and/or groups and/or category\n");
 
 static PyTypeObject pyhbac_hbacrule_element_type = {
-    PyObject_HEAD_INIT(NULL)
+    PyVarObject_HEAD_INIT(NULL, 0)
     .tp_name = sss_py_const_p(char, "pyhbac.HbacRuleElement"),
     .tp_basicsize = sizeof(HbacRuleElement),
     .tp_new = HbacRuleElement_new,
@@ -699,7 +702,7 @@ static void
 HbacRule_dealloc(HbacRuleObject *self)
 {
     HbacRule_clear(self);
-    self->ob_type->tp_free((PyObject*) self);
+    Py_TYPE(self)->tp_free((PyObject*) self);
 }
 
 static int
@@ -765,13 +768,13 @@ hbac_rule_set_enabled(HbacRuleObject *self, PyObject *enabled, void *closure)
 {
     CHECK_ATTRIBUTE_DELETE(enabled, "enabled");
 
-    if (PyString_Check(enabled) || PyUnicode_Check(enabled)) {
+    if (PyBytes_Check(enabled) || PyUnicode_Check(enabled)) {
         PyObject *utf8_str;
         char *str;
 
         utf8_str = get_utf8_string(enabled, "enabled");
         if (!utf8_str) return -1;
-        str = PyString_AsString(utf8_str);
+        str = PyBytes_AsString(utf8_str);
         if (!str) {
             Py_DECREF(utf8_str);
             return -1;
@@ -794,8 +797,8 @@ hbac_rule_set_enabled(HbacRuleObject *self, PyObject *enabled, void *closure)
     } else if (PyBool_Check(enabled)) {
         self->enabled = (enabled == Py_True);
         return 0;
-    } else if (PyInt_Check(enabled)) {
-        switch(PyInt_AsLong(enabled)) {
+    } else if (PYNUMBER_CHECK(enabled)) {
+        switch(PYNUMBER_ASLONG(enabled)) {
             case 0:
                 self->enabled = false;
                 break;
@@ -832,7 +835,7 @@ hbac_rule_set_name(HbacRuleObject *self, PyObject *name, void *closure)
 {
     CHECK_ATTRIBUTE_DELETE(name, "name");
 
-    if (!PyString_Check(name) && !PyUnicode_Check(name)) {
+    if (!PyBytes_Check(name) && !PyUnicode_Check(name)) {
         PyErr_Format(PyExc_TypeError, "name must be a string or Unicode");
         return -1;
     }
@@ -847,7 +850,7 @@ hbac_rule_get_name(HbacRuleObject *self, void *closure)
     if (PyUnicode_Check(self->name)) {
         Py_INCREF(self->name);
         return self->name;
-    } else if (PyString_Check(self->name)) {
+    } else if (PyBytes_Check(self->name)) {
         return PyUnicode_FromEncodedObject(self->name,
                                            PYHBAC_ENCODING, PYHBAC_ENCODING_ERRORS);
     }
@@ -953,7 +956,7 @@ py_hbac_rule_validate(HbacRuleObject *self, PyObject *args)
          attr <<= 1) {
         if (!(missing & attr)) continue;
 
-        py_attr = PyInt_FromLong(attr);
+        py_attr = PYNUMBER_FROMLONG(attr);
         if (!py_attr) {
             PyErr_NoMemory();
             goto fail;
@@ -1050,7 +1053,7 @@ PyDoc_STRVAR(HbacRuleObject__doc__,
 "and srchosts attributes.\n");
 
 static PyTypeObject pyhbac_hbacrule_type = {
-    PyObject_HEAD_INIT(NULL)
+    PyVarObject_HEAD_INIT(NULL, 0)
     .tp_name = sss_py_const_p(char, "pyhbac.HbacRule"),
     .tp_basicsize = sizeof(HbacRuleObject),
     .tp_new = HbacRule_new,
@@ -1104,7 +1107,7 @@ HbacRule_to_native(HbacRuleObject *pyrule)
         return NULL;
     }
 
-    rule->name = py_strdup(PyString_AsString(utf_name));
+    rule->name = py_strdup(PyBytes_AsString(utf_name));
     Py_DECREF(utf_name);
     if (rule->name == NULL) {
         goto fail;
@@ -1176,7 +1179,7 @@ static void
 HbacRequestElement_dealloc(HbacRequestElement *self)
 {
     HbacRequestElement_clear(self);
-    self->ob_type->tp_free((PyObject*) self);
+    Py_TYPE(self)->tp_free((PyObject*) self);
 }
 
 static int
@@ -1235,7 +1238,7 @@ hbac_request_element_set_name(HbacRequestElement *self,
 {
     CHECK_ATTRIBUTE_DELETE(name, "name");
 
-    if (!PyString_Check(name) && !PyUnicode_Check(name)) {
+    if (!PyBytes_Check(name) && !PyUnicode_Check(name)) {
         PyErr_Format(PyExc_TypeError, "name must be a string or Unicode");
         return -1;
     }
@@ -1250,7 +1253,7 @@ hbac_request_element_get_name(HbacRequestElement *self, void *closure)
     if (PyUnicode_Check(self->name)) {
         Py_INCREF(self->name);
         return self->name;
-    } else if (PyString_Check(self->name)) {
+    } else if (PyBytes_Check(self->name)) {
         return PyUnicode_FromEncodedObject(self->name,
                                            PYHBAC_ENCODING, PYHBAC_ENCODING_ERRORS);
     }
@@ -1341,7 +1344,7 @@ PyDoc_STRVAR(HbacRequestElement__doc__,
 "groups\n");
 
 static PyTypeObject pyhbac_hbacrequest_element_type = {
-    PyObject_HEAD_INIT(NULL)
+    PyVarObject_HEAD_INIT(NULL, 0)
     .tp_name = sss_py_const_p(char, "pyhbac.HbacRequestElement"),
     .tp_basicsize = sizeof(HbacRequestElement),
     .tp_new = HbacRequestElement_new,
@@ -1389,7 +1392,7 @@ HbacRequestElement_to_native(HbacRequestElement *pyel)
         return NULL;
     }
 
-    el->name = py_strdup(PyString_AsString(utf_name));
+    el->name = py_strdup(PyBytes_AsString(utf_name));
     Py_DECREF(utf_name);
     if (!el->name) {
         goto fail;
@@ -1471,7 +1474,7 @@ static void
 HbacRequest_dealloc(HbacRequest *self)
 {
     HbacRequest_clear(self);
-    self->ob_type->tp_free((PyObject*) self);
+    Py_TYPE(self)->tp_free((PyObject*) self);
 }
 
 static int
@@ -1613,7 +1616,7 @@ py_hbac_evaluate(HbacRequest *self, PyObject *args)
         }
         /* FALLTHROUGH */
     case HBAC_EVAL_DENY:
-        ret = PyInt_FromLong(eres);
+        ret = PYNUMBER_FROMLONG(eres);
         break;
     case HBAC_EVAL_ERROR:
         set_hbac_exception(PyExc_HbacError, info);
@@ -1766,7 +1769,7 @@ PyDoc_STRVAR(HbacRequest__doc__,
 "HbacRequest() -> new empty HBAC request");
 
 static PyTypeObject pyhbac_hbacrequest_type = {
-    PyObject_HEAD_INIT(NULL)
+    PyVarObject_HEAD_INIT(NULL, 0)
     .tp_name = sss_py_const_p(char, "pyhbac.HbacRequest"),
     .tp_basicsize = sizeof(HbacRequest),
     .tp_new = HbacRequest_new,
@@ -1901,14 +1904,36 @@ PyDoc_STRVAR(HbacError__doc__,
 "the name of the rule that was being processed. Use hbac_error_string()\n"
 "to get the text representation of the HBAC error");
 
+#ifdef IS_PY3K
+static struct PyModuleDef pyhbacdef = {
+    PyModuleDef_HEAD_INIT,
+    PYTHON_MODULE_NAME,
+    NULL,
+    -1,
+    pyhbac_module_methods,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+PyMODINIT_FUNC
+PyInit_pyhbac(void)
+#else
 PyMODINIT_FUNC
 initpyhbac(void)
+#endif
 {
     PyObject *m;
     int ret;
 
-    m = Py_InitModule(sss_py_const_p(char, PYTHON_MODULE_NAME), pyhbac_module_methods);
-    if (m == NULL) return;
+#ifdef IS_PY3K
+    m = PyModule_Create(&pyhbacdef);
+#else
+    m = Py_InitModule(sss_py_const_p(char, PYTHON_MODULE_NAME),
+                      pyhbac_module_methods);
+#endif
+    if (m == NULL) MODINITERROR;
 
     /* The HBAC module exception */
     PyExc_HbacError = sss_exception_with_doc(
@@ -1917,46 +1942,50 @@ initpyhbac(void)
                         PyExc_EnvironmentError, NULL);
     Py_INCREF(PyExc_HbacError);
     ret = PyModule_AddObject(m, sss_py_const_p(char, "HbacError"), PyExc_HbacError);
-    if (ret == -1) return;
+    if (ret == -1) MODINITERROR;
 
     /* HBAC rule categories */
     ret = PyModule_AddIntMacro(m, HBAC_CATEGORY_NULL);
-    if (ret == -1) return;
+    if (ret == -1) MODINITERROR;
     ret = PyModule_AddIntMacro(m, HBAC_CATEGORY_ALL);
-    if (ret == -1) return;
+    if (ret == -1) MODINITERROR;
 
     /* HBAC rule elements */
     ret = PyModule_AddIntMacro(m, HBAC_RULE_ELEMENT_USERS);
-    if (ret == -1) return;
+    if (ret == -1) MODINITERROR;
     ret = PyModule_AddIntMacro(m, HBAC_RULE_ELEMENT_SERVICES);
-    if (ret == -1) return;
+    if (ret == -1) MODINITERROR;
     ret = PyModule_AddIntMacro(m, HBAC_RULE_ELEMENT_TARGETHOSTS);
-    if (ret == -1) return;
+    if (ret == -1) MODINITERROR;
     ret = PyModule_AddIntMacro(m, HBAC_RULE_ELEMENT_SOURCEHOSTS);
-    if (ret == -1) return;
+    if (ret == -1) MODINITERROR;
 
     /* enum hbac_eval_result */
     ret = PyModule_AddIntMacro(m, HBAC_EVAL_ALLOW);
-    if (ret == -1) return;
+    if (ret == -1) MODINITERROR;
     ret = PyModule_AddIntMacro(m, HBAC_EVAL_DENY);
-    if (ret == -1) return;
+    if (ret == -1) MODINITERROR;
     ret = PyModule_AddIntMacro(m, HBAC_EVAL_ERROR);
-    if (ret == -1) return;
+    if (ret == -1) MODINITERROR;
 
     /* enum hbac_error_code */
     ret = PyModule_AddIntMacro(m, HBAC_ERROR_UNKNOWN);
-    if (ret == -1) return;
+    if (ret == -1) MODINITERROR;
     ret = PyModule_AddIntMacro(m, HBAC_SUCCESS);
-    if (ret == -1) return;
+    if (ret == -1) MODINITERROR;
     ret = PyModule_AddIntMacro(m, HBAC_ERROR_NOT_IMPLEMENTED);
-    if (ret == -1) return;
+    if (ret == -1) MODINITERROR;
     ret = PyModule_AddIntMacro(m, HBAC_ERROR_OUT_OF_MEMORY);
-    if (ret == -1) return;
+    if (ret == -1) MODINITERROR;
     ret = PyModule_AddIntMacro(m, HBAC_ERROR_UNPARSEABLE_RULE);
-    if (ret == -1) return;
+    if (ret == -1) MODINITERROR;
 
     TYPE_READY(m, pyhbac_hbacrule_type, "HbacRule");
     TYPE_READY(m, pyhbac_hbacrule_element_type, "HbacRuleElement");
     TYPE_READY(m, pyhbac_hbacrequest_element_type, "HbacRequestElement");
     TYPE_READY(m, pyhbac_hbacrequest_type, "HbacRequest");
+
+#ifdef IS_PY3K
+    return m;
+#endif
 }
diff --git a/src/python/pysss.c b/src/python/pysss.c
index 9e899f1399553a950e41e157612a7360de4c07b5..684ad72b1c0468bd2327d2b0ec87b5aa7348c349 100644
--- a/src/python/pysss.c
+++ b/src/python/pysss.c
@@ -43,13 +43,24 @@ static char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list,
 
     ret = talloc_array(mem_ctx, char *, PyList_Size(list)+1);
     for (i = 0; i < PyList_Size(list); i++) {
+        char *itemstr;
+        Py_ssize_t itemlen;
         PyObject *item = PyList_GetItem(list, i);
+#ifdef IS_PY3K
+        if (!PyUnicode_Check(item)) {
+#else
         if (!PyString_Check(item)) {
+#endif
             PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
             return NULL;
         }
-        ret[i] = talloc_strndup(ret, PyString_AsString(item),
-                                PyString_Size(item));
+#ifdef IS_PY3K
+        itemstr = PyUnicode_AsUTF8AndSize(item, &itemlen);
+#else
+        itemstr = PyString_AsString(item);
+        itemlen = strlen(itemstr);
+#endif
+        ret[i] = talloc_strndup(ret, itemstr, itemlen);
     }
 
     ret[i] = NULL;
@@ -791,7 +802,13 @@ static PyObject *py_sss_getgrouplist(PyObject *self, PyObject *args)
     for (i = 0; i < ngroups; i++) {
         gr = getgrgid(groups[i]);
         if (gr) {
-            PyTuple_SetItem(groups_tuple, idx, PyString_FromString(gr->gr_name));
+            PyTuple_SetItem(groups_tuple, idx,
+#ifdef IS_PY3K
+                    PyUnicode_FromString(gr->gr_name)
+#else
+                    PyString_FromString(gr->gr_name)
+#endif
+                    );
             idx++;
         }
     }
@@ -817,7 +834,7 @@ fail:
 static void PySssLocalObject_dealloc(PySssLocalObject *self)
 {
     talloc_free(self->mem_ctx);
-    self->ob_type->tp_free((PyObject*) self);
+    Py_TYPE(self)->tp_free((PyObject *)self);
 }
 
 /*
@@ -909,9 +926,9 @@ static PyMethodDef sss_local_methods[] = {
 
 static PyMemberDef sss_local_members[] = {
     { discard_const_p(char, "lock"), T_INT,
-      offsetof(PySssLocalObject, lock), RO, NULL},
+      offsetof(PySssLocalObject, lock), READONLY, NULL},
     { discard_const_p(char, "unlock"), T_INT,
-      offsetof(PySssLocalObject, unlock), RO, NULL},
+      offsetof(PySssLocalObject, unlock), READONLY, NULL},
     {NULL, 0, 0, 0, NULL} /* Sentinel */
 };
 
@@ -919,7 +936,7 @@ static PyMemberDef sss_local_members[] = {
  * sss.local object properties
  */
 static PyTypeObject pysss_local_type = {
-    PyObject_HEAD_INIT(NULL)
+    PyVarObject_HEAD_INIT(NULL, 0)
     .tp_name = sss_py_const_p(char, "sss.local"),
     .tp_basicsize = sizeof(PySssLocalObject),
     .tp_new = PySssLocalObject_new,
@@ -1036,7 +1053,7 @@ fail:
  */
 static void PySssPasswordObject_dealloc(PySssPasswordObject *self)
 {
-    self->ob_type->tp_free((PyObject*) self);
+    Py_TYPE(self)->tp_free((PyObject*) self);
 }
 
 /*
@@ -1079,7 +1096,7 @@ static PyMethodDef sss_password_methods[] = {
  */
 static PyMemberDef sss_password_members[] = {
     { discard_const_p(char, "AES_256"), T_INT,
-      offsetof(PySssPasswordObject, aes_256), RO, NULL},
+      offsetof(PySssPasswordObject, aes_256), READONLY, NULL},
     {NULL, 0, 0, 0, NULL} /* Sentinel */
 };
 
@@ -1087,7 +1104,7 @@ static PyMemberDef sss_password_members[] = {
  * sss.password object properties
  */
 static PyTypeObject pysss_password_type = {
-    PyObject_HEAD_INIT(NULL)
+    PyVarObject_HEAD_INIT(NULL, 0)
     .tp_name = sss_py_const_p(char, "sss.password"),
     .tp_basicsize = sizeof(PySssPasswordObject),
     .tp_new = PySssPasswordObject_new,
@@ -1111,23 +1128,48 @@ static PyMethodDef module_methods[] = {
 /*
  * Module initialization
  */
+#ifdef IS_PY3K
+static struct PyModuleDef pysssdef = {
+    PyModuleDef_HEAD_INIT,
+    "pysss",
+    NULL,
+    -1,
+    module_methods,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+PyMODINIT_FUNC
+PyInit_pysss(void)
+#else
 PyMODINIT_FUNC
 initpysss(void)
+#endif
 {
     PyObject *m;
 
     if (PyType_Ready(&pysss_local_type) < 0)
-        return;
+        MODINITERROR;
     if (PyType_Ready(&pysss_password_type) < 0)
-        return;
+        MODINITERROR;
 
+#ifdef IS_PY3K
+    m = PyModule_Create(&pysssdef);
+#else
     m = Py_InitModule(discard_const_p(char, "pysss"), module_methods);
+#endif
     if (m == NULL)
-        return;
+        MODINITERROR;
 
     Py_INCREF(&pysss_local_type);
     PyModule_AddObject(m, discard_const_p(char, "local"), (PyObject *)&pysss_local_type);
     Py_INCREF(&pysss_password_type);
     PyModule_AddObject(m, discard_const_p(char, "password"), (PyObject *)&pysss_password_type);
+
+#ifdef IS_PY3K
+    return m;
+#endif
 }
 
diff --git a/src/python/pysss_murmur.c b/src/python/pysss_murmur.c
index a193c56da08eb8aba09f88ddc10e23625dbe8f0c..97d752b2a7734a332a5d5da07d75b594638015c8 100644
--- a/src/python/pysss_murmur.c
+++ b/src/python/pysss_murmur.c
@@ -60,10 +60,36 @@ static PyMethodDef methods[] = {
     { NULL,NULL, 0, NULL }
 };
 
+#ifdef IS_PY3K
+static struct PyModuleDef pysss_murmurdef = {
+    PyModuleDef_HEAD_INIT,
+    "pysss_murmur",
+    NULL,
+    -1,
+    methods,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
 
 PyMODINIT_FUNC
+PyInit_pysss_murmur(void)
+#else
+PyMODINIT_FUNC
 initpysss_murmur(void)
+#endif
 {
-    Py_InitModule3(sss_py_const_p(char, "pysss_murmur"),
+    PyObject *m;
+#ifdef IS_PY3K
+    m = PyModule_Create(&pysss_murmurdef);
+#else
+    m = Py_InitModule3(sss_py_const_p(char, "pysss_murmur"),
                    methods, sss_py_const_p(char, "murmur hash functions"));
+#endif
+    if (m == NULL)
+        MODINITERROR;
+#ifdef IS_PY3K
+    return m;
+#endif
 }
diff --git a/src/python/pysss_nss_idmap.c b/src/python/pysss_nss_idmap.c
index 0870b0da614e127c925572a8fc444cee1c6cf441..36d66f405442d63e430f92862990f1656486112d 100644
--- a/src/python/pysss_nss_idmap.c
+++ b/src/python/pysss_nss_idmap.c
@@ -53,7 +53,7 @@ static int add_dict(PyObject *py_result, PyObject *key, PyObject *res_type,
         return ret;
     }
 
-    ret = PyDict_SetItem(py_dict, PyString_FromString(SSS_TYPE_KEY), id_type);
+    ret = PyDict_SetItem(py_dict, PyBytes_FromString(SSS_TYPE_KEY), id_type);
     if (ret != 0) {
         Py_XDECREF(py_dict);
         return ret;
@@ -70,14 +70,14 @@ static char *py_string_or_unicode_as_string(PyObject *inp)
 
     if (PyUnicode_Check(inp)) {
         py_str = PyUnicode_AsUTF8String(inp);
-    } else if (PyString_Check(inp)) {
+    } else if (PyBytes_Check(inp)) {
         py_str = inp;
     } else {
         PyErr_Format(PyExc_TypeError, "input must be unicode or a string");
         return NULL;
     }
 
-    return PyString_AS_STRING(py_str);
+    return PyBytes_AS_STRING(py_str);
 }
 
 static int do_getsidbyname(PyObject *py_result, PyObject *py_name)
@@ -94,8 +94,8 @@ static int do_getsidbyname(PyObject *py_result, PyObject *py_name)
 
     ret = sss_nss_getsidbyname(name, &sid, &id_type);
     if (ret == 0) {
-        ret = add_dict(py_result, py_name, PyString_FromString(SSS_SID_KEY),
-                       PyUnicode_FromString(sid), PyInt_FromLong(id_type));
+        ret = add_dict(py_result, py_name, PyBytes_FromString(SSS_SID_KEY),
+                       PyUnicode_FromString(sid), PYNUMBER_FROMLONG(id_type));
     }
     free(sid);
 
@@ -116,8 +116,8 @@ static int do_getnamebysid(PyObject *py_result, PyObject *py_sid)
 
     ret = sss_nss_getnamebysid(sid, &name, &id_type);
     if (ret == 0) {
-        ret = add_dict(py_result, py_sid, PyString_FromString(SSS_NAME_KEY),
-                       PyUnicode_FromString(name), PyInt_FromLong(id_type));
+        ret = add_dict(py_result, py_sid, PyBytes_FromString(SSS_NAME_KEY),
+                       PyUnicode_FromString(name), PYNUMBER_FROMLONG(id_type));
     }
     free(name);
 
@@ -133,9 +133,12 @@ static int do_getsidbyid(PyObject *py_result, PyObject *py_id)
     int ret;
     enum sss_id_type id_type;
 
+#ifndef IS_PY3K
     if (PyInt_Check(py_id)) {
         id = PyInt_AS_LONG(py_id);
-    } else if (PyLong_Check(py_id)) {
+    } else
+#endif
+    if (PyLong_Check(py_id)) {
         id = PyLong_AsLong(py_id);
     } else {
         id_str = py_string_or_unicode_as_string(py_id);
@@ -155,8 +158,8 @@ static int do_getsidbyid(PyObject *py_result, PyObject *py_id)
 
     ret = sss_nss_getsidbyid((uint32_t) id, &sid, &id_type);
     if (ret == 0) {
-        ret = add_dict(py_result, py_id, PyString_FromString(SSS_SID_KEY),
-                       PyUnicode_FromString(sid), PyInt_FromLong(id_type));
+        ret = add_dict(py_result, py_id, PyBytes_FromString(SSS_SID_KEY),
+                       PyUnicode_FromString(sid), PYNUMBER_FROMLONG(id_type));
     }
     free(sid);
 
@@ -177,8 +180,8 @@ static int do_getidbysid(PyObject *py_result, PyObject *py_sid)
 
     ret = sss_nss_getidbysid(sid, &id, &id_type);
     if (ret == 0) {
-        ret = add_dict(py_result, py_sid, PyString_FromString(SSS_ID_KEY),
-                       PyInt_FromLong(id), PyInt_FromLong(id_type));
+        ret = add_dict(py_result, py_sid, PyBytes_FromString(SSS_ID_KEY),
+                       PYNUMBER_FROMLONG(id), PYNUMBER_FROMLONG(id_type));
     }
 
     return ret;
@@ -220,8 +223,8 @@ static PyObject *check_args(enum lookup_type type, PyObject *args)
     }
 
     if (!(PyList_Check(obj) || PyTuple_Check(obj) ||
-          PyString_Check(obj) || PyUnicode_Check(obj) ||
-          (type == SIDBYID && (PyInt_Check(obj) || PyLong_Check(obj))))) {
+          PyBytes_Check(obj) || PyUnicode_Check(obj) ||
+          (type == SIDBYID && (PYNUMBER_CHECK(obj))))) {
         PyErr_Format(PyExc_ValueError,
                      "Only string, long or list or tuples of them " \
                      "are accepted\n");
@@ -241,9 +244,8 @@ static PyObject *check_args(enum lookup_type type, PyObject *args)
         for(i=0; i < len; i++) {
             py_value = PySequence_GetItem(obj, i);
             if ((py_value != NULL) &&
-                (PyString_Check(py_value) || PyUnicode_Check(py_value) ||
-                 (type == SIDBYID &&
-                  (PyInt_Check(py_value) || PyLong_Check(py_value))))) {
+                (PyBytes_Check(py_value) || PyUnicode_Check(py_value) ||
+                 (type == SIDBYID && PYNUMBER_CHECK(py_value)))) {
                 ret = do_lookup(type, py_result, py_value);
                 if (ret != 0) {
                     /* Skip this name */
@@ -349,15 +351,37 @@ static PyMethodDef methods[] = {
     { NULL,NULL, 0, NULL }
 };
 
+#ifdef IS_PY3K
+static struct PyModuleDef pysss_nss_idmap_def = {
+    PyModuleDef_HEAD_INIT,
+    "pysss_nss_idmap",
+    NULL,
+    -1,
+    methods,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
 
 PyMODINIT_FUNC
+PyInit_pysss_nss_idmap(void)
+#else
+PyMODINIT_FUNC
 initpysss_nss_idmap(void)
+#endif
 {
     PyObject *module;
 
+#ifdef IS_PY3K
+    module = PyModule_Create(&pysss_nss_idmap_def);
+#else
     module = Py_InitModule3(sss_py_const_p(char, "pysss_nss_idmap"),
                             methods,
                             sss_py_const_p(char, "SSSD ID-mapping functions"));
+#endif
+    if (module == NULL)
+        MODINITERROR;
 
     PyModule_AddIntConstant(module, "ID_NOT_SPECIFIED",
                             SSS_ID_TYPE_NOT_SPECIFIED);
@@ -369,4 +393,8 @@ initpysss_nss_idmap(void)
     PyModule_AddStringConstant(module, "NAME_KEY", SSS_NAME_KEY);
     PyModule_AddStringConstant(module, "ID_KEY", SSS_ID_KEY);
     PyModule_AddStringConstant(module, "TYPE_KEY", SSS_TYPE_KEY);
+
+#ifdef IS_PY3K
+    return module;
+#endif
 }
diff --git a/src/tests/pyhbac-test.py b/src/tests/pyhbac-test.py
index c4228368a27741eff568b1a2858d7be072d9fef6..b7f27026b6d1ca12a0759c09e31e1f2c2a2c484c 100755
--- a/src/tests/pyhbac-test.py
+++ b/src/tests/pyhbac-test.py
@@ -1,15 +1,20 @@
 #!/usr/bin/python2
+from __future__ import print_function
 
 import unittest
 import sys
 import os
 import copy
+import sys
 
 srcdir = os.getenv('builddir')
 if not srcdir:
     srcdir = "."
 MODPATH = srcdir + "/.libs" #FIXME - is there a way to get this from libtool?
 
+if sys.version_info[0] > 2:
+    unicode = str
+
 def compat_assertItemsEqual(this, expected_seq, actual_seq, msg=None):
     return this.assertEqual(sorted(expected_seq), sorted(actual_seq))
 
@@ -37,8 +42,8 @@ class PyHbacImport(unittest.TestCase):
         " Import the module and assert it comes from tree "
         try:
             import pyhbac
-        except ImportError, e:
-            print >>sys.stderr, "Could not load the pyhbac module. Please check if it is compiled"
+        except ImportError as e:
+            print("Could not load the pyhbac module. Please check if it is compiled", file=sys.stderr)
             raise e
         self.assertEqual(pyhbac.__file__, MODPATH + "/pyhbac.so")
 
diff --git a/src/tests/pysss_murmur-test.py b/src/tests/pysss_murmur-test.py
index ee0e8b8a0fdef9e6ab825c7fc5f2fe661ec669ea..41cb350f7b1fe1d82a5977eb66233ea2b38441ec 100755
--- a/src/tests/pysss_murmur-test.py
+++ b/src/tests/pysss_murmur-test.py
@@ -17,6 +17,7 @@
 #
 #  You should have received a copy of the GNU General Public License
 #  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+from __future__ import print_function
 
 import unittest
 import sys
@@ -46,6 +47,8 @@ class PySssMurmurImport(unittest.TestCase):
         " Make sure we load the in-tree module "
         self.system_path = sys.path[:]
         sys.path = [ MODPATH ]
+        print (os.getcwd())
+        print(MODPATH)
 
     def tearDown(self):
         " Restore the system path "
@@ -55,8 +58,8 @@ class PySssMurmurImport(unittest.TestCase):
         " Import the module and assert it comes from tree "
         try:
             import pysss_murmur
-        except ImportError, e:
-            print >>sys.stderr, "Could not load the pysss_murmur module. Please check if it is compiled"
+        except ImportError as e:
+            print("Could not load the pysss_murmur module. Please check if it is compiled", file=sys.stderr)
             raise e
         self.assertEqual(pysss_murmur.__file__, MODPATH + "/pysss_murmur.so")
 
diff --git a/src/tests/python-test.py b/src/tests/python-test.py
index 81e09c4bb96fb710e9e5fbcca051fc2c0581fc60..9967d1b5f2ce67f42cb92219ab51491a14910095 100644
--- a/src/tests/python-test.py
+++ b/src/tests/python-test.py
@@ -24,7 +24,7 @@ import os
 import tempfile
 import shutil
 import unittest
-import commands
+import subprocess
 import errno
 
 # module under test
@@ -37,14 +37,17 @@ class LocalTest(unittest.TestCase):
         self.local = pysss.local()
 
     def _run_and_check(self, runme):
-        (status, output) = commands.getstatusoutput(runme)
+        (status, output) = subprocess.call(runme, shell=True)
         self.failUnlessEqual(status, 0, output)
 
     def _get_object_info(self, name, subtree, domain):
         search_dn = "dn=name=%s,cn=%s,cn=%s,cn=sysdb" % (name, subtree, domain)
-        (status, output) = commands.getstatusoutput("ldbsearch -H %s %s" % (self.local_path,search_dn))
-
-        if status: return {}
+        try:
+            output = subprocess.check_call("ldbsearch -H %s %s" % (self.local_path,search_dn),
+                                           shell=True)
+            output = output.decode('utf-8')
+        except subprocess.CalledProcessError:
+            return {}
 
         kw = {}
         for key, value in [ l.split(':') for l in output.split('\n') if ":" in l ]:
@@ -82,9 +85,11 @@ class LocalTest(unittest.TestCase):
 
     def _get_object_membership(self, name, subtree, domain):
         search_dn = "dn=name=%s,cn=%s,cn=%s,cn=sysdb" % (name, subtree, domain)
-        (status, output) = commands.getstatusoutput("ldbsearch -H %s %s" % (self.local_path,search_dn))
-
-        if status:
+        try:
+            output = subprocess.check_call("ldbsearch -H %s %s" % (self.local_path,search_dn),
+                                           shell=True)
+            output = output.decode('utf-8')
+        except subprocess.CalledProcessError:
             return []
 
         members = [ value.strip() for key, value in [ l.split(':') for l in output.split('\n') if ":" in l ] if key == "memberof" ]
@@ -227,7 +232,7 @@ class UseraddTestNegative(LocalTest):
         self.local.useradd(self.username)
         try:
             self.local.useradd(self.username)
-        except IOError, e:
+        except IOError as e:
             self.assertEquals(e.errno, errno.EEXIST)
         else:
             self.fail("Was expecting exception")
@@ -240,7 +245,7 @@ class UseraddTestNegative(LocalTest):
         self.local.useradd(self.username, uid=1025)
         try:
             self.local.useradd("testUseraddUIDAlreadyExists2", uid=1025)
-        except IOError, e:
+        except IOError as e:
             self.assertEquals(e.errno, errno.EEXIST)
         else:
             self.fail("Was expecting exception")
@@ -270,7 +275,7 @@ class UserdelTest(LocalTest):
         self.validate_no_user("testUserdelNegative")
         try:
             self.local.userdel("testUserdelNegative")
-        except IOError, e:
+        except IOError as e:
             self.assertEquals(e.errno, errno.ENOENT)
         else:
             fail("Was expecting exception")
@@ -365,7 +370,7 @@ class GroupaddTestNegative(LocalTest):
         self.local.groupadd(self.groupname)
         try:
             self.local.groupadd(self.groupname)
-        except IOError, e:
+        except IOError as e:
             self.assertEquals(e.errno, errno.EEXIST)
         else:
             self.fail("Was expecting exception")
@@ -378,7 +383,7 @@ class GroupaddTestNegative(LocalTest):
         self.local.groupadd(self.groupname, gid=1025)
         try:
             self.local.groupadd("testGroupaddGIDAlreadyExists2", gid=1025)
-        except IOError, e:
+        except IOError as e:
             self.assertEquals(e.errno, errno.EEXIST)
         else:
             self.fail("Was expecting exception")
@@ -396,7 +401,7 @@ class GroupdelTest(LocalTest):
         self.validate_no_group("testGroupdelNegative")
         try:
             self.local.groupdel("testGroupdelNegative")
-        except IOError, e:
+        except IOError as e:
             self.assertEquals(e.errno, errno.ENOENT)
         else:
             fail("Was expecting exception")
diff --git a/src/util/sss_python.h b/src/util/sss_python.h
index 8f81bf91b2edc05230b06aa8cfa592dcb9325fa4..828bd22ec44fe9493bfaa246b072777b70c7b585 100644
--- a/src/util/sss_python.h
+++ b/src/util/sss_python.h
@@ -11,6 +11,20 @@
 #define sss_py_const_p(type, value) (value)
 #endif
 
+#if PY_MAJOR_VERSION >= 3
+#define IS_PY3K
+#define MODINITERROR return NULL
+#define PYNUMBER_CHECK(what) PyLong_Check(what)
+#define PYNUMBER_FROMLONG(what) PyLong_FromLong(what)
+#define PYNUMBER_ASLONG(what) PyLong_AsLong(what)
+#else
+#include <bytesobject.h>
+#define MODINITERROR return
+#define PYNUMBER_CHECK(what) PyInt_Check(what)
+#define PYNUMBER_FROMLONG(what) PyInt_FromLong(what)
+#define PYNUMBER_ASLONG(what) PyInt_AsLong(what)
+#endif
+
 /* Py_ssize_t compatibility for python < 2.5 as per
  * http://www.python.org/dev/peps/pep-0353/ */
 #ifndef HAVE_PY_SSIZE_T
@@ -45,7 +59,7 @@ sss_exception_with_doc(char *name, char *doc, PyObject *base, PyObject *dict);
 /* Convenience macros */
 #define TYPE_READY(module, type, name) do {         \
     if (PyType_Ready(&type) < 0)                    \
-        return;                                     \
+	MODINITERROR;                               \
     Py_INCREF(&type);                               \
     PyModule_AddObject(module,                      \
                        discard_const_p(char, name), \
-- 
1.9.3



More information about the sssd-devel mailing list