Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop support for EOL Python 2.7 #404

Merged
merged 2 commits into from
May 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 2 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["2.7", "3.5", "3.6", "3.7", "3.8", "3.9"]
python-version: ["3.5", "3.6", "3.7", "3.8", "3.9"]
os: [ubuntu-18.04, ubuntu-16.04, macos-latest, windows-2019]
exclude:
- { python-version: 2.7, os: windows-2019 }
- { python-version: 3.9, os: ubuntu-16.04 }
- { python-version: 3.9, os: macos-latest }
- { python-version: 3.9, os: windows-2019 }
Expand Down Expand Up @@ -72,7 +71,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade pytest six
python -m pip install --upgrade pytest
python -m pip install .

- name: Tests
Expand Down
17 changes: 9 additions & 8 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,20 @@ pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.cache
.coverage
.coverage.*
.hypothesis/
.nox/
.pytest_cache/
.testmondata
.tox/
cover/
coverage.xml
htmlcov/
nosetests.xml

# Translations
*.mo
Expand Down
3 changes: 2 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ repos:
rev: v2.1.0
hooks:
- id: pyupgrade
args: ["--py3-plus"]

- repo: https://github.com/psf/black
rev: 19.10b0
hooks:
- id: black
args: ["--target-version", "py27"]
args: ["--target-version", "py35"]

- repo: https://gitlab.com/pycqa/flake8
rev: 3.7.9
Expand Down
3 changes: 1 addition & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ arch:
- s390x

python:
- "2.7"
- "3.5"
- "3.8"
- "3.9-dev"
Expand All @@ -17,7 +16,7 @@ jobs:

install:
- pip install -U pip
- pip install -U pytest six
- pip install -U pytest
- pip install .

script: pytest
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ UltraJSON
:alt: Code style: Black
:target: https://github.com/psf/black

UltraJSON is an ultra fast JSON encoder and decoder written in pure C with bindings for Python 2.7 and 3.5+.
UltraJSON is an ultra fast JSON encoder and decoder written in pure C with bindings for Python 3.5+.

To install it just run pip as usual:

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
requires = ["setuptools>=42", "wheel", "setuptools_scm[toml]>=3.4"]

[tool.black]
target_version = ["py27"]
target_version = ["py35"]
8 changes: 4 additions & 4 deletions python/JSONtoObj.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Numeric decoder derived from from TCL library
* Copyright (c) 1994 Sun Microsystems, Inc.
*/

#include "py_defines.h"
#include <Python.h>
#include <ultrajson.h>


Expand Down Expand Up @@ -90,7 +90,7 @@ static JSOBJ Object_newArray(void *prv)

static JSOBJ Object_newInteger(void *prv, JSINT32 value)
{
return PyInt_FromLong( (long) value);
return PyLong_FromLong( (long) value);
}

static JSOBJ Object_newLong(void *prv, JSINT64 value)
Expand Down Expand Up @@ -147,7 +147,7 @@ PyObject* JSONToObj(PyObject* self, PyObject *args, PyObject *kwargs)
return NULL;
}

if (PyString_Check(arg))
if (PyBytes_Check(arg))
{
sarg = arg;
}
Expand All @@ -172,7 +172,7 @@ PyObject* JSONToObj(PyObject* self, PyObject *args, PyObject *kwargs)

dconv_s2d_init(DCONV_S2D_ALLOW_TRAILING_JUNK, 0.0, 0.0, "Infinity", "NaN");

ret = JSON_DecodeObject(&decoder, PyString_AS_STRING(sarg), PyString_GET_SIZE(sarg));
ret = JSON_DecodeObject(&decoder, PyBytes_AS_STRING(sarg), PyBytes_GET_SIZE(sarg));

dconv_s2d_free();

Expand Down
50 changes: 19 additions & 31 deletions python/objToJSON.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Numeric decoder derived from from TCL library
* Copyright (c) 1994 Sun Microsystems, Inc.
*/

#include "py_defines.h"
#include <Python.h>
#include <stdio.h>
#include <ultrajson.h>

