Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
dist/
RO.egg-info/
*.pyc
*.pyc

# Pycharm settings
.idea

2 changes: 2 additions & 0 deletions README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ Tkinter-compatible networking.

The docs directory contains installation instructions, an overview,
version history and the license.

> **WARNING:** this version is Python 3 only in preparation for SDSS-V. For SDSS-IV, use the ``python2`` branch.
4 changes: 2 additions & 2 deletions python/RO/Alg/IDGen.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

class IDGen(object):
"""generate a sequence of integer ID numbers, wrapping around if desired.

Warning: can be used as an iterator, but there is no stop condition!
"""
def __init__(self, startVal=1, wrapVal=None, incr=1):
Expand Down Expand Up @@ -49,6 +49,6 @@ def __next__(self):
if self.wrapVal is not None:
self.ind %= self.nSteps
return newID

def __repr__(self):
return "IDGen(startVal=%s, wrapVal=%s, incr=%s)" % (self.startVal, self.wrapVal, self.incr)
6 changes: 3 additions & 3 deletions python/RO/Alg/ListPlus.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ def get(self, key, defValue = None):
return self[key]
except (LookupError, TypeError):
return defValue

def has_key(self, key):
try:
self[key]
return True
except (LookupError, TypeError):
return False

def iteritems(self):
for key in self.keys():
yield (key, self[key])
Expand All @@ -34,6 +34,6 @@ def itervalues(self):

def keys(self):
return list(range(len(self)))

def values(self):
return self[:]
27 changes: 13 additions & 14 deletions python/RO/Alg/MultiDict.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@
and added SetDict.
2010-05-18 ROwen Modified SetDict to use sets
2015-09-24 ROwen Replace "== None" with "is None" to future-proof array tests and modernize the code.
2020-01-13 DGatlin Changed set([val]) to set(val) for Python 3
"""
__all__ = ["ListDict", "SetDict"]

try:
from UserDict import UserDict
except ImportError:
from collections import UserDict

except ImportError:
from UserDict import UserDict

class ListDict(UserDict):
"""A dictionary whose values are a list of items.
Expand All @@ -34,10 +33,10 @@ def __setitem__(self, key, val):
self.data[key].append(val)
else:
self.data[key] = [val]

def addList(self, key, valList):
"""Append values to the list of values for a given key, creating a new entry if necessary.

Inputs:
- valList: an iterable collection (preferably ordered) of values
"""
Expand All @@ -59,25 +58,25 @@ class SetDict(ListDict):
"""A dictionary whose values are a set of items, meaning
a list of unique items. Duplicate items are silently not added.
"""

def __setitem__(self, key, val):
"""Add a value to the set of values for a given key, creating a new entry if necessary.

Duplicate values are silently ignored.

Supports the notation: aListDict[key] = val
"""
valSet = self.data.get(key)
if valSet is None:
self.data[key] = set([val])
self.data[key] = set(val)
else:
valSet.add(val)

def addList(self, key, valList):
"""Add values to the set of values for a given key, creating a new entry if necessary.

Duplicate values are silently ignored.

Inputs:
- valList: an iterable collection of values
"""
Expand Down Expand Up @@ -107,7 +106,7 @@ def addList(self, key, valList):
print((RO.StringUtil.prettyDict(ad)))
print("listdict copy (modified):")
print((RO.StringUtil.prettyDict(ad2)))


ad = SetDict()
ad["a"] = "foo a"
Expand Down
4 changes: 2 additions & 2 deletions python/RO/Alg/MultiListIter.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
class MultiListIter(object):
def __init__(self, *lists):
self.iters = list(map(iter, lists))

def __iter__(self):
return self

def __next__(self):
return [next(elem) for elem in self.iters]

Expand Down
140 changes: 72 additions & 68 deletions python/RO/Alg/OrderedDict.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

History:
2002-02-01 ROwen First release.
2002-02-04 ROwen Added code for iterkeys, itervalues and iteritems
2002-02-04 ROwen Added code for iterkeys, itervalues and iteritems
(as I feared I would have to do, but my limited tests suggested otherwise).
Thanks to Jason Orendorff for insisting and for supplying the nice code
for itervalues and iteritems. Also added __str__ and copy methods,
Expand All @@ -34,9 +34,13 @@
Modified __repr__ to return a string that can recreate the dict.
Added __str__ to output the traditional dict representation.
2015-09-24 ROwen Replace "== None" with "is None" to modernize the code.
2020-05-13 DGatlin Removed a number of functions in OrderedDict that can simply
be inhereted by dict in Python 3
"""
__all__ = ["OrderedDict", "ReverseOrderedDict"]



class OrderedDict(dict):
"""A dictionary in which the order of adding items is preserved.
Replacing an existing item replaces it at its current location.
Expand All @@ -56,23 +60,21 @@ def __init__(self, seqOrDict=None):
for key, val in seqOrDict:
self[key] = val

def clear(self):
self.__keyList = []
dict.clear(self)
# def clear(self):
# self.__keyList = []
# dict.clear(self)

def copy(self):
return self.__class__(self)

def iterkeys(self):
return iter(self.__keyList)
return self.keys()

def itervalues(self):
for key in self.keys():
yield self[key]
return iter(self)

def iteritems(self):
for key in self:
yield (key, self[key])
return self.items()

