provisional.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. # coding=utf-8
  2. #
  3. # This file is part of Hypothesis, which may be found at
  4. # https://github.com/HypothesisWorks/hypothesis-python
  5. #
  6. # Most of this work is copyright (C) 2013-2018 David R. MacIver
  7. # (david@drmaciver.com), but it contains contributions by others. See
  8. # CONTRIBUTING.rst for a full list of people who may hold copyright, and
  9. # consult the git log if you need to determine who owns an individual
  10. # contribution.
  11. #
  12. # This Source Code Form is subject to the terms of the Mozilla Public License,
  13. # v. 2.0. If a copy of the MPL was not distributed with this file, You can
  14. # obtain one at http://mozilla.org/MPL/2.0/.
  15. #
  16. # END HEADER
  17. """This module contains various provisional APIs and strategies.
  18. It is intended for internal use, to ease code reuse, and is not stable.
  19. Point releases may move or break the contents at any time!
  20. Internet strategies should conform to https://tools.ietf.org/html/rfc3696 or
  21. the authoritative definitions it links to. If not, report the bug!
  22. """
  23. from __future__ import division, print_function, absolute_import
  24. import string
  25. import hypothesis.strategies as st
  26. @st.defines_strategy_with_reusable_values
  27. def domains():
  28. """A strategy for :rfc:`1035` fully qualified domain names."""
  29. atoms = st.text(string.ascii_letters + '0123456789-',
  30. min_size=1, max_size=63
  31. ).filter(lambda s: '-' not in s[0] + s[-1])
  32. return st.builds(
  33. lambda x, y: '.'.join(x + [y]),
  34. st.lists(atoms, min_size=1),
  35. # TODO: be more devious about top-level domains
  36. st.sampled_from(['com', 'net', 'org', 'biz', 'info'])
  37. ).filter(lambda url: len(url) <= 255)
  38. @st.defines_strategy_with_reusable_values
  39. def emails():
  40. """A strategy for email addresses.
  41. See https://github.com/HypothesisWorks/hypothesis-python/issues/162
  42. for work on a permanent replacement.
  43. """
  44. local_chars = string.ascii_letters + string.digits + "!#$%&'*+-/=^_`{|}~"
  45. local_part = st.text(local_chars, min_size=1, max_size=64)
  46. # TODO: include dot-atoms, quoted strings, escaped chars, etc in local part
  47. return st.builds('{}@{}'.format, local_part, domains()).filter(
  48. lambda addr: len(addr) <= 255)
  49. @st.defines_strategy_with_reusable_values
  50. def ip4_addr_strings():
  51. """A strategy for IPv4 address strings.
  52. This consists of four strings representing integers [0..255],
  53. without zero-padding, joined by dots.
  54. """
  55. return st.builds('{}.{}.{}.{}'.format, *(4 * [st.integers(0, 255)]))
  56. @st.defines_strategy_with_reusable_values
  57. def ip6_addr_strings():
  58. """A strategy for IPv6 address strings.
  59. This consists of sixteen quads of hex digits (0000 .. FFFF), joined
  60. by colons. Values do not currently have zero-segments collapsed.
  61. """
  62. part = st.integers(0, 2**16 - 1).map(u'{:04x}'.format)
  63. return st.tuples(*[part] * 8).map(lambda a: u':'.join(a).upper())