Пример #1
0
    def __call__(self) -> bool:
        # get and create venv
        venvs = VEnvs(path=self.config['venv'])
        venv = venvs.get(Path(self.config['project']), env=self.config.env)
        if not venv.exists():
            self.logger.info('Creating venv for project...')
            python = get_python(self.config)
            self.logger.debug('choosen python',
                              extra=dict(version=python.version))
            venv.create(python_path=python.path)

        # get env vars
        env_vars = os.environ.copy()
        if 'vars' in self.config:
            env_vars.update(self.config['vars'])
        env_vars = read_dotenv(
            path=Path(self.config['dotenv']),
            env_vars=env_vars,
        )

        shells = Shells(bin_path=venv.bin_path)
        with override_env_vars(env_vars):
            shells.run()
        self.logger.info('shell closed')
        return True
Пример #2
0
    def __call__(self) -> bool:
        resolver = get_resolver(reqs=self.args.name)
        name = next(iter(resolver.graph.get_layer(0))).dependencies[0].name

        # resolve (and merge)
        self.logger.info('build dependencies graph...')
        resolved = resolver.resolve(silent=self.config['silent'])
        if not resolved:
            conflict = analyze_conflict(resolver=resolver)
            self.logger.warning('conflict was found')
            print(conflict)
            return False

        # make venv
        venvs = VEnvs(path=self.config['venv'])
        venv = venvs.get_by_name(name)
        if venv.exists():
            self.logger.error('already installed', extra=dict(package=name))
            return False
        python = get_python(self.config)
        self.logger.info('creating venv...',
                         extra=dict(
                             venv=str(venv.path),
                             python=str(python.path),
                         ))
        venv.create(python_path=python.path)

        # install
        reqs = Requirement.from_graph(graph=resolver.graph, lock=True)
        self.logger.info('installation...',
                         extra=dict(
                             executable=venv.python_path,
                             packages=len(reqs),
                         ))
        code = PackageManager(executable=venv.python_path).install(reqs=reqs)
        if code != 0:
            return False

        # get entrypoints
        entrypoints = get_entrypoints(venv=venv, name=name)
        if entrypoints is None:
            return False

        # copy console scripts
        self.logger.info('copy executables...',
                         extra=dict(package=name, path=self.config['bin']))
        for entrypoint in entrypoints:
            if entrypoint.group != 'console_scripts':
                continue
            if not (venv.bin_path / entrypoint.name).exists():
                self.logger.error('cannot find script in venv',
                                  extra=dict(script=entrypoint.name))
            else:
                self._publish_script(
                    src=venv.bin_path / entrypoint.name,
                    dst=Path(self.config['bin']) / entrypoint.name,
                )
                self.logger.info('copied', extra=dict(script=entrypoint.name))

        return True
Пример #3
0
    def __call__(self) -> bool:
        venvs = VEnvs(path=self.config['venv'])
        for name in self.args.name:
            name = canonicalize_name(name)
            venv = venvs.get_by_name(name)
            if not venv.exists():
                self.logger.error('jail does not exist', extra=dict(package=name))
                return False

            # remove symlinks on entrypoints
            self.logger.info('remove executables...')
            for entrypoint in venv.bin_path.iterdir():
                global_entrypoint = Path(self.config['bin']) / entrypoint.name
                if not global_entrypoint.exists():
                    continue
                if not global_entrypoint.resolve().samefile(entrypoint):
                    continue
                global_entrypoint.unlink()
                self.logger.info('removed', extra=dict(script=entrypoint.name))

            # remove venv
            shutil.rmtree(venv.path)
            self.logger.info('jail removed', extra=dict(package=name))

        return True
Пример #4
0
 def __call__(self) -> bool:
     venvs = VEnvs(path=self.config['venv'])
     venv = venvs.get(Path(self.config['project']), env=self.config.env)
     if not venv.exists():
         self.logger.error('venv does not exist')
         return False
     venv.destroy()
     self.logger.info('venv removed')
     return True
