Repository: optuna/optuna

Issue:
Use function annotation syntax for Type Hints.
After dropping Python 2.7 support at #710, we can define type hints with function annotation syntax. 
~~Do you have a plan to update the coding style guideline?~~
https://github.com/optuna/optuna/wiki/Coding-Style-Conventions

## Progress

- [x] `optuna/integration/sklearn.py` (#1735)
- [x] `optuna/study.py` - assigned to harpy

## Note to the questioner

We still cannot use variable annotation syntax introduced by [PEP 526](https://www.python.org/dev/peps/pep-0526/) because we supports Python 3.5.


Discussion:
Thanks for bringing this up. There is a tracking issue now so let me just leave a reference. https://github.com/optuna/optuna/issues/713. I believe you are correct in that the coding style guideline should be updated. 
@c-bata 
List of files grepped by `# type:`.

- [x] setup
- [ ] optuna/visualization/parallel_coordinate
- [ ] optuna/visualization/slice
- [ ] optuna/visualization/intermediate_values
- [ ] optuna/visualization/optimization_history
- [ ] optuna/visualization/utils
- [ ] optuna/visualization/contour
- [ ] optuna/logging
- [ ] optuna/storages/rdb/models
- [ ] optuna/storages/rdb/storage
- [ ] optuna/storages/__init__
- [ ] optuna/storages/base
- [ ] optuna/storages/in_memory
- [ ] optuna/trial
- [ ] optuna/pruners/hyperband
- [ ] optuna/pruners/successive_halving
- [ ] optuna/pruners/nop
- [ ] optuna/pruners/median
- [ ] optuna/pruners/base
- [ ] optuna/pruners/percentile
- [ ] optuna/integration/cma
- [ ] optuna/integration/lightgbm
- [ ] optuna/integration/mxnet
- [ ] optuna/integration/chainermn
- [ ] optuna/integration/lightgbm_tuner/optimize
- [ ] optuna/integration/lightgbm_tuner/alias
- [ ] optuna/integration/lightgbm_tuner/__init__
- [ ] optuna/integration/lightgbm_tuner/sklearn
- [ ] optuna/integration/fastai
- [ ] optuna/integration/keras
- [ ] optuna/integration/__init__
- [ ] optuna/integration/pytorch_ignite
- [ ] optuna/integration/tensorflow
- [ ] optuna/integration/skopt
- [ ] optuna/integration/pytorch_lightning
- [ ] optuna/integration/xgboost
- [ ] optuna/integration/sklearn
- [ ] tests/pruners_tests/test_percentile
- [ ] tests/pruners_tests/test_median
- [ ] tests/pruners_tests/test_successive_halving
- [ ] tests/pruners_tests/test_nop
- [ ] tests/pruners_tests/test_hyperband
- [ ] tests/test_logging
- [ ] tests/integration_tests/test_skopt
- [ ] tests/integration_tests/test_pytorch_lightning
- [ ] tests/integration_tests/test_cma
- [ ] tests/integration_tests/test_lightgbm
- [ ] tests/integration_tests/test_chainermn
- [ ] tests/integration_tests/lightgbm_tuner_tests/test_optimize
- [ ] tests/integration_tests/lightgbm_tuner_tests/test_alias
- [ ] tests/integration_tests/test_pytorch_ignite
- [ ] tests/integration_tests/test_tensorflow
- [ ] tests/integration_tests/test_keras
- [ ] tests/integration_tests/test_mxnet
- [ ] tests/integration_tests/test_fastai
- [ ] tests/integration_tests/test_chainer
- [ ] tests/integration_tests/test_tfkeras
- [ ] tests/integration_tests/test_integration
- [ ] tests/integration_tests/test_xgboost
- [ ] tests/integration_tests/test_sklearn
- [ ] tests/integration_tests/test_sampler
- [ ] tests/test_dashboard
- [ ] tests/test_study
- [ ] tests/storages_tests/test_in_memory
- [ ] tests/storages_tests/test_storages
- [ ] tests/storages_tests/rdb_tests/test_storage
- [ ] tests/storages_tests/rdb_tests/test_models
- [ ] tests/samplers_tests/tpe_tests/test_parzen_estimator
- [ ] tests/samplers_tests/tpe_tests/test_sampler
- [ ] tests/samplers_tests/test_samplers
- [ ] tests/test_trial
- [ ] tests/test_structs
- [ ] tests/test_distributions
- [ ] tests/test_cli
- [ ] tests/visualization_tests/test_utils
- [ ] tests/visualization_tests/test_intermediate_plot
- [ ] tests/visualization_tests/test_parallel_coordinate
- [ ] tests/visualization_tests/test_slice
- [ ] tests/visualization_tests/test_contour
- [ ] tests/visualization_tests/test_optimization_history
Excuse me. I have a question about this issue.
You mean that someone needs to rewrite all the comments like #type hope -> fuga in all the above files into comments following Oputuna Specific Conventions of https://github.com/optuna/optuna/wiki/Coding-Style-Conventions ?
Also, it seems necessary to remove variable annotation syntax form all the above files. Am I right ?
> You mean that someone needs to rewrite all the comments like #type hope -> fuga in all the above files into comments following Oputuna Specific Conventions of https://github.com/optuna/optuna/wiki/Coding-Style-Conventions ?

Yes.

> Also, it seems necessary to remove variable annotation syntax form all the above files. Am I right ?

No. Optuna doesn't still adopt variable annotation syntax because of the Python3.5 support. We need to keep a comment-based annotation style for variables.
So, in short, do you need function declarations like below in Optuna for now?

```
def func(hoge, fuga) -> type:
    """hoge is integer and fuga is float"""

    some procedure
```
More precisely, you need to specify the types of `hoge` and `fuga` like below.

```python
def func(hoge: int, fuga: float) -> type:
    """hoge is integer and fuga is float"""

    a = [] # type: List[int]
    # some procedure
```
I encountered the importing problem of `optuna.study.Study` (https://github.com/optuna/optuna/pull/963/files#discussion_r388350274).

We have to avoid directly importing of `Study` class because it causes a runtime error.
Although I'm not sure what is the best choice, I avoid an import error by [forward reference](https://www.python.org/dev/peps/pep-0484/#forward-references).

```python
def prune(self, study: "optuna.study.Study", trial: FrozenTrial) -> bool:
    
    step = trial.last_step
```
@c-bata 
Like #734 , could you add [this list](https://github.com/optuna/optuna/issues/711#issuecomment-593362218) to the top of this issue, because it is easier to understand which we need to fix next?
Sounds good 👍  I updated the description.
This issue has not seen any recent activity.
I'll briefly explain how to install and use `com2ann` which automatically translates type comments into type annotations. I tweaked [the original version](https://github.com/ilevkivskyi/com2ann) to prevent translating type comments on variables (variable annotations) which Python 3.5 doesn't support.

How to install:

```
pip install git+https://github.com/harupy/com2ann.git@disable-variable-annotation
```

How to run:

```
com2ann path/to/file.py
```

What you need to do after running `com2ann`:

- Remove `if type_checking.TYPE_CHECKING` (in some modules, it's still required to prevent a circular import)
- Sort imports order
- Remove unused import
- Run `black --line-length=99 --exclude=docs .` to format code

[FYI] I checked the entire current Optuna code to see what files still need to be worked on. I fixed the first description on this page. We still have a lot of tasks to work on for this Issue. 

I think this is the best first issue for everyone. We're waiting for your contribution!

Resolving patch:
diff --git a/optuna/samplers/_random.py b/optuna/samplers/_random.py
--- a/optuna/samplers/_random.py
+++ b/optuna/samplers/_random.py
@@ -1,17 +1,14 @@
+from typing import Any
+from typing import Dict
+from typing import Optional
+
 import numpy
 
 from optuna import distributions
+from optuna.distributions import BaseDistribution
 from optuna.samplers import BaseSampler
-from optuna import type_checking
-
-if type_checking.TYPE_CHECKING:
-    from typing import Any  # NOQA
-    from typing import Dict  # NOQA
-    from typing import Optional  # NOQA
-
-    from optuna.distributions import BaseDistribution  # NOQA
-    from optuna.study import Study  # NOQA
-    from optuna.trial import FrozenTrial  # NOQA
+from optuna.study import Study
+from optuna.trial import FrozenTrial
 
 
 class RandomSampler(BaseSampler):
@@ -38,8 +35,7 @@ def objective(trial):
             seed: Seed for random number generator.
     """
 
-    def __init__(self, seed=None):
-        # type: (Optional[int]) -> None
+    def __init__(self, seed: Optional[int] = None) -> None:
 
         self._rng = numpy.random.RandomState(seed)
 
@@ -47,18 +43,25 @@ def reseed_rng(self) -> None:
 
         self._rng = numpy.random.RandomState()
 
-    def infer_relative_search_space(self, study, trial):
-        # type: (Study, FrozenTrial) -> Dict[str, BaseDistribution]
+    def infer_relative_search_space(
+        self, study: Study, trial: FrozenTrial
+    ) -> Dict[str, BaseDistribution]:
 
         return {}
 
-    def sample_relative(self, study, trial, search_space):
-        # type: (Study, FrozenTrial, Dict[str, BaseDistribution]) -> Dict[str, Any]
+    def sample_relative(
+        self, study: Study, trial: FrozenTrial, search_space: Dict[str, BaseDistribution]
+    ) -> Dict[str, Any]:
 
         return {}
 
-    def sample_independent(self, study, trial, param_name, param_distribution):
-        # type: (Study, FrozenTrial, str, distributions.BaseDistribution) -> Any
+    def sample_independent(
+        self,
+        study: Study,
+        trial: FrozenTrial,
+        param_name: str,
+        param_distribution: distributions.BaseDistribution,
+    ) -> Any:
 
         if isinstance(param_distribution, distributions.UniformDistribution):
             return self._rng.uniform(param_distribution.low, param_distribution.high)


Test patch: