Posted at

cloudmonkey CLI をpython3化してみる −2

More than 3 years have passed since last update.

昨日はインストールまではできるようになったけど、起動できなかったので

$ cloudmonkey

Traceback (most recent call last):

File "/Users/kentaro/porting/ven/bin/cloudmonkey", line 9, in <module>
load_entry_point('cloudmonkey', 'console_scripts', 'cloudmonkey')()
File "/Users/kentaro/porting/ven/lib/python3.5/site-packages/pkg_resources/__init__.py", line 542, in load_entry_point
return get_distribution(dist).load_entry_point(group, name)
File "/Users/kentaro/porting/ven/lib/python3.5/site-packages/pkg_resources/__init__.py", line 2569, in load_entry_point
return ep.load()
File "/Users/kentaro/porting/ven/lib/python3.5/site-packages/pkg_resources/__init__.py", line 2229, in load
return self.resolve()
File "/Users/kentaro/porting/ven/lib/python3.5/site-packages/pkg_resources/__init__.py", line 2235, in resolve
module = __import__(self.module_name, fromlist=['__name__'], level=0)
File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/cloudmonkey.py", line 48
except ImportError, e:
^
SyntaxError: invalid syntax

エラーの出ているcloudmonkey.py を変換

$ futurize --stage1 -w cloudmonkey/cloudmonkey.py

RefactoringTool: Skipping optional fixer: idioms

RefactoringTool: Skipping optional fixer: ws_comma
RefactoringTool: Refactored cloudmonkey/cloudmonkey.py
--- cloudmonkey/cloudmonkey.py (original)
+++ cloudmonkey/cloudmonkey.py (refactored)
@@ -17,6 +17,9 @@
# specific language governing permissions and limitations
# under the License.

+from __future__ import print_function
+from __future__ import absolute_import
+from functools import reduce
try:
import argcomplete
import argparse
@@ -32,26 +35,26 @@
import time
import types

- from cachemaker import loadcache, savecache, monkeycache, splitverbsubject
- from config import __version__, __description__, __projecturl__
- from config import display_types
- from config import read_config, write_config, config_file, default_profile
+ from .cachemaker import loadcache, savecache, monkeycache, splitverbsubject
+ from .config import __version__, __description__, __projecturl__
+ from .config import display_types
+ from .config import read_config, write_config, config_file, default_profile
from dicttoxml import dicttoxml
from optparse import OptionParser
from prettytable import PrettyTable
- from printer import monkeyprint
- from requester import monkeyrequest
- from requester import login
- from requester import logout
+ from .printer import monkeyprint
+ from .requester import monkeyrequest
+ from .requester import login
+ from .requester import logout
from urlparse import urlparse
from xml.dom.minidom import parseString
-except ImportError, e:
+except ImportError as e:
print("Import error in %s : %s" % (__name__, e))
import sys
sys.exit()

try:
- from precache import apicache
+ from .precache import apicache
except ImportError:
apicache = {'count': 0, 'verbs': [], 'asyncapis': []}

@@ -63,8 +66,8 @@
os.environ['TERM'] = 'vt100'
try:
import readline
-except ImportError, e:
- print("Module readline not found, autocompletions will fail", e)
+except ImportError as e:
+ print(("Module readline not found, autocompletions will fail", e))
else:
import rlcompleter
readline_doc = getattr(readline, '__doc__', '')
@@ -114,7 +117,7 @@
try:
if os.path.exists(self.history_file):
readline.read_history_file(self.history_file)
- except IOError, e:
+ except IOError as e:
logger.debug(u"Error: Unable to read history. " + unicode(e))
atexit.register(readline.write_history_file, self.history_file)

@@ -148,7 +151,7 @@
def cmdloop(self, intro=None):
self.interpreterMode = True
print(self.intro)
- print "Using management server profile:", self.profile, "\n"
+ print("Using management server profile:", self.profile, "\n")
while True:
try:
super(CloudMonkeyShell, self).cmdloop(intro="")
@@ -197,7 +200,7 @@
args_partition = args.partition(" ")
cmd = self.apicache[verb][args_partition[0]]['name']
args = args_partition[2]
- except KeyError, e:
+ except KeyError as e:
if default_handler:
default_handler(args)
else:
@@ -216,12 +219,12 @@
output = u""
try:
for arg in args:
- if isinstance(type(arg), types.NoneType) or not arg:
+ if isinstance(type(arg), type(None)) or not arg:
continue
if not (isinstance(arg, str) or isinstance(arg, unicode)):
arg = unicode(arg)
output += arg
- except Exception, e:
+ except Exception as e:
print(str(e))

output = output.encode("utf-8")
@@ -232,7 +235,7 @@
sys.stderr.write(output + "\n")
sys.stderr.flush()
else:
- print output
+ print(output)

