pyglove 0.5.0.dev202510080811__tar.gz → 0.5.0.dev202511030811__tar.gz
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 pyglove might be problematic. Click here for more details.
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/PKG-INFO +1 -1
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/geno/base.py +7 -3
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/monitoring.py +194 -93
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/monitoring_test.py +75 -35
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/base.py +70 -31
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/base_test.py +3 -3
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/dict.py +31 -12
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/dict_test.py +49 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/list.py +17 -3
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/list_test.py +24 -2
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/object.py +1 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/ref.py +19 -7
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/ref_test.py +94 -7
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/annotation_conversion.py +8 -1
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/annotation_conversion_test.py +14 -19
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/class_schema.py +24 -1
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/json_schema.py +221 -8
- pyglove-0.5.0.dev202511030811/pyglove/core/typing/json_schema_test.py +973 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/type_conversion.py +17 -3
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/type_conversion_test.py +1 -1
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/__init__.py +1 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/contextual.py +9 -4
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/contextual_test.py +10 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/json_conversion.py +255 -16
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/json_conversion_test.py +63 -4
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/views/html/controls/tab.py +33 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/views/html/controls/tab_test.py +37 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/evolution/base_test.py +1 -1
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove.egg-info/PKG-INFO +1 -1
- pyglove-0.5.0.dev202510080811/pyglove/core/typing/json_schema_test.py +0 -477
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/LICENSE +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/README.md +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/__init__.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/__init__.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/coding/__init__.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/coding/errors.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/coding/errors_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/coding/execution.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/coding/execution_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/coding/function_generation.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/coding/function_generation_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/coding/parsing.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/coding/parsing_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/coding/permissions.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/coding/permissions_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/detouring/__init__.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/detouring/class_detour.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/detouring/class_detour_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/geno/__init__.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/geno/base_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/geno/categorical.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/geno/categorical_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/geno/custom.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/geno/custom_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/geno/deduping.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/geno/deduping_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/geno/dna_generator.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/geno/dna_generator_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/geno/numerical.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/geno/numerical_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/geno/random.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/geno/random_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/geno/space.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/geno/space_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/geno/sweeping.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/geno/sweeping_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/hyper/__init__.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/hyper/base.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/hyper/categorical.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/hyper/categorical_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/hyper/custom.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/hyper/custom_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/hyper/derived.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/hyper/derived_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/hyper/dynamic_evaluation.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/hyper/dynamic_evaluation_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/hyper/evolvable.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/hyper/evolvable_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/hyper/iter.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/hyper/iter_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/hyper/numerical.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/hyper/numerical_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/hyper/object_template.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/hyper/object_template_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/io/__init__.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/io/file_system.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/io/file_system_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/io/sequence.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/io/sequence_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/logging.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/logging_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/patching/__init__.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/patching/object_factory.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/patching/object_factory_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/patching/pattern_based.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/patching/pattern_based_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/patching/rule_based.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/patching/rule_based_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/__init__.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/boilerplate.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/boilerplate_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/class_wrapper.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/class_wrapper_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/compounding.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/compounding_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/contextual_object.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/contextual_object_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/diff.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/diff_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/error_info.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/error_info_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/flags.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/flags_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/functor.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/functor_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/inferred.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/inferred_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/object_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/origin.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/origin_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/pure_symbolic.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/symbolize.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/symbolic/symbolize_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/tuning/__init__.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/tuning/backend.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/tuning/backend_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/tuning/early_stopping.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/tuning/local_backend.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/tuning/protocols.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/tuning/protocols_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/tuning/sample.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/tuning/sample_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/__init__.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/annotated.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/annotated_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/annotation_future_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/callable_ext.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/callable_ext_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/callable_signature.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/callable_signature_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/class_schema_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/custom_typing.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/inspect.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/inspect_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/key_specs.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/key_specs_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/pytype_support.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/typed_missing.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/typed_missing_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/value_specs.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/typing/value_specs_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/common_traits.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/common_traits_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/docstr_utils.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/docstr_utils_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/error_utils.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/error_utils_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/formatting.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/formatting_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/hierarchical.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/hierarchical_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/missing.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/missing_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/text_color.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/text_color_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/thread_local.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/thread_local_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/timing.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/timing_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/value_location.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/utils/value_location_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/views/__init__.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/views/base.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/views/base_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/views/html/__init__.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/views/html/base.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/views/html/base_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/views/html/controls/__init__.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/views/html/controls/base.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/views/html/controls/label.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/views/html/controls/label_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/views/html/controls/progress_bar.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/views/html/controls/progress_bar_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/views/html/controls/tooltip.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/views/html/controls/tooltip_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/views/html/tree_view.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/views/html/tree_view_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/__init__.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/early_stopping/__init__.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/early_stopping/base.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/early_stopping/base_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/early_stopping/step_wise.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/early_stopping/step_wise_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/evolution/__init__.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/evolution/base.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/evolution/hill_climb.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/evolution/hill_climb_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/evolution/mutators.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/evolution/mutators_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/evolution/neat.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/evolution/neat_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/evolution/nsga2.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/evolution/nsga2_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/evolution/recombinators.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/evolution/recombinators_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/evolution/regularized_evolution.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/evolution/regularized_evolution_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/evolution/selectors.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/evolution/selectors_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/evolution/where.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/evolution/where_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/mutfun/__init__.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/mutfun/base.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/mutfun/base_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/mutfun/basic_ops.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/mutfun/basic_ops_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/scalars/__init__.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/scalars/base.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/scalars/base_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/scalars/maths.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/scalars/maths_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/scalars/randoms.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/scalars/randoms_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/scalars/step_wise.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/ext/scalars/step_wise_test.py +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove.egg-info/SOURCES.txt +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove.egg-info/dependency_links.txt +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove.egg-info/requires.txt +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove.egg-info/top_level.txt +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/setup.cfg +0 -0
- {pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/setup.py +0 -0
|
@@ -1447,6 +1447,7 @@ class DNA(symbolic.Object):
|
|
|
1447
1447
|
*,
|
|
1448
1448
|
allow_partial: bool = False,
|
|
1449
1449
|
root_path: Optional[utils.KeyPath] = None,
|
|
1450
|
+
**kwargs,
|
|
1450
1451
|
) -> 'DNA':
|
|
1451
1452
|
"""Class method that load a DNA from a JSON value.
|
|
1452
1453
|
|
|
@@ -1454,6 +1455,7 @@ class DNA(symbolic.Object):
|
|
|
1454
1455
|
json_value: Input JSON value, only JSON dict is acceptable.
|
|
1455
1456
|
allow_partial: Whether to allow elements of the list to be partial.
|
|
1456
1457
|
root_path: KeyPath of loaded object in its object tree.
|
|
1458
|
+
**kwargs: Keyword arguments that will be passed to symbolic.from_json.
|
|
1457
1459
|
|
|
1458
1460
|
Returns:
|
|
1459
1461
|
A DNA object.
|
|
@@ -1463,16 +1465,18 @@ class DNA(symbolic.Object):
|
|
|
1463
1465
|
# NOTE(daiyip): DNA.parse will validate the input. Therefore, we can
|
|
1464
1466
|
# disable runtime type check during constructing the DNA objects.
|
|
1465
1467
|
with symbolic.enable_type_check(False):
|
|
1466
|
-
dna = DNA.parse(symbolic.from_json(json_value.get('value')))
|
|
1468
|
+
dna = DNA.parse(symbolic.from_json(json_value.get('value'), **kwargs))
|
|
1467
1469
|
if 'metadata' in json_value:
|
|
1468
1470
|
dna.rebind(
|
|
1469
|
-
metadata=symbolic.from_json(json_value.get('metadata')),
|
|
1471
|
+
metadata=symbolic.from_json(json_value.get('metadata'), **kwargs),
|
|
1470
1472
|
raise_on_no_change=False, skip_notification=True)
|
|
1471
1473
|
else:
|
|
1472
1474
|
dna = super(DNA, cls).from_json(
|
|
1473
1475
|
json_value,
|
|
1474
1476
|
allow_partial=allow_partial,
|
|
1475
|
-
root_path=root_path
|
|
1477
|
+
root_path=root_path,
|
|
1478
|
+
**kwargs,
|
|
1479
|
+
) # pytype: disable=bad-return-type
|
|
1476
1480
|
assert isinstance(dna, DNA)
|
|
1477
1481
|
if cloneable_metadata_keys:
|
|
1478
1482
|
dna._cloneable_metadata_keys = set(cloneable_metadata_keys) # pylint: disable=protected-access
|
|
@@ -14,7 +14,17 @@
|
|
|
14
14
|
"""Pluggable metric systems for monitoring.
|
|
15
15
|
|
|
16
16
|
This module allows PyGlove to plugin metrics to monitor the execution of
|
|
17
|
-
programs.
|
|
17
|
+
programs. There are three common metrics for monitoring: counters, scalars, and
|
|
18
|
+
distributions.
|
|
19
|
+
|
|
20
|
+
* Counters are metrics that track the number of times an event occurs. It's
|
|
21
|
+
monotonically increasing over time.
|
|
22
|
+
|
|
23
|
+
* Scalars are metrics that track a single value at a given time, for example,
|
|
24
|
+
available memory size. It does not accumulate over time like counters.
|
|
25
|
+
|
|
26
|
+
* Distributions are metrics that track the distribution of a numerical value.
|
|
27
|
+
For example, the latency of an operation.
|
|
18
28
|
"""
|
|
19
29
|
|
|
20
30
|
import abc
|
|
@@ -24,7 +34,7 @@ import math
|
|
|
24
34
|
import threading
|
|
25
35
|
import time
|
|
26
36
|
import typing
|
|
27
|
-
from typing import Any,
|
|
37
|
+
from typing import Any, Dict, Generic, Iterator, List, Optional, Tuple, Type, TypeVar, Union
|
|
28
38
|
from pyglove.core.utils import error_utils
|
|
29
39
|
|
|
30
40
|
try:
|
|
@@ -33,7 +43,10 @@ except ImportError:
|
|
|
33
43
|
numpy = None
|
|
34
44
|
|
|
35
45
|
|
|
36
|
-
|
|
46
|
+
MetricValueType = TypeVar('MetricValueType')
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class Metric(Generic[MetricValueType], metaclass=abc.ABCMeta):
|
|
37
50
|
"""Base class for metrics."""
|
|
38
51
|
|
|
39
52
|
def __init__(
|
|
@@ -41,12 +54,23 @@ class Metric(metaclass=abc.ABCMeta):
|
|
|
41
54
|
namespace: str,
|
|
42
55
|
name: str,
|
|
43
56
|
description: str,
|
|
44
|
-
parameter_definitions: Dict[str, Type[Union[int, str, bool]]]
|
|
57
|
+
parameter_definitions: Dict[str, Type[Union[int, str, bool]]],
|
|
58
|
+
**additional_flags,
|
|
45
59
|
) -> None:
|
|
60
|
+
"""Initializes the metric.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
namespace: The namespace of the metric.
|
|
64
|
+
name: The name of the metric.
|
|
65
|
+
description: The description of the metric.
|
|
66
|
+
parameter_definitions: The definitions of the parameters for the metric.
|
|
67
|
+
**additional_flags: Additional flags for the metric.
|
|
68
|
+
"""
|
|
46
69
|
self._namespace = namespace
|
|
47
70
|
self._name = name
|
|
48
71
|
self._description = description
|
|
49
72
|
self._parameter_definitions = parameter_definitions
|
|
73
|
+
self._flags = additional_flags
|
|
50
74
|
|
|
51
75
|
@property
|
|
52
76
|
def namespace(self) -> str:
|
|
@@ -73,6 +97,11 @@ class Metric(metaclass=abc.ABCMeta):
|
|
|
73
97
|
"""Returns the parameter definitions of the metric."""
|
|
74
98
|
return self._parameter_definitions
|
|
75
99
|
|
|
100
|
+
@property
|
|
101
|
+
def flags(self) -> Dict[str, Any]:
|
|
102
|
+
"""Returns the flags of the metric."""
|
|
103
|
+
return self._flags
|
|
104
|
+
|
|
76
105
|
def _parameters_key(self, **parameters) -> Tuple[Any, ...]:
|
|
77
106
|
"""Returns the parameters tuple for the metric."""
|
|
78
107
|
for k, t in self._parameter_definitions.items():
|
|
@@ -96,9 +125,24 @@ class Metric(metaclass=abc.ABCMeta):
|
|
|
96
125
|
)
|
|
97
126
|
return tuple(parameters[k] for k in self._parameter_definitions)
|
|
98
127
|
|
|
128
|
+
@abc.abstractmethod
|
|
129
|
+
def value(self, **parameters) -> MetricValueType:
|
|
130
|
+
"""Returns the value of the metric for the given parameters.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
**parameters: Parameters for parameterized counters.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
The value of the metric.
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class Counter(Metric[int]):
|
|
141
|
+
"""Base class for counters.
|
|
99
142
|
|
|
100
|
-
|
|
101
|
-
|
|
143
|
+
Counters are metrics that track the number of times an event occurs. It's
|
|
144
|
+
monotonically increasing over time.
|
|
145
|
+
"""
|
|
102
146
|
|
|
103
147
|
@abc.abstractmethod
|
|
104
148
|
def increment(self, delta: int = 1, **parameters) -> int:
|
|
@@ -112,20 +156,42 @@ class Counter(Metric):
|
|
|
112
156
|
The new value of the counter.
|
|
113
157
|
"""
|
|
114
158
|
|
|
159
|
+
|
|
160
|
+
class Scalar(Metric[MetricValueType]):
|
|
161
|
+
"""Base class for scalar values.
|
|
162
|
+
|
|
163
|
+
Scalar values are metrics that track a single value at a given time, for
|
|
164
|
+
example, available memory size. It does not accumulate over time like
|
|
165
|
+
counters.
|
|
166
|
+
"""
|
|
167
|
+
|
|
115
168
|
@abc.abstractmethod
|
|
116
|
-
def
|
|
117
|
-
"""
|
|
169
|
+
def set(self, value: MetricValueType, **parameters) -> None:
|
|
170
|
+
"""Sets the value of the scalar.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
value: The value to record.
|
|
174
|
+
**parameters: Parameters for parameterized scalars.
|
|
175
|
+
"""
|
|
176
|
+
|
|
177
|
+
@abc.abstractmethod
|
|
178
|
+
def increment(
|
|
179
|
+
self,
|
|
180
|
+
delta: MetricValueType = 1, **parameters
|
|
181
|
+
) -> MetricValueType:
|
|
182
|
+
"""Increments the scalar by delta and returns the new value.
|
|
118
183
|
|
|
119
184
|
Args:
|
|
185
|
+
delta: The amount to increment the counter by.
|
|
120
186
|
**parameters: Parameters for parameterized counters.
|
|
121
187
|
|
|
122
188
|
Returns:
|
|
123
|
-
The value of the
|
|
189
|
+
The new value of the metric.
|
|
124
190
|
"""
|
|
125
191
|
|
|
126
192
|
|
|
127
|
-
class
|
|
128
|
-
"""
|
|
193
|
+
class DistributionValue(metaclass=abc.ABCMeta):
|
|
194
|
+
"""Base for distribution value."""
|
|
129
195
|
|
|
130
196
|
@property
|
|
131
197
|
@abc.abstractmethod
|
|
@@ -173,27 +239,20 @@ class Distribution(metaclass=abc.ABCMeta):
|
|
|
173
239
|
"""Returns the fraction of values in the distribution less than value."""
|
|
174
240
|
|
|
175
241
|
|
|
176
|
-
class
|
|
177
|
-
"""Base class for
|
|
242
|
+
class Distribution(Metric[DistributionValue]):
|
|
243
|
+
"""Base class for distributional metrics.
|
|
178
244
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
Args:
|
|
184
|
-
value: The value to record.
|
|
185
|
-
**parameters: Parameters for parameterized scalars.
|
|
186
|
-
"""
|
|
245
|
+
Distributions are metrics that track the distribution of a numerical value.
|
|
246
|
+
For example, the latency of an operation.
|
|
247
|
+
"""
|
|
187
248
|
|
|
188
249
|
@abc.abstractmethod
|
|
189
|
-
def
|
|
190
|
-
"""
|
|
250
|
+
def record(self, value: float, **parameters) -> None:
|
|
251
|
+
"""Records a value to the distribution.
|
|
191
252
|
|
|
192
253
|
Args:
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
Returns:
|
|
196
|
-
The distribution of the scalar.
|
|
254
|
+
value: The value to record.
|
|
255
|
+
**parameters: Parameters for parameterized distributions.
|
|
197
256
|
"""
|
|
198
257
|
|
|
199
258
|
@contextlib.contextmanager
|
|
@@ -203,14 +262,14 @@ class Scalar(Metric):
|
|
|
203
262
|
scale: int = 1000,
|
|
204
263
|
error_parameter: str = 'error',
|
|
205
264
|
**parameters) -> Iterator[None]:
|
|
206
|
-
"""Context manager that records the duration of code block
|
|
265
|
+
"""Context manager that records the duration of code block.
|
|
207
266
|
|
|
208
267
|
Args:
|
|
209
268
|
scale: The scale of the duration.
|
|
210
269
|
error_parameter: The parameter name for recording the error. If the name
|
|
211
|
-
is not defined as a parameter for the
|
|
212
|
-
recorded.
|
|
213
|
-
**parameters: Parameters for parameterized
|
|
270
|
+
is not defined as a parameter for the distribution, the error tag will
|
|
271
|
+
not be recorded.
|
|
272
|
+
**parameters: Parameters for parameterized distributions.
|
|
214
273
|
"""
|
|
215
274
|
start_time = time.time()
|
|
216
275
|
error = None
|
|
@@ -226,12 +285,16 @@ class Scalar(Metric):
|
|
|
226
285
|
error_utils.ErrorInfo.from_exception(error).tag
|
|
227
286
|
if error is not None else ''
|
|
228
287
|
)
|
|
229
|
-
self.record(
|
|
288
|
+
self.record(duration, **parameters)
|
|
230
289
|
|
|
231
290
|
|
|
232
291
|
class MetricCollection(metaclass=abc.ABCMeta):
|
|
233
292
|
"""Base class for counter collections."""
|
|
234
293
|
|
|
294
|
+
_COUNTER_CLASS = Counter
|
|
295
|
+
_SCALAR_CLASS = Scalar
|
|
296
|
+
_DISTRIBUTION_CLASS = Distribution
|
|
297
|
+
|
|
235
298
|
def __init__(
|
|
236
299
|
self,
|
|
237
300
|
namespace: str,
|
|
@@ -266,13 +329,10 @@ class MetricCollection(metaclass=abc.ABCMeta):
|
|
|
266
329
|
def _get_or_create_metric(
|
|
267
330
|
self,
|
|
268
331
|
metric_cls: Type[Metric],
|
|
269
|
-
create_metric_fn: Callable[
|
|
270
|
-
[str, str, Dict[str, Type[Union[int, str, bool]]]],
|
|
271
|
-
Metric
|
|
272
|
-
],
|
|
273
332
|
name: str,
|
|
274
333
|
description: str,
|
|
275
|
-
parameter_definitions: Dict[str, Type[Union[int, str, bool]]]
|
|
334
|
+
parameter_definitions: Dict[str, Type[Union[int, str, bool]]],
|
|
335
|
+
**additional_flags,
|
|
276
336
|
) -> Metric:
|
|
277
337
|
"""Gets or creates a metric with the given name."""
|
|
278
338
|
full_name = f'{self._namespace}/{name}'
|
|
@@ -294,7 +354,13 @@ class MetricCollection(metaclass=abc.ABCMeta):
|
|
|
294
354
|
f'definitions ({metric.parameter_definitions!r}).'
|
|
295
355
|
)
|
|
296
356
|
else:
|
|
297
|
-
metric =
|
|
357
|
+
metric = metric_cls(
|
|
358
|
+
self.namespace,
|
|
359
|
+
name,
|
|
360
|
+
description,
|
|
361
|
+
parameter_definitions,
|
|
362
|
+
**additional_flags
|
|
363
|
+
)
|
|
298
364
|
self._metrics[full_name] = metric
|
|
299
365
|
return metric
|
|
300
366
|
|
|
@@ -303,7 +369,7 @@ class MetricCollection(metaclass=abc.ABCMeta):
|
|
|
303
369
|
name: str,
|
|
304
370
|
description: str,
|
|
305
371
|
parameters: Optional[Dict[str, Type[Union[int, str, bool]]]] = None,
|
|
306
|
-
**
|
|
372
|
+
**additional_flags
|
|
307
373
|
) -> Counter:
|
|
308
374
|
"""Gets or creates a counter with the given name.
|
|
309
375
|
|
|
@@ -312,7 +378,9 @@ class MetricCollection(metaclass=abc.ABCMeta):
|
|
|
312
378
|
description: The description of the counter.
|
|
313
379
|
parameters: The definitions of the parameters for the counter.
|
|
314
380
|
`default_parameters` from the collection will be used if not specified.
|
|
315
|
-
**
|
|
381
|
+
**additional_flags: Additional arguments for creating the counter.
|
|
382
|
+
Subclasses can use these arguments to provide additional information for
|
|
383
|
+
creating the counter.
|
|
316
384
|
|
|
317
385
|
Returns:
|
|
318
386
|
The counter with the given name.
|
|
@@ -320,28 +388,23 @@ class MetricCollection(metaclass=abc.ABCMeta):
|
|
|
320
388
|
if parameters is None:
|
|
321
389
|
parameters = self._default_parameter_definitions
|
|
322
390
|
return typing.cast(
|
|
323
|
-
Counter,
|
|
324
|
-
|
|
325
|
-
|
|
391
|
+
Counter,
|
|
392
|
+
self._get_or_create_metric(
|
|
393
|
+
self._COUNTER_CLASS,
|
|
394
|
+
name,
|
|
395
|
+
description,
|
|
396
|
+
parameters,
|
|
397
|
+
**additional_flags
|
|
326
398
|
)
|
|
327
399
|
)
|
|
328
400
|
|
|
329
|
-
@abc.abstractmethod
|
|
330
|
-
def _create_counter(
|
|
331
|
-
self,
|
|
332
|
-
name: str,
|
|
333
|
-
description: str,
|
|
334
|
-
parameter_definitions: Dict[str, Type[Union[int, str, bool]]],
|
|
335
|
-
**kwargs
|
|
336
|
-
) -> Counter:
|
|
337
|
-
"""Creates a counter with the given name."""
|
|
338
|
-
|
|
339
401
|
def get_scalar(
|
|
340
402
|
self,
|
|
341
403
|
name: str,
|
|
342
404
|
description: str,
|
|
343
405
|
parameters: Optional[Dict[str, Type[Union[int, str, bool]]]] = None,
|
|
344
|
-
|
|
406
|
+
value_type: Type[Union[int, float]] = int,
|
|
407
|
+
**additional_flags
|
|
345
408
|
) -> Scalar:
|
|
346
409
|
"""Gets or creates a scalar with the given name.
|
|
347
410
|
|
|
@@ -350,7 +413,8 @@ class MetricCollection(metaclass=abc.ABCMeta):
|
|
|
350
413
|
description: The description of the counter.
|
|
351
414
|
parameters: The definitions of the parameters for the counter.
|
|
352
415
|
`default_parameters` from the collection will be used if not specified.
|
|
353
|
-
|
|
416
|
+
value_type: The type of the value for the scalar.
|
|
417
|
+
**additional_flags: Additional arguments for creating the scalar.
|
|
354
418
|
|
|
355
419
|
Returns:
|
|
356
420
|
The counter with the given name.
|
|
@@ -360,19 +424,46 @@ class MetricCollection(metaclass=abc.ABCMeta):
|
|
|
360
424
|
return typing.cast(
|
|
361
425
|
Scalar,
|
|
362
426
|
self._get_or_create_metric(
|
|
363
|
-
|
|
427
|
+
self._SCALAR_CLASS,
|
|
428
|
+
name,
|
|
429
|
+
description,
|
|
430
|
+
parameters,
|
|
431
|
+
value_type=value_type,
|
|
432
|
+
**additional_flags
|
|
364
433
|
)
|
|
365
434
|
)
|
|
366
435
|
|
|
367
|
-
|
|
368
|
-
def _create_scalar(
|
|
436
|
+
def get_distribution(
|
|
369
437
|
self,
|
|
370
438
|
name: str,
|
|
371
439
|
description: str,
|
|
372
|
-
|
|
373
|
-
**
|
|
374
|
-
) ->
|
|
375
|
-
"""
|
|
440
|
+
parameters: Optional[Dict[str, Type[Union[int, str, bool]]]] = None,
|
|
441
|
+
**additional_flags
|
|
442
|
+
) -> Distribution:
|
|
443
|
+
"""Gets or creates a distribution with the given name.
|
|
444
|
+
|
|
445
|
+
Args:
|
|
446
|
+
name: The name of the distribution.
|
|
447
|
+
description: The description of the distribution.
|
|
448
|
+
parameters: The definitions of the parameters for the distribution.
|
|
449
|
+
`default_parameters` from the collection will be used if not specified.
|
|
450
|
+
**additional_flags: Additional arguments for creating the distribution.
|
|
451
|
+
|
|
452
|
+
Returns:
|
|
453
|
+
The distribution with the given name.
|
|
454
|
+
"""
|
|
455
|
+
if parameters is None:
|
|
456
|
+
parameters = self._default_parameter_definitions
|
|
457
|
+
return typing.cast(
|
|
458
|
+
Distribution,
|
|
459
|
+
self._get_or_create_metric(
|
|
460
|
+
self._DISTRIBUTION_CLASS,
|
|
461
|
+
name,
|
|
462
|
+
description,
|
|
463
|
+
parameters,
|
|
464
|
+
**additional_flags
|
|
465
|
+
)
|
|
466
|
+
)
|
|
376
467
|
|
|
377
468
|
#
|
|
378
469
|
# InMemoryMetricCollection.
|
|
@@ -401,14 +492,46 @@ class _InMemoryCounter(Counter):
|
|
|
401
492
|
return self._counter[self._parameters_key(**parameters)]
|
|
402
493
|
|
|
403
494
|
|
|
404
|
-
class _InMemoryScalar(Scalar):
|
|
495
|
+
class _InMemoryScalar(Scalar[MetricValueType]):
|
|
405
496
|
"""In-memory scalar."""
|
|
406
497
|
|
|
498
|
+
def __init__(self, *args, **kwargs):
|
|
499
|
+
super().__init__(*args, **kwargs)
|
|
500
|
+
self._values = collections.defaultdict(self.flags['value_type'])
|
|
501
|
+
self._lock = threading.Lock()
|
|
502
|
+
|
|
503
|
+
def increment(
|
|
504
|
+
self,
|
|
505
|
+
delta: MetricValueType = 1,
|
|
506
|
+
**parameters
|
|
507
|
+
) -> MetricValueType:
|
|
508
|
+
"""Increments the scalar by delta and returns the new value."""
|
|
509
|
+
parameters_key = self._parameters_key(**parameters)
|
|
510
|
+
with self._lock:
|
|
511
|
+
value = self._values[parameters_key]
|
|
512
|
+
value += delta
|
|
513
|
+
self._values[parameters_key] = value
|
|
514
|
+
return value
|
|
515
|
+
|
|
516
|
+
def set(self, value: MetricValueType, **parameters) -> None:
|
|
517
|
+
"""Sets the value of the scalar."""
|
|
518
|
+
parameters_key = self._parameters_key(**parameters)
|
|
519
|
+
with self._lock:
|
|
520
|
+
self._values[parameters_key] = value
|
|
521
|
+
|
|
522
|
+
def value(self, **parameters) -> MetricValueType:
|
|
523
|
+
"""Returns the distribution of the scalar."""
|
|
524
|
+
return self._values[self._parameters_key(**parameters)]
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
class _InMemoryDistribution(Distribution):
|
|
528
|
+
"""In-memory distribution."""
|
|
529
|
+
|
|
407
530
|
def __init__(self, *args, window_size: int = 1024 * 1024, **kwargs):
|
|
408
531
|
super().__init__(*args, **kwargs)
|
|
409
532
|
self._window_size = window_size
|
|
410
533
|
self._distributions = collections.defaultdict(
|
|
411
|
-
lambda:
|
|
534
|
+
lambda: _InMemoryDistributionValue(self._window_size)
|
|
412
535
|
)
|
|
413
536
|
self._lock = threading.Lock()
|
|
414
537
|
|
|
@@ -417,14 +540,13 @@ class _InMemoryScalar(Scalar):
|
|
|
417
540
|
parameters_key = self._parameters_key(**parameters)
|
|
418
541
|
self._distributions[parameters_key].add(value)
|
|
419
542
|
|
|
420
|
-
def
|
|
543
|
+
def value(self, **parameters) -> DistributionValue:
|
|
421
544
|
"""Returns the distribution of the scalar."""
|
|
422
|
-
|
|
423
|
-
return self._distributions[parameters_key]
|
|
545
|
+
return self._distributions[self._parameters_key(**parameters)]
|
|
424
546
|
|
|
425
547
|
|
|
426
|
-
class
|
|
427
|
-
"""In memory distribution
|
|
548
|
+
class _InMemoryDistributionValue(DistributionValue):
|
|
549
|
+
"""In memory distribution value."""
|
|
428
550
|
|
|
429
551
|
def __init__(self, window_size: int = 1024 * 1024):
|
|
430
552
|
self._window_size = window_size
|
|
@@ -511,30 +633,9 @@ class _InMemoryDistribution(Distribution):
|
|
|
511
633
|
class InMemoryMetricCollection(MetricCollection):
|
|
512
634
|
"""In-memory counter."""
|
|
513
635
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
description: str,
|
|
518
|
-
parameter_definitions: Dict[str, Type[Union[int, str, bool]]],
|
|
519
|
-
**kwargs
|
|
520
|
-
) -> Counter:
|
|
521
|
-
return _InMemoryCounter(
|
|
522
|
-
self._namespace, name, description, parameter_definitions
|
|
523
|
-
)
|
|
524
|
-
|
|
525
|
-
def _create_scalar(
|
|
526
|
-
self,
|
|
527
|
-
name: str,
|
|
528
|
-
description: str,
|
|
529
|
-
parameter_definitions: Dict[str, Type[Union[int, str, bool]]],
|
|
530
|
-
*,
|
|
531
|
-
window_size: int = 1024 * 1024,
|
|
532
|
-
**kwargs
|
|
533
|
-
) -> Scalar:
|
|
534
|
-
return _InMemoryScalar(
|
|
535
|
-
self._namespace, name, description, parameter_definitions,
|
|
536
|
-
window_size=window_size, **kwargs
|
|
537
|
-
)
|
|
636
|
+
_COUNTER_CLASS = _InMemoryCounter
|
|
637
|
+
_SCALAR_CLASS = _InMemoryScalar
|
|
638
|
+
_DISTRIBUTION_CLASS = _InMemoryDistribution
|
|
538
639
|
|
|
539
640
|
|
|
540
641
|
_METRIC_COLLECTION_CLS = InMemoryMetricCollection # pylint: disable=invalid-name
|
{pyglove-0.5.0.dev202510080811 → pyglove-0.5.0.dev202511030811}/pyglove/core/monitoring_test.py
RENAMED
|
@@ -55,7 +55,7 @@ class MetricCollectionTest(unittest.TestCase):
|
|
|
55
55
|
with self.assertRaisesRegex(
|
|
56
56
|
ValueError, 'Metric .* already exists with a different type'
|
|
57
57
|
):
|
|
58
|
-
collection.
|
|
58
|
+
collection.get_distribution('counter', 'counter description')
|
|
59
59
|
|
|
60
60
|
with self.assertRaisesRegex(
|
|
61
61
|
ValueError, 'Metric .* already exists with a different description'
|
|
@@ -71,11 +71,11 @@ class MetricCollectionTest(unittest.TestCase):
|
|
|
71
71
|
)
|
|
72
72
|
|
|
73
73
|
|
|
74
|
-
class
|
|
75
|
-
"""Tests for in memory distribution."""
|
|
74
|
+
class InMemoryDistributionValueTest(unittest.TestCase):
|
|
75
|
+
"""Tests for in memory distribution value."""
|
|
76
76
|
|
|
77
77
|
def test_empty_distribution(self):
|
|
78
|
-
dist = monitoring.
|
|
78
|
+
dist = monitoring._InMemoryDistributionValue()
|
|
79
79
|
self.assertEqual(dist.count, 0)
|
|
80
80
|
self.assertEqual(dist.sum, 0.0)
|
|
81
81
|
self.assertEqual(dist.mean, 0.0)
|
|
@@ -86,7 +86,7 @@ class InMemoryDistributionTest(unittest.TestCase):
|
|
|
86
86
|
self.assertEqual(dist.fraction_less_than(100), 0.0)
|
|
87
87
|
|
|
88
88
|
def test_add_value(self):
|
|
89
|
-
dist = monitoring.
|
|
89
|
+
dist = monitoring._InMemoryDistributionValue()
|
|
90
90
|
dist.add(1)
|
|
91
91
|
dist.add(3)
|
|
92
92
|
dist.add(10)
|
|
@@ -106,7 +106,7 @@ class InMemoryDistributionTest(unittest.TestCase):
|
|
|
106
106
|
def test_add_value_no_numpy(self):
|
|
107
107
|
numpy = monitoring.numpy
|
|
108
108
|
monitoring.numpy = None
|
|
109
|
-
dist = monitoring.
|
|
109
|
+
dist = monitoring._InMemoryDistributionValue()
|
|
110
110
|
dist.add(1)
|
|
111
111
|
dist.add(3)
|
|
112
112
|
dist.add(10)
|
|
@@ -125,7 +125,7 @@ class InMemoryDistributionTest(unittest.TestCase):
|
|
|
125
125
|
monitoring.numpy = numpy
|
|
126
126
|
|
|
127
127
|
def test_window_size(self):
|
|
128
|
-
dist = monitoring.
|
|
128
|
+
dist = monitoring._InMemoryDistributionValue(window_size=3)
|
|
129
129
|
dist.add(1)
|
|
130
130
|
dist.add(3)
|
|
131
131
|
dist.add(10)
|
|
@@ -199,50 +199,90 @@ class InMemoryScalarTest(unittest.TestCase):
|
|
|
199
199
|
self.assertEqual(scalar.description, 'scalar description')
|
|
200
200
|
self.assertEqual(scalar.parameter_definitions, {})
|
|
201
201
|
self.assertEqual(scalar.full_name, '/test/scalar')
|
|
202
|
-
|
|
203
|
-
self.assertEqual(
|
|
204
|
-
scalar.
|
|
205
|
-
scalar.
|
|
206
|
-
scalar.
|
|
207
|
-
scalar.
|
|
208
|
-
self.assertEqual(dist.count, 3)
|
|
209
|
-
|
|
210
|
-
scalar = collection.get_scalar('scalar2', 'scalar description')
|
|
211
|
-
with scalar.record_duration():
|
|
212
|
-
time.sleep(0.1)
|
|
213
|
-
self.assertGreaterEqual(scalar.distribution().mean, 100)
|
|
202
|
+
self.assertEqual(scalar.value(), 0)
|
|
203
|
+
self.assertEqual(scalar.increment(), 1)
|
|
204
|
+
self.assertEqual(scalar.value(), 1)
|
|
205
|
+
scalar.set(3)
|
|
206
|
+
self.assertEqual(scalar.increment(2), 5)
|
|
207
|
+
self.assertEqual(scalar.value(), 5)
|
|
214
208
|
|
|
215
209
|
def test_scalar_with_parameters(self):
|
|
216
210
|
collection = monitoring.InMemoryMetricCollection('/test')
|
|
217
211
|
scalar = collection.get_scalar(
|
|
218
|
-
'scalar', 'scalar description', {'field1': str}
|
|
212
|
+
'scalar', 'scalar description', {'field1': str}, float
|
|
219
213
|
)
|
|
220
214
|
self.assertEqual(scalar.namespace, '/test')
|
|
221
215
|
self.assertEqual(scalar.name, 'scalar')
|
|
222
216
|
self.assertEqual(scalar.description, 'scalar description')
|
|
223
217
|
self.assertEqual(scalar.parameter_definitions, {'field1': str})
|
|
224
218
|
self.assertEqual(scalar.full_name, '/test/scalar')
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
scalar.
|
|
228
|
-
scalar.
|
|
229
|
-
scalar.
|
|
230
|
-
|
|
231
|
-
self.assertEqual(dist.count, 2)
|
|
232
|
-
dist = scalar.distribution(field1='bar')
|
|
233
|
-
self.assertEqual(dist.count, 1)
|
|
219
|
+
self.assertEqual(scalar.value(field1='foo'), 0.0)
|
|
220
|
+
scalar.set(2.5, field1='bar')
|
|
221
|
+
self.assertEqual(scalar.value(field1='bar'), 2.5)
|
|
222
|
+
self.assertEqual(scalar.increment(1.1, field1='bar'), 3.6)
|
|
223
|
+
self.assertEqual(scalar.value(field1='bar'), 3.6)
|
|
224
|
+
self.assertEqual(scalar.value(field1='foo'), 0.0)
|
|
234
225
|
|
|
235
|
-
|
|
236
|
-
|
|
226
|
+
|
|
227
|
+
class InMemoryDistributionTest(unittest.TestCase):
|
|
228
|
+
"""Tests for in memory distribution."""
|
|
229
|
+
|
|
230
|
+
def test_distribution_without_parameters(self):
|
|
231
|
+
collection = monitoring.InMemoryMetricCollection('/test')
|
|
232
|
+
dist = collection.get_distribution(
|
|
233
|
+
'distribution', 'distribution description'
|
|
234
|
+
)
|
|
235
|
+
self.assertEqual(dist.namespace, '/test')
|
|
236
|
+
self.assertEqual(dist.name, 'distribution')
|
|
237
|
+
self.assertEqual(dist.description, 'distribution description')
|
|
238
|
+
self.assertEqual(dist.parameter_definitions, {})
|
|
239
|
+
self.assertEqual(dist.full_name, '/test/distribution')
|
|
240
|
+
v = dist.value()
|
|
241
|
+
self.assertEqual(v.count, 0)
|
|
242
|
+
dist.record(1)
|
|
243
|
+
dist.record(2)
|
|
244
|
+
dist.record(3)
|
|
245
|
+
v = dist.value()
|
|
246
|
+
self.assertEqual(v.count, 3)
|
|
247
|
+
|
|
248
|
+
dist = collection.get_distribution(
|
|
249
|
+
'distribution2', 'distribution description'
|
|
250
|
+
)
|
|
251
|
+
with dist.record_duration():
|
|
252
|
+
time.sleep(0.1)
|
|
253
|
+
self.assertGreaterEqual(dist.value().mean, 100)
|
|
254
|
+
|
|
255
|
+
def test_distribution_with_parameters(self):
|
|
256
|
+
collection = monitoring.InMemoryMetricCollection('/test')
|
|
257
|
+
dist = collection.get_distribution(
|
|
258
|
+
'distribution', 'distribution description', {'field1': str}
|
|
259
|
+
)
|
|
260
|
+
self.assertEqual(dist.namespace, '/test')
|
|
261
|
+
self.assertEqual(dist.name, 'distribution')
|
|
262
|
+
self.assertEqual(dist.description, 'distribution description')
|
|
263
|
+
self.assertEqual(dist.parameter_definitions, {'field1': str})
|
|
264
|
+
self.assertEqual(dist.full_name, '/test/distribution')
|
|
265
|
+
value = dist.value(field1='foo')
|
|
266
|
+
self.assertEqual(value.count, 0)
|
|
267
|
+
dist.record(1, field1='foo')
|
|
268
|
+
dist.record(2, field1='foo')
|
|
269
|
+
dist.record(3, field1='bar')
|
|
270
|
+
value = dist.value(field1='foo')
|
|
271
|
+
self.assertEqual(value.count, 2)
|
|
272
|
+
value = dist.value(field1='bar')
|
|
273
|
+
self.assertEqual(value.count, 1)
|
|
274
|
+
|
|
275
|
+
dist = collection.get_distribution(
|
|
276
|
+
'distribution2', 'distribution description', {'error': str}
|
|
237
277
|
)
|
|
238
278
|
with self.assertRaises(ValueError):
|
|
239
|
-
with
|
|
279
|
+
with dist.record_duration():
|
|
240
280
|
time.sleep(0.1)
|
|
241
281
|
raise ValueError()
|
|
242
|
-
self.assertGreaterEqual(
|
|
243
|
-
with
|
|
282
|
+
self.assertGreaterEqual(dist.value(error='ValueError').mean, 100)
|
|
283
|
+
with dist.record_duration():
|
|
244
284
|
time.sleep(0.1)
|
|
245
|
-
self.assertGreaterEqual(
|
|
285
|
+
self.assertGreaterEqual(dist.value(error='').mean, 100)
|
|
246
286
|
|
|
247
287
|
|
|
248
288
|
if __name__ == '__main__':
|