<commit_before># -*- coding: utf8 -*-
import os
import re
import subprocess
import warnings
import shlex

import yaml

from rlp.utils import decode_hex
from ethereum import utils

BINARY = 'solc'


class CompileError(Exception):
    pass


class SolcMissing(Exception):
    pass


def get_compiler_path():
    """ Return the path to the solc compiler.

    This funtion will search for the solc binary in the $PATH and return the
    path of the first executable occurence.
    """
    # If the user provides a specific solc binary let's use that
    given_binary = os.environ.get('SOLC_BINARY')
    if given_binary:
        return given_binary

    for path in os.getenv('PATH', '').split(os.pathsep):
        path = path.strip('"')
        executable_path = os.path.join(path, BINARY)

        if os.path.isfile(executable_path) and os.access(executable_path, os.X_OK):
            return executable_path

    return None


def get_solidity():
    """ Return the singleton used to interact with the solc compiler. """
    if get_compiler_path() is None:
        return None  # the compiler wasn't found in $PATH

    return solc_wrapper


def solc_arguments(libraries=None, combined='bin,abi', optimize=True, extra_args=None):
    """ Build the arguments to call the solc binary. """
    args = [
        '--combined-json', combined,
        '--add-std'
    ]

    if optimize:
        args.append('--optimize')

    if extra_args:
        try:
            args.extend(shlex.split(extra_args))
        except:  # if not a parseable string then treat it as a list
            args.extend(extra_args)

    if libraries is not None and len(libraries):
        addresses = [
            '{name}:{address}'.format(name=name, address=address.decode('utf8'))
            for name, address in libraries.items()
        ]
        args.extend([
            '--libraries',
            ','.join(addresses),
        ])

    return args


def solc_parse_output(compiler_output):
    """ Parses the compiler output. """
    # At the moment some solc output like --hashes or -- gas will not output
    # json at all so if used with those arguments the logic here will break.
    # Perhaps solidity will slowly switch to a json only output and this comment
    # can eventually go away and we will not need to add more logic here at all.
    result = yaml.safe_load(compiler_output)['contracts']

    if 'bin' in tuple(result.values())[0]:
        for value in result.values():
            value['bin_hex'] = value['bin']

            # decoding can fail if the compiled contract has unresolved symbols
            try:
                value['bin'] = decode_hex(value['bin_hex'])
            except TypeError:
                pass

    for json_data in ('abi', 'devdoc', 'userdoc'):
        # the values in the output can be configured through the
        # --combined-json flag, check that it's present in the first value and
        # assume all values are consistent
        if json_data not in tuple(result.values())[0]:
            continue

        for value in result.values():
            value[json_data] = yaml.safe_load(value[json_data])

    return result


def compiler_version():
    """ Return the version of the installed solc. """
    version_info = subprocess.check_output(['solc', '--version'])
    match = re.search(b'^Version: ([0-9a-z.-]+)/', version_info, re.MULTILINE)

    if match:
        return match.group(1)


def solidity_names(code):  # pylint: disable=too-many-branches
    """ Return the library and contract names in order of appearence. """
    names = []
    in_string = None
    backslash = False
    comment = None

    # "parse" the code by hand to handle the corner cases:
    #  - the contract or library can be inside a comment or string
    #  - multiline comments
    #  - the contract and library keywords could not be at the start of the line
    for pos, char in enumerate(code):
        if in_string:
            if not backslash and in_string == char:
                in_string = None
                backslash = False

            if char == '\\':  # pylint: disable=simplifiable-if-statement
                backslash = True
            else:
                backslash = False

        elif comment == '//':
            if char in ('\n', '\r'):
                comment = None

        elif comment == '/*':
            if char == '*' and code[pos + 1] == '/':
                comment = None

        else:
            if char == '"' or char == "'":
                in_string = char

            if char == '/':
                if code[pos + 1] == '/':
                    comment = '//'
                if code[pos + 1] == '*':
                    comment = '/*'

            if char == 'c' and code[pos: pos + 8] == 'contract':
                result = re.match('^contract[^_$a-zA-Z]+([_$a-zA-Z][_$a-zA-Z0-9]*)', code[pos:])

                if result:
                    names.append(('contract', result.groups()[0]))

            if char == 'l' and code[pos: pos + 7] == 'library':
                result = re.match('^library[^_$a-zA-Z]+([_$a-zA-Z][_$a-zA-Z0-9]*)', code[pos:])<commit_msg>solidity_names() recognizes interface<commit_after># -*- coding: utf8 -*-
import os
import re
import subprocess
import warnings
import shlex

import yaml

from rlp.utils import decode_hex
from ethereum import utils

BINARY = 'solc'


class CompileError(Exception):
    pass


class SolcMissing(Exception):
    pass


