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

Toughen ruff linting #436

Merged
merged 8 commits into from
Feb 7, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,25 @@ $ pipx install --suffix=@next 'vcspull' --pip-args '\--pre' --force

- `dir` -> `path` (#435)

### Development

- Strengthen linting (#436)

- Add flake8-commas (COM)

- https://docs.astral.sh/ruff/rules/#flake8-commas-com
- https://pypi.org/project/flake8-commas/

- Add flake8-builtins (A)

- https://docs.astral.sh/ruff/rules/#flake8-builtins-a
- https://pypi.org/project/flake8-builtins/

- Add flake8-errmsg (EM)

- https://docs.astral.sh/ruff/rules/#flake8-errmsg-em
- https://pypi.org/project/flake8-errmsg/

### Documentation

- Refactor API docs to split across multiple pages (#431)
Expand Down
14 changes: 8 additions & 6 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ def xdg_config_path(

@pytest.fixture(scope="function")
def config_path(
xdg_config_path: pathlib.Path, request: pytest.FixtureRequest
xdg_config_path: pathlib.Path,
request: pytest.FixtureRequest,
) -> pathlib.Path:
"""Ensure and return vcspull configuration path."""
conf_path = xdg_config_path / "vcspull"
Expand All @@ -73,7 +74,8 @@ def clean() -> None:

@pytest.fixture(autouse=True)
def set_xdg_config_path(
monkeypatch: pytest.MonkeyPatch, xdg_config_path: pathlib.Path
monkeypatch: pytest.MonkeyPatch,
xdg_config_path: pathlib.Path,
) -> None:
"""Set XDG_CONFIG_HOME environment variable."""
monkeypatch.setenv("XDG_CONFIG_HOME", str(xdg_config_path))
Expand All @@ -82,11 +84,11 @@ def set_xdg_config_path(
@pytest.fixture(scope="function")
def repos_path(user_path: pathlib.Path, request: pytest.FixtureRequest) -> pathlib.Path:
"""Return temporary directory for repository checkout guaranteed unique."""
dir = user_path / "repos"
dir.mkdir(exist_ok=True)
path = user_path / "repos"
path.mkdir(exist_ok=True)

def clean() -> None:
shutil.rmtree(dir)
shutil.rmtree(path)

request.addfinalizer(clean)
return dir
return path
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
master_doc = "index"

project = about["__title__"]
copyright = about["__copyright__"]
project_copyright = about["__copyright__"]

version = "%s" % (".".join(about["__version__"].split("."))[:2])
release = "%s" % (about["__version__"])
Expand Down Expand Up @@ -96,7 +96,7 @@
"sidebar/navigation.html",
"sidebar/projects.html",
"sidebar/scroll-end.html",
]
],
}

# linkify_issues
Expand Down
6 changes: 6 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,11 @@ select = [
"F", # pyflakes
"I", # isort
"UP", # pyupgrade
"A", # flake8-builtins
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"COM", # flake8-commas
"EM", # flake8-errmsg
"Q", # flake8-quotes
"PTH", # flake8-use-pathlib
"SIM", # flake8-simplify
Expand All @@ -160,6 +163,9 @@ select = [
"RUF", # Ruff-specific rules
"D", # pydocstyle
]
ignore = [
"COM812", # missing trailing comma, ruff format conflict
]

[tool.ruff.lint.pydocstyle]
convention = "numpy"
Expand Down
8 changes: 4 additions & 4 deletions scripts/generate_gitlab.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

parser = argparse.ArgumentParser(
description="Script to generate vcsconfig for all repositories \
under the given namespace (needs Gitlab >= 10.3)"
under the given namespace (needs Gitlab >= 10.3)",
)
parser.add_argument("gitlab_host", type=str, help="url to the gitlab instance")
parser.add_argument(
Expand All @@ -47,14 +47,14 @@
result = input(
"The target config file (%s) already exists, \
do you want to overwrite it? [y/N] "
% (config_filename)
% (config_filename),
)

if result != "y":
print(
"Aborting per user request as existing config file (%s) \
should not be overwritten!"
% (config_filename)
% (config_filename),
)
sys.exit(0)

Expand Down Expand Up @@ -103,7 +103,7 @@
name="origin",
fetch_url=f"ssh://{url_to_repo}",
push_url=f"ssh://{url_to_repo}",
)
),
},
"vcs": vcs,
}
Expand Down
35 changes: 19 additions & 16 deletions src/vcspull/_internal/config_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def __init__(self, content: "RawConfigData") -> None:
self.content = content

