Previous topic

music21.sieve

Next topic

music21.spanner

Table Of Contents

Table Of Contents

This Page

music21.sites

sites.py – Objects for keeping track of relationships among Music21Objects

SiteRef

class music21.sites.SiteRef

a single Site (stream, container, parent, reference, etc.) stored inside the Sites object.

A very simple object.

This site would be stored in the .sites.siteDict for, say a note.Note, if it were in st at offset 20.0

>>> st = stream.Stream()
>>> st.id = 'hi'
>>> s = sites.SiteRef()
>>> s.classString = st.classes[0]
>>> s.site = st
>>> s.isDead
False

If you call s.site, you always get an object out, but internally, there’s a .siteWeakref that stores a weakref to the site.

>>> s.site
<music21.stream.Stream hi>
>>> s.siteWeakref
<weakref at 0x...; to 'Stream' at 0x...>

If you turn sites.WEAKREF_ACTIVE to False then .siteWeakref just stores another reference to the site. Bad for memory. Good for debugging pickling.

SiteRef bases

SiteRef read/write properties

SiteRef.site

Sites

class music21.sites.Sites(containedById=None)

An object, stored within a Music21Object, that stores (weak) references to a collection of objects that may be contextually relevant to this object.

Most of these objects are locations (also called sites), or Streams that contain this object.

All defined contexts are stored as dictionaries in a dictionary. The outermost dictionary stores objects.

Sites bases

Sites methods

Sites.add(obj, offset=None, timeValue=None, idKey=None, classString=None)

Add a reference to the Sites collection for this object.

OFFSET IS IGNORED NOW!

N.B. – like all .sites operations, this is an advanced tool not for standard music21 usage. Instead of:

elObj.add(streamObj, 20.0)

use this command, which will take care of .sites.add as well as putting elObj in streamObj.elements:

streamObj.insert(20.0, elObj)

If offset is None, then obj is interpreted as a Context (such as a temperament, a time period, etc.)

If offset is not None, then obj is interpreted as location, i.e., a Stream.

offset can also be the term highestTime which is the highest available time in the obj (used for streamObj.append(el))

The timeValue argument is used to store the time as an int (in milliseconds after Jan 1, 1970) when this object was added to locations. If set to None, then the current time is used.

idKey stores the id() of the obj. If None, then id(obj) is used.

classString stores the class of obj. If None then obj.classes[0] is used.

TODO: Tests. Including updates.

Sites.clear()

Clear all stored data.

Sites.get(locationsTrail=False, sortByCreationTime=False, priorityTarget=None, excludeNone=False)

Get references; order, based on dictionary keys, is from most recently added to least recently added.

The locationsTrail option forces locations to come after all other defined contexts. v2.1 – It does nothing now... TODO: Remove

The sortByCreationTime option will sort objects by creation time, where most-recently assigned objects are returned first. Can be [False, other], [True, 1] or [‘reverse’, -1]

If priorityTarget is defined, this object will be placed first in the list of objects.

>>> class Mock(base.Music21Object):
...     pass
...
>>> aObj = Mock()
>>> bObj = Mock()
>>> cObj = Mock()
>>> aSites = sites.Sites()
>>> aSites.add(cObj, 345) # a location
>>> aSites.add(aObj)
>>> aSites.add(bObj)
>>> aSites.get() == [cObj, aObj, bObj]
True
>>> aSites.get(sortByCreationTime=True) == [bObj, aObj, cObj]
True
Sites.getAllByClass(className, found=None, idFound=None, memo=None)

Return all known references of a given class found in any association with this Sites object.

This will recursively search the defined contexts of existing defined contexts, and return a list of all objects that match the given class.

>>> class Mock(base.Music21Object):
...    pass
...
>>> class Mocker(base.Music21Object):
...    pass
...
>>> aObj = Mock()
>>> bObj = Mock()
>>> cObj = Mocker()
>>> dc = sites.Sites()
>>> dc.add(aObj)
>>> dc.add(bObj)
>>> dc.add(cObj)
>>> dc.getAllByClass(Mock) == [aObj, bObj]
True

A string (case insensitive) can also be used:

>>> dc.getAllByClass("mock") == [aObj, bObj]
True
Sites.getAttrByName(attrName)

Given an attribute name, search all objects and find the first that matches this attribute name; then return a reference to this attribute.

>>> class Mock(base.Music21Object):
...     attr1 = 234
...
>>> aObj = Mock()
>>> aObj.attr1 = 234
>>> bObj = Mock()
>>> bObj.attr1 = 98
>>> aSites = sites.Sites()
>>> aSites.add(aObj)
>>> len(aSites)
1
>>> aSites.getAttrByName('attr1') == 234
True
>>> aSites.remove(aObj)
>>> aSites.add(bObj)
>>> aSites.getAttrByName('attr1') == 98
True

An incorrect attribute name will just give none:

>>> aSites.getAttrByName('blah') is None
True
Sites.getById(siteId)

Return the object specified by an id. Used for testing and debugging. Should NOT be used in production code.

>>> a = note.Note()
>>> s = stream.Stream()
>>> s.append(a)
>>> a.sites.getById(id(s)) is s
True
Sites.getObjByClass(className, serialReverseSearch=True, callerFirst=None, sortByCreationTime=False, priorityTarget=None, getElementMethod='getElementAtOrBefore', memo=None)

Return the most recently added reference based on className. Class name can be a string or the class name.

This will recursively search the sitesDicts of objects in Site objects in the siteDict.

The callerFirst parameters is simply used to pass a reference of the first caller; this is necessary if we are looking within a Stream for a flat offset position.

