This file is indexed.

/usr/lib/python2.7/dist-packages/pytest_bdd/scenario.py is in python-pytest-bdd 2.18.2-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
"""Scenario implementation.

The pytest will collect the test case and the steps will be executed
line by line.

Example:

test_publish_article = scenario(
    feature_name="publish_article.feature",
    scenario_name="Publishing the article",
)
"""
import collections
import inspect
import os
import re

import pytest
try:
    from _pytest import fixtures as pytest_fixtures
except ImportError:
    from _pytest import python as pytest_fixtures
import six

from . import exceptions
from . import fixtures
from .feature import (
    Feature,
    force_encode,
    force_unicode,
    get_features,
)
from .steps import (
    execute,
    get_caller_function,
    get_caller_module,
    get_step_fixture_name,
    inject_fixture,
    recreate_function,
)
from .types import GIVEN
from .utils import get_args, get_fixture_value

if six.PY3:  # pragma: no cover
    import runpy

    def execfile(filename, init_globals):
        """Execute given file as a python script in given globals environment."""
        result = runpy.run_path(filename, init_globals=init_globals)
        init_globals.update(result)


PYTHON_REPLACE_REGEX = re.compile("\W")
ALPHA_REGEX = re.compile("^\d+_*")


def find_argumented_step_fixture_name(name, type_, fixturemanager, request=None):
    """Find argumented step fixture name."""
    # happens to be that _arg2fixturedefs is changed during the iteration so we use a copy
    for fixturename, fixturedefs in list(fixturemanager._arg2fixturedefs.items()):
        for fixturedef in fixturedefs:
            parser = getattr(fixturedef.func, "parser", None)
            match = parser.is_matching(name) if parser else None
            if match:
                converters = getattr(fixturedef.func, "converters", {})
                for arg, value in parser.parse_arguments(name).items():
                    if arg in converters:
                        value = converters[arg](value)
                    if request:
                        inject_fixture(request, arg, value)
                parser_name = get_step_fixture_name(parser.name, type_)
                if request:
                    try:
                        get_fixture_value(request, parser_name)
                    except pytest_fixtures.FixtureLookupError:
                        continue
                return parser_name


def _find_step_function(request, step, scenario, encoding):
    """Match the step defined by the regular expression pattern.

    :param request: PyTest request object.
    :param step: Step.
    :param scenario: Scenario.

    :return: Function of the step.
    :rtype: function
    """
    name = step.name
    try:
        return get_fixture_value(request, get_step_fixture_name(name, step.type, encoding))
    except pytest_fixtures.FixtureLookupError:
        try:
            name = find_argumented_step_fixture_name(name, step.type, request._fixturemanager, request)
            if name:
                return get_fixture_value(request, name)
            raise
        except pytest_fixtures.FixtureLookupError:
            raise exceptions.StepDefinitionNotFoundError(
                u"""Step definition is not found: {step}."""
                """ Line {step.line_number} in scenario "{scenario.name}" in the feature "{feature.filename}""".format(
                    step=step,
                    scenario=scenario,
                    feature=scenario.feature,
                )
            )


def _execute_step_function(request, scenario, step, step_func):
    """Execute step function.

    :param request: PyTest request.
    :param scenario: Scenario.
    :param step: Step.
    :param function step_func: Step function.
    :param example: Example table.
    """
    kw = dict(
        request=request,
        feature=scenario.feature,
        scenario=scenario,
        step=step,
        step_func=step_func,
    )

    request.config.hook.pytest_bdd_before_step(**kw)

    kw["step_func_args"] = {}
    try:
        # Get the step argument values.
        kwargs = dict((arg, get_fixture_value(request, arg)) for arg in get_args(step_func))
        kw["step_func_args"] = kwargs

        request.config.hook.pytest_bdd_before_step_call(**kw)
        # Execute the step.
        step_func(**kwargs)
        request.config.hook.pytest_bdd_after_step(**kw)
    except Exception as exception:
        request.config.hook.pytest_bdd_step_error(exception=exception, **kw)
        raise


