Exemplo n.º 1
0
 def disable(self):
     if 'linux' in platform:
         return self._disable_linux()
     elif 'darwin' in platform:
         self.profile = Profile()
         return self._disable_darwin()
     elif 'windows' in platform:
         return self._disable_windows()
Exemplo n.º 2
0
    def __init__(self, project_dir=''):
        self.profile = Profile()
        self.resources = Resources()

        if project_dir is not None:
            # Move to project dir
            project_dir = util.check_dir(project_dir)
            os.chdir(project_dir)
Exemplo n.º 3
0
    def _setup_windows(self):
        profile = Profile()
        resources = Resources()

        self.name = 'drivers'
        self.version = util.get_package_version(self.name, profile)
        self.spec_version = util.get_package_spec_version(self.name, resources)
Exemplo n.º 4
0
    def __init__(self, project_dir=''):
        self.profile = Profile()
        self.resources = Resources()

        if project_dir is not None:
            # Move to project dir
            project_dir = util.check_dir(project_dir)
            os.chdir(project_dir)
Exemplo n.º 5
0
    def __init__(self):
        profile = Profile()
        resources = Resources()

        self.name = 'examples'
        self.examples_dir = util.get_package_dir(self.name)
        self.version = util.get_package_version(self.name, profile)
        self.spec_version = util.get_package_spec_version(self.name, resources)
Exemplo n.º 6
0
def cli(ctx, list, verbose, exe):
    """Apio configuration."""

    if list:  # pragma: no cover
        profile = Profile()
        profile.list()
    elif verbose:  # pragma: no cover
        profile = Profile()
        profile.add_config('verbose', verbose)
    elif exe:  # pragma: no cover
        profile = Profile()
        profile.add_config('exe', exe)
    else:
        click.secho(ctx.get_help())
Exemplo n.º 7
0
    def __init__(self):
        profile = Profile()
        resources = Resources()

        self.name = 'system'
        self.version = util.get_package_version(self.name, profile)
        self.spec_version = util.get_package_spec_version(self.name, resources)

        self.ext = ''
        if 'Windows' == platform.system():
            self.ext = '.exe'
Exemplo n.º 8
0
def cli(ctx, packages, all, list, platform):
    """Uninstall packages."""

    if packages:
        _uninstall(packages, platform)
    elif all:  # pragma: no cover
        packages = Profile().packages
        _uninstall(packages, platform)
    elif list:
        Resources(platform).list_packages(installed=True, notinstalled=False)
    else:
        click.secho(ctx.get_help())
Exemplo n.º 9
0
    def list_packages(self, installed=True, notinstalled=True):
        """Return a list with all the installed/notinstalled packages"""

        self.profile = Profile()

        # Classify packages
        installed_packages, notinstalled_packages = self.get_packages()

        # Print tables
        terminal_width, _ = click.get_terminal_size()

        if installed and installed_packages:

            # - Print installed packages table
            click.echo('\nInstalled packages:\n')

            PACKAGELIST_TPL = ('{name:20} {description:30} {version:<8}')

            click.echo('-' * terminal_width)
            click.echo(
                PACKAGELIST_TPL.format(name=click.style('Name', fg='cyan'),
                                       version='Version',
                                       description='Description'))
            click.echo('-' * terminal_width)

            for package in installed_packages:
                click.echo(
                    PACKAGELIST_TPL.format(
                        name=click.style(package.get('name'), fg='cyan'),
                        version=package.get('version'),
                        description=package.get('description')))

        if notinstalled and notinstalled_packages:

            # - Print not installed packages table
            click.echo('\nNot installed packages:\n')

            PACKAGELIST_TPL = ('{name:20} {description:30}')

            click.echo('-' * terminal_width)
            click.echo(
                PACKAGELIST_TPL.format(name=click.style('Name', fg='yellow'),
                                       description='Description'))
            click.echo('-' * terminal_width)

            for package in notinstalled_packages:
                click.echo(
                    PACKAGELIST_TPL.format(
                        name=click.style(package.get('name'), fg='yellow'),
                        description=package.get('description')))
Exemplo n.º 10
0
class Drivers(object):  # pragma: no cover

    rules_local_path = util.safe_join(util.get_folder('resources'),
                                      '80-icestick.rules')
    rules_system_path = '/etc/udev/rules.d/80-icestick.rules'

    # Driver to restore: mac os
    driverC = ''

    def enable(self):
        if 'linux' in platform:
            return self._enable_linux()
        elif 'darwin' in platform:
            self.profile = Profile()
            return self._enable_darwin()
        elif 'windows' in platform:
            return self._enable_windows()

    def disable(self):
        if 'linux' in platform:
            return self._disable_linux()
        elif 'darwin' in platform:
            self.profile = Profile()
            return self._disable_darwin()
        elif 'windows' in platform:
            return self._disable_windows()

    def pre_upload(self):
        if 'darwin' in platform:
            self._pre_upload_darwin()

    def post_upload(self):
        if 'darwin' in platform:
            self._post_upload_darwin()

    def _enable_linux(self):
        click.secho('Configure FTDI drivers for FPGA')
        if not isfile(self.rules_system_path):
            subprocess.call(
                ['sudo', 'cp', self.rules_local_path, self.rules_system_path])
            subprocess.call(['sudo', 'service', 'udev', 'restart'])
            # subprocess.call(['sudo', 'udevadm', 'control', '--reload-rules'])
            # subprocess.call(['sudo', 'udevadm', 'trigger'])
            click.secho('FPGA drivers enabled', fg='green')
            click.secho('Unplug and reconnect your board', fg='yellow')
        else:
            click.secho('Already enabled', fg='yellow')

    def _disable_linux(self):
        if isfile(self.rules_system_path):
            click.secho('Revert FTDI drivers\' configuration')
            subprocess.call(['sudo', 'rm', self.rules_system_path])
            subprocess.call(['sudo', 'service', 'udev', 'restart'])
            # subprocess.call(['sudo', 'udevadm', 'control', '--reload-rules'])
            # subprocess.call(['sudo', 'udevadm', 'trigger'])
            click.secho('FPGA drivers disabled', fg='green')
            click.secho('Unplug and reconnect your board', fg='yellow')
        else:
            click.secho('Already disabled', fg='yellow')

    def _enable_darwin(self):
        # Check homebrew
        brew = subprocess.call('which brew > /dev/null', shell=True)
        if brew != 0:
            click.secho('Error: homebrew is required', fg='red')
        else:
            click.secho('Enable FTDI drivers for FPGA')
            subprocess.call(['brew', 'update'])
            subprocess.call(['brew', 'install', '--force', 'libftdi'])
            subprocess.call(['brew', 'unlink', 'libftdi'])
            subprocess.call(['brew', 'link', '--force', 'libftdi'])
            subprocess.call(['brew', 'install', '--force', 'libffi'])
            subprocess.call(['brew', 'unlink', 'libffi'])
            subprocess.call(['brew', 'link', '--force', 'libffi'])
            self.profile.add_setting('macos_drivers', True)
            self.profile.save()
            click.secho('FPGA drivers enabled', fg='green')

    def _disable_darwin(self):
        click.secho('Disable FTDI drivers\' configuration')
        self.profile.add_setting('macos_drivers', False)
        self.profile.save()
        click.secho('FPGA drivers disabled', fg='green')

    def _pre_upload_darwin(self):
        if self.profile.settings.get('macos_drivers', False):
            # Check and unload the drivers
            driverA = 'com.FTDI.driver.FTDIUSBSerialDriver'
            driverB = 'com.apple.driver.AppleUSBFTDI'
            if self._check_driver_darwin(driverA):
                subprocess.call(['sudo', 'kextunload', '-b', driverA])
                self.driverC = driverA
            elif self._check_driver_darwin(driverB):
                subprocess.call(['sudo', 'kextunload', '-b', driverB])
                self.driverC = driverB

    def _post_upload_darwin(self):
        if self.profile.settings.get('macos_drivers', False):
            # Restore previous driver configuration
            if self.driverC:
                subprocess.call(['sudo', 'kextload', '-b', self.driverC])

    def _check_driver_darwin(self, driver):
        return driver in subprocess.check_output(['kextstat'])

    def _enable_windows(self):
        drivers_base_dir = util.get_package_dir('tools-drivers')
        drivers_bin_dir = util.safe_join(drivers_base_dir, 'bin')
        drivers_share_dir = util.safe_join(drivers_base_dir, 'share')
        zadig_ini_path = util.safe_join(drivers_share_dir, 'zadig.ini')
        zadig_ini = 'zadig.ini'

        try:
            if isdir(drivers_bin_dir):
                click.secho('Launch drivers configuration tool')
                click.secho(FTDI_INSTALL_DRIVER_INSTRUCTIONS, fg='yellow')
                # Copy zadig.ini
                with open(zadig_ini, 'w') as ini_file:
                    with open(zadig_ini_path, 'r') as local_ini_file:
                        ini_file.write(local_ini_file.read())

                result = util.exec_command(
                    util.safe_join(drivers_bin_dir, 'zadig.exe'))
                click.secho('FPGA drivers configuration finished', fg='green')
            else:
                util._check_package('drivers')
                result = 1
        except Exception as e:
            click.secho('Error: ' + str(e), fg='red')
            result = 1
        finally:
            # Remove zadig.ini
            if isfile(zadig_ini):
                os.remove(zadig_ini)

        if not isinstance(result, int):
            result = result['returncode']
        return result

    def _disable_windows(self):
        click.secho('Launch device manager')
        click.secho(FTDI_UNINSTALL_DRIVER_INSTRUCTIONS, fg='yellow')

        result = util.exec_command('mmc devmgmt.msc')
        return result['returncode']
Exemplo n.º 11
0
class SCons(object):

    def __init__(self):
        self.resources = Resources()
        self.profile = Profile()

    def clean(self):
        return self.run('-c', deps=['scons'])

    def verify(self):
        return self.run('verify', deps=['scons', 'iverilog'])

    def sim(self):
        return self.run('sim', deps=['scons', 'iverilog', 'gtkwave'])

    def build(self, args):
        ret = self.process_arguments(args)
        if isinstance(ret, int):
            return ret
        if isinstance(ret, tuple):
            variables, board = ret
        return self.run('build', variables, board, deps=['scons', 'icestorm'])

    def upload(self, args, device=-1):
        ret = self.process_arguments(args)
        if isinstance(ret, int):
            return ret
        if isinstance(ret, tuple):
            variables, board = ret

        # Get programmer value
        programmer = ''
        if board:
            p = self.resources.boards[board]['programmer']
            type = p['type']
            content = self.resources.programmers[type]
            extra_args = p['extra_args'] if 'extra_args' in p else ''
            command = content['command'] if 'command' in content else ''
            args = content['args'] if 'args' in content else ''
            programmer = '{0} {1} {2}'.format(command, args, extra_args)

        # -- Check
        check = self.resources.boards[board]['check']

        # Check FTDI description
        if 'ftdi-desc' in check:
            detected_boards = System().detect_boards()
            if isinstance(detected_boards, int):
                return detected_boards

            if device:
                # Check device argument
                if board:
                    desc = check['ftdi-desc']
                    found = False
                    for b in detected_boards:
                        # Selected board
                        if device == b['index']:
                            # Check the device ftdi description
                            if desc in b['description']:
                                found = True
                            break
                    if not found:
                        device = -1
                else:
                    # Check device id
                    if int(device) >= len(detected_boards):
                        device = -1
            else:
                # Detect device
                device = -1
                if board:
                    desc = check['ftdi-desc']
                    for b in detected_boards:
                        if desc in b['description']:
                            # Select the first board that validates
                            # the ftdi description
                            device = b['index']
                            break
                else:
                    # Insufficient arguments
                    click.secho(
                        'Error: insufficient arguments: device or board',
                        fg='red')
                    click.secho(
                        'You have two options:\n' +
                        '  1) Execute your command with\n' +
                        '       `--device <deviceid>`\n' +
                        '  2) Execute your command with\n' +
                        '       `--board <boardname>`',
                        fg='yellow')
                    return 1

            if device == -1:
                # Board not detected
                click.secho('Error: board not detected', fg='red')
                return 1

        # Check platforms
        if 'platform' in check:
            # Device argument is ignored
            if device and device != -1:
                click.secho(
                    'Info: ignore device argument {0}'.format(device),
                    fg='yellow')

            platform = check['platform']
            current_platform = util.get_systype()
            if platform != current_platform:
                # Incorrect platform
                if platform == 'linux_armv7l':
                    click.secho(
                        'Error: incorrect platform: RPI2 or RPI3 required',
                        fg='red')
                else:
                    click.secho(
                        'Error: incorrect platform {0}'.format(platform),
                        fg='red')
                return 1

        return self.run('upload',
                        variables + ['device={0}'.format(device),
                                     'prog={0}'.format(programmer)],
                        board,
                        deps=['scons', 'icestorm'])

    def time(self, args):
        ret = self.process_arguments(args)
        if isinstance(ret, int):
            return ret
        if isinstance(ret, tuple):
            variables, board = ret
        return self.run('time', variables, board, deps=['scons', 'icestorm'])

    def run(self, command, variables=[], board=None, deps=[]):
        """Executes scons for building"""

        # -- Check for the SConstruct file
        if not isfile(join(util.get_project_dir(), 'SConstruct')):
            click.secho('Using default SConstruct file')
            variables += ['-f', join(
                dirname(__file__), '..', 'resources', 'SConstruct')]

        # -- Resolve packages
        if self.profile.check_exe_default():
            # Run on `default` config mode
            if not util.resolve_packages(self.resources.packages, deps):
                # Exit if a package is not installed
                return 1

        # -- Execute scons
        terminal_width, _ = click.get_terminal_size()
        start_time = time.time()

        if command == 'build' or \
           command == 'upload' or \
           command == 'time':
            if board:
                processing_board = board
            else:
                processing_board = 'custom board'
            click.echo('[%s] Processing %s' % (
                datetime.datetime.now().strftime('%c'),
                click.style(processing_board, fg='cyan', bold=True)))
            click.secho('-' * terminal_width, bold=True)

        if self.profile.get_verbose_mode() > 0:
            click.secho('Executing: scons -Q {0} {1}'.format(
                            command, ' '.join(variables)))

        result = util.exec_command(
            util.scons_command + ['-Q', command] + variables,
            stdout=util.AsyncPipe(self._on_run_out),
            stderr=util.AsyncPipe(self._on_run_err)
        )

        # -- Print result
        exit_code = result['returncode']
        is_error = exit_code != 0
        summary_text = ' Took %.2f seconds ' % (time.time() - start_time)
        half_line = '=' * int(
            ((terminal_width - len(summary_text) - 10) / 2))
        click.echo('%s [%s]%s%s' % (
            half_line,
            (click.style(' ERROR ', fg='red', bold=True)
             if is_error else click.style('SUCCESS', fg='green',
                                          bold=True)),
            summary_text,
            half_line
        ), err=is_error)

        if False:
            if is_error:
                print("""
  ______                     _
 |  ____|                   | |
 | |__   _ __ _ __ ___  _ __| |
 |  __| | '__| '__/ _ \| '__| |
 | |____| |  | | | (_) | |  |_|
 |______|_|  |_|  \___/|_|  (_)
""")
            else:
                print("""
   _____                             _
  / ____|                           | |
 | (___  _   _  ___ ___ ___  ___ ___| |
  \___ \| | | |/ __/ __/ _ \/ __/ __| |
  ____) | |_| | (_| (_|  __/\__ \__ \_|
 |_____/ \__,_|\___\___\___||___/___(_)
""")

        return exit_code

    def process_arguments(self, args):
        # -- Check arguments
        var_board = args['board']
        var_fpga = args['fpga']
        var_size = args['size']
        var_type = args['type']
        var_pack = args['pack']

        # TODO: reduce code size

        if var_board:
            if isfile('apio.ini'):
                click.secho('Info: ignore apio.ini board', fg='yellow')
            if var_board in self.resources.boards:
                fpga = self.resources.boards[var_board]['fpga']
                if fpga in self.resources.fpgas:
                    fpga_size = self.resources.fpgas[fpga]['size']
                    fpga_type = self.resources.fpgas[fpga]['type']
                    fpga_pack = self.resources.fpgas[fpga]['pack']

                    redundant_arguments = []
                    contradictory_arguments = []

                    if var_fpga:
                        if var_fpga in self.resources.fpgas:
                            if var_fpga == fpga:
                                # Redundant argument
                                redundant_arguments += ['fpga']
                            else:
                                # Contradictory argument
                                contradictory_arguments += ['fpga']
                        else:
                            # Unknown fpga
                            click.secho(
                                'Error: unknown fpga: {0}'.format(
                                    var_fpga), fg='red')
                            return 1

                    if var_size:
                        if var_size == fpga_size:
                            # Redundant argument
                            redundant_arguments += ['size']
                        else:
                            # Contradictory argument
                            contradictory_arguments += ['size']

                    if var_type:
                        if var_type == fpga_type:
                            # Redundant argument
                            redundant_arguments += ['type']
                        else:
                            # Contradictory argument
                            contradictory_arguments += ['type']

                    if var_pack:
                        if var_pack == fpga_pack:
                            # Redundant argument
                            redundant_arguments += ['pack']
                        else:
                            # Contradictory argument
                            contradictory_arguments += ['pack']

                    if redundant_arguments:
                        # Redundant argument
                        click.secho(
                            'Warning: redundant arguments: {}'.format(
                                ', '.join(redundant_arguments)), fg='yellow')

                    if contradictory_arguments:
                        # Contradictory argument
                        click.secho(
                            'Error: contradictory arguments: {}'.format(
                                ', '.join(contradictory_arguments)), fg='red')
                        return 1
                else:
                    # Unknown fpga
                    pass
            else:
                # Unknown board
                click.secho(
                    'Error: unknown board: {0}'.format(var_board), fg='red')
                return 1
        else:
            if var_fpga:
                if isfile('apio.ini'):
                    click.secho('Info: ignore apio.ini board', fg='yellow')
                if var_fpga in self.resources.fpgas:
                    fpga_size = self.resources.fpgas[var_fpga]['size']
                    fpga_type = self.resources.fpgas[var_fpga]['type']
                    fpga_pack = self.resources.fpgas[var_fpga]['pack']

                    redundant_arguments = []
                    contradictory_arguments = []

                    if var_size:
                        if var_size == fpga_size:
                            # Redundant argument
                            redundant_arguments += ['size']
                        else:
                            # Contradictory argument
                            contradictory_arguments += ['size']

                    if var_type:
                        if var_type == fpga_type:
                            # Redundant argument
                            redundant_arguments += ['type']
                        else:
                            # Contradictory argument
                            contradictory_arguments += ['type']

                    if var_pack:
                        if var_pack == fpga_pack:
                            # Redundant argument
                            redundant_arguments += ['pack']
                        else:
                            # Contradictory argument
                            contradictory_arguments += ['pack']

                    if redundant_arguments:
                        # Redundant argument
                        click.secho(
                            'Warning: redundant arguments: {}'.format(
                                ', '.join(redundant_arguments)), fg='yellow')

                    if contradictory_arguments:
                        # Contradictory argument
                        click.secho(
                            'Error: contradictory arguments: {}'.format(
                                ', '.join(contradictory_arguments)), fg='red')
                        return 1
                else:
                    # Unknown fpga
                    click.secho(
                        'Error: unknown fpga: {0}'.format(var_fpga), fg='red')
                    return 1
            else:
                if var_size and var_type and var_pack:
                    if isfile('apio.ini'):
                        click.secho('Info: ignore apio.ini board', fg='yellow')
                    fpga_size = var_size
                    fpga_type = var_type
                    fpga_pack = var_pack
                else:
                    if not var_size and not var_type and not var_pack:
                        # No arguments: use apio.ini board
                        p = Project()
                        p.read()
                        if p.board:
                            var_board = p.board
                            click.secho(
                                'Info: use apio.ini board: {}'.format(
                                    var_board))
                            fpga = self.resources.boards[var_board]['fpga']
                            fpga_size = self.resources.fpgas[fpga]['size']
                            fpga_type = self.resources.fpgas[fpga]['type']
                            fpga_pack = self.resources.fpgas[fpga]['pack']
                        else:
                            click.secho(
                                'Error: insufficient arguments: missing board',
                                fg='red')
                            click.secho(
                                'You have two options:\n' +
                                '  1) Execute your command with\n' +
                                '       `--board <boardname>`\n' +
                                '  2) Create an ini file using\n' +
                                '       `apio init --board <boardname>`',
                                fg='yellow')
                            return 1
                    else:
                        if isfile('apio.ini'):
                            click.secho('Info: ignore apio.ini board',
                                        fg='yellow')
                        # Insufficient arguments
                        missing = []
                        if not var_size:
                            missing += ['size']
                        if not var_type:
                            missing += ['type']
                        if not var_pack:
                            missing += ['pack']
                        pass
                        click.secho(
                            'Error: insufficient arguments: missing {}'.format(
                                ', '.join(missing)), fg='red')
                        return 1

        # -- Build Scons variables list
        variables = self.format_vars({
            'fpga_size': fpga_size,
            'fpga_type': fpga_type,
            'fpga_pack': fpga_pack
        })

        return variables, var_board

    def format_vars(self, args):
        """Format the given vars in the form: 'flag=value'"""
        variables = []
        for key, value in args.items():
            if value:
                variables += ['{0}={1}'.format(key, value)]
        return variables

    def _on_run_out(self, line):
        fg = 'green' if 'is up to date' in line else None
        click.secho(line, fg=fg)

    def _on_run_err(self, line):
        time.sleep(0.01)  # Delay
        fg = 'red' if 'error' in line.lower() else 'yellow'
        click.secho(line, fg=fg)
