CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-importlib-metadata

Read metadata from Python packages, providing third-party access to importlib.metadata functionality

Pending
Overview
Eval results
Files

entry-points.mddocs/

Entry Points System

Comprehensive entry point discovery and management, including entry point objects, collections, and selection mechanisms for package-defined executable scripts and plugins. Entry points allow packages to advertise functionality that can be discovered and loaded at runtime.

Capabilities

EntryPoint Class

Individual entry point objects representing package-defined entry points:

class EntryPoint:
    """
    An entry point as defined by Python packaging conventions.
    
    Entry points allow packages to advertise components for discovery by other packages.
    Common uses include console scripts, plugin systems, and extensible applications.
    """
    
    name: str      # Entry point name
    value: str     # Entry point value specification (module:attribute)
    group: str     # Entry point group (e.g., 'console_scripts')
    dist: Distribution | None  # Associated distribution (optional)
    
    def __init__(self, name: str, value: str, group: str) -> None:
        """
        Create an entry point.
        
        Parameters:
        - name: Entry point name
        - value: Entry point value (e.g., 'package.module:function')
        - group: Entry point group (e.g., 'console_scripts')
        """
    
    def load(self) -> Any:
        """
        Load the entry point from its definition.
        
        If only a module is indicated by the value, return that module. 
        Otherwise, return the named object.
        
        Returns:
        Any: The loaded object or module
        """
    
    def matches(self, **params) -> bool:
        """
        Check if EntryPoint matches the given parameters.
        
        Parameters:
        - **params: Parameters to match against (name, group, module, attr, extras)
        
        Returns:
        bool: True if all parameters match
        
        Raises:
        ValueError: If 'dist' parameter is provided (not suitable for matching)
        """
    
    @property
    def module(self) -> str:
        """Return the module name from the entry point value."""
    
    @property
    def attr(self) -> str:
        """Return the attribute name from the entry point value."""
    
    @property
    def extras(self) -> list[str]:
        """Return the list of extras from the entry point value."""
    
    # Class attributes
    pattern: re.Pattern[str]  # Regular expression for parsing entry point values
    
    # Internal methods
    def _for(self, dist: Distribution) -> EntryPoint:
        """
        Associate this entry point with a distribution.
        
        Parameters:
        - dist: Distribution to associate with
        
        Returns:
        EntryPoint: This entry point with distribution associated
        """
    
    def _key(self) -> tuple[str, str, str]:
        """
        Return comparison key for sorting and equality.
        
        Returns:
        tuple[str, str, str]: Tuple of (name, value, group)
        """
    
    # Comparison and representation methods
    def __lt__(self, other: EntryPoint) -> bool:
        """Less than comparison for sorting."""
    
    def __eq__(self, other: object) -> bool:
        """Equality comparison."""
    
    def __hash__(self) -> int:
        """Hash for use in sets and dictionaries."""
    
    def __repr__(self) -> str:
        """String representation of entry point."""
    
    def __setattr__(self, name: str, value: Any) -> None:
        """
        Prevent attribute modification (EntryPoint objects are immutable).
        
        Raises:
        AttributeError: Always, as EntryPoint objects are immutable
        """

Usage Examples

import importlib_metadata

# Get entry points and work with individual ones
eps = importlib_metadata.entry_points(group='console_scripts')
if eps:
    ep = next(iter(eps))
    print(f"Entry point: {ep.name}")
    print(f"Module: {ep.module}")
    print(f"Attribute: {ep.attr}")
    print(f"Group: {ep.group}")
    print(f"Extras: {ep.extras}")
    
    # Load the actual object
    try:
        obj = ep.load()
        print(f"Loaded: {obj}")
    except ImportError as e:
        print(f"Failed to load: {e}")

# Check if entry point matches criteria
pip_eps = importlib_metadata.entry_points(name='pip')
for ep in pip_eps:
    if ep.matches(group='console_scripts'):
        print(f"Found pip console script: {ep.value}")

EntryPoints Collection

Immutable collection class for working with multiple entry points:

class EntryPoints(tuple):
    """
    An immutable collection of selectable EntryPoint objects.
    
    Provides methods for filtering and accessing entry points by various criteria.
    """
    
    def __getitem__(self, name: str) -> EntryPoint:
        """
        Get the EntryPoint in self matching name.
        
        Parameters:
        - name: Entry point name to find
        
        Returns:
        EntryPoint: The matching entry point
        
        Raises:
        KeyError: If no entry point with the given name is found
        """
    
    def select(self, **params) -> EntryPoints:
        """
        Select entry points from self that match the given parameters.
        
        Parameters:
        - **params: Selection criteria (typically group and/or name)
        
        Returns:
        EntryPoints: New EntryPoints collection with matching entry points
        """
    
    @property
    def names(self) -> set[str]:
        """
        Return the set of all names of all entry points.
        
        Returns:
        set[str]: Set of entry point names
        """
    
    @property
    def groups(self) -> set[str]:
        """
        Return the set of all groups of all entry points.
        
        Returns:
        set[str]: Set of entry point groups
        """
    
    # Class attributes
    __slots__ = ()  # Memory optimization for tuple subclass
    
    # Class methods for construction
    @classmethod
    def _from_text_for(cls, text: str | None, dist: Distribution) -> EntryPoints:
        """
        Create EntryPoints from text with associated distribution.
        
        Parameters:
        - text: Entry points text content (e.g., from entry_points.txt)
        - dist: Distribution to associate with entry points
        
        Returns:
        EntryPoints: Collection of entry points with distribution associated
        """
    
    @staticmethod
    def _from_text(text: str | None) -> Iterator[EntryPoint]:
        """
        Parse entry points from text content.
        
        Parameters:
        - text: Entry points text content in INI format
        
        Returns:
        Iterator[EntryPoint]: Iterator of parsed entry points
        """
    
    # Representation method
    def __repr__(self) -> str:
        """
        Custom representation showing class name and tuple content.
        
        Returns:
        str: String representation like 'EntryPoints([...])'
        """

