CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-poetry-core

Poetry PEP 517 Build Backend for building Python packages with lightweight, compliant, self-contained build system

Pending
Overview
Eval results
Files

constraints.mddocs/

Version and Generic Constraint Handling

Poetry Core provides a comprehensive constraint system for handling version requirements and generic constraints. This includes PEP 440-compliant version constraints, Poetry-specific syntax (caret and tilde), and generic constraint operations.

Core Imports

# Version constraints
from poetry.core.constraints.version import (
    Version,
    VersionConstraint,
    VersionRange,
    VersionRangeConstraint,
    VersionUnion,
    EmptyConstraint,
    parse_constraint,
    parse_marker_version_constraint,
    constraint_regions
)

# Generic constraints
from poetry.core.constraints.generic import (
    BaseConstraint,
    Constraint,
    AnyConstraint,
    EmptyConstraint as GenericEmptyConstraint,
    MultiConstraint,
    UnionConstraint,
    parse_constraint as parse_generic_constraint,
    parse_extra_constraint
)
``` { .api }

## Version Constraints

Version constraints handle PEP 440 version specifications with additional Poetry syntax support.

### parse_constraint

```python
def parse_constraint(constraints: str) -> VersionConstraint:
    """
    Parse string version constraints into constraint objects.
    
    Args:
        constraints: Version constraint string supporting various formats:
            - PEP 440: ">=1.2.0,<2.0.0", "==1.5.*", "~=1.4.2"
            - Poetry caret: "^1.2.0" (compatible release)
            - Poetry tilde: "~1.2.0" (reasonably close)
            - Wildcards: "1.2.*"
            - Multiple: ">=1.0,<2.0,!=1.5"
            
    Returns:
        VersionConstraint object (Version, VersionRange, VersionUnion, etc.)
        
    Raises:
        ParseConstraintError: If constraint string is malformed
        
    Examples:
        >>> constraint = parse_constraint("^1.2.0")
        >>> print(constraint)  # >=1.2.0,<2.0.0
        
        >>> constraint = parse_constraint("~1.2.3")  
        >>> print(constraint)  # >=1.2.3,<1.3.0
        
        >>> constraint = parse_constraint(">=2.0,<3.0,!=2.5")
        >>> isinstance(constraint, VersionUnion)
        True
    """
``` { .api }

### parse_marker_version_constraint

```python
def parse_marker_version_constraint(constraint: str) -> VersionConstraint:
    """
    Parse version constraints from PEP 508 environment markers.
    
    Args:
        constraint: Version constraint from marker context
        
    Returns:
        VersionConstraint suitable for marker evaluation
        
    Example:
        >>> # From marker: python_version >= "3.8"
        >>> constraint = parse_marker_version_constraint("3.8")
        >>> print(constraint)
    """
``` { .api }

### constraint_regions

```python
def constraint_regions(constraints: list[VersionConstraint]) -> list[VersionRange]:
    """
    Analyze constraint regions for optimization and conflict detection.
    
    Args:
        constraints: List of version constraints to analyze
        
    Returns:
        List of VersionRange objects representing constraint regions
        
    Note:
        Utility function for advanced constraint analysis and optimization.
    """
``` { .api }

## Version Constraint Classes

### Version

```python
class Version(PEP440Version, VersionRangeConstraint):
    """
    Concrete version implementation with PEP 440 compliance and constraints.
    
    Combines PEP 440 version parsing with constraint satisfaction logic.
    Supports all PEP 440 version formats including pre-releases, dev releases,
    and local versions.
    """
    
    @classmethod
    def parse(cls, version: str) -> Version:
        """
        Parse version string into Version object.
        
        Args:
            version: PEP 440 compliant version string
            
        Returns:
            Version instance
            
        Example:
            >>> v = Version.parse("1.2.3")
            >>> v = Version.parse("2.0.0a1")  # alpha
            >>> v = Version.parse("1.0.0.dev0")  # dev
        """
    
    def allows(self, other: Version) -> bool:
        """Check if this version allows another version (equality)."""
        
    def intersect(self, other: VersionConstraint) -> VersionConstraint:
        """Create intersection with another constraint."""
        
    def union(self, other: VersionConstraint) -> VersionConstraint:
        """Create union with another constraint."""
