From 1056c73cba0a47d4b885e7fbde4419f4750f4f1c Mon Sep 17 00:00:00 2001 From: Joachim Metz Date: Sun, 31 May 2020 13:00:15 +0200 Subject: [PATCH] Added type annotations --- .gitignore | 3 + .travis.yml | 9 +- config/dpkg/changelog | 4 +- config/dpkg/control | 4 +- config/travis/install.sh | 8 +- .../travis/{run_pylint.sh => run_checks.sh} | 24 ++- config/travis/runtests.sh | 8 +- dfdatetime/__init__.py | 2 +- dfdatetime/apfs_time.py | 14 +- dfdatetime/cocoa_time.py | 38 +++-- dfdatetime/decorators.py | 12 +- dfdatetime/delphi_date_time.py | 35 ++-- dfdatetime/fake_time.py | 29 ++-- dfdatetime/fat_date_time.py | 33 ++-- dfdatetime/filetime.py | 31 ++-- dfdatetime/hfs_time.py | 31 ++-- dfdatetime/interface.py | 148 +++++++++-------- dfdatetime/java_time.py | 12 +- dfdatetime/ole_automation_date.py | 35 ++-- dfdatetime/posix_time.py | 102 ++++++------ dfdatetime/precisions.py | 33 ++-- dfdatetime/rfc2579_date_time.py | 52 +++--- dfdatetime/semantic_time.py | 70 ++++---- dfdatetime/systemtime.py | 44 ++--- dfdatetime/time_elements.py | 153 ++++++++++-------- dfdatetime/uuid_time.py | 25 +-- dfdatetime/webkit_time.py | 32 ++-- setup.py | 4 +- tests/interface.py | 5 +- 29 files changed, 567 insertions(+), 433 deletions(-) rename config/travis/{run_pylint.sh => run_checks.sh} (61%) diff --git a/.gitignore b/.gitignore index 8f5c09b3..cccac58b 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,9 @@ # Pycharm files /.idea +# Type check files +/.mypy_cache + # Test coverage files .coverage tests-coverage.txt diff --git a/.travis.yml b/.travis.yml index c6fd335a..ece58929 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ dist: bionic jobs: include: - name: "Pylint on Ubuntu Bionic (20.04) (Docker) with Python 3.8" - env: [TARGET="pylint", UBUNTU_VERSION="20.04"] + env: [TARGET="lint_and_type_check", UBUNTU_VERSION="20.04"] group: edge language: python python: 3.8 @@ -39,13 +39,6 @@ jobs: python: 3.8 services: - docker - - name: "Ubuntu Focal (20.04) (Docker) with Python 3.5 (tox)" - env: [TOXENV="py35", UBUNTU_VERSION="20.04"] - group: edge - language: python - python: 3.5 - services: - - docker - name: "Ubuntu Focal (20.04) (Docker) with Python 3.6 (tox)" env: [TOXENV="py36", UBUNTU_VERSION="20.04"] group: edge diff --git a/config/dpkg/changelog b/config/dpkg/changelog index 7faf6a8b..8a9173f9 100644 --- a/config/dpkg/changelog +++ b/config/dpkg/changelog @@ -1,5 +1,5 @@ -dfdatetime (20200501-1) unstable; urgency=low +dfdatetime (20200601-1) unstable; urgency=low * Auto-generated - -- Log2Timeline maintainers Fri, 01 May 2020 13:44:09 +0200 \ No newline at end of file + -- Log2Timeline maintainers Mon, 01 Jun 2020 07:47:13 +0200 \ No newline at end of file diff --git a/config/dpkg/control b/config/dpkg/control index 0e84d9a5..958cc966 100644 --- a/config/dpkg/control +++ b/config/dpkg/control @@ -2,9 +2,9 @@ Source: dfdatetime Section: python Priority: extra Maintainer: Log2Timeline maintainers -Build-Depends: debhelper (>= 9), dh-python, python3-all (>= 3.5~), python3-setuptools +Build-Depends: debhelper (>= 9), dh-python, python3-all (>= 3.6~), python3-setuptools Standards-Version: 4.1.4 -X-Python3-Version: >= 3.5 +X-Python3-Version: >= 3.6 Homepage: https://github.com/log2timeline/dfdatetime Package: python3-dfdatetime diff --git a/config/travis/install.sh b/config/travis/install.sh index 2ba7ff91..1438b6c2 100755 --- a/config/travis/install.sh +++ b/config/travis/install.sh @@ -37,9 +37,9 @@ then else RPM_PACKAGES=""; - if test ${TARGET} = "pylint"; + if test ${TARGET} = "lint_and_type_check"; then - RPM_PACKAGES="${RPM_PACKAGES} findutils pylint"; + RPM_PACKAGES="${RPM_PACKAGES} findutils pylint python3-mypy"; fi RPM_PACKAGES="${RPM_PACKAGES} python3 ${RPM_PYTHON3_DEPENDENCIES} ${RPM_PYTHON3_TEST_DEPENDENCIES}"; fi @@ -87,9 +87,9 @@ then then DPKG_PACKAGES="${DPKG_PACKAGES} sudo"; - elif test ${TARGET} = "pylint"; + elif test ${TARGET} = "lint_and_type_check"; then - DPKG_PACKAGES="${DPKG_PACKAGES} python3-distutils pylint"; + DPKG_PACKAGES="${DPKG_PACKAGES} mypy pylint python3-distutils"; fi if test "${TARGET}" != "jenkins3"; then diff --git a/config/travis/run_pylint.sh b/config/travis/run_checks.sh similarity index 61% rename from config/travis/run_pylint.sh rename to config/travis/run_checks.sh index a6f63d4f..e419ba41 100755 --- a/config/travis/run_pylint.sh +++ b/config/travis/run_checks.sh @@ -1,12 +1,14 @@ #!/bin/bash # -# Script to run pylint on Travis-CI. +# Script to run lint and type checks on Travis-CI. # # This file is generated by l2tdevtools update-dependencies.py, any dependency # related changes should be made in dependencies.ini. -# Exit on error. -set -e; +EXIT_SUCCESS=0; +EXIT_FAILURE=1; + +RESULT=${EXIT_SUCCESS}; pylint --version @@ -19,4 +21,20 @@ do echo "Checking: ${FILE}"; pylint --rcfile=.pylintrc ${FILE}; + + if test $? -ne ${EXIT_SUCCESS}; + then + RESULT=${EXIT_FAILURE}; + fi done + +mypy --version + +mypy --strict dfdatetime; + +if test $? -ne ${EXIT_SUCCESS}; +then + RESULT=${EXIT_FAILURE}; +fi + +exit ${RESULT}; diff --git a/config/travis/runtests.sh b/config/travis/runtests.sh index 7301061a..5190df6e 100755 --- a/config/travis/runtests.sh +++ b/config/travis/runtests.sh @@ -17,9 +17,9 @@ then then TEST_COMMAND="tox -e ${TOXENV}"; - elif test "${TARGET}" = "pylint"; + elif test "${TARGET}" = "lint_and_type_check"; then - TEST_COMMAND="./config/travis/run_pylint.sh"; + TEST_COMMAND="./config/travis/run_checks.sh"; else TEST_COMMAND="./config/travis/run_python3.sh"; fi @@ -51,9 +51,9 @@ then then TEST_COMMAND="./config/jenkins/linux/run_end_to_end_tests_py3.sh travis"; - elif test "${TARGET}" = "pylint"; + elif test "${TARGET}" = "lint_and_type_check"; then - TEST_COMMAND="./config/travis/run_pylint.sh"; + TEST_COMMAND="./config/travis/run_checks.sh"; else TEST_COMMAND="./config/travis/run_python3.sh"; fi diff --git a/dfdatetime/__init__.py b/dfdatetime/__init__.py index 90abc7cc..242b1e54 100644 --- a/dfdatetime/__init__.py +++ b/dfdatetime/__init__.py @@ -5,4 +5,4 @@ objects to preserve accuracy and precision. """ -__version__ = '20200501' +__version__ = '20200601' diff --git a/dfdatetime/apfs_time.py b/dfdatetime/apfs_time.py index 9b637da2..a6ddee7d 100644 --- a/dfdatetime/apfs_time.py +++ b/dfdatetime/apfs_time.py @@ -5,6 +5,8 @@ import decimal +from typing import Union # pylint: disable=unused-import + from dfdatetime import definitions from dfdatetime import posix_time @@ -19,14 +21,14 @@ class APFSTime(posix_time.PosixTimeInNanoseconds): is_local_time (bool): True if the date and time value is in local time. """ - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> 'Union[decimal.Decimal, None]': """Retrieves the normalized timestamp. Returns: decimal.Decimal: normalized timestamp, which contains the number of - seconds since January 1, 1970 00:00:00 and a fraction of second used - for increased precision, or None if the normalized timestamp cannot be - determined. + seconds since January 1, 1970 00:00:00 and a fraction of second + used for increased precision, or None if the normalized timestamp + cannot be determined. """ if self._normalized_timestamp is None: if (self._timestamp is not None and self._timestamp >= self._INT64_MIN and @@ -37,7 +39,7 @@ def _GetNormalizedTimestamp(self): return self._normalized_timestamp - def CopyFromDateTimeString(self, time_string): + def CopyFromDateTimeString(self, time_string: 'str') -> 'None': """Copies a APFS timestamp from a date and time string. Args: @@ -58,7 +60,7 @@ def CopyFromDateTimeString(self, time_string): self._timestamp > self._INT64_MAX): raise ValueError('Date time value not supported.') - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the APFS timestamp to a date and time string. Returns: diff --git a/dfdatetime/cocoa_time.py b/dfdatetime/cocoa_time.py index b3d96291..aaed103e 100644 --- a/dfdatetime/cocoa_time.py +++ b/dfdatetime/cocoa_time.py @@ -5,6 +5,8 @@ import decimal +from typing import Optional, Union # pylint: disable=unused-import + from dfdatetime import definitions from dfdatetime import interface @@ -12,7 +14,7 @@ class CocoaTimeEpoch(interface.DateTimeEpoch): """Cocoa time epoch.""" - def __init__(self): + def __init__(self) -> 'None': """Initializes a Cocoa time epoch.""" super(CocoaTimeEpoch, self).__init__(2001, 1, 1) @@ -32,32 +34,33 @@ class CocoaTime(interface.DateTimeValues): is_local_time (bool): True if the date and time value is in local time. """ # The difference between January 1, 2001 and January 1, 1970 in seconds. - _COCOA_TO_POSIX_BASE = -978307200 + _COCOA_TO_POSIX_BASE: 'int' = -978307200 - _EPOCH = CocoaTimeEpoch() + _EPOCH: 'interface.DateTimeEpoch' = CocoaTimeEpoch() - def __init__(self, timestamp=None): + def __init__(self, timestamp: 'Optional[float]' = None) -> 'None': """Initializes a Cocoa timestamp. Args: timestamp (Optional[float]): Cocoa timestamp. """ super(CocoaTime, self).__init__() - self._precision = definitions.PRECISION_1_SECOND - self._timestamp = timestamp + self._precision: 'str' = definitions.PRECISION_1_SECOND + self._timestamp: 'Union[float, None]' = timestamp @property - def timestamp(self): + def timestamp(self) -> 'Union[float, None]': """float: Cocoa timestamp or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> 'Union[decimal.Decimal, None]': """Retrieves the normalized timestamp. Returns: - float: normalized timestamp, which contains the number of seconds since - January 1, 1970 00:00:00 and a fraction of second used for increased - precision, or None if the normalized timestamp cannot be determined. + decimal.Decimal: normalized timestamp, which contains the number of + seconds since January 1, 1970 00:00:00 and a fraction of second + used for increased precision, or None if the normalized timestamp + cannot be determined. """ if self._normalized_timestamp is None: if self._timestamp is not None: @@ -66,7 +69,7 @@ def _GetNormalizedTimestamp(self): return self._normalized_timestamp - def CopyFromDateTimeString(self, time_string): + def CopyFromDateTimeString(self, time_string: 'str') -> 'None': """Copies a Cocoa timestamp from a date and time string. Args: @@ -92,11 +95,12 @@ def CopyFromDateTimeString(self, time_string): microseconds = date_time_values.get('microseconds', None) time_zone_offset = date_time_values.get('time_zone_offset', 0) - timestamp = self._GetNumberOfSecondsFromElements( - year, month, day_of_month, hours, minutes, seconds, time_zone_offset) - timestamp += self._COCOA_TO_POSIX_BASE + number_of_seconds = self._GetNumberOfSecondsFromElements( + year, month, day_of_month, hours, minutes, seconds, + time_zone_offset=time_zone_offset) + number_of_seconds += self._COCOA_TO_POSIX_BASE - timestamp = float(timestamp) + timestamp = float(number_of_seconds) if microseconds is not None: timestamp += float(microseconds) / definitions.MICROSECONDS_PER_SECOND @@ -104,7 +108,7 @@ def CopyFromDateTimeString(self, time_string): self._timestamp = timestamp self._time_zone_offset = time_zone_offset - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the Cocoa timestamp to a date and time string. Returns: diff --git a/dfdatetime/decorators.py b/dfdatetime/decorators.py index 4c9147ff..ff7184a1 100644 --- a/dfdatetime/decorators.py +++ b/dfdatetime/decorators.py @@ -4,12 +4,20 @@ from __future__ import unicode_literals import warnings +import typing +from typing import Any, Callable # pylint: disable=unused-import -def deprecated(function): # pylint: disable=invalid-name + +# pylint: disable=invalid-name +RETURN_TYPE = typing.TypeVar('RETURN_TYPE') + + +def deprecated( + function: 'Callable[..., RETURN_TYPE]') -> 'Callable[..., RETURN_TYPE]': """Decorator to mark functions or methods as deprecated.""" - def IssueDeprecationWarning(*args, **kwargs): + def IssueDeprecationWarning(*args: 'Any', **kwargs: 'Any') -> 'RETURN_TYPE': """Issue a deprecation warning.""" warnings.simplefilter('default', DeprecationWarning) warnings.warn('Call to deprecated function: {0:s}.'.format( diff --git a/dfdatetime/delphi_date_time.py b/dfdatetime/delphi_date_time.py index 01ad9747..52933a10 100644 --- a/dfdatetime/delphi_date_time.py +++ b/dfdatetime/delphi_date_time.py @@ -5,6 +5,8 @@ import decimal +from typing import Optional, Union # pylint: disable=unused-import + from dfdatetime import definitions from dfdatetime import interface @@ -12,7 +14,7 @@ class DelphiDateTimeEpoch(interface.DateTimeEpoch): """Delphi TDateTime epoch.""" - def __init__(self): + def __init__(self) -> 'None': """Initializes a Delphi TDateTime epoch.""" super(DelphiDateTimeEpoch, self).__init__(1899, 12, 30) @@ -34,33 +36,33 @@ class DelphiDateTime(interface.DateTimeValues): is_local_time (bool): True if the date and time value is in local time. """ # The difference between December 30, 1899 and January 1, 1970 in days. - _DELPHI_TO_POSIX_BASE = 25569 + _DELPHI_TO_POSIX_BASE: 'int' = 25569 - _EPOCH = DelphiDateTimeEpoch() + _EPOCH: 'interface.DateTimeEpoch' = DelphiDateTimeEpoch() - def __init__(self, timestamp=None): + def __init__(self, timestamp: 'Optional[float]' = None) -> 'None': """Initializes a Delphi TDateTime timestamp. Args: timestamp (Optional[float]): Delphi TDateTime timestamp. """ super(DelphiDateTime, self).__init__() - self._precision = definitions.PRECISION_1_MILLISECOND - self._timestamp = timestamp + self._precision: 'str' = definitions.PRECISION_1_MILLISECOND + self._timestamp: 'Union[float, None]' = timestamp @property - def timestamp(self): + def timestamp(self) -> 'Union[float, None]': """float: Delphi TDateTime timestamp or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> 'Union[decimal.Decimal, None]': """Retrieves the normalized timestamp. Returns: decimal.Decimal: normalized timestamp, which contains the number of - seconds since January 1, 1970 00:00:00 and a fraction of second used - for increased precision, or None if the normalized timestamp cannot be - determined. + seconds since January 1, 1970 00:00:00 and a fraction of second + used for increased precision, or None if the normalized timestamp + cannot be determined. """ if self._normalized_timestamp is None: if self._timestamp is not None: @@ -70,7 +72,7 @@ def _GetNormalizedTimestamp(self): return self._normalized_timestamp - def CopyFromDateTimeString(self, time_string): + def CopyFromDateTimeString(self, time_string: 'str') -> 'None': """Copies a Delphi TDateTime timestamp from a string. Args: @@ -99,10 +101,11 @@ def CopyFromDateTimeString(self, time_string): if year > 9999: raise ValueError('Unsupported year value: {0:d}.'.format(year)) - timestamp = self._GetNumberOfSecondsFromElements( - year, month, day_of_month, hours, minutes, seconds, time_zone_offset) + number_of_seconds = self._GetNumberOfSecondsFromElements( + year, month, day_of_month, hours, minutes, seconds, + time_zone_offset=time_zone_offset) - timestamp = float(timestamp) / definitions.SECONDS_PER_DAY + timestamp = float(number_of_seconds) / definitions.SECONDS_PER_DAY timestamp += self._DELPHI_TO_POSIX_BASE if microseconds is not None: timestamp += float(microseconds) / definitions.MICROSECONDS_PER_DAY @@ -111,7 +114,7 @@ def CopyFromDateTimeString(self, time_string): self._timestamp = timestamp self._time_zone_offset = time_zone_offset - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the Delphi TDateTime timestamp to a date and time string. Returns: diff --git a/dfdatetime/fake_time.py b/dfdatetime/fake_time.py index 691a17b7..85ff92d4 100644 --- a/dfdatetime/fake_time.py +++ b/dfdatetime/fake_time.py @@ -6,6 +6,8 @@ import decimal import time +from typing import Union # pylint: disable=unused-import + from dfdatetime import definitions from dfdatetime import interface from dfdatetime import posix_time @@ -21,38 +23,38 @@ class FakeTime(interface.DateTimeValues): is_local_time (bool): True if the date and time value is in local time. """ - _EPOCH = posix_time.PosixTimeEpoch() + _EPOCH: 'interface.DateTimeEpoch' = posix_time.PosixTimeEpoch() - def __init__(self): + def __init__(self) -> 'None': """Initializes a fake timestamp.""" # Note that time.time() and divmod return floating point values. timestamp, fraction_of_second = divmod(time.time(), 1) super(FakeTime, self).__init__() - self._microseconds = int( + self._microseconds: 'Union[int, None]' = int( fraction_of_second * definitions.MICROSECONDS_PER_SECOND) - self._number_of_seconds = int(timestamp) - self._precision = definitions.PRECISION_1_MICROSECOND + self._number_of_seconds: 'int' = int(timestamp) + self._precision: 'str' = definitions.PRECISION_1_MICROSECOND - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> 'Union[decimal.Decimal, None]': """Retrieves the normalized timestamp. Returns: decimal.Decimal: normalized timestamp, which contains the number of - seconds since January 1, 1970 00:00:00 and a fraction of second used - for increased precision, or None if the normalized timestamp cannot be - determined. + seconds since January 1, 1970 00:00:00 and a fraction of second + used for increased precision, or None if the normalized timestamp + cannot be determined. """ if self._normalized_timestamp is None: if self._number_of_seconds is not None: self._normalized_timestamp = ( - decimal.Decimal(self._microseconds) / + decimal.Decimal(self._microseconds or 0) / definitions.MICROSECONDS_PER_SECOND) self._normalized_timestamp += decimal.Decimal(self._number_of_seconds) return self._normalized_timestamp - def CopyFromDateTimeString(self, time_string): + def CopyFromDateTimeString(self, time_string: 'str') -> 'None': """Copies a fake timestamp from a date and time string. Args: @@ -76,11 +78,12 @@ def CopyFromDateTimeString(self, time_string): self._normalized_timestamp = None self._number_of_seconds = self._GetNumberOfSecondsFromElements( - year, month, day_of_month, hours, minutes, seconds, time_zone_offset) + year, month, day_of_month, hours, minutes, seconds, + time_zone_offset=time_zone_offset) self._microseconds = date_time_values.get('microseconds', None) self._time_zone_offset = time_zone_offset - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the fake timestamp to a date and time string. Returns: diff --git a/dfdatetime/fat_date_time.py b/dfdatetime/fat_date_time.py index a4b4d936..b8298925 100644 --- a/dfdatetime/fat_date_time.py +++ b/dfdatetime/fat_date_time.py @@ -5,6 +5,8 @@ import decimal +from typing import Optional, Union # pylint: disable=unused-import + from dfdatetime import definitions from dfdatetime import interface @@ -12,7 +14,7 @@ class FATDateTimeEpoch(interface.DateTimeEpoch): """FAT date time time epoch.""" - def __init__(self): + def __init__(self) -> 'None': """Initializes a FAT date time epoch.""" super(FATDateTimeEpoch, self).__init__(1980, 1, 1) @@ -39,33 +41,34 @@ class FATDateTime(interface.DateTimeValues): is_local_time (bool): True if the date and time value is in local time. """ - _EPOCH = FATDateTimeEpoch() + _EPOCH: 'interface.DateTimeEpoch' = FATDateTimeEpoch() # The difference between January 1, 1980 and January 1, 1970 in seconds. - _FAT_DATE_TO_POSIX_BASE = 315532800 + _FAT_DATE_TO_POSIX_BASE: 'int' = 315532800 - def __init__(self, fat_date_time=None): + def __init__(self, fat_date_time: 'Optional[int]' = None) -> 'None': """Initializes a FAT date time. Args: fat_date_time (Optional[int]): FAT date time. """ - number_of_seconds = None - if fat_date_time is not None: + if fat_date_time is None: + number_of_seconds = None + else: number_of_seconds = self._GetNumberOfSeconds(fat_date_time) super(FATDateTime, self).__init__() - self._precision = definitions.PRECISION_2_SECONDS - self._number_of_seconds = number_of_seconds + self._number_of_seconds: 'Union[int, None]' = number_of_seconds + self._precision: 'str' = definitions.PRECISION_2_SECONDS - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> 'Union[decimal.Decimal, None]': """Retrieves the normalized timestamp. Returns: decimal.Decimal: normalized timestamp, which contains the number of - seconds since January 1, 1970 00:00:00 and a fraction of second used - for increased precision, or None if the normalized timestamp cannot be - determined. + seconds since January 1, 1970 00:00:00 and a fraction of second + used for increased precision, or None if the normalized timestamp + cannot be determined. """ if self._normalized_timestamp is None: if self._number_of_seconds is not None and self._number_of_seconds >= 0: @@ -75,7 +78,7 @@ def _GetNormalizedTimestamp(self): return self._normalized_timestamp - def _GetNumberOfSeconds(self, fat_date_time): + def _GetNumberOfSeconds(self, fat_date_time: 'int') -> 'int': """Retrieves the number of seconds from a FAT date time. Args: @@ -120,7 +123,7 @@ def _GetNumberOfSeconds(self, fat_date_time): number_of_seconds += number_of_days * definitions.SECONDS_PER_DAY return number_of_seconds - def CopyFromDateTimeString(self, time_string): + def CopyFromDateTimeString(self, time_string: 'str') -> 'None': """Copies a FAT date time from a date and time string. Args: @@ -154,7 +157,7 @@ def CopyFromDateTimeString(self, time_string): self._number_of_seconds -= self._FAT_DATE_TO_POSIX_BASE self._time_zone_offset = time_zone_offset - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the FAT date time to a date and time string. Returns: diff --git a/dfdatetime/filetime.py b/dfdatetime/filetime.py index 9a170b04..472649c2 100644 --- a/dfdatetime/filetime.py +++ b/dfdatetime/filetime.py @@ -5,6 +5,8 @@ import decimal +from typing import Optional, Union # pylint: disable=unused-import + from dfdatetime import definitions from dfdatetime import interface @@ -12,7 +14,7 @@ class FiletimeEpoch(interface.DateTimeEpoch): """FILETIME epoch.""" - def __init__(self): + def __init__(self) -> 'None': """Initializes a FILETIME epoch.""" super(FiletimeEpoch, self).__init__(1601, 1, 1) @@ -30,34 +32,34 @@ class Filetime(interface.DateTimeValues): is_local_time (bool): True if the date and time value is in local time. """ - _EPOCH = FiletimeEpoch() + _EPOCH: 'interface.DateTimeEpoch' = FiletimeEpoch() # The difference between January 1, 1601 and January 1, 1970 in seconds. - _FILETIME_TO_POSIX_BASE = 11644473600 + _FILETIME_TO_POSIX_BASE: 'int' = 11644473600 - def __init__(self, timestamp=None): + def __init__(self, timestamp: 'Optional[int]' = None) -> 'None': """Initializes a FILETIME timestamp. Args: timestamp (Optional[int]): FILETIME timestamp. """ super(Filetime, self).__init__() - self._precision = definitions.PRECISION_100_NANOSECONDS - self._timestamp = timestamp + self._precision: 'str' = definitions.PRECISION_100_NANOSECONDS + self._timestamp: 'Union[int, None]' = timestamp @property - def timestamp(self): + def timestamp(self) -> 'Union[int, None]': """int: FILETIME timestamp or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> 'Union[decimal.Decimal, None]': """Retrieves the normalized timestamp. Returns: decimal.Decimal: normalized timestamp, which contains the number of - seconds since January 1, 1970 00:00:00 and a fraction of second used - for increased precision, or None if the normalized timestamp cannot be - determined. + seconds since January 1, 1970 00:00:00 and a fraction of second + used for increased precision, or None if the normalized timestamp + cannot be determined. """ if self._normalized_timestamp is None: if (self._timestamp is not None and self._timestamp >= 0 and @@ -68,7 +70,7 @@ def _GetNormalizedTimestamp(self): return self._normalized_timestamp - def CopyFromDateTimeString(self, time_string): + def CopyFromDateTimeString(self, time_string: 'str') -> 'None': """Copies a FILETIME timestamp from a date and time string. Args: @@ -97,7 +99,8 @@ def CopyFromDateTimeString(self, time_string): raise ValueError('Year value not supported: {0!s}.'.format(year)) timestamp = self._GetNumberOfSecondsFromElements( - year, month, day_of_month, hours, minutes, seconds, time_zone_offset) + year, month, day_of_month, hours, minutes, seconds, + time_zone_offset=time_zone_offset) timestamp += self._FILETIME_TO_POSIX_BASE timestamp *= definitions.MICROSECONDS_PER_SECOND timestamp += date_time_values.get('microseconds', 0) @@ -107,7 +110,7 @@ def CopyFromDateTimeString(self, time_string): self._timestamp = timestamp self._time_zone_offset = time_zone_offset - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the FILETIME timestamp to a date and time string. Returns: diff --git a/dfdatetime/hfs_time.py b/dfdatetime/hfs_time.py index 15867305..f695b2bd 100644 --- a/dfdatetime/hfs_time.py +++ b/dfdatetime/hfs_time.py @@ -5,6 +5,8 @@ import decimal +from typing import Optional, Union # pylint: disable=unused-import + from dfdatetime import definitions from dfdatetime import interface @@ -12,7 +14,7 @@ class HFSTimeEpoch(interface.DateTimeEpoch): """HFS time epoch.""" - def __init__(self): + def __init__(self) -> 'None': """Initializes a HFS time epoch.""" super(HFSTimeEpoch, self).__init__(1904, 1, 1) @@ -27,34 +29,34 @@ class HFSTime(interface.DateTimeValues): Attributes: is_local_time (bool): True if the date and time value is in local time. """ - _EPOCH = HFSTimeEpoch() + _EPOCH: 'interface.DateTimeEpoch' = HFSTimeEpoch() # The difference between Jan 1, 1904 and Jan 1, 1970 in seconds. - _HFS_TO_POSIX_BASE = 2082844800 + _HFS_TO_POSIX_BASE: 'int' = 2082844800 - def __init__(self, timestamp=None): + def __init__(self, timestamp: 'Optional[int]' = None) -> 'None': """Initializes a HFS timestamp. Args: timestamp (Optional[int]): HFS timestamp. """ super(HFSTime, self).__init__() - self._precision = definitions.PRECISION_1_SECOND - self._timestamp = timestamp + self._precision: 'str' = definitions.PRECISION_1_SECOND + self._timestamp: 'Union[int, None]' = timestamp @property - def timestamp(self): + def timestamp(self) -> 'Union[int, None]': """int: HFS timestamp or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> 'Union[decimal.Decimal, None]': """Retrieves the normalized timestamp. Returns: decimal.Decimal: normalized timestamp, which contains the number of - seconds since January 1, 1970 00:00:00 and a fraction of second used - for increased precision, or None if the normalized timestamp cannot be - determined. + seconds since January 1, 1970 00:00:00 and a fraction of second + used for increased precision, or None if the normalized timestamp + cannot be determined. """ if self._normalized_timestamp is None: if (self._timestamp is not None and self._timestamp >= 0 and @@ -64,7 +66,7 @@ def _GetNormalizedTimestamp(self): return self._normalized_timestamp - def CopyFromDateTimeString(self, time_string): + def CopyFromDateTimeString(self, time_string: 'str') -> 'None': """Copies a HFS timestamp from a date and time string. Args: @@ -94,11 +96,12 @@ def CopyFromDateTimeString(self, time_string): self._normalized_timestamp = None self._timestamp = self._GetNumberOfSecondsFromElements( - year, month, day_of_month, hours, minutes, seconds, time_zone_offset) + year, month, day_of_month, hours, minutes, seconds, + time_zone_offset=time_zone_offset) self._timestamp += self._HFS_TO_POSIX_BASE self._time_zone_offset = time_zone_offset - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the HFS timestamp to a date and time string. Returns: diff --git a/dfdatetime/interface.py b/dfdatetime/interface.py index 0cd26fc0..836066c0 100644 --- a/dfdatetime/interface.py +++ b/dfdatetime/interface.py @@ -6,6 +6,9 @@ import abc import calendar import decimal +import typing + +from typing import Optional, Tuple, Union from dfdatetime import decorators from dfdatetime import definitions @@ -24,7 +27,7 @@ class DateTimeEpoch(object): where 1 represents the first day. """ - def __init__(self, year, month, day_of_month): + def __init__(self, year: 'int', month: 'int', day_of_month: 'int') -> 'None': """Initializes a date time epoch. Args: @@ -35,15 +38,15 @@ def __init__(self, year, month, day_of_month): where 1 represents the first day. """ super(DateTimeEpoch, self).__init__() - self.day_of_month = day_of_month - self.month = month - self.year = year + self.day_of_month: 'int' = day_of_month + self.month: 'int' = month + self.year: 'int' = year class NormalizedTimeEpoch(DateTimeEpoch): """dfDateTime normalized time epoch.""" - def __init__(self): + def __init__(self) -> 'None': """Initializes a dfDateTime normalized time epoch.""" super(NormalizedTimeEpoch, self).__init__(1970, 1, 1) @@ -59,46 +62,47 @@ class DateTimeValues(object): # pylint: disable=redundant-returns-doc - _DAYS_PER_MONTH = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) + _DAYS_PER_MONTH: 'Tuple[int, ...]' = ( + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) - _EPOCH_NORMALIZED_TIME = NormalizedTimeEpoch() + _EPOCH_NORMALIZED_TIME: 'DateTimeEpoch' = NormalizedTimeEpoch() - _100NS_PER_SECOND = 10000000 - _100NS_PER_DECISECOND = 1000000 - _100NS_PER_MILLISECOND = 10000 - _100NS_PER_MICROSECOND = 10 + _100NS_PER_SECOND: 'int' = 10000000 + _100NS_PER_DECISECOND: 'int' = 1000000 + _100NS_PER_MILLISECOND: 'int' = 10000 + _100NS_PER_MICROSECOND: 'int' = 10 - _INT64_MIN = -(1 << 63) - _INT64_MAX = (1 << 63) - 1 + _INT64_MIN: 'int' = -(1 << 63) + _INT64_MAX: 'int' = (1 << 63) - 1 - _UINT32_MAX = (1 << 32) - 1 - _UINT60_MAX = (1 << 60) - 1 - _UINT64_MAX = (1 << 64) - 1 + _UINT32_MAX: 'int' = (1 << 32) - 1 + _UINT60_MAX: 'int' = (1 << 60) - 1 + _UINT64_MAX: 'int' = (1 << 64) - 1 - def __init__(self): + def __init__(self) -> 'None': """Initializes date time values.""" super(DateTimeValues, self).__init__() - self._normalized_timestamp = None - self._precision = None - self._time_zone_offset = None + self._normalized_timestamp: 'Union[decimal.Decimal, None]' = None + self._precision: 'Union[str, None]' = None + self._time_zone_offset: 'Union[int, None]' = None - self.is_local_time = False + self.is_local_time: 'bool' = False @property - def precision(self): + def precision(self) -> 'Union[str, None]': """precision (str): precision of the date and time value, which should be one of the PRECISION_VALUES in definitions. """ return self._precision @property - def time_zone_offset(self): + def time_zone_offset(self) -> 'Union[int, None]': """time_zone_offset (int): time zone offset in number of minutes from UTC or None if not set. """ return self._time_zone_offset - def __eq__(self, other): + def __eq__(self, other: 'object') -> 'bool': """Determines if the date time values are equal to other. Args: @@ -121,7 +125,7 @@ def __eq__(self, other): return normalized_timestamp == other_normalized_timestamp - def __ge__(self, other): + def __ge__(self, other: 'object') -> 'bool': """Determines if the date time values are greater than or equal to other. Args: @@ -147,7 +151,7 @@ def __ge__(self, other): return normalized_timestamp >= other_normalized_timestamp - def __gt__(self, other): + def __gt__(self, other: 'object') -> 'bool': """Determines if the date time values are greater than other. Args: @@ -173,7 +177,7 @@ def __gt__(self, other): return normalized_timestamp > other_normalized_timestamp - def __le__(self, other): + def __le__(self, other: 'object') -> 'bool': """Determines if the date time values are greater than or equal to other. Args: @@ -199,7 +203,7 @@ def __le__(self, other): return normalized_timestamp <= other_normalized_timestamp - def __lt__(self, other): + def __lt__(self, other: 'object') -> 'bool': """Determines if the date time values are less than other. Args: @@ -225,7 +229,7 @@ def __lt__(self, other): return normalized_timestamp < other_normalized_timestamp - def __ne__(self, other): + def __ne__(self, other: 'object') -> 'bool': """Determines if the date time values are not equal to other. Args: @@ -249,7 +253,9 @@ def __ne__(self, other): return normalized_timestamp != other_normalized_timestamp def _AdjustForTimeZoneOffset( - self, year, month, day_of_month, hours, minutes, time_zone_offset): + self, year: 'int', month: 'int', day_of_month: 'int', + hours: 'int', minutes: 'int', + time_zone_offset: 'int') -> 'Tuple[int, int, int, int, int]': """Adjusts the date and time values for a time zone offset. Args: @@ -261,7 +267,7 @@ def _AdjustForTimeZoneOffset( time_zone_offset (int): time zone offset in number of minutes from UTC. Returns: - tuple[int, int, int, int, int, int]: time zone correct year, month, + tuple[int, int, int, int, int]: time zone correct year, month, day_of_month, hours and minutes values. """ # Note that when the sign of the time zone offset is negative @@ -307,7 +313,8 @@ def _AdjustForTimeZoneOffset( return year, month, day_of_month, hours, minutes - def _CopyDateFromString(self, date_string): + def _CopyDateFromString( + self, date_string: str) -> Tuple[int, int, int]: """Copies a date from a string. Args: @@ -349,7 +356,7 @@ def _CopyDateFromString(self, date_string): return year, month, day_of_month - def _CopyDateTimeFromString(self, time_string): + def _CopyDateTimeFromString(self, time_string: str) -> typing.Dict[str, int]: """Copies a date and time from a string. Args: @@ -405,7 +412,8 @@ def _CopyDateTimeFromString(self, time_string): return date_time_values - def _CopyTimeFromString(self, time_string): + def _CopyTimeFromString(self, time_string: str) -> Tuple[ + int, int, int, Union[int, None], Union[int, None]]: """Copies a time from a string. Args: @@ -478,8 +486,8 @@ def _CopyTimeFromString(self, time_string): raise ValueError('Invalid time string.') try: - time_fraction = time_string[9:time_zone_string_index] - time_fraction = int(time_fraction, 10) + time_fraction_string = time_string[9:time_zone_string_index] + time_fraction = int(time_fraction_string, 10) except ValueError: raise ValueError('Unable to parse time fraction.') @@ -520,7 +528,8 @@ def _CopyTimeFromString(self, time_string): return hours, minutes, seconds, microseconds, time_zone_offset def _GetDateValues( - self, number_of_days, epoch_year, epoch_month, epoch_day_of_month): + self, number_of_days: int, epoch_year: int, epoch_month: int, + epoch_day_of_month: int) -> Tuple[int, int, int]: """Determines date values. Args: @@ -644,7 +653,9 @@ def _GetDateValues( return year, month, number_of_days - def _GetDateValuesWithEpoch(self, number_of_days, date_time_epoch): + def _GetDateValuesWithEpoch( + self, number_of_days: int, + date_time_epoch: DateTimeEpoch) -> Tuple[int, int, int]: """Determines date values. Args: @@ -658,7 +669,7 @@ def _GetDateValuesWithEpoch(self, number_of_days, date_time_epoch): number_of_days, date_time_epoch.year, date_time_epoch.month, date_time_epoch.day_of_month) - def _GetDayOfYear(self, year, month, day_of_month): + def _GetDayOfYear(self, year: int, month: int, day_of_month: int) -> int: """Retrieves the day of the year for a specific day of a month in a year. Args: @@ -685,7 +696,7 @@ def _GetDayOfYear(self, year, month, day_of_month): return day_of_year - def _GetDaysPerMonth(self, year, month): + def _GetDaysPerMonth(self, year: int, month: int) -> int: """Retrieves the number of days in a month of a specific year. Args: @@ -708,17 +719,17 @@ def _GetDaysPerMonth(self, year, month): return days_per_month @abc.abstractmethod - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> Union[decimal.Decimal, None]: """Retrieves the normalized timestamp. Returns: decimal.Decimal: normalized timestamp, which contains the number of - seconds since January 1, 1970 00:00:00 and a fraction of second used - for increased precision, or None if the normalized timestamp cannot be - determined. + seconds since January 1, 1970 00:00:00 and a fraction of second + used for increased precision, or None if the normalized timestamp + cannot be determined. """ - def _GetNumberOfDaysInCentury(self, year): + def _GetNumberOfDaysInCentury(self, year: int) -> int: """Retrieves the number of days in a century. Args: @@ -739,7 +750,7 @@ def _GetNumberOfDaysInCentury(self, year): return 36525 return 36524 - def _GetNumberOfDaysInYear(self, year): + def _GetNumberOfDaysInYear(self, year: int) -> int: """Retrieves the number of days in a specific year. Args: @@ -753,8 +764,8 @@ def _GetNumberOfDaysInYear(self, year): return 365 def _GetNumberOfSecondsFromElements( - self, year, month, day_of_month, hours, minutes, seconds, - time_zone_offset): + self, year: int, month: int, day_of_month: int, hours: int, minutes: int, + seconds: int, time_zone_offset: Optional[int] = None) -> int: """Retrieves the number of seconds from the date and time elements. Args: @@ -764,18 +775,18 @@ def _GetNumberOfSecondsFromElements( hours (int): hours. minutes (int): minutes. seconds (int): seconds. - time_zone_offset (int): time zone offset in number of minutes from UTC - or None if not set. + time_zone_offset (Optional[int]): time zone offset in number of minutes + from UTC. Returns: - int: number of seconds since January 1, 1970 00:00:00 or None if year, - month or day of month are not set. + int: number of seconds since January 1, 1970 00:00:00. Raises: - ValueError: if the time elements are invalid. + ValueError: if one or more date elements are missing or the time elements + are invalid. """ - if not year or not month or not day_of_month: - return None + if None in (year, month, day_of_month): + raise ValueError('One or more date elements missing.') # calendar.timegm does not sanity check the time elements. if hours is None: @@ -811,7 +822,8 @@ def _GetNumberOfSecondsFromElements( return int(number_of_seconds) - def _GetTimeValues(self, number_of_seconds): + def _GetTimeValues(self, number_of_seconds: Union[ + int, decimal.Decimal]) -> Tuple[int, int, int, int]: """Determines time values. Args: @@ -826,7 +838,7 @@ def _GetTimeValues(self, number_of_seconds): number_of_days, hours = divmod(number_of_hours, 24) return number_of_days, hours, minutes, seconds - def _IsLeapYear(self, year): + def _IsLeapYear(self, year: int) -> bool: """Determines if a year is a leap year. Args: @@ -839,7 +851,7 @@ def _IsLeapYear(self, year): return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0 @decorators.deprecated - def CopyFromString(self, time_string): + def CopyFromString(self, time_string: str) -> 'None': """Copies a date time value from a date and time string. Args: @@ -857,7 +869,7 @@ def CopyFromString(self, time_string): self.CopyFromDateTimeString(time_string) @abc.abstractmethod - def CopyFromDateTimeString(self, time_string): + def CopyFromDateTimeString(self, time_string: str) -> 'None': """Copies a date time value from a date and time string. Args: @@ -873,7 +885,7 @@ def CopyFromDateTimeString(self, time_string): ValueError: if the time string is invalid or not supported. """ - def CopyToPosixTimestamp(self): + def CopyToPosixTimestamp(self) -> Union[int, None]: """Copies the date time value to a POSIX timestamp. Returns: @@ -886,7 +898,9 @@ def CopyToPosixTimestamp(self): return int(normalized_timestamp) # TODO: remove this method when there is no more need for it in dfvfs. - def CopyToStatTimeTuple(self): + def CopyToStatTimeTuple(self) -> Union[ + Tuple[int, int], Tuple[int, None], + Tuple[None, None]]: """Copies the date time value to a stat timestamp tuple. Returns: @@ -910,7 +924,7 @@ def CopyToStatTimeTuple(self): return int(normalized_timestamp), None @abc.abstractmethod - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> Union[str, None]: """Copies the date time value to a date and time string. Returns: @@ -918,7 +932,7 @@ def CopyToDateTimeString(self): None if the timestamp cannot be copied to a date and time string. """ - def CopyToDateTimeStringISO8601(self): + def CopyToDateTimeStringISO8601(self) -> Union[str, None]: """Copies the date time value to an ISO 8601 date and time string. Returns: @@ -931,7 +945,8 @@ def CopyToDateTimeStringISO8601(self): date_time_string = '{0:s}Z'.format(date_time_string) return date_time_string - def GetDate(self): + def GetDate(self) -> Union[ + Tuple[int, int, int], Tuple[None, None, None]]: """Retrieves the date represented by the date and time values. Returns: @@ -952,7 +967,7 @@ def GetDate(self): return None, None, None # TODO: remove this method when there is no more need for it in plaso. - def GetPlasoTimestamp(self): + def GetPlasoTimestamp(self) -> Union[int, None]: """Retrieves a timestamp that is compatible with plaso. Returns: @@ -968,7 +983,8 @@ def GetPlasoTimestamp(self): 1, rounding=decimal.ROUND_HALF_UP) return int(normalized_timestamp) - def GetTimeOfDay(self): + def GetTimeOfDay(self) -> Union[ + Tuple[int, int, int], Tuple[None, None, None]]: """Retrieves the time of day represented by the date and time values. Returns: diff --git a/dfdatetime/java_time.py b/dfdatetime/java_time.py index 7d907a00..852eba0c 100644 --- a/dfdatetime/java_time.py +++ b/dfdatetime/java_time.py @@ -5,6 +5,8 @@ import decimal +from typing import Optional, Union # pylint: disable=unused-import + from dfdatetime import definitions from dfdatetime import posix_time @@ -23,14 +25,14 @@ class JavaTime(posix_time.PosixTimeInMilliseconds): is_local_time (bool): True if the date and time value is in local time. """ - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> 'Union[decimal.Decimal, None]': """Retrieves the normalized timestamp. Returns: decimal.Decimal: normalized timestamp, which contains the number of - seconds since January 1, 1970 00:00:00 and a fraction of second used - for increased precision, or None if the normalized timestamp cannot be - determined. + seconds since January 1, 1970 00:00:00 and a fraction of second + used for increased precision, or None if the normalized timestamp + cannot be determined. """ if self._normalized_timestamp is None: if (self._timestamp is not None and self._timestamp >= self._INT64_MIN and @@ -41,7 +43,7 @@ def _GetNormalizedTimestamp(self): return self._normalized_timestamp - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the POSIX timestamp to a date and time string. Returns: diff --git a/dfdatetime/ole_automation_date.py b/dfdatetime/ole_automation_date.py index 3b92f24f..9cda70e0 100644 --- a/dfdatetime/ole_automation_date.py +++ b/dfdatetime/ole_automation_date.py @@ -5,6 +5,8 @@ import decimal +from typing import Optional, Union # pylint: disable=unused-import + from dfdatetime import definitions from dfdatetime import interface @@ -12,7 +14,7 @@ class OLEAutomationDateEpoch(interface.DateTimeEpoch): """OLE automation date epoch.""" - def __init__(self): + def __init__(self) -> 'None': """Initializes a OLE automation date epoch.""" super(OLEAutomationDateEpoch, self).__init__(1899, 12, 30) @@ -31,34 +33,34 @@ class OLEAutomationDate(interface.DateTimeValues): Attributes: is_local_time (bool): True if the date and time value is in local time. """ - _EPOCH = OLEAutomationDateEpoch() + _EPOCH: 'interface.DateTimeEpoch' = OLEAutomationDateEpoch() # The difference between December 30, 1899 and January 1, 1970 in days. - _OLE_AUTOMATION_DATE_TO_POSIX_BASE = 25569 + _OLE_AUTOMATION_DATE_TO_POSIX_BASE: 'int' = 25569 - def __init__(self, timestamp=None): + def __init__(self, timestamp: 'Optional[float]' = None) -> 'None': """Initializes an OLE Automation date. Args: timestamp (Optional[float]): OLE Automation date. """ super(OLEAutomationDate, self).__init__() - self._precision = definitions.PRECISION_1_MICROSECOND - self._timestamp = timestamp + self._precision: 'str' = definitions.PRECISION_1_MICROSECOND + self._timestamp: 'Union[float, None]' = timestamp @property - def timestamp(self): + def timestamp(self) -> 'Union[float, None]': """float: OLE Automation date timestamp or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> 'Union[decimal.Decimal, None]': """Retrieves the normalized timestamp. Returns: decimal.Decimal: normalized timestamp, which contains the number of - seconds since January 1, 1970 00:00:00 and a fraction of second used - for increased precision, or None if the normalized timestamp cannot be - determined. + seconds since January 1, 1970 00:00:00 and a fraction of second + used for increased precision, or None if the normalized timestamp + cannot be determined. """ if self._normalized_timestamp is None: if self._timestamp is not None: @@ -69,7 +71,7 @@ def _GetNormalizedTimestamp(self): return self._normalized_timestamp - def CopyFromDateTimeString(self, time_string): + def CopyFromDateTimeString(self, time_string: 'str') -> 'None': """Copies an OLE Automation date from a date and time string. Args: @@ -95,10 +97,11 @@ def CopyFromDateTimeString(self, time_string): microseconds = date_time_values.get('microseconds', None) time_zone_offset = date_time_values.get('time_zone_offset', 0) - timestamp = self._GetNumberOfSecondsFromElements( - year, month, day_of_month, hours, minutes, seconds, time_zone_offset) + number_of_seconds = self._GetNumberOfSecondsFromElements( + year, month, day_of_month, hours, minutes, seconds, + time_zone_offset=time_zone_offset) - timestamp = float(timestamp) + timestamp = float(number_of_seconds) if microseconds is not None: timestamp += float(microseconds) / definitions.MICROSECONDS_PER_SECOND @@ -109,7 +112,7 @@ def CopyFromDateTimeString(self, time_string): self._timestamp = timestamp self._time_zone_offset = time_zone_offset - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the OLE Automation date to a date and time string. Returns: diff --git a/dfdatetime/posix_time.py b/dfdatetime/posix_time.py index 5442e36a..7f248982 100644 --- a/dfdatetime/posix_time.py +++ b/dfdatetime/posix_time.py @@ -5,6 +5,8 @@ import decimal +from typing import Optional, Union # pylint: disable=unused-import + from dfdatetime import definitions from dfdatetime import interface @@ -12,7 +14,7 @@ class PosixTimeEpoch(interface.DateTimeEpoch): """POSIX time epoch.""" - def __init__(self): + def __init__(self) -> 'None': """Initializes a POSIX time epoch.""" super(PosixTimeEpoch, self).__init__(1970, 1, 1) @@ -31,31 +33,31 @@ class PosixTime(interface.DateTimeValues): is_local_time (bool): True if the date and time value is in local time. """ - _EPOCH = PosixTimeEpoch() + _EPOCH: 'interface.DateTimeEpoch' = PosixTimeEpoch() - def __init__(self, timestamp=None): + def __init__(self, timestamp: 'Optional[int]' = None) -> 'None': """Initializes a POSIX timestamp. Args: timestamp (Optional[int]): POSIX timestamp. """ super(PosixTime, self).__init__() - self._precision = definitions.PRECISION_1_SECOND - self._timestamp = timestamp + self._precision: 'str' = definitions.PRECISION_1_SECOND + self._timestamp: 'Union[int, None]' = timestamp @property - def timestamp(self): + def timestamp(self) -> 'Union[int, None]': """int: POSIX timestamp or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> 'Union[decimal.Decimal, None]': """Retrieves the normalized timestamp. Returns: decimal.Decimal: normalized timestamp, which contains the number of - seconds since January 1, 1970 00:00:00 and a fraction of second used - for increased precision, or None if the normalized timestamp cannot be - determined. + seconds since January 1, 1970 00:00:00 and a fraction of second + used for increased precision, or None if the normalized timestamp + cannot be determined. """ if self._normalized_timestamp is None: if self._timestamp is not None: @@ -63,7 +65,7 @@ def _GetNormalizedTimestamp(self): return self._normalized_timestamp - def CopyFromDateTimeString(self, time_string): + def CopyFromDateTimeString(self, time_string: 'str') -> 'None': """Copies a POSIX timestamp from a date and time string. Args: @@ -86,10 +88,11 @@ def CopyFromDateTimeString(self, time_string): time_zone_offset = date_time_values.get('time_zone_offset', 0) self._timestamp = self._GetNumberOfSecondsFromElements( - year, month, day_of_month, hours, minutes, seconds, time_zone_offset) + year, month, day_of_month, hours, minutes, seconds, + time_zone_offset=time_zone_offset) self._time_zone_offset = time_zone_offset - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the POSIX timestamp to a date and time string. Returns: @@ -120,29 +123,29 @@ class PosixTimeInMilliseconds(interface.DateTimeValues): _EPOCH = PosixTimeEpoch() - def __init__(self, timestamp=None): + def __init__(self, timestamp: 'Optional[int]' = None) -> 'None': """Initializes a POSIX timestamp in milliseconds. Args: timestamp (Optional[int]): POSIX timestamp in milliseconds. """ super(PosixTimeInMilliseconds, self).__init__() - self._precision = definitions.PRECISION_1_MILLISECOND - self._timestamp = timestamp + self._precision: str = definitions.PRECISION_1_MILLISECOND + self._timestamp: Union[int, None] = timestamp @property - def timestamp(self): + def timestamp(self) -> 'Union[int, None]': """int: POSIX timestamp in milliseconds or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> 'Union[decimal.Decimal, None]': """Retrieves the normalized timestamp. Returns: decimal.Decimal: normalized timestamp, which contains the number of - seconds since January 1, 1970 00:00:00 and a fraction of second used - for increased precision, or None if the normalized timestamp cannot be - determined. + seconds since January 1, 1970 00:00:00 and a fraction of second + used for increased precision, or None if the normalized timestamp + cannot be determined. """ if self._normalized_timestamp is None: if self._timestamp is not None: @@ -152,7 +155,7 @@ def _GetNormalizedTimestamp(self): return self._normalized_timestamp - def CopyFromDateTimeString(self, time_string): + def CopyFromDateTimeString(self, time_string: 'str') -> 'None': """Copies a POSIX timestamp from a date and time string. Args: @@ -176,7 +179,8 @@ def CopyFromDateTimeString(self, time_string): time_zone_offset = date_time_values.get('time_zone_offset', 0) timestamp = self._GetNumberOfSecondsFromElements( - year, month, day_of_month, hours, minutes, seconds, time_zone_offset) + year, month, day_of_month, hours, minutes, seconds, + time_zone_offset=time_zone_offset) timestamp *= definitions.MILLISECONDS_PER_SECOND if microseconds: @@ -187,7 +191,7 @@ def CopyFromDateTimeString(self, time_string): self._timestamp = timestamp self._time_zone_offset = time_zone_offset - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the POSIX timestamp to a date and time string. Returns: @@ -219,29 +223,29 @@ class PosixTimeInMicroseconds(interface.DateTimeValues): _EPOCH = PosixTimeEpoch() - def __init__(self, timestamp=None): + def __init__(self, timestamp: 'Optional[int]' = None) -> 'None': """Initializes a POSIX timestamp in microseconds. Args: timestamp (Optional[int]): POSIX timestamp in microseconds. """ super(PosixTimeInMicroseconds, self).__init__() - self._precision = definitions.PRECISION_1_MICROSECOND - self._timestamp = timestamp + self._precision: str = definitions.PRECISION_1_MICROSECOND + self._timestamp: Union[int, None] = timestamp @property - def timestamp(self): + def timestamp(self) -> 'Union[int, None]': """int: POSIX timestamp in microseconds or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> 'Union[decimal.Decimal, None]': """Retrieves the normalized timestamp. Returns: decimal.Decimal: normalized timestamp, which contains the number of - seconds since January 1, 1970 00:00:00 and a fraction of second used - for increased precision, or None if the normalized timestamp cannot be - determined. + seconds since January 1, 1970 00:00:00 and a fraction of second + used for increased precision, or None if the normalized timestamp + cannot be determined. """ if self._normalized_timestamp is None: if self._timestamp is not None: @@ -251,7 +255,7 @@ def _GetNormalizedTimestamp(self): return self._normalized_timestamp - def CopyFromDateTimeString(self, time_string): + def CopyFromDateTimeString(self, time_string: 'str') -> 'None': """Copies a POSIX timestamp from a date and time string. Args: @@ -275,14 +279,15 @@ def CopyFromDateTimeString(self, time_string): time_zone_offset = date_time_values.get('time_zone_offset', 0) timestamp = self._GetNumberOfSecondsFromElements( - year, month, day_of_month, hours, minutes, seconds, time_zone_offset) + year, month, day_of_month, hours, minutes, seconds, + time_zone_offset=time_zone_offset) timestamp *= definitions.MICROSECONDS_PER_SECOND timestamp += microseconds self._timestamp = timestamp self._time_zone_offset = time_zone_offset - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the POSIX timestamp to a date and time string. Returns: @@ -314,29 +319,29 @@ class PosixTimeInNanoseconds(interface.DateTimeValues): _EPOCH = PosixTimeEpoch() - def __init__(self, timestamp=None): + def __init__(self, timestamp: 'Optional[int]' = None) -> 'None': """Initializes a POSIX timestamp in nanoseconds. Args: timestamp (Optional[int]): POSIX timestamp in nanoseconds. """ super(PosixTimeInNanoseconds, self).__init__() - self._precision = definitions.PRECISION_1_NANOSECOND - self._timestamp = timestamp + self._precision: str = definitions.PRECISION_1_NANOSECOND + self._timestamp: Union[int, None] = timestamp @property - def timestamp(self): + def timestamp(self) -> 'Union[int, None]': """int: POSIX timestamp or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> 'Union[decimal.Decimal, None]': """Retrieves the normalized timestamp. Returns: decimal.Decimal: normalized timestamp, which contains the number of - seconds since January 1, 1970 00:00:00 and a fraction of second used - for increased precision, or None if the normalized timestamp cannot be - determined. + seconds since January 1, 1970 00:00:00 and a fraction of second + used for increased precision, or None if the normalized timestamp + cannot be determined. """ if self._normalized_timestamp is None: if self._timestamp is not None: @@ -346,7 +351,7 @@ def _GetNormalizedTimestamp(self): return self._normalized_timestamp - def _CopyFromDateTimeString(self, time_string): + def _CopyFromDateTimeString(self, time_string: 'str') -> 'None': """Copies a POSIX timestamp from a date and time string. Args: @@ -370,7 +375,8 @@ def _CopyFromDateTimeString(self, time_string): time_zone_offset = date_time_values.get('time_zone_offset', 0) timestamp = self._GetNumberOfSecondsFromElements( - year, month, day_of_month, hours, minutes, seconds, time_zone_offset) + year, month, day_of_month, hours, minutes, seconds, + time_zone_offset=time_zone_offset) timestamp *= definitions.NANOSECONDS_PER_SECOND if microseconds: @@ -381,7 +387,7 @@ def _CopyFromDateTimeString(self, time_string): self._timestamp = timestamp self._time_zone_offset = time_zone_offset - def CopyFromDateTimeString(self, time_string): + def CopyFromDateTimeString(self, time_string: 'str') -> 'None': """Copies a POSIX timestamp from a date and time string. Args: @@ -395,7 +401,7 @@ def CopyFromDateTimeString(self, time_string): """ self._CopyFromDateTimeString(time_string) - def _CopyToDateTimeString(self): + def _CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the POSIX timestamp to a date and time string. Returns: @@ -415,7 +421,7 @@ def _CopyToDateTimeString(self): return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}.{6:09d}'.format( year, month, day_of_month, hours, minutes, seconds, nanoseconds) - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the POSIX timestamp to a date and time string. Returns: diff --git a/dfdatetime/precisions.py b/dfdatetime/precisions.py index de4f2ba3..6ce7abfb 100644 --- a/dfdatetime/precisions.py +++ b/dfdatetime/precisions.py @@ -5,6 +5,8 @@ import decimal +from typing import Optional, Tuple, Type, Union # pylint: disable=unused-import + from dfdatetime import definitions @@ -20,7 +22,8 @@ class DateTimePrecisionHelper(object): # pylint: disable=missing-raises-doc,redundant-returns-doc @classmethod - def CopyMicrosecondsToFractionOfSecond(cls, microseconds): + def CopyMicrosecondsToFractionOfSecond( + cls, microseconds: 'int') -> 'decimal.Decimal': """Copies the number of microseconds to a fraction of second value. Args: @@ -33,7 +36,9 @@ def CopyMicrosecondsToFractionOfSecond(cls, microseconds): raise NotImplementedError() @classmethod - def CopyToDateTimeString(cls, time_elements_tuple, fraction_of_second): + def CopyToDateTimeString( + cls, time_elements_tuple: 'Tuple[int, ...]', + fraction_of_second: 'decimal.Decimal') -> 'str': """Copies the time elements and fraction of second to a string. Args: @@ -54,7 +59,8 @@ class SecondsPrecisionHelper(DateTimePrecisionHelper): """Seconds precision helper.""" @classmethod - def CopyMicrosecondsToFractionOfSecond(cls, microseconds): + def CopyMicrosecondsToFractionOfSecond( + cls, microseconds: 'int') -> 'decimal.Decimal': """Copies the number of microseconds to a fraction of second value. Args: @@ -75,7 +81,9 @@ def CopyMicrosecondsToFractionOfSecond(cls, microseconds): return decimal.Decimal(0.0) @classmethod - def CopyToDateTimeString(cls, time_elements_tuple, fraction_of_second): + def CopyToDateTimeString( + cls, time_elements_tuple: 'Tuple[int, ...]', + fraction_of_second: 'decimal.Decimal') -> 'str': """Copies the time elements and fraction of second to a string. Args: @@ -105,7 +113,8 @@ class MillisecondsPrecisionHelper(DateTimePrecisionHelper): """Milliseconds precision helper.""" @classmethod - def CopyMicrosecondsToFractionOfSecond(cls, microseconds): + def CopyMicrosecondsToFractionOfSecond( + cls, microseconds: 'int') -> 'decimal.Decimal': """Copies the number of microseconds to a fraction of second value. Args: @@ -128,7 +137,9 @@ def CopyMicrosecondsToFractionOfSecond(cls, microseconds): return decimal.Decimal(milliseconds) / definitions.MILLISECONDS_PER_SECOND @classmethod - def CopyToDateTimeString(cls, time_elements_tuple, fraction_of_second): + def CopyToDateTimeString( + cls, time_elements_tuple: 'Tuple[int, ...]', + fraction_of_second: 'decimal.Decimal') -> 'str': """Copies the time elements and fraction of second to a string. Args: @@ -161,7 +172,8 @@ class MicrosecondsPrecisionHelper(DateTimePrecisionHelper): """Microseconds precision helper.""" @classmethod - def CopyMicrosecondsToFractionOfSecond(cls, microseconds): + def CopyMicrosecondsToFractionOfSecond( + cls, microseconds: 'int') -> 'decimal.Decimal': """Copies the number of microseconds to a fraction of second value. Args: @@ -182,7 +194,9 @@ def CopyMicrosecondsToFractionOfSecond(cls, microseconds): return decimal.Decimal(microseconds) / definitions.MICROSECONDS_PER_SECOND @classmethod - def CopyToDateTimeString(cls, time_elements_tuple, fraction_of_second): + def CopyToDateTimeString( + cls, time_elements_tuple: 'Tuple[int, ...]', + fraction_of_second: 'decimal.Decimal') -> 'str': """Copies the time elements and fraction of second to a string. Args: @@ -221,7 +235,8 @@ class PrecisionHelperFactory(object): } @classmethod - def CreatePrecisionHelper(cls, precision): + def CreatePrecisionHelper( + cls, precision: 'str') -> 'Type[DateTimePrecisionHelper]': """Creates a precision helper. Args: diff --git a/dfdatetime/rfc2579_date_time.py b/dfdatetime/rfc2579_date_time.py index ce18b19f..d0ce5297 100644 --- a/dfdatetime/rfc2579_date_time.py +++ b/dfdatetime/rfc2579_date_time.py @@ -5,6 +5,8 @@ import decimal +from typing import Optional, Tuple, Union # pylint: disable=unused-import + from dfdatetime import definitions from dfdatetime import interface @@ -45,28 +47,30 @@ class RFC2579DateTime(interface.DateTimeValues): # pylint: disable=missing-type-doc - def __init__(self, rfc2579_date_time_tuple=None): + def __init__(self, rfc2579_date_time_tuple: ( + 'Optional[Tuple[int, int, int, int, int, int, int, str, int, ' + 'int]]') = None): # pylint: disable=bad-whitespace """Initializes a RFC2579 date-time. Args: rfc2579_date_time_tuple: - (Optional[tuple[int, int, int, int, int, int, int]]): + (Optional[tuple[int, int, int, int, int, int, int, str, int, int]]): RFC2579 date-time time, contains year, month, day of month, hours, - minutes, seconds and deciseconds. + minutes, seconds, deciseconds and time zone offset. Raises: ValueError: if the system time is invalid. """ super(RFC2579DateTime, self).__init__() - self._number_of_seconds = None - self._precision = definitions.PRECISION_100_MILLISECONDS - self.day_of_month = None - self.hours = None - self.deciseconds = None - self.minutes = None - self.month = None - self.seconds = None - self.year = None + self._number_of_seconds: 'Union[int, None]' = None + self._precision: 'str' = definitions.PRECISION_100_MILLISECONDS + self.day_of_month: 'Union[int, None]' = None + self.hours: 'Union[int, None]' = None + self.deciseconds: 'Union[int, None]' = None + self.minutes: 'Union[int, None]' = None + self.month: 'Union[int, None]' = None + self.seconds: 'Union[int, None]' = None + self.year: 'Union[int, None]' = None if rfc2579_date_time_tuple: if len(rfc2579_date_time_tuple) < 10: @@ -125,27 +129,27 @@ def __init__(self, rfc2579_date_time_tuple=None): self._number_of_seconds = self._GetNumberOfSecondsFromElements( self.year, self.month, self.day_of_month, self.hours, self.minutes, - self.seconds, self._time_zone_offset) + self.seconds, time_zone_offset=self._time_zone_offset) - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> 'Union[decimal.Decimal, None]': """Retrieves the normalized timestamp. Returns: decimal.Decimal: normalized timestamp, which contains the number of - seconds since January 1, 1970 00:00:00 and a fraction of second used - for increased precision, or None if the normalized timestamp cannot be - determined. + seconds since January 1, 1970 00:00:00 and a fraction of second + used for increased precision, or None if the normalized timestamp + cannot be determined. """ if self._normalized_timestamp is None: if self._number_of_seconds is not None: self._normalized_timestamp = ( - decimal.Decimal(self.deciseconds) / + decimal.Decimal(self.deciseconds or 0) / definitions.DECISECONDS_PER_SECOND) self._normalized_timestamp += decimal.Decimal(self._number_of_seconds) return self._normalized_timestamp - def CopyFromDateTimeString(self, time_string): + def CopyFromDateTimeString(self, time_string: 'str') -> 'None': """Copies a RFC2579 date-time from a date and time string. Args: @@ -179,7 +183,8 @@ def CopyFromDateTimeString(self, time_string): self._normalized_timestamp = None self._number_of_seconds = self._GetNumberOfSecondsFromElements( - year, month, day_of_month, hours, minutes, seconds, time_zone_offset) + year, month, day_of_month, hours, minutes, seconds, + time_zone_offset=time_zone_offset) self._time_zone_offset = time_zone_offset self.year = year @@ -190,7 +195,7 @@ def CopyFromDateTimeString(self, time_string): self.seconds = seconds self.deciseconds = deciseconds - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the RFC2579 date-time to a date and time string. Returns: @@ -201,5 +206,6 @@ def CopyToDateTimeString(self): return None return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}.{6:01d}'.format( - self.year, self.month, self.day_of_month, self.hours, self.minutes, - self.seconds, self.deciseconds) + self.year or 0, self.month or 0, self.day_of_month or 0, + self.hours or 0, self.minutes or 0, self.seconds or 0, + self.deciseconds or 0) diff --git a/dfdatetime/semantic_time.py b/dfdatetime/semantic_time.py index f15725f0..5a50766d 100644 --- a/dfdatetime/semantic_time.py +++ b/dfdatetime/semantic_time.py @@ -3,8 +3,15 @@ from __future__ import unicode_literals +import typing + +from typing import Optional, Tuple, Union # pylint: disable=unused-import + from dfdatetime import interface +if typing.TYPE_CHECKING: + import decimal # pylint: disable=unused-import + class SemanticTime(interface.DateTimeValues): """Semantic time. @@ -18,9 +25,9 @@ class SemanticTime(interface.DateTimeValues): # pylint: disable=redundant-returns-doc - _SORT_ORDER = 50 + _SORT_ORDER: int = 50 - def __init__(self, string=None): + def __init__(self, string: 'Optional[str]' = None) -> 'None': """Initializes a semantic time. Args: @@ -28,14 +35,14 @@ def __init__(self, string=None): "Never", "Not set". """ super(SemanticTime, self).__init__() - self._string = string + self._string: 'Union[str, None]' = string @property - def string(self): + def string(self) -> 'Union[str, None]': """str: semantic representation of the time, such as: "Never".""" return self._string - def __eq__(self, other): + def __eq__(self, other: 'object') -> 'bool': """Determines if the date time values are equal to other. Args: @@ -49,7 +56,7 @@ def __eq__(self, other): return self._SORT_ORDER == other._SORT_ORDER # pylint: disable=protected-access - def __ge__(self, other): + def __ge__(self, other: 'object') -> 'bool': """Determines if the date time values are greater than or equal to other. Args: @@ -69,7 +76,7 @@ def __ge__(self, other): return self._SORT_ORDER >= other._SORT_ORDER # pylint: disable=protected-access - def __gt__(self, other): + def __gt__(self, other: 'object') -> 'bool': """Determines if the date time values are greater than other. Args: @@ -89,7 +96,7 @@ def __gt__(self, other): return self._SORT_ORDER > other._SORT_ORDER # pylint: disable=protected-access - def __le__(self, other): + def __le__(self, other: 'object') -> 'bool': """Determines if the date time values are greater than or equal to other. Args: @@ -109,7 +116,7 @@ def __le__(self, other): return self._SORT_ORDER <= other._SORT_ORDER # pylint: disable=protected-access - def __lt__(self, other): + def __lt__(self, other: 'object') -> 'bool': """Determines if the date time values are less than other. Args: @@ -129,7 +136,7 @@ def __lt__(self, other): return self._SORT_ORDER < other._SORT_ORDER # pylint: disable=protected-access - def __ne__(self, other): + def __ne__(self, other: 'object') -> 'bool': """Determines if the date time values are not equal to other. Args: @@ -143,18 +150,18 @@ def __ne__(self, other): return self._SORT_ORDER != other._SORT_ORDER # pylint: disable=protected-access - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> 'Union[decimal.Decimal, None]': """Retrieves the normalized timestamp. Returns: decimal.Decimal: normalized timestamp, which contains the number of - seconds since January 1, 1970 00:00:00 and a fraction of second used - for increased precision, or None if the normalized timestamp cannot be - determined. + seconds since January 1, 1970 00:00:00 and a fraction of second + used for increased precision, or None if the normalized timestamp + cannot be determined. """ return None - def CopyFromDateTimeString(self, time_string): + def CopyFromDateTimeString(self, time_string: 'str') -> 'None': """Copies semantic time from a date and time string. Args: @@ -166,7 +173,7 @@ def CopyFromDateTimeString(self, time_string): """ self._string = time_string - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the date time value to a date and time string. Returns: @@ -174,7 +181,7 @@ def CopyToDateTimeString(self): """ return self._string - def CopyToDateTimeStringISO8601(self): + def CopyToDateTimeStringISO8601(self) -> 'Union[str, None]': """Copies the date time value to an ISO 8601 date and time string. Returns: @@ -184,7 +191,8 @@ def CopyToDateTimeStringISO8601(self): """ return None - def CopyToStatTimeTuple(self): + def CopyToStatTimeTuple(self) -> ( + 'Union[Tuple[int, int], Tuple[int, None], Tuple[None, None]]'): """Copies the semantic timestamp to a stat timestamp tuple. Returns: @@ -193,7 +201,7 @@ def CopyToStatTimeTuple(self): """ return None, None - def GetPlasoTimestamp(self): + def GetPlasoTimestamp(self) -> 'Union[int, None]': """Retrieves a timestamp that is compatible with plaso. Returns: @@ -205,9 +213,9 @@ def GetPlasoTimestamp(self): class InvalidTime(SemanticTime): """Semantic time that represents invalid.""" - _SORT_ORDER = 1 + _SORT_ORDER: 'int' = 1 - def __init__(self): + def __init__(self) -> 'None': """Initializes a semantic time that represents invalid.""" super(InvalidTime, self).__init__(string='Invalid') @@ -215,13 +223,13 @@ def __init__(self): class Never(SemanticTime): """Semantic time that represents never.""" - _SORT_ORDER = 99 + _SORT_ORDER: 'int' = 99 - def __init__(self): + def __init__(self) -> 'None': """Initializes a semantic time that represents never.""" super(Never, self).__init__(string='Never') - def __eq__(self, other): + def __eq__(self, other: 'object') -> 'bool': """Determines if the date time values are equal to other. Args: @@ -232,7 +240,7 @@ def __eq__(self, other): """ return isinstance(other, Never) - def __ge__(self, other): + def __ge__(self, other: 'object') -> 'bool': """Determines if the date time values are greater than or equal to other. Args: @@ -249,7 +257,7 @@ def __ge__(self, other): return True - def __gt__(self, other): + def __gt__(self, other: 'object') -> 'bool': """Determines if the date time values are greater than other. Args: @@ -266,7 +274,7 @@ def __gt__(self, other): return not isinstance(other, Never) - def __le__(self, other): + def __le__(self, other: 'object') -> 'bool': """Determines if the date time values are less than or equal to other. Args: @@ -283,7 +291,7 @@ def __le__(self, other): return isinstance(other, Never) - def __lt__(self, other): + def __lt__(self, other: 'object') -> 'bool': """Determines if the date time values are less than other. Args: @@ -300,7 +308,7 @@ def __lt__(self, other): return False - def __ne__(self, other): + def __ne__(self, other: 'object') -> 'bool': """Determines if the date time values are not equal to other. Args: @@ -315,8 +323,8 @@ def __ne__(self, other): class NotSet(SemanticTime): """Semantic time that represents not set.""" - _SORT_ORDER = 2 + _SORT_ORDER: 'int' = 2 - def __init__(self): + def __init__(self) -> 'None': """Initializes a semantic time that represents not set.""" super(NotSet, self).__init__(string='Not set') diff --git a/dfdatetime/systemtime.py b/dfdatetime/systemtime.py index 9bd501fb..255bf0da 100644 --- a/dfdatetime/systemtime.py +++ b/dfdatetime/systemtime.py @@ -5,6 +5,8 @@ import decimal +from typing import Optional, Tuple, Union # pylint: disable=unused-import + from dfdatetime import definitions from dfdatetime import interface @@ -38,7 +40,8 @@ class Systemtime(interface.DateTimeValues): # TODO: make attributes read-only. - def __init__(self, system_time_tuple=None): + def __init__(self, system_time_tuple: ( + 'Optional[Tuple[int, int, int, int, int, int, int, int]]') = None): # pylint: disable=bad-whitespace """Initializes a SYSTEMTIME structure. Args: @@ -51,16 +54,16 @@ def __init__(self, system_time_tuple=None): ValueError: if the system time is invalid. """ super(Systemtime, self).__init__() - self._number_of_seconds = None - self._precision = definitions.PRECISION_1_MILLISECOND - self.day_of_month = None - self.day_of_week = None - self.hours = None - self.milliseconds = None - self.minutes = None - self.month = None - self.seconds = None - self.year = None + self._number_of_seconds: 'Union[int, None]' = None + self._precision: 'str' = definitions.PRECISION_1_MILLISECOND + self.day_of_month: 'Union[int, None]' = None + self.day_of_week: 'Union[int, None]' = None + self.hours: 'Union[int, None]' = None + self.milliseconds: 'Union[int, None]' = None + self.minutes: 'Union[int, None]' = None + self.month: 'Union[int, None]' = None + self.seconds: 'Union[int, None]' = None + self.year: 'Union[int, None]' = None if system_time_tuple: if len(system_time_tuple) < 8: @@ -106,25 +109,25 @@ def __init__(self, system_time_tuple=None): self.year, self.month, self.day_of_month, self.hours, self.minutes, self.seconds, self._time_zone_offset) - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> 'Union[decimal.Decimal, None]': """Retrieves the normalized timestamp. Returns: decimal.Decimal: normalized timestamp, which contains the number of - seconds since January 1, 1970 00:00:00 and a fraction of second used - for increased precision, or None if the normalized timestamp cannot be - determined. + seconds since January 1, 1970 00:00:00 and a fraction of second + used for increased precision, or None if the normalized timestamp + cannot be determined. """ if self._normalized_timestamp is None: if self._number_of_seconds is not None: self._normalized_timestamp = ( - decimal.Decimal(self.milliseconds) / + decimal.Decimal(self.milliseconds or 0) / definitions.MILLISECONDS_PER_SECOND) self._normalized_timestamp += decimal.Decimal(self._number_of_seconds) return self._normalized_timestamp - def CopyFromDateTimeString(self, time_string): + def CopyFromDateTimeString(self, time_string: 'str') -> 'None': """Copies a SYSTEMTIME structure from a date and time string. Args: @@ -171,7 +174,7 @@ def CopyFromDateTimeString(self, time_string): self.seconds = seconds self.milliseconds = milliseconds - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the SYSTEMTIME structure to a date and time string. Returns: @@ -182,5 +185,6 @@ def CopyToDateTimeString(self): return None return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}.{6:03d}'.format( - self.year, self.month, self.day_of_month, self.hours, self.minutes, - self.seconds, self.milliseconds) + self.year or 0, self.month or 0, self.day_of_month or 0, + self.hours or 0, self.minutes or 0, self.seconds or 0, + self.milliseconds or 0) diff --git a/dfdatetime/time_elements.py b/dfdatetime/time_elements.py index 29c2ff44..5c905766 100644 --- a/dfdatetime/time_elements.py +++ b/dfdatetime/time_elements.py @@ -5,6 +5,8 @@ import decimal +from typing import Dict, Optional, Tuple, Union # pylint: disable=unused-import + from dfdatetime import definitions from dfdatetime import interface from dfdatetime import precisions @@ -20,7 +22,8 @@ class TimeElements(interface.DateTimeValues): is_local_time (bool): True if the date and time value is in local time. """ - def __init__(self, time_elements_tuple=None): + def __init__( + self, time_elements_tuple: 'Optional[Tuple[int, ...]]' = None) -> 'None': """Initializes time elements. Args: @@ -32,9 +35,10 @@ def __init__(self, time_elements_tuple=None): ValueError: if the time elements tuple is invalid. """ super(TimeElements, self).__init__() - self._number_of_seconds = None - self._precision = definitions.PRECISION_1_SECOND - self._time_elements_tuple = time_elements_tuple + self._number_of_seconds: 'Union[int, None]' = None + self._precision: 'str' = definitions.PRECISION_1_SECOND + self._time_elements_tuple: 'Union[Tuple[int, ...], None]' = ( + time_elements_tuple) if time_elements_tuple: if len(time_elements_tuple) < 6: @@ -46,16 +50,16 @@ def __init__(self, time_elements_tuple=None): time_elements_tuple[0], time_elements_tuple[1], time_elements_tuple[2], time_elements_tuple[3], time_elements_tuple[4], time_elements_tuple[5], - self._time_zone_offset) + time_zone_offset=self._time_zone_offset) - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> 'Union[decimal.Decimal, None]': """Retrieves the normalized timestamp. Returns: decimal.Decimal: normalized timestamp, which contains the number of - seconds since January 1, 1970 00:00:00 and a fraction of second used - for increased precision, or None if the normalized timestamp cannot be - determined. + seconds since January 1, 1970 00:00:00 and a fraction of second + used for increased precision, or None if the normalized timestamp + cannot be determined. """ if self._normalized_timestamp is None: if self._number_of_seconds is not None: @@ -63,7 +67,8 @@ def _GetNormalizedTimestamp(self): return self._normalized_timestamp - def _CopyDateTimeFromStringISO8601(self, time_string): + def _CopyDateTimeFromStringISO8601( + self, time_string: 'str') -> 'Dict[str, int]': """Copies a date and time from an ISO 8601 date and time string. Args: @@ -104,12 +109,12 @@ def _CopyDateTimeFromStringISO8601(self, time_string): self._CopyTimeFromStringISO8601(time_string[11:])) date_time_values = { - 'year': year, - 'month': month, - 'day_of_month': day_of_month, - 'hours': hours, - 'minutes': minutes, - 'seconds': seconds} + 'year': year or 0, + 'month': month or 0, + 'day_of_month': day_of_month or 0, + 'hours': hours or 0, + 'minutes': minutes or 0, + 'seconds': seconds or 0} if microseconds is not None: date_time_values['microseconds'] = microseconds @@ -118,7 +123,8 @@ def _CopyDateTimeFromStringISO8601(self, time_string): return date_time_values - def _CopyFromDateTimeValues(self, date_time_values): + def _CopyFromDateTimeValues( + self, date_time_values: 'Dict[str, int]') -> 'None': """Copies time elements from date and time values. Args: @@ -136,12 +142,15 @@ def _CopyFromDateTimeValues(self, date_time_values): self._normalized_timestamp = None self._number_of_seconds = self._GetNumberOfSecondsFromElements( - year, month, day_of_month, hours, minutes, seconds, time_zone_offset) + year, month, day_of_month, hours, minutes, seconds, + time_zone_offset=time_zone_offset) self._time_elements_tuple = ( year, month, day_of_month, hours, minutes, seconds) self._time_zone_offset = time_zone_offset - def _CopyTimeFromStringISO8601(self, time_string): + def _CopyTimeFromStringISO8601(self, time_string: 'str') -> ( + 'Tuple[int, Union[int, None], Union[int, None], Union[int, None], ' + 'Union[int, None]]'): """Copies a time from an ISO 8601 date and time string. Args: @@ -194,8 +203,8 @@ def _CopyTimeFromStringISO8601(self, time_string): raise ValueError('Time string too short.') try: - minutes = time_string[time_string_index:time_string_index + 2] - minutes = int(minutes, 10) + minutes_string = time_string[time_string_index:time_string_index + 2] + minutes = int(minutes_string, 10) except ValueError: raise ValueError('Unable to parse minutes.') @@ -212,8 +221,8 @@ def _CopyTimeFromStringISO8601(self, time_string): raise ValueError('Time string too short.') try: - seconds = time_string[time_string_index:time_string_index + 2] - seconds = int(seconds, 10) + seconds_string = time_string[time_string_index:time_string_index + 2] + seconds = int(seconds_string, 10) except ValueError: raise ValueError('Unable to parse day of seconds.') @@ -237,10 +246,11 @@ def _CopyTimeFromStringISO8601(self, time_string): time_fraction_length = time_zone_string_index - time_string_index try: - time_fraction = time_string[time_string_index:time_zone_string_index] - time_fraction = int(time_fraction, 10) + time_fraction_string = time_string[ + time_string_index:time_zone_string_index] + time_fraction_value = int(time_fraction_string, 10) time_fraction = ( - decimal.Decimal(time_fraction) / + decimal.Decimal(time_fraction_value) / decimal.Decimal(10 ** time_fraction_length)) except ValueError: raise ValueError('Unable to parse time fraction.') @@ -296,7 +306,7 @@ def _CopyTimeFromStringISO8601(self, time_string): return hours, minutes, seconds, microseconds, time_zone_offset - def CopyFromDateTimeString(self, time_string): + def CopyFromDateTimeString(self, time_string: 'str') -> 'None': """Copies time elements from a date and time string. Args: @@ -312,7 +322,7 @@ def CopyFromDateTimeString(self, time_string): self._CopyFromDateTimeValues(date_time_values) - def CopyFromStringISO8601(self, time_string): + def CopyFromStringISO8601(self, time_string: 'str') -> 'None': """Copies time elements from an ISO 8601 date and time string. Currently not supported: @@ -338,11 +348,12 @@ def CopyFromStringISO8601(self, time_string): self._CopyFromDateTimeValues(date_time_values) - def CopyFromStringTuple(self, time_elements_tuple): + def CopyFromStringTuple( + self, time_elements_tuple: 'Tuple[str, ...]') -> 'None': """Copies time elements from string-based time elements tuple. Args: - time_elements_tuple (Optional[tuple[str, str, str, str, str, str]]): + time_elements_tuple (tuple[str, str, str, str, str, str]): time elements, contains year, month, day of month, hours, minutes and seconds. @@ -393,18 +404,18 @@ def CopyFromStringTuple(self, time_elements_tuple): self._normalized_timestamp = None self._number_of_seconds = self._GetNumberOfSecondsFromElements( year, month, day_of_month, hours, minutes, seconds, - self._time_zone_offset) + time_zone_offset=self._time_zone_offset) self._time_elements_tuple = ( year, month, day_of_month, hours, minutes, seconds) - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the time elements to a date and time string. Returns: str: date and time value formatted as: "YYYY-MM-DD hh:mm:ss" or None if time elements are missing. """ - if self._number_of_seconds is None: + if self._time_elements_tuple is None: return None return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}'.format( @@ -422,7 +433,9 @@ class TimeElementsWithFractionOfSecond(TimeElements): is_local_time (bool): True if the date and time value is in local time. """ - def __init__(self, fraction_of_second=None, time_elements_tuple=None): + def __init__( + self, fraction_of_second: 'Optional[decimal.Decimal]' = None, + time_elements_tuple: 'Optional[Tuple[int, ...]]' = None) -> 'None': """Initializes time elements. Args: @@ -444,17 +457,16 @@ def __init__(self, fraction_of_second=None, time_elements_tuple=None): super(TimeElementsWithFractionOfSecond, self).__init__( time_elements_tuple=time_elements_tuple) - self._precision = None - self.fraction_of_second = fraction_of_second + self.fraction_of_second: 'Union[decimal.Decimal, None]' = fraction_of_second - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> 'Union[decimal.Decimal, None]': """Retrieves the normalized timestamp. Returns: decimal.Decimal: normalized timestamp, which contains the number of - seconds since January 1, 1970 00:00:00 and a fraction of second used - for increased precision, or None if the normalized timestamp cannot be - determined. + seconds since January 1, 1970 00:00:00 and a fraction of second + used for increased precision, or None if the normalized timestamp + cannot be determined. """ if self._normalized_timestamp is None: if (self._number_of_seconds is not None and @@ -464,7 +476,8 @@ def _GetNormalizedTimestamp(self): return self._normalized_timestamp - def _CopyFromDateTimeValues(self, date_time_values): + def _CopyFromDateTimeValues( + self, date_time_values: 'Dict[str, int]') -> 'None': """Copies time elements from date and time values. Args: @@ -492,18 +505,20 @@ def _CopyFromDateTimeValues(self, date_time_values): self._normalized_timestamp = None self._number_of_seconds = self._GetNumberOfSecondsFromElements( - year, month, day_of_month, hours, minutes, seconds, time_zone_offset) + year, month, day_of_month, hours, minutes, seconds, + time_zone_offset=time_zone_offset) self._time_elements_tuple = ( year, month, day_of_month, hours, minutes, seconds) self._time_zone_offset = time_zone_offset self.fraction_of_second = fraction_of_second - def CopyFromStringTuple(self, time_elements_tuple): + def CopyFromStringTuple( + self, time_elements_tuple: 'Tuple[str, ...]') -> 'None': """Copies time elements from string-based time elements tuple. Args: - time_elements_tuple (Optional[tuple[str, str, str, str, str, str, str]]): + time_elements_tuple (tuple[str, str, str, str, str, str, str]): time elements, contains year, month, day of month, hours, minutes, seconds and fraction of seconds. @@ -530,7 +545,7 @@ def CopyFromStringTuple(self, time_elements_tuple): self.fraction_of_second = fraction_of_second - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the time elements to a date and time string. Returns: @@ -540,7 +555,7 @@ def CopyToDateTimeString(self): Raises: ValueError: if the precision value is unsupported. """ - if self._number_of_seconds is None or self.fraction_of_second is None: + if self._time_elements_tuple is None or self.fraction_of_second is None: return None precision_helper = precisions.PrecisionHelperFactory.CreatePrecisionHelper( @@ -561,7 +576,8 @@ class TimeElementsInMilliseconds(TimeElementsWithFractionOfSecond): represents 1 millisecond (PRECISION_1_MILLISECOND). """ - def __init__(self, time_elements_tuple=None): + def __init__( + self, time_elements_tuple: 'Optional[Tuple[int, ...]]' = None) -> 'None': """Initializes time elements. Args: @@ -595,11 +611,13 @@ def __init__(self, time_elements_tuple=None): self._precision = definitions.PRECISION_1_MILLISECOND @property - def milliseconds(self): + def milliseconds(self) -> 'int': """int: number of milliseconds.""" - return int(self.fraction_of_second * definitions.MILLISECONDS_PER_SECOND) + return int( + (self.fraction_of_second or 0) * definitions.MILLISECONDS_PER_SECOND) - def CopyFromStringTuple(self, time_elements_tuple): + def CopyFromStringTuple( + self, time_elements_tuple: 'Tuple[str, ...]') -> 'None': """Copies time elements from string-based time elements tuple. Args: @@ -619,22 +637,24 @@ def CopyFromStringTuple(self, time_elements_tuple): time_elements_tuple) try: - milliseconds = int(milliseconds, 10) + milliseconds_value = int(milliseconds, 10) except (TypeError, ValueError): raise ValueError('Invalid millisecond value: {0!s}'.format(milliseconds)) - if milliseconds < 0 or milliseconds >= definitions.MILLISECONDS_PER_SECOND: + if (milliseconds_value < 0 or + milliseconds_value >= definitions.MILLISECONDS_PER_SECOND): raise ValueError('Invalid number of milliseconds.') fraction_of_second = ( - decimal.Decimal(milliseconds) / definitions.MILLISECONDS_PER_SECOND) + decimal.Decimal(milliseconds_value) / + definitions.MILLISECONDS_PER_SECOND) - time_elements_tuple = ( + time_elements_tuple_with_fraction = ( year, month, day_of_month, hours, minutes, seconds, str(fraction_of_second)) super(TimeElementsInMilliseconds, self).CopyFromStringTuple( - time_elements_tuple) + time_elements_tuple_with_fraction) class TimeElementsInMicroseconds(TimeElementsWithFractionOfSecond): @@ -648,7 +668,8 @@ class TimeElementsInMicroseconds(TimeElementsWithFractionOfSecond): represents 1 microsecond (PRECISION_1_MICROSECOND). """ - def __init__(self, time_elements_tuple=None): + def __init__( + self, time_elements_tuple: 'Optional[Tuple[int, ...]]' = None) -> 'None': """Initializes time elements. Args: @@ -682,11 +703,13 @@ def __init__(self, time_elements_tuple=None): self._precision = definitions.PRECISION_1_MICROSECOND @property - def microseconds(self): + def microseconds(self) -> 'int': """int: number of microseconds.""" - return int(self.fraction_of_second * definitions.MICROSECONDS_PER_SECOND) + return int( + (self.fraction_of_second or 0) * definitions.MICROSECONDS_PER_SECOND) - def CopyFromStringTuple(self, time_elements_tuple): + def CopyFromStringTuple( + self, time_elements_tuple: 'Tuple[str, ...]') -> 'None': """Copies time elements from string-based time elements tuple. Args: @@ -706,19 +729,21 @@ def CopyFromStringTuple(self, time_elements_tuple): time_elements_tuple) try: - microseconds = int(microseconds, 10) + microseconds_value = int(microseconds, 10) except (TypeError, ValueError): raise ValueError('Invalid microsecond value: {0!s}'.format(microseconds)) - if microseconds < 0 or microseconds >= definitions.MICROSECONDS_PER_SECOND: + if (microseconds_value < 0 or + microseconds_value >= definitions.MICROSECONDS_PER_SECOND): raise ValueError('Invalid number of microseconds.') fraction_of_second = ( - decimal.Decimal(microseconds) / definitions.MICROSECONDS_PER_SECOND) + decimal.Decimal(microseconds_value) / + definitions.MICROSECONDS_PER_SECOND) - time_elements_tuple = ( + time_elements_tuple_with_fraction = ( year, month, day_of_month, hours, minutes, seconds, str(fraction_of_second)) super(TimeElementsInMicroseconds, self).CopyFromStringTuple( - time_elements_tuple) + time_elements_tuple_with_fraction) diff --git a/dfdatetime/uuid_time.py b/dfdatetime/uuid_time.py index de6290af..1f75a6e7 100644 --- a/dfdatetime/uuid_time.py +++ b/dfdatetime/uuid_time.py @@ -5,6 +5,8 @@ import decimal +from typing import Optional, Union # pylint: disable=unused-import + from dfdatetime import definitions from dfdatetime import interface @@ -12,7 +14,7 @@ class UUIDTimeEpoch(interface.DateTimeEpoch): """UUID version 1 time epoch.""" - def __init__(self): + def __init__(self) -> 'None': """Initializes an UUID version 1 time epoch.""" super(UUIDTimeEpoch, self).__init__(1582, 10, 15) @@ -29,12 +31,12 @@ class UUIDTime(interface.DateTimeValues): Attributes: is_local_time (bool): True if the date and time value is in local time. """ - _EPOCH = UUIDTimeEpoch() + _EPOCH: 'interface.DateTimeEpoch' = UUIDTimeEpoch() # The difference between October 15, 1582 and January 1, 1970 in seconds. - _UUID_TO_POSIX_BASE = 12219292800 + _UUID_TO_POSIX_BASE: 'int' = 12219292800 - def __init__(self, timestamp=None): + def __init__(self, timestamp: 'Optional[int]' = None) -> 'None': """Initializes an UUID version 1 timestamp. Args: @@ -47,15 +49,15 @@ def __init__(self, timestamp=None): raise ValueError('Invalid UUID version 1 timestamp.') super(UUIDTime, self).__init__() - self._precision = definitions.PRECISION_100_NANOSECONDS - self._timestamp = timestamp + self._precision: 'str' = definitions.PRECISION_100_NANOSECONDS + self._timestamp: 'Union[int, None]' = timestamp @property - def timestamp(self): + def timestamp(self) -> 'Union[int, None]': """int: UUID timestamp or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> 'Union[decimal.Decimal, None]': """Retrieves the normalized timestamp. Returns: @@ -73,7 +75,7 @@ def _GetNormalizedTimestamp(self): return self._normalized_timestamp - def CopyFromDateTimeString(self, time_string): + def CopyFromDateTimeString(self, time_string: 'str') -> 'None': """Copies an UUID timestamp from a date and time string. Args: @@ -102,7 +104,8 @@ def CopyFromDateTimeString(self, time_string): raise ValueError('Year value not supported.') timestamp = self._GetNumberOfSecondsFromElements( - year, month, day_of_month, hours, minutes, seconds, time_zone_offset) + year, month, day_of_month, hours, minutes, seconds, + time_zone_offset=time_zone_offset) timestamp += self._UUID_TO_POSIX_BASE timestamp *= definitions.MICROSECONDS_PER_SECOND timestamp += date_time_values.get('microseconds', 0) @@ -112,7 +115,7 @@ def CopyFromDateTimeString(self, time_string): self._timestamp = timestamp self._time_zone_offset = time_zone_offset - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the UUID timestamp to a date and time string. Returns: diff --git a/dfdatetime/webkit_time.py b/dfdatetime/webkit_time.py index e7d2ea49..1c669ac3 100644 --- a/dfdatetime/webkit_time.py +++ b/dfdatetime/webkit_time.py @@ -5,6 +5,8 @@ import decimal +from typing import Optional, Union # pylint: disable=unused-import + from dfdatetime import definitions from dfdatetime import interface @@ -12,7 +14,7 @@ class WebKitTimeEpoch(interface.DateTimeEpoch): """WebKit time epoch.""" - def __init__(self): + def __init__(self) -> 'None': """Initializes a WebKit time epoch.""" super(WebKitTimeEpoch, self).__init__(1601, 1, 1) @@ -27,33 +29,34 @@ class WebKitTime(interface.DateTimeValues): is_local_time (bool): True if the date and time value is in local time. """ - _EPOCH = WebKitTimeEpoch() + _EPOCH: 'interface.DateTimeEpoch' = WebKitTimeEpoch() # The difference between January 1, 1601 and January 1, 1970 in seconds. _WEBKIT_TO_POSIX_BASE = 11644473600 - def __init__(self, timestamp=None): + def __init__(self, timestamp: 'Optional[int]' = None) -> 'None': """Initializes a WebKit timestamp. Args: timestamp (Optional[int]): WebKit timestamp. """ super(WebKitTime, self).__init__() - self._precision = definitions.PRECISION_1_MICROSECOND - self._timestamp = timestamp + self._precision: 'str' = definitions.PRECISION_1_MICROSECOND + self._timestamp: 'Union[int, None]' = timestamp @property - def timestamp(self): - """decimal.Decimal: WebKit timestamp or None if timestamp is not set.""" + def timestamp(self) -> 'Union[int, None]': + """int: WebKit timestamp or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> 'Union[decimal.Decimal, None]': """Retrieves the normalized timestamp. Returns: - float: normalized timestamp, which contains the number of seconds since - January 1, 1970 00:00:00 and a fraction of second used for increased - precision, or None if the normalized timestamp cannot be determined. + decimal.Decimal: normalized timestamp, which contains the number of + seconds since January 1, 1970 00:00:00 and a fraction of second + used for increased precision, or None if the normalized timestamp + cannot be determined. """ if self._normalized_timestamp is None: if (self._timestamp is not None and self._timestamp >= self._INT64_MIN and @@ -65,7 +68,7 @@ def _GetNormalizedTimestamp(self): return self._normalized_timestamp - def CopyFromDateTimeString(self, time_string): + def CopyFromDateTimeString(self, time_string: 'str') -> 'None': """Copies a WebKit timestamp from a date and time string. Args: @@ -91,7 +94,8 @@ def CopyFromDateTimeString(self, time_string): time_zone_offset = date_time_values.get('time_zone_offset', 0) timestamp = self._GetNumberOfSecondsFromElements( - year, month, day_of_month, hours, minutes, seconds, time_zone_offset) + year, month, day_of_month, hours, minutes, seconds, + time_zone_offset=time_zone_offset) timestamp += self._WEBKIT_TO_POSIX_BASE timestamp *= definitions.MICROSECONDS_PER_SECOND timestamp += date_time_values.get('microseconds', 0) @@ -100,7 +104,7 @@ def CopyFromDateTimeString(self, time_string): self._timestamp = timestamp self._time_zone_offset = time_zone_offset - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> 'Union[str, None]': """Copies the WebKit timestamp to a date and time string. Returns: diff --git a/setup.py b/setup.py index 76aa3e85..d92e8323 100755 --- a/setup.py +++ b/setup.py @@ -22,9 +22,9 @@ bdist_rpm = None version_tuple = (sys.version_info[0], sys.version_info[1]) -if version_tuple < (3, 5): +if version_tuple < (3, 6): print(( - 'Unsupported Python version: {0:s}, version 3.5 or higher ' + 'Unsupported Python version: {0:s}, version 3.6 or higher ' 'required.').format(sys.version)) sys.exit(1) diff --git a/tests/interface.py b/tests/interface.py index 7a1fbe8c..3e6c9f09 100644 --- a/tests/interface.py +++ b/tests/interface.py @@ -570,9 +570,8 @@ def testGetNumberOfSecondsFromElements(self): 1601, 1, 2, 0, 0, 0, None) self.assertEqual(number_of_seconds, -11644387200) - number_of_seconds = date_time_values._GetNumberOfSecondsFromElements( - 0, 1, 2, 0, 0, 0, None) - self.assertIsNone(number_of_seconds) + with self.assertRaises(ValueError): + date_time_values._GetNumberOfSecondsFromElements(0, 1, 2, 0, 0, 0, None) with self.assertRaises(ValueError): date_time_values._GetNumberOfSecondsFromElements(