mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-14 21:43:01 +00:00
avoid deprecated datetime.utcnow
deprecated in Python 3.12 replace with equivalent utils.utcnow(with_tz=False)
This commit is contained in:
@@ -12,17 +12,21 @@ branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
|
||||
|
||||
def utcnow():
|
||||
return datetime.now(timezone.utc)._replace(tzinfo=None)
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.add_column('users', sa.Column('created', sa.DateTime, nullable=True))
|
||||
c = op.get_bind()
|
||||
# fill created date with current time
|
||||
now = datetime.utcnow()
|
||||
now = utcnow()
|
||||
c.execute(
|
||||
"""
|
||||
UPDATE users
|
||||
|
@@ -2,7 +2,6 @@
|
||||
# Copyright (c) Jupyter Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
import json
|
||||
from datetime import datetime
|
||||
from unittest import mock
|
||||
from urllib.parse import parse_qsl, quote, urlencode, urlparse, urlunparse
|
||||
|
||||
@@ -10,7 +9,7 @@ from oauthlib import oauth2
|
||||
from tornado import web
|
||||
|
||||
from .. import orm, roles, scopes
|
||||
from ..utils import get_browser_protocol, token_authenticated
|
||||
from ..utils import get_browser_protocol, token_authenticated, utcnow
|
||||
from .base import APIHandler, BaseHandler
|
||||
|
||||
|
||||
@@ -39,7 +38,7 @@ class TokenAPIHandler(APIHandler):
|
||||
self.parsed_scopes = scopes.parse_scopes(self.expanded_scopes)
|
||||
|
||||
# record activity whenever we see a token
|
||||
now = orm_token.last_activity = datetime.utcnow()
|
||||
now = orm_token.last_activity = utcnow(with_tz=False)
|
||||
if orm_token.user:
|
||||
orm_token.user.last_activity = now
|
||||
model = self.user_model(self.users[orm_token.user])
|
||||
|
@@ -4,7 +4,7 @@
|
||||
import asyncio
|
||||
import inspect
|
||||
import json
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from datetime import timedelta, timezone
|
||||
|
||||
from async_generator import aclosing
|
||||
from dateutil.parser import parse as parse_date
|
||||
@@ -23,6 +23,7 @@ from ..utils import (
|
||||
maybe_future,
|
||||
url_escape_path,
|
||||
url_path_join,
|
||||
utcnow,
|
||||
)
|
||||
from .base import APIHandler
|
||||
|
||||
@@ -367,7 +368,7 @@ class UserTokenListAPIHandler(APIHandler):
|
||||
if not user:
|
||||
raise web.HTTPError(404, "No such user: %s" % user_name)
|
||||
|
||||
now = datetime.utcnow()
|
||||
now = utcnow(with_tz=False)
|
||||
api_tokens = []
|
||||
|
||||
def sort_key(token):
|
||||
@@ -843,7 +844,7 @@ def _parse_timestamp(timestamp):
|
||||
# strip timezone info to naive UTC datetime
|
||||
dt = dt.astimezone(timezone.utc).replace(tzinfo=None)
|
||||
|
||||
now = datetime.utcnow()
|
||||
now = utcnow(with_tz=False)
|
||||
if (dt - now) > timedelta(minutes=59):
|
||||
raise web.HTTPError(
|
||||
400,
|
||||
|
@@ -96,6 +96,7 @@ from .utils import (
|
||||
subdomain_hook_idna,
|
||||
subdomain_hook_legacy,
|
||||
url_path_join,
|
||||
utcnow,
|
||||
)
|
||||
|
||||
common_aliases = {
|
||||
@@ -2093,7 +2094,7 @@ class JupyterHub(Application):
|
||||
# we don't want to allow user.created to be undefined,
|
||||
# so initialize it to last_activity (if defined) or now.
|
||||
if not user.created:
|
||||
user.created = user.last_activity or datetime.utcnow()
|
||||
user.created = user.last_activity or utcnow(with_tz=False)
|
||||
db.commit()
|
||||
|
||||
# The allowed_users set and the users in the db are now the same.
|
||||
@@ -3273,7 +3274,7 @@ class JupyterHub(Application):
|
||||
routes = await self.proxy.get_all_routes()
|
||||
users_count = 0
|
||||
active_users_count = 0
|
||||
now = datetime.utcnow()
|
||||
now = utcnow(with_tz=False)
|
||||
for prefix, route in routes.items():
|
||||
route_data = route['data']
|
||||
if 'user' not in route_data:
|
||||
|
@@ -10,7 +10,7 @@ import re
|
||||
import time
|
||||
import uuid
|
||||
import warnings
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import timedelta
|
||||
from http.client import responses
|
||||
from urllib.parse import parse_qs, parse_qsl, urlencode, urlparse, urlunparse
|
||||
|
||||
@@ -47,6 +47,7 @@ from ..utils import (
|
||||
maybe_future,
|
||||
url_escape_path,
|
||||
url_path_join,
|
||||
utcnow,
|
||||
)
|
||||
|
||||
# pattern for the authentication token header
|
||||
@@ -293,7 +294,7 @@ class BaseHandler(RequestHandler):
|
||||
recorded (bool): True if activity was recorded, False if not.
|
||||
"""
|
||||
if timestamp is None:
|
||||
timestamp = datetime.utcnow()
|
||||
timestamp = utcnow(with_tz=False)
|
||||
resolution = self.settings.get("activity_resolution", 0)
|
||||
if not obj.last_activity or resolution == 0:
|
||||
self.log.debug("Recording first activity for %s", obj)
|
||||
@@ -381,7 +382,7 @@ class BaseHandler(RequestHandler):
|
||||
orm_token = self.get_token()
|
||||
if orm_token is None:
|
||||
return None
|
||||
now = datetime.utcnow()
|
||||
now = utcnow(with_tz=False)
|
||||
recorded = self._record_activity(orm_token, now)
|
||||
if orm_token.user:
|
||||
# FIXME: scopes should give us better control than this
|
||||
|
@@ -14,7 +14,7 @@ from tornado.httputil import url_concat
|
||||
from .. import __version__
|
||||
from ..metrics import SERVER_POLL_DURATION_SECONDS, ServerPollStatus
|
||||
from ..scopes import needs_scope
|
||||
from ..utils import maybe_future, url_escape_path, url_path_join
|
||||
from ..utils import maybe_future, url_escape_path, url_path_join, utcnow
|
||||
from .base import BaseHandler
|
||||
|
||||
|
||||
@@ -484,7 +484,7 @@ class TokenPageHandler(BaseHandler):
|
||||
def sort_key(token):
|
||||
return (token.last_activity or never, token.created or never)
|
||||
|
||||
now = datetime.utcnow()
|
||||
now = utcnow(with_tz=False)
|
||||
|
||||
# group oauth client tokens by client id
|
||||
all_tokens = defaultdict(list)
|
||||
|
@@ -4,7 +4,8 @@
|
||||
import enum
|
||||
import json
|
||||
from base64 import decodebytes, encodebytes
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import timedelta
|
||||
from functools import partial
|
||||
|
||||
import alembic.command
|
||||
import alembic.config
|
||||
@@ -40,10 +41,10 @@ from sqlalchemy.pool import StaticPool
|
||||
from sqlalchemy.types import LargeBinary, Text, TypeDecorator
|
||||
from tornado.log import app_log
|
||||
|
||||
from .utils import compare_token, hash_token, new_token, random_port
|
||||
from .utils import compare_token, hash_token, new_token, random_port, utcnow
|
||||
|
||||
# top-level variable for easier mocking in tests
|
||||
utcnow = datetime.utcnow
|
||||
utcnow = partial(utcnow, with_tz=False)
|
||||
|
||||
|
||||
class JSONDict(TypeDecorator):
|
||||
@@ -278,7 +279,7 @@ class User(Base):
|
||||
return {s.name: s for s in self._orm_spawners}
|
||||
|
||||
admin = Column(Boolean(create_constraint=False), default=False)
|
||||
created = Column(DateTime, default=datetime.utcnow)
|
||||
created = Column(DateTime, default=utcnow)
|
||||
last_activity = Column(DateTime, nullable=True)
|
||||
|
||||
api_tokens = relationship(
|
||||
@@ -665,8 +666,8 @@ class APIToken(Hashed, Base):
|
||||
session_id = Column(Unicode(255), nullable=True)
|
||||
|
||||
# token metadata for bookkeeping
|
||||
now = datetime.utcnow # for expiry
|
||||
created = Column(DateTime, default=datetime.utcnow)
|
||||
now = utcnow # for expiry
|
||||
created = Column(DateTime, default=utcnow)
|
||||
expires_at = Column(DateTime, default=None, nullable=True)
|
||||
last_activity = Column(DateTime)
|
||||
note = Column(Unicode(1023))
|
||||
@@ -855,7 +856,7 @@ class OAuthCode(Expiring, Base):
|
||||
|
||||
@staticmethod
|
||||
def now():
|
||||
return datetime.utcnow().timestamp()
|
||||
return utcnow(with_tz=True).timestamp()
|
||||
|
||||
@classmethod
|
||||
def find(cls, db, code):
|
||||
|
@@ -4,11 +4,11 @@ Run with old versions of jupyterhub to test upgrade/downgrade
|
||||
|
||||
used in test_db.py
|
||||
"""
|
||||
from datetime import datetime
|
||||
from functools import partial
|
||||
|
||||
import jupyterhub
|
||||
from jupyterhub import orm
|
||||
from jupyterhub.utils import utcnow
|
||||
|
||||
|
||||
def populate_db(url):
|
||||
@@ -117,10 +117,11 @@ def populate_db(url):
|
||||
assert user.created
|
||||
assert admin.created
|
||||
# set last_activity
|
||||
user.last_activity = datetime.utcnow()
|
||||
now = utcnow().replace(tzinfo=None)
|
||||
user.last_activity = now
|
||||
spawner = user.orm_spawners['']
|
||||
spawner.started = datetime.utcnow()
|
||||
spawner.last_activity = datetime.utcnow()
|
||||
spawner.started = now
|
||||
spawner.last_activity = now
|
||||
db.commit()
|
||||
|
||||
|
||||
|
@@ -2444,7 +2444,7 @@ async def test_update_server_activity(app, user, server_name, fresh):
|
||||
# we use naive utc internally
|
||||
# initialize last_activity for one named and the default server
|
||||
for name in ("", "exists"):
|
||||
user.spawners[name].orm_spawner.last_activity = now.replace(tzinfo=None)
|
||||
user.spawners[name].orm_spawner.last_activity = internal_now
|
||||
app.db.commit()
|
||||
|
||||
td = timedelta(minutes=1)
|
||||
|
@@ -3,7 +3,7 @@
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
import os
|
||||
import socket
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import timedelta
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
@@ -11,6 +11,7 @@ import pytest
|
||||
from .. import crypto, objects, orm, roles
|
||||
from ..emptyclass import EmptyClass
|
||||
from ..user import User
|
||||
from ..utils import utcnow
|
||||
from .mocking import MockSpawner
|
||||
|
||||
|
||||
@@ -121,7 +122,7 @@ def test_token_expiry(db):
|
||||
user = orm.User(name='parker')
|
||||
db.add(user)
|
||||
db.commit()
|
||||
now = datetime.utcnow()
|
||||
now = utcnow(with_tz=False)
|
||||
token = user.new_api_token(expires_in=60)
|
||||
orm_token = orm.APIToken.find(db, token=token)
|
||||
assert orm_token
|
||||
@@ -506,7 +507,7 @@ def test_expiring_api_token(app, user):
|
||||
assert found is orm_token
|
||||
|
||||
with mock.patch.object(
|
||||
orm.APIToken, 'now', lambda: datetime.utcnow() + timedelta(seconds=60)
|
||||
orm.APIToken, 'now', lambda: utcnow(with_tz=False) + timedelta(seconds=60)
|
||||
):
|
||||
found = orm.APIToken.find(db, token)
|
||||
assert found is None
|
||||
|
@@ -3,7 +3,7 @@
|
||||
import json
|
||||
import warnings
|
||||
from collections import defaultdict
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import timedelta
|
||||
from urllib.parse import quote, urlparse
|
||||
|
||||
from sqlalchemy import inspect
|
||||
@@ -25,6 +25,7 @@ from .utils import (
|
||||
subdomain_hook_legacy,
|
||||
url_escape_path,
|
||||
url_path_join,
|
||||
utcnow,
|
||||
)
|
||||
|
||||
# detailed messages about the most common failure-to-start errors,
|
||||
@@ -757,7 +758,7 @@ class User:
|
||||
# update spawner start time, and activity for both spawner and user
|
||||
self.last_activity = (
|
||||
spawner.orm_spawner.started
|
||||
) = spawner.orm_spawner.last_activity = datetime.utcnow()
|
||||
) = spawner.orm_spawner.last_activity = utcnow(with_tz=False)
|
||||
db.commit()
|
||||
# wait for spawner.start to return
|
||||
# run optional preparation work to bootstrap the notebook
|
||||
@@ -964,7 +965,9 @@ class User:
|
||||
status = await spawner.poll()
|
||||
if status is None:
|
||||
await spawner.stop()
|
||||
self.last_activity = spawner.orm_spawner.last_activity = datetime.utcnow()
|
||||
self.last_activity = spawner.orm_spawner.last_activity = utcnow(
|
||||
with_tz=False
|
||||
)
|
||||
# remove server entry from db
|
||||
spawner.server = None
|
||||
if not spawner.will_resume:
|
||||
|
@@ -654,9 +654,18 @@ async def iterate_until(deadline_future, generator):
|
||||
continue
|
||||
|
||||
|
||||
def utcnow():
|
||||
"""Return timezone-aware utcnow"""
|
||||
return datetime.now(timezone.utc)
|
||||
def utcnow(*, with_tz=True):
|
||||
"""Return utcnow
|
||||
|
||||
with_tz (default): returns tz-aware datetime in UTC
|
||||
|
||||
if with_tz=False, returns UTC timestamp without tzinfo
|
||||
(used for most internal timestamp storage because databases often don't preserve tz info)
|
||||
"""
|
||||
now = datetime.now(timezone.utc)
|
||||
if not with_tz:
|
||||
now = now.replace(tzinfo=None)
|
||||
return now
|
||||
|
||||
|
||||
def _parse_accept_header(accept):
|
||||
|
Reference in New Issue
Block a user