Commits

AJ R committed d33867b

first crude working SavReader version for Py2 and Py3 (yaay)

Comments (0)

Files changed (8)

savReaderWriter/__init__.py

 # -*- coding: utf-8 -*-
 
 """
-SavReaderWriter.py: A cross-platform Python interface to the IBM SPSS
+savReaderWriter: A cross-platform Python interface to the IBM SPSS
 Statistics Input Output Module. Read or Write SPSS system files (.sav, .zsav)
 
-.. moduleauthor:: Albert-Jan Roskam <fomcl@yahoo.com>
+.. moduleauthor:: Albert-Jan Roskam <fomcl "at" yahoo "dot" com>
 
 """
 
 segfaults = False
 
 import os
+import sys
 
 try:
     import psyco
 
 version = __version__
 
+sys.path.insert(0, os.path.dirname(__file__))
+from py3k import *
 from error import *
 from generic import *
 from header import *

savReaderWriter/error.py

     """
     Error class for the IBM SPSS Statistics Input Output Module
     """
-    def __init__(self, msg=u"Unknown", retcode=None):
+    def __init__(self, msg="Unknown", retcode=None):
         self.retcode = retcode
         Exception.__init__(self, msg)
 

savReaderWriter/generic.py

 import math
 import locale
 import encodings
+import collections
 
 from savReaderWriter import *
 
     def _encodeFileName(self, fn):
         """Helper function to encode unicode file names into bytestring file
         names encoded in the file system's encoding. Needed for C functions
-        that have a c_char_p filename argument.
+        that have a c_char_p_ filename argument.
         http://effbot.org/pyref/sys.getfilesystemencoding.htm
         http://docs.python.org/2/howto/unicode.html under 'unicode filenames'"""
         if not isinstance(fn, unicode):
             encoding = "utf-8" if not encoding else encoding  # actually, ascii
         try:
             return fn.encode(encoding)
-        except UnicodeEncodeError, e:
+        except UnicodeEncodeError:
             msg = ("File system encoding %r can not be used to " +
                    "encode file name %r [%s]")
-            raise ValueError(msg % (encoding, fn, e))
+            raise ValueError(msg % (encoding, fn, sys.exc_info()[1]))
 
     def _loadLibs(self, folder):
         """Helper function that loads I/O libraries in the correct order"""
         load = WinDLL if sys.platform.lower().startswith("win") else CDLL
         if libs and debug:
             assert len(libs) == 6, "SPSS I/O needs to load 6 libraries!"
-            print os.path.basename(path).upper().center(79, "-")
-            print "\n".join(libs)
+            print(os.path.basename(path).upper().center(79, "-"))
+            print("\n".join(libs))
         return [load(os.path.join(path, lib)) for lib in libs][-2]
 
     def loadLibrary(self):
         fdopen.argtypes = [c_int, c_char_p]
         fdopen.restype = c_void_p
         fdopen.errcheck = self.errcheck
-        mode_ = "wb" if mode == "cp" else mode
-        with open(savFileName, mode_) as f:
+        mode_ = b"wb" if mode == b"cp" else bytes(mode)
+        with open(savFileName, mode_.decode("utf-8")) as f:
             self.fd = fdopen(f.fileno(), mode_)
         if mode == "rb":
             spssOpen = self.spssio.spssOpenRead
 
         savFileName = self._encodeFileName(savFileName)
         refSavFileName = self._encodeFileName(refSavFileName)
-        sav = c_char_p(savFileName)
+        sav = c_char_p_(savFileName)
         fh = c_int(self.fd)
         if mode == "cp":
-            retcode = spssOpen(sav, c_char_p(refSavFileName), pointer(fh))
+            retcode = spssOpen(sav, c_char_p_(refSavFileName), pointer(fh))
         else:
             retcode = spssOpen(sav, pointer(fh))
 
         msg = "Problem closing file in mode %r" % mode
         checkErrsWarns(msg, retcode)
 
