-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
draft: sketched out SO interface CI workflow. #798
base: main
Are you sure you want to change the base?
Changes from all commits
df86024
2bdc678
d9718b5
a094bfe
cde2320
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
|
||
name: interface-ci | ||
on: [pull_request] | ||
|
||
jobs: | ||
check-so-interface: | ||
runs-on: ubuntu-latest | ||
defaults: | ||
run: | ||
working-directory: ./tests/ci | ||
steps: | ||
- name: Check out the repository to the runner | ||
uses: actions/checkout@v4 | ||
- name: Check SO interface spec | ||
run: python ./check_so_interface.py |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,250 @@ | ||
import ast | ||
# functions and their arguments to check | ||
# specified here: https://www.overleaf.com/project/5e837cac9659910001e5f71e | ||
# could move this to a file | ||
#to complete: work on functions and arguments to check file and spec_args dictionary | ||
|
||
#Files that need to be checked: smurf_tune, smurf_command, smurf_util, smurf_noise, smurf_iv | ||
#python/pysmurf/client/util/smurf_util.py | ||
#python/pysmurf/client/command/smurf_command.py | ||
#python/pysmurf/client/debug/smurf_noise.py | ||
#python/pysmurf/client/debug/smurf_iv.py | ||
interface = { | ||
"python/pysmurf/client/tune/smurf_tune.py": { # file | ||
"SmurfTuneMixin": { # class | ||
"find_freq": [], # function and args | ||
} | ||
}, | ||
"python/pysmurf/client/command/smurf_command.py": { | ||
"SmurfCommandMixin": { | ||
"set_stream_enable": [] | ||
} | ||
}, | ||
"python/pysmurf/client/util/smurf_util.py": { | ||
"SmurfUtilMixin": { | ||
"which_on": [] | ||
} | ||
}, | ||
"python/pysmurf/client/debug/smurf_iv.py": { | ||
"SmurfIVMixin": { | ||
"run_iv": [] | ||
} | ||
}, | ||
"python/pysmurf/client/debug/smurf_noise.py": { | ||
"SmurfNoiseMixin": { | ||
"take_noise_psd" : [] | ||
} | ||
} | ||
} | ||
|
||
spec_args = { | ||
"setup": [ | ||
|
||
], | ||
"set_amplifier_bias": [ | ||
|
||
], | ||
"set_cryo_card_ps_en": [ | ||
|
||
], | ||
"which_on": [ | ||
|
||
], | ||
"band_off": [ | ||
|
||
], | ||
"channel_off": [ | ||
|
||
], | ||
"full_band_resp": [ | ||
|
||
], | ||
"find_freq": [ | ||
|
||
], | ||
"setup_notches": [ | ||
|
||
], | ||
"run_serial_gradient_descent": [ | ||
|
||
], | ||
"run_serial_eta_scan": [ | ||
|
||
], | ||
"plot_tune_summary": [ | ||
|
||
], | ||
"tracking_setup": [ | ||
|
||
], | ||
"set_amplitude_scale_array": [ | ||
|
||
], | ||
"set_tes_bias_bipolar_array": [ | ||
|
||
], | ||
"set_tes_bias_high_current": [ | ||
|
||
], | ||
"set_tes_bias_low_current": [ | ||
|
||
], | ||
"set_mode_dc" "set_mode_ac": [ | ||
|
||
], | ||
"flux_ramp_setup": [ | ||
|
||
], | ||
"set_stream_enable": [ | ||
|
||
], | ||
"take_stream_data": [ | ||
|
||
], | ||
"take_noise_psd": [ | ||
|
||
], | ||
"stream_data_on": [ | ||
|
||
], | ||
"stream_data_off": [ | ||
|
||
], | ||
"read_stream_data": [ | ||
|
||
], | ||
"set_downsample_filter": [ | ||
|
||
], | ||
"run_iv": [ | ||
|
||
], | ||
"analyze_iv": [ | ||
|
||
] | ||
} | ||
freeze = {} | ||
|
||
with open('tests/ci/frozen_functions.py', 'r') as fh: #opens file "fname", in read mode 'r', to be used in code as "fh" | ||
frozen = ast.parse(fh.read()) | ||
for node in ast.walk(frozen): | ||
if isinstance(node, ast.FunctionDef) and node.name in spec_args.keys(): | ||
freeze.update({node.name: node}) | ||
print("FROZEN") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's a lot of these print checks I put along the way to debug, and visualize the flow of my code. I haven't deleted them yet because I wanted to keep them in here to remember good places/dictionaries and lists to check in my code for future debugging. A final version of this code will definitely have these removed. |
||
print(freeze.items()) | ||
""" | ||
*** ==> I found this function in smurf_tune.py | ||
frozen functions list: | ||
|
||
SETUP FUNCTIONS | ||
setup | ||
set_amplifier_bias #smurf_command | ||
set_cryo_card_ps_en #smurf_command | ||
which_on #smurf_util | ||
band_off #smurf_util | ||
channel_off #smurf_util | ||
|
||
TUNING FUNCTIONS | ||
full_band_resp *** | ||
find_freq *** | ||
setup_notches *** | ||
run_serial_gradient_descent #smurf_command | ||
run_serial_eta_scan #smurf_command | ||
plot_tune_summary *** | ||
tracking_setup *** | ||
set_amplitude_scale_array #smurf_command | ||
|
||
TES/FLUX RAMP FUNCTIONS | ||
set_tes_bias_bipolar_array #smurf_util | ||
set_tes_bias_high_current #smurf_util | ||
set_tes_bias_low_current #smurft_util | ||
set_mode_dc #smurf_util | ||
set_mode_ac #smurf_util | ||
flux_ramp_setup *** | ||
|
||
DATA ACQUISITION FUNCTIONS | ||
set_stream_enable #smurf_command | ||
take_stream_data #smurf_util | ||
take_noise_psd #smurf_noise | ||
stream_data_on #smurf_util | ||
stream_data_off #surf_util | ||
read_stream_data #smurf_util | ||
set_downsample_filter #smurf_util | ||
|
||
IV FUNCTIONS | ||
run_iv #smurf_iv | ||
analyze_iv #smurf_iv | ||
|
||
DATA OUTPUTS TO DISK | ||
tune files generated when new resonators are found | ||
channel mapping file format | ||
.dat noise files - generated by take_stream_data | ||
iv_files - generated by run_iv" | ||
|
||
""" | ||
def compare_args(found, freeze): | ||
#print(freeze.values()) | ||
for func_name, func_node in found.items(): | ||
if func_name not in freeze: | ||
print(func_name + " not in specified functions") | ||
continue | ||
|
||
spec_func = freeze[func_name] | ||
#print(freeze[func_name]) | ||
if spec_func == []: | ||
print("waht") | ||
|
||
# Handle the case where spec_func is a list | ||
if isinstance(spec_func, list): | ||
if len(spec_func) == 0: | ||
print(f"No specification for {func_name}") | ||
continue | ||
spec_func = spec_func[0] # Assume the function is the first item in the list | ||
|
||
# Extract arguments from the AST node | ||
found_args = [arg.arg for arg in func_node.args.args] | ||
#print(found_args) | ||
found_defaults = [ast.unparse(d) if d else None for d in func_node.args.defaults] | ||
#print(found_defaults) | ||
|
||
# Extract arguments from the spec function | ||
spec_args_list = [arg.arg for arg in spec_func.args.args] | ||
spec_defaults = [ast.unparse(d) if d else None for d in spec_func.args.defaults] | ||
|
||
# Compare arguments | ||
if found_args != spec_args_list: | ||
print(f"Mismatch in arguments for function {func_name}") | ||
print(f"Found: {found_args}") | ||
print(f"Expected: {spec_args_list}") | ||
return False | ||
|
||
# Compare default values | ||
if found_defaults != spec_defaults: | ||
print(f"Mismatch in default values for function {func_name}") | ||
print(f"Found: {found_defaults}") | ||
print(f"Expected: {spec_defaults}") | ||
return False | ||
|
||
return True | ||
|
||
if __name__ == "__main__": #if this is the main thing being run | ||
for fname, spec in interface.items(): #loop over file names "fname" as keys and "spec" as values in dictionary called "interface" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. currently |
||
with open(fname, 'r') as fh: #opens file "fname", in read mode 'r', to be used in code as "fh" | ||
tree = ast.parse(fh.read()) #parsing contents of file into abstract syntax tree | ||
notfound = [] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. these two lines don't need to be in the context manager |
||
found = {} | ||
dump = ast.dump(tree) | ||
for node in ast.walk(tree): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the first layer in the tree is usually going to be made up of |
||
if isinstance(node, ast.FunctionDef) and node.name in spec_args.keys(): | ||
found.update({node.name: node}) | ||
for key in spec_args: | ||
if key not in found: | ||
notfound.append(key) | ||
#print("FOUND:") | ||
#print(found.items()) | ||
#print("NOT FOUND:") | ||
#print(notfound) | ||
#compare arguments | ||
assert compare_args(found, freeze) | ||
#print(ast.dump(found.get('find_freq'))) | ||
pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is going to be stored in this file? Is it a pseudo-python representation of the objects/methods structure that define the interface?