def _execute_scenario(feature, scenario, request, encoding):
    """Execute the scenario.

    :param feature: Feature.
    :param scenario: Scenario.
    :param request: request.
    :param encoding: Encoding.
    """
    request.config.hook.pytest_bdd_before_scenario(
        request=request,
        feature=feature,
        scenario=scenario,
    )

    try:
        givens = set()
        # Execute scenario steps
        for step in scenario.steps:
            try:
                step_func = _find_step_function(request, step, scenario, encoding=encoding)
            except exceptions.StepDefinitionNotFoundError as exception:
                request.config.hook.pytest_bdd_step_func_lookup_error(
                    request=request,
                    feature=feature,
                    scenario=scenario,
                    step=step,
                    exception=exception,
                )
                raise

            try:
                # Check if the fixture that implements given step has not been yet used by another given step
                if step.type == GIVEN:
                    if step_func.fixture in givens:
                        raise exceptions.GivenAlreadyUsed(
                            u'Fixture "{0}" that implements this "{1}" given step has been already used.'.format(
                                step_func.fixture, step.name,
                            )
                        )
                    givens.add(step_func.fixture)
            except exceptions.ScenarioValidationError as exception:
                request.config.hook.pytest_bdd_step_validation_error(
                    request=request,
                    feature=feature,
                    scenario=scenario,
                    step=step,
                    step_func=step_func,
                    exception=exception,
                )
                raise

            _execute_step_function(request, scenario, step, step_func)
    finally:
        request.config.hook.pytest_bdd_after_scenario(
            request=request,
            feature=feature,
            scenario=scenario,
        )


FakeRequest = collections.namedtuple("FakeRequest", ["module"])


def get_fixture(caller_module, fixture, path=None):
    """Get first conftest module from given one."""
    def call_fixture(function):
        args = []
        if "request" in get_args(function):
            args = [FakeRequest(module=caller_module)]
        return function(*args)

    if path is None:
        if hasattr(caller_module, fixture):
            return call_fixture(getattr(caller_module, fixture))
        path = os.path.dirname(caller_module.__file__)

    if os.path.exists(os.path.join(path, "__init__.py")):
        file_path = os.path.join(path, "conftest.py")
        if os.path.exists(file_path):
            globs = {}
            execfile(file_path, globs)
            if fixture in globs:
                return call_fixture(globs[fixture])
    else:
        return call_fixture(getattr(fixtures, fixture))
    return get_fixture(caller_module, fixture, path=os.path.dirname(path))


def _get_scenario_decorator(feature, feature_name, scenario, scenario_name, caller_module, caller_function, encoding):
    """Get scenario decorator."""
    g = locals()
    g["_execute_scenario"] = _execute_scenario

    scenario_name = force_encode(scenario_name, encoding)

    def decorator(_pytestbdd_function):
        if isinstance(_pytestbdd_function, pytest_fixtures.FixtureRequest):
            raise exceptions.ScenarioIsDecoratorOnly(
                "scenario function can only be used as a decorator. Refer to the documentation.",
            )

        g.update(locals())

        args = get_args(_pytestbdd_function)
        function_args = list(args)
        for arg in scenario.get_example_params():
            if arg not in function_args:
                function_args.append(arg)
        if "request" not in function_args:
            function_args.append("request")

        code = """def {name}({function_args}):
            _execute_scenario(feature, scenario, request, encoding)
            _pytestbdd_function({args})""".format(
            name=_pytestbdd_function.__name__,
            function_args=", ".join(function_args),
            args=", ".join(args))

        execute(code, g)

        _scenario = recreate_function(
            g[_pytestbdd_function.__name__],
            module=caller_module,
            firstlineno=caller_function.f_lineno,
        )

        for param_set in scenario.get_params():
            if param_set:
                _scenario = pytest.mark.parametrize(*param_set)(_scenario)

        for tag in scenario.tags.union(feature.tags):
            pytest.config.hook.pytest_bdd_apply_tag(tag=tag, function=_scenario)

        _scenario.__doc__ = "{feature_name}: {scenario_name}".format(
            feature_name=feature_name, scenario_name=scenario_name)
        _scenario.__scenario__ = scenario
        scenario.test_function = _scenario
        return _scenario

    return recreate_function(decorator, module=caller_module, firstlineno=caller_function.f_lineno)


