<commit_before># -*- coding: utf-8 -*-
from __future__ import print_function
"""
CLibrary.py -  Provides CLibrary class
Copyright 2010  <NAME>
Distributed under MIT/X11 license. See license.txt for more infomation.

Proxy to both CHeader and ctypes, allowing automatic type conversion and
function calling based on C header definitions.
"""


from ctypes import *
import sys, os, platform

import six


def find_lib(name, paths=[], dirHints=[]):
    """Search through likely directories to find non-system dlls. Return the first filepath that is found. Currently only supported on Windows.

    **Arguments** 
    =============   ==============================================
    name            (str) The name of the file to look for.
    paths           (list)(optional) A list of directory paths to search. 
    dirHints        (list)(optional) A list of directory names within ProgramFiles or ProgramFiles(x86) to search first. Used to reduce search time.

    Directories are searched in the order specified in paths, then in 'ProgramFiles', then 'ProgramFiles(x86)'
    """

    if platform.system() != 'Windows':
        raise Exception("CLibrary.find_lib is currently only supported on Windows machines. Sorry.")

    searchPaths = paths

    for directory in ['PROGRAMFILES', 'PROGRAMFILES(X86)', 'SYSTEMDRIVE']:
        p = os.environ.get(directory, None)
        if directory == 'SYSTEMDRIVE': ## fixes bug(feature?) where os.join doesn't insert slashes between c: and whatever you're trying to join
            p = os.path.join(p, os.sep)

        if p is not None:
            for d in dirHints:
                path = os.path.join(p,d)
                if os.path.exists(path):
                    searchPaths.append(path)
            searchPaths.append(p)
    
    for path in searchPaths:
        for root, dirs, files in os.walk(path):
            if name in files:
                return os.path.join(root, name)

    raise Exception('Could not find file named "%s". Searched recursively in %s.' % (name, str(searchPaths)))


class CLibrary:
    """The CLibrary class is intended to automate much of the work in using ctypes by integrating
    header file definitions from CParser. Ths class serves as a proxy to a ctypes, adding
    a few features:
      - allows easy access to values defined via CParser
      - automatic type conversions for function calls using CParser function signatures
      - creates ctype classes based on type definitions from CParser
      
    Initialize using a ctypes shared object and a CParser:
       headers = CParser.winDefs()
       lib = CLibrary(windll.User32, headers)
      
    There are 3 ways to access library elements:
        lib(type, name) - type can be one of 'values', 'functions', 'types', 'structs', 'unions', or 'enums'.
                          Returns an object matching name. For values, the value from the headers is
                          returned. For functions, a callable object is returned that handles automatic
                          type conversion for arguments and return values. for structs, types, and enums, 
                          a ctypes class is returned matching the type specified.
        lib.name   - searches in order through values, functions, types, structs, unions, and enums from 
                     header definitions and returns an object for the first match found. The object
                     returned is the same as returned by lib(type, name). This is the preferred way to access
                     elements from CLibrary, but may not work in some situations (for example, if
                     a struct and variable share the same name).
        lib[type]  - Accesses the header definitions directly, returns definition dictionaries
                     based on the type requested. This is equivalent to headers.defs[type].
    """
    Null = object()
    
    cTypes = {
        'char': c_char,
        'wchar': c_wchar,
        'unsigned char': c_ubyte,
        'short': c_short,
        'short int': c_short,
        'unsigned short': c_ushort,
        'unsigned short int': c_ushort,
        'int': c_int,
        'unsigned': c_uint,
        'unsigned int': c_uint,
        'long': c_long,
        'long int': c_long,
        'unsigned long': c_ulong,
        'unsigned long int': c_ulong,
        '__int64': c_longlong,
        'long long': c_longlong,
        'long long int': c_longlong,
        'unsigned __int64': c_ulonglong,
        'unsigned long long': c_ulonglong,
        'unsigned long long int': c_ulonglong,
        'float': c_float,
        'double': c_double,
        'long double': c_longdouble
    }
    cPtrTypes = {
        'char': c_char_p,
        'wchar': c_wchar_p,
        'void': c_void_p
    }
        
        
    
    def __init__(self, lib, headers, prefix=None):
        ## name everything using underscores to avoid name collisions with library
        
        self._lib_ = lib
        self._headers_ = headers
        self._defs_ = headers.defs
        if prefix is None:
            self._prefix_ = []
        elif type(prefix) is list:
            self._prefix_ = prefix
        else:
            self._prefix_ = [prefix]
        self._objs_ = {}
        for k in ['values', 'functions', 'types', 'structs', 'unions', 'enums']:
            self._objs_[k] = {}
        self._allObjs_ = {}
        self._structs_ = {}
        self._unions_ = {}

    def __call__(self, typ, name):
        if typ not in self._objs_:
            typs = self._objs_.keys()
            raise Exception("Type must be one of %s" % str(typs))
        
        if name not in self._objs_[typ]:
            self._objs_[typ][name] = self._mkObj_(typ, name)
            
        return self._objs_[typ][name]

    def _allNames_(self, name):
        return [name] + [p + name for p in self._prefix_]

    def _mkObj_(self, typ, name):
        names = self._allNames_(name)
        
        for n in names:
            if n in self._objs_:
                return self._objs_[n]
            
        for n in names:  ## try with and without prefix
            if n not in self._defs_[typ] and not (typ in ['structs', 'unions', 'enums'] and n in self._defs_['types']):
                continue
                
            if typ == 'values':
                return self._defs_[typ][n]
            elif typ == 'functions':
                return self._getFunction(n)
            elif typ == 'types':
                obj = self._defs_[typ][n]
                return self._ctype(obj)
            elif typ == 'structs':
                return self._cstruct('structs', n)
            elif typ == 'unions':
                return self._cstruct('unions', n)
            elif typ == 'enums':
                ## Allow automatic resolving of typedefs that alias enums
                if n not in self._defs_['enums']:
                    if n not in self._defs_['types']:
                        raise Exception('No enums named "%s"' % n)
                    typ = self._headers_.evalType([n])[0]
                    if typ[:5] != 'enum ':
                        raise Exception('No enums named "%s"' % n)
                    n = self._defs_['types'][typ][1]  ## look up internal name of enum 
                obj = self._defs_['enums'][n]
                    
                return obj
            else:
                raise Exception("Unknown type %s" % typ)
        raise NameError(name)
        

    def __getattr__(self, name):
        """Used to retrieve any type of definition from the headers. Searches for the name in this order:
        values, functions, types, structs, unions, enums."""
        if name not in self._allObjs_:
            names = self._allNames_(name)
            for k in ['values', 'functions', 'types', 'structs', 'unions', 'enums', None]:
                if k is None:
                    #obj = getattr(self._lib_, name)  # pull directly from the lib as a last resort?
                    raise NameError(name)
                obj = None
                for n in names:<commit_msg>fix: clibrary getattr should raise attributeerror<commit_after># -*- coding: utf-8 -*-