@staticmethod
def _load(format: "FormatLiteral", content: str) -> dict[str, t.Any]:
def _load(fmt: "FormatLiteral", content: str) -> dict[str, t.Any]:
"""Load raw config data and directly return it.

>>> ConfigReader._load("json", '{ "session_name": "my session" }')
Expand All @@ -35,21 +35,22 @@ def _load(format: "FormatLiteral", content: str) -> dict[str, t.Any]:
>>> ConfigReader._load("yaml", 'session_name: my session')
{'session_name': 'my session'}
"""
if format == "yaml":
if fmt == "yaml":
return t.cast(
dict[str, t.Any],
yaml.load(
content,
Loader=yaml.SafeLoader,
),
)
elif format == "json":
elif fmt == "json":
return t.cast(dict[str, t.Any], json.loads(content))
else:
raise NotImplementedError(f"{format} not supported in configuration")
msg = f"{fmt} not supported in configuration"
raise NotImplementedError(msg)

@classmethod
def load(cls, format: "FormatLiteral", content: str) -> "ConfigReader":
def load(cls, fmt: "FormatLiteral", content: str) -> "ConfigReader":
"""Load raw config data into a ConfigReader instance (to dump later).

>>> cfg = ConfigReader.load("json", '{ "session_name": "my session" }')
Expand All @@ -66,7 +67,7 @@ def load(cls, format: "FormatLiteral", content: str) -> "ConfigReader":
"""
return cls(
content=cls._load(
format=format,
fmt=fmt,
content=content,
),
)
Expand Down Expand Up @@ -105,14 +106,15 @@ def _from_file(cls, path: pathlib.Path) -> dict[str, t.Any]:
content = path.open().read()

if path.suffix in [".yaml", ".yml"]:
format: "FormatLiteral" = "yaml"
fmt: "FormatLiteral" = "yaml"
elif path.suffix == ".json":
format = "json"
fmt = "json"
else:
raise NotImplementedError(f"{path.suffix} not supported in {path}")
msg = f"{path.suffix} not supported in {path}"
raise NotImplementedError(msg)

return cls._load(
format=format,
fmt=fmt,
content=content,
)

Expand Down Expand Up @@ -158,7 +160,7 @@ def from_file(cls, path: pathlib.Path) -> "ConfigReader":

@staticmethod
def _dump(
format: "FormatLiteral",
fmt: "FormatLiteral",
content: "RawConfigData",
indent: int = 2,
**kwargs: t.Any,
Expand All @@ -171,22 +173,23 @@ def _dump(
>>> ConfigReader._dump("json", { "session_name": "my session" })
'{\n "session_name": "my session"\n}'
"""
if format == "yaml":
if fmt == "yaml":
return yaml.dump(
content,
indent=2,
default_flow_style=False,
Dumper=yaml.SafeDumper,
)
elif format == "json":
elif fmt == "json":
return json.dumps(
content,
indent=2,
)
else:
raise NotImplementedError(f"{format} not supported in config")
msg = f"{fmt} not supported in config"
raise NotImplementedError(msg)

def dump(self, format: "FormatLiteral", indent: int = 2, **kwargs: t.Any) -> str:
def dump(self, fmt: "FormatLiteral", indent: int = 2, **kwargs: t.Any) -> str:
r"""Dump via ConfigReader instance.

>>> cfg = ConfigReader({ "session_name": "my session" })
Expand All @@ -196,7 +199,7 @@ def dump(self, format: "FormatLiteral", indent: int = 2, **kwargs: t.Any) -> str
'{\n "session_name": "my session"\n}'
"""
return self._dump(
format=format,
fmt=fmt,
content=self.content,
indent=indent,
**kwargs,
Expand Down
2 changes: 1 addition & 1 deletion src/vcspull/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
vcspull sync "django-*" flask
vcspull sync -c ./myrepos.yaml "*"
vcspull sync -c ./myrepos.yaml myproject
"""
""",
).strip()


Expand Down
19 changes: 12 additions & 7 deletions src/vcspull/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,16 @@ def extract_repos(
continue
if isinstance(url, str):
conf["remotes"][remote_name] = GitRemote(
name=remote_name, fetch_url=url, push_url=url
name=remote_name,
fetch_url=url,
push_url=url,
)
elif isinstance(url, dict):
assert "push_url" in url
assert "fetch_url" in url
conf["remotes"][remote_name] = GitRemote(
name=remote_name, **url
name=remote_name,
**url,
)

def is_valid_config_dict(val: t.Any) -> "TypeGuard[ConfigDict]":
Expand Down Expand Up @@ -153,7 +156,7 @@ def find_home_config_files(
log.debug(
"No config file found. Create a .vcspull.yaml or .vcspull.json"
" in your $HOME directory. http://vcspull.git-pull.com for a"
" quickstart."
" quickstart.",
)
else:
if sum(filter(None, [has_json_config, has_yaml_config])) > 1:
Expand Down Expand Up @@ -280,7 +283,8 @@ def load_configs(


def detect_duplicate_repos(
config1: list["ConfigDict"], config2: list["ConfigDict"]
config1: list["ConfigDict"],
config2: list["ConfigDict"],
) -> list[ConfigDictTuple]:
"""Return duplicate repos dict if repo_dir same and vcs different.

Expand Down Expand Up @@ -379,7 +383,7 @@ def filter_repos(
r
for r in config
if fnmatch.fnmatch(str(pathlib.Path(r["path"]).parent), str(path))
]
],
)

