
    rh3*                        S r SSKJr  SSKJr  SSKrSSKrSSKJ	r	   " S S5      r
C " S S	\R                  5      r\S
:X  a  SSKr\R                  " \5        gg)z
Classes for pseudo-m21 objects to inherit from.  The most import attributes that nearly
everything in music21 -- not just things that live in streams --
should inherit from are given below.

Concept borrowed from m21j.
    )annotations)SequenceN)
deprecatedc                      \ rS rSr% SrSS/r0 rS\S'   0 rS\S'   0 r	S	\S
'   Sr
S\S'   \" SSS5      SS j5       r\SS j5       r\SS j5       rSS jrSS jrSrg)ProtoM21Object   a  
A class for pseudo-m21 objects to inherit from.  Any object can inherit from
ProtoM21Object, and it makes sense for anything a user is likely to encounter
to inherit from it.  Certain translators, etc. can choose to skip it.

>>> class PitchCounter(prebase.ProtoM21Object):
...     def _reprInternal(self):
...         return 'no pitches'

>>> pc = PitchCounter()
>>> pc.classes
('PitchCounter', 'ProtoM21Object', 'object')
>>> PitchCounter in pc.classSet
True
>>> 'Note' in pc.classSet
False

For a True/False intersection check against an iterable, use `classSet.isdisjoint`:

>>> classList = ('music21.note.Note', 'music21.note.Rest')
>>> pc.classSet.isdisjoint(classList)
True
>>> repr(pc)
'<music21.PitchCounter no pitches>'


ProtoM21Objects, like other Python primitives, cannot be put into streams --
this is what base.Music21Object does.

A ProtoM21Object defines several methods relating to unified representation
and keeping track of the classes of the object.  It has no instance attributes
or properties, and thus adds a very small creation time impact: recent
tests show that an empty object with an empty `__init__()` method can
be created in about 175ns while an empty object that subclasses ProtoM21Object
with the same empty `__init__()` takes only 180ns, or a 5ns impact.  On
real objects, the creation time percentage hit is usually much smaller.

ProtoM21Objects have no __init__() defined, so do not call super().__init__() on
objects that only inherit from ProtoM21Object unless you like wasting 200ns.
classesclassSetzdict[str, str]	_DOC_ATTRzdict[type, tuple[str, ...]]_classTupleCacheDictz!dict[type, frozenset[str | type]]_classSetCacheDict tuple[str, ...]	__slots__v7v10zUuse `someClass in .classSet`or for intersection: `not classSet.isdisjoint(classList)`c                B    U R                   R                  U5      (       + $ )a  
Given a class filter list (a list or tuple must be submitted),
which may have strings or class objects, determine
if this class is of the provided classes or a subclasses.

NOTE: this is a performance critical operation
for performance, only accept lists or tuples

DEPRECATED in v7 -- prefer `someClass in el.classSet` or
`not el.classSet.isdisjoint(classList)` instead.

>>> n = note.Note()
>>> #_DOCS_SHOW n.isClassOrSubclass(('Note',))
True
>>> #_DOCS_SHOW n.isClassOrSubclass(('GeneralNote',))
True
>>> #_DOCS_SHOW n.isClassOrSubclass((note.Note,))
True
>>> #_DOCS_SHOW n.isClassOrSubclass((note.Rest,))
False
>>> #_DOCS_SHOW n.isClassOrSubclass((note.Note, note.Rest))
True
>>> #_DOCS_SHOW n.isClassOrSubclass(('Rest', 'Note'))
True
)r
   