Expand Down Expand Up @@ -98,14 +98,14 @@ void initObjToJSON(void)
static void *PyIntToINT64(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen)
{
PyObject *obj = (PyObject *) _obj;
*((JSINT64 *) outValue) = PyInt_AS_LONG (obj);
*((JSINT64 *) outValue) = PyLong_AsLong (obj);
return NULL;
}
#else
static void *PyIntToINT32(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen)
{
PyObject *obj = (PyObject *) _obj;
*((JSINT32 *) outValue) = PyInt_AS_LONG (obj);
*((JSINT32 *) outValue) = PyLong_AsLong (obj);
return NULL;
}
#endif
Expand All @@ -132,23 +132,21 @@ static void *PyFloatToDOUBLE(JSOBJ _obj, JSONTypeContext *tc, void *outValue, si
static void *PyStringToUTF8(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen)
{
PyObject *obj = (PyObject *) _obj;
*_outLen = PyString_GET_SIZE(obj);
return PyString_AS_STRING(obj);
*_outLen = PyBytes_GET_SIZE(obj);
return PyBytes_AS_STRING(obj);
}

static void *PyUnicodeToUTF8(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen)
{
PyObject *obj = (PyObject *) _obj;
PyObject *newObj;
#if (PY_VERSION_HEX >= 0x03030000)
if (PyUnicode_IS_COMPACT_ASCII(obj))
{
Py_ssize_t len;
char *data = PyUnicode_AsUTF8AndSize(obj, &len);
*_outLen = len;
return data;
}
#endif
newObj = PyUnicode_AsUTF8String(obj);
if(!newObj)
{
Expand All @@ -157,8 +155,8 @@ static void *PyUnicodeToUTF8(JSOBJ _obj, JSONTypeContext *tc, void *outValue, si

GET_TC(tc)->newObj = newObj;

*_outLen = PyString_GET_SIZE(newObj);
return PyString_AS_STRING(newObj);
*_outLen = PyBytes_GET_SIZE(newObj);
return PyBytes_AS_STRING(newObj);
}

static void *PyRawJSONToUTF8(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen)
Expand Down Expand Up @@ -266,20 +264,18 @@ static int Dict_iterNext(JSOBJ obj, JSONTypeContext *tc)
Py_DECREF(itemNameTmp);
}
else
if (!PyString_Check(GET_TC(tc)->itemName))
if (!PyBytes_Check(GET_TC(tc)->itemName))
{
if (UNLIKELY(GET_TC(tc)->itemName == Py_None))
{
GET_TC(tc)->itemName = PyString_FromString("null");
GET_TC(tc)->itemName = PyUnicode_FromString("null");
return 1;
}

GET_TC(tc)->itemName = PyObject_Str(GET_TC(tc)->itemName);
#if PY_MAJOR_VERSION >= 3
itemNameTmp = GET_TC(tc)->itemName;
GET_TC(tc)->itemName = PyUnicode_AsUTF8String (GET_TC(tc)->itemName);
Py_DECREF(itemNameTmp);
#endif
}
else
{
Expand Down Expand Up @@ -308,17 +304,15 @@ static JSOBJ Dict_iterGetValue(JSOBJ obj, JSONTypeContext *tc)

static char *Dict_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen)
{
*outLen = PyString_GET_SIZE(GET_TC(tc)->itemName);
return PyString_AS_STRING(GET_TC(tc)->itemName);
*outLen = PyBytes_GET_SIZE(GET_TC(tc)->itemName);
return PyBytes_AS_STRING(GET_TC(tc)->itemName);
}

static int SortedDict_iterNext(JSOBJ obj, JSONTypeContext *tc)
{
PyObject *items = NULL, *item = NULL, *key = NULL, *value = NULL;
Py_ssize_t i, nitems;
#if PY_MAJOR_VERSION >= 3
PyObject* keyTmp;
#endif

// Upon first call, obtain a list of the keys and sort them. This follows the same logic as the
// stanard library's _json.c sort_keys handler.
Expand Down Expand Up @@ -355,14 +349,12 @@ static int SortedDict_iterNext(JSOBJ obj, JSONTypeContext *tc)
{
key = PyUnicode_AsUTF8String(key);
}
else if (!PyString_Check(key))
else if (!PyBytes_Check(key))
{
key = PyObject_Str(key);
#if PY_MAJOR_VERSION >= 3
keyTmp = key;
key = PyUnicode_AsUTF8String(key);
Py_DECREF(keyTmp);
#endif
}
else
{
Expand Down Expand Up @@ -421,8 +413,8 @@ static JSOBJ SortedDict_iterGetValue(JSOBJ obj, JSONTypeContext *tc)

static char *SortedDict_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen)
{
*outLen = PyString_GET_SIZE(GET_TC(tc)->itemName);
return PyString_AS_STRING(GET_TC(tc)->itemName);
*outLen = PyBytes_GET_SIZE(GET_TC(tc)->itemName);
return PyBytes_AS_STRING(GET_TC(tc)->itemName);
}

static void SetupDictIter(PyObject *dictObj, TypeContext *pc, JSONObjectEncoder *enc)
Expand Down Expand Up @@ -522,7 +514,7 @@ static void Object_beginTypeContext (JSOBJ _obj, JSONTypeContext *tc, JSONObject
return;
}
else
if (PyInt_Check(obj))
if (PyLong_Check(obj))
{
PRINTMARK();
#ifdef _LP64
Expand All @@ -533,7 +525,7 @@ static void Object_beginTypeContext (JSOBJ _obj, JSONTypeContext *tc, JSONObject
return;
}
else
if (PyString_Check(obj))
if (PyBytes_Check(obj))
{
PRINTMARK();
pc->PyTypeToJSON = PyStringToUTF8; tc->type = JT_UTF8;
Expand Down Expand Up @@ -644,7 +636,7 @@ static void Object_beginTypeContext (JSOBJ _obj, JSONTypeContext *tc, JSONObject
goto INVALID;
}

if (!PyString_Check(toJSONResult) && !PyUnicode_Check(toJSONResult))
if (!PyBytes_Check(toJSONResult) && !PyUnicode_Check(toJSONResult))
{
Py_DECREF(toJSONResult);
PyErr_Format (PyExc_TypeError, "expected string");
Expand All @@ -662,13 +654,9 @@ static void Object_beginTypeContext (JSOBJ _obj, JSONTypeContext *tc, JSONObject
PyErr_Clear();

objRepr = PyObject_Repr(obj);
#if PY_MAJOR_VERSION >= 3
PyObject* str = PyUnicode_AsEncodedString(objRepr, "utf-8", "~E~");
PyErr_Format (PyExc_TypeError, "%s is not JSON serializable", PyString_AS_STRING(str));
PyErr_Format (PyExc_TypeError, "%s is not JSON serializable", PyBytes_AS_STRING(str));
Py_XDECREF(str);
#else
PyErr_Format (PyExc_TypeError, "%s is not JSON serializable", PyString_AS_STRING(objRepr));
#endif
Py_DECREF(objRepr);

INVALID:
Expand Down Expand Up @@ -841,7 +829,7 @@ PyObject* objToJSON(PyObject* self, PyObject *args, PyObject *kwargs)
return NULL;
}

newobj = PyString_FromString (ret);
newobj = PyUnicode_FromString (ret);

if (ret != buffer)
{
Expand Down
53 changes: 0 additions & 53 deletions python/py_defines.h

This file was deleted.