<commit_before>"""
Basic Treant objects: the organizational units for :mod:`datreant`.

"""
import os
import sys
import shutil
from uuid import uuid4
import logging
import functools

import datreant
import datreant.backends.pytables
import datreant.backends.yaml
from datreant import limbs
from datreant import filesystem
from datreant import collections


class MultipleTreantsError(Exception):
    pass


class NoTreantsError(Exception):
    pass


def register(*treantclass):
    """Register a treant-derived class so datreant can handle it.

    In order for things like Bundle to know how to handle custom treants,
    they must be registered with the package. Give the class (not an instance)
    to this function to register it.

    :Arguments:
        *treantclass*
            treant-derived class to register; may enter more than one

    """
    for tc in treantclass:
        datreant._treants.update({tc._treanttype: tc})


@functools.total_ordering
class Treant(object):
    """Core class for all Treants.

    """
    # required components
    _treanttype = 'Treant'
    _backends = {'pytables': ['.h5', datreant.backends.pytables.TreantFile],
                 'yaml': ['.yml', datreant.backends.yaml.yamlTreantFile]}

    def __init__(self, treant, new=False, coordinator=None,
                 categories=None, tags=None, backend='pytables'):
        """Generate a new or regenerate an existing (on disk) Treant object.

        :Required arguments:
            *treant*
                base directory of a new or existing Treant; will regenerate
                a Treant if a state file is found, but will genereate a new
                one otherwise

                if multiple Treant state files are in the given directory,
                will raise :exception:`MultipleTreantsError`; specify
                the full path to the desired state file to regenerate the
                desired Treant in this case

                use the *new* keyword to force generation of a new Treant
                at the given path

        :Optional arguments:
            *new*
                generate a new Treant even if one already exists at the given
                location *treant*
            *categories*
                dictionary with user-defined keys and values; used to give
                Treants distinguishing characteristics
            *tags*
                list with user-defined values; like categories, but useful for
                adding many distinguishing descriptors
            *backend*
                backend to use for a new state file; only 'pytables' available;
                not used for object regeneration

        """
        if new:
            self._generate(treant, coordinator=coordinator,
                           categories=categories, tags=tags, backend=backend)
        else:
            try:
                self._regenerate(treant,
                                 coordinator=coordinator,
                                 categories=categories, tags=tags)
            except NoTreantsError:
                self._generate(treant,
                               coordinator=coordinator, categories=categories,
                               tags=tags, backend=backend)

    def __repr__(self):
        return "<Treant: '{}'>".format(self.name)

    def __getstate__(self):
        return self.filepath

    def __setstate__(self, state):
        self._regenerate(state)

    def __eq__(self, other):
        try:
            return (self.name + self.uuid) == (other.name + other.uuid)
        except AttributeError:
            return NotImplemented

    def __lt__(self, other):
        try:
            return (self.name + self.uuid) < (other.name + other.uuid)
        except AttributeError:
            return NotImplemented

    def __getitem__(self, handle):
        """Get dataset corresponding to given handle.

        If dataset doesn't exist, ``None`` is returned.

        :Arguments:
            *handle*
                name of data to retrieve

        :Returns:
            *data*
                stored data; ``None`` if nonexistent
        """
        return self.data.__getitem__(handle)

    def __setitem__(self, handle, data):
        """Set dataset corresponding to given handle.

        A data instance must be either a pandas Series, DataFrame, or Panel
        object. If dataset doesn't exist, it is added. If a dataset already
        exists for the given handle, it is replaced.

        :Arguments:
            *handle*
                name given to data; needed for retrieval
            *data*
                data to store; must be a pandas Series, DataFrame, or Panel

        """
        self.data.__setitem__(handle, data)

    def __delitem__(self, handle):
        """Remove a dataset.

        Note: the directory containing the dataset file (``Data.h5``) will NOT
        be removed if it still contains file after the removal of the dataset
        file.

        :Arguments:
            *handle*
                name of dataset to delete

        """
        self.data.__delitem__(handle)

    def __add__(a, b):
        """Addition of treants with collections or treants yields Bundle.

        """
        if (isinstance(a, (Treant, collections._CollectionBase)) and
           isinstance(b, (Treant, collections._CollectionBase))):
            return collections.Bundle(a, b)
        else:
            raise TypeError("Operands must be Treant-derived or Bundles.")

    def _generate(self, treant, coordinator=None, categories=None, tags=None,
                  backend='pytables'):
        """Generate new Treant object.

        """
        self._placeholders()

        # process keywords
        if not categories:
            categories = dict()
        if not tags:
            tags = list()

        # build basedir; stop if we hit a permissions error
        try:<commit_msg>Removed convenience access to data at top level of Treant.<commit_after>"""
Basic Treant objects: the organizational units for :mod:`datreant`.

"""
import os
import sys
import shutil
from uuid import uuid4
import logging
import functools

