<commit_before>"""
Getting started
---------------

All resources are subclasses of the :class:`labtronyx.bases.Base_Resource` class. Creating a resource is simple::

    from labtronyx.bases import Base_Interface, Base_Resource

    class RESOURCE_CLASS_NAME(Base_Resource):
        pass

Errors
------

Labtronyx has a number of build-in exception types that can be raised from resources. To import them::

   from labtronyx.common.errors import *

Packaging
---------

Interfaces and Resources are typically packaged together in a single plugin, as the interface is responsible for
instantiating and maintaining resource objects.

Instantiation
-------------

Resources are instantiated by an interface, not InstrumentManager.

When resources are created, they should be in the closed state. This is to prevent any locking issues if multiple
instances of Labtronyx are open. Resources should typically only be open if they are actively in use.

Usage Model
-----------

Resources may implement more functions than just those which are defined in the API below. When a driver is loaded, all
of the driver functions are linked at runtime to the resource object. They essentially become a single object and all
functions are available between both classes with one exception: if there is a naming conflict between a method in the
resource and a method in the driver, the resource resolve the conflict by calling the resource method.

.. note::

   In order to support proper operation using Remote Resources and Instruments, some limitations should be imposed to
   ensure maximum compatibility. All methods within a resource or driver must return serializable data.
   Serializable data types include:

       * str
       * unicode
       * int
       * long
       * float
       * bool
       * list
       * tuple
       * dict
       * None

   If a method returns an object that is not serializable, an exception will be passed back to the remote host. If the
   method returns a non-serializable data type, the method should be prefixed with an underscore ('_') to mark it as a
   protected function that cannot be accessed remotely.
"""

import uuid
import logging

import labtronyx.common as common

from labtronyx.common.plugin import PluginBase

class Base_Resource(PluginBase):
    """
    Resource Base Class
    """

    resourceType = "Generic"
    
    def __init__(self, manager, interface, resID, **kwargs):
        """
        :param manager:         Reference to the InstrumentManager instance
        :type manager:          InstrumentManager object
        :param interface:       Reference to the interface instance
        :type interface:        object
        :param resID:           Resource Identifier
        :type resID:            str
        """
        PluginBase.__init__(self)

        self._manager = manager
        self._interface = interface
        self._resID = resID

        self.logger = kwargs.get('logger', logging)

        # Instance variables
        self._uuid = str(uuid.uuid4())
        self._driver = None
            
    def __del__(self):
        try:
            self.close()
        except Exception as e:
            pass
        
    def __getattr__(self, name):
        if self._driver is not None:
            if hasattr(self._driver, name):
                # Only call driver functions if the resource is open
                if self.isOpen():
                    return getattr(self._driver, name)
                else:
                    # TODO: Raise the correct exception on failure here
                    raise RuntimeError("Resource not open, unable to call driver function")

            else:
                raise AttributeError
            
        else:
            raise AttributeError

    def __enter__(self):
        self.open()

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.close()

    @property
    def manager(self):
        return self._manager

    @property<commit_msg>ResourceNotOpen raised if driver function is invoked when resource is closed<commit_after>"""
Getting started
---------------

All resources are subclasses of the :class:`labtronyx.bases.Base_Resource` class. Creating a resource is simple::

    from labtronyx.bases import Base_Interface, Base_Resource

    class RESOURCE_CLASS_NAME(Base_Resource):
        pass

Errors
------

Labtronyx has a number of build-in exception types that can be raised from resources. To import them::

   from labtronyx.common.errors import *

Packaging
---------

Interfaces and Resources are typically packaged together in a single plugin, as the interface is responsible for
instantiating and maintaining resource objects.

Instantiation
-------------

Resources are instantiated by an interface, not InstrumentManager.

When resources are created, they should be in the closed state. This is to prevent any locking issues if multiple
instances of Labtronyx are open. Resources should typically only be open if they are actively in use.

Usage Model
-----------

Resources may implement more functions than just those which are defined in the API below. When a driver is loaded, all
of the driver functions are linked at runtime to the resource object. All driver functions are accessed directly from
the resource object as if they were a single object. Some things to note:

   * If there is a naming conflict between a method in the resource and a method in the driver, the resource method
     will be called
   * Driver functions cannot be called if the resource is not open

.. note::

   In order to support proper operation using Remote Resources and Instruments, some limitations should be imposed to
   ensure maximum compatibility. All methods within a resource or driver must return serializable data.
   Serializable data types include:

       * str
       * unicode
       * int
       * long
       * float
       * bool
       * list
       * tuple
       * dict
       * None

   If a method returns an object that is not serializable, an exception will be passed back to the remote host. If the
   method returns a non-serializable data type, the method should be prefixed with an underscore ('_') to mark it as a
   protected function that cannot be accessed remotely.
"""

import uuid
import logging

import labtronyx.common as common

from labtronyx.common.plugin import PluginBase

class Base_Resource(PluginBase):
    """
    Resource Base Class
    """

    resourceType = "Generic"
    
    def __init__(self, manager, interface, resID, **kwargs):
        """
        :param manager:         Reference to the InstrumentManager instance
        :type manager:          InstrumentManager object
        :param interface:       Reference to the interface instance
        :type interface:        object
        :param resID:           Resource Identifier
        :type resID:            str
        """
        PluginBase.__init__(self)

        self._manager = manager
        self._interface = interface
        self._resID = resID

        self.logger = kwargs.get('logger', logging)

        # Instance variables
        self._uuid = str(uuid.uuid4())
        self._driver = None
            
    def __del__(self):
        try:
            self.close()
        except Exception as e:
            pass
        
    def __getattr__(self, name):
        if self._driver is not None:
            if hasattr(self._driver, name):
                # Only call driver functions if the resource is open
                if self.isOpen():
                    return getattr(self._driver, name)

                else:
                    # Driver functions are locked out if the resource is not open
                    raise common.errors.ResourceNotOpen("Unable to call driver function on closed resource")

            else:
                raise AttributeError
            
        else:
            raise AttributeError

    def __enter__(self):
        self.open()

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.close()

    @property
    def manager(self):
        return self._manager

    @property
{'fraction_non_alphanumeric': 0.06270830761634366, 'fraction_numerical': 0.0002468831008517467, 'mean_word_length': 2.309640522875817, 'pattern_counts': {'":': 0, '<': 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': '1332314', 'n_tokens_mistral': 1952, 'n_tokens_neox': 1877, 'n_words': 886}