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
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
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
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
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
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
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)}
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, )
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
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
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
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')
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')
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