<commit_before>"""
Generic containers, data structures and language extensions.

This module has several functions:

    1. provides a set of reusable, probably encapsulated collection containers
       and supporting infrastructure: L{BaseDictionaryContainer},
       L{BaseCollectionContainer}; also L{AbstractIndexer}
    
    2. provides some missing generic data structures or data types:
       L{OrderedDict}, L{Stack}; also the heavily used, type-safe L{enum} class
       and some generic pattern implementations like L{singleton} or L{Proxy}
    
    3. serves as a compatibility layer, making it possible to develop CSB as
       platform- and Python version-independent: string, L{iterable}, L{metaclass}

In order to ensure cross-interpreter compatibility, checking for string instances
in CSB must always be implemented like this:

    >>> isinstance("s", string)

because "basestring" is not available in Python 3. Also, metaclass definitions
other than abstract classes must be implemented as follows:

    >>> MyClassBase = metaclass(MetaClass, base=BaseClass)
    >>> class MyClass(MyClassBase):
            pass
            
See also the notes about compatibility in L{csb.io}.             
"""

import re
import sys
import time
import threading

from abc import ABCMeta, abstractproperty, abstractmethod

try:
    string = basestring
except NameError:
    string = str
  

class InterruptibleThread(threading.Thread):
    
    def __init__(self, target, name=None, args=[], kwargs={}):
        
        super(InterruptibleThread, self).__init__(target=target, name=name, args=args, kwargs=kwargs)
        self.setDaemon(True)
        self.__result = None
        self.__target = target
        self.__name = name
        self.__args = args
        self.__kwargs = kwargs
        
    @property
    def result(self):
        return self.__result
    
    def run(self):
        try:
            self.__result = self.__target(*self.__args, **self.__kwargs)
        except Exception as ex:
            sys.stderr.write(ex)
            self.__result = None

def singleton(klass):
    """
    Singleton class decorator.
    """
    instances = {}
    
    def get():
        if klass not in instances:
            instances[klass] = klass()
        return instances[klass]
    
    return get
            
class validatedproperty(property):
    """
    Property decorator with predefined getter/setter and value checking
    or casting in the setter. The provided function will be the validator
    and must take and return a value.

    If the property is named C{foo}, a private field named C{_foo} will
    be used to store the value.

    Example:

        >>> @validatedproperty
        >>> def a(v):
        >>>     v = int(v)
        >>>     if v < 0:
        >>>         raise ValueError(v)
        >>>     return v

    """
    def __init__(self, validator):
        self.name = '_' + validator.__name__
        self.__doc__ = func.__doc__
        self.validator = validator
        self.argcount = validator.__code__.co_argcount
        assert 1 <= self.argcount <= 2

    def __get__(self, instance, cls):
        if instance is None:
            return self
        return getattr(instance, self.name)

    def __set__(self, instance, value):
        value = self.validator(value) if self.argcount == 1 else \
                self.validator(instance, value)
        setattr(instance, self.name, value)

class typedproperty(property):
    """
    Property decorator for convenient creation of typed, encapsulated fields.
    The provided function must be a dummy, only its name is used.

    Example:

        >>> @typedproperty(float)
        >>> def b():
        >>>     pass<commit_msg>small fix in csb.core.validatedproperty<commit_after>"""
Generic containers, data structures and language extensions.

This module has several functions:

    1. provides a set of reusable, probably encapsulated collection containers
       and supporting infrastructure: L{BaseDictionaryContainer},
       L{BaseCollectionContainer}; also L{AbstractIndexer}
    
    2. provides some missing generic data structures or data types:
       L{OrderedDict}, L{Stack}; also the heavily used, type-safe L{enum} class
       and some generic pattern implementations like L{singleton} or L{Proxy}
    
    3. serves as a compatibility layer, making it possible to develop CSB as
       platform- and Python version-independent: string, L{iterable}, L{metaclass}

In order to ensure cross-interpreter compatibility, checking for string instances
in CSB must always be implemented like this:

    >>> isinstance("s", string)

because "basestring" is not available in Python 3. Also, metaclass definitions
other than abstract classes must be implemented as follows:

    >>> MyClassBase = metaclass(MetaClass, base=BaseClass)
    >>> class MyClass(MyClassBase):
            pass
            
See also the notes about compatibility in L{csb.io}.             
"""

import re
import sys
import time
import threading

from abc import ABCMeta, abstractproperty, abstractmethod

try:
    string = basestring
except NameError:
    string = str
  

class InterruptibleThread(threading.Thread):
    
    def __init__(self, target, name=None, args=[], kwargs={}):
        
        super(InterruptibleThread, self).__init__(target=target, name=name, args=args, kwargs=kwargs)
        self.setDaemon(True)
        self.__result = None
        self.__target = target
        self.__name = name
        self.__args = args
        self.__kwargs = kwargs
        
    @property
    def result(self):
        return self.__result
    
    def run(self):
        try:
            self.__result = self.__target(*self.__args, **self.__kwargs)
        except Exception as ex:
            sys.stderr.write(ex)
            self.__result = None

def singleton(klass):
    """
    Singleton class decorator.
    """
    instances = {}
    
    def get():
        if klass not in instances:
            instances[klass] = klass()
        return instances[klass]
    
    return get
            
class validatedproperty(property):
    """
    Property decorator with predefined getter/setter and value checking
    or casting in the setter. The provided function will be the validator
    and must take and return a value.

    If the property is named C{foo}, a private field named C{_foo} will
    be used to store the value.

    Example:

        >>> @validatedproperty
        >>> def a(v):
        >>>     v = int(v)
        >>>     if v < 0:
        >>>         raise ValueError(v)
        >>>     return v

    """
    def __init__(self, validator):
        self.name = '_' + validator.__name__
        self.__doc__ = validator.__doc__
        self.validator = validator
        self.argcount = validator.__code__.co_argcount
        assert 1 <= self.argcount <= 2

    def __get__(self, instance, cls):
        if instance is None:
            return self
        return getattr(instance, self.name)

    def __set__(self, instance, value):
        value = self.validator(value) if self.argcount == 1 else \
                self.validator(instance, value)
        setattr(instance, self.name, value)

class typedproperty(property):
    """
    Property decorator for convenient creation of typed, encapsulated fields.
    The provided function must be a dummy, only its name is used.

    Example:

        >>> @typedproperty(float)
        >>> def b():
        >>>     pass
{'fraction_non_alphanumeric': 0.08470714381450208, 'fraction_numerical': 0.0021444846535316983, 'mean_word_length': 2.490177736202058, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 75, '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': '2930109', 'n_tokens_mistral': 1984, 'n_tokens_neox': 1961, 'n_words': 692}