summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/neps/dropping-python2.7-proposal.rst52
-rw-r--r--doc/source/neps/dropping-python2.7-proposal.rst1
-rw-r--r--doc/source/neps/index.rst1
-rw-r--r--numpy/core/src/multiarray/methods.c6
-rw-r--r--numpy/core/src/multiarray/strfuncs.c32
-rw-r--r--numpy/core/src/multiarray/strfuncs.h5
-rw-r--r--numpy/core/tests/test_arrayprint.py4
-rw-r--r--numpy/ma/core.py8
-rw-r--r--numpy/ma/tests/test_core.py10
9 files changed, 118 insertions, 1 deletions
diff --git a/doc/neps/dropping-python2.7-proposal.rst b/doc/neps/dropping-python2.7-proposal.rst
new file mode 100644
index 000000000..3cfe50bd0
--- /dev/null
+++ b/doc/neps/dropping-python2.7-proposal.rst
@@ -0,0 +1,52 @@
+====================================
+Plan for dropping Python 2.7 support
+====================================
+
+The Python core team plans to stop supporting Python 2 in 2020. The NumPy
+project has supported both Python 2 and Python 3 in parallel since 2010, and
+has found that supporting Python 2 is an increasing burden on our limited
+resources; thus, we plan to eventually drop Python 2 support as well. Now that
+we're entering the final years of community-supported Python 2, the NumPy
+project wants to clarify our plans, with the goal of to helping our downstream
+ecosystem make plans and accomplish the transition with as little disruption as
+possible.
+
+Our current plan is as follows.
+
+Until **December 31, 2018**, all NumPy releases will fully support both
+Python2 and Python3.
+
+Starting on **January 1, 2019**, any new feature releases will support only
+Python3.
+
+The last Python2 supporting release will be designated as a long term support
+(LTS) release, meaning that we will continue to merge bug fixes and make bug
+fix releases for a longer period than usual. Specifically, it will be
+supported by the community until **December 31, 2019**.
+
+On **January 1, 2020** we will raise a toast to Python2, and community support
+for the last Python2 supporting release will come to an end. However, it will
+continue to be available on PyPI indefinitely, and if any commercial vendors
+wish to extend the LTS support past this point then we are open to letting them
+use the LTS branch in the official NumPy repository to coordinate that.
+
+If you are a NumPy user who requires ongoing Python2 support in 2020 or later,
+then please contact your vendor. If you are a vendor who wishes to continue to
+support NumPy on Python2 in 2020+, please get in touch; ideally we'd like you
+to get involved in maintaining the LTS before it actually hits end of life so
+that we can make a clean handoff.
+
+To minimize disruption, running ``pip install numpy`` on Python 2 will continue
+to give the last working release in perpetuity, but after January 1, 2019 it
+may not contain the latest features, and after January 1, 2020 it may not
+contain the latest bug fixes.
+
+For more information on the scientific Python ecosystem's transition
+to Python3 only, see the python3-statement_.
+
+For more information on porting your code to run on Python 3, see the
+python3-howto_.
+
+.. _python3-statement: http://www.python3statement.org/
+
+.. _python3-howto: https://docs.python.org/3/howto/pyporting.html
diff --git a/doc/source/neps/dropping-python2.7-proposal.rst b/doc/source/neps/dropping-python2.7-proposal.rst
new file mode 100644
index 000000000..c67a626be
--- /dev/null
+++ b/doc/source/neps/dropping-python2.7-proposal.rst
@@ -0,0 +1 @@
+.. include:: ../../neps/dropping-python2.7-proposal.rst
diff --git a/doc/source/neps/index.rst b/doc/source/neps/index.rst
index de4cd64b6..d85f33606 100644
--- a/doc/source/neps/index.rst
+++ b/doc/source/neps/index.rst
@@ -35,3 +35,4 @@ Other NEPs
structured_array_extensions
datetime-proposal
datetime-proposal3
+ dropping-python2.7-proposal
diff --git a/numpy/core/src/multiarray/methods.c b/numpy/core/src/multiarray/methods.c
index 572352304..3f461b375 100644
--- a/numpy/core/src/multiarray/methods.c
+++ b/numpy/core/src/multiarray/methods.c
@@ -2505,6 +2505,12 @@ NPY_NO_EXPORT PyMethodDef array_methods[] = {
(PyCFunction)array_ufunc,
METH_VARARGS | METH_KEYWORDS, NULL},
+#ifndef NPY_PY3K
+ {"__unicode__",
+ (PyCFunction)array_unicode,
+ METH_NOARGS, NULL},
+#endif
+
/* for the sys module */
{"__sizeof__",
(PyCFunction) array_sizeof,
diff --git a/numpy/core/src/multiarray/strfuncs.c b/numpy/core/src/multiarray/strfuncs.c
index bb94eb9f3..646d15cdb 100644
--- a/numpy/core/src/multiarray/strfuncs.c
+++ b/numpy/core/src/multiarray/strfuncs.c
@@ -225,3 +225,35 @@ array_format(PyArrayObject *self, PyObject *args)
);
}
}
+
+#ifndef NPY_PY3K
+
+NPY_NO_EXPORT PyObject *
+array_unicode(PyArrayObject *self)
+{
+ PyObject *uni;
+
+ if (PyArray_NDIM(self) == 0) {
+ PyObject *item = PyArray_ToScalar(PyArray_DATA(self), self);
+ if (item == NULL){
+ return NULL;
+ }
+
+ /* defer to invoking `unicode` on the scalar */
+ uni = PyObject_CallFunctionObjArgs(
+ (PyObject *)&PyUnicode_Type, item, NULL);
+ Py_DECREF(item);
+ }
+ else {
+ /* Do what unicode(self) would normally do */
+ PyObject *str = PyObject_Str((PyObject *)self);
+ if (str == NULL){
+ return NULL;
+ }
+ uni = PyUnicode_FromObject(str);
+ Py_DECREF(str);
+ }
+ return uni;
+}
+
+#endif
diff --git a/numpy/core/src/multiarray/strfuncs.h b/numpy/core/src/multiarray/strfuncs.h
index 5dd661a20..7e869d926 100644
--- a/numpy/core/src/multiarray/strfuncs.h
+++ b/numpy/core/src/multiarray/strfuncs.h
@@ -13,4 +13,9 @@ array_str(PyArrayObject *self);
NPY_NO_EXPORT PyObject *
array_format(PyArrayObject *self, PyObject *args);
+#ifndef NPY_PY3K
+ NPY_NO_EXPORT PyObject *
+ array_unicode(PyArrayObject *self);
+#endif
+
#endif
diff --git a/numpy/core/tests/test_arrayprint.py b/numpy/core/tests/test_arrayprint.py
index f344ce910..62b5cf580 100644
--- a/numpy/core/tests/test_arrayprint.py
+++ b/numpy/core/tests/test_arrayprint.py
@@ -260,8 +260,10 @@ class TestPrintOptions(object):
assert_equal(repr(x), "array([0., 1., 2.])")
def test_0d_arrays(self):
+ unicode = type(u'')
+ assert_equal(unicode(np.array(u'café', np.unicode_)), u'café')
+
if sys.version_info[0] >= 3:
- assert_equal(str(np.array('café', np.unicode_)), 'café')
assert_equal(repr(np.array('café', np.unicode_)),
"array('café',\n dtype='<U4')")
else:
diff --git a/numpy/ma/core.py b/numpy/ma/core.py
index b71e8fa06..0d02bb315 100644
--- a/numpy/ma/core.py
+++ b/numpy/ma/core.py
@@ -3867,6 +3867,10 @@ class MaskedArray(ndarray):
def __str__(self):
return str(self._insert_masked_print())
+ if sys.version_info.major < 3:
+ def __unicode__(self):
+ return unicode(self._insert_masked_print())
+
def __repr__(self):
"""
Literal string representation.
@@ -6238,6 +6242,10 @@ class MaskedConstant(MaskedArray):
def __str__(self):
return str(masked_print_option._display)
+ if sys.version_info.major < 3:
+ def __unicode__(self):
+ return unicode(masked_print_option._display)
+
def __repr__(self):
if self is MaskedConstant.__singleton:
return 'masked'
diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py
index fd8d629f9..03de71f81 100644
--- a/numpy/ma/tests/test_core.py
+++ b/numpy/ma/tests/test_core.py
@@ -500,6 +500,16 @@ class TestMaskedArray(object):
' fill_value = 999999)\n'
)
+ def test_0d_unicode(self):
+ u = u'caf\xe9'
+ utype = type(u)
+
+ arr_nomask = np.ma.array(u)
+ arr_masked = np.ma.array(u, mask=True)
+
+ assert_equal(utype(arr_nomask), u)
+ assert_equal(utype(arr_masked), u'--')
+
def test_pickling(self):
# Tests pickling
for dtype in (int, float, str, object):