Skip to content

Drop Python 3.6#4150

Merged
toshihikoyanase merged 6 commits intooptuna:masterfrom
HideakiImamura:drop-python-3.6
Nov 10, 2022
Merged

Drop Python 3.6#4150
toshihikoyanase merged 6 commits intooptuna:masterfrom
HideakiImamura:drop-python-3.6

Conversation

@HideakiImamura
Copy link
Copy Markdown
Member

Motivation

The Python 3.6 is EOL and , recently, the latest official docker image of Ubuntu is 22.04, which does not support Python 3.6 anymore. We, the maintainers, have decided to drop Python 3.6 as we do not feel it is appropriate to continue to officially support it any longer. Future releases of Optuna will only be available for Python 3.7 or later. In addition, CI will not be testing with Python 3.6 at all; users who wish to continue using Python 3.6 will have to use versions of Optuna up to 3.0.3.

Description of the changes

  • Drop Python 3.6 in setup.py and CI.
  • Resolve some TODOs after Python 3.6 drop.
  • Fix some formatting errors, which are ignored due to pytest.skip.

@HideakiImamura HideakiImamura added the compatibility Change that breaks compatibility. label Nov 8, 2022
@github-actions github-actions bot added optuna.samplers Related to the `optuna.samplers` submodule. This is automatically labeled by github-actions. optuna.storages Related to the `optuna.storages` submodule. This is automatically labeled by github-actions. labels Nov 8, 2022
@not522 not522 self-assigned this Nov 8, 2022
@not522 not522 linked an issue Nov 8, 2022 that may be closed by this pull request
@not522
Copy link
Copy Markdown
Member

not522 commented Nov 8, 2022

Please remove the 3.6 badge from README.

@not522
Copy link
Copy Markdown
Member

not522 commented Nov 8, 2022

I found the following codes are related to this PR.

"Optuna supports Python 3.6 or newer." in docs/source/installation.rst

version = sys.version_info
if version < (3, 7, 0):
version_txt = str(version[0]) + "." + str(version[1]) + "." + str(version[2])
message = (
f"`QMCSampler` is not supported for Python {version_txt}. "
"Consider using Python 3.7 or later."
)
raise ValueError(message)

# Ordered list of fields required for `__repr__`, `__hash__` and dataframe creation.
# TODO(hvy): Remove this list in Python 3.7 as the order of `self.__dict__` is preserved.
_ordered_fields = [
"number",
"_values",
"datetime_start",
"datetime_complete",
"params",
"_distributions",
"user_attrs",
"system_attrs",
"intermediate_values",
"_trial_id",
"state",
]

@HideakiImamura
Copy link
Copy Markdown
Member Author

@not522 Thanks for the good catch! Fixed.

@not522
Copy link
Copy Markdown
Member

not522 commented Nov 9, 2022

"Optuna supports Python 3.6 or newer." in docs/source/installation.rst

Please update this statement.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Nov 9, 2022

Codecov Report

Merging #4150 (10c3c08) into master (8e3e66d) will increase coverage by 0.03%.
The diff coverage is 90.90%.

@@            Coverage Diff             @@
##           master    #4150      +/-   ##
==========================================
+ Coverage   90.03%   90.06%   +0.03%     
==========================================
  Files         161      161              
  Lines       12690    12680      -10     
==========================================
- Hits        11425    11420       -5     
+ Misses       1265     1260       -5     
Impacted Files Coverage Δ
optuna/_transform.py 94.35% <ø> (-0.09%) ⬇️
optuna/samplers/_qmc.py 97.93% <ø> (+2.79%) ⬆️
optuna/trial/_frozen.py 97.89% <0.00%> (-0.02%) ⬇️
optuna/integration/botorch.py 98.26% <100.00%> (+0.88%) ⬆️
optuna/storages/_journal/storage.py 96.94% <100.00%> (-0.02%) ⬇️

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

Copy link
Copy Markdown
Member

@not522 not522 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@not522 not522 removed their assignment Nov 9, 2022
@toshihikoyanase toshihikoyanase self-assigned this Nov 9, 2022
Copy link
Copy Markdown
Member

@toshihikoyanase toshihikoyanase left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your PR! The change will simplify CI, setup, and tests 👍
I have a question about FrozenTrial.

