Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/add-interactive-stack-trace' int…
Browse files Browse the repository at this point in the history
…o add-interactive-stack-trace
  • Loading branch information
Rocky14683 committed Jun 11, 2024
2 parents 5a15963 + 30f83ab commit afcd1e7
Show file tree
Hide file tree
Showing 18 changed files with 435 additions and 82 deletions.
3 changes: 2 additions & 1 deletion pip_version
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
3.4.3
3.5.3

2 changes: 1 addition & 1 deletion pros.spec
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ a = Analysis(
['pros/cli/main.py'],
pathex=[],
binaries=[],
datas=[],
datas=[('pros/autocomplete/*', 'pros/autocomplete')],
hiddenimports=[],
hookspath=[],
hooksconfig={},
Expand Down
26 changes: 26 additions & 0 deletions pros/autocomplete/pros-complete.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
_pros_completion() {
local IFS=$'\n'
local response
response=$(env COMP_WORDS="${COMP_WORDS[*]}" COMP_CWORD=$COMP_CWORD _PROS_COMPLETE=bash_complete $1)
for completion in $response; do
IFS=',' read type value <<<"$completion"
if [[ $type == 'dir' ]]; then
COMPREPLY=()
compopt -o dirnames
elif [[ $type == 'file' ]]; then
COMPREPLY=()
compopt -o default
elif [[ $type == 'plain' ]]; then
COMPREPLY+=($value)
fi
done
return 0
}
_pros_completion_setup() {
if [[ ${BASH_VERSINFO[0]} -ge 4 ]]; then
complete -o nosort -F _pros_completion pros
else
complete -F _pros_completion pros
fi
}
_pros_completion_setup
45 changes: 45 additions & 0 deletions pros/autocomplete/pros-complete.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Modified from https://github.com/StephLin/click-pwsh/blob/main/click_pwsh/shell_completion.py#L11
Register-ArgumentCompleter -Native -CommandName pros -ScriptBlock {
param($wordToComplete, $commandAst, $cursorPosition)
$env:COMP_WORDS = $commandAst
$env:COMP_WORDS = $env:COMP_WORDS.replace('\\', '/')
$incompleteCommand = $commandAst.ToString()
$myCursorPosition = $cursorPosition
if ($myCursorPosition -gt $incompleteCommand.Length) {
$myCursorPosition = $incompleteCommand.Length
}
$env:COMP_CWORD = @($incompleteCommand.substring(0, $myCursorPosition).Split(" ") | Where-Object { $_ -ne "" }).Length
if ( $wordToComplete.Length -gt 0) { $env:COMP_CWORD -= 1 }
$env:_PROS_COMPLETE = "powershell_complete"
pros | ForEach-Object {
$type, $value, $help = $_.Split(",", 3)
if ( ($type -eq "plain") -and ![string]::IsNullOrEmpty($value) ) {
[System.Management.Automation.CompletionResult]::new($value, $value, "ParameterValue", $value)
}
elseif ( ($type -eq "file") -or ($type -eq "dir") ) {
if ([string]::IsNullOrEmpty($wordToComplete)) {
$dir = "./"
}
else {
$dir = $wordToComplete.replace('\\', '/')
}
if ( (Test-Path -Path $dir) -and ((Get-Item $dir) -is [System.IO.DirectoryInfo]) ) {
[System.Management.Automation.CompletionResult]::new($dir, $dir, "ParameterValue", $dir)
}
Get-ChildItem -Path $dir | Resolve-Path -Relative | ForEach-Object {
$path = $_.ToString().replace('\\', '/').replace('Microsoft.PowerShell.Core/FileSystem::', '')
$isDir = $false
if ((Get-Item $path) -is [System.IO.DirectoryInfo]) {
$path = $path + "/"
$isDir = $true
}
if ( ($type -eq "file") -or ( ($type -eq "dir") -and $isDir ) ) {
[System.Management.Automation.CompletionResult]::new($path, $path, "ParameterValue", $path)
}
}
}
}
$env:COMP_WORDS = $null | Out-Null
$env:COMP_CWORD = $null | Out-Null
$env:_PROS_COMPLETE = $null | Out-Null
}
31 changes: 31 additions & 0 deletions pros/autocomplete/pros-complete.zsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
_pros_completion() {
local -a completions
local -a completions_with_descriptions
local -a response
(( ! $+commands[pros] )) && return 1
response=("${(@f)$(env COMP_WORDS="${words[*]}" COMP_CWORD=$((CURRENT-1)) _PROS_COMPLETE=zsh_complete pros)}")
for type key descr in ${response}; do
if [[ "$type" == "plain" ]]; then
if [[ "$descr" == "_" ]]; then
completions+=("$key")
else
completions_with_descriptions+=("$key":"$descr")
fi
elif [[ "$type" == "dir" ]]; then
_path_files -/
elif [[ "$type" == "file" ]]; then
_path_files -f
fi
done
if [ -n "$completions_with_descriptions" ]; then
_describe -V unsorted completions_with_descriptions -U
fi
if [ -n "$completions" ]; then
compadd -U -V unsorted -a completions
fi
}
if [[ $zsh_eval_context[-1] == loadautofunc ]]; then
_pros_completion "$@"
else
compdef _pros_completion pros
fi
14 changes: 14 additions & 0 deletions pros/autocomplete/pros.fish
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
function _pros_completion;
set -l response (env _PROS_COMPLETE=fish_complete COMP_WORDS=(commandline -cp) COMP_CWORD=(commandline -t) pros);
for completion in $response;
set -l metadata (string split "," $completion);
if test $metadata[1] = "dir";
__fish_complete_directories $metadata[2];
else if test $metadata[1] = "file";
__fish_complete_path $metadata[2];
else if test $metadata[1] = "plain";
echo $metadata[2];
end;
end;
end;
complete --no-files --command pros --arguments "(_pros_completion)";
10 changes: 10 additions & 0 deletions pros/cli/build.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import ctypes
import sys
from typing import *

import click
Expand All @@ -24,6 +26,10 @@ def make(project: c.Project, build_args):
analytics.send("make")
exit_code = project.compile(build_args)
if exit_code != 0:
if sys.platform == 'win32':
kernel32 = ctypes.windll.kernel32
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)

