Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop Python 3.6 #526

Merged
merged 13 commits into from Feb 1, 2022
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Expand Up @@ -12,7 +12,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-20.04, windows-2019]
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"]
python-version: ["3.7", "3.8", "3.9", "3.10"]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
Expand Down
13 changes: 7 additions & 6 deletions .pre-commit-config.yaml
Expand Up @@ -22,16 +22,17 @@ repos:
- id: requirements-txt-fixer
- id: trailing-whitespace

- repo: https://github.com/asottile/pyupgrade
rev: v2.29.1
hooks:
- id: pyupgrade
args: [--py36-plus]

- repo: https://github.com/PyCQA/isort
rev: 5.10.1
hooks:
- id: isort
args: ["-a", "from __future__ import annotations"]

- repo: https://github.com/asottile/pyupgrade
rev: v2.29.1
hooks:
- id: pyupgrade
args: [--py37-plus]

- repo: https://github.com/asottile/setup-cfg-fmt
rev: v1.20.0
Expand Down
2 changes: 2 additions & 0 deletions docs/conf.py
Expand Up @@ -11,6 +11,8 @@
# All configuration values have a default; values that are commented out
# serve to show the default.

from __future__ import annotations

import os
import sys

Expand Down
4 changes: 2 additions & 2 deletions nox/__init__.py
Expand Up @@ -12,14 +12,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Optional
from __future__ import annotations

from nox._options import noxfile_options as options
from nox._parametrize import Param as param
from nox._parametrize import parametrize_decorator as parametrize
from nox.registry import session_decorator as session
from nox.sessions import Session

needs_version: Optional[str] = None
needs_version: str | None = None

__all__ = ["needs_version", "parametrize", "param", "session", "options", "Session"]
2 changes: 2 additions & 0 deletions nox/__main__.py
Expand Up @@ -19,6 +19,8 @@
control to :meth:``nox.workflow.execute``.
"""

from __future__ import annotations

import sys

from nox import _options, tasks, workflow
Expand Down
20 changes: 11 additions & 9 deletions nox/_decorators.py
Expand Up @@ -12,11 +12,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import annotations

import copy
import functools
import inspect
import types
from typing import Any, Callable, Dict, Iterable, List, Optional
from typing import Any, Callable, Iterable

from . import _typing

Expand All @@ -27,12 +29,12 @@
class FunctionDecorator:
def __new__(
cls, func: Callable[..., Any], *args: Any, **kwargs: Any
) -> "FunctionDecorator":
) -> FunctionDecorator:
obj = super().__new__(cls)
return functools.wraps(func)(obj)


def _copy_func(src: Callable, name: Optional[str] = None) -> Callable:
def _copy_func(src: Callable, name: str | None = None) -> Callable:
dst = types.FunctionType(
src.__code__,
src.__globals__, # type: ignore[attr-defined]
Expand All @@ -51,11 +53,11 @@ def __init__(
self,
func: Callable,
python: _typing.Python = None,
reuse_venv: Optional[bool] = None,
name: Optional[str] = None,
reuse_venv: bool | None = None,
name: str | None = None,
venv_backend: Any = None,
venv_params: Any = None,
should_warn: Optional[Dict[str, Any]] = None,
should_warn: dict[str, Any] | None = None,
):
self.func = func
self.python = python
Expand All @@ -67,7 +69,7 @@ def __init__(
def __call__(self, *args: Any, **kwargs: Any) -> Any:
return self.func(*args, **kwargs)

def copy(self, name: Optional[str] = None) -> "Func":
def copy(self, name: str | None = None) -> Func:
return Func(
_copy_func(self.func, name),
self.python,
Expand All @@ -80,7 +82,7 @@ def copy(self, name: Optional[str] = None) -> "Func":


class Call(Func):
def __init__(self, func: Func, param_spec: "Param") -> None:
def __init__(self, func: Func, param_spec: Param) -> None:
call_spec = param_spec.call_spec
session_signature = f"({param_spec})"

Expand Down Expand Up @@ -113,5 +115,5 @@ def __call__(self, *args: Any, **kwargs: Any) -> Any:
return super().__call__(*args, **kwargs)

@classmethod
def generate_calls(cls, func: Func, param_specs: "Iterable[Param]") -> "List[Call]":
def generate_calls(cls, func: Func, param_specs: Iterable[Param]) -> list[Call]:
return [cls(func, param_spec) for param_spec in param_specs]
31 changes: 16 additions & 15 deletions nox/_option_set.py
Expand Up @@ -16,13 +16,14 @@
can be specified from the command line and the noxfile, easily used in tests,
and surfaced in documentation."""

