Browse code

Migrate basestring to a python3 compatible type (#17199)

Toshio Kuratomi authored on 2016/08/24 05:13:44
Showing 28 changed files
... ...
@@ -277,7 +277,8 @@ To test if something is a string, consider that it may be unicode.
277 277
     if type(x) == str:
278 278
 
279 279
     # yes
280
-    if isinstance(x, basestring):
280
+    from ansible.compat.six import string_types
281
+    if isinstance(x, string_types):
281 282
 
282 283
 Cleverness
283 284
 ==========
... ...
@@ -148,6 +148,7 @@ from pynsot.client import get_api_client
148 148
 from pynsot.app import HttpServerError
149 149
 from click.exceptions import UsageError
150 150
 
151
+from six import string_types
151 152
 
152 153
 def warning(*objs):
153 154
         print("WARNING: ", *objs, file=sys.stderr)
... ...
@@ -251,7 +252,7 @@ class NSoTInventory(object):
251 251
         obj[group]['hosts'] = []
252 252
         obj[group]['vars'] = hostvars
253 253
         try:
254
-            assert isinstance(query, basestring)
254
+            assert isinstance(query, string_types)
255 255
         except:
256 256
             sys.exit('ERR: Group queries must be a single string\n'
257 257
                      '  Group: %s\n'
... ...
@@ -40,7 +40,7 @@ import sys
40 40
 import time
41 41
 import ConfigParser
42 42
 
43
-from six import text_type
43
+from six import text_type, string_types
44 44
 
45 45
 # Disable logging message trigged by pSphere/suds.
46 46
 try:
... ...
@@ -160,7 +160,7 @@ class VMwareInventory(object):
160 160
             if isinstance(v, collections.MutableMapping):
161 161
                 items.extend(self._flatten_dict(v, new_key, sep).items())
162 162
             elif isinstance(v, (list, tuple)):
163
-                if all([isinstance(x, basestring) for x in v]):
163
+                if all([isinstance(x, string_types) for x in v]):
164 164
                     items.append((new_key, v))
165 165
             else:
166 166
                 items.append((new_key, v))
... ...
@@ -208,7 +208,7 @@ class VMwareInventory(object):
208 208
                 if obj_info != ():
209 209
                     l.append(obj_info)
210 210
             return l
211
-        elif isinstance(obj, (type(None), bool, int, long, float, basestring)):
211
+        elif isinstance(obj, (type(None), bool, int, long, float, string_types)):
212 212
             return obj
213 213
         else:
214 214
             return ()
... ...
@@ -24,7 +24,7 @@ import os
24 24
 import traceback
25 25
 import textwrap
26 26
 
27
-from ansible.compat.six import iteritems
27
+from ansible.compat.six import iteritems, string_types
28 28
 
29 29
 from ansible import constants as C
30 30
 from ansible.errors import AnsibleError, AnsibleOptionsError
... ...
@@ -309,13 +309,13 @@ class DocCLI(CLI):
309 309
 
310 310
         maintainers = set()
311 311
         if 'author' in doc:
312
-            if isinstance(doc['author'], basestring):
312
+            if isinstance(doc['author'], string_types):
313 313
                 maintainers.add(doc['author'])
314 314
             else:
315 315
                 maintainers.update(doc['author'])
316 316
 
317 317
         if 'maintainers' in doc:
318
-            if isinstance(doc['maintainers'], basestring):
318
+            if isinstance(doc['maintainers'], string_types):
319 319
                 maintainers.add(doc['author'])
320 320
             else:
321 321
                 maintainers.update(doc['author'])
... ...
@@ -30,6 +30,7 @@ import urllib
30 30
 from urllib2 import quote as urlquote, HTTPError
31 31
 
32 32
 import ansible.constants as C
33
+from ansible.compat.six import string_types
33 34
 from ansible.errors import AnsibleError
34 35
 from ansible.module_utils.urls import open_url
35 36
 from ansible.galaxy.token import GalaxyToken
... ...
@@ -41,22 +42,24 @@ except ImportError:
41 41
     from ansible.utils.display import Display
42 42
     display = Display()
43 43
 
44
+
44 45
 def g_connect(method):
45 46
     ''' wrapper to lazily initialize connection info to galaxy '''
46 47
     def wrapped(self, *args, **kwargs):
47 48
         if not self.initialized:
48 49
             display.vvvv("Initial connection to galaxy_server: %s" % self._api_server)
49 50
             server_version = self._get_server_api_version()
50
-            if not server_version in self.SUPPORTED_VERSIONS:
51
+            if server_version not in self.SUPPORTED_VERSIONS:
51 52
                 raise AnsibleError("Unsupported Galaxy server API version: %s" % server_version)
52 53
 
53 54
             self.baseurl = '%s/api/%s' % (self._api_server, server_version)
54
-            self.version = server_version # for future use
55
+            self.version = server_version  # for future use
55 56
             display.vvvv("Base API: %s" % self.baseurl)
56 57
             self.initialized = True
57 58
         return method(self, *args, **kwargs)
58 59
     return wrapped
59 60
 
61
+
60 62
 class GalaxyAPI(object):
61 63
     ''' This class is meant to be used as a API client for an Ansible Galaxy server '''
62 64
 
... ...
@@ -77,7 +80,6 @@ class GalaxyAPI(object):
77 77
         if galaxy.options.api_server != C.GALAXY_SERVER:
78 78
             self._api_server = galaxy.options.api_server
79 79
 
80
-
81 80
     def __auth_header(self):
82 81
         token = self.token.get()
83 82
         if token is None:
... ...
@@ -112,7 +114,7 @@ class GalaxyAPI(object):
112 112
         """
113 113
         url = '%s/api/' % self._api_server
114 114
         try:
115
-            return_data =open_url(url, validate_certs=self._validate_certs)
115
+            return_data = open_url(url, validate_certs=self._validate_certs)
116 116
         except Exception as e:
117 117
             raise AnsibleError("Failed to get data from the API server (%s): %s " % (url, to_str(e)))
118 118
 
... ...
@@ -121,7 +123,7 @@ class GalaxyAPI(object):
121 121
         except Exception as e:
122 122
             raise AnsibleError("Could not process data from the API server (%s): %s " % (url, to_str(e)))
123 123
 
124
-        if not 'current_version' in data:
124
+        if 'current_version' not in data:
125 125
             raise AnsibleError("missing required 'current_version' from server response (%s)" % url)
126 126
 
127 127
         return data['current_version']
... ...
@@ -159,9 +161,9 @@ class GalaxyAPI(object):
159 159
         Check the status of an import task.
160 160
         """
161 161
         url = '%s/imports/' % self.baseurl
162
-        if not task_id is None:
162
+        if task_id is not None:
163 163
             url = "%s?id=%d" % (url,task_id)
164
-        elif not github_user is None and not github_repo is None:
164
+        elif github_user is not None and github_repo is not None:
165 165
             url = "%s?github_user=%s&github_repo=%s" % (url,github_user,github_repo)
166 166
         else:
167 167
             raise AnsibleError("Expected task_id or github_user and github_repo")
... ...
@@ -249,11 +251,11 @@ class GalaxyAPI(object):
249 249
         page_size = kwargs.get('page_size', None)
250 250
         author = kwargs.get('author', None)
251 251
 
252
-        if tags and isinstance(tags, basestring):
252
+        if tags and isinstance(tags, string_types):
253 253
             tags = tags.split(',')
254 254
             search_url += '&tags_autocomplete=' + '+'.join(tags)
255 255
 
256
-        if platforms and isinstance(platforms, basestring):
256
+        if platforms and isinstance(platforms, string_types):
257 257
             platforms = platforms.split(',')
258 258
             search_url += '&platforms_autocomplete=' + '+'.join(platforms)
259 259
 
... ...
@@ -133,54 +133,10 @@ except ImportError:
133 133
     except ImportError:
134 134
         pass
135 135
 
136
-try:
137
-    # Python 2.6+
138
-    from ast import literal_eval
139
-except ImportError:
140
-    # a replacement for literal_eval that works with python 2.4. from:
141
-    # https://mail.python.org/pipermail/python-list/2009-September/551880.html
142
-    # which is essentially a cut/paste from an earlier (2.6) version of python's
143
-    # ast.py
144
-    from compiler import ast, parse
145
-
146
-    def literal_eval(node_or_string):
147
-        """
148
-        Safely evaluate an expression node or a string containing a Python
149
-        expression.  The string or node provided may only consist of the  following
150
-        Python literal structures: strings, numbers, tuples, lists, dicts,  booleans,
151
-        and None.
152
-        """
153
-        _safe_names = {'None': None, 'True': True, 'False': False}
154
-        # Okay to use basestring and long here because this is only for
155
-        # python 2.4 and 2.5
156
-        if isinstance(node_or_string, basestring):
157
-            node_or_string = parse(node_or_string, mode='eval')
158
-        if isinstance(node_or_string, ast.Expression):
159
-            node_or_string = node_or_string.node
160
-
161
-        def _convert(node):
162
-            if isinstance(node, ast.Const) and isinstance(node.value, (basestring, int, float, long, complex)):
163
-                return node.value
164
-            elif isinstance(node, ast.Tuple):
165
-                return tuple(map(_convert, node.nodes))
166
-            elif isinstance(node, ast.List):
167
-                return list(map(_convert, node.nodes))
168
-            elif isinstance(node, ast.Dict):
169
-                return dict((_convert(k), _convert(v)) for k, v in node.items())
170
-            elif isinstance(node, ast.Name):
171
-                if node.name in _safe_names:
172
-                    return _safe_names[node.name]
173
-            elif isinstance(node, ast.UnarySub):
174
-                return -_convert(node.expr)
175
-            raise ValueError('malformed string')
176
-        return _convert(node_or_string)
177
-
178
-_literal_eval = literal_eval
179
-
136
+from ansible.module_utils.pycompat24 import get_exception, literal_eval
180 137
 from ansible.module_utils.six import (PY2, PY3, b, binary_type, integer_types,
181 138
         iteritems, text_type, string_types)
182 139
 from ansible.module_utils.six.moves import map, reduce
183
-from ansible.module_utils.pycompat24 import get_exception
184 140
 from ansible.module_utils._text import to_native
185 141
 
186 142
 _NUMBERTYPES = tuple(list(integer_types) + [float])
... ...
@@ -213,6 +169,8 @@ except NameError:
213 213
     # Python 3
214 214
     basestring = string_types
215 215
 
216
+_literal_eval = literal_eval
217
+
216 218
 # End of deprecated names
217 219
 
218 220
 # Internal global holding passed in params.  This is consulted in case
... ...
@@ -49,6 +49,7 @@ try:
49 49
 except:
50 50
     HAS_LOOSE_VERSION = False
51 51
 
52
+from ansible.module_utils.six import string_types
52 53
 
53 54
 class AnsibleAWSError(Exception):
54 55
     pass
... ...
@@ -343,7 +344,7 @@ def ansible_dict_to_boto3_filter_list(filters_dict):
343 343
     filters_list = []
344 344
     for k,v in filters_dict.iteritems():
345 345
         filter_dict = {'Name': k}
346
-        if isinstance(v, basestring):
346
+        if isinstance(v, string_types):
347 347
             filter_dict['Values'] = [v]
348 348
         else:
349 349
             filter_dict['Values'] = v
... ...
@@ -438,7 +439,7 @@ def get_ec2_security_group_ids_from_names(sec_group_list, ec2_connection, vpc_id
438 438
 
439 439
     sec_group_id_list = []
440 440
 
441
-    if isinstance(sec_group_list, basestring):
441
+    if isinstance(sec_group_list, string_types):
442 442
         sec_group_list = [sec_group_list]
443 443
 
444 444
     # Get all security groups
... ...
@@ -22,6 +22,7 @@ from distutils.version import LooseVersion
22 22
 from ansible.module_utils.basic import AnsibleModule, env_fallback, get_exception
23 23
 from ansible.module_utils.shell import Shell, ShellError, HAS_PARAMIKO
24 24
 from ansible.module_utils.netcfg import parse
25
+from ansible.module_utils.six import string_types
25 26
 
26 27
 try:
27 28
     from jnpr.junos import Device
... ...
@@ -70,7 +71,7 @@ def to_list(val):
70 70
 
71 71
 
72 72
 def xml_to_json(val):
73
-    if isinstance(val, basestring):
73
+    if isinstance(val, string_types):
74 74
         return jxmlease.parse(val)
75 75
     else:
76 76
         return jxmlease.parse_etree(val)
... ...
@@ -33,6 +33,7 @@ import shlex
33 33
 import itertools
34 34
 
35 35
 from ansible.module_utils.basic import BOOLEANS_TRUE, BOOLEANS_FALSE
36
+from ansible.module_utils.six import string_types
36 37
 
37 38
 DEFAULT_COMMENT_TOKENS = ['#', '!', '/*', '*/']
38 39
 
... ...
@@ -197,7 +198,7 @@ class NetworkConfig(object):
197 197
         self.load(open(filename).read())
198 198
 
199 199
     def get(self, path):
200
-        if isinstance(path, basestring):
200
+        if isinstance(path, string_types):
201 201
             path = [path]
202 202
         for item in self._config:
203 203
             if item.text == path[-1]:
... ...
@@ -32,6 +32,7 @@ import itertools
32 32
 import shlex
33 33
 
34 34
 from ansible.module_utils.basic import BOOLEANS_TRUE, BOOLEANS_FALSE
35
+from ansible.module_utils.six import string_types
35 36
 
36 37
 def to_list(val):
37 38
     if isinstance(val, (list, tuple)):
... ...
@@ -75,7 +76,7 @@ class Cli(object):
75 75
         elif isinstance(command, dict):
76 76
             output = cmd.get('output') or output
77 77
             cmd = cmd['command']
78
-        if isinstance(prompt, basestring):
78
+        if isinstance(prompt, string_types):
79 79
             prompt = re.compile(re.escape(prompt))
80 80
         return Command(command, output, prompt=prompt, response=response)
81 81
 
... ...
@@ -42,3 +42,47 @@ def get_exception():
42 42
 
43 43
     """
44 44
     return sys.exc_info()[1]
45
+
46
+try:
47
+    # Python 2.6+
48
+    from ast import literal_eval
49
+except ImportError:
50
+    # a replacement for literal_eval that works with python 2.4. from:
51
+    # https://mail.python.org/pipermail/python-list/2009-September/551880.html
52
+    # which is essentially a cut/paste from an earlier (2.6) version of python's
53
+    # ast.py
54
+    from compiler import ast, parse
55
+    from ansible.module_utils.six import binary_type, string_types, text_type
56
+
57
+    def literal_eval(node_or_string):
58
+        """
59
+        Safely evaluate an expression node or a string containing a Python
60
+        expression.  The string or node provided may only consist of the  following
61
+        Python literal structures: strings, numbers, tuples, lists, dicts,  booleans,
62
+        and None.
63
+        """
64
+        _safe_names = {'None': None, 'True': True, 'False': False}
65
+        if isinstance(node_or_string, string_types):
66
+            node_or_string = parse(node_or_string, mode='eval')
67
+        if isinstance(node_or_string, ast.Expression):
68
+            node_or_string = node_or_string.node
69
+
70
+        def _convert(node):
71
+            # Okay to use long here because this is only for python 2.4 and 2.5
72
+            if isinstance(node, ast.Const) and isinstance(node.value, (text_type, binary_type, int, float, long, complex)):
73
+                return node.value
74
+            elif isinstance(node, ast.Tuple):
75
+                return tuple(map(_convert, node.nodes))
76
+            elif isinstance(node, ast.List):
77
+                return list(map(_convert, node.nodes))
78
+            elif isinstance(node, ast.Dict):
79
+                return dict((_convert(k), _convert(v)) for k, v in node.items())
80
+            elif isinstance(node, ast.Name):
81
+                if node.name in _safe_names:
82
+                    return _safe_names[node.name]
83
+            elif isinstance(node, ast.UnarySub):
84
+                return -_convert(node.expr)
85
+            raise ValueError('malformed string')
86
+        return _convert(node_or_string)
87
+
88
+__all__ = ('get_exception', 'literal_eval')
... ...
@@ -33,6 +33,7 @@ import re
33 33
 from uuid import UUID
34 34
 
35 35
 from ansible.module_utils.basic import BOOLEANS
36
+from ansible.module_utils.six import text_type, binary_type
36 37
 
37 38
 FINAL_STATUSES = ('ACTIVE', 'ERROR')
38 39
 VOLUME_STATUS = ('available', 'attaching', 'creating', 'deleting', 'in-use',
... ...
@@ -44,7 +45,7 @@ CLB_PROTOCOLS = ['DNS_TCP', 'DNS_UDP', 'FTP', 'HTTP', 'HTTPS', 'IMAPS',
44 44
                  'IMAPv4', 'LDAP', 'LDAPS', 'MYSQL', 'POP3', 'POP3S', 'SMTP',
45 45
                  'TCP', 'TCP_CLIENT_FIRST', 'UDP', 'UDP_STREAM', 'SFTP']
46 46
 
47
-NON_CALLABLES = (basestring, bool, dict, int, list, type(None))
47
+NON_CALLABLES = (text_type, binary_type, bool, dict, int, list, type(None))
48 48
 PUBLIC_NET_ID = "00000000-0000-0000-0000-000000000000"
49 49
 SERVICE_NET_ID = "11111111-1111-1111-1111-111111111111"
50 50
 
... ...
@@ -34,6 +34,8 @@ import select
34 34
 import subprocess
35 35
 import json
36 36
 
37
+from ansible.module_utils.six import text_type, binary_type
38
+
37 39
 class Service(object):
38 40
     """
39 41
     This is the generic Service manipulation class that is subclassed based on system.
... ...
@@ -112,7 +114,7 @@ class Service(object):
112 112
                 os._exit(0)
113 113
 
114 114
             # Start the command
115
-            if isinstance(cmd, basestring):
115
+            if isinstance(cmd, (text_type, binary_type)):
116 116
                 cmd = shlex.split(cmd)
117 117
             p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=lambda: os.close(pipe[1]))
118 118
             stdout = ""
... ...
@@ -37,7 +37,7 @@ class Taggable:
37 37
     def _load_tags(self, attr, ds):
38 38
         if isinstance(ds, list):
39 39
             return ds
40
-        elif isinstance(ds, basestring):
40
+        elif isinstance(ds, string_types):
41 41
             value = ds.split(',')
42 42
             if isinstance(value, list):
43 43
                 return [ x.strip() for x in value ]
... ...
@@ -21,6 +21,7 @@ __metaclass__ = type
21 21
 
22 22
 import json
23 23
 
24
+from ansible.compat.six import string_types
24 25
 from ansible.plugins.action import ActionBase
25 26
 from ansible.plugins.action.net_template import ActionModule as NetActionModule
26 27
 
... ...
@@ -32,7 +33,7 @@ class ActionModule(NetActionModule, ActionBase):
32 32
 
33 33
         result = dict(changed=False)
34 34
 
35
-        if isinstance(self._task.args['src'], basestring):
35
+        if isinstance(self._task.args['src'], string_types):
36 36
             self._handle_template()
37 37
 
38 38
         result.update(self._execute_module(module_name=self._task.action,
... ...
@@ -18,13 +18,12 @@
18 18
 from __future__ import (absolute_import, division, print_function)
19 19
 __metaclass__ = type
20 20
 
21
-from ansible.compat.six import iteritems
21
+from ansible.compat.six import iteritems, string_types
22 22
 
23 23
 from ansible.plugins.action import ActionBase
24 24
 from ansible.utils.boolean import boolean
25 25
 from ansible.utils.vars import isidentifier
26 26
 
27
-
28 27
 class ActionModule(ActionBase):
29 28
 
30 29
     TRANSFERS_FILES = False
... ...
@@ -45,7 +44,7 @@ class ActionModule(ActionBase):
45 45
                     result['msg'] = "The variable name '%s' is not valid. Variables must start with a letter or underscore character, and contain only letters, numbers and underscores." % k
46 46
                     return result
47 47
 
48
-                if isinstance(v, basestring) and v.lower() in ('true', 'false', 'yes', 'no'):
48
+                if isinstance(v, string_types) and v.lower() in ('true', 'false', 'yes', 'no'):
49 49
                     v = boolean(v)
50 50
                 facts[k] = v
51 51
 
... ...
@@ -24,6 +24,7 @@ import os
24 24
 import smtplib
25 25
 import json
26 26
 
27
+from ansible.compat.six import string_types
27 28
 from ansible.utils.unicode import to_bytes
28 29
 from ansible.plugins.callback import CallbackBase
29 30
 
... ...
@@ -108,7 +109,7 @@ class CallbackModule(CallbackBase):
108 108
         res = result._result
109 109
 
110 110
         sender = '"Ansible: %s" <root>' % host
111
-        if isinstance(res, basestring):
111
+        if isinstance(res, string_types):
112 112
             subject = 'Unreachable: %s' % res.strip('\r\n').split('\n')[-1]
113 113
             body = 'An error occurred for host ' + host + ' with the following message:\n\n' + res
114 114
         else:
... ...
@@ -123,7 +124,7 @@ class CallbackModule(CallbackBase):
123 123
         res = result._result
124 124
 
125 125
         sender = '"Ansible: %s" <root>' % host
126
-        if isinstance(res, basestring):
126
+        if isinstance(res, string_types):
127 127
             subject = 'Async failure: %s' % res.strip('\r\n').split('\n')[-1]
128 128
             body = 'An error occurred for host ' + host + ' with the following message:\n\n' + res
129 129
         else:
... ...
@@ -30,6 +30,7 @@ from functools import wraps
30 30
 from ansible.compat.six import with_metaclass
31 31
 
32 32
 from ansible import constants as C
33
+from ansible.compat.six import string_types
33 34
 from ansible.errors import AnsibleError
34 35
 from ansible.plugins import shell_loader
35 36
 from ansible.utils.unicode import to_bytes, to_unicode
... ...
@@ -248,7 +249,7 @@ class ConnectionBase(with_metaclass(ABCMeta, object)):
248 248
     def check_password_prompt(self, output):
249 249
         if self._play_context.prompt is None:
250 250
             return False
251
-        elif isinstance(self._play_context.prompt, basestring):
251
+        elif isinstance(self._play_context.prompt, string_types):
252 252
             return output.startswith(self._play_context.prompt)
253 253
         else:
254 254
             return self._play_context.prompt(output)
... ...
@@ -26,7 +26,7 @@ import shlex
26 26
 import traceback
27 27
 import json
28 28
 
29
-
29
+from ansible.compat.six import string_types
30 30
 from ansible.compat.six.moves.urllib.parse import urlunsplit
31 31
 from ansible.errors import AnsibleError, AnsibleConnectionFailure
32 32
 
... ...
@@ -106,7 +106,7 @@ class Connection(ConnectionBase):
106 106
         else:
107 107
             self._winrm_transport = transport_selector
108 108
         self._winrm_transport = hostvars.get('ansible_winrm_transport', self._winrm_transport)
109
-        if isinstance(self._winrm_transport, basestring):
109
+        if isinstance(self._winrm_transport, string_types):
110 110
             self._winrm_transport = [x.strip() for x in self._winrm_transport.split(',') if x.strip()]
111 111
 
112 112
         unsupported_transports = set(self._winrm_transport).difference(self._winrm_supported_authtypes)
... ...
@@ -126,8 +126,7 @@ def fileglob(pathname):
126 126
 def regex_replace(value='', pattern='', replacement='', ignorecase=False):
127 127
     ''' Perform a `re.sub` returning a string '''
128 128
 
129
-    if not isinstance(value, basestring):
130
-        value = str(value)
129
+    value = to_unicode(value, errors='strict', nonstring='simplerepr')
131 130
 
132 131
     if ignorecase:
133 132
         flags = re.I
... ...
@@ -122,6 +122,7 @@ import os
122 122
 
123 123
 from jinja2.exceptions import UndefinedError
124 124
 
125
+from ansible.compat.six import string_types
125 126
 from ansible.errors import AnsibleFileNotFound, AnsibleLookupError, AnsibleUndefinedVariable
126 127
 from ansible.plugins.lookup import LookupBase
127 128
 from ansible.utils.boolean import boolean
... ...
@@ -146,14 +147,14 @@ class LookupModule(LookupBase):
146 146
                     skip  = boolean(term.get('skip', False))
147 147
 
148 148
                     filelist = files
149
-                    if isinstance(files, basestring):
149
+                    if isinstance(files, string_types):
150 150
                         files = files.replace(',', ' ')
151 151
                         files = files.replace(';', ' ')
152 152
                         filelist = files.split(' ')
153 153
 
154 154
                     pathlist = paths
155 155
                     if paths:
156
-                        if isinstance(paths, basestring):
156
+                        if isinstance(paths, string_types):
157 157
                             paths = paths.replace(',', ' ')
158 158
                             paths = paths.replace(':', ' ')
159 159
                             paths = paths.replace(';', ' ')
... ...
@@ -17,6 +17,7 @@
17 17
 from __future__ import (absolute_import, division, print_function)
18 18
 __metaclass__ = type
19 19
 
20
+from ansible.compat.six import string_types
20 21
 from ansible.errors import AnsibleError
21 22
 from ansible.plugins.lookup import LookupBase
22 23
 from ansible.utils.listify import listify_lookup_plugin_terms
... ...
@@ -44,7 +45,7 @@ class LookupModule(LookupBase):
44 44
                 # ignore undefined items
45 45
                 break
46 46
 
47
-            if isinstance(term, basestring):
47
+            if isinstance(term, string_types):
48 48
                 # convert a variable to a list
49 49
                 term2 = listify_lookup_plugin_terms(term, templar=self._templar, loader=self._loader)
50 50
                 # but avoid converting a plain string to a list of one string
... ...
@@ -17,6 +17,7 @@
17 17
 from __future__ import (absolute_import, division, print_function)
18 18
 __metaclass__ = type
19 19
 
20
+from ansible.compat.six import string_types
20 21
 from ansible.errors import AnsibleError
21 22
 from ansible.plugins.lookup import LookupBase
22 23
 from ansible.utils.listify import listify_lookup_plugin_terms
... ...
@@ -41,7 +42,7 @@ class LookupModule(LookupBase):
41 41
             _raise_terms_error()
42 42
 
43 43
         # first term should be a list (or dict), second a string holding the subkey
44
-        if not isinstance(terms[0], (list, dict)) or not isinstance(terms[1], basestring):
44
+        if not isinstance(terms[0], (list, dict)) or not isinstance(terms[1], string_types):
45 45
             _raise_terms_error("first a dict or a list, second a string pointing to the subkey")
46 46
         subelements = terms[1].split(".")
47 47
 
... ...
@@ -59,7 +60,7 @@ class LookupModule(LookupBase):
59 59
         flags = {}
60 60
         if len(terms) == 3:
61 61
             flags = terms[2]
62
-        if not isinstance(flags, dict) and not all([isinstance(key, basestring) and key in FLAGS for key in flags]):
62
+        if not isinstance(flags, dict) and not all([isinstance(key, string_types) and key in FLAGS for key in flags]):
63 63
             _raise_terms_error("the optional third item must be a dict with flags %s" % FLAGS)
64 64
 
65 65
         # build_items
... ...
@@ -20,8 +20,6 @@ from __future__ import (absolute_import, division, print_function)
20 20
 __metaclass__ = type
21 21
 
22 22
 import os
23
-from ansible.errors import AnsibleError
24
-from ansible.utils.unicode import to_bytes
25 23
 
26 24
 # Note, sha1 is the only hash algorithm compatible with python2.4 and with
27 25
 # FIPS-140 mode (as of 11-2014)
... ...
@@ -40,12 +38,16 @@ except ImportError:
40 40
         # Assume we're running in FIPS mode here
41 41
         _md5 = None
42 42
 
43
+from ansible.compat.six import string_types
44
+from ansible.errors import AnsibleError
45
+from ansible.utils.unicode import to_bytes
46
+
43 47
 def secure_hash_s(data, hash_func=sha1):
44 48
     ''' Return a secure hash hex digest of data. '''
45 49
 
46 50
     digest = hash_func()
47 51
     try:
48
-        if not isinstance(data, basestring):
52
+        if not isinstance(data, string_types):
49 53
             data = "%s" % data
50 54
         digest.update(data)
51 55
     except UnicodeEncodeError:
... ...
@@ -24,10 +24,12 @@ __metaclass__ = type
24 24
 import os
25 25
 import sys
26 26
 import ast
27
-from ansible.parsing.yaml.loader import AnsibleLoader
28 27
 import traceback
29 28
 
30 29
 from collections import MutableMapping, MutableSet, MutableSequence
30
+
31
+from ansible.compat.six import string_types
32
+from ansible.parsing.yaml.loader import AnsibleLoader
31 33
 from ansible.plugins import fragment_loader
32 34
 
33 35
 try:
... ...
@@ -76,7 +78,7 @@ def get_docstring(filename, verbose=False):
76 76
                         doc = AnsibleLoader(child.value.s, file_name=filename).get_single_data()
77 77
                         fragments = doc.get('extends_documentation_fragment', [])
78 78
 
79
-                        if isinstance(fragments, basestring):
79
+                        if isinstance(fragments, string_types):
80 80
                             fragments = [ fragments ]
81 81
 
82 82
                         # Allow the module to specify a var other than DOCUMENTATION
... ...
@@ -37,9 +37,6 @@ _LATIN1_ALIASES = frozenset(('latin-1', 'LATIN-1', 'latin1', 'LATIN1',
37 37
 
38 38
 # EXCEPTION_CONVERTERS is defined below due to using to_unicode
39 39
 
40
-if PY3:
41
-    basestring = (str, bytes)
42
-
43 40
 def to_unicode(obj, encoding='utf-8', errors='replace', nonstring=None):
44 41
     '''Convert an object into a :class:`unicode` string
45 42
 
... ...
@@ -93,9 +90,9 @@ def to_unicode(obj, encoding='utf-8', errors='replace', nonstring=None):
93 93
     '''
94 94
     # Could use isbasestring/isunicode here but we want this code to be as
95 95
     # fast as possible
96
-    if isinstance(obj, basestring):
97
-        if isinstance(obj, text_type):
98
-            return obj
96
+    if isinstance(obj, text_type):
97
+        return obj
98
+    if isinstance(obj, binary_type):
99 99
         if encoding in _UTF8_ALIASES:
100 100
             return text_type(obj, 'utf-8', errors)
101 101
         if encoding in _LATIN1_ALIASES:
... ...
@@ -202,9 +199,9 @@ def to_bytes(obj, encoding='utf-8', errors='replace', nonstring=None):
202 202
     '''
203 203
     # Could use isbasestring, isbytestring here but we want this to be as fast
204 204
     # as possible
205
-    if isinstance(obj, basestring):
206
-        if isinstance(obj, binary_type):
207
-            return obj
205
+    if isinstance(obj, binary_type):
206
+        return obj
207
+    if isinstance(obj, text_type):
208 208
         return obj.encode(encoding, errors)
209 209
     if not nonstring:
210 210
         nonstring = 'simplerepr'
211 211
new file mode 100755
... ...
@@ -0,0 +1,16 @@
0
+#!/bin/sh
1
+
2
+BASEDIR=${1-"."}
3
+
4
+# Not entirely correct but
5
+# * basestring is still present and harmless in comments
6
+# * basestring is also currently present in modules.  Porting of modules is more
7
+#   of an Ansible 2.3 or greater goal.
8
+BASESTRING_USERS=$(grep -r basestring $BASEDIR |grep isinstance| grep -v lib/ansible/compat/six/_six.py|grep -v lib/ansible/module_utils/six.py|grep -v lib/ansible/modules/core|grep -v lib/ansible/modules/extras)
9
+
10
+if test -n "$BASESTRING_USERS" ; then
11
+  printf "$BASESTRING_USERS"
12
+  exit 1
13
+else
14
+  exit 0
15
+fi
... ...
@@ -3,16 +3,18 @@ import mock
3 3
 import os
4 4
 import re
5 5
 
6
+
6 7
 from nose.tools import eq_
7 8
 try:
8 9
     from nose.tools import assert_raises_regexp
9 10
 except ImportError:
11
+    from ansible.compat.six import string_types
10 12
     # Python < 2.7
11 13
     def assert_raises_regexp(expected, regexp, callable, *a, **kw):
12 14
         try:
13 15
             callable(*a, **kw)
14 16
         except expected as e:
15
-            if isinstance(regexp, basestring):
17
+            if isinstance(regexp, string_types):
16 18
                 regexp = re.compile(regexp)
17 19
             if not regexp.search(str(e)):
18 20
                 raise Exception('"%s" does not match "%s"' %