Skip to content

Commit 148eaf8

Browse files
BBBmauadeebshihadehmaxime-desroches
authored
Update to Python 3.12 (commaai#32548)
* 3.12 * pprofile is broken * use modified metadrivepy3-12 * 0.3.0 metadrive * add metadrive/commaai git dependency * metadrive git set * pin sounddevice 0.4.6 * datetime.utcnow() deprecation * poetry lock * make datetime not aware * poetry lock * pin pytools * google_crc32c wheel * unpin sounddevice * clean metadrive * use python crc * mypy * 3.12.4 * allow python3.11 * test * no pip * poetry * better * better * merge * remove * try * test * try this * snok * python * simpler * setuptools * lower * try * try * work? * ubuntu deps * ubuntu * try * remove * move * remove this * names * Update .github/workflows/tools_tests.yaml Co-authored-by: Adeeb Shihadeh <[email protected]> * python<4 * <3.13 --------- Co-authored-by: Adeeb Shihadeh <[email protected]> Co-authored-by: Maxime Desroches <[email protected]>
1 parent c2be8a5 commit 148eaf8

18 files changed

+1445
-1358
lines changed

.github/workflows/tools_tests.yaml

+19
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,25 @@ jobs:
3939
source selfdrive/test/setup_vsound.sh && \
4040
CI=1 pytest tools/sim/tests/test_metadrive_bridge.py"
4141
42+
test_python311:
43+
name: test python3.11 support
44+
runs-on: ubuntu-latest
45+
timeout-minutes: 5
46+
steps:
47+
- uses: actions/checkout@v4
48+
- name: Installing ubuntu dependencies
49+
run: INSTALL_EXTRA_PACKAGES=no tools/install_ubuntu_dependencies.sh
50+
- name: Installing python
51+
uses: actions/setup-python@v5
52+
with:
53+
python-version: '3.11.4'
54+
- name: Installing pip
55+
run: pip install pip==24.0
56+
- name: Installing poetry
57+
run: pip install poetry==1.7.0
58+
- name: Installing python dependencies
59+
run: poetry install --no-cache --no-root
60+
4261
devcontainer:
4362
name: devcontainer
4463
runs-on: ubuntu-latest

.python-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.11.4
1+
3.12.4

Dockerfile.openpilot_base

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
6464
USER $USER
6565

6666
ENV POETRY_VIRTUALENVS_CREATE=false
67-
ENV PYENV_VERSION=3.11.4
67+
ENV PYENV_VERSION=3.12.4
6868
ENV PYENV_ROOT="/home/$USER/pyenv"
6969
ENV PATH="$PYENV_ROOT/bin:$PYENV_ROOT/shims:$PATH"
7070

@@ -76,7 +76,7 @@ RUN cd /tmp && \
7676
rm -rf /tmp/* && \
7777
rm -rf /home/$USER/.cache && \
7878
find /home/$USER/pyenv -type d -name ".git" | xargs rm -rf && \
79-
rm -rf /home/$USER/pyenv/versions/3.11.4/lib/python3.11/test
79+
rm -rf /home/$USER/pyenv/versions/3.12.4/lib/python3.12/test
8080

8181
USER root
8282
RUN sudo git config --global --add safe.directory /tmp/openpilot

common/api/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import jwt
22
import os
33
import requests
4-
from datetime import datetime, timedelta
4+
from datetime import datetime, timedelta, UTC
55
from openpilot.system.hardware.hw import Paths
66
from openpilot.system.version import get_version
77

@@ -23,7 +23,7 @@ def request(self, method, endpoint, timeout=None, access_token=None, **params):
2323
return api_get(endpoint, method=method, timeout=timeout, access_token=access_token, **params)
2424

2525
def get_token(self, expiry_hours=1):
26-
now = datetime.utcnow()
26+
now = datetime.now(UTC).replace(tzinfo=None)
2727
payload = {
2828
'identity': self.dongle_id,
2929
'nbf': now,

poetry.lock

+1,399-1,333
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+3-4
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ repository = "https://github.com/commaai/openpilot"
8888
documentation = "https://docs.comma.ai"
8989

9090
[tool.poetry.dependencies]
91-
python = "~3.11"
91+
python = ">=3.11, <3.13"
9292

9393
# multiple users
9494
sounddevice = "*" # micd + soundd
@@ -154,15 +154,14 @@ inputs = "*"
154154
Jinja2 = "*"
155155
lru-dict = "*"
156156
matplotlib = "*"
157-
# No release for this fix https://github.com/metadriverse/metadrive/issues/632. Pinned to this commit until next release
158-
metadrive-simulator = {git = "https://github.com/metadriverse/metadrive.git", rev ="233a3a1698be7038ec3dd050ca10b547b4b3324c", markers = "platform_machine != 'aarch64'" } # no linux/aarch64 wheels for certain dependencies
157+
metadrive-simulator = { git = "https://github.com/commaai/metadrive.git", branch = "python3.12", markers = "platform_machine != 'aarch64'" } # no linux/aarch64 wheels for certain dependencies
159158
mpld3 = "*"
160159
mypy = "*"
161160
myst-parser = "*"
162161
natsort = "*"
163162
opencv-python-headless = "*"
164163
parameterized = "^0.8"
165-
pprofile = "*"
164+
#pprofile = "*"
166165
polyline = "*"
167166
pre-commit = "*"
168167
pyautogui = "*"

selfdrive/test/test_updated.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ def _check_update_state(self, update_available):
164164
# make sure LastUpdateTime is recent
165165
t = self._read_param("LastUpdateTime")
166166
last_update_time = datetime.datetime.fromisoformat(t)
167-
td = datetime.datetime.utcnow() - last_update_time
167+
td = datetime.datetime.now(datetime.UTC).replace(tzinfo=None) - last_update_time
168168
assert td.total_seconds() < 10
169169
self.params.remove("LastUpdateTime")
170170

system/athena/registration.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import jwt
55
from pathlib import Path
66

7-
from datetime import datetime, timedelta
7+
from datetime import datetime, timedelta, UTC
88
from openpilot.common.api import api_get
99
from openpilot.common.params import Params
1010
from openpilot.common.spinner import Spinner
@@ -66,7 +66,7 @@ def register(show_spinner=False) -> str | None:
6666
start_time = time.monotonic()
6767
while True:
6868
try:
69-
register_token = jwt.encode({'register': True, 'exp': datetime.utcnow() + timedelta(hours=1)}, private_key, algorithm='RS256')
69+
register_token = jwt.encode({'register': True, 'exp': datetime.now(UTC).replace(tzinfo=None) + timedelta(hours=1)}, private_key, algorithm='RS256')
7070
cloudlog.info("getting pilotauth")
7171
resp = api_get("v2/pilotauth/", method='POST', timeout=15,
7272
imei=imei1, imei2=imei2, serial=serial, public_key=public_key, register_token=register_token)

system/manager/manager.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def manager_init() -> None:
4242
("LongitudinalPersonality", str(log.LongitudinalPersonality.standard)),
4343
]
4444
if not PC:
45-
default_params.append(("LastUpdateTime", datetime.datetime.utcnow().isoformat().encode('utf8')))
45+
default_params.append(("LastUpdateTime", datetime.datetime.now(datetime.UTC).replace(tzinfo=None).isoformat().encode('utf8')))
4646

4747
if params.get_bool("RecordFrontLock"):
4848
params.put_bool("RecordFront", True)

system/qcomgpsd/qcomgpsd.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ def setup_quectel(diag: ModemDiag) -> bool:
173173
os.remove(ASSIST_DATA_FILE)
174174
#at_cmd("AT+QGPSXTRADATA?")
175175
if system_time_valid():
176-
time_str = datetime.datetime.utcnow().strftime("%Y/%m/%d,%H:%M:%S")
176+
time_str = datetime.datetime.now(datetime.UTC).replace(tzinfo=None).strftime("%Y/%m/%d,%H:%M:%S")
177177
at_cmd(f"AT+QGPSXTRATIME=0,\"{time_str}\",1,1,1000")
178178

179179
at_cmd("AT+QGPSCFG=\"outport\",\"usbnmea\"")

system/qcomgpsd/tests/test_qcomgpsd.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def check_assistance(self, should_be_loaded):
8585
if should_be_loaded:
8686
assert valid_duration == "10080" # should be max time
8787
injected_time = datetime.datetime.strptime(injected_time_str.replace("\"", ""), "%Y/%m/%d,%H:%M:%S")
88-
assert abs((datetime.datetime.utcnow() - injected_time).total_seconds()) < 60*60*12
88+
assert abs((datetime.datetime.now(datetime.UTC).replace(tzinfo=None) - injected_time).total_seconds()) < 60*60*12
8989
else:
9090
valid_duration, injected_time_str = out.split(",", 1)
9191
injected_time_str = injected_time_str.replace('\"', '').replace('\'', '')

system/statsd.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def get_influxdb_line(measurement: str, value: float | dict[str, float], timest
133133
# flush when started state changes or after FLUSH_TIME_S
134134
if (time.monotonic() > last_flush_time + STATS_FLUSH_TIME_S) or (sm['deviceState'].started != started_prev):
135135
result = ""
136-
current_time = datetime.utcnow().replace(tzinfo=UTC)
136+
current_time = datetime.now(UTC)
137137
tags['started'] = sm['deviceState'].started
138138

139139
for key, value in gauges.items():

system/ubloxd/pigeond.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import struct
77
import requests
88
import urllib.parse
9-
from datetime import datetime
9+
from datetime import datetime, UTC
1010

1111
from cereal import messaging
1212
from openpilot.common.params import Params
@@ -196,7 +196,7 @@ def initialize_pigeon(pigeon: TTYPigeon) -> bool:
196196
cloudlog.error(f"failed to restore almanac backup, status: {restore_status}")
197197

198198
# sending time to ublox
199-
t_now = datetime.utcnow()
199+
t_now = datetime.now(UTC).replace(tzinfo=None)
200200
if t_now >= datetime(2021, 6, 1):
201201
cloudlog.warning("Sending current time to ublox")
202202

system/updated/updated.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def sleep(self, t: float) -> None:
6060
self.ready_event.wait(timeout=t)
6161

6262
def write_time_to_param(params, param) -> None:
63-
t = datetime.datetime.utcnow()
63+
t = datetime.datetime.now(datetime.UTC).replace(tzinfo=None)
6464
params.put(param, t.isoformat().encode('utf8'))
6565

6666
def read_time_from_param(params, param) -> datetime.datetime | None:
@@ -279,7 +279,7 @@ def set_params(self, update_success: bool, failed_count: int, exception: str | N
279279
if len(self.branches):
280280
self.params.put("UpdaterAvailableBranches", ','.join(self.branches.keys()))
281281

282-
last_update = datetime.datetime.utcnow()
282+
last_update = datetime.datetime.now(datetime.UTC).replace(tzinfo=None)
283283
if update_success:
284284
write_time_to_param(self.params, "LastUpdateTime")
285285
else:
@@ -323,7 +323,7 @@ def get_description(basedir: str) -> str:
323323
for alert in ("Offroad_UpdateFailed", "Offroad_ConnectivityNeeded", "Offroad_ConnectivityNeededPrompt"):
324324
set_offroad_alert(alert, False)
325325

326-
now = datetime.datetime.utcnow()
326+
now = datetime.datetime.now(datetime.UTC).replace(tzinfo=None)
327327
dt = now - last_update
328328
build_metadata = get_build_metadata()
329329
if failed_count > 15 and exception is not None and self.has_internet:
@@ -429,7 +429,7 @@ def main() -> None:
429429
cloudlog.event("update installed")
430430

431431
if not params.get("InstallDate"):
432-
t = datetime.datetime.utcnow().isoformat()
432+
t = datetime.datetime.now(datetime.UTC).replace(tzinfo=None).isoformat()
433433
params.put("InstallDate", t.encode('utf8'))
434434

435435
updater = Updater()
@@ -469,7 +469,7 @@ def main() -> None:
469469

470470
# download update
471471
last_fetch = read_time_from_param(params, "UpdaterLastFetchTime")
472-
timed_out = last_fetch is None or (datetime.datetime.utcnow() - last_fetch > datetime.timedelta(days=3))
472+
timed_out = last_fetch is None or (datetime.datetime.now(datetime.UTC).replace(tzinfo=None) - last_fetch > datetime.timedelta(days=3))
473473
user_requested_fetch = wait_helper.user_request == UserRequest.FETCH
474474
if params.get_bool("NetworkMetered") and not timed_out and not user_requested_fetch:
475475
cloudlog.info("skipping fetch, connection metered")

system/webrtc/tests/test_stream_session.py

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# for aiortc and its dependencies
44
import warnings
55
warnings.filterwarnings("ignore", category=DeprecationWarning)
6+
warnings.filterwarnings("ignore", category=RuntimeWarning) # TODO: remove this when google-crc32c publish a python3.12 wheel
67

78
from aiortc import RTCDataChannel
89
from aiortc.mediastreams import VIDEO_CLOCK_RATE, VIDEO_TIME_BASE

system/webrtc/tests/test_webrtcd.py

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# for aiortc and its dependencies
55
import warnings
66
warnings.filterwarnings("ignore", category=DeprecationWarning)
7+
warnings.filterwarnings("ignore", category=RuntimeWarning) # TODO: remove this when google-crc32c publish a python3.12 wheel
78

89
from openpilot.system.webrtc.webrtcd import get_stream
910

system/webrtc/webrtcd.py

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# aiortc and its dependencies have lots of internal warnings :(
1212
import warnings
1313
warnings.filterwarnings("ignore", category=DeprecationWarning)
14+
warnings.filterwarnings("ignore", category=RuntimeWarning) # TODO: remove this when google-crc32c publish a python3.12 wheel
1415

1516
import capnp
1617
from aiohttp import web

tools/lib/azure_container.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import os
2-
from datetime import datetime, timedelta
2+
from datetime import datetime, timedelta, UTC
33
from functools import lru_cache
44
from pathlib import Path
55
from typing import IO
@@ -20,7 +20,7 @@ def get_azure_credential():
2020
@lru_cache
2121
def get_container_sas(account_name: str, container_name: str):
2222
from azure.storage.blob import BlobServiceClient, ContainerSasPermissions, generate_container_sas
23-
start_time = datetime.utcnow()
23+
start_time = datetime.now(UTC).replace(tzinfo=None)
2424
expiry_time = start_time + timedelta(hours=1)
2525
blob_service = BlobServiceClient(
2626
account_url=f"https://{account_name}.blob.core.windows.net",

0 commit comments

Comments
 (0)