logger(__name__).error(f'Failed to make project: Exit Code {exit_code}', extra={'sentry': False})
raise click.ClickException('Failed to build')
return exit_code
Expand Down Expand Up @@ -71,6 +77,10 @@ def build_compile_commands(project: c.Project, suppress_output: bool, compile_co
exit_code = project.make_scan_build(build_args, cdb_file=compile_commands, suppress_output=suppress_output,
sandbox=sandbox)
if exit_code != 0:
if sys.platform == 'win32':
kernel32 = ctypes.windll.kernel32
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)

logger(__name__).error(f'Failed to make project: Exit Code {exit_code}', extra={'sentry': False})
raise click.ClickException('Failed to build')
return exit_code
16 changes: 10 additions & 6 deletions pros/cli/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def callback(ctx: click.Context, param: click.Parameter, value: bool):
add_tag('no-sentry',value)
if value:
pros.common.sentry.disable_prompt()
decorator = click.option('--no-sentry', expose_value=False, is_flag=True, default=False, is_eager=True,
decorator = click.option('--no-sentry', expose_value=False, is_flag=True, default=True, is_eager=True,
help="Disable sentry reporting prompt.", callback=callback, cls=PROSOption, hidden=True)(f)
decorator.__name__ = f.__name__
return decorator
Expand Down Expand Up @@ -191,10 +191,13 @@ def callback(ctx: click.Context, param: click.Parameter, value: str):
if project_path is None:
if allow_none:
return None
else:
elif required:
raise click.UsageError(f'{os.path.abspath(value or ".")} is not inside a PROS project. '
f'Execute this command from within a PROS project or specify it '
f'with --project project/path')
else:
return None

return c.Project(project_path)

def wrapper(f: Union[click.Command, Callable]):
Expand Down Expand Up @@ -253,11 +256,12 @@ def resolve_v5_port(port: Optional[str], type: str, quiet: bool = False) -> Tupl
return None, False
if len(ports) > 1:
if not quiet:
port = click.prompt('Multiple {} ports were found. Please choose one: [{}]'
.format('v5', '|'.join([p.device for p in ports])),
default=ports[0].device,
brain_id = click.prompt('Multiple {} Brains were found. Please choose one to upload the program: [{}]'
.format('v5', ' | '.join([p.product.split(' ')[-1] for p in ports])),
default=ports[0].product.split(' ')[-1],
show_default=False,
type=click.Choice([p.device for p in ports]))
type=click.Choice([p.description.split(' ')[-1] for p in ports]))
port = [p.device for p in ports if p.description.split(' ')[-1] == brain_id][0]
assert port in [p.device for p in ports]
else:
return None, False
Expand Down
48 changes: 36 additions & 12 deletions pros/cli/conductor.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ def fetch(query: c.BaseTemplate):
else:
if template_file:
logger(__name__).debug(f'Template file exists but is not a valid template: {template_file}')
else:
logger(__name__).error(f'Template not found: {query.name}')
return -1
template = c.Conductor().resolve_template(query, allow_offline=False)
logger(__name__).debug(f'Template from resolved query: {template}')
if template is None:
Expand Down Expand Up @@ -91,7 +94,7 @@ def fetch(query: c.BaseTemplate):
help="Force apply the template, disregarding if the template is already installed.")
@click.option('--remove-empty-dirs/--no-remove-empty-dirs', 'remove_empty_directories', is_flag=True, default=True,
help='Remove empty directories when removing files')
@click.option('--early-access/--disable-early-access', '--early/--disable-early', '-ea/-dea', 'early_access', '--beta/--disable-beta', default=None,
@click.option('--early-access/--no-early-access', '--early/--no-early', '-ea/-nea', 'early_access', '--beta/--no-beta', default=None,
help='Create a project using the PROS 4 kernel')
@project_option()
@template_query(required=True)
Expand Down Expand Up @@ -142,7 +145,7 @@ def install(ctx: click.Context, **kwargs):
help="Force apply the template, disregarding if the template is already installed.")
@click.option('--remove-empty-dirs/--no-remove-empty-dirs', 'remove_empty_directories', is_flag=True, default=True,
help='Remove empty directories when removing files')
@click.option('--early-access/--disable-early-access', '--early/--disable-early', '-ea/-dea', 'early_access', '--beta/--disable-beta', default=None,
@click.option('--early-access/--no-early-access', '--early/--no-early', '-ea/-nea', 'early_access', '--beta/--no-beta', default=None,
help='Create a project using the PROS 4 kernel')
@project_option()
@template_query(required=False)
Expand All @@ -156,7 +159,7 @@ def upgrade(ctx: click.Context, project: c.Project, query: c.BaseTemplate, **kwa
"""
analytics.send("upgrade-project")
if not query.name:
for template in project.templates.keys():
for template in tuple(project.templates.keys()):
click.secho(f'Upgrading {template}', color='yellow')
q = c.BaseTemplate.create_query(name=template, target=project.target,
supported_kernels=project.templates['kernel'].version)
Expand Down Expand Up @@ -204,7 +207,7 @@ def uninstall_template(project: c.Project, query: c.BaseTemplate, remove_user: b
help='Compile the project after creation')
@click.option('--build-cache', is_flag=True, default=None, show_default=False,
help='Build compile commands cache after creation. Overrides --compile-after if both are specified.')
@click.option('--early-access/--disable-early-access', '--early/--disable-early', '-ea/-dea', 'early_access', '--beta/--disable-beta', default=None,
@click.option('--early-access/--no-early-access', '--early/--no-early', '-ea/-nea', 'early_access', '--beta/--no-beta', default=None,
help='Create a project using the PROS 4 kernel')
@click.pass_context
@default_options
Expand Down Expand Up @@ -248,7 +251,7 @@ def new_project(ctx: click.Context, path: str, target: str, version: str,


@conductor.command('query-templates',
aliases=['search-templates', 'ls-templates', 'lstemplates', 'querytemplates', 'searchtemplates'],
aliases=['search-templates', 'ls-templates', 'lstemplates', 'querytemplates', 'searchtemplates', 'q'],
context_settings={'ignore_unknown_options': True})
@click.option('--allow-offline/--no-offline', 'allow_offline', default=True, show_default=True,
help='(Dis)allow offline templates in the listing')
Expand All @@ -258,12 +261,13 @@ def new_project(ctx: click.Context, path: str, target: str, version: str,
help='Force update all remote depots, ignoring automatic update checks')
@click.option('--limit', type=int, default=15,
help='The maximum number of displayed results for each library')
@click.option('--early-access/--disable-early-access', '--early/--disable-early', '-ea/-dea', 'early_access', '--beta/--disable-beta', default=None,
@click.option('--early-access/--no-early-access', '--early/--no-early', '-ea/-nea', 'early_access', '--beta/--no-beta', default=None,
help='View a list of early access templates')
@template_query(required=False)
@project_option(required=False)
@click.pass_context
@default_options
def query_templates(ctx, query: c.BaseTemplate, allow_offline: bool, allow_online: bool, force_refresh: bool,
def query_templates(ctx, project: Optional[c.Project], query: c.BaseTemplate, allow_offline: bool, allow_online: bool, force_refresh: bool,
limit: int, early_access: bool):
"""
Query local and remote templates based on a spec
Expand All @@ -273,12 +277,10 @@ def query_templates(ctx, query: c.BaseTemplate, allow_offline: bool, allow_onlin
analytics.send("query-templates")
if limit < 0:
limit = 15
if early_access is None and project is not None:
early_access = project.use_early_access
templates = c.Conductor().resolve_templates(query, allow_offline=allow_offline, allow_online=allow_online,
force_refresh=force_refresh, early_access=early_access)
if early_access:
templates += c.Conductor().resolve_templates(query, allow_offline=allow_offline, allow_online=allow_online,
force_refresh=force_refresh, early_access=False)

render_templates = {}
for template in templates:
key = (template.identifier, template.origin)
Expand Down Expand Up @@ -368,4 +370,26 @@ def query_depots(url: bool):
_conductor = c.Conductor()
ui.echo(f"Available Depots{' (Add --url for the url)' if not url else ''}:\n")
ui.echo('\n'.join(_conductor.query_depots(url))+"\n")


@conductor.command('reset')
@click.option('--force', is_flag=True, default=False, help='Force reset')
@default_options
def reset(force: bool):
"""
Reset conductor.pros
Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
"""

if not force:
if not ui.confirm("This will remove all depots and templates. You will be unable to create a new PROS project if you do not have internet connection. Are you sure you want to continue?"):
ui.echo("Aborting")
return

# Delete conductor.pros
file = os.path.join(click.get_app_dir('PROS'), 'conductor.pros')
if os.path.exists(file):
os.remove(file)

ui.echo("Conductor was reset")

21 changes: 20 additions & 1 deletion pros/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import pros.cli.misc_commands
import pros.cli.interactive
import pros.cli.user_script
import pros.conductor as c

if sys.platform == 'win32':
kernel32 = ctypes.windll.kernel32
Expand Down Expand Up @@ -99,7 +100,23 @@ def use_analytics(ctx: click.Context, param, value):
ctx.exit(0)
ctx.ensure_object(dict)
analytics.set_use(touse)
ui.echo('Analytics set to : {}'.format(analytics.useAnalytics))
ui.echo(f'Analytics usage set to: {analytics.useAnalytics}')
ctx.exit(0)

def use_early_access(ctx: click.Context, param, value):
if value is None:
return
conductor = c.Conductor()
value = str(value).lower()
if value.startswith("t") or value in ["1", "yes", "y"]:
conductor.use_early_access = True
elif value.startswith("f") or value in ["0", "no", "n"]:
conductor.use_early_access = False
else:
ui.echo('Invalid argument provided for \'--use-early-access\'. Try \'--use-early-access=False\' or \'--use-early-access=True\'')
ctx.exit(0)
conductor.save()
ui.echo(f'Early access set to: {conductor.use_early_access}')
ctx.exit(0)


Expand All @@ -112,6 +129,8 @@ def use_analytics(ctx: click.Context, param, value):
callback=version)
@click.option('--use-analytics', help='Set analytics usage (True/False).', type=str, expose_value=False,
is_eager=True, default=None, callback=use_analytics)
@click.option('--use-early-access', type=str, expose_value=False, is_eager=True, default=None,
help='Create projects with PROS 4 kernel by default', callback=use_early_access)
def cli(ctx):
pros.common.sentry.register()
ctx.call_on_close(after_command)
Expand Down
Loading

0 comments on commit afcd1e7

Please sign in to comment.