isdisjoint)selfclassFilterLists     I/home/james-whalen/.local/lib/python3.13/site-packages/music21/prebase.pyisClassOrSubclass ProtoM21Object.isClassOrSubclassU   s    8 ==++O<<<    c                     U R                   U R                     $ ! [         aG    [        S U R                  R	                  5        5       5      nXR                   U R                  '   Us $ f = f)a  
Returns a tuple containing the names (strings, not objects) of classes that this
object belongs to -- starting with the object's class name and going up the mro()
for the object.

Notes are Music21Objects:

>>> n = note.Note('C#')
>>> n.classes
('Note', 'NotRest', 'GeneralNote', 'Music21Object', 'ProtoM21Object', 'object')

Durations are not, but they inherit from ProtoM21Object

>>> d = duration.Duration('half')
>>> d.classes
('Duration', 'ProtoM21Object', 'SlottedObjectMixin', 'object')


Having quick access to these things as strings makes it easier to do comparisons:

Example: find GClefs that are not Treble clefs (or treble 8vb, etc.):

>>> s = stream.Stream()
>>> s.insert(10, clef.GClef())
>>> s.insert(20, clef.TrebleClef())
>>> s.insert(30, clef.FrenchViolinClef())
>>> s.insert(40, clef.Treble8vbClef())
>>> s.insert(50, clef.BassClef())
>>> s2 = stream.Stream()
>>> for thing in s:
...    if isinstance(thing, clef.GClef) and not isinstance(thing, clef.TrebleClef):
...        s2.insert(thing)
>>> s2.show('text')
{10.0} <music21.clef.GClef>
{30.0} <music21.clef.FrenchViolinClef>

`Changed 2015 Sep`: returns a tuple, not a list.
c              3  8   #    U  H  oR                   v   M     g 7f)N)__name__).0xs     r   	<genexpr>)ProtoM21Object.classes.<locals>.<genexpr>   s     H3Gazz3Gs   )r   	__class__KeyErrortuplemro)r   
classTuples     r   r	   ProtoM21Object.classess   sa    P	,,T^^<< 	H4>>3E3E3GHHJ8B%%dnn5	s    AA,+A,c                @    U R                   U R                     $ ! [         a    [        U R                  5      nUR                  U R                  R                  5       5        U R                  R                  5        Vs/ s H  o"R                  S-   UR                  -   PM      Os  snf nnUR                  U5        U Vs/ s H  o"R                  SS5      PM     Os  snf nnUR                  U5        [        U5      nXPR                   U R                  '   Us $ f = f)aT  
Returns a set (that is, unordered, but indexed) of all classes that
this class belongs to, including
string names, fullyQualified string names, and objects themselves.

It's cached on a per-class basis, so makes for a really fast way of checking to
see if something belongs
to a particular class when you don't know if the user has given a string,
a fully qualified string name, or an object.

Did I mention it's fast?  It's a drop in substitute for the deprecated
`.isClassOrSubclass`.  It's not as fast as x in n.classes or isinstance(n, x)
if you know whether it's a string or class, but this is good and safe.

>>> n = note.Note()
>>> 'Note' in n.classSet
True
>>> 'music21.note.Note' in n.classSet
True
>>> note.Note in n.classSet
True

>>> 'Rest' in n.classSet
False
>>> note.Rest in n.classSet
False

>>> object in n.classSet
True

>>> sorted([s for s in n.classSet if isinstance(s, str)])
['GeneralNote',
 'Music21Object',
 'NotRest',
 'Note',
 'ProtoM21Object',
 'base.Music21Object',
 'builtins.object',
 'music21.base.Music21Object',
 'music21.note.GeneralNote',
 'music21.note.NotRest',
 'music21.note.Note',
 'music21.prebase.ProtoM21Object',
 'note.GeneralNote',
 'note.NotRest',
 'note.Note',
 'object',
 'prebase.ProtoM21Object']

>>> sorted([s for s in n.classSet if not isinstance(s, str)], key=lambda x: x.__name__)
[<class 'music21.note.GeneralNote'>,
 <class 'music21.base.Music21Object'>,
 <class 'music21.note.NotRest'>,
 <class 'music21.note.Note'>,
 <class 'music21.prebase.ProtoM21Object'>,
 <class 'object'>]

* Changed in v8: partially qualified objects such as 'note.Note' have been added.
.zmusic21. )r   r"   r#   listr	   extendr%   
__module__r   replace	frozenset)r   	classListr   fullyQualifiedStringspartiallyQualifiedStringsr
   s         r   r
   ProtoM21Object.classSet   s    z	**4>>:: 		(,T\\(:IT^^//12NRnnN`N`Nb$cNb\\C%7!**%DNb$c!$c23La(bLaq:r)BLa(b%(b67 +H6>##DNN3O		s(    A$D?%B%$DC>DDc                T   SnU R                   S:w  a  XR                   S-   -  nXR                  R                  -  nSU;   a  SU;  a  UR                  SS5      nU R	                  5       nU(       a  UR                  S5      (       d  US	-  nU(       a  XR                  5       -  nUS
-   $ )a  
Defines the default representation for a ProtoM21Object
which includes the module name, the class name, and additional
information, such as the memory location:

>>> p = prebase.ProtoM21Object()
>>> repr(p)
'<music21.prebase.ProtoM21Object object at 0x112590380>'

The additional information is defined in the `_reprInternal` method,
so objects inheriting from ProtoM21Object (such as Music21Object)
should change `_reprInternal` and not `__repr__`.
<__main__r)   z.base.zmusic21.basez.baser*   : >)r-   r"   __qualname__r.   _reprInternal
startswithstrip)r   reprHeadstrReprs      r   __repr__ProtoM21Object.__repr__   s     ??j(#--HNN///xN($B''4H$$&7--c22OH'H#~r   c                0    S[        [        U 5      5       3$ )a.  
Defines the insides of the representation.

Overload this method for most objects.

A default representation:

>>> p = prebase.ProtoM21Object()
>>> p._reprInternal()
'object at 0x112590380'

A more complex `_reprInternal` that handles the case of objects
with `.id` defined is found in Music21Object.
z
object at )hexid)r   s    r   r;   ProtoM21Object._reprInternal  s     C4M?++r   N)r   r   returnbool)rF   r   )rF   zfrozenset[str | type])rF   str)r   r-   r:   __firstlineno____doc__
_DOC_ORDERr   __annotations__r   r   r   r   r   propertyr	   r
   r@   r;   __static_attributes__r   r   r   r   r      s    'V 	J !#I~"
 9;5::<7<!#I#e D E=E=8 , ,\ G GR8,r   r   c                       \ rS rSrS rS rSrg)Testi  c                2    SSK Jn  U" U [        5       5        g )Nr   )testCopyAll)music21.test.commonTestrR   globals)r   rR   s     r   testCopyAndDeepcopyTest.testCopyAndDeepcopy  s    7D')$r   c                f    SSK Jn  U" 5       nSUl        [        U5      nU R	                  US5        g )Nr   )Music21Objecthelloz%<music21.base.Music21Object id=hello>)music21.baserX   rD   reprassertEqual)r   rX   brs       r   test_reprInternalTest.test_reprInternal"  s-    .OGCDr   r   N)r   r-   r:   rI   rU   r_   rN   r   r   r   rP   rP     s    %Er   rP   r6   )rJ   
__future__r   collections.abcr   typingtunittestmusic21.commonr   r   TestCaserP   r   music21mainTestr   r   r   <module>rj      sa    # $   %}, },@ 
E8 
E zT r   