CI: linting check to ensure `lib.NoDefault` is only used for typing
- [x] See https://github.com/pandas-dev/pandas/pull/53877#issuecomment-1609917156
- [x] All [code checks passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit)
- [x] Added [type annotations](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#type-hints) to new arguments/methods/functions

In this PR, I added a pre-commit hook to check that `pandas._libs.lib.NoDefault` is used only for typing. This is invoked by #53877. Before that PR, this new hook correctly catches all misused `NoDefault`:

<details>
<p></p>

```
(pandas-dev) D:\>pre-commit run unwanted-patterns-nodefault-not-used-for-typing --all-files
Check for pandas._libs.lib.NoDefault not used for typing.......................Failed   
- hook id: unwanted-patterns-nodefault-not-used-for-typing
- exit code: 1

pandas/tests/reshape/test_pivot_multilevel.py:38:NoDefault is not used for typing       
pandas/tests/reshape/test_pivot_multilevel.py:75:NoDefault is not used for typing       
pandas/core/frame.py:8831:NoDefault is not used for typing
pandas/core/frame.py:8831:NoDefault is not used for typing
pandas/core/reshape/pivot.py:514:NoDefault is not used for typing
pandas/core/reshape/pivot.py:515:NoDefault is not used for typing
pandas/core/reshape/pivot.py:529:NoDefault is not used for typing
pandas/core/reshape/pivot.py:525:NoDefault is not used for typing
pandas/core/reshape/pivot.py:530:NoDefault is not used for typing
pandas/core/reshape/pivot.py:535:NoDefault is not used for typing
pandas/core/reshape/pivot.py:542:NoDefault is not used for typing
pandas/core/reshape/pivot.py:572:NoDefault is not used for typing
```

</details>

After that PR, the check passes normally:

<details>
<p></p>

```
(pandas-dev) D:\>pre-commit run unwanted-patterns-nodefault-not-used-for-typing --all-files
Check for pandas._libs.lib.NoDefault not used for typing.......................Passed
```

</details>

In fact I don't work with ASTs very often so not sure if this check covers all possibilties. Please let me know if any modification is needed. (The runtime is a bit long but seems acceptable, approximately 10s to check all files.)

nice idea

I think you're repeatedly walking up and down the same paths - do you want to check `scripts/no_bool_in_generic.py`? that one checks for annotations, maybe there's some logic there that can be reused? Improved from approx. 10s for all files to approx. 4s @MarcoGorelli Thanks for your suggestion! Well done!

Would appreciate it if we could add a tiny little test case to scripts/tests/test_validate_unwanted_patterns.py too

Other than that, looks good! Didn't notice that there are tests for linting scripts, thanks for the reminder @MarcoGorelli. Added some simple tests now. Nice thanks @Charlie-XIAO 