<commit_before>__author__ = '<NAME>'

import logging

import openpathsampling as paths
from openpathsampling.netcdfplus import StorableObject, lazy_loading_attributes
from treelogic import TreeMixin

logger = logging.getLogger(__name__)


@lazy_loading_attributes('details')
class PathMoveChange(TreeMixin, StorableObject):
    '''
    A class that described the concrete realization of a PathMove.

    Attributes
    ----------
    mover : PathMover
        The mover that generated this PathMoveChange
    samples : list of Sample
        A list of newly generated samples by this particular move.
        Only used by node movers like RepEx or Shooters
    subchanges : list of PathMoveChanges
        the PathMoveChanges created by submovers
    details : Details
        an object that contains MoveType specific attributes and information.
        E.g. for a RandomChoiceMover which Mover was selected.
    '''

    def __init__(self, subchanges=None, samples=None, mover=None, details=None):
        StorableObject.__init__(self)

        self._len = None
        self._collapsed = None
        self._results = None
        self._trials = None
        self._accepted = None
        self.mover = mover
        if subchanges is None:
            self.subchanges = list()
        else:
            self.subchanges = subchanges

        if samples is None:
            self.samples = list()
        else:
            self.samples = samples
        self.details = details

    # hook for TreeMixin
    @property
    def _subnodes(self):
        return self.subchanges

    @property
    def submovers(self):
        return [ch.mover for ch in self.subchanges]

    @property
    def subchange(self):
        """
        Return the single/only sub-pathmovechange if there is only one.

        Returns
        -------
        PathMoveChange
        """
        if len(self.subchanges) == 1:
            return self.subchanges[0]
        else:
            # TODO: might raise exception
            return None

    @staticmethod<commit_msg>Draft of implicit PMC `details`<commit_after>__author__ = '<NAME>'

import logging

import openpathsampling as paths
from openpathsampling.netcdfplus import StorableObject, lazy_loading_attributes
from treelogic import TreeMixin

logger = logging.getLogger(__name__)


@lazy_loading_attributes('details')
class PathMoveChange(TreeMixin, StorableObject):
    '''
    A class that described the concrete realization of a PathMove.

    Attributes
    ----------
    mover : PathMover
        The mover that generated this PathMoveChange
    samples : list of Sample
        A list of newly generated samples by this particular move.
        Only used by node movers like RepEx or Shooters
    subchanges : list of PathMoveChanges
        the PathMoveChanges created by submovers
    details : Details
        an object that contains MoveType specific attributes and information.
        E.g. for a RandomChoiceMover which Mover was selected.
    '''

    def __init__(self, subchanges=None, samples=None, mover=None, details=None):
        StorableObject.__init__(self)

        self._len = None
        self._collapsed = None
        self._results = None
        self._trials = None
        self._accepted = None
        self.mover = mover
        if subchanges is None:
            self.subchanges = list()
        else:
            self.subchanges = subchanges

        if samples is None:
            self.samples = list()
        else:
            self.samples = samples
        self.details = details

    def __getattr__(self, item):
        # try to get attributes from details dict
        try:
            return getattr(self.details, item)
        except AttributeError as e:
            msg = "{0} not found in change's details".format(str(item))
            if not e.args: 
                e.args = [msg]
            else:
                e.args = tuple([e.args[0] + "; " + msg] + list(e.args[1:]))
            raise

    # hook for TreeMixin
    @property
    def _subnodes(self):
        return self.subchanges

    @property
    def submovers(self):
        return [ch.mover for ch in self.subchanges]

    @property
    def subchange(self):
        """
        Return the single/only sub-pathmovechange if there is only one.

        Returns
        -------
        PathMoveChange
        """
        if len(self.subchanges) == 1:
            return self.subchanges[0]
        else:
            # TODO: might raise exception
            return None

    @staticmethod
{'fraction_non_alphanumeric': 0.07340260888790626, 'fraction_numerical': 0.0015476453681185054, 'mean_word_length': 2.1007539410555176, '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': '7569630', 'n_tokens_mistral': 1211, 'n_tokens_neox': 1177, 'n_words': 391}