#2244 cli: progress bar fixes, and 'copr build' uploads first
Merged 2 years ago by praiskup. Opened 2 years ago by praiskup.
Unknown source progress-fix  into  main

file modified
+56 -44
@@ -36,7 +36,7 @@

  from copr_cli.helpers import cli_use_output_format

  from copr_cli.monitor import cli_monitor_parser

  from copr_cli.printers import cli_get_output_printer as get_printer

- from .util import ProgressBar, serializable

+ from copr_cli.util import get_progress_callback, serializable

  from .build_config import MockProfile

  

  
@@ -103,7 +103,7 @@

          setattr(namespace, self.dest, values)

  

  

- def buildopts_from_args(args, progress_callback):

+ def buildopts_from_args(args, progress_callback=None):

      """

      For all the build commands, parse the common set of build options.

      """
@@ -203,6 +203,16 @@

              owner = self.ownername

          return owner, name

  

+     def parse_dirname(self, name):

+         """

+         From specified <owner>/<dirname> or just <dirname> return the

+         tripled (owner, project, dirname).

+         """

+         owner, dirname = self.parse_name(name)

+         project = dirname.split(':')[0]

+         return owner, project, dirname

+ 

+ 

      def build_url(self, build_id):

          """

          Return the "generic" predictable url for build_id, which redirects
@@ -319,29 +329,34 @@

          # that the user actually has a valid credentials.

          self.client.base_proxy.auth_check()

  

+         username, projectname, project_dirname = self.parse_dirname(args.copr_repo)

+ 

          builds = []

          for pkg in args.pkgs:

              if os.path.exists(pkg):

-                 bar = ProgressBar(max=os.path.getsize(pkg))

-                 build_function = self.client.build_proxy.create_from_file

+                 progress_callback = get_progress_callback(os.path.getsize(pkg))

+                 buildopts = buildopts_from_args(args, progress_callback)

                  data = {"path": pkg}

- 

-                 # pylint: disable=function-redefined

-                 def progress_callback(monitor):

-                     bar.next(n=8192)

- 

                  print('Uploading package {0}'.format(pkg))

+                 try:

+                     builds.append(self.client.build_proxy.create_from_file(

+                         ownername=username, projectname=projectname,

+                         project_dirname=project_dirname, buildopts=buildopts,

+                         **data))

+                 finally:

+                     if progress_callback:

+                         progress_callback.finish()

              elif not urlparse(pkg).scheme:

                  raise CoprException("File {0} not found".format(pkg))

              else:

-                 bar = None

-                 progress_callback = None

-                 build_function = self.client.build_proxy.create_from_url

+                 buildopts = buildopts_from_args(args)

                  data = {"url": pkg}

+                 builds.append(self.client.build_proxy.create_from_url(

+                     ownername=username, projectname=projectname,

+                     project_dirname=project_dirname, buildopts=buildopts,

+                     **data))

  

-             builds.append(self.process_build(args, build_function, data, bar=bar, progress_callback=progress_callback))

- 

-         return builds

+         self.print_build_info_and_wait(builds, args)

  

      @requires_api_auth

      def action_build_pypi(self, args):
@@ -412,33 +427,34 @@

              data[arg] = getattr(args, arg)

          return self.process_build(args, self.client.build_proxy.create_from_custom, data)

  

-     def process_build(self, args, build_function, data, bar=None, progress_callback=None):

-         username, project_dirname = self.parse_name(args.copr_repo)

-         projectname = project_dirname.split(':')[0]

+     def print_build_info_and_wait(self, builds, args):

+         """

+         Print to stdout information about just submitted builds.  Note that our

+         users parse this non-parseable output, because we don't have issue #224

+         fixed.