``` { .api }

### VersionRange

```python
class VersionRange(VersionRangeConstraint):
    """
    Represents a range of versions with minimum and maximum bounds.
    
    Supports inclusive and exclusive bounds, unbounded ranges,
    and complex range operations.
    """
    
    def __init__(
        self,
        min_version: Version | None = None,
        max_version: Version | None = None,
        include_min: bool = True,
        include_max: bool = False,
    ) -> None:
        """
        Create version range.
        
        Args:
            min_version: Minimum version (None for unbounded)
            max_version: Maximum version (None for unbounded) 
            include_min: Whether minimum is inclusive
            include_max: Whether maximum is inclusive
            
        Example:
            >>> # >=1.0.0,<2.0.0
            >>> range1 = VersionRange(
            ...     Version.parse("1.0.0"),
            ...     Version.parse("2.0.0")
            ... )
            
            >>> # >1.0.0,<=1.5.0
            >>> range2 = VersionRange(
            ...     Version.parse("1.0.0"),
            ...     Version.parse("1.5.0"),
            ...     include_min=False,
            ...     include_max=True
            ... )
        """
        
    @property
    def min(self) -> Version | None:
        """Minimum version bound."""
        
    @property  
    def max(self) -> Version | None:
        """Maximum version bound."""
        
    def allows(self, version: Version) -> bool:
        """Check if version falls within this range."""
        
    def intersect(self, other: VersionConstraint) -> VersionConstraint:
        """Create intersection with another constraint."""
        
    def union(self, other: VersionConstraint) -> VersionConstraint:
        """Create union with another constraint."""
``` { .api }

### VersionUnion

```python
class VersionUnion(VersionConstraint):
    """
    Union of multiple version constraints (OR operation).
    
    Represents constraints like ">=1.0,<2.0 || >=3.0,<4.0" where
    a version can satisfy any of the constituent constraints.
    """
    
    def __init__(self, *constraints: VersionConstraint) -> None:
        """
        Create union of constraints.
        
        Args:
            constraints: Version constraints to union
            
        Example:
            >>> range1 = VersionRange(Version.parse("1.0.0"), Version.parse("2.0.0"))
            >>> range2 = VersionRange(Version.parse("3.0.0"), Version.parse("4.0.0"))
            >>> union = VersionUnion(range1, range2)
        """
        
    @property
    def constraints(self) -> tuple[VersionConstraint, ...]:
        """Constituent constraints in the union."""
        
    def allows(self, version: Version) -> bool:
        """Check if version satisfies any constraint in union."""
``` { .api }

### EmptyConstraint

```python
class EmptyConstraint(VersionConstraint):
    """
    Version constraint representing no valid versions.
    
    Used when constraints are impossible to satisfy or
    when explicitly excluding all versions.
    """
    
    def allows(self, version: Version) -> bool:
        """Always returns False - no versions allowed."""
        
    def is_empty(self) -> bool:
        """Always returns True."""
``` { .api }

## Generic Constraints

Generic constraints provide a framework for non-version constraint operations.

### parse_constraint (Generic)

```python
def parse_constraint(constraints: str) -> BaseConstraint:
    """
    Parse string constraints into generic constraint objects.
    
    Args:
        constraints: Constraint string
        
    Returns:
        BaseConstraint implementation
        
    Example:
        >>> constraint = parse_constraint("foo")
        >>> constraint = parse_constraint("foo,bar")  # Multi-constraint
    """
``` { .api }

### parse_extra_constraint

```python
def parse_extra_constraint(constraints: str) -> BaseConstraint:
    """
    Parse extra/optional feature constraints.
    
    Args:
        constraints: Extra constraint string (e.g., "dev,test")
        
    Returns:
        BaseConstraint for extra matching
        
    Example:
        >>> extra_constraint = parse_extra_constraint("dev,test")
        >>> # Used for conditional dependencies
    """
``` { .api }

## Generic Constraint Classes

### BaseConstraint

```python
class BaseConstraint:
    """
    Abstract base class for all constraint types.
    
    Defines the interface that all constraints must implement
    for matching, intersection, and union operations.
    """
    
    def allows(self, other: Any) -> bool:
        """Check if constraint allows a value."""
        
    def intersect(self, other: BaseConstraint) -> BaseConstraint:
        """Create intersection with another constraint."""
        
    def union(self, other: BaseConstraint) -> BaseConstraint: 
        """Create union with another constraint."""
        
    def is_any(self) -> bool:
        """Check if constraint matches any value."""
        
    def is_empty(self) -> bool:
        """Check if constraint matches no values."""
``` { .api }

### Constraint

```python
class Constraint(BaseConstraint):
    """
    Basic constraint implementation for exact matching.
    
    Matches values exactly against a stored constraint value.
    """
    
    def __init__(self, constraint: str) -> None:
        """
        Create constraint with exact matching value.
        
        Args:
            constraint: Value to match exactly
        """
        
    @property
    def constraint(self) -> str:
        """The constraint value."""