Exemplo n.º 12
0
 def __init__(self):
     self.resources = Resources()
     self.profile = Profile()
Exemplo n.º 13
0
class Installer(object):

    def __init__(self, package, platform='', force=False):

        # Parse version
        if '@' in package:
            split = package.split('@')
            self.package = split[0]
            self.version = split[1]
        else:
            self.package = package
            self.version = None

        self.forced_install = force
        self.packages_dir = ''

        self.resources = Resources(platform)

        if self.package in self.resources.packages:

            self.profile = Profile()

            dirname = 'packages'
            self.packages_dir = join(get_home_dir(), dirname)

            # Check version
            data = self.resources.packages[self.package]
            distribution = self.resources.distribution
            self.specversion = distribution['packages'][self.package]

            version = self._get_valid_version(
                data['repository']['name'],
                data['repository']['organization'],
                data['release']['tag_name'],
                self.version,
                self.specversion
            )

            # Valid version added with @
            if version and self.version:
                self.forced_install = True
            self.version = version if version else ''

            # Valid version
            if version:
                self.platform = platform or self._get_platform()

                release = data['release']
                self.compressed_name = release['compressed_name'].replace(
                    '%V', self.version).replace('%P', self.platform)
                self.uncompressed_name = release['uncompressed_name'].replace(
                    '%V', self.version).replace('%P', self.platform)
                self.package_name = data['release']['package_name']

                if isinstance(data['release']['extension'], dict):
                    for os in ['linux', 'darwin', 'windows']:
                        if os in self.platform:
                            self.extension = data['release']['extension'][os]
                else:
                    self.extension = data['release']['extension']

                self.tarball = self._get_tarball_name(
                    self.compressed_name,
                    self.extension
                )

                self.download_url = self._get_download_url(
                    data['repository']['name'],
                    data['repository']['organization'],
                    data['release']['tag_name'].replace('%V', self.version),
                    self.tarball
                )

    def install(self):
        if self.packages_dir == '':
            click.secho(
                'Error: No such package \'{0}\''.format(self.package),
                fg='red')
        elif self.version == '':
            click.secho(
                'Error: No valid version found. Semantic {0}'.format(
                    self.specversion),
                fg='red')
        else:
            click.echo('Installing %s package:' % click.style(
                self.package, fg='cyan'))
            if not isdir(self.packages_dir):
                makedirs(self.packages_dir)
            assert isdir(self.packages_dir)
            try:
                dlpath = None
                dlpath = self._download(self.download_url)
                if dlpath:
                    package_dir = join(self.packages_dir, self.package)
                    if isdir(package_dir):
                        shutil.rmtree(package_dir)
                    if self.uncompressed_name:
                        self._unpack(dlpath, self.packages_dir)
                    else:
                        self._unpack(dlpath, join(
                            self.packages_dir, self.package_name))
            except Exception as e:
                click.secho('Error: ' + str(e), fg='red')
            else:
                if dlpath:
                    remove(dlpath)
                    self.profile.add_package(self.package, self.version)
                    self.profile.save()
                    click.secho(
                        """Package \'{}\' has been """
                        """successfully installed!""".format(self.package),
                        fg='green')

            # Rename unpacked dir to package dir
            if self.uncompressed_name:
                unpack_dir = join(self.packages_dir, self.uncompressed_name)
                package_dir = join(self.packages_dir, self.package_name)
                if isdir(unpack_dir):
                    rename(unpack_dir, package_dir)

    def uninstall(self):
        if self.packages_dir == '':
            click.secho(
                'Error: No such package \'{0}\''.format(self.package),
                fg='red')
        else:
            if isdir(join(self.packages_dir, self.package_name)):
                click.echo('Uninstalling %s package' % click.style(
                    self.package, fg='cyan'))
                shutil.rmtree(join(self.packages_dir, self.package_name))
                click.secho(
                    """Package \'{}\' has been """
                    """successfully uninstalled!""".format(self.package),
                    fg='green')
            else:
                click.secho('Package \'{0}\' is not installed'.format(
                    self.package), fg='red')
            self.profile.remove_package(self.package)
            self.profile.save()

    def _get_platform(self):
        return get_systype()

    def _get_download_url(self, name, organization, tag, tarball):
        url = 'https://github.com/{0}/{1}/releases/download/{2}/{3}'.format(
            organization,
            name,
            tag,
            tarball)
        return url

    def _get_tarball_name(self, name, extension):
        tarball = '{0}.{1}'.format(
            name,
            extension)
        return tarball

    def _get_valid_version(self, name, organization, tag_name,
                           version='', specversion=''):
        # Check spec version
        try:
            spec = semantic_version.Spec(specversion)
        except ValueError:
            click.secho('Invalid distribution version {0}: {1}'.format(
                        name, specversion), fg='red')
            exit(1)

        # Download latest releases list
        releases = api_request('{}/releases'.format(name), organization)
        if releases is not None:
            for release in releases:
                if 'tag_name' in release:
                    if version:
                        # Version number via @
                        tag = tag_name.replace('%V', version)
                        if tag == release['tag_name']:
                            return self._check_sem_version(version, spec)
                    else:
                        pattern = tag_name.replace('%V', '(?P<v>.*?)') + '$'
                        match = re.search(pattern, release['tag_name'])
                        if match:
                            version = match.group('v')
                            return self._check_sem_version(version, spec)

    def _check_sem_version(self, version, spec):
        try:
            if semantic_version.Version(version) in spec:
                return version
        except ValueError:
            if version in str(spec):
                return version

    def _download(self, url):
        # Note: here we check only for the version of locally installed
        # packages. For this reason we don't say what's the installation
        # path.
        if self.profile.check_package_version(self.package, self.version) \
           or self.forced_install:
            fd = FileDownloader(url, self.packages_dir)
            filepath = fd.get_filepath()
            click.secho('Download ' + basename(filepath))
            try:
                fd.start()
            except KeyboardInterrupt:
                if isfile(filepath):
                    remove(filepath)
                click.secho('Abort download!', fg='red')
                exit(1)
            return filepath
        else:
            click.secho('Already installed. Version {0}'.format(
                self.profile.get_package_version(self.package)), fg='yellow')
            return None

    def _unpack(self, pkgpath, pkgdir):
        fu = FileUnpacker(pkgpath, pkgdir)
        return fu.start()
Exemplo n.º 14
0
    def __init__(self, package, platform='', force=False, checkversion=True):

        # Parse version
        if '@' in package:
            split = package.split('@')
            self.package = split[0]
            self.version = split[1]
        else:
            self.package = package
            self.version = None

        self.force_install = force
        self.packages_dir = ''

        self.resources = Resources(platform)

        if self.package in self.resources.packages:

            self.profile = Profile()

            dirname = 'packages'
            self.packages_dir = util.safe_join(util.get_home_dir(), dirname)

            # Get data
            data = self.resources.packages.get(self.package)
            distribution = self.resources.distribution

            self.spec_version = distribution.get('packages').get(self.package)
            self.package_name = data.get('release').get('package_name')
            self.extension = data.get('release').get('extension')
            platform = platform or self._get_platform()

            if checkversion:
                # Check version
                valid_version = self._get_valid_version(
                    data.get('repository').get('name'),
                    data.get('repository').get('organization'),
                    data.get('release').get('tag_name')
                )
                # Valid version
                if not valid_version:
                    # Error
                    click.secho('Error: no valid version found', fg='red')
                    exit(1)

                self.version = valid_version

                # e.g., [linux_x86_64, linux]
                platform_os = platform.split('_')[0]
                self.download_urls = [
                    {
                        'url': self.get_download_url(data, platform),
                        'platform': platform
                    },
                    {
                        'url': self.get_download_url(data, platform_os),
                        'platform': platform_os
                    }
                ]

        if self.packages_dir == '':
            click.secho(
                'Error: no such package \'{}\''.format(self.package),
                fg='red')
            exit(1)
Exemplo n.º 15
0
def cli(ctx, list, verbose, exe):
    """Apio configuration."""

    if list:  # pragma: no cover
        profile = Profile()
        profile.list()
    elif verbose:  # pragma: no cover
        profile = Profile()
        profile.add_config('verbose', verbose)
    elif exe:  # pragma: no cover
        profile = Profile()
        profile.add_config('exe', exe)
    else:
        click.secho(ctx.get_help())
Exemplo n.º 16
0
    def __init__(self, package, platform='', force=False):

        # Parse version
        if '@' in package:
            split = package.split('@')
            self.package = split[0]
            self.version = split[1]
        else:
            self.package = package
            self.version = None

        self.forced_install = force
        self.packages_dir = ''

        self.resources = Resources(platform)

        if self.package in self.resources.packages:

            self.profile = Profile()

            dirname = 'packages'
            self.packages_dir = join(get_home_dir(), dirname)

            # Check version
            data = self.resources.packages[self.package]
            distribution = self.resources.distribution
            self.specversion = distribution['packages'][self.package]

            version = self._get_valid_version(
                data['repository']['name'],
                data['repository']['organization'],
                data['release']['tag_name'],
                self.version,
                self.specversion
            )

            # Valid version added with @
            if version and self.version:
                self.forced_install = True
            self.version = version if version else ''

            # Valid version
            if version:
                self.platform = platform or self._get_platform()

                release = data['release']
                self.compressed_name = release['compressed_name'].replace(
                    '%V', self.version).replace('%P', self.platform)
                self.uncompressed_name = release['uncompressed_name'].replace(
                    '%V', self.version).replace('%P', self.platform)
                self.package_name = data['release']['package_name']

                if isinstance(data['release']['extension'], dict):
                    for os in ['linux', 'darwin', 'windows']:
                        if os in self.platform:
                            self.extension = data['release']['extension'][os]
                else:
                    self.extension = data['release']['extension']

                self.tarball = self._get_tarball_name(
                    self.compressed_name,
                    self.extension
                )

                self.download_url = self._get_download_url(
                    data['repository']['name'],
                    data['repository']['organization'],
                    data['release']['tag_name'].replace('%V', self.version),
                    self.tarball
                )
Exemplo n.º 17
0
 def __init__(self):
     self.resources = Resources()
     self.profile = Profile()