+         """

  

-         try:

-             buildopts = buildopts_from_args(args, progress_callback)

-             result = build_function(ownername=username, projectname=projectname,

-                                     project_dirname=project_dirname, buildopts=buildopts, **data)

+         print("Build was added to {0}:".format(builds[0].projectname))

  

-             builds = result if type(result) == list else [result]

-             print("Build was added to {0}:".format(builds[0].projectname))

+         for build in builds:

+             print("  {0}".format(self.build_url(build.id)))

  

-             for build in builds:

-                 print("  {0}".format(self.build_url(build.id)))

+         build_ids = [build.id for build in builds]

+         print("Created builds: {0}".format(" ".join(map(str, build_ids))))

  

-             build_ids = [build.id for build in builds]

-             print("Created builds: {0}".format(" ".join(map(str, build_ids))))

+         if not args.nowait:

+             self._watch_builds(build_ids)

  

-             if not args.nowait:

-                 self._watch_builds(build_ids)

  

-         except CoprException as ex:

-             sys.stderr.write(str(ex) + "\n")

-             sys.exit(1)

-         finally:

-             if bar:

-                 bar.finish()

+     def process_build(self, args, build_function, data):

+         username, projectname, project_dirname = self.parse_dirname(args.copr_repo)

+         buildopts = buildopts_from_args(args)

+         result = build_function(ownername=username,

+                                 projectname=projectname,

+                                 project_dirname=project_dirname,

+                                 buildopts=buildopts, **data)

+         builds = result if type(result) == list else [result]

+         self.print_build_info_and_wait(builds, args)

  

  

      @requires_api_auth
@@ -897,17 +913,13 @@

          print("Package's default source was successfully reseted.")

  

      def action_build_package(self, args):

-         ownername, project_dirname = self.parse_name(args.copr_repo)

-         projectname = project_dirname.split(':')[0]

-         buildopts = buildopts_from_args(args, None)

+         ownername, projectname, project_dirname = self.parse_dirname(args.copr_repo)

+ 

+         buildopts = buildopts_from_args(args)

          build = self.client.package_proxy.build(ownername=ownername, projectname=projectname,

                                                  packagename=args.name, buildopts=buildopts,

                                                  project_dirname=project_dirname)

-         print("Build was added to {0}.".format(build.projectname))

-         print("Created builds: {0}".format(build.id))

- 

-         if not args.nowait:

-             self._watch_builds([build.id])

+         self.print_build_info_and_wait([build], args)

  

      def action_build_module(self, args):

          """

file modified
+39 -28
@@ -6,43 +6,54 @@

  

  try:

      from progress.bar import Bar

- except ImportError:

-     progress = False

- else:

-     progress = True

  

+     class SpeedProgressBar(Bar):

+         """

+         Modified progress.bar.Bar with additional formatters %(download_speed)

+         and %(downloaded), with additional interface supported by

+         MultipartEncoderMonitor API.

+         Bar accepts the last N downloaded bytes, while MultipartEncoderMonitor

+         callback provides the total number of downloaded bytes.  N needs to be

+         calculated.

+         """

  

- class ProgressMixin(object):

- 

-     @property

-     def download_speed(self):

-         if self.avg == 0.0:

-             return "..."

-         return "{0}/s".format(humanize.naturalsize(1 / self.avg))

+         message = "%(percent)d%%"

+         suffix = "%(downloaded)s %(download_speed)s eta %(eta_td)s"

+         read_last = 0

  

-     @property

-     def downloaded(self):

-         return humanize.naturalsize(self.index)

+         @property

+         def download_speed(self):

+             """ Inverted value of Bar.avg """

+             if self.avg == 0.0:

+                 return "..."

+             return "{0}/s".format(humanize.naturalsize(1 / self.avg))

  

+         @property

+         def downloaded(self):

+             """ How many bytes are already downloaded """

+             return humanize.naturalsize(self.index)

  

- class DummyBar(object):

-     # pylint: disable=redefined-builtin

-     def __init__(self, max=None):

-         pass

+         def __call__(self, monitor):

+             """ MultipartEncoderMonitor expects callable """

+             read = monitor.bytes_read - self.read_last

+             self.read_last = monitor.bytes_read

+             self.next(read)

  

-     def next(self, n=None):

-         pass

  

-     def finish(self):

-         pass

+ except ImportError:

+     progress = False

+ else:

+     progress = True

  

  

- if progress:

-     class ProgressBar(Bar, ProgressMixin):

-         message = "%(percent)d%%"

-         suffix = "%(downloaded)s %(download_speed)s eta %(eta_td)s"

- else:

-     ProgressBar = DummyBar

+ def get_progress_callback(length):

+     """

+     If python-progress is installed, instantiate progress bar object.  Otherwise

+     just return None.

+     """

+     if not progress:

+         return None

+     return SpeedProgressBar(max=length)

  

  

  def serializable(result):

no initial comment

Build succeeded.

3 new commits added

  • cli: sync 'copr build' with other 'copr build*' methods
  • cli: de-duplicate printing builds, and waiting
  • cli: de-duplicate logic for taking dirname from arg
2 years ago

Build failed. More information on how to proceed and troubleshoot errors available at https://fedoraproject.org/wiki/Zuul-based-ci

rebased onto 026e64f

2 years ago

rebased onto 026e64f

2 years ago

Build failed. More information on how to proceed and troubleshoot errors available at https://fedoraproject.org/wiki/Zuul-based-ci

Build succeeded.

LGTM, but the progress bar was indeed complicated, so I might have missed something :-)

Commit 8fe1398 fixes this pull-request

Pull-Request has been merged by praiskup

2 years ago