-##    def closeFile(self):
-##        """Close file"""
-##        try:
-##            try:
-##                # Windows
-##                self.libc._close.errcheck = self.errcheck
-##                self.libc._close(c_void_p(self.fd))
-##            except AttributeError:
-##                # Linux
-##                self.libc.close.errcheck = self.errcheck
-##                self.libc.close(c_void_p(self.fd))
-##        except EnvironmentError, e:
-##            print e
-
     @property
     def releaseInfo(self):
         """This function reports release- and machine-specific information
         major = info["release number"]
         minor = info["release subnumber"]
         fixpack = info["fixpack number"]
-        return major, minor, fixpack
+        ver_info = (major, minor, fixpack)
+        return collections.namedtuple("_", "major minor fixpack")(*ver_info)
 
     @property
     def fileCompression(self):
             return self.setLocale
         else:
             currLocale = ".".join(locale.getlocale())
-            print "NOTE. Locale not set; getting current locale: ", currLocale
+            print("NOTE. Locale not set; getting current locale: %s" % currLocale)
             return currLocale
 
     @ioLocale.setter
             localeName = ".".join(locale.getlocale())
         func = self.spssio.spssSetLocale
         func.restype = c_char_p
-        self.setLocale = func(c_int(locale.LC_ALL), c_char_p(localeName))
+        self.setLocale = func(c_int(locale.LC_ALL), c_char_p_(localeName))
         if self.setLocale is None:
             raise ValueError("Invalid ioLocale: %r" % localeName)
         return self.setLocale
                    "character encoding (%s) incompatible with the current " +
                    "ioLocale setting. It may not be readable. Consider " +
                    "changing ioLocale or setting ioUtf8=True.")
-            print msg % (self.savFileName, self.fileEncoding)
+            print(msg % (self.savFileName, self.fileEncoding))
         return bool(isCompatible.value)
 
     @property
                 iana_code = rawEncoding.replace("-", "_")
             fileEncoding = iana_codes[iana_code]
             return fileEncoding
-        except AttributeError:
-            print ("NOTE. Function 'getFileEncoding' not found. You are " +
-                   "using a .dll from SPSS < v16.")
-            return preferredEncoding
         except KeyError:
             print ("NOTE. IANA coding lookup error. Code %r " % iana_code +
                    "does not map to any Python codec.")
     def record(self, record):
         try:
             self.pack_into(self.caseBuffer, 0, *record)
-        except struct.error, e:
-            msg = "Use ioUtf8=True to write unicode strings [%s]" % e
-            raise TypeError(msg)
-        args = c_int(self.fh), c_char_p(self.caseBuffer.raw)
+        except struct.error:
+            msg = "Use ioUtf8=True to write unicode strings [%s]"
+            raise TypeError(msg % sys.exc_info()[1])
+        args = c_int(self.fh), c_char_p_(self.caseBuffer.raw)
         retcode = self.wholeCaseOut(*args)
         if retcode:
             checkErrsWarns("Problem writing row\n" + record, retcode)
         files"""
         if nominator and nominator % 10**4 == 0:
             pctProgress = (float(nominator) / denominator) * 100
-            print "%2.1f%%... " % pctProgress,
+            print("%2.1f%%... " % pctProgress),

savReaderWriter/header.py

 
     @varNamesTypes.setter
     def varNamesTypes(self, varNamesVarTypes):
