예제 #1
0
    def project_changed(self, new_project: ExistingProjectParameter):
        try:
            self.is_processing = True
            self.project = Project(new_project.value)

            self.name.update(self.project.project_name)

            self.current_kernel = TemplateParameter(
                None,
                options=sorted(
                    {
                        t
                        for t in self.conductor.resolve_templates(
                            self.project.templates['kernel'].as_query())
                    },
                    key=lambda v: Version(v.version),
                    reverse=True))
            self.current_templates = [
                TemplateParameter(
                    None,
                    options=sorted(
                        {
                            t
                            for t in self.conductor.resolve_templates(
                                t.as_query())
                        },
                        key=lambda v: Version(v.version),
                        reverse=True))
                for t in self.project.templates.values() if t.name != 'kernel'
            ]
            self.new_templates = []

            self.is_processing = False
        except BaseException as e:
            ui.logger(__name__).exception(e)
예제 #2
0
    def run(self) -> P:
        _push_renderer(self)
        self.thread = current_thread()
        self.alive = True
        while self.alive:
            self.render(self.app)
            if not self.alive:
                break

            line = self.get_line()
            if not self.alive or not line or line.isspace():
                continue

            try:
                value = json.loads(line)
                if 'uuid' in value and 'event' in value:
                    Observable.notify(value['uuid'], value['event'],
                                      *value.get('args', []),
                                      **value.get('kwargs', {}))
            except json.JSONDecodeError as e:
                ui.logger(__name__).exception(e)
            except BaseException as e:
                ui.logger(__name__).exception(e)
                break
        self.stop_sem.release()
        self.stop()
        return self.run_rv
예제 #3
0
    def execute(self):
        if len(self.actions) == 0:
            ui.logger(__name__).warning('No actions necessary.')
            return
        location = self.project.location
        tfd, tfn = tempfile.mkstemp(prefix='pros-project-', suffix=f'-{self.project.name}.zip', text='w+b')
        with os.fdopen(tfd, 'w+b') as tf:
            with zipfile.ZipFile(tf, mode='w') as zf:
                files, length = it.tee(location.glob('**/*'), 2)
                length = len(list(length))
                with ui.progressbar(files, length=length, label=f'Backing up {self.project.name} to {tfn}') as pb:
                    for file in pb:
                        zf.write(file, arcname=file.relative_to(location))

        try:
            with ui.Notification():
                for action in self.actions:
                    ui.logger(__name__).debug(action.describe(self.conductor, self.project))
                    rv = action.execute(self.conductor, self.project)
                    ui.logger(__name__).debug(f'{action} returned {rv}')
                    if rv is not None and not rv:
                        raise ValueError('Action did not complete successfully')
            ui.echo('All actions performed successfully')
        except Exception as e:
            ui.logger(__name__).warning(f'Failed to perform transaction, restoring project to previous state')

            with zipfile.ZipFile(tfn) as zf:
                with ui.progressbar(zf.namelist(), label=f'Restoring {self.project.name} from {tfn}') as pb:
                    for file in pb:
                        zf.extract(file, path=location)

            ui.logger(__name__).exception(e)
        finally:
            ui.echo(f'Removing {tfn}')
            os.remove(tfn)
예제 #4
0
    def project_changed(self, new_project: ExistingProjectParameter):
        try:
            self.project = Project(new_project.value)

            assert self.project is not None

            if self.project.target == 'v5':
                self.advanced_options = {
                    'name':
                    parameters.Parameter(
                        self.project.upload_options.get(
                            'remote_name', self.project.name)),
                    'description':
                    parameters.Parameter(
                        self.project.upload_options.get(
                            'description', 'Created with PROS')),
                    'compress_bin':
                    parameters.BooleanParameter(
                        self.project.upload_options.get('compress_bin', True))
                }
                self.update_slots()
            else:
                self.advanced_options = {}

            self.update_comports()

            self.redraw()
        except BaseException as e:
            ui.logger(__name__).exception(e)
예제 #5
0
 def execute(self, conductor: c.Conductor, project: c.Project):
     try:
         conductor.remove_template(project, self.template, **self.remove_kwargs)
     except ValueError as e:
         if not self.suppress_not_removable:
             raise e
         else:
             ui.logger(__name__).warning(str(e))
예제 #6
0
 def wake_me(self):
     """
     Hack to wake up input thread to know to shut down
     """
     ui.logger(__name__).debug(f'Broadcasting WAKEME for {self.app}')
     if ui.ismachineoutput():
         ui._machineoutput({'type': 'wakeme'})
     else:
         ui.echo('Wake up the renderer!')