Exemplo n.º 18
0
class SCons(object):
    def __init__(self, project_dir=''):
        self.profile = Profile()
        self.resources = Resources()

        if project_dir is not None:
            # Move to project dir
            project_dir = util.check_dir(project_dir)
            os.chdir(project_dir)

    @util.command
    def clean(self):
        return self.run('-c', packages=['scons'])

    @util.command
    def verify(self):
        return self.run('verify', packages=['scons', 'iverilog'])

    @util.command
    def lint(self, args):
        var = format_vars({
            'all': args.get('all'),
            'top': args.get('top'),
            'nowarn': args.get('nowarn'),
            'warn': args.get('warn'),
            'nostyle': args.get('nostyle')
        })
        return self.run('lint', var, packages=['scons', 'verilator'])

    @util.command
    def sim(self):
        return self.run('sim', packages=['scons', 'iverilog', 'gtkwave'])

    @util.command
    def build(self, args):
        var, board = process_arguments(args, self.resources)
        return self.run('build', var, board, packages=['scons', 'icestorm'])

    @util.command
    def time(self, args):
        var, board = process_arguments(args, self.resources)
        return self.run('time', var, board, packages=['scons', 'icestorm'])

    @util.command
    def upload(self, args, serial_port, ftdi_id, sram):
        var, board = process_arguments(args, self.resources)
        programmer = self.get_programmer(board, serial_port, ftdi_id, sram)
        var += ['prog={0}'.format(programmer)]
        return self.run('upload', var, board, packages=['scons', 'icestorm'])

    def get_programmer(self, board, ext_serial, ext_ftdi_id, sram):
        programmer = ''

        if board:
            board_data = self.resources.boards.get(board)

            # Check platform
            self.check_platform(board_data)

            # Check pip packages
            self.check_pip_packages(board_data)

            # Serialize programmer command
            programmer = self.serialize_programmer(board_data, sram)

            # Replace USB vendor id
            if '${VID}' in programmer:
                vid = board_data.get('usb').get('vid')
                programmer = programmer.replace('${VID}', vid)

            # Replace USB product id
            if '${PID}' in programmer:
                pid = board_data.get('usb').get('pid')
                programmer = programmer.replace('${PID}', pid)

            # Replace FTDI index
            if '${FTDI_ID}' in programmer:
                self.check_usb(board, board_data)
                ftdi_id = self.get_ftdi_id(board, board_data, ext_ftdi_id)
                programmer = programmer.replace('${FTDI_ID}', ftdi_id)

            # TinyFPGA BX board is not detected in MacOS HighSierra
            if 'tinyprog' in board_data and 'darwin' in util.get_systype():
                # In this case the serial check is ignored
                return 'tinyprog --libusb --program'

            # Replace Serial port
            if '${SERIAL_PORT}' in programmer:
                self.check_usb(board, board_data)
                device = self.get_serial_port(board, board_data, ext_serial)
                programmer = programmer.replace('${SERIAL_PORT}', device)

        return programmer

    def check_platform(self, board_data):
        if 'platform' not in board_data:
            return

        platform = board_data.get('platform')
        current_platform = util.get_systype()
        if platform != current_platform:
            # Incorrect platform
            if platform == 'linux_armv7l':
                raise Exception('incorrect platform: RPI2 or RPI3 required')
            else:
                raise Exception('incorrect platform {0}'.format(platform))

    def check_pip_packages(self, board_data):
        prog_info = board_data.get('programmer')
        content = self.resources.programmers.get(prog_info.get('type'))
        all_pip_packages = self.resources.distribution.get('pip_packages')

        pip_packages = content.get('pip_packages') or []
        for pip_pkg in pip_packages:
            try:
                # Check pip_package version
                spec = semantic_version.Spec(all_pip_packages.get(pip_pkg, ''))
                pkg_version = pkg_resources.get_distribution(pip_pkg).version
                version = semantic_version.Version(pkg_version)
                if not spec.match(version):
                    click.secho('Error: \'{}\' '.format(pip_pkg) +
                                'version ({}) '.format(version) +
                                'does not match {}'.format(spec),
                                fg='red')
                    click.secho('Please run:\n'
                                '   pip install -U apio[{}]'.format(pip_pkg),
                                fg='yellow')
                    raise Exception
            except pkg_resources.DistributionNotFound:
                click.secho('Error: \'{}\' is not installed'.format(pip_pkg),
                            fg='red')
                click.secho('Please run:\n'
                            '   pip install -U apio[{}]'.format(pip_pkg),
                            fg='yellow')
                raise Exception
            try:
                # Check pip_package itself
                __import__(pip_pkg)
            except Exception as e:
                # Exit if a package is not working
                python_version = util.get_python_version()
                message = '\'{}\' not compatible with '.format(pip_pkg)
                message += 'Python {}'.format(python_version)
                message += '\n       {}'.format(e)
                raise Exception(message)

    def serialize_programmer(self, board_data, sram):
        prog_info = board_data.get('programmer')
        content = self.resources.programmers.get(prog_info.get('type'))

        programmer = content.get('command')

        # Add args
        if content.get('args'):
            programmer += ' {}'.format(content.get('args'))

        # Add extra args
        if prog_info.get('extra_args'):
            programmer += ' {}'.format(prog_info.get('extra_args'))

        # Enable SRAM programming
        if sram:
            # Only for iceprog programmer
            if programmer.startswith('iceprog'):
                programmer += ' -S'

        return programmer

    def check_usb(self, board, board_data):
        if 'usb' not in board_data:
            raise Exception('Missing board configuration: usb')

        usb_data = board_data.get('usb')
        hwid = '{0}:{1}'.format(usb_data.get('vid'), usb_data.get('pid'))
        found = False
        for usb_device in System().get_usb_devices():
            if usb_device.get('hwid') == hwid:
                found = True
                break

        if not found:
            # Board not connected
            if 'tinyprog' in board_data:
                click.secho('Activate bootloader by pressing the reset button',
                            fg='yellow')
            raise Exception('board ' + board + ' not connected')

    def get_serial_port(self, board, board_data, ext_serial_port):
        # Search Serial port by USB id
        device = self._check_serial(board, board_data, ext_serial_port)
        if device is None:
            # Board not connected
            raise Exception('board ' + board + ' not connected')
        return device

    def _check_serial(self, board, board_data, ext_serial_port):
        if 'usb' not in board_data:
            raise Exception('Missing board configuration: usb')

        usb_data = board_data.get('usb')
        hwid = '{0}:{1}'.format(usb_data.get('vid'), usb_data.get('pid'))

        # Match the discovered serial ports
        serial_ports = util.get_serial_ports()
        if len(serial_ports) == 0:
            # Board not available
            raise Exception('board ' + board + ' not available')
        for serial_port_data in serial_ports:
            port = serial_port_data.get('port')
            if ext_serial_port and ext_serial_port != port:
                # If the --device options is set but it doesn't match
                # the detected port, skip the port.
                continue
            if hwid.lower() in serial_port_data.get('hwid').lower():
                if 'tinyprog' in board_data and \
                   not self._check_tinyprog(board_data, port):
                    # If the board uses tinyprog use its port detection
                    # to double check the detected port.
                    # If the port is not detected, skip the port.
                    continue
                # If the hwid and the description pattern matches
                # with the detected port return the port.
                return port

    def _check_tinyprog(self, board_data, port):
        desc_pattern = '^' + board_data.get('tinyprog').get('desc') + '$'
        for tinyprog_meta in util.get_tinyprog_meta():
            tinyprog_port = tinyprog_meta.get('port')
            tinyprog_name = tinyprog_meta.get('boardmeta').get('name')
            if port == tinyprog_port and re.match(desc_pattern, tinyprog_name):
                # If the port is detected and it matches the pattern
                return True

    def get_ftdi_id(self, board, board_data, ext_ftdi_id):
        # Search device by FTDI id
        ftdi_id = self._check_ftdi(board, board_data, ext_ftdi_id)
        if ftdi_id is None:
            # Board not connected
            raise Exception('board ' + board + ' not connected')
        return ftdi_id

    def _check_ftdi(self, board, board_data, ext_ftdi_id):
        if 'ftdi' not in board_data:
            raise Exception('Missing board configuration: ftdi')

        desc_pattern = '^' + board_data.get('ftdi').get('desc') + '$'

        # Match the discovered FTDI chips
        ftdi_devices = System().get_ftdi_devices()
        if len(ftdi_devices) == 0:
            # Board not available
            raise Exception('board ' + board + ' not available')
        for ftdi_device in ftdi_devices:
            index = ftdi_device.get('index')
            if ext_ftdi_id and ext_ftdi_id != index:
                # If the --device options is set but it doesn't match
                # with the detected index, skip the port.
                continue
            if re.match(desc_pattern, ftdi_device.get('description')):
                # If matches the description pattern
                # return the index for the FTDI device.
                return index

    def run(self, command, variables=[], board=None, packages=[]):
        """Executes scons for building"""

        # -- Check for the SConstruct file
        if not isfile(util.safe_join(util.get_project_dir(), 'SConstruct')):
            variables += ['-f']
            variables += [
                util.safe_join(util.get_folder('resources'), 'SConstruct')
            ]
        else:
            click.secho('Info: use custom SConstruct file')

        # -- Resolve packages
        if self.profile.check_exe_default():
            # Run on `default` config mode
            if not util.resolve_packages(
                    packages, self.profile.packages,
                    self.resources.distribution.get('packages')):
                # Exit if a package is not installed
                raise Exception
        else:
            click.secho('Info: native config mode')

        # -- Execute scons
        return self._execute_scons(command, variables, board)

    def _execute_scons(self, command, variables, board):
        terminal_width, _ = click.get_terminal_size()
        start_time = time.time()

        if command == 'build' or \
           command == 'upload' or \
           command == 'time':
            if board:
                processing_board = board
            else:
                processing_board = 'custom board'
            click.echo('[%s] Processing %s' %
                       (datetime.datetime.now().strftime('%c'),
                        click.style(processing_board, fg='cyan', bold=True)))
            click.secho('-' * terminal_width, bold=True)

        if self.profile.get_verbose_mode() > 0:
            click.secho('Executing: {}'.format(
                ' '.join(util.scons_command + ['-Q', command] + variables)))

        result = util.exec_command(util.scons_command + ['-Q', command] +
                                   variables,
                                   stdout=util.AsyncPipe(self._on_stdout),
                                   stderr=util.AsyncPipe(self._on_stderr))

        # -- Print result
        exit_code = result.get('returncode')
        is_error = exit_code != 0
        summary_text = ' Took %.2f seconds ' % (time.time() - start_time)
        half_line = '=' * int(((terminal_width - len(summary_text) - 10) / 2))
        click.echo('%s [%s]%s%s' %
                   (half_line,
                    (click.style(' ERROR ', fg='red', bold=True) if is_error
                     else click.style('SUCCESS', fg='green', bold=True)),
                    summary_text, half_line),
                   err=is_error)

        return exit_code

    def _on_stdout(self, line):
        fg = 'green' if 'is up to date' in line else None
        click.secho(line, fg=fg)

    def _on_stderr(self, line):
        if '%|' in line and '100%|' not in line:
            # Remove previous line for tqdm progress bar
            CURSOR_UP = '\033[F'
            ERASE_LINE = '\033[K'
            sys.stdout.write(CURSOR_UP + ERASE_LINE)
        fg = 'red' if 'error' in line.lower() else 'yellow'
        click.secho(line, fg=fg)
Exemplo n.º 19
0
class Installer(object):

    def __init__(self, package):

        # Parse version
        if '@' in package:
            split = package.split('@')
            self.package = split[0]
            self.version = split[1]
        else:
            self.package = package
            self.version = None

        self.forced_install = False
        self.valid_version = True

        self.resources = Resources()
        self.profile = Profile()

        if self.package in self.resources.packages:

            data = self.resources.packages[self.package]

            if self.version:
                # Validate version
                valid = self._validate_version(
                    data['repository']['name'],
                    data['repository']['organization'],
                    data['release']['tag_name'],
                    self.version
                )
                if valid:
                    self.forced_install = True
                else:
                    self.valid_version = False
            else:
                # Get latest version
                self.version = self._get_latest_version(
                    data['repository']['name'],
                    data['repository']['organization'],
                    data['release']['tag_name']
                )

            self.arch = self._get_architecture()

            release = data['release']
            self.compressed_name = release['compressed_name'].replace(
                '%V', self.version).replace('%A', self.arch)
            self.uncompressed_name = release['uncompressed_name'].replace(
                '%V', self.version).replace('%A', self.arch)
            self.package_name = data['release']['package_name']

            if isinstance(data['release']['extension'], dict):
                for os in ['linux', 'darwin', 'windows']:
                    if os in self.arch:
                        self.extension = data['release']['extension'][os]
            else:
                self.extension = data['release']['extension']

            self.tarball = self._get_tarball_name(
                self.compressed_name,
                self.extension
            )

            self.download_url = self._get_download_url(
                data['repository']['name'],
                data['repository']['organization'],
                data['release']['tag_name'].replace('%V', self.version),
                self.tarball
            )

            if 'main_dir' in data.keys():
                self.packages_dir = join(expanduser('~'), data['main_dir'])
            else:
                self.packages_dir = join(util.get_home_dir(), 'packages')

    def install(self):
        if self.version is None:
            click.secho(
                'Error: No such package \'{0}\''.format(self.package),
                fg='red')
        elif not self.valid_version:
            click.secho(
                'Error: package \'{0}\' has no version {1}'.format(
                    self.package, self.version),
                fg='red')
        else:
            click.echo("Installing %s package:" % click.style(
                self.package, fg="cyan"))
            if not isdir(self.packages_dir):
                makedirs(self.packages_dir)
            assert isdir(self.packages_dir)
            try:
                dlpath = None
                dlpath = self._download(self.download_url)
                if dlpath:
                    package_dir = join(self.packages_dir, self.package)
                    if isdir(package_dir):
                        shutil.rmtree(package_dir)
                    self._unpack(dlpath, self.packages_dir)
            except Exception:
                click.secho('Package {0} not found'.format(
                    self.tarball), fg='red')
            else:
                if dlpath:
                    remove(dlpath)
                    self.profile.add(self.package, self.version)
                    self.profile.save()
                    click.secho(
                        """Package \'{}\' has been """
                        """successfully installed!""".format(self.package),
                        fg='green')

            # Rename unpacked dir to package dir
            if self.uncompressed_name:
                unpack_dir = join(self.packages_dir, self.uncompressed_name)
                package_dir = join(self.packages_dir, self.package_name)
                if isdir(unpack_dir):
                    rename(unpack_dir, package_dir)

    def uninstall(self):
        if self.version is None:
            click.secho(
                'Error: No such package \'{0}\''.format(self.package),
                fg='red')
        else:
            if isdir(join(self.packages_dir, self.package_name)):
                click.echo("Uninstalling %s package" % click.style(
                    self.package, fg="cyan"))
                shutil.rmtree(join(self.packages_dir, self.package_name))
                click.secho(
                    """Package \'{}\' has been """
                    """successfully uninstalled!""".format(self.package),
                    fg='green')
            else:
                click.secho('Package \'{0}\' is not installed'.format(
                    self.package), fg='red')
            self.profile.remove(self.package)
            self.profile.save()

    def _get_architecture(self):
        return util.get_systype()

    def _get_download_url(self, name, organization, tag, tarball):
        url = 'https://github.com/{0}/{1}/releases/download/{2}/{3}'.format(
            organization,
            name,
            tag,
            tarball)
        return url

    def _get_tarball_name(self, name, extension):
        tarball = '{0}.{1}'.format(
            name,
            extension)
        return tarball

    def _validate_version(self, name, organization, tag_name, version):
        releases = api_request('{}/releases'.format(name), organization)
        if releases is not None:
            for release in releases:
                if 'tag_name' in release and \
                   release['tag_name'] == tag_name.replace('%V', version):
                    return True
        return False

    def _get_latest_version(self, name, organization, tag_name):
        version = ''
        latest_release = api_request(
            '{}/releases/latest'.format(name), organization)
        if latest_release is not None and 'tag_name' in latest_release:
            pattern = tag_name.replace('%V', '(?P<v>.*?)') + '$'
            match = re.search(pattern, latest_release['tag_name'])
            if match:
                version = match.group('v')
        return version

    def _download(self, url):
        if self.profile.check_version(self.package, self.version) or \
           self.forced_install:
            fd = FileDownloader(url, self.packages_dir)
            click.secho('Download ' + basename(fd.get_filepath()))
            fd.start()
            return fd.get_filepath()
        else:
            click.secho('Already installed. Version {0}'.format(
                self.profile.get_version(self.package)), fg='yellow')
            return None

    def _unpack(self, pkgpath, pkgdir):
        fu = FileUnpacker(pkgpath, pkgdir)
        return fu.start()
