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 Python 3.9, require Python >= 3.10 #2132

Merged
merged 4 commits into from
May 8, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/build_lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ jobs:
python-version: "3.11"
- os: ubuntu
python-version: "3.10"
- os: ubuntu
python-version: "3.9"
# Disabled for now. See https://github.com/projectmesa/mesa/issues/1253
#- os: ubuntu
# python-version: 'pypy-3.8'
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ repos:
rev: v3.15.2
hooks:
- id: pyupgrade
args: [--py38-plus]
args: [--py310-plus]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0 # Use the ref you want to point at
hooks:
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/intro_tutorial.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"source": [
"### Tutorial Setup\n",
"\n",
"Create and activate a [virtual environment](http://docs.python-guide.org/en/latest/dev/virtualenvs/). *Python version 3.9 or higher is required*.\n",
"Create and activate a [virtual environment](http://docs.python-guide.org/en/latest/dev/virtualenvs/). *Python version 3.10 or higher is required*.\n",
"\n",
"Install Mesa:\n",
"\n",
Expand Down
4 changes: 2 additions & 2 deletions mesa/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
import warnings
import weakref
from collections import defaultdict
from collections.abc import Iterable, Iterator, MutableSet, Sequence
from collections.abc import Callable, Iterable, Iterator, MutableSet, Sequence
from random import Random

# mypy
from typing import TYPE_CHECKING, Any, Callable
from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
# We ensure that these are not imported during runtime to prevent cyclic
Expand Down
8 changes: 4 additions & 4 deletions mesa/batchrunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from collections.abc import Iterable, Mapping
from functools import partial
from multiprocessing import Pool
from typing import Any, Optional, Union
from typing import Any

from tqdm.auto import tqdm

Expand All @@ -11,9 +11,9 @@

def batch_run(
model_cls: type[Model],
parameters: Mapping[str, Union[Any, Iterable[Any]]],
parameters: Mapping[str, Any | Iterable[Any]],
# We still retain the Optional[int] because users may set it to None (i.e. use all CPUs)
number_processes: Optional[int] = 1,
number_processes: int | None = 1,
iterations: int = 1,
data_collection_period: int = -1,
max_steps: int = 1000,
Expand Down Expand Up @@ -76,7 +76,7 @@ def batch_run(


def _make_model_kwargs(
parameters: Mapping[str, Union[Any, Iterable[Any]]],
parameters: Mapping[str, Any | Iterable[Any]],
) -> list[dict[str, Any]]:
"""Create model kwargs from parameters dictionary.

Expand Down
2 changes: 1 addition & 1 deletion mesa/datacollection.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ def collect(self, model):
if self.model_reporters:
for var, reporter in self.model_reporters.items():
# Check if lambda or partial function
if isinstance(reporter, (types.LambdaType, partial)):
if isinstance(reporter, types.LambdaType | partial):
self.model_vars[var].append(reporter(model))
# Check if model attribute
elif isinstance(reporter, str):
Expand Down
4 changes: 2 additions & 2 deletions mesa/experimental/cell_space/cell_collection.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from __future__ import annotations

import itertools
from collections.abc import Iterable, Mapping
from collections.abc import Callable, Iterable, Mapping
from functools import cached_property
from random import Random
from typing import TYPE_CHECKING, Callable, Generic, TypeVar
from typing import TYPE_CHECKING, Generic, TypeVar

if TYPE_CHECKING:
from mesa.experimental.cell_space.cell import Cell
Expand Down
2 changes: 1 addition & 1 deletion mesa/experimental/cell_space/grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def _validate_parameters(self):
raise ValueError("Dimensions must be a list of positive integers.")
if not isinstance(self.torus, bool):
raise ValueError("Torus must be a boolean.")
if self.capacity is not None and not isinstance(self.capacity, (float, int)):
if self.capacity is not None and not isinstance(self.capacity, float | int):
raise ValueError("Capacity must be a number or None.")

def select_random_empty_cell(self) -> T:
Expand Down
6 changes: 3 additions & 3 deletions mesa/experimental/cell_space/network.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from random import Random
from typing import Any, Optional
from typing import Any

from mesa.experimental.cell_space.cell import Cell
from mesa.experimental.cell_space.discrete_space import DiscreteSpace
Expand All @@ -11,8 +11,8 @@ class Network(DiscreteSpace):
def __init__(
self,
G: Any, # noqa: N803
capacity: Optional[int] = None,
random: Optional[Random] = None,
capacity: int | None = None,
random: Random | None = None,
cell_klass: type[Cell] = Cell,
) -> None:
"""A Networked grid
Expand Down
3 changes: 1 addition & 2 deletions mesa/experimental/components/altair.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import contextlib
from typing import Optional

import solara

Expand All @@ -8,7 +7,7 @@


@solara.component
def SpaceAltair(model, agent_portrayal, dependencies: Optional[list[any]] = None):
def SpaceAltair(model, agent_portrayal, dependencies: list[any] | None = None):
space = getattr(model, "grid", None)
if space is None:
# Sometimes the space is defined as model.space instead of model.grid
Expand Down
8 changes: 3 additions & 5 deletions mesa/experimental/components/matplotlib.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import Optional

import networkx as nx
import solara
from matplotlib.figure import Figure
Expand All @@ -9,7 +7,7 @@


@solara.component
def SpaceMatplotlib(model, agent_portrayal, dependencies: Optional[list[any]] = None):
def SpaceMatplotlib(model, agent_portrayal, dependencies: list[any] | None = None):
space_fig = Figure()
space_ax = space_fig.subplots()
space = getattr(model, "grid", None)
Expand Down Expand Up @@ -116,7 +114,7 @@ def portray(space):


@solara.component
def PlotMatplotlib(model, measure, dependencies: Optional[list[any]] = None):
def PlotMatplotlib(model, measure, dependencies: list[any] | None = None):
fig = Figure()
ax = fig.subplots()
df = model.datacollector.get_model_vars_dataframe()
Expand All @@ -127,7 +125,7 @@ def PlotMatplotlib(model, measure, dependencies: Optional[list[any]] = None):
for m, color in measure.items():
ax.plot(df.loc[:, m], label=m, color=color)
fig.legend()
elif isinstance(measure, (list, tuple)):
elif isinstance(measure, list | tuple):
for m in measure:
ax.plot(df.loc[:, m], label=m)
fig.legend()
Expand Down
3 changes: 2 additions & 1 deletion mesa/experimental/devs/eventlist.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from __future__ import annotations

import itertools
from collections.abc import Callable
from enum import IntEnum
from heapq import heapify, heappop, heappush
from types import MethodType
from typing import Any, Callable
from typing import Any
from weakref import WeakMethod, ref


Expand Down
3 changes: 2 additions & 1 deletion mesa/experimental/devs/simulator.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from __future__ import annotations

import numbers
from typing import Any, Callable
from collections.abc import Callable
from typing import Any

from mesa import Model

Expand Down
4 changes: 2 additions & 2 deletions mesa/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
from collections import defaultdict

# mypy
from typing import Any, Union
from typing import Any

from mesa.agent import Agent, AgentSet
from mesa.datacollection import DataCollector

TimeT = Union[float, int]
TimeT = float | int


class Model:
Expand Down
10 changes: 5 additions & 5 deletions mesa/space.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
import itertools
import math
import warnings
from collections.abc import Iterable, Iterator, Sequence
from collections.abc import Callable, Iterable, Iterator, Sequence
from numbers import Real
from typing import Any, Callable, TypeVar, Union, cast, overload
from typing import Any, TypeVar, cast, overload
from warnings import warn

with contextlib.suppress(ImportError):
Expand All @@ -42,12 +42,12 @@

Coordinate = tuple[int, int]
# used in ContinuousSpace
FloatCoordinate = Union[tuple[float, float], npt.NDArray[float]]
FloatCoordinate = tuple[float, float] | npt.NDArray[float]
NetworkCoordinate = int

Position = Union[Coordinate, FloatCoordinate, NetworkCoordinate]
Position = Coordinate | FloatCoordinate | NetworkCoordinate

GridContent = Union[Agent, None]
GridContent = Agent | None
MultiGridContent = list[Agent]

F = TypeVar("F", bound=Callable[..., Any])
Expand Down
4 changes: 1 addition & 3 deletions mesa/time.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,12 @@
from collections.abc import Iterable

# mypy
from typing import Union

from mesa.agent import Agent, AgentSet
from mesa.model import Model

# BaseScheduler has a self.time of int, while
# StagedActivation has a self.time of float
TimeT = Union[float, int]
TimeT = float | int


class BaseScheduler:
Expand Down
7 changes: 3 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ build-backend = "hatchling.build"
name = "Mesa"
description = "Agent-based modeling (ABM) in Python"
license = { text = "Apache 2.0" }
requires-python = ">=3.9"
requires-python = ">=3.10"
authors = [
{ name = "Project Mesa Team", email = "projectmesa@googlegroups.com" },
]
Expand All @@ -25,7 +25,6 @@ classifiers = [
"Topic :: Scientific/Engineering :: Artificial Intelligence",
"Intended Audience :: Science/Research",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
Expand Down Expand Up @@ -81,9 +80,9 @@ path = "mesa/__init__.py"

[tool.ruff]
# See https://github.com/charliermarsh/ruff#rules for error code definitions.
# Hardcode to Python 3.9.
# Hardcode to Python 3.10.
# Reminder to update mesa-examples if the value below is changed.
target-version = "py39"
target-version = "py310"
extend-exclude = ["docs", "build"]

[tool.ruff.lint]
Expand Down
Loading