https://issues.qgis.org/https://issues.qgis.org/favicon.ico2013-08-28T02:35:49ZQGIS Issue TrackingQGIS Application - Bug report #8258: QgsVectorDataProvider.uniqueValues returns not None but QPyNullVarianthttps://issues.qgis.org/issues/8258?journal_id=443062013-08-28T02:35:49ZMatthias Kuhn
<ul></ul><p>Will now be:</p>
<pre>
>>> layer = iface.activeLayer()
>>> provider = layer.dataProvider()
>>> provider.uniqueValues(1)
[NULL, u'pentagon', u'quadrangle', u'triangle']
>>> f = provider.getFeatures( QgsFeatureRequest().setFilterFid( 0 ) ).next()
True
>>> f.attributes()
[u'f', NULL, 10]
>>> provider.uniqueValues(1)[0] == None
False
>>> provider.uniqueValues(1)[0] is None
False
>>> provider.uniqueValues(1)[0].isNull()
True
>>> if not provider.uniqueValues(1)[0]:
>>> 'it is NOT'
'it is NOT'
</pre>
<p>Now everything returning a NULL attribute returns a QPyNullVariant (by design) but will be represented as "NULL" on the console</p> QGIS Application - Bug report #8258: QgsVectorDataProvider.uniqueValues returns not None but QPyNullVarianthttps://issues.qgis.org/issues/8258?journal_id=443352013-08-28T16:26:56ZMinoru Akagi
<ul></ul><p>The evaluation of (None == None) is True. But the evaluation of the following conditional expression is False.<br /><pre>
>>> provider.uniqueValues(1)[0] == f.attributes()[1]
False
</pre></p>
<p>It makes sense to me that (QPyNullVariant == QPyNullVariant) is evaluated as True.</p> QGIS Application - Bug report #8258: QgsVectorDataProvider.uniqueValues returns not None but QPyNullVarianthttps://issues.qgis.org/issues/8258?journal_id=443362013-08-28T16:29:13ZNathan Woodrow
<ul></ul><p>You would think so but it's not the case.</p>
<p>We should be able to fix that by overloading the <i>eq</i> method. Hold tight.</p> QGIS Application - Bug report #8258: QgsVectorDataProvider.uniqueValues returns not None but QPyNullVarianthttps://issues.qgis.org/issues/8258?journal_id=443372013-08-28T16:35:08ZNathan Woodrow
<ul></ul><p>We can just do this:</p>
<pre><code>
from types import MethodType
from PyQt4.QtCore import QPyNullVariant
def __nonzero__(self):
return False
def __eq__(self, other):
return True
QPyNullVariant.__nonzero__ = MethodType(__nonzero__, None, QPyNullVariant)
QPyNullVariant.__eq__ = MethodType(__eq__, None, QPyNullVariant)
</code></pre>
<p>which will work like so:</p>
<pre><code>
>>> n = QPyNullVariant('QString')
>>> n2 = QPyNullVariant('QString')
>>> n == n2
True
</code></pre>
<p>Just be aware this doesn't compare the internal type of QPyNullVariant so maybe we should just compare that rather then returning True. In practice should this work?</p>
<pre><code>
>>> n = QPyNullVariant('QString')
>>> n2 = QPyNullVariant('int')
>>> n == n2
True
</code></pre>
<p>or do we not really care in this case? Because we are just trying to do: NULL == NULL</p> QGIS Application - Bug report #8258: QgsVectorDataProvider.uniqueValues returns not None but QPyNullVarianthttps://issues.qgis.org/issues/8258?journal_id=443572013-08-29T18:32:59ZNathan Woodrow
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Closed</i></li><li><strong>Resolution</strong> set to <i>fixed</i></li></ul><p>This is as fixed as we are going to be able to do.</p>
<pre><code>
>>> n = QPyNullVariant('QString')
>>> n2 = QPyNullVariant('QString')
>>> n == n2
True
>>> n = QPyNullVariant('QString')
>>> n2 = QPyNullVariant('int')
>>> n == n2
True
>>> n = QPyNullVariant('QString')
>>> n == None
True
>>> n = QPyNullVariant('QString')
>>> n is None
False
>>> n = 100
>>> n2 = QPyNullVariant('int')
>>> n == n2
False
</code></pre>
<p>There is also a new shortcut <code>NULL</code> type in <code>qgis.core</code> which is a <code>QPyNullVariant</code>. So you can just do:</p>
<pre><code>
>>> from qgis.core import NULL
>>> provider.uniqueValues(1)[0] == NULL
True
</code></pre> QGIS Application - Bug report #8258: QgsVectorDataProvider.uniqueValues returns not None but QPyNullVarianthttps://issues.qgis.org/issues/8258?journal_id=443582013-08-29T19:02:14ZMinoru Akagi
<ul><li><strong>Status</strong> changed from <i>Closed</i> to <i>Reopened</i></li></ul><p>Great works! Thanks, Matthias and Nathan!!</p>
<p>Now the evaluation of the following conditional expression is True.</p>
<pre>
>>> provider.uniqueValues(1)[0] == f.attributes()[1]
True
</pre>
<p>However, the following is also True!<br /><pre>
>>> provider.uniqueValues(1)[0] != f.attributes()[1]
True
</pre></p>
<p>Probably, we should override <i>ne</i> method too as below:<br /><pre>
def __ne__(self, other):
return not self.__eq__(other)
QPyNullVariant.__ne__ = MethodType(__ne__, None, QPyNullVariant)
</pre></p> QGIS Application - Bug report #8258: QgsVectorDataProvider.uniqueValues returns not None but QPyNullVarianthttps://issues.qgis.org/issues/8258?journal_id=443592013-08-29T19:07:17ZNathan Woodrow
<ul></ul><p>Good catch!</p>
<p>Will fix that now.</p> QGIS Application - Bug report #8258: QgsVectorDataProvider.uniqueValues returns not None but QPyNullVarianthttps://issues.qgis.org/issues/8258?journal_id=443762013-08-30T04:00:05ZMinoru Akagi
<ul><li><strong>% Done</strong> changed from <i>0</i> to <i>100</i></li><li><strong>Status</strong> changed from <i>Reopened</i> to <i>Closed</i></li></ul>