def test_plural():
    cow = Plural("cow", "cows")
    glass = Plural("glass", "glasses")

    n = 1
    assert f"The farmer has {n} {cow(n)}." == "The farmer has 1 cow."
    assert f"The bar has {n} {glass(n)}." == "The bar has 1 glass."

    n = 2
    assert f"The farmer has {n} {cow(n)}." == "The farmer has 2 cows."
    assert f"The bar has {n} {glass(n)}." == "The bar has 2 glasses."

    n = 3
    assert f"The farmer has {n} {cow(n)}." == "The farmer has 3 cows."
    assert f"The bar has {n} {glass(n)}." == "The bar has 3 glasses."

    assert repr(cow) == "Plural('cow', 'cows')"
    assert repr(glass) == "Plural('glass', 'glasses')"
Exemple #2
0
def check(
    pyproject_file: "PathLike" = "pyproject.toml",
    parser_class: str = "pyproject_parser:PyProject",
    show_traceback: bool = False,
):
    """
	Validate the given ``pyproject.toml`` file.
	"""

    # 3rd party
    import dom_toml
    from dom_toml.parser import BadConfigError
    from domdf_python_tools.paths import PathPlus
    from domdf_python_tools.words import Plural, word_join

    # this package
    from pyproject_parser.parsers import BuildSystemParser, PEP621Parser

    pyproject_file = PathPlus(pyproject_file)

    click.echo(f"Validating {str(pyproject_file)!r}")

    with handle_tracebacks(show_traceback, CustomTracebackHandler):
        parser: Type[PyProject] = resolve_class(parser_class, "parser-class")
        parser.load(filename=pyproject_file)

        raw_config = dom_toml.load(pyproject_file)

        _keys = Plural("key", "keys")

        def error_on_unknown(keys: Iterable[str], expected_keys: Iterable[str],
                             table_name: str):
            unknown_keys = set(keys) - set(expected_keys)

            if unknown_keys:
                raise BadConfigError(
                    f"Unknown {_keys(len(unknown_keys))} in '[{table_name}]': "
                    f"{word_join(sorted(unknown_keys), use_repr=True)}", )

        # Implements PEPs 517 and 518
        error_on_unknown(
            raw_config.get("build-system", {}).keys(), BuildSystemParser.keys,
            "build-system")

        # Implements PEP 621
        error_on_unknown(
            raw_config.get("project", {}).keys(),
            {*PEP621Parser.keys, "dynamic"}, "project")
Exemple #3
0
__all__ = ["ClickDirective", "nested_option", "setup"]


class NestedOption(str, enum.Enum):  # noqa: SLOT000
	NESTED_FULL = "full"
	NESTED_SHORT = "short"
	NESTED_NONE = "none"


NESTED_FULL = NestedOption.NESTED_FULL
NESTED_SHORT = NestedOption.NESTED_SHORT
NESTED_NONE = NestedOption.NESTED_NONE

click_purger = Purger("all_click")
_argument = Plural("argument", "argument(s)")


def _indent(text: str):
	return '\n'.join([f"    {line}" if not line.isspace() else line for line in text.split('\n')])


def _get_usage(ctx: click.Context) -> str:
	"""
	Alternative, non-prefixed version of 'get_usage'.
	"""

	formatter = ctx.make_formatter()
	pieces = ctx.command.collect_usage_pieces(ctx)
	formatter.write_usage(ctx.command_path, ' '.join(pieces), prefix='')
	return formatter.getvalue().rstrip('\n')
    "load_toml",
    "check_module",
    "paths_to_modules",
    "ConfigDict",
    "ImportChecker",
    "OK",
    "Error",
)

__author__: str = "Dominic Davis-Foster"
__copyright__: str = "2021 Dominic Davis-Foster"
__license__: str = "MIT License"
__version__: str = "0.4.1"
__email__: str = "*****@*****.**"

_module = Plural("module", "modules")


