Skip to contentSkip to conversation

Make scripts compatible with Python 3

PATCH New Nicolas Iooss 2 participants 3 messages Mar 23, 2014 – Mar 27, 2014

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Make scripts compatible with Python 3

Here are all the changes which are needed to make the scripts compatible with Python 3 while keeping compatibility with Python 2.6 and 2.7:

* use subprocess module instead of commands,
* use sys.maxsize instead of sys.maxint,
* use print as a function,
* use "as" keyword in except statements.

---
 support/genhomedircon   | 56 ++++++++++++++++++++++++-------------------------
 support/gennetfilter.py | 54 +++++++++++++++++++++++------------------------
 support/policyvers.py   |  2 +-
 support/pyplate.py      |  4 ++--
 4 files changed, 58 insertions(+), 58 deletions(-)
support/genhomedircon +28 -28
index 33dbcc1..ca296f9 100644
@@ -40,13 +40,13 @@
 #  are always "real" (including root, in the default configuration).
 #
 
-import commands, sys, os, pwd, string, getopt, re
+import subprocess, sys, os, pwd, string, getopt, re
 
 EXCLUDE_LOGINS=["/sbin/nologin", "/bin/false"]
 
 def getStartingUID():
-	starting_uid = sys.maxint
-	rc=commands.getstatusoutput("grep -h '^UID_MIN' /etc/login.defs")
+	starting_uid = sys.maxsize
+	rc=subprocess.getstatusoutput("grep -h '^UID_MIN' /etc/login.defs")
 	if rc[0] == 0:
 		uid_min = re.sub("^UID_MIN[^0-9]*", "", rc[1])
 		#stip any comment from the end of the line
@@ -54,7 +54,7 @@ def getStartingUID():
 		uid_min = uid_min.strip()
 		if int(uid_min) < starting_uid:
 			starting_uid = int(uid_min)
-	rc=commands.getstatusoutput("grep -h '^LU_UIDNUMBER' /etc/libuser.conf")
+	rc=subprocess.getstatusoutput("grep -h '^LU_UIDNUMBER' /etc/libuser.conf")
 	if rc[0] == 0:
 		lu_uidnumber = re.sub("^LU_UIDNUMBER[^0-9]*", "", rc[1])
 		#stip any comment from the end of the line
@@ -63,7 +63,7 @@ def getStartingUID():
 		lu_uidnumber = lu_uidnumber.strip()
 		if int(lu_uidnumber) < starting_uid:
 			starting_uid = int(lu_uidnumber)
-	if starting_uid == sys.maxint:
+	if starting_uid == sys.maxsize:
 		starting_uid = 500
 	return starting_uid
 
@@ -87,7 +87,7 @@ def getPrefixes():
 	return prefixes
  
 def getUsers(filecontextdir):
-	rc = commands.getstatusoutput("grep ^user %s/users" % filecontextdir)
+	rc = subprocess.getstatusoutput("grep ^user %s/users" % filecontextdir)
 	udict = {}
 	if rc[0] == 0:
 		ulist = rc[1].strip().split("\n")
@@ -113,9 +113,9 @@ def getUsers(filecontextdir):
 	return udict
 
 def update(filecontext, user, prefs):
-	rc=commands.getstatusoutput("grep -h '^HOME_DIR' %s | grep -v vmware | sed -e 's|HOME_DIR|%s|' -e 's/ROLE/%s/' -e 's/system_u/%s/'" % (filecontext, prefs["home"], prefs["role"], user))
+	rc=subprocess.getstatusoutput("grep -h '^HOME_DIR' %s | grep -v vmware | sed -e 's|HOME_DIR|%s|' -e 's/ROLE/%s/' -e 's/system_u/%s/'" % (filecontext, prefs["home"], prefs["role"], user))
 	if rc[0] == 0:
-		print rc[1]
+		print(rc[1])
 	else:
 		errorExit(string.join("grep/sed error ", rc[1]))
 	return rc
@@ -128,7 +128,7 @@ def oldgenhomedircon(filecontextdir, filecontext):
 		usage()
         #We are going to define home directory used by libuser and show-utils as a home directory root
         prefixes = {}