Usage Examples

import importlib_metadata

# Get all entry points
all_eps = importlib_metadata.entry_points()
print(f"Total entry points: {len(all_eps)}")
print(f"Available groups: {all_eps.groups}")
print(f"Available names: {len(all_eps.names)} unique names")

# Select by group
console_scripts = all_eps.select(group='console_scripts')
print(f"Console scripts: {len(console_scripts)}")

# Select by name
pip_eps = all_eps.select(name='pip')
print(f"Entry points named 'pip': {len(pip_eps)}")

# Combine selection criteria
specific_eps = all_eps.select(group='console_scripts', name='pip')
print(f"pip console scripts: {len(specific_eps)}")

# Access by name (dictionary-like)
if 'pip' in console_scripts.names:
    pip_ep = console_scripts['pip']
    print(f"pip script: {pip_ep.value}")

Entry Point Parsing and Validation

Entry points use a specific syntax for the value specification. The EntryPoint class uses a compiled regular expression pattern to parse these values:

# EntryPoint.pattern - Regular expression for parsing entry point values
# Pattern: r'(?P<module>[\w.]+)\s*(:\s*(?P<attr>[\w.]+)\s*)?((?P<extras>\[.*\])\s*)?$'

# Entry point value patterns (examples):
# - "module"                          # Module only
# - "package.module"                  # Package and module  
# - "package.module:attribute"        # Module with attribute
# - "package.module:object.attribute" # Nested attribute
# - "package.module:attr [extra1, extra2]"  # With extras

# The pattern captures three groups:
# - module: Required module/package name ([\w.]+)
# - attr: Optional attribute name after colon ([\w.]+)
# - extras: Optional extras specification in brackets (\[.*\])

The pattern is lenient about whitespace around the colon, following the attribute, and following any extras. Invalid entry point references raise ValueError with a descriptive message pointing to the packaging specification.

Usage Examples

import importlib_metadata

# Create entry point manually (for testing/examples)
ep = importlib_metadata.EntryPoint(
    name='my-script',
    value='mypackage.cli:main',
    group='console_scripts'
)

print(f"Entry point module: {ep.module}")      # 'mypackage.cli'
print(f"Entry point attr: {ep.attr}")          # 'main'
print(f"Entry point extras: {ep.extras}")      # []

# Entry point with extras
ep_with_extras = importlib_metadata.EntryPoint(
    name='advanced-script',
    value='mypackage.advanced:run [dev, test]',
    group='console_scripts'
)
print(f"Extras: {ep_with_extras.extras}")      # ['dev', 'test']

Distribution-Specific Entry Points

Entry points are associated with specific distributions and can be accessed through Distribution objects:

import importlib_metadata

# Get entry points for a specific distribution
dist = importlib_metadata.distribution('pip')
dist_eps = dist.entry_points

# Filter distribution entry points
console_scripts = dist_eps.select(group='console_scripts')
for ep in console_scripts:
    print(f"pip provides script: {ep.name} -> {ep.value}")
    print(f"Associated distribution: {ep.dist.name if ep.dist else 'None'}")

Error Handling

Entry point operations can raise various exceptions:

import importlib_metadata

eps = importlib_metadata.entry_points(group='console_scripts')

# KeyError when accessing non-existent entry point
try:
    ep = eps['nonexistent-script']
except KeyError:
    print("Entry point not found")

# ImportError when loading entry point
try:
    ep = next(iter(eps))
    obj = ep.load()
except ImportError as e:
    print(f"Failed to load entry point: {e}")

# ValueError when matching with 'dist' parameter
try:
    ep = next(iter(eps))
    ep.matches(dist=dist)  # Not allowed
except ValueError:
    print("Cannot match on 'dist' parameter")

# ValueError when creating entry point with invalid value
try:
    invalid_ep = importlib_metadata.EntryPoint(
        name='bad-script',
        value='invalid-name',  # Invalid module name
        group='console_scripts'
    )
except ValueError as e:
    print(f"Invalid entry point reference: {e}")

# AttributeError when trying to modify entry point (immutable)
try:
    ep = next(iter(eps))
    ep.name = 'new-name'  # Not allowed
except AttributeError:
    print("EntryPoint objects are immutable")

Install with Tessl CLI

npx tessl i tessl/pypi-importlib-metadata

docs

core-functions.md

distribution-classes.md

entry-points.md

index.md

path-file-management.md

tile.json