import datreant
import datreant.backends.pytables
import datreant.backends.yaml
from datreant import limbs
from datreant import filesystem
from datreant import collections


class MultipleTreantsError(Exception):
    pass


class NoTreantsError(Exception):
    pass


def register(*treantclass):
    """Register a treant-derived class so datreant can handle it.

    In order for things like Bundle to know how to handle custom treants,
    they must be registered with the package. Give the class (not an instance)
    to this function to register it.

    :Arguments:
        *treantclass*
            treant-derived class to register; may enter more than one

    """
    for tc in treantclass:
        datreant._treants.update({tc._treanttype: tc})


@functools.total_ordering
class Treant(object):
    """Core class for all Treants.

    """
    # required components
    _treanttype = 'Treant'
    _backends = {'pytables': ['.h5', datreant.backends.pytables.TreantFile],
                 'yaml': ['.yml', datreant.backends.yaml.yamlTreantFile]}

    def __init__(self, treant, new=False, coordinator=None,
                 categories=None, tags=None, backend='pytables'):
        """Generate a new or regenerate an existing (on disk) Treant object.

        :Required arguments:
            *treant*
                base directory of a new or existing Treant; will regenerate
                a Treant if a state file is found, but will genereate a new
                one otherwise

                if multiple Treant state files are in the given directory,
                will raise :exception:`MultipleTreantsError`; specify
                the full path to the desired state file to regenerate the
                desired Treant in this case

                use the *new* keyword to force generation of a new Treant
                at the given path

        :Optional arguments:
            *new*
                generate a new Treant even if one already exists at the given
                location *treant*
            *categories*
                dictionary with user-defined keys and values; used to give
                Treants distinguishing characteristics
            *tags*
                list with user-defined values; like categories, but useful for
                adding many distinguishing descriptors
            *backend*
                backend to use for a new state file; only 'pytables' available;
                not used for object regeneration

        """
        if new:
            self._generate(treant, coordinator=coordinator,
                           categories=categories, tags=tags, backend=backend)
        else:
            try:
                self._regenerate(treant,
                                 coordinator=coordinator,
                                 categories=categories, tags=tags)
            except NoTreantsError:
                self._generate(treant,
                               coordinator=coordinator, categories=categories,
                               tags=tags, backend=backend)

    def __repr__(self):
        return "<Treant: '{}'>".format(self.name)

    def __getstate__(self):
        return self.filepath

    def __setstate__(self, state):
        self._regenerate(state)

    def __eq__(self, other):
        try:
            return (self.name + self.uuid) == (other.name + other.uuid)
        except AttributeError:
            return NotImplemented

    def __lt__(self, other):
        try:
            return (self.name + self.uuid) < (other.name + other.uuid)
        except AttributeError:
            return NotImplemented

    def __add__(a, b):
        """Addition of treants with collections or treants yields Bundle.

        """
        if (isinstance(a, (Treant, collections._CollectionBase)) and
           isinstance(b, (Treant, collections._CollectionBase))):
            return collections.Bundle(a, b)
        else:
            raise TypeError("Operands must be Treant-derived or Bundles.")

    def _generate(self, treant, coordinator=None, categories=None, tags=None,
                  backend='pytables'):
        """Generate new Treant object.

        """
        self._placeholders()

        # process keywords
        if not categories:
            categories = dict()
        if not tags:
            tags = list()

        # build basedir; stop if we hit a permissions error
        try:
{'fraction_non_alphanumeric': 0.07258064516129033, 'fraction_numerical': 0.0004743833017077799, 'mean_word_length': 1.9692957746478874, 'pattern_counts': {'":': 0, '<': 7, '<?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': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5243861', 'n_tokens_mistral': 2709, 'n_tokens_neox': 2556, 'n_words': 949}