Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Cleanup old support for Python 3.6 and earlier code
Numba set the minimum required Python version to 3.7 in 7bdd800.
  • Loading branch information
jamesobutler committed Aug 7, 2022
commit 71799724b21b262945573aeafb6b47b09825f8a7
37 changes: 8 additions & 29 deletions numba/core/byteflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -1104,35 +1104,14 @@ def op_MAKE_FUNCTION(self, state, inst, MAKE_CLOSURE=False):
name = state.pop()
code = state.pop()
closure = annotations = kwdefaults = defaults = None
if PYVERSION < (3, 6):
num_posdefaults = inst.arg & 0xFF
num_kwdefaults = (inst.arg >> 8) & 0xFF
num_annotations = (inst.arg >> 16) & 0x7FFF
if MAKE_CLOSURE:
closure = state.pop()
if num_annotations > 0:
annotations = state.pop()
if num_kwdefaults > 0:
kwdefaults = []
for i in range(num_kwdefaults):
v = state.pop()
k = state.pop()
kwdefaults.append((k, v))
kwdefaults = tuple(kwdefaults)
if num_posdefaults:
defaults = []
for i in range(num_posdefaults):
defaults.append(state.pop())
defaults = tuple(defaults)
else:
if inst.arg & 0x8:
closure = state.pop()
if inst.arg & 0x4:
annotations = state.pop()
if inst.arg & 0x2:
kwdefaults = state.pop()
if inst.arg & 0x1:
defaults = state.pop()
if inst.arg & 0x8:
closure = state.pop()
if inst.arg & 0x4:
annotations = state.pop()
if inst.arg & 0x2:
kwdefaults = state.pop()
if inst.arg & 0x1:
defaults = state.pop()
res = state.make_temp()
state.append(
inst,
Expand Down
6 changes: 2 additions & 4 deletions numba/core/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -669,10 +669,8 @@ def define_objectmode_pipeline(state, name='object'):
pm.add_pass(PreLowerStripPhis, "remove phis nodes")
pm.add_pass(IRProcessing, "processing IR")

if utils.PYVERSION >= (3, 7):
# The following passes are needed to adjust for looplifting
pm.add_pass(CanonicalizeLoopEntry, "canonicalize loop entry")
pm.add_pass(CanonicalizeLoopExit, "canonicalize loop exit")
pm.add_pass(CanonicalizeLoopEntry, "canonicalize loop entry")
pm.add_pass(CanonicalizeLoopExit, "canonicalize loop exit")

pm.add_pass(ObjectModeFrontEnd, "object mode frontend")
pm.add_pass(InlineClosureLikes,
Expand Down
131 changes: 46 additions & 85 deletions numba/core/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import logging
import textwrap

from numba.core import errors, dataflow, controlflow, ir, config
from numba.core import errors, ir, config
from numba.core.errors import NotDefinedError, UnsupportedError, error_extras
from numba.core.ir_utils import get_definition, guard
from numba.core.utils import (PYVERSION, BINOPS_TO_OPERATORS,
Expand Down Expand Up @@ -1306,23 +1306,12 @@ def interpret(self, bytecode):
global_scope = ir.Scope(parent=None, loc=self.loc)
self.scopes.append(global_scope)

if PYVERSION < (3, 7):
# Control flow analysis
self.cfa = controlflow.ControlFlowAnalysis(bytecode)
self.cfa.run()
if config.DUMP_CFG:
self.cfa.dump()

# Data flow analysis
self.dfa = dataflow.DataFlowAnalysis(self.cfa)
self.dfa.run()
else:
flow = Flow(bytecode)
flow.run()
self.dfa = AdaptDFA(flow)
self.cfa = AdaptCFA(flow)
if config.DUMP_CFG:
self.cfa.dump()
flow = Flow(bytecode)
flow.run()
self.dfa = AdaptDFA(flow)
self.cfa = AdaptCFA(flow)
if config.DUMP_CFG:
self.cfa.dump()

# Temp states during interpretation
self.current_block = None
Expand Down Expand Up @@ -2125,77 +2114,49 @@ def op_BEGIN_FINALLY(self, inst, temps):
self.store(const_none, name=tmp)
self._exception_vars.add(tmp)

if PYVERSION < (3, 6):

def op_CALL_FUNCTION(self, inst, func, args, kws, res, vararg):
func = self.get(func)
args = [self.get(x) for x in args]
if vararg is not None:
vararg = self.get(vararg)

# Process keywords
keyvalues = []
removethese = []
for k, v in kws:
k, v = self.get(k), self.get(v)
for inst in self.current_block.body:
if isinstance(inst, ir.Assign) and inst.target is k:
removethese.append(inst)
keyvalues.append((inst.value.value, v))

# Remove keyword constant statements
for inst in removethese:
def op_CALL_FUNCTION(self, inst, func, args, res):
func = self.get(func)
args = [self.get(x) for x in args]
expr = ir.Expr.call(func, args, (), loc=self.loc)
self.store(expr, res)

def op_CALL_FUNCTION_KW(self, inst, func, args, names, res):
func = self.get(func)
args = [self.get(x) for x in args]
# Find names const
names = self.get(names)
for inst in self.current_block.body:
if isinstance(inst, ir.Assign) and inst.target is names:
self.current_block.remove(inst)
# scan up the block looking for the values, remove them
# and find their name strings
named_items = []
for x in inst.value.items:
for y in self.current_block.body[::-1]:
if x == y.target:
self.current_block.remove(y)
named_items.append(y.value.value)
break
keys = named_items
break

expr = ir.Expr.call(func, args, keyvalues, loc=self.loc,
vararg=vararg)
self.store(expr, res)
nkeys = len(keys)
posvals = args[:-nkeys]
kwvals = args[-nkeys:]
keyvalues = list(zip(keys, kwvals))

op_CALL_FUNCTION_VAR = op_CALL_FUNCTION
else:
def op_CALL_FUNCTION(self, inst, func, args, res):
func = self.get(func)
args = [self.get(x) for x in args]
expr = ir.Expr.call(func, args, (), loc=self.loc)
self.store(expr, res)

def op_CALL_FUNCTION_KW(self, inst, func, args, names, res):
func = self.get(func)
args = [self.get(x) for x in args]
# Find names const
names = self.get(names)
for inst in self.current_block.body:
if isinstance(inst, ir.Assign) and inst.target is names:
self.current_block.remove(inst)
# scan up the block looking for the values, remove them
# and find their name strings
named_items = []
for x in inst.value.items:
for y in self.current_block.body[::-1]:
if x == y.target:
self.current_block.remove(y)
named_items.append(y.value.value)
break
keys = named_items
break
expr = ir.Expr.call(func, posvals, keyvalues, loc=self.loc)
self.store(expr, res)

nkeys = len(keys)
posvals = args[:-nkeys]
kwvals = args[-nkeys:]
keyvalues = list(zip(keys, kwvals))

expr = ir.Expr.call(func, posvals, keyvalues, loc=self.loc)
self.store(expr, res)

def op_CALL_FUNCTION_EX(self, inst, func, vararg, varkwarg, res):
func = self.get(func)
vararg = self.get(vararg)
if varkwarg is not None:
varkwarg = self.get(varkwarg)
expr = ir.Expr.call(
func, [], [], loc=self.loc, vararg=vararg, varkwarg=varkwarg
)
self.store(expr, res)
def op_CALL_FUNCTION_EX(self, inst, func, vararg, varkwarg, res):
func = self.get(func)
vararg = self.get(vararg)
if varkwarg is not None:
varkwarg = self.get(varkwarg)
expr = ir.Expr.call(
func, [], [], loc=self.loc, vararg=vararg, varkwarg=varkwarg
)
self.store(expr, res)

def _build_tuple_unpack(self, inst, tuples, temps, is_assign):
first = self.get(tuples[0])
Expand Down
13 changes: 6 additions & 7 deletions numba/cpython/unicode.py
Original file line number Diff line number Diff line change
Expand Up @@ -1919,14 +1919,13 @@ def impl(a):
return impl


if utils.PYVERSION >= (3, 7):
@overload_method(types.UnicodeType, 'isascii')
def unicode_isascii(data):
"""Implements UnicodeType.isascii()"""
@overload_method(types.UnicodeType, 'isascii')
def unicode_isascii(data):
"""Implements UnicodeType.isascii()"""

def impl(data):
return data._is_ascii
return impl
def impl(data):
return data._is_ascii
return impl


@overload_method(types.UnicodeType, 'istitle')
Expand Down
14 changes: 3 additions & 11 deletions numba/misc/gdb_print_extension.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
"""gdb printing extension for Numba types.
"""
import re
import sys
_PYVERSION = sys.version_info[:2]

try:
import gdb.printing
Expand Down Expand Up @@ -177,16 +175,10 @@ def to_string(self):
# This needs sorting out, encoding is wrong
this_proc = gdb.selected_inferior()
mem = this_proc.read_memory(int(data), nitems * kind)
if _PYVERSION < (3, 0):
try:
buf = unicode(mem, 'utf-8') # noqa F821
except UnicodeDecodeError as e:
buf = "ERROR: %s" % str(e)
if isinstance(mem, memoryview):
buf = bytes(mem).decode()
else:
if isinstance(mem, memoryview):
buf = bytes(mem).decode()
else:
buf = mem.decode('utf-8')
buf = mem.decode('utf-8')
else:
buf = str(data)
return "'%s'" % buf
Expand Down
7 changes: 1 addition & 6 deletions numba/tests/test_unicode.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from itertools import permutations

from numba import njit
from numba.core import types, utils
from numba.core import types
import unittest
from numba.tests.support import (TestCase, no_pyobj_flags, MemoryLeakMixin)
from numba.core.errors import TypingError, UnsupportedError
Expand All @@ -12,9 +12,6 @@
from numba.extending import overload


_py37_or_later = utils.PYVERSION >= (3, 7)


def isascii(s):
return all(ord(c) < 128 for c in s)

Expand Down Expand Up @@ -2147,8 +2144,6 @@ def pyfunc(x):
for s in UNICODE_EXAMPLES + [''] + extras + cpython:
self.assertEqual(pyfunc(s), cfunc(s), msg=msg.format(s))

@unittest.skipUnless(_py37_or_later,
'isascii method requires Python 3.7 or later')
def test_isascii(self):
def pyfunc(x):
return x.isascii()
Expand Down
5 changes: 1 addition & 4 deletions numba/tests/test_unicode_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@

import unittest
from numba import jit, from_dtype
from numba.core import types, utils
from numba.core import types
from numba.typed import Dict
from numba.tests.support import (TestCase, skip_ppc64le_issue4563)

require_py37 = unittest.skipIf(utils.PYVERSION < (3, 7), "requires Python 3.7+")


def getitem(x, i):
return x[i]
Expand Down Expand Up @@ -555,7 +553,6 @@ def test_contains_getitem2(self):
self._test(pyfunc, cfunc, x, 0, y, ())
self._test(pyfunc, cfunc, y, (), x, 0)

@require_py37
def test_return_isascii(self):
pyfunc = return_isascii
cfunc = jit(nopython=True)(pyfunc)
Expand Down