<commit_before>import traceback
import inspect
import os
import sys

try:
    import multiprocessing
    USE_MULTIPROCESSING = True
except ImportError:
    USE_MULTIPROCESSING = False

import platform
from datetime import datetime


class RaygunMessageBuilder:

    def __init__(self):
        self.raygunMessage = RaygunMessage()

    def new(self):
        return RaygunMessageBuilder()

    def build(self):
        return self.raygunMessage

    def set_machine_name(self, name):
        self.raygunMessage.details['machineName'] = name
        return self

    def set_environment_details(self):
        self.raygunMessage.details['environment'] = {
            "processorCount": (
                multiprocessing.cpu_count() if USE_MULTIPROCESSING else "n/a"
            ),
            "architecture": platform.architecture()[0],
            "cpu": platform.processor(),
            "oSVersion": "%s %s" % (platform.system(), platform.release()),
            "environmentVariables": os.environ.data
        }

        return self

    def set_exception_details(self, raygunExceptionMessage):
        self.raygunMessage.details['error'] = raygunExceptionMessage
        return self

    def set_client_details(self):
        self.raygunMessage.details['client'] = {
            "name": "raygun4py",
            "version": "2.2.0",
            "clientUrl": "https://github.com/MindscapeHQ/raygun4py"
        }
        return self

    def set_customdata(self, userCustomData):
        if type(userCustomData) is dict:
            self.raygunMessage.details['userCustomData'] = userCustomData
        return self

    def set_tags(self, tags):
        if type(tags) is list or tuple:
            self.raygunMessage.details['tags'] = tags
        return self

    def set_request_details(self, request):
        if request:
            self.raygunMessage.details['request'] = {
              "hostName": request['hostName'],
              "url": request['url'],
              "httpMethod": request['httpMethod'],
              "queryString": request['queryString'],
              "form": request['form'],
              "headers": request['headers'],
              "rawData": request['rawData'],
            }

            if 'ipAddress' in request:
                self.raygunMessage.details['request']['iPAddress'] = request['ipAddress']
            elif 'iPAddress' in request:
                self.raygunMessage.details['request']['iPAddress'] = request['iPAddress']

        return self

    def set_version(self, version):
        self.raygunMessage.details['version'] = version
        return self

    def set_user(self, user):
        if user is not None:
            self.raygunMessage.details['user'] = user
        return self


class RaygunMessage:

    def __init__(self):
        self.occurredOn = datetime.utcnow()
        self.details = {}

    def get_error(self):
        return self.details['error']

    def get_details(self):
        return self.details


class RaygunErrorMessage:

    def __init__(self, exc_type, exc_value, exc_traceback, options):
        self.className = exc_type.__name__
        self.message = "%s: %s" % (exc_type.__name__, exc_value)
        self.stackTrace = []

        if 'transmitGlobalVariables' in options and options['transmitGlobalVariables'] is True:
            self.globalVariables = globals()

        frames = None
        try:
            frames = inspect.getinnerframes(exc_traceback)

            if frames:
                for frame in frames:
                    self.stackTrace.append({
                        'lineNumber': frame[2],
                        'className': frame[3],
                        'fileName': frame[1],
                        'methodName': frame[4][0] if frame[4] is not None else None,
                        'localVariables': self._get_locals(frame[0]) if 'transmitLocalVariables' in options and options['transmitLocalVariables'] is True else None
                    })
        finally:
            del frames

        self.data = ""

    def get_classname(self):
        return self.className

    def _get_locals(self, frame):
        result = {}
        localVars = getattr(frame, 'f_locals', {})

        if '__traceback_hide__' not in localVars:
            for key in localVars:
                try:
                    # Note that str() *can* fail; thus protect against it as much as we can.
                    result[key] = str(localVars[key])
                except Exception as e:
                    try:
                        r = repr(localVars[key])
                    except Exception as re:
                        r = "Couldn't convert to repr due to {0}".format(re)
                    result[key] = "!!! Couldn't convert {0!r} (repr: {1}) due to {2!r} !!!".format(key, r, e)
            return result<commit_msg>For local variables of type 'unicode' in py2 we can store them for serialization as jsonpickle knows how to handle them. Previously, str() would cause an exception as it can accept only old strings(strs) etc<commit_after>import traceback
import inspect
import os
import sys

try:
    import multiprocessing
    USE_MULTIPROCESSING = True
