Repository: mit-ll-responsible-ai/hydra-zen

Issue:
`validates_with_beartype` considers `Partial` as `NoneType`
Hi @rsokl. I was having a blast using this fascinating library. But It seems when used with `hydra_zen.third_party.validates_with_beartype`, it casts `hydra_zen.typing.Partial` as `NoneType`. 


```python
from hydra_zen.typing import Partial
from hydra_zen.third_party.beartype import validates_with_beartype


def f(x: Partial[list]):
    return x


val_f = validates_with_beartype(f)

val_f(3)
```

It raises the following error. Can you take a look?

```bash
beartype.roar.BeartypeCallHintParamViolation: @beartyped __main__.f() 
parameter x=3 violates type hint None, as int 3 not instance of <class "builtins.NoneType">.
```

Discussion:

Patch:
diff --git a/.github/workflows/tox_run.yml b/.github/workflows/tox_run.yml
index fe7d517c..6d7f016b 100644
--- a/.github/workflows/tox_run.yml
+++ b/.github/workflows/tox_run.yml
@@ -91,10 +91,10 @@ jobs:
     runs-on: ubuntu-latest
     steps:
     - uses: actions/checkout@v3
-    - name: Set up Python 3.8
+    - name: Set up Python 3.9
       uses: actions/setup-python@v4
       with:
-        python-version: 3.8
+        python-version: 3.9
     - name: Install dependencies
       run: |
         python -m pip install --upgrade pip
diff --git a/docs/source/changes.rst b/docs/source/changes.rst
index 514ba78b..4429b863 100644
--- a/docs/source/changes.rst
+++ b/docs/source/changes.rst
@@ -11,7 +11,7 @@ chronological order. All previous releases should still be available on pip.
 .. _v0.9.0:
 
 ---------------------
-0.9.0rc4 - 2022-11-21
+0.9.0rc5 - 2022-12-09
 ---------------------
 
 .. note:: This is documentation for an unreleased version of hydra-zen. You can try out this pre-release version using `pip install --pre hydra-zen`
@@ -123,6 +123,10 @@ Improvements
 - :func:`~hydra_zen.hydrated_dataclass` will now produce a pickle-compatible dataclass type. See :pull:`338`.
 - All documentation code blocks are scanned by pyright as part of our CI process. Several errors in the documentation were fixed. See :pull:`343` and :pull:`344`.
 
+Bug Fixes
+---------
+- :pull:`355` fixes an issue where the parameterized generic `hydra_zen.typing.Partial[<...>]` would return `None` for Python versions 3.9+. This prevented this annotation from being used by runtime type checkers.
+
 Compatibility-Breaking Changes
 ------------------------------
 - Previously, any class decorated by :func:`~hydra_zen.hydrated_dataclass` would have a `__module__` attribute set to `typing`. Now the class's `__module__` will reflect the module where its static definition resides. This enables pickle-compatibility  (:pull:`338`). This is unlikely to cause any issues for users.
diff --git a/pyproject.toml b/pyproject.toml
index 99780bc3..784ab096 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -203,7 +203,7 @@ commands = pytest -n auto tests/test_docs_typecheck.py -vv
 
 [testenv:third-party]
 install_command = pip install --upgrade --upgrade-strategy eager {opts} {packages}
-basepython = python3.8
+basepython = python3.9
 deps = {[testenv]deps}
        torch
        pytorch-lightning
diff --git a/src/hydra_zen/typing/_implementations.py b/src/hydra_zen/typing/_implementations.py
index 33074239..eccfc154 100644
--- a/src/hydra_zen/typing/_implementations.py
+++ b/src/hydra_zen/typing/_implementations.py
@@ -108,7 +108,7 @@ class Partial(Protocol[T2]):
     ) -> Self:
         ...
 
-    if sys.version_info >= (3, 9):  # pragma: no cover
+    if TYPE_CHECKING and sys.version_info >= (3, 9):  # pragma: no cover
 
         def __class_getitem__(cls, item: Any) -> types.GenericAlias:
             ...


Test patch:
diff --git a/tests/test_protocols.py b/tests/test_protocols.py
index 35db0c2b..d29b570b 100644
--- a/tests/test_protocols.py
+++ b/tests/test_protocols.py
@@ -146,3 +146,8 @@ def test_protocol_checkers(x, yes_builds, yes_just, yes_partial):
 def test_partial_protocol():
     assert isinstance(partial(int), Partial)
     assert not isinstance(print, Partial)
+
+
+def test_parameterized_partial_regression():
+    # https://github.com/mit-ll-responsible-ai/hydra-zen/issues/352
+    assert Partial[int].__origin__ is Partial  # type: ignore
diff --git a/tests/test_py39.py b/tests/test_py39.py
index b2ad85eb..ff17efda 100644
--- a/tests/test_py39.py
+++ b/tests/test_py39.py
@@ -20,7 +20,8 @@ from hydra_zen.structured_configs._utils import sanitized_type
 )
 def test_sanitized_type_expected_behavior(in_type, expected_type):
     # tests collections-as-generics introduced in py39
-    assert sanitized_type(in_type) is expected_type
+    actual = sanitized_type(in_type)
+    assert actual is expected_type or actual == expected_type
 
     @dataclass
     class Tmp:
diff --git a/tests/test_third_party/test_using_beartype.py b/tests/test_third_party/test_using_beartype.py
index 94aec645..c8e2d6d5 100644
--- a/tests/test_third_party/test_using_beartype.py
+++ b/tests/test_third_party/test_using_beartype.py
@@ -1,12 +1,21 @@
 # Copyright (c) 2022 Massachusetts Institute of Technology
 # SPDX-License-Identifier: MIT
 
+from functools import partial
+from typing import Type
+
 import pytest
 from beartype.cave import RegexTypes
 from beartype.vale import Is
 from typing_extensions import Annotated
 
+from hydra_zen import builds
 from hydra_zen.third_party.beartype import validates_with_beartype
+from hydra_zen.typing import Builds, Partial
+
+
+def func(x: int) -> float:
+    ...
 
 
 @pytest.mark.parametrize(
@@ -14,6 +23,8 @@ from hydra_zen.third_party.beartype import validates_with_beartype
     [
         (RegexTypes, "abc+", 22),
         (Annotated[str, Is[lambda text: 2 == len(text)]], "hi", "bye"),
+        (Partial[float], partial(func), func),
+        (Builds[Type[float]], builds(func), func),
     ],
 )
 def test_beartype_specific_fields(custom_type, good_val, bad_val):