-        badLengthMsg = "Empty or longer than %s chars" % \
-                       (MAXLENGTHS['SPSS_MAX_VARNAME'][0])
+        badLengthMsg = ("Empty or longer than %s chars" %
+                        (MAXLENGTHS['SPSS_MAX_VARNAME'][0]))
         varNames, varTypes = varNamesVarTypes
         varNameRetcodes = {
             0: ('SPSS_NAME_OK', 'Valid standard name'),
         func = self.spssio.spssSetVarName
         for varName in self.varNames:
             varLength = self.varTypes[varName]
-            retcode = validate(c_char_p(varName))
+            retcode = validate(c_char_p_(varName))
             if retcode:
-                msg = "%r is an invalid variable name [%r]" % \
-                      (varName, ": ".join(varNameRetcodes.get(retcode)))
+                msg = ("%r is an invalid variable name [%r]" %
+                       (varName, ": ".join(varNameRetcodes.get(retcode))))
                 raise SPSSIOError(msg, retcode)
-            retcode = func(c_int(self.fh), c_char_p(varName), c_int(varLength))
+            retcode = func(c_int(self.fh), c_char_p_(varName), c_int(varLength))
             if retcode:
                 msg = "Problem setting variable name %r" % varName
                 checkErrsWarns(msg, retcode)
             if self.varTypes[varName] == 0:
                 valuesArr, labelsArr = initArrays(True)
                 func = self.spssio.spssGetVarNValueLabels
-                retcode = func(c_int(self.fh), c_char_p(vName),
+                retcode = func(c_int(self.fh), c_char_p_(vName),
                                byref(valuesArr), byref(labelsArr),
                                byref(numLabels))
                 valuesArr, labelsArr = initArrays(True, numLabels.value)
             else:
                 valuesArr, labelsArr = initArrays(False)
                 func = self.spssio.spssGetVarCValueLabels
-                retcode = func(c_int(self.fh), c_char_p(vName),
+                retcode = func(c_int(self.fh), c_char_p_(vName),
                                byref(valuesArr), byref(labelsArr),
                                byref(numLabels))
                 valuesArr, labelsArr = initArrays(False, numLabels.value)
 
             # step 2: get labels with array of proper size
-            retcode = func(c_int(self.fh), c_char_p(vName), byref(valuesArr),
+            retcode = func(c_int(self.fh), c_char_p_(vName), byref(valuesArr),
                            byref(labelsArr), byref(numLabels))
             if retcode:
                 msg = "Problem getting value labels of variable %r"  % varName
             valueLabelsX = self.encode(valueLabelsX)
             for value, label in valueLabelsX.iteritems():
                 if self.varTypes[varName] == 0:
-                    retcode = valLabN(c_int(self.fh), c_char_p(varName),
-                                      c_double(value), c_char_p(label))
+                    retcode = valLabN(c_int(self.fh), c_char_p_(varName),
+                                      c_double(value), c_char_p_(label))
                 else:
-                    retcode = valLabC(c_int(self.fh), c_char_p(varName),
-                                      c_char_p(value), c_char_p(label))
+                    retcode = valLabC(c_int(self.fh), c_char_p_(varName),
+                                      c_char_p_(value), c_char_p_(label))
                 if retcode:
                     msg = "Problem setting value labels of variable %r"
                     checkErrsWarns(msg % varName, retcode)
         varLabels = {}
         for varName in self.varNames:
             vName = self.vNames[varName]
-            retcode = func(c_int(self.fh), c_char_p(vName),
+            retcode = func(c_int(self.fh), c_char_p_(vName),
                            byref(varLabel), c_int(lenBuff), byref(c_int()))
             varLabels[varName] = varLabel.value
             if retcode:
         func = self.spssio.spssSetVarLabel
         varLabels = self.encode(varLabels)
         for varName, varLabel in varLabels.iteritems():
-            retcode = func(c_int(self.fh), c_char_p(varName),
-                           c_char_p(varLabel))
+            retcode = func(c_int(self.fh), c_char_p_(varName),
+                           c_char_p_(varLabel))
             if retcode:
                 msg = ("Problem with setting variable label %r of variable %r"
                        % (varLabel, varName))
         self.formats_ = {}
         for varName in self.varNames:
             vName = self.vNames[varName]
-            retcode = func(c_int(self.fh), c_char_p(vName),
+            retcode = func(c_int(self.fh), c_char_p_(vName),
                            byref(printFormat_), byref(printDec_),
                            byref(printWid_))
             if retcode:
         e.g. format F5.3 is returned as 'F' and '5'"""
         regex = re.compile("\w+(?P<varWid>\d+)[.]?\d?", re.I)
         bareformats, varWids = {}, {}
-        for varName, format_ in self.formats.iteritems():
+        for varName, format_ in self.formats.items():
             bareformats[varName] = re.sub(r"\d+.", "", format_)
             varWids[varName] = int(regex.search(format_).group("varWid"))
         return bareformats, varWids
         isAnyVar = re.compile(regex, re.IGNORECASE)
         funcP = self.spssio.spssSetVarPrintFormat  # print type
         funcW = self.spssio.spssSetVarWriteFormat  # write type
-        for varName, format_ in self.encode(formats).iteritems():
+        for varName, format_ in self.encode(formats).items():
             format_ = format_.upper()
             gotString = isStringVar.match(format_)
             gotAny = isAnyVar.match(format_)
             if printFormat is None:
                 raise ValueError(msg)
 
-            args = (c_int(self.fh), c_char_p(varName), c_int(printFormat),
+            args = (c_int(self.fh), c_char_p_(varName), c_int(printFormat),
                     c_int(printDec), c_int(printWid))
             retcode1, retcode2 = funcP(*args), funcW(*args)
             if retcodes.get(retcode1) == "SPSS_INVALID_PRFOR":
                     create_string_buffer(9))
         missingFmt = c_int()
         vName = self.vNames[varName]
-        retcode = func(c_int(self.fh), c_char_p(vName),
+        retcode = func(c_int(self.fh), c_char_p_(vName),
                        byref(missingFmt), *map(byref, args))
         if retcode:
             msg = "Error getting missing value for variable %r" % varName
         varMeasureLevels = {}
         for varName in self.varNames:
             vName = self.vNames[varName]
-            retcode = func(c_int(self.fh), c_char_p(vName),
+            retcode = func(c_int(self.fh), c_char_p_(vName),
                            byref(measureLevel))
             varMeasureLevels[varName] = levels.get(measureLevel.value)
             if retcode:
                 msg = "Valid levels are %"
                 raise ValueError(msg % ", ".join(levels.keys()))
             level = levels.get(level.lower())
-            retcode = func(c_int(self.fh), c_char_p(varName), c_int(level))
+            retcode = func(c_int(self.fh), c_char_p_(varName), c_int(level))
             if retcode:
                 msg = ("Problem setting variable mesasurement level. " +
                        "Valid levels are: %s")
         varColumnWidths = {}
         for varName in self.varNames:
             vName = self.vNames[varName]
-            retcode = func(c_int(self.fh), c_char_p(vName),
+            retcode = func(c_int(self.fh), c_char_p_(vName),
                            byref(varColumnWidth))
             if retcode:
                 msg = "Problem getting column width: %r" % varName
             return
         func = self.spssio.spssSetVarColumnWidth
         for varName, varColumnWidth in varColumnWidths.iteritems():
-            retcode = func(c_int(self.fh), c_char_p(varName),
+            retcode = func(c_int(self.fh), c_char_p_(varName),
                            c_int(varColumnWidth))
             if retcode:
                 msg = "Error setting variable colunm width"
         varAlignments = {}
         for varName in self.varNames:
             vName = self.vNames[varName]
-            retcode = func(c_int(self.fh), c_char_p(vName),
+            retcode = func(c_int(self.fh), c_char_p_(vName),
                            byref(alignment_))
             alignment = alignments[alignment_.value]
             varAlignments[varName] = alignment
                 msg = "Valid alignments are %"
                 raise ValueError(msg % ", ".join(alignments.keys()))
             alignment = alignments.get(varAlignment.lower())
-            retcode = func(c_int(self.fh), c_char_p(varName), c_int(alignment))
+            retcode = func(c_int(self.fh), c_char_p_(varName), c_int(alignment))
             if retcode:
                 msg = "Problem setting variable alignment for variable %r"
                 checkErrsWarns(msg % varName, retcode)
         Returns/Takes a dictionary with SETNAME as keys and a list of SPSS
         variables as values. For example: {'SALARY': ['salbegin',
         'salary'], 'DEMOGR': ['gender', 'minority', 'educ']}"""
-        varSets = c_char_p()
+        varSets = c_char_p_()
         func = self.spssio.spssGetVariableSets
         retcode = func(c_int(self.fh), byref(varSets))
         if retcode:
         varSets_ = []
         for varName, varSet in varSets.iteritems():
             varSets_.append("%s= %s" % (varName, " ".join(varSet)))
-        varSets_ = c_char_p("\n".join(varSets_))
+        varSets_ = c_char_p_("\n".join(varSets_))
         retcode = self.spssio.spssSetVariableSets(c_int(self.fh), varSets_)
         if retcode:
             msg = "Problem setting variable set information"
         varRole_ = c_int()
         for varName in self.varNames:
             vName = self.vNames[varName]
-            retcode = func(c_int(self.fh), c_char_p(vName), byref(varRole_))
+            retcode = func(c_int(self.fh), c_char_p_(vName), byref(varRole_))
             varRole = roles.get(varRole_.value)
             varRoles[varName] = varRole
             if retcode:
         func = self.spssio.spssSetVarRole
         for varName, varRole in varRoles.iteritems():
             varRole = roles.get(varRole)
-            retcode = func(c_int(self.fh), c_char_p(varName), c_int(varRole))
+            retcode = func(c_int(self.fh), c_char_p_(varName), c_int(varRole))
             if retcode:
                 msg = "Problem setting variable role %r for variable %r"
                 checkErrsWarns(msg % (varRole, varName), retcode)
 
             # step 1: get array size
             nAttr = c_int()
-            retcode = func(c_int(self.fh), c_char_p(vName),
+            retcode = func(c_int(self.fh), c_char_p_(vName),
                            byref(attrNamesArr), byref(attrValuesArr),
                            byref(nAttr))
             if retcode:
             nAttr = c_int(nAttr.value)
             attrNamesArr = (POINTER(c_char_p * nAttr.value))()
             attrValuesArr = (POINTER(c_char_p * nAttr.value))()
-            retcode = func(c_int(self.fh), c_char_p(vName),
+            retcode = func(c_int(self.fh), c_char_p_(vName),
                            byref(attrNamesArr), byref(attrValuesArr),
                            byref(nAttr))
             if retcode:
             nAttr = len(attributes)
             attrNames = (c_char_p * nAttr)(*attributes.keys())
             attrValues = (c_char_p * nAttr)(*attributes.values())
-            retcode = func(c_int(self.fh), c_char_p(varName),
+            retcode = func(c_int(self.fh), c_char_p_(varName),
                            pointer(attrNames), pointer(attrValues),
                            c_int(nAttr))
             if retcode:
                 # line below added/modified after Issue #4:
                 # Assertion during creating of multRespDefs
                 rest["valueLen"] = len(str(rest["countedValue"]))
-                template = "%%(valueLen)s %%(countedValue)s %%(lblLen)s %s " \
-                           % tail
+                template = ("%%(valueLen)s %%(countedValue)s %%(lblLen)s %s "
+                            % tail)
             mrespDef += template % rest
             mrespDefs.append(mrespDef.rstrip())
         mrespDefs = "\n".join(mrespDefs)
         # or replace 'normal' MR definitions. I assumed 'complement'.
         #####
 
-        # Alternative approach
-        #nSets = c_int()
-        #func = self.spssio.spssGetMultRespCount
-        #retcode = func(c_int(self.fh), byref(nSets))
-        #if not nSets.value:
-        #    return {}
-        #func = self.spssio.spssGetMultRespDefByIndex
-        #ppSet = c_char_p()
-        #for i in range(nSets.value):
-        #    retcode = func(c_int(self.fh), c_int(i), byref(ppSet))
-        #    print ppSet.value, retcodes.get(retcode, retcode)
-        #    if retcode > 0:
-        #        msg = "Problem getting multiple response definitions"
-        #        raise SPSSIOError(msg, retcode)
-        #    self.freeMemory("spssFreeMultRespDefStruct", ppSet)
-
         ## Normal Multiple response definitions
         func = self.spssio.spssGetMultRespDefs
         mrDefs = c_char_p()
         multRespDefs = {}
         if mrDefs.value:
             for mrDef in mrDefs.value.split("\n"):
-                for setName, rest in self._getMultRespDef(mrDef).iteritems():
+                for setName, rest in self._getMultRespDef(mrDef).items():
                     multRespDefs[setName] = rest
             self.freeMemory("spssFreeMultRespDefs", mrDefs)
 
         ## Extended Multiple response definitions
-        mrDefsEx = c_char_p()
+        mrDefsEx = c_char_p_()
         func = self.spssio.spssGetMultRespDefsEx
         retcode = func(c_int(self.fh), pointer(mrDefsEx))
         if retcode:
             return
         multRespDefs = self._setMultRespDefs(multRespDefs)
         func = self.spssio.spssSetMultRespDefs
-        retcode = func(c_int(self.fh), c_char_p(multRespDefs))
+        retcode = func(c_int(self.fh), c_char_p_(multRespDefs))
         if retcode:
             msg = "Problem setting multiple response definitions"
             checkErrsWarns(msg, retcode)
         if not varName:
             return
         func = self.spssio.spssSetCaseWeightVar
-        retcode = func(c_int(self.fh), c_char_p(varName))
+        retcode = func(c_int(self.fh), c_char_p_(varName))
         if retcode:
             msg = "Problem setting case weight variable name %r" % varName
             checkErrsWarns(msg, retcode)
         isAllInts = all([isinstance(d, int) for d in dateInfo])
         isSixPlusTriplets = (len(dateInfo) - 6) % 3 == 0
         if not isAllInts and isSixPlusTriplets:
-            msg = ("TRENDS date info must consist of 6 fixed elements" +
-                   "+ <nCases> three-element groups of other date info " +
+            msg = ("TRENDS date info must consist of 6 fixed elements"
+                   "+ <nCases> three-element groups of other date info "
                    "(all ints)")
             raise TypeError(msg)
         func = self.spssio.spssSetDateVariables
     @textInfo.setter
     def textInfo(self, savFileName):
         info = (os.path.basename(savFileName), __version__, time.asctime())
-        textInfo = "File '%s' built using SavReaderWriter.py version %s (%s)"
+        textInfo = "File '%s' built using savReaderWriter version %s (%s)"
         textInfo = textInfo % info
         if self.ioUtf8 and isinstance(savFileName, unicode):
             textInfo = textInfo.encode("utf-8")
         func = self.spssio.spssSetTextInfo
-        retcode = func(c_int(self.fh), c_char_p(textInfo[:256]))
+        retcode = func(c_int(self.fh), c_char_p_(textInfo[:256]))
         if retcode:
             checkErrsWarns("Problem setting textInfo", retcode)
 
     @fileLabel.setter
     def fileLabel(self, idStr):
         if idStr is None:
-            idStr = "File created by user %r at %s"[:64] % \
-                    (getpass.getuser(), time.asctime())
+            idStr = ("File created by user %r at %s"[:64] %
+                     (getpass.getuser(), time.asctime()))
         if self.ioUtf8 and isinstance(idStr, unicode):
             idStr = idStr.encode("utf-8")
-        retcode = self.spssio.spssSetIdString(c_int(self.fh), c_char_p(idStr))
+        retcode = self.spssio.spssSetIdString(c_int(self.fh), c_char_p_(idStr))
         if retcode:
             checkErrsWarns("Problem setting file label (id string)", retcode)
 
 
         # write GUI information
         if not retcode:
-            args = c_int(self.fh), c_char_p(asciiGUID)
+            args = c_int(self.fh), c_char_p_(asciiGUID)
             func = self.spssio.spssSetDEWGUID
             retcode = func(*args)
         else:

savReaderWriter/py3k.py

+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+import sys
+import functools
+from ctypes import c_char_p
+
+isPy3k = sys.version_info[0] == 3
+
+try:
+    unicode
+except NameError:
+    basestring = unicode = str  # Python 3
+
+try:
+    xrange
+except NameError:
+    xrange = range
+
+if isPy3k:
+    bytes = functools.partial(bytes, encoding="utf-8")
+
+def c_char_p_(s):
+    """Wrapper for ctypes.c_char_p; in Python 3.x, s is converted to a utf-8
+    encoded bytestring"""
+    if not isPy3k:
+        # # for now, keep this, but later change this so Python 2.7 also takes unicode strings as args
+        return c_char_p(s)
+    else:
+        print("&&&&&  %s" % s)
+        s = s.encode("utf-8") if isinstance(s, str) else s
+        print("-----------> %s" % type(s))
+        return c_char_p(s)
+

savReaderWriter/savHeaderReader.py

                     allValues = [allValues]
                 for varName in allValues:
                     report.append(varName)
-        print os.linesep.join(report)
+        print(os.linesep.join(report))
         return os.linesep.join(report)

savReaderWriter/savReader.py

 import operator
 import locale
 import datetime
+import collections
 
 from savReaderWriter import *
 from header import *
     def __enter__(self):
         """ This function opens the spss data file (context manager)."""
         if self.verbose and self.ioUtf8_:
-            print unicode(self).replace(os.linesep, "\n")
+            print(self.replace(os.linesep, "\n"))
         elif self.verbose:
-            print str(self).replace(os.linesep, "\n")
+            print(str(self).replace(os.linesep, "\n"))
         return iter(self)
 
     def __exit__(self, type, value, tb):
                                              self.nCases)
         return self.fileReport
 
+    @property
+    def shape(self):
+        """This function returns the number of rows (nrows) and columns
+        (ncols) as a namedtuple"""
+        dim = (self.nCases, self.numVars)
+        return collections.namedtuple("_", "nrows ncols")(*dim)
+
     def _isAutoRawMode(self):
         """Helper function for formatValues function. Determines whether
         iterating over each individual value is really needed"""
 
         is_index = False
         rstart = cstart = 0
+        cstop = cstep = None
         try:
             row, col = key
             if row < 0:
             theDate = (self.gregorianEpoch +
                        datetime.timedelta(seconds=spssDateValue))
             return datetime.datetime.strftime(theDate, fmt)
-        except OverflowError:
-            return recodeSysmisTo
-        except TypeError:
-            return recodeSysmisTo
-        except ValueError:
+        except (OverflowError, TypeError, ValueError):
             return recodeSysmisTo
 
     def getFileReport(self, savFileName, varNames, varTypes,
             if diff:
                 msg = "Variable names misspecified (%r)" % ", ".join(diff)
                 raise NameError(msg)
-            varPos = [varNames.index(v) for v in self.varNames
+            varPos = [self.varNames.index(v) for v in self.varNames
                       if v in selectVars]
             self.selector = operator.itemgetter(*varPos)
             header = self.selector(self.varNames)

savReaderWriter/savWriter.py

         varHandle = c_double()
         func = self.spssio.spssGetVarHandle
         for varName in self.varNames:
-            retcode = func(c_int(self.fh), c_char_p(varName), byref(varHandle))
+            retcode = func(c_int(self.fh), c_char_p_(varName), byref(varHandle))
             varHandles[varName] = varHandle.value
             if retcode:
                 msg = "Problem getting variable handle for variable %r"
         else:
             funcC = self.spssio.spssSetValueChar
             retcode = funcC(c_int(self.fh), c_double(varHandle),
-                            c_char_p(value))
+                            c_char_p_(value))
         if retcode:
             isString = isinstance(value, basestring)
             valType = "character" if isString else "numerical"
         nCases = len(records)
         for case, record in enumerate(records):
             self.writerow(record)
-            self.printPctProgress(case, nCases)
+            self.printPctProgress(case, nCases)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.