Exemplo n.º 20
0
class SCons(object):

    def __init__(self, project_dir=''):
        self.profile = Profile()
        self.resources = Resources()

        if project_dir is not None:
            # Move to project dir
            project_dir = util.check_dir(project_dir)
            os.chdir(project_dir)

    @util.command
    def clean(self):
        return self.run('-c', packages=['scons'])

    @util.command
    def verify(self):
        return self.run('verify', packages=['scons', 'iverilog'])

    @util.command
    def lint(self, args):
        var = format_vars({
            'all': args.get('all'),
            'top': args.get('top'),
            'nowarn': args.get('nowarn'),
            'warn': args.get('warn'),
            'nostyle': args.get('nostyle')
        })
        return self.run('lint', var, packages=['scons', 'verilator'])

    @util.command
    def sim(self):
        return self.run('sim', packages=['scons', 'iverilog', 'gtkwave'])

    @util.command
    def build(self, args):
        var, board = process_arguments(args, self.resources)
        return self.run('build', var, board, packages=['scons', 'icestorm'])

    @util.command
    def time(self, args):
        var, board = process_arguments(args, self.resources)
        return self.run('time', var, board, packages=['scons', 'icestorm'])

    @util.command
    def upload(self, args, serial_port, ftdi_id, sram):
        var, board = process_arguments(args, self.resources)
        programmer = self.get_programmer(board, serial_port, ftdi_id, sram)
        var += ['prog={0}'.format(programmer)]
        return self.run('upload', var, board, packages=['scons', 'icestorm'])

    def get_programmer(self, board, ext_serial, ext_ftdi_id, sram):
        programmer = ''

        if board:
            board_data = self.resources.boards.get(board)

            # Check platform
            self.check_platform(board_data)

            # Check pip packages
            self.check_pip_packages(board_data)

            # Serialize programmer command
            programmer = self.serialize_programmer(board_data, sram)

            # Replace USB vendor id
            if '${VID}' in programmer:
                vid = board_data.get('usb').get('vid')
                programmer = programmer.replace('${VID}', vid)

            # Replace USB product id
            if '${PID}' in programmer:
                pid = board_data.get('usb').get('pid')
                programmer = programmer.replace('${PID}', pid)

            # Replace FTDI index
            if '${FTDI_ID}' in programmer:
                self.check_usb(board, board_data)
                ftdi_id = self.get_ftdi_id(board, board_data, ext_ftdi_id)
                programmer = programmer.replace('${FTDI_ID}', ftdi_id)

            # TinyFPGA BX board is not detected in MacOS HighSierra
            if 'tinyprog' in board_data and 'darwin' in util.get_systype():
                # In this case the serial check is ignored
                return 'tinyprog --libusb --program'

            # Replace Serial port
            if '${SERIAL_PORT}' in programmer:
                self.check_usb(board, board_data)
                device = self.get_serial_port(board, board_data, ext_serial)
                programmer = programmer.replace('${SERIAL_PORT}', device)

        return programmer

    def check_platform(self, board_data):
        if 'platform' not in board_data:
            return

        platform = board_data.get('platform')
        current_platform = util.get_systype()
        if platform != current_platform:
            # Incorrect platform
            if platform == 'linux_armv7l':
                raise Exception(
                    'incorrect platform: RPI2 or RPI3 required')
            else:
                raise Exception(
                    'incorrect platform {0}'.format(platform))

    def check_pip_packages(self, board_data):
        prog_info = board_data.get('programmer')
        content = self.resources.programmers.get(prog_info.get('type'))
        all_pip_packages = self.resources.distribution.get('pip_packages')

        pip_packages = content.get('pip_packages') or []
        for pip_pkg in pip_packages:
            try:
                # Check pip_package version
                spec = semantic_version.Spec(all_pip_packages.get(pip_pkg, ''))
                pkg_version = pkg_resources.get_distribution(pip_pkg).version
                version = semantic_version.Version(pkg_version)
                if not spec.match(version):
                    click.secho(
                        'Error: \'{}\' '.format(pip_pkg) +
                        'version ({}) '.format(version) +
                        'does not match {}'.format(spec),
                        fg='red')
                    click.secho('Please run:\n'
                                '   pip install -U apio[{}]'.format(pip_pkg),
                                fg='yellow')
                    raise Exception
            except pkg_resources.DistributionNotFound:
                click.secho(
                    'Error: \'{}\' is not installed'.format(pip_pkg),
                    fg='red')
                click.secho('Please run:\n'
                            '   pip install -U apio[{}]'.format(pip_pkg),
                            fg='yellow')
                raise Exception
            try:
                # Check pip_package itself
                __import__(pip_pkg)
            except Exception as e:
                # Exit if a package is not working
                python_version = util.get_python_version()
                message = '\'{}\' not compatible with '.format(pip_pkg)
                message += 'Python {}'.format(python_version)
                message += '\n       {}'.format(e)
                raise Exception(message)

    def serialize_programmer(self, board_data, sram):
        prog_info = board_data.get('programmer')
        content = self.resources.programmers.get(prog_info.get('type'))

        programmer = content.get('command')

        # Add args
        if content.get('args'):
            programmer += ' {}'.format(content.get('args'))

        # Add extra args
        if prog_info.get('extra_args'):
            programmer += ' {}'.format(prog_info.get('extra_args'))

        # Enable SRAM programming
        if sram:
            # Only for iceprog programmer
            if programmer.startswith('iceprog'):
                programmer += ' -S'

        return programmer

    def check_usb(self, board, board_data):
        if 'usb' not in board_data:
            raise Exception('Missing board configuration: usb')

        usb_data = board_data.get('usb')
        hwid = '{0}:{1}'.format(
            usb_data.get('vid'),
            usb_data.get('pid')
        )
        found = False
        for usb_device in System().get_usb_devices():
            if usb_device.get('hwid') == hwid:
                found = True
                break

        if not found:
            # Board not connected
            if 'tinyprog' in board_data:
                click.secho(
                    'Activate bootloader by pressing the reset button',
                    fg='yellow')
            raise Exception('board ' + board + ' not connected')

    def get_serial_port(self, board, board_data, ext_serial_port):
        # Search Serial port by USB id
        device = self._check_serial(board, board_data, ext_serial_port)
        if device is None:
            # Board not connected
            raise Exception('board ' + board + ' not connected')
        return device

    def _check_serial(self, board, board_data, ext_serial_port):
        if 'usb' not in board_data:
            raise Exception('Missing board configuration: usb')

        usb_data = board_data.get('usb')
        hwid = '{0}:{1}'.format(
            usb_data.get('vid'),
            usb_data.get('pid')
        )

        # Match the discovered serial ports
        serial_ports = util.get_serial_ports()
        if len(serial_ports) == 0:
            # Board not available
            raise Exception('board ' + board + ' not available')
        for serial_port_data in serial_ports:
            port = serial_port_data.get('port')
            if ext_serial_port and ext_serial_port != port:
                # If the --device options is set but it doesn't match
                # the detected port, skip the port.
                continue
            if hwid.lower() in serial_port_data.get('hwid').lower():
                if 'tinyprog' in board_data and \
                   not self._check_tinyprog(board_data, port):
                    # If the board uses tinyprog use its port detection
                    # to double check the detected port.
                    # If the port is not detected, skip the port.
                    continue
                # If the hwid and the description pattern matches
                # with the detected port return the port.
                return port

    def _check_tinyprog(self, board_data, port):
        desc_pattern = '^' + board_data.get('tinyprog').get('desc') + '$'
        for tinyprog_meta in util.get_tinyprog_meta():
            tinyprog_port = tinyprog_meta.get('port')
            tinyprog_name = tinyprog_meta.get('boardmeta').get('name')
            if port == tinyprog_port and re.match(desc_pattern, tinyprog_name):
                # If the port is detected and it matches the pattern
                return True

    def get_ftdi_id(self, board, board_data, ext_ftdi_id):
        # Search device by FTDI id
        ftdi_id = self._check_ftdi(board, board_data, ext_ftdi_id)
        if ftdi_id is None:
            # Board not connected
            raise Exception('board ' + board + ' not connected')
        return ftdi_id

    def _check_ftdi(self, board, board_data, ext_ftdi_id):
        if 'ftdi' not in board_data:
            raise Exception('Missing board configuration: ftdi')

        desc_pattern = '^' + board_data.get('ftdi').get('desc') + '$'

        # Match the discovered FTDI chips
        ftdi_devices = System().get_ftdi_devices()
        if len(ftdi_devices) == 0:
            # Board not available
            raise Exception('board ' + board + ' not available')
        for ftdi_device in ftdi_devices:
            index = ftdi_device.get('index')
            if ext_ftdi_id and ext_ftdi_id != index:
                # If the --device options is set but it doesn't match
                # with the detected index, skip the port.
                continue
            if re.match(desc_pattern, ftdi_device.get('description')):
                # If matches the description pattern
                # return the index for the FTDI device.
                return index

    def run(self, command, variables=[], board=None, packages=[]):
        """Executes scons for building"""

        # -- Check for the SConstruct file
        if not isfile(util.safe_join(util.get_project_dir(), 'SConstruct')):
            variables += ['-f']
            variables += [util.safe_join(
                util.get_folder('resources'), 'SConstruct')]
        else:
            click.secho('Info: use custom SConstruct file')

        # -- Resolve packages
        if self.profile.check_exe_default():
            # Run on `default` config mode
            if not util.resolve_packages(
              packages,
              self.profile.packages,
              self.resources.distribution.get('packages')
             ):
                # Exit if a package is not installed
                raise Exception
        else:
            click.secho('Info: native config mode')

        # -- Execute scons
        return self._execute_scons(command, variables, board)

    def _execute_scons(self, command, variables, board):
        terminal_width, _ = click.get_terminal_size()
        start_time = time.time()

        if command == 'build' or \
           command == 'upload' or \
           command == 'time':
            if board:
                processing_board = board
            else:
                processing_board = 'custom board'
            click.echo('[%s] Processing %s' % (
                datetime.datetime.now().strftime('%c'),
                click.style(processing_board, fg='cyan', bold=True)))
            click.secho('-' * terminal_width, bold=True)

        if self.profile.get_verbose_mode() > 0:
            click.secho('Executing: {}'.format(
                ' '.join(util.scons_command + ['-Q', command] + variables)))

        result = util.exec_command(
            util.scons_command + ['-Q', command] + variables,
            stdout=util.AsyncPipe(self._on_stdout),
            stderr=util.AsyncPipe(self._on_stderr)
        )

        # -- Print result
        exit_code = result.get('returncode')
        is_error = exit_code != 0
        summary_text = ' Took %.2f seconds ' % (time.time() - start_time)
        half_line = '=' * int(
            ((terminal_width - len(summary_text) - 10) / 2))
        click.echo('%s [%s]%s%s' % (
            half_line,
            (click.style(' ERROR ', fg='red', bold=True)
             if is_error else click.style('SUCCESS', fg='green', bold=True)),
            summary_text,
            half_line
        ), err=is_error)

        return exit_code

    def _on_stdout(self, line):
        fg = 'green' if 'is up to date' in line else None
        click.secho(line, fg=fg)

    def _on_stderr(self, line):
        if '%|' in line and '100%|' not in line:
            # Remove previous line for tqdm progress bar
            CURSOR_UP = '\033[F'
            ERASE_LINE = '\033[K'
            sys.stdout.write(CURSOR_UP + ERASE_LINE)
        fg = 'red' if 'error' in line.lower() else 'yellow'
        click.secho(line, fg=fg)
