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

Add more linting #338

Merged
merged 1 commit into from
Jan 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ repos:
- id: black

- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.207
rev: v0.0.237
hooks:
- id: ruff
args: ["--fix"]
Expand Down
6 changes: 3 additions & 3 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import os
import shutil

from jupyter_core.version import __version__, version_info

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
Expand Down Expand Up @@ -61,11 +63,9 @@

# General information about the project.
project = "jupyter_core"
copyright = "2015, Jupyter Development Team"
copyright = "2015, Jupyter Development Team" # noqa
author = "Jupyter Development Team"

from jupyter_core.version import __version__, version_info

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
Expand Down
11 changes: 7 additions & 4 deletions jupyter_core/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,12 @@ def _jupyter_abspath(subcommand):
jupyter_subcommand = f"jupyter-{subcommand}"
abs_path = which(jupyter_subcommand, path=search_path)
if abs_path is None:
raise Exception(f"\nJupyter command `{jupyter_subcommand}` not found.")
msg = f"\nJupyter command `{jupyter_subcommand}` not found."
raise Exception(msg)

if not os.access(abs_path, os.X_OK):
raise Exception(f"\nJupyter command `{jupyter_subcommand}` is not executable.")
msg = f"\nJupyter command `{jupyter_subcommand}` is not executable."
raise Exception(msg)

return abs_path

Expand Down Expand Up @@ -215,10 +217,11 @@ def _evaluate_argcomplete(parser: JupyterParser) -> List[str]:
# traitlets >= 5.8 not available, just try to complete this without
# worrying about subcommands
parser.argcomplete()
raise AssertionError("Control flow should not reach end of autocomplete()")
msg = "Control flow should not reach end of autocomplete()"
raise AssertionError(msg)


def main() -> None:
def main() -> None: # noqa
"""The command entry point."""
parser = jupyter_parser()
argv = sys.argv
Expand Down
24 changes: 10 additions & 14 deletions jupyter_core/migrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import os
import re
import shutil
from datetime import datetime
from datetime import datetime, timezone

from traitlets.config.loader import JSONFileConfigLoader, PyFileConfigLoader
from traitlets.log import get_logger
Expand Down Expand Up @@ -176,12 +176,10 @@ def migrate_static_custom(src, dst):
if not custom_js_empty or not custom_css_empty:
ensure_dir_exists(dst)

if not custom_js_empty:
if migrate_file(custom_js, pjoin(dst, "custom.js")):
migrated = True
if not custom_css_empty:
if migrate_file(custom_css, pjoin(dst, "custom.css")):
migrated = True
if not custom_js_empty and migrate_file(custom_js, pjoin(dst, "custom.js")):
migrated = True
if not custom_css_empty and migrate_file(custom_css, pjoin(dst, "custom.css")):
migrated = True

return migrated

Expand Down Expand Up @@ -225,9 +223,8 @@ def migrate():
for src_t, dst_t in migrations.items():
src = src_t.format(**env)
dst = dst_t.format(**env)
if os.path.exists(src):
if migrate_one(src, dst):
migrated = True
if os.path.exists(src) and migrate_one(src, dst):
migrated = True

for name in config_migrations:
if migrate_config(name, env):
Expand All @@ -236,14 +233,13 @@ def migrate():
custom_src = custom_src_t.format(**env)
custom_dst = custom_dst_t.format(**env)

if os.path.exists(custom_src):
if migrate_static_custom(custom_src, custom_dst):
migrated = True
if os.path.exists(custom_src) and migrate_static_custom(custom_src, custom_dst):
migrated = True

# write a marker to avoid re-running migration checks
ensure_dir_exists(env["jupyter_config"])
with open(os.path.join(env["jupyter_config"], "migrated"), "w", encoding="utf-8") as f:
f.write(datetime.utcnow().isoformat())
f.write(datetime.now(tz=timezone.utc).isoformat())

return migrated

Expand Down
33 changes: 14 additions & 19 deletions jupyter_core/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,15 @@ def _do_i_own(path: str) -> bool:
try:
return p.owner() == os.getlogin()
except Exception:
pass
pass # noqa

if hasattr(os, 'geteuid'):
try:
st = p.stat()
return st.st_uid == os.geteuid()
except (NotImplementedError, OSError):
# geteuid not always implemented
pass
pass # noqa