def print_result(self, result, result_filter=[]):
if not result or len(result) == 0:
@@ -297,7 +300,7 @@
if isinstance(result[0], dict):
keys = result[0].keys()
writer = csv.DictWriter(sys.stdout, keys)
- print ','.join(keys)
+ print(','.join(keys))
for item in result:
row = {}
for k in keys:
@@ -312,7 +315,7 @@
elif isinstance(result, dict):
keys = result.keys()
writer = csv.DictWriter(sys.stdout, keys)
- print ','.join(keys)
+ print(','.join(keys))
writer.writerow(result)

def print_result_tabular(result):
@@ -428,7 +431,7 @@
try:
args = args.strip()
args.decode("utf-8")
- except UnicodeError, ignore:
+ except UnicodeError as ignore:
args = args.encode("utf-8")

if self.pipe_runner(args):
@@ -444,12 +447,12 @@
args = []
while True:
try:
- next_val = lexp.next()
+ next_val = next(lexp)
if not next_val:
break
next_val = next_val.decode("utf-8")
args.append(next_val.replace(u'\x00', u''))
- except ValueError, err:
+ except ValueError as err:
self.monkeyprint("Command parsing error: ", err)
return

@@ -600,14 +603,14 @@
return
uuids = self.update_param_cache(api, response)
if len(uuids) > 1:
- print
+ print()
options = sorted(self.param_cache[api]["options"],
key=lambda x: x[1])
for option in options:
uuid = option[0]
name = option[1]
if uuid.startswith(value):
- print uuid, name
+ print(uuid, name)
autocompletions = map(lambda x: x + " ", uuids)
search_string = value

@@ -662,7 +665,7 @@
allowed_blank_keys = ["username", "password", "apikey", "secretkey",
"domain"]
if key not in allowed_blank_keys and not value:
- print "Blank value of %s is not allowed" % key
+ print("Blank value of %s is not allowed" % key)
return

self.prompt = self.get_prompt()
@@ -671,19 +674,19 @@
key = 'url'
self.url = "%s://%s:%s%s" % (self.protocol, self.host,
self.port, self.path)
- print "This option has been deprecated, please set 'url' instead"
- print "This server url will be used:", self.url
+ print("This option has been deprecated, please set 'url' instead")
+ print("This server url will be used:", self.url)
write_config(self.get_attr, self.config_file)
read_config(self.get_attr, self.set_attr, self.config_file)
self.init_credential_store()
if key.strip() == 'profile' and self.interpreterMode:
- print "\nLoaded server profile '%s' with options:" % value
+ print("\nLoaded server profile '%s' with options:" % value)
for option in default_profile.keys():
value = self.get_attr(option)
if option in ["password", "apikey", "secretkey"] and value:
value = value[:2] + "XXX" + value[4:6] + "YYY...(hidden)"
- print " %s = %s" % (option, value)
- print
+ print(" %s = %s" % (option, value))
+ print()

def complete_set(self, text, line, begidx, endidx):
mline = line.partition(" ")[2].lstrip().partition(" ")
@@ -714,7 +717,7 @@
session, sessionkey = login(self.url, self.username, self.password)
self.credentials['session'] = session
self.credentials['sessionkey'] = sessionkey
- except Exception, e:
+ except Exception as e:
self.monkeyprint("Error: Login failed to the server: ", unicode(e))

