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

fix datetime utc warning #323

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
31 changes: 9 additions & 22 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#
# This file is part of Invenio.
# Copyright (C) 2020 CERN.
# Copyright (C) 2022 Graz University of Technology.
# Copyright (C) 2022-2024 Graz University of Technology.
#
# Invenio is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.
Expand All @@ -29,55 +29,42 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
python-version: [3.8, 3.9]
requirements-level: [pypi]
python-version: [3.9, 3.12]
db-service: [postgresql14, mysql8]
include:
- db-service: postgresql14
DB: postgresql
POSTGRESQL_VERSION: POSTGRESQL_14_LATEST
SQLALCHEMY_DATABASE_URI: "postgresql+psycopg2://invenio:invenio@localhost:5432/invenio"
EXTRAS: "tests,postgresql"

- db-service: mysql8
DB: mysql
MYSQL_VERSION: MYSQL_8_LATEST
SQLALCHEMY_DATABASE_URI: "mysql+pymysql://invenio:invenio@localhost:3306/invenio"
EXTRAS: "tests,mysql"

env:
SQLALCHEMY_DATABASE_URI: ${{matrix.SQLALCHEMY_DATABASE_URI}}
POSTGRESQL_VERSION: ${{matrix.POSTGRESQL_VERSION}}
MYSQL_VERSION: ${{matrix.MYSQL_VERSION}}
DB: ${{ matrix.DB }}
EXTRAS: tests,admin,${{ matrix.DB }}

steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Generate dependencies
run: |
pip install wheel requirements-builder
requirements-builder -e ${{ matrix.EXTRAS }} --level=${{ matrix.requirements-level }} setup.py > .${{ matrix.requirements-level }}-${{ matrix.python-version }}-requirements.txt

- name: Cache pip
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('.${{ matrix.requirements-level }}-${{ matrix.python-version }}-requirements.txt') }}
cache: pip
cache-dependency-path: setup.cfg

- name: Install dependencies
run: |
pip install -r .${{matrix.requirements-level}}-${{ matrix.python-version }}-requirements.txt
pip install .[${{ matrix.EXTRAS }}]
pip install .[$EXTRAS]
pip freeze
docker --version
docker-compose --version
docker version

- name: Run tests
run: |
Expand Down
5 changes: 3 additions & 2 deletions invenio_records/dumpers/indexedat.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#
# This file is part of Invenio.
# Copyright (C) 2022 CERN.
# Copyright (C) 2024 Graz University of Technology.
#
# Invenio is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.
Expand All @@ -11,7 +12,7 @@
Dumper used to dump/load the indexed time of a record to/from a search engine body.
"""

import arrow
from datetime import datetime, timezone

from .search import SearchDumperExt

Expand All @@ -25,7 +26,7 @@ def __init__(self, key="indexed_at"):

def dump(self, record, data):
"""Dump relations."""
data[self.key] = arrow.utcnow().isoformat()
data[self.key] = datetime.now(timezone.utc).isoformat()

def load(self, data, record_cls):
"""Load (remove) indexed data."""
Expand Down
6 changes: 3 additions & 3 deletions invenio_records/dumpers/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#
# This file is part of Invenio.
# Copyright (C) 2020 CERN.
# Copyright (C) 2024 Graz University of Technology.
#
# Invenio is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.
Expand All @@ -15,9 +16,8 @@
from uuid import UUID

import arrow
import pytz
from invenio_db import db
from sqlalchemy.sql.sqltypes import JSON, Boolean, DateTime, Integer, String, Text
from sqlalchemy.sql.sqltypes import JSON, Boolean, DateTime, Integer, String
from sqlalchemy.sql.type_api import Variant
from sqlalchemy_utils.types.uuid import UUIDType

Expand Down Expand Up @@ -96,7 +96,7 @@ def _serialize(value, dump_type):
if value is None:
return value
if dump_type in (datetime,):
return pytz.utc.localize(value).isoformat()
return value.isoformat()
elif dump_type in (UUID,):
return str(value)
elif dump_type is not None:
Expand Down
11 changes: 6 additions & 5 deletions invenio_records/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#
# This file is part of Invenio.
# Copyright (C) 2015-2020 CERN.
# Copyright (C) 2024 Graz University of Technology.
#
# Invenio is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.
Expand All @@ -10,7 +11,7 @@

import uuid
from copy import deepcopy
from datetime import datetime
from datetime import datetime, timezone

from invenio_db import db
from sqlalchemy.dialects import mysql, postgresql
Expand All @@ -19,7 +20,7 @@
from sqlalchemy_utils.types import JSONType, UUIDType


class Timestamp(object):
class Timestamp:
"""Timestamp model mix-in with fractional seconds support.

SQLAlchemy-Utils timestamp model does not have support for fractional
Expand All @@ -28,20 +29,20 @@ class Timestamp(object):

