<commit_before>"""
Dynamically generated set of TestCases based on set of yaml files decribing
some integration tests. These files are shared among all official Elasticsearch
clients.
"""
import re
from os import walk, environ
from os.path import exists, join, dirname, pardir
import yaml

from elasticsearch import TransportError
from elasticsearch.compat import string_types
from elasticsearch.helpers.test import _get_version

from ..test_cases import SkipTest
from . import ElasticsearchTestCase

# some params had to be changed in python, keep track of them so we can rename
# those in the tests accordingly
PARAMS_RENAMES = {
    'type': 'doc_type',
    'from': 'from_',
}

# mapping from catch values to http status codes
CATCH_CODES = {
    'missing': 404,
    'conflict': 409,
}

# test features we have implemented
IMPLEMENTED_FEATURES = ('gtelte', 'stash_in_path')

# broken YAML tests on some releases
SKIP_TESTS = {
    (1, 1, 2): set(('TestCatRecovery10Basic', ))
}

class InvalidActionType(Exception):
    pass

class YamlTestCase(ElasticsearchTestCase):
    def setUp(self):
        super(YamlTestCase, self).setUp()
        if hasattr(self, '_setup_code'):
            self.run_code(self._setup_code)
        self.last_response = None
        self._state = {}

    def _resolve(self, value):
        # resolve variables
        if isinstance(value, string_types) and value.startswith('$'):
            value = value[1:]
            self.assertIn(value, self._state)
            value = self._state[value]
        if isinstance(value, string_types):
            value = value.strip()
        elif isinstance(value, dict):
            value = dict((k, self._resolve(v)) for (k, v) in value.items())
        elif isinstance(value, list):
            value = list(map(self._resolve, value))
        return value

    def _lookup(self, path):
        # fetch the possibly nested value from last_response
        value = self.last_response
        if path == '$body':
            return value
        path = path.replace(r'\.', '\1')
        for step in path.split('.'):
            if not step:
                continue
            step = step.replace('\1', '.')
            step = self._resolve(step)
            if step.isdigit():
                step = int(step)
                self.assertIsInstance(value, list)
                self.assertGreater(len(value), step)
            else:
                self.assertIn(step, value)
            value = value[step]
        return value

    def run_code(self, test):
        """ Execute an instruction based on it's type. """
        for action in test:
            self.assertEquals(1, len(action))
            action_type, action = list(action.items())[0]

            if hasattr(self, 'run_' + action_type):
                getattr(self, 'run_' + action_type)(action)
            else:
                raise InvalidActionType(action_type)<commit_msg>Sometimes we have dicts indexed by integers in yaml tests<commit_after>"""
Dynamically generated set of TestCases based on set of yaml files decribing
some integration tests. These files are shared among all official Elasticsearch
clients.
"""
import re
from os import walk, environ
from os.path import exists, join, dirname, pardir
import yaml

from elasticsearch import TransportError
from elasticsearch.compat import string_types
from elasticsearch.helpers.test import _get_version

from ..test_cases import SkipTest
from . import ElasticsearchTestCase

# some params had to be changed in python, keep track of them so we can rename
# those in the tests accordingly
PARAMS_RENAMES = {
    'type': 'doc_type',
    'from': 'from_',
}

# mapping from catch values to http status codes
CATCH_CODES = {
    'missing': 404,
    'conflict': 409,
}

# test features we have implemented
IMPLEMENTED_FEATURES = ('gtelte', 'stash_in_path')

# broken YAML tests on some releases
SKIP_TESTS = {
    (1, 1, 2): set(('TestCatRecovery10Basic', ))
}

class InvalidActionType(Exception):
    pass

class YamlTestCase(ElasticsearchTestCase):
    def setUp(self):
        super(YamlTestCase, self).setUp()
        if hasattr(self, '_setup_code'):
            self.run_code(self._setup_code)
        self.last_response = None
        self._state = {}

    def _resolve(self, value):
        # resolve variables
        if isinstance(value, string_types) and value.startswith('$'):
            value = value[1:]
            self.assertIn(value, self._state)
            value = self._state[value]
        if isinstance(value, string_types):
            value = value.strip()
        elif isinstance(value, dict):
            value = dict((k, self._resolve(v)) for (k, v) in value.items())
        elif isinstance(value, list):
            value = list(map(self._resolve, value))
        return value

    def _lookup(self, path):
        # fetch the possibly nested value from last_response
        value = self.last_response
        if path == '$body':
            return value
        path = path.replace(r'\.', '\1')
        for step in path.split('.'):
            if not step:
                continue
            step = step.replace('\1', '.')
            step = self._resolve(step)
            if step.isdigit() and step not in value:
                step = int(step)
                self.assertIsInstance(value, list)
                self.assertGreater(len(value), step)
            else:
                self.assertIn(step, value)
            value = value[step]
        return value

    def run_code(self, test):
        """ Execute an instruction based on it's type. """
        for action in test:
            self.assertEquals(1, len(action))
            action_type, action = list(action.items())[0]

            if hasattr(self, 'run_' + action_type):
                getattr(self, 'run_' + action_type)(action)
            else:
                raise InvalidActionType(action_type)
{'fraction_non_alphanumeric': 0.09945689069925323, 'fraction_numerical': 0.005431093007467753, 'mean_word_length': 2.420197330237957, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5620041', 'n_tokens_mistral': 1671, 'n_tokens_neox': 1637, 'n_words': 513}