
    rh                       % S SK Jr  / SQrS SKJr  S SKrS SKrS SKrS SKrS SK	r	S SK
rS SKrS SKJr  S SKJr  S SKJr  S SKJr  S S	KJr  \R(                  (       a  S S
KJr  S SKJr  \R2                  " S5      r " S S\R6                  5      r " S S\R:                  5      r " S S\R:                  5      r0 r S\!S'   SS jr" " S S\RF                  5      r$\\4r%\&S:X  a  S SKr\RN                  " \$5        gg)    )annotations)MetadataEntryMetadataBundleMetadataBundleException)OrderedDictN)common)readPickleGzip)environment)exceptions21)prebase)Iterable)Metadatazmetadata.bundlesc                      \ rS rSrSrg)r   /    N)__name__
__module____qualname____firstlineno____static_attributes__r       R/home/james-whalen/.local/lib/python3.13/site-packages/music21/metadata/bundles.pyr   r   /   s    r   r   c                      \ rS rSrSr    S       SS jjrS rS rS rS r	SS	 jr
SS
 jr\S 5       r\S 5       r\S 5       r\S 5       r\S 5       rSrg)r   5   a  
An entry in a metadata bundle.

The metadata entry holds information about the source of the metadata,
and can be parsed to reconstitute the score object the metadata was
derived from:

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> metadataEntry = coreBundle.search('bwv66.6')[0]
>>> metadataEntry
<music21.metadata.bundles.MetadataEntry 'bach_bwv66_6_mxl'>

The sourcePath of the metadata entry refers to the file path at which its
score file is found, but it is usually a relative path to the top of the corpus
directory.  It is a pathlib object.

>>> metadataEntry.sourcePath
PosixPath('bach/bwv66.6.mxl')

The metadata property contains its :class:`~music21.metadata.RichMetadata` object:

>>> metadataEntry.metadata
<music21.metadata.RichMetadata object at 0x...>

Note that the id is not necessarily the current memory location.

And the metadata entry can be parsed:

>>> metadataEntry.parse()
<music21.stream.Score ...>
Nc                H    [        U5      U l        X l        X0l        X@l        g N)str_sourcePath_number_metadataPayload_corpusName)self
sourcePathnumbermetadataPayload
corpusNames        r   __init__MetadataEntry.__init__Y   s!     !$J /%r   c                H    U R                   U R                  U R                  4$ )z
This is all the information that is needed for pickling.
Specifically do not include _corpusName.

Note do not pickle Pathlib objects, so make sure to do ._sourcePath
not .sourcePath
)r   metadatar$   r"   s    r   __getnewargs__MetadataEntry.__getnewargs__f   s%     MMKK
 	
r   c                ,    [        U R                  5      $ r   )repr
corpusPathr+   s    r   _reprInternalMetadataEntry._reprInternalt   s    DOO$$r   c                    U R                   $ )a  
Allows MetadataEntries to be used where file paths are being employed,
so it can be used with opening and closing, etc.

Returns self.sourcePath() as a string

>>> mde1 = metadata.bundles.MetadataEntry(sourcePath='/tmp/myFile.xml')
>>> mde1.__fspath__()
'/tmp/myFile.xml'
)r   r+   s    r   
__fspath__MetadataEntry.__fspath__w   s     r   c                    SSK Jn  U R                  b$  UR                  U R                  U R                  S9$ UR                  U R                  5      $ )Nr   corpus)r$   )music21r8   r$   parser#   )r"   r8   s     r   r:   MetadataEntry.parse   s=    ";;"<<<DD<<00r   c                F    U R                  5       nUR                  U5        g r   )r:   show)r"   
showFormatscores      r   r=   MetadataEntry.show   s    



:r   c                <    U R                   R                  " X40 UD6$ r   )r*   search)r"   queryfieldkeywordss       r   rB   MetadataEntry.search   s    }}##E=H==r   c                V    [         R                  U R                  U R                  5      $ )zN
Returns the sourcePath as a string, with _number appended if it is not None.
)r   corpusPathToKeyr#   r$   r+   s    r   r0   MetadataEntry.corpusPath   s    
 --doot{{KKr   c                    U R                   $ )z;
Returns the Metadata object that is stored in the bundle.
)r    r+   s    r   r*   MetadataEntry.metadata   s    
 $$$r   c                    U R                   $ r   )r   r+   s    r   r$   MetadataEntry.number   s    ||r   c                B    [         R                  " U R                  5      $ r   )pathlibPathr   r+   s    r   r#   MetadataEntry.sourcePath   s    ||D,,--r   c                    U R                   $ r   )r!   r+   s    r   r&   MetadataEntry.corpusName   s    r   )r!   r    r   r   ) NNrT   )r#   str | pathlib.Pathr$   
int | Noner%   zMetadata | Noner&   r   r   NN)r   r   r   r   __doc__r'   r,   r1   r4   r:   r=   rB   propertyr0   r*   r$   r#   r&   r   r   r   r   r   r   5   s    H 13$(26#%	
&-
&!
& #0
& !	
&
% 1> L L % %   . .    r   r   c                     \ rS rSrSrS*S+S jjrS,S jrS rS,S jrS r	S,S	 jr
S,S
 jrS rS,S jrS rS rS rS rS-S jrS r\S 5       r\R,                  S 5       r\S.S j5       r\S 5       r    S/S jrS r\S*S0S jj5       rS1S jrS rS rS r S r!S r"\S  5       r#S*S! jr$  S2S"S#.   S3S$ jjjr%S% r&S& r'S' r(S*S( jr)S)r*g)4r      a  
An object that provides access to, searches within, and stores and loads
multiple Metadata objects.

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> coreBundle
<music21.metadata.bundles.MetadataBundle 'core': {151... entries}>

