Skip to content

Commit 5c6ed48

Browse files
topolaritystevengj
andauthored
Drop Python 2.x support and fix CI (#1098)
* Drop Python 2.x support and fix CI * Fix `memcpy` ABI to resolve crash on Julia `nightly` * Upgrade PackageCompiler to v2 in CI * Run `pip` under correct arch in macOS CI * Use `macos-15-intel` runner for macOS x64 * Update aot.yml: restore previous PackageCompiler cmd --------- Co-authored-by: Steven G. Johnson <stevenj@mit.edu>
1 parent 3bb48e8 commit 5c6ed48

10 files changed

Lines changed: 56 additions & 123 deletions

File tree

.github/workflows/aot.yml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,14 @@ jobs:
3737
architecture: ${{ matrix.architecture }}
3838
- run: python --version
3939
- run: python -m pip install --user numpy
40-
- name: Install libpython2.7 for `find_libpython` test
41-
run: sudo apt-get install python2.7-dev
42-
if: ${{ matrix.python-version != '2.7' && matrix.os == 'ubuntu-latest' }}
4340
- name: Setup julia
4441
uses: julia-actions/setup-julia@v2
4542
with:
4643
version: ${{ matrix.julia-version }}
4744
arch: ${{ matrix.architecture }}
4845
show-versioninfo: true
4946

50-
- name: Install PackageCompiler.jl
51-
run: using Pkg; Pkg.add("PackageCompiler", version="1")
52-
shell: julia --color=yes {0}
47+
- run: julia -e 'using Pkg; pkg"add PackageCompiler"'
5348

5449
- run: aot/compile.jl
5550
- run: aot/assert_has_pycall.jl

.github/workflows/conda.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@ jobs:
3232
${{ matrix.os }} ${{ matrix.architecture }}
3333
steps:
3434
- uses: actions/checkout@v6
35-
- name: Install libpython2.7 for `find_libpython` test
36-
run: sudo apt-get install python2.7-dev
37-
if: ${{ matrix.python-version != '2.7' && matrix.os == 'ubuntu-latest' }}
3835
- name: Setup julia
3936
uses: julia-actions/setup-julia@v2
4037
with:

.github/workflows/system.yml

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,29 @@ jobs:
1515
matrix:
1616
os:
1717
- ubuntu-latest
18-
- macos-latest
1918
- windows-latest
2019
architecture: [x64]
2120
python-version: ['3.x']
2221
julia-version:
2322
- '1'
2423
- 'nightly'
2524
include:
25+
- os: macos-latest
26+
architecture: arm64
27+
python-version: '3.x'
28+
julia-version: '1'
29+
- os: macos-latest
30+
architecture: arm64
31+
python-version: '3.x'
32+
julia-version: 'nightly'
33+
- os: macos-15-intel
34+
architecture: x64
35+
python-version: '3.x'
36+
julia-version: '1'
37+
- os: macos-15-intel
38+
architecture: x64
39+
python-version: '3.x'
40+
julia-version: 'nightly'
2641
# 32 bit Windows:
2742
- os: windows-latest
2843
architecture: x86
@@ -31,7 +46,7 @@ jobs:
3146
# Sweep python-version and julia-version only on Ubuntu:
3247
- os: ubuntu-latest
3348
architecture: x64
34-
python-version: '3.9'
49+
python-version: '3.10'
3550
julia-version: '1'
3651
- os: ubuntu-latest
3752
architecture: x64
@@ -41,16 +56,6 @@ jobs:
4156
architecture: x64
4257
python-version: '3.x'
4358
julia-version: '1.4'
44-
# Test Python 2.7 only with a few combinations (TODO: drop 2.7).
45-
# Note that it does not work in macOS:
46-
- os: ubuntu-latest
47-
architecture: x64
48-
python-version: '2.7'
49-
julia-version: '1'
50-
- os: windows-2019
51-
architecture: x64
52-
python-version: '2.7'
53-
julia-version: '1'
5459
fail-fast: false
5560
name: Test
5661
Julia ${{ matrix.julia-version }}
@@ -63,16 +68,11 @@ jobs:
6368
with:
6469
python-version: ${{ matrix.python-version }}
6570
architecture: ${{ matrix.architecture }}
66-
- run: python -m pip install --user numpy
67-
- run: python -m pip install virtualenv
68-
# virtualenv test with Python 2.7 is failing for some reason.
69-
# Skipping it for now.
70-
if: ${{ matrix.python-version != '2.7' }}
71+
- name: Install numpy
72+
run: python -m pip install --user numpy
73+
- name: Install virtualenv
74+
run: python -m pip install virtualenv
7175
- run: virtualenv --version
72-
if: ${{ matrix.python-version != '2.7' }}
73-
- name: Install libpython2.7 for `find_libpython` test
74-
run: sudo apt-get install python2.7-dev
75-
if: ${{ matrix.python-version != '2.7' && matrix.os == 'ubuntu-latest' }}
7676
- name: Setup julia
7777
uses: julia-actions/setup-julia@v2
7878
with:

deps/build.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ try # make sure deps.jl file is removed on error
4646
(Sys.isunix() && !Sys.isapple()) ?
4747
whichfirst("python3", "python") : "Conda"),
4848
vers = isempty(py) || py == "Conda" ? v"0.0" : vparse(pyconfigvar(py,"VERSION","0.0"))
49-
if vers < v"2.7"
49+
if vers < v"3.3"
5050
if isempty(py) || py == "Conda"
5151
throw(UseCondaPython())
5252
else
53-
error("Python version $vers < 2.7 is not supported")
53+
error("Python version $vers < 3.3 is not supported")
5454
end
5555
end
5656