from __future__ import print_function
"""
CLibrary.py -  Provides CLibrary class
Copyright 2010  <NAME>
Distributed under MIT/X11 license. See license.txt for more infomation.

Proxy to both CHeader and ctypes, allowing automatic type conversion and
function calling based on C header definitions.
"""


from ctypes import *
import sys, os, platform

import six


def find_lib(name, paths=[], dirHints=[]):
    """Search through likely directories to find non-system dlls. Return the first filepath that is found. Currently only supported on Windows.

    **Arguments** 
    =============   ==============================================
    name            (str) The name of the file to look for.
    paths           (list)(optional) A list of directory paths to search. 
    dirHints        (list)(optional) A list of directory names within ProgramFiles or ProgramFiles(x86) to search first. Used to reduce search time.

    Directories are searched in the order specified in paths, then in 'ProgramFiles', then 'ProgramFiles(x86)'
    """

    if platform.system() != 'Windows':
        raise Exception("CLibrary.find_lib is currently only supported on Windows machines. Sorry.")

    searchPaths = paths

    for directory in ['PROGRAMFILES', 'PROGRAMFILES(X86)', 'SYSTEMDRIVE']:
        p = os.environ.get(directory, None)
        if directory == 'SYSTEMDRIVE': ## fixes bug(feature?) where os.join doesn't insert slashes between c: and whatever you're trying to join
            p = os.path.join(p, os.sep)

        if p is not None:
            for d in dirHints:
                path = os.path.join(p,d)
                if os.path.exists(path):
                    searchPaths.append(path)
            searchPaths.append(p)
    
    for path in searchPaths:
        for root, dirs, files in os.walk(path):
            if name in files:
                return os.path.join(root, name)

    raise Exception('Could not find file named "%s". Searched recursively in %s.' % (name, str(searchPaths)))