-        rc=commands.getstatusoutput("grep -h '^HOME' /etc/default/useradd")
+        rc=subprocess.getstatusoutput("grep -h '^HOME' /etc/default/useradd")
         if rc[0] == 0:
                 homedir = rc[1].split("=")[1]
                 homedir = homedir.split("#")[0]
@@ -143,7 +143,7 @@ def oldgenhomedircon(filecontextdir, filecontext):
                         sys.stderr.flush()
 
 
-        rc=commands.getstatusoutput("grep -h '^LU_HOMEDIRECTORY' /etc/libuser.conf")
+        rc=subprocess.getstatusoutput("grep -h '^LU_HOMEDIRECTORY' /etc/libuser.conf")
         if rc[0] == 0:
                 homedir = rc[1].split("=")[1]
                 homedir = homedir.split("#")[0]
@@ -165,7 +165,7 @@ def oldgenhomedircon(filecontextdir, filecontext):
         #this works by grepping the file_contexts for
         # 1. ^/ makes sure this is not a comment
         # 2. prints only the regex in the first column first cut on \t then on space
-        rc=commands.getstatusoutput("grep \"^/\" %s | cut -f 1 | cut -f 1 -d \" \" " %  (sys.argv[2]) )
+        rc=subprocess.getstatusoutput("grep \"^/\" %s | cut -f 1 | cut -f 1 -d \" \" " %  (sys.argv[2]) )
         if rc[0] == 0:
                 prefix_regex = rc[1].split("\n")
         else:
@@ -204,14 +204,14 @@ def oldgenhomedircon(filecontextdir, filecontext):
 	sed_dir = "h; s|^HOME_DIR|%s/[^/]+|; s|ROLE_|user_|" % (string.join(prefixes.keys(), "/[^/]+|; s|ROLE_|user_|; p; g; s|^HOME_DIR|"),)
 
 	# Fill in HOME_ROOT, HOME_DIR, and ROLE for users not explicitly defined in /etc/security/selinux/src/policy/users
-	rc=commands.getstatusoutput("sed -e \"/^HOME_ROOT/{%s}\" -e \"/^HOME_DIR/{%s}\" %s" % (sed_root, sed_dir, filecontext))
+	rc=subprocess.getstatusoutput("sed -e \"/^HOME_ROOT/{%s}\" -e \"/^HOME_DIR/{%s}\" %s" % (sed_root, sed_dir, filecontext))
 	if rc[0] == 0:
-		print rc[1]
+		print(rc[1])
 	else:
 		errorExit(string.join("sed error ", rc[1]))
 
 	users = getUsers(filecontextdir)
-	print "\n#\n# User-specific file contexts\n#\n"
+	print("\n#\n# User-specific file contexts\n#\n")
 
 	# Fill in HOME and ROLE for users that are defined
 	for u in users.keys():
@@ -225,7 +225,7 @@ def oldgenhomedircon(filecontextdir, filecontext):
 
 def getDefaultHomeDir():
 	ret = []
-	rc=commands.getstatusoutput("grep -h '^HOME' /etc/default/useradd")
+	rc=subprocess.getstatusoutput("grep -h '^HOME' /etc/default/useradd")
 	if rc[0] == 0:
 		homedir = rc[1].split("=")[1]
 		homedir = homedir.split("#")[0]
@@ -238,7 +238,7 @@ def getDefaultHomeDir():
 			sys.stderr.write("%s\n" % rc[1])
 			sys.stderr.write("You do not have access to /etc/default/useradd HOME=\n")
 			sys.stderr.flush()
-	rc=commands.getstatusoutput("grep -h '^LU_HOMEDIRECTORY' /etc/libuser.conf")
+	rc=subprocess.getstatusoutput("grep -h '^LU_HOMEDIRECTORY' /etc/libuser.conf")
 	if rc[0] == 0:
 		homedir = rc[1].split("=")[1]
 		homedir = homedir.split("#")[0]
@@ -256,7 +256,7 @@ def getDefaultHomeDir():
 	return ret
 
 def getSELinuxType(directory):