@@ -95,8 +95,8 @@ try # make sure deps.jl file is removed on error
9595

9696
@info "PyCall is using $python (Python $pyversion) at $programname, libpython = $libpy_name"
9797

98-
if pyversion < v"2.7"
99-
error("Python 2.7 or later is required for PyCall")
98+
if pyversion < v"3.3"
99+
error("Python 3.3 or later is required for PyCall")
100100
end
101101

102102
writeifchanged("deps.jl", """

src/PyCall.jl

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -867,23 +867,9 @@ append!(a::PyObject, items::PyObject) =
867867
PyObject(@pycheckn ccall((@pysym :PySequence_InPlaceConcat),
868868
PyPtr, (PyPtr, PyPtr), a, items))
869869

870-
if pyversion >= v"3.3"
871-
function empty!(o::PyObject)
872-
pydecref(pycall(o."clear", PyObject)) # list.clear() was added in 3.3
873-
return o
874-
end
875-
else
876-
function empty!(o::PyObject)
877-
p = _getproperty(o, "clear")
878-
if p != C_NULL # for dict, set, etc.
879-
pydecref(pycall(PyObject(o)."clear", PyObject))
880-
else
881-
for i = length(o)-1:-1:0
882-
delete!(o, i)
883-
end
884-
end
885-
return o
886-
end
870+
function empty!(o::PyObject)
871+
pydecref(pycall(o."clear", PyObject)) # list.clear() was added in 3.3
872+
return o
887873
end
888874

889875
#########################################################################
@@ -932,9 +918,6 @@ https://github.com/ipython/ipython/blob/5.9.0/IPython/utils/dir2.py
932918
"""
933919
function get_real_method(obj, name)
934920
ispynull(obj) && return nothing
935-
@static if pyversion < v"3"
936-
pyisinstance(obj, @pyglobalobj :PyType_Type) && return nothing
937-
end
938921

939922
canary = try
940923
trygetproperty(obj, "_ipython_canary_method_should_not_exist_", nothing)

src/conversions.jl

Lines changed: 21 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,10 @@
55

66
# conversions from Julia types to PyObject:
77

8-
@static if pyversion < v"3"
9-
PyObject(i::Unsigned) = PyObject(@pycheckn ccall(@pysym(:PyInt_FromSize_t),
10-
PyPtr, (UInt,), i))
11-
PyObject(i::Integer) = PyObject(@pycheckn ccall(@pysym(:PyInt_FromSsize_t),
12-
PyPtr, (Int,), i))
13-
else
14-
PyObject(i::Unsigned) = PyObject(@pycheckn ccall(@pysym(:PyLong_FromUnsignedLongLong),
15-
PyPtr, (Culonglong,), i))
16-
PyObject(i::Integer) = PyObject(@pycheckn ccall(@pysym(:PyLong_FromLongLong),
17-
PyPtr, (Clonglong,), i))
18-
end
8+
PyObject(i::Unsigned) = PyObject(@pycheckn ccall(@pysym(:PyLong_FromUnsignedLongLong),
9+
PyPtr, (Culonglong,), i))
10+
PyObject(i::Integer) = PyObject(@pycheckn ccall(@pysym(:PyLong_FromLongLong),
11+
PyPtr, (Clonglong,), i))
1912

2013
PyObject(b::Bool) = PyObject(@pycheckn ccall((@pysym :PyBool_FromLong),
2114
PyPtr, (Clong,), b))
@@ -31,25 +24,17 @@ PyObject(n::Nothing) = pyerr_check("PyObject(nothing)", pyincref(pynothing[]))
3124

3225
# conversions to Julia types from PyObject
3326

34-
@static if pyversion < v"3"
35-
convert(::Type{T}, po::PyObject) where {T<:Integer} =
36-
T(@pycheck ccall(@pysym(:PyInt_AsSsize_t), Int, (PyPtr,), po))
37-
elseif pyversion < v"3.2"
38-
convert(::Type{T}, po::PyObject) where {T<:Integer} =
39-
T(@pycheck ccall(@pysym(:PyLong_AsLongLong), Clonglong, (PyPtr,), po))
40-
else
41-
function convert(::Type{T}, po::PyObject) where {T<:Integer}
42-
overflow = Ref{Cint}()
43-
val = T(@pycheck ccall(@pysym(:PyLong_AsLongLongAndOverflow), Clonglong, (PyPtr, Ref{Cint}), po, overflow))
44-
iszero(overflow[]) || throw(InexactError(:convert, T, po))
45-
return val
46-
end
47-
function convert(::Type{Integer}, po::PyObject)
48-
overflow = Ref{Cint}()
49-
val = @pycheck ccall(@pysym(:PyLong_AsLongLongAndOverflow), Clonglong, (PyPtr, Ref{Cint}), po, overflow)
50-
iszero(overflow[]) || return convert(BigInt, po)
51-
return val
52-
end
27+
function convert(::Type{T}, po::PyObject) where {T<:Integer}
28+
overflow = Ref{Cint}()
29+
val = T(@pycheck ccall(@pysym(:PyLong_AsLongLongAndOverflow), Clonglong, (PyPtr, Ref{Cint}), po, overflow))
30+
iszero(overflow[]) || throw(InexactError(:convert, T, po))
31+
return val
32+
end
33+
function convert(::Type{Integer}, po::PyObject)
34+
overflow = Ref{Cint}()
35+
val = @pycheck ccall(@pysym(:PyLong_AsLongLongAndOverflow), Clonglong, (PyPtr, Ref{Cint}), po, overflow)
36+
iszero(overflow[]) || return convert(BigInt, po)
37+
return val
5338
end
5439

5540
convert(::Type{Bool}, po::PyObject) =
@@ -78,13 +63,9 @@ end
7863

7964
function PyObject(s::AbstractString)
8065
sb = String(s)
81-
if pyunicode_literals || !isascii(sb)
82-
PyObject(@pycheckn ccall(@pysym(PyUnicode_DecodeUTF8),
83-
PyPtr, (Ptr{UInt8}, Int, Ptr{UInt8}),
84-
sb, sizeof(sb), C_NULL))
85-
else
86-
pybytes(sb)
87-
end
66+
PyObject(@pycheckn ccall(@pysym(PyUnicode_DecodeUTF8),
67+
PyPtr, (Ptr{UInt8}, Int, Ptr{UInt8}),
68+
sb, sizeof(sb), C_NULL))
8869
end
8970

9071
const _ps_ptr= Ptr{UInt8}[C_NULL]
@@ -713,16 +694,9 @@ include("pydates.jl")
713694
# A type-query function f(o::PyObject) returns the Julia type
714695
# for use with the convert function, or Union{} if there isn't one.
715696

716-
@static if pyversion < v"3"
717-
pyint_query(o::PyObject) = pyisinstance(o, @pyglobalobj :PyInt_Type) ?
718-
(pyisinstance(o, @pyglobalobj :PyBool_Type) ? Bool : Int) :
719-
pyisinstance(o, @pyglobalobj :PyLong_Type) ? BigInt :
720-
pyisinstance(o, npy_integer) ? Int : Union{}
721-
else
722-
pyint_query(o::PyObject) = pyisinstance(o, @pyglobalobj :PyLong_Type) ?
723-
(pyisinstance(o, @pyglobalobj :PyBool_Type) ? Bool : Integer) :
724-
pyisinstance(o, npy_integer) ? Integer : Union{}
725-
end
697+
pyint_query(o::PyObject) = pyisinstance(o, @pyglobalobj :PyLong_Type) ?
698+
(pyisinstance(o, @pyglobalobj :PyBool_Type) ? Bool : Integer) :
699+
pyisinstance(o, npy_integer) ? Integer : Union{}
726700

727701
pyfloat_query(o::PyObject) = pyisinstance(o, @pyglobalobj :PyFloat_Type) || pyisinstance(o, npy_floating) ? Float64 : Union{}
728702

src/pyarray.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ function copy(a::PyArray{T,N}) where {T,N}
147147
# `Array`) otherwise we do a regular `copyto!`, such that A[I...] == a[I...]
148148
A = Array{T}(undef, a.dims)
149149
if a.f_contig
150-
ccall(:memcpy, Cvoid, (Ptr{T}, Ptr{T}, Int), A, a, sizeof(T)*length(a))
150+
ccall(:memcpy, Cvoid, (Ptr{Cvoid}, Ptr{Cvoid}, Csize_t), A, a, sizeof(T)*length(a))
151151
else
152152
copyto!(A, a)
153153
end

src/pyeval.jl

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,6 @@ pynamespace(m::Module) =
1010
return PyDict{String,PyObject,true}(pyincref(@pycheckn ccall((@pysym :PyModule_GetDict), PyPtr, (PyPtr,), pyimport("__main__"))))
1111
else
1212
ns = PyDict{String,PyObject}()
13-
# In Python 2, it looks like `__builtin__` (w/o 's') must
14-
# exist at module namespace. See also:
15-
# http://mail.python.org/pipermail/python-dev/2001-April/014068.html
16-
# https://github.com/ipython/ipython/blob/512d47340c09d184e20811ca46aaa2f862bcbafe/IPython/core/interactiveshell.py#L1295-L1299
17-
if pyversion < v"3"
18-
ns["__builtin__"] = builtin
19-
end
2013
# Following CPython implementation, we introduce
2114
# `__builtins__` in the namespace. See:
2215
# https://docs.python.org/2/library/__builtin__.html

src/startup.jl

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,7 @@ else
117117
end
118118

119119
# hashes changed from long to intptr_t in Python 3.2
120-
const Py_hash_t = pyversion < v"3.2" ? Clong : Int
121-
122-
# whether to use unicode for strings by default, ala Python 3
123-
const pyunicode_literals = pyversion >= v"3.0"
120+
const Py_hash_t = Int
124121

125122
if libpython == nothing
126123
macro pysym(func)

test/runtests.jl

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ end
3131
pymodule_exists(s::AbstractString) = !ispynull(pyimport_e(s))
3232

3333
# default integer type for PyAny conversions
34-
const PyInt = pyversion < v"3" ? Int : Clonglong
34+
const PyInt = Clonglong
3535

3636
@testset "conversions" begin
3737
# conversion of NumPy scalars before npy_initialized by array conversions (#481)
@@ -193,11 +193,7 @@ const PyInt = pyversion < v"3" ? Int : Clonglong
193193
@test showable("text/html", py"Issue816()")
194194
@test !showable("text/html", py"Issue816")
195195
@test showable("text/html", py"CallableAsSpecialRepr()")
196-
if PyCall.pyversion_build < v"3"
197-
@test_broken showable("text/html", py"CallableAsSpecialRepr")
198-
else
199-
@test showable("text/html", py"CallableAsSpecialRepr")
200-
end
196+
@test showable("text/html", py"CallableAsSpecialRepr")
201197
end
202198

203199
# in Python 3, we need a specific encoding to write strings or bufferize them
@@ -279,10 +275,8 @@ const PyInt = pyversion < v"3" ? Int : Clonglong
279275
let i = BigInt(12345678901234567890), o = PyObject(i) # BigInt
280276
@test o - i == 0
281277
@test convert(BigInt, o) == i
282-
if pyversion >= v"3.2"
283-
@test PyAny(o) == i == convert(Integer, o)
284-
@test_throws InexactError convert(Int64, o)
285-
end
278+
@test PyAny(o) == i == convert(Integer, o)
279+
@test_throws InexactError convert(Int64, o)
286280
end
287281

288282
# bigfloat conversion

0 commit comments

Comments
 (0)