def minor(self) -> Version: """ Update current minor part of the version """ self._version.minor += 1 self._version.patch = 0 self._version.state = Extension.SNAPSHOT if self._version.state else None sysout(f"Version has been updated to {self._version} (Minor)") return self._version
def _create_app(self, app_name: str, extensions: List[AppExtension]) -> None: """Create a Simple HSPyLib application""" sysout(f'Application: {app_name}') self._create_base_app_struct(app_name) self._mkfile('src/main/__main__.py', (self.TEMPLATES / "tpl-main.py").read_text()) self._mkfile('src/main/usage.txt', (self.TEMPLATES / "tpl-usage.txt").read_text()) self._apply_extensions(extensions, app_name)
def _apply_extensions(self, extensions: List[AppExtension], app_name: str): """TODO""" if AppExtension.GRADLE in extensions: sysout('Applying gradle extensions') self._init_gradle(app_name) if AppExtension.GIT in extensions: sysout('Initializing git repository') self._init_git()
def _create_qt_app(self, app_name: str, extensions: List[AppExtension]) -> None: """Create an HSPyLib QT application""" sysout(f'QT Application: {app_name}') self._create_base_app_struct(app_name) self._mkdir('src/main/resources/forms') self._mkfile('src/main/resources/forms/main_qt_view.ui', (self.TEMPLATES / "tpl-main_qt_view.ui").read_text()) self._mkfile('src/main/__main__.py', (self.TEMPLATES / "tpl-main-qt.py").read_text()) self._apply_extensions(extensions, app_name)
def print_error(message: str, argument: Any = None, wait_interval: int = 2) -> None: """TODO""" syserr(f"### Error: {message} \"{argument or ''}\"") time.sleep(wait_interval) sysout('%CUU(2)%%ED0%', end='')
def restore_terminal(clear_screen: bool = True): """Clear terminal and restore default attributes""" if clear_screen: vt_print('%HOM%%ED2%%MOD(0)%') set_auto_wrap() set_show_cursor() set_enable_echo() sysout('%NC%')
def exit_app(exit_code: int = signal.SIGHUP, frame=None, exit_msg: str = "Done.") -> None: """Exit the application. Commonly hooked to signals""" sysout(str(frame) if frame else '', end='') sysout(f"%HOM%%ED2%%NC%\n{exit_msg}\n") restore_terminal(False) sys.exit(exit_code if exit_code else 0)
def _create_widget(self, app_name: str) -> None: """Create an HSPyLib Widget application""" widget_name = camelcase(app_name).replace('_', '').replace(' ', '') sysout(f'Widget: {widget_name}') self._mkfile( f"widget_{app_name.lower()}.py", (self.TEMPLATES / "tpl-widget.py").read_text().replace('_WIDGET_NAME_', f"{widget_name}") )
def usage(self, exit_code: int = 0, no_exit: bool = False) -> None: """Display the usage message and exit with the specified code ( or zero as default ) :param no_exit: Do no exit the application on usage call :param exit_code: The exit code """ sysout(self._app_usage) if not no_exit: self.exit_handler(exit_code)
def _loop_actions(self) -> None: """Wait for the user interactions""" while not self.done: if self.org and self.space and not self.cf.is_targeted(): self._target() else: self._set_org() self._set_space() if not self.org or not self.space or not self.cf.is_targeted(): raise CFExecutionError( f"Unable to target ORG={self.org} SPACE={self.space} => {self.cf.last_result}" ) action = mselect(CFManager.CF_ACTIONS, 'Please select an action to perform') if not action: self.done = True else: if self._is_callable(action): if self._allow_multiple(action.lower()): apps = self._choose_apps() else: app = self._select_app() apps = [app] if app else None if apps: for app in apps: self._perform(action, app=app.name, org=self.org, space=self.space) else: if action.lower() == 'status': apps = self._get_apps(refresh=True) if len(apps) > 0: sysout("{} {} {} {} {} {}".format( 'Name'.ljust(CFApplication.max_name_length), 'State'.ljust(7), 'Inst'.ljust(5), 'Mem'.ljust(4), 'Disk'.ljust(4), 'URLs', )) for app in apps: app.print_status() elif action.lower() == 'target': self.space = None self.org = None self.cf.targeted = { 'org': None, 'space': None, 'targeted': False } continue MenuUtils.wait_enter()
def version(self, exit_code: int = 0, no_exit: bool = False) -> None: """Display the current program version and exit :param no_exit: Do no exit the application on usage call :param exit_code: The exit code """ sysout('{} v{}'.format(self._app_name, '.'.join(map(str, self._app_version)))) if not no_exit: self.exit_handler(exit_code)
def promote(self) -> Version: """ Promote the current version in the order: DEVELOPMENT->SNAPSHOT->STABLE->RELEASE """ self._assert_extension() if self._version.state and self._version.state != Extension.RELEASE: self._version.state = Extension.of_value( min(Extension.RELEASE.value, self._version.state.value << 1)) sysout(f"Version has been promoted to {self._version}") else: syserr(f"Version {self._version} can't be promoted") return self._version
def print_warning(message: str, argument: str = None, wait_interval: int = 2, color: VtColors = VtColors.YELLOW) -> None: """TODO""" sysout( f"{color.placeholder()}### Warn: {message} \"{argument or ''}\"") time.sleep(wait_interval) sysout('%CUU(2)%%ED0%', end='')
def execute(self, *args) -> ExitCode: ret_val = ExitCode.SUCCESS if (not args or len(args) < 3) and not any(a in args for a in ['-h', '--help']): if not self._read_args(): return ExitCode.ERROR elif args[0] in ['-h', '--help']: sysout(self.usage()) return ExitCode.SUCCESS elif args[0] in ['-v', '--version']: sysout(self.version()) return ExitCode.SUCCESS elif args[0] in ['-d', '--decimal']: self.decimal = True args = args[1:] if not self.args: self.args = args for tm in self.args: if re.match(r"[+-]", tm): self.op = tm elif re.match(r"^([0-9]{1,2}:?)+", tm): try: parts = [int(math.floor(float(s))) for s in tm.split(':')] except ValueError: parts = [0, 0, 0] ret_val = ExitCode.ERROR f_hours = parts[0] if len(parts) > 0 else 0 f_minutes = parts[1] if len(parts) > 1 else 0 f_secs = parts[2] if len(parts) > 2 else 0 tm_amount = ((f_hours * 60 + f_minutes) * 60 + f_secs) if self.op == '+': self.total_seconds += tm_amount elif self.op == '-': self.total_seconds -= tm_amount else: raise WidgetExecutionError(f"Invalid time input: '{tm}'") self.total_seconds, seconds = divmod(self.total_seconds, 60) hours, minutes = divmod(self.total_seconds, 60) sysout('%HOM%%ED2%%MOD(0)%', end='') if self.decimal: sysout( f"{hours:02d}.{self._decimal(minutes):02d}.{self._decimal(seconds):02d}" ) else: sysout( f"{hours:02d}:{self._decimal(minutes):02d}:{self._decimal(seconds):02d}" ) return ret_val
def prepare_render(render_msg: str = '', render_color: VtColors = VtColors.ORANGE): """Prepare the terminal for TUI renderization""" signal.signal(signal.SIGINT, exit_app) signal.signal(signal.SIGHUP, exit_app) set_auto_wrap(False) set_show_cursor(False) sysout( f"%ED2%%HOM%{render_color.placeholder()}{render_msg}%HOM%%CUD(1)%%ED0%" ) save_cursor()
def demote(self) -> Version: """ Demote the current version in the order: RELEASE->STABLE->SNAPSHOT->DEVELOPMENT """ self._assert_extension() if self._version.state and self._version.state != Extension.DEVELOPMENT: self._version.state = Extension.of_value( max(Extension.DEVELOPMENT.value, self._version.state.value >> 1)) sysout(f"Version has been demoted to {self._version}") else: syserr(f"Version {self._version} can't be demoted") return self._version
def _decode_and_write(destination_dir: str, file_entries: List[dict]) -> None: """B64 decode and write entries to file""" for entry in file_entries: FileEntry.of( '{}/{}'.format(destination_dir, os.path.basename(entry['path'])), entry['data'], entry['size']).save() sysout( f"%GREEN%'{entry['path']}' successfully downloaded into '{destination_dir}'" )
def display_contacts(persons, companies) -> None: if len(persons) > 0 or len(companies) > 0: SearchView.display_table( ["UUID", "NAME", "PHONE", "ADDRESS", "CPL", "AGE", "EMAIL"], persons, 'PERSONS') SearchView.display_table( ["UUID", "NAME", "PHONE", "ADDRESS", "CPL", "WEBSITE"], companies, 'COMPANIES') else: sysout('-=- No results to be displayed -=-') MenuUtils.wait_enter()
def prompt(self) -> None: """Create a new firebase configuration by prompting the user for information""" config = CaseInsensitiveDict() sysout("### Firebase setup") sysout('-' * 31) config['PROJECT_ID'] = self.project_id() config['DATABASE'] = self.database() config['USERNAME'] = self.username() config['PASSPHRASE'] = self.passphrase() config['UUID'] = self.uuid() self.setup(config)
def _init_sockets(self) -> None: """Initialize sockets""" if self.net_type == self.NET_TYPE_UDP: self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) else: self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: self.socket.connect(self.host) sysout(f"Successfully connected to {self.host}") except socket.error as err: raise WidgetExecutionError( 'Unable to initialize sockets') from err
def _set_space(self) -> None: """Set the active space""" if not self.space: sysout('%YELLOW%Checking space...') spaces = self.cf.spaces() if not spaces: raise CFExecutionError( f'Unable to retrieve spaces: => {self.cf.last_result}') self.space = mselect(spaces, title='Please select a space') if not self.space: sys.exit(1) else: self._target()
def get(self, key) -> None: """Display the vault entry specified by name :param key: The vault entry name to get """ entry = self.service.get_by_key(key) if entry: sysout("\n{}".format(entry.to_string(True, True))) else: log.error( "Attempt to get from Vault failed for name={}".format(key)) syserr("### No entry specified by '{}' was found in vault".format( key)) log.debug("Vault get issued. User={}".format(getpass.getuser()))
def _set_org(self) -> None: """Set the active organization""" if not self.org: sysout('%YELLOW%Checking organization...') orgs = self.cf.orgs() if not orgs: raise CFExecutionError( f'Unable to retrieve organizations: => {self.cf.last_result}' ) self.org = mselect(orgs, title='Please select the organization') if not self.org: sys.exit(1) else: self._target()
def _exec_application(self) -> None: if self.getarg('number') == 'one': sysout(f"One: {self.getarg('anything')}") elif self.getarg('number') == 'two': sysout(f"Two: {self.getarg('anything')}") elif self.getarg('number') == 'three': sysout(f"Three: {self.getarg('anything')}") sysout('Done')
def remove(self, key: str) -> None: """Remove a vault entry :param key: The vault entry name to be removed """ entry = self.service.get_by_key(key) if entry: self.service.remove(entry) sysout("%GREEN%\n=== Entry removed ===\n\n%NC%{}".format( entry.to_string())) else: log.error( "Attempt to remove to Vault failed for name={}".format(key)) syserr("### No entry specified by '{}' was found in vault".format( key)) log.debug("Vault remove issued. User={}".format(getpass.getuser()))
def _exec_application(self) -> None: """Execute the application""" if self.getarg('part'): caller = getattr(self.versioner, self.getarg('part')) else: caller = getattr(self.versioner, self.getarg('state')) caller() if self.versioner.save(self.getopt('backup')): sysout( f"%GREEN%Successfully updated version to {self.versioner.version()}" ) else: syserr( f"Failed to update version. No matches found for version {self.getarg('version')}" )
def _get_apps(self, refresh: bool = False) -> List[CFApplication]: """Retrieve all cf applications under the target/org""" if refresh or not self.apps: sysout(f'%GREEN%Retrieving {self.space} applications ...') apps = self.cf.apps() apps = list(map(CFApplication.of, apps if apps else [])) if not apps: if "OK" not in self.cf.last_result: raise CFExecutionError( f'Unable to retrieve applications: => {self.cf.last_result}' ) sysout('%YELLOW%No apps found') self.apps = apps return self.apps
def _render(self, nav_color: VtColors) -> None: """TODO""" restore_cursor() set_enable_echo() for idx, item in enumerate(self.items): self._print_cell( idx, item, MenuDashBoard.CELL_TPL if self.tab_index != idx else MenuDashBoard.SEL_CELL_TPL) sysout(f'%EL2%\r> %GREEN%{self.items[self.tab_index].tooltip}%NC%') sysout(self.NAV_FMT.format(nav_color.placeholder(), self.NAV_ICONS), end='') self.re_render = False
def execute(self) -> Optional[Menu]: """TODO""" while self.selected != 0 and not self.done: sysout(str(self)) try: self.selected = MenuUtils.prompt(end='$ ') if not self.selected: continue if self.selected.isalnum() and self.is_valid_option(): return self.trigger_menu_item() MenuUtils.print_error("Invalid option", self.selected) self.selected = None except InputAbortedError: continue
def _setup_parameters(self, *params, **kwargs) -> None: """Initialize application parameters and options""" if len(*params) == 0: welcome = self.WELCOME sysout(f"{welcome}") self.usage() else: # @formatter:off self._with_option('d', 'dest-dir', True) self._with_arguments(ArgumentChain.builder().when( 'operation', 'create').require('app-name', '.+').require( 'app-type', '|'.join(AppType.values())).accept( 'app-ext', '.+').end().when('operation', 'widgets').accept( 'widget-name', '.+').accept('widget-args', '.+').end().build())