class CLibrary:
    """The CLibrary class is intended to automate much of the work in using ctypes by integrating
    header file definitions from CParser. Ths class serves as a proxy to a ctypes, adding
    a few features:
      - allows easy access to values defined via CParser
      - automatic type conversions for function calls using CParser function signatures
      - creates ctype classes based on type definitions from CParser
      
    Initialize using a ctypes shared object and a CParser:
       headers = CParser.winDefs()
       lib = CLibrary(windll.User32, headers)
      
    There are 3 ways to access library elements:
        lib(type, name) - type can be one of 'values', 'functions', 'types', 'structs', 'unions', or 'enums'.
                          Returns an object matching name. For values, the value from the headers is
                          returned. For functions, a callable object is returned that handles automatic
                          type conversion for arguments and return values. for structs, types, and enums, 
                          a ctypes class is returned matching the type specified.
        lib.name   - searches in order through values, functions, types, structs, unions, and enums from 
                     header definitions and returns an object for the first match found. The object
                     returned is the same as returned by lib(type, name). This is the preferred way to access
                     elements from CLibrary, but may not work in some situations (for example, if
                     a struct and variable share the same name).
        lib[type]  - Accesses the header definitions directly, returns definition dictionaries
                     based on the type requested. This is equivalent to headers.defs[type].
    """
    Null = object()
    
    cTypes = {
        'char': c_char,
        'wchar': c_wchar,
        'unsigned char': c_ubyte,
        'short': c_short,
        'short int': c_short,
        'unsigned short': c_ushort,
        'unsigned short int': c_ushort,
        'int': c_int,
        'unsigned': c_uint,
        'unsigned int': c_uint,
        'long': c_long,
        'long int': c_long,
        'unsigned long': c_ulong,
        'unsigned long int': c_ulong,
        '__int64': c_longlong,
        'long long': c_longlong,
        'long long int': c_longlong,
        'unsigned __int64': c_ulonglong,
        'unsigned long long': c_ulonglong,
        'unsigned long long int': c_ulonglong,
        'float': c_float,
        'double': c_double,
        'long double': c_longdouble
    }
    cPtrTypes = {
        'char': c_char_p,
        'wchar': c_wchar_p,
        'void': c_void_p
    }
        
        
    
    def __init__(self, lib, headers, prefix=None):
        ## name everything using underscores to avoid name collisions with library
        
        self._lib_ = lib
        self._headers_ = headers
        self._defs_ = headers.defs
        if prefix is None:
            self._prefix_ = []
        elif type(prefix) is list:
            self._prefix_ = prefix
        else:
            self._prefix_ = [prefix]
        self._objs_ = {}
        for k in ['values', 'functions', 'types', 'structs', 'unions', 'enums']:
            self._objs_[k] = {}
        self._allObjs_ = {}
        self._structs_ = {}
        self._unions_ = {}

    def __call__(self, typ, name):
        if typ not in self._objs_:
            typs = self._objs_.keys()
            raise Exception("Type must be one of %s" % str(typs))
        
        if name not in self._objs_[typ]:
            self._objs_[typ][name] = self._mkObj_(typ, name)
            
        return self._objs_[typ][name]

    def _allNames_(self, name):
        return [name] + [p + name for p in self._prefix_]

    def _mkObj_(self, typ, name):
        names = self._allNames_(name)
        
        for n in names:
            if n in self._objs_:
                return self._objs_[n]
            
        for n in names:  ## try with and without prefix
            if n not in self._defs_[typ] and not (typ in ['structs', 'unions', 'enums'] and n in self._defs_['types']):
                continue
                
            if typ == 'values':
                return self._defs_[typ][n]
            elif typ == 'functions':
                return self._getFunction(n)
            elif typ == 'types':
                obj = self._defs_[typ][n]
                return self._ctype(obj)
            elif typ == 'structs':
                return self._cstruct('structs', n)
            elif typ == 'unions':
                return self._cstruct('unions', n)
            elif typ == 'enums':
                ## Allow automatic resolving of typedefs that alias enums
                if n not in self._defs_['enums']:
                    if n not in self._defs_['types']:
                        raise Exception('No enums named "%s"' % n)
                    typ = self._headers_.evalType([n])[0]
                    if typ[:5] != 'enum ':
                        raise Exception('No enums named "%s"' % n)
                    n = self._defs_['types'][typ][1]  ## look up internal name of enum 
                obj = self._defs_['enums'][n]
                    
                return obj
            else:
                raise Exception("Unknown type %s" % typ)
        raise NameError(name)
        

    def __getattr__(self, name):
        """Used to retrieve any type of definition from the headers. Searches for the name in this order:
        values, functions, types, structs, unions, enums."""
        if name not in self._allObjs_:
            names = self._allNames_(name)
            for k in ['values', 'functions', 'types', 'structs', 'unions', 'enums', None]:
                if k is None:
                    #obj = getattr(self._lib_, name)  # pull directly from the lib as a last resort?
                    raise AttributeError(name)
                obj = None
                for n in names:
{'fraction_non_alphanumeric': 0.0979493216033703, 'fraction_numerical': 0.002849885385044297, 'mean_word_length': 1.9168774846404049, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, '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': '1856527', 'n_tokens_mistral': 4442, 'n_tokens_neox': 4265, 'n_words': 1612}