from __future__ import annotations

import argparse
import collections
import functools
from argparse import ArgumentError as ArgumentError
from argparse import ArgumentParser, Namespace
from typing import Any, Callable, List, Optional, Tuple, Union
from typing import Any, Callable

import argcomplete

Expand Down Expand Up @@ -77,14 +78,14 @@ def __init__(
self,
name: str,
*flags: str,
group: Optional[OptionGroup],
help: Optional[str] = None,
group: OptionGroup | None,
help: str | None = None,
noxfile: bool = False,
merge_func: Optional[Callable[[Namespace, Namespace], Any]] = None,
finalizer_func: Optional[Callable[[Any, Namespace], Any]] = None,
default: Union[Any, Callable[[], Any]] = None,
merge_func: Callable[[Namespace, Namespace], Any] | None = None,
finalizer_func: Callable[[Any, Namespace], Any] | None = None,
default: Any | Callable[[], Any] = None,
hidden: bool = False,
completer: Optional[Callable[..., List[str]]] = None,
completer: Callable[..., list[str]] | None = None,
**kwargs: Any,
) -> None:
self.name = name
Expand All @@ -100,7 +101,7 @@ def __init__(
self._default = default

@property
def default(self) -> Optional[Union[bool, str]]:
def default(self) -> bool | str | None:
if callable(self._default):
return self._default()
return self._default
Expand Down Expand Up @@ -154,10 +155,10 @@ def flag_pair_merge_func(

def make_flag_pair(
name: str,
enable_flags: Union[Tuple[str, str], Tuple[str]],
disable_flags: Tuple[str],
enable_flags: tuple[str, str] | tuple[str],
disable_flags: tuple[str],
**kwargs: Any,
) -> Tuple[Option, Option]:
) -> tuple[Option, Option]:
"""Returns two options - one to enable a behavior and another to disable it.

The positive option is considered to be available to the noxfile, as
Expand Down Expand Up @@ -191,10 +192,10 @@ class OptionSet:
def __init__(self, *args: Any, **kwargs: Any) -> None:
self.parser_args = args
self.parser_kwargs = kwargs
self.options: "collections.OrderedDict[str, Option]" = collections.OrderedDict()
self.groups: "collections.OrderedDict[str, OptionGroup]" = (
collections.OrderedDict()
)
self.options: collections.OrderedDict[str, Option] = collections.OrderedDict()
self.groups: collections.OrderedDict[
str, OptionGroup
] = collections.OrderedDict()

def add_options(self, *args: Option) -> None:
"""Adds a sequence of Options to the OptionSet.
Expand Down
12 changes: 7 additions & 5 deletions nox/_options.py
Expand Up @@ -12,11 +12,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import annotations

import argparse
import functools
import os
import sys
from typing import Any, List, Optional, Sequence, Union
from typing import Any, Sequence

from nox import _option_set
from nox.tasks import discover_manifest, filter_manifest, load_nox_module
Expand Down Expand Up @@ -63,7 +65,7 @@

def _sessions_and_keywords_merge_func(
key: str, command_args: argparse.Namespace, noxfile_args: argparse.Namespace
) -> List[str]:
) -> list[str]:
"""Only return the Noxfile value for sessions/keywords if neither sessions
or keywords are specified on the command-line.

Expand Down Expand Up @@ -137,7 +139,7 @@ def _envdir_merge_func(
return command_args.envdir or noxfile_args.envdir or ".nox"


def _sessions_default() -> Optional[List[str]]:
def _sessions_default() -> list[str] | None:
"""Looks at the NOXSESSION env var to set the default value for sessions."""
nox_env = os.environ.get("NOXSESSION")
env_sessions = nox_env.split(",") if nox_env else None
Expand Down Expand Up @@ -186,7 +188,7 @@ def _R_finalizer(value: bool, args: argparse.Namespace) -> bool:

def _posargs_finalizer(
value: Sequence[Any], args: argparse.Namespace
) -> Union[Sequence[Any], List[Any]]:
) -> Sequence[Any] | list[Any]:
"""Removes the leading "--"s in the posargs array (if any) and asserts that
remaining arguments came after a "--".
"""
Expand All @@ -212,7 +214,7 @@ def _posargs_finalizer(

def _session_completer(
prefix: str, parsed_args: argparse.Namespace, **kwargs: Any
) -> List[str]:
) -> list[str]:
global_config = parsed_args
module = load_nox_module(global_config)
manifest = discover_manifest(module, global_config)
Expand Down
30 changes: 16 additions & 14 deletions nox/_parametrize.py
Expand Up @@ -12,9 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import annotations

import functools
import itertools
from typing import Any, Callable, Dict, Iterable, List, Optional, Sequence, Tuple, Union
from typing import Any, Callable, Iterable, Sequence, Union


class Param:
Expand All @@ -31,8 +33,8 @@ class Param:
def __init__(
self,
*args: Any,
arg_names: Optional[Sequence[str]] = None,
id: Optional[str] = None,
arg_names: Sequence[str] | None = None,
id: str | None = None,
) -> None:
self.args = tuple(args)
self.id = id
Expand All @@ -43,7 +45,7 @@ def __init__(
self.arg_names = tuple(arg_names)

@property
def call_spec(self) -> Dict[str, Any]:
def call_spec(self) -> dict[str, Any]:
return dict(zip(self.arg_names, self.args))

def __str__(self) -> str:
Expand All @@ -56,11 +58,11 @@ def __str__(self) -> str:

__repr__ = __str__

def copy(self) -> "Param":
def copy(self) -> Param:
new = self.__class__(*self.args, arg_names=self.arg_names, id=self.id)
return new

def update(self, other: "Param") -> None:
def update(self, other: Param) -> None:
self.id = ", ".join([str(self), str(other)])
self.args = self.args + other.args
self.arg_names = self.arg_names + other.arg_names
Expand All @@ -78,7 +80,7 @@ def __eq__(self, other: object) -> bool:
raise NotImplementedError


def _apply_param_specs(param_specs: List[Param], f: Any) -> Any:
def _apply_param_specs(param_specs: list[Param], f: Any) -> Any:
previous_param_specs = getattr(f, "parametrize", None)
new_param_specs = update_param_specs(previous_param_specs, param_specs)
f.parametrize = new_param_specs
Expand All @@ -89,9 +91,9 @@ def _apply_param_specs(param_specs: List[Param], f: Any) -> Any:


def parametrize_decorator(
arg_names: Union[str, List[str], Tuple[str]],
arg_values_list: Union[Iterable[ArgValue], ArgValue],
ids: Optional[Iterable[Optional[str]]] = None,
arg_names: str | list[str] | tuple[str],
arg_values_list: Iterable[ArgValue] | ArgValue,
ids: Iterable[str | None] | None = None,
) -> Callable[[Any], Any]:
"""Parametrize a session.