Пример #5
0
    def __call__(self) -> bool:
        # get command
        command = self.args.name
        if not command:
            command = self.config.get('command')
            if not command:
                self.logger.error('command required')
                return False
        if isinstance(command, str):
            command = shlex.split(command)

        # get and make venv
        venvs = VEnvs(path=self.config['venv'])
        venv = venvs.get(Path(self.config['project']), env=self.config.env)
        if not venv.exists():
            self.logger.warning('venv does not exist, creating...', extra=dict(
                project=self.config['project'],
                env=self.config.env,
                path=str(venv.path),
            ))
            python = get_python(self.config)
            self.logger.debug('choosen python', extra=dict(version=python.version))
            venv.create(python_path=python.path)
            self.logger.info('venv created', extra=dict(path=venv.path))

        # install executable
        executable = venv.bin_path / command[0]
        if not executable.exists():
            self.logger.warning('executable is not found in venv, trying to install...', extra=dict(
                executable=command[0],
            ))
            result = self._install(name=command[0], python_path=venv.python_path)
            if not result:
                return False
        if not executable.exists():
            self.logger.error('package installed, but executable is not found')
            return False

        # get env vars
        env_vars = os.environ.copy()
        if 'vars' in self.config:
            env_vars.update(self.config['vars'])
        env_vars = read_dotenv(
            path=Path(self.config['dotenv']),
            env_vars=env_vars,
        )

        # run
        self.logger.info('running...', extra=dict(command=command))
        with override_env_vars(env_vars):
            result = subprocess.run([str(executable)] + command[1:])
        if result.returncode != 0:
            self.logger.error('command failed', extra=dict(code=result.returncode))
            return False

        self.logger.info('command successfully completed')
        return True
Пример #6
0
    def __call__(self) -> bool:
        resolver = get_resolver(reqs=self.args.name)
        name = next(iter(resolver.graph.get_layer(0))).dependencies[0].name

        # make venv
        venvs = VEnvs(path=self.config['venv'])
        venv = venvs.get_by_name(name)
        if venv.exists():
            self.logger.error('already installed', extra=dict(package=name))
            return False
        python = get_python(self.config)
        self.logger.info('creating venv...',
                         extra=dict(
                             venv=str(venv.path),
                             python=str(python.path),
                         ))
        venv.create(python_path=python.path)

        # install
        ok = install_deps(
            resolver=resolver,
            python_path=venv.python_path,
            logger=self.logger,
            silent=self.config['silent'],
        )
        if not ok:
            return False

        # get entrypoints
        entrypoints = get_entrypoints(venv=venv, name=name)
        if entrypoints is None:
            return False

        # copy console scripts
        self.logger.info('copy executables...',
                         extra=dict(package=name, path=self.config['bin']))
        for entrypoint in entrypoints:
            if entrypoint.group != 'console_scripts':
                continue

            entrypoint_filename = entrypoint.name
            if IS_WINDOWS:
                entrypoint_filename += '.exe'

            if not (venv.bin_path / entrypoint_filename).exists():
                self.logger.error('cannot find script in venv',
                                  extra=dict(script=entrypoint.name))
                continue
            self._publish_script(
                src=venv.bin_path / entrypoint_filename,
                dst=Path(self.config['bin']) / entrypoint_filename,
            )
            self.logger.info('copied', extra=dict(script=entrypoint.name))

        return True
Пример #7
0
def test_iter(temp_path):
    venvs = VEnvs(path=temp_path / 'venvs' / '{project}')

    (temp_path / 'papa').mkdir()
    venv1 = venvs.get(project_path=temp_path / 'papa', env='emeritus')
    venv1.create()

    venv2 = venvs.get_by_name(name='ghost')
    venv2.create()

    assert {str(venv.path) for venv in venvs} == {str(venv1.path), str(venv2.path)}
Пример #8
0
 def container_name(self) -> str:
     return '{prefix}{name}-{digest}-{env}'.format(
         prefix=DOCKER_PREFIX,
         name=self.path.name,
         digest=VEnvs._encode(str(self.path)),
         env=self.env,
     )