class ConfigDict(TypedDict, total=False):
    """
	:class:`typing.TypedDict` representing the configuration mapping parsed from ``pyproject.toml`` or similar.
	"""

    #: List of modules to always try to import.
    always: List[str]

    #: Mapping of :pep:`508` markers to lists of imports to try to import if the markers evaluate to :py:obj:`True`.
    only_if: Mapping[str, List[str]]

    #: Configuration for ``importcheck``.
    config: Dict[str, Any]
Exemple #5
0
# this package
from consolekit.terminal_colours import ColourTrilean, resolve_color_default, strip_ansi
from consolekit.utils import TerminalRenderer

__all__ = [
    "MarkdownHelpCommand",
    "MarkdownHelpGroup",
    "MarkdownHelpMixin",
    "RawHelpCommand",
    "RawHelpGroup",
    "RawHelpMixin",
    "SuggestionGroup",
    "ContextInheritingGroup",
]

_argument = Plural("argument", "arguments")


class RawHelpMixin:
    """
	Mixin class for :class:`click.Command` and :class:`click.Group` which leaves the help text unformatted.

	.. seealso:: :class:`~.RawHelpCommand` and :class:`~.RawHelpGroup`

	.. tip:: This can be combined with groups such as :class:`~.SuggestionGroup`.

	.. versionadded:: 0.8.0
	"""

    help: Optional[str]  # noqa: A003  # pylint: disable=redefined-builtin
from domdf_python_tools.words import Plural
from packaging.requirements import InvalidRequirement
from shippinglabel.requirements import ComparableRequirement
from sphinx.environment import BuildEnvironment
from sphinx.util.docutils import SphinxDirective

# this package
from sphinxcontrib.extras_require.purger import extras_require_purger
from sphinxcontrib.extras_require.sources import sources

__all__ = [
    "ExtrasRequireDirective", "validate_requirements", "make_node_content",
    "get_requirements"
]

_requirement = Plural("requirement", "requirements")


class ExtrasRequireDirective(SphinxDirective):
    """
	Directive to show a notice to users that a module, class or function has additional requirements.
	"""

    has_content: bool = True

    #: One argument is required, the name of the extra (e.g. "testing", "docs")
    required_arguments: int = 1

    option_spec = {source[0]: source[2] for source in sources}
    option_spec["scope"] = str
Exemple #7
0
import click
from domdf_python_tools.paths import PathPlus, unwanted_dirs
from domdf_python_tools.typing import PathLike
from domdf_python_tools.words import Plural
from rich.console import Console
from rich.syntax import Syntax

__author__: str = "Dominic Davis-Foster"
__copyright__: str = "2020 Dominic Davis-Foster"
__license__: str = "MIT License"
__version__: str = "0.0.0"
__email__: str = "*****@*****.**"

__all__ = ["greppy"]

_match = Plural("match", "matches")


def greppy(
    pattern: Union[Pattern, str],
    search_dir: PathLike = '.',
    *,
    summary: bool = False,
    file: IO = None,
) -> Set[PathPlus]:
    """
	Recursively grep over Python files in the files in the given directory, and search for ``pattern``.

	:param pattern: The pattern to search for.
	:param search_dir: The directory to search in.
	:param summary: Show only a summary of the results.
Exemple #8
0
#  Copyright (C) 2012-2016 Ian Cordasco <*****@*****.**>
#  MIT Licensed
#

# stdlib
from typing import Tuple

# 3rd party
import click
import flake8.main.application  # type: ignore
from domdf_python_tools.words import Plural
from typing_extensions import NoReturn

__all__ = ["Application"]

_error = Plural("error", "errors")
_file = Plural("file", "files")


class Application(flake8.main.application.Application):
    """
	Wrapper around flake8 providing a formatted count at the end.
	"""
    def exit(self) -> NoReturn:  # noqa: A003  # pylint: disable=redefined-builtin
        """
		Handle finalization and exiting the program.

		This should be the last thing called on the application instance.
		It will check certain options and exit appropriately.
		"""