<commit_before>from sqlalchemy import and_, or_, func


# field_ops
# =========
# Map codes we accept in API docs to SQLAlchemy function names

field_ops = {
    'gt': '__gt__',
    'ge': '__ge__',
    'lt': '__lt__',
    'le': '__le__',
    'ne': '__ne__',
    'like': 'like',
    'ilike': 'ilike',
    'is': 'is_',
    'isnot': 'isnot',
    'eq': 'eq',
    'in': 'in'
}


def parse_general(table, field, value):
    """To parse the non-tree style way of providing arguments.

    :param table: SQLAlchemy table objects
    :param field: specified column/table attribute
    :param value: target value to build a condition against

    :returns: table condition (SQL WHERE clause)"""

    # straigtforward time and geom filters
    if field in general_filters:
        return general_filters[field](table, value)

    field_tokens = field.split("__")
    column = table.columns.get(field_tokens[0])

    # equality filters based on table columns<commit_msg>tree parsing functionality added to condition_builder<commit_after>from sqlalchemy import and_, or_, func


# field_ops
# =========
# Map codes we accept in API docs to SQLAlchemy function names

field_ops = {
    'gt': '__gt__',
    'ge': '__ge__',
    'lt': '__lt__',
    'le': '__le__',
    'ne': '__ne__',
    'like': 'like',
    'ilike': 'ilike',
    'is': 'is_',
    'isnot': 'isnot',
    'eq': 'eq',
    'in': 'in'
}


def parse_tree(table, condition_tree):
    """Parse nested conditions provided as a dict for a single table. Wraps
    _parse_condition_tree and raises a ValueError if it fails.

    :param table: table object whose columns are being used in the conditions
    :param condition_tree: dictionary of conditions created from JSON

    :returns SQLAlchemy conditions for querying the table with"""

    try:
        return _parse_condition_tree(table, condition_tree)
    except Exception as ex:
        raise ValueError('{} caused parse to fail for table {} with args {}'
                         .format(ex, table, condition_tree))


def _parse_condition_tree(table, condition_tree):
    """Parse nested conditions provided as a dict for a single table.

    :param table: table object whose columns are being used in the conditions
    :param condition_tree: dictionary of conditions created from JSON

    :returns SQLAlchemy conditions for querying the table with"""

    op = condition_tree.keys()[0].lower()

    if len(condition_tree[op]) >= 1:

        if op == "and":
            # A non-leaf node, values are *iterable*! Takes the form:
            # {'and', [{'<STMT>': ('<COLUMN>', 'TARGET_VALUE')}, ... ]
            # Or if a nested query is desired:
            # {'and': [{'and', [{'<STMT>': ('<COLUMN>', '<TARGET_VALUE>')}, ... ]}

            return and_(
                _parse_condition_tree(table, child)
                for child in condition_tree['and']
            )

        elif op == "or":
            # See 'and'.

            return or_(
                _parse_condition_tree(table, child)
                for child in condition_tree['or']
            )

        elif op in field_ops:
            # At this point we are at a leaf. Leaves take the form:
            # {'<STMT>': ('<COLUMN>': '<TARGET_VALUE>')}

            value = condition_tree[op]
            column = value[0]
            target = value[1]

            try:
                return _operator_to_condition(
                    getattr(table, 'columns')[column], op, target
                )

            # This pretty much exists solely for date__time_of_day.
            except KeyError:
                return getattr(column, field_ops[op])(target)

    else:
        raise ValueError("Incorrect number of arguments provided.")


def parse_general(table, field, value):
    """To parse the non-tree style way of providing arguments.

    :param table: SQLAlchemy table objects
    :param field: specified column/table attribute
    :param value: target value to build a condition against

    :returns: table condition (SQL WHERE clause)"""

    # straigtforward time and geom filters
    if field in general_filters:
        return general_filters[field](table, value)

    field_tokens = field.split("__")
    column = table.columns.get(field_tokens[0])

    # equality filters based on table columns
{'fraction_non_alphanumeric': 0.11489957963568426, 'fraction_numerical': 0.0014012143858010276, 'mean_word_length': 2.6021867115222874, 'pattern_counts': {'":': 2, '<': 11, '<?xml version=': 0, '>': 12, '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': '3847588', 'n_tokens_mistral': 1257, 'n_tokens_neox': 1208, 'n_words': 425}