<commit_before>import weakref
from fontParts.base.errors import FontPartsError
from fontParts.base.base import BaseDict, dynamicProperty
from fontParts.base import normalizers


class BaseGroups(BaseDict):

    """
    A Groups object. This object normally created as part of a :class:`BaseFont`. An 
    orphan Groups object can be created like this::
    
        >>> groups = RGroups()
    
    This object behaves like a Python dictionary. Most of the dictionary functionality 
    comes from :class:`BaseDict`, look at that object for the required environment 
    implementation details.
    
    Groups uses :func:`normalizers.normalizeGroupKey` to normalize the key of the 
    ``dict``, and :func:`normalizers.normalizeGroupValue` to normalize the the value 
    of the ``dict``.
    """

    keyNormalizer = normalizers.normalizeGroupKey
    valueNormalizer = normalizers.normalizeGroupValue

    # -------
    # Parents
    # -------

    def getParent(self):
        """
        Return the Groups' parent :class:`fontParts.base.BaseFont`.
        
        This is a backwards compatibility method.
        """
        return self.font

    # Font

    _font = None

    font = dynamicProperty("font", "The Groups' parent :class:`BaseFont`.")

    def _get_font(self):
        if self._font is None:
            return None
        return self._font()

    def _set_font(self, font):
        assert self._font is None or self._font() == font
        if font is not None:
            font = weakref.ref(font)
        self._font = font

    # ---------
    # Searching
    # ---------

    def findGlyph(self, glyphName):
        """
        Returns a ``list`` of the group or groups associated with **glyphName**. 
        **glyphName** will be an :ref:`type-string`. If no group is found to contain
        **glyphName** an empty ``list`` will be returned. ::
        
            >>> font.groups.findGlyph("A")
            ["A_accented"]
        """
        glyphName = normalizers.normalizeGlyphName(glyphName)
        keys = self._findGlyph(glyphName)
        keys = [self.keyNormalizer(key) for key in keys]
        return keys

    def _findGlyph(self, glyphName):
        """
        This is the environment implementation of
        :meth:`BaseGroups.findGlyph`. **glyphName** will be
        an :ref:`type-string`.
        
        Subclasses may override this method.
        """
        found = []
        for key, groupList in self.items():
            if glyphName in groupList:
                found.append(key)
        return found

    # ---------------------
    # RoboFab Compatibility
    # ---------------------

    def remove(self, groupName):
        """
        Removes a group from the Groups. **groupName** will be
        a :ref:`type-string` that is the group name to 
        be removed.
        
        This is a backwards compatibility method.
        """
        del self[groupName]

    def asDict(self):
        """
        Return the Groups as a ``dict``.
        
        This is a backwards compatibility method.
        """
        d = {}
        for k, v in self.items():
            d[k] = v
        return d

    # -------------------
    # Inherited Functions
    # -------------------
    
    def __contains__(self, groupName):
        """
        Tests to see if a group name is in the Groups. 
        **groupName** will be a :ref:`type-string`. 
        This returns a ``bool`` indicating if the **groupName**
        is in the Groups. ::
        
            >>> "myGroup" in font.groups
            True
        """
        super(BaseGroups, self).__contains__(groupName)

    def __delitem__(self, groupName):
        """
        Removes **groupName** from the Groups. **groupName** is a :ref:`type-string`.::
        
            >>> del font.groups["myGroup"]
        """
        super(BaseGroups, self).__delitem__(groupName)

    def __getitem__(self, groupName):
        """
        Returns the contents of the named group. **groupName** is a :ref:`type-string`.
        The returned value will be a ``list`` of the group contents.::
        
            >>> font.groups["myGroup"]
            ["A", "B", "C"]
            
        It is important to understand that any changes to the returned group contents 
        will not be reflected in the Groups object. If one wants to make a change to 
        the group contents, one should do the following::
        
            >>> group = font.groups["myGroup"]
            >>> group.remove("A")
            >>> font.groups["myGroup"] = group
        """
        super(BaseGroups, self).__getitem__(groupName)
        
    def __iter__(self):
        """
        Iterates through the Groups, giving the key for each iteration. The order that
        the Groups will iterate though is not fixed nor is it ordered.::
        
            >>> for groupName in font.groups:
            >>>     print groupName
            "myGroup"
            "myGroup3"
            "myGroup2"
        """
        super(BaseGroups, self).__iter__()
        
    def __len__(self):
        """
        Returns the number of groups in Groups as an ``int``.::
        
            >>> len(font.groups)
            5
        """
        super(BaseGroups, self).__len__()
        
    def __setitem__(self, groupName, glyphNames):
        """
        Sets the **groupName** to the list of **glyphNames**. **groupName** is the 
        group name as a :ref:`type-string` and **glyphNames** is a ``list`` of glyph 
        names as :ref:`type-string`.
        
            >>> font.groups["myGroup"] = ["A", "B", "C"]
        """
        super(BaseGroups, self).__setitem__(groupName, value)
        
    def clear(self):
        """
        Removes all group information from Groups, 
        resetting the Groups to an empty dictionary. ::<commit_msg>Missed a changed variable name.<commit_after>import weakref
from fontParts.base.errors import FontPartsError
from fontParts.base.base import BaseDict, dynamicProperty
from fontParts.base import normalizers


class BaseGroups(BaseDict):

    """
    A Groups object. This object normally created as part of a :class:`BaseFont`. An 
    orphan Groups object can be created like this::
    
        >>> groups = RGroups()
    
    This object behaves like a Python dictionary. Most of the dictionary functionality 
    comes from :class:`BaseDict`, look at that object for the required environment 
    implementation details.
    
    Groups uses :func:`normalizers.normalizeGroupKey` to normalize the key of the 
    ``dict``, and :func:`normalizers.normalizeGroupValue` to normalize the the value 
    of the ``dict``.
    """

    keyNormalizer = normalizers.normalizeGroupKey
    valueNormalizer = normalizers.normalizeGroupValue

    # -------
    # Parents
    # -------

    def getParent(self):
        """
        Return the Groups' parent :class:`fontParts.base.BaseFont`.
        
        This is a backwards compatibility method.
        """
        return self.font

    # Font

    _font = None

    font = dynamicProperty("font", "The Groups' parent :class:`BaseFont`.")

    def _get_font(self):
        if self._font is None:
            return None
        return self._font()

    def _set_font(self, font):
        assert self._font is None or self._font() == font
        if font is not None:
            font = weakref.ref(font)
        self._font = font

    # ---------
    # Searching
    # ---------

    def findGlyph(self, glyphName):
        """
        Returns a ``list`` of the group or groups associated with **glyphName**. 
        **glyphName** will be an :ref:`type-string`. If no group is found to contain
        **glyphName** an empty ``list`` will be returned. ::
        
            >>> font.groups.findGlyph("A")
            ["A_accented"]
        """
        glyphName = normalizers.normalizeGlyphName(glyphName)
        keys = self._findGlyph(glyphName)
        keys = [self.keyNormalizer(key) for key in keys]
        return keys

    def _findGlyph(self, glyphName):
        """
        This is the environment implementation of
        :meth:`BaseGroups.findGlyph`. **glyphName** will be
        an :ref:`type-string`.
        
        Subclasses may override this method.
        """
        found = []
        for key, groupList in self.items():
            if glyphName in groupList:
                found.append(key)
        return found

    # ---------------------
    # RoboFab Compatibility
    # ---------------------

    def remove(self, groupName):
        """
        Removes a group from the Groups. **groupName** will be
        a :ref:`type-string` that is the group name to 
        be removed.
        
        This is a backwards compatibility method.
        """
        del self[groupName]

    def asDict(self):
        """
        Return the Groups as a ``dict``.
        
        This is a backwards compatibility method.
        """
        d = {}
        for k, v in self.items():
            d[k] = v
        return d

    # -------------------
    # Inherited Functions
    # -------------------
    
    def __contains__(self, groupName):
        """
        Tests to see if a group name is in the Groups. 
        **groupName** will be a :ref:`type-string`. 
        This returns a ``bool`` indicating if the **groupName**
        is in the Groups. ::
        
            >>> "myGroup" in font.groups
            True
        """
        super(BaseGroups, self).__contains__(groupName)

    def __delitem__(self, groupName):
        """
        Removes **groupName** from the Groups. **groupName** is a :ref:`type-string`.::
        
            >>> del font.groups["myGroup"]
        """
        super(BaseGroups, self).__delitem__(groupName)

    def __getitem__(self, groupName):
        """
        Returns the contents of the named group. **groupName** is a :ref:`type-string`.
        The returned value will be a ``list`` of the group contents.::
        
            >>> font.groups["myGroup"]
            ["A", "B", "C"]
            
        It is important to understand that any changes to the returned group contents 
        will not be reflected in the Groups object. If one wants to make a change to 
        the group contents, one should do the following::
        
            >>> group = font.groups["myGroup"]
            >>> group.remove("A")
            >>> font.groups["myGroup"] = group
        """
        super(BaseGroups, self).__getitem__(groupName)
        
    def __iter__(self):
        """
        Iterates through the Groups, giving the key for each iteration. The order that
        the Groups will iterate though is not fixed nor is it ordered.::
        
            >>> for groupName in font.groups:
            >>>     print groupName
            "myGroup"
            "myGroup3"
            "myGroup2"
        """
        super(BaseGroups, self).__iter__()
        
    def __len__(self):
        """
        Returns the number of groups in Groups as an ``int``.::
        
            >>> len(font.groups)
            5
        """
        super(BaseGroups, self).__len__()
        
    def __setitem__(self, groupName, glyphNames):
        """
        Sets the **groupName** to the list of **glyphNames**. **groupName** is the 
        group name as a :ref:`type-string` and **glyphNames** is a ``list`` of glyph 
        names as :ref:`type-string`.
        
            >>> font.groups["myGroup"] = ["A", "B", "C"]
        """
        super(BaseGroups, self).__setitem__(groupName, glyphNames)
        
    def clear(self):
        """
        Removes all group information from Groups, 
        resetting the Groups to an empty dictionary. ::
{'fraction_non_alphanumeric': 0.12159275399470221, 'fraction_numerical': 0.0005126890540886952, 'mean_word_length': 1.7986609277857484, 'pattern_counts': {'":': 0, '<': 3, '<?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': '3488319', 'n_tokens_mistral': 3176, 'n_tokens_neox': 3022, 'n_words': 1032}