def do_logout(self, args):
@@ -723,7 +726,7 @@
"""
try:
logout(self.url, self.credentials.get('session'))
- except Exception, e:
+ except Exception as e:
pass
self.credentials['session'] = None
self.credentials['sessionkey'] = None
@@ -775,7 +778,7 @@
startIdx = 1
elif historyArg == "clear" or historyArg == "c":
readline.clear_history()
- print "CloudMonkey history cleared"
+ print("CloudMonkey history cleared")
return
elif len(historyArg) > 1 and historyArg[0] == "!" and historyArg[1:].isdigit():
command = readline.get_history_item(long(historyArg[1:]))
RefactoringTool: Files that were modified:
RefactoringTool: cloudmonkey/cloudmonkey.py

すごい量だなぁ

$ futurize --stage2 -w cloudmonkey/cloudmonkey.py

RefactoringTool: Refactored cloudmonkey/cloudmonkey.py

--- cloudmonkey/cloudmonkey.py (original)
+++ cloudmonkey/cloudmonkey.py (refactored)
@@ -19,6 +19,13 @@

from __future__ import print_function
from __future__ import absolute_import
+from future import standard_library
+standard_library.install_aliases()
+from builtins import map
+from builtins import next
+from builtins import filter
+from builtins import str
+from builtins import range
from functools import reduce
try:
import argcomplete
@@ -46,7 +53,7 @@
from .requester import monkeyrequest
from .requester import login
from .requester import logout
- from urlparse import urlparse
+ from urllib.parse import urlparse
from xml.dom.minidom import parseString
except ImportError as e:
print("Import error in %s : %s" % (__name__, e))
@@ -109,16 +116,15 @@
self.init_credential_store()
logging.basicConfig(filename=self.log_file,
level=logging.DEBUG, format=log_fmt)
- logger.debug("Loaded config fields:\n%s" % map(lambda x: "%s=%s" %
- (x, getattr(self, x)),
- self.config_options))
+ logger.debug("Loaded config fields:\n%s" % ["%s=%s" %
+ (x, getattr(self, x)) for x in self.config_options])
cmd.Cmd.__init__(self)

try:
if os.path.exists(self.history_file):
readline.read_history_file(self.history_file)
except IOError as e:
- logger.debug(u"Error: Unable to read history. " + unicode(e))
+ logger.debug(u"Error: Unable to read history. " + str(e))
atexit.register(readline.write_history_file, self.history_file)

def init_credential_store(self):
@@ -221,8 +227,8 @@
for arg in args:
if isinstance(type(arg), type(None)) or not arg:
continue
- if not (isinstance(arg, str) or isinstance(arg, unicode)):
- arg = unicode(arg)
+ if not (isinstance(arg, str) or isinstance(arg, str)):
+ arg = str(arg)
output += arg
except Exception as e:
print(str(e))
@@ -249,7 +255,7 @@
if result_filter:
for res in result_filter:
tfilter[res] = 1
- for okey, oval in result.iteritems():
+ for okey, oval in result.items():
if isinstance(oval, dict):
for tkey in oval:
if tkey not in tfilter:
@@ -289,8 +295,8 @@
if "count" in result:
result.pop("count")

- if len(result.keys()) == 1:
- item = result[result.keys()[0]]
+ if len(list(result.keys())) == 1:
+ item = result[list(result.keys())[0]]
if isinstance(item, list):
result = item
elif isinstance(item, dict):
@@ -298,7 +304,7 @@

if isinstance(result, list) and len(result) > 0:
if isinstance(result[0], dict):
- keys = result[0].keys()
+ keys = list(result[0].keys())
writer = csv.DictWriter(sys.stdout, keys)
print(','.join(keys))
for item in result:
@@ -307,13 +313,13 @@
if k not in item:
row[k] = None
else:
- if type(item[k]) is unicode:
+ if type(item[k]) is str:
row[k] = item[k].encode('utf8')
else:
row[k] = item[k]
writer.writerow(row)
elif isinstance(result, dict):
- keys = result.keys()
+ keys = list(result.keys())
writer = csv.DictWriter(sys.stdout, keys)
print(','.join(keys))
writer.writerow(result)
@@ -327,8 +333,7 @@
toprow = []
if not result:
return
- toprow = set(reduce(lambda x, y: x + y, map(lambda x: x.keys(),
- filter(lambda x: isinstance(x, dict), result))))
+ toprow = set(reduce(lambda x, y: x + y, [list(x.keys()) for x in [x for x in result if isinstance(x, dict)]]))
printer = print_table(printer, toprow)
for node in result:
if not node:
@@ -336,13 +341,13 @@
for key in toprow:
if key not in node:
node[key] = ''
- row = map(lambda x: node[x], toprow)
+ row = [node[x] for x in toprow]
if printer and row:
printer.add_row(row)
print_table(printer, toprow)

def print_result_as_dict(result):
- for key in sorted(result.keys(), key=lambda x:
+ for key in sorted(list(result.keys()), key=lambda x:
x not in ['id', 'count', 'name'] and x):
if isinstance(result[key], list):
self.monkeyprint(key + ":")
@@ -351,7 +356,7 @@
self.monkeyprint(key + ":")
print_result_as_dict(result[key])
else:
- value = unicode(result[key])
+ value = str(result[key])
self.monkeyprint(key, " = ", value)

def print_result_as_list(result):
@@ -404,20 +409,20 @@
if not api:
return
logger.debug("Updating param cache for %s API" % api)
- responsekey = filter(lambda x: 'response' in x, result.keys())[0]
+ responsekey = filter(lambda x: 'response' in x, list(result.keys()))[0]
result = result[responsekey]
options = []
uuids = []
- for key in result.keys():
+ for key in list(result.keys()):
if isinstance(result[key], list):
for element in result[key]:
- if 'id' in element.keys():
- uuid = unicode(element['id'])
+ if 'id' in list(element.keys()):
+ uuid = str(element['id'])
name = ""
keyspace = ["name", "displayname",
"username", "description"]
for name_key in keyspace:
- if name_key in element.keys():
+ if name_key in list(element.keys()):
name = element[name_key]
break
options.append((uuid, name,))
@@ -462,15 +467,13 @@

field_filter = []
if 'filter' in args_dict:
- field_filter = filter(lambda x: x.strip() != '',
- args_dict.pop('filter').split(','))
+ field_filter = [x for x in args_dict.pop('filter').split(',') if x.strip() != '']
field_filter = list(set(field_filter))

missing = []
if verb in self.apicache and subject in self.apicache[verb]:
- missing = filter(lambda x: x not in [key.split('[')[0].lower()
- for key in args_dict],
- self.apicache[verb][subject]['requiredparams'])
+ missing = [x for x in self.apicache[verb][subject]['requiredparams'] if x not in [key.split('[')[0].lower()
+ for key in args_dict]]

if len(missing) > 0:
self.monkeyprint("Missing arguments: ", ' '.join(missing))
@@ -484,13 +487,13 @@
result = self.make_request(apiname, args_dict, isasync)

if not result or not isinstance(result, dict):
- if isinstance(result, unicode):
+ if isinstance(result, str):
result = result.decode("utf-8")
logger.debug("Invalid command result: %s" % result)
return

try:
- responsekeys = filter(lambda x: 'response' in x, result.keys())
+ responsekeys = [x for x in list(result.keys()) if 'response' in x]
for responsekey in responsekeys:
self.print_result(result[responsekey], field_filter)
if apiname.startswith("list") and "id" not in args_dict:
@@ -513,13 +516,10 @@
search_string = ""

if separator != " ": # Complete verb subjects
- autocompletions = map(lambda x: x + " ",
- self.apicache[verb].keys())
+ autocompletions = [x + " " for x in list(self.apicache[verb].keys())]
search_string = subject
else: # Complete subject params
- autocompletions = map(lambda x: x + "=",
- map(lambda x: x['name'],
- self.apicache[verb][subject]['params']))
+ autocompletions = [x + "=" for x in [x['name'] for x in self.apicache[verb][subject]['params']]]
search_string = text
if self.paramcompletion == 'true':
param = line[:endidx].split(" ")[-1]
@@ -528,25 +528,19 @@
param = param[:idx]
if param == "filter":
response_params = self.apicache[verb][subject]["response"]
- used = filter(lambda x: x.strip() != "",
- value.split(",")[:-1])
- unused = map(lambda x: x['name'] + ",", filter(lambda x:
- "name" in x and x["name"] not in used,
- response_params))
+ used = [x for x in value.split(",")[:-1] if x.strip() != ""]
+ unused = [x['name'] + "," for x in [x for x in response_params if "name" in x and x["name"] not in used]]
last_value = value.split(",")[-1]
if last_value:
- unused = filter(lambda x: x.startswith(last_value),
- unused)
+ unused = [x for x in unused if x.startswith(last_value)]
suffix = ",".join(used)
if suffix:
suffix += ","
global normal_readline
if normal_readline:
- return filter(lambda x: x.startswith(last_value),
- map(lambda x: x, unused))
+ return [x for x in [x for x in unused] if x.startswith(last_value)]
else: # OSX fix
- return filter(lambda x: x.startswith(value),
- map(lambda x: suffix + x, unused))
+ return [x for x in [suffix + x for x in unused] if x.startswith(value)]
elif len(value) < 36 and idx != -1:
api = None
logger.debug("[Paramcompl] For %s %s %s=" % (verb, subject,
@@ -574,10 +568,9 @@
params = self.apicache[verb][subject]['params']
arg = filter(lambda x: x['name'] == param, params)[0]
if "type" in arg and arg["type"] == "boolean":
- return filter(lambda x: x.startswith(value),
- ["true ", "false "])
+ return [x for x in ["true ", "false "] if x.startswith(value)]
related = arg['related']
- apis = filter(lambda x: 'list' in x, related)
+ apis = [x for x in related if 'list' in x]
logger.debug("[Paramcompl] Related APIs: %s" % apis)
if len(apis) > 0:
api = apis[0]
@@ -589,7 +582,7 @@
uuids = []
cache_burst_ts = int(time.time()) - 900
logger.debug("Trying paramcompletion using API: %s" % api)
- if api in self.param_cache.keys() and \
+ if api in list(self.param_cache.keys()) and \
len(self.param_cache[api]["options"]) > 0 and \
self.param_cache[api]["ts"] > cache_burst_ts:
for option in self.param_cache[api]["options"]:
@@ -611,7 +604,7 @@
name = option[1]
if uuid.startswith(value):
print(uuid, name)
- autocompletions = map(lambda x: x + " ", uuids)
+ autocompletions = [x + " " for x in uuids]
search_string = value

if subject != "" and line.split(" ")[-1].find('=') == -1:
@@ -681,7 +674,7 @@
self.init_credential_store()
if key.strip() == 'profile' and self.interpreterMode:
print("\nLoaded server profile '%s' with options:" % value)
- for option in default_profile.keys():
+ for option in list(default_profile.keys()):
value = self.get_attr(option)
if option in ["password", "apikey", "secretkey"] and value:
value = value[:2] + "XXX" + value[4:6] + "YYY...(hidden)"
@@ -718,7 +711,7 @@
self.credentials['session'] = session
self.credentials['sessionkey'] = sessionkey
except Exception as e:
- self.monkeyprint("Error: Login failed to the server: ", unicode(e))
+ self.monkeyprint("Error: Login failed to the server: ", str(e))

def do_logout(self, args):
"""
@@ -773,7 +766,7 @@
numLen = len(str(endIdx))
historyArg = args.split(' ')[0]
if historyArg.isdigit():
- startIdx = endIdx - long(historyArg)
+ startIdx = endIdx - int(historyArg)
if startIdx < 1:
startIdx = 1
elif historyArg == "clear" or historyArg == "c":
@@ -781,11 +774,11 @@
print("CloudMonkey history cleared")
return
elif len(historyArg) > 1 and historyArg[0] == "!" and historyArg[1:].isdigit():
- command = readline.get_history_item(long(historyArg[1:]))
+ command = readline.get_history_item(int(historyArg[1:]))
readline.set_startup_hook(lambda: readline.insert_text(command))
self.hook_count = 1
return
- for idx in xrange(startIdx, endIdx):
+ for idx in range(startIdx, endIdx):
self.monkeyprint("%s %s" % (str(idx).rjust(numLen),
readline.get_history_item(idx)))