``` { .api }

### AnyConstraint

```python
class AnyConstraint(BaseConstraint):
    """
    Constraint that matches any value.
    
    Represents the absence of constraints - all values are valid.
    """
    
    def allows(self, other: Any) -> bool:
        """Always returns True - allows any value."""
        
    def is_any(self) -> bool:
        """Always returns True."""
``` { .api }

### EmptyConstraint (Generic)

```python
class EmptyConstraint(BaseConstraint):
    """
    Generic constraint matching no values.
    
    Represents impossible or explicitly empty constraints.
    """
    
    def allows(self, other: Any) -> bool:
        """Always returns False - allows no values."""
        
    def is_empty(self) -> bool:
        """Always returns True."""
``` { .api }

### MultiConstraint

```python
class MultiConstraint(BaseConstraint):
    """
    Conjunction of multiple constraints (AND operation).
    
    All constituent constraints must be satisfied.
    """
    
    def __init__(self, *constraints: BaseConstraint) -> None:
        """
        Create conjunction of constraints.
        
        Args:
            constraints: Constraints that must all be satisfied
        """
        
    @property
    def constraints(self) -> tuple[BaseConstraint, ...]:
        """Constituent constraints."""
        
    def allows(self, other: Any) -> bool:
        """Check if all constraints allow the value."""
``` { .api }

### UnionConstraint

```python
class UnionConstraint(BaseConstraint):
    """
    Disjunction of multiple constraints (OR operation).
    
    Any constituent constraint can be satisfied.
    """
    
    def __init__(self, *constraints: BaseConstraint) -> None:
        """
        Create disjunction of constraints.
        
        Args:
            constraints: Constraints where any can be satisfied
        """
        
    @property
    def constraints(self) -> tuple[BaseConstraint, ...]:
        """Constituent constraints."""
        
    def allows(self, other: Any) -> bool:
        """Check if any constraint allows the value."""
``` { .api }

## Usage Examples

### Basic Version Constraint Parsing

```python
from poetry.core.constraints.version import parse_constraint, Version

def demonstrate_version_constraints():
    """Show various version constraint formats."""
    
    # Poetry caret constraint (compatible release)
    caret = parse_constraint("^1.2.0")
    print(f"Caret ^1.2.0: {caret}")  # >=1.2.0,<2.0.0
    
    # Poetry tilde constraint (reasonably close)
    tilde = parse_constraint("~1.2.3") 
    print(f"Tilde ~1.2.3: {tilde}")  # >=1.2.3,<1.3.0
    
    # PEP 440 constraints
    pep440 = parse_constraint(">=1.0,<2.0,!=1.5")
    print(f"PEP 440: {pep440}")
    
    # Wildcard constraints
    wildcard = parse_constraint("1.2.*")
    print(f"Wildcard: {wildcard}")
    
    # Test version satisfaction
    version = Version.parse("1.2.5")
    print(f"Version {version} satisfies caret: {caret.allows(version)}")
    print(f"Version {version} satisfies tilde: {tilde.allows(version)}")

demonstrate_version_constraints()
``` { .api }

### Complex Constraint Operations

```python
from poetry.core.constraints.version import parse_constraint, VersionUnion

def constraint_operations():
    """Demonstrate constraint intersection and union."""
    
    # Create individual constraints
    constraint1 = parse_constraint(">=1.0.0")
    constraint2 = parse_constraint("<3.0.0") 
    constraint3 = parse_constraint("!=2.0.0")
    
    # Intersection (AND) - must satisfy all
    intersection = constraint1.intersect(constraint2).intersect(constraint3)
    print(f"Intersection: {intersection}")  # >=1.0.0,<3.0.0,!=2.0.0
    
    # Union (OR) - can satisfy any
    union = constraint1.union(constraint3)
    print(f"Union: {union}")
    
    # Test complex constraint
    test_versions = ["0.9.0", "1.5.0", "2.0.0", "2.5.0", "3.5.0"]
    
    print(f"\nTesting intersection ({intersection}):")
    for version_str in test_versions:
        version = Version.parse(version_str)
        satisfies = intersection.allows(version)
        print(f"  {version}: {'✓' if satisfies else '✗'}")

constraint_operations()
``` { .api }

### Building Custom Constraints

```python
from poetry.core.constraints.version import Version, VersionRange, VersionUnion

