Source code for lbt_recipes.settings

# coding: utf-8
"""Class to handle settings for running recipes locally."""
from __future__ import division
import argparse
import shlex
import os

from honeybee.typing import int_in_range


[docs]class RecipeSettings(object): """Parameters specifying how to run recipes locally. Args: folder: Path to a project folder in which the recipe will be executed. If None, the default project folder for the Recipe will be used. (Default: None). workers: An integer to set the number of CPUs used in the execution of the recipe. This number should not exceed the number of CPUs on the machine running the simulation and should be lower if other tasks are running while the simulation is running. If set to None, it should automatically default to one less than the number of CPUs currently available on the machine. (Default: None). reload_old: A boolean to indicate whether existing results for a given project and simulation ID should be reloaded if they are found instead of re-running the entire recipe from the beginning. If False, any existing results will be overwritten by the new simulation. (Default: False). report_out: A boolean to indicate whether the recipe progress should be displayed in the cmd window (False) or printed (True). Printing can be useful for debugging and capturing what's happening in the process but recipe reports can often be very long and so it can slow Grasshopper slightly. (Default: False). debug_folder: An optional path to a debug folder. If debug folder is provided all the steps of the simulation will be executed inside the debug folder which can be used for further inspection. Properties: * folder * workers * reload_old * report_out * debug_folder """ __slots__ = ('_folder', '_workers', '_reload_old', '_report_out', '_debug_folder') def __init__(self, folder=None, workers=None, reload_old=False, report_out=False, debug_folder=None): """Initialize RecipeSettings.""" self.folder = folder self.workers = workers self.reload_old = reload_old self.report_out = report_out self.debug_folder = debug_folder
[docs] @classmethod def from_string(cls, settings_string): """Create an RecipeSettings object from a RecipeSettings string.""" # parse the string representation parser = argparse.ArgumentParser() parser.add_argument('--folder', action="store", dest="folder") parser.add_argument('--workers', action="store", dest="workers", type=int) parser.add_argument('--reload-old', action="store_true", default=False) parser.add_argument('--report-out', action="store_true", default=False) parser.add_argument('--debug-folder', action="store", dest="debug_folder") argument_list = shlex.split(settings_string) args = parser.parse_args(argument_list) # assign the properties folder = args.folder if 'folder' in args else None workers = int(args.workers) if 'workers' in args else None debug_folder = args.debug_folder if 'debug_folder' in args else None return cls(folder, workers, args.reload_old, args.report_out, debug_folder)
@property def folder(self): """Get or set the path to a project folder in which the recipe will be executed. """ return self._folder @folder.setter def folder(self, value): if value is not None: value = str(value).replace('\\', '/') if value.endswith('/'): value = value[:-1] self._folder = value @property def workers(self): """Get or set a integer the number of CPUs used in the execution of the recipe. If set to None, this should be equal to one less than the number of processors currently available on the machine. """ return self._workers if self._workers is not None \ else self._recommended_processor_count() @workers.setter def workers(self, value): if value is not None: value = int_in_range(value, mi=1, input_name='recipe workers') self._workers = value @property def reload_old(self): """Get or set a boolean for whether existing results should be reloaded.""" return self._reload_old @reload_old.setter def reload_old(self, value): self._reload_old = bool(value) @property def report_out(self): """Get or set a boolean for whether to print the recipe progress.""" return self._report_out @report_out.setter def report_out(self, value): self._report_out = bool(value) @property def debug_folder(self): """Get or set the path to a folder in which the simulation steps are executed. """ return self._debug_folder @debug_folder.setter def debug_folder(self, value): if value is not None: value = str(value).replace('\\', '/') if value.endswith('/'): value = value[:-1] self._debug_folder = value
[docs] def ToString(self): """Overwrite .NET ToString.""" return self.__repr__()
[docs] def duplicate(self): """Get a copy of this object.""" return self.__copy__()
@staticmethod def _recommended_processor_count(): """Get an integer for one minus the number of processors on this machine. This method should work on all of the major operating systems and in both IronPython and cPython. If, for whatever reason, the number of processors could not be sensed, a value of 1 will be returned. """ try: # assume that we are in cPython cpu_count = os.cpu_count() except AttributeError: # we are probably in IronPython try: from System.Environment import ProcessorCount cpu_count = ProcessorCount except ImportError: # no idea what Python this is; let's play it safe cpu_count = 1 return 1 if cpu_count is None or cpu_count <= 1 else cpu_count - 1 def __copy__(self): return RecipeSettings( self.folder, self.workers, self.reload_old, self.report_out, self.debug_folder) def __key(self): """A tuple based on the object properties, useful for hashing.""" return (self.folder, self.workers, self.reload_old, self.report_out, self.debug_folder) def __hash__(self): return hash(self.__key()) def __eq__(self, other): return isinstance(other, RecipeSettings) and self.__key() == other.__key() def __ne__(self, other): return not self.__eq__(other) def __repr__(self): """RecipeSettings representation.""" rep_str = '--folder "{}"'.format(self.folder) if self.folder is not None else '' rep_str += ' --workers {}'.format(self.workers) if self.reload_old: rep_str += ' --reload-old' if self.report_out: rep_str += ' --report-out' if self.debug_folder: rep_str += '--debug-folder "{}"'.format(self.debug_folder) return rep_str