Hallo,

python 3 uses only the 'str' type, while python 2 also uses 'unicode'.
This patch adds a type_is_str() function to common.py - depending on the
python version, it checks for both. This helper function is used to keep
the complexity outside of the rule classes.

The rule classes get adjusted to use type_is_str() instead of checking
for type(x) == str, which means they support both python versions.

Finally, add test-common.py with some tests for type_is_str().

References: https://bugs.launchpad.net/apparmor/+bug/1513880


I propose this patch for trunk and 2.10 (except the rule/signal.py
change because 2.10 doesn't contain SignalRule yet)


[ 21-change-rule-classes-for-py2-str-type.diff ]

=== modified file ./utils/apparmor/common.py
--- utils/apparmor/common.py    2014-12-17 00:54:04.150444000 +0100
+++ utils/apparmor/common.py    2015-11-29 21:14:49.301661957 +0100
@@ -245,6 +245,15 @@
         return False
     return True
 
+def type_is_str(var):
+    ''' returns True if the given variable is a str (or unicode string when 
using python 2)'''
+    if type(var) == str:
+        return True
+    elif sys.version_info[0] < 3 and type(var) == unicode:  # python 2 
sometimes uses the 'unicode' type
+        return True
+    else:
+        return False
+
 class DebugLogger(object):
     def __init__(self, module_name=__name__):
         self.debugging = False
=== modified file ./utils/apparmor/rule/capability.py
--- utils/apparmor/rule/capability.py   2015-07-17 00:19:58.515815472 +0200
+++ utils/apparmor/rule/capability.py   2015-11-29 21:15:57.373653618 +0100
@@ -14,7 +14,7 @@
 # ----------------------------------------------------------------------
 
 from apparmor.regex import RE_PROFILE_CAP
-from apparmor.common import AppArmorBug, AppArmorException
+from apparmor.common import AppArmorBug, AppArmorException, type_is_str
 from apparmor.rule import BaseRule, BaseRuleset, parse_modifiers
 import re
 
@@ -47,7 +47,7 @@
             self.all_caps = True
             self.capability = set()
         else:
-            if type(cap_list) == str:
+            if type_is_str(cap_list):
                 self.capability = {cap_list}
             elif type(cap_list) == list and len(cap_list) > 0:
                 self.capability = set(cap_list)
=== modified file ./utils/apparmor/rule/change_profile.py
--- utils/apparmor/rule/change_profile.py       2015-07-17 00:19:58.529814641 
+0200
+++ utils/apparmor/rule/change_profile.py       2015-11-29 21:16:36.585638082 
+0100
@@ -14,7 +14,7 @@
 # ----------------------------------------------------------------------
 
 from apparmor.regex import RE_PROFILE_CHANGE_PROFILE, strip_quotes
-from apparmor.common import AppArmorBug, AppArmorException
+from apparmor.common import AppArmorBug, AppArmorException, type_is_str
 from apparmor.rule import BaseRule, BaseRuleset, parse_modifiers, 
quote_if_needed
 
 # setup module translations
@@ -48,7 +48,7 @@
         self.all_execconds = False
         if execcond == ChangeProfileRule.ALL:
             self.all_execconds = True
-        elif type(execcond) == str:
+        elif type_is_str(execcond):
             if not execcond.strip():
                 raise AppArmorBug('Empty exec condition in change_profile 
rule')
             elif execcond.startswith('/') or execcond.startswith('@'):
@@ -62,7 +62,7 @@
         self.all_targetprofiles = False
         if targetprofile == ChangeProfileRule.ALL:
             self.all_targetprofiles = True
-        elif type(targetprofile) == str:
+        elif type_is_str(targetprofile):
             if targetprofile.strip():
                 self.targetprofile = targetprofile
             else:
=== modified file ./utils/apparmor/rule/network.py
--- utils/apparmor/rule/network.py      2015-08-24 21:32:50.122441922 +0200
+++ utils/apparmor/rule/network.py      2015-11-29 21:17:13.125616867 +0100
@@ -16,7 +16,7 @@
 import re
 
 from apparmor.regex import RE_PROFILE_NETWORK
-from apparmor.common import AppArmorBug, AppArmorException
+from apparmor.common import AppArmorBug, AppArmorException, type_is_str
 from apparmor.rule import BaseRule, BaseRuleset, parse_modifiers
 
 # setup module translations
@@ -66,7 +66,7 @@
         self.all_domains = False
         if domain == NetworkRule.ALL:
             self.all_domains = True
-        elif type(domain) == str:
+        elif type_is_str(domain):
             if domain in network_domain_keywords:
                 self.domain = domain
             else:
@@ -78,7 +78,7 @@
         self.all_type_or_protocols = False
         if type_or_protocol == NetworkRule.ALL:
             self.all_type_or_protocols = True
-        elif type(type_or_protocol) == str:
+        elif type_is_str(type_or_protocol):
             if type_or_protocol in network_protocol_keywords:
                 self.type_or_protocol = type_or_protocol
             elif type_or_protocol in network_type_keywords:
=== modified file ./utils/apparmor/rule/rlimit.py
--- utils/apparmor/rule/rlimit.py       2015-07-17 00:19:58.574811968 +0200
+++ utils/apparmor/rule/rlimit.py       2015-11-29 21:18:18.101563810 +0100
@@ -16,7 +16,7 @@
 import re
 
 from apparmor.regex import RE_PROFILE_RLIMIT, strip_quotes
-from apparmor.common import AppArmorBug, AppArmorException
+from apparmor.common import AppArmorBug, AppArmorException, type_is_str
 from apparmor.rule import BaseRule, BaseRuleset, parse_comment, quote_if_needed
 
 # setup module translations
@@ -57,7 +57,7 @@
         if audit or deny or allow_keyword:
             raise AppArmorBug('The audit, allow or deny keywords are not 
allowed in rlimit rules.')
 
-        if type(rlimit) == str:
+        if type_is_str(rlimit):
             if rlimit in rlimit_all:
                 self.rlimit = rlimit
             else:
@@ -70,7 +70,7 @@
         self.all_values = False
         if value == RlimitRule.ALL:
             self.all_values = True
-        elif type(value) == str:
+        elif type_is_str(value):
             if not value.strip():
                 raise AppArmorBug('Empty value in rlimit rule')
 
=== modified file ./utils/apparmor/rule/signal.py
--- utils/apparmor/rule/signal.py       2015-11-23 22:15:45.411432694 +0100
+++ utils/apparmor/rule/signal.py       2015-11-29 21:18:38.877542865 +0100
@@ -16,7 +16,7 @@
 
 from apparmor.aare import AARE
 from apparmor.regex import RE_PROFILE_SIGNAL, RE_PROFILE_NAME
-from apparmor.common import AppArmorBug, AppArmorException
+from apparmor.common import AppArmorBug, AppArmorException, type_is_str
 from apparmor.rule import BaseRule, BaseRuleset, check_and_split_list, 
parse_modifiers, quote_if_needed
 
 # setup module translations
@@ -96,7 +96,7 @@
         self.all_peers = False
         if peer == SignalRule.ALL:
             self.all_peers = True
-        elif type(peer) == str:
+        elif type_is_str(peer):
             if len(peer.strip()) == 0:
                 raise AppArmorBug('Passed empty peer to SignalRule: %s' % 
str(peer))
             self.peer = AARE(peer, False, log_event=log_event)
=== modified file ./utils/test/test-common.py
--- utils/test/test-common.py   2015-11-29 21:58:47.320305689 +0100
+++ utils/test/test-common.py   2015-11-29 21:13:39.121644329 +0100
@@ -0,0 +1,32 @@
+#! /usr/bin/env python
+# ------------------------------------------------------------------
+#
+#    Copyright (C) 2015 Christian Boltz <appar...@cboltz.de>
+#
+#    This program is free software; you can redistribute it and/or
+#    modify it under the terms of version 2 of the GNU General Public
+#    License published by the Free Software Foundation.
+#
+# ------------------------------------------------------------------
+
+import unittest
+from common_test import AATest, setup_all_loops
+
+from apparmor.common import type_is_str
+
+class TestIs_str_type(AATest):
+    tests = [
+        ('foo',     True),
+        (u'foo',    True),
+        (42,        False),
+        (True,      False),
+        ([],        False),
+    ]
+
+    def _run_test(self, params, expected):
+        self.assertEqual(type_is_str(params), expected)
+
+
+setup_all_loops(__name__)
+if __name__ == '__main__':
+    unittest.main(verbosity=2)


Regards,

Christian Boltz
-- 
[BILD] Als langjährig tätiger Strafverteidiger (und Fan von Volker
Pispers) muß ich jedoch dringend davor warnen, stinkende tote Fische in
dieses Freiexemplar der sogenannten "Zeitung" einzuwickeln. Weil das ein
Strafverfahren wegen Beleidigung zulasten des Fisches nach sich ziehen
könnte.
[http://www.kanzlei-hoenig.de/2012/keine-stinkende-tote-fische-im-briefkasten/]


-- 
AppArmor mailing list
AppArmor@lists.ubuntu.com
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/apparmor

Reply via email to