Initial implementation of blender benchmark addon
Just some glue logic to query progress and results from benchmark. Needed to move files around, so oth standalone and addon are happy.
This commit is contained in:
203
benchmark/__init__.py
Normal file
203
benchmark/__init__.py
Normal file
@@ -0,0 +1,203 @@
|
||||
bl_info = {
|
||||
"name": "Benchmark",
|
||||
"author": "Sergey Sharybin",
|
||||
"blender": (2, 80, 0),
|
||||
"location": "",
|
||||
"description": "Addon to provide benchmark functionality",
|
||||
"warning": "",
|
||||
"wiki_url": "",
|
||||
"support": 'OFFICIAL',
|
||||
"category": "Benchmark",
|
||||
}
|
||||
|
||||
import datetime
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import bpy
|
||||
from threading import Thread
|
||||
from bpy.props import IntProperty, FloatProperty
|
||||
|
||||
from .foundation import (benchrunner,
|
||||
buildbot,
|
||||
config,
|
||||
context,
|
||||
logger,
|
||||
system_info,
|
||||
util)
|
||||
|
||||
|
||||
class ProgressProviderSink:
|
||||
current_progress = 0.0
|
||||
current_step = ''
|
||||
|
||||
def __init__(self):
|
||||
self.current_progress = 0.0
|
||||
self.current_step = ''
|
||||
|
||||
def progress(self, count, total, prefix="", suffix=""):
|
||||
if total != 0:
|
||||
self.current_progress = float(count) / float(total)
|
||||
else:
|
||||
self.current_progress = 0.0
|
||||
|
||||
def clear(self):
|
||||
pass
|
||||
|
||||
def step(self, step_name):
|
||||
self.current_step = step_name
|
||||
|
||||
class LoggerProviderSink:
|
||||
def HEADER(self, *args):
|
||||
pass
|
||||
|
||||
def WARNING(self, *args):
|
||||
pass
|
||||
|
||||
def ERROR(self, *args):
|
||||
pass
|
||||
|
||||
def OK(self, *args):
|
||||
pass
|
||||
|
||||
def BOLD(self, *args):
|
||||
pass
|
||||
|
||||
def INFO(self, *args):
|
||||
pass
|
||||
|
||||
def DEBUG(self, *args):
|
||||
pass
|
||||
|
||||
def FATAL(self, *args):
|
||||
pass
|
||||
|
||||
|
||||
def getResultJSONString(ctx, results):
|
||||
# Convert custom classes to dictionaries for easier JSON dump.
|
||||
json_results = results
|
||||
stats = json_results['stats']
|
||||
for scene in ctx.scenes:
|
||||
if scene not in stats:
|
||||
continue
|
||||
if stats[scene]:
|
||||
stats[scene] = stats[scene].asDict()
|
||||
stats[scene]['result'] = 'OK'
|
||||
else:
|
||||
stats[scene] = {'result': 'CRASH'}
|
||||
return json.dumps(json_results, sort_keys=True, indent=2)
|
||||
|
||||
|
||||
def benchmark_thread(ctx):
|
||||
# This is actual device configuration which is used to render the
|
||||
# benchmark scene.
|
||||
blender_device_info = benchrunner.benchmarkGetDeviceInfo(ctx)
|
||||
if not blender_device_info['device_type']:
|
||||
# TODO(sergey): Report an error somehow.
|
||||
return
|
||||
all_stats = benchrunner.benchmarkAll(ctx)
|
||||
# Gather all information together.
|
||||
timestamp = datetime.datetime.now(datetime.timezone.utc).isoformat()
|
||||
old_executable = sys.executable
|
||||
sys.executable = bpy.app.binary_path_python
|
||||
results = {
|
||||
"timestamp": timestamp,
|
||||
"blender_version": system_info.getBlenderVersion(ctx),
|
||||
"system_info": system_info.gatherSystemInfo(ctx),
|
||||
"device_info": blender_device_info,
|
||||
"stats": all_stats if all_stats else {}
|
||||
}
|
||||
sys.executable = old_executable
|
||||
json_string = getResultJSONString(ctx, results)
|
||||
print(json_string)
|
||||
|
||||
|
||||
class BenchmarkOperator(bpy.types.Operator):
|
||||
bl_idname = "wm.benchmark"
|
||||
bl_label = "benchmark Operator"
|
||||
|
||||
first_mouse_x: IntProperty()
|
||||
first_value: FloatProperty()
|
||||
|
||||
benchmark_context = None
|
||||
thread = None
|
||||
timer = None
|
||||
progress_provider = None
|
||||
logger_provider = None
|
||||
|
||||
def setup_sink(self):
|
||||
self.progress_provider = ProgressProviderSink()
|
||||
self.logger_provider = LoggerProviderSink()
|
||||
foundation.progress.setProvider(self.progress_provider)
|
||||
foundation.logger.setProvider(self.logger_provider)
|
||||
|
||||
def update_status(self):
|
||||
rounded = int(self.progress_provider.current_progress * 100) / 100
|
||||
step = self.progress_provider.current_step
|
||||
print(f"{step}: {rounded}")
|
||||
|
||||
def done(self, context):
|
||||
wm = context.window_manager
|
||||
wm.event_timer_remove(self.timer)
|
||||
# Restore all modifications to the benchmark foundation.
|
||||
foundation.progress.restoreDefaultProvider()
|
||||
foundation.logger.restoreDefaultProvider()
|
||||
# Destroy objects of sinks.
|
||||
del self.progress_provider
|
||||
del self.logger_provider
|
||||
self.progress_provider = None
|
||||
self.logger_provider = None
|
||||
|
||||
def modal(self, context, event):
|
||||
if event.type == 'TIMER':
|
||||
if self.thread.is_alive():
|
||||
self.update_status()
|
||||
return {'PASS_THROUGH'}
|
||||
else:
|
||||
self.done(context)
|
||||
return {'FINISHED'}
|
||||
|
||||
return {'PASS_THROUGH'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
# Before doing anything, make sure we have all sinks set up, so we do
|
||||
# not miss any progress report.
|
||||
self.setup_sink()
|
||||
wm = context.window_manager
|
||||
script_directory = os.path.dirname(os.path.realpath(__file__))
|
||||
configure_script = os.path.join(script_directory, "configure.py")
|
||||
ctx = foundation.context.Context()
|
||||
ctx.blender = "<blender>"
|
||||
ctx.configure_script = configure_script
|
||||
ctx.scenes = ["<monkey>"]
|
||||
ctx.scenes_dir = "<scenes>"
|
||||
ctx.device_type = 'CPU'
|
||||
# Only applies for GPU, should match Cycles name
|
||||
ctx.device_name = ""
|
||||
# Set this to True when having multiple GPUs of same name and only
|
||||
# one of the mis to be enabled. Or when requesting GPU render without
|
||||
# specifying GPU name.
|
||||
ctx.device_single = True
|
||||
# ctx.image_output_dir = "/tmp/"
|
||||
self.benchmark_context = ctx
|
||||
# Create thread for the actual benchmark.
|
||||
self.thread = Thread(target = benchmark_thread,
|
||||
args = (self.benchmark_context, ))
|
||||
self.thread.start()
|
||||
# Create timer to query thread status
|
||||
self.timer = wm.event_timer_add(0.1, context.window)
|
||||
# Register self as modal.
|
||||
context.window_manager.modal_handler_add(self)
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_class(BenchmarkOperator)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_class(BenchmarkOperator)
|
||||
|
||||
|
||||
#if __name__ == "__main__":
|
||||
# register()
|
@@ -5,7 +5,6 @@ import sys
|
||||
|
||||
SCRIPT_PATH = os.path.realpath(__file__)
|
||||
SCRIPT_DIR = os.path.dirname(SCRIPT_PATH)
|
||||
sys.path.append(os.path.join(SCRIPT_DIR, "third_party"))
|
||||
|
||||
import argparse
|
||||
import datetime
|
||||
@@ -364,8 +363,8 @@ def main():
|
||||
print("Using device name override: {}" .
|
||||
format(farm_config["device_name_override"]))
|
||||
# Print prelmiinary information.
|
||||
blender_dvice_info = benchrunner.benchmarkGetDeviceInfo(ctx)
|
||||
if not blender_dvice_info['device_type']:
|
||||
blender_device_info = benchrunner.benchmarkGetDeviceInfo(ctx)
|
||||
if not blender_device_info['device_type']:
|
||||
logger.ERROR("Requested device can not be enabled in Blender.")
|
||||
logger.INFO("Requested device details:")
|
||||
logger.INFO(" Device type: {}" . format(ctx.device_type))
|
||||
@@ -374,9 +373,9 @@ def main():
|
||||
else:
|
||||
logger.INFO("Configured device details:")
|
||||
logger.INFO(" Device type: {}" .
|
||||
format(blender_dvice_info["device_type"]))
|
||||
format(blender_device_info["device_type"]))
|
||||
logger.INFO(" Compute devices:")
|
||||
for compute_device in blender_dvice_info["compute_devices"]:
|
||||
for compute_device in blender_device_info["compute_devices"]:
|
||||
logger.INFO(" {}" . format(compute_device))
|
||||
# Run benchmark.
|
||||
all_stats = benchrunner.benchmarkAll(ctx)
|
||||
@@ -386,7 +385,7 @@ def main():
|
||||
"timestamp": timestamp,
|
||||
"blender_version": system_info.getBlenderVersion(ctx),
|
||||
"system_info": system_info.gatherSystemInfo(ctx),
|
||||
"device_info": blender_dvice_info,
|
||||
"device_info": blender_device_info,
|
||||
"stats": all_stats if all_stats else {}
|
||||
}
|
||||
if farm_config["device_name_override"]:
|
||||
|
@@ -2,10 +2,10 @@ import os
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
from foundation import (logger,
|
||||
progress,
|
||||
stats,
|
||||
util)
|
||||
from . import (logger,
|
||||
progress,
|
||||
stats,
|
||||
util)
|
||||
|
||||
|
||||
def constructBenchmarkCommand(ctx, scene, blendfile, output_folder, cfra):
|
||||
@@ -36,7 +36,7 @@ def constructBenchmarkCommand(ctx, scene, blendfile, output_folder, cfra):
|
||||
|
||||
def benchmarkBlenderWatched(command):
|
||||
# Run Blender with configured command line.
|
||||
logger.DEBUG("About to execuet command: {}" . format(command))
|
||||
logger.DEBUG("About to execute command: {}" . format(command))
|
||||
start_time = time.time()
|
||||
process = subprocess.Popen(command,
|
||||
stdout=subprocess.PIPE,
|
||||
@@ -85,7 +85,7 @@ def benchmarkScene(ctx, scene):
|
||||
cfra = util.queryCurrentFrame(blendfile)
|
||||
command = constructBenchmarkCommand(ctx, scene, blendfile, "/tmp/", cfra)
|
||||
logger.DEBUG("Command for rendering: {}" . format(command))
|
||||
|
||||
progress.step('WARM_UP')
|
||||
logger.INFO("> Warm-up round, making sure everything is ready " +
|
||||
"(this might take several minutes).")
|
||||
warmup_command = command + ['--benchmark-warmup']
|
||||
@@ -97,6 +97,7 @@ def benchmarkScene(ctx, scene):
|
||||
if os.path.exists(full_image_output):
|
||||
os.remove(full_image_output)
|
||||
# TODO(sergey): Consider doing several passes.
|
||||
progress.step('RUN')
|
||||
logger.INFO("> Doing real benchmark pass now.")
|
||||
stats = benchmarkBlenderWatched(command)
|
||||
# Rename file to more sensible name.
|
||||
@@ -109,6 +110,7 @@ def benchmarkScene(ctx, scene):
|
||||
logger.INFO("Total render time: {}" . format(
|
||||
util.humanReadableTimeDifference(
|
||||
stats.pipeline_render_time)))
|
||||
progress.step('')
|
||||
return stats
|
||||
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import configparser
|
||||
import foundation
|
||||
from foundation import util
|
||||
from .. import foundation
|
||||
from ..foundation import util
|
||||
import os
|
||||
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import os
|
||||
|
||||
from foundation import logger
|
||||
from . import logger
|
||||
|
||||
|
||||
class Context:
|
||||
|
@@ -23,6 +23,86 @@ class COLORS_ANSI:
|
||||
VERBOSE = False
|
||||
COLORS = COLORS_DUMMY
|
||||
|
||||
class DefaultLoggerProvider:
|
||||
def HEADER(self, *args):
|
||||
print(COLORS.HEADER + COLORS.BOLD, end="")
|
||||
print(*args, end="")
|
||||
print(COLORS.ENDC)
|
||||
|
||||
|
||||
def WARNING(self, *args):
|
||||
print(COLORS.WARNING + COLORS.BOLD, end="")
|
||||
print(*args, end="")
|
||||
print(COLORS.ENDC)
|
||||
|
||||
|
||||
def ERROR(self, *args):
|
||||
print(COLORS.FAIL + COLORS.BOLD, end="")
|
||||
print(*args, end="")
|
||||
print(COLORS.ENDC)
|
||||
|
||||
|
||||
def OK(self, *args):
|
||||
print(COLORS.OKGREEN + COLORS.BOLD, end="")
|
||||
print(*args, end="")
|
||||
print(COLORS.ENDC)
|
||||
|
||||
|
||||
def BOLD(self, *args):
|
||||
print(COLORS.BOLD, end="")
|
||||
print(*args, end="")
|
||||
print(COLORS.ENDC)
|
||||
|
||||
|
||||
def INFO(self, *args):
|
||||
print(*args)
|
||||
|
||||
|
||||
def DEBUG(self, *args):
|
||||
# TODO(sergey): Add check that debug is enabled.
|
||||
if False:
|
||||
print(*args)
|
||||
|
||||
|
||||
def FATAL(self, *args):
|
||||
import sys
|
||||
ERROR(*args)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
LOGGER_PROVIDER = DefaultLoggerProvider()
|
||||
|
||||
def HEADER(*args):
|
||||
LOGGER_PROVIDER.HEADER(*args)
|
||||
|
||||
|
||||
def WARNING(*args):
|
||||
LOGGER_PROVIDER.WARNING(*args)
|
||||
|
||||
|
||||
def ERROR(*args):
|
||||
LOGGER_PROVIDER.ERROR(*args)
|
||||
|
||||
|
||||
def OK(*args):
|
||||
LOGGER_PROVIDER.OK(*args)
|
||||
|
||||
|
||||
def BOLD(*args):
|
||||
LOGGER_PROVIDER.BOLD(*args)
|
||||
|
||||
|
||||
def INFO(*args):
|
||||
LOGGER_PROVIDER.INFO(*args)
|
||||
|
||||
|
||||
def DEBUG(*args):
|
||||
LOGGER_PROVIDER.DEBUG(*args)
|
||||
|
||||
|
||||
def FATAL(*args):
|
||||
LOGGER_PROVIDER.FATAL(*args)
|
||||
|
||||
|
||||
def supportsColor():
|
||||
"""
|
||||
@@ -43,53 +123,17 @@ def supportsColor():
|
||||
return True
|
||||
|
||||
|
||||
def HEADER(*args):
|
||||
print(COLORS.HEADER + COLORS.BOLD, end="")
|
||||
print(*args, end="")
|
||||
print(COLORS.ENDC)
|
||||
|
||||
|
||||
def WARNING(*args):
|
||||
print(COLORS.WARNING + COLORS.BOLD, end="")
|
||||
print(*args, end="")
|
||||
print(COLORS.ENDC)
|
||||
|
||||
|
||||
def ERROR(*args):
|
||||
print(COLORS.FAIL + COLORS.BOLD, end="")
|
||||
print(*args, end="")
|
||||
print(COLORS.ENDC)
|
||||
|
||||
|
||||
def OK(*args):
|
||||
print(COLORS.OKGREEN + COLORS.BOLD, end="")
|
||||
print(*args, end="")
|
||||
print(COLORS.ENDC)
|
||||
|
||||
|
||||
def BOLD(*args):
|
||||
print(COLORS.BOLD, end="")
|
||||
print(*args, end="")
|
||||
print(COLORS.ENDC)
|
||||
|
||||
|
||||
def INFO(*args):
|
||||
print(*args)
|
||||
|
||||
|
||||
def DEBUG(*args):
|
||||
# TODO(sergey): Add check that debug is enabled.
|
||||
if False:
|
||||
print(*args)
|
||||
|
||||
|
||||
def FATAL(*args):
|
||||
import sys
|
||||
ERROR(*args)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def init():
|
||||
if not VERBOSE and supportsColor():
|
||||
global COLORS
|
||||
COLORS = COLORS_ANSI
|
||||
|
||||
|
||||
def setProvider(provider):
|
||||
global LOGGER_PROVIDER
|
||||
LOGGER_PROVIDER = provider
|
||||
|
||||
|
||||
def restoreDefaultProvider():
|
||||
global LOGGER_PROVIDER
|
||||
LOGGER_PROVIDER = DefaultLoggerProvider()
|
||||
|
@@ -1,34 +1,77 @@
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
from foundation import logger
|
||||
from . import logger
|
||||
|
||||
class DefaultProgressProvider:
|
||||
"""
|
||||
Default progress provider implementation, which draws progress
|
||||
bar in the console, unless current logging is set to evrbose mode.
|
||||
"""
|
||||
def progress(self, count, total, prefix="", suffix=""):
|
||||
if logger.VERBOSE:
|
||||
return
|
||||
|
||||
size = shutil.get_terminal_size((80, 20))
|
||||
|
||||
if prefix != "":
|
||||
prefix = prefix + " "
|
||||
if suffix != "":
|
||||
suffix = " " + suffix
|
||||
|
||||
bar_len = size.columns - len(prefix) - len(suffix) - 10
|
||||
filled_len = int(round(bar_len * count / float(total)))
|
||||
|
||||
percents = round(100.0 * count / float(total), 1)
|
||||
bar = '=' * filled_len + '-' * (bar_len - filled_len)
|
||||
|
||||
sys.stdout.write('%s[%s] %s%%%s\r' % (prefix, bar, percents, suffix))
|
||||
sys.stdout.flush()
|
||||
|
||||
def clear(self):
|
||||
if logger.VERBOSE:
|
||||
return
|
||||
|
||||
size = shutil.get_terminal_size((80, 20))
|
||||
sys.stdout.write(" " * size.columns + "\r")
|
||||
sys.stdout.flush()
|
||||
|
||||
def step(self, step_name):
|
||||
pass
|
||||
|
||||
|
||||
PROGRESS_PROVIDER = DefaultProgressProvider()
|
||||
|
||||
|
||||
def progress(count, total, prefix="", suffix=""):
|
||||
if logger.VERBOSE:
|
||||
return
|
||||
|
||||
size = shutil.get_terminal_size((80, 20))
|
||||
|
||||
if prefix != "":
|
||||
prefix = prefix + " "
|
||||
if suffix != "":
|
||||
suffix = " " + suffix
|
||||
|
||||
bar_len = size.columns - len(prefix) - len(suffix) - 10
|
||||
filled_len = int(round(bar_len * count / float(total)))
|
||||
|
||||
percents = round(100.0 * count / float(total), 1)
|
||||
bar = '=' * filled_len + '-' * (bar_len - filled_len)
|
||||
|
||||
sys.stdout.write('%s[%s] %s%%%s\r' % (prefix, bar, percents, suffix))
|
||||
sys.stdout.flush()
|
||||
"""
|
||||
Report new progress status of the current task.
|
||||
"""
|
||||
PROGRESS_PROVIDER.progress(count, total, prefix, suffix)
|
||||
|
||||
|
||||
def progressClear():
|
||||
if logger.VERBOSE:
|
||||
return
|
||||
"""
|
||||
Clear all possible progress bar lines in the ocnsole.
|
||||
"""
|
||||
PROGRESS_PROVIDER.clear()
|
||||
|
||||
size = shutil.get_terminal_size((80, 20))
|
||||
sys.stdout.write(" " * size.columns + "\r")
|
||||
sys.stdout.flush()
|
||||
def step(step_name):
|
||||
PROGRESS_PROVIDER.step(step_name)
|
||||
|
||||
|
||||
def setProvider(provider):
|
||||
"""
|
||||
Override progress provider with a given name.
|
||||
Is used by glue logic to hijack progress and do smart things.
|
||||
"""
|
||||
global PROGRESS_PROVIDER
|
||||
PROGRESS_PROVIDER = provider
|
||||
|
||||
|
||||
def restoreDefaultProvider():
|
||||
"""
|
||||
Restore default progress provider.
|
||||
"""
|
||||
global PROGRESS_PROVIDER
|
||||
PROGRESS_PROVIDER = DefaultProgressProvider()
|
||||
|
@@ -1,13 +1,13 @@
|
||||
import re
|
||||
|
||||
from foundation import util
|
||||
from . import util
|
||||
|
||||
|
||||
class Stats:
|
||||
def __init__(self):
|
||||
# Pepare some regex for parsing
|
||||
self.re_path_tracing = re.compile(
|
||||
".*Rendered ([0-9]+)/([0-9]+) Tiles" +
|
||||
".*(Rendered|Path Tracing Tile) ([0-9]+)/([0-9]+)( Tiles)?" +
|
||||
"(, Sample ([0-9]+)\/([0-9]+))?$")
|
||||
self.re_total_render_time = re.compile(
|
||||
".*Total render time: ([0-9]+(\.[0-9]+)?)")
|
||||
@@ -35,8 +35,8 @@ class Stats:
|
||||
# Current tile progress.
|
||||
match = self.re_path_tracing.match(line)
|
||||
if match:
|
||||
self.current_tiles = int(match.group(1))
|
||||
self.total_tiles = int(match.group(2))
|
||||
self.current_tiles = int(match.group(2))
|
||||
self.total_tiles = int(match.group(3))
|
||||
# Total render time.
|
||||
match = self.re_total_render_time.match(line)
|
||||
if match:
|
||||
|
@@ -6,8 +6,8 @@ import subprocess
|
||||
import sys
|
||||
|
||||
# Usually comes from third_party
|
||||
import cpuinfo
|
||||
import cpu_cores
|
||||
from .third_party import cpuinfo
|
||||
from .third_party import cpu_cores
|
||||
|
||||
|
||||
def _getBlenderDeviceInfo(ctx):
|
||||
@@ -38,7 +38,7 @@ def getBlenderVersion(ctx):
|
||||
"build_commit_date",
|
||||
"build_commit_time",
|
||||
"build_hash")
|
||||
command = [ctx.blender, "--version"]
|
||||
command = [ctx.blender, "--background", "--version"]
|
||||
process = subprocess.Popen(command,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT)
|
||||
|
@@ -4,6 +4,6 @@
|
||||
version_info = (0, 1, 3)
|
||||
__version__ = ".".join([str(x) for x in version_info])
|
||||
|
||||
from cpu_cores.common import CPUCoresCounter
|
||||
from .common import CPUCoresCounter
|
||||
|
||||
__all__ = ['CPUCoresCounter']
|
@@ -20,10 +20,10 @@ class CPUCoresCounter(object):
|
||||
else:
|
||||
cls.platform = sys.platform
|
||||
if cls.platform.startswith('darwin'):
|
||||
from cpu_cores.darwin import DarwinCPUCoresCounter
|
||||
from .darwin import DarwinCPUCoresCounter
|
||||
return DarwinCPUCoresCounter()
|
||||
elif cls.platform.startswith('linux'):
|
||||
from cpu_cores.linux import LinuxCPUCoresCounter
|
||||
from .linux import LinuxCPUCoresCounter
|
||||
return LinuxCPUCoresCounter()
|
||||
else:
|
||||
raise NotImplementedError("unsupported platform type [%s]" %
|
@@ -4,7 +4,7 @@
|
||||
import shlex
|
||||
import subprocess
|
||||
|
||||
from cpu_cores.common import CPUCoresCounter
|
||||
from .common import CPUCoresCounter
|
||||
|
||||
CPUINFO_COMMAND = "/usr/sbin/system_profiler" \
|
||||
" -detailLevel full SPHardwareDataType"
|
@@ -1,7 +1,7 @@
|
||||
# This file is part of cpu_cores released under the MIT license.
|
||||
# See the LICENSE file for more information.
|
||||
|
||||
from cpu_cores.common import CPUCoresCounter
|
||||
from .common import CPUCoresCounter
|
||||
|
||||
CPUINFO_FILEPATH = "/proc/cpuinfo"
|
||||
|
@@ -1,6 +1,5 @@
|
||||
import foundation
|
||||
from foundation import progress
|
||||
import dateutil
|
||||
from . import progress
|
||||
from .third_party import dateutil
|
||||
import os
|
||||
import requests
|
||||
import tarfile
|
||||
@@ -45,7 +44,7 @@ def queryMainScene(filepath, callbacks):
|
||||
Return the equivalent to bpy.context.scene
|
||||
"""
|
||||
|
||||
from blendfile import blendfile
|
||||
from .blendfile import blendfile
|
||||
|
||||
with blendfile.open_blend(filepath) as blend:
|
||||
# There is no bpy.context.scene, we get it from the main window
|
||||
|
@@ -5,7 +5,6 @@ import sys
|
||||
|
||||
SCRIPT_PATH = os.path.realpath(__file__)
|
||||
SCRIPT_DIR = os.path.dirname(SCRIPT_PATH)
|
||||
sys.path.append(os.path.join(SCRIPT_DIR, "third_party"))
|
||||
|
||||
import argparse
|
||||
import foundation
|
||||
|
292
benchmark/third_party/dateutil/test/_common.py
vendored
292
benchmark/third_party/dateutil/test/_common.py
vendored
@@ -1,292 +0,0 @@
|
||||
from __future__ import unicode_literals
|
||||
try:
|
||||
import unittest2 as unittest
|
||||
except ImportError:
|
||||
import unittest
|
||||
|
||||
import os
|
||||
import datetime
|
||||
import time
|
||||
import subprocess
|
||||
import warnings
|
||||
import tempfile
|
||||
import pickle
|
||||
|
||||
|
||||
class WarningTestMixin(object):
|
||||
# Based on https://stackoverflow.com/a/12935176/467366
|
||||
class _AssertWarnsContext(warnings.catch_warnings):
|
||||
def __init__(self, expected_warnings, parent, **kwargs):
|
||||
super(WarningTestMixin._AssertWarnsContext, self).__init__(**kwargs)
|
||||
|
||||
self.parent = parent
|
||||
try:
|
||||
self.expected_warnings = list(expected_warnings)
|
||||
except TypeError:
|
||||
self.expected_warnings = [expected_warnings]
|
||||
|
||||
self._warning_log = []
|
||||
|
||||
def __enter__(self, *args, **kwargs):
|
||||
rv = super(WarningTestMixin._AssertWarnsContext, self).__enter__(*args, **kwargs)
|
||||
|
||||
if self._showwarning is not self._module.showwarning:
|
||||
super_showwarning = self._module.showwarning
|
||||
else:
|
||||
super_showwarning = None
|
||||
|
||||
def showwarning(*args, **kwargs):
|
||||
if super_showwarning is not None:
|
||||
super_showwarning(*args, **kwargs)
|
||||
|
||||
self._warning_log.append(warnings.WarningMessage(*args, **kwargs))
|
||||
|
||||
self._module.showwarning = showwarning
|
||||
return rv
|
||||
|
||||
def __exit__(self, *args, **kwargs):
|
||||
super(WarningTestMixin._AssertWarnsContext, self).__exit__(self, *args, **kwargs)
|
||||
|
||||
self.parent.assertTrue(any(issubclass(item.category, warning)
|
||||
for warning in self.expected_warnings
|
||||
for item in self._warning_log))
|
||||
|
||||
def assertWarns(self, warning, callable=None, *args, **kwargs):
|
||||
warnings.simplefilter('always')
|
||||
context = self.__class__._AssertWarnsContext(warning, self)
|
||||
if callable is None:
|
||||
return context
|
||||
else:
|
||||
with context:
|
||||
callable(*args, **kwargs)
|
||||
|
||||
|
||||
class PicklableMixin(object):
|
||||
def _get_nobj_bytes(self, obj, dump_kwargs, load_kwargs):
|
||||
"""
|
||||
Pickle and unpickle an object using ``pickle.dumps`` / ``pickle.loads``
|
||||
"""
|
||||
pkl = pickle.dumps(obj, **dump_kwargs)
|
||||
return pickle.loads(pkl, **load_kwargs)
|
||||
|
||||
def _get_nobj_file(self, obj, dump_kwargs, load_kwargs):
|
||||
"""
|
||||
Pickle and unpickle an object using ``pickle.dump`` / ``pickle.load`` on
|
||||
a temporary file.
|
||||
"""
|
||||
with tempfile.TemporaryFile('w+b') as pkl:
|
||||
pickle.dump(obj, pkl, **dump_kwargs)
|
||||
pkl.seek(0) # Reset the file to the beginning to read it
|
||||
nobj = pickle.load(pkl, **load_kwargs)
|
||||
|
||||
return nobj
|
||||
|
||||
def assertPicklable(self, obj, asfile=False,
|
||||
dump_kwargs=None, load_kwargs=None):
|
||||
"""
|
||||
Assert that an object can be pickled and unpickled. This assertion
|
||||
assumes that the desired behavior is that the unpickled object compares
|
||||
equal to the original object, but is not the same object.
|
||||
"""
|
||||
get_nobj = self._get_nobj_file if asfile else self._get_nobj_bytes
|
||||
dump_kwargs = dump_kwargs or {}
|
||||
load_kwargs = load_kwargs or {}
|
||||
|
||||
nobj = get_nobj(obj, dump_kwargs, load_kwargs)
|
||||
self.assertIsNot(obj, nobj)
|
||||
self.assertEqual(obj, nobj)
|
||||
|
||||
|
||||
class TZContextBase(object):
|
||||
"""
|
||||
Base class for a context manager which allows changing of time zones.
|
||||
|
||||
Subclasses may define a guard variable to either block or or allow time
|
||||
zone changes by redefining ``_guard_var_name`` and ``_guard_allows_change``.
|
||||
The default is that the guard variable must be affirmatively set.
|
||||
|
||||
Subclasses must define ``get_current_tz`` and ``set_current_tz``.
|
||||
"""
|
||||
_guard_var_name = "DATEUTIL_MAY_CHANGE_TZ"
|
||||
_guard_allows_change = True
|
||||
|
||||
def __init__(self, tzval):
|
||||
self.tzval = tzval
|
||||
self._old_tz = None
|
||||
|
||||
@classmethod
|
||||
def tz_change_allowed(cls):
|
||||
"""
|
||||
Class method used to query whether or not this class allows time zone
|
||||
changes.
|
||||
"""
|
||||
guard = bool(os.environ.get(cls._guard_var_name, False))
|
||||
|
||||
# _guard_allows_change gives the "default" behavior - if True, the
|
||||
# guard is overcoming a block. If false, the guard is causing a block.
|
||||
# Whether tz_change is allowed is therefore the XNOR of the two.
|
||||
return guard == cls._guard_allows_change
|
||||
|
||||
@classmethod
|
||||
def tz_change_disallowed_message(cls):
|
||||
""" Generate instructions on how to allow tz changes """
|
||||
msg = ('Changing time zone not allowed. Set {envar} to {gval} '
|
||||
'if you would like to allow this behavior')
|
||||
|
||||
return msg.format(envar=cls._guard_var_name,
|
||||
gval=cls._guard_allows_change)
|
||||
|
||||
def __enter__(self):
|
||||
if not self.tz_change_allowed():
|
||||
raise ValueError(self.tz_change_disallowed_message())
|
||||
|
||||
self._old_tz = self.get_current_tz()
|
||||
self.set_current_tz(self.tzval)
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
if self._old_tz is not None:
|
||||
self.set_current_tz(self._old_tz)
|
||||
|
||||
self._old_tz = None
|
||||
|
||||
def get_current_tz(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def set_current_tz(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class TZEnvContext(TZContextBase):
|
||||
"""
|
||||
Context manager that temporarily sets the `TZ` variable (for use on
|
||||
*nix-like systems). Because the effect is local to the shell anyway, this
|
||||
will apply *unless* a guard is set.
|
||||
|
||||
If you do not want the TZ environment variable set, you may set the
|
||||
``DATEUTIL_MAY_NOT_CHANGE_TZ_VAR`` variable to a truthy value.
|
||||
"""
|
||||
_guard_var_name = "DATEUTIL_MAY_NOT_CHANGE_TZ_VAR"
|
||||
_guard_allows_change = False
|
||||
|
||||
def get_current_tz(self):
|
||||
return os.environ.get('TZ', UnsetTz)
|
||||
|
||||
def set_current_tz(self, tzval):
|
||||
if tzval is UnsetTz and 'TZ' in os.environ:
|
||||
del os.environ['TZ']
|
||||
else:
|
||||
os.environ['TZ'] = tzval
|
||||
|
||||
time.tzset()
|
||||
|
||||
|
||||
class TZWinContext(TZContextBase):
|
||||
"""
|
||||
Context manager for changing local time zone on Windows.
|
||||
|
||||
Because the effect of this is system-wide and global, it may have
|
||||
unintended side effect. Set the ``DATEUTIL_MAY_CHANGE_TZ`` environment
|
||||
variable to a truthy value before using this context manager.
|
||||
"""
|
||||
def get_current_tz(self):
|
||||
p = subprocess.Popen(['tzutil', '/g'], stdout=subprocess.PIPE)
|
||||
|
||||
ctzname, err = p.communicate()
|
||||
ctzname = ctzname.decode() # Popen returns
|
||||
|
||||
if p.returncode:
|
||||
raise OSError('Failed to get current time zone: ' + err)
|
||||
|
||||
return ctzname
|
||||
|
||||
def set_current_tz(self, tzname):
|
||||
p = subprocess.Popen('tzutil /s "' + tzname + '"')
|
||||
|
||||
out, err = p.communicate()
|
||||
|
||||
if p.returncode:
|
||||
raise OSError('Failed to set current time zone: ' +
|
||||
(err or 'Unknown error.'))
|
||||
|
||||
|
||||
###
|
||||
# Compatibility functions
|
||||
|
||||
def _total_seconds(td):
|
||||
# Python 2.6 doesn't have a total_seconds() method on timedelta objects
|
||||
return ((td.seconds + td.days * 86400) * 1000000 +
|
||||
td.microseconds) // 1000000
|
||||
|
||||
|
||||
total_seconds = getattr(datetime.timedelta, 'total_seconds', _total_seconds)
|
||||
|
||||
|
||||
###
|
||||
# Utility classes
|
||||
class NotAValueClass(object):
|
||||
"""
|
||||
A class analogous to NaN that has operations defined for any type.
|
||||
"""
|
||||
def _op(self, other):
|
||||
return self # Operation with NotAValue returns NotAValue
|
||||
|
||||
def _cmp(self, other):
|
||||
return False
|
||||
|
||||
__add__ = __radd__ = _op
|
||||
__sub__ = __rsub__ = _op
|
||||
__mul__ = __rmul__ = _op
|
||||
__div__ = __rdiv__ = _op
|
||||
__truediv__ = __rtruediv__ = _op
|
||||
__floordiv__ = __rfloordiv__ = _op
|
||||
|
||||
__lt__ = __rlt__ = _op
|
||||
__gt__ = __rgt__ = _op
|
||||
__eq__ = __req__ = _op
|
||||
__le__ = __rle__ = _op
|
||||
__ge__ = __rge__ = _op
|
||||
|
||||
|
||||
NotAValue = NotAValueClass()
|
||||
|
||||
|
||||
class ComparesEqualClass(object):
|
||||
"""
|
||||
A class that is always equal to whatever you compare it to.
|
||||
"""
|
||||
|
||||
def __eq__(self, other):
|
||||
return True
|
||||
|
||||
def __ne__(self, other):
|
||||
return False
|
||||
|
||||
def __le__(self, other):
|
||||
return True
|
||||
|
||||
def __ge__(self, other):
|
||||
return True
|
||||
|
||||
def __lt__(self, other):
|
||||
return False
|
||||
|
||||
def __gt__(self, other):
|
||||
return False
|
||||
|
||||
__req__ = __eq__
|
||||
__rne__ = __ne__
|
||||
__rle__ = __le__
|
||||
__rge__ = __ge__
|
||||
__rlt__ = __lt__
|
||||
__rgt__ = __gt__
|
||||
|
||||
|
||||
ComparesEqual = ComparesEqualClass()
|
||||
|
||||
|
||||
class UnsetTzClass(object):
|
||||
""" Sentinel class for unset time zone variable """
|
||||
pass
|
||||
|
||||
|
||||
UnsetTz = UnsetTzClass()
|
@@ -1,99 +0,0 @@
|
||||
from dateutil.easter import easter
|
||||
from dateutil.easter import EASTER_WESTERN, EASTER_ORTHODOX, EASTER_JULIAN
|
||||
|
||||
from datetime import date
|
||||
|
||||
try:
|
||||
import unittest2 as unittest
|
||||
except ImportError:
|
||||
import unittest
|
||||
|
||||
# List of easters between 1990 and 2050
|
||||
western_easter_dates = [
|
||||
date(1990, 4, 15), date(1991, 3, 31), date(1992, 4, 19), date(1993, 4, 11),
|
||||
date(1994, 4, 3), date(1995, 4, 16), date(1996, 4, 7), date(1997, 3, 30),
|
||||
date(1998, 4, 12), date(1999, 4, 4),
|
||||
|
||||
date(2000, 4, 23), date(2001, 4, 15), date(2002, 3, 31), date(2003, 4, 20),
|
||||
date(2004, 4, 11), date(2005, 3, 27), date(2006, 4, 16), date(2007, 4, 8),
|
||||
date(2008, 3, 23), date(2009, 4, 12),
|
||||
|
||||
date(2010, 4, 4), date(2011, 4, 24), date(2012, 4, 8), date(2013, 3, 31),
|
||||
date(2014, 4, 20), date(2015, 4, 5), date(2016, 3, 27), date(2017, 4, 16),
|
||||
date(2018, 4, 1), date(2019, 4, 21),
|
||||
|
||||
date(2020, 4, 12), date(2021, 4, 4), date(2022, 4, 17), date(2023, 4, 9),
|
||||
date(2024, 3, 31), date(2025, 4, 20), date(2026, 4, 5), date(2027, 3, 28),
|
||||
date(2028, 4, 16), date(2029, 4, 1),
|
||||
|
||||
date(2030, 4, 21), date(2031, 4, 13), date(2032, 3, 28), date(2033, 4, 17),
|
||||
date(2034, 4, 9), date(2035, 3, 25), date(2036, 4, 13), date(2037, 4, 5),
|
||||
date(2038, 4, 25), date(2039, 4, 10),
|
||||
|
||||
date(2040, 4, 1), date(2041, 4, 21), date(2042, 4, 6), date(2043, 3, 29),
|
||||
date(2044, 4, 17), date(2045, 4, 9), date(2046, 3, 25), date(2047, 4, 14),
|
||||
date(2048, 4, 5), date(2049, 4, 18), date(2050, 4, 10)
|
||||
]
|
||||
|
||||
orthodox_easter_dates = [
|
||||
date(1990, 4, 15), date(1991, 4, 7), date(1992, 4, 26), date(1993, 4, 18),
|
||||
date(1994, 5, 1), date(1995, 4, 23), date(1996, 4, 14), date(1997, 4, 27),
|
||||
date(1998, 4, 19), date(1999, 4, 11),
|
||||
|
||||
date(2000, 4, 30), date(2001, 4, 15), date(2002, 5, 5), date(2003, 4, 27),
|
||||
date(2004, 4, 11), date(2005, 5, 1), date(2006, 4, 23), date(2007, 4, 8),
|
||||
date(2008, 4, 27), date(2009, 4, 19),
|
||||
|
||||
date(2010, 4, 4), date(2011, 4, 24), date(2012, 4, 15), date(2013, 5, 5),
|
||||
date(2014, 4, 20), date(2015, 4, 12), date(2016, 5, 1), date(2017, 4, 16),
|
||||
date(2018, 4, 8), date(2019, 4, 28),
|
||||
|
||||
date(2020, 4, 19), date(2021, 5, 2), date(2022, 4, 24), date(2023, 4, 16),
|
||||
date(2024, 5, 5), date(2025, 4, 20), date(2026, 4, 12), date(2027, 5, 2),
|
||||
date(2028, 4, 16), date(2029, 4, 8),
|
||||
|
||||
date(2030, 4, 28), date(2031, 4, 13), date(2032, 5, 2), date(2033, 4, 24),
|
||||
date(2034, 4, 9), date(2035, 4, 29), date(2036, 4, 20), date(2037, 4, 5),
|
||||
date(2038, 4, 25), date(2039, 4, 17),
|
||||
|
||||
date(2040, 5, 6), date(2041, 4, 21), date(2042, 4, 13), date(2043, 5, 3),
|
||||
date(2044, 4, 24), date(2045, 4, 9), date(2046, 4, 29), date(2047, 4, 21),
|
||||
date(2048, 4, 5), date(2049, 4, 25), date(2050, 4, 17)
|
||||
]
|
||||
|
||||
# A random smattering of Julian dates.
|
||||
# Pulled values from http://www.kevinlaughery.com/east4099.html
|
||||
julian_easter_dates = [
|
||||
date( 326, 4, 3), date( 375, 4, 5), date( 492, 4, 5), date( 552, 3, 31),
|
||||
date( 562, 4, 9), date( 569, 4, 21), date( 597, 4, 14), date( 621, 4, 19),
|
||||
date( 636, 3, 31), date( 655, 3, 29), date( 700, 4, 11), date( 725, 4, 8),
|
||||
date( 750, 3, 29), date( 782, 4, 7), date( 835, 4, 18), date( 849, 4, 14),
|
||||
date( 867, 3, 30), date( 890, 4, 12), date( 922, 4, 21), date( 934, 4, 6),
|
||||
date(1049, 3, 26), date(1058, 4, 19), date(1113, 4, 6), date(1119, 3, 30),
|
||||
date(1242, 4, 20), date(1255, 3, 28), date(1257, 4, 8), date(1258, 3, 24),
|
||||
date(1261, 4, 24), date(1278, 4, 17), date(1333, 4, 4), date(1351, 4, 17),
|
||||
date(1371, 4, 6), date(1391, 3, 26), date(1402, 3, 26), date(1412, 4, 3),
|
||||
date(1439, 4, 5), date(1445, 3, 28), date(1531, 4, 9), date(1555, 4, 14)
|
||||
]
|
||||
|
||||
|
||||
class EasterTest(unittest.TestCase):
|
||||
def testEasterWestern(self):
|
||||
for easter_date in western_easter_dates:
|
||||
self.assertEqual(easter_date,
|
||||
easter(easter_date.year, EASTER_WESTERN))
|
||||
|
||||
def testEasterOrthodox(self):
|
||||
for easter_date in orthodox_easter_dates:
|
||||
self.assertEqual(easter_date,
|
||||
easter(easter_date.year, EASTER_ORTHODOX))
|
||||
|
||||
def testEasterJulian(self):
|
||||
for easter_date in julian_easter_dates:
|
||||
self.assertEqual(easter_date,
|
||||
easter(easter_date.year, EASTER_JULIAN))
|
||||
|
||||
def testEasterBadMethod(self):
|
||||
# Invalid methods raise ValueError
|
||||
with self.assertRaises(ValueError):
|
||||
easter(1975, 4)
|
166
benchmark/third_party/dateutil/test/test_imports.py
vendored
166
benchmark/third_party/dateutil/test/test_imports.py
vendored
@@ -1,166 +0,0 @@
|
||||
import sys
|
||||
|
||||
try:
|
||||
import unittest2 as unittest
|
||||
except ImportError:
|
||||
import unittest
|
||||
|
||||
class ImportVersionTest(unittest.TestCase):
|
||||
""" Test that dateutil.__version__ can be imported"""
|
||||
|
||||
def testImportVersionStr(self):
|
||||
from dateutil import __version__
|
||||
|
||||
def testImportRoot(self):
|
||||
import dateutil
|
||||
|
||||
self.assertTrue(hasattr(dateutil, '__version__'))
|
||||
|
||||
|
||||
class ImportEasterTest(unittest.TestCase):
|
||||
""" Test that dateutil.easter-related imports work properly """
|
||||
|
||||
def testEasterDirect(self):
|
||||
import dateutil.easter
|
||||
|
||||
def testEasterFrom(self):
|
||||
from dateutil import easter
|
||||
|
||||
def testEasterStar(self):
|
||||
from dateutil.easter import easter
|
||||
|
||||
|
||||
class ImportParserTest(unittest.TestCase):
|
||||
""" Test that dateutil.parser-related imports work properly """
|
||||
def testParserDirect(self):
|
||||
import dateutil.parser
|
||||
|
||||
def testParserFrom(self):
|
||||
from dateutil import parser
|
||||
|
||||
def testParserAll(self):
|
||||
# All interface
|
||||
from dateutil.parser import parse
|
||||
from dateutil.parser import parserinfo
|
||||
|
||||
# Other public classes
|
||||
from dateutil.parser import parser
|
||||
|
||||
for var in (parse, parserinfo, parser):
|
||||
self.assertIsNot(var, None)
|
||||
|
||||
|
||||
class ImportRelativeDeltaTest(unittest.TestCase):
|
||||
""" Test that dateutil.relativedelta-related imports work properly """
|
||||
def testRelativeDeltaDirect(self):
|
||||
import dateutil.relativedelta
|
||||
|
||||
def testRelativeDeltaFrom(self):
|
||||
from dateutil import relativedelta
|
||||
|
||||
def testRelativeDeltaAll(self):
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from dateutil.relativedelta import MO, TU, WE, TH, FR, SA, SU
|
||||
|
||||
for var in (relativedelta, MO, TU, WE, TH, FR, SA, SU):
|
||||
self.assertIsNot(var, None)
|
||||
|
||||
# In the public interface but not in all
|
||||
from dateutil.relativedelta import weekday
|
||||
self.assertIsNot(weekday, None)
|
||||
|
||||
|
||||
class ImportRRuleTest(unittest.TestCase):
|
||||
""" Test that dateutil.rrule related imports work properly """
|
||||
def testRRuleDirect(self):
|
||||
import dateutil.rrule
|
||||
|
||||
def testRRuleFrom(self):
|
||||
from dateutil import rrule
|
||||
|
||||
def testRRuleAll(self):
|
||||
from dateutil.rrule import rrule
|
||||
from dateutil.rrule import rruleset
|
||||
from dateutil.rrule import rrulestr
|
||||
from dateutil.rrule import YEARLY, MONTHLY, WEEKLY, DAILY
|
||||
from dateutil.rrule import HOURLY, MINUTELY, SECONDLY
|
||||
from dateutil.rrule import MO, TU, WE, TH, FR, SA, SU
|
||||
|
||||
rr_all = (rrule, rruleset, rrulestr,
|
||||
YEARLY, MONTHLY, WEEKLY, DAILY,
|
||||
HOURLY, MINUTELY, SECONDLY,
|
||||
MO, TU, WE, TH, FR, SA, SU)
|
||||
|
||||
for var in rr_all:
|
||||
self.assertIsNot(var, None)
|
||||
|
||||
# In the public interface but not in all
|
||||
from dateutil.rrule import weekday
|
||||
self.assertIsNot(weekday, None)
|
||||
|
||||
|
||||
class ImportTZTest(unittest.TestCase):
|
||||
""" Test that dateutil.tz related imports work properly """
|
||||
def testTzDirect(self):
|
||||
import dateutil.tz
|
||||
|
||||
def testTzFrom(self):
|
||||
from dateutil import tz
|
||||
|
||||
def testTzAll(self):
|
||||
from dateutil.tz import tzutc
|
||||
from dateutil.tz import tzoffset
|
||||
from dateutil.tz import tzlocal
|
||||
from dateutil.tz import tzfile
|
||||
from dateutil.tz import tzrange
|
||||
from dateutil.tz import tzstr
|
||||
from dateutil.tz import tzical
|
||||
from dateutil.tz import gettz
|
||||
from dateutil.tz import tzwin
|
||||
from dateutil.tz import tzwinlocal
|
||||
|
||||
tz_all = ["tzutc", "tzoffset", "tzlocal", "tzfile", "tzrange",
|
||||
"tzstr", "tzical", "gettz"]
|
||||
|
||||
tz_all += ["tzwin", "tzwinlocal"] if sys.platform.startswith("win") else []
|
||||
lvars = locals()
|
||||
|
||||
for var in tz_all:
|
||||
self.assertIsNot(lvars[var], None)
|
||||
|
||||
|
||||
@unittest.skipUnless(sys.platform.startswith('win'), "Requires Windows")
|
||||
class ImportTZWinTest(unittest.TestCase):
|
||||
""" Test that dateutil.tzwin related imports work properly """
|
||||
def testTzwinDirect(self):
|
||||
import dateutil.tzwin
|
||||
|
||||
def testTzwinFrom(self):
|
||||
from dateutil import tzwin
|
||||
|
||||
def testTzwinStar(self):
|
||||
from dateutil.tzwin import tzwin
|
||||
from dateutil.tzwin import tzwinlocal
|
||||
|
||||
tzwin_all = [tzwin, tzwinlocal]
|
||||
|
||||
for var in tzwin_all:
|
||||
self.assertIsNot(var, None)
|
||||
|
||||
|
||||
class ImportZoneInfoTest(unittest.TestCase):
|
||||
def testZoneinfoDirect(self):
|
||||
import dateutil.zoneinfo
|
||||
|
||||
def testZoneinfoFrom(self):
|
||||
from dateutil import zoneinfo
|
||||
|
||||
def testZoneinfoStar(self):
|
||||
from dateutil.zoneinfo import gettz
|
||||
from dateutil.zoneinfo import gettz_db_metadata
|
||||
from dateutil.zoneinfo import rebuild
|
||||
|
||||
zi_all = (gettz, gettz_db_metadata, rebuild)
|
||||
|
||||
for var in zi_all:
|
||||
self.assertIsNot(var, None)
|
897
benchmark/third_party/dateutil/test/test_parser.py
vendored
897
benchmark/third_party/dateutil/test/test_parser.py
vendored
@@ -1,897 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
from ._common import unittest
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from dateutil.tz import tzoffset
|
||||
from dateutil.parser import parse, parserinfo
|
||||
|
||||
from six import assertRaisesRegex, PY3
|
||||
from six.moves import StringIO
|
||||
|
||||
|
||||
class ParserTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.tzinfos = {"BRST": -10800}
|
||||
self.brsttz = tzoffset("BRST", -10800)
|
||||
self.default = datetime(2003, 9, 25)
|
||||
|
||||
# Parser should be able to handle bytestring and unicode
|
||||
self.uni_str = '2014-05-01 08:00:00'
|
||||
self.str_str = self.uni_str.encode()
|
||||
|
||||
def testEmptyString(self):
|
||||
with self.assertRaises(ValueError):
|
||||
parse('')
|
||||
|
||||
def testNone(self):
|
||||
with self.assertRaises(TypeError):
|
||||
parse(None)
|
||||
|
||||
def testInvalidType(self):
|
||||
with self.assertRaises(TypeError):
|
||||
parse(13)
|
||||
|
||||
def testDuckTyping(self):
|
||||
# We want to support arbitrary classes that implement the stream
|
||||
# interface.
|
||||
|
||||
class StringPassThrough(object):
|
||||
def __init__(self, stream):
|
||||
self.stream = stream
|
||||
|
||||
def read(self, *args, **kwargs):
|
||||
return self.stream.read(*args, **kwargs)
|
||||
|
||||
dstr = StringPassThrough(StringIO('2014 January 19'))
|
||||
|
||||
self.assertEqual(parse(dstr), datetime(2014, 1, 19))
|
||||
|
||||
def testParseStream(self):
|
||||
dstr = StringIO('2014 January 19')
|
||||
|
||||
self.assertEqual(parse(dstr), datetime(2014, 1, 19))
|
||||
|
||||
def testParseStr(self):
|
||||
self.assertEqual(parse(self.str_str),
|
||||
parse(self.uni_str))
|
||||
|
||||
def testParserParseStr(self):
|
||||
from dateutil.parser import parser
|
||||
|
||||
self.assertEqual(parser().parse(self.str_str),
|
||||
parser().parse(self.uni_str))
|
||||
|
||||
def testParseUnicodeWords(self):
|
||||
|
||||
class rus_parserinfo(parserinfo):
|
||||
MONTHS = [("янв", "Январь"),
|
||||
("фев", "Февраль"),
|
||||
("мар", "Март"),
|
||||
("апр", "Апрель"),
|
||||
("май", "Май"),
|
||||
("июн", "Июнь"),
|
||||
("июл", "Июль"),
|
||||
("авг", "Август"),
|
||||
("сен", "Сентябрь"),
|
||||
("окт", "Октябрь"),
|
||||
("ноя", "Ноябрь"),
|
||||
("дек", "Декабрь")]
|
||||
|
||||
self.assertEqual(parse('10 Сентябрь 2015 10:20',
|
||||
parserinfo=rus_parserinfo()),
|
||||
datetime(2015, 9, 10, 10, 20))
|
||||
|
||||
def testParseWithNulls(self):
|
||||
# This relies on the from __future__ import unicode_literals, because
|
||||
# explicitly specifying a unicode literal is a syntax error in Py 3.2
|
||||
# May want to switch to u'...' if we ever drop Python 3.2 support.
|
||||
pstring = '\x00\x00August 29, 1924'
|
||||
|
||||
self.assertEqual(parse(pstring),
|
||||
datetime(1924, 8, 29))
|
||||
|
||||
def testDateCommandFormat(self):
|
||||
self.assertEqual(parse("Thu Sep 25 10:36:28 BRST 2003",
|
||||
tzinfos=self.tzinfos),
|
||||
datetime(2003, 9, 25, 10, 36, 28,
|
||||
tzinfo=self.brsttz))
|
||||
|
||||
def testDateCommandFormatUnicode(self):
|
||||
self.assertEqual(parse("Thu Sep 25 10:36:28 BRST 2003",
|
||||
tzinfos=self.tzinfos),
|
||||
datetime(2003, 9, 25, 10, 36, 28,
|
||||
tzinfo=self.brsttz))
|
||||
|
||||
def testDateCommandFormatReversed(self):
|
||||
self.assertEqual(parse("2003 10:36:28 BRST 25 Sep Thu",
|
||||
tzinfos=self.tzinfos),
|
||||
datetime(2003, 9, 25, 10, 36, 28,
|
||||
tzinfo=self.brsttz))
|
||||
|
||||
def testDateCommandFormatWithLong(self):
|
||||
if not PY3:
|
||||
self.assertEqual(parse("Thu Sep 25 10:36:28 BRST 2003",
|
||||
tzinfos={"BRST": long(-10800)}),
|
||||
datetime(2003, 9, 25, 10, 36, 28,
|
||||
tzinfo=self.brsttz))
|
||||
|
||||
def testDateCommandFormatIgnoreTz(self):
|
||||
self.assertEqual(parse("Thu Sep 25 10:36:28 BRST 2003",
|
||||
ignoretz=True),
|
||||
datetime(2003, 9, 25, 10, 36, 28))
|
||||
|
||||
def testDateCommandFormatStrip1(self):
|
||||
self.assertEqual(parse("Thu Sep 25 10:36:28 2003"),
|
||||
datetime(2003, 9, 25, 10, 36, 28))
|
||||
|
||||
def testDateCommandFormatStrip2(self):
|
||||
self.assertEqual(parse("Thu Sep 25 10:36:28", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36, 28))
|
||||
|
||||
def testDateCommandFormatStrip3(self):
|
||||
self.assertEqual(parse("Thu Sep 10:36:28", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36, 28))
|
||||
|
||||
def testDateCommandFormatStrip4(self):
|
||||
self.assertEqual(parse("Thu 10:36:28", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36, 28))
|
||||
|
||||
def testDateCommandFormatStrip5(self):
|
||||
self.assertEqual(parse("Sep 10:36:28", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36, 28))
|
||||
|
||||
def testDateCommandFormatStrip6(self):
|
||||
self.assertEqual(parse("10:36:28", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36, 28))
|
||||
|
||||
def testDateCommandFormatStrip7(self):
|
||||
self.assertEqual(parse("10:36", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36))
|
||||
|
||||
def testDateCommandFormatStrip8(self):
|
||||
self.assertEqual(parse("Thu Sep 25 2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateCommandFormatStrip9(self):
|
||||
self.assertEqual(parse("Sep 25 2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateCommandFormatStrip10(self):
|
||||
self.assertEqual(parse("Sep 2003", default=self.default),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateCommandFormatStrip11(self):
|
||||
self.assertEqual(parse("Sep", default=self.default),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateCommandFormatStrip12(self):
|
||||
self.assertEqual(parse("2003", default=self.default),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateRCommandFormat(self):
|
||||
self.assertEqual(parse("Thu, 25 Sep 2003 10:49:41 -0300"),
|
||||
datetime(2003, 9, 25, 10, 49, 41,
|
||||
tzinfo=self.brsttz))
|
||||
|
||||
def testISOFormat(self):
|
||||
self.assertEqual(parse("2003-09-25T10:49:41.5-03:00"),
|
||||
datetime(2003, 9, 25, 10, 49, 41, 500000,
|
||||
tzinfo=self.brsttz))
|
||||
|
||||
def testISOFormatStrip1(self):
|
||||
self.assertEqual(parse("2003-09-25T10:49:41-03:00"),
|
||||
datetime(2003, 9, 25, 10, 49, 41,
|
||||
tzinfo=self.brsttz))
|
||||
|
||||
def testISOFormatStrip2(self):
|
||||
self.assertEqual(parse("2003-09-25T10:49:41"),
|
||||
datetime(2003, 9, 25, 10, 49, 41))
|
||||
|
||||
def testISOFormatStrip3(self):
|
||||
self.assertEqual(parse("2003-09-25T10:49"),
|
||||
datetime(2003, 9, 25, 10, 49))
|
||||
|
||||
def testISOFormatStrip4(self):
|
||||
self.assertEqual(parse("2003-09-25T10"),
|
||||
datetime(2003, 9, 25, 10))
|
||||
|
||||
def testISOFormatStrip5(self):
|
||||
self.assertEqual(parse("2003-09-25"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testISOStrippedFormat(self):
|
||||
self.assertEqual(parse("20030925T104941.5-0300"),
|
||||
datetime(2003, 9, 25, 10, 49, 41, 500000,
|
||||
tzinfo=self.brsttz))
|
||||
|
||||
def testISOStrippedFormatStrip1(self):
|
||||
self.assertEqual(parse("20030925T104941-0300"),
|
||||
datetime(2003, 9, 25, 10, 49, 41,
|
||||
tzinfo=self.brsttz))
|
||||
|
||||
def testISOStrippedFormatStrip2(self):
|
||||
self.assertEqual(parse("20030925T104941"),
|
||||
datetime(2003, 9, 25, 10, 49, 41))
|
||||
|
||||
def testISOStrippedFormatStrip3(self):
|
||||
self.assertEqual(parse("20030925T1049"),
|
||||
datetime(2003, 9, 25, 10, 49, 0))
|
||||
|
||||
def testISOStrippedFormatStrip4(self):
|
||||
self.assertEqual(parse("20030925T10"),
|
||||
datetime(2003, 9, 25, 10))
|
||||
|
||||
def testISOStrippedFormatStrip5(self):
|
||||
self.assertEqual(parse("20030925"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testPythonLoggerFormat(self):
|
||||
self.assertEqual(parse("2003-09-25 10:49:41,502"),
|
||||
datetime(2003, 9, 25, 10, 49, 41, 502000))
|
||||
|
||||
def testNoSeparator1(self):
|
||||
self.assertEqual(parse("199709020908"),
|
||||
datetime(1997, 9, 2, 9, 8))
|
||||
|
||||
def testNoSeparator2(self):
|
||||
self.assertEqual(parse("19970902090807"),
|
||||
datetime(1997, 9, 2, 9, 8, 7))
|
||||
|
||||
def testDateWithDash1(self):
|
||||
self.assertEqual(parse("2003-09-25"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDash2(self):
|
||||
self.assertEqual(parse("2003-Sep-25"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDash3(self):
|
||||
self.assertEqual(parse("25-Sep-2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDash4(self):
|
||||
self.assertEqual(parse("25-Sep-2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDash5(self):
|
||||
self.assertEqual(parse("Sep-25-2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDash6(self):
|
||||
self.assertEqual(parse("09-25-2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDash7(self):
|
||||
self.assertEqual(parse("25-09-2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDash8(self):
|
||||
self.assertEqual(parse("10-09-2003", dayfirst=True),
|
||||
datetime(2003, 9, 10))
|
||||
|
||||
def testDateWithDash9(self):
|
||||
self.assertEqual(parse("10-09-2003"),
|
||||
datetime(2003, 10, 9))
|
||||
|
||||
def testDateWithDash10(self):
|
||||
self.assertEqual(parse("10-09-03"),
|
||||
datetime(2003, 10, 9))
|
||||
|
||||
def testDateWithDash11(self):
|
||||
self.assertEqual(parse("10-09-03", yearfirst=True),
|
||||
datetime(2010, 9, 3))
|
||||
|
||||
def testDateWithDot1(self):
|
||||
self.assertEqual(parse("2003.09.25"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDot2(self):
|
||||
self.assertEqual(parse("2003.Sep.25"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDot3(self):
|
||||
self.assertEqual(parse("25.Sep.2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDot4(self):
|
||||
self.assertEqual(parse("25.Sep.2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDot5(self):
|
||||
self.assertEqual(parse("Sep.25.2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDot6(self):
|
||||
self.assertEqual(parse("09.25.2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDot7(self):
|
||||
self.assertEqual(parse("25.09.2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDot8(self):
|
||||
self.assertEqual(parse("10.09.2003", dayfirst=True),
|
||||
datetime(2003, 9, 10))
|
||||
|
||||
def testDateWithDot9(self):
|
||||
self.assertEqual(parse("10.09.2003"),
|
||||
datetime(2003, 10, 9))
|
||||
|
||||
def testDateWithDot10(self):
|
||||
self.assertEqual(parse("10.09.03"),
|
||||
datetime(2003, 10, 9))
|
||||
|
||||
def testDateWithDot11(self):
|
||||
self.assertEqual(parse("10.09.03", yearfirst=True),
|
||||
datetime(2010, 9, 3))
|
||||
|
||||
def testDateWithSlash1(self):
|
||||
self.assertEqual(parse("2003/09/25"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSlash2(self):
|
||||
self.assertEqual(parse("2003/Sep/25"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSlash3(self):
|
||||
self.assertEqual(parse("25/Sep/2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSlash4(self):
|
||||
self.assertEqual(parse("25/Sep/2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSlash5(self):
|
||||
self.assertEqual(parse("Sep/25/2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSlash6(self):
|
||||
self.assertEqual(parse("09/25/2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSlash7(self):
|
||||
self.assertEqual(parse("25/09/2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSlash8(self):
|
||||
self.assertEqual(parse("10/09/2003", dayfirst=True),
|
||||
datetime(2003, 9, 10))
|
||||
|
||||
def testDateWithSlash9(self):
|
||||
self.assertEqual(parse("10/09/2003"),
|
||||
datetime(2003, 10, 9))
|
||||
|
||||
def testDateWithSlash10(self):
|
||||
self.assertEqual(parse("10/09/03"),
|
||||
datetime(2003, 10, 9))
|
||||
|
||||
def testDateWithSlash11(self):
|
||||
self.assertEqual(parse("10/09/03", yearfirst=True),
|
||||
datetime(2010, 9, 3))
|
||||
|
||||
def testDateWithSpace1(self):
|
||||
self.assertEqual(parse("2003 09 25"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSpace2(self):
|
||||
self.assertEqual(parse("2003 Sep 25"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSpace3(self):
|
||||
self.assertEqual(parse("25 Sep 2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSpace4(self):
|
||||
self.assertEqual(parse("25 Sep 2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSpace5(self):
|
||||
self.assertEqual(parse("Sep 25 2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSpace6(self):
|
||||
self.assertEqual(parse("09 25 2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSpace7(self):
|
||||
self.assertEqual(parse("25 09 2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSpace8(self):
|
||||
self.assertEqual(parse("10 09 2003", dayfirst=True),
|
||||
datetime(2003, 9, 10))
|
||||
|
||||
def testDateWithSpace9(self):
|
||||
self.assertEqual(parse("10 09 2003"),
|
||||
datetime(2003, 10, 9))
|
||||
|
||||
def testDateWithSpace10(self):
|
||||
self.assertEqual(parse("10 09 03"),
|
||||
datetime(2003, 10, 9))
|
||||
|
||||
def testDateWithSpace11(self):
|
||||
self.assertEqual(parse("10 09 03", yearfirst=True),
|
||||
datetime(2010, 9, 3))
|
||||
|
||||
def testDateWithSpace12(self):
|
||||
self.assertEqual(parse("25 09 03"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testStrangelyOrderedDate1(self):
|
||||
self.assertEqual(parse("03 25 Sep"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testStrangelyOrderedDate2(self):
|
||||
self.assertEqual(parse("2003 25 Sep"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testStrangelyOrderedDate3(self):
|
||||
self.assertEqual(parse("25 03 Sep"),
|
||||
datetime(2025, 9, 3))
|
||||
|
||||
def testHourWithLetters(self):
|
||||
self.assertEqual(parse("10h36m28.5s", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36, 28, 500000))
|
||||
|
||||
def testHourWithLettersStrip1(self):
|
||||
self.assertEqual(parse("10h36m28s", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36, 28))
|
||||
|
||||
def testHourWithLettersStrip2(self):
|
||||
self.assertEqual(parse("10h36m", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36))
|
||||
|
||||
def testHourWithLettersStrip3(self):
|
||||
self.assertEqual(parse("10h", default=self.default),
|
||||
datetime(2003, 9, 25, 10))
|
||||
|
||||
def testHourWithLettersStrip4(self):
|
||||
self.assertEqual(parse("10 h 36", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36))
|
||||
|
||||
def testHourWithLetterStrip5(self):
|
||||
self.assertEqual(parse("10 h 36.5", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36, 30))
|
||||
|
||||
def testMinuteWithLettersSpaces1(self):
|
||||
self.assertEqual(parse("36 m 5", default=self.default),
|
||||
datetime(2003, 9, 25, 0, 36, 5))
|
||||
|
||||
def testMinuteWithLettersSpaces2(self):
|
||||
self.assertEqual(parse("36 m 5 s", default=self.default),
|
||||
datetime(2003, 9, 25, 0, 36, 5))
|
||||
|
||||
def testMinuteWithLettersSpaces3(self):
|
||||
self.assertEqual(parse("36 m 05", default=self.default),
|
||||
datetime(2003, 9, 25, 0, 36, 5))
|
||||
|
||||
def testMinuteWithLettersSpaces4(self):
|
||||
self.assertEqual(parse("36 m 05 s", default=self.default),
|
||||
datetime(2003, 9, 25, 0, 36, 5))
|
||||
|
||||
def testAMPMNoHour(self):
|
||||
with self.assertRaises(ValueError):
|
||||
parse("AM")
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
parse("Jan 20, 2015 PM")
|
||||
|
||||
def testHourAmPm1(self):
|
||||
self.assertEqual(parse("10h am", default=self.default),
|
||||
datetime(2003, 9, 25, 10))
|
||||
|
||||
def testHourAmPm2(self):
|
||||
self.assertEqual(parse("10h pm", default=self.default),
|
||||
datetime(2003, 9, 25, 22))
|
||||
|
||||
def testHourAmPm3(self):
|
||||
self.assertEqual(parse("10am", default=self.default),
|
||||
datetime(2003, 9, 25, 10))
|
||||
|
||||
def testHourAmPm4(self):
|
||||
self.assertEqual(parse("10pm", default=self.default),
|
||||
datetime(2003, 9, 25, 22))
|
||||
|
||||
def testHourAmPm5(self):
|
||||
self.assertEqual(parse("10:00 am", default=self.default),
|
||||
datetime(2003, 9, 25, 10))
|
||||
|
||||
def testHourAmPm6(self):
|
||||
self.assertEqual(parse("10:00 pm", default=self.default),
|
||||
datetime(2003, 9, 25, 22))
|
||||
|
||||
def testHourAmPm7(self):
|
||||
self.assertEqual(parse("10:00am", default=self.default),
|
||||
datetime(2003, 9, 25, 10))
|
||||
|
||||
def testHourAmPm8(self):
|
||||
self.assertEqual(parse("10:00pm", default=self.default),
|
||||
datetime(2003, 9, 25, 22))
|
||||
|
||||
def testHourAmPm9(self):
|
||||
self.assertEqual(parse("10:00a.m", default=self.default),
|
||||
datetime(2003, 9, 25, 10))
|
||||
|
||||
def testHourAmPm10(self):
|
||||
self.assertEqual(parse("10:00p.m", default=self.default),
|
||||
datetime(2003, 9, 25, 22))
|
||||
|
||||
def testHourAmPm11(self):
|
||||
self.assertEqual(parse("10:00a.m.", default=self.default),
|
||||
datetime(2003, 9, 25, 10))
|
||||
|
||||
def testHourAmPm12(self):
|
||||
self.assertEqual(parse("10:00p.m.", default=self.default),
|
||||
datetime(2003, 9, 25, 22))
|
||||
|
||||
def testAMPMRange(self):
|
||||
with self.assertRaises(ValueError):
|
||||
parse("13:44 AM")
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
parse("January 25, 1921 23:13 PM")
|
||||
|
||||
def testPertain(self):
|
||||
self.assertEqual(parse("Sep 03", default=self.default),
|
||||
datetime(2003, 9, 3))
|
||||
self.assertEqual(parse("Sep of 03", default=self.default),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testWeekdayAlone(self):
|
||||
self.assertEqual(parse("Wed", default=self.default),
|
||||
datetime(2003, 10, 1))
|
||||
|
||||
def testLongWeekday(self):
|
||||
self.assertEqual(parse("Wednesday", default=self.default),
|
||||
datetime(2003, 10, 1))
|
||||
|
||||
def testLongMonth(self):
|
||||
self.assertEqual(parse("October", default=self.default),
|
||||
datetime(2003, 10, 25))
|
||||
|
||||
def testZeroYear(self):
|
||||
self.assertEqual(parse("31-Dec-00", default=self.default),
|
||||
datetime(2000, 12, 31))
|
||||
|
||||
def testFuzzy(self):
|
||||
s = "Today is 25 of September of 2003, exactly " \
|
||||
"at 10:49:41 with timezone -03:00."
|
||||
self.assertEqual(parse(s, fuzzy=True),
|
||||
datetime(2003, 9, 25, 10, 49, 41,
|
||||
tzinfo=self.brsttz))
|
||||
|
||||
def testFuzzyWithTokens(self):
|
||||
s1 = "Today is 25 of September of 2003, exactly " \
|
||||
"at 10:49:41 with timezone -03:00."
|
||||
self.assertEqual(parse(s1, fuzzy_with_tokens=True),
|
||||
(datetime(2003, 9, 25, 10, 49, 41,
|
||||
tzinfo=self.brsttz),
|
||||
('Today is ', 'of ', ', exactly at ',
|
||||
' with timezone ', '.')))
|
||||
|
||||
s2 = "http://biz.yahoo.com/ipo/p/600221.html"
|
||||
self.assertEqual(parse(s2, fuzzy_with_tokens=True),
|
||||
(datetime(2060, 2, 21, 0, 0, 0),
|
||||
('http://biz.yahoo.com/ipo/p/', '.html')))
|
||||
|
||||
def testFuzzyAMPMProblem(self):
|
||||
# Sometimes fuzzy parsing results in AM/PM flag being set without
|
||||
# hours - if it's fuzzy it should ignore that.
|
||||
s1 = "I have a meeting on March 1, 1974."
|
||||
s2 = "On June 8th, 2020, I am going to be the first man on Mars"
|
||||
|
||||
# Also don't want any erroneous AM or PMs changing the parsed time
|
||||
s3 = "Meet me at the AM/PM on Sunset at 3:00 AM on December 3rd, 2003"
|
||||
s4 = "Meet me at 3:00AM on December 3rd, 2003 at the AM/PM on Sunset"
|
||||
|
||||
self.assertEqual(parse(s1, fuzzy=True), datetime(1974, 3, 1))
|
||||
self.assertEqual(parse(s2, fuzzy=True), datetime(2020, 6, 8))
|
||||
self.assertEqual(parse(s3, fuzzy=True), datetime(2003, 12, 3, 3))
|
||||
self.assertEqual(parse(s4, fuzzy=True), datetime(2003, 12, 3, 3))
|
||||
|
||||
def testFuzzyIgnoreAMPM(self):
|
||||
s1 = "Jan 29, 1945 14:45 AM I going to see you there?"
|
||||
|
||||
self.assertEqual(parse(s1, fuzzy=True), datetime(1945, 1, 29, 14, 45))
|
||||
|
||||
def testExtraSpace(self):
|
||||
self.assertEqual(parse(" July 4 , 1976 12:01:02 am "),
|
||||
datetime(1976, 7, 4, 0, 1, 2))
|
||||
|
||||
def testRandomFormat1(self):
|
||||
self.assertEqual(parse("Wed, July 10, '96"),
|
||||
datetime(1996, 7, 10, 0, 0))
|
||||
|
||||
def testRandomFormat2(self):
|
||||
self.assertEqual(parse("1996.07.10 AD at 15:08:56 PDT",
|
||||
ignoretz=True),
|
||||
datetime(1996, 7, 10, 15, 8, 56))
|
||||
|
||||
def testRandomFormat3(self):
|
||||
self.assertEqual(parse("1996.July.10 AD 12:08 PM"),
|
||||
datetime(1996, 7, 10, 12, 8))
|
||||
|
||||
def testRandomFormat4(self):
|
||||
self.assertEqual(parse("Tuesday, April 12, 1952 AD 3:30:42pm PST",
|
||||
ignoretz=True),
|
||||
datetime(1952, 4, 12, 15, 30, 42))
|
||||
|
||||
def testRandomFormat5(self):
|
||||
self.assertEqual(parse("November 5, 1994, 8:15:30 am EST",
|
||||
ignoretz=True),
|
||||
datetime(1994, 11, 5, 8, 15, 30))
|
||||
|
||||
def testRandomFormat6(self):
|
||||
self.assertEqual(parse("1994-11-05T08:15:30-05:00",
|
||||
ignoretz=True),
|
||||
datetime(1994, 11, 5, 8, 15, 30))
|
||||
|
||||
def testRandomFormat7(self):
|
||||
self.assertEqual(parse("1994-11-05T08:15:30Z",
|
||||
ignoretz=True),
|
||||
datetime(1994, 11, 5, 8, 15, 30))
|
||||
|
||||
def testRandomFormat8(self):
|
||||
self.assertEqual(parse("July 4, 1976"), datetime(1976, 7, 4))
|
||||
|
||||
def testRandomFormat9(self):
|
||||
self.assertEqual(parse("7 4 1976"), datetime(1976, 7, 4))
|
||||
|
||||
def testRandomFormat10(self):
|
||||
self.assertEqual(parse("4 jul 1976"), datetime(1976, 7, 4))
|
||||
|
||||
def testRandomFormat11(self):
|
||||
self.assertEqual(parse("7-4-76"), datetime(1976, 7, 4))
|
||||
|
||||
def testRandomFormat12(self):
|
||||
self.assertEqual(parse("19760704"), datetime(1976, 7, 4))
|
||||
|
||||
def testRandomFormat13(self):
|
||||
self.assertEqual(parse("0:01:02", default=self.default),
|
||||
datetime(2003, 9, 25, 0, 1, 2))
|
||||
|
||||
def testRandomFormat14(self):
|
||||
self.assertEqual(parse("12h 01m02s am", default=self.default),
|
||||
datetime(2003, 9, 25, 0, 1, 2))
|
||||
|
||||
def testRandomFormat15(self):
|
||||
self.assertEqual(parse("0:01:02 on July 4, 1976"),
|
||||
datetime(1976, 7, 4, 0, 1, 2))
|
||||
|
||||
def testRandomFormat16(self):
|
||||
self.assertEqual(parse("0:01:02 on July 4, 1976"),
|
||||
datetime(1976, 7, 4, 0, 1, 2))
|
||||
|
||||
def testRandomFormat17(self):
|
||||
self.assertEqual(parse("1976-07-04T00:01:02Z", ignoretz=True),
|
||||
datetime(1976, 7, 4, 0, 1, 2))
|
||||
|
||||
def testRandomFormat18(self):
|
||||
self.assertEqual(parse("July 4, 1976 12:01:02 am"),
|
||||
datetime(1976, 7, 4, 0, 1, 2))
|
||||
|
||||
def testRandomFormat19(self):
|
||||
self.assertEqual(parse("Mon Jan 2 04:24:27 1995"),
|
||||
datetime(1995, 1, 2, 4, 24, 27))
|
||||
|
||||
def testRandomFormat20(self):
|
||||
self.assertEqual(parse("Tue Apr 4 00:22:12 PDT 1995", ignoretz=True),
|
||||
datetime(1995, 4, 4, 0, 22, 12))
|
||||
|
||||
def testRandomFormat21(self):
|
||||
self.assertEqual(parse("04.04.95 00:22"),
|
||||
datetime(1995, 4, 4, 0, 22))
|
||||
|
||||
def testRandomFormat22(self):
|
||||
self.assertEqual(parse("Jan 1 1999 11:23:34.578"),
|
||||
datetime(1999, 1, 1, 11, 23, 34, 578000))
|
||||
|
||||
def testRandomFormat23(self):
|
||||
self.assertEqual(parse("950404 122212"),
|
||||
datetime(1995, 4, 4, 12, 22, 12))
|
||||
|
||||
def testRandomFormat24(self):
|
||||
self.assertEqual(parse("0:00 PM, PST", default=self.default,
|
||||
ignoretz=True),
|
||||
datetime(2003, 9, 25, 12, 0))
|
||||
|
||||
def testRandomFormat25(self):
|
||||
self.assertEqual(parse("12:08 PM", default=self.default),
|
||||
datetime(2003, 9, 25, 12, 8))
|
||||
|
||||
def testRandomFormat26(self):
|
||||
self.assertEqual(parse("5:50 A.M. on June 13, 1990"),
|
||||
datetime(1990, 6, 13, 5, 50))
|
||||
|
||||
def testRandomFormat27(self):
|
||||
self.assertEqual(parse("3rd of May 2001"), datetime(2001, 5, 3))
|
||||
|
||||
def testRandomFormat28(self):
|
||||
self.assertEqual(parse("5th of March 2001"), datetime(2001, 3, 5))
|
||||
|
||||
def testRandomFormat29(self):
|
||||
self.assertEqual(parse("1st of May 2003"), datetime(2003, 5, 1))
|
||||
|
||||
def testRandomFormat30(self):
|
||||
self.assertEqual(parse("01h02m03", default=self.default),
|
||||
datetime(2003, 9, 25, 1, 2, 3))
|
||||
|
||||
def testRandomFormat31(self):
|
||||
self.assertEqual(parse("01h02", default=self.default),
|
||||
datetime(2003, 9, 25, 1, 2))
|
||||
|
||||
def testRandomFormat32(self):
|
||||
self.assertEqual(parse("01h02s", default=self.default),
|
||||
datetime(2003, 9, 25, 1, 0, 2))
|
||||
|
||||
def testRandomFormat33(self):
|
||||
self.assertEqual(parse("01m02", default=self.default),
|
||||
datetime(2003, 9, 25, 0, 1, 2))
|
||||
|
||||
def testRandomFormat34(self):
|
||||
self.assertEqual(parse("01m02h", default=self.default),
|
||||
datetime(2003, 9, 25, 2, 1))
|
||||
|
||||
def testRandomFormat35(self):
|
||||
self.assertEqual(parse("2004 10 Apr 11h30m", default=self.default),
|
||||
datetime(2004, 4, 10, 11, 30))
|
||||
|
||||
def test_99_ad(self):
|
||||
self.assertEqual(parse('0099-01-01T00:00:00'),
|
||||
datetime(99, 1, 1, 0, 0))
|
||||
|
||||
def test_31_ad(self):
|
||||
self.assertEqual(parse('0031-01-01T00:00:00'),
|
||||
datetime(31, 1, 1, 0, 0))
|
||||
|
||||
def testInvalidDay(self):
|
||||
with self.assertRaises(ValueError):
|
||||
parse("Feb 30, 2007")
|
||||
|
||||
def testUnspecifiedDayFallback(self):
|
||||
# Test that for an unspecified day, the fallback behavior is correct.
|
||||
self.assertEqual(parse("April 2009", default=datetime(2010, 1, 31)),
|
||||
datetime(2009, 4, 30))
|
||||
|
||||
def testUnspecifiedDayFallbackFebNoLeapYear(self):
|
||||
self.assertEqual(parse("Feb 2007", default=datetime(2010, 1, 31)),
|
||||
datetime(2007, 2, 28))
|
||||
|
||||
def testUnspecifiedDayFallbackFebLeapYear(self):
|
||||
self.assertEqual(parse("Feb 2008", default=datetime(2010, 1, 31)),
|
||||
datetime(2008, 2, 29))
|
||||
|
||||
def testErrorType01(self):
|
||||
self.assertRaises(ValueError,
|
||||
parse, 'shouldfail')
|
||||
|
||||
def testCorrectErrorOnFuzzyWithTokens(self):
|
||||
assertRaisesRegex(self, ValueError, 'Unknown string format',
|
||||
parse, '04/04/32/423', fuzzy_with_tokens=True)
|
||||
assertRaisesRegex(self, ValueError, 'Unknown string format',
|
||||
parse, '04/04/04 +32423', fuzzy_with_tokens=True)
|
||||
assertRaisesRegex(self, ValueError, 'Unknown string format',
|
||||
parse, '04/04/0d4', fuzzy_with_tokens=True)
|
||||
|
||||
def testIncreasingCTime(self):
|
||||
# This test will check 200 different years, every month, every day,
|
||||
# every hour, every minute, every second, and every weekday, using
|
||||
# a delta of more or less 1 year, 1 month, 1 day, 1 minute and
|
||||
# 1 second.
|
||||
delta = timedelta(days=365+31+1, seconds=1+60+60*60)
|
||||
dt = datetime(1900, 1, 1, 0, 0, 0, 0)
|
||||
for i in range(200):
|
||||
self.assertEqual(parse(dt.ctime()), dt)
|
||||
dt += delta
|
||||
|
||||
def testIncreasingISOFormat(self):
|
||||
delta = timedelta(days=365+31+1, seconds=1+60+60*60)
|
||||
dt = datetime(1900, 1, 1, 0, 0, 0, 0)
|
||||
for i in range(200):
|
||||
self.assertEqual(parse(dt.isoformat()), dt)
|
||||
dt += delta
|
||||
|
||||
def testMicrosecondsPrecisionError(self):
|
||||
# Skip found out that sad precision problem. :-(
|
||||
dt1 = parse("00:11:25.01")
|
||||
dt2 = parse("00:12:10.01")
|
||||
self.assertEqual(dt1.microsecond, 10000)
|
||||
self.assertEqual(dt2.microsecond, 10000)
|
||||
|
||||
def testMicrosecondPrecisionErrorReturns(self):
|
||||
# One more precision issue, discovered by Eric Brown. This should
|
||||
# be the last one, as we're no longer using floating points.
|
||||
for ms in [100001, 100000, 99999, 99998,
|
||||
10001, 10000, 9999, 9998,
|
||||
1001, 1000, 999, 998,
|
||||
101, 100, 99, 98]:
|
||||
dt = datetime(2008, 2, 27, 21, 26, 1, ms)
|
||||
self.assertEqual(parse(dt.isoformat()), dt)
|
||||
|
||||
def testHighPrecisionSeconds(self):
|
||||
self.assertEqual(parse("20080227T21:26:01.123456789"),
|
||||
datetime(2008, 2, 27, 21, 26, 1, 123456))
|
||||
|
||||
def testCustomParserInfo(self):
|
||||
# Custom parser info wasn't working, as Michael Elsdörfer discovered.
|
||||
from dateutil.parser import parserinfo, parser
|
||||
|
||||
class myparserinfo(parserinfo):
|
||||
MONTHS = parserinfo.MONTHS[:]
|
||||
MONTHS[0] = ("Foo", "Foo")
|
||||
myparser = parser(myparserinfo())
|
||||
dt = myparser.parse("01/Foo/2007")
|
||||
self.assertEqual(dt, datetime(2007, 1, 1))
|
||||
|
||||
def testCustomParserShortDaynames(self):
|
||||
# Horacio Hoyos discovered that day names shorter than 3 characters,
|
||||
# for example two letter German day name abbreviations, don't work:
|
||||
# https://github.com/dateutil/dateutil/issues/343
|
||||
from dateutil.parser import parserinfo, parser
|
||||
|
||||
class GermanParserInfo(parserinfo):
|
||||
WEEKDAYS = [("Mo", "Montag"),
|
||||
("Di", "Dienstag"),
|
||||
("Mi", "Mittwoch"),
|
||||
("Do", "Donnerstag"),
|
||||
("Fr", "Freitag"),
|
||||
("Sa", "Samstag"),
|
||||
("So", "Sonntag")]
|
||||
|
||||
myparser = parser(GermanParserInfo())
|
||||
dt = myparser.parse("Sa 21. Jan 2017")
|
||||
self.assertEqual(dt, datetime(2017, 1, 21))
|
||||
|
||||
def testNoYearFirstNoDayFirst(self):
|
||||
dtstr = '090107'
|
||||
|
||||
# Should be MMDDYY
|
||||
self.assertEqual(parse(dtstr),
|
||||
datetime(2007, 9, 1))
|
||||
|
||||
self.assertEqual(parse(dtstr, yearfirst=False, dayfirst=False),
|
||||
datetime(2007, 9, 1))
|
||||
|
||||
def testYearFirst(self):
|
||||
dtstr = '090107'
|
||||
|
||||
# Should be MMDDYY
|
||||
self.assertEqual(parse(dtstr, yearfirst=True),
|
||||
datetime(2009, 1, 7))
|
||||
|
||||
self.assertEqual(parse(dtstr, yearfirst=True, dayfirst=False),
|
||||
datetime(2009, 1, 7))
|
||||
|
||||
def testDayFirst(self):
|
||||
dtstr = '090107'
|
||||
|
||||
# Should be DDMMYY
|
||||
self.assertEqual(parse(dtstr, dayfirst=True),
|
||||
datetime(2007, 1, 9))
|
||||
|
||||
self.assertEqual(parse(dtstr, yearfirst=False, dayfirst=True),
|
||||
datetime(2007, 1, 9))
|
||||
|
||||
def testDayFirstYearFirst(self):
|
||||
dtstr = '090107'
|
||||
# Should be YYDDMM
|
||||
self.assertEqual(parse(dtstr, yearfirst=True, dayfirst=True),
|
||||
datetime(2009, 7, 1))
|
||||
|
||||
def testUnambiguousYearFirst(self):
|
||||
dtstr = '2015 09 25'
|
||||
self.assertEqual(parse(dtstr, yearfirst=True),
|
||||
datetime(2015, 9, 25))
|
||||
|
||||
def testUnambiguousDayFirst(self):
|
||||
dtstr = '2015 09 25'
|
||||
self.assertEqual(parse(dtstr, dayfirst=True),
|
||||
datetime(2015, 9, 25))
|
||||
|
||||
def testUnambiguousDayFirstYearFirst(self):
|
||||
dtstr = '2015 09 25'
|
||||
self.assertEqual(parse(dtstr, dayfirst=True, yearfirst=True),
|
||||
datetime(2015, 9, 25))
|
@@ -1,577 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
from ._common import unittest, WarningTestMixin, NotAValue
|
||||
|
||||
import calendar
|
||||
from datetime import datetime, date, timedelta
|
||||
|
||||
from dateutil.relativedelta import relativedelta, MO, TU, WE, FR, SU
|
||||
|
||||
|
||||
class RelativeDeltaTest(WarningTestMixin, unittest.TestCase):
|
||||
now = datetime(2003, 9, 17, 20, 54, 47, 282310)
|
||||
today = date(2003, 9, 17)
|
||||
|
||||
def testInheritance(self):
|
||||
# Ensure that relativedelta is inheritance-friendly.
|
||||
class rdChildClass(relativedelta):
|
||||
pass
|
||||
|
||||
ccRD = rdChildClass(years=1, months=1, days=1, leapdays=1, weeks=1,
|
||||
hours=1, minutes=1, seconds=1, microseconds=1)
|
||||
|
||||
rd = relativedelta(years=1, months=1, days=1, leapdays=1, weeks=1,
|
||||
hours=1, minutes=1, seconds=1, microseconds=1)
|
||||
|
||||
self.assertEqual(type(ccRD + rd), type(ccRD),
|
||||
msg='Addition does not inherit type.')
|
||||
|
||||
self.assertEqual(type(ccRD - rd), type(ccRD),
|
||||
msg='Subtraction does not inherit type.')
|
||||
|
||||
self.assertEqual(type(-ccRD), type(ccRD),
|
||||
msg='Negation does not inherit type.')
|
||||
|
||||
self.assertEqual(type(ccRD * 5.0), type(ccRD),
|
||||
msg='Multiplication does not inherit type.')
|
||||
|
||||
self.assertEqual(type(ccRD / 5.0), type(ccRD),
|
||||
msg='Division does not inherit type.')
|
||||
|
||||
def testMonthEndMonthBeginning(self):
|
||||
self.assertEqual(relativedelta(datetime(2003, 1, 31, 23, 59, 59),
|
||||
datetime(2003, 3, 1, 0, 0, 0)),
|
||||
relativedelta(months=-1, seconds=-1))
|
||||
|
||||
self.assertEqual(relativedelta(datetime(2003, 3, 1, 0, 0, 0),
|
||||
datetime(2003, 1, 31, 23, 59, 59)),
|
||||
relativedelta(months=1, seconds=1))
|
||||
|
||||
def testMonthEndMonthBeginningLeapYear(self):
|
||||
self.assertEqual(relativedelta(datetime(2012, 1, 31, 23, 59, 59),
|
||||
datetime(2012, 3, 1, 0, 0, 0)),
|
||||
relativedelta(months=-1, seconds=-1))
|
||||
|
||||
self.assertEqual(relativedelta(datetime(2003, 3, 1, 0, 0, 0),
|
||||
datetime(2003, 1, 31, 23, 59, 59)),
|
||||
relativedelta(months=1, seconds=1))
|
||||
|
||||
def testNextMonth(self):
|
||||
self.assertEqual(self.now+relativedelta(months=+1),
|
||||
datetime(2003, 10, 17, 20, 54, 47, 282310))
|
||||
|
||||
def testNextMonthPlusOneWeek(self):
|
||||
self.assertEqual(self.now+relativedelta(months=+1, weeks=+1),
|
||||
datetime(2003, 10, 24, 20, 54, 47, 282310))
|
||||
|
||||
def testNextMonthPlusOneWeek10am(self):
|
||||
self.assertEqual(self.today +
|
||||
relativedelta(months=+1, weeks=+1, hour=10),
|
||||
datetime(2003, 10, 24, 10, 0))
|
||||
|
||||
def testNextMonthPlusOneWeek10amDiff(self):
|
||||
self.assertEqual(relativedelta(datetime(2003, 10, 24, 10, 0),
|
||||
self.today),
|
||||
relativedelta(months=+1, days=+7, hours=+10))
|
||||
|
||||
def testOneMonthBeforeOneYear(self):
|
||||
self.assertEqual(self.now+relativedelta(years=+1, months=-1),
|
||||
datetime(2004, 8, 17, 20, 54, 47, 282310))
|
||||
|
||||
def testMonthsOfDiffNumOfDays(self):
|
||||
self.assertEqual(date(2003, 1, 27)+relativedelta(months=+1),
|
||||
date(2003, 2, 27))
|
||||
self.assertEqual(date(2003, 1, 31)+relativedelta(months=+1),
|
||||
date(2003, 2, 28))
|
||||
self.assertEqual(date(2003, 1, 31)+relativedelta(months=+2),
|
||||
date(2003, 3, 31))
|
||||
|
||||
def testMonthsOfDiffNumOfDaysWithYears(self):
|
||||
self.assertEqual(date(2000, 2, 28)+relativedelta(years=+1),
|
||||
date(2001, 2, 28))
|
||||
self.assertEqual(date(2000, 2, 29)+relativedelta(years=+1),
|
||||
date(2001, 2, 28))
|
||||
|
||||
self.assertEqual(date(1999, 2, 28)+relativedelta(years=+1),
|
||||
date(2000, 2, 28))
|
||||
self.assertEqual(date(1999, 3, 1)+relativedelta(years=+1),
|
||||
date(2000, 3, 1))
|
||||
self.assertEqual(date(1999, 3, 1)+relativedelta(years=+1),
|
||||
date(2000, 3, 1))
|
||||
|
||||
self.assertEqual(date(2001, 2, 28)+relativedelta(years=-1),
|
||||
date(2000, 2, 28))
|
||||
self.assertEqual(date(2001, 3, 1)+relativedelta(years=-1),
|
||||
date(2000, 3, 1))
|
||||
|
||||
def testNextFriday(self):
|
||||
self.assertEqual(self.today+relativedelta(weekday=FR),
|
||||
date(2003, 9, 19))
|
||||
|
||||
def testNextFridayInt(self):
|
||||
self.assertEqual(self.today+relativedelta(weekday=calendar.FRIDAY),
|
||||
date(2003, 9, 19))
|
||||
|
||||
def testLastFridayInThisMonth(self):
|
||||
self.assertEqual(self.today+relativedelta(day=31, weekday=FR(-1)),
|
||||
date(2003, 9, 26))
|
||||
|
||||
def testNextWednesdayIsToday(self):
|
||||
self.assertEqual(self.today+relativedelta(weekday=WE),
|
||||
date(2003, 9, 17))
|
||||
|
||||
def testNextWenesdayNotToday(self):
|
||||
self.assertEqual(self.today+relativedelta(days=+1, weekday=WE),
|
||||
date(2003, 9, 24))
|
||||
|
||||
def test15thISOYearWeek(self):
|
||||
self.assertEqual(date(2003, 1, 1) +
|
||||
relativedelta(day=4, weeks=+14, weekday=MO(-1)),
|
||||
date(2003, 4, 7))
|
||||
|
||||
def testMillenniumAge(self):
|
||||
self.assertEqual(relativedelta(self.now, date(2001, 1, 1)),
|
||||
relativedelta(years=+2, months=+8, days=+16,
|
||||
hours=+20, minutes=+54, seconds=+47,
|
||||
microseconds=+282310))
|
||||
|
||||
def testJohnAge(self):
|
||||
self.assertEqual(relativedelta(self.now,
|
||||
datetime(1978, 4, 5, 12, 0)),
|
||||
relativedelta(years=+25, months=+5, days=+12,
|
||||
hours=+8, minutes=+54, seconds=+47,
|
||||
microseconds=+282310))
|
||||
|
||||
def testJohnAgeWithDate(self):
|
||||
self.assertEqual(relativedelta(self.today,
|
||||
datetime(1978, 4, 5, 12, 0)),
|
||||
relativedelta(years=+25, months=+5, days=+11,
|
||||
hours=+12))
|
||||
|
||||
def testYearDay(self):
|
||||
self.assertEqual(date(2003, 1, 1)+relativedelta(yearday=260),
|
||||
date(2003, 9, 17))
|
||||
self.assertEqual(date(2002, 1, 1)+relativedelta(yearday=260),
|
||||
date(2002, 9, 17))
|
||||
self.assertEqual(date(2000, 1, 1)+relativedelta(yearday=260),
|
||||
date(2000, 9, 16))
|
||||
self.assertEqual(self.today+relativedelta(yearday=261),
|
||||
date(2003, 9, 18))
|
||||
|
||||
def testYearDayBug(self):
|
||||
# Tests a problem reported by Adam Ryan.
|
||||
self.assertEqual(date(2010, 1, 1)+relativedelta(yearday=15),
|
||||
date(2010, 1, 15))
|
||||
|
||||
def testNonLeapYearDay(self):
|
||||
self.assertEqual(date(2003, 1, 1)+relativedelta(nlyearday=260),
|
||||
date(2003, 9, 17))
|
||||
self.assertEqual(date(2002, 1, 1)+relativedelta(nlyearday=260),
|
||||
date(2002, 9, 17))
|
||||
self.assertEqual(date(2000, 1, 1)+relativedelta(nlyearday=260),
|
||||
date(2000, 9, 17))
|
||||
self.assertEqual(self.today+relativedelta(yearday=261),
|
||||
date(2003, 9, 18))
|
||||
|
||||
def testAddition(self):
|
||||
self.assertEqual(relativedelta(days=10) +
|
||||
relativedelta(years=1, months=2, days=3, hours=4,
|
||||
minutes=5, microseconds=6),
|
||||
relativedelta(years=1, months=2, days=13, hours=4,
|
||||
minutes=5, microseconds=6))
|
||||
|
||||
def testAbsoluteAddition(self):
|
||||
self.assertEqual(relativedelta() + relativedelta(day=0, hour=0),
|
||||
relativedelta(day=0, hour=0))
|
||||
self.assertEqual(relativedelta(day=0, hour=0) + relativedelta(),
|
||||
relativedelta(day=0, hour=0))
|
||||
|
||||
def testAdditionToDatetime(self):
|
||||
self.assertEqual(datetime(2000, 1, 1) + relativedelta(days=1),
|
||||
datetime(2000, 1, 2))
|
||||
|
||||
def testRightAdditionToDatetime(self):
|
||||
self.assertEqual(relativedelta(days=1) + datetime(2000, 1, 1),
|
||||
datetime(2000, 1, 2))
|
||||
|
||||
def testAdditionInvalidType(self):
|
||||
with self.assertRaises(TypeError):
|
||||
relativedelta(days=3) + 9
|
||||
|
||||
def testAdditionUnsupportedType(self):
|
||||
# For unsupported types that define their own comparators, etc.
|
||||
self.assertIs(relativedelta(days=1) + NotAValue, NotAValue)
|
||||
|
||||
def testSubtraction(self):
|
||||
self.assertEqual(relativedelta(days=10) -
|
||||
relativedelta(years=1, months=2, days=3, hours=4,
|
||||
minutes=5, microseconds=6),
|
||||
relativedelta(years=-1, months=-2, days=7, hours=-4,
|
||||
minutes=-5, microseconds=-6))
|
||||
|
||||
def testRightSubtractionFromDatetime(self):
|
||||
self.assertEqual(datetime(2000, 1, 2) - relativedelta(days=1),
|
||||
datetime(2000, 1, 1))
|
||||
|
||||
def testSubractionWithDatetime(self):
|
||||
self.assertRaises(TypeError, lambda x, y: x - y,
|
||||
(relativedelta(days=1), datetime(2000, 1, 1)))
|
||||
|
||||
def testSubtractionInvalidType(self):
|
||||
with self.assertRaises(TypeError):
|
||||
relativedelta(hours=12) - 14
|
||||
|
||||
def testSubtractionUnsupportedType(self):
|
||||
self.assertIs(relativedelta(days=1) + NotAValue, NotAValue)
|
||||
|
||||
def testMultiplication(self):
|
||||
self.assertEqual(datetime(2000, 1, 1) + relativedelta(days=1) * 28,
|
||||
datetime(2000, 1, 29))
|
||||
self.assertEqual(datetime(2000, 1, 1) + 28 * relativedelta(days=1),
|
||||
datetime(2000, 1, 29))
|
||||
|
||||
def testMultiplicationUnsupportedType(self):
|
||||
self.assertIs(relativedelta(days=1) * NotAValue, NotAValue)
|
||||
|
||||
def testDivision(self):
|
||||
self.assertEqual(datetime(2000, 1, 1) + relativedelta(days=28) / 28,
|
||||
datetime(2000, 1, 2))
|
||||
|
||||
def testDivisionUnsupportedType(self):
|
||||
self.assertIs(relativedelta(days=1) / NotAValue, NotAValue)
|
||||
|
||||
def testBoolean(self):
|
||||
self.assertFalse(relativedelta(days=0))
|
||||
self.assertTrue(relativedelta(days=1))
|
||||
|
||||
def testComparison(self):
|
||||
d1 = relativedelta(years=1, months=1, days=1, leapdays=0, hours=1,
|
||||
minutes=1, seconds=1, microseconds=1)
|
||||
d2 = relativedelta(years=1, months=1, days=1, leapdays=0, hours=1,
|
||||
minutes=1, seconds=1, microseconds=1)
|
||||
d3 = relativedelta(years=1, months=1, days=1, leapdays=0, hours=1,
|
||||
minutes=1, seconds=1, microseconds=2)
|
||||
|
||||
self.assertEqual(d1, d2)
|
||||
self.assertNotEqual(d1, d3)
|
||||
|
||||
def testInequalityTypeMismatch(self):
|
||||
# Different type
|
||||
self.assertFalse(relativedelta(year=1) == 19)
|
||||
|
||||
def testInequalityUnsupportedType(self):
|
||||
self.assertIs(relativedelta(hours=3) == NotAValue, NotAValue)
|
||||
|
||||
def testInequalityWeekdays(self):
|
||||
# Different weekdays
|
||||
no_wday = relativedelta(year=1997, month=4)
|
||||
wday_mo_1 = relativedelta(year=1997, month=4, weekday=MO(+1))
|
||||
wday_mo_2 = relativedelta(year=1997, month=4, weekday=MO(+2))
|
||||
wday_tu = relativedelta(year=1997, month=4, weekday=TU)
|
||||
|
||||
self.assertTrue(wday_mo_1 == wday_mo_1)
|
||||
|
||||
self.assertFalse(no_wday == wday_mo_1)
|
||||
self.assertFalse(wday_mo_1 == no_wday)
|
||||
|
||||
self.assertFalse(wday_mo_1 == wday_mo_2)
|
||||
self.assertFalse(wday_mo_2 == wday_mo_1)
|
||||
|
||||
self.assertFalse(wday_mo_1 == wday_tu)
|
||||
self.assertFalse(wday_tu == wday_mo_1)
|
||||
|
||||
def testMonthOverflow(self):
|
||||
self.assertEqual(relativedelta(months=273),
|
||||
relativedelta(years=22, months=9))
|
||||
|
||||
def testWeeks(self):
|
||||
# Test that the weeks property is working properly.
|
||||
rd = relativedelta(years=4, months=2, weeks=8, days=6)
|
||||
self.assertEqual((rd.weeks, rd.days), (8, 8 * 7 + 6))
|
||||
|
||||
rd.weeks = 3
|
||||
self.assertEqual((rd.weeks, rd.days), (3, 3 * 7 + 6))
|
||||
|
||||
def testRelativeDeltaRepr(self):
|
||||
self.assertEqual(repr(relativedelta(years=1, months=-1, days=15)),
|
||||
'relativedelta(years=+1, months=-1, days=+15)')
|
||||
|
||||
self.assertEqual(repr(relativedelta(months=14, seconds=-25)),
|
||||
'relativedelta(years=+1, months=+2, seconds=-25)')
|
||||
|
||||
self.assertEqual(repr(relativedelta(month=3, hour=3, weekday=SU(3))),
|
||||
'relativedelta(month=3, weekday=SU(+3), hour=3)')
|
||||
|
||||
def testRelativeDeltaFractionalYear(self):
|
||||
with self.assertRaises(ValueError):
|
||||
relativedelta(years=1.5)
|
||||
|
||||
def testRelativeDeltaFractionalMonth(self):
|
||||
with self.assertRaises(ValueError):
|
||||
relativedelta(months=1.5)
|
||||
|
||||
def testRelativeDeltaFractionalAbsolutes(self):
|
||||
# Fractional absolute values will soon be unsupported,
|
||||
# check for the deprecation warning.
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
relativedelta(year=2.86)
|
||||
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
relativedelta(month=1.29)
|
||||
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
relativedelta(day=0.44)
|
||||
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
relativedelta(hour=23.98)
|
||||
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
relativedelta(minute=45.21)
|
||||
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
relativedelta(second=13.2)
|
||||
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
relativedelta(microsecond=157221.93)
|
||||
|
||||
def testRelativeDeltaFractionalRepr(self):
|
||||
rd = relativedelta(years=3, months=-2, days=1.25)
|
||||
|
||||
self.assertEqual(repr(rd),
|
||||
'relativedelta(years=+3, months=-2, days=+1.25)')
|
||||
|
||||
rd = relativedelta(hours=0.5, seconds=9.22)
|
||||
self.assertEqual(repr(rd),
|
||||
'relativedelta(hours=+0.5, seconds=+9.22)')
|
||||
|
||||
def testRelativeDeltaFractionalWeeks(self):
|
||||
# Equivalent to days=8, hours=18
|
||||
rd = relativedelta(weeks=1.25)
|
||||
d1 = datetime(2009, 9, 3, 0, 0)
|
||||
self.assertEqual(d1 + rd,
|
||||
datetime(2009, 9, 11, 18))
|
||||
|
||||
def testRelativeDeltaFractionalDays(self):
|
||||
rd1 = relativedelta(days=1.48)
|
||||
|
||||
d1 = datetime(2009, 9, 3, 0, 0)
|
||||
self.assertEqual(d1 + rd1,
|
||||
datetime(2009, 9, 4, 11, 31, 12))
|
||||
|
||||
rd2 = relativedelta(days=1.5)
|
||||
self.assertEqual(d1 + rd2,
|
||||
datetime(2009, 9, 4, 12, 0, 0))
|
||||
|
||||
def testRelativeDeltaFractionalHours(self):
|
||||
rd = relativedelta(days=1, hours=12.5)
|
||||
d1 = datetime(2009, 9, 3, 0, 0)
|
||||
self.assertEqual(d1 + rd,
|
||||
datetime(2009, 9, 4, 12, 30, 0))
|
||||
|
||||
def testRelativeDeltaFractionalMinutes(self):
|
||||
rd = relativedelta(hours=1, minutes=30.5)
|
||||
d1 = datetime(2009, 9, 3, 0, 0)
|
||||
self.assertEqual(d1 + rd,
|
||||
datetime(2009, 9, 3, 1, 30, 30))
|
||||
|
||||
def testRelativeDeltaFractionalSeconds(self):
|
||||
rd = relativedelta(hours=5, minutes=30, seconds=30.5)
|
||||
d1 = datetime(2009, 9, 3, 0, 0)
|
||||
self.assertEqual(d1 + rd,
|
||||
datetime(2009, 9, 3, 5, 30, 30, 500000))
|
||||
|
||||
def testRelativeDeltaFractionalPositiveOverflow(self):
|
||||
# Equivalent to (days=1, hours=14)
|
||||
rd1 = relativedelta(days=1.5, hours=2)
|
||||
d1 = datetime(2009, 9, 3, 0, 0)
|
||||
self.assertEqual(d1 + rd1,
|
||||
datetime(2009, 9, 4, 14, 0, 0))
|
||||
|
||||
# Equivalent to (days=1, hours=14, minutes=45)
|
||||
rd2 = relativedelta(days=1.5, hours=2.5, minutes=15)
|
||||
d1 = datetime(2009, 9, 3, 0, 0)
|
||||
self.assertEqual(d1 + rd2,
|
||||
datetime(2009, 9, 4, 14, 45))
|
||||
|
||||
# Carry back up - equivalent to (days=2, hours=2, minutes=0, seconds=1)
|
||||
rd3 = relativedelta(days=1.5, hours=13, minutes=59.5, seconds=31)
|
||||
self.assertEqual(d1 + rd3,
|
||||
datetime(2009, 9, 5, 2, 0, 1))
|
||||
|
||||
def testRelativeDeltaFractionalNegativeDays(self):
|
||||
# Equivalent to (days=-1, hours=-1)
|
||||
rd1 = relativedelta(days=-1.5, hours=11)
|
||||
d1 = datetime(2009, 9, 3, 12, 0)
|
||||
self.assertEqual(d1 + rd1,
|
||||
datetime(2009, 9, 2, 11, 0, 0))
|
||||
|
||||
# Equivalent to (days=-1, hours=-9)
|
||||
rd2 = relativedelta(days=-1.25, hours=-3)
|
||||
self.assertEqual(d1 + rd2,
|
||||
datetime(2009, 9, 2, 3))
|
||||
|
||||
def testRelativeDeltaNormalizeFractionalDays(self):
|
||||
# Equivalent to (days=2, hours=18)
|
||||
rd1 = relativedelta(days=2.75)
|
||||
|
||||
self.assertEqual(rd1.normalized(), relativedelta(days=2, hours=18))
|
||||
|
||||
# Equvalent to (days=1, hours=11, minutes=31, seconds=12)
|
||||
rd2 = relativedelta(days=1.48)
|
||||
|
||||
self.assertEqual(rd2.normalized(),
|
||||
relativedelta(days=1, hours=11, minutes=31, seconds=12))
|
||||
|
||||
def testRelativeDeltaNormalizeFractionalDays2(self):
|
||||
# Equivalent to (hours=1, minutes=30)
|
||||
rd1 = relativedelta(hours=1.5)
|
||||
|
||||
self.assertEqual(rd1.normalized(), relativedelta(hours=1, minutes=30))
|
||||
|
||||
# Equivalent to (hours=3, minutes=17, seconds=5, microseconds=100)
|
||||
rd2 = relativedelta(hours=3.28472225)
|
||||
|
||||
self.assertEqual(rd2.normalized(),
|
||||
relativedelta(hours=3, minutes=17, seconds=5, microseconds=100))
|
||||
|
||||
def testRelativeDeltaNormalizeFractionalMinutes(self):
|
||||
# Equivalent to (minutes=15, seconds=36)
|
||||
rd1 = relativedelta(minutes=15.6)
|
||||
|
||||
self.assertEqual(rd1.normalized(),
|
||||
relativedelta(minutes=15, seconds=36))
|
||||
|
||||
# Equivalent to (minutes=25, seconds=20, microseconds=25000)
|
||||
rd2 = relativedelta(minutes=25.33375)
|
||||
|
||||
self.assertEqual(rd2.normalized(),
|
||||
relativedelta(minutes=25, seconds=20, microseconds=25000))
|
||||
|
||||
def testRelativeDeltaNormalizeFractionalSeconds(self):
|
||||
# Equivalent to (seconds=45, microseconds=25000)
|
||||
rd1 = relativedelta(seconds=45.025)
|
||||
self.assertEqual(rd1.normalized(),
|
||||
relativedelta(seconds=45, microseconds=25000))
|
||||
|
||||
def testRelativeDeltaFractionalPositiveOverflow2(self):
|
||||
# Equivalent to (days=1, hours=14)
|
||||
rd1 = relativedelta(days=1.5, hours=2)
|
||||
self.assertEqual(rd1.normalized(),
|
||||
relativedelta(days=1, hours=14))
|
||||
|
||||
# Equivalent to (days=1, hours=14, minutes=45)
|
||||
rd2 = relativedelta(days=1.5, hours=2.5, minutes=15)
|
||||
self.assertEqual(rd2.normalized(),
|
||||
relativedelta(days=1, hours=14, minutes=45))
|
||||
|
||||
# Carry back up - equivalent to:
|
||||
# (days=2, hours=2, minutes=0, seconds=2, microseconds=3)
|
||||
rd3 = relativedelta(days=1.5, hours=13, minutes=59.50045,
|
||||
seconds=31.473, microseconds=500003)
|
||||
self.assertEqual(rd3.normalized(),
|
||||
relativedelta(days=2, hours=2, minutes=0,
|
||||
seconds=2, microseconds=3))
|
||||
|
||||
def testRelativeDeltaFractionalNegativeOverflow(self):
|
||||
# Equivalent to (days=-1)
|
||||
rd1 = relativedelta(days=-0.5, hours=-12)
|
||||
self.assertEqual(rd1.normalized(),
|
||||
relativedelta(days=-1))
|
||||
|
||||
# Equivalent to (days=-1)
|
||||
rd2 = relativedelta(days=-1.5, hours=12)
|
||||
self.assertEqual(rd2.normalized(),
|
||||
relativedelta(days=-1))
|
||||
|
||||
# Equivalent to (days=-1, hours=-14, minutes=-45)
|
||||
rd3 = relativedelta(days=-1.5, hours=-2.5, minutes=-15)
|
||||
self.assertEqual(rd3.normalized(),
|
||||
relativedelta(days=-1, hours=-14, minutes=-45))
|
||||
|
||||
# Equivalent to (days=-1, hours=-14, minutes=+15)
|
||||
rd4 = relativedelta(days=-1.5, hours=-2.5, minutes=45)
|
||||
self.assertEqual(rd4.normalized(),
|
||||
relativedelta(days=-1, hours=-14, minutes=+15))
|
||||
|
||||
# Carry back up - equivalent to:
|
||||
# (days=-2, hours=-2, minutes=0, seconds=-2, microseconds=-3)
|
||||
rd3 = relativedelta(days=-1.5, hours=-13, minutes=-59.50045,
|
||||
seconds=-31.473, microseconds=-500003)
|
||||
self.assertEqual(rd3.normalized(),
|
||||
relativedelta(days=-2, hours=-2, minutes=0,
|
||||
seconds=-2, microseconds=-3))
|
||||
|
||||
def testInvalidYearDay(self):
|
||||
with self.assertRaises(ValueError):
|
||||
relativedelta(yearday=367)
|
||||
|
||||
def testAddTimedeltaToUnpopulatedRelativedelta(self):
|
||||
td = timedelta(
|
||||
days=1,
|
||||
seconds=1,
|
||||
microseconds=1,
|
||||
milliseconds=1,
|
||||
minutes=1,
|
||||
hours=1,
|
||||
weeks=1
|
||||
)
|
||||
|
||||
expected = relativedelta(
|
||||
weeks=1,
|
||||
days=1,
|
||||
hours=1,
|
||||
minutes=1,
|
||||
seconds=1,
|
||||
microseconds=1001
|
||||
)
|
||||
|
||||
self.assertEqual(expected, relativedelta() + td)
|
||||
|
||||
def testAddTimedeltaToPopulatedRelativeDelta(self):
|
||||
td = timedelta(
|
||||
days=1,
|
||||
seconds=1,
|
||||
microseconds=1,
|
||||
milliseconds=1,
|
||||
minutes=1,
|
||||
hours=1,
|
||||
weeks=1
|
||||
)
|
||||
|
||||
rd = relativedelta(
|
||||
year=1,
|
||||
month=1,
|
||||
day=1,
|
||||
hour=1,
|
||||
minute=1,
|
||||
second=1,
|
||||
microsecond=1,
|
||||
years=1,
|
||||
months=1,
|
||||
days=1,
|
||||
weeks=1,
|
||||
hours=1,
|
||||
minutes=1,
|
||||
seconds=1,
|
||||
microseconds=1
|
||||
)
|
||||
|
||||
expected = relativedelta(
|
||||
year=1,
|
||||
month=1,
|
||||
day=1,
|
||||
hour=1,
|
||||
minute=1,
|
||||
second=1,
|
||||
microsecond=1,
|
||||
years=1,
|
||||
months=1,
|
||||
weeks=2,
|
||||
days=2,
|
||||
hours=2,
|
||||
minutes=2,
|
||||
seconds=2,
|
||||
microseconds=1002,
|
||||
)
|
||||
|
||||
self.assertEqual(expected, rd + td)
|
4704
benchmark/third_party/dateutil/test/test_rrule.py
vendored
4704
benchmark/third_party/dateutil/test/test_rrule.py
vendored
File diff suppressed because it is too large
Load Diff
2161
benchmark/third_party/dateutil/test/test_tz.py
vendored
2161
benchmark/third_party/dateutil/test/test_tz.py
vendored
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user