Skip to content

Commit

Permalink
Merge de9633d into d8a43ac
Browse files Browse the repository at this point in the history
  • Loading branch information
Mansur908 committed Feb 29, 2024
2 parents d8a43ac + de9633d commit b6915a9
Show file tree
Hide file tree
Showing 13 changed files with 63 additions and 49 deletions.
6 changes: 4 additions & 2 deletions examples/manual_repo/basic_repo.py
Expand Up @@ -23,7 +23,7 @@

import os
import tempfile
from datetime import datetime, timedelta
from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import Any, Dict

Expand All @@ -47,7 +47,9 @@

def _in(days: float) -> datetime:
"""Adds 'days' to now and returns datetime object w/o microseconds."""
return datetime.utcnow().replace(microsecond=0) + timedelta(days=days)
return datetime.now(timezone.utc).replace(microsecond=0) + timedelta(
days=days
)


# Create top-level metadata
Expand Down
6 changes: 4 additions & 2 deletions examples/manual_repo/hashed_bin_delegation.py
Expand Up @@ -19,7 +19,7 @@
import hashlib
import os
import tempfile
from datetime import datetime, timedelta
from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import Any, Dict, Iterator, List, Tuple

Expand All @@ -38,7 +38,9 @@

def _in(days: float) -> datetime:
"""Adds 'days' to now and returns datetime object w/o microseconds."""
return datetime.utcnow().replace(microsecond=0) + timedelta(days=days)
return datetime.now(timezone.utc).replace(microsecond=0) + timedelta(
days=days
)


roles: Dict[str, Metadata[Targets]] = {}
Expand Down
6 changes: 4 additions & 2 deletions examples/manual_repo/succinct_hash_bin_delegations.py
Expand Up @@ -20,7 +20,7 @@
import math
import os
import tempfile
from datetime import datetime, timedelta
from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import Dict, Tuple

Expand Down Expand Up @@ -99,7 +99,9 @@ def create_key() -> Tuple[Key, SSlibSigner]:
# NOTE: See "Targets" and "Targets delegation" paragraphs in 'basic_repo.py'
# example for more details about the Targets object.

expiration_date = datetime.utcnow().replace(microsecond=0) + timedelta(days=7)
expiration_date = datetime.now(timezone.utc).replace(microsecond=0) + timedelta(
days=7
)
targets = Metadata(Targets(expires=expiration_date))

succinct_roles = SuccinctRoles(
Expand Down
4 changes: 2 additions & 2 deletions examples/repository/_simplerepo.py
Expand Up @@ -7,7 +7,7 @@
import json
import logging
from collections import defaultdict
from datetime import datetime, timedelta
from datetime import datetime, timedelta, timezone
from typing import Dict, List, Union

from securesystemslib import keys
Expand Down Expand Up @@ -130,7 +130,7 @@ def open(self, role: str) -> Metadata:
def close(self, role: str, md: Metadata) -> None:
"""Store a version of metadata. Handle version bumps, expiry, signing"""
md.signed.version += 1
md.signed.expires = datetime.utcnow() + self.expiry_period
md.signed.expires = datetime.now(timezone.utc) + self.expiry_period

md.signatures.clear()
for signer in self.signer_cache[role]:
Expand Down
4 changes: 2 additions & 2 deletions examples/uploader/_localrepo.py
Expand Up @@ -7,7 +7,7 @@
import json
import logging
import os
from datetime import datetime, timedelta
from datetime import datetime, timedelta, timezone
from typing import Dict

import requests
Expand Down Expand Up @@ -77,7 +77,7 @@ def open(self, role: str) -> Metadata:
def close(self, role: str, md: Metadata) -> None:
"""Store a version of metadata. Handle version bumps, expiry, signing"""
md.signed.version += 1
md.signed.expires = datetime.utcnow() + self.expiry_period
md.signed.expires = datetime.now(timezone.utc) + self.expiry_period

with open(f"{self.key_dir}/{role}", "rt", encoding="utf-8") as f:
signer = SSlibSigner(json.loads(f.read()))
Expand Down
5 changes: 2 additions & 3 deletions tests/generated_data/generate_md.py
Expand Up @@ -5,7 +5,7 @@

import os
import sys
from datetime import datetime
from datetime import UTC, datetime
from typing import Dict, List, Optional

from securesystemslib.signer import SSlibKey, SSlibSigner
Expand Down Expand Up @@ -48,8 +48,7 @@
}
)

