python / python/cpython

Improving conciseness of ipaddress factory functions.

Ouverte
#93,880 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

stdlib type-feature
Langage dominant
Python
Étoiles
77.2k
Forks
36k
Métriques de merge des PR
Métriques de PR en attente

Description

Suggestion to refactor the 3 factory functions ip_address, ip_network, ip_interface.
In addition making a similar modification in the _prefix_from_ip_string function.

Currently the functions contain code which can be improved in terms of conciseness and extendability.

  • try/catch containing a pass statement can be substituted with contextlib.suppress making the code more concise
  • we can use a for loop which will iterate over the class objects to further increase conciseness

Current factory function implementations (docstrings not included for brevity)

def ip_address(address):
    try:
        return IPv4Address(address)
    except (AddressValueError, NetmaskValueError):
        pass

    try:
        return IPv6Address(address)
    except (AddressValueError, NetmaskValueError):
        pass

    raise ValueError(f'{address!r} does not appear to be an IPv4 or IPv6 address')


def ip_network(address, strict=True):
    try:
        return IPv4Network(address, strict)
    except (AddressValueError, NetmaskValueError):
        pass

    try:
        return IPv6Network(address, strict)
    except (AddressValueError, NetmaskValueError):
        pass

    raise ValueError(f'{address!r} does not appear to be an IPv4 or IPv6 network')


def ip_interface(address):
    try:
        return IPv4Interface(address)
    except (AddressValueError, NetmaskValueError):
        pass

    try:
        return IPv6Interface(address)
    except (AddressValueError, NetmaskValueError):
        pass

    raise ValueError(f'{address!r} does not appear to be an IPv4 or IPv6 interface')

Proposed function implementations

def ip_address(address):
    for ip_class in [IPv4Address, IPv6Address]:
        with contextlib.suppress(AddressValueError, NetmaskValueError):
            return ip_class(address)

    raise ValueError(f'{address!r} does not appear to be an IPv4 or IPv6 address')


def ip_network(address, strict=True):
    for network_class in [IPv4Network, IPv6Network]:
        with contextlib.suppress(AddressValueError, NetmaskValueError):
            return network_class(address, strict)

    raise ValueError(f'{address!r} does not appear to be an IPv4 or IPv6 network')


def ip_interface(address):
    for ip_interface_class in [IPv4Interface, IPv6Interface]:
        with contextlib.suppress(AddressValueError, NetmaskValueError):
            return ip_interface_class(address)

    raise ValueError(f'{address!r} does not appear to be an IPv4 or IPv6 interface')

current _prefix_from_ip_string function (docstrings and comments not included for brevity)

    @classmethod
    def _prefix_from_ip_string(cls, ip_str):
        try:
            ip_int = cls._ip_int_from_string(ip_str)
        except AddressValueError:
            cls._report_invalid_netmask(ip_str)

        try:
            return cls._prefix_from_ip_int(ip_int)
        except ValueError:
            pass

        ip_int ^= cls._ALL_ONES
        try:
            return cls._prefix_from_ip_int(ip_int)
        except ValueError:
            cls._report_invalid_netmask(ip_str)

Suggested improvement

    @classmethod
    def _prefix_from_ip_string(cls, ip_str):
        try:
            ip_int = cls._ip_int_from_string(ip_str)
        except AddressValueError:
            cls._report_invalid_netmask(ip_str)

        with contextlib.suppress(ValueError):
            return cls._prefix_from_ip_int(ip_int)

        ip_int ^= cls._ALL_ONES
        try:
            return cls._prefix_from_ip_int(ip_int)
        except ValueError:
            cls._report_invalid_netmask(ip_str)

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Repérez les points d’entrée ip_address, ip_network, ip_interface et _prefix_from_ip_string dans l’implémentation de ipaddress, puis examinez la gestion des exceptions qui les entoure. Comparez les modifications proposées concernant la boucle et la suppression avec le comportement actuel, y compris les chemins d’erreur existants, et vérifiez que les tests ipaddress concernés passent toujours.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python
Domaine
networking
Type d'issue
Refactorisation
Difficulté
3/5
Temps estimé
1-2 jours
Activité
À l'abandon
Clarté
Plutôt claire
Accessibilité débutants
35/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.