Skip to content

Commit

Permalink
Extract out ProgressPrinter
Browse files Browse the repository at this point in the history
This is a preparation before supporting 'clang-cl' for Windows (google#1179).

Our plan is to download LLVM for Windows in 'update_deps.py', and in
that process we would like to use 'ProgressPrinter' to show progress for
both downloading the archive and extracting it.

To avoid code duplicate between 'build_qt.py' and 'update_deps.py',
let's extract 'ProgressPrinter' into a new file first.

This is a mechanical refactoring commit. There must be no observable
behavior change.
  • Loading branch information
yukawa committed Feb 18, 2025
1 parent 76343ff commit ca202a1
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 118 deletions.
63 changes: 2 additions & 61 deletions src/build_tools/build_qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,9 @@
import subprocess
import sys
import tarfile
import time
from typing import Any, Union

from progress_printer import ProgressPrinter
from vs_util import get_vs_env_vars


Expand Down Expand Up @@ -156,66 +157,6 @@ def is_linux() -> bool:
return os.name == 'posix' and os.uname()[0] == 'Linux'


class ProgressPrinter:
"""A utility to print progress message with carriage return and trancatoin."""

def __enter__(self):
if not sys.stdout.isatty():

class NoOpImpl:
"""A no-op implementation in case stdout is not attached to concole."""

def print_line(self, msg: str) -> None:
"""No-op implementation.
Args:
msg: Unused.
"""
del msg # Unused
return

def cleanup(self) -> None:
pass

self.impl = NoOpImpl()
return self

class Impl:
"""A real implementation in case stdout is attached to concole."""

last_output_time_ns = time.time_ns()

def print_line(self, msg: str) -> None:
"""Print the given message with carriage return and trancatoin.
Args:
msg: Message to be printed.
"""
colmuns = os.get_terminal_size().columns
now = time.time_ns()
if (now - self.last_output_time_ns) < 25000000:
return
msg = msg + ' ' * max(colmuns - len(msg), 0)
msg = msg[0:(colmuns)] + '\r'
sys.stdout.write(msg)
sys.stdout.flush()
self.last_output_time_ns = now

def cleanup(self) -> None:
colmuns = os.get_terminal_size().columns
sys.stdout.write(' ' * colmuns + '\r')
sys.stdout.flush()

self.impl = Impl()
return self

def print_line(self, msg: str) -> None:
self.impl.print_line(msg)

def __exit__(self, *exc):
self.impl.cleanup()


def qt_extract_filter(
members: Iterator[tarfile.TarInfo],
) -> Iterator[tarfile.TarInfo]:
Expand Down
95 changes: 95 additions & 0 deletions src/build_tools/progress_printer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# -*- coding: utf-8 -*-
# Copyright 2010-2021, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""A console utility to show progress."""

import os
import sys
import time


class ProgressPrinter:
"""A utility to print progress message with carriage return and trancatoin."""

def __enter__(self):
if not sys.stdout.isatty():

class NoOpImpl:
"""A no-op implementation in case stdout is not attached to concole."""

def print_line(self, msg: str) -> None:
"""No-op implementation.
Args:
msg: Unused.
"""
del msg # Unused
return

def cleanup(self) -> None:
pass

self.impl = NoOpImpl()
return self

class Impl:
"""A real implementation in case stdout is attached to concole."""

last_output_time_ns = time.time_ns()

def print_line(self, msg: str) -> None:
"""Print the given message with carriage return and trancatoin.
Args:
msg: Message to be printed.
"""
colmuns = os.get_terminal_size().columns
now = time.time_ns()
if (now - self.last_output_time_ns) < 25000000:
return
msg = msg + ' ' * max(colmuns - len(msg), 0)
msg = msg[0:(colmuns)] + '\r'
sys.stdout.write(msg)
sys.stdout.flush()
self.last_output_time_ns = now

def cleanup(self) -> None:
colmuns = os.get_terminal_size().columns
sys.stdout.write(' ' * colmuns + '\r')
sys.stdout.flush()

self.impl = Impl()
return self

def print_line(self, msg: str) -> None:
self.impl.print_line(msg)

def __exit__(self, *exc):
self.impl.cleanup()
59 changes: 2 additions & 57 deletions src/build_tools/update_deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@
import shutil
import stat
import subprocess
import sys
import time
import zipfile

import requests

from progress_printer import ProgressPrinter


ABS_SCRIPT_PATH = pathlib.Path(__file__).absolute()
# src/build_tools/fetch_deps.py -> src/
Expand Down Expand Up @@ -182,61 +182,6 @@ def download(archive: ArchiveInfo, dryrun: bool = False) -> None:
)


class ProgressPrinter:
"""A utility to print progress message with carriage return and trancatoin."""

def __enter__(self):
if not sys.stdout.isatty():

class NoOpImpl:
"""A no-op implementation in case stdout is not attached to concole."""

def print_line(self, msg: str) -> None:
"""No-op implementation.
Args:
msg: Unused.
"""
del msg # Unused
return

self.cleaner = None
return NoOpImpl()

class Impl:
"""A real implementation in case stdout is attached to concole."""
last_output_time_ns = time.time_ns()

def print_line(self, msg: str) -> None:
"""Print the given message with carriage return and trancatoin.
Args:
msg: Message to be printed.
"""
colmuns = os.get_terminal_size().columns
now = time.time_ns()
if (now - self.last_output_time_ns) < 25000000:
return
msg = msg + ' ' * max(colmuns - len(msg), 0)
msg = msg[0 : (colmuns)] + '\r'
sys.stdout.write(msg)
sys.stdout.flush()
self.last_output_time_ns = now

class Cleaner:
def cleanup(self) -> None:
colmuns = os.get_terminal_size().columns
sys.stdout.write(' ' * colmuns + '\r')
sys.stdout.flush()

self.cleaner = Cleaner()
return Impl()

def __exit__(self, *exc):
if self.cleaner:
self.cleaner.cleanup()


def extract_ninja(dryrun: bool = False) -> None:
"""Extract ninja-win archive.
Expand Down

0 comments on commit ca202a1

Please sign in to comment.