Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'release/scripts/modules/bpy_extras/wm_utils/progress_report.py')
-rw-r--r--release/scripts/modules/bpy_extras/wm_utils/progress_report.py167
1 files changed, 167 insertions, 0 deletions
diff --git a/release/scripts/modules/bpy_extras/wm_utils/progress_report.py b/release/scripts/modules/bpy_extras/wm_utils/progress_report.py
new file mode 100644
index 00000000000..bcce44aab9f
--- /dev/null
+++ b/release/scripts/modules/bpy_extras/wm_utils/progress_report.py
@@ -0,0 +1,167 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+import time
+
+
+class ProgressReport:
+ """
+ A basic 'progress report' using either simple prints in console, or WindowManager's 'progress' API.
+
+ This object can be used as a context manager.
+
+ It supports multiple levels of 'substeps' - you shall always enter at least one substep (because level 0
+ has only one single step, representing the whole 'area' of the progress stuff).
+
+ You should give the expected number of substeps each time you enter a new one (you may then step more or less then
+ given number, but this will give incoherent progression).
+
+ Leaving a substep automatically steps by one the parent level.
+
+ with ProgressReport() as progress: # Not giving a WindowManager here will default to console printing.
+ progress.enter_substeps(10)
+ for i in range(10):
+ progress.enter_substeps(100)
+ for j in range(100):
+ progress.step()
+ progress.leave_substeps() # No need to step here, this implicitly does it.
+ progress.leave_substeps("Finished!") # You may pass some message too.
+ """
+ __slots__ = ('wm', 'running', 'steps', 'curr_step', 'start_time')
+
+ def __init__(self, wm=None):
+ self_wm = getattr(self, 'wm', None)
+ if self_wm:
+ self.finalize()
+ self.running = False
+
+ self.wm = wm
+ self.steps = [100000]
+ self.curr_step = [0]
+
+ initialize = __init__
+
+ def __enter__(self):
+ self.start_time = [time.time()]
+ if self.wm:
+ self.wm.progress_begin(0, self.steps[0])
+ self.update()
+ self.running = True
+ return self
+
+ def __exit__(self, exc_type=None, exc_value=None, traceback=None):
+ self.running = False
+ if self.wm:
+ self.wm.progress_end()
+ self.wm = None
+ print("\n")
+ self.steps = [100000]
+ self.curr_step = [0]
+ self.start_time = [time.time()]
+
+ def start(self):
+ self.__enter__()
+
+ def finalize(self):
+ self.__exit__()
+
+ def update(self, msg=""):
+ steps = sum(s * cs for (s, cs) in zip(self.steps, self.curr_step))
+ steps_percent = steps / self.steps[0] * 100.0
+ tm = time.time()
+ loc_tm = tm - self.start_time[-1]
+ tm -= self.start_time[0]
+ if self.wm and self.running:
+ self.wm.progress_update(steps)
+ if msg:
+ prefix = " " * (len(self.steps) - 1)
+ print(prefix + "(%8.4f sec | %8.4f sec) %s\nProgress: %6.2f%%\r" %
+ (tm, loc_tm, msg, steps_percent), end='')
+ else:
+ print("Progress: %6.2f%%\r" % (steps_percent,), end='')
+
+ def enter_substeps(self, nbr, msg=""):
+ if msg:
+ self.update(msg)
+ self.steps.append(self.steps[-1] / max(nbr, 1))
+ self.curr_step.append(0)
+ self.start_time.append(time.time())
+
+ def step(self, msg="", nbr=1):
+ self.curr_step[-1] += nbr
+ self.update(msg)
+
+ def leave_substeps(self, msg=""):
+ if (msg):
+ self.update(msg)
+ assert(len(self.steps) > 1)
+ del self.steps[-1]
+ del self.curr_step[-1]
+ del self.start_time[-1]
+ self.step()
+
+
+class ProgressReportSubstep:
+ """
+ A sub-step context manager for ProgressReport.
+
+ It can be used to generate other sub-step contexts too, and can act as a (limited) proxy of its real ProgressReport.
+
+ Its exit method always ensure ProgressReport is back on 'level' it was before entering this context.
+ This means it is especially useful to ensure a coherent behavior around code that could return/continue/break
+ from many places, without having to bother to explicitly leave substep in each and every possible place!
+
+ with ProgressReport() as progress: # Not giving a WindowManager here will default to console printing.
+ with ProgressReportSubstep(progress, 10, final_msg="Finished!") as subprogress1:
+ for i in range(10):
+ with ProgressReportSubstep(subprogress1, 100) as subprogress2:
+ for j in range(100):
+ subprogress2.step()
+ """
+ __slots__ = ('progress', 'nbr', 'msg', 'final_msg', 'level')
+
+ def __init__(self, progress, nbr, msg="", final_msg=""):
+ # Allows to generate a subprogress context handler from another one.
+ progress = getattr(progress, 'progress', progress)
+
+ self.progress = progress
+ self.nbr = nbr
+ self.msg = msg
+ self.final_msg = final_msg
+
+ def __enter__(self):
+ self.level = len(self.progress.steps)
+ self.progress.enter_substeps(self.nbr, self.msg)
+ return self
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ assert(len(self.progress.steps) > self.level)
+ while len(self.progress.steps) > self.level + 1:
+ self.progress.leave_substeps()
+ self.progress.leave_substeps(self.final_msg)
+
+ def enter_substeps(self, nbr, msg=""):
+ self.progress.enter_substeps(nbr, msg)
+
+ def step(self, msg="", nbr=1):
+ self.progress.step(msg, nbr)
+
+ def leave_substeps(self, msg=""):
+ self.progress.leave_substeps(msg)