Skip to content

Commit dd9cebc

Browse files
MAINT: Update to Python 3.12 (#243)
* GHA updates * relax pandas constraint, expand tox envs * update tests for latest versions * add tox env python 3.12
1 parent 4f1493d commit dd9cebc

File tree

11 files changed

+92
-70
lines changed

11 files changed

+92
-70
lines changed

.github/workflows/build_wheels.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
fetch-depth: 0
2828

2929
# - name: Setup Python
30-
# uses: actions/setup-python@v4
30+
# uses: actions/setup-python@v5
3131
# with:
3232
# python-version: ${{ matrix.python }}
3333

@@ -77,7 +77,7 @@ jobs:
7777
with:
7878
fetch-depth: 0
7979

80-
- uses: actions/setup-python@v4
80+
- uses: actions/setup-python@v5
8181
name: Install Python
8282
with:
8383
python-version: '3.11'

.github/workflows/ci_tests_full.yml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,44 +25,47 @@ jobs:
2525
runs-on: ubuntu-latest
2626
steps:
2727
- uses: actions/checkout@v4
28-
- uses: actions/setup-python@v4
28+
- uses: actions/setup-python@v5
2929
with:
30-
python-version: "3.10"
30+
python-version: "3.11"
3131

3232
- name: flake8 Lint
3333
uses: py-actions/flake8@v2
3434

3535
tests:
36+
name: Unit Tests for ${{ matrix.python-version }} on ${{ matrix.os }}
3637
runs-on: ${{ matrix.os }}
3738
strategy:
3839
fail-fast: false
3940
matrix:
4041
os: [ubuntu-latest, windows-latest, macos-latest]
41-
python-version: ["3.8", "3.9", "3.10", "3.11"]
42+
python-version: ["3.9", "3.10", "3.11", "3.12"]
4243

4344
steps:
4445
- name: Checkout Zipline
4546
uses: actions/checkout@v4
4647

4748
- name: Set up Python ${{ matrix.python-version }}
48-
uses: actions/setup-python@v4
49+
uses: actions/setup-python@v5
4950
with:
5051
python-version: ${{ matrix.python-version }}
5152

52-
- name: Install TA-Lib Linux
53+
- name: Install TA-Lib
5354
if: ${{ matrix.os == 'ubuntu-latest' }}
5455
run: |
5556
sudo ./tools/install_talib.sh
5657
57-
- name: Install TA-Lib macOS
58+
- name: Install TA-Lib HDF5 c-blosc
5859
if: ${{ matrix.os == 'macos-latest' }}
5960
run: |
6061
brew install ta-lib
62+
brew install hdf5
63+
brew install c-blosc
6164
6265
- name: Developer Command Prompt for Microsoft Visual C++
6366
uses: ilammy/msvc-dev-cmd@v1
6467

65-
- name: Install TA-Lib Windows
68+
- name: Install TA-Lib
6669
if: ${{ matrix.os == 'windows-latest' }}
6770
run: |
6871
./tools/install_talib.bat

.github/workflows/ci_tests_quick.yml

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,15 @@ jobs:
2424
runs-on: ubuntu-latest
2525
steps:
2626
- uses: actions/checkout@v4
27-
- uses: actions/setup-python@v4
27+
- uses: actions/setup-python@v5
2828
with:
2929
python-version: "3.11"
3030

3131
- name: flake8 Lint
3232
uses: py-actions/flake8@v2
3333

3434
tests:
35+
name: Unit Tests for ${{ matrix.python-version }} on ${{ matrix.os }}
3536
runs-on: ${{ matrix.os }}
3637
strategy:
3738
fail-fast: false
@@ -44,30 +45,26 @@ jobs:
4445
uses: actions/checkout@v4
4546

4647
- name: Set up Python ${{ matrix.python-version }}
47-
uses: actions/setup-python@v4
48+
uses: actions/setup-python@v5
4849
with:
4950
python-version: ${{ matrix.python-version }}
5051

51-
- name: Install TA-Lib Linux
52+
- name: Install TA-Lib
5253
if: ${{ matrix.os == 'ubuntu-latest' }}
5354
run: |
5455
sudo ./tools/install_talib.sh
5556
56-
- name: Install TA-Lib macOS
57+
- name: Install TA-Lib HDF5 c-blosc
5758
if: ${{ matrix.os == 'macos-latest' }}
5859
run: |
5960
brew install ta-lib
60-
61-
- name: Install HDF5 macOS
62-
if: ${{ matrix.os == 'macos-latest' }}
63-
run: |
6461
brew install hdf5
6562
brew install c-blosc
6663
6764
- name: Developer Command Prompt for Microsoft Visual C++
6865
uses: ilammy/msvc-dev-cmd@v1
6966

70-
- name: Install TA-Lib Windows
67+
- name: Install TA-Lib
7168
if: ${{ matrix.os == 'windows-latest' }}
7269
run: |
7370
./tools/install_talib.bat

pyproject.toml

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ classifiers = [
1818
'License :: OSI Approved :: Apache Software License',
1919
'Natural Language :: English',
2020
'Programming Language :: Python',
21-
'Programming Language :: Python :: 3.8',
2221
'Programming Language :: Python :: 3.9',
2322
'Programming Language :: Python :: 3.10',
2423
'Programming Language :: Python :: 3.11',
24+
'Programming Language :: Python :: 3.12',
2525
'Operating System :: OS Independent',
2626
'Intended Audience :: Science/Research',
2727
'Topic :: Office/Business :: Financial :: Investment',
@@ -47,7 +47,7 @@ dependencies = [
4747
'networkx >=2.0',
4848
'numexpr >=2.6.1',
4949
'numpy >=1.14.5',
50-
'pandas >=2.0',
50+
'pandas >=1.3',
5151
'patsy >=0.4.0',
5252
'python-dateutil >=2.4.2',
5353
'python-interface >=1.5.3',
@@ -73,7 +73,8 @@ requires = [
7373
'setuptools>=42.0.0',
7474
"setuptools_scm[toml]>=6.2",
7575
'wheel>=0.36.0',
76-
'Cython>=0.29.21,<3',
76+
'Cython>=0.29.21',
77+
# 'Cython>=3',
7778
'oldest-supported-numpy; python_version>="3.8"',
7879
]
7980
build-backend = 'setuptools.build_meta'
@@ -102,7 +103,8 @@ dev = [
102103
'flake8 >=3.9.1',
103104
'black',
104105
'pre-commit >=2.12.1',
105-
'Cython>=0.29.21,<3',
106+
# 'Cython>=0.29.21,<3',
107+
'Cython>=0.29.21',
106108
]
107109
docs = [
108110
'Cython',
@@ -176,17 +178,17 @@ exclude = '''
176178
[tool.tox]
177179
legacy_tox_ini = """
178180
[tox]
179-
envlist = py{38,39,310,311}-pandas{2}
181+
envlist = py{39,310}-pandas{13,14,15}, py{39,310,311,312}-pandas{20,21,22}
180182
isolated_build = True
181183
skip_missing_interpreters = True
182184
minversion = 3.23.0
183185
184186
[gh-actions]
185187
python =
186-
3.8: py38
187188
3.9: py39
188189
3.10: py310
189190
3.11: py311
191+
3.12: py312
190192
191193
[testenv]
192194
usedevelop = True
@@ -196,7 +198,12 @@ setenv =
196198
changedir = tmp
197199
extras = test
198200
deps =
199-
pandas2: pandas>=2.0
201+
pandas13: pandas>=1.3.0,<1.4
202+
pandas14: pandas>=1.4.0,<1.5
203+
pandas15: pandas>=1.5.0,<1.6
204+
pandas20: pandas>=2.0,<2.1
205+
pandas21: pandas>=2.1,<2.2
206+
pandas22: pandas>=2.2,<2.3
200207
201208
commands =
202209
pytest -n 4 --reruns 5 --cov={toxinidir}/src --cov-report term --cov-report=xml --cov-report=html:htmlcov {toxinidir}/tests

src/zipline/algorithm.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1455,7 +1455,19 @@ def get_datetime(self, tz=None):
14551455
The current simulation datetime converted to ``tz``.
14561456
"""
14571457
dt = self.datetime
1458-
assert dt.tzinfo == timezone.utc, "Algorithm should have a utc datetime"
1458+
from packaging.version import Version
1459+
import pytz
1460+
1461+
if Version(pd.__version__) < Version("2.0.0"):
1462+
assert (
1463+
dt.tzinfo == pytz.utc
1464+
), f"Algorithm should have a pytc utc datetime, {dt.tzinfo}"
1465+
else:
1466+
assert (
1467+
dt.tzinfo == timezone.utc
1468+
), f"Algorithm should have a timezone.utc datetime, {dt.tzinfo}"
1469+
1470+
# assert dt.tzinfo == timezone.utc, "Algorithm should have a utc datetime"
14591471
if tz is not None:
14601472
dt = dt.astimezone(tz)
14611473
return dt

src/zipline/utils/pandas_utils.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
skip_pipeline_new_pandas = (
1919
"Pipeline categoricals are not yet compatible with pandas >=0.19"
2020
)
21-
skip_pipeline_blaze = "Blaze doesn't play nicely with Pandas >=1.0"
21+
# skip_pipeline_blaze = "Blaze doesn't play nicely with Pandas >=1.0"
2222

2323

2424
def july_5th_holiday_observance(datetime_index):
@@ -226,8 +226,8 @@ def categorical_df_concat(df_list, inplace=False):
226226

227227
# Assert each dataframe has the same columns/dtypes
228228
df = df_list[0]
229-
if not all([(df.dtypes.equals(df_i.dtypes)) for df_i in df_list[1:]]):
230-
raise ValueError("Input DataFrames must have the same columns/dtypes.")
229+
if not all([set(df.columns) == set(df_i.columns) for df_i in df_list[1:]]):
230+
raise ValueError("Input DataFrames must have the same columns.")
231231

232232
categorical_columns = df.columns[df.dtypes == "category"]
233233

@@ -238,7 +238,7 @@ def categorical_df_concat(df_list, inplace=False):
238238

239239
with ignore_pandas_nan_categorical_warning():
240240
for df in df_list:
241-
df[col].cat.set_categories(new_categories, inplace=True)
241+
df[col] = df[col].cat.set_categories(new_categories)
242242

243243
return pd.concat(df_list)
244244

tests/pipeline/test_factor.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from functools import partial
66
from itertools import product
77
from unittest import skipIf
8-
98
import numpy as np
109
import pandas as pd
1110
import pytest
@@ -14,7 +13,7 @@
1413
from parameterized import parameterized
1514
from scipy.stats.mstats import winsorize as scipy_winsorize
1615
from toolz import compose
17-
16+
from packaging.version import Version
1817
from zipline.errors import BadPercentileBounds, UnknownRankMethod
1918
from zipline.lib.labelarray import LabelArray
2019
from zipline.lib.normalize import naive_grouped_rowwise_apply as grouped_apply
@@ -41,6 +40,12 @@
4140

4241
from .base import BaseUSEquityPipelineTestCase
4342

43+
pandas_two_point_two = False
44+
if Version(pd.__version__) >= Version("2.2"):
45+
# pandas 2.2.0 has a bug in qcut that causes it to return a Series with
46+
# the wrong dtype when labels=False.
47+
pandas_two_point_two = True
48+
4449

4550
class F(Factor):
4651
dtype = float64_dtype
@@ -1466,6 +1471,8 @@ def test_quantiles_masked(self, seed):
14661471
mask=self.build_mask(self.ones_mask(shape=shape)),
14671472
)
14681473

1474+
# skip until https://github.com/pandas-dev/pandas/issues/58240 fixed
1475+
@skipIf(pandas_two_point_two, "pd.qcut has a bug in pandas 2.2")
14691476
def test_quantiles_uneven_buckets(self):
14701477
permute = partial(permute_rows, 5)
14711478
shape = (5, 5)

tests/pipeline/test_quarters_estimates.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from datetime import timedelta
22
from functools import partial
3-
3+
from packaging.version import Version
44
import itertools
55
from parameterized import parameterized
66
import numpy as np
@@ -238,6 +238,11 @@ def test_load_one_day(self):
238238
end_date=pd.Timestamp("2015-01-15"),
239239
)
240240

241+
# type changes to datatime[ns] in pandas 2.0.0
242+
if Version(pd.__version__) >= Version("2"):
243+
self.expected_out.event_date = self.expected_out.event_date.astype(
244+
"datetime64[ns]"
245+
)
241246
assert_frame_equal(
242247
results.sort_index(axis=1), self.expected_out.sort_index(axis=1)
243248
)
@@ -660,7 +665,6 @@ def make_loader(cls, events, columns):
660665
return PreviousEarningsEstimatesLoader(events, columns)
661666

662667
def get_expected_estimate(self, q1_knowledge, q2_knowledge, comparable_date):
663-
664668
# The expected estimate will be for q2 if the last thing
665669
# we've seen is that the release date already happened.
666670
# Otherwise, it'll be for q1, as long as the release date

tests/pipeline/test_us_equity_pricing_loader.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
from parameterized import parameterized
1919
import sys
20+
from packaging.version import Version
2021
import numpy as np
2122
from numpy.testing import (
2223
assert_allclose,
@@ -473,6 +474,9 @@ def test_load_adjustments(self, tables, adjustment_type):
473474
@parameterized.expand([(True,), (False,)])
474475
@pytest.mark.skipif(sys.platform == "win32", reason="does not run on windows")
475476
def test_load_adjustments_to_df(self, convert_dts):
477+
if Version(pd.__version__) < Version("2.0") and not convert_dts:
478+
pytest.skip("pandas < 2.0 behaves differently datetime64[s]")
479+
476480
reader = self.adjustment_reader
477481
adjustment_dfs = reader.unpack_db_to_component_dfs(convert_dates=convert_dts)
478482

0 commit comments

Comments
 (0)