def get_compiler_path():
    """ Return the path to the solc compiler.

    This funtion will search for the solc binary in the $PATH and return the
    path of the first executable occurence.
    """
    # If the user provides a specific solc binary let's use that
    given_binary = os.environ.get('SOLC_BINARY')
    if given_binary:
        return given_binary

    for path in os.getenv('PATH', '').split(os.pathsep):
        path = path.strip('"')
        executable_path = os.path.join(path, BINARY)

        if os.path.isfile(executable_path) and os.access(executable_path, os.X_OK):
            return executable_path

    return None


def get_solidity():
    """ Return the singleton used to interact with the solc compiler. """
    if get_compiler_path() is None:
        return None  # the compiler wasn't found in $PATH

    return solc_wrapper


def solc_arguments(libraries=None, combined='bin,abi', optimize=True, extra_args=None):
    """ Build the arguments to call the solc binary. """
    args = [
        '--combined-json', combined,
        '--add-std'
    ]

    if optimize:
        args.append('--optimize')

    if extra_args:
        try:
            args.extend(shlex.split(extra_args))
        except:  # if not a parseable string then treat it as a list
            args.extend(extra_args)

    if libraries is not None and len(libraries):
        addresses = [
            '{name}:{address}'.format(name=name, address=address.decode('utf8'))
            for name, address in libraries.items()
        ]
        args.extend([
            '--libraries',
            ','.join(addresses),
        ])

    return args


def solc_parse_output(compiler_output):
    """ Parses the compiler output. """
    # At the moment some solc output like --hashes or -- gas will not output
    # json at all so if used with those arguments the logic here will break.
    # Perhaps solidity will slowly switch to a json only output and this comment
    # can eventually go away and we will not need to add more logic here at all.
    result = yaml.safe_load(compiler_output)['contracts']

    if 'bin' in tuple(result.values())[0]:
        for value in result.values():
            value['bin_hex'] = value['bin']

            # decoding can fail if the compiled contract has unresolved symbols
            try:
                value['bin'] = decode_hex(value['bin_hex'])
            except TypeError:
                pass

    for json_data in ('abi', 'devdoc', 'userdoc'):
        # the values in the output can be configured through the
        # --combined-json flag, check that it's present in the first value and
        # assume all values are consistent
        if json_data not in tuple(result.values())[0]:
            continue

        for value in result.values():
            value[json_data] = yaml.safe_load(value[json_data])

    return result


def compiler_version():
    """ Return the version of the installed solc. """
    version_info = subprocess.check_output(['solc', '--version'])
    match = re.search(b'^Version: ([0-9a-z.-]+)/', version_info, re.MULTILINE)

    if match:
        return match.group(1)


def solidity_names(code):  # pylint: disable=too-many-branches
    """ Return the library and contract names in order of appearence. """
    names = []
    in_string = None
    backslash = False
    comment = None

    # "parse" the code by hand to handle the corner cases:
    #  - the contract or library can be inside a comment or string
    #  - multiline comments
    #  - the contract and library keywords could not be at the start of the line
    for pos, char in enumerate(code):
        if in_string:
            if not backslash and in_string == char:
                in_string = None
                backslash = False

            if char == '\\':  # pylint: disable=simplifiable-if-statement
                backslash = True
            else:
                backslash = False

        elif comment == '//':
            if char in ('\n', '\r'):
                comment = None

        elif comment == '/*':
            if char == '*' and code[pos + 1] == '/':
                comment = None

        else:
            if char == '"' or char == "'":
                in_string = char

            if char == '/':
                if code[pos + 1] == '/':
                    comment = '//'
                if code[pos + 1] == '*':
                    comment = '/*'

            if char == 'c' and code[pos: pos + 8] == 'contract':
                result = re.match('^contract[^_$a-zA-Z]+([_$a-zA-Z][_$a-zA-Z0-9]*)', code[pos:])

                if result:
                    names.append(('contract', result.groups()[0]))

            if char == 'i' and code[pos: pos + 9] == 'interface':
                result = re.match('^interface[^_$a-zA-Z]+([_$a-zA-Z][_$a-zA-Z0-9]*)', code[pos:])

                if result:
                    names.append(('contract', result.groups()[0]))


            if char == 'l' and code[pos: pos + 7] == 'library':
                result = re.match('^library[^_$a-zA-Z]+([_$a-zA-Z][_$a-zA-Z0-9]*)', code[pos:])
{'fraction_non_alphanumeric': 0.11863442389758179, 'fraction_numerical': 0.0036036036036036037, 'mean_word_length': 2.0827243496053787, 'pattern_counts': {'":': 2, '<': 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': '4905116', 'n_tokens_mistral': 3158, 'n_tokens_neox': 2969, 'n_words': 978}