if vcs_url:
Expand All @@ -391,14 +395,15 @@ def filter_repos(

if name:
repo_list.extend(
[r for r in config if fnmatch.fnmatch(str(r.get("name")), name)]
[r for r in config if fnmatch.fnmatch(str(r.get("name")), name)],
)

return repo_list


def is_config_file(
filename: str, extensions: t.Optional[t.Union[list[str], str]] = None
filename: str,
extensions: t.Optional[t.Union[list[str], str]] = None,
) -> bool:
"""Return True if file has a valid config file type.

Expand Down
4 changes: 2 additions & 2 deletions src/vcspull/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def template(self, record: logging.LogRecord) -> str:
]

tpl = "".join(
reset + levelname + asctime + name + module_funcName + lineno + reset
reset + levelname + asctime + name + module_funcName + lineno + reset,
)

return tpl
Expand All @@ -176,7 +176,7 @@ class RepoLogFormatter(LogFormatter):
def template(self, record: logging.LogRecord) -> str:
"""Template for logging vcs bin name, along with a contextual hint."""
record.message = "".join(
[Fore.MAGENTA, Style.BRIGHT, record.message, Fore.RESET, Style.RESET_ALL]
[Fore.MAGENTA, Style.BRIGHT, record.message, Fore.RESET, Style.RESET_ALL],
)
return "{}|{}| {}({}) {}".format(
Fore.GREEN + Style.DIM,
Expand Down
8 changes: 4 additions & 4 deletions tests/fixtures/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"upstream": "git+https://github.com/emre/kaptan",
"ms": "git+https://github.com/ms/kaptan.git",
},
}
},
},
"/home/me/myproject": {
".vim": {
Expand All @@ -31,7 +31,7 @@
".tmux": {
"url": "[email protected]:tony/tmux-config.git",
"shell_command_after": [
"ln -sf /home/me/.tmux/.tmux.conf /home/me/.tmux.conf"
"ln -sf /home/me/.tmux/.tmux.conf /home/me/.tmux.conf",
],
},
},
Expand Down Expand Up @@ -73,14 +73,14 @@
"name": "upstream",
"fetch_url": "git+https://github.com/emre/kaptan",
"push_url": "git+https://github.com/emre/kaptan",
}
},
),
"ms": GitRemote(
**{
"name": "ms",
"fetch_url": "git+https://github.com/ms/kaptan.git",
"push_url": "git+https://github.com/ms/kaptan.git",
}
},
),
},
},
Expand Down
4 changes: 2 additions & 2 deletions tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,6 @@ def write_config(config_path: pathlib.Path, content: str) -> pathlib.Path:
return config_path


def load_raw(data: str, format: t.Literal["yaml", "json"]) -> dict[str, t.Any]:
def load_raw(data: str, fmt: t.Literal["yaml", "json"]) -> dict[str, t.Any]:
"""Load configuration data via string value. Accepts yaml or json."""
return ConfigReader._load(format=format, content=data)
return ConfigReader._load(fmt=fmt, content=data)
Loading
Loading