예제 #7
0
 def execute(self, conductor: c.Conductor, project: c.Project):
     try:
         conductor.apply_template(project, self.template, **self.apply_kwargs)
     except InvalidTemplateException as e:
         if e.reason != TemplateAction.AlreadyInstalled or not self.suppress_already_installed:
             raise e
         else:
             ui.logger(__name__).warning(str(e))
     return None
예제 #8
0
    def _add_template(self):
        options = self.conductor.resolve_templates(
            identifier=BaseTemplate(target=self.project.target), unique=True)
        ui.logger(__name__).debug(options)
        p = TemplateParameter(None, options)

        @p.on('removed')
        def remove_template():
            self.new_templates.remove(p)

        self.new_templates.append(p)
예제 #9
0
    def update_comports(self):
        list_all_comports.cache_clear()

        if isinstance(self.project, Project):
            options = {}
            if self.project.target == 'v5':
                options = {p.device for p in find_v5_ports('system')}
            elif self.project.target == 'cortex':
                options = [p.device for p in find_cortex_ports()]
            if options != {*self.port.options}:
                self.port.options = list(options)
                if self.port.value not in options:
                    self.port.update(self.port.options[0] if len(
                        self.port.options) > 0 else 'No ports found')
                ui.logger(__name__).debug('Updating ports')

                if self.project and self.project.target == 'v5':
                    self.update_slots()

                self.redraw()
예제 #10
0
def prompt_to_send(event: Dict[str, Any], hint: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
    """
    Asks the user for permission to send data to Sentry
    """
    global cli_config
    with ui.Notification():
        if cli_config is None or (cli_config.offer_sentry is not None and not cli_config.offer_sentry):
            return

        if 'extra' in event and not event['extra'].get('sentry', True):
            ui.logger(__name__).debug('Not sending candidate event because event was tagged with extra.sentry = False')
            return
        if 'exc_info' in hint and (not getattr(hint['exc_info'][1], 'sentry', True) or
                                   any(isinstance(hint['exc_info'][1], t) for t in SUPPRESSED_EXCEPTIONS)):
            ui.logger(__name__).debug('Not sending candidate event because exception was tagged with sentry = False')
            return

        if not event['tags']:
            event['tags'] = dict()

        extra_text = ''
        if 'message' in event:
            extra_text += event['message'] + '\n'
        if 'culprit' in event:
            extra_text += event['culprit'] + '\n'
        if 'logentry' in event and 'message' in event['logentry']:
            extra_text += event['logentry']['message'] + '\n'
        if 'exc_info' in hint:
            import traceback
            extra_text += ''.join(traceback.format_exception(*hint['exc_info'], limit=4))

        event['tags']['confirmed'] = ui.confirm('We detected something went wrong! Do you want to send a report?',
                                                log=extra_text)
        if event['tags']['confirmed']:
            ui.echo('Sending bug report.')

            ui.echo(f'Want to get updates? Visit https://pros.cs.purdue.edu/report.html?event={event["event_id"]}')
            return event
        else:
            ui.echo('Not sending bug report.')
예제 #11
0
    def stop(self):
        ui.logger(__name__).debug(f'Stopping {self.app}')
        self.alive = False

        if current_thread() != self.thread:
            ui.logger(__name__).debug(
                f'Interrupting render thread of {self.app}')
            while not self.stop_sem.acquire(timeout=0.1):
                self.wake_me()

        ui.logger(__name__).debug(f'Broadcasting stop {self.app}')
        self._output({'uuid': self.app.uuid, 'should_exit': True})

        _remove_renderer(self)
        top_renderer = _current_renderer()
        if top_renderer:
            top_renderer.wake_me()
예제 #12
0
def upgrade(force_check, no_install):
    """
    Check for updates to the PROS CLI
    """
    from pros.upgrade import UpgradeManager
    manager = UpgradeManager()
    manifest = manager.get_manifest(force_check)
    ui.logger(__name__).debug(repr(manifest))
    if manager.has_stale_manifest:
        ui.logger(__name__).error(
            'Failed to get latest upgrade information. '
            'Try running with --debug for more information')
        return -1
    if not manager.needs_upgrade:
        ui.finalize('upgradeInfo', 'PROS CLI is up to date')
    else:
        ui.finalize('upgradeInfo', manifest)
        if not no_install:
            if not manager.can_perform_upgrade:
                ui.logger(__name__).error(
                    f'This manifest cannot perform the upgrade.')
                return -3
            ui.finalize('upgradeComplete', manager.perform_upgrade())