Exemplo n.º 21
0
class SCons(object):
    def __init__(self, project_dir=''):
        self.resources = Resources()
        self.profile = Profile()

        if project_dir is not None:
            # Move to project dir
            project_dir = util.check_dir(project_dir)
            os.chdir(project_dir)

    def clean(self):
        return self.run('-c', deps=['scons'])

    def verify(self):
        return self.run('verify', deps=['scons', 'iverilog'])

    def sim(self):
        return self.run('sim', deps=['scons', 'iverilog', 'gtkwave'])

    def build(self, args):
        ret = self.process_arguments(args)
        if isinstance(ret, int):
            return ret
        if isinstance(ret, tuple):
            variables, board = ret
        return self.run('build', variables, board, deps=['scons', 'icestorm'])

    def upload(self, args, device=-1):
        ret = self.process_arguments(args)
        if isinstance(ret, int):
            return ret
        if isinstance(ret, tuple):
            variables, board = ret

        # Get programmer value
        programmer = ''
        if board:
            p = self.resources.boards[board]['programmer']
            type = p['type']
            content = self.resources.programmers[type]
            extra_args = p['extra_args'] if 'extra_args' in p else ''
            command = content['command'] if 'command' in content else ''
            args = content['args'] if 'args' in content else ''
            programmer = '{0} {1} {2}'.format(command, args, extra_args)

        # -- Check
        check = self.resources.boards[board]['check']

        # Check FTDI description
        if 'ftdi-desc' in check:
            detected_boards = System().detect_boards()
            if isinstance(detected_boards, int):
                return detected_boards

            if device:
                # Check device argument
                if board:
                    desc = check['ftdi-desc']
                    found = False
                    for b in detected_boards:
                        # Selected board
                        if device == b['index']:
                            # Check the device ftdi description
                            if desc in b['description']:
                                found = True
                            break
                    if not found:
                        device = -1
                else:
                    # Check device id
                    if int(device) >= len(detected_boards):
                        device = -1
            else:
                # Detect device
                device = -1
                if board:
                    desc = check['ftdi-desc']
                    for b in detected_boards:
                        if desc in b['description']:
                            # Select the first board that validates
                            # the ftdi description
                            device = b['index']
                            break
                else:
                    # Insufficient arguments
                    click.secho(
                        'Error: insufficient arguments: device or board',
                        fg='red')
                    click.secho('You have two options:\n' +
                                '  1) Execute your command with\n' +
                                '       `--device <deviceid>`\n' +
                                '  2) Execute your command with\n' +
                                '       `--board <boardname>`',
                                fg='yellow')
                    return 1

            if device == -1:
                # Board not detected
                click.secho('Error: board not detected', fg='red')
                return 1

        # Check platforms
        if 'platform' in check:
            # Device argument is ignored
            if device and device != -1:
                click.secho('Info: ignore device argument {0}'.format(device),
                            fg='yellow')

            platform = check['platform']
            current_platform = util.get_systype()
            if platform != current_platform:
                # Incorrect platform
                if platform == 'linux_armv7l':
                    click.secho(
                        'Error: incorrect platform: RPI2 or RPI3 required',
                        fg='red')
                else:
                    click.secho(
                        'Error: incorrect platform {0}'.format(platform),
                        fg='red')
                return 1

        return self.run('upload',
                        variables +
                        ['prog={0}'.format(programmer.replace('%D%', device))],
                        board,
                        deps=['scons', 'icestorm'])

    def time(self, args):
        ret = self.process_arguments(args)
        if isinstance(ret, int):
            return ret
        if isinstance(ret, tuple):
            variables, board = ret
        return self.run('time', variables, board, deps=['scons', 'icestorm'])

    def run(self, command, variables=[], board=None, deps=[]):
        """Executes scons for building"""

        # -- Check for the SConstruct file
        if not isfile(util.safe_join(util.get_project_dir(), 'SConstruct')):
            click.secho('Info: default SConstruct file')
            variables += ['-f']
            variables += [
                util.safe_join(util.get_folder('resources'), 'SConstruct')
            ]

        # -- Resolve packages
        if self.profile.check_exe_default():
            # Run on `default` config mode
            if not util.resolve_packages(self.resources.packages, deps):
                # Exit if a package is not installed
                return 1
        else:
            click.secho('Info: native config mode')

        # -- Execute scons
        terminal_width, _ = click.get_terminal_size()
        start_time = time.time()

        if command == 'build' or \
           command == 'upload' or \
           command == 'time':
            if board:
                processing_board = board
            else:
                processing_board = 'custom board'
            click.echo('[%s] Processing %s' %
                       (datetime.datetime.now().strftime('%c'),
                        click.style(processing_board, fg='cyan', bold=True)))
            click.secho('-' * terminal_width, bold=True)

        if self.profile.get_verbose_mode() > 0:
            click.secho('Executing: scons -Q {0} {1}'.format(
                command, ' '.join(variables)))

        result = util.exec_command(util.scons_command + ['-Q', command] +
                                   variables,
                                   stdout=util.AsyncPipe(self._on_run_out),
                                   stderr=util.AsyncPipe(self._on_run_err))

        # -- Print result
        exit_code = result['returncode']
        is_error = exit_code != 0
        summary_text = ' Took %.2f seconds ' % (time.time() - start_time)
        half_line = '=' * int(((terminal_width - len(summary_text) - 10) / 2))
        click.echo('%s [%s]%s%s' %
                   (half_line,
                    (click.style(' ERROR ', fg='red', bold=True) if is_error
                     else click.style('SUCCESS', fg='green', bold=True)),
                    summary_text, half_line),
                   err=is_error)

        if False:
            if is_error:
                print("""
  ______                     _
 |  ____|                   | |
 | |__   _ __ _ __ ___  _ __| |
 |  __| | '__| '__/ _ \| '__| |
 | |____| |  | | | (_) | |  |_|
 |______|_|  |_|  \___/|_|  (_)
""")
            else:
                print("""
   _____                             _
  / ____|                           | |
 | (___  _   _  ___ ___ ___  ___ ___| |
  \___ \| | | |/ __/ __/ _ \/ __/ __| |
  ____) | |_| | (_| (_|  __/\__ \__ \_|
 |_____/ \__,_|\___\___\___||___/___(_)
""")

        return exit_code

    def process_arguments(self, args):
        # -- Check arguments
        var_board = args['board']
        var_fpga = args['fpga']
        var_size = args['size']
        var_type = args['type']
        var_pack = args['pack']

        # TODO: reduce code size

        if var_board:
            if isfile('apio.ini'):
                click.secho('Info: ignore apio.ini board', fg='yellow')
            if var_board in self.resources.boards:
                fpga = self.resources.boards[var_board]['fpga']
                if fpga in self.resources.fpgas:
                    fpga_size = self.resources.fpgas[fpga]['size']
                    fpga_type = self.resources.fpgas[fpga]['type']
                    fpga_pack = self.resources.fpgas[fpga]['pack']

                    redundant_arguments = []
                    contradictory_arguments = []

                    if var_fpga:
                        if var_fpga in self.resources.fpgas:
                            if var_fpga == fpga:
                                # Redundant argument
                                redundant_arguments += ['fpga']
                            else:
                                # Contradictory argument
                                contradictory_arguments += ['fpga']
                        else:
                            # Unknown fpga
                            click.secho(
                                'Error: unknown fpga: {0}'.format(var_fpga),
                                fg='red')
                            return 1

                    if var_size:
                        if var_size == fpga_size:
                            # Redundant argument
                            redundant_arguments += ['size']
                        else:
                            # Contradictory argument
                            contradictory_arguments += ['size']

                    if var_type:
                        if var_type == fpga_type:
                            # Redundant argument
                            redundant_arguments += ['type']
                        else:
                            # Contradictory argument
                            contradictory_arguments += ['type']

                    if var_pack:
                        if var_pack == fpga_pack:
                            # Redundant argument
                            redundant_arguments += ['pack']
                        else:
                            # Contradictory argument
                            contradictory_arguments += ['pack']

                    if redundant_arguments:
                        # Redundant argument
                        click.secho('Warning: redundant arguments: {}'.format(
                            ', '.join(redundant_arguments)),
                                    fg='yellow')

                    if contradictory_arguments:
                        # Contradictory argument
                        click.secho(
                            'Error: contradictory arguments: {}'.format(
                                ', '.join(contradictory_arguments)),
                            fg='red')
                        return 1
                else:
                    # Unknown fpga
                    pass
            else:
                # Unknown board
                click.secho('Error: unknown board: {0}'.format(var_board),
                            fg='red')
                return 1
        else:
            if var_fpga:
                if isfile('apio.ini'):
                    click.secho('Info: ignore apio.ini board', fg='yellow')
                if var_fpga in self.resources.fpgas:
                    fpga_size = self.resources.fpgas[var_fpga]['size']
                    fpga_type = self.resources.fpgas[var_fpga]['type']
                    fpga_pack = self.resources.fpgas[var_fpga]['pack']

                    redundant_arguments = []
                    contradictory_arguments = []

                    if var_size:
                        if var_size == fpga_size:
                            # Redundant argument
                            redundant_arguments += ['size']
                        else:
                            # Contradictory argument
                            contradictory_arguments += ['size']

                    if var_type:
                        if var_type == fpga_type:
                            # Redundant argument
                            redundant_arguments += ['type']
                        else:
                            # Contradictory argument
                            contradictory_arguments += ['type']

                    if var_pack:
                        if var_pack == fpga_pack:
                            # Redundant argument
                            redundant_arguments += ['pack']
                        else:
                            # Contradictory argument
                            contradictory_arguments += ['pack']

                    if redundant_arguments:
                        # Redundant argument
                        click.secho('Warning: redundant arguments: {}'.format(
                            ', '.join(redundant_arguments)),
                                    fg='yellow')

                    if contradictory_arguments:
                        # Contradictory argument
                        click.secho(
                            'Error: contradictory arguments: {}'.format(
                                ', '.join(contradictory_arguments)),
                            fg='red')
                        return 1
                else:
                    # Unknown fpga
                    click.secho('Error: unknown fpga: {0}'.format(var_fpga),
                                fg='red')
                    return 1
            else:
                if var_size and var_type and var_pack:
                    if isfile('apio.ini'):
                        click.secho('Info: ignore apio.ini board', fg='yellow')
                    fpga_size = var_size
                    fpga_type = var_type
                    fpga_pack = var_pack
                else:
                    if not var_size and not var_type and not var_pack:
                        # No arguments: use apio.ini board
                        p = Project()
                        p.read()
                        if p.board:
                            var_board = p.board
                            click.secho(
                                'Info: apio.ini board {}'.format(var_board))
                            fpga = self.resources.boards[var_board]['fpga']
                            fpga_size = self.resources.fpgas[fpga]['size']
                            fpga_type = self.resources.fpgas[fpga]['type']
                            fpga_pack = self.resources.fpgas[fpga]['pack']
                        else:
                            click.secho(
                                'Error: insufficient arguments: missing board',
                                fg='red')
                            click.secho(
                                'You have two options:\n' +
                                '  1) Execute your command with\n' +
                                '       `--board <boardname>`\n' +
                                '  2) Create an ini file using\n' +
                                '       `apio init --board <boardname>`',
                                fg='yellow')
                            return 1
                    else:
                        if isfile('apio.ini'):
                            click.secho('Info: ignore apio.ini board',
                                        fg='yellow')
                        # Insufficient arguments
                        missing = []
                        if not var_size:
                            missing += ['size']
                        if not var_type:
                            missing += ['type']
                        if not var_pack:
                            missing += ['pack']
                        pass
                        click.secho(
                            'Error: insufficient arguments: missing {}'.format(
                                ', '.join(missing)),
                            fg='red')
                        return 1

        # -- Build Scons variables list
        variables = self.format_vars({
            'fpga_size': fpga_size,
            'fpga_type': fpga_type,
            'fpga_pack': fpga_pack
        })

        return variables, var_board

    def format_vars(self, args):
        """Format the given vars in the form: 'flag=value'"""
        variables = []
        for key, value in args.items():
            if value:
                variables += ['{0}={1}'.format(key, value)]
        return variables

    def _on_run_out(self, line):
        fg = 'green' if 'is up to date' in line else None
        click.secho(line, fg=fg)

    def _on_run_err(self, line):
        time.sleep(0.01)  # Delay
        fg = 'red' if 'error' in line.lower() else 'yellow'
        click.secho(line, fg=fg)
Exemplo n.º 22
0
    def __init__(self, package, platform='', force=False):

        # Parse version
        if '@' in package:
            split = package.split('@')
            self.package = split[0]
            self.version = split[1]
        else:
            self.package = package
            self.version = None

        self.forced_install = force
        self.packages_dir = ''

        self.resources = Resources(platform)

        if self.package in self.resources.packages:

            self.profile = Profile()

            dirname = 'packages'
            self.packages_dir = join(get_home_dir(), dirname)

            # Check version
            data = self.resources.packages[self.package]
            distribution = self.resources.distribution
            self.specversion = distribution['packages'][self.package]

            version = self._get_valid_version(
                data['repository']['name'], data['repository']['organization'],
                data['release']['tag_name'], self.version, self.specversion)

            # Valid version added with @
            if version and self.version:
                self.forced_install = True
            self.version = version if version else ''

            # Valid version
            if version:
                self.platform = platform or self._get_platform()

                release = data['release']
                self.compressed_name = release['compressed_name'].replace(
                    '%V', self.version).replace('%P', self.platform)
                self.uncompressed_name = release['uncompressed_name'].replace(
                    '%V', self.version).replace('%P', self.platform)
                self.package_name = data['release']['package_name']

                if isinstance(data['release']['extension'], dict):
                    for os in ['linux', 'darwin', 'windows']:
                        if os in self.platform:
                            self.extension = data['release']['extension'][os]
                else:
                    self.extension = data['release']['extension']

                self.tarball = self._get_tarball_name(self.compressed_name,
                                                      self.extension)

                self.download_url = self._get_download_url(
                    data['repository']['name'],
                    data['repository']['organization'],
                    data['release']['tag_name'].replace('%V', self.version),
                    self.tarball)
Exemplo n.º 23
0
class Installer(object):
    def __init__(self, package, platform='', force=False):

        # Parse version
        if '@' in package:
            split = package.split('@')
            self.package = split[0]
            self.version = split[1]
        else:
            self.package = package
            self.version = None

        self.forced_install = force
        self.packages_dir = ''

        self.resources = Resources(platform)

        if self.package in self.resources.packages:

            self.profile = Profile()

            dirname = 'packages'
            self.packages_dir = join(get_home_dir(), dirname)

            # Check version
            data = self.resources.packages[self.package]
            distribution = self.resources.distribution
            self.specversion = distribution['packages'][self.package]

            version = self._get_valid_version(
                data['repository']['name'], data['repository']['organization'],
                data['release']['tag_name'], self.version, self.specversion)

            # Valid version added with @
            if version and self.version:
                self.forced_install = True
            self.version = version if version else ''

            # Valid version
            if version:
                self.platform = platform or self._get_platform()

                release = data['release']
                self.compressed_name = release['compressed_name'].replace(
                    '%V', self.version).replace('%P', self.platform)
                self.uncompressed_name = release['uncompressed_name'].replace(
                    '%V', self.version).replace('%P', self.platform)
                self.package_name = data['release']['package_name']

                if isinstance(data['release']['extension'], dict):
                    for os in ['linux', 'darwin', 'windows']:
                        if os in self.platform:
                            self.extension = data['release']['extension'][os]
                else:
                    self.extension = data['release']['extension']

                self.tarball = self._get_tarball_name(self.compressed_name,
                                                      self.extension)

                self.download_url = self._get_download_url(
                    data['repository']['name'],
                    data['repository']['organization'],
                    data['release']['tag_name'].replace('%V', self.version),
                    self.tarball)

    def install(self):
        if self.packages_dir == '':
            click.secho('Error: No such package \'{0}\''.format(self.package),
                        fg='red')
        elif self.version == '':
            click.secho('Error: No valid version found. Semantic {0}'.format(
                self.specversion),
                        fg='red')
        else:
            click.echo('Installing %s package:' %
                       click.style(self.package, fg='cyan'))
            if not isdir(self.packages_dir):
                makedirs(self.packages_dir)
            assert isdir(self.packages_dir)
            try:
                dlpath = None
                dlpath = self._download(self.download_url)
                if dlpath:
                    package_dir = join(self.packages_dir, self.package)
                    if isdir(package_dir):
                        shutil.rmtree(package_dir)
                    if self.uncompressed_name:
                        self._unpack(dlpath, self.packages_dir)
                    else:
                        self._unpack(
                            dlpath, join(self.packages_dir, self.package_name))
            except Exception as e:
                click.secho('Error: ' + str(e), fg='red')
            else:
                if dlpath:
                    remove(dlpath)
                    self.profile.add_package(self.package, self.version)
                    self.profile.save()
                    click.secho("""Package \'{}\' has been """
                                """successfully installed!""".format(
                                    self.package),
                                fg='green')

            # Rename unpacked dir to package dir
            if self.uncompressed_name:
                unpack_dir = join(self.packages_dir, self.uncompressed_name)
                package_dir = join(self.packages_dir, self.package_name)
                if isdir(unpack_dir):
                    rename(unpack_dir, package_dir)

    def uninstall(self):
        if self.packages_dir == '':
            click.secho('Error: No such package \'{0}\''.format(self.package),
                        fg='red')
        else:
            if isdir(join(self.packages_dir, self.package_name)):
                click.echo('Uninstalling %s package' %
                           click.style(self.package, fg='cyan'))
                shutil.rmtree(join(self.packages_dir, self.package_name))
                click.secho("""Package \'{}\' has been """
                            """successfully uninstalled!""".format(
                                self.package),
                            fg='green')
            else:
                click.secho('Package \'{0}\' is not installed'.format(
                    self.package),
                            fg='red')
            self.profile.remove_package(self.package)
            self.profile.save()

    def _get_platform(self):
        return get_systype()

    def _get_download_url(self, name, organization, tag, tarball):
        url = 'https://github.com/{0}/{1}/releases/download/{2}/{3}'.format(
            organization, name, tag, tarball)
        return url

    def _get_tarball_name(self, name, extension):
        tarball = '{0}.{1}'.format(name, extension)
        return tarball

    def _get_valid_version(self,
                           name,
                           organization,
                           tag_name,
                           version='',
                           specversion=''):
        # Check spec version
        try:
            spec = semantic_version.Spec(specversion)
        except ValueError:
            click.secho('Invalid distribution version {0}: {1}'.format(
                name, specversion),
                        fg='red')
            exit(1)

        # Download latest releases list
        releases = api_request('{}/releases'.format(name), organization)
        if releases is not None:
            for release in releases:
                if 'tag_name' in release:
                    if version:
                        # Version number via @
                        tag = tag_name.replace('%V', version)
                        if tag == release['tag_name']:
                            return self._check_sem_version(version, spec)
                    else:
                        pattern = tag_name.replace('%V', '(?P<v>.*?)') + '$'
                        match = re.search(pattern, release['tag_name'])
                        if match:
                            version = match.group('v')
                            return self._check_sem_version(version, spec)

    def _check_sem_version(self, version, spec):
        try:
            if semantic_version.Version(version) in spec:
                return version
        except ValueError:
            if version in str(spec):
                return version

    def _download(self, url):
        # Note: here we check only for the version of locally installed
        # packages. For this reason we don't say what's the installation
        # path.
        if self.profile.check_package_version(self.package, self.version) \
           or self.forced_install:
            fd = FileDownloader(url, self.packages_dir)
            filepath = fd.get_filepath()
            click.secho('Download ' + basename(filepath))
            try:
                fd.start()
            except KeyboardInterrupt:
                if isfile(filepath):
                    remove(filepath)
                click.secho('Abort download!', fg='red')
                exit(1)
            return filepath
        else:
            click.secho('Already installed. Version {0}'.format(
                self.profile.get_package_version(self.package)),
                        fg='yellow')
            return None

    def _unpack(self, pkgpath, pkgdir):
        fu = FileUnpacker(pkgpath, pkgdir)
        return fu.start()