# no ownership checks worked, check write access
return os.access(p, os.W_OK)
Expand Down Expand Up @@ -207,10 +207,10 @@ def jupyter_runtime_dir() -> str:
else:
deprecation(
"Jupyter is migrating its paths to use standard platformdirs\n"
+ "given by the platformdirs library. To remove this warning and\n"
+ "see the appropriate new directories, set the environment variable\n"
+ "`JUPYTER_PLATFORM_DIRS=1` and then run `jupyter --paths`.\n"
+ "The use of platformdirs will be the default in `jupyter_core` v6"
"given by the platformdirs library. To remove this warning and\n"
"see the appropriate new directories, set the environment variable\n"
"`JUPYTER_PLATFORM_DIRS=1` and then run `jupyter --paths`.\n"
"The use of platformdirs will be the default in `jupyter_core` v6"
)
if os.name == "nt":
programdata = os.environ.get("PROGRAMDATA", None)
Expand Down Expand Up @@ -261,10 +261,7 @@ def jupyter_path(*subdirs: str) -> List[str]:
# Check if site.getuserbase() exists to be compatible with virtualenv,
# which often does not have this method.
userbase: Optional[str]
if hasattr(site, "getuserbase"):
userbase = site.getuserbase()
else:
userbase = site.USER_BASE
userbase = site.getuserbase() if hasattr(site, "getuserbase") else site.USER_BASE

if userbase:
userdir = os.path.join(userbase, "share", "jupyter")
Expand Down Expand Up @@ -334,10 +331,7 @@ def jupyter_config_path() -> List[str]:
userbase: Optional[str]
# Check if site.getuserbase() exists to be compatible with virtualenv,
# which often does not have this method.
if hasattr(site, "getuserbase"):
userbase = site.getuserbase()
else:
userbase = site.USER_BASE
userbase = site.getuserbase() if hasattr(site, "getuserbase") else site.USER_BASE

if userbase:
userdir = os.path.join(userbase, "etc", "jupyter")
Expand Down Expand Up @@ -439,7 +433,7 @@ def is_file_hidden_posix(abs_path: str, stat_res: Optional[Any] = None) -> bool:
raise

# check that dirs can be listed
if stat.S_ISDIR(stat_res.st_mode): # type:ignore[misc]
if stat.S_ISDIR(stat_res.st_mode): # type:ignore[misc] # noqa
# use x-access, not actual listing, in case of slow/large listings
if not os.access(abs_path, os.X_OK | os.R_OK):
return True
Expand All @@ -457,7 +451,7 @@ def is_file_hidden_posix(abs_path: str, stat_res: Optional[Any] = None) -> bool:
is_file_hidden = is_file_hidden_posix


def is_hidden(abs_path: str, abs_root: str = "") -> bool:
def is_hidden(abs_path: str, abs_root: str = "") -> bool: # noqa
"""Is a file hidden or contained in a hidden directory?

This will start with the rightmost path element and work backwards to the
Expand Down Expand Up @@ -554,7 +548,7 @@ def win32_restrict_file_to_user(fname: str) -> None:
win32security.SetFileSecurity(fname, win32security.DACL_SECURITY_INFORMATION, sd)


def _win32_restrict_file_to_user_ctypes(fname: str) -> None:
def _win32_restrict_file_to_user_ctypes(fname: str) -> None: # noqa
"""Secure a windows file to read-only access for the user.

