Skip to content

Commit

Permalink
fix: Update formatting and add missing typing
Browse files Browse the repository at this point in the history
This commit also fixes a bug introduced in v0.5.1 along with slightly
restructuring the imports in cli.py and commands/__init__.py to delay
importing other modules for a bit longer and clean up the
initialisation of the tool.
  • Loading branch information
multimac committed Aug 6, 2020
1 parent b00d082 commit 3199c6b
Show file tree
Hide file tree
Showing 20 changed files with 404 additions and 205 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ pip-log.txt
/test.py
/test_*.*

/setup.cfg
MANIFEST.in
/setup.py
/docs/site/*
Expand Down
36 changes: 19 additions & 17 deletions conventional/cli.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,10 @@
import asyncio
import enum
import logging
import pathlib
from typing import List

import confuse
import typer

from .commands import group as main
from .util.typer import ColorFormatter, TyperHandler

handler = TyperHandler()
handler.formatter = ColorFormatter()

logger = logging.getLogger()
logging.basicConfig(handlers=[handler], force=True)

# Importing aiocache results in a warning being logged. Temporarily disable it
# until it has been imported.
logging.getLogger("aiocache").setLevel(logging.ERROR)


class Verbosity(str, enum.Enum):
Expand Down Expand Up @@ -46,16 +32,32 @@ def init(
"""
Conventional - An extensible command-line tool for parsing and processing structured commits.
"""
import asyncio
import logging

import aiocache
from .util.config import find_project_configuration_file
import confuse

logging.getLogger().setLevel(getattr(logging, verbosity))
from .util.typer import ColorFormatter, TyperHandler

handler = TyperHandler()
handler.formatter = ColorFormatter()

logger = logging.getLogger()
logging.basicConfig(handlers=[handler], force=True)

# Importing aiocache results in a warning being logged. Temporarily disable it
# until it has been imported.
logging.getLogger("aiocache").setLevel(logging.ERROR)
import aiocache # noqa: F401

# Reset aiocache log level since aiocache has now been imported and unnecessary
# warning has been avioded.
logging.getLogger("aiocache").setLevel(logging.NOTSET)

from .util.config import find_project_configuration_file

logging.getLogger().setLevel(getattr(logging, verbosity))

config = confuse.Configuration("Conventional", "conventional")

project_config_file = asyncio.run(find_project_configuration_file())
Expand Down
26 changes: 20 additions & 6 deletions conventional/commands/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from asyncio import run
from typing import Optional

from confuse import Configuration
from typer import Context, FileText, Option, Typer

group = Typer()
Expand All @@ -17,14 +15,18 @@ def _list_commits(
mode="w",
),
from_rev: Optional[str] = Option(
None, "--from", help="The commit or tag to start from when listing commits from."
None,
"--from",
help="The commit or tag to start from when listing commits from.",
),
from_last_tag: bool = Option(
False,
"--from-last-tag",
help="If given, the commit list will start from the most-recent tag.",
),
to_rev: str = Option("HEAD", "--to", help="The commit or tag to stop at listing commits."),
to_rev: str = Option(
"HEAD", "--to", help="The commit or tag to stop at listing commits."
),
reverse: bool = Option(
False,
"--reverse",
Expand All @@ -41,6 +43,9 @@ def _list_commits(
"""
Retrieves commits from the git repository at PATH, or the current directory if PATH is not provided.
"""
from asyncio import run

from confuse import Configuration

from .list_commits import cli_main

Expand All @@ -64,7 +69,8 @@ def _parse_commit(
ctx: Context,
*,
input: FileText = Option(
"-", help="A file to read commits from. If `-`, commits will be read from stdin."
"-",
help="A file to read commits from. If `-`, commits will be read from stdin.",
),
output: FileText = Option(
"-",
Expand All @@ -78,11 +84,16 @@ def _parse_commit(
"""
Parses a stream of commits in the given file or from stdin.
"""
from asyncio import run

from confuse import Configuration

from .parse_commit import cli_main

config = ctx.find_object(Configuration)
run(cli_main(config, input=input, output=output, include_unparsed=include_unparsed,))
run(
cli_main(config, input=input, output=output, include_unparsed=include_unparsed,)
)


@group.command("template")
Expand Down Expand Up @@ -112,6 +123,9 @@ def _template(
"""
Reads a stream of commits from the given file or stdin and uses them to render a template.
"""
from asyncio import run

from confuse import Configuration

from .template import cli_main

Expand Down
10 changes: 8 additions & 2 deletions conventional/commands/list_commits.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ async def cli_main(
logger.warning("--include-unparsed is ignored without --parse")

stream = main(
config, from_rev=from_rev, from_last_tag=from_last_tag, to_rev=to_rev, reverse=reverse,
config,
from_rev=from_rev,
from_last_tag=from_last_tag,
to_rev=to_rev,
reverse=reverse,
) # type: AsyncIterable[Any]

if parse:
Expand Down Expand Up @@ -57,7 +61,9 @@ async def main(
except confuse.NotFoundError:
tag_filter = None

tags = await git.get_tags(pattern=tag_filter, sort="creatordate", reverse=True)
tags = await git.get_tags(
pattern=tag_filter, sort="creatordate", reverse=True
)
from_rev = next(tag["name"] for tag in tags if tag["name"] not in excluded)

async for commit in git.get_commits(start=from_rev, end=to_rev, reverse=reverse):
Expand Down
19 changes: 13 additions & 6 deletions conventional/commands/parse_commit.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import importlib
import json
import logging
from typing import Any, AsyncIterable, Optional, TextIO, TypedDict
from typing import Any, AsyncIterable, Optional, TextIO, TypedDict, cast

import confuse

Expand All @@ -24,13 +24,17 @@ def load_parser(config: confuse.Configuration) -> Parser[Any]:

custom_config = parser_config["config"]
cls = getattr(importlib.import_module(module), name)
return cls(custom_config)
return cast(Parser[Any], cls(custom_config))


async def cli_main(
config: confuse.Configuration, *, input: TextIO, output: TextIO, include_unparsed: bool,
):
async def _yield_input():
config: confuse.Configuration,
*,
input: TextIO,
output: TextIO,
include_unparsed: bool,
) -> None:
async def _yield_input() -> AsyncIterable[git.Commit]:
for line in input:
item = json.loads(line)
yield item
Expand All @@ -43,7 +47,10 @@ async def _yield_input():


async def main(
config: confuse.Configuration, *, input: AsyncIterable[git.Commit], include_unparsed: bool,
config: confuse.Configuration,
*,
input: AsyncIterable[git.Commit],
include_unparsed: bool,
) -> AsyncIterable[ParsedCommit]:

parser = load_parser(config)
Expand Down
49 changes: 30 additions & 19 deletions conventional/commands/template.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import fnmatch
import json
import logging
from typing import Any, AsyncIterable, Dict, List, Optional, TextIO, Tuple, TypedDict
from typing import Any, AsyncIterable, Dict, List, Optional, TextIO, Tuple, Type, TypedDict, cast

import confuse
import jinja2
import typer

from .. import git
from ..util.confuse import Filename
Expand All @@ -20,13 +22,10 @@ class Change(TypedDict):


class Version(Dict[Optional[str], List[Change]]):
def __init__(self, *arg, **kwargs):
super().__init__(*arg, **kwargs)

def has_commits(self):
def has_commits(self) -> bool:
return any(self.get_commits())

def get_commits(self):
def get_commits(self) -> List[Change]:
return [commit for commits in self.values() for commit in commits]


Expand All @@ -40,21 +39,27 @@ async def cli_main(
output: TextIO,
include_unparsed: bool,
unreleased_version: Optional[str],
):
async def _yield_input():
for line in input:
) -> None:
async def _yield_input(stream: TextIO) -> AsyncIterable[Change]:
for line in stream:
item = json.loads(line)
yield line
yield cast(Change, item)

async def _yield_commits():
async def _yield_commits() -> AsyncIterable[Change]:
from .list_commits import main as list_commits
from .parse_commit import main as parse_commit, ParsedCommit
from .parse_commit import main as parse_commit

def _yield_commit_range(from_rev: str, to_rev: str) -> AsyncIterable[ParsedCommit]:
def _yield_commit_range(
from_rev: Optional[str], to_rev: str
) -> AsyncIterable[Change]:
return parse_commit(
config,
input=list_commits(
config, from_rev=from_rev, from_last_tag=False, to_rev=to_rev, reverse=True,
config,
from_rev=from_rev,
from_last_tag=False,
to_rev=to_rev,
reverse=True,
),
include_unparsed=True,
)
Expand All @@ -65,7 +70,7 @@ def _yield_commit_range(from_rev: str, to_rev: str) -> AsyncIterable[ParsedCommi
except confuse.NotFoundError:
tag_filter = None

from_rev = None
from_rev = None # type: Optional[str]
for tag in await git.get_tags(pattern=tag_filter, sort="creatordate"):
if tag["name"] in excluded:
continue
Expand All @@ -88,7 +93,7 @@ def _yield_commit_range(from_rev: str, to_rev: str) -> AsyncIterable[ParsedCommi
yield commit

if input is not None:
commit_stream = _yield_input()
commit_stream = _yield_input(input)
else:
commit_stream = _yield_commits()

Expand Down Expand Up @@ -116,7 +121,9 @@ async def main(
def _is_unreleased(tag: Optional[git.Tag]) -> bool:
return tag is None or tag["name"] == unreleased_version

def _read_config(view: confuse.ConfigView, default: Any = DEFAULT, typ=str) -> Any:
def _read_config(
view: confuse.ConfigView, default: Any = DEFAULT, typ: Type = str
) -> Any:
try:
return view.get(typ)
except confuse.NotFoundError:
Expand Down Expand Up @@ -152,7 +159,9 @@ def _ignore_tag(tag: str) -> bool:
version[typ].append(change)

if change["source"]["tags"]:
tags = [tag for tag in change["source"]["tags"] if not _ignore_tag(tag["name"])]
tags = [
tag for tag in change["source"]["tags"] if not _ignore_tag(tag["name"])
]

if tags:
tag = sorted(tags, key=lambda tag: tag["name"])[0]
Expand All @@ -170,7 +179,9 @@ def _ignore_tag(tag: str) -> bool:

unreleased_tag: Optional[git.Tag] = None
if unreleased_version is not None:
logger.debug(f"Using {unreleased_version} as the version for unreleased commit(s)")
logger.debug(
f"Using {unreleased_version} as the version for unreleased commit(s)"
)
unreleased_tag = {
"name": unreleased_version,
"object_name": "",
Expand Down
27 changes: 22 additions & 5 deletions conventional/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,18 @@
import io
import logging
import pathlib
from asyncio import StreamReader
from asyncio.subprocess import Process
from typing import AsyncIterable, AsyncIterator, Dict, Iterable, List, Optional, TypedDict, cast
from typing import (
Any,
AsyncIterable,
AsyncIterator,
Dict,
Iterable,
List,
Optional,
TypedDict,
cast,
)

import aiocache
import dateutil.parser
Expand Down Expand Up @@ -109,7 +118,7 @@ async def _process_delimited_stream(


@contextlib.asynccontextmanager
async def _run(*args, **kwargs) -> AsyncIterator[Process]:
async def _run(*args: Any, **kwargs: Any) -> AsyncIterator[Process]:
logger.debug(f"Running command: {args}")
if "cwd" in kwargs and kwargs["cwd"] is not None:
logger.debug(f" in {kwargs['cwd']}")
Expand Down Expand Up @@ -162,7 +171,11 @@ async def is_git_repository(path: pathlib.PurePath = None) -> bool:


async def get_commits(
*, start: str = None, end: str = "HEAD", path: pathlib.PurePath = None, reverse: bool = False,
*,
start: str = None,
end: str = "HEAD",
path: pathlib.PurePath = None,
reverse: bool = False,
) -> AsyncIterable[Commit]:
"""Get the commits between start and end."""

Expand Down Expand Up @@ -208,7 +221,11 @@ async def get_commits(

@aiocache.cached()
async def get_tags(
*, path: pathlib.PurePath = None, pattern: str = None, sort: str = None, reverse: bool = False
*,
path: pathlib.PurePath = None,
pattern: str = None,
sort: str = None,
reverse: bool = False,
) -> Iterable[Tag]:
""" Gets all tags in the repository. """

Expand Down
Loading

0 comments on commit 3199c6b

Please sign in to comment.