Python bugs

Bjorn Pettersen bjorn at roguewave.com
Mon Nov 29 17:49:09 EST 1999


> Skip said:
>  > I believe os.environ is a class to allow constructs like
>  > 
>  >     os.environ["FOO"] = "PYTHON"
>  > 
>  > to work like
>  > 
>  >     os.putenv("FOO", "PYTHON")
> 
> Bjorn Pettersen writes:
>  > Which is a good thing, but shouldn't preclude it from 
> being used as a
>  > dictionary in the update statement (although the fix 
> probably have to be to
>  > Dict.update rahter than os.environ).
> 
>   Very much so.  os.environ does exactly the right thing; 
> {}.update is 
> simply too simple.  ;-)  Shouldn't be had to fix, given a little
> motivation.  The implementation should retain the special case of
> "real" dictionaries, but also implement a generic version that uses
> the mapping API.
>   I'm sure Guido would be glad to receive a patch.  ;-)  ;-)

I'm sure he would ;-)  Unfortunately my skills at writing Python C code are
rather lacking (that's what we have swig for, right :-)

Anyway, here's my initial attempt, which shouldn't be considered more than
pseudo code.  If someone with more knowledge in this area wouldn't mind
spending some more time on this, I'm sure it would be educational (at least
for me <wink>)

-- bjorn

dict_update(mp, args)
      register dictobject *mp;
      PyObject *args;
{
	register int i;
	dictobject *other;
	dictentry *entry;

	if (other == mp)
		goto done; /* a.update(a); nothing to do */
	
	if (!PyArg_Parse(args, "O!", &PyDict_Type, &other)) {
	  /* general case. when other != type({}) */
	  PyObject* other_keys = PyObject_CallMethod(args, "keys", NULL);
	  int keys_length = PyList_Size(other_keys);
	  int i;
	  for (i=0; i<keys_length; i++) {
		PyObject* key = PyList_GetItem(other_keys, i);

		/* except you can't use PyObject_CallMethod on 'special'
names */
		/* I couldn't find Py_BuildValue in the index... */

		PyObject* val = PyObject_CallMethod(args, "__getitem__",
Py_BuildValue(???, key));

		/* Can you use PyDict_SetItem with a dictobject? */
		PyDict_SetItem((PyObject*)mp, key, val);
		
		/* I'm assuming both the key and val objects need to have
their ref counts incremented(?) */
	  }
		
	} else {

	  /* Do one big resize at the start, rather than incrementally
		 resizing as we insert new items.  Expect that there will be
		 no (or few) overlapping keys. */
	  if ((mp->ma_fill + other->ma_used)*3 >= mp->ma_size*2) {
		if (dictresize(mp, (mp->ma_used + other->ma_used)*3/2) != 0)
		  return NULL;
	  }
	  for (i = 0; i < other->ma_size; i++) {
		entry = &other->ma_table[i];
		if (entry->me_value != NULL) {
		  Py_INCREF(entry->me_key);
		  Py_INCREF(entry->me_value);
		  insertdict(mp, entry->me_key, entry->me_hash,
					 entry->me_value);
		}
	  }
	}
  done:
	Py_INCREF(Py_None);
	return Py_None;
}




More information about the Python-list mailing list