def add_command(self, command): """Adds a command to the shell. Parameters: - (shell.commands.Command) command: The command to add. """ if isinstance(command, commands.Command): if command.name in self._commands: self.log(Language.get(Shell, "replacing_command") % command.name, level=3) else: self.log(Language.get(Shell, "loading_command") % command.name, level=3) self._commands[command.name] = command for alias in command.aliases: if alias not in self._commands: self.log(Language.get(Shell, "adding_alias") % (alias, command.name), level=3) self._commands[alias] = command.name else: self.log(Language.get(Shell, "ignoring_alias") % alias, level=3) else: self.error(Language.get(Shell, "command_not_loaded"))
def __init__( self, name ): """Initialize a command. Parameters: - (str) name: The name of the command. """ self.name = name self.aliases = [] self._description = Language.get( self.__class__, "description" ) self._long_description = Language.get( self.__class__, "long_description" )
def run(self, args=[]): """Launches the shell session. Parameters: - (list) args: Arguments passed to the shell. """ # Shell mode if len(args) == 0: self._running = True while self._running: try: commandline = self.input("%s > " % self._title) args = self.parse_line(commandline) if len(args) == 0: continue self.execute(args) except KeyboardInterrupt: print() self.log(Language.get(Shell, "interrupt_by_user"), level=0) self.exit() # Single command execution else: self.execute(args)
def name(self): srm_value = self.get_value(unit="°SRM") closest_srm = Color.srm_names[0] for value in Color.srm_names: if srm_value >= value: closest_srm = value else: break return Language.get(Color, "color_%d_SRM" % closest_srm)
def execute(self, args=[]): """Executes a parsed command line. Parameters: - (list) args: The parsed command line. """ command = self.get_command(args[0]) if command != None: command.run(self, args) else: self.error(Language.get(Shell, "unknown_command") % args[0])
def error(self, message, code=0): """Prints an error message to the standard error output. Prints an error message to the standard error output. If an error code greater than 0 is passed, it is prefixed to the message. Parameters: - (str) message: The error message to print. - (int) code: The error code associated to the message (default: 0) """ if code > 0: message = Language.get(Shell, "error_number") % (code, message) print("[!] %s" % message, file=sys.stderr)
def run( self, shell, args ): if len(args) > 1: if args[1] in shell._commands: command_name = args[1] # Avoid cyclic-dependencies tested_names = [] while isinstance( shell._commands[command_name], str ) and command_name not in tested_names: tested_names.append( command_name ) command_name = shell._commands[command_name] if isinstance( shell._commands[command_name], Command ): if args[1] == command_name: shell.print( Language.get( Help, "help_of_command" ) % command_name, lpad=1 ) else: shell.print( Language.get( Help, "help_of_alias" ) % (args[1], command_name), lpad=1 ) shell.print( "" ) shell.print( shell._commands[command_name].long_description, lpad=2 ) else: shell.error( Language.get( Help, "unknown_command" ) % args[1] ) else: shell.error( Language.get( Help, "unknown_command" ) % args[1] ) else: shell.print( "%s\n" % Language.get( Help, "commands_list" ), lpad=1 ) command_name_length = 0 for command in shell._commands: if command_name_length < len(command): command_name_length = len(command) command_name_length += 5 for command_name in shell._commands: command = shell._commands[command_name] if isinstance( command, Command ): lines = shell.print( command.description, left_text=" %s" % command_name, lpad=command_name_length ) # Print aliases' list if any if len(command.aliases): alias_title = "%s%s " % ( "".ljust( command_name_length ), Language.get( Help, "aliases" ) ) lines += shell.print( ", ".join( command.aliases ), left_text=alias_title, lpad=len( alias_title ) ) # If the command's information is larger than 1 line, empty line is added if lines > 1: shell.print( "" ) return 0
def __init__( self, config ): self.name = config["ingredient"]["name"] self.description = Language.get( self.__class__, "%s_description" % self.clean_name ) self.aliases = [] self.styles = [] self.substitutes = [] self.characteristics = [] self.country = None if "aliases" in config["ingredient"]: self.aliases = list(filter(len, re.split( r"\s*,\s*", config["ingredient"]["aliases"] ))) if "styles" in config["ingredient"]: self.styles = list(filter(len, re.split( r"\s*,\s*", config["ingredient"]["styles"] ))) if "substitutes" in config["ingredient"]: self.substitutes = list(filter(len, re.split( r"\s*,\s*", config["ingredient"]["substitutes"] ))) if "characteristics" in config["ingredient"]: self.characteristics = list(filter(len, re.split( r"\s*,\s*", config["ingredient"]["characteristics"] ))) if "country" in config["ingredient"]: self.country = Ingredient.sanitize_name( config["ingredient"]["country"] )
def run(self, shell, args): options = List.parse_options(args) hops = Hop.list_hops() printed_hops = 0 if options["alpha_acids"] and len(options["alpha_acids"]): comparator = "eq" if options["alpha_acids"][0] in [">", "<"]: if options["alpha_acids"][0] == "<": comparator = "lt" elif options["alpha_acids"][0] == ">": comparator = "gt" options["alpha_acids"] = options["alpha_acids"][1:] percent = unit.Unit.create(options["alpha_acids"]) if isinstance(percent, proportion.Proportion) or ( isinstance(percent, unit.Range) and isinstance(percent.get_min(), proportion.Proportion)): options["alpha_acids"] = (comparator, percent) else: shell.error(Language.get(List, "not_an_alpha_acids_percent")) options["alpha_acids"] = None return 1 for hop in hops: match_options = True # Name filter if match_options and (options["name"] and len(options["name"])): if options["name"].lower() not in hop.name.lower(): match_options = False # Purpose filter if match_options and (options["aroma"] or options["bittering"] or options["dual"]): match_options = False if options["aroma"] and hop.purpose == "aroma": match_options = True if options["bittering"] and hop.purpose == "bittering": match_options = True if options["dual"] and hop.purpose == "dual": match_options = True # Country filter # TODO: compare language names and aliases. if match_options and (options["country"] and len(options["country"])): if Ingredient.sanitize_name( options["country"]) != Ingredient.sanitize_name( hop.country): match_options = False # Style filter # TODO: compare language names and aliases. if match_options and (options["style"] and len(options["style"])): match_options = False for style in hop.styles: if Ingredient.sanitize_name( options["style"]) == Ingredient.sanitize_name( style): match_options = True break # Alpha acids filter if match_options and options["alpha_acids"]: comparator, percent = options["alpha_acids"] if comparator == "eq" and percent != hop.alpha_acids: match_options = False elif comparator == "lt" and percent <= hop.alpha_acids: match_options = False elif comparator == "gt" and percent >= hop.alpha_acids: match_options = False if match_options: shell.print("%s (%saa)" % (hop.name, hop.alpha_acids), lpad=1) printed_hops += 1 if printed_hops > 0: shell.log(Language.get(List, "n_hops_listed") % printed_hops, level=0) else: shell.log(Language.get(List, "no_hop_found"), level=0) return 0
def run(self, shell, args): if len(args) <= 1: shell.error(Language.get(Info, "please_specify_hop")) else: args.pop(0) hop_name = " ".join(args) hop = Hop.get(hop_name) if hop: title = Language.get(Info, "hop_variety") % hop.name shell.print(title, lpad=1) shell.print("=" * len(title), lpad=1) shell.print("") shell.print(hop.description, lpad=1) shell.print("") left_length = 0 keys = { "purpose": "purpose", "alpha_acids": "alpha_acids", "cohumulone": "cohumulone", "beta_acids": "beta_acids", "humulene": "_humulene_oil", "myrcene": "_myrcene_oil", "caryophyllene": "_caryophyllene_oil", "farnesene": "_farnesene_oil", "oil_per_100g": "_oil_volume_per_100g", "aliases": "aliases", "country": "country", "characteristics": "characteristics", "styles": "styles", "substitutes": "substitutes" } for key in keys: if keys[key] in hop.__dict__ and hop.__dict__[ keys[key]] != None: will_be_printed = True if isinstance(hop.__dict__[keys[key]], list) and len( hop.__dict__[keys[key]]) == 0: will_be_printed = False if will_be_printed: if len(Language.get(Info, key)) > left_length: left_length = len(Language.get(Info, key)) # Before & After spaces left_length += 2 if hop.purpose: shell.print(Language.get(Info, "purpose_%s" % hop.purpose), left_text=" %s" % Language.get(Info, "purpose"), lpad=left_length) if hop.alpha_acids: shell.print(hop.alpha_acids.to_string(), left_text=" %s" % Language.get(Info, "alpha_acids"), lpad=left_length) if hop.cohumulone: shell.print(hop.cohumulone.to_string(), left_text=" %s" % Language.get(Info, "cohumulone"), lpad=left_length) if hop.beta_acids: shell.print(hop.beta_acids.to_string(), left_text=" %s" % Language.get(Info, "beta_acids"), lpad=left_length) if hop.humulene: humulene_text = hop.humulene.to_string() humulene_volume = hop.get_humulene_volume() if humulene_volume != None: humulene_text += " (%s/100 g)" % humulene_volume.to_string( "mL") shell.print(humulene_text, left_text=" %s" % Language.get(Info, "humulene"), lpad=left_length) if hop.myrcene: myrcene_text = hop.myrcene.to_string() myrcene_volume = hop.get_myrcene_volume() if myrcene_volume != None: myrcene_text += " (%s/100 g)" % myrcene_volume.to_string( "mL") shell.print(myrcene_text, left_text=" %s" % Language.get(Info, "myrcene"), lpad=left_length) if hop.caryophyllene: caryophyllene_text = hop.caryophyllene.to_string() caryophyllene_volume = hop.get_caryophyllene_volume() if caryophyllene_volume != None: caryophyllene_text += " (%s/100 g)" % caryophyllene_volume.to_string( "mL") shell.print(caryophyllene_text, left_text=" %s" % Language.get(Info, "caryophyllene"), lpad=left_length) if hop.farnesene: farnesene_text = hop.farnesene.to_string() farnesene_volume = hop.get_farnesene_volume() if farnesene_volume != None: farnesene_text += " (%s/100 g)" % farnesene_volume.to_string( "mL") shell.print(farnesene_text, left_text=" %s" % Language.get(Info, "farnesene"), lpad=left_length) if hop.oil_volume_per_100g: shell.print(hop.oil_volume_per_100g.to_string(unit="mL"), left_text=" %s" % Language.get(Info, "oil_per_100g"), lpad=left_length) shell.print("") if len(hop.aliases): shell.print(", ".join(hop.aliases), left_text=" %s" % Language.get(Info, "aliases"), lpad=left_length) if hop.country: shell.print(hop.country_name, left_text=" %s" % Language.get(Info, "country"), lpad=left_length) if len(hop.characteristics): shell.print(", ".join(hop.characteristics), left_text=" %s" % Language.get(Info, "characteristics"), lpad=left_length) if len(hop.styles): shell.print(", ".join(hop.styles), left_text=" %s" % Language.get(Info, "styles"), lpad=left_length) if len(hop.substitutes): shell.print(", ".join(hop.substitutes), left_text=" %s" % Language.get(Info, "substitutes"), lpad=left_length) shell.print("") else: shell.error( Language.get(Info, "hop_does_not_exist") % hop_name) return 0
def country_name( self ): return Language.get( Ingredient, "country_%s" % self.country )
def parse_options_as_array( cls, args, silent=False ): """Parses options from arguments list to an ordered array. Parses options from arguments list to an orderd array where elements are tuples (option name, value). Unknown options and other arguments are added as string to the list. Parameters: - (list) args: The command line arguments. - (bool) silent: Disable warning messages. Return value: - (list) -- the parsed options. """ options = [] current_option = None current_value = None values_to_parse = 0 for arg in args: match = re.match( r"^-(?:-?([a-zA-Z0-9][a-zA-Z0-9_-]*)?)$", arg ) if match: if current_option != None: if not silent and (values_to_parse > 0 or (values_to_parse == -1 and len(current_value) == 0)): log.warn( Language.get( Command, "missing_value" ) % current_option ) options.append( (current_option, current_value) ) current_option = match.group( 1 ).lower() if match.group( 1 ) else None if current_option in cls._options: values_to_parse = cls._options[current_option]["params"] if "params" in cls._options[current_option] else 0 if values_to_parse == 0: current_value = True else: current_value = "" else: if not silent: log.warn( Language.get( Command, "unknown_option" ) % current_option ) options.append( match.group( 0 ) ) current_option = None current_value = None values_to_parse = 0 else: if values_to_parse > 0 or values_to_parse == -1: if len(current_value): current_value += " " + arg else: current_value = arg if values_to_parse > 0: values_to_parse -= 1 else: if current_option != None: if not silent and (values_to_parse > 0 or (values_to_parse == -1 and len(current_value) == 0)): log.warn( Language.get( Command, "missing_value" ) % current_option ) options.append( (current_option, current_value) ) current_option = None current_value = None values_to_parse = 0 options.append( arg ) if current_option != None: if not silent and (values_to_parse > 0 or (values_to_parse == -1 and len(current_value) == 0)): log.warn( Language.get( Command, "missing_value" ) % current_option ) options.append( (current_option, current_value) ) return options
def run(self, shell, args): options = List.parse_options(args) yeasts = Yeast.list_yeasts() printed_yeasts = 0 if options["attenuation"] and len(options["attenuation"]): percent = unit.Unit.create(options["attenuation"]) if isinstance(percent, proportion.Proportion) or ( isinstance(percent, unit.Range) and isinstance(percent.get_min(), proportion.Proportion)): options["attenuation"] = percent else: shell.error(Language.get(List, "not_an_attenuation_percent")) options["attenuation"] = None return 1 for yeast in yeasts: match_options = True # Name filter if match_options and (options["name"] and len(options["name"])): if options["name"].lower() not in yeast.name.lower(): match_options = False # Form filter if match_options and (options["dry"] or options["liquid"]): match_options = False if options["dry"] and yeast.is_dry(): match_options = True if options["liquid"] and yeast.is_liquid(): match_options = True # Style filter # TODO: compare language names and aliases. if match_options and (options["style"] and len(options["style"])): match_options = False for style in yeast.styles: if Ingredient.sanitize_name( options["style"]) == Ingredient.sanitize_name( style): match_options = True break # Attenuation filter if match_options and options["attenuation"]: match_options = (options["attenuation"] == yeast.attenuation) if match_options: shell.print("%s" % yeast.name, lpad=1) printed_yeasts += 1 if printed_yeasts > 0: shell.log(Language.get(List, "n_yeasts_listed") % printed_yeasts, level=0) else: shell.log(Language.get(List, "no_yeast_found"), level=0) return 0
def run(self, shell, args): if len(args) <= 1: shell.error(Language.get(Info, "please_specify_yeast")) else: args.pop(0) yeast_name = " ".join(args) yeast = Yeast.get(yeast_name) if yeast: title = yeast.name shell.print(title, lpad=1) shell.print("=" * len(title), lpad=1) shell.print("") shell.print(yeast.description, lpad=1) shell.print("") left_length = 0 keys = { "form": "form", "strain": "strain", "attenuation": "attenuation", "alcohol_tolerance": "alcohol_tolerance", "temperature": "temperature", "flocculation": "flocculation", "pitching_rate": "pitching_rate", "aliases": "aliases", "characteristics": "characteristics", "styles": "styles", "substitutes": "substitutes" } for key in keys: if keys[key] in yeast.__dict__ and yeast.__dict__[ keys[key]] != None: will_be_printed = True if isinstance(yeast.__dict__[keys[key]], list) and len( yeast.__dict__[keys[key]]) == 0: will_be_printed = False if will_be_printed: if len(Language.get(Info, key)) > left_length: left_length = len(Language.get(Info, key)) # Before & After spaces left_length += 2 if yeast.form: shell.print(Language.get(Info, "form_%s" % yeast.form), left_text=" %s" % Language.get(Info, "form"), lpad=left_length) if yeast.strain: shell.print(yeast.strain, left_text=" %s" % Language.get(Info, "strain"), lpad=left_length) if yeast.attenuation: shell.print(yeast.attenuation.to_string(), left_text=" %s" % Language.get(Info, "attenuation"), lpad=left_length) if yeast.temperature: shell.print(yeast.temperature.to_string(unit="°C"), left_text=" %s" % Language.get(Info, "temperature"), lpad=left_length) if yeast.alcohol_tolerance: shell.print(yeast.alcohol_tolerance.to_string(), left_text=" %s" % Language.get(Info, "alcohol_tolerance"), lpad=left_length) if yeast.dry_weight: shell.print(yeast.dry_weight.to_string(), left_text=" %s" % Language.get(Info, "dry_weight"), lpad=left_length) if yeast.flocculation: shell.print(yeast.flocculation, left_text=" %s" % Language.get(Info, "flocculation"), lpad=left_length) if yeast.pitching_rate: shell.print(yeast.pitching_rate, left_text=" %s" % Language.get(Info, "pitching_rate"), lpad=left_length) if len(yeast.aliases): shell.print(", ".join(yeast.aliases), left_text=" %s" % Language.get(Info, "aliases"), lpad=left_length) if len(yeast.characteristics): shell.print(", ".join(yeast.characteristics), left_text=" %s" % Language.get(Info, "characteristics"), lpad=left_length) if len(yeast.styles): shell.print(", ".join(yeast.styles), left_text=" %s" % Language.get(Info, "styles"), lpad=left_length) if len(yeast.substitutes): shell.print(", ".join(yeast.substitutes), left_text=" %s" % Language.get(Info, "substitutes"), lpad=left_length) shell.print("") else: shell.error( Language.get(Info, "yeast_does_not_exist") % yeast_name) return 0
def run( self, shell, args ): if len(args) < 2: shell.print( Language.get( Command, "help_message" ) % args[0], lpad=1 ) return 1 args.pop( 0 ) s_value = args[0] args.pop( 0 ) value = None elements = unit.Unit.parse( s_value ) # Unit may be the next argument if elements == None and len(args) > 0: s_value += args[0] args.pop( 0 ) elements = unit.Unit.parse( s_value ) # If the value could be parsed as an handled unit if elements != None: value = unit.Unit.create( s_value ) if value != None: to_unit = None in_keyword = False if len(args) > 0 and args[0] == "in": in_keyword = True args.pop( 0 ) if len(args) > 0: to_unit = args[0] args.pop( 0 ) if to_unit != None: if to_unit in unit.Unit.units: if to_unit in value.conversion_units: shell.print( value.to_string( unit=to_unit ) ) else: shell.error( Language.get( Command, "conversion_not_implemented" ) % (elements[1], to_unit) ) return 3 else: shell.error( Language.get( Command, "unit_not_handled" ) % to_unit ) return 2 elif not in_keyword: for to_unit in value.conversion_units: shell.print( value.to_string( unit=to_unit ) ) # Color name special case if isinstance( value, color.Color ): shell.print( value.name ) else: shell.error( Language.get( Command, "in_keyword_alone" ) ) return 1 else: shell.error( Language.get( Command, "unit_not_handled" ) % elements[1] ) return 2 else: shell.error( Language.get( Command, "it_is_not_an_unit" ) ) return 2 return 0