warp-lang 0.9.0__py3-none-win_amd64.whl → 0.11.0__py3-none-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of warp-lang might be problematic. Click here for more details.
- warp/__init__.py +15 -7
- warp/__init__.pyi +1 -0
- warp/bin/warp-clang.dll +0 -0
- warp/bin/warp.dll +0 -0
- warp/build.py +22 -443
- warp/build_dll.py +384 -0
- warp/builtins.py +998 -488
- warp/codegen.py +1307 -739
- warp/config.py +5 -3
- warp/constants.py +6 -0
- warp/context.py +1291 -548
- warp/dlpack.py +31 -31
- warp/fabric.py +326 -0
- warp/fem/__init__.py +27 -0
- warp/fem/cache.py +389 -0
- warp/fem/dirichlet.py +181 -0
- warp/fem/domain.py +263 -0
- warp/fem/field/__init__.py +101 -0
- warp/fem/field/field.py +149 -0
- warp/fem/field/nodal_field.py +299 -0
- warp/fem/field/restriction.py +21 -0
- warp/fem/field/test.py +181 -0
- warp/fem/field/trial.py +183 -0
- warp/fem/geometry/__init__.py +19 -0
- warp/fem/geometry/closest_point.py +70 -0
- warp/fem/geometry/deformed_geometry.py +271 -0
- warp/fem/geometry/element.py +744 -0
- warp/fem/geometry/geometry.py +186 -0
- warp/fem/geometry/grid_2d.py +373 -0
- warp/fem/geometry/grid_3d.py +435 -0
- warp/fem/geometry/hexmesh.py +953 -0
- warp/fem/geometry/partition.py +376 -0
- warp/fem/geometry/quadmesh_2d.py +532 -0
- warp/fem/geometry/tetmesh.py +840 -0
- warp/fem/geometry/trimesh_2d.py +577 -0
- warp/fem/integrate.py +1616 -0
- warp/fem/operator.py +191 -0
- warp/fem/polynomial.py +213 -0
- warp/fem/quadrature/__init__.py +2 -0
- warp/fem/quadrature/pic_quadrature.py +245 -0
- warp/fem/quadrature/quadrature.py +294 -0
- warp/fem/space/__init__.py +292 -0
- warp/fem/space/basis_space.py +489 -0
- warp/fem/space/collocated_function_space.py +105 -0
- warp/fem/space/dof_mapper.py +236 -0
- warp/fem/space/function_space.py +145 -0
- warp/fem/space/grid_2d_function_space.py +267 -0
- warp/fem/space/grid_3d_function_space.py +306 -0
- warp/fem/space/hexmesh_function_space.py +352 -0
- warp/fem/space/partition.py +350 -0
- warp/fem/space/quadmesh_2d_function_space.py +369 -0
- warp/fem/space/restriction.py +160 -0
- warp/fem/space/shape/__init__.py +15 -0
- warp/fem/space/shape/cube_shape_function.py +738 -0
- warp/fem/space/shape/shape_function.py +103 -0
- warp/fem/space/shape/square_shape_function.py +611 -0
- warp/fem/space/shape/tet_shape_function.py +567 -0
- warp/fem/space/shape/triangle_shape_function.py +429 -0
- warp/fem/space/tetmesh_function_space.py +292 -0
- warp/fem/space/topology.py +295 -0
- warp/fem/space/trimesh_2d_function_space.py +221 -0
- warp/fem/types.py +77 -0
- warp/fem/utils.py +495 -0
- warp/native/array.h +164 -55
- warp/native/builtin.h +150 -174
- warp/native/bvh.cpp +75 -328
- warp/native/bvh.cu +406 -23
- warp/native/bvh.h +37 -45
- warp/native/clang/clang.cpp +136 -24
- warp/native/crt.cpp +1 -76
- warp/native/crt.h +111 -104
- warp/native/cuda_crt.h +1049 -0
- warp/native/cuda_util.cpp +15 -3
- warp/native/cuda_util.h +3 -1
- warp/native/cutlass/tools/library/scripts/conv2d_operation.py +463 -0
- warp/native/cutlass/tools/library/scripts/conv3d_operation.py +321 -0
- warp/native/cutlass/tools/library/scripts/gemm_operation.py +988 -0
- warp/native/cutlass/tools/library/scripts/generator.py +4625 -0
- warp/native/cutlass/tools/library/scripts/library.py +799 -0
- warp/native/cutlass/tools/library/scripts/manifest.py +402 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/docs/source/conf.py +96 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/profile/conv/conv2d_f16_sm80.py +106 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/profile/gemm/gemm_f32_sm80.py +91 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/setup.py +80 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/__init__.py +48 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/arguments.py +118 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/c_types.py +241 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/compiler.py +432 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/conv2d_operation.py +631 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/epilogue.py +1026 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/frontend.py +104 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/gemm_operation.py +1276 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/library.py +744 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/memory_manager.py +74 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/operation.py +110 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/parser.py +619 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/reduction_operation.py +398 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/tensor_ref.py +70 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/__init__.py +4 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/conv2d_testbed.py +646 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/gemm_grouped_testbed.py +235 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/gemm_testbed.py +557 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/profiler.py +70 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/type_hint.py +39 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/utils/__init__.py +1 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/utils/device.py +76 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/utils/reference_model.py +255 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/__init__.py +0 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_f16nhwc_f16nhwc_f16nhwc_tensor_op_f16_sm80.py +201 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +177 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_f32nhwc_f32nhwc_f32nhwc_simt_f32_sm80.py +98 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_tf32nhwc_tf32nhwc_f32nhwc_tensor_op_f32_sm80.py +95 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_few_channels_f16nhwc_f16nhwc_f16nhwc_tensor_op_f32_sm80.py +163 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_fixed_channels_f16nhwc_f16nhwc_f16nhwc_tensor_op_f32_sm80.py +187 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_f16nhwc_f16nhwc_f16nhwc_tensor_op_f16_sm80.py +309 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +54 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_f32nhwc_f32nhwc_f32nhwc_simt_f32_sm80.py +96 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_tf32nhwc_tf32nhwc_f32nhwc_tensor_op_f32_sm80.py +107 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_strided_dgrad_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +253 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_f16nhwc_f16nhwc_f16nhwc_tensor_op_f16_sm80.py +97 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +242 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_f32nhwc_f32nhwc_f32nhwc_simt_f32_sm80.py +96 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_tf32nhwc_tf32nhwc_f32nhwc_tensor_op_f32_sm80.py +107 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/run_all_tests.py +10 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/frontend/test_frontend.py +146 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/__init__.py +0 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_bf16_sm80.py +96 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_f16_sm80.py +447 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_f32_sm80.py +146 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_f64_sm80.py +102 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_grouped_sm80.py +203 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_s8_sm80.py +229 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/run_all_tests.py +9 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/unit/test_sm80.py +453 -0
- warp/native/cutlass/tools/library/scripts/rank_2k_operation.py +398 -0
- warp/native/cutlass/tools/library/scripts/rank_k_operation.py +387 -0
- warp/native/cutlass/tools/library/scripts/rt.py +796 -0
- warp/native/cutlass/tools/library/scripts/symm_operation.py +400 -0
- warp/native/cutlass/tools/library/scripts/trmm_operation.py +407 -0
- warp/native/cutlass_gemm.cu +5 -3
- warp/native/exports.h +1240 -949
- warp/native/fabric.h +228 -0
- warp/native/hashgrid.cpp +4 -4
- warp/native/hashgrid.h +22 -2
- warp/native/initializer_array.h +2 -2
- warp/native/intersect.h +22 -7
- warp/native/intersect_adj.h +8 -8
- warp/native/intersect_tri.h +13 -16
- warp/native/marching.cu +157 -161
- warp/native/mat.h +119 -19
- warp/native/matnn.h +2 -2
- warp/native/mesh.cpp +108 -83
- warp/native/mesh.cu +243 -6
- warp/native/mesh.h +1547 -458
- warp/native/nanovdb/NanoVDB.h +1 -1
- warp/native/noise.h +272 -329
- warp/native/quat.h +51 -8
- warp/native/rand.h +45 -35
- warp/native/range.h +6 -2
- warp/native/reduce.cpp +157 -0
- warp/native/reduce.cu +348 -0
- warp/native/runlength_encode.cpp +62 -0
- warp/native/runlength_encode.cu +46 -0
- warp/native/scan.cu +11 -13
- warp/native/scan.h +1 -0
- warp/native/solid_angle.h +442 -0
- warp/native/sort.cpp +13 -0
- warp/native/sort.cu +9 -1
- warp/native/sparse.cpp +338 -0
- warp/native/sparse.cu +545 -0
- warp/native/spatial.h +2 -2
- warp/native/temp_buffer.h +30 -0
- warp/native/vec.h +126 -24
- warp/native/volume.h +120 -0
- warp/native/warp.cpp +658 -53
- warp/native/warp.cu +660 -68
- warp/native/warp.h +112 -12
- warp/optim/__init__.py +1 -0
- warp/optim/linear.py +922 -0
- warp/optim/sgd.py +92 -0
- warp/render/render_opengl.py +392 -152
- warp/render/render_usd.py +11 -11
- warp/sim/__init__.py +2 -2
- warp/sim/articulation.py +385 -185
- warp/sim/collide.py +21 -8
- warp/sim/import_mjcf.py +297 -106
- warp/sim/import_urdf.py +389 -210
- warp/sim/import_usd.py +198 -97
- warp/sim/inertia.py +17 -18
- warp/sim/integrator_euler.py +14 -8
- warp/sim/integrator_xpbd.py +161 -19
- warp/sim/model.py +795 -291
- warp/sim/optimizer.py +2 -6
- warp/sim/render.py +65 -3
- warp/sim/utils.py +3 -0
- warp/sparse.py +1227 -0
- warp/stubs.py +665 -223
- warp/tape.py +66 -15
- warp/tests/__main__.py +3 -6
- warp/tests/assets/curlnoise_golden.npy +0 -0
- warp/tests/assets/pnoise_golden.npy +0 -0
- warp/tests/assets/torus.usda +105 -105
- warp/tests/{test_class_kernel.py → aux_test_class_kernel.py} +9 -1
- warp/tests/aux_test_conditional_unequal_types_kernels.py +21 -0
- warp/tests/{test_dependent.py → aux_test_dependent.py} +2 -2
- warp/tests/{test_reference.py → aux_test_reference.py} +1 -1
- warp/tests/aux_test_unresolved_func.py +14 -0
- warp/tests/aux_test_unresolved_symbol.py +14 -0
- warp/tests/disabled_kinematics.py +239 -0
- warp/tests/run_coverage_serial.py +31 -0
- warp/tests/test_adam.py +103 -106
- warp/tests/test_arithmetic.py +128 -74
- warp/tests/test_array.py +1497 -211
- warp/tests/test_array_reduce.py +150 -0
- warp/tests/test_atomic.py +64 -28
- warp/tests/test_bool.py +99 -0
- warp/tests/test_builtins_resolution.py +1292 -0
- warp/tests/test_bvh.py +75 -43
- warp/tests/test_closest_point_edge_edge.py +54 -57
- warp/tests/test_codegen.py +233 -128
- warp/tests/test_compile_consts.py +28 -20
- warp/tests/test_conditional.py +108 -24
- warp/tests/test_copy.py +10 -12
- warp/tests/test_ctypes.py +112 -88
- warp/tests/test_dense.py +21 -14
- warp/tests/test_devices.py +98 -0
- warp/tests/test_dlpack.py +136 -108
- warp/tests/test_examples.py +277 -0
- warp/tests/test_fabricarray.py +955 -0
- warp/tests/test_fast_math.py +15 -11
- warp/tests/test_fem.py +1271 -0
- warp/tests/test_fp16.py +53 -19
- warp/tests/test_func.py +187 -74
- warp/tests/test_generics.py +194 -49
- warp/tests/test_grad.py +180 -116
- warp/tests/test_grad_customs.py +176 -0
- warp/tests/test_hash_grid.py +52 -37
- warp/tests/test_import.py +10 -23
- warp/tests/test_indexedarray.py +577 -24
- warp/tests/test_intersect.py +18 -9
- warp/tests/test_large.py +141 -0
- warp/tests/test_launch.py +251 -15
- warp/tests/test_lerp.py +64 -65
- warp/tests/test_linear_solvers.py +154 -0
- warp/tests/test_lvalue.py +493 -0
- warp/tests/test_marching_cubes.py +12 -13
- warp/tests/test_mat.py +508 -2778
- warp/tests/test_mat_lite.py +115 -0
- warp/tests/test_mat_scalar_ops.py +2889 -0
- warp/tests/test_math.py +103 -9
- warp/tests/test_matmul.py +305 -69
- warp/tests/test_matmul_lite.py +410 -0
- warp/tests/test_mesh.py +71 -14
- warp/tests/test_mesh_query_aabb.py +41 -25
- warp/tests/test_mesh_query_point.py +325 -34
- warp/tests/test_mesh_query_ray.py +39 -22
- warp/tests/test_mlp.py +30 -22
- warp/tests/test_model.py +92 -89
- warp/tests/test_modules_lite.py +39 -0
- warp/tests/test_multigpu.py +88 -114
- warp/tests/test_noise.py +12 -11
- warp/tests/test_operators.py +16 -20
- warp/tests/test_options.py +11 -11
- warp/tests/test_pinned.py +17 -18
- warp/tests/test_print.py +32 -11
- warp/tests/test_quat.py +275 -129
- warp/tests/test_rand.py +18 -16
- warp/tests/test_reload.py +38 -34
- warp/tests/test_rounding.py +50 -43
- warp/tests/test_runlength_encode.py +190 -0
- warp/tests/test_smoothstep.py +9 -11
- warp/tests/test_snippet.py +143 -0
- warp/tests/test_sparse.py +460 -0
- warp/tests/test_spatial.py +276 -243
- warp/tests/test_streams.py +110 -85
- warp/tests/test_struct.py +331 -85
- warp/tests/test_tape.py +39 -21
- warp/tests/test_torch.py +118 -89
- warp/tests/test_transient_module.py +12 -13
- warp/tests/test_types.py +614 -0
- warp/tests/test_utils.py +494 -0
- warp/tests/test_vec.py +354 -1987
- warp/tests/test_vec_lite.py +73 -0
- warp/tests/test_vec_scalar_ops.py +2099 -0
- warp/tests/test_volume.py +457 -293
- warp/tests/test_volume_write.py +124 -134
- warp/tests/unittest_serial.py +35 -0
- warp/tests/unittest_suites.py +341 -0
- warp/tests/unittest_utils.py +568 -0
- warp/tests/unused_test_misc.py +71 -0
- warp/tests/{test_debug.py → walkthough_debug.py} +3 -17
- warp/thirdparty/appdirs.py +36 -45
- warp/thirdparty/unittest_parallel.py +549 -0
- warp/torch.py +72 -30
- warp/types.py +1744 -713
- warp/utils.py +360 -350
- warp_lang-0.11.0.dist-info/LICENSE.md +36 -0
- warp_lang-0.11.0.dist-info/METADATA +238 -0
- warp_lang-0.11.0.dist-info/RECORD +332 -0
- {warp_lang-0.9.0.dist-info → warp_lang-0.11.0.dist-info}/WHEEL +1 -1
- warp/bin/warp-clang.exp +0 -0
- warp/bin/warp-clang.lib +0 -0
- warp/bin/warp.exp +0 -0
- warp/bin/warp.lib +0 -0
- warp/tests/test_all.py +0 -215
- warp/tests/test_array_scan.py +0 -60
- warp/tests/test_base.py +0 -208
- warp/tests/test_unresolved_func.py +0 -7
- warp/tests/test_unresolved_symbol.py +0 -7
- warp_lang-0.9.0.dist-info/METADATA +0 -20
- warp_lang-0.9.0.dist-info/RECORD +0 -177
- /warp/tests/{test_compile_consts_dummy.py → aux_test_compile_consts_dummy.py} +0 -0
- /warp/tests/{test_reference_reference.py → aux_test_reference_reference.py} +0 -0
- /warp/tests/{test_square.py → aux_test_square.py} +0 -0
- {warp_lang-0.9.0.dist-info → warp_lang-0.11.0.dist-info}/top_level.txt +0 -0
warp/thirdparty/appdirs.py
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
#!/usr/bin/env python
|
|
2
1
|
# -*- coding: utf-8 -*-
|
|
3
2
|
# Copyright (c) 2005-2010 ActiveState Software Inc.
|
|
4
3
|
# Copyright (c) 2013 Eddy Petrișor
|
|
5
4
|
|
|
6
5
|
"""Utilities for determining application-specific dirs.
|
|
7
6
|
|
|
8
|
-
See <
|
|
7
|
+
See <https://github.com/ActiveState/appdirs> for details and usage.
|
|
9
8
|
"""
|
|
10
9
|
# Dev Notes:
|
|
11
10
|
# - MSDN on where to store app data files:
|
|
12
11
|
# http://support.microsoft.com/default.aspx?scid=kb;en-us;310294#XSLTH3194121123120121120120
|
|
13
12
|
# - Mac OS X: http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileSystem/index.html
|
|
14
|
-
# - XDG spec for Un*x:
|
|
13
|
+
# - XDG spec for Un*x: https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
|
15
14
|
|
|
16
15
|
__version__ = "1.4.4"
|
|
17
16
|
__version_info__ = tuple(int(segment) for segment in __version__.split("."))
|
|
@@ -77,7 +76,7 @@ def user_data_dir(appname=None, appauthor=None, version=None, roaming=False):
|
|
|
77
76
|
if system == "win32":
|
|
78
77
|
if appauthor is None:
|
|
79
78
|
appauthor = appname
|
|
80
|
-
const =
|
|
79
|
+
const = "CSIDL_APPDATA" if roaming else "CSIDL_LOCAL_APPDATA"
|
|
81
80
|
path = os.path.normpath(_get_win_folder(const))
|
|
82
81
|
if appname:
|
|
83
82
|
if appauthor is not False:
|
|
@@ -184,15 +183,19 @@ def user_config_dir(appname=None, appauthor=None, version=None, roaming=False):
|
|
|
184
183
|
for a discussion of issues.
|
|
185
184
|
|
|
186
185
|
Typical user config directories are:
|
|
187
|
-
Mac OS X:
|
|
186
|
+
Mac OS X: ~/Library/Preferences/<AppName>
|
|
188
187
|
Unix: ~/.config/<AppName> # or in $XDG_CONFIG_HOME, if defined
|
|
189
188
|
Win *: same as user_data_dir
|
|
190
189
|
|
|
191
190
|
For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME.
|
|
192
191
|
That means, by default "~/.config/<AppName>".
|
|
193
192
|
"""
|
|
194
|
-
if system
|
|
193
|
+
if system == "win32":
|
|
195
194
|
path = user_data_dir(appname, appauthor, None, roaming)
|
|
195
|
+
elif system == "darwin":
|
|
196
|
+
path = os.path.expanduser("~/Library/Preferences/")
|
|
197
|
+
if appname:
|
|
198
|
+
path = os.path.join(path, appname)
|
|
196
199
|
else:
|
|
197
200
|
path = os.getenv("XDG_CONFIG_HOME", os.path.expanduser("~/.config"))
|
|
198
201
|
if appname:
|
|
@@ -232,10 +235,14 @@ def site_config_dir(appname=None, appauthor=None, version=None, multipath=False)
|
|
|
232
235
|
|
|
233
236
|
WARNING: Do not use this on Windows. See the Vista-Fail note above for why.
|
|
234
237
|
"""
|
|
235
|
-
if system
|
|
238
|
+
if system == "win32":
|
|
236
239
|
path = site_data_dir(appname, appauthor)
|
|
237
240
|
if appname and version:
|
|
238
241
|
path = os.path.join(path, version)
|
|
242
|
+
elif system == "darwin":
|
|
243
|
+
path = os.path.expanduser("/Library/Preferences")
|
|
244
|
+
if appname:
|
|
245
|
+
path = os.path.join(path, appname)
|
|
239
246
|
else:
|
|
240
247
|
# XDG default for $XDG_CONFIG_DIRS
|
|
241
248
|
# only first, if multipath is False
|
|
@@ -466,35 +473,6 @@ def _get_win_folder_from_registry(csidl_name):
|
|
|
466
473
|
return dir
|
|
467
474
|
|
|
468
475
|
|
|
469
|
-
def _get_win_folder_with_pywin32(csidl_name):
|
|
470
|
-
from win32com.shell import shellcon, shell
|
|
471
|
-
|
|
472
|
-
dir = shell.SHGetFolderPath(0, getattr(shellcon, csidl_name), 0, 0)
|
|
473
|
-
# Try to make this a unicode path because SHGetFolderPath does
|
|
474
|
-
# not return unicode strings when there is unicode data in the
|
|
475
|
-
# path.
|
|
476
|
-
try:
|
|
477
|
-
dir = unicode(dir)
|
|
478
|
-
|
|
479
|
-
# Downgrade to short path name if have highbit chars. See
|
|
480
|
-
# <http://bugs.activestate.com/show_bug.cgi?id=85099>.
|
|
481
|
-
has_high_char = False
|
|
482
|
-
for c in dir:
|
|
483
|
-
if ord(c) > 255:
|
|
484
|
-
has_high_char = True
|
|
485
|
-
break
|
|
486
|
-
if has_high_char:
|
|
487
|
-
try:
|
|
488
|
-
import win32api
|
|
489
|
-
|
|
490
|
-
dir = win32api.GetShortPathName(dir)
|
|
491
|
-
except ImportError:
|
|
492
|
-
pass
|
|
493
|
-
except UnicodeError:
|
|
494
|
-
pass
|
|
495
|
-
return dir
|
|
496
|
-
|
|
497
|
-
|
|
498
476
|
def _get_win_folder_with_ctypes(csidl_name):
|
|
499
477
|
import ctypes
|
|
500
478
|
|
|
@@ -549,23 +527,36 @@ def _get_win_folder_with_jna(csidl_name):
|
|
|
549
527
|
return dir
|
|
550
528
|
|
|
551
529
|
|
|
530
|
+
def _get_win_folder_from_environ(csidl_name):
|
|
531
|
+
env_var_name = {
|
|
532
|
+
"CSIDL_APPDATA": "APPDATA",
|
|
533
|
+
"CSIDL_COMMON_APPDATA": "ALLUSERSPROFILE",
|
|
534
|
+
"CSIDL_LOCAL_APPDATA": "LOCALAPPDATA",
|
|
535
|
+
}[csidl_name]
|
|
536
|
+
|
|
537
|
+
return os.environ[env_var_name]
|
|
538
|
+
|
|
539
|
+
|
|
552
540
|
if system == "win32":
|
|
553
541
|
try:
|
|
554
|
-
import
|
|
555
|
-
|
|
556
|
-
_get_win_folder = _get_win_folder_with_pywin32
|
|
542
|
+
from ctypes import windll
|
|
557
543
|
except ImportError:
|
|
558
544
|
try:
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
_get_win_folder = _get_win_folder_with_ctypes
|
|
545
|
+
import com.sun.jna
|
|
562
546
|
except ImportError:
|
|
563
547
|
try:
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
548
|
+
if PY3:
|
|
549
|
+
import winreg as _winreg
|
|
550
|
+
else:
|
|
551
|
+
import _winreg
|
|
567
552
|
except ImportError:
|
|
553
|
+
_get_win_folder = _get_win_folder_from_environ
|
|
554
|
+
else:
|
|
568
555
|
_get_win_folder = _get_win_folder_from_registry
|
|
556
|
+
else:
|
|
557
|
+
_get_win_folder = _get_win_folder_with_jna
|
|
558
|
+
else:
|
|
559
|
+
_get_win_folder = _get_win_folder_with_ctypes
|
|
569
560
|
|
|
570
561
|
|
|
571
562
|
# ---- self test code
|
|
@@ -0,0 +1,549 @@
|
|
|
1
|
+
# Licensed under the MIT License
|
|
2
|
+
# https://github.com/craigahobbs/unittest-parallel/blob/main/LICENSE
|
|
3
|
+
|
|
4
|
+
# SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
5
|
+
# SPDX-License-Identifier: LicenseRef-NvidiaProprietary
|
|
6
|
+
#
|
|
7
|
+
# NVIDIA CORPORATION, its affiliates and licensors retain all intellectual
|
|
8
|
+
# property and proprietary rights in and to this material, related
|
|
9
|
+
# documentation and any modifications thereto. Any use, reproduction,
|
|
10
|
+
# disclosure or distribution of this material and related documentation
|
|
11
|
+
# without an express license agreement from NVIDIA CORPORATION or
|
|
12
|
+
# its affiliates is strictly prohibited.
|
|
13
|
+
|
|
14
|
+
"""
|
|
15
|
+
unittest-parallel command-line script main module
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import argparse
|
|
19
|
+
import concurrent.futures # NVIDIA Modification
|
|
20
|
+
import multiprocessing
|
|
21
|
+
import os
|
|
22
|
+
import sys
|
|
23
|
+
import tempfile
|
|
24
|
+
import time
|
|
25
|
+
import unittest
|
|
26
|
+
from contextlib import contextmanager
|
|
27
|
+
from io import StringIO
|
|
28
|
+
|
|
29
|
+
import warp.tests.unittest_suites # NVIDIA Modification
|
|
30
|
+
from warp.tests.unittest_utils import ( # NVIDIA modification
|
|
31
|
+
ParallelJunitTestResult,
|
|
32
|
+
ParallelTeamCityTestResult,
|
|
33
|
+
write_junit_results,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
try:
|
|
37
|
+
import coverage
|
|
38
|
+
|
|
39
|
+
COVERAGE_AVAILABLE = True # NVIDIA Modification
|
|
40
|
+
except ImportError:
|
|
41
|
+
COVERAGE_AVAILABLE = False # NVIDIA Modification
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# The following variables are NVIDIA Modifications
|
|
45
|
+
RUNNING_IN_TEAMCITY = os.environ.get("TEAMCITY_VERSION") is not None
|
|
46
|
+
TEST_SUITE_NAME = "WarpTests"
|
|
47
|
+
START_DIRECTORY = os.path.dirname(__file__) # The directory to start test discovery
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def main(argv=None):
|
|
51
|
+
"""
|
|
52
|
+
unittest-parallel command-line script main entry point
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
# Command line arguments
|
|
56
|
+
parser = argparse.ArgumentParser(prog="unittest-parallel")
|
|
57
|
+
# parser.add_argument("-v", "--verbose", action="store_const", const=2, default=1, help="Verbose output")
|
|
58
|
+
parser.add_argument("-q", "--quiet", dest="verbose", action="store_const", const=0, default=2, help="Quiet output")
|
|
59
|
+
parser.add_argument("-f", "--failfast", action="store_true", default=False, help="Stop on first fail or error")
|
|
60
|
+
parser.add_argument(
|
|
61
|
+
"-b", "--buffer", action="store_true", default=False, help="Buffer stdout and stderr during tests"
|
|
62
|
+
)
|
|
63
|
+
parser.add_argument(
|
|
64
|
+
"-k",
|
|
65
|
+
dest="testNamePatterns",
|
|
66
|
+
action="append",
|
|
67
|
+
type=_convert_select_pattern,
|
|
68
|
+
help="Only run tests which match the given substring",
|
|
69
|
+
)
|
|
70
|
+
parser.add_argument(
|
|
71
|
+
"-p",
|
|
72
|
+
"--pattern",
|
|
73
|
+
metavar="PATTERN",
|
|
74
|
+
default="test*.py",
|
|
75
|
+
help="'autodetect' suite only: Pattern to match tests ('test*.py' default)", # NVIDIA Modification
|
|
76
|
+
)
|
|
77
|
+
parser.add_argument(
|
|
78
|
+
"-t",
|
|
79
|
+
"--top-level-directory",
|
|
80
|
+
metavar="TOP",
|
|
81
|
+
help="Top level directory of project (defaults to start directory)",
|
|
82
|
+
)
|
|
83
|
+
parser.add_argument(
|
|
84
|
+
"--junit-report-xml", metavar="FILE", help="Generate JUnit report format XML file"
|
|
85
|
+
) # NVIDIA Modification
|
|
86
|
+
parser.add_argument(
|
|
87
|
+
"-s",
|
|
88
|
+
"--suite",
|
|
89
|
+
type=str,
|
|
90
|
+
default="default",
|
|
91
|
+
choices=["autodetect", "default", "kit"],
|
|
92
|
+
help="Name of the test suite to run (default is 'default').",
|
|
93
|
+
) # NVIDIA Modification
|
|
94
|
+
group_parallel = parser.add_argument_group("parallelization options")
|
|
95
|
+
group_parallel.add_argument(
|
|
96
|
+
"-j",
|
|
97
|
+
"--jobs",
|
|
98
|
+
metavar="COUNT",
|
|
99
|
+
type=int,
|
|
100
|
+
default=0,
|
|
101
|
+
help="The number of test processes (default is 0, all cores)",
|
|
102
|
+
)
|
|
103
|
+
group_parallel.add_argument(
|
|
104
|
+
"-m",
|
|
105
|
+
"--maxjobs",
|
|
106
|
+
metavar="MAXCOUNT",
|
|
107
|
+
type=int,
|
|
108
|
+
default=8,
|
|
109
|
+
help="The maximum number of test processes (default is 8)",
|
|
110
|
+
) # NVIDIA Modification
|
|
111
|
+
group_parallel.add_argument(
|
|
112
|
+
"--level",
|
|
113
|
+
choices=["module", "class", "test"],
|
|
114
|
+
default="class",
|
|
115
|
+
help="Set the test parallelism level (default is 'class')",
|
|
116
|
+
)
|
|
117
|
+
group_parallel.add_argument(
|
|
118
|
+
"--disable-process-pooling",
|
|
119
|
+
action="store_true",
|
|
120
|
+
default=False,
|
|
121
|
+
help="Do not reuse processes used to run test suites",
|
|
122
|
+
)
|
|
123
|
+
group_parallel.add_argument(
|
|
124
|
+
"--disable-concurrent-futures",
|
|
125
|
+
action="store_true",
|
|
126
|
+
default=False,
|
|
127
|
+
help="Use multiprocessing instead of concurrent.futures.",
|
|
128
|
+
) # NVIDIA Modification
|
|
129
|
+
group_parallel.add_argument(
|
|
130
|
+
"--serial-fallback",
|
|
131
|
+
action="store_true",
|
|
132
|
+
default=False,
|
|
133
|
+
help="Run in a single-process (no spawning) mode without multiprocessing or concurrent.futures.",
|
|
134
|
+
) # NVIDIA Modification
|
|
135
|
+
group_coverage = parser.add_argument_group("coverage options")
|
|
136
|
+
group_coverage.add_argument("--coverage", action="store_true", help="Run tests with coverage")
|
|
137
|
+
group_coverage.add_argument("--coverage-branch", action="store_true", help="Run tests with branch coverage")
|
|
138
|
+
group_coverage.add_argument(
|
|
139
|
+
"--coverage-html",
|
|
140
|
+
metavar="DIR",
|
|
141
|
+
help="Generate coverage HTML report",
|
|
142
|
+
default=os.path.join(START_DIRECTORY, "..", "..", "htmlcov"),
|
|
143
|
+
)
|
|
144
|
+
group_coverage.add_argument("--coverage-xml", metavar="FILE", help="Generate coverage XML report")
|
|
145
|
+
group_coverage.add_argument(
|
|
146
|
+
"--coverage-fail-under", metavar="MIN", type=float, help="Fail if coverage percentage under min"
|
|
147
|
+
)
|
|
148
|
+
args = parser.parse_args(args=argv)
|
|
149
|
+
|
|
150
|
+
if args.coverage_branch:
|
|
151
|
+
args.coverage = args.coverage_branch
|
|
152
|
+
|
|
153
|
+
if args.coverage and not COVERAGE_AVAILABLE:
|
|
154
|
+
parser.exit(
|
|
155
|
+
status=2, message="--coverage was used, but coverage was not found. Is it installed?\n"
|
|
156
|
+
) # NVIDIA Modification
|
|
157
|
+
|
|
158
|
+
process_count = max(0, args.jobs)
|
|
159
|
+
if process_count == 0:
|
|
160
|
+
process_count = multiprocessing.cpu_count()
|
|
161
|
+
process_count = min(process_count, args.maxjobs) # NVIDIA Modification
|
|
162
|
+
|
|
163
|
+
# Create the temporary directory (for coverage files)
|
|
164
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
165
|
+
# Discover tests
|
|
166
|
+
with _coverage(args, temp_dir):
|
|
167
|
+
test_loader = unittest.TestLoader()
|
|
168
|
+
if args.testNamePatterns:
|
|
169
|
+
test_loader.testNamePatterns = args.testNamePatterns
|
|
170
|
+
|
|
171
|
+
auto_discover_suite = warp.tests.unittest_suites.auto_discover_suite(
|
|
172
|
+
test_loader, args.pattern
|
|
173
|
+
) # NVIDIA Modification
|
|
174
|
+
|
|
175
|
+
# NVIDIA Modification
|
|
176
|
+
if args.suite != "autodetect":
|
|
177
|
+
# Print notices for test classes missing from the suite when compared to auto-discovered tests
|
|
178
|
+
discover_suite = warp.tests.unittest_suites.compare_unittest_suites(
|
|
179
|
+
test_loader, args.suite, auto_discover_suite
|
|
180
|
+
)
|
|
181
|
+
else:
|
|
182
|
+
discover_suite = auto_discover_suite
|
|
183
|
+
|
|
184
|
+
# Get the parallelizable test suites
|
|
185
|
+
if args.level == "test":
|
|
186
|
+
test_suites = list(_iter_test_cases(discover_suite))
|
|
187
|
+
elif args.level == "class":
|
|
188
|
+
test_suites = list(_iter_class_suites(discover_suite))
|
|
189
|
+
else: # args.level == 'module'
|
|
190
|
+
test_suites = list(_iter_module_suites(discover_suite))
|
|
191
|
+
|
|
192
|
+
# Don't use more processes than test suites
|
|
193
|
+
process_count = max(1, min(len(test_suites), process_count))
|
|
194
|
+
|
|
195
|
+
if RUNNING_IN_TEAMCITY:
|
|
196
|
+
print(f"##teamcity[testSuiteStarted name='{TEST_SUITE_NAME}']") # NVIDIA Modification for TC
|
|
197
|
+
|
|
198
|
+
if not args.serial_fallback:
|
|
199
|
+
# Report test suites and processes
|
|
200
|
+
print(
|
|
201
|
+
f"Running {len(test_suites)} test suites ({discover_suite.countTestCases()} total tests) across {process_count} processes",
|
|
202
|
+
file=sys.stderr,
|
|
203
|
+
)
|
|
204
|
+
if args.verbose > 1:
|
|
205
|
+
print(file=sys.stderr)
|
|
206
|
+
|
|
207
|
+
# Run the tests in parallel
|
|
208
|
+
start_time = time.perf_counter()
|
|
209
|
+
|
|
210
|
+
if args.disable_concurrent_futures:
|
|
211
|
+
multiprocessing_context = multiprocessing.get_context(method="spawn")
|
|
212
|
+
maxtasksperchild = 1 if args.disable_process_pooling else None
|
|
213
|
+
with multiprocessing_context.Pool(
|
|
214
|
+
process_count,
|
|
215
|
+
maxtasksperchild=maxtasksperchild,
|
|
216
|
+
initializer=set_worker_cache,
|
|
217
|
+
initargs=(args, temp_dir),
|
|
218
|
+
) as pool, multiprocessing.Manager() as manager:
|
|
219
|
+
test_manager = ParallelTestManager(manager, args, temp_dir)
|
|
220
|
+
results = pool.map(test_manager.run_tests, test_suites)
|
|
221
|
+
else:
|
|
222
|
+
# NVIDIA Modification added concurrent.futures
|
|
223
|
+
with concurrent.futures.ProcessPoolExecutor(
|
|
224
|
+
max_workers=process_count,
|
|
225
|
+
mp_context=multiprocessing.get_context(method="spawn"),
|
|
226
|
+
initializer=set_worker_cache,
|
|
227
|
+
initargs=(args, temp_dir),
|
|
228
|
+
) as executor, multiprocessing.Manager() as manager:
|
|
229
|
+
test_manager = ParallelTestManager(manager, args, temp_dir)
|
|
230
|
+
results = list(executor.map(test_manager.run_tests, test_suites, timeout=3600))
|
|
231
|
+
else:
|
|
232
|
+
# This entire path is an NVIDIA Modification
|
|
233
|
+
|
|
234
|
+
# Report test suites and processes
|
|
235
|
+
print(f"Running {discover_suite.countTestCases()} total tests (serial fallback)", file=sys.stderr)
|
|
236
|
+
if args.verbose > 1:
|
|
237
|
+
print(file=sys.stderr)
|
|
238
|
+
|
|
239
|
+
import warp as wp
|
|
240
|
+
|
|
241
|
+
# force rebuild of all kernels
|
|
242
|
+
wp.build.clear_kernel_cache()
|
|
243
|
+
print("Cleared Warp kernel cache")
|
|
244
|
+
|
|
245
|
+
# Run the tests in serial
|
|
246
|
+
start_time = time.perf_counter()
|
|
247
|
+
|
|
248
|
+
with multiprocessing.Manager() as manager:
|
|
249
|
+
test_manager = ParallelTestManager(manager, args, temp_dir)
|
|
250
|
+
results = [test_manager.run_tests(discover_suite)]
|
|
251
|
+
|
|
252
|
+
stop_time = time.perf_counter()
|
|
253
|
+
test_duration = stop_time - start_time
|
|
254
|
+
|
|
255
|
+
if RUNNING_IN_TEAMCITY:
|
|
256
|
+
print(f"##teamcity[testSuiteFinished name='{TEST_SUITE_NAME}']") # NVIDIA Modification for TC
|
|
257
|
+
|
|
258
|
+
# Aggregate parallel test run results
|
|
259
|
+
tests_run = 0
|
|
260
|
+
errors = []
|
|
261
|
+
failures = []
|
|
262
|
+
skipped = 0
|
|
263
|
+
expected_failures = 0
|
|
264
|
+
unexpected_successes = 0
|
|
265
|
+
test_records = [] # NVIDIA Modification
|
|
266
|
+
for result in results:
|
|
267
|
+
tests_run += result[0]
|
|
268
|
+
errors.extend(result[1])
|
|
269
|
+
failures.extend(result[2])
|
|
270
|
+
skipped += result[3]
|
|
271
|
+
expected_failures += result[4]
|
|
272
|
+
unexpected_successes += result[5]
|
|
273
|
+
test_records += result[6] # NVIDIA Modification
|
|
274
|
+
is_success = not (errors or failures or unexpected_successes)
|
|
275
|
+
|
|
276
|
+
# Compute test info
|
|
277
|
+
infos = []
|
|
278
|
+
if failures:
|
|
279
|
+
infos.append(f"failures={len(failures)}")
|
|
280
|
+
if errors:
|
|
281
|
+
infos.append(f"errors={len(errors)}")
|
|
282
|
+
if skipped:
|
|
283
|
+
infos.append(f"skipped={skipped}")
|
|
284
|
+
if expected_failures:
|
|
285
|
+
infos.append(f"expected failures={expected_failures}")
|
|
286
|
+
if unexpected_successes:
|
|
287
|
+
infos.append(f"unexpected successes={unexpected_successes}")
|
|
288
|
+
|
|
289
|
+
# Report test errors
|
|
290
|
+
if errors or failures:
|
|
291
|
+
print(file=sys.stderr)
|
|
292
|
+
for error in errors:
|
|
293
|
+
print(error, file=sys.stderr)
|
|
294
|
+
for failure in failures:
|
|
295
|
+
print(failure, file=sys.stderr)
|
|
296
|
+
elif args.verbose > 0:
|
|
297
|
+
print(file=sys.stderr)
|
|
298
|
+
|
|
299
|
+
# Test report
|
|
300
|
+
print(unittest.TextTestResult.separator2, file=sys.stderr)
|
|
301
|
+
print(f'Ran {tests_run} {"tests" if tests_run > 1 else "test"} in {test_duration:.3f}s', file=sys.stderr)
|
|
302
|
+
print(file=sys.stderr)
|
|
303
|
+
print(f'{"OK" if is_success else "FAILED"}{" (" + ", ".join(infos) + ")" if infos else ""}', file=sys.stderr)
|
|
304
|
+
|
|
305
|
+
if test_records and args.junit_report_xml:
|
|
306
|
+
# NVIDIA modification to report results in Junit XML format
|
|
307
|
+
write_junit_results(
|
|
308
|
+
args.junit_report_xml,
|
|
309
|
+
test_records,
|
|
310
|
+
tests_run,
|
|
311
|
+
len(failures) + unexpected_successes,
|
|
312
|
+
len(errors),
|
|
313
|
+
skipped,
|
|
314
|
+
test_duration,
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
# Return an error status on failure
|
|
318
|
+
if not is_success:
|
|
319
|
+
if RUNNING_IN_TEAMCITY:
|
|
320
|
+
print("##teamcity[buildStatus status='FAILURE']") # NVIDIA Modification for TC
|
|
321
|
+
parser.exit(status=len(errors) + len(failures) + unexpected_successes)
|
|
322
|
+
|
|
323
|
+
# Coverage?
|
|
324
|
+
if args.coverage:
|
|
325
|
+
# Combine the coverage files
|
|
326
|
+
cov_options = {}
|
|
327
|
+
cov_options["config_file"] = True # Grab configuration from pyproject.toml (must install coverage[toml])
|
|
328
|
+
cov = coverage.Coverage(**cov_options)
|
|
329
|
+
cov.combine(data_paths=[os.path.join(temp_dir, x) for x in os.listdir(temp_dir)])
|
|
330
|
+
|
|
331
|
+
# Coverage report
|
|
332
|
+
print(file=sys.stderr)
|
|
333
|
+
percent_covered = cov.report(ignore_errors=True, file=sys.stderr)
|
|
334
|
+
print(f"Total coverage is {percent_covered:.2f}%", file=sys.stderr)
|
|
335
|
+
|
|
336
|
+
# HTML coverage report
|
|
337
|
+
if args.coverage_html:
|
|
338
|
+
cov.html_report(directory=args.coverage_html, ignore_errors=True)
|
|
339
|
+
|
|
340
|
+
# XML coverage report
|
|
341
|
+
if args.coverage_xml:
|
|
342
|
+
cov.xml_report(outfile=args.coverage_xml, ignore_errors=True)
|
|
343
|
+
|
|
344
|
+
# Fail under
|
|
345
|
+
if args.coverage_fail_under and percent_covered < args.coverage_fail_under:
|
|
346
|
+
parser.exit(status=2)
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def _convert_select_pattern(pattern):
|
|
350
|
+
if "*" not in pattern:
|
|
351
|
+
return f"*{pattern}*"
|
|
352
|
+
return pattern
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
@contextmanager
|
|
356
|
+
def _coverage(args, temp_dir):
|
|
357
|
+
# Running tests with coverage?
|
|
358
|
+
if args.coverage:
|
|
359
|
+
# Generate a random coverage data file name - file is deleted along with containing directory
|
|
360
|
+
with tempfile.NamedTemporaryFile(dir=temp_dir, delete=False) as coverage_file:
|
|
361
|
+
pass
|
|
362
|
+
|
|
363
|
+
# Create the coverage object
|
|
364
|
+
cov_options = {
|
|
365
|
+
"branch": args.coverage_branch,
|
|
366
|
+
"data_file": coverage_file.name,
|
|
367
|
+
# NVIDIA Modification removed unneeded options
|
|
368
|
+
}
|
|
369
|
+
cov_options["config_file"] = True # Grab configuration from pyproject.toml (must install coverage[toml])
|
|
370
|
+
cov = coverage.Coverage(**cov_options)
|
|
371
|
+
try:
|
|
372
|
+
# Start measuring code coverage
|
|
373
|
+
cov.start()
|
|
374
|
+
|
|
375
|
+
# Yield for unit test running
|
|
376
|
+
yield cov
|
|
377
|
+
finally:
|
|
378
|
+
# Stop measuring code coverage
|
|
379
|
+
cov.stop()
|
|
380
|
+
|
|
381
|
+
# Save the collected coverage data to the data file
|
|
382
|
+
cov.save()
|
|
383
|
+
else:
|
|
384
|
+
# Not running tests with coverage - yield for unit test running
|
|
385
|
+
yield None
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
# Iterate module-level test suites - all top-level test suites returned from TestLoader.discover
|
|
389
|
+
def _iter_module_suites(test_suite):
|
|
390
|
+
for module_suite in test_suite:
|
|
391
|
+
if module_suite.countTestCases():
|
|
392
|
+
yield module_suite
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
# Iterate class-level test suites - test suites that contains test cases
|
|
396
|
+
def _iter_class_suites(test_suite):
|
|
397
|
+
has_cases = any(isinstance(suite, unittest.TestCase) for suite in test_suite)
|
|
398
|
+
if has_cases:
|
|
399
|
+
yield test_suite
|
|
400
|
+
else:
|
|
401
|
+
for suite in test_suite:
|
|
402
|
+
yield from _iter_class_suites(suite)
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
# Iterate test cases (methods)
|
|
406
|
+
def _iter_test_cases(test_suite):
|
|
407
|
+
if isinstance(test_suite, unittest.TestCase):
|
|
408
|
+
yield test_suite
|
|
409
|
+
else:
|
|
410
|
+
for suite in test_suite:
|
|
411
|
+
yield from _iter_test_cases(suite)
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
class ParallelTestManager:
|
|
415
|
+
def __init__(self, manager, args, temp_dir):
|
|
416
|
+
self.args = args
|
|
417
|
+
self.temp_dir = temp_dir
|
|
418
|
+
self.failfast = manager.Event()
|
|
419
|
+
|
|
420
|
+
def run_tests(self, test_suite):
|
|
421
|
+
# Fail fast?
|
|
422
|
+
if self.failfast.is_set():
|
|
423
|
+
return [0, [], [], 0, 0, 0]
|
|
424
|
+
|
|
425
|
+
# NVIDIA Modification for TeamCity and GitLab
|
|
426
|
+
|
|
427
|
+
if RUNNING_IN_TEAMCITY:
|
|
428
|
+
resultclass = ParallelTeamCityTestResult
|
|
429
|
+
elif self.args.junit_report_xml:
|
|
430
|
+
resultclass = ParallelJunitTestResult
|
|
431
|
+
else:
|
|
432
|
+
resultclass = ParallelTextTestResult
|
|
433
|
+
|
|
434
|
+
# Run unit tests
|
|
435
|
+
with _coverage(self.args, self.temp_dir):
|
|
436
|
+
runner = unittest.TextTestRunner(
|
|
437
|
+
stream=StringIO(),
|
|
438
|
+
resultclass=resultclass, # NVIDIA Modification for TC
|
|
439
|
+
verbosity=self.args.verbose,
|
|
440
|
+
failfast=self.args.failfast,
|
|
441
|
+
buffer=self.args.buffer,
|
|
442
|
+
)
|
|
443
|
+
result = runner.run(test_suite)
|
|
444
|
+
|
|
445
|
+
# Set failfast, if necessary
|
|
446
|
+
if result.shouldStop:
|
|
447
|
+
self.failfast.set()
|
|
448
|
+
|
|
449
|
+
# Clean up kernel cache (NVIDIA modification)
|
|
450
|
+
import warp as wp
|
|
451
|
+
|
|
452
|
+
wp.build.clear_kernel_cache()
|
|
453
|
+
|
|
454
|
+
# Return (test_count, errors, failures, skipped_count, expected_failure_count, unexpected_success_count)
|
|
455
|
+
return (
|
|
456
|
+
result.testsRun,
|
|
457
|
+
[self._format_error(result, error) for error in result.errors],
|
|
458
|
+
[self._format_error(result, failure) for failure in result.failures],
|
|
459
|
+
len(result.skipped),
|
|
460
|
+
len(result.expectedFailures),
|
|
461
|
+
len(result.unexpectedSuccesses),
|
|
462
|
+
result.test_record, # NVIDIA modification
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
@staticmethod
|
|
466
|
+
def _format_error(result, error):
|
|
467
|
+
return "\n".join(
|
|
468
|
+
[
|
|
469
|
+
unittest.TextTestResult.separator1,
|
|
470
|
+
result.getDescription(error[0]),
|
|
471
|
+
unittest.TextTestResult.separator2,
|
|
472
|
+
error[1],
|
|
473
|
+
]
|
|
474
|
+
)
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
class ParallelTextTestResult(unittest.TextTestResult):
|
|
478
|
+
def __init__(self, stream, descriptions, verbosity):
|
|
479
|
+
stream = type(stream)(sys.stderr)
|
|
480
|
+
super().__init__(stream, descriptions, verbosity)
|
|
481
|
+
self.test_record = [] # NVIDIA modification
|
|
482
|
+
|
|
483
|
+
def startTest(self, test):
|
|
484
|
+
if self.showAll:
|
|
485
|
+
self.stream.writeln(f"{self.getDescription(test)} ...")
|
|
486
|
+
self.stream.flush()
|
|
487
|
+
super(unittest.TextTestResult, self).startTest(test)
|
|
488
|
+
|
|
489
|
+
def _add_helper(self, test, dots_message, show_all_message):
|
|
490
|
+
if self.showAll:
|
|
491
|
+
self.stream.writeln(f"{self.getDescription(test)} ... {show_all_message}")
|
|
492
|
+
elif self.dots:
|
|
493
|
+
self.stream.write(dots_message)
|
|
494
|
+
self.stream.flush()
|
|
495
|
+
|
|
496
|
+
def addSuccess(self, test):
|
|
497
|
+
super(unittest.TextTestResult, self).addSuccess(test)
|
|
498
|
+
self._add_helper(test, ".", "ok")
|
|
499
|
+
|
|
500
|
+
def addError(self, test, err):
|
|
501
|
+
super(unittest.TextTestResult, self).addError(test, err)
|
|
502
|
+
self._add_helper(test, "E", "ERROR")
|
|
503
|
+
|
|
504
|
+
def addFailure(self, test, err):
|
|
505
|
+
super(unittest.TextTestResult, self).addFailure(test, err)
|
|
506
|
+
self._add_helper(test, "F", "FAIL")
|
|
507
|
+
|
|
508
|
+
def addSkip(self, test, reason):
|
|
509
|
+
super(unittest.TextTestResult, self).addSkip(test, reason)
|
|
510
|
+
self._add_helper(test, "s", f"skipped {reason!r}")
|
|
511
|
+
|
|
512
|
+
def addExpectedFailure(self, test, err):
|
|
513
|
+
super(unittest.TextTestResult, self).addExpectedFailure(test, err)
|
|
514
|
+
self._add_helper(test, "x", "expected failure")
|
|
515
|
+
|
|
516
|
+
def addUnexpectedSuccess(self, test):
|
|
517
|
+
super(unittest.TextTestResult, self).addUnexpectedSuccess(test)
|
|
518
|
+
self._add_helper(test, "u", "unexpected success")
|
|
519
|
+
|
|
520
|
+
def printErrors(self):
|
|
521
|
+
pass
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
def set_worker_cache(args, temp_dir):
|
|
525
|
+
"""Change the Warp cache to avoid conflicts.
|
|
526
|
+
This function is run at the start of every new process. (NVIDIA modification)
|
|
527
|
+
If the environment variable `WARP_CACHE_ROOT` is detected, the cache will be placed in the provided path.
|
|
528
|
+
"""
|
|
529
|
+
|
|
530
|
+
with _coverage(args, temp_dir):
|
|
531
|
+
import warp as wp
|
|
532
|
+
from warp.thirdparty import appdirs
|
|
533
|
+
|
|
534
|
+
pid = os.getpid()
|
|
535
|
+
|
|
536
|
+
if "WARP_CACHE_ROOT" in os.environ:
|
|
537
|
+
cache_root_dir = os.path.join(os.getenv("WARP_CACHE_ROOT"), f"{wp.config.version}-{pid}")
|
|
538
|
+
else:
|
|
539
|
+
cache_root_dir = appdirs.user_cache_dir(
|
|
540
|
+
appname="warp", appauthor="NVIDIA Corporation", version=f"{wp.config.version}-{pid}"
|
|
541
|
+
)
|
|
542
|
+
|
|
543
|
+
wp.config.kernel_cache_dir = cache_root_dir
|
|
544
|
+
|
|
545
|
+
wp.build.clear_kernel_cache()
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
if __name__ == "__main__": # pragma: no cover
|
|
549
|
+
main()
|