def filter_cmd_action(cmd_str, cmd_vars, cmd_dict): """ filter command filter category name modifiers: Lu - letter, u - uppercase, l - lowercase, t - titlecase, m - modifier, 0 - other Mn - mark, n - non-spacing, c - spacing combining, e - enclosing Nd - number, d - decimal digit, l - letter, o - other Pc - punctuation, c - connector, d - dash, s - open, e - close, i - initial quote, f- final quote, 0 - other Sm - symbol, m - math, c - currency, k - modifier, o - other Zd - separator, s - space, l - line, p - paragraph Cc - other, c - control, f - format, s- surrogate, o - private use, n - not assinged This is summed up in regex: \*\*|L[ultmo\*]|M[nce\*]|N[dlo\*]|P[cdseifo\*]|S[mcko\*]|Z[slp\*]|C[cfson\*] """ cat_arg = name_arg = None variables = cmd_vars.split(' ') if len(cmd_vars) else [] cat_regex = '\*\*|L[ultmo\*]|M[nce\*]|N[dlo\*]|P[cdseifo\*]|S[mcko\*]|Z[slp\*]|C[cfson\*]' category_validator = ci.RegexValidator(pattern=cat_regex) if len(variables) > 2: print_filter_usage(cmd_str) return (ci.COMMAND_ACTION_NOP, None) if len(variables) > 0: cat_arg = variables[0] if len(cat_arg) != 2: print_filter_usage(cmd_str) return (ci.COMMAND_ACTION_NOP, None) name_arg = variables[1] if len(variables) > 1 else None if cat_arg is None: cat = ci.get_string(prompt='Enter filter value for category', default='**', validators=category_validator) else: if ci.validate(cat_arg, validators=category_validator): cat = cat_arg else: print_filter_usage(cmd_str) return (ci.COMMAND_ACTION_NOP, None) if name_arg is None: name = ci.get_string(prompt='Enter description keyword filter value', default=name_arg, required=False) else: name = name_arg cmd_dict['cat_filter'] = cat cmd_dict['name_filter'] = name raise ci.RefreshScreenInterrupt
def get_url_and_pn_re(default=DEFAULT_URL, default_re=DEFAULT_PN_RE, use_gui=True): if not use_gui: # use cooked_input url = ci.get_string( prompt="What Onshape document URL do want to renumber", default=default) pn_re = ci.get_string( prompt="Regular expression for part names to set as part number", default=DEFAULT_PN_RE) did, wvm, eid = parse_url(url, w_required=True) return did, wvm, eid, pn_re else: # use tkinter # TODO -- need to clean up -- add instructions, tables, etc. window = tk.Tk() window.title("Onshape Part Re-numbering Utility") window.geometry('950x150') url_str_var = tk.StringVar() url_str_var.set(default) re_str_var = tk.StringVar() re_str_var.set(default_re) lbl = tk.Label(window, text="Onshape model document URL:") lbl.grid(column=0, row=0) txt = tk.Entry(window, textvariable=url_str_var, width=120) txt.grid(column=1, row=0) lbl = tk.Label(window, text="Part number regular expression:") lbl.grid(column=0, row=1) txt = tk.Entry(window, textvariable=re_str_var, width=40) txt.grid(column=1, row=1) lbl = tk.Label(window, text="") lbl.grid(column=0, row=2) btn = tk.Button(window, text="Submit", command=window.quit) btn.grid(column=1, row=3) txt.focus() window.mainloop() url = url_str_var.get() pn_re = re_str_var.get() window.destroy() did, wvm, eid = parse_url(url, w_required=True) return did, wvm, eid, pn_re
def _find_doc(self, path, after=None, max_attempts=60, delay=1): """ Look in the nominated path for a new "docx" document for a file modified after `after`. If none are found, retry every `delay` seconds for at most `max_attempts` attempts. If no documents are found, raise a `RuntimeError`. """ count = 0 while count < max_attempts: count += 1 if count == 10: logger.info( "So far unable to find a new 'docx' file in %s. If you " "downloaded the Google Document elsewhere, please move it " "into this folder.", path) if not os.path.exists(path): break for filename in os.listdir(path): if filename.endswith(DOCX_EXTENSION): fpath = os.path.join(path, filename) if os.path.getmtime(fpath) > after: return fpath time.sleep(delay) if self.interactive: fpath = ci.get_string(prompt=( "We were unable to find the downloaded Google Doc in the " f"expected path: '{path}'. If the document was downloaded " "elsewhere, please enter the full path of downloaded " "document now (including file name)"), required=False) if fpath: return fpath raise RuntimeError(f"Cannot find 'docx' document in {path}.")
def create_html_action(row, action_dict): endpoints = action_dict['endpoints'] created = action_dict['created'] export_dir = Path.home().joinpath('export') dir_validator = ci.SimpleValidator(os.path.isdir) try: export_dir = ci.get_string(prompt='directory for html export: ', validators=dir_validator, default=str(export_dir)) except (ci.ValidationError): if ci.get_yes_no(prompt='Should I create the directory', default='no') == 'yes': os.mkdir(export_dir) else: print('Unable to export html') return toc_filename = Path(export_dir, TOC_FILENAME) with open(toc_filename, mode='w', encoding='utf-8') as f: create_toc(f, endpoints, created) for group in endpoints: for endpt in group['endpoints']: filename = Path(export_dir, endpt["name"] + '.html') with open(filename, mode='w', encoding='utf-8') as f: export_individual_endpoint_as_html(f, endpt) print('\n\n')
def test_err_fmt(self): input_str = 'foo\nbar\nblat\nfoo\nbar\nblat' err_fmt_str = 'You entered: "{value}", I said not "foo" or "bar" ({error_content})' not_foo_validator = ci.NoneOfValidator( ci.ChoiceValidator(['foo', 'bar'])) with redirect_stdin(StringIO(input_str)): result = ci.get_string(prompt='Enter a value (not "foo" or "bar")', validators=not_foo_validator) assert (result == 'blat') result = ci.get_string( prompt='Enter a value (not "foo" or "bar") - w error fmt str', validators=not_foo_validator, validator_error_fmt=err_fmt_str) assert (result == 'blat')
def get_dwe_from_url_action(row, action_dict): # Get the element id to work with url = ci.get_string( prompt="Get DID,WVM and EID from what Onshape document") did, wvm, eid = parse_url(url) action_dict['did'] = did action_dict['wvm'] = wvm action_dict['eid'] = eid print(f'\nSetting did={did}, wvm={wvm} and eid={eid}\n\n')
def add_event_action(row, action_item): events = action_dict['events'] event_types = action_dict['event_types'] cmds = action_dict['commands'] desc = ci.get_string(prompt="Event description? ", commands=cmds) tbl = ci.create_table(event_types, ["name", "desc"], ["Name", "Desc"], add_item_to_item_data=True) event_type = tbl.get_table_choice(prompt='Type? ', commands=cmds) date = ci.get_date(prompt='Date? ', default='today', commands=cmds) type_id = event_type.item_data['item'].id events.append(Event(len(events) + 1, date, desc, type_id))
def list_documents_action(row, action_dict): # Uses Documents API/Get Documents # parms - q - search for string in name of document # filter - 0-9 for filter, 0 - my docs, 6- by owner, 7 by company, 9 by team # owner - owner id for filter 6 or 7, team if 9 # offset - offset into the page (max 20) # limit - number of documents returned per page c = action_dict['client'] doc_query = {'offset': 0, 'limit': 20} name_filter = ci.get_string( prompt='String to filter document names (hit enter for no filter)', required=False, commands=std_commands) if name_filter is not None and len(name_filter) > 0: doc_query['q'] = name_filter if ci.get_yes_no(prompt='Show only your documents', default='no', commands=std_commands) == 'yes': filter_val, owner = (0, None) # filter by company doc_query = {'filter': 0} elif ci.get_yes_no(prompt='Show documents for your company', default='no', commands=std_commands) == 'yes': doc_query = { 'filter': 7, 'owner': action_dict['company'] } # filter by company # elif ...: # TODO - implement other filters - team, owner, etc. #filter_val, owner = (9, action_dict['team']) # filter by team #doc_query = {'filter': 9, 'owner': action_dict['team']} # filter by team else: if ci.get_yes_no( prompt= "Are you sure you want to fetch with no filters... this could take a long time!", default='no') == 'no': print('Cancelling action') raise ci.COMMAND_ACTION_CANCEL docs = c.list_documents(query=doc_query) tbl = create_docs_table(c, docs) tbl.get_table_choice(required=False, commands=table_commands) print('\n')
def get_document(client, company_id): # Uses Documents API/Get Documents # parms - q - search for string in name of document # filter - 0-9 for filter, 0 - my docs, 6- by owner, 7 by company, 9 by team # owner - owner id for filter 6 or 7, team if 9 # offset - offset into the page (max 20) # limit - number of documents returned per page fname_filter_str = ci.get_string(prompt='Document string to search for', commands=std_commands) filter_val, owner = (7, company_id) # filter by company doc_query = {'filter': filter_val, 'owner': owner} doc_query['q'] = fname_filter_str docs = c.list_documents(query=doc_query) tbl = create_docs_table(c, docs) if tbl.get_num_rows() == 1: # TODO - this doesn't work! choice = tbl.get_row(tag='1') else: choice = tbl.get_table_choice(prompt='choose a document', commands=table_commands) doc = choice.item_data['row'] return doc
def test_get_string(self): input_str = 'foo\n\nbar\nblat\n\nGo\n' with redirect_stdin(StringIO(input_str)): result = get_string(prompt='Enter any string', required=True) assert (result == 'foo') result = get_string( prompt='Enter any string at least 3 letters long', min_len=3, required=True) assert (result == 'bar') result = get_string( prompt='Enter any string at least 3 letters long', max_len=3, required=True) assert (result == 'Go') with redirect_stdin(StringIO(input_str)): result = get_string( prompt='Enter any string less than 4 letters long', max_len=3, required=True) assert (result == 'foo') result = get_string( prompt='Enter any string less than 4 letters long', min_len=2, max_len=3, required=True) assert (result == 'bar') result = get_string( prompt='Enter any string less than 4 letters long', max_len=3, required=False) assert (result is None)
def get_bom_action(row, action_dict): print('\n') c = action_dict['client'] did = action_dict['did'] wvm = action_dict['wvm'] eid = action_dict['eid'] types = ["flattened", "top-level", "multi-level"] type_vals = { "flattened": (False, False), "top-level": (True, False), "multi-level": (True, True) } prompt_str = f'BOM type ({", ".join(types)})' type_cleaner = ci.ChoiceCleaner(types) use_type = ci.get_string(prompt=prompt_str, cleaners=type_cleaner, default="flattened", commands=std_commands) indented, multi_level = type_vals[use_type] print( f'Fetching {multi_level} BOM from OnShape (did={did}, wvm={wvm}, eid={eid})' ) response = c.get_assembly_bom(did, wvm, eid, indented=indented, multi_level=multi_level, generate_if_absent=True) response_json = json.loads(response.text) try: status = response_json['status'] if status == 404: msg = response_json['message'] print("\nStatus 404 returned: {}\n".format(msg)) return except: pass bom_table = response_json['bomTable'] format_ver = bom_table['formatVersion'] name = bom_table['name'] bom_type = bom_table['type'] created_at = bom_table['createdAt'] doc_name = bom_table['bomSource']['document']['name'] top_pn = bom_table['bomSource']['element']['partNumber'] try: top_revision = bom_table['bomSource']['element'][ 'revision'] # column may not be there.. except (KeyError): top_revision = '--' state = bom_table['bomSource']['element']['state'] title = ( f"\n\n{bom_type} {name} (format version {format_ver}) - {doc_name} ({state} {top_pn}{top_revision}) created_at: {created_at}" ) rows = [] for idx, item in enumerate(bom_table['items']): item_num = item['item'] qty = item['quantity'] part_num = item['partNumber'] desc = item['description'] revision = item['revision'] state = item['state'] rows.append( ci.TableItem([qty, part_num, revision, state, desc], tag=item_num)) col_names = "Qty PartNum Rev State Desc".split() ci.Table(rows, col_names=col_names, title=title, tag_str='ItemNums').show_table() print('\n') # export to csv if ci.get_yes_no(prompt='Export to CSV file', default='no') == 'yes': cmds = {'/cancel': ci.GetInputCommand(cancel_cmd_action)} file_name = ci.get_string(prompt="CSV file_name to export to: ", default=f"{top_pn}_bom_export.csv", commands=cmds) with open(file_name, "w", encoding='utf-8', newline='') as f: hdr = 'ITEM_NUM QUANTITY PART_NUM REVISION STATE DESCRIPTION' csv_writer = csv.writer(f) csv_writer.writerow([f'{bom_type} BOM for:', top_pn]) csv_writer.writerow([]) csv_writer.writerow(hdr.split()) for item in bom_table['items']: csv_writer.writerow([ item['item'], item['quantity'], item['partNumber'], item['revision'], item['state'], item['description'] ])
import cooked_input # get user name user_name = cooked_input.get_string(prompt="what is your name?", required=False) print("user name is {}".format(user_name))
import cooked_input as ci cap_cleaner = ci.CapitalizationCleaner(style=ci.ALL_WORDS_CAP_STYLE) name = ci.get_string(prompt="What is your name?", cleaners=[cap_cleaner]) print(name)
from cooked_input.convertors import YesNoConvertor if __name__ == '__main__': colors = ['red', 'green', 'blue'] good_flavors = ['cherry', 'lime', 'lemon', 'orange'] bad_flavors = 'licorice' good_flavor_validator = ChoiceValidator(choices=good_flavors) not_in_choices_validator = NoneOfValidator( validators=[ChoiceValidator(choices=bad_flavors)]) strip_and_lower_cleaners = [ StripCleaner(), CapitalizationCleaner(style='lower') ] # simplest way print(get_string(prompt='Enter some text')) # strip and capitalization cleaners print( get_input( prompt= 'Enter any string (will be stripped of trailing spaces and converted to upper)', cleaners=[ StripCleaner(lstrip=False, rstrip=True), CapitalizationCleaner(style='upper') ])) print( get_input(prompt='Enter your name (all words will be capitalized)', cleaners=CapitalizationCleaner(style='all_words')))
def change_last_name(row, action_dict): result = get_string(prompt='Enter a new last name', default=action_dict['last']) action_dict['last'] = result