except ImportError:
    USE_MULTIPROCESSING = False

import platform
from datetime import datetime


class RaygunMessageBuilder:

    def __init__(self):
        self.raygunMessage = RaygunMessage()

    def new(self):
        return RaygunMessageBuilder()

    def build(self):
        return self.raygunMessage

    def set_machine_name(self, name):
        self.raygunMessage.details['machineName'] = name
        return self

    def set_environment_details(self):
        self.raygunMessage.details['environment'] = {
            "processorCount": (
                multiprocessing.cpu_count() if USE_MULTIPROCESSING else "n/a"
            ),
            "architecture": platform.architecture()[0],
            "cpu": platform.processor(),
            "oSVersion": "%s %s" % (platform.system(), platform.release()),
            "environmentVariables": os.environ.data
        }

        return self

    def set_exception_details(self, raygunExceptionMessage):
        self.raygunMessage.details['error'] = raygunExceptionMessage
        return self

    def set_client_details(self):
        self.raygunMessage.details['client'] = {
            "name": "raygun4py",
            "version": "2.2.0",
            "clientUrl": "https://github.com/MindscapeHQ/raygun4py"
        }
        return self

    def set_customdata(self, userCustomData):
        if type(userCustomData) is dict:
            self.raygunMessage.details['userCustomData'] = userCustomData
        return self

    def set_tags(self, tags):
        if type(tags) is list or tuple:
            self.raygunMessage.details['tags'] = tags
        return self

    def set_request_details(self, request):
        if request:
            self.raygunMessage.details['request'] = {
              "hostName": request['hostName'],
              "url": request['url'],
              "httpMethod": request['httpMethod'],
              "queryString": request['queryString'],
              "form": request['form'],
              "headers": request['headers'],
              "rawData": request['rawData'],
            }

            if 'ipAddress' in request:
                self.raygunMessage.details['request']['iPAddress'] = request['ipAddress']
            elif 'iPAddress' in request:
                self.raygunMessage.details['request']['iPAddress'] = request['iPAddress']

        return self

    def set_version(self, version):
        self.raygunMessage.details['version'] = version
        return self

    def set_user(self, user):
        if user is not None:
            self.raygunMessage.details['user'] = user
        return self


class RaygunMessage:

    def __init__(self):
        self.occurredOn = datetime.utcnow()
        self.details = {}

    def get_error(self):
        return self.details['error']

    def get_details(self):
        return self.details


class RaygunErrorMessage:

    def __init__(self, exc_type, exc_value, exc_traceback, options):
        self.className = exc_type.__name__
        self.message = "%s: %s" % (exc_type.__name__, exc_value)
        self.stackTrace = []

        if 'transmitGlobalVariables' in options and options['transmitGlobalVariables'] is True:
            self.globalVariables = globals()

        frames = None
        try:
            frames = inspect.getinnerframes(exc_traceback)

            if frames:
                for frame in frames:
                    self.stackTrace.append({
                        'lineNumber': frame[2],
                        'className': frame[3],
                        'fileName': frame[1],
                        'methodName': frame[4][0] if frame[4] is not None else None,
                        'localVariables': self._get_locals(frame[0]) if 'transmitLocalVariables' in options and options['transmitLocalVariables'] is True else None
                    })
        finally:
            del frames

        self.data = ""

    def get_classname(self):
        return self.className

    def _get_locals(self, frame):
        result = {}
        localVars = getattr(frame, 'f_locals', {})

        if '__traceback_hide__' not in localVars:
            for key in localVars:
                try:
                    # Note that str() *can* fail; thus protect against it as much as we can.
                    result[key] = str(localVars[key])
                except Exception as e:
                    if type(localVars[key]) is unicode:
                        result[key] = localVars[key]
                    else:
                        try:
                            r = repr(localVars[key])
                        except Exception as re:
                            r = "Couldn't convert to repr due to {0}".format(re)
                        result[key] = "!!! Couldn't convert {0!r} (repr: {1}) due to {2!r} !!!".format(key, r, e)
            return result
{'fraction_non_alphanumeric': 0.10396484570058924, 'fraction_numerical': 0.0034954559073204832, 'mean_word_length': 1.980357142857143, 'pattern_counts': {'":': 30, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, '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': '5978672', 'n_tokens_mistral': 2733, 'n_tokens_neox': 2630, 'n_words': 670}