(The coreBundle has around 15100 entries; I've put '...' in the
docs so I don't need to rewrite them every time we add a new piece)

>>> #_DOCS_SHOW searchResults = coreBundle.search('bach', field='composer')
>>> searchResults = metadata.bundles.demo_bundle('bach')  #_DOCS_HIDE
>>> searchResults
<music21.metadata.bundles.MetadataBundle {363 entries}>

>>> resultsEntries = searchResults.search('3/4')
>>> resultsEntries
<music21.metadata.bundles.MetadataBundle {40 entries}>


Results are ordered by their source path:

>>> resultsEntries[0]
<music21.metadata.bundles.MetadataEntry 'bach_bwv11_6_mxl'>

To get a score out of the entry, call .parse()

>>> resultsEntries[0].parse()
<music21.stream.Score ...>

Or pass it into converter:

>>> converter.parse(resultsEntries[0])
<music21.stream.Score ...>


A metadata bundle can be instantiated in three ways, (1) from a ``Corpus`` instance,
or (2) a string indicating which corpus name to draw from, and then calling
.read() or (3) by calling
.metadataBundle on a corpus object.  This
calls `.read()` automatically:


Method 1:

>>> coreCorpus = corpus.corpora.CoreCorpus()
>>> coreBundle = metadata.bundles.MetadataBundle(coreCorpus)
>>> localCorpus = corpus.corpora.LocalCorpus()
>>> localBundle = metadata.bundles.MetadataBundle(localCorpus)

Method 2:

>>> coreBundle = metadata.bundles.MetadataBundle('core')
>>> localBundle = metadata.bundles.MetadataBundle('local')

After calling these you'll need to call ``read()``:

>>> coreBundle
<music21.metadata.bundles.MetadataBundle 'core': {0 entries}>
>>> coreBundle.read()
<music21.metadata.bundles.MetadataBundle 'core': {151... entries}>
>>> coreBundle
<music21.metadata.bundles.MetadataBundle 'core': {151... entries}>

Method 3:

>>> coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> localBundle = corpus.corpora.LocalCorpus().metadataBundle

>>> coreBundle
<music21.metadata.bundles.MetadataBundle 'core': {151... entries}>



Additionally, any two metadata bundles can be operated on together as
though they were sets, allowing us to build up more complex searches:

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> #_DOCS_SHOW bachBundle = coreBundle.search('bach', 'composer')
>>> bachBundle = metadata.bundles.demo_bundle('bach')  #_DOCS_HIDE
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {363 entries}>
>>> #_DOCS_SHOW tripleMeterBundle = coreBundle.search('3/4')
>>> tripleMeterBundle = metadata.bundles.demo_bundle('3/4')  #_DOCS_HIDE
>>> tripleMeterBundle
<music21.metadata.bundles.MetadataBundle {1875 entries}>
>>> bachBundle.intersection(tripleMeterBundle)
<music21.metadata.bundles.MetadataBundle {40 entries}>

Finally, a metadata bundle need not be associated with any corpus at all,
and can be populated ad hoc:

>>> anonymousBundle = metadata.bundles.MetadataBundle()
>>> mdb = corpus.corpora.CoreCorpus().search('monteverdi')[:4]
>>> paths = [common.getCorpusFilePath() / x.sourcePath for x in mdb]
>>> failedPaths = anonymousBundle.addFromPaths(
...     paths, useMultiprocessing=False)
>>> failedPaths
[]
>>> anonymousBundle
<music21.metadata.bundles.MetadataBundle {4 entries}>
Nc                R   SSK Jn  [        5       U l        [	        U[
        UR                  R                  [        S 5      45      (       d  [        S5      eS U l
        U   [	        XR                  R                  5      (       a  UR                  U l        Xl        g Xl        S U l        g )Nr   r7   z4Need to take a string, corpus, or None as expression)r9   r8   r   _metadataEntries
isinstancer   corporaCorpustyper   _corpusname_name)r"   exprr8   s      r   r'   MetadataBundle.__init__%  sx    "AL$fnn&;&;T$Z HII)*`aa37dNN1122DJKJDKr   c                &    U R                  US5      $ )a  
Compute the set-wise `and` of two metadata bundles:

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> #_DOCS_SHOW bachBundle = coreBundle.search('bach', 'composer')
>>> bachBundle = metadata.bundles.demo_bundle('bach')  #_DOCS_HIDE
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {363 entries}>
>>> #_DOCS_SHOW tripleMeterBundle = coreBundle.search('3/4')
>>> tripleMeterBundle = metadata.bundles.demo_bundle('3/4')  #_DOCS_HIDE
>>> tripleMeterBundle
<music21.metadata.bundles.MetadataBundle {1875 entries}>
>>> bachBundle & tripleMeterBundle
<music21.metadata.bundles.MetadataBundle {40 entries}>

Returns a new metadata bundle.
__and___apply_set_operationr"   metadataBundles     r   rh   MetadataBundle.__and__8  s    & ((
 	
r   c                \    [        US5      (       a  U R                  UR                  :X  a  gg)a  
True if `expr` is of the same type, and contains an identical set of
entries, otherwise false:

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> #_DOCS_SHOW bachBundle = coreBundle.search('bach', 'composer')
>>> bachBundle = metadata.bundles.demo_bundle('bach')  #_DOCS_HIDE
>>> #_DOCS_SHOW corelliBundle = coreBundle.search('corelli', 'composer')
>>> corelliBundle = metadata.bundles.demo_bundle('corelli')  #_DOCS_HIDE
>>> bachBundle == corelliBundle
False
>>> bachBundle == coreBundle.search(
...     'bach',
...     field='composer',
...     )
True
>>> bachBundle == 'foo'
False

r]   TF)hasattrr]   )r"   others     r   __eq__MetadataBundle.__eq__P  s,    , 5,--$$(>(>>r   c                &    U R                  US5      $ )aY  
True when one metadata bundle is either a superset or an identical set
to another bundle:

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> #_DOCS_SHOW bachBundle = coreBundle.search('bach', 'composer')
>>> bachBundle = metadata.bundles.demo_bundle('bach')  #_DOCS_HIDE
>>> #_DOCS_SHOW corelliBundle = coreBundle.search('corelli', 'composer')
>>> corelliBundle = metadata.bundles.demo_bundle('corelli')  #_DOCS_HIDE
>>> bachBundle >= bachBundle
True
>>> bachBundle >= corelliBundle
False
>>> bachBundle >= coreBundle
False
>>> corelliBundle >= bachBundle
False
>>> corelliBundle >= corelliBundle
True
>>> corelliBundle >= coreBundle
False
>>> coreBundle >= bachBundle
True
>>> coreBundle >= corelliBundle
True
>>> coreBundle >= coreBundle
True

Returns boolean.
__ge___apply_set_predicaterk   s     r   rt   MetadataBundle.__ge__k      @ ((BBr   c                N    [        U R                  R                  5       5      U   $ r   )listr]   values)r"   is     r   __getitem__MetadataBundle.__getitem__  s!    D))0023A66r   c                &    U R                  US5      $ )aR  
True when one metadata bundle is either a subset or an identical set to
another bundle:

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> #_DOCS_SHOW bachBundle = coreBundle.search('bach', 'composer')
>>> bachBundle = metadata.bundles.demo_bundle('bach')  #_DOCS_HIDE
>>> #_DOCS_SHOW corelliBundle = coreBundle.search('corelli', 'composer')
>>> corelliBundle = metadata.bundles.demo_bundle('corelli')  #_DOCS_HIDE
>>> bachBundle > bachBundle
False
>>> bachBundle > corelliBundle
False
>>> bachBundle > coreBundle
False
>>> corelliBundle > bachBundle
False
>>> corelliBundle > corelliBundle
False
>>> corelliBundle > coreBundle
False
>>> coreBundle > bachBundle
True
>>> coreBundle > corelliBundle
True
>>> coreBundle > coreBundle
False


Returns boolean.
__gt__ru   rk   s     r   r   MetadataBundle.__gt__  s    B ((BBr   c                &    U R                  US5      $ )aW  
True when one metadata bundle is either a subset or an identical set to
another bundle:

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> #_DOCS_SHOW bachBundle = coreBundle.search('bach', 'composer')
>>> bachBundle = metadata.bundles.demo_bundle('bach')  #_DOCS_HIDE
>>> #_DOCS_SHOW corelliBundle = coreBundle.search('corelli', 'composer')
>>> corelliBundle = metadata.bundles.demo_bundle('corelli')  #_DOCS_HIDE
>>> bachBundle <= bachBundle
True
>>> bachBundle <= corelliBundle
False
>>> bachBundle <= coreBundle
True
>>> corelliBundle <= bachBundle
False
>>> corelliBundle <= corelliBundle
True
>>> corelliBundle <= coreBundle
True
>>> coreBundle <= bachBundle
False
>>> coreBundle <= corelliBundle
False
>>> coreBundle <= coreBundle
True

Returns boolean.
__le__ru   rk   s     r   r   MetadataBundle.__le__  rx   r   c                ,    [        U R                  5      $ r   )lenr]   r+   s    r   __len__MetadataBundle.__len__  s    4(())r   c                &    U R                  US5      $ )a5  
True when one metadata bundle is a subset of another bundle:

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> #_DOCS_SHOW bachBundle = coreBundle.search('bach', 'composer')
>>> bachBundle = metadata.bundles.demo_bundle('bach')  #_DOCS_HIDE
>>> #_DOCS_SHOW corelliBundle = coreBundle.search('corelli', 'composer')
>>> corelliBundle = metadata.bundles.demo_bundle('corelli')  #_DOCS_HIDE
>>> bachBundle < bachBundle
False
>>> bachBundle < corelliBundle
False
>>> bachBundle < coreBundle
True
>>> corelliBundle < bachBundle
False
>>> corelliBundle < corelliBundle
False
>>> corelliBundle < coreBundle
True
>>> coreBundle < bachBundle
False
>>> coreBundle < corelliBundle
False
>>> coreBundle < coreBundle
False

Return boolean.
__lt__ru   rk   s     r   r   MetadataBundle.__lt__  s    > ((BBr   c                &    U R                  US5      $ )a  
Compute the set-wise `or` of two metadata bundles:

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> #_DOCS_SHOW bachBundle = coreBundle.search('bach', 'composer')
>>> bachBundle = metadata.bundles.demo_bundle('bach')  #_DOCS_HIDE
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {363 entries}>
>>> #_DOCS_SHOW corelliBundle = coreBundle.search('corelli', 'composer')
>>> corelliBundle = metadata.bundles.demo_bundle('corelli')  #_DOCS_HIDE
>>> corelliBundle
<music21.metadata.bundles.MetadataBundle {1 entry}>
>>> bachBundle | corelliBundle
<music21.metadata.bundles.MetadataBundle {364 entries}>

Returns a new metadata bundle.
__or__ri   rk   s     r   r   MetadataBundle.__or__  s    & ((
 	
r   c                    [        U 5      S:X  a  SnOS[        [        U 5      5      -   S-   nU R                  b  U R                  < SU 3nU$ )N   z	{1 entry}{z	 entries}z: )r   r   rc   )r"   statuss     r   r1   MetadataBundle._reprInternal  sL    t9> F3s4y>)K7F99 		}Bvh/Fr   c                &    U R                  US5      $ )a9  
Compute the set-wise `subtraction` of two metadata bundles:

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> #_DOCS_SHOW bachBundle = coreBundle.search('bach', 'composer')
>>> bachBundle = metadata.bundles.demo_bundle('bach')  #_DOCS_HIDE
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {363 entries}>
>>> #_DOCS_SHOW tripleMeterBundle = coreBundle.search('3/4')
>>> tripleMeterBundle = metadata.bundles.demo_bundle('3/4')  #_DOCS_HIDE
>>> tripleMeterBundle
<music21.metadata.bundles.MetadataBundle {1875 entries}>
>>> bachBundle - tripleMeterBundle
<music21.metadata.bundles.MetadataBundle {323 entries}>

Returns a new metadata bundle.

>>> bachBundle - bachBundle
<music21.metadata.bundles.MetadataBundle {0 entries}>
__sub__ri   rk   s     r   r   MetadataBundle.__sub__  s    , ((
 	
r   c                &    U R                  US5      $ )a  
Compute the set-wise `exclusive or` of two metadata bundles:

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> #_DOCS_SHOW bachBundle = coreBundle.search('bach', 'composer')
>>> bachBundle = metadata.bundles.demo_bundle('bach')  #_DOCS_HIDE
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {363 entries}>

>>> #_DOCS_SHOW tripleMeterBundle = coreBundle.search('3/4')
>>> tripleMeterBundle = metadata.bundles.demo_bundle('3/4')  #_DOCS_HIDE
>>> tripleMeterBundle
<music21.metadata.bundles.MetadataBundle {1875 entries}>
>>> bachBundle ^ tripleMeterBundle
<music21.metadata.bundles.MetadataBundle {2158 entries}>

Returns a new metadata bundle.
__xor__ri   rk   s     r   r   MetadataBundle.__xor__6  s    ( ((
 	
r   c                    [        U[        U 5      5      (       d  [        S5      e[        U R                  R                  5       5      n[        UR                  R                  5       5      n[        X25      " U5      n[        U 5      " 5       nU H?  nXpR                  ;   a  U R                  U   nOUR                  U   nXR                  U'   MA     [        UR                  R                  5       5      n	[        [        U	S S95      Ul        U$ )N'metadataBundle must be a MetadataBundlec                     U S   R                   $ Nr   r#   mdes    r   <lambda>5MetadataBundle._apply_set_operation.<locals>.<lambda>c  s    3q6K\K\r   key)r^   ra   r   setr]   keysgetattrrz   itemsr   sorted)
r"   rl   operatorselfKeys	otherKeys
resultKeysresultBundler   metadataEntrymdbItemss
             r   rj   #MetadataBundle._apply_set_operationQ  s    .$t*55)*STTt,,113477<<>?	 ' ;I F
'+Dz|C+++ $ 5 5c : . ? ? D1>))#.  599V9V9\9\9^4_(3F8?\5^ )_%r   c                    [        U[        U 5      5      (       d  [        S5      e[        U R                  R                  5       5      n[        UR                  R                  5       5      n[        X25      " U5      $ )zJ
Applies a predicate such as '__or__' to self and another metadataBundle.
r   )r^   ra   r   r   r]   r   r   )r"   rl   	predicater   r   s        r   rv   #MetadataBundle._apply_set_predicatef  sc     .$t*55)*STTt,,113477<<>?	x+I66r   c                    U R                   b%  [        R                  " U R                   5      nUb  U$ U R                  c  gSSKJn  UR                  U R                  5      $ )ah  
The `corpus.corpora.Corpus` object associated with the metadata
bundle's name.

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> coreBundle
<music21.metadata.bundles.MetadataBundle 'core': {151... entries}>
>>> coreBundle.corpus
<music21.corpus.corpora.CoreCorpus>
Nr   )manager)rb   r   unwrapWeakrefrc   music21.corpusr   fromName)r"   cObjr   s      r   r8   MetadataBundle.corpust  sR     <<#''5D99*		**r   c                :    [         R                  " U5      U l        g r   )r   wrapWeakrefrb   )r"   	newCorpuss     r   r8   r     s    )))4r   c                    U R                   nUc  gUR                  n[        U[        R                  5      (       d  [        R                  " U5      $ U$ )aV  
The filesystem name of the cached metadata bundle, if the metadata
bundle's name is not None.

>>> ccPath = corpus.corpora.CoreCorpus().metadataBundle.filePath
>>> ccPath.name
'core.p.gz'
>>> '_metadataCache' in ccPath.parts
True

>>> localPath = corpus.corpora.LocalCorpus().metadataBundle.filePath
>>> localPath.name
'local.p.gz'

Local corpora metadata is stored in the scratch dir, not the
corpus directory

>>> '_metadataCache' in localPath.parts
False

>>> funkCorpus = corpus.corpora.LocalCorpus('funk')
>>> funkPath = funkCorpus.metadataBundle.filePath
>>> funkPath.name
'local-funk.p.gz'
N)r8   cacheFilePathr^   rO   rP   )r"   ccfps      r   filePathMetadataBundle.filePath  sC    6 KK9//Cc7<<00||C((
r   c                    U R                   $ )a  
The name of the metadata bundle.

Can be 'core', 'local', '{name}' where name is the name
of a named local corpus or None.

The names 'core' and 'local' refer to the core and local
corpora respectively: (virtual corpus is currently offline)

>>> metadata.bundles.MetadataBundle().name is None
True
>>> corpus.corpora.CoreCorpus().metadataBundle.name
'core'

>>> funkCorpus = corpus.corpora.LocalCorpus('funk')
>>> funkCorpus.metadataBundle.name
'funk'

Return string or None.
)rd   r+   s    r   rc   MetadataBundle.name  s    , zzr   c           	        SSK Jn  / n/ n/ n	U R                  bD  U R                  R                  5       (       a%  U R                  R	                  5       R
                  n
O[        R                  " 5       n
SU
 3nUSL a  [        R                  U5        O[        R                  U5        SnSnU H  nU R                  U5      nXR                  ;   a'  UR	                  5       R
                  nUU
:  a  US-  nMJ  US-  nU R                  nUc  SnUR                  S5      (       a  US	S nUR                  R                  UUUUS
9nUR!                  U5        M     SnSU S3nUSL a  [        R                  U5        O[        R                  U5        U(       a!  UR                  R"                  R$                  nO UR                  R"                  R&                  nU" U5       H  nUR                  R"                  R)                  [+        U5      US   US   [+        U	5      5      nUSL a  [        R                  U5        O[        R                  U5        US-  nUR-                  US   5        U	R-                  US   5        US    H  nUU R                  UR.                  '   M     US-  S:X  d  M  USL d  M  U R1                  5         M     U R3                  5         USL a  U R1                  5         U	$ )au  
Parse and store metadata from numerous files.

If any files cannot be loaded, their file paths will be collected in a
list that is returned.

Returns a list of file paths with errors and stores the extracted
metadata in `self._metadataEntries`.

>>> metadataBundle = metadata.bundles.MetadataBundle()
>>> p = corpus.corpora.CoreCorpus().getWorkList('bach/bwv66.6')
>>> metadataBundle.addFromPaths(
...     p,
...     parseUsingCorpus=False,
...     useMultiprocessing=False,
...     storeOnDisk=False, #_DOCS_HIDE
...     )
[]
>>> len(metadataBundle._metadataEntries)
1

Set Verbose to True to get updates even if debug is off.
r   )r*   Nz"MetadataBundle Modification Time: Tr   corezlocal-   )	jobNumberparseUsingCorpusr&   zSkipped z sources already in cache.remainingJobsr   metadataEntrieserrors2   )r9   r*   r   existsstatst_ctimetimeenvironLocalwarn
printDebugrH   r]   rc   
startswithcachingMetadataCachingJobappendJobProcessorprocess_parallelprocess_serial_reportr   extendr0   writevalidate)r"   pathsr   useMultiprocessingstoreOnDiskverboser*   jobsaccumulatedResultsaccumulatedErrorsmetadataBundleModificationTimemessagecurrentJobNumberskippedJobsCountpathr   pathModificationTimer&   jobcurrentIterationjobProcessorresultr   s                          r   addFromPathsMetadataBundle.addFromPaths  s   > 	%==$)=)=)?)?-1]]-?-?-A-J-J*-1YY[*67U6VWd?g&##G,D&&t,C+++'+yy{';';$'*HH$)$!J!#
$$X..'^
""55*!1%	 6 C KK+ , -..HId?g&##G,#++88IIL#++88GGL"4(F&&33;;D	'z"%&	G $!!'*''0!%%f->&?@$$VH%56!'(9!:BO%%m&>&>? "; 2%*t0C

% )& 	$JJL  r   c                8    U R                   R                  5         g)a  
Clear all keys in a metadata bundle:

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> bachBundle = coreBundle.search('bach', 'composer')
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {363 entries}>

>>> bachBundle.clear()
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {0 entries}>

Returns None.

OMIT_FROM_DOCS

Do not use the cached bach on this -- the .clear() manipulates the metadata bundle.
N)r]   clearr+   s    r   r   MetadataBundle.clear9  s    ( 	##%r   c                R   [        U [        R                  5      (       ac   U R                  [        R
                  " 5       S-  5      n U R                  nUS   S:X  a  [        U5      S:  a  USS nSR                  U5      nOxSU ;   a  U R                  S5      S   nOU nUR                  [        R                  5      (       a  USS nUR                  SS5      nUR                  [        R                  S5      nUR                  SS5      nUb  U SU 3$ U$ ! [         a     Nf = f)	a  
Given a file path or corpus path, return the metadata key:

>>> mb = metadata.bundles.MetadataBundle()
>>> key = mb.corpusPathToKey('bach/bwv1007/prelude')
>>> key.endswith('bach_bwv1007_prelude')
True

>>> key = mb.corpusPathToKey('corelli/opus3no1/1grave.xml')
>>> key.endswith('corelli_opus3no1_1grave_xml')
True

Numbers are appended if given

>>> key = mb.corpusPathToKey('corelli/opus3no1/1grave.xml', number=3)
>>> key.endswith('corelli_opus3no1_1grave_xml_3')
True
r8   r   /r   N_.)r^   rO   rP   relative_tor   getSourceFilePath
ValueErrorpartsr   joinsplitr   ossepreplace)r   r$   r   r0   s       r   rH   MetadataBundle.corpusPathToKeyO  s   ( h--#//0H0H0JX0UV NNEQx33u:>ab	%J8#%^^H5b9
%
$$RVV,,'^
#++C5J#++BFFC8J''S1
  \6(++3  s   'D 
D&%D&c                    U R                   b;  U R                   R                  5       (       a  U R                   R                  5         ggg)zw
Delete the filesystem cache of a named metadata bundle.

Does not delete the in-memory metadata bundle.

Return None.
N)r   r   unlinkr+   s    r   deleteMetadataBundle.delete  s;     ==$}}##%%$$& & %r   c                &    U R                  US5      $ )a  
Compute the set-wise difference of two metadata bundles:

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> #_DOCS_SHOW bachBundle = coreBundle.search('bach', 'composer')
>>> bachBundle = metadata.bundles.demo_bundle('bach')  #_DOCS_HIDE
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {363 entries}>

>>> #_DOCS_SHOW tripleMeterBundle = coreBundle.search('3/4')
>>> tripleMeterBundle = metadata.bundles.demo_bundle('3/4')  #_DOCS_HIDE
>>> tripleMeterBundle
<music21.metadata.bundles.MetadataBundle {1875 entries}>

>>> bachBundle.difference(tripleMeterBundle)
<music21.metadata.bundles.MetadataBundle {323 entries}>

Returns a new metadata bundle.

differenceri   rk   s     r   r  MetadataBundle.difference  s    * ((
 	
r   c                &    U R                  US5      $ )a  
Compute the set-wise intersection of two metadata bundles:

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> #_DOCS_SHOW bachBundle = coreBundle.search('bach', 'composer')
>>> bachBundle = metadata.bundles.demo_bundle('bach')  #_DOCS_HIDE
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {363 entries}>

>>> #_DOCS_SHOW tripleMeterBundle = coreBundle.search('3/4')
>>> tripleMeterBundle = metadata.bundles.demo_bundle('3/4')  #_DOCS_HIDE
>>> tripleMeterBundle
<music21.metadata.bundles.MetadataBundle {1875 entries}>

>>> bachBundle.intersection(tripleMeterBundle)
<music21.metadata.bundles.MetadataBundle {40 entries}>

Returns a new MetadataBundle.
intersectionri   rk   s     r   r  MetadataBundle.intersection  s    * ((
 	
r   c                &    U R                  US5      $ )a  
True if the set of keys in one metadata bundle are disjoint with
the set of keys in another:

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> #_DOCS_SHOW bachBundle = coreBundle.search('bach', 'composer')
>>> bachBundle = metadata.bundles.demo_bundle('bach')  #_DOCS_HIDE
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {363 entries}>

>>> #_DOCS_SHOW corelliBundle = coreBundle.search('corelli', 'composer')
>>> corelliBundle = metadata.bundles.demo_bundle('corelli')  #_DOCS_HIDE
>>> corelliBundle
<music21.metadata.bundles.MetadataBundle {1 entry}>

>>> bachBundle.isdisjoint(corelliBundle)
True

>>> #_DOCS_SHOW tripleMeterBundle = coreBundle.search('3/4')
>>> tripleMeterBundle = metadata.bundles.demo_bundle('3/4')  #_DOCS_HIDE
>>> tripleMeterBundle
<music21.metadata.bundles.MetadataBundle {1875 entries}>

>>> bachBundle.isdisjoint(tripleMeterBundle)
False

Returns boolean.

isdisjointru   rk   s     r   r  MetadataBundle.isdisjoint  s    < ((FFr   c                &    U R                  US5      $ )a  
True if the set of keys in one metadata bundle are a subset of
the keys in another:

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> #_DOCS_SHOW bachBundle = coreBundle.search('bach', 'composer')
>>> bachBundle = metadata.bundles.demo_bundle('bach')  #_DOCS_HIDE
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {363 entries}>

>>> tripleMeterBachBundle = bachBundle.search('3/4')
>>> tripleMeterBachBundle
<music21.metadata.bundles.MetadataBundle {40 entries}>

>>> tripleMeterBachBundle.issubset(bachBundle)
True

>>> bachBundle.issubset(tripleMeterBachBundle)
False

Returns boolean.
issubsetru   rk   s     r   r  MetadataBundle.issubset  s    0 ((DDr   c                &    U R                  US5      $ )a  
True if the set of keys in one metadata bundle are a superset of
the keys in another:

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> #_DOCS_SHOW bachBundle = coreBundle.search('bach', 'composer')
>>> bachBundle = metadata.bundles.demo_bundle('bach')  #_DOCS_HIDE
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {363 entries}>

>>> tripleMeterBachBundle = bachBundle.search('3/4')
>>> tripleMeterBachBundle
<music21.metadata.bundles.MetadataBundle {40 entries}>

>>> tripleMeterBachBundle.issuperset(bachBundle)
False

>>> bachBundle.issuperset(tripleMeterBachBundle)
True

Returns boolean.

issupersetru   rk   s     r   r  MetadataBundle.issuperset  s    0 ((FFr   c                     SSK Jn   SSK Jn  [        [	        U R
                  U R                  -   [        UR                  5      -   5      5      $ )a  
List all available search field names:

>>> for field in metadata.bundles.MetadataBundle.listSearchFields():
...     field
...
'abstract'
'accessRights'
'accompanyingMaterialWriter'
...
'composer'
'composerAlias'
'composerCorporate'
'conceptor'
'conductor'
...
'dateCreated'
'dateFirstPublished'
'dateIssued'
'dateModified'
'dateSubmitted'
'dateValid'
...
'tempoFirst'
'tempos'
'textLanguage'
'textOriginalLanguage'
'timeSignatureFirst'
'timeSignatures'
'title'
...
r   )
properties)RichMetadata)	music21.metadatar  r  tupler   ALL_UNIQUE_NAMESALL_MUSIC21_WORK_IDSrz    additionalRichMetadataAttributes)r  r  s     r   listSearchFieldsMetadataBundle.listSearchFields  sJ    D 	01V''--.<@@AB
  	r   c           	     t   [         R                  " 5       nUR                  5         Uc  U R                  nUc#  U R                  c  [
        R                  " S5      e[        U[        R                  5      (       d  [        R                  " U5      nUR                  5       (       d;  [        R                  SR                  U R                  U R                  5      5        U $ [        U5      nUR                  U l        [        R                  SU R                  U" 5       S[!        U R                  5      /5        U $ )a  
Load cached metadata from the file path suggested by the name of this
MetadataBundle ('core', 'local', or a name).

If a specific filepath is given with the `filePath` keyword, attempt to
load cached metadata from the file at that location.

If `filePath` is None, and `self.filePath` is also None, do nothing.

>>> #_DOCS_SHOW coreBundle = metadata.bundles.MetadataBundle('core').read()

If a metadata is unnamed, and no file path is specified, an exception
will be thrown:

>>> anonymousBundle = metadata.bundles.MetadataBundle().read()
Traceback (most recent call last):
music21.exceptions21.MetadataException: Unnamed MetadataBundles have
    no default file path to read from.

z?Unnamed MetadataBundles have no default file path to read from.zQno metadata found for: {0!r}; try building cache with corpus.cacheMetadata({1!r})zMetadataBundle: loading time:z	md items:)r   Timerstartr   rc   r   MetadataExceptionr^   rO   rP   r   r   r   formatr	   r]   r   )r"   r   timernewMdbs       r   readMetadataBundle.read?  s   * }}H		 100  (GLL11||H-H  ## %ZZ`Z`(,		499[>? K) & 7 7+IIG%%&!
 	 r   r   )fileExtensionsc               v   SSK Jn  [        UR                  U5      5      n[	        5       nUc'  Uc$  U(       d  [        S5      eUR                  5       u  p!U R                  R                  5        Hs  u  pU	R                  c  M  U	R                  n
U(       a  U
R                  U;  a  M9  XR                  ;   a  MJ  U	R                  X5      S   (       d  Me  XR                  U'   Mu     [        [        [        UR                  R                  5       5      S S95      Ul        U(       a  UR                  " S0 UD6$ U$ )aw  
Perform search, on all stored metadata, permit regular expression
matching.

>>> workList = corpus.corpora.CoreCorpus().getWorkList('ciconia')
>>> metadataBundle = metadata.bundles.MetadataBundle()
>>> failedPaths = metadataBundle.addFromPaths(
...     workList,
...     parseUsingCorpus=False,
...     useMultiprocessing=False,
...     storeOnDisk=False, #_DOCS_HIDE
...     )
>>> failedPaths
[]

>>> searchResult = metadataBundle.search(
...     'cicon',
...     field='composer'
...     )
>>> searchResult
<music21.metadata.bundles.MetadataBundle {1 entry}>
>>> len(searchResult)
1
>>> searchResult[0]
<music21.metadata.bundles.MetadataEntry 'ciconia_quod_jactatur_xml'>
>>> searchResult = metadataBundle.search(
...     'cicon',
...     field='composer',
...     fileExtensions=('.krn',),
...     )
>>> len(searchResult)  # no files in this format
0

>>> searchResult = metadataBundle.search(
...     'cicon',
...     field='composer',
...     fileExtensions=('.xml',),
...     )
>>> len(searchResult)
1

Searches can also use keyword args:

>>> metadataBundle.search(composer='cicon')
<music21.metadata.bundles.MetadataBundle {1 entry}>
r   )r`   zQuery cannot be emptyc                     U S   R                   $ r   r   r   s    r   r   'MetadataBundle.search.<locals>.<lambda>  s    3q6#4#4r   r   r   )music21.corpus.corporar`   r   translateExtensionsr   r   popitemr]   r   r*   r#   suffixrB   r   r   rz   )r"   rC   rD   r-  rE   r`   acceptable_extensionsnewMetadataBundler   r   sps              r   rB   MetadataBundle.searchq  s   p 	2*-f.H.H.X*Y*,=U]-.EFF#++-LE"&"7"7"="="?C%%-))B$:O)O888##E1!44:G2237 #@ .94)::@@BC46.7* $++7h77  r   c                &    U R                  US5      $ )a  
Compute the set-wise symmetric difference of two metadata bundles:

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> #_DOCS_SHOW bachBundle = coreBundle.search('bach', 'composer')
>>> bachBundle = metadata.bundles.demo_bundle('bach')  #_DOCS_HIDE
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {363 entries}>
>>> #_DOCS_SHOW tripleMeterBundle = coreBundle.search('3/4')
>>> tripleMeterBundle = metadata.bundles.demo_bundle('3/4')  #_DOCS_HIDE
>>> tripleMeterBundle
<music21.metadata.bundles.MetadataBundle {1875 entries}>
>>> bachBundle.symmetric_difference(tripleMeterBundle)
<music21.metadata.bundles.MetadataBundle {2158 entries}>

Returns a new MetadataBundle.
symmetric_differenceri   rk   s     r   r:  #MetadataBundle.symmetric_difference  s    & (("
 	
r   c                &    U R                  US5      $ )a  
Compute the set-wise union of two metadata bundles:

>>> #_DOCS_SHOW coreBundle = corpus.corpora.CoreCorpus().metadataBundle
>>> coreBundle = metadata.bundles.demo_bundle('core')  #_DOCS_HIDE
>>> #_DOCS_SHOW bachBundle = coreBundle.search('bach', 'composer')
>>> bachBundle = metadata.bundles.demo_bundle('bach')  #_DOCS_HIDE
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {363 entries}>
>>> beethovenBundle = coreBundle.search(
...     'beethoven',
...     field='composer',
...     )
>>> beethovenBundle
<music21.metadata.bundles.MetadataBundle {23 entries}>

>>> bachBundle.union(beethovenBundle)
<music21.metadata.bundles.MetadataBundle {386 entries}>

Returns a new MetadataBundle.
unionri   rk   s     r   r=  MetadataBundle.union  s    , ((
 	
r   c                6   [         R                  " 5       nUR                  5         [        R	                  S/5        / n[        5       nU R                  R                  5        H  u  pEUR                  nXc;   a  M  [        U[        5      (       a3  UR                  S5      (       a  UR                  UR                  5        M`  [        U[        5      (       a  [        R                  " U5      nUR                  5       (       d  [         R                   " 5       U-  nUR#                  5       (       d  UR%                  U5        UR                  UR                  5        M     U H  nU R                  U	 M     SU S3n[        R	                  U5        ['        U5      $ )z
Validate each metadata entry in a metadata bundle.

If the entry represents a non-virtual corpus asset, test that its
source path is locatable on disk.  If not, remove the metadata entry
from the metadata bundle.
zMetadataBundle: validating...zhttp:z'MetadataBundle: finished validating in z	 seconds.)r   r%  r&  r   r   r   r]   r   r#   r^   r   r   addrO   rP   is_absolutegetCorpusFilePathr   r   r   )r"   r)  invalidatedKeysvalidatedPathsr   r   r#   r   s           r   r   MetadataBundle.validate  sL    !@ AB"&"7"7"="="?C '11J+*c**z/D/DW/M/M""=#;#;<J,,$\\*5
))++#557*D
$$&&&&s+}778' #@( #C%%c* #;E7)L(?##r   c                p   U=(       d    U R                   nU R                   b  U R                   n[        R                  SU/5        U R                  nSU l        [        R
                  " U SS9n[        R                  " US5       nUR                  U5        SSS5        X l        U $ ! , (       d  f       N= f)aG  
Write the metadata bundle to disk as a pickle file.

If `filePath` is None, use `self.filePath`.

Returns the metadata bundle.

>>> #_DOCS_SHOW bachBundle = coreBundle.search('bach', 'composer')
>>> bachBundle = metadata.bundles.demo_bundle('bach')  #_DOCS_HIDE
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {363 entries}>
>>> bachBundle.filePath is None
True

>>> import os
>>> e = environment.Environment()
>>> tempFilePath = e.getTempFile()
>>> bachBundle.write(filePath=tempFilePath)
<music21.metadata.bundles.MetadataBundle {363 entries}>
>>> os.remove(tempFilePath)
NzMetadataBundle: writing:   )protocolwb)	r   r   r   rb   pickledumpsgzipopenr   )r"   r   storedCorpusClientuncompressedoutFps        r   r   MetadataBundle.write$  s    , ,t}}==$}}H##%?$JK!%DL "<<q9L 8T*eL) +-L	 +*s   B''
B5)rb   r]   rd   r8   r   )re   z,'music21.corpus.corpora.Corpus' | str | None)rl   r   )rl   r   r   r   )returnzpathlib.Path | None)FTTF)r   rU   r$   rV   )rR  NonerW   )rC   z
str | Noner-  zIterable[str])+r   r   r   r   rX   r'   rh   rq   rt   r}   r   r   r   r   r   r1   r   r   rj   rv   rY   r8   setterr   rc   r   r   staticmethodrH   r	  r  r  r  r  r  r"  r+  rB   r:  r=  r   r   r   r   r   r   r   r      s`   hX&
06 CD7!CF CD*CB
0
6
6*7 + +. ]]5 5 " "H  8 h!T&, / /b
'
4
4G@E4G4 ' 'R0h W!
 )+W!W!
 &W!r