expires_str = "2050-01-01T00:00:00Z"
EXPIRY = datetime.strptime(expires_str, "%Y-%m-%dT%H:%M:%SZ")
EXPIRY = datetime(2050, 1, 1, tzinfo=UTC)
OUT_DIR = "generated_data/ed25519_metadata"
if not os.path.exists(OUT_DIR):
os.mkdir(OUT_DIR)
Expand Down
2 changes: 1 addition & 1 deletion tests/repository_simulator.py
Expand Up @@ -124,7 +124,7 @@ def __init__(self) -> None:

self.fetch_tracker = FetchTracker()

now = datetime.datetime.utcnow()
now = datetime.datetime.now(datetime.timezone.utc)
self.safe_expiry = now.replace(microsecond=0) + datetime.timedelta(
days=30
)
Expand Down
9 changes: 5 additions & 4 deletions tests/test_api.py
Expand Up @@ -14,7 +14,7 @@
import tempfile
import unittest
from copy import copy, deepcopy
from datetime import datetime, timedelta
from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import Any, ClassVar, Dict, Optional

Expand Down Expand Up @@ -313,7 +313,8 @@ def test_metadata_signed_is_expired(self) -> None:
snapshot_path = os.path.join(self.repo_dir, "metadata", "snapshot.json")
md = Metadata.from_file(snapshot_path)

self.assertEqual(md.signed.expires, datetime(2030, 1, 1, 0, 0))
expected_expiry = datetime(2030, 1, 1, 0, 0, tzinfo=timezone.utc)
self.assertEqual(md.signed.expires, expected_expiry)

# Test is_expired with reference_time provided
is_expired = md.signed.is_expired(md.signed.expires)
Expand All @@ -326,10 +327,10 @@ def test_metadata_signed_is_expired(self) -> None:
# Test is_expired without reference_time,
# manipulating md.signed.expires
expires = md.signed.expires
md.signed.expires = datetime.utcnow()
md.signed.expires = datetime.now(timezone.utc)
is_expired = md.signed.is_expired()
self.assertTrue(is_expired)
md.signed.expires = datetime.utcnow() + timedelta(days=1)
md.signed.expires = datetime.now(timezone.utc) + timedelta(days=1)
is_expired = md.signed.is_expired()
self.assertFalse(is_expired)
md.signed.expires = expires
Expand Down
10 changes: 5 additions & 5 deletions tests/test_trusted_metadata_set.py
Expand Up @@ -4,7 +4,7 @@
import os
import sys
import unittest
from datetime import datetime
from datetime import UTC, datetime
from typing import Callable, ClassVar, Dict, List, Optional, Tuple