Expand Down Expand Up @@ -119,7 +121,7 @@ def parametrize_decorator(

# If there's only one arg_name, arg_values_list should be a single item
# or list. Transform it so it'll work with the combine step.
_arg_values_list: List[Union[Param, Iterable[Union[Any, ArgValue]]]] = []
_arg_values_list: list[Param | Iterable[Any | ArgValue]] = []
if len(arg_names) == 1:
# In this case, the arg_values_list can also just be a single item.
# Must be mutable for the transformation steps
Expand All @@ -141,7 +143,7 @@ def parametrize_decorator(
ids = []

# Generate params for each item in the param_args_values list.
param_specs: List[Param] = []
param_specs: list[Param] = []
for param_arg_values, param_id in itertools.zip_longest(_arg_values_list, ids):
if isinstance(param_arg_values, Param):
param_spec = param_arg_values
Expand All @@ -155,8 +157,8 @@ def parametrize_decorator(


def update_param_specs(
param_specs: Optional[Iterable[Param]], new_specs: List[Param]
) -> List[Param]:
param_specs: Iterable[Param] | None, new_specs: list[Param]
) -> list[Param]:
"""Produces all combinations of the given sets of specs."""
if not param_specs:
return new_specs
Expand Down
2 changes: 2 additions & 0 deletions nox/_typing.py
Expand Up @@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import annotations

__all__ = ["TYPE_CHECKING", "ClassVar", "NoReturn", "Python"]

import typing as _typing
Expand Down