File: test_codemods.py

package info (click to toggle)
python-hypothesis 6.138.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 15,272 kB
  • sloc: python: 62,853; ruby: 1,107; sh: 253; makefile: 41; javascript: 6
file content (169 lines) | stat: -rw-r--r-- 6,193 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# This file is part of Hypothesis, which may be found at
# https://github.com/HypothesisWorks/hypothesis/
#
# Copyright the Hypothesis Authors.
# Individual contributors are listed in AUTHORS.rst and the git log.
#
# This Source Code Form is subject to the terms of the Mozilla Public License,
# v. 2.0. If a copy of the MPL was not distributed with this file, You can
# obtain one at https://mozilla.org/MPL/2.0/.

from libcst.codemod import CodemodTest

from hypothesis.extra import codemods


def test_refactor_function_is_idempotent():
    before = (
        "from hypothesis.strategies import complex_numbers\n\n"
        "complex_numbers(None)\n"
    )
    after = codemods.refactor(before)
    assert before.replace("None", "min_magnitude=0") == after
    assert codemods.refactor(after) == after


class TestFixComplexMinMagnitude(CodemodTest):
    TRANSFORM = codemods.HypothesisFixComplexMinMagnitude

    def test_noop(self) -> None:
        before = """
            from hypothesis.strategies import complex_numbers, complex_numbers as cn

            complex_numbers(min_magnitude=1)  # value OK
            complex_numbers(max_magnitude=None)  # different argument

            class Foo:
                def complex_numbers(self, **kw): pass

                complex_numbers(min_magnitude=None)  # defined in a different scope
        """
        self.assertCodemod(before=before, after=before)

    def test_substitution(self) -> None:
        before = """
            from hypothesis.strategies import complex_numbers, complex_numbers as cn

            complex_numbers(min_magnitude=None)  # simple call to fix
            complex_numbers(min_magnitude=None, max_magnitude=1)  # plus arg after
            complex_numbers(allow_infinity=False, min_magnitude=None)  # plus arg before
            cn(min_magnitude=None)  # imported as alias
        """
        self.assertCodemod(before=before, after=before.replace("None", "0"))


class TestFixPositionalKeywonlyArgs(CodemodTest):
    TRANSFORM = codemods.HypothesisFixPositionalKeywonlyArgs

    def test_substitution(self) -> None:
        before = """
            import hypothesis.strategies as st

            st.floats(0, 1, False, False, 32)
            st.fractions(0, 1, 9)
        """
        after = """
            import hypothesis.strategies as st

            st.floats(0, 1, allow_nan=False, allow_infinity=False, width=32)
            st.fractions(0, 1, max_denominator=9)
        """
        self.assertCodemod(before=before, after=after)

    def test_noop_with_new_floats_kw(self) -> None:
        before = """
            import hypothesis.strategies as st

            st.floats(0, 1, False, False, True, 32, False, False)  # allow_subnormal=True
        """
        self.assertCodemod(before=before, after=before)

    def test_noop_if_unsure(self) -> None:
        before = """
            import random

            if random.getrandbits(1):
                from hypothesis import target
                from hypothesis.strategies import lists as sets

                def fractions(*args):
                    pass

            else:
                from hypothesis import target
                from hypothesis.strategies import fractions, sets

            fractions(0, 1, 9)
            sets(None, 1)
            target(0, 'label')
        """
        after = before.replace("'label'", "label='label'")
        self.assertCodemod(before=before, after=after)

    def test_stateful_rule_noop(self):
        # `rule()(lambda self: None)` is a call with a positional argument, and
        # so we need an additional check that the "func" node is a Name rather than
        # itself being a Call, lest we rewrite the outer instead of the inner.
        # (this may be an upstream bug in metadata processing)
        before = """
            from hypothesis.stateful import RuleBasedStateMachine, rule

            class MultipleRulesSameFuncMachine(RuleBasedStateMachine):
                rule1 = rule()(lambda self: None)
        """
        self.assertCodemod(before=before, after=before)

    def test_kwargs_noop(self):
        before = """
            from hypothesis import target

            kwargs = {"observation": 1, "label": "foobar"}
            target(**kwargs)
        """
        self.assertCodemod(before=before, after=before)

    def test_noop_with_too_many_arguments_passed(self) -> None:
        # If there are too many arguments, we should leave this alone to raise
        # TypeError on older versions instead of deleting the additional args.
        before = """
            import hypothesis.strategies as st

            st.sets(st.integers(), 0, 1, True)
        """
        self.assertCodemod(before=before, after=before)


class TestHealthCheckAll(CodemodTest):
    TRANSFORM = codemods.HypothesisFixHealthCheckAll

    def test_noop_other_attributes(self):
        # Test that calls to other attributes of HealthCheck are not modified
        before = "result = HealthCheck.data_too_large"
        self.assertCodemod(before=before, after=before)

    def test_substitution(self) -> None:
        # Test that HealthCheck.all() is replaced with list(HealthCheck)
        before = "result = HealthCheck.all()"
        after = "result = list(HealthCheck)"
        # self.assertEqual(run_codemod(input_code), expected_code)
        self.assertCodemod(before=before, after=after)


class TestFixCharactersArguments(CodemodTest):
    TRANSFORM = codemods.HypothesisFixCharactersArguments

    def test_substitution(self) -> None:
        for in_, out in codemods.HypothesisFixCharactersArguments._replacements.items():
            before = f"""
                import hypothesis.strategies as st
                st.characters({in_}=...)
            """
            self.assertCodemod(before=before, after=before.replace(in_, out))

    def test_remove_redundant_exclude_categories(self) -> None:
        args = "blacklist_categories=OUT, whitelist_categories=IN"
        before = f"""
                import hypothesis.strategies as st
                st.characters({args})
            """
        self.assertCodemod(before=before, after=before.replace(args, "categories=IN"))