float atime/mtime/ctime - a bad idea?

I just found a place in my own code that broke because stat now returns floats for mtime etc. I was using a Zope "OIBTree" object, which is a dict-like extension type mapping strings to ints; it very reasonbly doesn't like it if you assign a float to it. I'm not say that because *my* code breaks, this is a bad feature. But I am worried that we'll find more programs using external data types that won't accept floats (I'm thinking of Numpy arrays), and I'm now not so sure if this is acceptable breakage... Apparently the fact that it "works" on the Mac isn't really a great proof. Maybe we can introduce a variant of the stat() function that returns floats, or alternative field names that are only available when using attributes (not when using the tuple-ish API)? --Guido van Rossum (home page: http://www.python.org/~guido/)

"GvR" == Guido van Rossum <guido@python.org> writes:
GvR> Maybe we can introduce a variant of the stat() function that GvR> returns floats, or alternative field names that are only GvR> available when using attributes (not when using the tuple-ish GvR> API)? +1 on the latter idea. Since the st_mtime, st_atime, and st_ctime attributes, and the tuple-ish API are documented as returning ints, I think you shouldn't change that. Provide different field names for float values, e.g. f_mtime, f_ctime, f_atime, or maybe just mtime, atime, and ctime... ? -Barry

"MvL" == Martin v Loewis <martin@v.loewis.de> writes:
>> +1 on the latter idea. Since the st_mtime, st_atime, and >> st_ctime attributes, and the tuple-ish API are documented as >> returning ints, I think you shouldn't change that. Provide >> different field names for float values, e.g. f_mtime, f_ctime, >> f_atime, or maybe just mtime, atime, and ctime... ? MvL> The previous suggestion was st_mtimef, st_ctimef, ... Names which differ by one character at the end of the name are error prone, IME. Plus it makes stuff like dabbrev-expand harder to use. :) -Barry

martin@v.loewis.de (Martin v. Loewis):
The previous suggestion was st_mtimef, st_ctimef, ...
For some reason, st_fmtime and st_fctime seem easier to read and pronounce to me. Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+

BAW> Provide different field names for float values, e.g. f_mtime, BAW> f_ctime, f_atime, or maybe just mtime, atime, and ctime... ? Martin> The previous suggestion was st_mtimef, st_ctimef, ... Why not simply provide an alternative method, os.fstat()? Seems cleaner to me. The field names are hard enough to remember as it is... Skip

BAW> Provide different field names for float values, e.g. f_mtime, BAW> f_ctime, f_atime, or maybe just mtime, atime, and ctime... ? Martin> The previous suggestion was st_mtimef, st_ctimef, ... Skip> Why not simply provide an alternative method, os.fstat()? Seems Skip> cleaner to me. The field names are hard enough to remember as it Skip> is... Doh! Engage brain before hitting the <send> key... Of course there is already an fstat() function. I'll shut up now. Skip

Skip Montanaro <skip@pobox.com> writes:
Martin> The previous suggestion was st_mtimef, st_ctimef, ...
Why not simply provide an alternative method, os.fstat()?
Because os.fstat already exists, and also has the option of either returning floating point time stamps or integer time stamps - just like os.stat and os.lstat. Regards, Martin

Guido van Rossum <guido@python.org> writes:
In this case, could you fix your code by truncating/rounding, or by using a different container?
Assuming that in all cases of breakage it would be possible to easily "fix" the code somehow, I'd like to have a migration plan, following PEP 5: I.e. together with adding a new feature for float time stamps, we should deprecate the old feature (of int time stamps) - perhaps not right now, but as a pending deprecation. Then, after some time, we should drop the old feature and continue with just the new one. So I'd like to see a solution which does not look ugly when the deprecated feature is gone and just the new feature stays. Perhaps a flag "times_are_float" would be the right approach? N: flag defaults to False, users need to ask for floats explicitly N+1: omitting the flag is deprecated N+2: flag defaults to True, users need to ask for ints explicitly N+5: the flag is removed There are variations to this plan, adding a phase where it is an error to omit the flag, or where a pending deprecation is added. Regards, Martin

I added int() around the st_mtime reference, because there's no "OFBTree" data type, and because second resolution was good enough.
Agreed, but I don't like adding and then deleting a "temporary" new argument to stat() and fstat(). In this particular case, I think having a global flag should be good enough. We can easily rig the standard library not to depend on its value. It should be settable by calling a function, e.g. os.stat_times(int) or os.stat_times(float) If you think passing the actual type objects is too cute, we can call it stat_float_times() and pass a bool. Without an argument it could return the current status, with the twist that if the platform doesn't support float times it will always return int. Or maybe we can make it return the precision. --Guido van Rossum (home page: http://www.python.org/~guido/)

"GvR" == Guido van Rossum <guido@python.org> writes:
GvR> In this particular case, I think having a global flag should GvR> be good enough. We can easily rig the standard library not GvR> to depend on its value. It should be settable by calling a GvR> function, e.g. GvR> os.stat_times(int) GvR> or GvR> os.stat_times(float) GvR> If you think passing the actual type objects is too cute, we GvR> can call it stat_float_times() and pass a bool. So then why not just make this an optional argument flag on the os.stat() call itself? That way you could migrate some code at a different rate than other code (a global flag might be fine for your application, but break some 3rd party library you're using). -Barry

Barry:
And Kevin:
Please don't! The global setting isn't sufficient since many of us access many 3rd party modules.
Most code doesn't care; most 3rd party code will work either way. Martin proposed adding an option to the stat() call itself first, but that seems a rather heavy-handed way to ensure backwards compatibility for such a very rare situation. If you are using a 3rd party library that breaks due to the floats, you can disable the floats until you've got time to fix it. You can live with the ints a little longer. --Guido van Rossum (home page: http://www.python.org/~guido/)

"GvR" == Guido van Rossum <guido@python.org> writes:
GvR> Most code doesn't care; most 3rd party code will work either GvR> way. Martin proposed adding an option to the stat() call GvR> itself first, but that seems a rather heavy-handed way to GvR> ensure backwards compatibility for such a very rare GvR> situation. GvR> If you are using a 3rd party library that breaks due to the GvR> floats, you can disable the floats until you've got time to GvR> fix it. You can live with the ints a little longer. But you may end up ping ponging between floats and ints as you import new libraries into your app. If, as you surmise, most code won't care, then that won't be a real problem. But if it is, you might see code like this: ostate = os.stat_times() os.stat_times(True) try: # do something requiring float times finally: os.stat_times(ostate) Maybe it won't matter in practice, but global state like that always tickles the gag reflex in me. ;) -Barry

barry@python.org (Barry A. Warsaw) writes:
With Guido's most recent suggestion (put ints into the tuple), it is even more likely that nothing will break if floats are activated (we should investigate the two known incidents to find out whether they were using the tuple interface).
# do something requiring float times
I think this is a central point here: Why would anything *require* float times? If the system does not support subsecond timestamps, or Python does not expose that (e.g. Windows), you will get floats, but you won't get fractions of a second.
Maybe it won't matter in practice, but global state like that always tickles the gag reflex in me. ;)
I completely agree about reflexes and general feelings. However, we assume that this indeed won't matter in practice. Regards, Martin

"MvL" == Martin v Loewis <martin@v.loewis.de> writes:
>> But you may end up ping ponging between floats and ints as you >> import new libraries into your app. If, as you surmise, most >> code won't care, then that won't be a real problem. MvL> With Guido's most recent suggestion (put ints into the MvL> tuple), it is even more likely that nothing will break if MvL> floats are activated (we should investigate the two known MvL> incidents to find out whether they were using the tuple MvL> interface). Cool, that sounds like the best compromise. -Barry

I was using the tuple interface -- this code needed to work under Python 2.1.
I completely agree about reflexes and general feelings. However, we assume that this indeed won't matter in practice.
Amen. --Guido van Rossum (home page: http://www.python.org/~guido/)

Maybe it won't matter in practice, but global state like that always tickles the gag reflex in me. ;)
Believe me, mine too -- if I thought it was a real problem. But I don't. --Guido van Rossum (home page: http://www.python.org/~guido/)

Guido van Rossum <guido@python.org> writes:
Sounds good. Unless I hear otherwise, I'll add stat_float_times(bool). That still leaves the question of a migration plan, assuming that users, in general, would appreciate to silently get subsecond timestamps where possible. Here is a proposal: - 2.3: just add stat_float_times. In the documentation, warn that the value will change in the future. - 2.4: make stat_float_times(True) the default. Applications that break would need to add stat_float_times(False) in a central place. This has no phase were a warning is emitted, but any scheme that adds a warning means that the user first has to add something (to silence the warning), and then to remove something (when the default changes - although the option might stay forever). Regards, Martin

On 16 Oct 2002, Martin v. Loewis wrote:
Please don't! The global setting isn't sufficient since many of us access many 3rd party modules. Why not simply create properies that return the int/float versions from the same structure and store the float versions? That seems to be an instant win for all use-cases. My 2e-2cents, -Kevin -- -- Kevin Jacobs The OPAL Group - Enterprise Systems Architect Voice: (216) 986-0710 x 19 E-mail: jacobs@theopalgroup.com Fax: (216) 986-0714 WWW: http://www.theopalgroup.com

Kevin Jacobs <jacobs@penguin.theopalgroup.com> writes:
Why is that insufficient? As long as you have modules that require int time stamps, you can't switch to float time stamps. If you find you are using such a module, tell the module author about that, and wait for a corrected module.
Why not simply create properies that return the int/float versions from the same structure and store the float versions?
How can the property know whether to return an int or a float? Regards, Martin

On 16 Oct 2002, Martin v. Loewis wrote:
Why break all modules when only one needs the old behavior? Think about how from __future__ import is set up.
By name -- anyone who wants a floating point value can request fst_mtime vs. st_mtime, or whatever. -Kevin -- Kevin Jacobs The OPAL Group - Enterprise Systems Architect Voice: (216) 986-0710 x 19 E-mail: jacobs@theopalgroup.com Fax: (216) 986-0714 WWW: http://www.theopalgroup.com

Why break all modules when only one needs the old behavior? Think about how from __future__ import is set up.
Because this is IMO a *very* small change, for which I don't want to invoke such heavy guns. --Guido van Rossum (home page: http://www.python.org/~guido/)

Kevin Jacobs <jacobs@penguin.theopalgroup.com> writes:
Why break all modules when only one needs the old behavior? Think about how from __future__ import is set up.
Nothing will break; that's the entire purpose of this change.
By name -- anyone who wants a floating point value can request fst_mtime vs. st_mtime, or whatever.
Been there, done that (posixmodule.c 2.254). Please understand that, after the transitional phase, fst_mtime is what everyone will use. This is plain ugly, since it is inconsistent with the names of all other fields. So all we need to do is to accommodate the transition, and we do that with Guido's proposed change. Regards, Martin

Sounds good. I wonder if we could let the tuple-ish interface return ints forever (or until it's no longer supported). --Guido van Rossum (home page: http://www.python.org/~guido/)

Guido van Rossum <guido@python.org> writes:
I wonder if we could let the tuple-ish interface return ints forever (or until it's no longer supported).
That would not be easy to implement. The structseq type does not support unnamed sequence members (yet), which we'ld need: the int members would have only indices, and the float members only names. It probably could be made work by allowing NULL names in a PyStructSequence_Field. I'll try to do this. Regards, Martin

That sounds good to me. Or you could "subclass" the PyStructSequence class with something that special-cases the st_?time attributes. --Guido van Rossum (home page: http://www.python.org/~guido/)

Guido van Rossum wrote:
If you're suggesting a new API, why not have it return one of the new datetime objects ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/

Martin v. Löwis wrote:
AFAIK, PythonLabs is working on this. Even though development seems to have stalled recently... See CVS:/python/nondist/sandbox/datetime/ -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/

If you're suggesting a new API, why not have it return one of the new datetime objects ?
That would require much more changes to the user code to use the new feature. And in many cases a basic timestamp is just what you need -- all you usually do is comparing them, occasionally printing them, and both are done just as easily using the int or float form. --Guido van Rossum (home page: http://www.python.org/~guido/)

"GvR" == Guido van Rossum <guido@python.org> writes:
GvR> Maybe we can introduce a variant of the stat() function that GvR> returns floats, or alternative field names that are only GvR> available when using attributes (not when using the tuple-ish GvR> API)? +1 on the latter idea. Since the st_mtime, st_atime, and st_ctime attributes, and the tuple-ish API are documented as returning ints, I think you shouldn't change that. Provide different field names for float values, e.g. f_mtime, f_ctime, f_atime, or maybe just mtime, atime, and ctime... ? -Barry

"MvL" == Martin v Loewis <martin@v.loewis.de> writes:
>> +1 on the latter idea. Since the st_mtime, st_atime, and >> st_ctime attributes, and the tuple-ish API are documented as >> returning ints, I think you shouldn't change that. Provide >> different field names for float values, e.g. f_mtime, f_ctime, >> f_atime, or maybe just mtime, atime, and ctime... ? MvL> The previous suggestion was st_mtimef, st_ctimef, ... Names which differ by one character at the end of the name are error prone, IME. Plus it makes stuff like dabbrev-expand harder to use. :) -Barry

martin@v.loewis.de (Martin v. Loewis):
The previous suggestion was st_mtimef, st_ctimef, ...
For some reason, st_fmtime and st_fctime seem easier to read and pronounce to me. Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+

BAW> Provide different field names for float values, e.g. f_mtime, BAW> f_ctime, f_atime, or maybe just mtime, atime, and ctime... ? Martin> The previous suggestion was st_mtimef, st_ctimef, ... Why not simply provide an alternative method, os.fstat()? Seems cleaner to me. The field names are hard enough to remember as it is... Skip

BAW> Provide different field names for float values, e.g. f_mtime, BAW> f_ctime, f_atime, or maybe just mtime, atime, and ctime... ? Martin> The previous suggestion was st_mtimef, st_ctimef, ... Skip> Why not simply provide an alternative method, os.fstat()? Seems Skip> cleaner to me. The field names are hard enough to remember as it Skip> is... Doh! Engage brain before hitting the <send> key... Of course there is already an fstat() function. I'll shut up now. Skip

Skip Montanaro <skip@pobox.com> writes:
Martin> The previous suggestion was st_mtimef, st_ctimef, ...
Why not simply provide an alternative method, os.fstat()?
Because os.fstat already exists, and also has the option of either returning floating point time stamps or integer time stamps - just like os.stat and os.lstat. Regards, Martin

Guido van Rossum <guido@python.org> writes:
In this case, could you fix your code by truncating/rounding, or by using a different container?
Assuming that in all cases of breakage it would be possible to easily "fix" the code somehow, I'd like to have a migration plan, following PEP 5: I.e. together with adding a new feature for float time stamps, we should deprecate the old feature (of int time stamps) - perhaps not right now, but as a pending deprecation. Then, after some time, we should drop the old feature and continue with just the new one. So I'd like to see a solution which does not look ugly when the deprecated feature is gone and just the new feature stays. Perhaps a flag "times_are_float" would be the right approach? N: flag defaults to False, users need to ask for floats explicitly N+1: omitting the flag is deprecated N+2: flag defaults to True, users need to ask for ints explicitly N+5: the flag is removed There are variations to this plan, adding a phase where it is an error to omit the flag, or where a pending deprecation is added. Regards, Martin

I added int() around the st_mtime reference, because there's no "OFBTree" data type, and because second resolution was good enough.
Agreed, but I don't like adding and then deleting a "temporary" new argument to stat() and fstat(). In this particular case, I think having a global flag should be good enough. We can easily rig the standard library not to depend on its value. It should be settable by calling a function, e.g. os.stat_times(int) or os.stat_times(float) If you think passing the actual type objects is too cute, we can call it stat_float_times() and pass a bool. Without an argument it could return the current status, with the twist that if the platform doesn't support float times it will always return int. Or maybe we can make it return the precision. --Guido van Rossum (home page: http://www.python.org/~guido/)

"GvR" == Guido van Rossum <guido@python.org> writes:
GvR> In this particular case, I think having a global flag should GvR> be good enough. We can easily rig the standard library not GvR> to depend on its value. It should be settable by calling a GvR> function, e.g. GvR> os.stat_times(int) GvR> or GvR> os.stat_times(float) GvR> If you think passing the actual type objects is too cute, we GvR> can call it stat_float_times() and pass a bool. So then why not just make this an optional argument flag on the os.stat() call itself? That way you could migrate some code at a different rate than other code (a global flag might be fine for your application, but break some 3rd party library you're using). -Barry

Barry:
And Kevin:
Please don't! The global setting isn't sufficient since many of us access many 3rd party modules.
Most code doesn't care; most 3rd party code will work either way. Martin proposed adding an option to the stat() call itself first, but that seems a rather heavy-handed way to ensure backwards compatibility for such a very rare situation. If you are using a 3rd party library that breaks due to the floats, you can disable the floats until you've got time to fix it. You can live with the ints a little longer. --Guido van Rossum (home page: http://www.python.org/~guido/)

"GvR" == Guido van Rossum <guido@python.org> writes:
GvR> Most code doesn't care; most 3rd party code will work either GvR> way. Martin proposed adding an option to the stat() call GvR> itself first, but that seems a rather heavy-handed way to GvR> ensure backwards compatibility for such a very rare GvR> situation. GvR> If you are using a 3rd party library that breaks due to the GvR> floats, you can disable the floats until you've got time to GvR> fix it. You can live with the ints a little longer. But you may end up ping ponging between floats and ints as you import new libraries into your app. If, as you surmise, most code won't care, then that won't be a real problem. But if it is, you might see code like this: ostate = os.stat_times() os.stat_times(True) try: # do something requiring float times finally: os.stat_times(ostate) Maybe it won't matter in practice, but global state like that always tickles the gag reflex in me. ;) -Barry

barry@python.org (Barry A. Warsaw) writes:
With Guido's most recent suggestion (put ints into the tuple), it is even more likely that nothing will break if floats are activated (we should investigate the two known incidents to find out whether they were using the tuple interface).
# do something requiring float times
I think this is a central point here: Why would anything *require* float times? If the system does not support subsecond timestamps, or Python does not expose that (e.g. Windows), you will get floats, but you won't get fractions of a second.
Maybe it won't matter in practice, but global state like that always tickles the gag reflex in me. ;)
I completely agree about reflexes and general feelings. However, we assume that this indeed won't matter in practice. Regards, Martin

"MvL" == Martin v Loewis <martin@v.loewis.de> writes:
>> But you may end up ping ponging between floats and ints as you >> import new libraries into your app. If, as you surmise, most >> code won't care, then that won't be a real problem. MvL> With Guido's most recent suggestion (put ints into the MvL> tuple), it is even more likely that nothing will break if MvL> floats are activated (we should investigate the two known MvL> incidents to find out whether they were using the tuple MvL> interface). Cool, that sounds like the best compromise. -Barry

I was using the tuple interface -- this code needed to work under Python 2.1.
I completely agree about reflexes and general feelings. However, we assume that this indeed won't matter in practice.
Amen. --Guido van Rossum (home page: http://www.python.org/~guido/)

Maybe it won't matter in practice, but global state like that always tickles the gag reflex in me. ;)
Believe me, mine too -- if I thought it was a real problem. But I don't. --Guido van Rossum (home page: http://www.python.org/~guido/)

Guido van Rossum <guido@python.org> writes:
Sounds good. Unless I hear otherwise, I'll add stat_float_times(bool). That still leaves the question of a migration plan, assuming that users, in general, would appreciate to silently get subsecond timestamps where possible. Here is a proposal: - 2.3: just add stat_float_times. In the documentation, warn that the value will change in the future. - 2.4: make stat_float_times(True) the default. Applications that break would need to add stat_float_times(False) in a central place. This has no phase were a warning is emitted, but any scheme that adds a warning means that the user first has to add something (to silence the warning), and then to remove something (when the default changes - although the option might stay forever). Regards, Martin

On 16 Oct 2002, Martin v. Loewis wrote:
Please don't! The global setting isn't sufficient since many of us access many 3rd party modules. Why not simply create properies that return the int/float versions from the same structure and store the float versions? That seems to be an instant win for all use-cases. My 2e-2cents, -Kevin -- -- Kevin Jacobs The OPAL Group - Enterprise Systems Architect Voice: (216) 986-0710 x 19 E-mail: jacobs@theopalgroup.com Fax: (216) 986-0714 WWW: http://www.theopalgroup.com

Kevin Jacobs <jacobs@penguin.theopalgroup.com> writes:
Why is that insufficient? As long as you have modules that require int time stamps, you can't switch to float time stamps. If you find you are using such a module, tell the module author about that, and wait for a corrected module.
Why not simply create properies that return the int/float versions from the same structure and store the float versions?
How can the property know whether to return an int or a float? Regards, Martin

On 16 Oct 2002, Martin v. Loewis wrote:
Why break all modules when only one needs the old behavior? Think about how from __future__ import is set up.
By name -- anyone who wants a floating point value can request fst_mtime vs. st_mtime, or whatever. -Kevin -- Kevin Jacobs The OPAL Group - Enterprise Systems Architect Voice: (216) 986-0710 x 19 E-mail: jacobs@theopalgroup.com Fax: (216) 986-0714 WWW: http://www.theopalgroup.com

Why break all modules when only one needs the old behavior? Think about how from __future__ import is set up.
Because this is IMO a *very* small change, for which I don't want to invoke such heavy guns. --Guido van Rossum (home page: http://www.python.org/~guido/)

Kevin Jacobs <jacobs@penguin.theopalgroup.com> writes:
Why break all modules when only one needs the old behavior? Think about how from __future__ import is set up.
Nothing will break; that's the entire purpose of this change.
By name -- anyone who wants a floating point value can request fst_mtime vs. st_mtime, or whatever.
Been there, done that (posixmodule.c 2.254). Please understand that, after the transitional phase, fst_mtime is what everyone will use. This is plain ugly, since it is inconsistent with the names of all other fields. So all we need to do is to accommodate the transition, and we do that with Guido's proposed change. Regards, Martin

Sounds good. I wonder if we could let the tuple-ish interface return ints forever (or until it's no longer supported). --Guido van Rossum (home page: http://www.python.org/~guido/)

Guido van Rossum <guido@python.org> writes:
I wonder if we could let the tuple-ish interface return ints forever (or until it's no longer supported).
That would not be easy to implement. The structseq type does not support unnamed sequence members (yet), which we'ld need: the int members would have only indices, and the float members only names. It probably could be made work by allowing NULL names in a PyStructSequence_Field. I'll try to do this. Regards, Martin

That sounds good to me. Or you could "subclass" the PyStructSequence class with something that special-cases the st_?time attributes. --Guido van Rossum (home page: http://www.python.org/~guido/)

Guido van Rossum wrote:
If you're suggesting a new API, why not have it return one of the new datetime objects ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/

Martin v. Löwis wrote:
AFAIK, PythonLabs is working on this. Even though development seems to have stalled recently... See CVS:/python/nondist/sandbox/datetime/ -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/

If you're suggesting a new API, why not have it return one of the new datetime objects ?
That would require much more changes to the user code to use the new feature. And in many cases a basic timestamp is just what you need -- all you usually do is comparing them, occasionally printing them, and both are done just as easily using the int or float form. --Guido van Rossum (home page: http://www.python.org/~guido/)
participants (8)
-
barry@python.org
-
Greg Ewing
-
Guido van Rossum
-
Kevin Jacobs
-
loewis@informatik.hu-berlin.de
-
M.-A. Lemburg
-
martin@v.loewis.de
-
Skip Montanaro