If priorityTarget is specified, this location will be searched first. use priorityTarget=activeSite to prioritize that.

The getElementMethod is a string that selects which Stream method is used to get elements for searching with getElementsByClass() calls.

>>> class Mock(base.Music21Object):
...     pass
...
>>> import time
>>> aObj = Mock()
>>> bObj = Mock()
>>> aSites = sites.Sites()
>>> aSites.add(aObj)
>>> aSites.add(bObj)
>>> # we get the most recently added object first
>>> aSites.getObjByClass('Mock', sortByCreationTime=True) == bObj
True
>>> aSites.getObjByClass(Mock, sortByCreationTime=True) == bObj
True
Sites.getSiteCount()

Return the number of non-dead sites, excluding the None site. This does not unwrap weakrefs for performance.

>>> a = note.Note()
>>> a.sites.getSiteCount()
0
>>> s = stream.Stream()
>>> s.append(a)
>>> a.sites.getSiteCount()
1
>>> sf = s.flat
>>> a.sites.getSiteCount()
2
Sites.getSiteIds()

Return a list of all site Ids.

>>> class Mock(base.Music21Object):
...     pass
...
>>> aSite = Mock()
>>> dc = sites.Sites()
>>> dc.add(aSite)
>>> dc.getSiteIds() == [id(aSite)]
True
Sites.getSites(idExclude=None, excludeNone=False)

Get all Site objects in .siteDict that are locations. Note that this unwraps all sites from weakrefs and is thus an expensive operation.

>>> class Mock(base.Music21Object):
...     pass
...
>>> aObj = Mock()
>>> bObj = Mock()
>>> aSites = sites.Sites()
>>> aSites.add(aObj, 234)
>>> aSites.add(bObj, 3000)
>>> len(aSites.getSites())
2
>>> len(aSites.getSites(idExclude=[id(aObj)]))
1
Sites.getSitesByClass(className)

Return a list of unwrapped site from siteDict.site [SiteRef.site] (generally a Stream) that matches the provided class.

Input can be either a Class object or a string

>>> class Mock(base.Music21Object):
...     pass
...
>>> aObj = Mock()
>>> bObj = Mock()
>>> cObj = stream.Stream()
>>> aSites = sites.Sites()
>>> aSites.add(aObj, 234)
>>> aSites.add(bObj, 3000)
>>> aSites.add(cObj, 200)
>>> aSites.getSitesByClass(Mock) == [aObj, bObj]
True
>>> aSites.getSitesByClass('Stream') == [cObj]
True
Sites.hasSiteId(siteId)

Return True or False if this Sites object already has this site id.

>>> class Mock(base.Music21Object):
...     pass
...
>>> aSite = Mock()
>>> bSite = Mock()
>>> dc = sites.Sites()
>>> dc.add(aSite, 0)
>>> dc.hasSiteId(id(aSite))
True
Sites.hasSpannerSite()

Return True if this object is found in any Spanner. This is determined by looking for a SpannerStorage Stream class as a Site.

Sites.hasVariantSite()

Return True if this object is found in any Variant. This is determined by looking for a VariantStorage Stream class as a Site.

Sites.isSite(obj)

Given an object, determine if it is an object in a Site stored in this Sites’s siteDict. This will return False if the object is simply a context and not a location.

>>> class Mock(base.Music21Object):
...     pass
...
>>> aSite = Mock()
>>> aLocations = sites.Sites()
>>> aLocations.add(aSite)
>>> aLocations.isSite(aSite)
True
Sites.purgeLocations(rescanIsDead=False)

Clean all locations that refer to objects that no longer exist.

The removeOrphanedSites option removes sites that may have been the result of deepcopy: the element has the site, but the site does not have the element. This results b/c Sites are shallow-copied, and then elements are re-added.

>>> class Mock(base.Music21Object):
...     pass
...
>>> aSite = Mock()
>>> cSite = Mock()
>>> aLocations = sites.Sites()
>>> aLocations.add(aSite, 0)
>>> aLocations.add(cSite) # a context
>>> del aSite
>>> len(aLocations)
2
>>> aLocations.purgeLocations(rescanIsDead=True)
>>> len(aLocations)
1
Sites.remove(site)

Remove the object (a context or location site) specified from Sites. Object provided can be a location site (i.e., a Stream) or a pure context (like a Temperament).

N.B. – like all .sites operations, this is an advanced tool not for standard music21 usage. Instead of:

elObj.remove(streamObj)

use this command, which will take care of .sites.remove as well as removing elObj from streamObj.elements:

streamObj.remove(elObj)
>>> class Mock(base.Music21Object):
...     pass
...
>>> aSite = Mock()
>>> bSite = Mock()
>>> cSite = Mock()
>>> aSites = sites.Sites()
>>> aSites.add(aSite, 23)
>>> len(aSites)
1
>>> aSites.add(bSite, 233)
>>> len(aSites)
2
>>> aSites.add(cSite, 232223)
>>> len(aSites)
3
>>> aSites.remove(aSite)
>>> len(aSites)
2
Sites.removeById(idKey)

Remove a site entry by id key, which is id() of the object.

Sites.setAttrByName(attrName, value)

Given an attribute name, search all objects and find the first that matches this attribute name; then return a reference to this attribute.

>>> class Mock(base.Music21Object):
...     attr1 = 234
...
>>> aObj = Mock()
>>> bObj = Mock()
>>> bObj.attr1 = 98
>>> aSites = sites.Sites()
>>> aSites.add(aObj)
>>> aSites.add(bObj)
>>> aSites.setAttrByName('attr1', 'test')
>>> aSites.getAttrByName('attr1') == 'test'
True