created = db.Column(
db.DateTime().with_variant(mysql.DATETIME(fsp=6), "mysql"),
default=datetime.utcnow,
default=lambda: datetime.now(timezone.utc),
nullable=False,
)
updated = db.Column(
db.DateTime().with_variant(mysql.DATETIME(fsp=6), "mysql"),
default=datetime.utcnow,
default=lambda: datetime.now(timezone.utc),
nullable=False,
)


@db.event.listens_for(Timestamp, "before_update", propagate=True)
def timestamp_before_update(mapper, connection, target):
"""Update `updated` property with current time on `before_update` event."""
target.updated = datetime.utcnow()
target.updated = datetime.now(timezone.utc)


class RecordMetadataBase(Timestamp):
Expand Down
3 changes: 2 additions & 1 deletion invenio_records/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# This file is part of Invenio.
# Copyright (C) 2015-2018 CERN.
# Copyright (C) 2021 TU Wien.
# Copyright (C) 2024 Graz University of Technology.
#
# Invenio is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.
Expand All @@ -11,7 +12,7 @@

from jsonschema.validators import Draft4Validator, extend, validator_for

PartialDraft4Validator = extend(Draft4Validator, {"required": None})
PartialDraft4Validator = extend(Draft4Validator, {"required": lambda *_: None})
"""Partial JSON Schema (draft 4) validator.

Special validator that contains the same validation rules of Draft4Validator,
Expand Down
9 changes: 0 additions & 9 deletions requirements-devel.txt

This file was deleted.

14 changes: 0 additions & 14 deletions requirements-docs.txt

This file was deleted.

3 changes: 1 addition & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ install_requires =

[options.extras_require]
tests =
pytest-black>=0.3.0
invenio-admin>=1.4.0,<2.0.0
pytest-black-ng>=0.3.0
pytest-invenio>=2.1.0,<3.0.0
pytest-mock>=1.6.0
sphinx>=4.5.0
Expand Down
13 changes: 8 additions & 5 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#
# This file is part of Invenio.
# Copyright (C) 2015-2018 CERN.
# Copyright (C) 2024 Graz University of Technology.
#
# Invenio is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.
Expand All @@ -11,7 +12,7 @@

import copy
import uuid
from datetime import datetime, timedelta
from datetime import datetime, timedelta, timezone

import pytest
from jsonresolver import JSONResolver
Expand All @@ -22,13 +23,12 @@

from invenio_records import Record
from invenio_records.errors import MissingModelError
from invenio_records.models import RecordMetadata
from invenio_records.validators import PartialDraft4Validator


def strip_ms(dt):
"""Strip microseconds."""
return dt - timedelta(microseconds=dt.microsecond)
return (dt - timedelta(microseconds=dt.microsecond)).replace(tzinfo=None)


def test_get_records(testapp, db):
Expand Down Expand Up @@ -61,17 +61,20 @@ def test_revision_id_created_updated_properties(testapp, db):
assert record.revision_id == 0
dt_c = record.created
assert dt_c
assert strip_ms(record.created) == strip_ms(dt_c)
dt_u = record.updated
assert dt_u
record["title"] = "test 2"
record.commit()
db.session.commit()

assert record.revision_id == 1
assert strip_ms(record.created) == strip_ms(dt_c)
assert strip_ms(record.updated) >= strip_ms(dt_u)

assert dt_u.tzinfo is None
utcnow = datetime.utcnow()
# Why was that necessary to test?
# assert dt_u.tzinfo is None
utcnow = datetime.now(timezone.utc)
assert dt_u > utcnow - timedelta(seconds=10)
assert dt_u < utcnow + timedelta(seconds=10)

Expand Down
9 changes: 6 additions & 3 deletions tests/test_systemfields.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# This file is part of Invenio.
# Copyright (C) 2020 CERN.
# Copyright (C) 2021 RERO.
# Copyright (C) 2024 Graz University of Technology.
#
# Invenio is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.
Expand Down Expand Up @@ -247,14 +248,16 @@ def test_extension_post_create(testapp, db, ExtensionRecord):

def test_extension_pre_dump(testapp, db, ExtensionRecord):
"""Test pre dump hook."""
rec = ExtensionRecord({}).dumps()
with pytest.deprecated_call():
rec = ExtensionRecord({}).dumps()
assert ExtensionRecord.ext.called == ["pre_init", "post_init", "pre_dump"]


def test_extension_post_load(testapp, db, ExtensionRecord):
"""Test post load hook."""
dump = ExtensionRecord({}).dumps()
rec = ExtensionRecord.loads(dump)
with pytest.deprecated_call():
dump = ExtensionRecord({}).dumps()
rec = ExtensionRecord.loads(dump)
assert ExtensionRecord.ext.called == [
"pre_init",
"post_init",
Expand Down