[Zope-Perl] perl ref len method.
Gisle Aas
gisle@ActiveState.com
25 Jan 2001 14:01:23 -0800
"Chris McDonough" <chrism@digicool.com> writes:
> I don't think this matters much, but in the perlmodule docs, you say:
>
> len(p) -- for arrays and hashes this return the natural size. For all other
> things it return 1, because Python does not provide hooks for overriding
> boolean tests and we want that stuff to be TRUE.
>
> You can override the truth test in Python via __nonzero__ or __len__.
I guess I did not discover this because I never tried to overload
'perl ref' object's as numbers. This is a patch that should fix this
problem.
--Gisle
Change 14147 by gisle@caliper on 2001/01/25 13:57:36
Provide overloading of pysvrv_nonzero so that we don't have
to let len() do the wrong thing for things that are neither
array nor hash.
Affected files ...
... //depot/main/Apps/Bifrost/pyperl/perlmodule.pod#3 edit
... //depot/main/Apps/Bifrost/pyperl/svrv_object.c#9 edit
Differences ...
==== //depot/main/Apps/Bifrost/pyperl/perlmodule.pod#3 (text) ====
@@ -389,9 +389,8 @@
=item len(p)
-For arrays and hashes this return the natural size. For all other
-things it return 1, because python does not provide hooks for
-overriding boolean tests and we want that stuff to be TRUE.
+For arrays and hashes this return the size. For all other things it
+will raise a TypeError exception.
=back
==== //depot/main/Apps/Bifrost/pyperl/svrv_object.c#9 (text) ====
@@ -1431,17 +1431,10 @@
len = HvKEYS(sv); /* XXX support tied hashes */
}
else {
-#if 1
- /* since this is also used to define truth, it makes
- * sense to make length non-zero for most other things.
- */
- len = 1;
-#else
ENTER_PYTHON;
type_error("Can't count", sv);
len = -1;
ENTER_PERL; /* just so we can change back :-( */
-#endif
}
ENTER_PYTHON;
@@ -1449,7 +1442,34 @@
return len;
}
+static int
+pysvrv_nonzero(PySVRV *self)
+{
+ SV* sv;
+ int v;
+ dCTX;
+
+ ASSERT_LOCK_PYTHON;
+ CHECK_OWNED_INT;
+ ENTER_PERL;
+ sv = SvRV(self->rv);
+ if (SvTYPE(sv) == SVt_PVAV) {
+ v = try_array_len((AV*)sv) != 0;
+ }
+ else if (SvTYPE(sv) == SVt_PVHV) {
+ v = HvKEYS(sv) != 0; /* XXX support tied hashes */
+ }
+ else {
+ v = 1;
+ }
+ ENTER_PYTHON;
+
+ ASSERT_LOCK_PYTHON;
+ return v;
+}
+
+
static PyObject *
pysvrv_item(PySVRV *self, int index)
{
@@ -1954,6 +1974,31 @@
return status;
}
+static PyNumberMethods pysvrv_as_number = {
+ 0, /*nb_add*/
+ 0, /*nb_subtract*/
+ 0, /*nb_multiply*/
+ 0, /*nb_divide*/
+ 0, /*nb_remainder*/
+ 0, /*nb_divmod*/
+ 0, /*nb_power*/
+ 0, /*nb_negative*/
+ 0, /*nb_positive*/
+ 0, /*nb_absolute*/
+ (inquiry)pysvrv_nonzero, /*nb_nonzero*/
+ 0, /*nb_invert*/
+ 0, /*nb_lshift*/
+ 0, /*nb_rshift*/
+ 0, /*nb_and*/
+ 0, /*nb_xor*/
+ 0, /*nb_or*/
+ 0, /*nb_coerce*/
+ 0, /*nb_int*/
+ 0, /*nb_long*/
+ 0, /*nb_float*/
+ 0, /*nb_oct*/
+ 0, /*nb_hex*/
+};
static PyMappingMethods pysvrv_as_mapping = {
(inquiry)pysvrv_length, /* mp_length */
@@ -1988,7 +2033,7 @@
(setattrfunc)pysvrv_setattr, /*tp_setattr*/
0, /*tp_compare*/
(reprfunc)pysvrv_repr, /*tp_repr*/
- 0, /*tp_as_number*/
+ &pysvrv_as_number, /*tp_as_number*/
&pysvrv_as_sequence, /*tp_as_sequence*/
&pysvrv_as_mapping, /*tp_as_mapping*/
0, /*tp_hash*/