-	rc=commands.getstatusoutput("grep ^SELINUXTYPE= %s/config" % directory)
+	rc=subprocess.getstatusoutput("grep ^SELINUXTYPE= %s/config" % directory)
 	if rc[0]==0:
 		return rc[1].split("=")[-1].strip()
 	return "targeted"
@@ -299,7 +299,7 @@ class selinuxConfig:
 		return self.getFileContextDir()+"/homedir_template"
 
 	def getHomeRootContext(self, homedir):
-		rc=commands.getstatusoutput("grep HOME_ROOT  %s | sed -e \"s|^HOME_ROOT|%s|\"" % ( self.getHomeDirTemplate(), homedir))
+		rc=subprocess.getstatusoutput("grep HOME_ROOT  %s | sed -e \"s|^HOME_ROOT|%s|\"" % ( self.getHomeDirTemplate(), homedir))
 		if rc[0] == 0:
 			return rc[1]+"\n"
 		else:
@@ -318,10 +318,10 @@ class selinuxConfig:
 
 	def getUsers(self):
 		users=""
-		rc = commands.getstatusoutput('grep "^user" %s' % self.getSystemUsersFile())
+		rc = subprocess.getstatusoutput('grep "^user" %s' % self.getSystemUsersFile())
 		if rc[0] == 0:
 			users+=rc[1]+"\n"
-		rc = commands.getstatusoutput("grep ^user %s" % self.getUsersFile())
+		rc = subprocess.getstatusoutput("grep ^user %s" % self.getUsersFile())
 		if rc[0] == 0:
 			users+=rc[1]
 		udict = {}
@@ -351,7 +351,7 @@ class selinuxConfig:
 
 	def getHomeDirContext(self, user, home, role):
 		ret="\n\n#\n# Context for user %s\n#\n\n" % user
-		rc=commands.getstatusoutput("grep '^HOME_DIR' %s | sed -e 's|HOME_DIR|%s|' -e 's/ROLE/%s/' -e 's/system_u/%s/'" % (self.getHomeDirTemplate(), home, role, user))
+		rc=subprocess.getstatusoutput("grep '^HOME_DIR' %s | sed -e 's|HOME_DIR|%s|' -e 's/ROLE/%s/' -e 's/system_u/%s/'" % (self.getHomeDirTemplate(), home, role, user))
 		return ret + rc[1] + "\n"
 
 	def genHomeDirContext(self):
@@ -363,12 +363,12 @@ class selinuxConfig:
 		return ret+"\n"
 
 	def checkExists(self, home):
-		if commands.getstatusoutput("grep -E '^%s[^[:alnum:]_-]' %s" % (home, self.getFileContextFile()))[0] == 0:
+		if subprocess.getstatusoutput("grep -E '^%s[^[:alnum:]_-]' %s" % (home, self.getFileContextFile()))[0] == 0:
 			return 0
 		#this works by grepping the file_contexts for
 		# 1. ^/ makes sure this is not a comment
 		# 2. prints only the regex in the first column first cut on \t then on space
-		rc=commands.getstatusoutput("grep \"^/\" %s | cut -f 1 | cut -f 1 -d \" \" " %  self.getFileContextFile() )
+		rc=subprocess.getstatusoutput("grep \"^/\" %s | cut -f 1 | cut -f 1 -d \" \" " %  self.getFileContextFile() )
 		if rc[0] == 0:
 			prefix_regex = rc[1].split("\n")
 		else:
@@ -426,14 +426,14 @@ class selinuxConfig:
 		return ret
 
 	def printout(self):
-		print self.genoutput()
+		print(self.genoutput())
 
 	def write(self):
 		try:
 			fd = open(self.getFileContextDir()+"/file_contexts.homedirs", "w")
 			fd.write(self.genoutput())
 			fd.close()
-		except IOError, error:
+		except IOError as error:
 			sys.stderr.write("%s: %s\n" % ( sys.argv[0], error ))
 
 
@@ -473,9 +473,9 @@ try:
 	selconf=selinuxConfig(directory, type, usepwd)
 	selconf.write()
 
-except getopt.error, error:
+except getopt.error as error:
 	errorExit(string.join("Options Error ", error))
