From cd8e27b104e67b6faf6b70617dadc2cec2f05ca4 Mon Sep 17 00:00:00 2001 From: Alessandro Thea Date: Mon, 14 Sep 2020 07:33:00 +0200 Subject: [PATCH 01/11] Playing with rich table in `ipbb.repo` See #101 --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 3c9ce94c..de2d64dd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,5 +10,6 @@ pexpect==4.8.0 psutil==5.7.2 pytest==6.0.2 PyYAML==5.3.1 +rich==6.1.2 sh==1.14.0 texttable==1.6.3 From 7249bf8158d024d2288869f1603a302423ccb6aa Mon Sep 17 00:00:00 2001 From: Alessandro Thea Date: Sun, 4 Oct 2020 22:19:09 +0200 Subject: [PATCH 02/11] First pass at replacing click secho and Texttable with rich --- requirements.txt | 7 +-- src/ipbb/cli/proj.py | 1 - src/ipbb/cmds/__init__.py | 4 +- src/ipbb/cmds/_utils.py | 39 +++++++------ src/ipbb/console.py | 6 ++ src/ipbb/scripts/builder.py | 111 ++++++++++++++++++------------------ 6 files changed, 89 insertions(+), 79 deletions(-) create mode 100644 src/ipbb/console.py diff --git a/requirements.txt b/requirements.txt index de2d64dd..c3453ff8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,13 +3,12 @@ click-didyoumean==0.0.3 configparser==5.0.0 future==0.18.2 ipaddress==1.0.23 -ipaddress -ipdb==0.13.3 +ipdb==0.13.4 ipython==7.16.1 pexpect==4.8.0 psutil==5.7.2 -pytest==6.0.2 +pytest==6.1.1 PyYAML==5.3.1 rich==6.1.2 sh==1.14.0 -texttable==1.6.3 +texttable==1.6.3 \ No newline at end of file diff --git a/src/ipbb/cli/proj.py b/src/ipbb/cli/proj.py index 630e1e80..9ecec5b2 100644 --- a/src/ipbb/cli/proj.py +++ b/src/ipbb/cli/proj.py @@ -13,7 +13,6 @@ from ._utils import completeComponent, completeProject, completeDepFile from os.path import join, split, exists, splitext, relpath, isdir -from click import echo, style, secho # ------------------------------------------------------------------------------ diff --git a/src/ipbb/cmds/__init__.py b/src/ipbb/cmds/__init__.py index 848bc60e..236b3645 100644 --- a/src/ipbb/cmds/__init__.py +++ b/src/ipbb/cmds/__init__.py @@ -1,7 +1,6 @@ # Import click for ansi colors import yaml -from click import echo, secho, style, confirm from . import _utils @@ -9,6 +8,7 @@ from os.path import join, split, exists, splitext, basename, dirname from ..defaults import kWorkAreaFile, kProjAreaFile, kProjUserFile, kSourceDir, kProjDir +from ..console import cprint # ------------------------------------------------------------------------------ @@ -192,7 +192,7 @@ def depParser(self): pass if self._depParser.errors: - secho('WARNING: dep parsing errors detected', fg='yellow') + cprint('WARNING: dep parsing errors detected', style='yellow') return self._depParser diff --git a/src/ipbb/cmds/_utils.py b/src/ipbb/cmds/_utils.py index 72f02773..e7b6d5d5 100644 --- a/src/ipbb/cmds/_utils.py +++ b/src/ipbb/cmds/_utils.py @@ -4,10 +4,15 @@ import sys import re -from click import echo, secho, style, confirm, get_current_context, ClickException, Abort, BadParameter -from texttable import Texttable +# from click import echo, secho, style, confirm +from click import get_current_context, ClickException, Abort, BadParameter +# from texttable import Texttable from os.path import join, relpath, exists, split, realpath +from rich.prompt import Confirm + from ..tools.alien import AlienBranch +from ..console import cprint + # ------------------------------------------------------------------------------ class DirSentry: @@ -39,7 +44,7 @@ def raiseError(aMessage): Print the error message to screen in bright red and a ClickException error """ - secho("\nERROR: " + aMessage + "\n", fg='red') + cprint("\nERROR: " + aMessage + "\n", style='red') raise ClickException("Command aborted.") # ------------------------------------------------------------------------------ @@ -106,12 +111,12 @@ def ensureNoParsingErrors(aCurrentProj, aDepFileParser): from .formatters import DepFormatter fmt = DepFormatter(aDepFileParser) - secho("ERROR: Project '{}' contains {} parsing error{}.".format( + cprint("ERROR: Project '{}' contains {} parsing error{}.".format( aCurrentProj, len(aDepFileParser.errors), ("" if len(aDepFileParser.errors) == 1 else "s"), - ), fg='red') - secho(fmt.drawParsingErrors(), fg='red') + ), style='red') + cprint(fmt.drawParsingErrors(), style='red') raise Abort() @@ -129,25 +134,25 @@ def ensureNoMissingFiles(aCurrentProj, aDepFileParser): from .formatters import DepFormatter fmt = DepFormatter(aDepFileParser) - secho("ERROR: Project '{}' contains unresolved dependencies: {} unresolved file{}.".format( + cprint("ERROR: Project '{}' contains unresolved dependencies: {} unresolved file{}.".format( aCurrentProj, len(aDepFileParser.unresolved), ("" if len(aDepFileParser.unresolved) == 1 else "s"), - ), fg='red') - secho(fmt.drawUnresolvedFiles(), fg='red') + ), style='red') + cprint(fmt.drawUnresolvedFiles(), style='red') - secho("") - confirm("Do you want to continue anyway?", abort=True) + cprint("") + if not Confirm.ask("Do you want to continue anyway?"): + raise click.Abort() # ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------ def echoVivadoConsoleError( aExc ): - echo( - style("Vivado error/critical warnings detected\n", fg='red') + - style("\n".join(aExc.errors), fg='red') + '\n' + - style("\n".join(aExc.criticalWarns), fg='yellow') - ) + cprint("Vivado error/critical warnings detected", style='red') + cprint("\n".join(aExc.errors), style='red') + cprint("\n".join(aExc.criticalWarns), style='yellow') + # ------------------------------------------------------------------------------ @@ -214,7 +219,7 @@ def validateMacAddress(value): # ------------------------------------------------------------------------------ def printRegTable(aRegs, aHeader=True, aSort=True): - echo ( formatRegTable(aRegs, aHeader, aSort) ) + cprint ( formatRegTable(aRegs, aHeader, aSort) ) # ------------------------------------------------------------------------------ diff --git a/src/ipbb/console.py b/src/ipbb/console.py new file mode 100644 index 00000000..dc300d13 --- /dev/null +++ b/src/ipbb/console.py @@ -0,0 +1,6 @@ +from rich.console import Console + +console = Console() + +def cprint(*args, **kwargs): + console.print(*args, **kwargs) \ No newline at end of file diff --git a/src/ipbb/scripts/builder.py b/src/ipbb/scripts/builder.py index 0e0bd70e..1d0921bb 100755 --- a/src/ipbb/scripts/builder.py +++ b/src/ipbb/scripts/builder.py @@ -7,12 +7,9 @@ import traceback from io import StringIO, BytesIO -from texttable import Texttable -from click import echo, style, secho - from ..cmds import Environment from ..cmds.formatters import DepFormatter - +from ..console import cprint from .._version import __version__ # ------------------------------------------------------------------------------ @@ -90,62 +87,66 @@ def _compose_cli(): from ..cli import debug climain.add_command(debug.debug) + + # ------------------------------------------------------------------------------ +def validate_completion(): + """ + This function should be moved to an unit test + """ + _compose_cli() + from click._bashcomplete import get_choices + + def choices_without_help(cli, args, incomplete): + completions = get_choices(cli, 'dummy', args, incomplete) + return [c[0] for c in completions] + + for inc in [ + '', + 'f', + 'felix-pie', + 'felix-pie:', + 'felix-pie:p', + 'felix-pie:projects/', + 'felix-pie:projects/hi', + 'felix-pie:projects/hitfinder/' + ]: + print("-" * 80) + print("Completing component'" + inc + "'") + print("-" * 80) + print(choices_without_help(climain, ['proj', 'create', 'vivado', 'jbsc-hf-fc-tightG'], inc)) + print() + + for inc in [ + '', + ]: + print("-" * 80) + print("Completing dep file'" + inc + "'") + print("-" * 80) + print(choices_without_help(climain, ['ipbb', 'toolbox', 'check-dep', 'felix-pie:projects/hitfinder'], inc)) + print() + + for inc in [ + '', + ]: + print("-" * 80) + print("Completing dep file'" + inc + "'") + print("-" * 80) + print(choices_without_help(climain, ['proj', 'create', 'vivado', 'jbsc-hf-fc-tightG', 'felix-pie:projects/hitfinder', '-t'], inc)) + print() + raise SystemExit(0) # ------------------------------------------------------------------------------ def main(): '''Discovers the env at startup''' - if sys.version_info[0:2] < (2, 7): - click.secho("Error: Python 2.7 is required to run IPBB", fg='red') + if sys.version_info[0:2] < (3, 6): + cprint("Error: Python 3.6 is required to run IPBB", style='red') raise SystemExit(-1) _compose_cli() - # if True: - if False: - from click._bashcomplete import get_choices - - def choices_without_help(cli, args, incomplete): - completions = get_choices(cli, 'dummy', args, incomplete) - return [c[0] for c in completions] - - for inc in [ - '', - 'f', - 'felix-pie', - 'felix-pie:', - 'felix-pie:p', - 'felix-pie:projects/', - 'felix-pie:projects/hi', - 'felix-pie:projects/hitfinder/' - ]: - print("-" * 80) - print("Completing component'" + inc + "'") - print("-" * 80) - print(choices_without_help(climain, ['proj', 'create', 'vivado', 'jbsc-hf-fc-tightG'], inc)) - print() - - for inc in [ - '', - ]: - print("-" * 80) - print("Completing dep file'" + inc + "'") - print("-" * 80) - print(choices_without_help(climain, ['ipbb', 'toolbox', 'check-dep', 'felix-pie:projects/hitfinder'], inc)) - print() - - for inc in [ - '', - ]: - print("-" * 80) - print("Completing dep file'" + inc + "'") - print("-" * 80) - print(choices_without_help(climain, ['proj', 'create', 'vivado', 'jbsc-hf-fc-tightG', 'felix-pie:projects/hitfinder', '-t'], inc)) - print() - raise SystemExit(0) - obj = Environment() try: climain(obj=obj) @@ -154,7 +155,7 @@ def choices_without_help(cli, args, incomplete): exc_type, exc_obj, exc_tb = sys.exc_info() lFirstFrame = traceback.extract_tb(exc_tb)[-1] - secho( + cprint( u"ERROR ('{}' exception caught): '{}'\n\nFile \"{}\", line {}, in {}\n {}".format( exc_type.__name__, e, @@ -163,16 +164,16 @@ def choices_without_help(cli, args, incomplete): lFirstFrame[2], lFirstFrame[3], ), - fg='red', + style='red', ) if obj.printExceptionStack: lExc = (BytesIO() if (version_info[0] <= 2) else StringIO()) traceback.print_exc(file=lExc) - print("Exception in user code:") - print('-' * 60) - secho(lExc.getvalue(), fg='red') - print('-' * 60) + cprint("Exception in user code:") + cprint('-' * 60) + cprint(lExc.getvalue(), style='red') + cprint('-' * 60) raise SystemExit(-1) From 7af360308631716eebfd2bd6a12d2d42105dde95 Mon Sep 17 00:00:00 2001 From: Alessandro Thea Date: Sun, 4 Oct 2020 23:51:55 +0200 Subject: [PATCH 03/11] Second pass, long way to go --- src/ipbb/cmds/_utils.py | 50 +++------- src/ipbb/cmds/formatters.py | 20 ++-- src/ipbb/cmds/proj.py | 51 +++++----- src/ipbb/cmds/repo.py | 182 +++++++++++++++++++----------------- 4 files changed, 151 insertions(+), 152 deletions(-) diff --git a/src/ipbb/cmds/_utils.py b/src/ipbb/cmds/_utils.py index e7b6d5d5..4f8d218a 100644 --- a/src/ipbb/cmds/_utils.py +++ b/src/ipbb/cmds/_utils.py @@ -4,11 +4,10 @@ import sys import re -# from click import echo, secho, style, confirm from click import get_current_context, ClickException, Abort, BadParameter -# from texttable import Texttable from os.path import join, relpath, exists, split, realpath from rich.prompt import Confirm +from rich.table import Table from ..tools.alien import AlienBranch from ..console import cprint @@ -199,7 +198,6 @@ def validateIpAddress(value): lHexIp = ''.join([ '%02x' % ord(c) for c in lIp.packed]) return 'X"{}"'.format(lHexIp) -# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------ @@ -214,80 +212,58 @@ def validateMacAddress(value): lHexMac = ''.join([ '%02x' % int(c, 16) for c in value.split(':')]) return 'X"{}"'.format(lHexMac) -# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------ def printRegTable(aRegs, aHeader=True, aSort=True): cprint ( formatRegTable(aRegs, aHeader, aSort) ) -# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------ def formatRegTable(aRegs, aHeader=True, aSort=True): - lRegTable = Texttable(max_width=0) - lRegTable.set_deco(Texttable.VLINES | Texttable.BORDER | Texttable.HEADER) - lRegTable.set_chars(['-', '|', '+', '-']) - if aHeader: - lRegTable.header( ['name', 'value'] ) - lRegs = sorted(aRegs) if aSort else aRegs - for k in lRegs: - lRegTable.add_row( [str(k), hex(aRegs[k])] ) - - return lRegTable.draw() -# ------------------------------------------------------------------------------ + lRegTable = Table('name', 'value', show_header=aHeader) + for k in (sorted(aRegs) if aSort else aRegs): + lRegTable.add_row( str(k), hex(aRegs[k]) ) + return lRegTable # ------------------------------------------------------------------------------ def printDictTable(aDict, aHeader=True, aSort=True, aFmtr=None): - echo ( formatDictTable(aDict, aHeader, aSort, aFmtr) ) -# ------------------------------------------------------------------------------ + cprint ( formatDictTable(aDict, aHeader, aSort, aFmtr) ) # ------------------------------------------------------------------------------ def formatDictTable(aDict, aHeader=True, aSort=True, aFmtr=str): - lDictTable = Texttable(max_width=0) - lDictTable.set_deco(Texttable.VLINES | Texttable.BORDER | Texttable.HEADER) - lDictTable.set_chars(['-', '|', '+', '-']) - if aHeader: - lDictTable.header( ['name', 'value'] ) + lDictTable = Table('name', 'value', show_header=aHeader) for k in (sorted(aDict) if aSort else aDict): v = aDict[k] - lDictTable.add_row( [str(k), aFmtr(v) if aFmtr else v]) + lDictTable.add_row(str(k), aFmtr(v) if aFmtr else v) + return lDictTable - return lDictTable.draw() -# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------ def printAlienTable(aBranch, aHeader=True, aSort=True, aFmtr=None): - echo ( formatAlienTable(aBranch, aHeader, aSort, aFmtr) ) -# ------------------------------------------------------------------------------ + cprint ( formatAlienTable(aBranch, aHeader, aSort, aFmtr) ) # ------------------------------------------------------------------------------ def formatAlienTable(aBranch, aHeader=True, aSort=True, aFmtr=str): - lAlienTable = Texttable(max_width=0) - lAlienTable.set_deco(Texttable.VLINES | Texttable.BORDER | Texttable.HEADER) - lAlienTable.set_chars(['-', '|', '+', '-']) - if aHeader: - lAlienTable.header( ['name', 'value'] ) + lAlienTable = Table('name', 'value', show_header=aHeader) for k in (sorted(aBranch) if aSort else aBranch): v = aBranch[k] if isinstance(v, AlienBranch): continue - lAlienTable.add_row( [str(k), aFmtr(v) if aFmtr else v]) + lAlienTable.add_row( str(k), aFmtr(v) if aFmtr else v) - return lAlienTable.draw() -# ------------------------------------------------------------------------------ + return lAlienTable # ------------------------------------------------------------------------------ def getClickRootName(): return get_current_context().find_root().info_name -# ------------------------------------------------------------------------------ diff --git a/src/ipbb/cmds/formatters.py b/src/ipbb/cmds/formatters.py index 35f687ad..3a0a6136 100644 --- a/src/ipbb/cmds/formatters.py +++ b/src/ipbb/cmds/formatters.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from texttable import Texttable +from rich.table import Table, Column from os.path import ( join, split, @@ -70,12 +70,18 @@ def drawDeptreeCommandsSummary(self): Draws a deptree commands summary table. """ - lCommandKinds = ['setup', 'src', 'hlssrc', 'util', 'addrtab', 'iprepo'] - lDepTable = Texttable() - lDepTable.set_cols_align(['c'] * len(lCommandKinds)) - lDepTable.add_row(lCommandKinds) - lDepTable.add_row([len(self.parser.commands[k]) for k in lCommandKinds]) - return lDepTable.draw() + # lCommandKinds = ['setup', 'src', 'hlssrc', 'util', 'addrtab', 'iprepo'] + # lDepTable = Texttable() + # lDepTable.set_cols_align(['c'] * len(lCommandKinds)) + # lDepTable.add_row(lCommandKinds) + # lDepTable.add_row([len(self.parser.commands[k]) for k in lCommandKinds]) + # return lDepTable.draw() + + lCommandKinds = ('setup', 'src', 'hlssrc', 'util', 'addrtab', 'iprepo') + lDepTable = Table( *(Column(c, justify='center') for c in lCommandKinds) ) + lDepTable.add_row( *(str(len(self.parser.commands[k])) for k in lCommandKinds) ) + return lDepTable + def drawUnresolvedSummary(self): """ diff --git a/src/ipbb/cmds/proj.py b/src/ipbb/cmds/proj.py index 6d81c2f4..73fb6960 100644 --- a/src/ipbb/cmds/proj.py +++ b/src/ipbb/cmds/proj.py @@ -7,32 +7,37 @@ # Elements +from ..console import cprint from ..tools.common import SmartOpen from ..defaults import kProjAreaFile, kProjDir from . import ProjectInfo from ._utils import DirSentry, raiseError, validateComponent, findFirstParentDir from ..depparser import depfiletypes, Pathmaker +from rich.table import Table from os.path import join, split, exists, splitext, relpath, isdir, basename -from click import echo, style, secho -from texttable import Texttable +# from click import echo, style, secho +# from texttable import Texttable # ------------------------------------------------------------------------------ def info(env): - secho("Projects", fg='blue') + cprint("Projects", style='blue') + + # lHeader = ('name', 'toolset', 'topPkg', 'topCmp', 'topDep') + # lProjTable = Texttable(120) + # lProjTable.set_deco(Texttable.HEADER | Texttable.BORDER) + # lProjTable.set_chars(['-', '|', '+', '-']) + # lProjTable.header(lHeader) lHeader = ('name', 'toolset', 'topPkg', 'topCmp', 'topDep') - lProjTable = Texttable(120) - lProjTable.set_deco(Texttable.HEADER | Texttable.BORDER) - lProjTable.set_chars(['-', '|', '+', '-']) - lProjTable.header(lHeader) + lProjTable = Table(*lHeader) for p in sorted(env.projects): lProjInfo = ProjectInfo(join(env.projdir, p)) - lProjTable.add_row([p] + [lProjInfo.settings[k] for k in lHeader[1:]] ) + lProjTable.add_row(p, *(lProjInfo.settings[k] for k in lHeader[1:]) ) - echo(lProjTable.draw()) + cprint(lProjTable) # ------------------------------------------------------------------------------ @@ -63,30 +68,30 @@ def create(env, toolset, projname, component, topdep): lTopPackage, lTopComponent = component if lTopPackage not in env.sources: - secho('Top-level package {} not found'.format(lTopPackage), fg='red') - echo('Available packages:') + cprint('Top-level package {} not found'.format(lTopPackage), style='red') + cprint('Available packages:') for lPkg in env.sources: - echo(' - ' + lPkg) + cprint(' - ' + lPkg) raiseError("Top-level package {} not found".format(lTopPackage)) lTopComponentPath = lPathmaker.getPath(lTopPackage, lTopComponent) if not exists(lTopComponentPath): - secho( + cprint( "Top-level component '{}:{}'' not found".format(lTopPackage, lTopComponent), - fg='red', + style='red', ) lParent = findFirstParentDir(lTopComponentPath, lPathmaker.getPath(lTopPackage)) - secho('\nSuggestions (based on the first existing parent path)', fg='cyan') + cprint('\nSuggestions (based on the first existing parent path)', style='cyan') # When in Py3 https://docs.python.org/3/library/os.html#os.scandir for d in [ join(lParent, s) for s in os.listdir(lParent) if isdir(join(lParent, s)) ]: - echo(' - ' + d) - echo() + cprint(' - ' + d) + cprint() raise click.Abort() @@ -111,7 +116,7 @@ def create(env, toolset, projname, component, topdep): # ------------------------------------------------------------------------------ if not lTopExists: import glob - secho('Top-level dep file {} not found or not uniquely resolved'.format(lTopDepPath), fg='red') + cprint('Top-level dep file {} not found or not uniquely resolved'.format(lTopDepPath), style='red') lTopDepDir = lPathmaker.getPath(lTopPackage, lTopComponent, 'include') @@ -120,9 +125,9 @@ def create(env, toolset, projname, component, topdep): "'{}'".format(relpath(p, lTopDepDir)) for p in glob.glob(join(lTopDepDir, '*' + ft)) ] - echo('Suggestions (*{}):'.format(ft)) + cprint('Suggestions (*{}):'.format(ft)) for lC in lTopDepCandidates: - echo(' - ' + lC) + cprint(' - ' + lC) raiseError("Top-level dependency file {} not found".format(lTopDepPath)) @@ -140,8 +145,8 @@ def create(env, toolset, projname, component, topdep): } pi.saveSettings() - secho( - '{} project area \'{}\' created'.format(toolset.capitalize(), projname), fg='green' + cprint( + '{} project area \'{}\' created'.format(toolset.capitalize(), projname), style='green' ) @@ -181,6 +186,6 @@ def cd(env, projname, aVerbose): os.chdir(join(env.projdir, projname)) if aVerbose: - echo("New current directory %s" % os.getcwd()) + cprint("New current directory %s" % os.getcwd()) diff --git a/src/ipbb/cmds/repo.py b/src/ipbb/cmds/repo.py index 3877ec57..f419ec80 100644 --- a/src/ipbb/cmds/repo.py +++ b/src/ipbb/cmds/repo.py @@ -8,9 +8,9 @@ import yaml # Elements -from click import echo, style, secho from os.path import join, split, exists, splitext, dirname, basename, abspath +from ..console import cprint from ..defaults import kSourceDir, kProjDir, kWorkAreaFile, kRepoSetupFile from ..depparser import Pathmaker from ..tools.common import mkdir @@ -19,13 +19,15 @@ from .proj import info as proj_info from urllib.parse import urlparse from distutils.dir_util import mkpath -from texttable import Texttable +from rich.table import Table + +# from texttable import Texttable # ------------------------------------------------------------------------------ def init(env, workarea): '''Initialise a new firmware development area''' - secho('Setting up new firmware work area \'' + workarea + '\'', fg='green') + cprint('Setting up new firmware work area \'' + workarea + '\'', style='green') if env.work.path is not None: raise click.ClickException( @@ -48,62 +50,71 @@ def info(env, verbose): '''Print a brief report about the current working area''' if not env.work.path: - secho('ERROR: No ipbb work area detected', fg='red') + cprint('ERROR: No ipbb work area detected', style='red') return - echo() - secho("ipbb environment", fg='blue') - # echo ( "----------------") + cprint() - lEnvTable = Texttable(max_width=0) - lEnvTable.add_row(["Work path", env.work.path]) + lEnvTable = Table('name', 'path', title='ipbb environment', title_style='blue', show_header=False) + lEnvTable.add_row("Work path", env.work.path) if env.currentproj.path: - lEnvTable.add_row(["Project path", env.currentproj.path]) - echo(lEnvTable.draw()) + lEnvTable.add_row("Project path", env.currentproj.path) + cprint(lEnvTable) if not env.currentproj.path: - echo() + cprint() srcs_info(env) - echo() + cprint() proj_info(env) return - echo() + cprint() if not env.currentproj.settings: return - secho("Project '%s'" % env.currentproj.name, fg='blue') - - echo(formatDictTable(env.currentproj.settings, aHeader=False)) + t = formatDictTable(env.currentproj.settings, aHeader=False) + t.title = "Project '[green]%s[/green]'" % env.currentproj.name + t.title_style = 'blue' + cprint(t) - echo() + cprint() if env.currentproj.usersettings: - secho("User settings", fg='blue') - echo(formatDictTable(env.currentproj.usersettings, aHeader=False)) + cprint("User settings", style='blue') + t = formatDictTable(env.currentproj.usersettings, aHeader=False) + t.title = "User settings" + t.title_style = 'blue' + cprint(t) - echo() + cprint() lParser = env.depParser lDepFmt = DepFormatter(lParser) if lParser.errors: - secho("Dep tree parsing error(s):", fg='red') - echo(lDepFmt.drawParsingErrors()) - echo() + t = lDepFmt.drawParsingErrors() + t.title = "Dep tree parsing error(s)" + t.title_style = 'red' + cprint(t) + + cprint() - secho("Dependecy tree elements", fg='blue') - echo(lDepFmt.drawDeptreeCommandsSummary()) + t = lDepFmt.drawDeptreeCommandsSummary() + t.title = "Dependecy tree elements" + t.title_style = 'blue' + cprint(t) - echo() + cprint() if lParser.unresolved: - secho("Unresolved item(s)", fg='red') - echo(lDepFmt.drawUnresolvedSummary()) + t = lDepFmt.drawUnresolvedSummary() + t.title = "Unresolved item(s)" + t.title_style = 'red' + cprint(t) - echo() + cprint() # ------------------------------------------------------------------------------ @@ -121,18 +132,18 @@ def add(env): def _repoInit(env, dest): if dest not in env.sources: - secho('Source package {} not found'.format(dest), fg='red') - echo('Available repositories:') + cprint('Source package {} not found'.format(dest), style='red') + cprint('Available repositories:') for lPkg in env.sources: - echo(' - ' + lPkg) + cprint(' - ' + lPkg) raiseError("Source package {} not found".format(dest)) setupPath = join(env.srcdir, dest, kRepoSetupFile) if not exists(setupPath): - secho('No repository setup file found in {}. Skipping'.format(dest), fg='blue') + cprint('No repository setup file found in {}. Skipping'.format(dest), style='blue') return - secho('Setting up {}'.format(dest), fg='blue') + cprint('Setting up {}'.format(dest), style='blue') setupCfg = None with open(setupPath, 'r') as f: @@ -140,7 +151,7 @@ def _repoInit(env, dest): setupCfg = setupCfg.get('init', None) if setupCfg is None: - echo("No init configuration file. Skipping.") + cprint("No init configuration file. Skipping.") return cmds = [ l.split() for l in setupCfg ] @@ -148,9 +159,9 @@ def _repoInit(env, dest): # ensure that all commands exist missingCmds = [(i, cmd) for i, cmd in enumerate(cmds) if not sh.which(cmd[0])] if missingCmds: - secho('Some setup commands have not been found', fg='red') + cprint('Some setup commands have not been found', style='red') for i, cmd in missingCmds: - echo(' - {} (line {})'.format(cmd, i)) + cprint(' - {} (line {})'.format(cmd, i)) raiseError("Setup commands not found".format(dest)) @@ -161,25 +172,25 @@ def _repoInit(env, dest): # In red the failed one # In white the remaining commands for cmd in cmds: - secho('> '+' '.join(cmd), fg='cyan') + cprint('> '+' '.join(cmd), style='cyan') sh.Command(cmd[0])(*cmd[1:], _out=sys.stdout) # ------------------------------------------------------------------------------ def _repoReset(env, dest): if dest not in env.sources: - secho('Source package {} not found'.format(dest), fg='red') - echo('Available repositories:') + cprint('Source package {} not found'.format(dest), style='red') + cprint('Available repositories:') for lPkg in env.sources: - echo(' - ' + lPkg) + cprint(' - ' + lPkg) raiseError("Source package {} not found".format(dest)) setupPath = join(env.srcdir, dest, kRepoSetupFile) if not exists(setupPath): - secho('No repository setup file found in {}. Skipping'.format(dest), fg='blue') + cprint('No repository setup file found in {}. Skipping'.format(dest), style='blue') return - secho('Resetting up {}'.format(dest), fg='blue') + cprint('Resetting up {}'.format(dest), style='blue') setupCfg = None with open(setupPath, 'r') as f: @@ -187,7 +198,7 @@ def _repoReset(env, dest): setupCfg = setupCfg.get('reset', None) if setupCfg is None: - echo("No reset configuration file. Skipping.") + cprint("No reset configuration file. Skipping.") return cmds = [ l.split() for l in setupCfg ] @@ -195,9 +206,9 @@ def _repoReset(env, dest): # ensure that all commands exist missingCmds = [(i, cmd) for i, cmd in enumerate(cmds) if not sh.which(cmd[0])] if missingCmds: - secho('Some setup commands have not been found', fg='red') + cprint('Some setup commands have not been found', style='red') for i, cmd in missingCmds: - echo(' - {} (line {})'.format(cmd, i)) + cprint(' - {} (line {})'.format(cmd, i)) raiseError("Setup commands not found".format(dest)) @@ -208,14 +219,14 @@ def _repoReset(env, dest): # In red the failed one # In white the remaining commands for cmd in cmds: - secho('> '+' '.join(cmd), fg='cyan') + cprint('> '+' '.join(cmd), style='cyan') sh.Command(cmd[0])(*cmd[1:], _out=sys.stdout) # ------------------------------------------------------------------------------ def git(env, repo, branch, revision, dest): '''Add a git repository to the source area''' - echo('Adding git repository ' + style(repo, fg='blue')) + cprint('Adding git repository ' + style(repo, style='blue')) # Ensure that the destination direcotry doesn't exist # Maybe not necessary @@ -243,7 +254,7 @@ def git(env, repo, branch, revision, dest): ) # Multiple references elif len(lRemoteRefs) > 1: - echo(lRemoteRefs) + cprint(lRemoteRefs) raise click.ClickException( 'Found {} references matching \'{}\''.format(len(lRemoteRefs), branch) ) @@ -263,9 +274,9 @@ def git(env, repo, branch, revision, dest): ) # All good, go ahead with cloning - echo( + cprint( "{} {} resolved as reference {}".format( - lRefKind.capitalize(), style(branch, fg='blue'), lRefName + lRefKind.capitalize(), style(branch, style='blue'), lRefName ) ) @@ -281,11 +292,11 @@ def git(env, repo, branch, revision, dest): # option handling stage. if branch is not None: - echo('Checking out branch/tag ' + style(branch, fg='blue')) + cprint('Checking out branch/tag ' + style(branch, style='blue')) sh.git('checkout', branch, '-q', _out=sys.stdout, _cwd=lRepoLocalPath) elif revision is not None: - echo('Checking out revision ' + style(revision, fg='blue')) + cprint('Checking out revision ' + style(revision, style='blue')) try: sh.git('checkout', revision, '-q', _out=sys.stdout, _cwd=lRepoLocalPath) except Exception as err: @@ -293,14 +304,14 @@ def git(env, repo, branch, revision, dest): # did not alter the state of the cloned repo in any # way. (This appears to be the case from experience but no # hard reference could be found.) - secho("Failed to check out requested revision." \ - " Staying on default branch.", fg='red') + cprint("Failed to check out requested revision." \ + " Staying on default branch.", style='red') - secho( + cprint( 'Repository \'{}\' successfully cloned to:\n {}'.format( lRepoName, join(env.srcdir, lRepoName) ), - fg='green', + style='green', ) _repoInit(env, lRepoName) @@ -314,7 +325,7 @@ def svn(env, repo, dest, rev, dryrun, sparse): lRepoName = splitext(basename(lUrl.path))[0] if dest is None else dest # ------------------------------------------------------------------------- # Stop if the target directory already exists - echo('Adding svn repository ' + style(repo, fg='blue')) + cprint('Adding svn repository ' + style(repo, style='blue')) lRepoLocalPath = join(env.srcdir, lRepoName) @@ -335,11 +346,11 @@ def svn(env, repo, dest, rev, dryrun, sparse): # Do the checkout lCmd = ['svn'] + lArgs - echo('Executing ' + style(' '.join(lCmd), fg='blue')) + cprint('Executing ' + style(' '.join(lCmd), style='blue')) if not dryrun: sh.svn(*lArgs, _out=sys.stdout, _cwd=env.srcdir) else: - echo('Sparse checkout mode: ' + style(' '.join(sparse), fg='blue')) + cprint('Sparse checkout mode: ' + style(' '.join(sparse), style='blue')) # ---------------------------------------------------------------------- # Checkout an empty base folder lArgs = ['checkout', '--depth=empty', repo] @@ -352,7 +363,7 @@ def svn(env, repo, dest, rev, dryrun, sparse): lArgs += ['-r', str(rev)] lCmd = ['svn'] + lArgs - echo('Executing ' + style(' '.join(lCmd), fg='blue')) + cprint('Executing ' + style(' '.join(lCmd), style='blue')) if not dryrun: sh.svn(*lArgs, _out=sys.stdout, _cwd=env.srcdir) # ---------------------------------------------------------------------- @@ -366,13 +377,13 @@ def svn(env, repo, dest, rev, dryrun, sparse): # Recursively check out intermediate, empty folders for lPartial in lPartials: lArgs = ['up', '--depth=empty', lPartial] - echo('Executing ' + style(' '.join(['svn'] + lArgs), fg='blue')) + cprint('Executing ' + style(' '.join(['svn'] + lArgs), style='blue')) if not dryrun: sh.svn(*lArgs, _out=sys.stdout, _cwd=lRepoLocalPath) # Finally check out the target lArgs = ['up', '--set-depth=infinity', lPath] - echo('Executing ' + style(' '.join(['svn'] + lArgs), fg='blue')) + cprint('Executing ' + style(' '.join(['svn'] + lArgs), style='blue')) if not dryrun: sh.svn(*lArgs, _out=sys.stdout, _cwd=lRepoLocalPath) @@ -385,7 +396,7 @@ def svn(env, repo, dest, rev, dryrun, sparse): def tar(env, repo, dest, strip): '''Add a tarball-ed package to the source area''' - click.secho("Warning: Command 'untar' is still experimental", fg='yellow') + click.cprint("Warning: Command 'untar' is still experimental", style='yellow') lProtocols = ['file', 'http', 'https'] lExtensions = ['.tar', '.tar.gz', '.tgz'] @@ -422,11 +433,11 @@ def tar(env, repo, dest, strip): # ------------------------------------------------------------------------- # Stop if the target directory already exists - echo( + cprint( 'Adding tarball ' - + style(repo, fg='blue') + + style(repo, style='blue') + ' to ' - + style(lRepoName, fg='blue') + + style(lRepoName, style='blue') ) lRepoLocalPath = join(env.work.path, kSourceDir, lRepoName) @@ -460,11 +471,11 @@ def symlink(env, path): if exists(lRepoLocalPath): raise click.ClickException('Repository already exists \'%s\'' % lRepoLocalPath) - echo( + cprint( 'Adding symlink ' - + style(abspath(path), fg='blue') + + style(abspath(path), style='blue') + ' as ' - + style(lRepoName, fg='blue') + + style(lRepoName, style='blue') ) sh.ln('-s', abspath(path), _cwd=env.srcdir ) @@ -479,19 +490,20 @@ def srcs(env): def srcs_info(env): if not env.work.path: - secho('ERROR: No ipbb work area detected', fg='red') + cprint('ERROR: No ipbb work area detected', style='red') return - echo() - secho("Firmware Packages", fg='blue') + cprint() + cprint("Firmware Packages", style='blue') lSrcs = env.sources if not lSrcs: return - lSrcTable = Texttable(max_width=0) - lSrcTable.set_deco(Texttable.HEADER | Texttable.BORDER) - lSrcTable.set_chars(['-', '|', '+', '-']) - lSrcTable.header(['name', 'kind', 'version', 'hash']) + # lSrcTable = Texttable(max_width=0) + # lSrcTable.set_deco(Texttable.HEADER | Texttable.BORDER) + # lSrcTable.set_chars(['-', '|', '+', '-']) + # lSrcTable.header(['name', 'kind', 'version', 'hash']) + lSrcTable = Table('name', 'kind', 'version', 'hash') for lSrc in lSrcs: lSrcDir = join(env.srcdir, lSrc) @@ -564,8 +576,8 @@ def srcs_info(env): lHash = lSVNInfo['Revision'] - lSrcTable.add_row([lSrc, lKind, lHEADId, lHash]) - echo(lSrcTable.draw()) + lSrcTable.add_row(lSrc, lKind, lHEADId, lHash) + cprint(lSrcTable) # ------------------------------------------------------------------------------ @@ -574,13 +586,13 @@ def srcs_create_component(env, component): lCmpPath = lPathMaker.getPath(*component) if exists(lPathMaker.getPath(*component)): - secho("ERROR: Component '{}' already exists".format(lCmpPath), fg='red') + cprint("ERROR: Component '{}' already exists".format(lCmpPath), style='red') raise click.ClickException("Command aborted") for sd in ['src', 'include', 'iprepo', 'addrtab']: lPath = lPathMaker.getPath(*component, command=sd) mkdir(lPath) - secho("Folder {} created.".format(lPath), fg='cyan') + cprint("Folder {} created.".format(lPath), style='cyan') # ------------------------------------------------------------------------------ @@ -588,11 +600,11 @@ def srcs_run(env, pkg, cmd, args): if pkg: if pkg not in env.sources: - secho( + cprint( "ERROR: '{}' package not known.\nKnown packages:\n{}".format( pkg, '\n'.join((' * ' + s for s in env.sources)) ), - fg='red', + style='red', ) raise click.ClickException("Command failed") wd = join(env.srcdir, pkg) @@ -602,7 +614,7 @@ def srcs_run(env, pkg, cmd, args): try: lCmd = sh.Command(cmd) except sh.CommandNotFound as lExc: - secho("ERROR: Command '{}' not found in path".format(cmd), fg='red') + cprint("ERROR: Command '{}' not found in path".format(cmd), style='red') raise click.ClickException("Command aborted") try: From d71d23969f34684c776b014ff80dd6fc7481473c Mon Sep 17 00:00:00 2001 From: Alessandro Thea Date: Tue, 20 Oct 2020 14:25:44 +0200 Subject: [PATCH 04/11] Replacing more Texttable with rich --- src/ipbb/cmds/dep.py | 56 +++++++++++++++++++------------------ src/ipbb/cmds/formatters.py | 41 +++++++++++---------------- src/ipbb/cmds/proj.py | 2 -- 3 files changed, 45 insertions(+), 54 deletions(-) diff --git a/src/ipbb/cmds/dep.py b/src/ipbb/cmds/dep.py index 44016481..aaa81e60 100644 --- a/src/ipbb/cmds/dep.py +++ b/src/ipbb/cmds/dep.py @@ -21,11 +21,12 @@ isfile, isdir, ) +from ..console import cprint from ..tools.common import which, SmartOpen from .formatters import DepFormatter from ._utils import DirSentry, printDictTable, printAlienTable -from click import echo, secho, style, confirm -from texttable import Texttable +from rich.table import Table, Column +from rich.padding import Padding # ------------------------------------------------------------------------------ def dep(env, proj): @@ -97,24 +98,23 @@ def report(env, filters): lParser = env.depParser lDepFmt = DepFormatter(lParser) - secho('* Variables', fg='blue') + cprint('* Variables', style='blue') # printDictTable(lParser.vars, aHeader=False) printAlienTable(lParser.settings, aHeader=False) - echo() - secho('* Dep-tree commands', fg='blue') + cprint() + cprint('* Dep-tree commands', style='blue') lPrepend = re.compile('(^|\n)') for k in lParser.commands: - echo(' + {0} ({1})'.format(k, len(lParser.commands[k]))) + cprint(' + {0} ({1})'.format(k, len(lParser.commands[k]))) if not lParser.commands[k]: - echo() + cprint() continue - lCmdTable = Texttable(max_width=0) - lCmdTable.header(lCmdHeaders) - lCmdTable.set_deco(Texttable.HEADER | Texttable.BORDER) - lCmdTable.set_chars(['-', '|', '+', '-']) + lCmdTable = Table(*lCmdHeaders) + # lCmdTable.set_deco(Texttable.HEADER | Texttable.BORDER) + # lCmdTable.set_chars(['-', '|', '+', '-']) for lCmd in lParser.commands[k]: lRow = [ relpath(lCmd.filepath, env.srcdir), @@ -127,12 +127,13 @@ def report(env, filters): if lFilters and not all([rxp.match(lRow[i]) for i, rxp in lFilters]): continue - lCmdTable.add_row(lRow) + lCmdTable.add_row(*lRow) - echo(lPrepend.sub(r'\g<1> ', lCmdTable.draw())) - echo() + # cprint(lPrepend.sub(r'\g<1> ', lCmdTable.draw())) + cprint(Padding.indent(lCmdTable, 4)) + cprint() - secho('Resolved packages & components', fg='blue') + cprint('Resolved packages & components', style='blue') lString = '' @@ -142,36 +143,37 @@ def report(env, filters): lString += 'packages: ' + lDepFmt.drawPackages() + '\n' lString += 'components:\n' lString += lDepFmt.drawComponents() - echo(lString+'\n') + cprint(lString+'\n') if lParser.errors: - secho("Dep tree parsing error(s):", fg='red') - echo(lDepFmt.drawParsingErrors()) + cprint("Dep tree parsing error(s):", style='red') + cprint(lDepFmt.drawParsingErrors()) if lParser.unresolved: lString = '' if lParser.unresolvedPackages: - secho("Unresolved packages:", fg='red') - echo(lDepFmt.drawUnresolvedPackages()) - echo() + cprint("Unresolved packages:", style='red') + cprint(lDepFmt.drawUnresolvedPackages()) + cprint() # ------ lCNF = lParser.unresolvedComponents if lCNF: - secho("Unresolved components:", fg='red') - echo(lDepFmt.drawUnresolvedComponents()) - echo() + cprint("Unresolved components:", style='red') + cprint(lDepFmt.drawUnresolvedComponents()) + cprint() # ------ # ------ - echo(lString) + cprint(lString) if lParser.unresolvedFiles: - secho("Unresolved files:", fg='red') + cprint("Unresolved files:", style='red') - echo(lPrepend.sub(r'\g<1> ', lDepFmt.drawUnresolvedFiles())) + # cprint(lPrepend.sub(r'\g<1> ', lDepFmt.drawUnresolvedFiles())) + cprint(Padding.indent(lDepFmt.drawUnresolvedFiles(), 4)) # ------------------------------------------------------------------------------ diff --git a/src/ipbb/cmds/formatters.py b/src/ipbb/cmds/formatters.py index 3a0a6136..f742768a 100644 --- a/src/ipbb/cmds/formatters.py +++ b/src/ipbb/cmds/formatters.py @@ -91,16 +91,14 @@ def drawUnresolvedSummary(self): if not lParser.unresolved: return '' - lUnresolved = Texttable() - lUnresolved.add_row(["packages", "components", "paths"]) + lUnresolved = Table() + lUnresolved.add_row("packages", "components", "paths") lUnresolved.add_row( - [ - len(lParser.unresolvedPackages), - len(lParser.unresolvedComponents), - len(lParser.unresolvedPaths), - ] + str(len(lParser.unresolvedPackages)), + str(len(lParser.unresolvedComponents)), + str(len(lParser.unresolvedPaths)), ) - return lUnresolved.draw() + return lUnresolved def drawUnresolvedFiles(self): """ @@ -110,9 +108,8 @@ def drawUnresolvedFiles(self): if not lFNF: return "" - lFNFTable = Texttable(max_width=0) - lFNFTable.header(['path expression', 'package', 'component', 'included by']) - lFNFTable.set_deco(Texttable.HEADER | Texttable.BORDER) + lFNFTable = Table('path expression', 'package', 'component', 'included by') + # lFNFTable.set_deco(Texttable.HEADER | Texttable.BORDER) for pkg in sorted(lFNF): lCmps = lFNF[pkg] @@ -120,16 +117,14 @@ def drawUnresolvedFiles(self): lPathExps = lCmps[cmp] for pathexp in sorted(lPathExps): lFNFTable.add_row( - [ - relpath(pathexp, self.parser.rootdir), - pkg, - cmp, - '\n'.join( - [(relpath(src, self.parser.rootdir) if src != '__top__' else '(top)') for src in lPathExps[pathexp]] - ), - ] + relpath(pathexp, self.parser.rootdir), + pkg, + cmp, + '\n'.join( + [(relpath(src, self.parser.rootdir) if src != '__top__' else '(top)') for src in lPathExps[pathexp]] + ), ) - return lFNFTable.draw() + return lFNFTable def drawParsingErrors(self): """ @@ -141,18 +136,14 @@ def drawParsingErrors(self): lErrors = self.parser.errors - lErrTable = Texttable(max_width=0) - lErrTable.header(['dep file', 'line', 'error']) - lErrTable.set_deco(Texttable.HEADER | Texttable.BORDER) + lErrTable = Table('dep file', 'line', 'error') for lPkg, lCmp, lDepName, lDepPath, lLineNo, lLine, lErr in lErrors: lErrTable.add_row( - [ relpath(lDepPath, self.parser.rootdir)+':'+str(lLineNo), "'"+lLine+"'", str(lErr)+(': {}'.format(lErr.__cause__) if hasattr(lErr,'__cause__') else ''), - ] ) return lErrTable.draw() diff --git a/src/ipbb/cmds/proj.py b/src/ipbb/cmds/proj.py index 73fb6960..b4ca0f98 100644 --- a/src/ipbb/cmds/proj.py +++ b/src/ipbb/cmds/proj.py @@ -16,8 +16,6 @@ from rich.table import Table from os.path import join, split, exists, splitext, relpath, isdir, basename -# from click import echo, style, secho -# from texttable import Texttable # ------------------------------------------------------------------------------ def info(env): From b77d1cbbffce1e0f9f22867f5da1261bf4ed072e Mon Sep 17 00:00:00 2001 From: Alessandro Thea Date: Thu, 10 Dec 2020 01:02:05 +0100 Subject: [PATCH 05/11] make-project renamed generate project. --- src/ipbb/cmds/formatters.py | 6 +++--- src/ipbb/cmds/repo.py | 36 +++++++++++++----------------------- 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/src/ipbb/cmds/formatters.py b/src/ipbb/cmds/formatters.py index f742768a..bb25a3e9 100644 --- a/src/ipbb/cmds/formatters.py +++ b/src/ipbb/cmds/formatters.py @@ -78,7 +78,8 @@ def drawDeptreeCommandsSummary(self): # return lDepTable.draw() lCommandKinds = ('setup', 'src', 'hlssrc', 'util', 'addrtab', 'iprepo') - lDepTable = Table( *(Column(c, justify='center') for c in lCommandKinds) ) + # lDepTable = Table( *(Column(c, justify='center') for c in lCommandKinds) ) + lDepTable = Table( *lCommandKinds) lDepTable.add_row( *(str(len(self.parser.commands[k])) for k in lCommandKinds) ) return lDepTable @@ -91,8 +92,7 @@ def drawUnresolvedSummary(self): if not lParser.unresolved: return '' - lUnresolved = Table() - lUnresolved.add_row("packages", "components", "paths") + lUnresolved = Table("packages", "components", "paths") lUnresolved.add_row( str(len(lParser.unresolvedPackages)), str(len(lParser.unresolvedComponents)), diff --git a/src/ipbb/cmds/repo.py b/src/ipbb/cmds/repo.py index f419ec80..11e64658 100644 --- a/src/ipbb/cmds/repo.py +++ b/src/ipbb/cmds/repo.py @@ -226,7 +226,7 @@ def _repoReset(env, dest): def git(env, repo, branch, revision, dest): '''Add a git repository to the source area''' - cprint('Adding git repository ' + style(repo, style='blue')) + cprint('Adding git repository [blue]{}[/blue]'.format(repo)) # Ensure that the destination direcotry doesn't exist # Maybe not necessary @@ -275,8 +275,8 @@ def git(env, repo, branch, revision, dest): # All good, go ahead with cloning cprint( - "{} {} resolved as reference {}".format( - lRefKind.capitalize(), style(branch, style='blue'), lRefName + "{} [blue]{}[/blue] resolved as reference {}".format( + lRefKind.capitalize(), branch, lRefName ) ) @@ -292,11 +292,11 @@ def git(env, repo, branch, revision, dest): # option handling stage. if branch is not None: - cprint('Checking out branch/tag ' + style(branch, style='blue')) + cprint('Checking out branch/tag [blue]{}[/blue]'.format(branch)) sh.git('checkout', branch, '-q', _out=sys.stdout, _cwd=lRepoLocalPath) elif revision is not None: - cprint('Checking out revision ' + style(revision, style='blue')) + cprint('Checking out revision [blue]{}[/blue]'.format(revision)) try: sh.git('checkout', revision, '-q', _out=sys.stdout, _cwd=lRepoLocalPath) except Exception as err: @@ -325,7 +325,7 @@ def svn(env, repo, dest, rev, dryrun, sparse): lRepoName = splitext(basename(lUrl.path))[0] if dest is None else dest # ------------------------------------------------------------------------- # Stop if the target directory already exists - cprint('Adding svn repository ' + style(repo, style='blue')) + cprint('Adding svn repository [blue]{}[/blue'.format(repo)) lRepoLocalPath = join(env.srcdir, lRepoName) @@ -346,11 +346,11 @@ def svn(env, repo, dest, rev, dryrun, sparse): # Do the checkout lCmd = ['svn'] + lArgs - cprint('Executing ' + style(' '.join(lCmd), style='blue')) + cprint('Executing [blue]{}[/blue]'.format(' '.join(lCmd))) if not dryrun: sh.svn(*lArgs, _out=sys.stdout, _cwd=env.srcdir) else: - cprint('Sparse checkout mode: ' + style(' '.join(sparse), style='blue')) + cprint('Sparse checkout mode: [blue]{}[/blue]'.format(sparse)) # ---------------------------------------------------------------------- # Checkout an empty base folder lArgs = ['checkout', '--depth=empty', repo] @@ -363,7 +363,7 @@ def svn(env, repo, dest, rev, dryrun, sparse): lArgs += ['-r', str(rev)] lCmd = ['svn'] + lArgs - cprint('Executing ' + style(' '.join(lCmd), style='blue')) + cprint('Executing [blue]{}[/blue]'.format(' '.join(lCmd))) if not dryrun: sh.svn(*lArgs, _out=sys.stdout, _cwd=env.srcdir) # ---------------------------------------------------------------------- @@ -377,13 +377,13 @@ def svn(env, repo, dest, rev, dryrun, sparse): # Recursively check out intermediate, empty folders for lPartial in lPartials: lArgs = ['up', '--depth=empty', lPartial] - cprint('Executing ' + style(' '.join(['svn'] + lArgs), style='blue')) + cprint('Executing [blue]{}[/blue]'.format(' '.join(['svn'] + lArgs))) if not dryrun: sh.svn(*lArgs, _out=sys.stdout, _cwd=lRepoLocalPath) # Finally check out the target lArgs = ['up', '--set-depth=infinity', lPath] - cprint('Executing ' + style(' '.join(['svn'] + lArgs), style='blue')) + cprint('Executing [blue]{}[/blue]'.format(' '.join(['svn'] + lArgs))) if not dryrun: sh.svn(*lArgs, _out=sys.stdout, _cwd=lRepoLocalPath) @@ -434,10 +434,7 @@ def tar(env, repo, dest, strip): # ------------------------------------------------------------------------- # Stop if the target directory already exists cprint( - 'Adding tarball ' - + style(repo, style='blue') - + ' to ' - + style(lRepoName, style='blue') + 'Adding tarball [blue]{}[/blue] to [blue]{}[/blue]'.format(repo, lRepoName) ) lRepoLocalPath = join(env.work.path, kSourceDir, lRepoName) @@ -472,10 +469,7 @@ def symlink(env, path): raise click.ClickException('Repository already exists \'%s\'' % lRepoLocalPath) cprint( - 'Adding symlink ' - + style(abspath(path), style='blue') - + ' as ' - + style(lRepoName, style='blue') + 'Adding symlink [blue]{}[/blue] to [blue]{}[/blue]'.format(path, lRepoName) ) sh.ln('-s', abspath(path), _cwd=env.srcdir ) @@ -499,10 +493,6 @@ def srcs_info(env): if not lSrcs: return - # lSrcTable = Texttable(max_width=0) - # lSrcTable.set_deco(Texttable.HEADER | Texttable.BORDER) - # lSrcTable.set_chars(['-', '|', '+', '-']) - # lSrcTable.header(['name', 'kind', 'version', 'hash']) lSrcTable = Table('name', 'kind', 'version', 'hash') for lSrc in lSrcs: lSrcDir = join(env.srcdir, lSrc) From a97297e2d0ad825a39bd4cb10a58fac1fbb2d91e Mon Sep 17 00:00:00 2001 From: Alessandro Thea Date: Thu, 10 Dec 2020 10:37:31 +0100 Subject: [PATCH 06/11] Adding protection against markup-like text fragments in exceptions --- src/ipbb/cmds/_utils.py | 4 ++-- src/ipbb/scripts/builder.py | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ipbb/cmds/_utils.py b/src/ipbb/cmds/_utils.py index 4f8d218a..764b5652 100644 --- a/src/ipbb/cmds/_utils.py +++ b/src/ipbb/cmds/_utils.py @@ -149,8 +149,8 @@ def ensureNoMissingFiles(aCurrentProj, aDepFileParser): # ------------------------------------------------------------------------------ def echoVivadoConsoleError( aExc ): cprint("Vivado error/critical warnings detected", style='red') - cprint("\n".join(aExc.errors), style='red') - cprint("\n".join(aExc.criticalWarns), style='yellow') + cprint("\n".join(aExc.errors), markup=False, style='red') + cprint("\n".join(aExc.criticalWarns), markup=False, style='yellow') # ------------------------------------------------------------------------------ diff --git a/src/ipbb/scripts/builder.py b/src/ipbb/scripts/builder.py index 1d0921bb..cbc8179e 100755 --- a/src/ipbb/scripts/builder.py +++ b/src/ipbb/scripts/builder.py @@ -5,8 +5,10 @@ import ipbb import sys import traceback +import rich from io import StringIO, BytesIO + from ..cmds import Environment from ..cmds.formatters import DepFormatter from ..console import cprint @@ -164,11 +166,12 @@ def main(): lFirstFrame[2], lFirstFrame[3], ), + markup=False, style='red', ) if obj.printExceptionStack: - lExc = (BytesIO() if (version_info[0] <= 2) else StringIO()) + lExc = StringIO() traceback.print_exc(file=lExc) cprint("Exception in user code:") cprint('-' * 60) From 3e79898799bca02ad020f80e94d3d352cdaaeb2c Mon Sep 17 00:00:00 2001 From: Alessandro Thea Date: Thu, 4 Mar 2021 17:25:07 +0100 Subject: [PATCH 07/11] Post-rebase bugfix --- src/ipbb/cmds/formatters.py | 2 -- src/ipbb/cmds/proj.py | 4 ++-- src/ipbb/cmds/repo.py | 12 ++++++------ src/ipbb/utils.py | 4 ++-- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/ipbb/cmds/formatters.py b/src/ipbb/cmds/formatters.py index 419983a6..9ef01a79 100644 --- a/src/ipbb/cmds/formatters.py +++ b/src/ipbb/cmds/formatters.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - from rich.table import Table, Column from os.path import ( join, diff --git a/src/ipbb/cmds/proj.py b/src/ipbb/cmds/proj.py index fb3c9e35..78a97b1e 100644 --- a/src/ipbb/cmds/proj.py +++ b/src/ipbb/cmds/proj.py @@ -10,8 +10,8 @@ from ..console import cprint from ..tools.common import SmartOpen from ..defaults import kProjAreaFile, kProjDir -from . import ProjectInfo -from ._utils import DirSentry, raiseError, validateComponent, findFirstParentDir +from ..context import ProjectInfo +from ..utils import DirSentry, raiseError, validateComponent, findFirstParentDir from ..depparser import depfiletypes, Pathmaker from rich.table import Table diff --git a/src/ipbb/cmds/repo.py b/src/ipbb/cmds/repo.py index d79d83d7..845ebc62 100644 --- a/src/ipbb/cmds/repo.py +++ b/src/ipbb/cmds/repo.py @@ -56,18 +56,18 @@ def info(ictx, verbose): cprint() - lEnvTable = Table('name', 'path', title='ipbb environment', title_style='blue', show_header=False) + lEnvTable = Table('name', 'path', title='ipbb context', title_style='blue', show_header=False) lEnvTable.add_row("Work path", ictx.work.path) if ictx.currentproj.path: lEnvTable.add_row("Project path", ictx.currentproj.path) cprint(lEnvTable) - if not env.currentproj.path: + if not ictx.currentproj.path: cprint() - srcs_info(env) + srcs_info(ictx) cprint() - proj_info(env) + proj_info(ictx) return cprint() @@ -82,9 +82,9 @@ def info(ictx, verbose): cprint() - if env.currentproj.usersettings: + if ictx.currentproj.usersettings: cprint("User settings", style='blue') - t = formatDictTable(env.currentproj.usersettings, aHeader=False) + t = formatDictTable(ictx.currentproj.usersettings, aHeader=False) t.title = "User settings" t.title_style = 'blue' cprint(t) diff --git a/src/ipbb/utils.py b/src/ipbb/utils.py index 764b5652..255696df 100644 --- a/src/ipbb/utils.py +++ b/src/ipbb/utils.py @@ -9,8 +9,8 @@ from rich.prompt import Confirm from rich.table import Table -from ..tools.alien import AlienBranch -from ..console import cprint +from .tools.alien import AlienBranch +from .console import cprint # ------------------------------------------------------------------------------ From 7dd880561abfa6ee6c99180a1ec936c82ac1feb5 Mon Sep 17 00:00:00 2001 From: Alessandro Thea Date: Thu, 4 Mar 2021 17:26:06 +0100 Subject: [PATCH 08/11] more env -> ictx --- src/ipbb/cli/_utils.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/ipbb/cli/_utils.py b/src/ipbb/cli/_utils.py index 6298a6b5..76f2261e 100644 --- a/src/ipbb/cli/_utils.py +++ b/src/ipbb/cli/_utils.py @@ -16,13 +16,13 @@ def completeDepFileImpl(ctx, args, incomplete): # print (ctx.command.params) if ctx.params.get(cmp_argname, None) is None: return [] - env = Context() + ictx = Context() # nothing to complete if not in an ipbb area - if env.work.path is None: + if ictx.work.path is None: return [] lPkg, lCmp = ctx.params[cmp_argname] - basepath = env.pathMaker.getPath(lPkg, lCmp, 'include') + basepath = ictx.pathMaker.getPath(lPkg, lCmp, 'include') if not exists(basepath): return [] @@ -42,43 +42,43 @@ def completeDepFileImpl(ctx, args, incomplete): # ------------------------------------------------------------------------------ def completeProject(ctx, args, incomplete): - env = Context() + ictx = Context() # nothing to complete if not in an ipbb area - if env.work.path is None: + if ictx.work.path is None: return [] - return [proj for proj in env.projects if incomplete in proj] + return [proj for proj in ictx.projects if incomplete in proj] # ------------------------------------------------------------------------------ def completeSrcPackage(ctx, args, incomplete): - env = Context() + ictx = Context() # nothing to complete if not in an ipbb area - if env.work.path is None: + if ictx.work.path is None: return [] - return [pkg for pkg in env.sources if incomplete in pkg] + return [pkg for pkg in ictx.sources if incomplete in pkg] # ------------------------------------------------------------------------------ def completeComponent(ctx, args, incomplete): - env = Context() + ictx = Context() # nothing to complete if not in an ipbb area - if env.work.path is None: + if ictx.work.path is None: return [] lPkgSeps = incomplete.count(':') if lPkgSeps > 1: return [] elif lPkgSeps == 0: - return [ (p + ':') for p in env.sources if p.startswith(incomplete) ] - # pkgs = [p for p in env.sources if p.startswith(incomplete) ] + return [ (p + ':') for p in ictx.sources if p.startswith(incomplete) ] + # pkgs = [p for p in ictx.sources if p.startswith(incomplete) ] # comps = [] # for p in pkgs: - # comps += _findComponentsInPackage(env, p) + # comps += _findComponentsInPackage(ictx, p) # return comps @@ -86,23 +86,23 @@ def completeComponent(ctx, args, incomplete): lPkg, incomp_cmp = incomplete.split(':') # bail out if package is misspelled - if lPkg not in env.sources: + if lPkg not in ictx.sources: return [] # Scan the package for matches with the partial component path - return _findComponentsInPackage(env, lPkg, incomp_cmp) + return _findComponentsInPackage(ictx, lPkg, incomp_cmp) return [] # ------------------------------------------------------------------------------ -def _findComponentsInPackage(env, pkg, incomp_cmp='', exclude=['.git', '.svn'], match_subdir='firmware'): +def _findComponentsInPackage(ictx, pkg, incomp_cmp='', exclude=['.git', '.svn'], match_subdir='firmware'): """ Helper function to find components in a package, starting from an incomplete component path """ lMatchingComps = [] - lPkgPath = join(env.srcdir, pkg) + lPkgPath = join(ictx.srcdir, pkg) # Resolve the list of paths to lSearchPaths = [] From 140858243a6b8b68646e603fde3079b9c643e066 Mon Sep 17 00:00:00 2001 From: Alessandro Thea Date: Thu, 4 Mar 2021 20:05:16 +0100 Subject: [PATCH 09/11] Post-merge fixes --- src/ipbb/cmds/repo.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/ipbb/cmds/repo.py b/src/ipbb/cmds/repo.py index 845ebc62..29e42a7e 100644 --- a/src/ipbb/cmds/repo.py +++ b/src/ipbb/cmds/repo.py @@ -534,6 +534,19 @@ def _svn_info(): if lLine ) } + + lHEADId = lSVNInfo['URL'].replace(lSVNInfo['Repository Root'] + '/', '') + + lSVNStatus = sh.svn('status', '-q') + if len(lSVNStatus): + lHEADId += '*' + + lHash = lSVNInfo['Revision'] + + return lHEADId, lHash + +# ------------------------------------------------------------------------------ +def srcs_info(ictx): if not ictx.work.path: cprint('ERROR: No ipbb work area detected', style='red') @@ -559,11 +572,11 @@ def _svn_info(): try: sh.git('rev-parse', '--git-dir') except sh.ErrorReturnCode_128: - lSrcTable.add_row([lSrc, lKind+' (broken)', '(unknown)', None]) + lSrcTable.add_row(lSrc, lKind+' (broken)', '(unknown)', None) continue lHEADId, lHash = _git_info() - lSrcTable.add_row([lSrc, lKind, lHEADId, lHash]) + lSrcTable.add_row(lSrc, lKind, lHEADId, lHash) lSubmods = sh.git('submodule').strip() if not lSubmods: @@ -580,9 +593,9 @@ def _svn_info(): lKind = 'svn' lHEADId, lHash = _svn_info() - lSrcTable.add_row([lSrc, lKind, lHEADId, lHash]) + lSrcTable.add_row(lSrc, lKind, lHEADId, lHash) else: - lSrcTable.add_row([lSrc, lKind, lHEADId, lHash]) + lSrcTable.add_row(lSrc, lKind, lHEADId, lHash) lSrcTable.add_row(lSrc, lKind, lHEADId, lHash) From 15d405251c046e18d22216109ef4fa67a6072e8d Mon Sep 17 00:00:00 2001 From: Alessandro Thea Date: Sat, 20 Mar 2021 01:27:33 +0100 Subject: [PATCH 10/11] import fix --- src/ipbb/scripts/builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ipbb/scripts/builder.py b/src/ipbb/scripts/builder.py index 1882cd0d..ae01a0cd 100755 --- a/src/ipbb/scripts/builder.py +++ b/src/ipbb/scripts/builder.py @@ -11,7 +11,7 @@ from ..context import Context -from ..cmds.formatters import DepFormatter +from ..depparser import DepFormatter from ..console import cprint from .._version import __version__ From e14794ae470217f8095c6742aac2535d1a3c5923 Mon Sep 17 00:00:00 2001 From: Alessandro Thea Date: Sat, 20 Mar 2021 15:33:02 +0100 Subject: [PATCH 11/11] Fixed generate-ipbb-repo test script More work required, at least it runs now --- src/ipbb/depparser/_formatters.py | 32 +++++++++++++------ tests/scripts/generate-ipbb-repo.py | 48 +++++++++++++---------------- 2 files changed, 43 insertions(+), 37 deletions(-) diff --git a/src/ipbb/depparser/_formatters.py b/src/ipbb/depparser/_formatters.py index 848493c7..f7f258bb 100644 --- a/src/ipbb/depparser/_formatters.py +++ b/src/ipbb/depparser/_formatters.py @@ -143,21 +143,33 @@ def drawParsingErrors(self): str(lErr)+(': {}'.format(lErr.__cause__) if hasattr(lErr,'__cause__') else ''), ) - return lErrTable.draw() + return lErrTable # ----------------------------------------------------------------------------- def drawSummary(self): - lOutTxt = '' - lOutTxt += self.drawDeptreeCommandsSummary() + grid = Table.grid(expand=True) + grid.add_column() + grid.add_row("[bold]Groups[/]") + grid.add_row(self.drawDeptreeCommandsSummary()) + grid.add_row("") + grid.add_row("[bold]Packages[/]") + grid.add_row(self.drawPackages()) + grid.add_row("") + if self.parser.unresolved: + grid.add_row("[bold]Unresolved[/]") + grid.add_row(self.drawUnresolvedSummary()) - lOutTxt += '\n' - lOutTxt += self.drawPackages() + # Switch to using tables + # lOutTxt = '' + # lOutTxt += self.drawDeptreeCommandsSummary() - if self.parser.unresolved: - lOutTxt += '\n' - lOutTxt += self.drawUnresolvedSummary() - return lOutTxt + # lOutTxt += '\n' + # lOutTxt += self.drawPackages() + + # if self.parser.unresolved: + # lOutTxt += self.drawUnresolvedSummary() + # return lOutTxt - return lOutTxt + return grid # ----------------------------------------------------------------------------- \ No newline at end of file diff --git a/tests/scripts/generate-ipbb-repo.py b/tests/scripts/generate-ipbb-repo.py index 9b14ace2..0e72018d 100755 --- a/tests/scripts/generate-ipbb-repo.py +++ b/tests/scripts/generate-ipbb-repo.py @@ -5,11 +5,14 @@ import yaml import pprint from click import echo, secho +from rich.panel import Panel +from rich.text import Text from os.path import exists, dirname, join, basename, splitext from os import mkdir, makedirs from shutil import rmtree from ipbb.depparser import DepFileParser, DepFormatter from ipbb.depparser import Pathmaker +from ipbb.console import cprint, console CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) @@ -18,9 +21,11 @@ @click.argument('repofile', type=click.Path(exists=True)) @click.argument('dest', type=click.Path()) def cli(repofile, dest): + with open(repofile, 'r') as f: repocfg = yaml.safe_load(f) - pprint.pprint(repocfg) + cprint(Panel.fit("Repo config")) + cprint(repocfg) reponame = repocfg.get('name', splitext(basename(repofile))) repopath = join(dest, reponame) @@ -41,45 +46,34 @@ def cli(repofile, dest): pm = Pathmaker(dest) for t in repocfg['top']: - print('++++++++++++++++++++++++ Parsing',t, '+++++++++') + cprint("Parsing", t) dp = DepFileParser('vivado', pm, {}, 0) # import ipdb # ipdb.set_trace() dp.parse(reponame, t['cmp'], t['file']) - print('\n\n\n') - print('-'*80) - print(' Summary ', t['file']) - print('-'*80) - print(">>> Commands") - pprint.pprint(dp.commands) - print(">>> Libs") - pprint.pprint(dp.libs) - print(">>> Errors") - pprint.pprint(dp.errors) - print(">>> Lost files") - pprint.pprint(dp.unresolved) + cprint('\n') + cprint('-'*80) + cprint(' Summary ', t['file']) + cprint('-'*80) + cprint(">>> Commands") + cprint(dp.commands) + cprint(">>> Libs") + cprint(dp.libs) + cprint(">>> Errors") + cprint(dp.errors) + cprint(">>> Lost files") + cprint(dp.unresolved) df = DepFormatter(dp) - print(df.drawSummary()) + cprint(Panel.fit(df.drawSummary())) def main(): try: cli() except Exception as e: - hline = '-' * 80 - echo() - secho(hline, fg='red') - secho("FATAL ERROR: Caught '" + type(e).__name__ + "' exception:", fg='red') - secho(e, fg='red') - secho(hline, fg='red') - import StringIO - - lTrace = StringIO.StringIO() - traceback.print_exc(file=lTrace) - print(lTrace.getvalue()) - # Do something with lTrace + console.print_exception() raise SystemExit(-1)