File pytimeparse2-1.7.1.obscpio of Package python-pytimeparse2
07070100000000000081A4000000000000000000000001645D608F000000F5000000000000000000000000000000000000001F00000000pytimeparse2-1.7.1/.coveragerc[run]
source =
pytimeparse2
tests
parallel = True
concurrency =
thread
multiprocessing
omit =
*.tox/*
*setup.py
[report]
fail_under = 100
show_missing = True
exclude_lines =
pragma: no cover
nocv
MemoryError
07070100000001000041ED000000000000000000000002645D608F00000000000000000000000000000000000000000000001B00000000pytimeparse2-1.7.1/.github07070100000002000041ED000000000000000000000002645D608F00000000000000000000000000000000000000000000002500000000pytimeparse2-1.7.1/.github/workflows07070100000003000081A4000000000000000000000001645D608F00000274000000000000000000000000000000000000002F00000000pytimeparse2-1.7.1/.github/workflows/check.ymlname: Python package
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-20.04
strategy:
max-parallel: 4
matrix:
python-version: ['3.6.15', 3.7, 3.8, 3.9, '3.10', '3.11']
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install tox tox-gh-actions
- name: Test with tox
run: tox
07070100000004000081A4000000000000000000000001645D608F0000006B000000000000000000000000000000000000001E00000000pytimeparse2-1.7.1/.gitignore*.pyc
*~
*.c
.DS_Store
/.coverage
/MANIFEST
/build/
/dist/
*.egg-info/
venv
.tox
.mypy_cache
.idea
.vscode
07070100000005000081A4000000000000000000000001645D608F00000054000000000000000000000000000000000000001900000000pytimeparse2-1.7.1/.pep8[flake8]
ignore =
exclude = /.tox/*
max-line-length = 120
import-order-style = pep8
07070100000006000081A4000000000000000000000001645D608F0000043A000000000000000000000000000000000000001F00000000pytimeparse2-1.7.1/LICENSE.rstThe MIT License (MIT)
Copyright (c) 2021 Sergey Klyuykov
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
07070100000007000081A4000000000000000000000001645D608F00000039000000000000000000000000000000000000001F00000000pytimeparse2-1.7.1/MANIFEST.ininclude LICENSE.rst
include README.rst
include setup.cfg
07070100000008000081A4000000000000000000000001645D608F00000C1F000000000000000000000000000000000000001E00000000pytimeparse2-1.7.1/README.rstpytimeparse2: time expression parser
=====================================
.. image:: https://github.com/onegreyonewhite/pytimeparse2/actions/workflows/check.yml/badge.svg?branch=master
:target: https://github.com/onegreyonewhite/pytimeparse2/actions
:alt: Pipeline status
.. image:: https://badge.fury.io/py/pytimeparse2.svg
:target: https://badge.fury.io/py/pytimeparse2
This is a `pytimeparse <https://github.com/wroberts/pytimeparse>`_ based project with the aim of optimizing functionality and providing stable support.
Copyright (c) 2021 Sergey Klyuykov <onegreyonewhite@mail.ru>
Licensed under the MIT License (see source file ``pytimeparse2.py`` for
details).
A small Python library to parse various kinds of time expressions,
inspired by
`this StackOverflow question <http://stackoverflow.com/questions/4628122/how-to-construct-a-timedelta-object-from-a-simple-string>`_.
The single function ``pytimeparse2.parse`` defined in the library parses time
expressions like the following:
- ``32m``
- ``2h32m``
- ``3d2h32m``
- ``1w3d2h32m``
- ``1w 3d 2h 32m``
- ``1 w 3 d 2 h 32 m``
- ``4:13``
- ``4:13:02``
- ``4:13:02.266``
- ``2:04:13:02.266``
- ``2 days, 4:13:02`` (``uptime`` format)
- ``2 days, 4:13:02.266``
- ``5hr34m56s``
- ``5 hours, 34 minutes, 56 seconds``
- ``5 hrs, 34 mins, 56 secs``
- ``2 days, 5 hours, 34 minutes, 56 seconds``
- ``1.2 m``
- ``1.2 min``
- ``1.2 mins``
- ``1.2 minute``
- ``1.2 minutes``
- ``172 hours``
- ``172 hr``
- ``172 h``
- ``172 hrs``
- ``172 hour``
- ``1.24 days``
- ``5 d``
- ``5 day``
- ``5 days``
- ``5.6 wk``
- ``5.6 week``
- ``5.6 weeks``
It returns the time as a number of seconds (an integer value if
possible, otherwise a floating-point number)::
>>> from pytimeparse import parse
>>> parse('1.2 minutes')
72
For months and years, the library does not consider complications such as leap-
years and leap-seconds. Instead, it assumes "30 days for a month" and "365 days
for a year" as the basis for calculations with those units.
- ``2 mo``
- ``2 months``
- ``3y``
- ``3 years``
- ``1y2mo3w4d5h6m7s8ms``
For better capability with dates, use keyword ``as_timedelta=True`` which mark for function returns
value as ``datetime.timedelta`` or ``dateutil.relitivedelta.relativedelta`` (if installed)::
>>> from pytimeparse import parse
>>> parse('24h', as_timedelta=True)
relativedelta(days=+1)
You can also forced disable dateutil support by calling ``disable_dateutil()`` before ``parse(...)``.
For returning support call ``enable_dateutil()``.
Notes
-----
A number of seconds can be converted back into a string using the
``datetime`` module in the standard library, as noted in
`this other StackOverflow question <http://stackoverflow.com/questions/538666/python-format-timedelta-to-string>`_::
>>> from pytimeparse import parse
>>> import datetime
>>> parse('1 day, 14:20:16')
138016
>>> str(datetime.timedelta(seconds=138016))
'1 day, 14:20:16'
Future work
-----------
1. Speed up with Cython for some python versions.
2. Use github actions for testing and releasing.
07070100000009000081ED000000000000000000000001645D608F00000184000000000000000000000000000000000000002200000000pytimeparse2-1.7.1/autorelease.sh#!/usr/bin/env bash
CURRENT_VERSION=$(python3 setup.py --version | tr -d '\n')
TAG=$(git tag -l $CURRENT_VERSION)
if [ -z "${TAG}" ]; then
echo "Creating new tag ${CURRENT_VERSION}.";
git tag $CURRENT_VERSION > /dev/null 2>&1;
git push origin $CURRENT_VERSION > /dev/null 2>&1;
else
echo "Current release ${CURRENT_VERSION} already exists. Update version to release."
fi
0707010000000A000081A4000000000000000000000001645D608F00002357000000000000000000000000000000000000002300000000pytimeparse2-1.7.1/pytimeparse2.py#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
(c) Sergey Klyuykov <onegreyonewhite@mail.ru> 3 Nov 2021
Implements a single function, `parse`, which can parse various
kinds of time expressions.
"""
# MIT LICENSE
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
__version__ = '1.7.1'
import typing
import re
from datetime import timedelta
try:
from dateutil.relativedelta import relativedelta
HAS_RELITIVE_TIMEDELTA = True
except ImportError: # pragma: no cover
HAS_RELITIVE_TIMEDELTA = False
relativedelta = None # type: ignore
SIGN = r'(?P<sign>[+|-]|\+)?'
YEARS = r'(?P<years>[\d.]+)\s*(?:ys?|yrs?.?|years?)'
MONTHS = r'(?P<months>[\d.]+)\s*(?:mos?.?|mths?.?|months?)'
WEEKS = r'(?P<weeks>[\d.]+)\s*(?:w|wks?|weeks?)'
DAYS = r'(?P<days>[\d.]+)\s*(?:d|dys?|days?)'
HOURS = r'(?P<hours>[\d.]+)\s*(?:h|hrs?|hours?)'
MINS = r'(?P<minutes>[\d.]+)\s*(?:m|(mins?)|(minutes?))'
SECS = r'(?P<seconds>[\d.]+)\s*(?:s|secs?|seconds?)'
MILLIS = r'(?P<milliseconds>[\d.]+)\s*(?:ms|msecs?|millis|milliseconds?)'
SEPARATORS = r'[,/]'
SECCLOCK = r':(?P<seconds>\d{2}(?:\.\d+)?)'
MINCLOCK = r'(?P<minutes>\d{1,2}):(?P<seconds>\d{2}(?:\.\d+)?)'
HOURCLOCK = r'(?P<hours>\d+):(?P<minutes>\d{2}):(?P<seconds>\d{2}(?:\.\d+)?)'
DAYCLOCK = (r'(?P<days>\d+):(?P<hours>\d{2}):'
r'(?P<minutes>\d{2}):(?P<seconds>\d{2}(?:\.\d+)?)')
MULTIPLIERS = {
'years': 60 * 60 * 24 * 365,
'months': 60 * 60 * 24 * 30,
'weeks': 60 * 60 * 24 * 7,
'days': 60 * 60 * 24,
'hours': 60 * 60,
'minutes': 60,
'seconds': 1,
'milliseconds': 1e-3,
}
def OPT(x):
return r'(?:{x})?'.format(x=x)
def OPTSEP(x):
return r'(?:{x}\s*(?:{SEPARATORS}\s*)?)?'.format(x=x, SEPARATORS=SEPARATORS)
TIMEFORMATS = [
(rf'{OPTSEP(YEARS)}\s*'
rf'{OPTSEP(MONTHS)}\s*'
rf'{OPTSEP(WEEKS)}\s*'
rf'{OPTSEP(DAYS)}\s*'
rf'{OPTSEP(HOURS)}\s*'
rf'{OPTSEP(MINS)}\s*'
rf'{OPT(SECS)}\s*'
rf'{OPT(MILLIS)}'),
rf'{OPTSEP(WEEKS)}\s*{OPTSEP(DAYS)}\s*{OPTSEP(HOURS)}\s*{OPTSEP(MINS)}\s*{OPT(SECS)}\s*{OPT(MILLIS)}',
rf'{MINCLOCK}',
rf'{OPTSEP(WEEKS)}\s*{OPTSEP(DAYS)}\s*{HOURCLOCK}',
rf'{DAYCLOCK}',
rf'{SECCLOCK}',
rf'{YEARS}',
rf'{MONTHS}',
]
COMPILED_SIGN = re.compile(r'\s*' + SIGN + r'\s*(?P<unsigned>.*)$')
COMPILED_TIMEFORMATS = [
re.compile(r'\s*' + timefmt + r'\s*$', re.I)
for timefmt in TIMEFORMATS
]
def _all_digits(mdict, delta_class):
if HAS_RELITIVE_TIMEDELTA and issubclass(delta_class, relativedelta):
if 'milliseconds' in mdict:
mdict['microseconds'] = float(mdict.pop('milliseconds') or 0) * 1000
return delta_class(**{k: float(v) for k, v in mdict.items() if v}).normalized()
delta = delta_class(**{
key: float(mdict.pop(key) or 0)
for key in mdict.copy()
if key in ('hours', 'minutes', 'days', 'milliseconds')
})
for time_type, value in mdict.items():
if not value:
continue
if value.isdigit():
delta += delta_class(seconds=MULTIPLIERS[time_type] * int(value, 10))
elif value.replace('.', '', 1).isdigit():
delta += delta_class(seconds=MULTIPLIERS[time_type] * float(value))
return delta
def _interpret_as_minutes(sval, mdict):
"""
Times like "1:22" are ambiguous; do they represent minutes and seconds
or hours and minutes? By default, parse assumes the latter. Call
this function after parsing out a dictionary to change that assumption.
>>> import pprint
>>> pprint.pprint(_interpret_as_minutes('1:24', {'seconds': '24', 'minutes': '1'}))
{'hours': '1', 'minutes': '24'}
"""
if sval.count(':') == 1 and '.' not in sval and (('hours' not in mdict) or (mdict['hours'] is None)) and (
('days' not in mdict) or (mdict['days'] is None)) and (('weeks' not in mdict) or (mdict['weeks'] is None)) \
and (('months' not in mdict) or (mdict['months'] is None)) \
and (('years' not in mdict) or (mdict['years'] is None)):
mdict['hours'] = mdict['minutes']
mdict['minutes'] = mdict['seconds']
mdict.pop('seconds')
return mdict
def _normilized_relativedelta(value: typing.Optional[timedelta]) -> typing.Optional[timedelta]:
if relativedelta is not None and isinstance(value, relativedelta):
return value.normalized()
return value
def _parse(
sval: typing.Union[str, int, float],
granularity: str = 'seconds',
delta_class: typing.Type[timedelta] = timedelta
) -> typing.Optional[timedelta]:
if isinstance(sval, (int, float)):
return _normilized_relativedelta(delta_class(seconds=float(sval)))
if sval.replace('.', '', 1).replace('-', '', 1).replace('+', '', 1).isdigit():
return _normilized_relativedelta(delta_class(seconds=float(sval)))
match = COMPILED_SIGN.match(sval)
sign = -1 if match.groupdict()['sign'] == '-' else 1 # type: ignore
sval = match.groupdict()['unsigned'] # type: ignore
for timefmt in COMPILED_TIMEFORMATS:
match = timefmt.match(sval)
if not (match and match.group(0).strip()):
continue
mdict = match.groupdict()
if granularity == 'minutes':
mdict = _interpret_as_minutes(sval, mdict)
return sign * _all_digits(mdict, delta_class)
return timedelta(seconds=float(sval)) * sign
def enable_dateutil():
global HAS_RELITIVE_TIMEDELTA
assert relativedelta is not None, 'Module python-dateutil should be installed before.'
HAS_RELITIVE_TIMEDELTA = True
def disable_dateutil():
global HAS_RELITIVE_TIMEDELTA
HAS_RELITIVE_TIMEDELTA = False
def parse(
sval: typing.Union[str, int, float],
granularity: str = 'seconds',
raise_exception: bool = False,
as_timedelta: bool = False,
) -> typing.Optional[typing.Union[int, float, timedelta, typing.NoReturn]]:
"""
Parse a time expression, returning it as a number of seconds. If
possible, the return value will be an `int`; if this is not
possible, the return will be a `float`. Returns `None` if a time
expression cannot be parsed from the given string.
Arguments:
- `sval`: the string value to parse
- `granularity`: minimal type of digits after last colon (default is ``seconds``)
- `raise_exception`: raise exception on parsing errors (default is ``False``)
- `as_timedelta`: return ``datetime.timedelta`` object instead of ``int`` (default is ``False``)
>>> parse('1:24')
84
>>> parse(':22')
22
>>> parse('1 minute, 24 secs')
84
>>> parse('1m24s')
84
>>> parse('1.2 minutes')
72
>>> parse('1.2 seconds')
1.2
Time expressions can be signed.
>>> parse('- 1 minute')
-60
>>> parse('+ 1 minute')
60
If granularity is specified as ``minutes``, then ambiguous digits following
a colon will be interpreted as minutes; otherwise they are considered seconds.
>>> parse('1:30')
90
>>> parse('1:30', granularity='minutes')
5400
If ``as_timedelta`` is specified as ``True``, then return timedelta object.
>>> parse('24h', as_timedelta=True)
relativedelta(days=+1)
>>> parse('48:00', as_timedelta=True, granularity='minutes')
relativedelta(days=+2)
If ``raise_exception`` is specified as ``True``, then exception will raised
on failed parsing.
>>> parse(':1.1.1', raise_exception=True)
Traceback (most recent call last):
...
ValueError: could not convert string to float: ':1.1.1'
"""
try:
value = _parse(sval, granularity, relativedelta if HAS_RELITIVE_TIMEDELTA and as_timedelta else timedelta)
if not as_timedelta and value is not None:
new_value = value.total_seconds()
if new_value.is_integer():
return int(new_value)
else:
return new_value
return value
except Exception:
if raise_exception:
raise
return None
0707010000000B000081A4000000000000000000000001645D608F0000051B000000000000000000000000000000000000001D00000000pytimeparse2-1.7.1/setup.cfg[metadata]
name = pytimeparse2
version = attr: pytimeparse2.__version__
description = Time expression parser.
long_description = file: README.rst
long_description_content_type = text/x-rst
license = MIT
author = Sergey Klyuykov
author_email = onegreyonewhite@mail.ru
url = https://github.com/onegreyonewhite/pytimeparse2
keywords = parsing, time, timeparsing, text
classifiers =
Development Status :: 5 - Production/Stable
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Programming Language :: Python
Programming Language :: Python :: 3
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: Implementation :: CPython
Topic :: Software Development :: Libraries
Topic :: Software Development :: Libraries :: Python Modules
Topic :: Text Processing
Topic :: Utilities
[options]
zip_safe = False
include_package_data = True
python_requires = >=3.6
[options.extras_require]
dateutil =
python-dateutil~=2.8.2
[build_sphinx]
project = 'pytimeparse2'
[aliases]
0707010000000C000081A4000000000000000000000001645D608F00003870000000000000000000000000000000000000001C00000000pytimeparse2-1.7.1/setup.py#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
setup.py
(c) Sergey Klyuykov 3 Nov 2021
distutils setup script for pytimeparse2.
"""
# Compilation block
########################################################################################
import re
import os
import sys
import subprocess
import fnmatch
import codecs
import gzip
import shutil
# allow setup.py to be run from any path
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
from setuptools import find_packages, setup, errors, Command
from setuptools.extension import Extension
from setuptools.command.sdist import sdist as _sdist
from setuptools.command.build_py import build_py as build_py_orig
from setuptools.command.install_lib import install_lib as _install_lib
try:
from Cython.Build import cythonize, build_ext as _build_ext
except ImportError:
has_cython = False
else:
has_cython = True
try:
from sphinx.setup_command import BuildDoc
import sphinx # noqa: F401
has_sphinx = True
except ImportError:
has_sphinx = False
ignored_keys = ['-h', '--help', '--version']
is_help = any([a for a in ignored_keys if a in sys.argv])
is_develop = 'develop' in sys.argv
is_build = (any([a for a in ['compile', 'bdist_wheel', 'bdist'] if a in sys.argv]) or is_develop) and not is_help
def get_discription(file_path='README.rst', folder=os.getcwd()):
with codecs.open("{}/{}".format(folder, file_path), 'r', encoding='utf-8') as readme:
return readme.read()
def load_requirements(file_name, folder=os.getcwd()):
with codecs.open(os.path.join(folder, file_name), 'r', encoding='utf-8')as req_file:
return req_file.read().strip().split('\n')
def get_file_ext(ext):
file_types = [".py", ".pyx", ".c", '.cpp'] if has_cython else [".c", '.cpp', ".py"]
for ftype in file_types:
fname = ext.replace(".", "/") + ftype
if os.path.exists(fname):
return fname
return None
def listfiles(folder):
if not isinstance(folder, (list, tuple)):
folder = [folder]
folder = filter(lambda p: os.path.isdir(p), folder)
for one_folder in folder:
for root, folders, files in os.walk(one_folder):
for filename in folders + files:
yield os.path.join(root, filename)
def clear_old_extentions(extensions_list, packages):
for filename in listfiles(packages):
_filename, _f_ext = os.path.splitext(filename)
if os.path.isdir(_filename) or _f_ext not in ['.c', '.cpp']:
continue
has_py = (
os.path.exists('{}.py'.format(_filename)) or
os.path.exists('{}.pyx'.format(_filename))
)
if has_py and filename.replace('/', '.').replace(_f_ext, '') in extensions_list:
print('Removing old extention [{}].'.format(filename))
os.remove(filename)
def make_extention(module_name, files, extra_compile_args, main_include_dir=os.path.join(os.getcwd(), 'include')):
include_dirs = list(filter(
lambda f: bool(f) and os.path.exists(f) and os.path.isdir(f),
[os.path.join(module_name.split('.')[0], 'include'), main_include_dir]
))
return Extension(
module_name, files,
extra_compile_args=extra_compile_args,
include_dirs=include_dirs
)
def make_extensions(extensions_list, packages):
if not isinstance(extensions_list, list):
raise Exception("Extension list should be `list`.")
if not is_help:
clear_old_extentions(extensions_list, packages)
extensions_dict = {}
for ext in extensions_list:
files = []
module_name = ext
if isinstance(ext, (list, tuple)):
module_name = ext[0]
for file_module in ext[1]:
file_name = get_file_ext(file_module)
files += [file_name] if file_name else []
else:
file_name = get_file_ext(ext)
files += [file_name] if file_name else []
if files:
extensions_dict[module_name] = files
extra_compile_args = [
'-g0', '-ggdb1',
"-fno-strict-aliasing",
"-ffast-math",
"-fno-var-tracking-assignments",
"-pipe", "-std=c99", '-Werror=sign-compare',
]
if 'compile' in sys.argv:
extra_compile_args.append("-DBUILD_FROM_SOURCE")
ext_modules = list(
make_extention(m, f, extra_compile_args)
for m, f in extensions_dict.items()
)
ext_count = len(ext_modules)
nthreads = ext_count if ext_count < 10 else 10
language_level = 3
if is_help:
pass
elif has_cython and ('compile' in sys.argv or 'bdist_wheel' in sys.argv or 'build_ext' in sys.argv):
cy_kwargs = dict(
nthreads=nthreads,
force=True,
language_level=language_level,
compiler_directives=dict(
linetrace='CYTHON_TRACE_NOGIL' in sys.argv,
profile=True,
c_string_type='str',
c_string_encoding='utf8'
),
)
return cythonize(ext_modules, **cy_kwargs), extensions_dict
return ext_modules, extensions_dict
def minify_js_file(js_file, jsmin_func):
return jsmin_func(js_file, quote_chars="'\"`")
def minify_css_file(css_file, cssmin_func):
return cssmin_func(css_file)
def minify_static_files(base_dir, files, exclude=None):
exclude = exclude or []
patterns = dict()
try:
from jsmin import jsmin as jsmin_func
patterns['*.js'] = (minify_js_file, jsmin_func)
except:
pass
try:
from csscompressor import compress as csscompressor_func
patterns['*.css'] = (minify_css_file, csscompressor_func)
except:
pass
regex_exclude = [re.compile(r, re.MULTILINE) for r in exclude]
for fnext, funcs in patterns.items():
for fext_file in filter(lambda f: fnmatch.fnmatch(f, fnext), files):
if fnmatch.fnmatch(fext_file, '*.min.*'):
continue
fext_file = os.path.join(base_dir, fext_file)
if os.path.exists(fext_file):
if not any(filter(lambda fp: bool(fp.search(fext_file)), regex_exclude)):
func, subfunc = funcs
with codecs.open(fext_file, 'r', encoding='utf-8') as static_file_fd:
minified = func(static_file_fd.read(), subfunc)
with codecs.open(fext_file, 'w', encoding='utf-8') as static_file_fd:
static_file_fd.write(minified)
print('Minfied file {fext_file}.'.format(fext_file=fext_file))
with open(fext_file, 'rb') as f_in:
with gzip.open("{}.gz".format(fext_file), 'wb') as f_out:
shutil.copyfileobj(f_in, f_out)
print('Compressed file {fext_file}.'.format(fext_file=fext_file))
def compile_py_func(fullname, compile_file_func):
if compile_file_func(fullname, ddir=os.path.dirname(fullname), legacy=True, optimize=0):
os.remove(fullname)
def compile_python_sources(base_dir, files, exclude=None):
exclude = exclude or []
patterns = dict()
try:
from compileall import compile_file
patterns['*.py'] = (compile_py_func, compile_file)
except:
pass
regex_exclude = [re.compile(r, re.MULTILINE) for r in exclude]
for fnext, funcs in patterns.items():
for fext_file in filter(lambda f: fnmatch.fnmatch(f, fnext), files):
fext_file = os.path.join(base_dir, fext_file)
if os.path.exists(fext_file):
if not any(filter(lambda fp: bool(fp.search(fext_file)), regex_exclude)):
func, subfunc = funcs
funcs[0](fext_file, funcs[1])
print('Compiled {fext_file}.'.format(fext_file=fext_file))
class _Compile(_sdist):
extensions_dict = dict()
static_exclude = []
def __filter_files(self, files):
for _files in self.extensions_dict.values():
for file in _files:
if file in files:
files.remove(file)
return files
def make_release_tree(self, base_dir, files):
if has_cython:
files = self.__filter_files(files)
_sdist.make_release_tree(self, base_dir, files)
minify_static_files(base_dir, files, self.static_exclude)
def run(self):
return _sdist.run(self)
class GithubRelease(Command):
'''
Make release on github via githubrelease
'''
description = 'Make release on github via githubrelease'
user_options = [
('body=', 'b', 'Body message.'),
('assets=', 'a', 'Release assets patterns.'),
('repo=', 'r', 'Repository for release.'),
('release=', 'R', 'Release version.'),
('dry-run=', 'd', 'Dry run.'),
('publish=', 'p', 'Publish release or just create draft.'),
]
def initialize_options(self):
self.body = None or os.getenv('CI_COMMIT_DESCRIPTION', None)
self.assets = None
self.repo = None
self.dry_run = False
self.publish = False
self.release = None or self.distribution.metadata.version
def finalize_options(self):
if self.repo is None:
raise Exception("Parameter --repo is missing")
if self.release is None:
raise Exception("Parameter --release is missing")
self._gh_args = (self.repo, self.release)
self._gh_kwargs = dict(
publish=self.publish, name=self.release, dry_run=self.dry_run
)
if self.assets:
assets = self.assets.format(release=self.release)
assets = list(filter(bool, assets.split('\n')))
self._gh_kwargs['asset_pattern'] = assets
if self.body:
self._gh_kwargs['body'] = self.body
def run(self):
from github_release import gh_release_create
gh_release_create(*self._gh_args, **self._gh_kwargs)
class build_py(build_py_orig):
exclude = []
compile_extentions_types = ['.py', '.pyx']
wheel_extentions_types = ['.c', '.cpp'] + compile_extentions_types
def _filter_modules(self, module_tuple):
pkg, mod, file = module_tuple
try:
file_name, file_ext = os.path.splitext(file)
module_name = file_name.replace('/', '.')
except:
return True
if 'bdist_wheel' in sys.argv:
exclude_list = self.wheel_extentions_types
elif 'compile' in sys.argv:
exclude_list = self.compile_extentions_types
else:
return True
if module_name in self.exclude and file_ext in exclude_list:
return False
return True
def find_package_modules(self, package, package_dir):
modules = build_py_orig.find_package_modules(self, package, package_dir)
return list(filter(self._filter_modules, modules))
class install_lib(_install_lib):
exclude = []
static_exclude = []
compile_exclude = []
def _filter_files_with_ext(self, filename):
_filename, _fext = os.path.splitext(filename)
if _fext in build_py.wheel_extentions_types:
return True
return False
def install(self):
result = _install_lib.install(self)
files = list(listfiles(self.install_dir))
so_extentions = list(filter(lambda f: fnmatch.fnmatch(f, '*.so'), files))
for source in filter(self._filter_files_with_ext, files):
_source_name, _source_ext = os.path.splitext(source)
if any(filter(lambda f: fnmatch.fnmatch(f, _source_name+"*.so"), so_extentions)):
print('Removing extention sources [{}].'.format(source))
os.remove(source)
minify_static_files('', files, self.static_exclude)
if os.getenv('BUILD_COMPILE', '') == 'true':
compile_python_sources('', files, self.compile_exclude)
return result
def get_compile_command(extensions_dict=None):
extensions_dict = extensions_dict or dict()
compile_class = _Compile
compile_class.extensions_dict = extensions_dict
return compile_class
def make_setup(**opts):
if 'packages' not in opts:
opts['packages'] = find_packages()
ext_modules_list = opts.pop('ext_modules_list', [])
ext_mod, ext_mod_dict = make_extensions(ext_modules_list, opts['packages'])
opts['ext_modules'] = opts.get('ext_modules', []) + ext_mod
cmdclass = opts.get('cmdclass', dict())
static_exclude = opts.pop('static_exclude_min', [])
if 'compile' not in cmdclass:
compile_class = get_compile_command(ext_mod_dict)
compile_class.static_exclude = static_exclude
cmdclass.update({"compile": get_compile_command(ext_mod_dict)})
if has_cython:
build_py.exclude = ext_modules_list
install_lib.static_exclude = static_exclude
install_lib.compile_exclude = opts.pop('compile_modules_exclude', [])
cmdclass.update({
'build_ext': _build_ext,
'build_py': build_py,
'install_lib': install_lib
})
if has_sphinx and 'build_sphinx' not in cmdclass:
cmdclass['build_sphinx'] = BuildDoc
cmdclass['githubrelease'] = GithubRelease
opts['cmdclass'] = cmdclass
webpack_path = os.path.join(os.getcwd(), 'webpack.config.js')
if os.path.exists(webpack_path) and is_build and os.environ.get('DONT_YARN', "") != 'true':
try:
subprocess.check_call(['yarn', 'install', '--pure-lockfile', '--mutex network'], stdout=sys.stdout, stderr=sys.stderr)
subprocess.check_call(['yarn', 'devBuild' if is_develop else 'build'], stdout=sys.stdout, stderr=sys.stderr)
except Exception as err:
raise errors.CompileError(str(err))
setup(**opts)
########################################################################################
# end block
ext_list = []
if 'develop' in sys.argv:
ext_list = []
kwargs = dict(
name='pytimeparse2',
py_modules=['pytimeparse2'],
ext_modules_list=ext_list,
install_requires=[],
project_urls={
"Issue Tracker": "https://github.com/onegreyonewhite/pytimeparse2/-/issues",
"Source Code": "https://github.com/onegreyonewhite/pytimeparse2.git",
"Releases": "https://pypi.org/project/pytimeparse2/#history",
},
)
make_setup(**kwargs)
0707010000000D000081A4000000000000000000000001645D608F0000A46A000000000000000000000000000000000000001C00000000pytimeparse2-1.7.1/tests.py#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
(c) Sergey Klyuykov <onegreyonewhite@mail.ru> 3 Nov 2021
Unit tests for the `parse` function.
"""
from __future__ import absolute_import
import datetime
import doctest
import re
import pytimeparse2 as timeparse
import unittest
from dateutil.relativedelta import relativedelta
class TestParsing(unittest.TestCase):
"""
Unit tests for basic regex mat
"""
def test_mins(self):
"""Test parsing minutes."""
self.assertEqual(re.match(timeparse.MINS, '32m').groupdict(),
{'minutes': '32'})
self.assertEqual(re.match(timeparse.MINS, '32min').groupdict(),
{'minutes': '32'})
self.assertEqual(re.match(timeparse.MINS, '32mins').groupdict(),
{'minutes': '32'})
self.assertEqual(re.match(timeparse.MINS, '32minute').groupdict(),
{'minutes': '32'})
self.assertEqual(re.match(timeparse.MINS, '32minutes').groupdict(),
{'minutes': '32'})
self.assertEqual(re.match(timeparse.MINS, '32mins').groupdict(),
{'minutes': '32'})
self.assertEqual(re.match(timeparse.MINS, '32min').groupdict(),
{'minutes': '32'})
def test_hrs(self):
"""Test parsing hours."""
self.assertEqual(re.match(timeparse.HOURS, '32h').groupdict(),
{'hours': '32'})
self.assertEqual(re.match(timeparse.HOURS, '32hr').groupdict(),
{'hours': '32'})
self.assertEqual(re.match(timeparse.HOURS, '32hrs').groupdict(),
{'hours': '32'})
self.assertEqual(re.match(timeparse.HOURS, '32hour').groupdict(),
{'hours': '32'})
self.assertEqual(re.match(timeparse.HOURS, '32hours').groupdict(),
{'hours': '32'})
self.assertEqual(re.match(timeparse.HOURS, '32 hours').groupdict(),
{'hours': '32'})
self.assertEqual(re.match(timeparse.HOURS, '32 h').groupdict(),
{'hours': '32'})
def test_months(self):
"""Test parsing months."""
self.assertEqual(re.match(timeparse.MONTHS, '32mo').groupdict(),
{'months': '32'})
self.assertEqual(re.match(timeparse.MONTHS, '32mon').groupdict(),
{'months': '32'})
self.assertEqual(re.match(timeparse.MONTHS, '32month').groupdict(),
{'months': '32'})
self.assertEqual(re.match(timeparse.MONTHS, '32months').groupdict(),
{'months': '32'})
self.assertEqual(re.match(timeparse.MONTHS, '32 mo').groupdict(),
{'months': '32'})
self.assertEqual(re.match(timeparse.MONTHS, '32 months').groupdict(),
{'months': '32'})
self.assertEqual(re.match(timeparse.MONTHS, '32mos').groupdict(),
{'months': '32'})
self.assertEqual(re.match(timeparse.MONTHS, '32mths').groupdict(),
{'months': '32'})
self.assertEqual(re.match(timeparse.MONTHS, '2.3mo').groupdict(),
{'months': '2.3'})
self.assertEqual(re.match(timeparse.MONTHS, '2.5mo').groupdict(),
{'months': '2.5'})
def test_years(self):
"""Test parsing years."""
self.assertEqual(re.match(timeparse.YEARS, '32y').groupdict(),
{'years': '32'})
self.assertEqual(re.match(timeparse.YEARS, '32ys').groupdict(),
{'years': '32'})
self.assertEqual(re.match(timeparse.YEARS, '32yrs').groupdict(),
{'years': '32'})
self.assertEqual(re.match(timeparse.YEARS, '32year').groupdict(),
{'years': '32'})
self.assertEqual(re.match(timeparse.YEARS, '32years').groupdict(),
{'years': '32'})
self.assertEqual(re.match(timeparse.YEARS, '32 y').groupdict(),
{'years': '32'})
self.assertEqual(re.match(timeparse.YEARS, '32 years').groupdict(),
{'years': '32'})
self.assertEqual(re.match(timeparse.YEARS, '2.3y').groupdict(),
{'years': '2.3'})
self.assertEqual(re.match(timeparse.YEARS, '2.5y').groupdict(),
{'years': '2.5'})
def test_time(self):
"""Test parsing time expression."""
self.assertGreater(
set(re.match(timeparse.TIMEFORMATS[0] + r'\s*$',
'16h32m64s ').groupdict().items()),
set([('hours', '16'), ('minutes', '32'), ('seconds', '64')]))
class TestNumberOutput(unittest.TestCase):
"""
Unit tests to ensure that numerical outputs are correct
"""
def test_timeparse_multipliers(self):
"""Test parsing time unit multipliers."""
self.assertEqual(timeparse.parse('32 min'),
1920)
self.assertEqual(timeparse.parse('1 min'),
60)
self.assertEqual(timeparse.parse('1 hours'),
3600)
self.assertEqual(timeparse.parse('1 day'),
86400)
self.assertEqual(timeparse.parse('1 sec'),
1)
def test_timeparse_signs(self):
"""Test parsing time signs."""
self.assertEqual(timeparse.parse('+32 m 1 s'), 1921)
self.assertEqual(timeparse.parse('+ 32 m 1 s'), 1921)
self.assertEqual(timeparse.parse('-32 m 1 s'), -1921)
self.assertEqual(timeparse.parse('- 32 m 1 s'), -1921)
self.assertIsNone(timeparse.parse('32 m - 1 s'))
self.assertIsNone(timeparse.parse('32 m + 1 s'))
def test_timeparse_1(self):
"""timeparse test case 1."""
self.assertEqual(timeparse.parse('32m'), 1920)
self.assertEqual(timeparse.parse('+32m'), 1920)
self.assertEqual(timeparse.parse('-32m'), -1920)
def test_timeparse_2(self):
"""timeparse test case 2."""
self.assertEqual(timeparse.parse('2h32m'), 9120)
self.assertEqual(timeparse.parse('+2h32m'), 9120)
self.assertEqual(timeparse.parse('-2h32m'), -9120)
def test_timeparse_3(self):
"""timeparse test case 3."""
self.assertEqual(timeparse.parse('3d2h32m'), 268320)
self.assertEqual(timeparse.parse('+3d2h32m'), 268320)
self.assertEqual(timeparse.parse('-3d2h32m'), -268320)
def test_timeparse_4(self):
"""timeparse test case 4."""
self.assertEqual(timeparse.parse('1w3d2h32m'), 873120)
self.assertEqual(timeparse.parse('+1w3d2h32m'), 873120)
self.assertEqual(timeparse.parse('-1w3d2h32m'), -873120)
def test_timeparse_5(self):
"""timeparse test case 5."""
self.assertEqual(timeparse.parse('1w 3d 2h 32m'), 873120)
self.assertEqual(timeparse.parse('+1w 3d 2h 32m'), 873120)
self.assertEqual(timeparse.parse('-1w 3d 2h 32m'), -873120)
def test_timeparse_6(self):
"""timeparse test case 6."""
self.assertEqual(timeparse.parse('1 w 3 d 2 h 32 m'), 873120)
self.assertEqual(timeparse.parse('+1 w 3 d 2 h 32 m'), 873120)
self.assertEqual(timeparse.parse('-1 w 3 d 2 h 32 m'), -873120)
def test_timeparse_7(self):
"""timeparse test case 7."""
self.assertEqual(timeparse.parse('4:13'), 253)
self.assertEqual(timeparse.parse('+4:13'), 253)
self.assertEqual(timeparse.parse('-4:13'), -253)
def test_timeparse_bare_seconds(self):
"""timeparse test bare seconds, without minutes."""
self.assertEqual(timeparse.parse(':13'), 13)
self.assertEqual(timeparse.parse('+:13'), 13)
self.assertEqual(timeparse.parse('-:13'), -13)
def test_timeparse_8(self):
"""timeparse test case 8."""
self.assertEqual(timeparse.parse('4:13:02'), 15182)
self.assertEqual(timeparse.parse('+4:13:02'), 15182)
self.assertEqual(timeparse.parse('-4:13:02'), -15182)
def test_timeparse_9(self):
"""timeparse test case 9."""
self.assertAlmostEqual(timeparse.parse('4:13:02.266'), 15182.266)
self.assertAlmostEqual(timeparse.parse('+4:13:02.266'), 15182.266)
self.assertAlmostEqual(timeparse.parse('-4:13:02.266'), -15182.266)
def test_timeparse_10(self):
"""timeparse test case 10."""
self.assertAlmostEqual(timeparse.parse('2:04:13:02.266'),
187982.266)
self.assertAlmostEqual(timeparse.parse('+2:04:13:02.266'),
187982.266)
self.assertAlmostEqual(timeparse.parse('-2:04:13:02.266'),
-187982.266)
def test_timeparse_granularity_1(self):
"""Check that minute-level granularity applies correctly."""
self.assertEqual(timeparse.parse('4:32', granularity='minutes'), 272*60)
self.assertEqual(timeparse.parse('+4:32', granularity='minutes'), 272*60)
self.assertEqual(timeparse.parse('-4:32', granularity='minutes'), -272*60)
def test_timeparse_granularity_2(self):
"""Check that minute-level granularity does not apply inappropriately."""
self.assertEqual(timeparse.parse('4:32:02', granularity='minutes'), 272*60+2)
self.assertEqual(timeparse.parse('+4:32:02', granularity='minutes'), 272*60+2)
self.assertEqual(timeparse.parse('-4:32:02', granularity='minutes'), -(272*60+2))
def test_timeparse_granularity_3(self):
"""Check that minute-level granularity does not apply inappropriately."""
self.assertAlmostEqual(timeparse.parse('7:02.223', granularity='minutes'), 7*60 + 2.223)
self.assertAlmostEqual(timeparse.parse('+7:02.223', granularity='minutes'), 7*60 + 2.223)
self.assertAlmostEqual(timeparse.parse('-7:02.223', granularity='minutes'), -(7*60 + 2.223))
def test_timeparse_granularity_4(self):
"""Check that minute-level granularity does not apply inappropriately."""
self.assertEqual(timeparse.parse('0:02', granularity='seconds'), 2)
self.assertEqual(timeparse.parse('+0:02', granularity='seconds'), 2)
self.assertEqual(timeparse.parse('-0:02', granularity='seconds'), -2)
def test_timeparse_unparsed(self):
"""Check that unparsed values tries to converts into int(). """
self.assertEqual(timeparse.parse(100), 100)
self.assertEqual(timeparse.parse(-18.333), -18.333)
self.assertEqual(timeparse.parse('99.1'), 99.1)
self.assertEqual(timeparse.parse('-99.1'), -99.1)
def test_timeparse_11(self):
"""timeparse test case 11."""
# uptime format
self.assertEqual(timeparse.parse('2 days, 4:13:02'), 187982)
self.assertEqual(timeparse.parse('+2 days, 4:13:02'), 187982)
self.assertEqual(timeparse.parse('-2 days, 4:13:02'), -187982)
def test_timeparse_12(self):
"""timeparse test case 12."""
self.assertAlmostEqual(timeparse.parse('2 days, 4:13:02.266'),
187982.266)
self.assertAlmostEqual(timeparse.parse('+2 days, 4:13:02.266'),
187982.266)
self.assertAlmostEqual(timeparse.parse('-2 days, 4:13:02.266'),
-187982.266)
def test_timeparse_13(self):
"""timeparse test case 13."""
self.assertEqual(timeparse.parse('5hr34m56s'), 20096)
self.assertEqual(timeparse.parse('+5hr34m56s'), 20096)
self.assertEqual(timeparse.parse('-5hr34m56s'), -20096)
def test_timeparse_14(self):
"""timeparse test case 14."""
self.assertEqual(timeparse.parse('5 hours, 34 minutes, 56 seconds'),
20096)
self.assertEqual(timeparse.parse('+5 hours, 34 minutes, 56 seconds'),
20096)
self.assertEqual(timeparse.parse('-5 hours, 34 minutes, 56 seconds'),
-20096)
def test_timeparse_15(self):
"""timeparse test case 15."""
self.assertEqual(timeparse.parse('5 hrs, 34 mins, 56 secs'), 20096)
self.assertEqual(timeparse.parse('+5 hrs, 34 mins, 56 secs'), 20096)
self.assertEqual(timeparse.parse('-5 hrs, 34 mins, 56 secs'), -20096)
def test_timeparse_16(self):
"""timeparse test case 16."""
self.assertEqual(
timeparse.parse('2 days, 5 hours, 34 minutes, 56 seconds'),
192896)
self.assertEqual(
timeparse.parse('+2 days, 5 hours, 34 minutes, 56 seconds'),
192896)
self.assertEqual(
timeparse.parse('-2 days, 5 hours, 34 minutes, 56 seconds'),
-192896)
def test_timeparse_16b(self):
"""timeparse test case 16b."""
self.assertAlmostEqual(timeparse.parse('1.75 s'), 1.75)
self.assertAlmostEqual(timeparse.parse('+1.75 s'), 1.75)
self.assertAlmostEqual(timeparse.parse('-1.75 s'), -1.75)
def test_timeparse_16c(self):
"""timeparse test case 16c."""
self.assertAlmostEqual(timeparse.parse('1.75 sec'), 1.75)
self.assertAlmostEqual(timeparse.parse('+1.75 sec'), 1.75)
self.assertAlmostEqual(timeparse.parse('-1.75 sec'), -1.75)
def test_timeparse_16d(self):
"""timeparse test case 16d."""
self.assertAlmostEqual(timeparse.parse('1.75 secs'), 1.75)
self.assertAlmostEqual(timeparse.parse('+1.75 secs'), 1.75)
self.assertAlmostEqual(timeparse.parse('-1.75 secs'), -1.75)
def test_timeparse_16e(self):
"""timeparse test case 16e."""
self.assertAlmostEqual(timeparse.parse('1.75 second'), 1.75)
self.assertAlmostEqual(timeparse.parse('+1.75 second'), 1.75)
self.assertAlmostEqual(timeparse.parse('-1.75 second'), -1.75)
def test_timeparse_16f(self):
"""timeparse test case 16f."""
self.assertAlmostEqual(timeparse.parse('1.75 seconds'), 1.75)
self.assertAlmostEqual(timeparse.parse('+1.75 seconds'), 1.75)
self.assertAlmostEqual(timeparse.parse('-1.75 seconds'), -1.75)
def test_timeparse_17(self):
"""timeparse test case 17."""
self.assertEqual(timeparse.parse('1.2 m'), 72)
self.assertEqual(timeparse.parse('+1.2 m'), 72)
self.assertEqual(timeparse.parse('-1.2 m'), -72)
def test_timeparse_18(self):
"""timeparse test case 18."""
self.assertEqual(timeparse.parse('1.2 min'), 72)
self.assertEqual(timeparse.parse('+1.2 min'), 72)
self.assertEqual(timeparse.parse('-1.2 min'), -72)
def test_timeparse_19(self):
"""timeparse test case 19."""
self.assertEqual(timeparse.parse('1.2 mins'), 72)
self.assertEqual(timeparse.parse('+1.2 mins'), 72)
self.assertEqual(timeparse.parse('-1.2 mins'), -72)
def test_timeparse_20(self):
"""timeparse test case 20."""
self.assertEqual(timeparse.parse('1.2 minute'), 72)
self.assertEqual(timeparse.parse('+1.2 minute'), 72)
self.assertEqual(timeparse.parse('-1.2 minute'), -72)
def test_timeparse_21(self):
"""timeparse test case 21."""
self.assertEqual(timeparse.parse('1.2 minutes'), 72)
self.assertEqual(timeparse.parse('+1.2 minutes'), 72)
self.assertEqual(timeparse.parse('-1.2 minutes'), -72)
def test_timeparse_22(self):
"""timeparse test case 22."""
self.assertEqual(timeparse.parse('172 hours'), 619200)
self.assertEqual(timeparse.parse('+172 hours'), 619200)
self.assertEqual(timeparse.parse('-172 hours'), -619200)
def test_timeparse_23(self):
"""timeparse test case 23."""
self.assertEqual(timeparse.parse('172 hr'), 619200)
self.assertEqual(timeparse.parse('+172 hr'), 619200)
self.assertEqual(timeparse.parse('-172 hr'), -619200)
def test_timeparse_24(self):
"""timeparse test case 24."""
self.assertEqual(timeparse.parse('172 h'), 619200)
self.assertEqual(timeparse.parse('+172 h'), 619200)
self.assertEqual(timeparse.parse('-172 h'), -619200)
def test_timeparse_25(self):
"""timeparse test case 25."""
self.assertEqual(timeparse.parse('172 hrs'), 619200)
self.assertEqual(timeparse.parse('+172 hrs'), 619200)
self.assertEqual(timeparse.parse('-172 hrs'), -619200)
def test_timeparse_26(self):
"""timeparse test case 26."""
self.assertEqual(timeparse.parse('172 hour'), 619200)
self.assertEqual(timeparse.parse('+172 hour'), 619200)
self.assertEqual(timeparse.parse('-172 hour'), -619200)
def test_timeparse_27(self):
"""timeparse test case 27."""
self.assertEqual(timeparse.parse('1.24 days'), 107136)
self.assertEqual(timeparse.parse('+1.24 days'), 107136)
self.assertEqual(timeparse.parse('-1.24 days'), -107136)
def test_timeparse_28(self):
"""timeparse test case 28."""
self.assertEqual(timeparse.parse('5 d'), 432000)
self.assertEqual(timeparse.parse('+5 d'), 432000)
self.assertEqual(timeparse.parse('-5 d'), -432000)
def test_timeparse_29(self):
"""timeparse test case 29."""
self.assertEqual(timeparse.parse('5 day'), 432000)
self.assertEqual(timeparse.parse('+5 day'), 432000)
self.assertEqual(timeparse.parse('-5 day'), -432000)
def test_timeparse_30(self):
"""timeparse test case 30."""
self.assertEqual(timeparse.parse('5 days'), 432000)
self.assertEqual(timeparse.parse('+5 days'), 432000)
self.assertEqual(timeparse.parse('-5 days'), -432000)
def test_timeparse_31(self):
"""timeparse test case 31."""
self.assertEqual(timeparse.parse('5.6 wk'), 3386880)
self.assertEqual(timeparse.parse('+5.6 wk'), 3386880)
self.assertEqual(timeparse.parse('-5.6 wk'), -3386880)
def test_timeparse_32(self):
"""timeparse test case 32."""
self.assertEqual(timeparse.parse('5.6 week'), 3386880)
self.assertEqual(timeparse.parse('+5.6 week'), 3386880)
self.assertEqual(timeparse.parse('-5.6 week'), -3386880)
def test_timeparse_33(self):
"""timeparse test case 33."""
self.assertEqual(timeparse.parse('5.6 weeks'), 3386880)
self.assertEqual(timeparse.parse('+5.6 weeks'), 3386880)
self.assertEqual(timeparse.parse('-5.6 weeks'), -3386880)
def test_milliseconds(self):
self.assertEqual(timeparse.parse('3 ms'), 0.003)
self.assertEqual(timeparse.parse('3 millis'), 0.003)
self.assertEqual(timeparse.parse('3 msecs'), 0.003)
self.assertEqual(timeparse.parse('3 milliseconds'), 0.003)
def test_plain_numbers(self):
self.assertEqual(timeparse.parse('10'), 10)
self.assertEqual(timeparse.parse('10.1'), 10.1)
self.assertEqual(timeparse.parse('-10'), -10)
self.assertEqual(timeparse.parse('-10.1'), -10.1)
def test_combined(self):
self.assertEqual(timeparse.parse('1y2mo3w4d5h6m7s8ms'), 38898367.008)
class TestRelativeDeltaOutput(unittest.TestCase):
"""
Unit tests to ensure that numerical outputs are correct
"""
def test_timeparse_multipliers(self):
"""Test parsing time unit multipliers."""
self.assertEqual(timeparse.parse('32 min', as_timedelta=True), relativedelta(minutes=32))
self.assertEqual(timeparse.parse('1 min', as_timedelta=True), relativedelta(minutes=1))
self.assertEqual(timeparse.parse('1 hours', as_timedelta=True), relativedelta(hours=1))
self.assertEqual(timeparse.parse('1 day', as_timedelta=True), relativedelta(days=1))
self.assertEqual(timeparse.parse('1 sec', as_timedelta=True), relativedelta(seconds=1))
def test_timeparse_signs(self):
"""Test parsing time signs."""
self.assertEqual(timeparse.parse('+32 m 1 s', as_timedelta=True), relativedelta(minutes=32, seconds=1))
self.assertEqual(timeparse.parse('+ 32 m 1 s', as_timedelta=True), relativedelta(minutes=32, seconds=1))
self.assertEqual(timeparse.parse('-32 m 1 s', as_timedelta=True), -relativedelta(minutes=32, seconds=1))
self.assertEqual(timeparse.parse('- 32 m 1 s', as_timedelta=True), -relativedelta(minutes=32, seconds=1))
self.assertIsNone(timeparse.parse('32 m - 1 s', as_timedelta=True))
self.assertIsNone(timeparse.parse('32 m + 1 s', as_timedelta=True))
def test_timeparse_1(self):
"""timeparse test case 1."""
self.assertEqual(timeparse.parse('32m', as_timedelta=True), relativedelta(minutes=32))
self.assertEqual(timeparse.parse('+32m', as_timedelta=True), relativedelta(minutes=32))
self.assertEqual(timeparse.parse('-32m', as_timedelta=True), -relativedelta(minutes=32))
def test_timeparse_2(self):
"""timeparse test case 2."""
self.assertEqual(timeparse.parse('2h32m', as_timedelta=True), relativedelta(hours=2, minutes=32))
self.assertEqual(timeparse.parse('+2h32m', as_timedelta=True), relativedelta(hours=2, minutes=32))
self.assertEqual(timeparse.parse('-2h32m', as_timedelta=True), -relativedelta(hours=2, minutes=32))
def test_timeparse_3(self):
"""timeparse test case 3."""
self.assertEqual(timeparse.parse('3d2h32m', as_timedelta=True), relativedelta(days=3, hours=2, minutes=32))
self.assertEqual(timeparse.parse('+3d2h32m', as_timedelta=True), relativedelta(days=3, hours=2, minutes=32))
self.assertEqual(timeparse.parse('-3d2h32m', as_timedelta=True), -relativedelta(days=3, hours=2, minutes=32))
def test_timeparse_4(self):
"""timeparse test case 4."""
self.assertEqual(timeparse.parse('1w3d2h32m', as_timedelta=True), relativedelta(weeks=1, days=3, hours=2, minutes=32))
self.assertEqual(timeparse.parse('+1w3d2h32m', as_timedelta=True), relativedelta(weeks=1, days=3, hours=2, minutes=32))
self.assertEqual(timeparse.parse('-1w3d2h32m', as_timedelta=True), -relativedelta(weeks=1, days=3, hours=2, minutes=32))
def test_timeparse_5(self):
"""timeparse test case 5."""
self.assertEqual(timeparse.parse('1w 3d 2h 32m', as_timedelta=True), relativedelta(weeks=1, days=3, hours=2, minutes=32))
self.assertEqual(timeparse.parse('+1w 3d 2h 32m', as_timedelta=True), relativedelta(weeks=1, days=3, hours=2, minutes=32))
self.assertEqual(timeparse.parse('-1w 3d 2h 32m', as_timedelta=True), -relativedelta(weeks=1, days=3, hours=2, minutes=32))
def test_timeparse_6(self):
"""timeparse test case 6."""
self.assertEqual(timeparse.parse('1 w 3 d 2 h 32 m', as_timedelta=True), relativedelta(weeks=1, days=3, hours=2, minutes=32))
self.assertEqual(timeparse.parse('+1 w 3 d 2 h 32 m', as_timedelta=True), relativedelta(weeks=1, days=3, hours=2, minutes=32))
self.assertEqual(timeparse.parse('-1 w 3 d 2 h 32 m', as_timedelta=True), -relativedelta(weeks=1, days=3, hours=2, minutes=32))
def test_timeparse_7(self):
"""timeparse test case 7."""
self.assertEqual(timeparse.parse('4:13', as_timedelta=True), relativedelta(minutes=4, seconds=13))
self.assertEqual(timeparse.parse('+4:13', as_timedelta=True), relativedelta(minutes=4, seconds=13))
self.assertEqual(timeparse.parse('-4:13', as_timedelta=True), -relativedelta(minutes=4, seconds=13))
def test_timeparse_bare_seconds(self):
"""timeparse test bare seconds, without minutes."""
self.assertEqual(timeparse.parse(':13', as_timedelta=True), relativedelta(seconds=13))
self.assertEqual(timeparse.parse('+:13', as_timedelta=True), relativedelta(seconds=13))
self.assertEqual(timeparse.parse('-:13', as_timedelta=True), -relativedelta(seconds=13))
def test_timeparse_8(self):
"""timeparse test case 8."""
self.assertEqual(timeparse.parse('4:13:02', as_timedelta=True), relativedelta(hours=4, minutes=13, seconds=2))
self.assertEqual(timeparse.parse('+4:13:02', as_timedelta=True), relativedelta(hours=4, minutes=13, seconds=2))
self.assertEqual(timeparse.parse('-4:13:02', as_timedelta=True), -relativedelta(hours=4, minutes=13, seconds=2))
def test_timeparse_9(self):
"""timeparse test case 9."""
self.assertEqual(timeparse.parse('4:13:02.266', as_timedelta=True), relativedelta(hours=4, minutes=13, seconds=2, microseconds=266*1000))
self.assertEqual(timeparse.parse('+4:13:02.266', as_timedelta=True), relativedelta(hours=4, minutes=13, seconds=2, microseconds=266*1000))
self.assertEqual(timeparse.parse('-4:13:02.266', as_timedelta=True), -relativedelta(hours=4, minutes=13, seconds=2, microseconds=266*1000))
def test_timeparse_10(self):
"""timeparse test case 10."""
self.assertEqual(timeparse.parse('2:04:13:02.266', as_timedelta=True), relativedelta(days=2, hours=4, minutes=13, seconds=2, microseconds=266*1000))
self.assertEqual(timeparse.parse('+2:04:13:02.266', as_timedelta=True), relativedelta(days=2, hours=4, minutes=13, seconds=2, microseconds=266*1000))
self.assertEqual(timeparse.parse('-2:04:13:02.266', as_timedelta=True), -relativedelta(days=2, hours=4, minutes=13, seconds=2, microseconds=266*1000))
def test_timeparse_granularity_1(self):
"""Check that minute-level granularity applies correctly."""
self.assertEqual(timeparse.parse('4:32', granularity='minutes', as_timedelta=True), relativedelta(hours=4, minutes=32))
self.assertEqual(timeparse.parse('+4:32', granularity='minutes', as_timedelta=True), relativedelta(hours=4, minutes=32))
self.assertEqual(timeparse.parse('-4:32', granularity='minutes', as_timedelta=True), -relativedelta(hours=4, minutes=32))
def test_timeparse_granularity_2(self):
"""Check that minute-level granularity does not apply inappropriately."""
self.assertEqual(timeparse.parse('4:32:02', granularity='minutes', as_timedelta=True), relativedelta(hours=4, minutes=32, seconds=2))
self.assertEqual(timeparse.parse('+4:32:02', granularity='minutes', as_timedelta=True), relativedelta(hours=4, minutes=32, seconds=2))
self.assertEqual(timeparse.parse('-4:32:02', granularity='minutes', as_timedelta=True), -relativedelta(hours=4, minutes=32, seconds=2))
def test_timeparse_granularity_3(self):
"""Check that minute-level granularity does not apply inappropriately."""
self.assertEqual(timeparse.parse('7:02.223', granularity='minutes', as_timedelta=True), relativedelta(minutes=7, seconds=2, microseconds=1000*223))
self.assertEqual(timeparse.parse('+7:02.223', granularity='minutes', as_timedelta=True), relativedelta(minutes=7, seconds=2, microseconds=1000*223))
self.assertEqual(timeparse.parse('-7:02.223', granularity='minutes', as_timedelta=True), -relativedelta(minutes=7, seconds=2, microseconds=1000*223))
def test_timeparse_granularity_4(self):
"""Check that minute-level granularity does not apply inappropriately."""
self.assertEqual(timeparse.parse('0:02', granularity='seconds', as_timedelta=True), relativedelta(seconds=2))
self.assertEqual(timeparse.parse('+0:02', granularity='seconds', as_timedelta=True), relativedelta(seconds=2))
self.assertEqual(timeparse.parse('-0:02', granularity='seconds', as_timedelta=True), -relativedelta(seconds=2))
def test_timeparse_unparsed(self):
"""Check that unparsed values tries to converts into int(). """
self.assertEqual(timeparse.parse(100, as_timedelta=True), relativedelta(seconds=100))
self.assertEqual(timeparse.parse(-18.333, as_timedelta=True), -relativedelta(seconds=18, microseconds=333*1000))
self.assertEqual(timeparse.parse('99.1', as_timedelta=True), relativedelta(seconds=99, microseconds=100*1000))
self.assertEqual(timeparse.parse('-99.1', as_timedelta=True), -relativedelta(seconds=99, microseconds=100*1000))
def test_timeparse_11(self):
"""timeparse test case 11."""
# uptime format
self.assertEqual(timeparse.parse('2 days, 4:13:02', as_timedelta=True), relativedelta(days=2, hours=4, minutes=13, seconds=2))
self.assertEqual(timeparse.parse('+2 days, 4:13:02', as_timedelta=True), relativedelta(days=2, hours=4, minutes=13, seconds=2))
self.assertEqual(timeparse.parse('-2 days, 4:13:02', as_timedelta=True), -relativedelta(days=2, hours=4, minutes=13, seconds=2))
def test_timeparse_12(self):
"""timeparse test case 12."""
self.assertEqual(timeparse.parse('2 days, 4:13:02.266', as_timedelta=True), relativedelta(days=2, hours=4, minutes=13, seconds=2, microseconds=1000*266))
self.assertEqual(timeparse.parse('+2 days, 4:13:02.266', as_timedelta=True), relativedelta(days=2, hours=4, minutes=13, seconds=2, microseconds=1000*266))
self.assertEqual(timeparse.parse('-2 days, 4:13:02.266', as_timedelta=True), -relativedelta(days=2, hours=4, minutes=13, seconds=2, microseconds=1000*266))
def test_timeparse_13(self):
"""timeparse test case 13."""
self.assertEqual(timeparse.parse('5hr34m56s', as_timedelta=True), relativedelta(hours=5, minutes=34, seconds=56))
self.assertEqual(timeparse.parse('+5hr34m56s', as_timedelta=True), relativedelta(hours=5, minutes=34, seconds=56))
self.assertEqual(timeparse.parse('-5hr34m56s', as_timedelta=True), -relativedelta(hours=5, minutes=34, seconds=56))
def test_timeparse_14(self):
"""timeparse test case 14."""
self.assertEqual(timeparse.parse('5 hours, 34 minutes, 56 seconds', as_timedelta=True), relativedelta(hours=5, minutes=34, seconds=56))
self.assertEqual(timeparse.parse('+5 hours, 34 minutes, 56 seconds', as_timedelta=True), relativedelta(hours=5, minutes=34, seconds=56))
self.assertEqual(timeparse.parse('-5 hours, 34 minutes, 56 seconds', as_timedelta=True), -relativedelta(hours=5, minutes=34, seconds=56))
def test_timeparse_15(self):
"""timeparse test case 15."""
self.assertEqual(timeparse.parse('5 hrs, 34 mins, 56 secs', as_timedelta=True), relativedelta(hours=5, minutes=34, seconds=56))
self.assertEqual(timeparse.parse('+5 hrs, 34 mins, 56 secs', as_timedelta=True), relativedelta(hours=5, minutes=34, seconds=56))
self.assertEqual(timeparse.parse('-5 hrs, 34 mins, 56 secs', as_timedelta=True), -relativedelta(hours=5, minutes=34, seconds=56))
def test_timeparse_16(self):
"""timeparse test case 16."""
self.assertEqual(timeparse.parse('2 days, 5 hours, 34 minutes, 56 seconds', as_timedelta=True), relativedelta(days=2, hours=5, minutes=34, seconds=56))
self.assertEqual(timeparse.parse('+2 days, 5 hours, 34 minutes, 56 seconds', as_timedelta=True), relativedelta(days=2, hours=5, minutes=34, seconds=56))
self.assertEqual(timeparse.parse('-2 days, 5 hours, 34 minutes, 56 seconds', as_timedelta=True), -relativedelta(days=2, hours=5, minutes=34, seconds=56))
def test_timeparse_16b(self):
"""timeparse test case 16b."""
self.assertEqual(timeparse.parse('1.75 s', as_timedelta=True), relativedelta(seconds=1, microseconds=75*10000))
self.assertEqual(timeparse.parse('+1.75 s', as_timedelta=True), relativedelta(seconds=1, microseconds=75*10000))
self.assertEqual(timeparse.parse('-1.75 s', as_timedelta=True), -relativedelta(seconds=1, microseconds=75*10000))
def test_timeparse_16c(self):
"""timeparse test case 16c."""
self.assertEqual(timeparse.parse('1.75 sec', as_timedelta=True), relativedelta(seconds=1, microseconds=75*10000))
self.assertEqual(timeparse.parse('+1.75 sec', as_timedelta=True), relativedelta(seconds=1, microseconds=75*10000))
self.assertEqual(timeparse.parse('-1.75 sec', as_timedelta=True), -relativedelta(seconds=1, microseconds=75*10000))
def test_timeparse_16d(self):
"""timeparse test case 16d."""
self.assertEqual(timeparse.parse('1.75 secs', as_timedelta=True), relativedelta(seconds=1, microseconds=75*10000))
self.assertEqual(timeparse.parse('+1.75 secs', as_timedelta=True), relativedelta(seconds=1, microseconds=75*10000))
self.assertEqual(timeparse.parse('-1.75 secs', as_timedelta=True), -relativedelta(seconds=1, microseconds=75*10000))
def test_timeparse_16e(self):
"""timeparse test case 16e."""
self.assertEqual(timeparse.parse('1.75 second', as_timedelta=True), relativedelta(seconds=1, microseconds=75*10000))
self.assertEqual(timeparse.parse('+1.75 second', as_timedelta=True), relativedelta(seconds=1, microseconds=75*10000))
self.assertEqual(timeparse.parse('-1.75 second', as_timedelta=True), -relativedelta(seconds=1, microseconds=75*10000))
def test_timeparse_16f(self):
"""timeparse test case 16f."""
self.assertEqual(timeparse.parse('1.75 seconds', as_timedelta=True), relativedelta(seconds=1, microseconds=75*10000))
self.assertEqual(timeparse.parse('+1.75 seconds', as_timedelta=True), relativedelta(seconds=1, microseconds=75*10000))
self.assertEqual(timeparse.parse('-1.75 seconds', as_timedelta=True), -relativedelta(seconds=1, microseconds=75*10000))
def test_timeparse_17(self):
"""timeparse test case 17."""
self.assertEqual(timeparse.parse('1.2 m', as_timedelta=True), relativedelta(minutes=1, seconds=12))
self.assertEqual(timeparse.parse('+1.2 m', as_timedelta=True), relativedelta(minutes=1, seconds=12))
self.assertEqual(timeparse.parse('-1.2 m', as_timedelta=True), -relativedelta(minutes=1, seconds=12))
def test_timeparse_18(self):
"""timeparse test case 18."""
self.assertEqual(timeparse.parse('1.2 min', as_timedelta=True), relativedelta(minutes=1, seconds=12))
self.assertEqual(timeparse.parse('+1.2 min', as_timedelta=True), relativedelta(minutes=1, seconds=12))
self.assertEqual(timeparse.parse('-1.2 min', as_timedelta=True), -relativedelta(minutes=1, seconds=12))
def test_timeparse_19(self):
"""timeparse test case 19."""
self.assertEqual(timeparse.parse('1.2 mins', as_timedelta=True), relativedelta(minutes=1, seconds=12))
self.assertEqual(timeparse.parse('+1.2 mins', as_timedelta=True), relativedelta(minutes=1, seconds=12))
self.assertEqual(timeparse.parse('-1.2 mins', as_timedelta=True), -relativedelta(minutes=1, seconds=12))
def test_timeparse_20(self):
"""timeparse test case 20."""
self.assertEqual(timeparse.parse('1.2 minute', as_timedelta=True), relativedelta(minutes=1, seconds=12))
self.assertEqual(timeparse.parse('+1.2 minute', as_timedelta=True), relativedelta(minutes=1, seconds=12))
self.assertEqual(timeparse.parse('-1.2 minute', as_timedelta=True), -relativedelta(minutes=1, seconds=12))
def test_timeparse_21(self):
"""timeparse test case 21."""
self.assertEqual(timeparse.parse('1.2 minutes', as_timedelta=True), relativedelta(minutes=1, seconds=12))
self.assertEqual(timeparse.parse('+1.2 minutes', as_timedelta=True), relativedelta(minutes=1, seconds=12))
self.assertEqual(timeparse.parse('-1.2 minutes', as_timedelta=True), -relativedelta(minutes=1, seconds=12))
def test_timeparse_22(self):
"""timeparse test case 22."""
self.assertEqual(timeparse.parse('172 hours', as_timedelta=True), relativedelta(hours=172))
self.assertEqual(timeparse.parse('+172 hours', as_timedelta=True), relativedelta(hours=172))
self.assertEqual(timeparse.parse('-172 hours', as_timedelta=True), -relativedelta(hours=172))
def test_timeparse_23(self):
"""timeparse test case 23."""
self.assertEqual(timeparse.parse('172 hr', as_timedelta=True), relativedelta(hours=172))
self.assertEqual(timeparse.parse('+172 hr', as_timedelta=True), relativedelta(hours=172))
self.assertEqual(timeparse.parse('-172 hr', as_timedelta=True), -relativedelta(hours=172))
def test_timeparse_24(self):
"""timeparse test case 24."""
self.assertEqual(timeparse.parse('172 h', as_timedelta=True), relativedelta(hours=172))
self.assertEqual(timeparse.parse('+172 h', as_timedelta=True), relativedelta(hours=172))
self.assertEqual(timeparse.parse('-172 h', as_timedelta=True), -relativedelta(hours=172))
def test_timeparse_25(self):
"""timeparse test case 25."""
self.assertEqual(timeparse.parse('172 hrs', as_timedelta=True), relativedelta(hours=172))
self.assertEqual(timeparse.parse('+172 hrs', as_timedelta=True), relativedelta(hours=172))
self.assertEqual(timeparse.parse('-172 hrs', as_timedelta=True), -relativedelta(hours=172))
def test_timeparse_26(self):
"""timeparse test case 26."""
self.assertEqual(timeparse.parse('172 hour', as_timedelta=True), relativedelta(hours=172))
self.assertEqual(timeparse.parse('+172 hour', as_timedelta=True), relativedelta(hours=172))
self.assertEqual(timeparse.parse('-172 hour', as_timedelta=True), -relativedelta(hours=172))
def test_timeparse_27(self):
"""timeparse test case 27."""
self.assertEqual(timeparse.parse('1.24 days', as_timedelta=True), relativedelta(days=1, hours=5, minutes=45, seconds=36))
self.assertEqual(timeparse.parse('+1.24 days', as_timedelta=True), relativedelta(days=1, hours=5, minutes=45, seconds=36))
self.assertEqual(timeparse.parse('-1.24 days', as_timedelta=True), -relativedelta(days=1, hours=5, minutes=45, seconds=36))
def test_timeparse_28(self):
"""timeparse test case 28."""
self.assertEqual(timeparse.parse('5 d', as_timedelta=True), relativedelta(days=5))
self.assertEqual(timeparse.parse('+5 d', as_timedelta=True), relativedelta(days=5))
self.assertEqual(timeparse.parse('-5 d', as_timedelta=True), -relativedelta(days=5))
def test_timeparse_29(self):
"""timeparse test case 29."""
self.assertEqual(timeparse.parse('5 day', as_timedelta=True), relativedelta(days=5))
self.assertEqual(timeparse.parse('+5 day', as_timedelta=True), relativedelta(days=5))
self.assertEqual(timeparse.parse('-5 day', as_timedelta=True), -relativedelta(days=5))
def test_timeparse_30(self):
"""timeparse test case 30."""
self.assertEqual(timeparse.parse('5 days', as_timedelta=True), relativedelta(days=5))
self.assertEqual(timeparse.parse('+5 days', as_timedelta=True), relativedelta(days=5))
self.assertEqual(timeparse.parse('-5 days', as_timedelta=True), -relativedelta(days=5))
def test_timeparse_31(self):
"""timeparse test case 31."""
self.assertEqual(timeparse.parse('5.6 wk', as_timedelta=True), relativedelta(days=39, hours=4, minutes=48))
self.assertEqual(timeparse.parse('+5.6 wk', as_timedelta=True), relativedelta(days=39, hours=4, minutes=48))
self.assertEqual(timeparse.parse('-5.6 wk', as_timedelta=True), -relativedelta(days=39, hours=4, minutes=48))
def test_timeparse_32(self):
"""timeparse test case 32."""
self.assertEqual(timeparse.parse('5.6 week', as_timedelta=True), relativedelta(days=39, hours=4, minutes=48))
self.assertEqual(timeparse.parse('+5.6 week', as_timedelta=True), relativedelta(days=39, hours=4, minutes=48))
self.assertEqual(timeparse.parse('-5.6 week', as_timedelta=True), -relativedelta(days=39, hours=4, minutes=48))
def test_timeparse_33(self):
"""timeparse test case 33."""
self.assertEqual(timeparse.parse('5.6 weeks', as_timedelta=True), relativedelta(days=39, hours=4, minutes=48))
self.assertEqual(timeparse.parse('+5.6 weeks', as_timedelta=True), relativedelta(days=39, hours=4, minutes=48))
self.assertEqual(timeparse.parse('-5.6 weeks', as_timedelta=True), -relativedelta(days=39, hours=4, minutes=48))
def test_milliseconds(self):
self.assertEqual(timeparse.parse('3 ms', as_timedelta=True), relativedelta(microseconds=3000))
self.assertEqual(timeparse.parse('3 millis', as_timedelta=True), relativedelta(microseconds=3000))
self.assertEqual(timeparse.parse('3 msecs', as_timedelta=True), relativedelta(microseconds=3000))
self.assertEqual(timeparse.parse('3 milliseconds', as_timedelta=True), relativedelta(microseconds=3000))
def test_plain_numbers(self):
self.assertEqual(timeparse.parse('10', as_timedelta=True), relativedelta(seconds=10))
self.assertEqual(timeparse.parse('10.1', as_timedelta=True), relativedelta(seconds=10, microseconds=100000))
self.assertEqual(timeparse.parse('-10', as_timedelta=True), -relativedelta(seconds=10))
self.assertEqual(timeparse.parse('-10.1', as_timedelta=True), -relativedelta(seconds=10, microseconds=100000))
def test_combined(self):
self.assertEqual(timeparse.parse('1y2mo3w4d5h6m7s8ms', as_timedelta=True), relativedelta(years=1, months=2, weeks=3, days=4, hours=5, minutes=6, seconds=7, microseconds=8000))
class MiscTests(unittest.TestCase):
"""
Miscellaneous unit tests for the `timeparse` module.
"""
def test_strange(self):
self.assertIsNone(timeparse.parse('1.1.1:22'))
def test_doctest(self):
"""Run timeparse doctests."""
self.assertTrue(doctest.testmod(timeparse, raise_on_error=True))
def test_disable_dateutil(self):
self.assertNotIsInstance(timeparse.parse('10:10', as_timedelta=True), datetime.timedelta)
timeparse.disable_dateutil()
self.assertIsInstance(timeparse.parse('10:10', as_timedelta=True), datetime.timedelta)
timeparse.enable_dateutil()
self.assertNotIsInstance(timeparse.parse('10:10', as_timedelta=True), datetime.timedelta)
if __name__ == '__main__':
unittest.main('tests')
0707010000000E000081A4000000000000000000000001645D608F000006CC000000000000000000000000000000000000001B00000000pytimeparse2-1.7.1/tox.ini[tox]
envlist = flake,mypy,py36-coverage,py3{7,8,9,10,11}-install
skipsdist = True
[gh-actions]
python =
3.6: flake,mypy,py36-coverage
3.7: py37-install
3.8: py38-install
3.9: py39-install
3.10: py310-install
3.11: py311-install
[testenv]
setenv =
CCACHE_DIR = {envdir}/.ccache
passenv =
CC
allowlist_externals =
rm
ls
ln
bash
pwd
cd
find
xargs
commands =
pwd
pip uninstall pytimeparse2 -y
install: rm -rfv {envdir}/dist/
install: python {toxinidir}/setup.py bdist_wheel --dist-dir {envdir}/dist/
install: bash -c "pip install -U {envdir}/dist/$(ls {envdir}/dist)[dateutil]"
coverage: python setup.py install_egg_info
coverage: pip install -U -e .[dateutil]
install: bash -c "cd {envdir} && python {toxinidir}/tests.py -vv --failfast"
coverage: coverage debug sys
coverage: coverage erase
coverage: coverage run tests.py -vv --failfast {posargs}
coverage: coverage combine
coverage: coverage report
rm -rf .eggs build pytimeparse2.egg-info {envdir}/dist
install: pip uninstall pytimeparse2 -y
deps =
coverage: coverage~=5.1
mock==3.0.5
[testenv:flake]
basepython = python3.6
deps =
flake8
commands =
flake8 --config=.pep8 pytimeparse2.py
[testenv:mypy]
basepython = python3.6
deps =
mypy
types-python-dateutil
commands =
mypy pytimeparse2.py
[testenv:contrib]
basepython = python3.6
skipsdist = True
envdir = {toxinidir}/venv
passenv = *
allowlist_externals = *
commands =
python setup.py install_egg_info
pip install -U -e .
deps =
tox
[testenv:build]
passenv = *
changedir = .
allowlist_externals =
tox
rm
commands =
rm -rf dist build
tox -c tox_build.ini --workdir {toxworkdir}
deps =
0707010000000F000081A4000000000000000000000001645D608F00000121000000000000000000000000000000000000002100000000pytimeparse2-1.7.1/tox_build.ini[tox]
envlist = py36-{wheel,build}
skipsdist = True
[testenv]
passenv = *
changedir = .
whitelist_externals =
rm
ls
grep
bash
commands =
rm -rf build
build: python setup.py compile -v
wheel: python setup.py bdist_wheel -v
deps =
wheel==0.31.1
setuptools>=40.6.3
07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!151 blocks