我们从Python开源项目中,提取了以下50个代码示例,用于说明如何使用six.moves.input()。
def prompt_for_role(roles): """ Ask user which role to assume. """ if len(roles) == 1: return roles[0] print 'Please select a role:' count = 1 for r in roles: print ' %d) %s' % (count, r[0]) count = count + 1 choice = 0 while choice < 1 or choice > len(roles) + 1: try: choice = int(input("Choice: ")) except ValueError: choice = 0 return roles[choice - 1]
def _setup_osf(args): # Command line options have precedence over environment variables, # which have precedence over the config file. config = config_from_env(config_from_file()) username = _get_username(args, config) project = config.get('project') if args.project is None: args.project = project # still None? We are in trouble if args.project is None: sys.exit('You have to specify a project ID via the command line,' ' configuration file or environment variable.') password = None if username is not None: password = os.getenv("OSF_PASSWORD") # Prompt user when password is not set if password is None: password = getpass.getpass('Please input your password: ') return OSF(username=username, password=password)
def __init__(self, redirector, terminators, multilineCommands, legalChars, commentGrammars, commentInProgress, case_insensitive, blankLinesAllowed, prefixParser, preparse, postparse, shortcuts): """Creates and uses parsers for user input according to app's parameters.""" self.commentGrammars = commentGrammars self.preparse = preparse self.postparse = postparse self.shortcuts = shortcuts self.main_parser = self._build_main_parser(redirector=redirector, terminators=terminators, multilineCommands=multilineCommands, legalChars=legalChars, commentInProgress=commentInProgress, case_insensitive=case_insensitive, blankLinesAllowed=blankLinesAllowed, prefixParser=prefixParser) self.input_source_parser = self._build_input_source_parser(legalChars=legalChars, commentInProgress=commentInProgress)
def span(self, raw): """Parses the input string search for a span pattern and if if found, returns a slice from the History list. :param raw: str - string potentially containing a span of the forms a..b, a:b, a:, ..b :return: List[HistoryItem] - slice from the History list """ if raw.lower() in ('*', '-', 'all'): raw = ':' results = self.spanpattern.search(raw) if not results: raise IndexError if not results.group('separator'): return [self[self._to_index(results.group('start'))]] start = self._to_index(results.group('start')) or 0 # Ensure start is not None end = self._to_index(results.group('end')) reverse = False if end is not None: if end < start: (start, end) = (end, start) reverse = True end += 1 result = self[start:end] if reverse: result.reverse() return result
def test_base_cmdloop_without_queue(): # Create a cmd2.Cmd() instance and make sure basic settings are like we want for test app = cmd2.Cmd() app.use_rawinput = True app.intro = 'Hello World, this is an intro ...' app.stdout = StdOut() # Mock out the input call so we don't actually wait for a user's response on stdin m = mock.MagicMock(name='input', return_value='quit') sm.input = m # Need to patch sys.argv so cmd2 doesn't think it was called with arguments equal to the py.test args testargs = ["prog"] expected = app.intro + '\n' with mock.patch.object(sys, 'argv', testargs): # Run the command loop app.cmdloop() out = app.stdout.buffer assert out == expected
def test_cmdloop_without_rawinput(): # Create a cmd2.Cmd() instance and make sure basic settings are like we want for test app = cmd2.Cmd() app.use_rawinput = False app.echo = False app.intro = 'Hello World, this is an intro ...' app.stdout = StdOut() # Mock out the input call so we don't actually wait for a user's response on stdin m = mock.MagicMock(name='input', return_value='quit') sm.input = m # Need to patch sys.argv so cmd2 doesn't think it was called with arguments equal to the py.test args testargs = ["prog"] expected = app.intro + '\n' with mock.patch.object(sys, 'argv', testargs): # Run the command loop app.cmdloop() out = app.stdout.buffer assert out == expected
def test_select_invalid_option(select_app): # Mock out the input call so we don't actually wait for a user's response on stdin m = mock.MagicMock(name='input') # If side_effect is an iterable then each call to the mock will return the next value from the iterable. m.side_effect = ['3', '1'] # First pass and invalid selection, then pass a valid one sm.input = m food = 'fish' out = run_cmd(select_app, "eat {}".format(food)) expected = normalize(""" 1. sweet 2. salty 3 isn't a valid choice. Pick a number between 1 and 2: {} with sweet sauce, yum! """.format(food)) # Make sure our mock was called exactly twice with the expected arguments arg = 'Sauce? ' calls = [mock.call(arg), mock.call(arg)] m.assert_has_calls(calls) # And verify the expected output to stdout assert out == expected
def test_select_list_of_strings(select_app): # Mock out the input call so we don't actually wait for a user's response on stdin m = mock.MagicMock(name='input', return_value='2') sm.input = m out = run_cmd(select_app, "study") expected = normalize(""" 1. math 2. science Good luck learning {}! """.format('science')) # Make sure our mock was called with the expected arguments m.assert_called_once_with('Subject? ') # And verify the expected output to stdout assert out == expected
def test_select_list_of_tuples(select_app): # Mock out the input call so we don't actually wait for a user's response on stdin m = mock.MagicMock(name='input', return_value='2') sm.input = m out = run_cmd(select_app, "procrastinate") expected = normalize(""" 1. Netflix 2. WebSurfing Have fun procrasinating with {}! """.format('Porn')) # Make sure our mock was called with the expected arguments m.assert_called_once_with('How would you like to procrastinate? ') # And verify the expected output to stdout assert out == expected
def test_select_uneven_list_of_tuples(select_app): # Mock out the input call so we don't actually wait for a user's response on stdin m = mock.MagicMock(name='input', return_value='2') sm.input = m out = run_cmd(select_app, "play") expected = normalize(""" 1. Electric Guitar 2. Drums Charm us with the {}... """.format('Drums')) # Make sure our mock was called with the expected arguments m.assert_called_once_with('Instrument? ') # And verify the expected output to stdout assert out == expected
def test_pseudo_raw_input_tty_rawinput_false(): # gin up some input like it's coming from a tty fakein = io.StringIO(u'{}'.format('set\n')) mtty = mock.MagicMock(name='isatty', return_value=True) fakein.isatty = mtty mreadline = mock.MagicMock(name='readline', wraps=fakein.readline) fakein.readline = mreadline # run the cmdloop, telling it where to get input from app = cmd2.Cmd(stdin=fakein) app.use_rawinput = False app._cmdloop() # because we mocked the readline() call, we won't get the prompt # or the name of the command in the output, so we can't check # if its there. We assume that if readline() got called twice, once # for the 'set' command, and once for the 'quit' command, # that the rest of it worked assert mreadline.call_count == 2 # the next helper function and two tests check for piped # input when use_rawinput is True.
def ashellsort(inarray): """ Shellsort algorithm. Sorts a 1D-array. Usage: ashellsort(inarray) Returns: sorted-inarray, sorting-index-vector (for original array) """ n = len(inarray) svec = inarray *1.0 ivec = list(range(n)) gap = n/2 # integer division needed while gap >0: for i in range(gap,n): for j in range(i-gap,-1,-gap): while j>=0 and svec[j]>svec[j+gap]: temp = svec[j] svec[j] = svec[j+gap] svec[j+gap] = temp itemp = ivec[j] ivec[j] = ivec[j+gap] ivec[j+gap] = itemp gap = gap / 2 # integer division needed # svec is now sorted input vector, ivec has the order svec[i] = vec[ivec[i]] return svec, ivec
def main(): folder = "/ais/gobi4/mren/data/cityscapes" for split in ["train", "valid", "test"]: output_fname = os.path.join(folder, "sem_seg", "{}_full_size.h5".format(split)) if os.path.exists(output_fname): confirm = input("Overwrite existing file {}? [Y/n]".format(output_fname)) if confirm == "n" or confirm == "N": return a = CityscapesAssembler( folder=folder, height=-1, width=-1, split=split, coarse_label=False, output_fname=output_fname, semantic_only=True) a.assemble()
def add_test_case(source, words, tokens, language): with open(TESTCASES_PATH) as f: cases = [json.loads(row) for row in f.readlines() if row.strip()] for case in cases: if case['sentence'] == source: print('The test case "%s" is already included.' % (source)) print('Do you want to update the test case with the new configuration? ' 'Enter `yes` to update or `no` to cencel. (y/n)') while True: response = input(colorize('Update?: ')) if response in {'y', 'yes'}: break elif response in {'n', 'no'}: return False else: print('Please enter `yes` or `no`.') with open(TESTCASES_PATH, 'a') as f: f.write(json.dumps({ 'sentence': source, 'language': language, 'tokens': tokens, 'expected': words, }, ensure_ascii=False, sort_keys=True).encode('utf-8') + '\n') print('Thank you for submission. Your test case "%s" is added.\n\n' % ( source))
def float_input(self, question, message='Invalid entry', default=None, required=True): ''' Method for floating point inputs with optionally specifiable error message. ''' float_result = None requiredFlag = True while (float_result is None and requiredFlag): result = input('%s: ' % question) if not result and not required: float_result = None requiredFlag = False if not result and default: float_result = default if float_result is None and requiredFlag: try: float_result = float(result) except ValueError: self.stdout.write(self.style.ERROR(message)) float_result = None return float_result
def manual(opts): if opts.mock: bot = MockEiBotBoard() else: bot = EiBotBoard.find() try: bot.servo_setup(config.PEN_DOWN_POSITION, config.PEN_UP_POSITION, config.SERVO_SPEED, config.SERVO_SPEED) if opts.cmd: cmd = ' '.join(opts.cmd) manual_command(bot, cmd) else: while True: cmd = input('(axibot) ') manual_command(bot, cmd) finally: bot.close()
def output_seed(seed): # type: (Seed) -> None """ Outputs the user's seed to stdout, along with lots of warnings about security. """ print( 'WARNING: Anyone who has your seed can spend your IOTAs! ' 'Clear the screen after recording your seed!' ) compat.input('') print('Your seed is:') print('') print(binary_type(seed).decode('ascii')) print('') print( 'Clear the screen to prevent shoulder surfing, ' 'and press return to continue.' ) print('https://en.wikipedia.org/wiki/Shoulder_surfing_(computer_security)') compat.input('')
def __init__(self): self.more_info = False self.dynamic = False self.mode_list = ['frequency', 'sigscore', 'count'] self.mode = 'frequency' # self.spanish_to_english = False self.num_options = 20 load_prev = input('Load previous session? y/n\n') if load_prev != 'n': loaded_voicebox = self.load_session() # unpickles a previously-saved object self.cursor = loaded_voicebox.cursor self.cursor_position = loaded_voicebox.cursor_position self.voices = loaded_voicebox.voices self.active_voice = loaded_voicebox.active_voice self.log = loaded_voicebox.log else: self.cursor = "|" self.cursor_position = 0 self.voices = {} self.load_voices() self.active_voice = self.choose_voice() self.log = []
def add_voice(self): new_voice = Voice({}) # creates new voice with no name and empty tree of corpora texts = os.listdir('texts') add_another_corpus = '' while add_another_corpus != 'n': for i in range(len(texts)): print("%s %s" % (i + 1, texts[i])) choice = input('Enter the number of the corpus you want to load:\n') corpus_name = texts[int(choice) - 1] path = 'texts/%s' % corpus_name f = open(path, 'r') text = f.read() corpus_weight_prompt = 'Enter the weight for %s:\n' % corpus_name corpus_weight = float(input(corpus_weight_prompt)) new_voice.add_corpus(Corpus(text, corpus_name), corpus_weight) texts.remove(corpus_name) add_another_corpus = input('Add another corpus to this voice? y/n\n') voicename = input('Name this voice:\n') new_voice.name = voicename new_voice.normalize_weights() self.voices[voicename] = new_voice # asks user to specify a transcript and number of characters, and makes separate voices for that number of # the most represented characters in the transcript
def load_voices_from_transcript(self): transcripts = os.listdir('texts/transcripts') for i in range(len(transcripts)): print("%s %s" % (i + 1, transcripts[i])) choice = input('Enter the number of the transcript you want to load:\n') transcript_name = transcripts[int(choice) - 1] number = int(input('Enter the number of voices to load:\n')) for charname, size in self.biggest_characters(transcript_name, number): print(charname) path = 'texts/transcripts/%s/%s' % (transcript_name, charname) source_text = open(path).read() corpus_name = charname weighted_corpora = {} weighted_corpora[charname] = [Corpus(source_text, corpus_name), 1] self.voices[charname] = Voice(weighted_corpora, charname) # retrieves a list of the top 20 largest character text files in a transcript folder
def create_db(db_filename, conf_filename, python_path, manage_path): if not os.path.isfile(db_filename): print("create:\tdb\t{0}".format(db_filename)) os.environ["SETTINGS"] = conf_filename res = subprocess.check_output([python_path, manage_path, "db", "upgrade"]) if not res: res = "OK" print("result:\t{0}".format(res)) username = input("Choose a username for accessing Gthnk: ") password = getpass("Choose a password:") res = subprocess.check_output([python_path, manage_path, "user_add", "-e", username, "-p", password]) if not res: res = "OK" print("result:\t{0}".format(res)) else: print("exists:\t{0}".format(db_filename))
def get_confirmation(prompt): """Method to confirm decisions Args: prompt(str): Question to ask the user Returns: (bool): True indicating yes, False indicating no """ decision = False while True: confirm = input("{} (y/n): ".format(prompt)) if confirm.lower() == "y": decision = True break elif confirm.lower() == "n": decision = False break else: print("Enter 'y' or 'n' for 'yes' or 'no'") return decision
def pager(text, pagesize=None): """ Paging output, mimic external command less/more """ if not pagesize: pagesize = config.Option.get("pagesize") if pagesize <= 0: msg(text) return i = 1 text = text.splitlines() l = len(text) for line in text: msg(line) if i % pagesize == 0: ans = input("--More--(%d/%d)" % (i, l)) if ans.lower().strip() == "q": break i += 1 return
def _call_validator(opttype, optdict, option, value): if opttype not in VALIDATORS: raise Exception('Unsupported type "%s"' % opttype) try: return VALIDATORS[opttype](optdict, option, value) except TypeError: try: return VALIDATORS[opttype](value) except optik_ext.OptionValueError: raise except: raise optik_ext.OptionValueError('%s value (%r) should be of type %s' % (option, value, opttype)) # user input functions ######################################################## # user input functions will ask the user for input on stdin then validate # the result and return the validated value or raise optparse.OptionValueError # XXX add to documentation
def format_option_value(optdict, value): """return the user input's value from a 'compiled' value""" if isinstance(value, (list, tuple)): value = ','.join(value) elif isinstance(value, dict): value = ','.join(['%s:%s' % (k, v) for k, v in value.items()]) elif hasattr(value, 'match'): # optdict.get('type') == 'regexp' # compiled regexp value = value.pattern elif optdict.get('type') == 'yn': value = value and 'yes' or 'no' elif isinstance(value, string_types) and value.isspace(): value = "'%s'" % value elif optdict.get('type') == 'time' and isinstance(value, (float, int, long)): value = format_time(value) elif optdict.get('type') == 'bytes' and hasattr(value, '__int__'): value = format_bytes(value) return value
def pseudo_raw_input(self, prompt): """copied from cmd's cmdloop; like raw_input, but accounts for changed stdin, stdout""" if self.use_rawinput: try: line = sm.input(prompt) except EOFError: line = 'EOF' else: self.stdout.write(prompt) self.stdout.flush() line = self.stdin.readline() if not len(line): line = 'EOF' else: if line[-1] == '\n': # this was always true in Cmd line = line[:-1] return line
def main(): state = ConnectFourGame.initial_state() while True: winner = ConnectFourGame.get_winner(state) if winner is not None: dump_state(state) break legal_moves = ConnectFourGame.get_moves(state)[1] result = ( MCTS(ConnectFourGame, state) .get_simulation_result(1000)) move = result.move dump_state(state, result.root.children, move) if state.current_player == 0: while True: try: move = int(input('')) assert move in legal_moves state = ConnectFourGame.apply_move(state, move) break except (AssertionError, ValueError): print(dumps({'error': 'That is not a legal move'})) else: state = ConnectFourGame.apply_move(state, move)
def main(): state = TicTacToeGame.initial_state() while True: if state.winner: TicTacToeGame.print_board(state) if state.winner is Draw: print('Draw!') elif state.winner: print(state.winner + ' wins') break if state.current_player == 'O': while True: TicTacToeGame.print_board(state) try: move = int(input('Move:')) state = TicTacToeGame.apply_move(state, move) break except ValueError: print('That is not a legal move') else: result = (MCTS(TicTacToeGame, state) .get_simulation_result(100)) state = TicTacToeGame.apply_move(state, result.move)
def user_input(self, prompt=None): """ A wrapper function for getting user input while keeping track of the amount of time spent waiting for it. """ start = arrow.utcnow() try: if self.default_format and prompt: return raw_input('%(format)s%(prompt)s%(end)s' % { 'format': self.default_format, 'prompt': prompt, 'end': TerminalFormats.ENDC }) else: return raw_input(prompt) finally: end = arrow.utcnow() self._waiting_on_user_delta += end - start
def handle(self, config, email, password, target, name, **options): try: config.get('serverapi', 'server_id') except NoOptionError: pass else: raise CommandError("This server is already registered. If you've unregistered it from your team dashboard, you can delete {}".format(options['config_path'])) if email is None: email = input("Enter your Cloak email: ") if password is None: password = getpass("Enter your Cloak password: ") if target is None: target = input("Enter the target identifier (from the team dashboard): ") server = Server.register(email, password, target, name) config.set('serverapi', 'server_id', server.server_id) config.set('serverapi', 'auth_token', server.auth_token) print("This server has been registered. The next step is to request a certificate.", file=self.stdout)
def ask_for_domain(): """ Prompt the user for a Canvas domain. To ensure that the API calls are made on an encrypted SSL connection the initial 'https://' is pre-specified. To ensure that the user input is 1) a valid URL and 2) a URL representing a Canvas web server request is used to fetch a resources on the Canvas page. If the GET requests fails the URL was not valid. If the server returns a 404 unauthenticated error the domain is very likely to be a Canvas server, if anything else is returned the URL points to a correct URL that is not a Canvas server. """ found = False # Keep asking until a valid domain has been entered by the user while not found: domain = u"https://" + input(u"\nEnter the Canvas domain of your institution:\n$ https://") found = static_functions.validate_domain(domain) return domain
def ask_for_advanced_settings(settings): choice = -1 while choice not in (1, 2): settings.print_settings(clear=True) print(ANSI.format(u"\n\nAll mandatory settings are set. Do you wish see advanced settings?", u"announcer")) print(ANSI.format(u"\n[1]\tShow advanced settings (recommended)", u"bold")) print(ANSI.format(u"[2]\tUse default settings", u"bold")) try: choice = int(input(u"\nChoose number: ")) except ValueError: continue if choice == 1: return True elif choice == 2: return False else: continue
def ask_for_assignment_sync(settings): choice = -1 while choice not in (1, 2): settings.print_advanced_settings(clear=True) print(ANSI.format(u"\n\nAssignments settings", u"announcer")) print(ANSI.format(u"Would you like CanvasSync to synchronize assignments?\n\n" u"The assignment description will be downloaded as a HTML to be viewed offline\n" u"and files hosted on the Canvas server that are described in the assignment\n" u"description section will be downloaded to the same folder.\n", u"white")) print(ANSI.format(u"1) Sync assignments (default)", u"bold")) print(ANSI.format(u"2) Do not sync assignments", u"bold")) try: choice = int(input(u"\nChoose number: ")) except ValueError: continue if choice == 1: return True elif choice == 2: return False else: continue
def main_menu(settings): """ Main menu function, calss the settings.show_ main_screen function and handles user response """ to_do = settings.show_main_screen(settings.settings_file_exists()) # Act according to the users input to the main menu function if to_do == u"quit": sys.exit() elif to_do == u"set_settings": settings.set_settings() main_menu(settings) elif to_do == u"show_settings": settings.show(quit=False) main_menu(settings) elif to_do == u"show_help": usage.help() else: do_sync(settings, "")
def askYesNo(msg, default=None): default = default and default.lower() y = 'Y' if default == 'y' else 'y' n = 'N' if default == 'n' else 'n' prompt = msg + ' (%s/%s)? ' % (y, n) value = None while value is None: value = input(prompt).lower() if value == '' and default: return default == 'y' if value not in ('y', 'n', 'yes', 'no'): value = None return value in ('y', 'yes')
def get_file_abspath(): file_abspath = None while file_abspath is None: file_path = input('\nPath to your file: ') if sys.platform.startswith('win'): file_path = file_path.replace('/', os.sep) else: file_path = file_path.replace('\\', os.sep) file_abspath = os.path.abspath(file_path) if not os.path.isfile(file_abspath): print('Invalid file path!') file_abspath = None return file_abspath
def get_encoding(): encoding = ENCODING print('\nDefault encoding for input and output files:', encoding) change_encoding_ans = None while change_encoding_ans is None: change_encoding_ans = input('Change encoding? [N/y] ') if change_encoding_ans and change_encoding_ans[0].lower() == 'y': new_encoding = None while new_encoding is None: new_encoding = input('New encoding: ') if not new_encoding: new_encoding = None encoding = new_encoding return encoding
def edit_file(file_path, ask=None): # return True if user tries to edit the file if ask: try: answer = input(ask) except KeyboardInterrupt: return False if answer.lower() != "yes": return False editor = os.environ.get("EDITOR", Config.get("misc.editor")) res = os.system("{} {}".format(editor, file_path)) if res != 0: print("Error executing the default editor ({})".format(editor)) return res == 0
def __input_slack(self): slack_conf = self.slack() while True: token = input("Please type for Slack api token. [required] %s : " % slack_conf["token"]) if not token: if slack_conf["token"]: token = slack_conf["token"] break else: continue else: break default_chanel = input("Please type for default channel. [not required] %s : " % slack_conf["channel"]) if not default_chanel and slack_conf["channel"]: default_chanel = slack_conf["channel"] bot_icon = input("Please type for image url. [not required] %s : " % slack_conf["bot_icon"]) if not bot_icon and slack_conf["bot_icon"]: bot_icon = slack_conf["bot_icon"] return { "token": token, "channel": default_chanel, "bot_icon": bot_icon }
def modifyChangelistUser(self, changelist, newUser): # fixup the user field of a changelist after it has been submitted. changes = p4CmdList("change -o %s" % changelist) if len(changes) != 1: die("Bad output from p4 change modifying %s to user %s" % (changelist, newUser)) c = changes[0] if c['User'] == newUser: return # nothing to do c['User'] = newUser input = marshal.dumps(c) result = p4CmdList("change -f -i", stdin=input) for r in result: if 'code' in r: if r['code'] == 'error': die("Could not modify user field of changelist %s to %s:%s" % (changelist, newUser, r['data'])) if 'data' in r: print("Updated user field for changelist %s to %s" % (changelist, newUser)) return die("Could not modify user field of changelist %s to %s" % (changelist, newUser))
def cli(project, base_image, base_deps, add_deps, requirements): project_dir = utils.get_project_dir() scrapy_config = shub_utils.get_config() if not scrapy_config.has_option('settings', project): raise shub_exceptions.BadConfigException( 'Settings for the project is not found') settings_module = scrapy_config.get('settings', project) values = { 'base_image': base_image, 'system_deps': _format_system_deps(base_deps, add_deps), 'system_env': _format_system_env(settings_module), 'requirements': _format_requirements(project_dir, requirements), } values = {key: value if value else '' for key, value in values.items()} source = Template(DOCKERFILE_TEMPLATE.strip()) results = source.substitute(values) results = results.replace('\n\n', '\n') click.echo("The following Dockerfile will be created:\n{}".format(results)) valid = {"yes": True, "y": True, "ye": True, "no": False, "n": False} while True: dockefile_path = os.path.join(project_dir, 'Dockerfile') choice = input("Save to {}: (y/n)".format(dockefile_path)).lower() if choice in valid: if valid[choice]: with open(dockefile_path, 'w') as dockerfile: dockerfile.write(results) click.echo('Saved.') break click.echo("Please respond with 'yes'('y') or 'no'(n)")
def init(args): """Initialize or edit an existing .osfcli.config file.""" # reading existing config file, convert to configparser object config = config_from_file() config_ = configparser.ConfigParser() config_.add_section('osf') if 'username' not in config.keys(): config_.set('osf', 'username', '') else: config_.set('osf', 'username', config['username']) if 'project' not in config.keys(): config_.set('osf', 'project', '') else: config_.set('osf', 'project', config['project']) # now we can start asking for new values print('Provide a username for the config file [current username: {}]:'.format( config_.get('osf', 'username'))) username = input() if username: config_.set('osf', 'username', username) print('Provide a project for the config file [current project: {}]:'.format( config_.get('osf', 'project'))) project = input() if project: config_.set('osf', 'project', project) cfgfile = open(".osfcli.config", "w") config_.write(cfgfile) cfgfile.close()
def get_input(text=''): i = input(text) if isinstance(i, bytes): return i.decode('utf-8', errors='replace') return i