def index(self, key):
"""Return the index of key.
Expand All @@ -92,71 +94,71 @@ def insert(self, ind, key, value):
self.__keyList.insert(ind, key)
dict.__setitem__(self, key, value)

def keys(self):
return self.__keyList[:]

def pop(self, key):
val = self[key]
self.__delitem__(key)
return val

def popitem(self, i=-1):
"""Remove the ith item from the dictionary (the last item if i is omitted)
and returns (key, value). This emulates list.pop() instead of dict.popitem(),
since ordered dictionaries have a defined order.
"""
key = self.__keyList[i]
item = (key, self[key])
self.__delitem__(key)
return item

def setdefault(self, key, value):
if key not in self:
self[key] = value
return self[key]
# def keys(self):
# return self.__keyList[:]

# def pop(self, key):
# val = self[key]
# self.__delitem__(key)
# return val

# def popitem(self, i=-1):
# """Remove the ith item from the dictionary (the last item if i is omitted)
# and returns (key, value). This emulates list.pop() instead of dict.popitem(),
# since ordered dictionaries have a defined order.
# """
# key = self.__keyList[i]
# item = (key, self[key])
# self.__delitem__(key)
# return item

# def setdefault(self, key, value):
# if key not in self:
# self[key] = value
# return self[key]

def sort(self, cmpFunc=None):
"""Sort the keys.
"""
self.__keyList.sort(cmpFunc)
pass

def update(self, aDict):
"""Add all items from dictionary aDict to self (in order if aDict is an ordered dictionary).
"""
for key, value in aDict.items():
self[key] = value
# def update(self, aDict):
# """Add all items from dictionary aDict to self (in order if aDict is an ordered dictionary).
# """
# for key, value in aDict.items():
# self[key] = value

def values(self):
return [self[key] for key in self.keys()]
# def values(self):
# return [self[key] for key in self.keys()

def _checkIntegrity(self):
"""Perform an internal consistency check and raise an AssertionError if anything is wrong.

In principal a bug could lead to the system getting out of synch, hence this method.
"""
assert len(self) == len(self.__keyList), \
"length of dict %r != length of key list %r" % (len(self), len(self.__keyList))
assert len(self) == len(self.keys()), \
"length of dict %r != length of key list %r" % (len(self), len(self.keys()))
for key in self.keys():
assert key in self, \
"key %r in key list missing from dictionary" % (key,)

def __delitem__(self, key):
dict.__delitem__(self, key)
self.__keyList.remove(key)
# def __delitem__(self, key):
# dict.__delitem__(self, key)
# self.__keyList.remove(key)

def __iter__(self):
return iter(self.keys())
# def __iter__(self):
# return iter(self.keys())

def __repr__(self):
return "%s([%s])" % (self.__class__.__name__, ', '.join(["(%r, %r)" % item for item in self.items()]))
# def __repr__(self):
# return "%s([%s])" % (self.__class__.__name__, ', '.join(["(%r, %r)" % item for item in self.items()]))

def __str__(self):
return "{%s}" % (', '.join(["(%r, %r)" % item for item in self.items()]),)
# def __str__(self):
# return "{%s}" % (', '.join(["(%r, %r)" % item for item in self.items()]),)

def __setitem__(self, key, value):
if key not in self:
self.__keyList.append(key)
dict.__setitem__(self, key, value)
# def __setitem__(self, key, value):
# if key not in self:
# self.__keyList.append(key)
# dict.__setitem__(self, key, value)


class ReverseOrderedDict(OrderedDict):
Expand Down Expand Up @@ -192,17 +194,18 @@ def __repr__(self):
descrList.reverse()
return "%s([%s])" % (self.__class__.__name__, ', '.join(descrList))


if __name__ == "__main__":
print("testing OrderedDict")
import copy
import random

# basic setup
showOutput = 0 # display results or just complain if failure?
nItems = 10 # length of dictionary to test
nToDelete = 2 # number of items to delete
nToReplace = 5 # number of items to replace

assert nToDelete > 0
assert nToReplace > 0
assert nItems >= nToDelete + nToReplace
Expand All @@ -211,29 +214,29 @@ def testDict(desKeys, desValues, theDict):
"""Test an ordered dictionary, given the expected keys and values (in order)"""
actKeys = list(theDict.keys())
assert desKeys == actKeys, "keys() failed; keys %r != %r" % (desKeys, actKeys)

actValues = list(theDict.values())
assert desValues == actValues, "values() failed; values %r != %r" % (desValues, actValues)

assert len(theDict) == len(desKeys), "len() failed: %r != %r" % (len(desKeys), len(theDict))

# verify that iteration works:
actKeys = [key for key in theDict]
assert desKeys == actKeys, "__iter__() failed; keys %r != %r" % (desKeys, actKeys)

actValues = [v for v in theDict.values()]
assert desValues == actValues, "itervalues() failed; values %r != %r" % (desValues, actValues)

desKeyValues = list(map(lambda key, v: (key, v), desKeys, desValues))
actKeyValues = [kv for kv in theDict.items()]
assert desKeyValues == actKeyValues, "iteritems() failed; values %r != %r" % (desKeyValues, actKeyValues)

theDict._checkIntegrity()

theDict._checkIntegrity()



def keyToValue(key):
return "val[%r]" % (key,)

def altKeyToValue(key):
return "alt[%r]" % (key,)

Expand Down Expand Up @@ -270,17 +273,18 @@ def altKeyToValue(key):
testDict(inKeys, inValues, oDict)
if showOutput:
print(("after replacing %r items: %r" % (nToReplace, oDict)))

# test copying
dictCopy = oDict.copy()
assert list(dictCopy.keys()) == list(oDict.keys()), "copy failed; keys %r != %r" % (list(dictCopy.keys()), list(testDict.keys()))

testKey = list(dictCopy.keys())[0]
dictCopy[testKey] = "changed value"
assert list(dictCopy.values()) != list(oDict.values()), "copy failed; changing a value in one affected the other"

# add a new item to dictCopy and make sure the integrity of both are preserved
# (verifies that the __keyList lists in each dictionary are separate entities)
dictCopy[()] = "value for ()"
dictCopy._checkIntegrity()
oDict._checkIntegrity()
print('Tests complete')
Loading