Index: parcels/osaf/sharing/EIM.txt =================================================================== --- parcels/osaf/sharing/EIM.txt (revision 13954) +++ parcels/osaf/sharing/EIM.txt (working copy) @@ -1280,4 +1280,82 @@ >>> rs RecordSet(set([]), set([])) +sort_records(records) will return records such that depenencies occur first:: + >>> class DemoA(sharing.Record): + ... URI = 'cid:eim.test.demoA-record@osaf.us' + ... uuid = sharing.key(int) + + >>> class DemoB(sharing.Record): + ... URI = 'cid:eim.test.demoB-record@osaf.us' + ... uuid = sharing.key(DemoA.uuid) + + >>> class DemoC(sharing.Record): + ... URI = 'cid:eim.test.demoC-record@osaf.us' + ... uuid = sharing.key(DemoB.uuid) + + >>> class DemoD(sharing.Record): + ... URI = 'cid:eim.test.demoD-record@osaf.us' + ... uuid = sharing.key(DemoC.uuid) + + >>> rA = DemoA(1) + >>> rB = DemoB(1) + >>> rC = DemoC(1) + >>> rD = DemoD(1) + + >>> list(sharing.sort_records( [rA, rB, rC, rD] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + >>> list(sharing.sort_records( [rA, rC, rD, rB] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + >>> list(sharing.sort_records( [rA, rD, rB, rC] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + + >>> list(sharing.sort_records( [rA, rD, rC, rB] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + >>> list(sharing.sort_records( [rA, rB, rD, rC] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + >>> list(sharing.sort_records( [rA, rC, rB, rD] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + + >>> list(sharing.sort_records( [rB, rC, rD, rA] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + >>> list(sharing.sort_records( [rB, rD, rA, rC] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + >>> list(sharing.sort_records( [rB, rA, rC, rD] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + + >>> list(sharing.sort_records( [rB, rA, rD, rC] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + >>> list(sharing.sort_records( [rB, rC, rA, rD] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + >>> list(sharing.sort_records( [rB, rD, rC, rA] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + + >>> list(sharing.sort_records( [rC, rD, rA, rB] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + >>> list(sharing.sort_records( [rC, rA, rB, rD] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + >>> list(sharing.sort_records( [rC, rB, rD, rA] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + + >>> list(sharing.sort_records( [rC, rB, rA, rD] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + >>> list(sharing.sort_records( [rC, rD, rB, rA] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + >>> list(sharing.sort_records( [rC, rA, rD, rB] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + + >>> list(sharing.sort_records( [rD, rA, rB, rC] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + >>> list(sharing.sort_records( [rD, rB, rC, rA] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + >>> list(sharing.sort_records( [rD, rC, rA, rB] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + + >>> list(sharing.sort_records( [rD, rC, rB, rA] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + >>> list(sharing.sort_records( [rD, rA, rC, rB] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + >>> list(sharing.sort_records( [rD, rB, rA, rC] )) + [DemoA(1), DemoB(1), DemoC(1), DemoD(1)] + Index: parcels/osaf/sharing/eim.py =================================================================== --- parcels/osaf/sharing/eim.py (revision 13954) +++ parcels/osaf/sharing/eim.py (working copy) @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. from __future__ import with_statement + __all__ = [ 'UnknownType', 'typeinfo_for', 'BytesType', 'TextType', 'DateType', 'IntType', 'BlobType', 'ClobType', 'DecimalType', 'get_converter', @@ -19,6 +20,7 @@ 'Record', 'RecordSet', 'lookupSchemaURI', 'Filter', 'Translator', 'exporter', 'TimestampType', 'IncompatibleTypes', 'Inherit' ] + from symbols import Symbol # XXX change this to peak.util.symbols from simplegeneric import generic from weakref import WeakValueDictionary @@ -37,9 +39,6 @@ - - - def exporter(*types): """Mark a translator method as exporting the specified item type(s)""" for t in types: @@ -368,18 +367,17 @@ self.exclusions|other.exclusions) return rs -''' Partial sketch of a dependency-ordering routine - def sort_records(records): """Sort an iterable of records such that dependencies occur first""" + waiting = {} seen = {} def release(key): - seen[key] = True to_release = [key] while to_release: key = to_release.pop() + seen[key] = True if key not in waiting: continue for deps, record in waiting[key]: @@ -395,11 +393,12 @@ for dep in record.requiresKeys(): if dep not in seen: waiting.setdefault(dep,[]).append(pair) + deps.append(dep) if deps: continue # can't process record with outstanding dependencies - + yield record # allow the record to pass, then its dependents - for record in release(r.getKey()): + for record in release(record.getKey()): yield record while waiting: @@ -407,8 +406,8 @@ if key not in seen: # release only unseen root dependencies for record in release(key): yield record -''' + class Filter: """Suppress inclusion of specified field(s) in Records and RecordSets""" @@ -721,6 +720,12 @@ return t(*res) + def requiresKeys(self): + data = {} + for f in self.__class__.__fields__: + if isinstance(f.type, key): + data.setdefault(f.type.owner, []).append(self[f.offset]) + return [(k,)+tuple(v) for k,v in data.items()] @@ -731,12 +736,6 @@ - - - - - - required_translator_attrs = dict( version=int, URI=str, description=unicode).items()