[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*/