Beispiel #1
0
def hostnames(
    draw, allow_leading_digit=True, allow_idn=True
):  # pragma: no cover
    # type: (DrawCallable, bool, bool) -> Text
    """
    A strategy which generates host names.

    @param allow_leading_digit: Whether to allow a leading digit in host names;
        they were not allowed prior to RFC 1123.

    @param allow_idn: Whether to allow non-ASCII characters as allowed by
        internationalized domain names (IDNs).
    """
    labels = draw(
        lists(hostname_labels(allow_idn=allow_idn), min_size=1, max_size=5)
        .filter(lambda ls: sum(len(l) for l in ls) + len(ls) - 1 <= 252)
    )

    name = u".".join(labels)

    # Filter names that are not IDNA-encodable.
    # We try pretty hard not to generate bogus names in the first place... but
    # catching all cases is not trivial.
    try:
        idna_encode(name)
    except IDNAError:
        assume(False)

    return name
Beispiel #2
0
def hostnames(draw,
              allow_leading_digit=True,
              allow_idn=True):  # pragma: no cover
    # type: (DrawCallable, bool, bool) -> Text
    """
    A strategy which generates host names.

    @param allow_leading_digit: Whether to allow a leading digit in host names;
        they were not allowed prior to RFC 1123.

    @param allow_idn: Whether to allow non-ASCII characters as allowed by
        internationalized domain names (IDNs).
    """
    labels = cast(
        Sequence[Text],
        draw(
            lists(
                hostname_labels(allow_idn=allow_idn), min_size=1,
                max_size=5).filter(
                    lambda ls: sum(len(s) for s in ls) + len(ls) - 1 <= 252)),
    )

    name = u".".join(labels)

    # Filter names that are not IDNA-encodable.
    # We try pretty hard not to generate bogus names in the first place... but
    # catching all cases is not trivial.
    try:
        idna_encode(name)
    except IDNAError:
        assume(False)

    return name
Beispiel #3
0
    def idna_text(draw, min_size=1, max_size=None):
        # type: (DrawCallable, int, Optional[int]) -> Text
        """
        A strategy which generates IDNA-encodable text.

        @param min_size: The minimum number of characters in the text.
            C{None} is treated as C{0}.

        @param max_size: The maximum number of characters in the text.
            Use C{None} for an unbounded size.
        """
        alphabet = idna_characters()

        assert min_size >= 1

        if max_size is not None:
            assert max_size >= 1

        result = cast(
            Text,
            draw(text(min_size=min_size, max_size=max_size,
                      alphabet=alphabet)),
        )

        # FIXME: There should be a more efficient way to ensure we produce
        # valid IDNA text.
        try:
            idna_encode(result)
        except IDNAError:
            assume(False)

        return result
Beispiel #4
0
 def test_idna_text_valid(self, text):
     # type: (Text) -> None
     """
     idna_text() generates IDNA-encodable text.
     """
     try:
         idna_encode(text)
     except IDNAError:  # pragma: no cover
         raise AssertionError("Invalid IDNA text: {!r}".format(text))
Beispiel #5
0
 def test_hostname_labels_valid_idn(self, label):
     # type: (Text) -> None
     """
     hostname_labels() generates IDN host name labels.
     """
     try:
         check_label(label)
         idna_encode(label)
     except UnicodeError:  # pragma: no cover
         raise AssertionError("Invalid IDN label: {!r}".format(label))
Beispiel #6
0
 def test_hostnames_idn(self, hostname):
     # type: (Text) -> None
     """
     hostnames() generates a IDN host names.
     """
     try:
         for label in hostname.split(u"."):
             check_label(label)
         idna_encode(hostname)
     except UnicodeError:  # pragma: no cover
         raise AssertionError(
             "Invalid IDN host name: {!r}".format(hostname))
Beispiel #7
0
        def test_hostname_labels_long_idn_punycode(self, data):
            # type: (SearchStrategy) -> None
            """
            hostname_labels() handles case where idna_text() generates text
            that encoded to punycode ends up as longer than allowed.
            """
            @composite
            def mock_idna_text(draw, min_size, max_size):
                # type: (DrawCallable, int, int) -> Text
                # We want a string that does not exceed max_size, but when
                # encoded to punycode, does exceed max_size.
                # So use a unicode character that is larger when encoded,
                # "á" being a great example, and use it max_size times, which
                # will be max_size * 3 in size when encoded.
                return u"\N{LATIN SMALL LETTER A WITH ACUTE}" * max_size

            with patch("hyperlink.hypothesis.idna_text", mock_idna_text):
                label = data.draw(hostname_labels())
                try:
                    check_label(label)
                    idna_encode(label)
                except UnicodeError:  # pragma: no cover
                    raise AssertionError(
                        "Invalid IDN label: {!r}".format(label))