Closed assumptionsoup closed 6 years ago
These changes made sense, thanks for the PR. Odd that maya would turn everything into longs, though... Can they really represent arbitrary length ints? We may have to add some sort of check where, if it is a long, it does a max bounds check. No idea about the tuple thing offhand. Maybe just didn't want to have to deal with mutuality, and maintaining the live link to the optionvar? Or was afraid people would store the result in their own data structures, and not know / forget that the result was maintaining a live link to the optionVar? Will need to take a closer look.
Thanks for merging this Paul. I should have mentioned that I was using Maya 2018. I guess this is new behavior. I'm seeing a lot of queries return longs now. As for your question about arbitrary integer lengths, the python docs have this to say:
Plain integers (also just called integers) are implemented using long in C, which gives them at least 32 bits of precision (sys.maxint is always set to the maximum plain integer value for the current platform, the minimum value is -sys.maxint - 1). Long integers have unlimited precision.
This is the opposite of what I had assumed, so that was really interesting to learn.
I'm guessing mutability wasn't maintained because optionvar lists don't allow set item
operations. Here was my quick'n dirty implementation. It might help explain things. Note, that it doesn't maintain the link on get
- something I would probably change if this were heading pymel's way:
class MutableOptionVarList(collections.MutableSequence):
def __init__(self, value, key):
if value:
self._items = list(value)
else:
self._items = []
self.key = key
def __getitem__(self, index):
return self._items[index]
def __setitem__(self, index, value):
self._items[index] = value
self._saveOptionVar()
def __delitem__(self, index):
self._items.pop(index)
self._saveOptionVar()
def __len__(self):
return len(self._items)
def insert(self, index, value):
if index == len(self._items):
self._items.append(value)
if isinstance(value, basestring):
return cmd.optionVar(stringValueAppend=[self.key, value])
if isinstance(value, (int, long)):
return cmd.optionVar(intValueAppend=[self.key, value])
if isinstance(value, float):
return cmd.optionVar(floatValueAppend=[self.key, value])
else:
raise TypeError('unsupported datatype: strings, ints, floats and their subclasses are supported')
else:
self._items.insert(index, value)
self._saveOptionVar()
def _saveOptionVar(self):
if len(self._items) == 0:
return cmd.optionVar(clearArray=self.key)
listType = type(self._items[0])
if issubclass(listType, basestring):
flag = 'stringValue'
elif issubclass(listType, (int, long)):
flag = 'intValue'
elif issubclass(listType, float):
flag = 'floatValue'
else:
raise TypeError('%r is unsupported; Only strings, ints, float, lists, and their subclasses are supported' % listType)
cmd.optionVar(**{flag: [self.key, self._items[0]]}) # force to this datatype
flag += "Append"
for elem in self._items[1:]:
if not isinstance(elem, listType):
raise TypeError('all elements in list must be of the same datatype')
cmd.optionVar(**{flag: [self.key, elem]})
def __repr__(self):
return '%s(%r, %r)' % (type(self).__name__, self._items, self.key)
OptionVar lists are a little wonky right now.
Everything is working fine so far, but...
This is obviously not ideal when you try to modify existing optionvar lists.
By the way, is there any reason why OptionVarList is a tuple (other than terrible performance when doing anything aside from a clear/append)? I just cobbled together a mutable version for myself, and I'd be happy to integrate it once I've written some tests.