Exemplo n.º 24
0
class Resources(object):

    def __init__(self, platform=''):
        self.packages = self._load_resource('packages')
        self.boards = self._load_resource('boards')
        self.fpgas = self._load_resource('fpgas')
        self.programmers = self._load_resource('programmers')
        self.distribution = self._load_resource('distribution')

        # Check available packages
        self.packages = self._check_packages(self.packages, platform)

        # Sort resources
        self.packages = OrderedDict(sorted(self.packages.items(),
                                           key=lambda t: t[0]))
        self.boards = OrderedDict(sorted(self.boards.items(),
                                         key=lambda t: t[0]))
        self.fpgas = OrderedDict(sorted(self.fpgas.items(),
                                        key=lambda t: t[0]))

    def _load_resource(self, name):
        resource = None
        filepath = util.safe_join(util.get_folder('resources'), name + '.json')
        with open(filepath, 'r') as f:
            # Load the JSON file
            resource = json.loads(f.read())
        return resource

    def get_package_release_name(self, package):
        return self.packages.get(package).get('release').get('package_name')

    def list_packages(self, installed=True, notinstalled=True):
        """Return a list with all the installed/notinstalled packages"""

        self.profile = Profile()

        # Classify packages
        installed_packages = []
        notinstalled_packages = []

        for package in self.packages:
            data = {
                'name': package,
                'version': None,
                'description': self.packages.get(package).get('description')
            }
            if package in self.profile.packages:
                data['version'] = self.profile.get_package_version(
                    package, self.get_package_release_name(package))
                installed_packages += [data]
            else:
                notinstalled_packages += [data]

        # Print tables
        terminal_width, _ = click.get_terminal_size()

        if installed and installed_packages:

            # - Print installed packages table
            click.echo('\nInstalled packages:\n')

            PACKAGELIST_TPL = ('{name:20} {description:30} {version:<8}')

            click.echo('-' * terminal_width)
            click.echo(PACKAGELIST_TPL.format(
                name=click.style('Name', fg='cyan'), version='Version',
                description='Description'))
            click.echo('-' * terminal_width)

            for package in installed_packages:
                click.echo(PACKAGELIST_TPL.format(
                    name=click.style(package.get('name'), fg='cyan'),
                    version=package.get('version'),
                    description=package.get('description')))

        if notinstalled and notinstalled_packages:

            # - Print not installed packages table
            click.echo('\nNot installed packages:\n')

            PACKAGELIST_TPL = ('{name:20} {description:30}')

            click.echo('-' * terminal_width)
            click.echo(PACKAGELIST_TPL.format(
                name=click.style('Name', fg='yellow'),
                description='Description'))
            click.echo('-' * terminal_width)

            for package in notinstalled_packages:
                click.echo(PACKAGELIST_TPL.format(
                    name=click.style(package.get('name'), fg='yellow'),
                    description=package.get('description')))

    def list_boards(self):
        """Return a list with all the supported boards"""

        # Print table
        click.echo('\nSupported boards:\n')

        BOARDLIST_TPL = ('{board:25} {fpga:20} {type:<5} {size:<5} {pack:<10}')
        terminal_width, _ = click.get_terminal_size()

        click.echo('-' * terminal_width)
        click.echo(BOARDLIST_TPL.format(
            board=click.style('Board', fg='cyan'), fpga='FPGA', type='Type',
            size='Size', pack='Pack'))
        click.echo('-' * terminal_width)

        for board in self.boards:
            fpga = self.boards.get(board).get('fpga')
            click.echo(BOARDLIST_TPL.format(
                board=click.style(board, fg='cyan'),
                fpga=fpga,
                type=self.fpgas.get(fpga).get('type'),
                size=self.fpgas.get(fpga).get('size'),
                pack=self.fpgas.get(fpga).get('pack')))

        click.secho(BOARDS_MSG, fg='green')

    def list_fpgas(self):
        """Return a list with all the supported FPGAs"""

        # Print table
        click.echo('\nSupported FPGAs:\n')

        FPGALIST_TPL = ('{fpga:30} {type:<5} {size:<5} {pack:<10}')
        terminal_width, _ = click.get_terminal_size()

        click.echo('-' * terminal_width)
        click.echo(FPGALIST_TPL.format(
            fpga=click.style('FPGA', fg='cyan'), type='Type',
            size='Size', pack='Pack'))
        click.echo('-' * terminal_width)

        for fpga in self.fpgas:
            click.echo(FPGALIST_TPL.format(
                fpga=click.style(fpga, fg='cyan'),
                type=self.fpgas.get(fpga).get('type'),
                size=self.fpgas.get(fpga).get('size'),
                pack=self.fpgas.get(fpga).get('pack')))

    def _check_packages(self, packages, current_platform=''):
        filtered_packages = {}
        for pkg in packages.keys():
            check = True
            release = packages.get(pkg).get('release')
            if 'available_platforms' in release:
                platforms = release.get('available_platforms')
                check = False
                current_platform = current_platform or util.get_systype()
                for platform in platforms:
                    check |= current_platform in platform
            if check:
                filtered_packages[pkg] = packages.get(pkg)
        return filtered_packages
Exemplo n.º 25
0
class Resources(object):
    def __init__(self, platform=''):
        self.packages = self._load_resource('packages')
        self.boards = self._load_resource('boards')
        self.fpgas = self._load_resource('fpgas')
        self.programmers = self._load_resource('programmers')
        self.distribution = self._load_resource('distribution')

        # Check available packages
        self.packages = self._check_packages(self.packages, platform)

        # Sort resources
        self.packages = OrderedDict(
            sorted(self.packages.items(), key=lambda t: t[0]))
        self.boards = OrderedDict(
            sorted(self.boards.items(), key=lambda t: t[0]))
        self.fpgas = OrderedDict(sorted(self.fpgas.items(),
                                        key=lambda t: t[0]))

    def _load_resource(self, name):
        resource = None
        filepath = util.safe_join(util.get_folder('resources'), name + '.json')
        with open(filepath, 'r') as f:
            # Load the JSON file
            resource = json.loads(f.read())
        return resource

    def get_package_release_name(self, package):
        return self.packages.get(package).get('release').get('package_name')

    def list_packages(self, installed=True, notinstalled=True):
        """Return a list with all the installed/notinstalled packages"""

        self.profile = Profile()

        # Classify packages
        installed_packages = []
        notinstalled_packages = []

        for package in self.packages:
            data = {
                'name': package,
                'version': None,
                'description': self.packages.get(package).get('description')
            }
            if package in self.profile.packages:
                data['version'] = self.profile.get_package_version(
                    package, self.get_package_release_name(package))
                installed_packages += [data]
            else:
                notinstalled_packages += [data]

        # Print tables
        terminal_width, _ = click.get_terminal_size()

        if installed and installed_packages:

            # - Print installed packages table
            click.echo('\nInstalled packages:\n')

            PACKAGELIST_TPL = ('{name:20} {description:30} {version:<8}')

            click.echo('-' * terminal_width)
            click.echo(
                PACKAGELIST_TPL.format(name=click.style('Name', fg='cyan'),
                                       version='Version',
                                       description='Description'))
            click.echo('-' * terminal_width)

            for package in installed_packages:
                click.echo(
                    PACKAGELIST_TPL.format(
                        name=click.style(package.get('name'), fg='cyan'),
                        version=package.get('version'),
                        description=package.get('description')))

        if notinstalled and notinstalled_packages:

            # - Print not installed packages table
            click.echo('\nNot installed packages:\n')

            PACKAGELIST_TPL = ('{name:20} {description:30}')

            click.echo('-' * terminal_width)
            click.echo(
                PACKAGELIST_TPL.format(name=click.style('Name', fg='yellow'),
                                       description='Description'))
            click.echo('-' * terminal_width)

            for package in notinstalled_packages:
                click.echo(
                    PACKAGELIST_TPL.format(
                        name=click.style(package.get('name'), fg='yellow'),
                        description=package.get('description')))

    def list_boards(self):
        """Return a list with all the supported boards"""

        # Print table
        click.echo('\nSupported boards:\n')

        BOARDLIST_TPL = ('{board:25} {fpga:20} {type:<5} {size:<5} {pack:<10}')
        terminal_width, _ = click.get_terminal_size()

        click.echo('-' * terminal_width)
        click.echo(
            BOARDLIST_TPL.format(board=click.style('Board', fg='cyan'),
                                 fpga='FPGA',
                                 type='Type',
                                 size='Size',
                                 pack='Pack'))
        click.echo('-' * terminal_width)

        for board in self.boards:
            fpga = self.boards.get(board).get('fpga')
            click.echo(
                BOARDLIST_TPL.format(board=click.style(board, fg='cyan'),
                                     fpga=fpga,
                                     type=self.fpgas.get(fpga).get('type'),
                                     size=self.fpgas.get(fpga).get('size'),
                                     pack=self.fpgas.get(fpga).get('pack')))

        click.secho(BOARDS_MSG, fg='green')

    def list_fpgas(self):
        """Return a list with all the supported FPGAs"""

        # Print table
        click.echo('\nSupported FPGAs:\n')

        FPGALIST_TPL = ('{fpga:30} {type:<5} {size:<5} {pack:<10}')
        terminal_width, _ = click.get_terminal_size()

        click.echo('-' * terminal_width)
        click.echo(
            FPGALIST_TPL.format(fpga=click.style('FPGA', fg='cyan'),
                                type='Type',
                                size='Size',
                                pack='Pack'))
        click.echo('-' * terminal_width)

        for fpga in self.fpgas:
            click.echo(
                FPGALIST_TPL.format(fpga=click.style(fpga, fg='cyan'),
                                    type=self.fpgas.get(fpga).get('type'),
                                    size=self.fpgas.get(fpga).get('size'),
                                    pack=self.fpgas.get(fpga).get('pack')))

    def _check_packages(self, packages, current_platform=''):
        filtered_packages = {}
        for pkg in packages.keys():
            check = True
            release = packages.get(pkg).get('release')
            if 'available_platforms' in release:
                platforms = release.get('available_platforms')
                check = False
                current_platform = current_platform or util.get_systype()
                for platform in platforms:
                    check |= current_platform in platform
            if check:
                filtered_packages[pkg] = packages.get(pkg)
        return filtered_packages
Exemplo n.º 26
0
class Drivers(object):  # pragma: no cover

    # FTDI rules files paths
    ftdi_rules_local_path = util.safe_join(
        util.get_folder('resources'), '80-fpga-ftdi.rules')
    ftdi_rules_system_path = '/etc/udev/rules.d/80-fpga-ftdi.rules'
    old_ftdi_rules_system_path = '/etc/udev/rules.d/80-icestick.rules'

    # Serial rules files paths
    serial_rules_local_path = util.safe_join(
        util.get_folder('resources'), '80-fpga-serial.rules')
    serial_rules_system_path = '/etc/udev/rules.d/80-fpga-serial.rules'

    # Driver to restore: mac os
    driverC = ''

    def ftdi_enable(self):
        if 'linux' in platform:
            return self._ftdi_enable_linux()
        elif 'darwin' in platform:
            self._setup_darwin()
            return self._ftdi_enable_darwin()
        elif 'windows' in platform:
            self._setup_windows()
            return self._ftdi_enable_windows()

    def ftdi_disable(self):
        if 'linux' in platform:
            return self._ftdi_disable_linux()
        elif 'darwin' in platform:
            self._setup_darwin()
            return self._ftdi_disable_darwin()
        elif 'windows' in platform:
            self._setup_windows()
            return self._ftdi_disable_windows()

    def serial_enable(self):
        if 'linux' in platform:
            return self._serial_enable_linux()
        elif 'darwin' in platform:
            self._setup_darwin()
            return self._serial_enable_darwin()
        elif 'windows' in platform:
            self._setup_windows()
            return self._serial_enable_windows()

    def serial_disable(self):
        if 'linux' in platform:
            return self._serial_disable_linux()
        elif 'darwin' in platform:
            self._setup_darwin()
            return self._serial_disable_darwin()
        elif 'windows' in platform:
            self._setup_windows()
            return self._serial_disable_windows()

    def pre_upload(self):
        if 'darwin' in platform:
            self._setup_darwin()
            self._pre_upload_darwin()

    def post_upload(self):
        if 'darwin' in platform:
            self._setup_darwin()
            self._post_upload_darwin()

    def _setup_darwin(self):
        self.profile = Profile()

    def _setup_windows(self):
        profile = Profile()
        resources = Resources()

        self.name = 'drivers'
        self.version = util.get_package_version(self.name, profile)
        self.spec_version = util.get_package_spec_version(self.name, resources)

    def _ftdi_enable_linux(self):
        click.secho('Configure FTDI drivers for FPGA')
        if not isfile(self.ftdi_rules_system_path):
            subprocess.call(['sudo', 'cp',
                             self.ftdi_rules_local_path,
                             self.ftdi_rules_system_path])
            self._reload_rules()
            click.secho('FTDI drivers enabled', fg='green')
            click.secho('Unplug and reconnect your board', fg='yellow')
        else:
            click.secho('Already enabled', fg='yellow')

    def _ftdi_disable_linux(self):
        if isfile(self.old_ftdi_rules_system_path):
            subprocess.call(['sudo', 'rm', self.old_ftdi_rules_system_path])
        if isfile(self.ftdi_rules_system_path):
            click.secho('Revert FTDI drivers configuration')
            subprocess.call(['sudo', 'rm', self.ftdi_rules_system_path])
            self._reload_rules()
            click.secho('FTDI drivers disabled', fg='green')
            click.secho('Unplug and reconnect your board', fg='yellow')
        else:
            click.secho('Already disabled', fg='yellow')

    def _serial_enable_linux(self):
        click.secho('Configure Serial drivers for FPGA')
        if not isfile(self.serial_rules_system_path):
            group_added = self._add_dialout_group()
            subprocess.call(['sudo', 'cp',
                            self.serial_rules_local_path,
                            self.serial_rules_system_path])
            self._reload_rules()
            click.secho('Serial drivers enabled', fg='green')
            click.secho('Unplug and reconnect your board', fg='yellow')
            if group_added:
                click.secho('Restart your machine to enable the dialout group',
                            fg='yellow')
        else:
            click.secho('Already enabled', fg='yellow')

    def _serial_disable_linux(self):
        if isfile(self.serial_rules_system_path):
            click.secho('Revert Serial drivers configuration')
            subprocess.call(['sudo', 'rm', self.serial_rules_system_path])
            self._reload_rules()
            click.secho('Serial drivers disabled', fg='green')
            click.secho('Unplug and reconnect your board', fg='yellow')
        else:
            click.secho('Already disabled', fg='yellow')

    def _reload_rules(self):
        subprocess.call(['sudo', 'udevadm', 'control', '--reload-rules'])
        subprocess.call(['sudo', 'udevadm', 'trigger'])
        subprocess.call(['sudo', 'service', 'udev', 'restart'])

    def _add_dialout_group(self):
        groups = subprocess.check_output('groups')
        if 'dialout' not in groups:
            subprocess.call('sudo usermod -a -G dialout $USER', shell=True)
            return True

    def _ftdi_enable_darwin(self):
        # Check homebrew
        brew = subprocess.call('which brew > /dev/null', shell=True)
        if brew != 0:
            click.secho('Error: homebrew is required', fg='red')
        else:
            click.secho('Enable FTDI drivers for FPGA')
            subprocess.call(['brew', 'update'])
            self._brew_install('libffi')
            self._brew_install('libftdi')
            self.profile.add_setting('macos_ftdi_drivers', True)
            self.profile.save()
            click.secho('FTDI drivers enabled', fg='green')

    def _ftdi_disable_darwin(self):
        click.secho('Disable FTDI drivers configuration')
        self.profile.add_setting('macos_ftdi_drivers', False)
        self.profile.save()
        click.secho('FTDI drivers disabled', fg='green')

    def _serial_enable_darwin(self):
        # Check homebrew
        brew = subprocess.call('which brew > /dev/null', shell=True)
        if brew != 0:
            click.secho('Error: homebrew is required', fg='red')
        else:
            click.secho('Enable Serial drivers for FPGA')
            subprocess.call(['brew', 'update'])
            self._brew_install('libffi')
            self._brew_install('libusb')
            # self._brew_install_serial_drivers()
            click.secho('Serial drivers enabled', fg='green')

    def _serial_disable_darwin(self):
        click.secho('Disable Serial drivers configuration')
        click.secho('Serial drivers disabled', fg='green')

    def _brew_install(self, package):
        subprocess.call(['brew', 'install', '--force', package])
        subprocess.call(['brew', 'unlink', package])
        subprocess.call(['brew', 'link', '--force', package])

    def _brew_install_serial_drivers(self):
        subprocess.call(
            ['brew', 'tap', 'mengbo/ch340g-ch34g-ch34x-mac-os-x-driver',
             'https://github.com/mengbo/ch340g-ch34g-ch34x-mac-os-x-driver'])
        subprocess.call(
            ['brew', 'cask', 'install', 'wch-ch34x-usb-serial-driver'])

    def _pre_upload_darwin(self):
        if self.profile.settings.get('macos_ftdi_drivers', False):
            # Check and unload the drivers
            driverA = 'com.FTDI.driver.FTDIUSBSerialDriver'
            driverB = 'com.apple.driver.AppleUSBFTDI'
            if self._check_ftdi_driver_darwin(driverA):
                subprocess.call(['sudo', 'kextunload', '-b', driverA])
                self.driverC = driverA
            elif self._check_ftdi_driver_darwin(driverB):
                subprocess.call(['sudo', 'kextunload', '-b', driverB])
                self.driverC = driverB

    def _post_upload_darwin(self):
        if self.profile.settings.get('macos_ftdi_drivers', False):
            # Restore previous driver configuration
            if self.driverC:
                subprocess.call(['sudo', 'kextload', '-b', self.driverC])

    def _check_ftdi_driver_darwin(self, driver):
        return driver in str(subprocess.check_output(['kextstat']))

    def _ftdi_enable_windows(self):
        drivers_base_dir = util.get_package_dir('tools-drivers')
        drivers_bin_dir = util.safe_join(drivers_base_dir, 'bin')
        drivers_share_dir = util.safe_join(drivers_base_dir, 'share')
        zadig_ini_path = util.safe_join(drivers_share_dir, 'zadig.ini')
        zadig_ini = 'zadig.ini'

        try:
            if util.check_package(
                self.name,
                self.version,
                self.spec_version,
                drivers_bin_dir
            ):
                click.secho('Launch drivers configuration tool')
                click.secho(FTDI_INSTALL_DRIVER_INSTRUCTIONS, fg='yellow')
                # Copy zadig.ini
                with open(zadig_ini, 'w') as ini_file:
                    with open(zadig_ini_path, 'r') as local_ini_file:
                        ini_file.write(local_ini_file.read())

                result = util.exec_command(
                    util.safe_join(drivers_bin_dir, 'zadig.exe'))
                click.secho('FTDI drivers configuration finished',
                            fg='green')
            else:
                result = 1
        except Exception as e:
            click.secho('Error: ' + str(e), fg='red')
            result = 1
        finally:
            # Remove zadig.ini
            if isfile(zadig_ini):
                os.remove(zadig_ini)

        if not isinstance(result, int):
            result = result.get('returncode')
        return result

    def _ftdi_disable_windows(self):
        click.secho('Launch device manager')
        click.secho(FTDI_UNINSTALL_DRIVER_INSTRUCTIONS, fg='yellow')

        result = util.exec_command('mmc devmgmt.msc')
        return result.get('returncode')

    def _serial_enable_windows(self):
        drivers_base_dir = util.get_package_dir('tools-drivers')
        drivers_bin_dir = util.safe_join(drivers_base_dir, 'bin')

        try:
            if util.check_package(
                self.name,
                self.version,
                self.spec_version,
                drivers_bin_dir
            ):
                click.secho('Launch drivers configuration tool')
                click.secho(SERIAL_INSTALL_DRIVER_INSTRUCTIONS, fg='yellow')
                result = util.exec_command(
                    util.safe_join(drivers_bin_dir, 'serial_install.exe'))
                click.secho('Serial drivers configuration finished',
                            fg='green')
            else:
                result = 1
        except Exception as e:
            click.secho('Error: ' + str(e), fg='red')
            result = 1

        if not isinstance(result, int):
            result = result.get('returncode')
        return result

    def _serial_disable_windows(self):
        click.secho('Launch device manager')
        click.secho(SERIAL_UNINSTALL_DRIVER_INSTRUCTIONS, fg='yellow')

        result = util.exec_command('mmc devmgmt.msc')
        return result.get('returncode')
