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

main: disable colorama on Linux and flush output #494

Merged
merged 12 commits into from Oct 21, 2022
17 changes: 9 additions & 8 deletions .github/workflows/test.yml
Expand Up @@ -51,6 +51,8 @@ jobs:

steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Setup python for test ${{ matrix.py }}
uses: actions/setup-python@v4
Expand Down Expand Up @@ -91,10 +93,13 @@ jobs:
if: matrix.tox-target == 'min'
run: tox -e ${{env.BASE}}-${{ matrix.tox-target }}

- name: Rename coverage report file
if: matrix.tox-target == 'tox'
run: mv ".tox/coverage.${BASE}.xml" .tox/coverage.xml
shell: bash
- name: Run path test
if: matrix.tox-target == 'tox' && matrix.py == '3.10'
run: tox -e path

- name: Combine coverage files
if: always()
run: tox -e coverage

- uses: codecov/codecov-action@v3
if: always()
Expand All @@ -106,10 +111,6 @@ jobs:
env_vars: PYTHON
name: ${{ matrix.py }} - ${{ matrix.os }}

- name: Run path test
if: matrix.tox-target == 'tox' && matrix.py == '3.10'
run: tox -e path

type:
runs-on: ubuntu-latest
env:
Expand Down
36 changes: 21 additions & 15 deletions src/build/__main__.py
Expand Up @@ -4,6 +4,7 @@
import argparse
import contextlib
import os
import platform
import shutil
import subprocess
import sys
Expand Down Expand Up @@ -46,6 +47,10 @@ def _init_colors() -> Dict[str, str]:
_STYLES = _init_colors()


def _cprint(fmt: str = '', msg: str = '') -> None:
print(fmt.format(msg, **_STYLES), flush=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! I just noticed the flush=True. I was going to do a follow up PR since I noticed that build's output can get mangled with the build system's output if it goes to stderr. But there's a flush here already! :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, because Python default output buffering is evil )

#494 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely no argument there!!! Dealing with this in cibuildwheel, scikit-build, etc.



def _showwarning(
message: Union[Warning, str],
category: Type[Warning],
Expand All @@ -54,18 +59,19 @@ def _showwarning(
file: Optional[TextIO] = None,
line: Optional[str] = None,
) -> None: # pragma: no cover
print('{yellow}WARNING{reset} {}'.format(message, **_STYLES))
_cprint('{yellow}WARNING{reset} {}', str(message))


def _setup_cli() -> None:
warnings.showwarning = _showwarning

try:
import colorama
except ModuleNotFoundError:
pass
else:
colorama.init() # fix colors on windows
if platform.system() == 'Windows':
try:
import colorama

colorama.init()
except ModuleNotFoundError:
pass
abitrolly marked this conversation as resolved.
Show resolved Hide resolved


def _error(msg: str, code: int = 1) -> NoReturn: # pragma: no cover
Expand All @@ -75,20 +81,20 @@ def _error(msg: str, code: int = 1) -> NoReturn: # pragma: no cover
:param msg: Error message
:param code: Error code
"""
print('{red}ERROR{reset} {}'.format(msg, **_STYLES))
_cprint('{red}ERROR{reset} {}', msg)
raise SystemExit(code)


class _ProjectBuilder(ProjectBuilder):
@staticmethod
def log(message: str) -> None:
print('{bold}* {}{reset}'.format(message, **_STYLES))
_cprint('{bold}* {}{reset}', message)


class _IsolatedEnvBuilder(IsolatedEnvBuilder):
@staticmethod
def log(message: str) -> None:
print('{bold}* {}{reset}'.format(message, **_STYLES))
_cprint('{bold}* {}{reset}', message)


def _format_dep_chain(dep_chain: Sequence[str]) -> str:
Expand Down Expand Up @@ -119,7 +125,7 @@ def _build_in_current_env(
missing = builder.check_dependencies(distribution)
if missing:
dependencies = ''.join('\n\t' + dep for deps in missing for dep in (deps[0], _format_dep_chain(deps[1:])) if dep)
print()
_cprint()
_error(f'Missing dependencies:{dependencies}')

return builder.build(distribution, outdir, config_settings or {})
Expand Down Expand Up @@ -147,7 +153,7 @@ def _handle_build_error() -> Iterator[None]:
_error(str(e))
except BuildBackendException as e:
if isinstance(e.exception, subprocess.CalledProcessError):
print()
_cprint()
_error(str(e))

if e.exc_info:
Expand All @@ -160,7 +166,7 @@ def _handle_build_error() -> Iterator[None]:
tb = ''.join(tb_lines)
else:
tb = traceback.format_exc(-1)
print('\n{dim}{}{reset}\n'.format(tb.strip('\n'), **_STYLES))
_cprint('\n{dim}{}{reset}\n', tb.strip('\n'))
_error(str(e))


Expand Down Expand Up @@ -370,10 +376,10 @@ def main(cli_args: Sequence[str], prog: Optional[str] = None) -> None: # noqa:
artifact_list = _natural_language_list(
['{underline}{}{reset}{bold}{green}'.format(artifact, **_STYLES) for artifact in built]
)
print('{bold}{green}Successfully built {}{reset}'.format(artifact_list, **_STYLES))
_cprint('{bold}{green}Successfully built {}{reset}', artifact_list)
except Exception as e: # pragma: no cover
tb = traceback.format_exc().strip('\n')
print('\n{dim}{}{reset}\n'.format(tb, **_STYLES))
_cprint('\n{dim}{}{reset}\n', tb)
_error(str(e))


Expand Down
16 changes: 7 additions & 9 deletions tox.ini
Expand Up @@ -47,9 +47,9 @@ commands =
description = verify build can run from source (bootstrap)
setenv =
PYTHONPATH = {toxinidir}/src
commands =
python -E -m pip uninstall -y build
pytest -ra {posargs:-n auto}
COVERAGE_FILE = {toxworkdir}/.coverage.{envname}
commands_pre =
python -E -m pip uninstall -y build colorama

[testenv:type]
description = run type check on code base
Expand All @@ -60,9 +60,8 @@ commands =
[testenv:{py311, py310, py39, py38, py37, py36, pypy37, pypy38, pypy39}-min]
description = check minimum versions required of all dependencies
skip_install = true
commands =
commands_pre =
pip install .[test] -c tests/constraints.txt
pytest -ra {posargs:-n auto}

[testenv:docs]
description = build documentations
Expand Down Expand Up @@ -90,19 +89,18 @@ description = combine coverage from test environments
passenv =
DIFF_AGAINST
setenv =
COVERAGE_FILE = {toxworkdir}/.coverage
skip_install = true
deps =
coverage>=5.1
coverage[toml]>=5.1
diff_cover>=3
parallel_show_output = true
commands =
coverage combine
coverage combine {toxworkdir}
coverage report --skip-covered --show-missing -i
coverage xml -o {toxworkdir}/coverage.xml -i
coverage html -d {toxworkdir}/htmlcov -i
python -m diff_cover.diff_cover_tool --compare-branch {env:DIFF_AGAINST:origin/main} {toxworkdir}/coverage.xml
depends = {py311, py310, py39, py38, py37, py36, pypy37, pypy38, pypy39}
depends = {py311, py310, py39, py38, py37, py36, pypy37, pypy38, pypy39}{,-min}, path

[flake8]
max-line-length = 127
Expand Down