0
6%$N/r   r   zdict[str, MetadataBundle]_test_bundlesc                   U [         ;   a	  [         U    $ U S:X  a'  SSKJn  U" 5       R                  [         S'   [         S   $ U S:X  a&  [	        S5      R                  SS5      nU[         S'   U$ U S:X  a$  [	        S5      R                  SSS9nU[         S'   U$ U S:X  a%  [	        S5      R                  S5      nU[         S'   U$ [        S	U < 35      e)
z-
This helps with testing by reusing bundles.
r   r   
CoreCorpusbachcomposercorellirD   z3/4zno demo bundle called )rV  r1  rY  rl   demo_bundlerB   r   )whichrY  
bachBundlecorelliBundletripleMeterBundles        r   r^  r^  `  s     U##5 * ; ;fV$$ (//
C
 *f	#F+229J2O#0i ~'/66u=0e  
-eY7
88r   c                       \ rS rSrS rS rSrg)Testi|  c                    SSK Jn  U" 5       nUR                  nUR                  S5      S   nU R	                  [        U5      S5        g )Nr   rX  zbwv66.6z;<music21.metadata.bundles.MetadataEntry 'bach_bwv66_6_mxl'>)r1  rY  rl   rB   assertEqualr/   )r"   rY  cc
coreBundler   s        r   testOneFromCorpusTest.testOneFromCorpus~  sE    5\&&
")))4Q7m,V	Xr   c                   SSK Jn  U" 5       nUR                  S5      n[        5       nUR	                  USSSS9nU R                  U5        UR                  SSS9nU R                  [        U5      S	5        U R                  [        US   5      S
5        UR                  SSSS9nU R                  [        U5      S5        UR                  SSSS9nU R                  [        U5      S	5        g )Nr   rX  ciconiaF)r   r   r   ciconr[  r]  r   zD<music21.metadata.bundles.MetadataEntry 'ciconia_quod_jactatur_xml'>)z.krn)rD   r-  )z.xml)
r1  rY  getWorkListr   r   assertFalserB   rf  r   r/   )r"   rY  rg  workListmdbfailedPathssearchResults          r   testFileExtensionsTest.testFileExtensions  s   5\>>),&&"$	 ' 
 	%zz " 
 	\*A.l1o._	azz$ " 

 	\*A.zz$ " 

 	\*A.r   r   N)r   r   r   r   ri  rt  r   r   r   r   rd  rd  |  s    X/r   rd  __main__)r_  r   )(
__future__r   __all__collectionsr   rL  r  rO   rJ  r   typingtunittestr9   r   music21.common.fileToolsr	   r
   r   r   TYPE_CHECKINGcollections.abcr   r  r   Environmentr   Music21Exceptionr   ProtoM21Objectr   r   rV  __annotations__r^  TestCaserd  
_DOC_ORDERr   mainTestr   r   r   <module>r     s    # $  	       3     ??() &&'9:	l;; 	} G** } F[W++ [L% ,.( -98(/8 (/\ 
 zT r   