Exemplo n.º 27
0
 def post_upload(self):
     if 'darwin' in platform:
         self.profile = Profile()
         self._post_upload_darwin()
Exemplo n.º 28
0
class Resources(object):
    def __init__(self):
        self.packages = self._load_resource('packages')
        self.boards = self._load_resource('boards')
        self.fpgas = self._load_resource('fpgas')

    def _load_resource(self, name):
        resource = None
        filepath = os.path.join(os.path.dirname(__file__), 'resources',
                                name + '.json')
        with open(filepath, 'r') as f:
            # Load the JSON file
            resource = json.loads(f.read())
        return resource

    def list_packages(self, installed=True, notinstalled=True):
        """Return a list with all the installed/notinstalled packages"""

        self.profile = Profile()

        # Classify packages
        installed_packages = []
        notinstalled_packages = []

        for package in self.packages:
            data = {
                'name': package,
                'version': None,
                'description': self.packages[package]['description']
            }
            if self.profile.check_package(package):
                data['version'] = self.profile.get_version(package)
                installed_packages += [data]
            else:
                notinstalled_packages += [data]

        # Print tables
        terminal_width, _ = click.get_terminal_size()

        if installed and installed_packages:

            # - Print installed packages table
            click.echo('\nInstalled packages:\n')

            PACKAGELIST_TPL = ('{name:20} {description:30} {version:<8}')

            click.echo('-' * terminal_width)
            click.echo(
                PACKAGELIST_TPL.format(name=click.style('Name', fg='cyan'),
                                       version='Version',
                                       description='Description'))
            click.echo('-' * terminal_width)

            for package in installed_packages:
                click.echo(
                    PACKAGELIST_TPL.format(name=click.style(package['name'],
                                                            fg='cyan'),
                                           version=package['version'],
                                           description=package['description']))

        if notinstalled and notinstalled_packages:

            # - Print not installed packages table
            click.echo('\nNot installed packages:\n')

            PACKAGELIST_TPL = ('{name:20} {description:30}')

            click.echo('-' * terminal_width)
            click.echo(
                PACKAGELIST_TPL.format(name=click.style('Name', fg='yellow'),
                                       description='Description'))
            click.echo('-' * terminal_width)

            for package in notinstalled_packages:
                click.echo(
                    PACKAGELIST_TPL.format(name=click.style(package['name'],
                                                            fg='yellow'),
                                           description=package['description']))

    def list_boards(self):
        """Return a list with all the supported boards"""

        # Print table
        click.echo('\nSupported boards:\n')

        BOARDLIST_TPL = ('{board:22} {fpga:20} {type:<5} {size:<5} {pack:<10}')
        terminal_width, _ = click.get_terminal_size()

        click.echo('-' * terminal_width)
        click.echo(
            BOARDLIST_TPL.format(board=click.style('Board', fg='cyan'),
                                 fpga='FPGA',
                                 type='Type',
                                 size='Size',
                                 pack='Pack'))
        click.echo('-' * terminal_width)

        for board in self.boards:
            fpga = self.boards[board]['fpga']
            click.echo(
                BOARDLIST_TPL.format(board=click.style(board, fg='cyan'),
                                     fpga=fpga,
                                     type=self.fpgas[fpga]['type'],
                                     size=self.fpgas[fpga]['size'],
                                     pack=self.fpgas[fpga]['pack']))

        click.secho(BOARDS_MSG, fg='green')

    def list_fpgas(self):
        """Return a list with all the supported FPGAs"""

        # Print table
        click.echo('\nSupported FPGAs:\n')

        FPGALIST_TPL = ('{fpga:30} {type:<5} {size:<5} {pack:<10}')
        terminal_width, _ = click.get_terminal_size()

        click.echo('-' * terminal_width)
        click.echo(
            FPGALIST_TPL.format(fpga=click.style('FPGA', fg='cyan'),
                                type='Type',
                                size='Size',
                                pack='Pack'))
        click.echo('-' * terminal_width)

        for fpga in self.fpgas:
            click.echo(
                FPGALIST_TPL.format(fpga=click.style(fpga, fg='cyan'),
                                    type=self.fpgas[fpga]['type'],
                                    size=self.fpgas[fpga]['size'],
                                    pack=self.fpgas[fpga]['pack']))
Exemplo n.º 29
0
class Installer(object):

    def __init__(self, package, platform='', force=False, checkversion=True):

        # Parse version
        if '@' in package:
            split = package.split('@')
            self.package = split[0]
            self.version = split[1]
        else:
            self.package = package
            self.version = None

        self.force_install = force
        self.packages_dir = ''

        self.resources = Resources(platform)

        if self.package in self.resources.packages:

            self.profile = Profile()

            dirname = 'packages'
            self.packages_dir = util.safe_join(util.get_home_dir(), dirname)

            # Get data
            data = self.resources.packages.get(self.package)
            distribution = self.resources.distribution

            self.spec_version = distribution.get('packages').get(self.package)
            self.package_name = data.get('release').get('package_name')
            self.extension = data.get('release').get('extension')
            platform = platform or self._get_platform()

            if checkversion:
                # Check version
                valid_version = self._get_valid_version(
                    data.get('repository').get('name'),
                    data.get('repository').get('organization'),
                    data.get('release').get('tag_name')
                )
                # Valid version
                if not valid_version:
                    # Error
                    click.secho('Error: no valid version found', fg='red')
                    exit(1)

                self.version = valid_version

                # e.g., [linux_x86_64, linux]
                platform_os = platform.split('_')[0]
                self.download_urls = [
                    {
                        'url': self.get_download_url(data, platform),
                        'platform': platform
                    },
                    {
                        'url': self.get_download_url(data, platform_os),
                        'platform': platform_os
                    }
                ]

        if self.packages_dir == '':
            click.secho(
                'Error: no such package \'{}\''.format(self.package),
                fg='red')
            exit(1)

    def get_download_url(self, data, platform):
        compressed_name = data.get('release').get('compressed_name')
        self.compressed_name = compressed_name.replace(
            '%V', self.version).replace('%P', platform)
        uncompressed_name = data.get('release').get('uncompressed_name')
        self.uncompressed_name = uncompressed_name.replace(
            '%V', self.version).replace('%P', platform)

        tarball = self._get_tarball_name(
            self.compressed_name,
            self.extension
        )

        download_url = self._get_download_url(
            data.get('repository').get('name'),
            data.get('repository').get('organization'),
            data.get('release').get('tag_name').replace(
                '%V', self.version),
            tarball
        )

        return download_url

    def install(self):
        click.echo('Installing %s package:' % click.style(
            self.package, fg='cyan'))
        if not isdir(self.packages_dir):
            makedirs(self.packages_dir)
        assert isdir(self.packages_dir)
        dlpath = None
        try:
            # Try full platform
            platform_download_url = self.download_urls[0].get('url')
            dlpath = self._download(platform_download_url)
        except IOError as e:
            click.secho('Warning: permission denied in packages directory',
                        fg='yellow')
            click.secho(str(e), fg='red')
        except Exception:
            # Try os name
            dlpath = self._install_os_package(platform_download_url)

        # Install downloaded package
        self._install_package(dlpath)

        # Rename unpacked dir to package dir
        self._rename_unpacked_dir()

    def _install_os_package(self, platform_download_url):
        os_download_url = self.download_urls[1].get('url')
        if platform_download_url != os_download_url:
            click.secho(
                'Warning: full platform does not match: {}\
                '.format(self.download_urls[0].get('platform')),
                fg='yellow')
            click.secho(
                '         Trying OS name: {}\
                '.format(self.download_urls[1].get('platform')),
                fg='yellow')
            try:
                return self._download(os_download_url)
            except Exception as e:
                click.secho(
                    'Error: {}'.format(str(e)),
                    fg='red')
        else:
            click.secho(
                'Error: package not availabe for this platform',
                fg='red')

    def _install_package(self, dlpath):
        if dlpath:
            package_dir = util.safe_join(
                self.packages_dir, self.package_name)
            if isdir(package_dir):
                shutil.rmtree(package_dir)
            if self.uncompressed_name:
                self._unpack(dlpath, self.packages_dir)
            else:
                self._unpack(dlpath, util.safe_join(
                    self.packages_dir, self.package_name))

            remove(dlpath)
            self.profile.add_package(self.package, self.version)
            self.profile.save()
            click.secho(
                """Package \'{}\' has been """
                """successfully installed!""".format(self.package),
                fg='green')

    def _rename_unpacked_dir(self):
        if self.uncompressed_name:
            unpack_dir = util.safe_join(
                self.packages_dir, self.uncompressed_name)
            package_dir = util.safe_join(
                self.packages_dir, self.package_name)
            if isdir(unpack_dir):
                rename(unpack_dir, package_dir)

    def uninstall(self):
        if isdir(util.safe_join(self.packages_dir, self.package_name)):
            click.echo('Uninstalling %s package:' % click.style(
                self.package, fg='cyan'))
            shutil.rmtree(
                util.safe_join(self.packages_dir, self.package_name))
            click.secho(
                """Package \'{}\' has been """
                """successfully uninstalled!""".format(self.package),
                fg='green')
        else:
            util.show_package_path_error(self.package)
        self.profile.remove_package(self.package)
        self.profile.save()

    def _get_platform(self):
        return util.get_systype()

    def _get_download_url(self, name, organization, tag, tarball):
        url = 'https://github.com/{0}/{1}/releases/download/{2}/{3}'.format(
            organization,
            name,
            tag,
            tarball)
        return url

    def _get_tarball_name(self, name, extension):
        tarball = '{0}.{1}'.format(
            name,
            extension)
        return tarball

    def _get_valid_version(self, rel_name, organization, tag_name):

        # Download latest releases list
        releases = api_request('{}/releases'.format(rel_name), organization)

        if self.version:
            # Find required version via @
            if not util.check_package_version(self.version, self.spec_version):
                util.show_package_version_warning(
                    self.package, self.version, self.spec_version)
                exit(1)
            return self._find_required_version(
                releases, tag_name, self.version, self.spec_version)
        else:
            # Find latest version release
            return self._find_latest_version(
                releases, tag_name, self.spec_version)

    def _find_required_version(self, releases, tag_name, req_v, spec_v):
        for release in releases:
            if 'tag_name' in release:
                tag = tag_name.replace('%V', req_v)
                if tag == release.get('tag_name'):
                    prerelease = release.get('prerelease', False)
                    if prerelease and not self.force_install:
                        click.secho(
                            'Warning: ' + req_v + ' is' +
                            ' a pre-release. Use --force to install',
                            fg='yellow')
                        exit(1)
                    return req_v

    def _find_latest_version(self, releases, tag_name, spec_v):
        for release in releases:
            if 'tag_name' in release:
                pattern = tag_name.replace('%V', '(?P<v>.*?)') + '$'
                match = re.search(pattern, release.get('tag_name'))
                if match:
                    prerelease = release.get('prerelease', False)
                    if not prerelease:
                        version = match.group('v')
                        if util.check_package_version(version, spec_v):
                            return version

    def _download(self, url):
        # Note: here we check only for the version of locally installed
        # packages. For this reason we don't say what's the installation
        # path.
        if not self.profile.installed_version(self.package, self.version) \
           or self.force_install:
            fd = FileDownloader(url, self.packages_dir)
            filepath = fd.get_filepath()
            click.secho('Download ' + basename(filepath))
            try:
                fd.start()
            except KeyboardInterrupt:
                if isfile(filepath):
                    remove(filepath)
                click.secho('Abort download!', fg='red')
                exit(1)
            return filepath
        else:
            click.secho('Already installed. Version {0}'.format(
                self.profile.get_package_version(self.package)), fg='yellow')
            return None

    def _unpack(self, pkgpath, pkgdir):
        fu = FileUnpacker(pkgpath, pkgdir)
        return fu.start()