RefactoringTool: Files that were modified:
RefactoringTool: cloudmonkey/cloudmonkey.py

$ cloudmonkey

Traceback (most recent call last):

File "/Users/kentaro/porting/ven/bin/cloudmonkey", line 9, in <module>
load_entry_point('cloudmonkey', 'console_scripts', 'cloudmonkey')()
File "/Users/kentaro/porting/ven/lib/python3.5/site-packages/pkg_resources/__init__.py", line 542, in load_entry_point
return get_distribution(dist).load_entry_point(group, name)
File "/Users/kentaro/porting/ven/lib/python3.5/site-packages/pkg_resources/__init__.py", line 2569, in load_entry_point
return ep.load()
File "/Users/kentaro/porting/ven/lib/python3.5/site-packages/pkg_resources/__init__.py", line 2229, in load
return self.resolve()
File "/Users/kentaro/porting/ven/lib/python3.5/site-packages/pkg_resources/__init__.py", line 2235, in resolve
module = __import__(self.module_name, fromlist=['__name__'], level=0)
File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/cloudmonkey.py", line 45, in <module>
from .cachemaker import loadcache, savecache, monkeycache, splitverbsubject
File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/cachemaker.py", line 25
except ImportError, e:
^
SyntaxError: invalid syntax

今度はcachemaker.py

