<commit_before># -*- coding: utf-8 -*-

import re

_REGEX = re.compile("^([0-9]+)"   # major
                    "\.([0-9]+)"  # minor
                    "\.([0-9]+)"  # patch
                    "(\-[0-9A-Za-z]+(\.[0-9A-Za-z]+)*)?"    # pre-release
                    "(\+[0-9A-Za-z]+(\.[0-9A-Za-z]+)*)?$")  # build

def parse(version):
    """
    Parse version to major, minor, patch, pre-release, build parts.
    """
    match = _REGEX.match(version)
    if match is None:
        raise ValueError('%s is not valid SemVer string' % version)

    rv = {
        'major': int(match.group(1)),
        'minor': int(match.group(2)),
        'patch': int(match.group(3)),
    }

    if match.group(4):
        rv['prerelease'] = match.group(4).lstrip('-')

    if match.group(6):
        rv['build'] = match.group(6).lstrip('+')

    return rv


def compare(ver1, ver2):
    def compare_by_keys(d1, d2, keys):
        for key in keys:
            v = cmp(d1.get(key), d2.get(key))
            if v != 0:
                return v
        return 0

    v1, v2 = parse(ver1), parse(ver2)

    return compare_by_keys(
        v1, v2, ['major', 'minor', 'patch', 'prerelease', 'build'])


def match(version, match_expr):
    prefix = match_expr[:2]
    if prefix in ('>=', '<=', '=='):
        match_version = match_expr[2:]
    elif prefix and prefix[0] in ('>', '<', '='):
        prefix = prefix[0]
        match_version = match_expr[1:]
    else:
        raise ValueError("match_expr parameter should be in format <op><ver>, "
                         "where <op> is one of ['<', '>', '==', '<=', '>=']. "
                         "You provided: %r" % match_expr)
<commit_msg>Use self documented regular expression.<commit_after># -*- coding: utf-8 -*-

import re

_REGEX = re.compile('^(?P<major>[0-9]+)'
                    '\.(?P<minor>[0-9]+)'
                    '\.(?P<patch>[0-9]+)'
                    '(\-(?P<prerelease>[0-9A-Za-z]+(\.[0-9A-Za-z]+)*))?'
                    '(\+(?P<build>[0-9A-Za-z]+(\.[0-9A-Za-z]+)*))?$')

def parse(version):
    """
    Parse version to major, minor, patch, pre-release, build parts.
    """
    match = _REGEX.match(version)
    if match is None:
        raise ValueError('%s is not valid SemVer string' % version)

    verinfo = match.groupdict()

    verinfo['major'] = int(verinfo['major'])
    verinfo['minor'] = int(verinfo['minor'])
    verinfo['patch'] = int(verinfo['patch'])

    return verinfo


def compare(ver1, ver2):
    def compare_by_keys(d1, d2, keys):
        for key in keys:
            v = cmp(d1.get(key), d2.get(key))
            if v != 0:
                return v
        return 0

    v1, v2 = parse(ver1), parse(ver2)

    return compare_by_keys(
        v1, v2, ['major', 'minor', 'patch', 'prerelease', 'build'])


def match(version, match_expr):
    prefix = match_expr[:2]
    if prefix in ('>=', '<=', '=='):
        match_version = match_expr[2:]
    elif prefix and prefix[0] in ('>', '<', '='):
        prefix = prefix[0]
        match_version = match_expr[1:]
    else:
        raise ValueError("match_expr parameter should be in format <op><ver>, "
                         "where <op> is one of ['<', '>', '==', '<=', '>=']. "
                         "You provided: %r" % match_expr)

{'fraction_non_alphanumeric': 0.2020788749617854, 'fraction_numerical': 0.022928767960868235, 'mean_word_length': 2.0101195952161914, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 22, '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': '1711332', 'n_tokens_mistral': 1176, 'n_tokens_neox': 1123, 'n_words': 250}