from securesystemslib.interface import (
Expand Down Expand Up @@ -279,7 +279,7 @@ def test_update_root_new_root_ver_same_as_trusted_root_ver(self) -> None:

def test_root_expired_final_root(self) -> None:
def root_expired_modifier(root: Root) -> None:
root.expires = datetime(1970, 1, 1)
root.expires = datetime(1970, 1, 1, tzinfo=UTC)

# intermediate root can be expired
root = self.modify_metadata(Root.type, root_expired_modifier)
Expand Down Expand Up @@ -329,7 +329,7 @@ def bump_snapshot_version(timestamp: Timestamp) -> None:
def test_update_timestamp_expired(self) -> None:
# new_timestamp has expired
def timestamp_expired_modifier(timestamp: Timestamp) -> None:
timestamp.expires = datetime(1970, 1, 1)
timestamp.expires = datetime(1970, 1, 1, tzinfo=UTC)

# expired intermediate timestamp is loaded but raises
timestamp = self.modify_metadata(
Expand Down Expand Up @@ -406,7 +406,7 @@ def test_update_snapshot_expired_new_snapshot(self) -> None:
self.trusted_set.update_timestamp(self.metadata[Timestamp.type])

def snapshot_expired_modifier(snapshot: Snapshot) -> None:
snapshot.expires = datetime(1970, 1, 1)
snapshot.expires = datetime(1970, 1, 1, tzinfo=UTC)

# expired intermediate snapshot is loaded but will raise
snapshot = self.modify_metadata(
Expand Down Expand Up @@ -486,7 +486,7 @@ def test_update_targets_expired_new_target(self) -> None:

# new_delegated_target has expired
def target_expired_modifier(target: Targets) -> None:
target.expires = datetime(1970, 1, 1)
target.expires = datetime(1970, 1, 1, tzinfo=UTC)

targets = self.modify_metadata(Targets.type, target_expired_modifier)
with self.assertRaises(exceptions.ExpiredMetadataError):
Expand Down
27 changes: 14 additions & 13 deletions tests/test_updater_top_level_update.py
Expand Up @@ -11,6 +11,7 @@
import sys
import tempfile
import unittest
from datetime import timezone
from typing import Iterable, Optional
from unittest.mock import MagicMock, Mock, call, patch

Expand Down Expand Up @@ -43,7 +44,7 @@ class TestRefresh(unittest.TestCase):
# set dump_dir to trigger repository state dumps
dump_dir: Optional[str] = None

past_datetime = datetime.datetime.utcnow().replace(
past_datetime = datetime.datetime.now(timezone.utc).replace(
microsecond=0
) - datetime.timedelta(days=5)

Expand Down Expand Up @@ -320,7 +321,7 @@ def test_expired_timestamp_version_rollback(self, mock_time: Mock) -> None:
- Second updater refresh performed on day 18:
assert that rollback check uses expired timestamp v1"""

now = datetime.datetime.utcnow()
now = datetime.datetime.now(timezone.utc)
self.sim.timestamp.expires = now + datetime.timedelta(days=7)

self.sim.timestamp.version = 2
Expand All @@ -332,9 +333,9 @@ def test_expired_timestamp_version_rollback(self, mock_time: Mock) -> None:

self.sim.timestamp.version = 1

mock_time.utcnow.return_value = (
datetime.datetime.utcnow() + datetime.timedelta(days=18)
)
mock_time.now.return_value = datetime.datetime.now(
timezone.utc
) + datetime.timedelta(days=18)
with patch("datetime.datetime", mock_time):
# Check that a rollback protection is performed even if
# local timestamp has expired
Expand All @@ -356,7 +357,7 @@ def test_expired_timestamp_snapshot_rollback(self, mock_time: Mock) -> None:
- Second updater refresh performed on day 18:
assert that rollback protection is done with expired timestamp v1"""

now = datetime.datetime.utcnow()
now = datetime.datetime.now(timezone.utc)
self.sim.timestamp.expires = now + datetime.timedelta(days=7)

# Bump the snapshot version number to 3
Expand All @@ -371,9 +372,9 @@ def test_expired_timestamp_snapshot_rollback(self, mock_time: Mock) -> None:
self.sim.update_snapshot()
self.sim.timestamp.expires = now + datetime.timedelta(days=21)

mock_time.utcnow.return_value = (
datetime.datetime.utcnow() + datetime.timedelta(days=18)
)
mock_time.now.return_value = datetime.datetime.now(
timezone.utc
) + datetime.timedelta(days=18)
with patch("datetime.datetime", mock_time):
# Assert that rollback protection is done even if
# local timestamp has expired
Expand Down Expand Up @@ -750,7 +751,7 @@ def test_expired_metadata(self, mock_time: Mock) -> None:
- Second updater refresh performed on day 18,
it is successful and timestamp/snaphot final versions are v2"""

now = datetime.datetime.utcnow()
now = datetime.datetime.now(timezone.utc)
self.sim.timestamp.expires = now + datetime.timedelta(days=7)

# Make a successful update of valid metadata which stores it in cache
Expand All @@ -762,9 +763,9 @@ def test_expired_metadata(self, mock_time: Mock) -> None:

# Mocking time so that local timestam has expired
# but the new timestamp has not
mock_time.utcnow.return_value = (
datetime.datetime.utcnow() + datetime.timedelta(days=18)
)
mock_time.now.return_value = datetime.datetime.now(
timezone.utc
) + datetime.timedelta(days=18)
with patch("datetime.datetime", mock_time):
self._run_refresh()

Expand Down
29 changes: 18 additions & 11 deletions tuf/api/_payload.py
Expand Up @@ -10,7 +10,7 @@
import io
import logging
from dataclasses import dataclass
from datetime import datetime
from datetime import datetime, timezone
from typing import (
IO,
Any,
Expand Down Expand Up @@ -60,8 +60,8 @@ class Signed(metaclass=abc.ABCMeta):
version: Metadata version number. If None, then 1 is assigned.
spec_version: Supported TUF specification version. If None, then the
version currently supported by the library is assigned.
expires: Metadata expiry date. If None, then current date and time is
assigned.
expires: Metadata expiry date in UTC timezone. If None, then current
date and time is assigned.
unrecognized_fields: Dictionary of all attributes that are not managed
by TUF Metadata API
Expand All @@ -79,16 +79,22 @@ def _type(self) -> str:

@property
def expires(self) -> datetime:
"""Get the metadata expiry date.
# Use 'datetime' module to e.g. expire in seven days from now
obj.expires = utcnow() + timedelta(days=7)
"""
"""Get the metadata expiry date."""
return self._expires

@expires.setter
def expires(self, value: datetime) -> None:
"""Set the metadata expiry date.
# Use 'datetime' module to e.g. expire in seven days from now
obj.expires = now(timezone.utc) + timedelta(days=7)
"""
self._expires = value.replace(microsecond=0)
if self._expires.tzinfo is None:
# Naive datetime: just make it UTC
self._expires = self._expires.replace(tzinfo=timezone.utc)
elif self._expires.tzinfo != timezone.utc:
raise ValueError(f"Expected tz UTC, not {self._expires.tzinfo}")

# NOTE: Signed is a stupid name, because this might not be signed yet, but
# we keep it to match spec terminology (I often refer to this as "payload",
Expand All @@ -115,7 +121,7 @@ def __init__(

self.spec_version = spec_version

self.expires = expires or datetime.utcnow()
self.expires = expires or datetime.now(timezone.utc)

if version is None:
version = 1
Expand Down Expand Up @@ -176,6 +182,7 @@ def _common_fields_from_dict(
# what the constructor expects and what we store. The inverse operation
# is implemented in '_common_fields_to_dict'.
expires = datetime.strptime(expires_str, "%Y-%m-%dT%H:%M:%SZ")
expires = expires.replace(tzinfo=timezone.utc)

return version, spec_version, expires

Expand All @@ -190,7 +197,7 @@ def _common_fields_to_dict(self) -> Dict[str, Any]:
"_type": self._type,
"version": self.version,
"spec_version": self.spec_version,
"expires": self.expires.isoformat() + "Z",
"expires": self.expires.strftime("%Y-%m-%dT%H:%M:%SZ"),
**self.unrecognized_fields,
}

Expand All @@ -205,7 +212,7 @@ def is_expired(self, reference_time: Optional[datetime] = None) -> bool:
``True`` if expiration time is less than the reference time.
"""
if reference_time is None:
reference_time = datetime.utcnow()
reference_time = datetime.now(timezone.utc)

return reference_time >= self.expires

Expand Down
2 changes: 1 addition & 1 deletion tuf/api/metadata.py
Expand Up @@ -98,7 +98,7 @@ class Metadata(Generic[T]):
New Metadata instances can be created from scratch with::
one_day = datetime.utcnow() + timedelta(days=1)
one_day = datetime.now(timezone.utc) + timedelta(days=1)
timestamp = Metadata(Timestamp(expires=one_day))
Apart from ``expires`` all of the arguments to the inner constructors have
Expand Down
2 changes: 1 addition & 1 deletion tuf/ngclient/_internal/trusted_metadata_set.py
Expand Up @@ -110,7 +110,7 @@ def __init__(self, root_data: bytes, envelope_type: EnvelopeType):
error type and content will contain more details.
"""
self._trusted_set: Dict[str, Signed] = {}
self.reference_time = datetime.datetime.utcnow()
self.reference_time = datetime.datetime.now(datetime.timezone.utc)

if envelope_type is EnvelopeType.SIMPLE:
self._load_data = _load_from_simple_envelope
Expand Down

0 comments on commit b6915a9

Please sign in to comment.