Exemplo n.º 30
0
class Installer(object):

    def __init__(self, package, platform='', force=False, checkversion=True):

        # Parse version
        if '@' in package:
            split = package.split('@')
            self.package = split[0]
            self.version = split[1]
        else:
            self.package = package
            self.version = None

        self.force_install = force
        self.packages_dir = ''

        self.resources = Resources(platform)

        if self.package in self.resources.packages:

            self.profile = Profile()

            dirname = 'packages'
            self.packages_dir = util.safe_join(util.get_home_dir(), dirname)

            # Get data
            data = self.resources.packages.get(self.package)
            distribution = self.resources.distribution

            self.specversion = distribution.get('packages').get(self.package)
            self.package_name = data.get('release').get('package_name')
            self.extension = data.get('release').get('extension')
            platform = platform or self._get_platform()

            if checkversion:
                # Check version
                valid_version = self._get_valid_version(
                    data.get('repository').get('name'),
                    data.get('repository').get('organization'),
                    data.get('release').get('tag_name'),
                    self.version,
                    self.specversion,
                    force
                )
                # Valid version
                if not valid_version:
                    # Error
                    click.secho(
                        'Error: No version {} found'.format(self.version),
                        fg='red')
                    exit(1)

                self.version = valid_version

                # e.g., [linux_x86_64, linux]
                platform_os = platform.split('_')[0]
                self.download_urls = [
                    {
                        'url': self.get_download_url(data, platform),
                        'platform': platform
                    },
                    {
                        'url': self.get_download_url(data, platform_os),
                        'platform': platform_os
                    }
                ]

        if self.packages_dir == '':
            click.secho(
                'Error: No such package \'{0}\''.format(self.package),
                fg='red')
            exit(1)

    def get_download_url(self, data, platform):
        compressed_name = data.get('release').get('compressed_name')
        self.compressed_name = compressed_name.replace(
            '%V', self.version).replace('%P', platform)
        uncompressed_name = data.get('release').get('uncompressed_name')
        self.uncompressed_name = uncompressed_name.replace(
            '%V', self.version).replace('%P', platform)

        tarball = self._get_tarball_name(
            self.compressed_name,
            self.extension
        )

        download_url = self._get_download_url(
            data.get('repository').get('name'),
            data.get('repository').get('organization'),
            data.get('release').get('tag_name').replace(
                '%V', self.version),
            tarball
        )

        return download_url

    def install(self):
        click.echo('Installing %s package:' % click.style(
            self.package, fg='cyan'))
        if not isdir(self.packages_dir):
            makedirs(self.packages_dir)
        assert isdir(self.packages_dir)
        dlpath = None
        try:
            # Try full platform
            platform_download_url = self.download_urls[0].get('url')
            dlpath = self._download(platform_download_url)
        except IOError as e:
            click.secho('Warning: permission denied in packages directory',
                        fg='yellow')
            click.secho(str(e), fg='red')
        except Exception as e:
            # Try os name
            dlpath = self._install_os_package(platform_download_url)

        # Install downloaded package
        self._install_package(dlpath)

        # Rename unpacked dir to package dir
        self._rename_unpacked_dir()

    def _install_os_package(self, platform_download_url):
        os_download_url = self.download_urls[1].get('url')
        if platform_download_url != os_download_url:
            click.secho(
                'Warning: full platform does not match: {}\
                '.format(self.download_urls[0].get('platform')),
                fg='yellow')
            click.secho(
                '         Trying OS name: {}\
                '.format(self.download_urls[1].get('platform')),
                fg='yellow')
            try:
                return self._download(os_download_url)
            except Exception as e:
                click.secho(
                    'Error: {}'.format(str(e)),
                    fg='red')
        else:
            click.secho(
                'Error: package not availabe for this platform',
                fg='red')

    def _install_package(self, dlpath):
        if dlpath:
            package_dir = util.safe_join(
                self.packages_dir, self.package_name)
            if isdir(package_dir):
                shutil.rmtree(package_dir)
            if self.uncompressed_name:
                self._unpack(dlpath, self.packages_dir)
            else:
                self._unpack(dlpath, util.safe_join(
                    self.packages_dir, self.package_name))

            remove(dlpath)
            self.profile.add_package(self.package, self.version)
            self.profile.save()
            click.secho(
                """Package \'{}\' has been """
                """successfully installed!""".format(self.package),
                fg='green')

    def _rename_unpacked_dir(self):
        if self.uncompressed_name:
            unpack_dir = util.safe_join(
                self.packages_dir, self.uncompressed_name)
            package_dir = util.safe_join(
                self.packages_dir, self.package_name)
            if isdir(unpack_dir):
                rename(unpack_dir, package_dir)

    def uninstall(self):
        if isdir(util.safe_join(self.packages_dir, self.package_name)):
            click.echo('Uninstalling %s package' % click.style(
                self.package, fg='cyan'))
            shutil.rmtree(
                util.safe_join(self.packages_dir, self.package_name))
            click.secho(
                """Package \'{}\' has been """
                """successfully uninstalled!""".format(self.package),
                fg='green')
        else:
            click.secho('Package \'{0}\' is not installed'.format(
                self.package), fg='red')
        self.profile.remove_package(self.package)
        self.profile.save()

    def _get_platform(self):
        return util.get_systype()

    def _get_download_url(self, name, organization, tag, tarball):
        url = 'https://github.com/{0}/{1}/releases/download/{2}/{3}'.format(
            organization,
            name,
            tag,
            tarball)
        return url

    def _get_tarball_name(self, name, extension):
        tarball = '{0}.{1}'.format(
            name,
            extension)
        return tarball

    def _get_valid_version(self, name, organization, tag_name,
                           req_version='', specversion='', force=False):
        # Check spec version
        try:
            spec = semantic_version.Spec(specversion)
        except ValueError:
            click.secho('Invalid distribution version {0}: {1}'.format(
                        name, specversion), fg='red')
            exit(1)

        # Download latest releases list
        releases = api_request('{}/releases'.format(name), organization)

        if req_version:
            # Find required version via @
            return self._find_required_version(
                releases, tag_name, req_version, spec, force)
        else:
            # Find latest version release
            return self._find_latest_version(
                releases, tag_name, req_version, spec)

    def _find_required_version(self, releases, tag_name, req_version, spec,
                               force):
        version = self._check_sem_version(req_version, spec)
        for release in releases:
            prerelease = 'prerelease' in release and release.get('prerelease')
            if 'tag_name' in release:
                tag = tag_name.replace('%V', req_version)
                if tag == release.get('tag_name'):
                    if prerelease and not force:
                        click.secho(
                            'Warning: ' + req_version + ' is' +
                            ' a pre-release.\n' +
                            '         Use --force to install',
                            fg='yellow')
                        exit(2)
                    return version

    def _find_latest_version(self, releases, tag_name, req_version, spec):
        for release in releases:
            prerelease = 'prerelease' in release and release.get('prerelease')
            if 'tag_name' in release:
                pattern = tag_name.replace('%V', '(?P<v>.*?)') + '$'
                match = re.search(pattern, release.get('tag_name'))
                if match:
                    if not prerelease:
                        version = match.group('v')
                        return self._check_sem_version(version, spec)

    def _check_sem_version(self, version, spec):
        try:
            if semantic_version.Version(version) in spec:
                return version
            else:
                click.secho(
                    'Error: Invalid semantic version ({0})'.format(
                        self.specversion),
                    fg='red')
                exit(1)
        except ValueError:
            click.secho(
                'Error: Invalid semantic version ({0})'.format(
                    self.specversion),
                fg='red')
            exit(1)

    def _download(self, url):
        # Note: here we check only for the version of locally installed
        # packages. For this reason we don't say what's the installation
        # path.
        if self.profile.check_package_version(self.package, self.version) \
           or self.force_install:
            fd = FileDownloader(url, self.packages_dir)
            filepath = fd.get_filepath()
            click.secho('Download ' + basename(filepath))
            try:
                fd.start()
            except KeyboardInterrupt:
                if isfile(filepath):
                    remove(filepath)
                click.secho('Abort download!', fg='red')
                exit(1)
            return filepath
        else:
            click.secho('Already installed. Version {0}'.format(
                self.profile.get_package_version(self.package)), fg='yellow')
            return None

    def _unpack(self, pkgpath, pkgdir):
        fu = FileUnpacker(pkgpath, pkgdir)
        return fu.start()
Exemplo n.º 31
0
    def __init__(self, package):

        # Parse version
        if '@' in package:
            split = package.split('@')
            self.package = split[0]
            self.version = split[1]
        else:
            self.package = package
            self.version = None

        self.forced_install = False
        self.valid_version = True

        self.resources = Resources()
        self.profile = Profile()

        if self.package in self.resources.packages:

            data = self.resources.packages[self.package]

            if self.version:
                # Validate version
                valid = self._validate_version(
                    data['repository']['name'],
                    data['repository']['organization'],
                    data['release']['tag_name'],
                    self.version
                )
                if valid:
                    self.forced_install = True
                else:
                    self.valid_version = False
            else:
                # Get latest version
                self.version = self._get_latest_version(
                    data['repository']['name'],
                    data['repository']['organization'],
                    data['release']['tag_name']
                )

            self.arch = self._get_architecture()

            release = data['release']
            self.compressed_name = release['compressed_name'].replace(
                '%V', self.version).replace('%A', self.arch)
            self.uncompressed_name = release['uncompressed_name'].replace(
                '%V', self.version).replace('%A', self.arch)
            self.package_name = data['release']['package_name']

            if isinstance(data['release']['extension'], dict):
                for os in ['linux', 'darwin', 'windows']:
                    if os in self.arch:
                        self.extension = data['release']['extension'][os]
            else:
                self.extension = data['release']['extension']

            self.tarball = self._get_tarball_name(
                self.compressed_name,
                self.extension
            )

            self.download_url = self._get_download_url(
                data['repository']['name'],
                data['repository']['organization'],
                data['release']['tag_name'].replace('%V', self.version),
                self.tarball
            )

            if 'main_dir' in data.keys():
                self.packages_dir = join(expanduser('~'), data['main_dir'])
            else:
                self.packages_dir = join(util.get_home_dir(), 'packages')
Exemplo n.º 32
0
    def list_packages(self, installed=True, notinstalled=True):
        """Return a list with all the installed/notinstalled packages"""

        self.profile = Profile()

        # Classify packages
        installed_packages = []
        notinstalled_packages = []

        for package in self.packages:
            data = {
                'name': package,
                'version': None,
                'description': self.packages.get(package).get('description')
            }
            if package in self.profile.packages:
                data['version'] = self.profile.get_package_version(
                    package, self.get_package_release_name(package))
                installed_packages += [data]
            else:
                notinstalled_packages += [data]

        # Print tables
        terminal_width, _ = click.get_terminal_size()

        if installed and installed_packages:

            # - Print installed packages table
            click.echo('\nInstalled packages:\n')

            PACKAGELIST_TPL = ('{name:20} {description:30} {version:<8}')

            click.echo('-' * terminal_width)
            click.echo(PACKAGELIST_TPL.format(
                name=click.style('Name', fg='cyan'), version='Version',
                description='Description'))
            click.echo('-' * terminal_width)

            for package in installed_packages:
                click.echo(PACKAGELIST_TPL.format(
                    name=click.style(package.get('name'), fg='cyan'),
                    version=package.get('version'),
                    description=package.get('description')))

        if notinstalled and notinstalled_packages:

            # - Print not installed packages table
            click.echo('\nNot installed packages:\n')

            PACKAGELIST_TPL = ('{name:20} {description:30}')

            click.echo('-' * terminal_width)
            click.echo(PACKAGELIST_TPL.format(
                name=click.style('Name', fg='yellow'),
                description='Description'))
            click.echo('-' * terminal_width)

            for package in notinstalled_packages:
                click.echo(PACKAGELIST_TPL.format(
                    name=click.style(package.get('name'), fg='yellow'),
                    description=package.get('description')))
Exemplo n.º 33
0
    def __init__(self, package, platform='', force=False, checkversion=True):

        # Parse version
        if '@' in package:
            split = package.split('@')
            self.package = split[0]
            self.version = split[1]
        else:
            self.package = package
            self.version = None

        self.force_install = force
        self.packages_dir = ''

        self.resources = Resources(platform)

        if self.package in self.resources.packages:

            self.profile = Profile()

            dirname = 'packages'
            self.packages_dir = util.safe_join(util.get_home_dir(), dirname)

            # Get data
            data = self.resources.packages.get(self.package)
            distribution = self.resources.distribution

            self.specversion = distribution.get('packages').get(self.package)
            self.package_name = data.get('release').get('package_name')
            self.extension = data.get('release').get('extension')
            platform = platform or self._get_platform()

            if checkversion:
                # Check version
                valid_version = self._get_valid_version(
                    data.get('repository').get('name'),
                    data.get('repository').get('organization'),
                    data.get('release').get('tag_name'),
                    self.version,
                    self.specversion,
                    force
                )
                # Valid version
                if not valid_version:
                    # Error
                    click.secho(
                        'Error: No version {} found'.format(self.version),
                        fg='red')
                    exit(1)

                self.version = valid_version

                # e.g., [linux_x86_64, linux]
                platform_os = platform.split('_')[0]
                self.download_urls = [
                    {
                        'url': self.get_download_url(data, platform),
                        'platform': platform
                    },
                    {
                        'url': self.get_download_url(data, platform_os),
                        'platform': platform_os
                    }
                ]

        if self.packages_dir == '':
            click.secho(
                'Error: No such package \'{0}\''.format(self.package),
                fg='red')
            exit(1)
Exemplo n.º 34
0
    def list_packages(self, installed=True, notinstalled=True):
        """Return a list with all the installed/notinstalled packages"""

        self.profile = Profile()

        # Classify packages
        installed_packages = []
        notinstalled_packages = []

        for package in self.packages:
            data = {
                'name': package,
                'version': None,
                'description': self.packages.get(package).get('description')
            }
            if package in self.profile.packages:
                data['version'] = self.profile.get_package_version(
                    package, self.get_package_release_name(package))
                installed_packages += [data]
            else:
                notinstalled_packages += [data]

        # Print tables
        terminal_width, _ = click.get_terminal_size()

        if installed and installed_packages:

            # - Print installed packages table
            click.echo('\nInstalled packages:\n')

            PACKAGELIST_TPL = ('{name:20} {description:30} {version:<8}')

            click.echo('-' * terminal_width)
            click.echo(
                PACKAGELIST_TPL.format(name=click.style('Name', fg='cyan'),
                                       version='Version',
                                       description='Description'))
            click.echo('-' * terminal_width)

            for package in installed_packages:
                click.echo(
                    PACKAGELIST_TPL.format(
                        name=click.style(package.get('name'), fg='cyan'),
                        version=package.get('version'),
                        description=package.get('description')))

        if notinstalled and notinstalled_packages:

            # - Print not installed packages table
            click.echo('\nNot installed packages:\n')

            PACKAGELIST_TPL = ('{name:20} {description:30}')

            click.echo('-' * terminal_width)
            click.echo(
                PACKAGELIST_TPL.format(name=click.style('Name', fg='yellow'),
                                       description='Description'))
            click.echo('-' * terminal_width)

            for package in notinstalled_packages:
                click.echo(
                    PACKAGELIST_TPL.format(
                        name=click.style(package.get('name'), fg='yellow'),
                        description=package.get('description')))
Exemplo n.º 35
0
 def _setup_darwin(self):
     self.profile = Profile()