-except ValueError, error:
+except ValueError as error:
 	errorExit(string.join("ValueError ", error))
-except IndexError, error:
+except IndexError as error:
 	errorExit("IndexError")
support/gennetfilter.py +27 -27

94 lines not on this page · raw message

support/policyvers.py +1 -1
index 0d969a4..a367ef1 100644
@@ -1,4 +1,4 @@
 #!/usr/bin/python
 import selinux
 if selinux.is_selinux_enabled():
-	print selinux.security_policyvers()
+	print(selinux.security_policyvers())
support/pyplate.py +2 -2
index 44b662a..96f057b 100644
@@ -182,7 +182,7 @@ class ForTemplateNode(TemplateNode):
       self.vars = []
       for v in self.vars_temp:
         self.vars.append(v.strip())
-      #print self.vars
+      #print(self.vars)
       self.expression = match.group(2)
 
   def execute(self, stream, data):
@@ -258,7 +258,7 @@ class FunctionTemplateNode(TemplateNode):
     self.vars = []
     for v in self.vars_temp:
       self.vars.append(v.strip())
-    #print self.vars
+    #print(self.vars)
     self.parent.functions[self.function_name] = self
 
   def execute(self, stream, data):
Signature · 1 line
1.9.0
#1 lore raw

PATCH 1/1 Make scripts compatible with Python 3

2014-03-23 22:05 GMT+01:00 Nicolas Iooss <[email protected]>:

Quoted 4 lines

Here are all the changes which are needed to make the scripts compatible with Python 3 while keeping compatibility with Python 2.6 and 2.7:

* use subprocess module instead of commands,

I've learnt today that Python 2 doesn't have subprocess.getstatusoutput function even though the commands module is deprecated [1] and Python 3 provides it without documenting "New in python 3" [2] :( I haven't tested building the monolithic policy with Python 2 after my patch so it didn't occurred to me that this specific config is broken. I think it's best to cancel at least the support/genhomedircon part of this patch for now.

Looking at that, is there any reason why support/genhomedircon uses lines like this instead of opening the file with open() and parsing the file with Python code?

    rc=commands.getstatusoutput("grep \"^/\" %s | cut -f 1 | cut -f 1

-d \" \" " % (sys.argv[2]) )

I believe that every "commands.getstatusoutput" call can be replaced by pure Python code. I'll send a patch soon (maybe a few days) which does exactly this, if it's possible and if nobody tells me I'm wrong in doing that.

Regards,

Nicolas

[1] http://docs.python.org/2/library/commands.html
[2] http://docs.python.org/3.0/library/subprocess.html#subprocess.getstatusoutput

#2 lore raw

PATCH 1/1 Make scripts compatible with Python 3

Quoted 18 lines · Nicolas Iooss

2014-03-23 22:05 GMT+01:00 Nicolas Iooss <[email protected]>:

Quoted 4 lines

Here are all the changes which are needed to make the scripts compatible with Python 3 while keeping compatibility with Python 2.6 and 2.7:

* use subprocess module instead of commands,

I've learnt today that Python 2 doesn't have subprocess.getstatusoutput function even though the commands module is deprecated [1] and Python 3 provides it without documenting "New in python 3" [2] :( I haven't tested building the monolithic policy with Python 2 after my patch so it didn't occurred to me that this specific config is broken. I think it's best to cancel at least the support/genhomedircon part of this patch for now.

Looking at that, is there any reason why support/genhomedircon uses lines like this instead of opening the file with open() and parsing the file with Python code?

Quoted 7 lines
    rc=commands.getstatusoutput("grep \"^/\" %s | cut -f 1 | cut -f 1

-d \" \" " % (sys.argv[2]) )

I believe that every "commands.getstatusoutput" call can be replaced by pure Python code. I'll send a patch soon (maybe a few days) which does exactly this, if it's possible and if nobody tells me I'm wrong in doing that.

I wouldn't worry about that script. We kept it around to work on RHEL4 systems. That OS has been end of life for a while, so I'll probably remove the RHEL4 refpolicy stuff very soon.

Signature · 3 lines
Chris PeBenito
Tresys Technology, LLC
www.tresys.com | oss.tresys.com