def main(): """Simple entry point""" args = args_parsing() # `Processes` is a singleton, let's populate the internal list here. Processes() # `Configuration` is a singleton, let's populate the internal object here. configuration = Configuration(config_path=args.config_path) # From configuration, gather the entries user-enabled. enabled_entries = [ (entry.value, entry.name) for entry in Entries if configuration.get('entries', {}).get(entry.name, True) ] output = Output(preferred_distribution=args.distribution, format_to_json=args.json) # We will map this function onto our enabled entries to instantiate them. def _entry_instantiator(entry_tuple): return entry_tuple[0](name=entry_tuple[1]) # Let's use a context manager stack to manage conditional use of `TheadPoolExecutor`. with ExitStack() as cm_stack: if not configuration.get('parallel_loading'): mapper = map else: # Instantiate a threads pool to load our enabled entries in parallel. # We use threads (and not processes) since most work done by our entries is IO-bound. # `max_workers` is manually computed to mimic Python 3.8+ behaviour, but for our needs. # See <https://github.com/python/cpython/pull/13618>. executor = cm_stack.enter_context( ThreadPoolExecutor(max_workers=min( len(enabled_entries) or 1, (os.cpu_count() or 1) + 4))) mapper = executor.map for entry_instance in mapper(_entry_instantiator, enabled_entries): output.add_entry(entry_instance) output.output() # Has the screenshot flag been specified ? if args.screenshot is not None: # If so, but still _falsy_, pass `None` as no output file has been specified by the user. take_screenshot((args.screenshot or None))
def main(): """Simple entry point""" args = args_parsing() # Setup logging. logging.basicConfig(format='%(levelname)s: %(message)s') # Populate our internal singletons once and for all. Processes() Environment() configuration = Configuration(config_path=args.config_path) # From configuration, gather the entries user-configured. available_entries = configuration.get('entries') if available_entries is None: # If none were specified, lazy-mimic a full-enabled entries list without any configuration. available_entries = [{'type': entry_name} for entry_name in Entries.__members__.keys()] output = Output( preferred_logo_style=args.logo_style, preferred_distribution=args.distribution, format_to_json=args.json ) # We will map this function onto our enabled entries to instantiate them. def _entry_instantiator(entry: dict) -> Optional[Entry]: # Based on **required** `type` field, instantiate the corresponding `Entry` object. try: return Entries[entry.pop('type')].value( name=entry.pop('name', None), # `name` is fully-optional. options=entry # Remaining fields should be propagated as options. ) except KeyError as key_error: logging.warning( 'One entry (misses or) uses an invalid `type` field (%s).', key_error ) return None # Let's use a context manager stack to manage conditional use of `TheadPoolExecutor`. with ExitStack() as cm_stack: if not configuration.get('parallel_loading'): mapper = map else: # Instantiate a threads pool to load our enabled entries in parallel. # We use threads (and not processes) since most work done by our entries is IO-bound. # `max_workers` is manually computed to mimic Python 3.8+ behaviour, but for our needs. # See <https://github.com/python/cpython/pull/13618>. executor = cm_stack.enter_context(ThreadPoolExecutor( max_workers=min(len(available_entries) or 1, (os.cpu_count() or 1) + 4) )) mapper = executor.map for entry_instance in mapper(_entry_instantiator, available_entries): if not entry_instance: continue output.add_entry(entry_instance) output.output() # Has the screenshot flag been specified ? if args.screenshot is not None: # If so, but still _falsy_, pass `None` as no output file has been specified by the user. try: screenshot_taken = take_screenshot((args.screenshot or None)) except KeyboardInterrupt: screenshot_taken = False print() finally: sys.exit((not screenshot_taken))