Follows guidance from win32 library creator:
Expand Down Expand Up @@ -992,16 +986,17 @@ def secure_write(fname: str, binary: bool = False) -> Iterator[Any]:
if os.name != "nt":
# Enforce that the file got the requested permissions before writing
file_mode = get_file_mode(fname)
if 0o0600 != file_mode:
if file_mode != 0o0600: # noqa
if allow_insecure_writes:
issue_insecure_write_warning()
else:
raise RuntimeError(
msg = (
"Permissions assignment failed for secure file: '{file}'."
" Got '{permissions}' instead of '0o0600'.".format(
file=fname, permissions=oct(file_mode)
)
)
raise RuntimeError(msg)
yield f


Expand Down
31 changes: 15 additions & 16 deletions jupyter_core/tests/test_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def get_jupyter_output(cmd):
if not isinstance(cmd, list):
cmd = [cmd]
return (
check_output([sys.executable, "-m", "jupyter_core"] + cmd, stderr=PIPE)
check_output([sys.executable, "-m", "jupyter_core", *cmd], stderr=PIPE)
.decode("utf8")
.strip()
)
Expand Down Expand Up @@ -108,7 +108,7 @@ def test_paths_json():


def test_paths_debug():
vars = [
names = [
"JUPYTER_PREFER_ENV_PATH",
"JUPYTER_NO_CONFIG",
"JUPYTER_CONFIG_PATH",
Expand All @@ -118,12 +118,12 @@ def test_paths_debug():
"JUPYTER_RUNTIME_DIR",
]
output = get_jupyter_output(["--paths", "--debug"])
for v in vars:
for v in names:
assert f"{v} is not set" in output

with patch.dict("os.environ", [(v, "y") for v in vars]):
with patch.dict("os.environ", [(v, "y") for v in names]):
output = get_jupyter_output(["--paths", "--debug"])
for v in vars:
for v in names:
assert f"{v} is set" in output


Expand Down Expand Up @@ -161,17 +161,16 @@ def test_subcommand_list(tmpdir):
def get_path(dummy):
return str(c)

with patch.object(sysconfig, "get_path", get_path):
with patch.dict("os.environ", {"PATH": path}):
subcommands = list_subcommands()
assert subcommands == [
"babel-fish",
"baz",
"bop",
"foo",
"xyz",
"yo-eyropa-ganymyde-callysto",
]
with patch.object(sysconfig, "get_path", get_path), patch.dict("os.environ", {"PATH": path}):
subcommands = list_subcommands()
assert subcommands == [
"babel-fish",
"baz",
"bop",
"foo",
"xyz",
"yo-eyropa-ganymyde-callysto",
]


skip_darwin = pytest.mark.skipif(sys.platform == "darwin", reason="Fails on macos")
Expand Down
8 changes: 4 additions & 4 deletions jupyter_core/tests/test_paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ def check_user_only_permissions(fname):
assert "administrators" in permissions
assert permissions["administrators"] == {"f"}
assert "everyone" not in permissions
assert len(permissions) == 2
assert len(permissions) == 2 # noqa

directory = tempfile.mkdtemp()
fname = os.path.join(directory, "check_perms")
Expand All @@ -570,16 +570,16 @@ def test_secure_write_unix():
with secure_write(fname) as f:
f.write("test 1")
mode = os.stat(fname).st_mode
assert 0o0600 == (stat.S_IMODE(mode) & 0o7677) # tolerate owner-execute bit
assert 0o0600 == (stat.S_IMODE(mode) & 0o7677) # noqa # tolerate owner-execute bit
with open(fname, encoding="utf-8") as f:
assert f.read() == "test 1"

# Try changing file permissions ahead of time
os.chmod(fname, 0o755)
os.chmod(fname, 0o755) # noqa
with secure_write(fname) as f:
f.write("test 2")
mode = os.stat(fname).st_mode
assert 0o0600 == (stat.S_IMODE(mode) & 0o7677) # tolerate owner-execute bit
assert 0o0600 == (stat.S_IMODE(mode) & 0o7677) # noqa # tolerate owner-execute bit
with open(fname, encoding="utf-8") as f:
assert f.read() == "test 2"
finally:
Expand Down
2 changes: 1 addition & 1 deletion jupyter_core/troubleshoot.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def get_data() -> Dict[str, Any]:
return env


def main() -> None:
def main() -> None: # noqa
"""
print out useful info
"""
Expand Down
10 changes: 4 additions & 6 deletions jupyter_core/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,7 @@ def deprecation(message: str, internal: Union[str, List[str]] = "jupyter_core/")
we know that our internal code is calling out to another library.
"""
_internal: List[str]
if isinstance(internal, str):
_internal = [internal]
else:
_internal = internal
_internal = [internal] if isinstance(internal, str) else internal

# stack level of the first external frame from here
stacklevel = _external_stacklevel(_internal)
Expand All @@ -110,7 +107,7 @@ def _close(self):

def _runner(self):
loop = self.__io_loop
assert loop is not None
assert loop is not None # noqa
try:
loop.run_forever()
finally:
Expand Down Expand Up @@ -146,7 +143,8 @@ def run_sync(coro: Callable[..., Awaitable[T]]) -> Callable[..., T]:
Whatever the coroutine-function returns.
"""

assert inspect.iscoroutinefunction(coro)
if not inspect.iscoroutinefunction(coro):
raise AssertionError

def wrapped(*args, **kwargs):
name = threading.current_thread().name
Expand Down
2 changes: 1 addition & 1 deletion jupyter_core/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# Build up version_info tuple for backwards compatibility
pattern = r"(?P<major>\d+).(?P<minor>\d+).(?P<patch>\d+)(?P<rest>.*)"
match = re.match(pattern, __version__)
assert match is not None
assert match is not None # noqa
parts: List[object] = [int(match[part]) for part in ["major", "minor", "patch"]]
if match["rest"]:
parts.append(match["rest"])
Expand Down