def build_custom_constraints():
    """Build constraints programmatically."""
    
    # Create version range manually
    min_version = Version.parse("2.0.0")
    max_version = Version.parse("3.0.0")
    
    range1 = VersionRange(
        min_version=min_version,
        max_version=max_version,
        include_min=True,    # >=2.0.0
        include_max=False    # <3.0.0  
    )
    
    # Create another range
    range2 = VersionRange(
        min_version=Version.parse("4.0.0"),
        max_version=Version.parse("5.0.0"),
        include_min=True,
        include_max=False
    )
    
    # Combine ranges with union
    combined = VersionUnion(range1, range2)
    print(f"Combined constraint: {combined}")
    # Allows: >=2.0.0,<3.0.0 || >=4.0.0,<5.0.0
    
    # Test versions against combined constraint
    test_versions = ["1.5.0", "2.5.0", "3.5.0", "4.5.0", "5.5.0"]
    
    for version_str in test_versions:
        version = Version.parse(version_str)
        allowed = combined.allows(version)
        print(f"{version}: {'allowed' if allowed else 'rejected'}")

build_custom_constraints()
``` { .api }

### Generic Constraint Usage

```python
from poetry.core.constraints.generic import (
    parse_constraint, 
    MultiConstraint,
    UnionConstraint,
    AnyConstraint
)

def demonstrate_generic_constraints():
    """Show generic constraint operations."""
    
    # Parse simple constraints
    constraint1 = parse_constraint("development")
    constraint2 = parse_constraint("testing")
    
    # Create multi-constraint (AND)
    both_required = MultiConstraint(constraint1, constraint2)
    print(f"Must have both: {both_required}")
    
    # Create union constraint (OR)
    either_allowed = UnionConstraint(constraint1, constraint2)
    print(f"Can have either: {either_allowed}")
    
    # Any constraint (no restrictions)
    any_constraint = AnyConstraint()
    print(f"Any allowed: {any_constraint.is_any()}")
    
    # Test constraint matching
    print(f"'development' satisfies both_required: {both_required.allows('development')}")
    print(f"'testing' satisfies either_allowed: {either_allowed.allows('testing')}")

demonstrate_generic_constraints()
``` { .api }

### Poetry Constraint Syntax

```python
def poetry_syntax_examples():
    """Demonstrate Poetry-specific constraint syntax."""
    
    constraints = {
        "^1.2.3": "Caret - compatible release (>=1.2.3,<2.0.0)",
        "~1.2.3": "Tilde - reasonably close (>=1.2.3,<1.3.0)", 
        "^0.2.3": "Caret with 0.x (>=0.2.3,<0.3.0)",
        "^0.0.3": "Caret with 0.0.x (>=0.0.3,<0.0.4)",
        "~1.2": "Tilde major.minor (>=1.2.0,<1.3.0)",
        "1.2.*": "Wildcard (>=1.2.0,<1.3.0)",
        ">=1.2,<2.0": "Range constraint",
        "!=1.5": "Exclusion constraint"
    }
    
    print("Poetry Constraint Syntax:")
    for syntax, description in constraints.items():
        try:
            parsed = parse_constraint(syntax)
            print(f"{syntax:15} -> {parsed} ({description})")
        except Exception as e:
            print(f"{syntax:15} -> ERROR: {e}")

poetry_syntax_examples()
``` { .api }

## Error Handling

```python
from poetry.core.exceptions import ParseConstraintError
from poetry.core.constraints.version import parse_constraint

def safe_constraint_parsing(constraint_str: str):
    """Safely parse constraints with error handling."""
    
    try:
        constraint = parse_constraint(constraint_str)
        return constraint
        
    except ParseConstraintError as e:
        print(f"Invalid constraint '{constraint_str}': {e}")
        return None
        
    except Exception as e:
        print(f"Unexpected error parsing '{constraint_str}': {e}")
        return None

# Usage
constraints_to_test = [
    "^1.2.0",      # Valid
    ">=1.0,<2.0",  # Valid 
    "invalid",     # Invalid
    "^",           # Invalid
    "1.2.3.4.5"    # Invalid
]

for constraint_str in constraints_to_test:
    result = safe_constraint_parsing(constraint_str)
    if result:
        print(f"✓ {constraint_str} -> {result}")
    else:
        print(f"✗ {constraint_str} -> Failed to parse")
``` { .api }

Install with Tessl CLI

npx tessl i tessl/pypi-poetry-core

docs

build-backend.md

builders.md

configuration.md

constraints.md

factory-core.md

index.md

json-validation.md

packages.md

utilities.md

vcs-support.md

version-system.md

tile.json