def scenario(feature_name, scenario_name, encoding="utf-8", example_converters=None,
             caller_module=None, caller_function=None):
    """Scenario decorator.

    :param str feature_name: Feature file name. Absolute or relative to the configured feature base path.
    :param str scenario_name: Scenario name.
    :param str encoding: Feature file encoding.
    :param dict example_converters: optional `dict` of example converter function, where key is the name of the
        example parameter, and value is the converter function.
    """
    scenario_name = force_unicode(scenario_name, encoding)
    caller_module = caller_module or get_caller_module()
    caller_function = caller_function or get_caller_function()

    # Get the feature
    base_path = get_fixture(caller_module, "pytestbdd_feature_base_dir")
    strict_gherkin = get_fixture(caller_module, "pytestbdd_strict_gherkin")
    feature = Feature.get_feature(base_path, feature_name, encoding=encoding, strict_gherkin=strict_gherkin)

    # Get the sc_enario
    try:
        scenario = feature.scenarios[scenario_name]
    except KeyError:
        raise exceptions.ScenarioNotFound(
            u'Scenario "{scenario_name}" in feature "{feature_name}" in {feature_filename} is not found.'.format(
                scenario_name=scenario_name,
                feature_name=feature.name or "[Empty]",
                feature_filename=feature.filename,
            )
        )

    scenario.example_converters = example_converters

    # Validate the scenario
    scenario.validate()

    return _get_scenario_decorator(
        feature,
        feature_name,
        scenario,
        scenario_name,
        caller_module,
        caller_function,
        encoding,
    )


def make_python_name(string):
    """Make python attribute name out of a given string."""
    string = re.sub(PYTHON_REPLACE_REGEX, "", string.replace(" ", "_"))
    return re.sub(ALPHA_REGEX, "", string).lower()


def get_python_name_generator(name):
    """Generate a sequence of suitable python names out of given arbitrary string name."""
    python_name = make_python_name(name)
    suffix = ''
    index = 0

    def get_name():
        return 'test_{0}{1}'.format(python_name, suffix)
    while True:
        yield get_name()
        index += 1
        suffix = '_{0}'.format(index)


def scenarios(*feature_paths, **kwargs):
    """Parse features from the paths and put all found scenarios in the caller module.

    :param *feature_paths: feature file paths to use for scenarios
    """
    frame = inspect.stack()[1]
    module = inspect.getmodule(frame[0])
    base_path = get_fixture(module, "pytestbdd_feature_base_dir")
    strict_gherkin = get_fixture(module, "pytestbdd_strict_gherkin")
    abs_feature_paths = []
    for path in feature_paths:
        if not os.path.isabs(path):
            path = os.path.abspath(os.path.join(base_path, path))
        abs_feature_paths.append(path)
    found = False

    module_scenarios = frozenset(
        (attr.__scenario__.feature.filename, attr.__scenario__.name)
        for name, attr in module.__dict__.items() if hasattr(attr, '__scenario__'))

    index = 10
    for feature in get_features(abs_feature_paths, strict_gherkin=strict_gherkin):
        for scenario_name, scenario_object in feature.scenarios.items():
            # skip already bound scenarios
            if (scenario_object.feature.filename, scenario_name) not in module_scenarios:
                @scenario(feature.filename, scenario_name, **kwargs)
                def _scenario():
                    pass  # pragma: no cover
                for test_name in get_python_name_generator(scenario_name):
                    if test_name not in module.__dict__:
                        # found an unique test name
                        # recreate function to set line number
                        _scenario = recreate_function(_scenario, module=module, firstlineno=index * 4)
                        index += 1
                        module.__dict__[test_name] = _scenario
                        break
            found = True
    if not found:
        raise exceptions.NoScenariosFound(abs_feature_paths)