From d8ba42c49f134ffd97673a5ec04fd25ed667c505 Mon Sep 17 00:00:00 2001 From: Jane Liu Date: Wed, 9 Oct 2024 16:27:30 -0700 Subject: [PATCH 1/8] Updated cli.py so 'happi load' can handle glob searches, like 'happi load tmo_*'. --- happi/cli.py | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/happi/cli.py b/happi/cli.py index 65b56b95..d777ed68 100644 --- a/happi/cli.py +++ b/happi/cli.py @@ -396,9 +396,30 @@ def edit(ctx, name: str, edits: list[str]): @happi_cli.command() -@click.argument('item_names', nargs=-1) +@click.option('--glob/--regex', 'use_glob', default=True, + help='use glob style (default) or regex style search terms. ' + r'Regex requires backslashes to be escaped (eg. at\\d.\\d)') +@click.argument('search_criteria', nargs=-1) @click.pass_context -def load(ctx, item_names: list[str]): +def load( + ctx: click.Context, + use_glob: bool, + search_criteria: list[str] +): + + final_results = search_parser( + client=get_happi_client_from_config(ctx.obj), + use_glob=use_glob, + search_criteria=search_criteria, + ) + + if not final_results: + return [] + + item_names = [] + for res in final_results: + item_names.append(res['name']) + """Open IPython terminal with ITEM_NAMES loaded.""" logger.debug('Starting load block') @@ -406,13 +427,12 @@ def load(ctx, item_names: list[str]): client = get_happi_client_from_config(ctx.obj) devices = {} - names = " ".join(item_names) - names = names.split() - if len(names) < 1: + + if len(item_names) < 1: raise click.BadArgumentUsage('No item names given') logger.info(f'Creating shell with devices {item_names}') - for name in names: + for name in item_names: try: devices[name] = client.load_device(name=name) except SearchError as e: From 6450a1e77ef4020ccae61fe333a09c6375d532be Mon Sep 17 00:00:00 2001 From: Jane Liu Date: Wed, 9 Oct 2024 16:31:05 -0700 Subject: [PATCH 2/8] Added pre-commit changes. --- happi/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/happi/cli.py b/happi/cli.py index d777ed68..b112dc8c 100644 --- a/happi/cli.py +++ b/happi/cli.py @@ -427,7 +427,7 @@ def load( client = get_happi_client_from_config(ctx.obj) devices = {} - + if len(item_names) < 1: raise click.BadArgumentUsage('No item names given') logger.info(f'Creating shell with devices {item_names}') From 779086d2e0c4e82bb62ece673eac663913a52a4a Mon Sep 17 00:00:00 2001 From: Jane Liu Date: Thu, 10 Oct 2024 11:00:27 -0700 Subject: [PATCH 3/8] Updated cli.py with logic to handle user input with glob and non-glob patterns. --- happi/cli.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/happi/cli.py b/happi/cli.py index b112dc8c..a7ad64f8 100644 --- a/happi/cli.py +++ b/happi/cli.py @@ -406,19 +406,21 @@ def load( use_glob: bool, search_criteria: list[str] ): + item_names = [] - final_results = search_parser( - client=get_happi_client_from_config(ctx.obj), - use_glob=use_glob, - search_criteria=search_criteria, - ) - - if not final_results: - return [] + if '*' not in (' '.join(search_criteria)): + item_names = search_criteria + else: + final_results = search_parser( + client=get_happi_client_from_config(ctx.obj), + use_glob=use_glob, + search_criteria=search_criteria, + ) + if not final_results: + return [] - item_names = [] - for res in final_results: - item_names.append(res['name']) + for res in final_results: + item_names.append(res['name']) """Open IPython terminal with ITEM_NAMES loaded.""" From 06274c5ba6dca66e17798e4b9914a8d8aeba0f24 Mon Sep 17 00:00:00 2001 From: Jane Liu Date: Thu, 10 Oct 2024 11:29:41 -0700 Subject: [PATCH 4/8] Updated cli.py with documentation for the new feature and pre-commit changes. --- happi/cli.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/happi/cli.py b/happi/cli.py index a7ad64f8..2b4d5092 100644 --- a/happi/cli.py +++ b/happi/cli.py @@ -406,6 +406,9 @@ def load( use_glob: bool, search_criteria: list[str] ): + """ Checks if the search string contains a glob pattern. If so, + it's sent to the search_parser() function. """ + item_names = [] if '*' not in (' '.join(search_criteria)): From 9cfbf0c94c9303abba55af61ef75e6549224e0f6 Mon Sep 17 00:00:00 2001 From: Jane Liu Date: Thu, 10 Oct 2024 11:35:03 -0700 Subject: [PATCH 5/8] Added release notes. --- .../348-heuristic_loading.rst | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 docs/source/upcoming_release_notes/348-heuristic_loading.rst diff --git a/docs/source/upcoming_release_notes/348-heuristic_loading.rst b/docs/source/upcoming_release_notes/348-heuristic_loading.rst new file mode 100644 index 00000000..606a4218 --- /dev/null +++ b/docs/source/upcoming_release_notes/348-heuristic_loading.rst @@ -0,0 +1,22 @@ +348 heuristic_loading +################# + +API Breaks +---------- +- N/A + +Features +-------- +Updated happi's load() function to support searching and loading in one user-friendly expression. The load() function is now able to accept glob expressions like 'happi load tmo_*'. + +Bugfixes +-------- +- N/A + +Maintenance +----------- +- N/A + +Contributors +------------ +janeliu-slac From 85a13c0c07eb17ff14a07c923536b200f80c68df Mon Sep 17 00:00:00 2001 From: Jane Liu Date: Thu, 10 Oct 2024 13:19:58 -0700 Subject: [PATCH 6/8] Removed the line "if '*' not in (' '.join(search_criteria))". --- happi/cli.py | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/happi/cli.py b/happi/cli.py index 2b4d5092..27e118f2 100644 --- a/happi/cli.py +++ b/happi/cli.py @@ -406,24 +406,18 @@ def load( use_glob: bool, search_criteria: list[str] ): - """ Checks if the search string contains a glob pattern. If so, - it's sent to the search_parser() function. """ - item_names = [] - - if '*' not in (' '.join(search_criteria)): - item_names = search_criteria - else: - final_results = search_parser( - client=get_happi_client_from_config(ctx.obj), - use_glob=use_glob, - search_criteria=search_criteria, - ) - if not final_results: - return [] + final_results = search_parser( + client=get_happi_client_from_config(ctx.obj), + use_glob=use_glob, + search_criteria=search_criteria, + ) + if not final_results: + return [] - for res in final_results: - item_names.append(res['name']) + item_names = [] + for res in final_results: + item_names.append(res['name']) """Open IPython terminal with ITEM_NAMES loaded.""" @@ -432,12 +426,14 @@ def load( client = get_happi_client_from_config(ctx.obj) devices = {} + names = " ".join(item_names) + names = names.split() - if len(item_names) < 1: + if len(names) < 1: raise click.BadArgumentUsage('No item names given') logger.info(f'Creating shell with devices {item_names}') - for name in item_names: + for name in names: try: devices[name] = client.load_device(name=name) except SearchError as e: From 137bb1888d50d5c872a3a53837633e234bec714a Mon Sep 17 00:00:00 2001 From: Jane Liu Date: Thu, 10 Oct 2024 17:37:41 -0700 Subject: [PATCH 7/8] Recoded the feature to gather the results of each search term individually, then load the union of the results. --- happi/cli.py | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/happi/cli.py b/happi/cli.py index 27e118f2..83842530 100644 --- a/happi/cli.py +++ b/happi/cli.py @@ -406,32 +406,39 @@ def load( use_glob: bool, search_criteria: list[str] ): + term = [] + results = set() - final_results = search_parser( - client=get_happi_client_from_config(ctx.obj), - use_glob=use_glob, - search_criteria=search_criteria, - ) - if not final_results: - return [] + for item in search_criteria: + term.append(item) + + final_results = search_parser( + client=get_happi_client_from_config(ctx.obj), + use_glob=use_glob, + search_criteria=term, + ) + if not final_results: + print('%s was not found.' % item) + else: + for res in final_results: + results.add(res['name']) - item_names = [] - for res in final_results: - item_names.append(res['name']) + term = [] - """Open IPython terminal with ITEM_NAMES loaded.""" + # Open IPython terminal with RESULTS loaded logger.debug('Starting load block') # retrieve client client = get_happi_client_from_config(ctx.obj) devices = {} - names = " ".join(item_names) + names = " ".join(results) names = names.split() + print(names) if len(names) < 1: raise click.BadArgumentUsage('No item names given') - logger.info(f'Creating shell with devices {item_names}') + logger.info(f'Creating shell with devices {results}') for name in names: try: From 37d9c0614b73bf828eb10502421ba18f969034c9 Mon Sep 17 00:00:00 2001 From: Jane Liu Date: Fri, 11 Oct 2024 11:50:08 -0700 Subject: [PATCH 8/8] Removed some print statements used for testing. --- happi/cli.py | 1 - 1 file changed, 1 deletion(-) diff --git a/happi/cli.py b/happi/cli.py index 83842530..ce1b43e3 100644 --- a/happi/cli.py +++ b/happi/cli.py @@ -434,7 +434,6 @@ def load( devices = {} names = " ".join(results) names = names.split() - print(names) if len(names) < 1: raise click.BadArgumentUsage('No item names given')