Пример #9
0
    def __call__(self) -> bool:
        venvs = VEnvs(path=self.config['venv'])
        name = canonicalize_name(self.args.name)
        venv = venvs.get_by_name(name)
        if not venv.exists():
            self.logger.error('jail does not exist', extra=dict(package=name))
            return False

        # get list of exposed entrypoints
        entrypoints_names = []
        for entrypoint in venv.bin_path.iterdir():
            global_entrypoint = Path(self.config['bin']) / entrypoint.name
            if not global_entrypoint.exists():
                continue
            if not global_entrypoint.resolve().samefile(entrypoint):
                continue
            entrypoints_names.append(entrypoint.name)

        root = InstalledConverter().load(paths=[venv.lib_path], names={name})
        version = None
        for subdep in root.dependencies:
            if subdep.name != name:
                continue
            version = str(subdep.constraint).replace('=', '')

        data = dict(
            name=name,
            path=str(venv.path),
            entrypoints=entrypoints_names,
            version=version,
            size=dict(
                lib=format_size(get_path_size(venv.lib_path)),
                total=format_size(get_path_size(venv.path)),
            ),
        )

        print(
            make_json(
                data=data,
                key=self.config.get('filter'),
                colors=not self.config['nocolors'],
                table=self.config['table'],
            ))
        return True
Пример #10
0
    def __call__(self) -> bool:
        venvs = VEnvs(path=self.config['venv'])
        venv = venvs.get(Path(self.config['project']), env=self.config.env)
        if venv.exists():
            self.logger.error('venv already exists',
                              extra=dict(path=venv.path))
            return False

        self.logger.info('creating venv for project...',
                         extra=dict(path=venv.path))
        python = get_python(self.config)
        self.logger.info('chosen python',
                         extra=dict(
                             version=python.version,
                             path=str(python.path),
                         ))
        venv.create(python_path=python.path)
        self.logger.info('venv created', extra=dict(path=venv.path))
        return True
Пример #11
0
def get_venv(config: Config) -> VEnv:
    """Get preferred venv.

    Lookup order:

    1. Venv for current project and env (if exists).
    2. Current active venv.
    3. If no active venv then venv for current project and env will be returned.

    Use it when you want to work only with virtual environment.
    """
    venvs = VEnvs(path=config['venv'])

    # venv for current project exists
    project_venv = venvs.get(Path(config['project']), env=config.env)
    if project_venv.exists():
        return project_venv

    # now some venv is active
    if venvs.current is not None:
        return venvs.current

    return project_venv
Пример #12
0
def test_get(temp_path):
    venvs = VEnvs(path=temp_path / 'venvs' / '{project}' / '{env}')
    (temp_path / 'papa').mkdir()
    venv = venvs.get(project_path=temp_path / 'papa', env='emeritus')
    assert str(venv.path) == str(temp_path / 'venvs' / 'papa' / 'emeritus')
Пример #13
0
def test_get_by_name(temp_path):
    venvs = VEnvs(path=temp_path / 'venvs' / '{project}' / '{env}')
    venv = venvs.get_by_name(name='papa')
    assert str(venv.path) == str(temp_path / 'venvs' / 'papa')
Пример #14
0
    def __call__(self) -> bool:
        project_path = Path(self.config['project'])

        command = self.config.get('command')
        if not command:
            self.logger.error('command required')
            return False
        if isinstance(command, str):
            command = shlex.split(command)

        # get and make venv
        venvs = VEnvs(path=self.config['venv'])
        venv = venvs.get(project_path, env=self.config.env)
        if not venv.exists():
            self.logger.warning('venv does not exist, creating...',
                                extra=dict(
                                    project=self.config['project'],
                                    env=self.config.env,
                                    path=str(venv.path),
                                ))
            python = get_python(self.config)
            self.logger.debug('choosen python',
                              extra=dict(version=python.version))
            venv.create(python_path=python.path)
            self.logger.info('venv created', extra=dict(path=venv.path))

        # install executable
        executable = venv.bin_path / command[0]
        if not executable.exists():
            self.logger.warning(
                'executable is not found in venv, trying to install...',
                extra=dict(executable=command[0], ))
            result = install_dep(
                name=command[0],
                python_path=venv.python_path,
                logger=self.logger,
                silent=self.config['silent'],
            )
            if not result:
                return False
        if not executable.exists():
            self.logger.error('package installed, but executable is not found')
            return False

        # write script
        entrypoint_filename = '-'.join(self.args.name)
        if not entrypoint_filename:
            entrypoint_filename = '{}-{}'.format(project_path.name,
                                                 executable.stem)
        script = self._make_script(command=command, executable=executable)
        self.logger.debug(script)
        path = Path(self.config['bin']) / entrypoint_filename
        exists = path.exists()
        path.touch(mode=0o770)
        path.write_text(script)

        if exists:
            self.logger.info('script updated', extra=dict(path=path))
        else:
            self.logger.info('script created', extra=dict(path=path))
        return True