$ futurize --stage1 -w cloudmonkey/cachemaker.py

RefactoringTool: Skipping optional fixer: idioms

RefactoringTool: Skipping optional fixer: ws_comma
RefactoringTool: Refactored cloudmonkey/cachemaker.py
--- cloudmonkey/cachemaker.py (original)
+++ cloudmonkey/cachemaker.py (refactored)
@@ -16,15 +16,17 @@
# specific language governing permissions and limitations
# under the License.

+from __future__ import print_function
+from __future__ import absolute_import
try:
import json
import os
import types

- from config import config_fields
-except ImportError, e:
+ from .config import config_fields
+except ImportError as e:
import sys
- print "ImportError", e
+ print("ImportError", e)
sys.exit(1)

@@ -73,8 +75,8 @@
f.close()
try:
apicache = json.loads(data)
- except ValueError, e:
- print "Error processing json:", json_file, e
+ except ValueError as e:
+ print("Error processing json:", json_file, e)
return {}
return apicache

@@ -83,16 +85,16 @@
"""
Feed this a dictionary of api bananas, it spits out processed cache
"""
- if isinstance(type(apis), types.NoneType) or apis is None:
+ if isinstance(type(apis), type(None)) or apis is None:
return {}

responsekey = filter(lambda x: 'response' in x, apis.keys())

if len(responsekey) == 0:
- print "[monkeycache] Invalid dictionary, has no response"
+ print("[monkeycache] Invalid dictionary, has no response")
return None
if len(responsekey) != 1:
- print "[monkeycache] Multiple responsekeys, chosing first one"
+ print("[monkeycache] Multiple responsekeys, chosing first one")

responsekey = responsekey[0]
verbs = set()
@@ -102,7 +104,7 @@

apilist = getvalue(apis[responsekey], 'api')
if apilist is None:
- print "[monkeycache] Server response issue, no apis found"
+ print("[monkeycache] Server response issue, no apis found")

for api in apilist:
name = getvalue(api, 'name')
@@ -174,9 +176,9 @@

if __name__ == "__main__":
cache_file = config_fields['core']['cache_file']
- print "[cachemaker] Pre-caching using user's cloudmonkey cache", cache_file
+ print("[cachemaker] Pre-caching using user's cloudmonkey cache", cache_file)
if os.path.exists(cache_file):
main(cache_file)
else:
- print "[cachemaker] Unable to cache apis, file not found", cache_file
- print "[cachemaker] Run cloudmonkey sync to generate cache"
+ print("[cachemaker] Unable to cache apis, file not found", cache_file)
+ print("[cachemaker] Run cloudmonkey sync to generate cache")
RefactoringTool: Files that were modified:
RefactoringTool: cloudmonkey/cachemaker.py

$ futurize --stage2 -w cloudmonkey/cachemaker.py

RefactoringTool: Refactored cloudmonkey/cachemaker.py

--- cloudmonkey/cachemaker.py (original)
+++ cloudmonkey/cachemaker.py (refactored)
@@ -39,7 +39,7 @@

def splitcsvstring(string):
if string is not None:
- return filter(lambda x: x.strip() != '', string.split(','))
+ return [x for x in string.split(',') if x.strip() != '']
else:
return []

@@ -88,7 +88,7 @@
if isinstance(type(apis), type(None)) or apis is None:
return {}