else \
pip install ${PIP_OPTIONS} -e '.[checking, document, integration]' -f https://download.pytorch.org/whl/torch_stable.html; \
fi \
pip install ${PIP_OPTIONS} -e '.[checking, document, integration]' -f https://download.pytorch.org/whl/torch_stable.html; \
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!

[Note] We could remove this line when we dropped Python 3.5 support actually.

Comment on lines -67 to -70
# TODO(hvy): Avoid casting to `OrderedDict` when Python 3.6 is no longer supported since
# order will be guaranteed.
search_space = OrderedDict(search_space)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Changed in version 3.7: Dictionary order is guaranteed to be insertion order. This behavior was an implementation detail of CPython from 3.6.

https://docs.python.org/3.7/library/stdtypes.html?highlight=dict#dict

params = {k: distributions[k].to_external_repr(p) for k, p in log["params"].items()}
if log["datetime_start"] is not None:
datetime_start = datetime_from_isoformat(log["datetime_start"])
datetime_start = datetime.datetime.fromisoformat(log["datetime_start"])
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution This does not support parsing arbitrary ISO 8601 strings - it is only intended as the inverse operation of datetime.isoformat().
https://docs.python.org/3.10/library/datetime.html#datetime.datetime.fromisoformat

I confirmed that log["datetime_start"] and log["datetime_complete"] are formatted by the datetime.isoformat function.

e.g.,

def create_new_trial(self, study_id: int, template_trial: Optional[FrozenTrial] = None) -> int:
log: Dict[str, Any] = {
"study_id": study_id,
"datetime_start": datetime.datetime.now().isoformat(timespec="microseconds"),
}
if template_trial:
log["state"] = template_trial.state
if template_trial.values is not None and len(template_trial.values) > 1:
log["value"] = None
log["values"] = template_trial.values
else:
log["value"] = template_trial.value
log["values"] = None
if template_trial.datetime_start:
log["datetime_start"] = template_trial.datetime_start.isoformat(
timespec="microseconds"
)
else:
log["datetime_start"] = None
if template_trial.datetime_complete:
log["datetime_complete"] = template_trial.datetime_complete.isoformat(
timespec="microseconds"
)

Comment on lines -169 to -183
# Ordered list of fields required for `__repr__`, `__hash__` and dataframe creation.
# TODO(hvy): Remove this list in Python 3.7 as the order of `self.__dict__` is preserved.
_ordered_fields = [
"number",
"_values",
"datetime_start",
"datetime_complete",
"params",
"_distributions",
"user_attrs",
"system_attrs",
"intermediate_values",
"_trial_id",
"state",
]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: The keys of self.__dict__ will be as follows:

['_number', 'state', '_values', '_datetime_start', 'datetime_complete', '_params', '_user_attrs', '_system_attrs', 'intermediate_values', '_distributions', '_trial_id']

We can see some differences:

  • Some field including number, params, user_attrs and system_attrs will be prefixed with _.
  • The order of fields is different. For example, _values is the second item of _ordered_field, but it is the third one of self.__dict__.

But, I don't think they affect users because of the following two reasons:

  • hash value will be changed, but hash values are different process by process originally. So, we cannot compare hash values of different processes even if we use the current master.
  • I confirmed that trial_str = repr(trial) can be restored by eval(trial_str).
  • I also confirmed that dumped trial with repr in master can be restored by eval in this PR.

What do you think of it?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the insightful review. Actually, the items and order of self.__dict__ and _ordered_field are different each other. But, as you confirmed,

I confirmed that trial_str = repr(trial) can be restored by eval(trial_str).
I also confirmed that dumped trial with repr in master can be restored by eval in this PR.

The impact of this change on users would be minimal. So, we can accept it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your reply. That makes sense.

@c-bata c-bata mentioned this pull request Nov 9, 2022
2 tasks
Copy link
Copy Markdown
Member

@toshihikoyanase toshihikoyanase left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thank you.

When we release v3.1.0, we need to update the installation section of optuna.org.

image

@HideakiImamura HideakiImamura deleted the drop-python-3.6 branch June 9, 2023 02:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

compatibility Change that breaks compatibility. optuna.samplers Related to the `optuna.samplers` submodule. This is automatically labeled by github-actions. optuna.storages Related to the `optuna.storages` submodule. This is automatically labeled by github-actions.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[RFC] Drop Python 3.6 support

4 participants