*.pyc
+__pycache__/
/COPYING
/MANIFEST
## Debian.
include debian/rules debian/control debian/changelog
include debian/copyright debian/compat debian/source/format
+include debian/*.install
FREEOBJ(me);
}
+#ifdef PY3
+ static int rbuf_pygetbuf(PyObject *me, Py_buffer *vw, int f)
+ {
+ buf *b = BUF_B(me);
+ return (PyBuffer_FillInfo(vw, me, BCUR(b), BLEFT(b), 1, f));
+ }
+#else
static Py_ssize_t rbuf_pysegcount(PyObject *me, Py_ssize_t *nn)
{ if (nn) *nn = BSZ(BUF_B(me)); return (1); }
static Py_ssize_t rbuf_pyreadbuf(PyObject *me, Py_ssize_t seg, void **q)
{ assert(seg == 0); *q = BCUR(BUF_B(me)); return (BLEFT(BUF_B(me))); }
+#endif
static PyObject *rbmeth_skip(PyObject *me, PyObject *arg)
{
};
static const PyBufferProcs rbuf_pybuffer = {
+#ifdef PY3
+ rbuf_pygetbuf, /* @bf_getbuffer@ */
+ 0, /* @bf_releasebuffer@ */
+#else
rbuf_pyreadbuf, /* @bf_getreadbuffer@ */
0, /* @bf_getwritebuffer@ */
rbuf_pysegcount, /* @bf_getsegcount@ */
0 /* @bf_getcharbuffer@ */
+#endif
};
static const PyTypeObject rbuf_pytype_skel = {
return ((PyObject *)me);
}
+#ifdef PY3
+ static int wbuf_pygetbuf(PyObject *me, Py_buffer *vw, int f)
+ {
+ buf *b = BUF_B(me);
+ if (PyBuffer_FillInfo(vw, me, BBASE(b), BLEN(b), 0, f)) return (-1);
+ BUF_LK(me)++; return (0);
+ }
+ static void wbuf_pyrlsbuf(PyObject *me, Py_buffer *vw)
+ { BUF_LK(me)--; }
+#else
static Py_ssize_t wbuf_pysegcount(PyObject *me, Py_ssize_t *nn)
{ if (nn) *nn = BLEN(BUF_B(me)); return (1); }
static Py_ssize_t wbuf_pyreadbuf(PyObject *me, Py_ssize_t seg, void **q)
{ assert(seg == 0); *q = BBASE(BUF_B(me)); return (BLEN(BUF_B(me))); }
+#endif
static PyObject *wbmeth_zero(PyObject *me, PyObject *arg)
{
};
static const PyBufferProcs wbuf_pybuffer = {
+#ifdef PY3
+ wbuf_pygetbuf, /* @bf_getbuffer@ */
+ wbuf_pyrlsbuf /* @bf_releasebuffer@ */
+#else
wbuf_pyreadbuf, /* @bf_getreadbuffer@ */
0, /* @bf_getwritebuffer@ */
wbuf_pysegcount, /* @bf_getsegcount@ */
0 /* @bf_getcharbuffer@ */
+#endif
};
static const PyTypeObject wbuf_pytype_skel = {
#if defined(CACHE_HASH) || PY_VERSION_HEX >= 0x02030000
x->ob_shash = -1;
#endif
+#ifdef PY2
x->ob_sstate = SSTATE_NOT_INTERNED;
+#endif
return ((PyObject *)x);
}
PyObject *rc = 0;
if (i < 0 || i >= BIN_LEN(me)) IXERR("out of range");
+#ifdef PY3
+ rc = getulong(BIN_PTR(me)[i]&0xff);
+#else
rc = bytestring_pywrap(BIN_PTR(me) + i, 1);
+#endif
end:
return (rc);
}
if (i < 0) i += BIN_LEN(me);
rc = bytestring_pyitem(me, i);
} else if (PySlice_Check(ix)) {
- if (PySlice_GetIndicesEx((PySliceObject *)ix, BIN_LEN(me),
- &i, &j, &k, &n))
+ if (PySlice_GetIndicesEx(PY23((PySliceObject *), NOTHING)ix,
+ BIN_LEN(me), &i, &j, &k, &n))
return (0);
if (k == 1) return bytestring_pyslice(me, i, j);
rc = bytestring_pywrap(0, n);
0, /* @nb_add@ */
0, /* @nb_subtract@ */
0, /* @nb_multiply@ */
+#ifdef PY2
0, /* @nb_divide@ */
+#endif
0, /* @nb_remainder@ */
0, /* @nb_divmod@ */
0, /* @nb_power@ */
#endif
}
-EXPORT void init_base(void)
+#ifdef PY3
+static PyModuleDef moddef = {
+ PyModuleDef_HEAD_INIT,
+ "catacomb._base", /* @m_name@ */
+ "Low-level module for Catacomb bindings. Use `catacomb' instead.",
+ /* @m_doc@ */
+ 0, /* @m_size@ */
+ 0, /* @m_methods@ */
+ 0, /* @m_slots@ */
+ 0, /* @m_traverse@ */
+ 0, /* @m_clear@ */
+ 0 /* @m_free@ */
+};
+#endif
+
+EXPORT PyMODINIT_FUNC PY23(init_base, PyInit__base)(void)
{
PyObject *mod;
INIT_MODULES;
INITTYPE(thingtab, root);
init_random();
+#ifdef PY3
+ moddef.m_methods = donemethods();
+ mod = PyModule_Create(&moddef);
+#else
mod = Py_InitModule("catacomb._base", donemethods());
+#endif
INSERT_MODULES;
INSERT("_MiscTable", thingtab_pytype);
INSERT("smallprimes", smallprimes());
+#ifdef PY3
+ return (mod);
+#endif
}
/*----- That's all, folks -------------------------------------------------*/
else: pass # can't do this.
_sys.setdlopenflags(_dlflags)
-import _base
+if _sys.version_info >= (3,): from . import _base
+else: import _base
if _odlflags >= 0:
_sys.setdlopenflags(_odlflags)
lostexchook = default_lostexchook
## Text/binary conversions.
-def _bin(s): return s
+if _sys.version_info >= (3,):
+ def _bin(s): return s.encode('iso8859-1')
+else:
+ def _bin(s): return s
## Iterating over dictionaries.
-def _iteritems(dict): return dict.iteritems()
-def _itervalues(dict): return dict.itervalues()
+if _sys.version_info >= (3,):
+ def _iteritems(dict): return dict.items()
+ def _itervalues(dict): return dict.values()
+else:
+ def _iteritems(dict): return dict.iteritems()
+ def _itervalues(dict): return dict.itervalues()
## The built-in bignum type.
-_long = long
+try: long
+except NameError: _long = int
+else: _long = long
## How to fix a name back into the right identifier. Alas, the rules are not
## consistent.
_pp_commas(pp, p, items)
###--------------------------------------------------------------------------
+### Mappings.
+
+if _sys.version_info >= (3,):
+ class _tmp:
+ def __str__(me): return '%s(%r)' % (type(me).__name__, list(me))
+ __repr__ = __str__
+ def _repr_pretty_(me, pp, cyclep):
+ ind = _pp_bgroup_tyname(pp, me, '([')
+ _pp_commas(pp, pp.pretty, me)
+ pp.end_group(ind, '])')
+ _augment(_base._KeyView, _tmp)
+ _augment(_base._ValueView, _tmp)
+ _augment(_base._ItemView, _tmp)
+
+###--------------------------------------------------------------------------
### Bytestrings.
class _tmp:
def fromhex(x):
return ByteString(_unhexify(x))
fromhex = staticmethod(fromhex)
- def hex(me): return _hexify(me)
- __hex__ = hex
+ if _sys.version_info >= (3,):
+ def hex(me): return _hexify(me).decode()
+ else:
+ def hex(me): return _hexify(me)
+ __hex__ = hex
def __repr__(me):
return 'bytes(%r)' % me.hex()
_augment(ByteString, _tmp)
def __rtruediv__(me, you):
n, d = _split_rat(you)
return type(me)(me._d*n, me._n*d)
- __div__ = __truediv__
- __rdiv__ = __rtruediv__
+ if _sys.version_info < (3,):
+ __div__ = __truediv__
+ __rdiv__ = __rtruediv__
def _order(me, you, op):
n, d = _split_rat(you)
return op(me._n*d, n*me._d)
def __rtruediv__(me, you):
if isinstance(you, float): return you/_long(me)
else: return IntRat(you, me)
- __div__ = __truediv__
- __rdiv__ = __rtruediv__
+ if _sys.version_info < (3,):
+ __div__ = __truediv__
+ __rdiv__ = __rtruediv__
_repr_pretty_ = _pp_str
_augment(MP, _tmp)
def quadsolve(x, y): return x.reduce().quadsolve(y)
def __truediv__(me, you): return GFRat(me, you)
def __rtruediv__(me, you): return GFRat(you, me)
- __div__ = __truediv__
- __rdiv__ = __rtruediv__
+ if _sys.version_info < (3,):
+ __div__ = __truediv__
+ __rdiv__ = __rtruediv__
_repr_pretty_ = _pp_str
_augment(GF, _tmp)
import binascii as _B
import errno as _E
import os as _OS
-from cStringIO import StringIO as _StringIO
+import sys as _SYS
+
+if _SYS.version_info >= (3,): from io import StringIO as _StringIO
+else: from cStringIO import StringIO as _StringIO
import catacomb as _C
###--------------------------------------------------------------------------
### Python version portability.
-def _iterkeys(dict): return dict.iterkeys()
-def _itervalues(dict): return dict.itervalues()
-def _iteritems(dict): return dict.iteritems()
-
-def _bin(text): return text
-def _text(bin): return bin
+if _SYS.version_info >= (3,):
+ def _iterkeys(dict): return dict.keys()
+ def _itervalues(dict): return dict.values()
+ def _iteritems(dict): return dict.items()
+ def _bin(text): return text.encode(errors = "surrogateescape")
+ def _text(bin): return bin.decode(errors = "surrogateescape")
+else:
+ def _iterkeys(dict): return dict.iterkeys()
+ def _itervalues(dict): return dict.itervalues()
+ def _iteritems(dict): return dict.iteritems()
+ def _bin(text): return text
+ def _text(bin): return bin
_NUL = _bin('\0')
_CIPHER = _bin('cipher:')
Section: python
Priority: extra
XS-Python-Version: >= 2.6, << 2.8
+XS-Python3-Version: >= 3.0
Maintainer: Mark Wooding <mdw@distorted.org.uk>
Build-Depends: debhelper (>= 10), dh-python, pkg-config,
- python (>= 2.6.6-3~), python-all-dev,
+ python (>= 2.6.6-3~), python-all-dev, python3-all-dev,
mlib-dev (>= 2.4.99~), catacomb-dev (>= 2.5.0)
Standards-Version: 3.8.0
clarity of source code and portability more than performance.
.
This package allows the Catacomb library to be used in Python programs.
+
+Package: python3-catacomb
+Architecture: any
+XB-Python-Version: ${python3:Versions}
+Depends: ${shlibs:Depends}, ${python3:Depends}
+Provides: ${python3:Provides}
+Description: Python 3 bindings for the Catacomb cryptographic library.
+ Catacomb is a cryptographic library. It implements a large number of
+ encryption algorithms, hash functions, message authentication codes
+ and random number generators. It has a multi-precision maths library,
+ for implementing public key schemes such as RSA, DSA and Diffie-Hellman.
+ It contains rudimentary key-management tools.
+ .
+ The objective of Catacomb is to make a crypto library which is
+ relatively straightforward to audit for security. Its focus is on
+ clarity of source code and portability more than performance.
+ .
+ This package allows the Catacomb library to be used in Python 3 programs.
--- /dev/null
+debian/tmp/usr/bin
+debian/tmp/usr/share/man
+debian/tmp/usr/lib/python2.*
--- /dev/null
+debian/tmp/usr/lib/python3.*
#! /usr/bin/make -f
-%:; dh $@ --parallel --with python2
+%:; dh $@ --parallel --with python2,python3
-export PYTHONS := $(shell pyversions -r)
+export PYTHON := $(shell pyversions -d)
+export PYTHONS := $(shell pyversions -r && py3versions -r)
override_dh_auto_test:
dh_auto_test -- OPTS-check=-V
override_dh_auto_install:
- dh_auto_install -- prefix=/usr
+ dh_auto_install -- prefix=/usr \
+ $(foreach p,$(filter-out $(PYTHON),$(PYTHONS)), \
+ OPTS-install/$p="--install-scripts=/usr/bin-$p")
return (rc);
}
+#ifdef PY2
static PyObject *ecpt_pylong(PyObject *me)
{
ec p = EC_INIT;
EC_DESTROY(&p);
return (rc);
}
+#endif
static PyObject *ecpt_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
{
0, /* @nb_add@ */
0, /* @nb_subtract@ */
0, /* @nb_multiply@ */
+#ifdef PY2
0, /* @nb_divide@ */
+#endif
0, /* @nb_remainder@ */
0, /* @nb_divmod@ */
0, /* @nb_power@ */
0, /* @nb_and@ */
0, /* @nb_xor@ */
0, /* @nb_or@ */
+#ifdef PY2
0, /* @nb_coerce@ */
+#endif
ecpt_pyint, /* @nb_int@ */
- ecpt_pylong, /* @nb_long@ */
+ PY23(ecpt_pylong, 0), /* @nb_long@ */
0, /* @nb_float@ */
+#ifdef PY2
0, /* @nb_oct@ */
0, /* @nb_hex@ */
+#endif
0, /* @nb_inplace_add@ */
0, /* @nb_inplace_subtract@ */
0, /* @nb_inplace_multiply@ */
+#ifdef PY2
0, /* @nb_inplace_divide@ */
+#endif
0, /* @nb_inplace_remainder@ */
0, /* @nb_inplace_power@ */
0, /* @nb_inplace_lshift@ */
static const PyMemberDef ecpt_pymembers[] = {
#define MEMBERSTRUCT ecpt_pyobj
- MEMRNM(curve, T_OBJECT, ob_type, READONLY,
+ MEMRNM(curve, T_OBJECT, PY23(ob_type, ob_base.ob_type), READONLY,
"P.curve -> elliptic curve containing P")
#undef MEMBERSTRUCT
{ 0 }
ecpt_pyadd, /* @nb_add@ */
ecpt_pysub, /* @nb_subtract@ */
ecpt_pymul, /* @nb_multiply@ */
+#ifdef PY2
0, /* @nb_divide@ */
+#endif
0, /* @nb_remainder@ */
0, /* @nb_divmod@ */
0, /* @nb_power@ */
0, /* @nb_and@ */
0, /* @nb_xor@ */
0, /* @nb_or@ */
+#ifdef PY2
0, /* @nb_coerce@ */
+#endif
0, /* @nb_int@ */
0, /* @nb_long@ */
0, /* @nb_float@ */
+#ifdef PY2
0, /* @nb_oct@ */
0, /* @nb_hex@ */
+#endif
0, /* @nb_inplace_add@ */
0, /* @nb_inplace_subtract@ */
static Py_hash_t fe_pyhash(PyObject *me)
{ return (mphash(FE_X(me))); }
+#ifdef PY2
static int fe_pycoerce(PyObject **x, PyObject **y)
{
mp *z;
end:
return (-1);
}
+#endif
static PyObject *fe_pyint(PyObject *x)
{
return (rc);
}
+#ifdef PY2
static PyObject *fe_pylong(PyObject *x)
{
mp *xx = F_OUT(FE_F(x), MP_NEW, FE_X(x));
MP_DROP(xx);
return (rc);
}
+#endif
#define BASEOP(name, radix, pre) \
static PyObject *fe_py##name(PyObject *x) { \
MP_DROP(xx); \
return (rc); \
}
+#ifdef PY2
BASEOP(oct, 8, "0");
+#endif
BASEOP(hex, 16, "0x");
#undef BASEOP
static const PyMemberDef fe_pymembers[] = {
#define MEMBERSTRUCT fe_pyobj
- MEMRNM(field, T_OBJECT, ob_type, READONLY,
+ MEMRNM(field, T_OBJECT, PY23(ob_type, ob_base.ob_type), READONLY,
"X.field -> field containing X")
#undef MEMBERSTRUCT
{ 0 }
fe_pyadd, /* @nb_add@ */
fe_pysub, /* @nb_subtract@ */
fe_pymul, /* @nb_multiply@ */
+#ifdef PY2
fe_pydiv, /* @nb_divide@ */
+#endif
0, /* @nb_remainder@ */
0, /* @nb_divmod@ */
fe_pyexp, /* @nb_power@ */
0, /* @nb_and@ */
0, /* @nb_xor@ */
0, /* @nb_or@ */
+#ifdef PY2
fe_pycoerce, /* @nb_coerce@ */
+#endif
fe_pyint, /* @nb_int@ */
- fe_pylong, /* @nb_long@ */
+ PY23(fe_pylong, 0), /* @nb_long@ */
0 /* meaningless */, /* @nb_float@ */
+#ifdef PY2
fe_pyoct, /* @nb_oct@ */
fe_pyhex, /* @nb_hex@ */
+#endif
0, /* @nb_inplace_add@ */
0, /* @nb_inplace_subtract@ */
0, /* @nb_inplace_multiply@ */
+#ifdef PY2
0, /* @nb_inplace_divide@ */
+#endif
0, /* @nb_inplace_remainder@ */
0, /* @nb_inplace_power@ */
0, /* @nb_inplace_lshift@ */
return (rc);
}
+#ifdef PY2
static PyObject *ge_pylong(PyObject *me)
{
mp *x = 0;
mp_drop(x);
return (rc);
}
+#endif
static PyObject *ge_pyint(PyObject *me)
{
0, /* @nb_add@ */
0, /* @nb_subtract@ */
ge_pymul, /* @nb_multiply@ */
+#ifdef PY2
ge_pydiv, /* @nb_divide@ */
+#endif
0, /* @nb_remainder@ */
0, /* @nb_divmod@ */
ge_pyexp, /* @nb_power@ */
0, /* @nb_and@ */
0, /* @nb_xor@ */
0, /* @nb_or@ */
+#ifdef PY2
0, /* @nb_coerce@ */
+#endif
ge_pyint, /* @nb_int@ */
- ge_pylong, /* @nb_long@ */
+ PY23(ge_pylong, 0), /* @nb_long@ */
0 /* meaningless */, /* @nb_float@ */
+#ifdef PY2
0, /* @nb_oct@ */
0, /* @nb_hex@ */
+#endif
0, /* @nb_inplace_add@ */
0, /* @nb_inplace_subtract@ */
0, /* @nb_inplace_multiply@ */
+#ifdef PY2
0, /* @nb_inplace_divide@ */
+#endif
0, /* @nb_inplace_remainder@ */
0, /* @nb_inplace_power@ */
0, /* @nb_inplace_lshift@ */
mp *x;
mpw *p;
+#ifdef PY3
+ int ov;
+ long j = PyLong_AsLongAndOverflow(obj, &ov);
+ if (!ov) return mp_fromlong(MP_NEW, j);
+#endif
+
sz = Py_SIZE(l);
if (sz < 0) sz = -sz;
bits = (unsigned long)sz * PyLong_SHIFT;
return (0);
return (x);
}
+#ifdef PY2
else if (PyInt_Check(o))
return (mp_fromlong(MP_NEW, PyInt_AS_LONG(o)));
+#endif
else if ((l = PyNumber_Long(o)) != 0) {
x = mp_frompylong(l);
Py_DECREF(l);
#define BASEOP(name, radix, pre) \
static PyObject *mp_py##name(PyObject *x) \
{ return mp_topystring(MP_X(x), radix, 0, pre, 0); }
+#ifdef PY2
BASEOP(oct, 8, "0");
+#endif
BASEOP(hex, 16, "0x");
#undef BASEOP
if (!mp_tolong_checked(MP_X(x), &l, 0)) return (PyInt_FromLong(l));
else return mp_topylong(MP_X(x));
}
+#ifdef PY2
static PyObject *mp_pylong(PyObject *x)
{ return (mp_topylong(MP_X(x))); }
+#endif
static PyObject *mp_pyfloat(PyObject *x)
{
PyObject *l = mp_topylong(MP_X(x));
return (PyFloat_FromDouble(f));
}
+#ifdef PY2
#define COERCE(pre, PRE) \
static int pre##_pycoerce(PyObject **x, PyObject **y) \
{ \
COERCE(mp, MP)
COERCE(gf, GF)
#undef COERCE
+#endif
static PyObject *mp_pyrichcompare(PyObject *x, PyObject *y, int op)
{
return (rc);
}
+#ifdef PY2
static int mp_pycompare(PyObject *x, PyObject *y)
{ return mp_cmp(MP_X(x), MP_X(y)); }
+#endif
static PyObject *mp_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
{
mp_pyadd, /* @nb_add@ */
mp_pysub, /* @nb_subtract@ */
mp_pymul, /* @nb_multiply@ */
+#ifdef PY2
0, /* @nb_divide@ */
+#endif
mp_pymod, /* @nb_remainder@ */
mp_pydivmod, /* @nb_divmod@ */
mp_pyexp, /* @nb_power@ */
mp_pyand2c, /* @nb_and@ */
mp_pyxor2c, /* @nb_xor@ */
mp_pyor2c, /* @nb_or@ */
+#ifdef PY2
mp_pycoerce, /* @nb_coerce@ */
+#endif
mp_pyint, /* @nb_int@ */
- mp_pylong, /* @nb_long@ */
+ PY23(mp_pylong, 0), /* @nb_long@ */
mp_pyfloat, /* @nb_float@ */
+#ifdef PY2
mp_pyoct, /* @nb_oct@ */
mp_pyhex, /* @nb_hex@ */
+#endif
0, /* @nb_inplace_add@ */
0, /* @nb_inplace_subtract@ */
0, /* @nb_inplace_multiply@ */
+#ifdef PY2
0, /* @nb_inplace_divide@ */
+#endif
0, /* @nb_inplace_remainder@ */
0, /* @nb_inplace_power@ */
0, /* @nb_inplace_lshift@ */
0, /* @tp_print@ */
0, /* @tp_getattr@ */
0, /* @tp_setattr@ */
- mp_pycompare, /* @tp_compare@ */
+ PY23(mp_pycompare, 0), /* @tp_compare@/@tp_as_async@ */
mp_pyrepr, /* @tp_repr@ */
PYNUMBER(mp), /* @tp_as_number@ */
0, /* @tp_as_sequence@ */
"Multiprecision integers, similar to `long' but more efficient and\n"
"versatile. Support all the standard arithmetic operations, with\n"
"implicit conversions from `PrimeFilter', and other objects which\n"
- "convert to `long'.\n"
+ "convert to `" PY23("long", "int") "'.\n"
"\n"
"Constructor MP(X, [radix = R]) attempts to convert X to an `MP'. If\n"
"X is a string, it's read in radix-R form, or we look for a prefix\n"
"if R = 0. Other acceptable things are field elements, elliptic curve\n"
+ PY23(
"points, group elements, Python `int' and `long' objects, and anything\n"
- "with an integer conversion.\n"
+ "with an integer conversion.\n",
+ "points, group elements, Python `int' objects, and anything with an\n"
+ "integer conversion.\n")
"\n"
"Notes:\n"
"\n"
gf_pyadd, /* @nb_add@ */
gf_pysub, /* @nb_subtract@ */
gf_pymul, /* @nb_multiply@ */
+#ifdef PY2
0, /* @nb_divide@ */
+#endif
gf_pymod, /* @nb_remainder@ */
gf_pydivmod, /* @nb_divmod@ */
gf_pyexp, /* @nb_power@ */
gf_pyand, /* @nb_and@ */
gf_pyxor, /* @nb_xor@ */
gf_pyor, /* @nb_or@ */
+#ifdef PY2
gf_pycoerce, /* @nb_coerce@ */
+#endif
mp_pyint, /* @nb_int@ */
- mp_pylong, /* @nb_long@ */
+ PY23(mp_pylong, 0), /* @nb_long@ */
0 /* doesn't make any sense */, /* @nb_float@ */
+#ifdef PY2
mp_pyoct, /* @nb_oct@ */
mp_pyhex, /* @nb_hex@ */
+#endif
0, /* @nb_inplace_add@ */
0, /* @nb_inplace_subtract@ */
0, /* @nb_inplace_multiply@ */
+#ifdef PY2
0, /* @nb_inplace_divide@ */
+#endif
0, /* @nb_inplace_remainder@ */
0, /* @nb_inplace_power@ */
0, /* @nb_inplace_lshift@ */
"Constructor GF(X, [radix = R]) attempts to convert X to a `GF'. If\n"
"X is a string, it's read in radix-R form, or we look for a prefix\n"
"if R = 0. Other acceptable things are field elements, elliptic curve\n"
+ PY23(
"points, group elements, Python `int' and `long' objects, and anything\n"
- "with an integer conversion.\n"
+ "with an integer conversion.\n",
+ "points, group elements, Python `int' objects, and anything with an\n"
+ "integer conversion.\n")
"\n"
"The name is hopelessly wrong from a technical point of view, but\n"
"but it's much easier to type than `p2' or `c2' or whatever.\n"
return (rc);
}
+#ifdef PY2
static PyObject *pfilt_pylong(PyObject *me)
{ return (mp_topylong(PFILT_F(me)->m)); }
+#endif
static PyObject *pfget_x(PyObject *me, void *hunoz)
{ return (mp_pywrap(MP_COPY(PFILT_F(me)->m))); }
0, /* @nb_add@ */
0, /* @nb_subtract@ */
0, /* @nb_multiply@ */
+#ifdef PY2
0, /* @nb_divide@ */
+#endif
0, /* @nb_remainder@ */
0, /* @nb_divmod@ */
0, /* @nb_power@ */
0, /* @nb_and@ */
0, /* @nb_xor@ */
0, /* @nb_or@ */
+#ifdef PY2
0, /* @nb_coerce@ */
+#endif
pfilt_pyint, /* @nb_int@ */
- pfilt_pylong, /* @nb_long@ */
+ PY23(pfilt_pylong, 0), /* @nb_long@ */
0, /* @nb_float@ */
+#ifdef PY2
0, /* @nb_oct@ */
0, /* @nb_hex@ */
+#endif
0, /* @nb_inplace_add@ */
0, /* @nb_inplace_subtract@ */
0, /* @nb_inplace_multiply@ */
+#ifdef PY2
0, /* @nb_inplace_divide@ */
+#endif
0, /* @nb_inplace_remainder@ */
0, /* @nb_inplace_power@ */
0, /* @nb_inplace_lshift@ */
###--------------------------------------------------------------------------
### Imported modules.
-from sys import argv, stdin, stdout, stderr
+import sys as SYS; from sys import argv, stdin, stdout, stderr
import os as OS
import itertools as I
import math as M
import catacomb as C
+if SYS.version_info >= (3,):
+ xrange = range
+ range = lambda *args: list(xrange(*args))
+
###--------------------------------------------------------------------------
### Utilities.
from __future__ import with_statement
from os import environ
-from sys import argv, exit, stdin, stdout, stderr
+import sys as SYS; from sys import argv, exit, stdin, stdout, stderr
from getopt import getopt, GetoptError
from fnmatch import fnmatch
import re
###--------------------------------------------------------------------------
### Python version portability.
-def _text(bin): return bin
-def _bin(text): return text
+if SYS.version_info >= (3,):
+ import io as IO
+ def hack_stream(stream):
+ _enc = stream.encoding
+ _lbuf = stream.line_buffering
+ _nl = stream.newlines
+ return IO.TextIOWrapper(stream.detach(),
+ encoding = _enc,
+ line_buffering = _lbuf,
+ newline = _nl,
+ errors = "surrogateescape")
+ SYS.stdout = stdout = hack_stream(stdout)
+ def _text(bin): return bin.decode(errors = "surrogateescape")
+ def _bin(text): return text.encode(errors = "surrogateescape")
+else:
+ def _text(bin): return bin
+ def _bin(text): return text
def _excval(): return SYS.exc_info()[1]
0 /* @tp_is_gc@ */
};
+/*----- Mapping views -----------------------------------------------------*/
+
+#ifdef PY3
+
+static PyTypeObject *keyview_pytype, *itemview_pytype, *valview_pytype;
+
+typedef struct view_pyobj {
+ PyObject_HEAD
+ PyObject *map;
+} view_pyobj;
+#define VIEW_MAP(o) (((view_pyobj *)(o))->map)
+
+static PyObject *gmap_mkview(PyObject *me, PyTypeObject *ty)
+{
+ view_pyobj *v = PyObject_NEW(view_pyobj, ty);
+ v->map = me; Py_INCREF(me);
+ return ((PyObject *)v);
+}
+
+static void view_pydealloc(PyObject *me)
+ { Py_DECREF(VIEW_MAP(me)); FREEOBJ(me); }
+
+#define BINOP(op, update) \
+ static PyObject *view_py##op(PyObject *me, PyObject *you) \
+ { \
+ PyObject *set = 0; \
+ PyObject *rc = 0; \
+ \
+ set = PySet_New(me); if (!set) goto end; \
+ if (!PyObject_CallMethod(set, #update, "(O)", you)) goto end; \
+ rc = set; set = 0; \
+ end: \
+ Py_XDECREF(set); \
+ return (rc); \
+ }
+BINOP(and, intersection_update)
+BINOP(or, update)
+BINOP(xor, symmetric_difference_update)
+#undef BINOP
+
+static int all_contained_p(PyObject *x, PyObject *y)
+{
+ PyObject *i = 0, *e;
+ int b, rc = -1;
+
+ i = PyObject_GetIter(x); if (!i) goto end;
+ for (;;) {
+ e = PyIter_Next(i); if (!e) break;
+ b = PySequence_Contains(y, e); Py_DECREF(e); if (b < 0) goto end;
+ if (!b) { rc = 0; goto end; }
+ }
+ if (PyErr_Occurred()) goto end;
+ rc = 1;
+end:
+ Py_XDECREF(i);
+ return (rc);
+}
+
+static Py_ssize_t view_pysize(PyObject *me)
+ { return (PyMapping_Size(VIEW_MAP(me))); }
+
+static PyObject *view_pyrichcompare(PyObject *me, PyObject *you, int op)
+{
+ PyObject *map = ITER_MAP(me);
+ Py_ssize_t mysz, yoursz;
+ int b;
+
+ mysz = PyMapping_Size(map); if (mysz < 0) return (0);
+ yoursz = PyObject_Size(you);
+ if (yoursz < 0) { PyErr_Clear(); RETURN_NOTIMPL; }
+
+ switch (op) {
+ case Py_EQ:
+ if (mysz != yoursz) RETURN_FALSE;
+ b = all_contained_p(you, me);
+ break;
+ case Py_NE:
+ if (mysz != yoursz) RETURN_TRUE;
+ b = all_contained_p(you, me);
+ break;
+ case Py_LT:
+ if (mysz >= yoursz) RETURN_FALSE;
+ b = all_contained_p(me, you);
+ break;
+ case Py_LE:
+ if (mysz > yoursz) RETURN_FALSE;
+ b = all_contained_p(me, you);
+ break;
+ case Py_GE:
+ if (mysz < yoursz) RETURN_FALSE;
+ b = all_contained_p(you, me);
+ break;
+ case Py_GT:
+ if (mysz <= yoursz) RETURN_FALSE;
+ b = all_contained_p(you, me);
+ break;
+ default:
+ abort();
+ }
+ if (b < 0) return (0);
+ return (getbool(b));
+}
+
+static PyObject *keyview_pyiter(PyObject *me)
+ { return (gmap_mkiter(VIEW_MAP(me), keyiter_pytype)); }
+
+static int keyview_pyhaskey(PyObject *me, PyObject *k)
+{
+ PyObject *map = VIEW_MAP(me);
+ const struct gmap_ops *gmops = GMAP_OPS(map);
+ return (gmops->lookup(map, k, 0) ? 1 : PyErr_Occurred() ? -1 : 0);
+}
+
+static int itemview_pyhaskey(PyObject *me, PyObject *it)
+{
+ PyObject *map = VIEW_MAP(me);
+ const struct gmap_ops *gmops = GMAP_OPS(map);
+ void *e;
+ int b;
+ PyObject *v;
+
+ if (!PyTuple_Check(it) || PyTuple_GET_SIZE(it) != 2) return (0);
+ e = gmops->lookup(map, PyTuple_GET_ITEM(it, 0), 0);
+ if (!e) return (PyErr_Occurred() ? -1 : 0);
+ v = gmops->entry_value(map, e); if (!v) return (-1);
+ b = PyObject_RichCompareBool(v, PyTuple_GET_ITEM(it, 1), Py_EQ);
+ Py_DECREF(v); return (b);
+}
+
+static PyObject *valview_pyiter(PyObject *me)
+ { return (gmap_mkiter(VIEW_MAP(me), valiter_pytype)); }
+
+static PyObject *itemview_pyiter(PyObject *me)
+ { return (gmap_mkiter(VIEW_MAP(me), itemiter_pytype)); }
+
+static const PyNumberMethods view_pynumber = {
+ 0, /* @nb_add@ */
+ 0, /* @nb_subtract@ */
+ 0, /* @nb_multiply@ */
+#ifdef PY2
+ 0, /* @nb_divide@ */
+#endif
+ 0, /* @nb_remainder@ */
+ 0, /* @nb_divmod@ */
+ 0, /* @nb_power@ */
+ 0, /* @nb_negative@ */
+ 0, /* @nb_positive@ */
+ 0, /* @nb_absolute@ */
+ 0, /* @nb_nonzero@ */
+ 0, /* @nb_invert@ */
+ 0, /* @nb_lshift@ */
+ 0, /* @nb_rshift@ */
+ view_pyand, /* @nb_and@ */
+ view_pyxor, /* @nb_xor@ */
+ view_pyor, /* @nb_or@ */
+ 0, /* @nb_coerce@ */
+ 0, /* @nb_int@ */
+ 0, /* @nb_long@ */
+ 0, /* @nb_float@ */
+ 0, /* @nb_oct@ */
+ 0, /* @nb_hex@ */
+};
+
+static const PySequenceMethods keyview_pysequence = {
+ view_pysize, /* @sq_length@ */
+ 0, /* @sq_concat@ */
+ 0, /* @sq_repeat@ */
+ 0, /* @sq_item@ */
+ 0, /* @sq_slice@ */
+ 0, /* @sq_ass_item@ */
+ 0, /* @sq_ass_slice@ */
+ keyview_pyhaskey, /* @sq_contains@ */
+ 0, /* @sq_inplace_concat@ */
+ 0, /* @sq_inplace_repeat@ */
+};
+
+static const PyTypeObject keyview_pytype_skel = {
+ PyVarObject_HEAD_INIT(0, 0) /* Header */
+ "_KeyView", /* @tp_name@ */
+ sizeof(view_pyobj), /* @tp_basicsize@ */
+ 0, /* @tp_itemsize@ */
+
+ view_pydealloc, /* @tp_dealloc@ */
+ 0, /* @tp_print@ */
+ 0, /* @tp_getattr@ */
+ 0, /* @tp_setattr@ */
+ 0, /* @tp_compare@ */
+ 0, /* @tp_repr@ */
+ PYNUMBER(view), /* @tp_as_number@ */
+ PYSEQUENCE(keyview), /* @tp_as_sequence@ */
+ 0, /* @tp_as_mapping@ */
+ 0, /* @tp_hash@ */
+ 0, /* @tp_call@ */
+ 0, /* @tp_str@ */
+ 0, /* @tp_getattro@ */
+ 0, /* @tp_setattro@ */
+ 0, /* @tp_as_buffer@ */
+ Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
+ Py_TPFLAGS_BASETYPE,
+
+ /* @tp_doc@ */
+ "View of a mapping's keys.",
+
+ 0, /* @tp_traverse@ */
+ 0, /* @tp_clear@ */
+ view_pyrichcompare, /* @tp_richcompare@ */
+ 0, /* @tp_weaklistoffset@ */
+ keyview_pyiter, /* @tp_iter@ */
+ 0, /* @tp_iternext@ */
+ 0, /* @tp_methods@ */
+ 0, /* @tp_members@ */
+ 0, /* @tp_getset@ */
+ 0, /* @tp_base@ */
+ 0, /* @tp_dict@ */
+ 0, /* @tp_descr_get@ */
+ 0, /* @tp_descr_set@ */
+ 0, /* @tp_dictoffset@ */
+ 0, /* @tp_init@ */
+ PyType_GenericAlloc, /* @tp_alloc@ */
+ abstract_pynew, /* @tp_new@ */
+ 0, /* @tp_free@ */
+ 0 /* @tp_is_gc@ */
+};
+
+static const PySequenceMethods valview_pysequence = {
+ view_pysize, /* @sq_length@ */
+ 0, /* @sq_concat@ */
+ 0, /* @sq_repeat@ */
+ 0, /* @sq_item@ */
+ 0, /* @sq_slice@ */
+ 0, /* @sq_ass_item@ */
+ 0, /* @sq_ass_slice@ */
+ 0, /* @sq_contains@ */
+ 0, /* @sq_inplace_concat@ */
+ 0, /* @sq_inplace_repeat@ */
+};
+
+static const PyTypeObject valview_pytype_skel = {
+ PyVarObject_HEAD_INIT(0, 0) /* Header */
+ "_ValueView", /* @tp_name@ */
+ sizeof(view_pyobj), /* @tp_basicsize@ */
+ 0, /* @tp_itemsize@ */
+
+ view_pydealloc, /* @tp_dealloc@ */
+ 0, /* @tp_print@ */
+ 0, /* @tp_getattr@ */
+ 0, /* @tp_setattr@ */
+ 0, /* @tp_compare@ */
+ 0, /* @tp_repr@ */
+ PYNUMBER(view), /* @tp_as_number@ */
+ PYSEQUENCE(valview), /* @tp_as_sequence@ */
+ 0, /* @tp_as_mapping@ */
+ 0, /* @tp_hash@ */
+ 0, /* @tp_call@ */
+ 0, /* @tp_str@ */
+ 0, /* @tp_getattro@ */
+ 0, /* @tp_setattro@ */
+ 0, /* @tp_as_buffer@ */
+ Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
+ Py_TPFLAGS_BASETYPE,
+
+ /* @tp_doc@ */
+ "View of a mapping's values.",
+
+ 0, /* @tp_traverse@ */
+ 0, /* @tp_clear@ */
+ 0, /* @tp_richcompare@ */
+ 0, /* @tp_weaklistoffset@ */
+ valview_pyiter, /* @tp_iter@ */
+ 0, /* @tp_iternext@ */
+ 0, /* @tp_methods@ */
+ 0, /* @tp_members@ */
+ 0, /* @tp_getset@ */
+ 0, /* @tp_base@ */
+ 0, /* @tp_dict@ */
+ 0, /* @tp_descr_get@ */
+ 0, /* @tp_descr_set@ */
+ 0, /* @tp_dictoffset@ */
+ 0, /* @tp_init@ */
+ PyType_GenericAlloc, /* @tp_alloc@ */
+ abstract_pynew, /* @tp_new@ */
+ 0, /* @tp_free@ */
+ 0 /* @tp_is_gc@ */
+};
+
+static const PySequenceMethods itemview_pysequence = {
+ view_pysize, /* @sq_length@ */
+ 0, /* @sq_concat@ */
+ 0, /* @sq_repeat@ */
+ 0, /* @sq_item@ */
+ 0, /* @sq_slice@ */
+ 0, /* @sq_ass_item@ */
+ 0, /* @sq_ass_slice@ */
+ itemview_pyhaskey, /* @sq_contains@ */
+ 0, /* @sq_inplace_concat@ */
+ 0, /* @sq_inplace_repeat@ */
+};
+
+static const PyTypeObject itemview_pytype_skel = {
+ PyVarObject_HEAD_INIT(0, 0) /* Header */
+ "_ItemView", /* @tp_name@ */
+ sizeof(view_pyobj), /* @tp_basicsize@ */
+ 0, /* @tp_itemsize@ */
+
+ view_pydealloc, /* @tp_dealloc@ */
+ 0, /* @tp_print@ */
+ 0, /* @tp_getattr@ */
+ 0, /* @tp_setattr@ */
+ 0, /* @tp_compare@ */
+ 0, /* @tp_repr@ */
+ PYNUMBER(view), /* @tp_as_number@ */
+ PYSEQUENCE(itemview), /* @tp_as_sequence@ */
+ 0, /* @tp_as_mapping@ */
+ 0, /* @tp_hash@ */
+ 0, /* @tp_call@ */
+ 0, /* @tp_str@ */
+ 0, /* @tp_getattro@ */
+ 0, /* @tp_setattro@ */
+ 0, /* @tp_as_buffer@ */
+ Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
+ Py_TPFLAGS_BASETYPE,
+
+ /* @tp_doc@ */
+ "View of a mapping's key/value items.",
+
+ 0, /* @tp_traverse@ */
+ 0, /* @tp_clear@ */
+ view_pyrichcompare, /* @tp_richcompare@ */
+ 0, /* @tp_weaklistoffset@ */
+ itemview_pyiter, /* @tp_iter@ */
+ 0, /* @tp_iternext@ */
+ 0, /* @tp_methods@ */
+ 0, /* @tp_members@ */
+ 0, /* @tp_getset@ */
+ 0, /* @tp_base@ */
+ 0, /* @tp_dict@ */
+ 0, /* @tp_descr_get@ */
+ 0, /* @tp_descr_set@ */
+ 0, /* @tp_dictoffset@ */
+ 0, /* @tp_init@ */
+ PyType_GenericAlloc, /* @tp_alloc@ */
+ abstract_pynew, /* @tp_new@ */
+ 0, /* @tp_free@ */
+ 0 /* @tp_is_gc@ */
+};
+
+#endif
+
/*----- Other mapping protocol support ------------------------------------*/
Py_ssize_t gmap_pysize(PyObject *me)
0 /* @sq_inplace_repeat@ */
};
+#ifdef PY3
+
+PyObject *gmapmeth_keys(PyObject *me)
+ { return (gmap_mkview(me, keyview_pytype)); }
+
+PyObject *gmapmeth_values(PyObject *me)
+ { return (gmap_mkview(me, valview_pytype)); }
+
+PyObject *gmapmeth_items(PyObject *me)
+ { return (gmap_mkview(me, itemview_pytype)); }
+
+#else
+
PyObject *gmapmeth_has_key(PyObject *me, PyObject *arg)
{
PyObject *k;
PyObject *gmapmeth_iteritems(PyObject *me)
{ return (gmap_mkiter(me, itemiter_pytype)); }
+#endif
+
PyObject *gmap_pyiter(PyObject *me)
{ return gmap_mkiter(me, keyiter_pytype); }
unsigned foundp;
int rc = -1;
- v = PyObject_CallMethod(map, "iteritems", 0);
+ v = PyObject_CallMethod(map, PY23("iteritems", "items"), 0);
+#ifdef PY3
+ if (v) { i = PyObject_GetIter(v); Py_DECREF(v); v = 0; }
+#else
i = v; v = 0;
+#endif
if (i) {
for (;;) {
INITTYPE(keyiter, root);
INITTYPE(itemiter, root);
INITTYPE(valiter, root);
+#ifdef PY3
+ INITTYPE(keyview, root);
+ INITTYPE(valview, root);
+ INITTYPE(itemview, root);
+#endif
}
void pyke_gmap_pyinsert(PyObject *mod)
INSERT("_KeyIter", keyiter_pytype);
INSERT("_ValueIter", valiter_pytype);
INSERT("_ItemIter", itemiter_pytype);
+#ifdef PY3
+ INSERT("_KeyView", keyview_pytype);
+ INSERT("_ValueView", valview_pytype);
+ INSERT("_ItemView", itemview_pytype);
+#endif
}
/*----- That's all, folks -------------------------------------------------*/
Py_DECREF(i); i = t;
if ((j = PyLong_FromUnsignedLong(LO64(u))) == 0) goto end;
if ((t = PyNumber_InPlaceOr(i, j)) == 0) goto end;
+# ifdef PY2
Py_DECREF(i); i = t;
if ((t = PyNumber_Int(i)) == 0) goto end;
+# endif
rc = t;
end:
Py_XDECREF(i);
PyObject *t;
if (!o) VALERR("can't delete");
+#ifdef PY2
if (PyInt_Check(o)) {
long i = PyInt_AS_LONG(o);
if (i < 0) VALERR("must be nonnegative");
*p = i;
} else
+#endif
{
if ((t = PyNumber_Long(o)) == 0) goto end;
*p = PyLong_AsUnsignedLong(t);
r->sz = BIN_LEN(o);
return (1);
}
+#ifdef PY2
if (PyUnicode_Check(o)) {
o = _PyUnicode_AsDefaultEncodedString(o, 0);
if (!o) return (0);
r->sz = PyString_GET_SIZE(o);
return (1);
}
+#endif
return (PyObject_AsReadBuffer(o, &r->p, &r->sz) ? 0 : 1);
}
if (ty->ht_name)
ty->ht_type.tp_name = TEXT_STR(ty->ht_name);
ty->ht_slots = 0;
+#ifdef PY3
+ ty->ht_qualname = 0;
+#endif
(void)PyObject_INIT(&ty->ht_type, metaty);
Py_INCREF(metaty);
return (ty);
void typeready(PyTypeObject *ty)
{
+#ifdef PY3
+ PyHeapTypeObject *hty = (PyHeapTypeObject *)ty;
+ hty->ht_qualname = hty->ht_name;
+#endif
PyType_Ready(ty);
PyDict_SetItemString(ty->tp_dict, "__module__", modname);
}
while (mm->ml_name) {
if ((func = PyCFunction_NewEx((/*unconst*/ PyMethodDef *)mm,
0, mod)) == 0 ||
- (meth = PyMethod_New(func, 0, exc)) == 0 ||
+ (meth = PY23(PyMethod_New(func, 0, exc),
+ PyInstanceMethod_New(func))) == 0 ||
PyDict_SetItemString(dict, mm->ml_name, meth))
goto fail;
Py_DECREF(func); func = 0;
/*----- Python version compatibility hacks --------------------------------*/
+/* Explicit version switching. */
+#if PY_VERSION_HEX >= 0x03000000
+# define PY3 1
+# define PY23(two, three) three
+#else
+# define PY2 1
+# define PY23(two, three) two
+#endif
+
/* The handy `Py_TYPE' and `Py_SIZE' macros turned up in 2.6. Define them if
* they're not already here.
*/
# define PyVarObject_HEAD_INIT(super, sz) PyObject_HEAD_INIT(super) sz,
#endif
+/* Python 3 doesn't have `int', only `long', even though it's called `int' at
+ * the Python level. Provide some obvious macros to fill in the gaps.
+ */
+#ifdef PY3
+# define PyInt_Check PyLong_Check
+# define PyInt_FromLong PyLong_FromLong
+# define PyInt_AS_LONG PyLong_AS_LONG
+# define PyInt_AsLong PyLong_AsLong
+# define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask
+# define PyNumber_Int PyNumber_Long
+#endif
+
/* Python 3.2 changed the type of hash values, so paper over this annoying
* difference.
*/
typedef long Py_hash_t;
#endif
+/* Python 3 always has the `CHECKTYPES' behaviour, and doesn't define the
+ * flag.
+ */
+#ifdef PY3
+# define Py_TPFLAGS_CHECKTYPES 0
+#endif
+
/* Plain octet strings. Python 2 calls these `str', while Python 3 calls
* them `bytes'. We call them `bin' here, and define the following.
*
# * `YN' is a format character for `PyArg_ParseTuple...' for retrieving an
* octet string and length from any sort-of vaguely binary-ish object.
*/
+#ifdef PY3
+# define BINOBJ PyBytesObject
+# define BIN_TYPE PyBytes_Type
+# define BIN_CHECK(obj) PyBytes_Check(obj)
+# define BIN_PTR(obj) PyBytes_AS_STRING(obj)
+# define BIN_LEN(obj) PyBytes_GET_SIZE(obj)
+# define BIN_FROMSTR(str) PyBytes_FromString(str)
+# define BIN_FROMSTRLEN(str, len) PyBytes_FromStringAndSize(str, len)
+# define BIN_FORMAT PyBytes_FromFormat
+# define BIN_VFORMAT PyBytes_FromFormatV
+# define BIN_PREPAREWRITE(obj, ptr, sz) do { \
+ (obj) = PyBytes_FromStringAndSize(0, (sz)); \
+ (ptr) = PyBytes_AS_STRING(obj); \
+ } while (0)
+# define BIN_DONEWRITE(obj, sz) do Py_SIZE(obj) = (sz); while (0)
+# define BIN_SETLEN(obj, len) do Py_SIZE(obj) = (len); while (0)
+# define Y "y"
+# define YN "y#"
+#else
# define BINOBJ PyStringObject
# define BIN_TYPE PyString_Type
# define BIN_CHECK(obj) PyString_Check(obj)
# define BIN_SETLEN(obj, len) do Py_SIZE(obj) = (len); while (0)
# define Y "s"
# define YN "s#"
+#endif
/* Text strings. Both Python 2 and Python 3 call these `str', but they're
* very different because a Python 3 `str' is Unicode inside. When dealing
*
* (Use `s' and `s#' in `PyArg_ParseTuple...'.)
*/
+#ifdef PY3
+# define TEXTOBJ PyUnicodeObject
+# define TEXT_TYPE PyUnicode_Type
+# define TEXT_CHECK(obj) PyUnicode_Check(obj)
+# if PY_VERSION_HEX >= 0x03030000
+# define TEXT_PTR(obj) PyUnicode_AsUTF8(obj)
+# define TEXT_STR(obj) PyUnicode_AsUTF8(obj)
+# define TEXT_PTRLEN(obj, ptr, len) do { \
+ Py_ssize_t len_; \
+ (ptr) = PyUnicode_AsUTF8AndSize((obj), &len_); \
+ (len) = len_; \
+ } while (0)
+# define TEXT_PREPAREWRITE(obj, ptr, sz) do { \
+ (obj) = PyUnicode_New((sz), 127); \
+ (ptr) = PyUnicode_DATA(obj); \
+ } while (0)
+# define TEXT_DONEWRITE(obj, len) do { \
+ size_t len_ = (len); \
+ assert(PyUnicode_IS_COMPACT_ASCII(obj)); \
+ ((char *)PyUnicode_DATA(obj))[len_] = 0; \
+ ((PyASCIIObject *)(obj))->length = len_; \
+ } while (0)
+# else
+# define TEXT_PTR(obj) _PyUnicode_AsString(obj)
+# define TEXT_STR(obj) _PyUnicode_AsString(obj)
+# define TEXT_PTRLEN(obj, ptr, len) do { \
+ Py_ssize_t len_; \
+ (ptr) = _PyUnicode_AsStringAndSize((obj), &len_); \
+ (len) = len_; \
+ } while (0)
+# define TEXT_PREPAREWRITE(obj, ptr, sz) do { \
+ (obj) = PyBytes_FromStringAndSize(0, (sz)); \
+ (ptr) = PyBytes_AS_STRING(obj); \
+ } while (0)
+# define TEXT_DONEWRITE(obj, len) do { \
+ PyObject *new_; \
+ Py_SIZE(obj) = (len); \
+ new_ = PyUnicode_FromEncodedObject(obj, 0, 0); \
+ assert(new_); Py_DECREF(obj); (obj) = new_; \
+ } while (0)
+# endif
+# define TEXT_FORMAT PyUnicode_FromFormat
+# define TEXT_VFORMAT PyUnicode_FromFormatV
+# define TEXT_FROMSTR(str) PyUnicode_FromString(str)
+# define TEXT_FROMSTRLEN(str, len) PyUnicode_FromStringAndSize(str, len)
+#else
# define TEXTOBJ PyStringObject
# define TEXT_TYPE PyString_Type
# define TEXT_CHECK(obj) PyString_Check(obj)
# define TEXT_DONEWRITE(obj, sz) do { Py_SIZE(obj) = (sz); } while (0)
# define TEXT_FROMSTR(str) PyString_FromString(str)
# define TEXT_FROMSTRLEN(str, len) PyString_FromStringAndSize(str, len)
+#endif
/*----- Utilities for returning values and exceptions ---------------------*/
#define GMAP_NAMETHDECL(func, doc) \
extern PyObject *gmapmeth_##func(PyObject *);
+#ifdef PY3
+# define GMAP_DOROMETHODS(METH, KWMETH, NAMETH) \
+ NAMETH(keys, "D.keys() -> LIST") \
+ NAMETH(values, "D.values() -> LIST") \
+ NAMETH(items, "D.items() -> LIST") \
+ KWMETH(get, "D.get(KEY, [default = None]) -> VALUE")
+#else
# define GMAP_DOROMETHODS(METH, KWMETH, NAMETH) \
METH (has_key, "D.has_key(KEY) -> BOOL") \
NAMETH(keys, "D.keys() -> LIST") \
NAMETH(itervalues, "D.itervalues() -> ITER") \
NAMETH(iteritems, "D.iteritems() -> ITER") \
KWMETH(get, "D.get(KEY, [default = None]) -> VALUE")
+#endif
#define GMAP_DOMETHODS(METH, KWMETH, NAMETH) \
GMAP_DOROMETHODS(METH, KWMETH, NAMETH) \
x = C.ByteString(T.bin("once upon a time there was a string"))
- ## Check that simple indexing works.
- me.assertEqual(type(x[3]), C.ByteString)
- me.assertEqual(x[3], 'e')
- me.assertEqual(x[-5], 't')
+ ## Check that simple indexing works. Alas the behaviour differs between
+ ## Python major versions.
+ if T.PY3:
+ me.assertEqual(type(x[3]), int)
+ me.assertEqual(x[3], 101)
+ me.assertEqual(x[-5], 116)
+ else:
+ me.assertEqual(type(x[3]), C.ByteString)
+ me.assertEqual(x[3], 'e')
+ me.assertEqual(x[-5], 't')
## Check out-of-range detection.
x[34]; me.assertRaises(IndexError, lambda: x[35])
for bad in [lambda x: [x]]:
me.assertRaises(TypeError, pow, C.MP(5), bad(2))
me.assertRaises(TypeError, pow, C.MP(5), bad(2), 7)
- if not T.DEBUGP:
+ if not (T.PY2 and T.DEBUGP):
## Debug builds of Python 2 crash here, and it's not our fault. Run
##
## $ python2.7-dbg -c 'pow(long(5), 2, [7])'
me.assertRaises(TypeError, pow, bad(5), C.GF(2), bad(7))
me.assertRaises(TypeError, pow, bad(5), bad(2), C.GF(7))
me.assertRaises(TypeError, pow, C.GF(5), bad(2), bad(7))
- if not T.DEBUGP:
+ if not (T.PY2 and T.DEBUGP):
## Python bug: see above.
me.assertRaises(TypeError, pow, C.GF(5), 2, bad(7))
me.assertEqual(str(y), '6556380541834372447694561492436749633')
me.assertEqual(repr(y), 'MP(6556380541834372447694561492436749633)')
me.assertEqual(hex(y), '0x4eeb684a0954ec4ceb255e3e9778d41')
- me.assertEqual(oct(y), '047353320450112516611472622536175135706501')
+ me.assertEqual(oct(y), T.py23('0', '0o') +
+ '47353320450112516611472622536175135706501')
try: bin
except NameError: pass
else: me.assertEqual(bin(C.MP(661438603)),
me.assertEqual(str(y), '0x4eeb684a0954ec4ceb255e3e9778d41')
me.assertEqual(repr(y), 'GF(0x4eeb684a0954ec4ceb255e3e9778d41)')
me.assertEqual(hex(y), '0x4eeb684a0954ec4ceb255e3e9778d41')
- me.assertEqual(oct(y), '047353320450112516611472622536175135706501')
+ me.assertEqual(oct(y), T.py23('0', '0o') +
+ '47353320450112516611472622536175135706501')
try: bin
except NameError: pass
else: me.assertEqual(bin(C.GF(661438603)),
### Main code.
## Some compatibility hacks.
-import itertools as I
-def bin(x): return x
-range = xrange
-long = long
-imap = I.imap
-def byteseq(seq): return "".join(map(chr, seq))
-def iterkeys(m): return m.iterkeys()
-def itervalues(m): return m.itervalues()
-def iteritems(m): return m.iteritems()
-from cStringIO import StringIO
-MAXFIXNUM = SYS.maxint
+if SYS.version_info >= (3,):
+ PY2, PY3 = False, True
+ def bin(x): return x.encode('iso8859-1')
+ def py23(x, y): return y
+ range = range
+ byteseq = bytes
+ long = int
+ imap = map
+ def iterkeys(m): return m.keys()
+ def itervalues(m): return m.values()
+ def iteritems(m): return m.items()
+ from io import StringIO
+ MAXFIXNUM = SYS.maxsize
+else:
+ import itertools as I
+ PY2, PY3 = True, False
+ def bin(x): return x
+ def py23(x, y): return x
+ range = xrange
+ long = long
+ imap = I.imap
+ def byteseq(seq): return "".join(map(chr, seq))
+ def iterkeys(m): return m.iterkeys()
+ def itervalues(m): return m.itervalues()
+ def iteritems(m): return m.iteritems()
+ from cStringIO import StringIO
+ MAXFIXNUM = SYS.maxint
DEBUGP = hasattr(SYS, "gettotalrefcount")
any = True
if k >= limk: limk = k + 1
me.assertTrue(me._mkkey(k) in map)
- me.assertTrue(map.has_key(me._mkkey(k)))
+ if PY2: me.assertTrue(map.has_key(me._mkkey(k)))
me.assertEqual(me._getvalue(map[me._mkkey(k)]), v)
me.assertEqual(me._getvalue(map.get(me._mkkey(k))), v)
if any: me.assertTrue(me._mkkey(k) in map)
- me.assertFalse(map.has_key(me._mkkey(limk)))
+ if PY2: me.assertFalse(map.has_key(me._mkkey(limk)))
me.assertRaises(KeyError, lambda: map[me._mkkey(limk)])
me.assertEqual(map.get(me._mkkey(limk)), None)
- for listfn, getfn in [(lambda x: x.keys(), me._getkey),
- (lambda x: x.values(), me._getvalue),
- (lambda x: x.items(), me._getitem)]:
- rlist, mlist = listfn(map), listfn(model)
- me.assertEqual(type(rlist), list)
- rlist = B.map(getfn, rlist)
- rlist.sort(); mlist.sort(); me.assertEqual(rlist, mlist)
- for iterfn, getfn in [(lambda x: x.iterkeys(), me._getkey),
- (lambda x: x.itervalues(), me._getvalue),
- (lambda x: x.iteritems(), me._getitem)]:
- me.assertEqual(set(imap(getfn, iterfn(map))), set(iterfn(model)))
+
+ if PY3:
+ empty = set()
+
+ for k, v in iteritems(map):
+ me.assertTrue(k in map.keys())
+ me.assertTrue((k, v) in map.items())
+ me.assertFalse(me._mkkey(limk) in map.keys())
+
+ for viewfn, getfn in [(lambda x: x.keys(), me._getkey),
+ (lambda x: x.items(), me._getitem)]:
+ rview, rview2, mview = viewfn(map), viewfn(map), viewfn(model)
+ me.assertEqual(set(imap(getfn, rview)), set(mview))
+ me.assertEqual(rview, rview2)
+ me.assertEqual(rview, set(rview2))
+ me.assertEqual(rview | empty, set(rview))
+ me.assertEqual(rview | rview2, set(rview))
+ me.assertEqual(rview ^ empty, set(rview))
+ me.assertEqual(rview ^ rview, empty)
+ me.assertEqual(rview & empty, empty)
+ me.assertEqual(len(rview), len(model))
+
+ if any: subset = set(rview2); subset.pop()
+ superset = set(rview2); superset.add(object())
+
+ me.assertFalse(rview < rview2)
+ me.assertTrue(rview < superset)
+ me.assertFalse(superset < rview)
+ me.assertFalse(rview < empty)
+ if any:
+ me.assertTrue(empty < rview)
+ me.assertTrue(subset < rview)
+ me.assertFalse(rview < subset)
+
+ me.assertTrue(rview <= rview2)
+ me.assertTrue(rview <= superset)
+ me.assertFalse(superset <= rview)
+ if any:
+ me.assertTrue(empty <= rview)
+ me.assertFalse(rview <= empty)
+ me.assertTrue(subset <= rview)
+ me.assertFalse(rview <= subset)
+
+ me.assertTrue(rview >= rview2)
+ me.assertTrue(superset >= rview)
+ me.assertFalse(rview >= superset)
+ if any:
+ me.assertTrue(rview >= empty)
+ me.assertFalse(empty >= rview)
+ me.assertTrue(rview >= subset)
+ me.assertFalse(subset >= rview)
+
+ me.assertFalse(rview > rview2)
+ me.assertTrue(superset > rview)
+ me.assertFalse(rview > superset)
+ me.assertFalse(empty > rview)
+ if any:
+ me.assertTrue(rview > empty)
+ me.assertTrue(rview > subset)
+ me.assertFalse(subset > rview)
+
+ else:
+ for listfn, getfn in [(lambda x: x.keys(), me._getkey),
+ (lambda x: x.values(), me._getvalue),
+ (lambda x: x.items(), me._getitem)]:
+ rlist, mlist = listfn(map), listfn(model)
+ me.assertEqual(type(rlist), list)
+ rlist = B.map(getfn, rlist)
+ rlist.sort(); mlist.sort(); me.assertEqual(rlist, mlist)
+ for iterfn, getfn in [(lambda x: x.iterkeys(), me._getkey),
+ (lambda x: x.itervalues(), me._getvalue),
+ (lambda x: x.iteritems(), me._getitem)]:
+ me.assertEqual(set(imap(getfn, iterfn(map))), set(iterfn(model)))
class MutableMappingTestMixin (ImmutableMappingTextMixin):
map = emptymapfn()
me.assertEqual(len(map), 0)
- def check_views():
- me.check_immutable_mapping(map, model)
+ if not PY3:
+ def check_views():
+ me.check_immutable_mapping(map, model)
+ else:
+ kview, iview, vview = map.keys(), map.items(), map.values()
+ def check_views():
+ me.check_immutable_mapping(map, model)
+ me.assertEqual(set(imap(me._getkey, kview)), model.keys())
+ me.assertEqual(set(imap(me._getitem, iview)), model.items())
+ me.assertEqual(set(imap(me._getvalue, vview)), set(model.values()))
model = { 1: 101, 2: 202, 4: 404 }
for k, v in iteritems(model): map[me._mkkey(k)] = me._mkvalue(v)