- responsekey = filter(lambda x: 'response' in x, apis.keys())
+ responsekey = [x for x in list(apis.keys()) if 'response' in x]

if len(responsekey) == 0:
print("[monkeycache] Invalid dictionary, has no response")
RefactoringTool: Files that were modified:
RefactoringTool: cloudmonkey/cachemaker.py

$ cloudmonkey

Traceback (most recent call last):

File "/Users/kentaro/porting/ven/bin/cloudmonkey", line 9, in <module>
load_entry_point('cloudmonkey', 'console_scripts', 'cloudmonkey')()
File "/Users/kentaro/porting/ven/lib/python3.5/site-packages/pkg_resources/__init__.py", line 542, in load_entry_point
return get_distribution(dist).load_entry_point(group, name)
File "/Users/kentaro/porting/ven/lib/python3.5/site-packages/pkg_resources/__init__.py", line 2569, in load_entry_point
return ep.load()
File "/Users/kentaro/porting/ven/lib/python3.5/site-packages/pkg_resources/__init__.py", line 2229, in load
return self.resolve()
File "/Users/kentaro/porting/ven/lib/python3.5/site-packages/pkg_resources/__init__.py", line 2235, in resolve
module = __import__(self.module_name, fromlist=['__name__'], level=0)
File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/cloudmonkey.py", line 52, in <module>
from .printer import monkeyprint
File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/printer.py", line 27
except ImportError, e:
^
SyntaxError: invalid syntax

$ futurize --stage1 -w cloudmonkey/printer.py

RefactoringTool: Skipping optional fixer: idioms

RefactoringTool: Skipping optional fixer: ws_comma
RefactoringTool: Refactored cloudmonkey/printer.py
--- cloudmonkey/printer.py (original)
+++ cloudmonkey/printer.py (refactored)
@@ -16,6 +16,7 @@
# specific language governing permissions and limitations
# under the License.

+from __future__ import print_function
try:
from pygments import highlight
from pygments.console import ansiformat
@@ -24,8 +25,8 @@
from pygments.token import *

import sys
-except ImportError, e:
- print e
+except ImportError as e:
+ print(e)

