[Python-Dev] Usefulness of binary compatibility accross Python versions?

Random832 random832 at fastmail.com
Wed Dec 20 15:17:57 EST 2017


On Mon, Dec 18, 2017, at 05:23, Antoine Pitrou wrote:
> On Sun, 17 Dec 2017 21:07:02 -0500
> Random832 <random832 at fastmail.com> wrote:
> > 
> > Is there any practical for of having the flag off for one slot and on
> > for another slot that's been added later?
> > 
> > Could this be replaced (that is, a slot for such a thing added before
> > it's too late) with a simple counter that goes up with each version, and
> > any "unused" slot should have NULL or some other sentinel value?
> 
> Any replacement here would break binary compatibility, which is what
> those flags are precisely meant to avoid.

I meant replacing the mechanism for new fields, rather than existing ones.

> > If it
> > really is important to have the flags themselves, just add another set
> > of flags - Py_TPFLAGS_HAVE_MORE_FLAGS.
> 
> Yes, we could... but it's more complication again.

Hmm, maybe that could be eased with macros...


/* Doing this preprocessor trick because if we used a ternary
 * operator, dummy macros needed to prevent compile errors may
 * become an attractive nuisance */
#define Py_TPFLAG_CHK(tp, flagname) \
	Py__TPFCHK_##flagname(tp, flagname)
#define Py__TPFCHK_OLD(tp, flagname) \
	((tp).tp_flags & Py_TPFLAGS_##flagname)
#define Py__TPFCHK_NEW(tp, flagname) \
	((tp).tp_flags & Py_TPFLAGS_TPFLAGVER \
	 && (tp).tp_flagver >= Py_TPFLAGVER_##flagname \
	 && Py_TPFLAGCHK_##flagname(tp))

#define Py__TPFCHK_HEAPTYPE  Py__TPFCHK_OLD
#define Py_TPFLAGS_HEAPTYPE (1UL<<9)

#define Py__TPFCHK_TPFLAGVER Py__TPFCHK_OLD
#define Py_TPFLAGS_TPFLAGVER (1UL<<31)

#define Py__TPFCHK_NEWFLD Py__TPFCHK_NEW
#define Py_TPFLAGVER_NEWFLD 32
#define Py_TPFLAGCHK_NEWFLD(tp) ((tp).tp_newfld != NULL)

So to check heap type you get Py_TPFLAG_CHK(tp, HEAPTYPE)
((tp).tp_flags & (1UL<<9))

And to check newfld1 you get Py_TPFLAG_CHK(tp, NEWFLD)
((tp).tp_flags & (1UL<<31) && (tp).tp_flagver >= 32 && ((tp).tp_newfld != ((void *)0)))

Or in a "more flags" scenario:

#define Py__TPFCHK_NEW(tp, flagname) \
	((tp).tp_flags & Py_TPFLAGS_TPMOREFLAGS \
	 && (tp).tp_moreflag & PY_TPMOREFLAGS_##flagname)


More information about the Python-Dev mailing list