From a831901aaf3cd07d1804456ba978af317a944956 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 | 2 +- config/travis/install.sh | 8 +- .../travis/{run_pylint.sh => run_checks.sh} | 24 ++- config/travis/runtests.sh | 8 +- dfdatetime/apfs_time.py | 13 +- dfdatetime/cocoa_time.py | 33 ++-- dfdatetime/decorators.py | 11 +- dfdatetime/delphi_date_time.py | 30 ++-- dfdatetime/fake_time.py | 26 +-- dfdatetime/fat_date_time.py | 28 ++-- dfdatetime/filetime.py | 26 +-- dfdatetime/hfs_time.py | 26 +-- dfdatetime/interface.py | 122 +++++++------- dfdatetime/java_time.py | 11 +- dfdatetime/ole_automation_date.py | 30 ++-- dfdatetime/posix_time.py | 99 +++++------ dfdatetime/precisions.py | 32 +++- dfdatetime/rfc2579_date_time.py | 50 +++--- dfdatetime/semantic_time.py | 59 ++++--- dfdatetime/systemtime.py | 43 ++--- dfdatetime/time_elements.py | 154 ++++++++++-------- dfdatetime/uuid_time.py | 20 ++- dfdatetime/webkit_time.py | 29 ++-- tests/interface.py | 5 +- 25 files changed, 505 insertions(+), 387 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..2de77b21 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 diff --git a/config/travis/install.sh b/config/travis/install.sh index 2ba7ff91..53e03ec2 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} pylint python3-distutils python3-mypy"; 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..b14395eb 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 + REUSLT=${EXIT_SUCCESS}; + fi done + +mypy --version + +mypy --strict dfdatetime tests; + +if test $? -ne ${EXIT_SUCCESS}; +then + REUSLT=${EXIT_SUCCESS}; +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/apfs_time.py b/dfdatetime/apfs_time.py index 9b637da2..6d3ccf5a 100644 --- a/dfdatetime/apfs_time.py +++ b/dfdatetime/apfs_time.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import decimal +import typing from dfdatetime import definitions from dfdatetime import posix_time @@ -19,14 +20,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) -> typing.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 +38,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 +59,7 @@ def CopyFromDateTimeString(self, time_string): self._timestamp > self._INT64_MAX): raise ValueError('Date time value not supported.') - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> typing.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..88460908 100644 --- a/dfdatetime/cocoa_time.py +++ b/dfdatetime/cocoa_time.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import decimal +import typing from dfdatetime import definitions from dfdatetime import interface @@ -12,7 +13,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) @@ -36,28 +37,29 @@ class CocoaTime(interface.DateTimeValues): _EPOCH = CocoaTimeEpoch() - def __init__(self, timestamp=None): + def __init__(self, timestamp: typing.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: typing.Union[float, None] = timestamp @property - def timestamp(self): + def timestamp(self) -> typing.Union[float, None]: """float: Cocoa timestamp or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> typing.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 +68,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 +94,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 +107,7 @@ def CopyFromDateTimeString(self, time_string): self._timestamp = timestamp self._time_zone_offset = time_zone_offset - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> typing.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..912c2d1e 100644 --- a/dfdatetime/decorators.py +++ b/dfdatetime/decorators.py @@ -4,12 +4,19 @@ from __future__ import unicode_literals import warnings +import typing -def deprecated(function): # pylint: disable=invalid-name +# pylint: disable=invalid-name +RETURN_TYPE = typing.TypeVar('RETURN_TYPE') + + +def deprecated(function: typing.Callable[..., RETURN_TYPE]) -> typing.Callable[ + ..., RETURN_TYPE]: """Decorator to mark functions or methods as deprecated.""" - def IssueDeprecationWarning(*args, **kwargs): + def IssueDeprecationWarning( + *args: typing.Any, **kwargs: typing.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..de7c4a46 100644 --- a/dfdatetime/delphi_date_time.py +++ b/dfdatetime/delphi_date_time.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import decimal +import typing from dfdatetime import definitions from dfdatetime import interface @@ -12,7 +13,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) @@ -38,29 +39,29 @@ class DelphiDateTime(interface.DateTimeValues): _EPOCH = DelphiDateTimeEpoch() - def __init__(self, timestamp=None): + def __init__(self, timestamp: typing.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: typing.Union[float, None] = timestamp @property - def timestamp(self): + def timestamp(self) -> typing.Union[float, None]: """float: Delphi TDateTime timestamp or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> typing.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 +71,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 +100,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 +113,7 @@ def CopyFromDateTimeString(self, time_string): self._timestamp = timestamp self._time_zone_offset = time_zone_offset - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> typing.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..3186842b 100644 --- a/dfdatetime/fake_time.py +++ b/dfdatetime/fake_time.py @@ -5,6 +5,7 @@ import decimal import time +import typing from dfdatetime import definitions from dfdatetime import interface @@ -23,36 +24,36 @@ class FakeTime(interface.DateTimeValues): _EPOCH = 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: typing.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) -> typing.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 +77,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) -> typing.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..fb832265 100644 --- a/dfdatetime/fat_date_time.py +++ b/dfdatetime/fat_date_time.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import decimal +import typing from dfdatetime import definitions from dfdatetime import interface @@ -12,7 +13,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) @@ -44,28 +45,29 @@ class FATDateTime(interface.DateTimeValues): # The difference between January 1, 1980 and January 1, 1970 in seconds. _FAT_DATE_TO_POSIX_BASE = 315532800 - def __init__(self, fat_date_time=None): + def __init__(self, fat_date_time: typing.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: typing.Union[int, None] = number_of_seconds + self._precision: str = definitions.PRECISION_2_SECONDS - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> typing.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 +77,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 +122,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 +156,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) -> typing.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..638b0995 100644 --- a/dfdatetime/filetime.py +++ b/dfdatetime/filetime.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import decimal +import typing from dfdatetime import definitions from dfdatetime import interface @@ -12,7 +13,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) @@ -35,29 +36,29 @@ class Filetime(interface.DateTimeValues): # The difference between January 1, 1601 and January 1, 1970 in seconds. _FILETIME_TO_POSIX_BASE = 11644473600 - def __init__(self, timestamp=None): + def __init__(self, timestamp: typing.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: typing.Union[int, None] = timestamp @property - def timestamp(self): + def timestamp(self) -> typing.Union[int, None]: """int: FILETIME timestamp or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> typing.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 +69,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 +98,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 +109,7 @@ def CopyFromDateTimeString(self, time_string): self._timestamp = timestamp self._time_zone_offset = time_zone_offset - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> typing.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..62cfa824 100644 --- a/dfdatetime/hfs_time.py +++ b/dfdatetime/hfs_time.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import decimal +import typing from dfdatetime import definitions from dfdatetime import interface @@ -12,7 +13,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) @@ -32,29 +33,29 @@ class HFSTime(interface.DateTimeValues): # The difference between Jan 1, 1904 and Jan 1, 1970 in seconds. _HFS_TO_POSIX_BASE = 2082844800 - def __init__(self, timestamp=None): + def __init__(self, timestamp: typing.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: typing.Union[int, None] = timestamp @property - def timestamp(self): + def timestamp(self) -> typing.Union[int, None]: """int: HFS timestamp or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> typing.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 +65,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 +95,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) -> typing.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..a7829ebb 100644 --- a/dfdatetime/interface.py +++ b/dfdatetime/interface.py @@ -6,6 +6,7 @@ import abc import calendar import decimal +import typing from dfdatetime import decorators from dfdatetime import definitions @@ -24,7 +25,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 +36,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) @@ -75,30 +76,30 @@ class DateTimeValues(object): _UINT60_MAX = (1 << 60) - 1 _UINT64_MAX = (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: typing.Union[decimal.Decimal, None] = None + self._precision: typing.Union[str, None] = None + self._time_zone_offset: typing.Union[int, None] = None - self.is_local_time = False + self.is_local_time: bool = False @property - def precision(self): + def precision(self) -> typing.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) -> typing.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 +122,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 +148,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 +174,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 +200,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 +226,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 +250,8 @@ 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) -> typing.Tuple[int, int, int, int, int]: """Adjusts the date and time values for a time zone offset. Args: @@ -261,7 +263,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 +309,8 @@ def _AdjustForTimeZoneOffset( return year, month, day_of_month, hours, minutes - def _CopyDateFromString(self, date_string): + def _CopyDateFromString( + self, date_string: str) -> typing.Tuple[int, int, int]: """Copies a date from a string. Args: @@ -349,7 +352,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 +408,8 @@ def _CopyDateTimeFromString(self, time_string): return date_time_values - def _CopyTimeFromString(self, time_string): + def _CopyTimeFromString(self, time_string: str) -> typing.Tuple[ + int, int, int, typing.Union[int, None], typing.Union[int, None]]: """Copies a time from a string. Args: @@ -478,8 +482,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 +524,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) -> typing.Tuple[int, int, int]: """Determines date values. Args: @@ -644,7 +649,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) -> typing.Tuple[int, int, int]: """Determines date values. Args: @@ -658,7 +665,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 +692,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 +715,17 @@ def _GetDaysPerMonth(self, year, month): return days_per_month @abc.abstractmethod - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> typing.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 +746,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 +760,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: typing.Optional[int] = None) -> int: """Retrieves the number of seconds from the date and time elements. Args: @@ -764,18 +771,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 +818,8 @@ def _GetNumberOfSecondsFromElements( return int(number_of_seconds) - def _GetTimeValues(self, number_of_seconds): + def _GetTimeValues(self, number_of_seconds: typing.Union[ + int, decimal.Decimal]) -> typing.Tuple[int, int, int, int]: """Determines time values. Args: @@ -826,7 +834,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 +847,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 +865,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 +881,7 @@ def CopyFromDateTimeString(self, time_string): ValueError: if the time string is invalid or not supported. """ - def CopyToPosixTimestamp(self): + def CopyToPosixTimestamp(self) -> typing.Union[int, None]: """Copies the date time value to a POSIX timestamp. Returns: @@ -886,7 +894,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) -> typing.Union[ + typing.Tuple[int, int], typing.Tuple[int, None], + typing.Tuple[None, None]]: """Copies the date time value to a stat timestamp tuple. Returns: @@ -910,7 +920,7 @@ def CopyToStatTimeTuple(self): return int(normalized_timestamp), None @abc.abstractmethod - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> typing.Union[str, None]: """Copies the date time value to a date and time string. Returns: @@ -918,7 +928,7 @@ def CopyToDateTimeString(self): None if the timestamp cannot be copied to a date and time string. """ - def CopyToDateTimeStringISO8601(self): + def CopyToDateTimeStringISO8601(self) -> typing.Union[str, None]: """Copies the date time value to an ISO 8601 date and time string. Returns: @@ -931,7 +941,8 @@ def CopyToDateTimeStringISO8601(self): date_time_string = '{0:s}Z'.format(date_time_string) return date_time_string - def GetDate(self): + def GetDate(self) -> typing.Union[ + typing.Tuple[int, int, int], typing.Tuple[None, None, None]]: """Retrieves the date represented by the date and time values. Returns: @@ -952,7 +963,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) -> typing.Union[int, None]: """Retrieves a timestamp that is compatible with plaso. Returns: @@ -968,7 +979,8 @@ def GetPlasoTimestamp(self): 1, rounding=decimal.ROUND_HALF_UP) return int(normalized_timestamp) - def GetTimeOfDay(self): + def GetTimeOfDay(self) -> typing.Union[ + typing.Tuple[int, int, int], typing.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..388bcb40 100644 --- a/dfdatetime/java_time.py +++ b/dfdatetime/java_time.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import decimal +import typing from dfdatetime import definitions from dfdatetime import posix_time @@ -23,14 +24,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) -> typing.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 +42,7 @@ def _GetNormalizedTimestamp(self): return self._normalized_timestamp - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> typing.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..cac54687 100644 --- a/dfdatetime/ole_automation_date.py +++ b/dfdatetime/ole_automation_date.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import decimal +import typing from dfdatetime import definitions from dfdatetime import interface @@ -12,7 +13,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) @@ -36,29 +37,29 @@ class OLEAutomationDate(interface.DateTimeValues): # The difference between December 30, 1899 and January 1, 1970 in days. _OLE_AUTOMATION_DATE_TO_POSIX_BASE = 25569 - def __init__(self, timestamp=None): + def __init__(self, timestamp: typing.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: typing.Union[float, None] = timestamp @property - def timestamp(self): + def timestamp(self) -> typing.Union[float, None]: """float: OLE Automation date timestamp or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> typing.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 +70,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 +96,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 +111,7 @@ def CopyFromDateTimeString(self, time_string): self._timestamp = timestamp self._time_zone_offset = time_zone_offset - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> typing.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..7d0e9f33 100644 --- a/dfdatetime/posix_time.py +++ b/dfdatetime/posix_time.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import decimal +import typing from dfdatetime import definitions from dfdatetime import interface @@ -12,7 +13,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) @@ -33,29 +34,29 @@ class PosixTime(interface.DateTimeValues): _EPOCH = PosixTimeEpoch() - def __init__(self, timestamp=None): + def __init__(self, timestamp: typing.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: typing.Union[int, None] = timestamp @property - def timestamp(self): + def timestamp(self) -> typing.Union[int, None]: """int: POSIX timestamp or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> typing.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 +64,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 +87,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) -> typing.Union[str, None]: """Copies the POSIX timestamp to a date and time string. Returns: @@ -120,29 +122,29 @@ class PosixTimeInMilliseconds(interface.DateTimeValues): _EPOCH = PosixTimeEpoch() - def __init__(self, timestamp=None): + def __init__(self, timestamp: typing.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: typing.Union[int, None] = timestamp @property - def timestamp(self): + def timestamp(self) -> typing.Union[int, None]: """int: POSIX timestamp in milliseconds or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> typing.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 +154,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 +178,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 +190,7 @@ def CopyFromDateTimeString(self, time_string): self._timestamp = timestamp self._time_zone_offset = time_zone_offset - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> typing.Union[str, None]: """Copies the POSIX timestamp to a date and time string. Returns: @@ -219,29 +222,29 @@ class PosixTimeInMicroseconds(interface.DateTimeValues): _EPOCH = PosixTimeEpoch() - def __init__(self, timestamp=None): + def __init__(self, timestamp: typing.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: typing.Union[int, None] = timestamp @property - def timestamp(self): + def timestamp(self) -> typing.Union[int, None]: """int: POSIX timestamp in microseconds or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> typing.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 +254,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 +278,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) -> typing.Union[str, None]: """Copies the POSIX timestamp to a date and time string. Returns: @@ -314,29 +318,29 @@ class PosixTimeInNanoseconds(interface.DateTimeValues): _EPOCH = PosixTimeEpoch() - def __init__(self, timestamp=None): + def __init__(self, timestamp: typing.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: typing.Union[int, None] = timestamp @property - def timestamp(self): + def timestamp(self) -> typing.Union[int, None]: """int: POSIX timestamp or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> typing.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 +350,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 +374,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 +386,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 +400,7 @@ def CopyFromDateTimeString(self, time_string): """ self._CopyFromDateTimeString(time_string) - def _CopyToDateTimeString(self): + def _CopyToDateTimeString(self) -> typing.Union[str, None]: """Copies the POSIX timestamp to a date and time string. Returns: @@ -415,7 +420,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) -> typing.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..b222d223 100644 --- a/dfdatetime/precisions.py +++ b/dfdatetime/precisions.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import decimal +import typing from dfdatetime import definitions @@ -20,7 +21,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 +35,9 @@ def CopyMicrosecondsToFractionOfSecond(cls, microseconds): raise NotImplementedError() @classmethod - def CopyToDateTimeString(cls, time_elements_tuple, fraction_of_second): + def CopyToDateTimeString( + cls, time_elements_tuple: typing.Tuple[int, ...], + fraction_of_second: decimal.Decimal) -> str: """Copies the time elements and fraction of second to a string. Args: @@ -54,7 +58,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 +80,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: typing.Tuple[int, ...], + fraction_of_second: decimal.Decimal) -> str: """Copies the time elements and fraction of second to a string. Args: @@ -105,7 +112,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 +136,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: typing.Tuple[int, ...], + fraction_of_second: decimal.Decimal) -> str: """Copies the time elements and fraction of second to a string. Args: @@ -161,7 +171,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 +193,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: typing.Tuple[int, ...], + fraction_of_second: decimal.Decimal) -> str: """Copies the time elements and fraction of second to a string. Args: @@ -221,7 +234,8 @@ class PrecisionHelperFactory(object): } @classmethod - def CreatePrecisionHelper(cls, precision): + def CreatePrecisionHelper(cls, precision: str) -> typing.Type[ + DateTimePrecisionHelper]: """Creates a precision helper. Args: diff --git a/dfdatetime/rfc2579_date_time.py b/dfdatetime/rfc2579_date_time.py index ce18b19f..d53b7d74 100644 --- a/dfdatetime/rfc2579_date_time.py +++ b/dfdatetime/rfc2579_date_time.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import decimal +import typing from dfdatetime import definitions from dfdatetime import interface @@ -45,28 +46,29 @@ class RFC2579DateTime(interface.DateTimeValues): # pylint: disable=missing-type-doc - def __init__(self, rfc2579_date_time_tuple=None): + def __init__(self, rfc2579_date_time_tuple: typing.Optional[ + typing.Tuple[int, int, int, int, int, int, int, str, int, int]] = None): """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: typing.Union[int, None] = None + self._precision: str = definitions.PRECISION_100_MILLISECONDS + self.day_of_month: typing.Union[int, None] = None + self.hours: typing.Union[int, None] = None + self.deciseconds: typing.Union[int, None] = None + self.minutes: typing.Union[int, None] = None + self.month: typing.Union[int, None] = None + self.seconds: typing.Union[int, None] = None + self.year: typing.Union[int, None] = None if rfc2579_date_time_tuple: if len(rfc2579_date_time_tuple) < 10: @@ -125,27 +127,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) -> typing.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 +181,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 +193,7 @@ def CopyFromDateTimeString(self, time_string): self.seconds = seconds self.deciseconds = deciseconds - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> typing.Union[str, None]: """Copies the RFC2579 date-time to a date and time string. Returns: @@ -201,5 +204,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..590aa1b1 100644 --- a/dfdatetime/semantic_time.py +++ b/dfdatetime/semantic_time.py @@ -3,6 +3,9 @@ from __future__ import unicode_literals +import decimal +import typing + from dfdatetime import interface @@ -20,7 +23,7 @@ class SemanticTime(interface.DateTimeValues): _SORT_ORDER = 50 - def __init__(self, string=None): + def __init__(self, string: typing.Optional[str] = None) -> None: """Initializes a semantic time. Args: @@ -28,14 +31,14 @@ def __init__(self, string=None): "Never", "Not set". """ super(SemanticTime, self).__init__() - self._string = string + self._string: typing.Union[str, None] = string @property - def string(self): + def string(self) -> typing.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 +52,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 +72,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 +92,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 +112,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 +132,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 +146,18 @@ def __ne__(self, other): return self._SORT_ORDER != other._SORT_ORDER # pylint: disable=protected-access - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> typing.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 +169,7 @@ def CopyFromDateTimeString(self, time_string): """ self._string = time_string - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> typing.Union[str, None]: """Copies the date time value to a date and time string. Returns: @@ -174,7 +177,7 @@ def CopyToDateTimeString(self): """ return self._string - def CopyToDateTimeStringISO8601(self): + def CopyToDateTimeStringISO8601(self) -> typing.Union[str, None]: """Copies the date time value to an ISO 8601 date and time string. Returns: @@ -184,7 +187,9 @@ def CopyToDateTimeStringISO8601(self): """ return None - def CopyToStatTimeTuple(self): + def CopyToStatTimeTuple(self) -> typing.Union[ + typing.Tuple[int, int], typing.Tuple[int, None], + typing.Tuple[None, None]]: """Copies the semantic timestamp to a stat timestamp tuple. Returns: @@ -193,7 +198,7 @@ def CopyToStatTimeTuple(self): """ return None, None - def GetPlasoTimestamp(self): + def GetPlasoTimestamp(self) -> typing.Union[int, None]: """Retrieves a timestamp that is compatible with plaso. Returns: @@ -207,7 +212,7 @@ class InvalidTime(SemanticTime): _SORT_ORDER = 1 - def __init__(self): + def __init__(self) -> None: """Initializes a semantic time that represents invalid.""" super(InvalidTime, self).__init__(string='Invalid') @@ -217,11 +222,11 @@ class Never(SemanticTime): _SORT_ORDER = 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 +237,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 +254,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 +271,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 +288,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 +305,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: @@ -317,6 +322,6 @@ class NotSet(SemanticTime): _SORT_ORDER = 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..277c2875 100644 --- a/dfdatetime/systemtime.py +++ b/dfdatetime/systemtime.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import decimal +import typing from dfdatetime import definitions from dfdatetime import interface @@ -38,7 +39,8 @@ class Systemtime(interface.DateTimeValues): # TODO: make attributes read-only. - def __init__(self, system_time_tuple=None): + def __init__(self, system_time_tuple: typing.Optional[ + typing.Tuple[int, int, int, int, int, int, int, int]] = None): """Initializes a SYSTEMTIME structure. Args: @@ -51,16 +53,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: typing.Union[int, None] = None + self._precision: str = definitions.PRECISION_1_MILLISECOND + self.day_of_month: typing.Union[int, None] = None + self.day_of_week: typing.Union[int, None] = None + self.hours: typing.Union[int, None] = None + self.milliseconds: typing.Union[int, None] = None + self.minutes: typing.Union[int, None] = None + self.month: typing.Union[int, None] = None + self.seconds: typing.Union[int, None] = None + self.year: typing.Union[int, None] = None if system_time_tuple: if len(system_time_tuple) < 8: @@ -106,25 +108,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) -> typing.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 +173,7 @@ def CopyFromDateTimeString(self, time_string): self.seconds = seconds self.milliseconds = milliseconds - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> typing.Union[str, None]: """Copies the SYSTEMTIME structure to a date and time string. Returns: @@ -182,5 +184,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..ee4f4bdb 100644 --- a/dfdatetime/time_elements.py +++ b/dfdatetime/time_elements.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import decimal +import typing from dfdatetime import definitions from dfdatetime import interface @@ -20,7 +21,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: typing.Optional[ + typing.Tuple[int, ...]] = None) -> None: """Initializes time elements. Args: @@ -32,9 +34,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: typing.Union[int, None] = None + self._precision: str = definitions.PRECISION_1_SECOND + self._time_elements_tuple: typing.Union[ + typing.Tuple[int, ...], None] = time_elements_tuple if time_elements_tuple: if len(time_elements_tuple) < 6: @@ -46,16 +49,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) -> typing.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 +66,8 @@ def _GetNormalizedTimestamp(self): return self._normalized_timestamp - def _CopyDateTimeFromStringISO8601(self, time_string): + def _CopyDateTimeFromStringISO8601( + self, time_string: str) -> typing.Dict[str, int]: """Copies a date and time from an ISO 8601 date and time string. Args: @@ -104,12 +108,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 +122,8 @@ def _CopyDateTimeFromStringISO8601(self, time_string): return date_time_values - def _CopyFromDateTimeValues(self, date_time_values): + def _CopyFromDateTimeValues( + self, date_time_values: typing.Dict[str, int]) -> None: """Copies time elements from date and time values. Args: @@ -136,12 +141,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) -> typing.Tuple[ + int, typing.Union[int, None], typing.Union[int, None], + typing.Union[int, None], typing.Union[int, None]]: """Copies a time from an ISO 8601 date and time string. Args: @@ -194,8 +202,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 +220,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 +245,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 +305,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 +321,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 +347,12 @@ def CopyFromStringISO8601(self, time_string): self._CopyFromDateTimeValues(date_time_values) - def CopyFromStringTuple(self, time_elements_tuple): + def CopyFromStringTuple( + self, time_elements_tuple: typing.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 +403,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) -> typing.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 +432,10 @@ 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: typing.Optional[decimal.Decimal] = None, + time_elements_tuple: typing.Optional[ + typing.Tuple[int, ...]] = None) -> None: """Initializes time elements. Args: @@ -444,17 +457,17 @@ 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: typing.Union[ + decimal.Decimal, None] = fraction_of_second - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> typing.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 +477,8 @@ def _GetNormalizedTimestamp(self): return self._normalized_timestamp - def _CopyFromDateTimeValues(self, date_time_values): + def _CopyFromDateTimeValues( + self, date_time_values: typing.Dict[str, int]) -> None: """Copies time elements from date and time values. Args: @@ -492,18 +506,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: typing.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 +546,7 @@ def CopyFromStringTuple(self, time_elements_tuple): self.fraction_of_second = fraction_of_second - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> typing.Union[str, None]: """Copies the time elements to a date and time string. Returns: @@ -540,7 +556,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 +577,8 @@ class TimeElementsInMilliseconds(TimeElementsWithFractionOfSecond): represents 1 millisecond (PRECISION_1_MILLISECOND). """ - def __init__(self, time_elements_tuple=None): + def __init__(self, time_elements_tuple: typing.Optional[ + typing.Tuple[int, ...]] = None) -> None: """Initializes time elements. Args: @@ -595,11 +612,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: typing.Tuple[str, ...]) -> None: """Copies time elements from string-based time elements tuple. Args: @@ -619,22 +638,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 +669,8 @@ class TimeElementsInMicroseconds(TimeElementsWithFractionOfSecond): represents 1 microsecond (PRECISION_1_MICROSECOND). """ - def __init__(self, time_elements_tuple=None): + def __init__(self, time_elements_tuple: typing.Optional[ + typing.Tuple[int, ...]] = None) -> None: """Initializes time elements. Args: @@ -682,11 +704,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: typing.Tuple[str, ...]) -> None: """Copies time elements from string-based time elements tuple. Args: @@ -706,19 +730,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..585c8918 100644 --- a/dfdatetime/uuid_time.py +++ b/dfdatetime/uuid_time.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import decimal +import typing from dfdatetime import definitions from dfdatetime import interface @@ -12,7 +13,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) @@ -34,7 +35,7 @@ class UUIDTime(interface.DateTimeValues): # The difference between October 15, 1582 and January 1, 1970 in seconds. _UUID_TO_POSIX_BASE = 12219292800 - def __init__(self, timestamp=None): + def __init__(self, timestamp: typing.Optional[int] = None) -> None: """Initializes an UUID version 1 timestamp. Args: @@ -47,15 +48,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: typing.Union[int, None] = timestamp @property - def timestamp(self): + def timestamp(self) -> typing.Union[int, None]: """int: UUID timestamp or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> typing.Union[decimal.Decimal, None]: """Retrieves the normalized timestamp. Returns: @@ -73,7 +74,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 +103,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 +114,7 @@ def CopyFromDateTimeString(self, time_string): self._timestamp = timestamp self._time_zone_offset = time_zone_offset - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> typing.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..d0fab9c0 100644 --- a/dfdatetime/webkit_time.py +++ b/dfdatetime/webkit_time.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import decimal +import typing from dfdatetime import definitions from dfdatetime import interface @@ -12,7 +13,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) @@ -32,28 +33,29 @@ class WebKitTime(interface.DateTimeValues): # 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: typing.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: typing.Union[int, None] = timestamp @property - def timestamp(self): - """decimal.Decimal: WebKit timestamp or None if timestamp is not set.""" + def timestamp(self) -> typing.Union[int, None]: + """int: WebKit timestamp or None if timestamp is not set.""" return self._timestamp - def _GetNormalizedTimestamp(self): + def _GetNormalizedTimestamp(self) -> typing.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 +67,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 +93,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 +103,7 @@ def CopyFromDateTimeString(self, time_string): self._timestamp = timestamp self._time_zone_offset = time_zone_offset - def CopyToDateTimeString(self): + def CopyToDateTimeString(self) -> typing.Union[str, None]: """Copies the WebKit timestamp to a date and time string. Returns: 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(