MONKEY_COLORS = {
RefactoringTool: Files that were modified:
RefactoringTool: cloudmonkey/printer.py

$ futurize --stage2 -w cloudmonkey/printer.py

RefactoringTool: No files need to be modified.

$ cloudmonkey

Traceback (most recent call last):

File "/Users/kentaro/porting/ven/bin/cloudmonkey", line 9, in <module>
load_entry_point('cloudmonkey', 'console_scripts', 'cloudmonkey')()
File "/Users/kentaro/porting/ven/lib/python3.5/site-packages/pkg_resources/__init__.py", line 542, in load_entry_point
return get_distribution(dist).load_entry_point(group, name)
File "/Users/kentaro/porting/ven/lib/python3.5/site-packages/pkg_resources/__init__.py", line 2569, in load_entry_point
return ep.load()
File "/Users/kentaro/porting/ven/lib/python3.5/site-packages/pkg_resources/__init__.py", line 2229, in load
return self.resolve()
File "/Users/kentaro/porting/ven/lib/python3.5/site-packages/pkg_resources/__init__.py", line 2235, in resolve
module = __import__(self.module_name, fromlist=['__name__'], level=0)
File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/cloudmonkey.py", line 53, in <module>
from .requester import monkeyrequest
File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/requester.py", line 36
except ImportError, e:
^
SyntaxError: invalid syntax

$ futurize --stage1 -w cloudmonkey/requester.py

RefactoringTool: Skipping optional fixer: idioms

RefactoringTool: Skipping optional fixer: ws_comma
RefactoringTool: Refactored cloudmonkey/requester.py
--- cloudmonkey/requester.py (original)
+++ cloudmonkey/requester.py (refactored)
@@ -17,6 +17,7 @@
# specific language governing permissions and limitations
# under the License.

+from __future__ import print_function
try:
import base64
import hashlib
@@ -33,8 +34,8 @@
from datetime import datetime, timedelta
from requests_toolbelt import SSLAdapter
from urllib2 import HTTPError, URLError
-except ImportError, e:
- print "Import error in %s : %s" % (__name__, e)
+except ImportError as e:
+ print("Import error in %s : %s" % (__name__, e))
import sys
sys.exit()

@@ -74,7 +75,7 @@

try:
resp = session.post(url, params=args, verify=verifysslcert)
- except requests.exceptions.ConnectionError, e:
+ except requests.exceptions.ConnectionError as e:
writeError("Connection refused by server: %s" % e)
return None, None

@@ -197,7 +198,7 @@
try:
return make_request_with_password(command, args, logger, url,
credentials, verifysslcert)
- except (requests.exceptions.ConnectionError, Exception), e:
+ except (requests.exceptions.ConnectionError, Exception) as e:
return None, e

def sign_request(params, secret_key):
@@ -231,9 +232,9 @@
elif response.status_code != 200 and response.status_code != 401:
error = "{0}: {1}".format(response.status_code,
response.headers.get('X-Description'))
- except requests.exceptions.ConnectionError, e:
+ except requests.exceptions.ConnectionError as e:
return None, "Connection refused by server: %s" % e
- except Exception, pokemon:
+ except Exception as pokemon:
error = pokemon.message

logger_debug(logger, "Response received: %s" % result)
@@ -263,7 +264,7 @@
def process_json(response):
try:
response = json.loads(response, "utf-8")
- except ValueError, e:
+ except ValueError as e:
logger_debug(logger, "Error processing json: %s" % e)
writeError("Error processing json: %s" % e)
response = None
@@ -292,7 +293,7 @@
while timeout > 0:
interval = 2
while interval > 0:
- sys.stdout.write(u"%s\r" % cursor.next())
+ sys.stdout.write(u"%s\r" % next(cursor))
sys.stdout.flush()
time.sleep(0.1)
interval -= 0.1
RefactoringTool: Files that were modified:
RefactoringTool: cloudmonkey/requester.py

$ futurize --stage2 -w cloudmonkey/requester.py

RefactoringTool: Refactored cloudmonkey/requester.py

--- cloudmonkey/requester.py (original)
+++ cloudmonkey/requester.py (refactored)
@@ -18,6 +18,12 @@
# under the License.

from __future__ import print_function
+from future import standard_library
+standard_library.install_aliases()
+from builtins import filter
+from builtins import zip
+from builtins import next
+from builtins import str
try:
import base64
import hashlib
@@ -28,12 +34,12 @@
import ssl
import sys
import time
- import urllib
- import urllib2
+ import urllib.request, urllib.parse, urllib.error
+ import urllib.request, urllib.error, urllib.parse

from datetime import datetime, timedelta
from requests_toolbelt import SSLAdapter
- from urllib2 import HTTPError, URLError
+ from urllib.error import HTTPError, URLError
except ImportError as e:
print("Import error in %s : %s" % (__name__, e))
import sys
@@ -183,9 +189,9 @@
expirationtime = datetime.utcnow() + timedelta(seconds=int(expires))
args["expires"] = expirationtime.strftime('%Y-%m-%dT%H:%M:%S+0000')

- for key in args.keys():
+ for key in list(args.keys()):
value = args[key]
- if isinstance(value, unicode):
+ if isinstance(value, str):
value = value.encode("utf-8")
args[key] = value
if not key:
@@ -202,12 +208,12 @@
return None, e

def sign_request(params, secret_key):
- request = zip(params.keys(), params.values())
+ request = list(zip(list(params.keys()), list(params.values())))
request.sort(key=lambda x: x[0].lower())
hash_str = "&".join(
["=".join(
[r[0].lower(),
- urllib.quote_plus(str(r[1]), safe="*").lower()
+ urllib.parse.quote_plus(str(r[1]), safe="*").lower()
.replace("+", "%20").replace("%3A", ":")]
) for r in request]
)
@@ -275,12 +281,12 @@
if not response or not isinstance(response, dict):
return response, error

- m = list(v for v in response.keys() if 'response' in v.lower())
+ m = list(v for v in list(response.keys()) if 'response' in v.lower())
if not m:
return response, 'Invalid response received: %s' % response

isasync = isasync and (asyncblock == "true" or asyncblock == "True")
- responsekey = filter(lambda x: 'response' in x, response.keys())[0]
+ responsekey = filter(lambda x: 'response' in x, list(response.keys()))[0]

if isasync and 'jobid' in response[responsekey]:
jobid = response[responsekey]['jobid']
@@ -306,7 +312,7 @@
return response, error

response = process_json(response)
- responsekeys = filter(lambda x: 'response' in x, response.keys())
+ responsekeys = [x for x in list(response.keys()) if 'response' in x]

if len(responsekeys) < 1:
continue
RefactoringTool: Files that were modified:
RefactoringTool: cloudmonkey/requester.py



$ cloudmonkey

☁ Apache CloudStack 🐵 cloudmonkey 5.3.3. Type help or ? to list commands.

Using management server profile: local

(local) 🐵 >

オオオオオオーー

ヤッタァー

起動したぁ

(local) 🐵 >?

Documented commands (type help <topic>):
========================================
EOF change disable history prepare reset start
activate clean disassociate import query resize stop
add configure enable issue quit restart suspend
api copy exit ldap reboot restore sync
archive create expunge list reconnect revert update
assign dedicate extract lock recover revoke upgrade
associate delete find login register saml upload
attach deploy generate logout release scale
authorize destroy get mark remove set
cancel detach help migrate replace shell

helpも出力されるみたい ♪

でも設定してみるとエラーで終了

(local) 🐵 > set url https://comp-api.jp-e1.cloudn-service.com/client/api

(local) 🐵 > exit
Traceback (most recent call last):
File "/Users/kentaro/porting/ven/bin/cloudmonkey", line 9, in <module>
load_entry_point('cloudmonkey', 'console_scripts', 'cloudmonkey')()
File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/cloudmonkey.py", line 920, in main
shell.cmdloop()
File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/cloudmonkey.py", line 163, in cmdloop
super(CloudMonkeyShell, self).cmdloop(intro="")
File "/usr/local/Cellar/python3/3.5.2_1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/cmd.py", line 138, in cmdloop
stop = self.onecmd(line)
File "/usr/local/Cellar/python3/3.5.2_1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/cmd.py", line 217, in onecmd
return func(arg)
File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/cloudmonkey.py", line 841, in do_exit
return self.do_quit(args)
File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/cloudmonkey.py", line 847, in do_quit
self.monkeyprint("Bye!")
File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/cloudmonkey.py", line 238, in monkeyprint
monkeyprint(output)
File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/printer.py", line 122, in monkeyprint
if text.startswith("Error"):
TypeError: startswith first arg must be bytes or a tuple of bytes, not str

ヘルプは動いてるんだけどなぁ

(local) 🐵 > ? set

Set config for cloudmonkey. For example, options can be:
url, auth, log_file, history_file
You may also edit your ~/.cloudmonkey_config instead of using set.

Example:
set url http://localhost:8080/client/api
set prompt 🐵 cloudmonkey>
set log_file /var/log/cloudmonkey.log

どこにエラーがるのかなぁ

ログには何も残ってないからファイルの書き込みかなぁ

$ ls ~/.cloudmonkey/log

/Users/kentaro/.cloudmonkey/log

このあたりが怪しい??


File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/config.py", line 141, in write_config
config.write(cfg)

プロジェクトでconfig.write()を検索しても、この1行しかないので


File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/config.py", line 214, in read_config
write_config(get_attr, config_file)

1行遡るとこの行らしい

write_config(get_attr, config_file)

write_configは config.py から来ているみたい

    from .config import read_config, write_config, config_file, default_profile

結局 ここにたどり着くみたい

py

TypeError: a bytes-like object is required, not 'str'

書き込もうとしている、ファイルがバイナリじゃないといけない?

python2 とpython3の差としてファイルの開け方に差があり、バイナリの場合は b を追加するみたい。

def write_config(get_attr, config_file):

global config_fields, mandatory_sections
global default_profile, default_profile_name
config = ConfigParser()
if os.path.exists(config_file):
try:
with open(config_file, 'r') as cfg:
config.read_file(cfg)
except IOError as e:
print("Error: config_file not found", e)

def write_config(get_attr, config_file):

global config_fields, mandatory_sections
global default_profile, default_profile_name
config = ConfigParser()
if os.path.exists(config_file):
try:
with open(config_file, 'rb') as cfg:
config.read_file(cfg)
except IOError as e:
print("Error: config_file not found", e)

にしてみたところ!!!

cloudmonkey

Selected profile (local) does not exist, using default values
Missing configuration was set using default values for keys:
`asyncblock = true, history_file = /Users/kentaro/.cloudmonkey/history, profile = local, log_file = /Users/kentaro/.cloudmonkey/log, cache_file = /Users/kentaro/.cloudmonkey/cache, paramcompletion = true, prompt = 🐵 > , display = default, color = true` in /Users/kentaro/.cloudmonkey/config
☁ Apache CloudStack 🐵 cloudmonkey 5.3.3. Type help or ? to list commands.

Using management server profile: local

(local) 🐵 >

起動に成功 !!!

(local) 🐵 > help

Documented commands (type help <topic>):
========================================
EOF change disable history prepare reset start
activate clean disassociate import query resize stop
add configure enable issue quit restart suspend
api copy exit ldap reboot restore sync
archive create expunge list reconnect revert update
assign dedicate extract lock recover revoke upgrade
associate delete find login register saml upload
attach deploy generate logout release scale
authorize destroy get mark remove set
cancel detach help migrate replace shell

(local) 🐵 > exit
Traceback (most recent call last):
File "/Users/kentaro/porting/ven/bin/cloudmonkey", line 9, in <module>
load_entry_point('cloudmonkey', 'console_scripts', 'cloudmonkey')()
File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/cloudmonkey.py", line 920, in main
shell.cmdloop()
File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/cloudmonkey.py", line 163, in cmdloop
super(CloudMonkeyShell, self).cmdloop(intro="")
File "/usr/local/Cellar/python3/3.5.2_1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/cmd.py", line 138, in cmdloop
stop = self.onecmd(line)
File "/usr/local/Cellar/python3/3.5.2_1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/cmd.py", line 217, in onecmd
return func(arg)
File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/cloudmonkey.py", line 841, in do_exit
return self.do_quit(args)
File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/cloudmonkey.py", line 847, in do_quit
self.monkeyprint("Bye!")
File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/cloudmonkey.py", line 238, in monkeyprint
monkeyprint(output)
File "/Users/kentaro/porting/cloudstack-cloudmonkey/cloudmonkey/printer.py", line 122, in monkeyprint
if text.startswith("Error"):
TypeError: startswith first arg must be bytes or a tuple of bytes, not str

ヘルプは表示されるけど、終了すらできないみたい...

今日はここまで