def find_packages(self, name, constraint=None, extras=None): packages = [] if constraint is not None and not isinstance(constraint, BaseConstraint): version_parser = VersionParser() constraint = version_parser.parse_constraints(constraint) key = name if constraint: key = '{}:{}'.format(key, str(constraint)) if self._cache.store('matches').has(key): versions = self._cache.store('matches').get(key) else: candidates = [ str(c.version) for c in self._repository.find_all_candidates(name) ] versions = [] for version in candidates: if version in versions: continue if (not constraint or (constraint and constraint.matches(Constraint('=', version)))): versions.append(version) self._cache.store('matches').put(key, versions, 5) for version in versions: packages.append(Package(name, version, extras=extras)) return packages
def solve(self, requested, fixed=None) -> List[Operation]: resolver = Resolver(Provider(self._package, self._pool), UI(self._io)) base = None if fixed is not None: base = DependencyGraph() for fixed_req in fixed: base.add_vertex(fixed_req.name, fixed_req, True) try: graph = resolver.resolve(requested, base=base) except ResolverError as e: raise SolverProblemError(e) packages = [v.payload for v in graph.vertices.values()] # Setting info for vertex in graph.vertices.values(): tags = self._get_tags_for_vertex(vertex, requested) if 'main' in tags['category']: vertex.payload.category = 'main' else: vertex.payload.category = 'dev' if not tags['optional']: vertex.payload.optional = False else: vertex.payload.optional = True # Finding the less restrictive requirements requirements = {} parser = VersionParser() for req_name, reqs in tags['requirements'].items(): for req in reqs: if req_name == 'python': if 'python' not in requirements: requirements['python'] = req continue previous = parser.parse_constraints(requirements['python']) current = parser.parse_constraints(req) if current.matches(previous): requirements['python'] = req if req_name == 'platform': if 'platform' not in requirements: requirements['platform'] = req continue vertex.payload.requirements = requirements operations = [] for package in packages: installed = False for pkg in self._locked.packages: if package.name == pkg.name: installed = True # Checking version if package.version != pkg.version: operations.append(Update(pkg, package)) break if not installed: operations.append(Install(package)) # Checking for removals for pkg in self._locked.packages: remove = True for package in packages: if pkg.name == package.name: remove = False break if remove: operations.append(Uninstall(pkg)) return list(reversed(operations))
def __init__(self, pool, parser=VersionParser()): self._pool = pool self._parser = parser
def parser(): return VersionParser()
class Package(object): AVAILABLE_PYTHONS = {'2', '2.7', '3', '3.4', '3.5', '3.6', '3.7'} supported_link_types = { 'require': { 'description': 'requires', 'method': 'requires' }, 'provide': { 'description': 'provides', 'method': 'provides' } } STABILITY_STABLE = 0 STABILITY_RC = 5 STABILITY_BETA = 10 STABILITY_ALPHA = 15 STABILITY_DEV = 20 stabilities = { 'stable': STABILITY_STABLE, 'rc': STABILITY_RC, 'beta': STABILITY_BETA, 'alpha': STABILITY_ALPHA, 'dev': STABILITY_DEV, } def __init__(self, name, version, pretty_version=None): """ Creates a new in memory package. """ self._pretty_name = name self._name = name.lower() self._version = str(parse_version(version)) self._pretty_version = pretty_version or version self.description = '' self._stability = parse_stability(version) self._dev = self._stability == 'dev' self._authors = [] self.homepage = None self.repository_url = None self.keywords = [] self._license = None self.readme = None self.source_type = '' self.source_reference = '' self.source_url = '' self.requires = [] self.dev_requires = [] self.extras = {} self._parser = VersionParser() self.category = 'main' self.hashes = [] self.optional = False # Requirements for making it mandatory self.requirements = {} self.build = None self.include = [] self.exclude = [] self.classifiers = [] self._python_versions = '*' self._python_constraint = self._parser.parse_constraints('*') self._platform = '*' self._platform_constraint = EmptyConstraint() self.cwd = None @property def name(self): return self._name @property def pretty_name(self): return self._pretty_name @property def version(self): return self._version @property def pretty_version(self): return self._pretty_version @property def unique_name(self): return self.name + '-' + self._version @property def pretty_string(self): return self.pretty_name + ' ' + self.pretty_version @property def full_pretty_version(self): if not self._dev and self.source_type not in ['hg', 'git']: return self._pretty_version # if source reference is a sha1 hash -- truncate if len(self.source_reference) == 40: return '{} {}'.format(self._pretty_version, self.source_reference[0:7]) return '{} {}'.format(self._pretty_version, self.source_reference) @property def authors(self): # type: () -> list return self._authors @property def author_name(self): # type: () -> str return self._get_author()['name'] @property def author_email(self): # type: () -> str return self._get_author()['email'] def _get_author(self): # type: () -> dict if not self._authors: return {'name': None, 'email': None} m = AUTHOR_REGEX.match(self._authors[0]) name = m.group('name') email = m.group('email') return {'name': name, 'email': email} @property def python_versions(self): return self._python_versions @python_versions.setter def python_versions(self, value): self._python_versions = value self._python_constraint = self._parser.parse_constraints(value) @property def python_constraint(self): return self._python_constraint @property def platform(self): # type: () -> str return self._platform @platform.setter def platform(self, value): # type: (str) -> None self._platform = value self._platform_constraint = GenericConstraint.parse(value) @property def platform_constraint(self): return self._platform_constraint @property def license(self): return self._license @license.setter def license(self, value): if value is None: self._license = value elif isinstance(value, License): self._license = value else: self._license = license_by_id(value) @property def all_classifiers(self): classifiers = copy.copy(self.classifiers) # Automatically set python classifiers parser = VersionParser() if self.python_versions == '*': python_constraint = parser.parse_constraints('~2.7 || ^3.4') else: python_constraint = self.python_constraint for version in sorted(self.AVAILABLE_PYTHONS): if len(version) == 1: constraint = parser.parse_constraints(version + '.*') else: constraint = Constraint('=', version) if python_constraint.matches(constraint): classifiers.append( 'Programming Language :: Python :: {}'.format(version)) # Automatically set license classifiers if self.license: classifiers.append(self.license.classifier) classifiers = set(classifiers) return sorted(classifiers) def is_dev(self): return self._dev def is_prerelease(self): return self._stability != 'stable' def add_dependency( self, name, # type: str constraint=None, # type: Union[str, dict, None] category='main' # type: str ): # type: (...) -> Dependency if constraint is None: constraint = '*' if isinstance(constraint, dict): optional = constraint.get('optional', False) python_versions = constraint.get('python') platform = constraint.get('platform') allows_prereleases = constraint.get('allows-prereleases', False) if 'git' in constraint: # VCS dependency dependency = VCSDependency( name, 'git', constraint['git'], branch=constraint.get('branch', None), tag=constraint.get('tag', None), rev=constraint.get('rev', None), optional=optional, ) if python_versions: dependency.python_versions = python_versions if platform: dependency.platform = platform elif 'file' in constraint: file_path = Path(constraint['file']) dependency = FileDependency(file_path, base=self.cwd) else: version = constraint['version'] dependency = Dependency(name, version, optional=optional, category=category, allows_prereleases=allows_prereleases) if python_versions: dependency.python_versions = python_versions if platform: dependency.platform = platform if 'extras' in constraint: for extra in constraint['extras']: dependency.extras.append(extra) else: dependency = Dependency(name, constraint, category=category) if category == 'dev': self.dev_requires.append(dependency) else: self.requires.append(dependency) return dependency def __hash__(self): return hash((self._name, self._version)) def __eq__(self, other): if not isinstance(other, Package): return NotImplemented return self._name == other.name and self._version == other.version def __str__(self): return self.unique_name def __repr__(self): return '<Package {}>'.format(self.unique_name)
def increment_version(self, version, rule): from poetry.semver.version_parser import VersionParser parser = VersionParser() version_regex = ( 'v?(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:\.(\d+))?{}(?:\+[^\s]+)?' ).format(parser._modifier_regex) m = re.match(version_regex, version) if not m: raise ValueError( 'The project\'s version doesn\'t seem to follow semver') if m.group(3): index = 2 elif m.group(2): index = 1 else: index = 0 matches = m.groups()[:index + 1] base = '.'.join(matches) extra_matches = list(g or '' for g in m.groups()[4:]) extras = version[len('.'.join(matches)):] increment = 1 is_prerelease = (extra_matches[0] or extra_matches[1]) != '' bump_prerelease = rule in { 'premajor', 'preminor', 'prepatch', 'prerelease' } position = -1 if rule in {'major', 'premajor'}: if m.group(1) != '0' or m.group(2) != '0' or not is_prerelease: position = 0 elif rule in {'minor', 'preminor'}: if m.group(2) != '0' or not is_prerelease: position = 1 elif rule in {'patch', 'prepatch'}: if not is_prerelease: position = 2 elif rule == 'prerelease' and not is_prerelease: position = 2 if position != -1: extra_matches[0] = None base = parser._manipulate_version_string(matches, position, increment=increment) if bump_prerelease: # We bump the prerelease part of the version sep = '' if not extra_matches[0]: extra_matches[0] = 'alpha' extra_matches[1] = '.0' sep = '-' else: if extras.startswith(('.', '_', '-')): sep = extras[0] prerelease = extra_matches[1] if not prerelease: prerelease = '.1' psep = '' if prerelease.startswith(('.', '-')): psep = prerelease[0] prerelease = prerelease[1:] new_prerelease = str(int(prerelease) + 1) extra_matches[1] = '{}{}'.format(psep, new_prerelease) extras = '{}{}{}{}'.format(sep, extra_matches[0], extra_matches[1], extra_matches[2]) else: extras = '' return '.'.join(base.split('.')[:max(index, position) + 1]) + extras
class Dependency: def __init__(self, name: str, constraint: str, optional: bool = False, category: str = 'main', allows_prereleases: bool = False): self._name = name.lower() self._pretty_name = name self._parser = VersionParser() try: self._constraint = self._parser.parse_constraints(constraint) except ValueError: self._constraint = self._parser.parse_constraints('*') self._pretty_constraint = constraint self._optional = optional self._category = category self._allows_prereleases = allows_prereleases self._python_versions = '*' self._python_constraint = self._parser.parse_constraints('*') self._platform = '*' self._platform_constraint = self._parser.parse_constraints('*') self._extras = [] @property def name(self): return self._name @property def constraint(self): return self._constraint @property def pretty_constraint(self): return self._pretty_constraint @property def pretty_name(self): return self._pretty_name @property def category(self): return self._category @property def python_versions(self): return self._python_versions @python_versions.setter def python_versions(self, value: str): self._python_versions = value self._python_constraint = self._parser.parse_constraints(value) @property def python_constraint(self): return self._python_constraint @property def platform(self) -> str: return self._platform @platform.setter def platform(self, value: str): self._platform = value @property def platform_constraint(self): return self._platform_constraint @property def extras(self) -> list: return self._extras def allows_prereleases(self): return self._allows_prereleases def is_optional(self): return self._optional def is_vcs(self): return False def accepts(self, package: 'poetry.packages.Package') -> bool: """ Determines if the given package matches this dependency. """ return (self._name == package.name and self._constraint.matches(Constraint('=', package.version)) and (not package.is_prerelease() or self.allows_prereleases())) def to_pep_508(self) -> str: requirement = f'{self.pretty_name}' if isinstance(self.constraint, MultiConstraint): requirement += ' ({})'.format(','.join([ str(c).replace(' ', '') for c in self.constraint.constraints ])) else: requirement += ' ({})'.format( str(self.constraint).replace(' ', '')) # Markers markers = [] # Python marker if self.python_versions != '*': python_constraint = self.python_constraint markers.append( self._create_nested_marker('python_version', python_constraint)) if markers: requirement += f'; {" and ".join(markers)}' return requirement def _create_nested_marker(self, name, constraint): if isinstance(constraint, MultiConstraint): parts = [] for c in constraint.constraints: parts.append(self._create_nested_marker(name, c)) glue = ' and ' if constraint.is_disjunctive(): parts = [f'({part})' for part in parts] glue = ' or ' marker = glue.join(parts) else: marker = f'{name}{constraint.string_operator}"{constraint.version}"' return marker def activate(self): """ Set the dependency as mandatory. """ self._optional = False def __eq__(self, other): if not isinstance(other, Dependency): return NotImplemented return self._name == other.name and self._constraint == other.constraint def __hash__(self): return hash((self._name, self._pretty_constraint)) def __str__(self): return f'{self._pretty_name} ({self._pretty_constraint})' def __repr__(self): return f'<Dependency {str(self)}>'
def handle(self): packages = self.argument('name') is_dev = self.option('dev') section = 'dependencies' if is_dev: section = 'dev-dependencies' original_content = self.poetry.file.read() content = self.poetry.file.read() poetry_content = content['tool']['poetry'] for name in packages: for key in poetry_content[section]: if key.lower() == name.lower(): raise ValueError(f'Package {name} is already present') requirements = self._determine_requirements(packages) requirements = self._format_requirements(requirements) # validate requirements format parser = VersionParser() for constraint in requirements.values(): parser.parse_constraints(constraint) for name, constraint in requirements.items(): if self.option('optional'): constraint = {'version': constraint, 'optional': True} poetry_content[section][name] = constraint # Write new content self.poetry.file.write(content) # Cosmetic new line self.line('') # Update packages self.reset_poetry() installer = Installer(self.output, self.venv, self.poetry.package, self.poetry.locker, self.poetry.pool) installer.dry_run(self.option('dry-run')) installer.update(True) installer.whitelist(requirements) try: status = installer.run() except Exception: self.poetry.file.write(original_content) raise if status != 0 or self.option('dry-run'): # Revert changes if not self.option('dry-run'): self.error('\n' 'Addition failed, reverting pyproject.toml ' 'to its original content.') self.poetry.file.write(original_content) return status
class Dependency(object): def __init__(self, name, # type: str constraint, # type: str optional=False, # type: bool category='main', # type: str allows_prereleases=False # type: bool ): self._name = canonicalize_name(name) self._pretty_name = name self._parser = VersionParser() try: if not isinstance(constraint, BaseConstraint): self._constraint = self._parser.parse_constraints(constraint) else: self._constraint = constraint except ValueError: self._constraint = self._parser.parse_constraints('*') self._pretty_constraint = constraint self._optional = optional self._category = category self._allows_prereleases = allows_prereleases self._python_versions = '*' self._python_constraint = self._parser.parse_constraints('*') self._platform = '*' self._platform_constraint = EmptyConstraint() self._extras = [] self._in_extras = [] @property def name(self): return self._name @property def constraint(self): return self._constraint @property def pretty_constraint(self): return self._pretty_constraint @property def pretty_name(self): return self._pretty_name @property def category(self): return self._category @property def python_versions(self): return self._python_versions @python_versions.setter def python_versions(self, value): self._python_versions = value self._python_constraint = self._parser.parse_constraints(value) @property def python_constraint(self): return self._python_constraint @property def platform(self): return self._platform @platform.setter def platform(self, value): self._platform = value self._platform_constraint = GenericConstraint.parse(value) @property def platform_constraint(self): return self._platform_constraint @property def extras(self): # type: () -> list return self._extras @property def in_extras(self): # type: () -> list return self._in_extras def allows_prereleases(self): return self._allows_prereleases def is_optional(self): return self._optional def is_vcs(self): return False def is_file(self): return False def is_directory(self): return False def accepts(self, package): # type: (poetry.packages.Package) -> bool """ Determines if the given package matches this dependency. """ return ( self._name == package.name and self._constraint.matches(Constraint('=', package.version)) and (not package.is_prerelease() or self.allows_prereleases()) ) def to_pep_508(self, with_extras=True): # type: (bool) -> str requirement = self.pretty_name if self.extras: requirement += '[{}]'.format(','.join(self.extras)) if isinstance(self.constraint, MultiConstraint): requirement += ' ({})'.format(','.join( [str(c).replace(' ', '') for c in self.constraint.constraints] )) elif str(self.constraint) != '*': requirement += ' ({})'.format(str(self.constraint).replace(' ', '')) # Markers markers = [] # Python marker if self.python_versions != '*': python_constraint = self.python_constraint markers.append( self._create_nested_marker('python_version', python_constraint) ) in_extras = ' || '.join(self._in_extras) if in_extras and with_extras: markers.append( self._create_nested_marker( 'extra', GenericConstraint.parse(in_extras) ) ) if markers: if len(markers) > 1: markers = ['({})'.format(m) for m in markers] requirement += '; {}'.format(' and '.join(markers)) else: requirement += '; {}'.format(markers[0]) return requirement def _create_nested_marker(self, name, constraint): if isinstance(constraint, MultiConstraint): parts = [] for c in constraint.constraints: multi = False if isinstance(c, MultiConstraint): multi = True parts.append((multi, self._create_nested_marker(name, c))) glue = ' and ' if constraint.is_disjunctive(): parts = [ '({})'.format(part[1]) if part[0] else part[1] for part in parts ] glue = ' or ' else: parts = [part[1] for part in parts] marker = glue.join(parts) else: marker = '{} {} "{}"'.format( name, constraint.string_operator, constraint.version ) return marker def activate(self): """ Set the dependency as mandatory. """ self._optional = False def deactivate(self): """ Set the dependency as optional. """ self._optional = True def __eq__(self, other): if not isinstance(other, Dependency): return NotImplemented return self._name == other.name and self._constraint == other.constraint def __hash__(self): return hash((self._name, self._pretty_constraint)) def __str__(self): return '{} ({})'.format( self._pretty_name, self._pretty_constraint ) def __repr__(self): return '<{} {}>'.format(self.__class__.__name__, str(self))
def _get_tags_for_vertex(self, vertex, requested): category = 'dev' optional = True python_version = None platform = None if not vertex.incoming_edges: # Original dependency for req in requested: if vertex.payload.name == req.name: category = req.category optional = req.is_optional() python_version = str(req.python_constraint) platform = str(req.platform_constraint) break return category, optional, python_version, platform parser = VersionParser() python_versions = [] platforms = [] for edge in vertex.incoming_edges: python_version = None platform = None for req in edge.origin.payload.requires: if req.name == vertex.payload.name: python_version = req.python_versions platform = req.platform break (top_category, top_optional, top_python_version, top_platform) = self._get_tags_for_vertex( edge.origin, requested ) if top_category == 'main': category = top_category optional = optional and top_optional # Take the most restrictive constraints if top_python_version is not None: if python_version is not None: previous = parser.parse_constraints(python_version) current = parser.parse_constraints(top_python_version) if top_python_version != '*' and previous.matches(current): python_versions.append(top_python_version) else: python_versions.append(python_version) else: python_versions.append(top_python_version) elif python_version is not None: python_versions.append(python_version) if top_platform is not None: if platform is not None: previous = GenericConstraint.parse(platform) current = GenericConstraint.parse(top_platform) if top_platform != '*' and previous.matches(current): platforms.append(top_platform) else: platforms.append(platform) else: platforms.append(top_platform) elif platform is not None: platforms.append(platform) if not python_versions: python_version = None else: # Find the least restrictive constraint python_version = python_versions[0] previous = parser.parse_constraints(python_version) for constraint in python_versions[1:]: current = parser.parse_constraints(constraint) if python_version == '*': continue elif constraint == '*': python_version = constraint elif current.matches(previous): python_version = constraint if not platforms: platform = None else: platform = platforms[0] previous = GenericConstraint.parse(platform) for constraint in platforms[1:]: current = GenericConstraint.parse(constraint) if platform == '*': continue elif constraint == '*': platform = constraint elif current.matches(previous): platform = constraint return category, optional, python_version, platform
class Package: supported_link_types = { 'require': { 'description': 'requires', 'method': 'requires' }, 'provide': { 'description': 'provides', 'method': 'provides' } } STABILITY_STABLE = 0 STABILITY_RC = 5 STABILITY_BETA = 10 STABILITY_ALPHA = 15 STABILITY_DEV = 20 stabilities = { 'stable': STABILITY_STABLE, 'rc': STABILITY_RC, 'beta': STABILITY_BETA, 'alpha': STABILITY_ALPHA, 'dev': STABILITY_DEV, } def __init__(self, name, version, pretty_version=None): """ Creates a new in memory package. """ self._pretty_name = name self._name = name.lower() self._version = version self._pretty_version = pretty_version or version self.description = '' self._stability = parse_stability(version) self._dev = self._stability == 'dev' self._authors = [] self.homepage = None self.repository_url = None self.keywords = [] self.license = None self.readme = '' self.source_type = '' self.source_reference = '' self.source_url = '' self.requires = [] self.dev_requires = [] self.extras = {} self._parser = VersionParser() self.category = 'main' self.hashes = [] self.optional = False # Requirements for making it mandatory self.requirements = {} self._python_versions = '*' self._python_constraint = self._parser.parse_constraints('*') self._platform = '*' self._platform_constraint = self._parser.parse_constraints('*') @property def name(self): return self._name @property def pretty_name(self): return self._pretty_name @property def version(self): return self._version @property def pretty_version(self): return self._pretty_version @property def unique_name(self): return self.name + '-' + self._version @property def pretty_string(self): return self.pretty_name + ' ' + self.pretty_version @property def full_pretty_version(self): if not self._dev and self.source_type not in ['hg', 'git']: return self._pretty_version # if source reference is a sha1 hash -- truncate if len(self.source_reference) == 40: return '{} {}'.format(self._pretty_version, self.source_reference[0:7]) return '{} {}'.format(self._pretty_version, self.source_reference) @property def authors(self) -> list: return self._authors @property def python_versions(self): return self._python_versions @python_versions.setter def python_versions(self, value: str): self._python_versions = value self._python_constraint = self._parser.parse_constraints(value) @property def python_constraint(self): return self._python_constraint @property def platform(self) -> str: return self._platform @platform.setter def platform(self, value: str): self._platform = value self._platform_constraint = self._parser.parse_constraints(value) @property def platform_constraint(self): return self._platform_constraint def is_dev(self): return self._dev def is_prerelease(self): return self._stability != 'stable' def add_dependency(self, name: str, constraint: Union[str, dict, None] = None, category: str = 'main') -> Dependency: if constraint is None: constraint = '*' if isinstance(constraint, dict): if 'git' in constraint: # VCS dependency optional = constraint.get('optional', False) python_versions = constraint.get('python') platform = constraint.get('platform') dependency = VCSDependency( name, 'git', constraint['git'], branch=constraint.get('branch', None), tag=constraint.get('tag', None), rev=constraint.get('rev', None), optional=optional, ) if python_versions: dependency.python_versions = python_versions if platform: dependency.platform = platform else: version = constraint['version'] optional = constraint.get('optional', False) allows_prereleases = constraint.get('allows_prereleases', False) python_versions = constraint.get('python') platform = constraint.get('platform') dependency = Dependency(name, version, optional=optional, category=category, allows_prereleases=allows_prereleases) if python_versions: dependency.python_versions = python_versions if platform: dependency.platform = platform if 'extras' in constraint: for extra in constraint['extras']: dependency.extras.append(extra) else: dependency = Dependency(name, constraint, category=category) if category == 'dev': self.dev_requires.append(dependency) else: self.requires.append(dependency) return dependency def __hash__(self): return hash((self._name, self._version)) def __eq__(self, other): if not isinstance(other, Package): return NotImplemented return self._name == other.name and self._version == other.version def __str__(self): return self.unique_name def __repr__(self): return '<Package {}>'.format(self.unique_name)
def handle(self): from poetry.installation import Installer from poetry.semver.version_parser import VersionParser packages = self.argument('name') is_dev = self.option('dev') if (self.option('git') or self.option('path') or self.option('extras')) and len(packages) > 1: raise ValueError( 'You can only specify one package ' 'when using the --git or --path options' ) if self.option('git') and self.option('path'): raise RuntimeError( '--git and --path cannot be used at the same time' ) section = 'dependencies' if is_dev: section = 'dev-dependencies' original_content = self.poetry.file.read() content = self.poetry.file.read() poetry_content = content['tool']['poetry'] for name in packages: for key in poetry_content[section]: if key.lower() == name.lower(): raise ValueError( 'Package {} is already present'.format(name) ) if self.option('git') or self.option('path'): requirements = { packages[0]: '' } else: requirements = self._determine_requirements( packages, allow_prereleases=self.option('allow-prereleases') ) requirements = self._format_requirements(requirements) # validate requirements format parser = VersionParser() for constraint in requirements.values(): parser.parse_constraints(constraint) for name, constraint in requirements.items(): constraint = { 'version': constraint } if self.option('git'): del constraint['version'] constraint['git'] = self.option('git') elif self.option('path'): del constraint['version'] constraint['path'] = self.option('path') if self.option('optional'): constraint['optional'] = True if self.option('allow-prereleases'): constraint['allows-prereleases'] = True if self.option('extras'): constraint['extras'] = self.option('extras') if len(constraint) == 1 and 'version' in constraint: constraint = constraint['version'] poetry_content[section][name] = constraint # Write new content self.poetry.file.write(content) # Cosmetic new line self.line('') # Update packages self.reset_poetry() installer = Installer( self.output, self.venv, self.poetry.package, self.poetry.locker, self.poetry.pool ) installer.dry_run(self.option('dry-run')) installer.update(True) installer.whitelist(requirements) try: status = installer.run() except Exception: self.poetry.file.write(original_content) raise if status != 0 or self.option('dry-run'): # Revert changes if not self.option('dry-run'): self.error( '\n' 'Addition failed, reverting pyproject.toml ' 'to its original content.' ) self.poetry.file.write(original_content) return status