#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
#
#
# Missing docstring; pylint: disable=C0111
#
import inspect
import itertools
import math
import sys
import six
import time
# Redefining built-in 'range'; pylint: disable=W0622
# Imports from package six are not grouped: pylint: disable=C0412
"""Thrown if a ProgressTracker determines that it can't be instantiated.
For example, the tracker which depends on a UNIX style terminal should
throw this exception if it can't find a valid terminal."""
return "ProgressTrackerException: {0}".format(
format2=None):
"""Format a pair of numbers 'v1' and 'v2' representing a fraction, such
as v1=3 v2=200, such that for all anticipated values of v1 (0 through
v2) , the result is a fixed width pair separated by '/':
format_pair("{0:d}", 3, 200) --> " 3/200"
'format1' is the preferred number format. In the event that targetwidth
is specified and the width of (format1.format(v2) > targetwidth), then
'format2' is used instead:
format_pair("{0:.1f}", 20.322, 1000.23,
targetwidth=5, format2="{0:d}") --> " 20/1000"
This provides a mechanism for downshifting the accuracy of an output
to preserve column width.
Inputs are scaled (divided by 'scale') if scale is specified."""
if scale:
# see if format2 is shorter.
# convert type 'float' to 'int'.
if "d" in format2:
else:
if "d" in v1format:
else:
"""This class implements a rudimentary download speed estimator.
newdata() is used to indicate download progress; curl calls
us back pretty frequently so that's not a terrible way to
go. Download progress records are kept on a deque, and are
expired after self.interval seconds have elapsed. Speed estimates
are smoothed so that things don't bounce around too fast.
The class also implements some heuristics designed to prevent
handing out crappy estimates early in the download."""
# INTERVAL describes the interval, in seconds, which is used to
# compute the download speed.
# This is the decay rate (or how much we mix in the historical
# notion of speed into the current notion).
# Ok to modify this during operation.
self.__last_smooth_speed = None
self.__starttime = None
self.__donetime = None
if speed is None:
return None
#
# A little hack to keep things tidy: if the length of
# the speedstr > 5, we whack off the floating point
# portion.
#
"{num:d}{shortunit}")
speedstr += "/s"
return speedstr
"""Add new data as it becomes available; timestamp can be
overridden, although this is primarily designed for testing."""
# must be started before adding data (sorry)
assert self.__starttime
#
# Step 1: Insert latest datum
#
#
# Step 2: Expunge old data
#
else:
break
#
# Step 3: Recompute the estimate
#
# compute time delta between front and back of deque
# can't operate yet
return
#
# 'ratiocomplete' is just the percentage done. It is
# used to disable 'startup mode' if the d/l completes
# very rapidly. We'll always start giving the user an
# estimate once ratiocomplete >= 50%.
# pylint is picky about this message:
# old-division; pylint: disable=W1619
#
# Keep track of whether we're in the warmup phase. This
# is used to deny estimates to callers until we feel good
# about them. This is very heuristic; it's a higher bar than
# we use below for disabling the estimate, basically because
# we want to open with a solid estimate.
#
#
# Even if we haven't accomplished the above requirements,
# exit startup mode when we're 1/3 done or more.
#
#
# Take a look at the deque length as well as how much an
# interval's worth of data we have. If it is quite short,
# maybe the download has stalled out, or perhaps the user
# used ctrl-z and then resumed; disable the estimate until we
# build up more data.
#
if self.__last_smooth_speed is None:
else:
assert not self.__starttime
assert not self.__donetime
not self.__last_smooth_speed:
return None
if self.__donetime is None:
return None
try:
# pylint is picky about this message:
# old-division; pylint: disable=W1619
except ZeroDivisionError:
return None
return None if self.__donetime is None else \
s = "<SpeedEstimator: "
d.pop("_SpeedEstimator__deque")
s += str(d)
s += " __deque=["
if x % 3 == 0:
s += "\n "
s += "(t={0:>.3f}, b={1:5d}), ".format(
s += "]>"
return s
"""This helper class is used to implement damping of excessive
printing by progress trackers.
'print_value': This is a handy 'clicker' attribute which can be
read to get a monotonically increasing count of the number of times
time_to_print() has returned True. Can be used to key a spinner,
e.g.:
print("{0}".format(pt.print_value.format(len(__spinner_chars))))
"""
#
# See if it has been more than __delay time since the last time we
# indicated that it was time to print. If this returns true, the
# caller should go ahead and print; this will not return true again
# until the 'delay' period has elapsed again.
#
return False
return True
"""OutSpec is used by the progress tracker frontend to convey
contextual information to backend routines about the output
being requested. 'first' means "this is the first output
for this group of items" (so perhaps print a header).
'last' similarly means "this is the last output for this
group of items." Additional strings can be passed via
the 'changed' list, denoting other events of significance."""
s = "<outspec:"
s += ">"
return s
# Defining "boolness" of a class, Python 2 uses the special method
# called __nonzero__() while Python 3 uses __bool__(). For Python
# 2 and 3 compatibility, define __bool__() only, and let
# __nonzero__ = __bool__
"""This class describes an item of interest in tracking progress
against some "bucket" of work (for example, searching a filesystem for
some item).
This provides a way to wrap together begin and end times of the
operation, the operation's name, and 'curinfo'-- some additional
tidbit of information (such as the current directory being scanned)."""
#
# Used by clients to track if this item has been printed yet.
# The object itself does not care about the value of this
# attribute but will clear it on reset()
#
#
# This attribute allows us to hang some client data
# off of this object; use this to store some information
# about the thing we're currently working on.
#
# This is a kludge but I can't find a better way to do this
# and keep pylint's "definied outside of __init__" rule (W0201)
# happy, without either repeating all of this code twice, or
# disabling the rule file-wide. Both of which seem even worse.
#
# Start 'starttime' when 'items' is first set (even to zero)
# Note that starttime is initially set to -1 to avoid starting
# the timer during __init__().
#
# Special behavior only for 'items' and only when not resetting
return
"can't set items after explicit done(). " \
"Tried to set {0}={1} (is {2})".format(
return 0.0
if endtime is None:
info = ""
"""This class extends TrackerItem to include the notion of progress
towards some goal which is known in advance of beginning the operation
(such as downloading 37 packages). In addition to the features of
TrackerItem, this class provides helpful routines for conversion to
printable strings of the form " 3/100"."""
# See comment in superclass.
# start 'starttime' when items gets set to non-zero
# Special behavior only for 'items' and only when not resetting
return
"can't set values after explicit done(). " \
"Tried to set {0}={1} (is {2})".format(
# see if this is the first time we're setting items
raise RuntimeError(
"Cannot alter items until goalitems is set")
# Arguments number differs from overridden method;
# pylint: disable=W0221
# See if we indeed met our goal.
exstr = _("Goal mismatch '{name}': "
"expected goal: {expected}, "
"current value: {current}").format(
return True
# For use when you want to display something happening,
# such as: Downloading item 3/3, since typically items is
# not incremented until after the operation completes.
#
# To ensure that we don't print 4/3 in the last iteration of
# output, we also account for that case.
else:
"""Returns progress towards a goal as a percentage.
i.e. 37 / 100 would yield 37.0"""
return 0
# pylint is picky about this message:
# old-division; pylint: disable=W1619
info = ""
#
# This implements a decorator which is used to mark methods in
# this class as abstract-- needing to be implemented by subclasses.
#
# This is similar to, but looser than, the sorts of abstractness
# enforcement we'd get from using python's abc module; in abc,
# abstractness is checked and enforced at construction time. Some
# of our subclasses are more dynamic than that-- building out
# the required methods at __init__ time.
#
# Unused argument 'args', 'kwargs'; pylint: disable=W0613
raise NotImplementedError("{0} is abstract in "
"superclass; you must implement it in your "
return enforce_abstract
#
# We define a separate class to hold the set of interfaces which comprise
# a progress tracker 'backend'. This mix-in allows introspection by
# subclasses about which interfaces actually comprise the backend APIs
# versus front-end APIs.
#
# allow def func(args): pass
# More than one statement on a line; pylint: disable=C0321
#
# This set of methods should be regarded as abstract *and* protected.
#
"""This essentially abstract class forms the interface that other
modules in the system use to record progress against various goals."""
# More than one statement on a line; pylint: disable=C0321
# Major phases of operation
# Extra phase used when we're doing some part of a subphase
# (such as rebuilding the search index) in a standalone operation.
# Planning phases
# Action phases
# Finalization/Job phases
# pkgrepo job items
# Operation purpose. This set of modes is used by callers to indicate
# to the progress tracker what's going on at a high level. This allows
# output to be customized by subclasses to meet the needs of a
# particular purpose.
#
# The purpose of current operations is in the "normal" set of things,
# including install, uninstall, change-variant, and other operations
# in which we can print arbitrary status information with impunity
#
#
# The purpose of current operations is in the service of trying to
# output a listing (list, contents, etc.) to the end user. Subclasses
# will likely want to suppress various bits of status (for non-tty
# output) or erase it (for tty output).
#
#
# The purpose of current operations is in the service of figuring out
# if the packaging system itself is up to date.
#
#
# Types of lint phases
#
# needs to be here due to use of _()
self.phase_names = {
}
# find the widest string in the list of phases so we can
# set column width properly.
self.phase_max_width = \
self.li_phase_names = {
}
# fetching catalogs
pass
# planning an operation
# getting manifests over the network
# verifying the content of a repository
# fixing the content of a repository
# archiving to .p5p files
# Called when bits arrive, either from on-disk cache or over-the-wire.
"""Call to provide news that the download has made progress."""
pass
"""Call when all downloading is finished."""
pass
# Running actions
pass
"""Call to provide news that the upload has made progress."""
pass
"""Call when all republishing is finished."""
pass
"""Call to indicate a new phase of lint progress."""
pass
"""Called once an image determines its linked image name."""
pass
"""Call when we recurse into a child linked image."""
pass
"""Call when we return from a child linked image."""
pass
"""Call to update the progress tracker with the list of
images being operated on."""
pass
"""Call to display output from linked image operations."""
pass
"""Call to indicate that the named child made progress."""
pass
adjusted=0):
pass
"""This class is used by the client to render and track progress
towards the completion of various tasks, such as download,
installation, update, etc.
The superclass is largely concerned with tracking the raw numbers, and
with calling various callback routines when events of interest occur.
The callback routines are defined in the ProgressTrackerBackend class,
below.
Different subclasses provide the actual rendering to the user, with
differing levels of detail and prettiness.
Note that as currently envisioned, this class is concerned with
tracking the progress of long-running operations: it is NOT a general
purpose output mechanism nor an error collector.
Most subclasses of ProgressTracker need not override the methods of
this class. However, most subclasses will need need to mix in and
define ALL of the methods from the ProgressTrackerBackend class."""
# Attribute defined outside __init__; pylint: disable=W0201
self.dl_estimator = None
# republishing support; republishing also uses dl_bytes
self.repub_pkgs = \
GoalTrackerItem(_("Republished pkgs"))
self.repub_send_bytes = \
GoalTrackerItem(_("Republish sent bytes"))
# Attribute defined outside __init__; pylint: disable=W0201
# We don't know the goal in advance for this one
self.refresh_target_catalog = None
_("Verify Repository Content"))
# archiving support
# reversioning support
# Used to measure elapsed time of entire planning; not otherwise
# rendered to the user.
self._planitems = {
TrackerItem(_("Solver setup")),
TrackerItem(_("Running solver")),
TrackerItem(_("Finding local manifests")),
GoalTrackerItem(_("Package planning")),
TrackerItem(_("Merging actions")),
TrackerItem(_("Checking for conflicting actions")),
TrackerItem(_("Consolidating action changes")),
TrackerItem(_("Evaluating mediators")),
TrackerItem(_("Finalizing action plan")),
TrackerItem(_("Evaluating mediator changes")),
GoalTrackerItem(_("Verifying Packages")),
GoalTrackerItem(_("Fixing Packages")),
}
self._actionitems = {
GoalTrackerItem(_("Removing old actions")),
GoalTrackerItem(_("Installing new actions")),
GoalTrackerItem(_("Updating modified actions")),
}
TrackerItem(_("Updating package state database")),
TrackerItem(_("Updating image state")),
TrackerItem(_("Creating fast lookup database")),
GoalTrackerItem(_("Updating package cache")),
TrackerItem(_("Reading search index")),
GoalTrackerItem(_("Updating search index")),
GoalTrackerItem(_("Building new search index")),
# pkgrepo job items
TrackerItem(_("Deleting search index")),
TrackerItem(_("Updating catalog")),
GoalTrackerItem(_("Analyzing removed packages")),
GoalTrackerItem(_("Analyzing repository packages")),
GoalTrackerItem(_("Removing package manifests")),
GoalTrackerItem(_("Removing package files")),
GoalTrackerItem(_("Verifying repository content")),
GoalTrackerItem(_("Fixing repository content"))
}
self._archive_name = None
# Lint's interaction with the progresstracker probably
# needs further work.
self.lint_phase = None
self.lint_phasetype = None
# This GoalTrackerItem is created on the fly.
# Linked images
self.linked_name = None
self.linked_running = []
self.linked_pkg_op = None
# Attribute defined outside __init__; pylint: disable=W0201
"""Used to signal to the progresstracker that it should make
the output ready for use by another subsystem. In a
terminal-based environment, this would make sure that no
partially printed lines were present, and flush e.g. stdout."""
#
# We can wind up doing multiple refreshes in some cases,
# for example when we have to check if pkg(7) is up-to-date,
# so we reset these each time we start.
#
# Attribute defined outside __init__; pylint: disable=W0201
assert self.refresh_full_refresh
# for now we only refresh one at a time, so we stash
# this here, and then assert for it in end_pub and
# in refresh_progress.
# when called back from the transport we lose the knowledge
# of what 'pub' is, at least for now.
# If refreshes fail, we might not meet the goal.
if goal:
raise RuntimeError(
"can't set goal on non-goal tracker")
if completion:
# These can fail to reach their goals due to various transport
# errors, depot misconfigurations, etc. So disable goal check.
"""Call when all archiving is finished"""
# only print 'last' if we printed 'first'
# Attribute defined outside __init__; pylint: disable=W0201
# indicate that this is the first _dl_output
# call
"""Call to provide news that the download has made progress"""
#
# These guards are present because download_add_progress can
# be called when an *upload* aborts; we want to prevent updates
# to these items, since they in this case might have no goals.
#
if cachehit:
else:
if nbytes > 0:
if nfiles > 0:
"""Call when all downloading is finished."""
if dryrun:
# Dryrun mode is used by pkgrecv in order to
# simulate a download; we do what we have to
# in order to fake up a download result.
timestamp=0)
else:
"""Called to set the goal for a particular phase of action
activity (i.e. ACTION_REMOVE, ACTION_INSTALL, or ACTION_UPDATE.
"""
"""Called when done each phase of actions processing."""
if total_actions != 0:
if goal:
raise RuntimeError(
"can't set goal on non-goal tracker")
# only print the 'done' if we printed the 'start'
# We don't have a good value to set this to.
# Attribute defined outside __init__; pylint: disable=W0201
if getbytes is not None:
# Allow reset of GET and SEND amounts on a per-package
# basis. This allows the user to monitor the overall
# progress of the operation in terms of total packages
# while not requiring the program to pre-process all
# packages to determine total byte sizes before starting
# the operation.
assert sendbytes is not None
#
# We can't do our normal trick of checking to see if
# dl_bytes.items is zero because it might have been reset
# above.
#
# indicate that this is the first _republish_output call
"""Call to provide news that the upload has made progress"""
#
# upload_add_progress can be called when a *download* aborts;
# this guard prevents us from updating the item (which has
# no goal set, and will raise an exception).
#
"""Call when all republishing is finished"""
if dryrun:
# Get the header printed if we've not printed
# anything else thus far (happens in dryrun mode).
# Attribute defined outside __init__; pylint: disable=W0201
if self.lint_phase is not None:
if self.lint_phase is None:
else:
"""Called once an image determines its linked image name."""
"""Called when we recurse into a child linked image."""
# Attribute defined outside __init__; pylint: disable=W0201
"""Called when we return from a child linked image."""
"""Call to update the progress tracker with the list of
images being operated on."""
# Attribute defined outside __init__; pylint: disable=W0201
"""Call to display output from linked image operations."""
"""Call to indicate that the named child made progress."""
adjusted=0):
"""This class is a proxy, dispatching incoming progress tracking calls
to one or more contained (in self._trackers) additional progress
trackers. So, you can use this class to route progress tracking calls
to multiple places at once (for example, to the screen and to a log
file).
We hijack most of the methods of the front-end superclass, except for
the constructor. For each hijacked method, we substitute a closure of
the multido() routine bound with the appropriate arguments."""
raise ProgressTrackerException("No trackers specified")
#
# Returns a multido closure, which will iterate and call the
# named method for each tracker registered with the class.
#
# self and method_name are bound in this context.
return multido
#
# Look in the ProgressTrackerFrontend for a list of frontend
# methods to multiplex.
#
if methname == "__init__":
continue
if not inspect.isfunction(m):
continue
# Override all methods which aren't the constructor.
# Yes, this is a big hammer.
return
"""This progress tracker outputs nothing, but is semantically
intended to be "quiet." See also NullProgressTracker below."""
#
# At construction, we inspect the ProgressTrackerBackend abstract
# superclass, and implement all of its methods as empty stubs.
#
# We modify the object such that all of the methods it needs to
# implement are set to this __donothing empty method.
# Unused argument 'args', 'kwargs';
# pylint: disable=W0613
pass
if methname == "__init__":
continue
continue
"""This ProgressTracker is a subclass of QuietProgressTracker because
that's convenient for now. It is semantically intended to be a no-op
progress tracker, and is useful for short-running operations which
need not display progress of any kind.
This subclass should be used by external consumers wanting to create
their own ProgressTracker class as any new output methods added to the
ProgressTracker class will also be handled here, insulating them from
additions to the ProgressTracker class."""
"""This ProgressTracker is principally used for debugging.
Essentially it uses method replacement in order to create a
"tracing" ProgressTracker that shows calls to front end methods
and calls from the frontend to the backend."""
#
# When an instance of this class is initialized, we use inspection to
# insert a new method for each method; for frontend methods "chain"
# the old one behind the new one. The new method dumps out the
# arguments.
#
# Unused argument 'args', 'kwargs';
# pylint: disable=W0613
pass
# We modify the instance such that all of the methods it needs
# to implement are set to this __printargs method.
s = ""
for x in args:
s = s[:-2]
#
# Invoke chained method implementation; it's
# counter-intuitive, but we do this before
# printing things out, because under the
# circumstances we create in
# test_progress_tracker(), the chained method
# could throw an exception, aborting an
# upstream MultiProgressTracker's multido(),
# and spoiling the test_multi() test case.
#
return __printargs
if methname == "__init__":
continue
#
# this gets us the bound method, which we say here
# is "chained"-- we'll call it next after our inserted
# method.
#
continue
if methname == "__init__":
continue
continue
"""This tracker writes a series of dots for every operation.
This is intended for use by linked images."""
def make_dot():
# Unused argument 'args', 'kwargs';
# pylint: disable=W0613
return dot
if methname == "__init__":
continue
continue
"""This progress tracker is a generically useful tracker for command
line output. It needs no special terminal features and so is
appropriate for sending through a pipe. This code is intended to be
platform neutral."""
# Default to printing periodic output every 5 seconds.
if not print_engine:
else:
return ""
# The following string was originally expressed as
# "%*s: ". % \
# (self.phase_max_width, self.phase_names[self.major_phase]
# )
# however xgettext incorrectly flags this as an improper use of
# non-parameterized messages, which gets detected as an error
# during our build. So instead, we express the string using
# an equivalent <str>.format(..) function
#
# Helper routines
#
# In the case of listing/up-to-date check operations, we
# we don't want to output planning information, so skip.
return
# indicate that we just printed.
# See __generic_start above.
return
if msg is None:
# See __generic_start above.
return
if msg is None:
else:
#
# Overridden methods from ProgressTrackerBackend
#
# See __generic_start above.
return
m = _("Retrieving target catalog '{0}' "
"...").format(p)
elif self.refresh_full_refresh:
m = _("Retrieving catalog '{0}' ...").format(p)
else:
m = _("Refreshing catalog '{0}' ...").format(p)
_("Planning completed in {0:>.2f} seconds").format(
return
return
# Reset timer; this prevents double printing for
# outspec.first and then again for the timer expiration
#
# There are a couple of reasons we might fetch manifests--
# pkgrecv, pkglint, etc. can all do this. _phase_prefix()
# adjusts the output based on the major phase.
#
_("Fetching manifests: {num} {pctcomplete}% "
"complete").format(
# For now, manifest commit is hard to handle in this
# line-oriented prog tracker, as we alternate back and forth
# between fetching and committing, and we don't want to
# spam the user with this too much.
pass
pass
pass
pass
pass
pass
pass
return
# Reset timer; this prevents double printing for
# outspec.first and then again for the timer expiration
else:
# 'first' or time to print
_("Download: {num} items {mbs}MB "
"{pctcomplete}% complete {speed}").format(
else:
# 'last'
msg=_("Download: Completed {num} in {sec:>.2f} "
"seconds {speed}").format(
return
# tell ptimer that we just printed.
msg=_("Archiving: Completed {num} in {secs:>.2f} "
"seconds").format(
return
_("Archiving: {pair} items {mbs}MB {pctcomplete}% "
"complete").format(
#
# The progress tracking infrastructure wants to tell us about each
# kind of action activity (install, remove, update). For this
# progress tracker, we don't really care to expose that to the user,
# so we work in terms of total actions instead.
#
return
# reset timer, since we're definitely printing now...
total_actions = \
total_goal = \
_("{num} actions ({type})").format(
total_goal = \
total_time = \
if total_goal == 0:
return
_("Completed {numactions:d} actions in {time:>.2f} "
"seconds.").format(
pass
_("Linked image publisher check ..."))
return
return
_("Finished processing linked images."))
if not output:
return
else:
return
return
msg = _("Linked images: {pair} done; {numworking:d} working: "
"{running}").format(
return
return
# tell ptimer that we just printed.
msg=_("Reversioned {revs} of {pkgs} packages "
"and adjusted {adjs} packages.").format(
return
_("Reversioning: {pkgs} processed, {revs} reversioned, "
"{adjs} adjusted").format(
"""This progress tracker is a subclass of CommandLineProgressTracker
which is specific for RAD progress event.
"""
# Default to printing periodic output every 5 seconds.
# Output constants.
return "Utility"
#
# Helper routines
#
# prepare progress json.
if phase:
if prog_json:
return prog_json
else:
# If event handler is set, report an event. Otherwise, print.
else:
# In the case of listing/up-to-date check operations, we
# don't want to output planning information, so skip.
return
# indicate that we just printed.
# See __generic_start above.
return
if msg is None:
msg = _("Done")
# See __generic_start above.
return
if msg is None:
msg = _("Done ({elapsed:>.3f}s)")
else:
msg = _("Done")
_("Checking that pkg(7) is up to date ..."))
# See __generic_start above.
return
m = _("Retrieving target catalog '{0}' "
"...").format(p)
elif self.refresh_full_refresh:
m = _("Retrieving catalog '{0}' ...").format(p)
else:
m = _("Refreshing catalog '{0}' ...").format(p)
return
return
# Reset timer; this prevents double printing for
# outspec.first and then again for the timer expiration
#
# There are a couple of reasons we might fetch manifests--
# pkgrecv, pkglint, etc. can all do this. _phase_prefix()
# adjusts the output based on the major phase.
#
if goalitems is None:
goalitems = 0
}
return
# Reset timer; this prevents double printing for
# outspec.first and then again for the timer expiration
else:
# 'first' or time to print
prog_json = {
}
else:
# 'last'
}
return
# tell ptimer that we just printed.
}
return
}
#
# The progress tracking infrastructure wants to tell us about each
# kind of action activity (install, remove, update). For this
# progress tracker, we don't really care to expose that to the user,
# so we work in terms of total actions instead.
#
return
# reset timer, since we're definitely printing now...
total_actions = \
total_goal = \
}
total_goal = \
total_time = \
if total_goal == 0:
return
}
}
}
pass
_("Linked image publisher check ..."))
return
return
_("Finished processing linked images."))
if not output:
return []
return lines
return
return
}
return
return
# tell ptimer that we just printed.
}
return
}
"""Construct json schema."""
json_schema = {"$schema":
"title": "progress schema",
"type": "object",
},
}
return json_schema
"""This tracker is used for recursion with linked children.
This is intended for use only by linked images."""
# We modify the instance such that everything except for the
# linked image methods are no-opped out. In multi-level
# recursion, this ensures that output from children is
# displayed.
# Unused argument 'args', 'kwargs';
# pylint: disable=W0613
pass
if methname == "__init__":
continue
continue
continue
"""This progress tracker is designed for UNIX-like OS's-- those which
have UNIX-like terminal semantics. It attempts to load the 'curses'
package. If that or other terminal-liveness tests fail, it gives up:
the client should pick some other more suitable tracker. (Probably
CommandLineProgressTracker)."""
#
# The minimum interval (in seconds) at which we should update the
# display during operations which produce a lot of output. Needed to
# avoid spamming a slow terminal.
#
try:
except printengine.PrintEngineException as e:
raise ProgressTrackerException(
"Couldn't create print engine: {0}".format(
if term_delay is None:
else self.TERM_DELAY
self._jobs_lastjob = None
if not output_file.isatty():
raise ProgressTrackerException(
"output_file is not a TTY")
# For linked image spinners.
self.__linked_spinners = []
#
# Overridden methods from ProgressTrackerBackend
#
# Ensure the last message displayed is flushed in case the
# corresponding operation did not complete successfully.
return
_("Checking that pkg(7) is up to date {0}").format(
# Unused argument 'op'; pylint: disable=W0613
return
return
# for very small xfers (like when we just get the attrs) this
# isn't very interesting, so elide it.
nbytes = ""
else:
nbytes = " " + \
prefix = _("Retrieving target catalog")
elif self.refresh_full_refresh:
prefix = _("Retrieving catalog")
else:
prefix = _("Refreshing catalog")
return
return
extra_info = ""
return
return
#
# There are a couple of reasons we might fetch manifests--
# pkgrecv, pkglint, etc. can all do this. So we adjust
# the output based on the major mode.
#
msg = _("Creating Plan ({name} {pair}) "
"{spinner}").format(
# note to translators: the position of these strings
# should probably be left alone, as they form part of
# the progress output text.
return
else:
# The first time, emit header.
_("PKG"), _("Processed"), _("Reversioned"),
_("Adjusted")))
s = "{0:<40.40} {1:>11} {2:>13} {3:>11}".format(
return
return
msg = _("Creating Plan (Committing Manifests): "
return
"""If 'repository_scan' is set and we have no FRMRI set, we emit
a message saying that we're performing a scan if the repository.
If we have no FMRI, we emit a message saying we don't know what
package we're looking at.
"""
if repository_scan:
pkg_stem = _("Scanning repository "
"(this could take some time)")
else:
pkg_stem = _("Unknown package")
else:
return
return
s = "{0:64} {1} {2}".format(
return
# The first time, emit header.
_("ARCHIVE"), _("FILES"), _("STORE (MB)")))
s = "{0:<44.44} {1:>11} {2:>11}".format(
return
# The first time, emit header.
_("FILES"), _("XFER (MB)"), _("SPEED")))
pkg_name = _("Completed")
else:
# show speed if greater than 0, otherwise "--"
else:
speedstr = "--"
# Use floats unless it makes the field too wide
s = "{0:<34.34} {1:>9} {2:>13} {3:>12} {4:>7}".format(
return
# The first time, emit header.
_("PROCESS"), _("ITEMS"), _("GET (MB)"),
_("SEND (MB)")))
pkg_name = "Completed"
else:
s = "{0:<40.40} {1:>12} {2:>11} {3:>11}".format(
return
return
# emit header if needed
return
pass
return
# emit phases header if needed
else:
return
_("Linked image publisher check"))
return
return
if not output:
return
else:
return
return
msg = _("{phase} linked: {numdone} done; "
"{numworking:d} working: {running}").format(
return
return
# find the index of the child that made progress
# update that child's spinner
self.__linked_spinners[i] = \
for i in self.__linked_spinners
])
#
# This code lives here, for now, anyway, because it is called both from
# the API test suite and from the $SRC/tests/interactive/runprogress.py
# utility.
#
# Unused variables (in several loops) pylint: disable=W0612
import random
print("Use ctrl-c to skip sections")
if not gofast:
fast = 1.0
else:
fast = 0.10
dlscript = {
"a-very-very-long-package-name-which-will-have-to-be-truncated": [],
}
t.set_purpose(purp)
try:
for x in ["woop", "gub", "zip", "yowee"]:
t.refresh_start_pub(p)
t.refresh_progress(x, 0)
t.refresh_end_pub(p)
t.refresh_done()
except KeyboardInterrupt:
t.flush()
try:
if k.startswith("PLAN_")])
t.plan_all_start()
# we always try to set a goal; this will fail
# for ungoaled items, so then we try again
# without a goal. This saves us the complicated
# task of inspecting the tracker-- and
# multiprogress makes such inspection much
# harder.
try:
except RuntimeError:
t.plan_start(planid)
for x in range(0, r):
t.plan_all_done()
except KeyboardInterrupt:
t.flush()
try:
t.manifest_commit()
except KeyboardInterrupt:
t.flush()
perpkgfiles = 50
pkggoalbytes = 0
filesizemax = 250000
hunkmax = 8192
# invent a list of random download chunks.
hunks = []
while filesize > 0:
# pylint is picky about this message:
# old-division; pylint: disable=W1619
try:
n = 0
t.download_done()
except KeyboardInterrupt:
t.flush()
try:
t.reset_download()
n = 0
t.republish_done()
except KeyboardInterrupt:
t.flush()
try:
t.reset_download()
n = 0
t.archive_done()
except KeyboardInterrupt:
t.flush()
try:
nactions = 100
t.actions_done(act)
t.actions_all_done()
except KeyboardInterrupt:
t.flush()
try:
continue
# we always try to set a goal; this will fail for
# ungoaled items, so then we try again without a goal.
# This saves us the complicated task of inspecting the
# tracker-- and multiprogress makes such inspection
# much harder.
try:
except RuntimeError:
for x in range(0, r):
except KeyboardInterrupt:
t.flush()
try:
# do some other things to drive up test coverage.
t.flush()
# test lint
t.lint_done()
except KeyboardInterrupt:
t.flush()
return