Skip to content
This repository has been archived by the owner on Sep 24, 2023. It is now read-only.

Porting to Python 3 #14

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
_env
qpm.egg-info/
.vimrc
venv*/
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ os:
- osx

python:
- "2.7"
- "3.7"

install:
- sudo pip2 install . -q
- sudo pip3 install . -q
- curl -s -L https://github.com/supercollider/supercollider/releases/download/Version-3.7.1/SuperCollider-OSX-3.7.1.zip -o SuperCollider-Mac.zip
- unzip -qq -d . SuperCollider-Mac.zip
- qpm quark checkout CommonTests CommonTestsGUI UnitTesting API --location $HOME/Quarks
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ Written in Python.

Author: Scott Carver (https://github.com/scztt)

Supported versions:
- Python 2.7
Supported Python versions:
- 3.6
- 3.7
- 3.8

Features and Usage
------------------
Expand Down Expand Up @@ -58,7 +60,6 @@ Requirements
------------

- semantic-version==2.2.0
- wsgiref==0.1.2
- nose==1.3.0
- gitpython==0.3.2
- PyDispatcher==2.0.3
Expand Down
File renamed without changes.
6 changes: 0 additions & 6 deletions qpm-test.py

This file was deleted.

1 change: 0 additions & 1 deletion qpm/cli/controllers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ class Meta:
description = 'SuperCollider test and installation tool'
stacked_on = 'base'
stacked_type = 'embedded'
description = 'do things with sclang'

@expose(hide=True)
def default(self):
Expand Down
6 changes: 2 additions & 4 deletions qpm/cli/controllers/quark.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@
import itertools
from multiprocessing.pool import ThreadPool

import qpm.quarks
import qpm.sclang_process as process

from cement.core import controller
from qpm.quarks import *
from cement.core.controller import CementBaseController, expose
from cement.core.controller import CementBaseController

quark_list_m = '''
Available quarks from {{repo-count}} repos.
Expand All @@ -22,7 +21,6 @@ class Meta:
description = 'Quark installation and test tool'
stacked_on = 'base'
stacked_type = 'nested'
description = 'do things with quarks'

class Quark_List(CementBaseController):
class Meta:
Expand Down Expand Up @@ -149,7 +147,7 @@ def do_request_specs(quark_spec):

requests = list(itertools.chain(*pool.map(do_request_specs, quark_specs)))
if len(requests) > 20:
print 'Requesting info on %s quark version - this may take some time...' % len(requests)
print('Requesting info on %s quark version - this may take some time...' % len(requests))

results_list = pool.map(do_request_version, requests)

Expand Down
6 changes: 3 additions & 3 deletions qpm/cli/controllers/sclang.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import qpm.sclang_process as process
import qpm.sclang_testing as testing

from base import *
from .base import *

class SCLang_Execute(SCLang_AbstractBase):
class Meta:
Expand Down Expand Up @@ -58,7 +58,7 @@ def default(self):
result = testing.find_tests(sclang, self.app.pargs.print_output,
self.app.pargs.include, self.app.pargs.exclude)
self.app.render(result, 'test_list')
except Exception, e:
except Exception as e:
self.app.render(e, 'error')

class SCLang_RunTest(SCLang_AbstractBase):
Expand Down Expand Up @@ -125,7 +125,7 @@ def default(self):
else:
self.app.close(0)

except Exception, e:
except Exception as e:
self.app.render(e, 'error')
self.app.close(1)

Expand Down
58 changes: 29 additions & 29 deletions qpm/core/app.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import os.path
import numbers
import json

from cement.core import foundation, controller, output, handler

Expand Down Expand Up @@ -48,23 +47,24 @@ def render(self, data, template):
return ""

def render_default(self, data):
print data
print(data)

def render_error(self, error):
print failF("ERROR:\n" + str(error))
raise error
print(failF("ERROR:\n" + str(error)))

def render_quark_list(self, quarks):
print self.column_list(quarks, 3, 30)
print(self.column_list(quarks, 3, 30))

def render_quark_checkout(self, quarks):
print '\nResult:'
print('\nResult:')
for name, result in quarks.iteritems():
name = name.rjust(20)
print ' %s ===> %s' % (name, result)
print ''
print(' %s ===> %s' % (name, result))
print('')

def render_test_list(self, tests):
print self.column_list(tests, 2, 50)
print(self.column_list(tests, 2, 50))

def column_list(self, list, columns=4, width=35, indent=''):
groups = zip(*(iter(list),) * columns)
Expand All @@ -81,7 +81,7 @@ def render_quark_versions(self, list):

for name, versions in list.iteritems():
name = name.rjust(20)
print '%s: %s' % (headingF(name), passF(' '.join(['HEAD'] + versions)))
print('%s: %s' % (headingF(name), passF(' '.join(['HEAD'] + versions))))

def render_test_summary(self, summary):
summary_str = '\n '
Expand All @@ -99,25 +99,25 @@ def render_test_summary(self, summary):
else:
summary_str += failF("NO TESTS RUN")

print summary_str
print(summary_str)
if summary['failed_tests'] > 0:
print 'Search for ? or ! to find failed tests.'
print('Search for ? or ! to find failed tests.')

def render_quark_info(self, summary):
for quark_name in summary:
print headingF(quark_name)
print(headingF(quark_name))
for version in sorted(summary[quark_name].keys()):
if version == 'HEAD' and summary[quark_name][version].get('version'):
print ' %s (v%s)' %(version, summary[quark_name][version]['version'])
print(' %s (v%s)' %(version, summary[quark_name][version]['version']))
else:
print ' ' + version
print(' ' + version)

for key, val in summary[quark_name][version].iteritems():
if key == 'error':
print (' ' * 4) + (failF('(%s)' % val.decode('utf-8', 'ignore'))).ljust(6)
print((' ' * 4) + (failF('(%s)' % val.decode('utf-8', 'ignore'))).ljust(6))
else:
if not isinstance(val, basestring): val = ", ".join(val)
print (' ' * 4) + ('%s: ' % key).rjust(15) + val
if not isinstance(val, str): val = ", ".join(val)
print((' ' * 4) + ('%s: ' % key).rjust(15) + val)

def render_test_result(self, test_result):
duration = float(test_result.get('duration', 0))
Expand All @@ -127,31 +127,31 @@ def render_test_result(self, test_result):
completed = (test_result.get('completed') == True)
if completed:
if test_result.get('skip'):
print template % skipF('[-] ') + (' Skipped (reason: %s)' % test_result.get('skipReason')).rjust(12)
print(template % skipF('[-] ') + (' Skipped (reason: %s)' % test_result.get('skipReason')).rjust(12))
elif test_result.get('results'):
total = len(test_result['results'])
passing = len(filter(lambda p: p.get('pass', False), test_result['results']))
passing = len(list(filter(lambda p: p.get('pass', False), test_result['results'])))

format = passF if (total == passing and not test_result.get('error')) else failF
print template % format('[%d/%d]' % (passing, total))
print(template % format('[%d/%d]' % (passing, total)))

if test_result.get('error'):
total += 1
print failF('!'.rjust(12)) + ' %s' % ('Encountered error: %s' % test_result.get('error')).strip()
print(failF('!'.rjust(12)) + ' %s' % ('Encountered error: %s' % test_result.get('error')).strip())

for subtest in test_result.get('results', []):
if subtest.get('pass', False):
print passF('*'.rjust(12)) + ' %s' % unescape(subtest.get('test')).strip()
print(passF('*'.rjust(12)) + ' %s' % unescape(subtest.get('test')).strip())
else:
print failF('!'.rjust(12)) + ' %s' % (unescape(subtest.get('test'))).strip()
print(failF('!'.rjust(12)) + ' %s' % (unescape(subtest.get('test'))).strip())
if subtest.get('reason'):
print (' ' * 14) + '%s' % unescape(" ".join(subtest['reason']).strip())
print((' ' * 14) + '%s' % unescape(" ".join(subtest['reason']).strip()))
else:
if test_result.get('error'):
print template % failF('[!]') + ' (No results found)'
print failF('!'.rjust(12)) + ' %s' % ('Error: "%s"' % test_result.get('error')).strip()
print(template % failF('[!]') + ' (No results found)')
print(failF('!'.rjust(12)) + ' %s' % ('Error: "%s"' % test_result.get('error')).strip())
else:
print template % passF(' (completed)')
print(template % passF(' (completed)'))
else:
print template % failF('[!]') + ' (Did not complete.)'
print failF('!'.rjust(12)) + ' %s' % ('Error: "%s"' % test_result.get('error')).strip()
print(template % failF('[!]') + ' (Did not complete.)')
print(failF('!'.rjust(12)) + ' %s' % ('Error: "%s"' % test_result.get('error')).strip())
2 changes: 1 addition & 1 deletion qpm/quarks/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import requests
from github_http import GitHubEndpoint
from .github_http import GitHubEndpoint

endpoints = [GitHubEndpoint]

Expand Down
6 changes: 3 additions & 3 deletions qpm/quarks/github_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ def url_match(cls, url):
patterns = [
GITHUB_GIT_URL_REGEXP,
GITHUB_HTTP_URL_REGEXP
];
]
matches = filter(lambda p: re.match(p, url), patterns)
return len(matches) > 0
return len(list(matches)) > 0

def __init__(self, name, url):
self.url = url
Expand Down Expand Up @@ -142,7 +142,7 @@ def checkout(self, version, quark_store):
shutil.move(os.path.join(quark_destination_tmp, folders[0]), quark_destination)
shutil.rmtree(quark_destination_tmp)
else:
raise Exception('Problem with file download: $s (size %s)' % (zip_destination, size))
raise Exception('Problem with file download: %s (size %s)' % (zip_destination, size))

return quark_destination

Expand Down
35 changes: 20 additions & 15 deletions qpm/sclang_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,12 @@ def load_script(name):
script = f.read()
return script

def do_execute(sclang_path, code, includes=[], excludes=[], print_output=False):
def do_execute(sclang_path, code, includes=None, excludes=None, print_output=False):
if not(sclang_path) or not(os.path.exists(sclang_path)):
raise Exception("No sclang binary found in path %s" % sclang_path)
# mutable arguments such as [] should not be in the arguments
includes = includes if includes else []
excludes = excludes if excludes else []

#app.render({ "message": "Launching sclang at %s" % sclang_path })
proc = ScLangProcess(sclang_path, print_output=print_output)
Expand All @@ -71,7 +74,7 @@ def do_execute(sclang_path, code, includes=[], excludes=[], print_output=False):
if output:
return output.group(1), error
else:
print error
print(error)
return "", error

def set_non_block(output):
Expand All @@ -82,8 +85,9 @@ def safe_read(output):
fd = output.fileno()
set_fd_non_block(fd)
try:
return output.read()
except Exception, e:
text = output.read()
return text.decode() if text else ""
except Exception as e:
time.sleep(0.2)
return ""

Expand All @@ -110,7 +114,7 @@ def __init__(self, path, classlib=None, headless=True, print_output=False):
self.error = ""
self.includes = set()
self.excludes = set()
self.classlib = classlib if (classlib != None) else find_classlibrary(os.path.dirname(os.path.dirname(path)))
self.classlib = classlib if (classlib is not None) else find_classlibrary(os.path.dirname(os.path.dirname(path)))
if not(self.classlib):
raise Exception("Could not find classlib.")
else:
Expand Down Expand Up @@ -154,7 +158,7 @@ def launch(self):

if self.print_output:
#app.render({ "message": "Running: %s" % ' '.join(cmd) })
print "Running: %s" % ' '.join(cmd)
print("Running: %s" % ' '.join(cmd))

global_app.log.debug('Launching with command: %s' % (' '.join(cmd)))
self.proc = subprocess.Popen(cmd,
Expand Down Expand Up @@ -199,7 +203,7 @@ def wait_for(self, regex, timeout=30, kill_on_error=True, filter_allowed_errors=

while self.running() and not(re_match) and time.time() < (start_time + timeout):
read = safe_read(self.proc.stdout)
if self.print_output and read: print read
if self.print_output and read: print(read)
output += read
error += safe_read(self.proc.stderr)
re_match = re.search(regex, output, re.DOTALL)
Expand Down Expand Up @@ -231,15 +235,15 @@ def wait_for(self, regex, timeout=30, kill_on_error=True, filter_allowed_errors=

def running(self):
if self.proc:
return (self.proc.returncode == None)
return self.proc.returncode is None
else:
return False

def kill(self):
if self.launched:
tries = 3
self.return_code = None
while tries and self.return_code == None:
while tries and self.return_code is None:
tries -= 1
self.proc.kill()
time.sleep(0.1)
Expand All @@ -258,7 +262,8 @@ def execute(self, command):
global_app.log.debug('output:\n%s' % self.output)
global_app.log.debug('error:\n%s' % self.error)
raise Exception("Process not ready - may not have launched correctly")
self.proc.stdin.write("%s %s" % (command, chr(0x1b)))
self.proc.stdin.write(("%s %s\n" % (command, chr(0x1b))).encode('utf-8'))
self.proc.stdin.flush()



Expand All @@ -272,7 +277,7 @@ def runFile(sclang_path, file_path, timeout=30):
buffer = ""
while (time.time() - start_time) < timeout:
buffer += proc.stdout.read()
if proc.poll() == None:
if proc.poll() is None:
time.sleep(0.1)
else:
break
Expand All @@ -281,7 +286,7 @@ def runFile(sclang_path, file_path, timeout=30):
for str in resultStrings:
try:
results.append(json.loads(str))
except Exception, e:
except Exception as e:
results.append(e)
return results

Expand All @@ -290,7 +295,7 @@ def convert_quark_infos(sclang_path, quark_infos):

date = datetime.date.today()
fd, infos_file = tempfile.mkstemp('.json', 'quark_infos' + "_".join([str(date.day), str(date.month), str(date.year)]))
with file(infos_file, 'w') as f: f.write(infos_string)
with open(infos_file, 'w') as f: f.write(infos_string)

sc_script = r'''
~result = ();
Expand Down Expand Up @@ -353,9 +358,9 @@ def convert_quark_infos(sclang_path, quark_infos):
''' % (infos_file)

result_string = do_execute(sclang_path, sc_script, True)[0]
print type(result_string)
print(type(result_string))
result_string = result_string.decode('utf8')
print result_string
print(result_string)
result = json.loads(result_string)

return result
Loading