Skip to content
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

Bugfix 2428 python embedding with MET_PYTHON_EXE defined #2462

Merged
merged 14 commits into from
Feb 24, 2023

Conversation

hsoh-u
Copy link
Collaborator

@hsoh-u hsoh-u commented Feb 23, 2023

Expected Differences

Same as the bugfix for 11.0

If MET_PYTHON_EXE is defined, the met_point_data is saved as temporary NetCDF file and MET reads the NetCDF file by using compile time python. The log message shows if the temporary file was created.
Without the environment variable MET_PYTHON_EXE

DEBUG 3: Initializing MET compile time python instance: /usr/local/met-python3/bin/python3.8
DEBUG 3: Running MET compile time python instance (/usr/local/met-python3/bin/python3.8) to run user's python script (../../../../scripts/python/read_met_point_obs).
DEBUG 2: Processing 78376 observations at 8465 locations.

With the environment variable MET_PYTHON_EXE

DEBUG 3: Initializing MET compile time python instance: /usr/local/met-python3/bin/python3.8
DEBUG 3: Running user-specified python instance (MET_PYTHON_EXE=/usr/local/python3/bin/python3) to run user's python script (../../../../scripts/python/read_met_point_obs).
DEBUG 4: Writing temporary Python point data file:
DEBUG 4:        /usr/local/python3/bin/python3 /d1/personal/hsoh/git/bugfixes/bugfix_2428_python_from_env_2/MET/share/met/wrappers/write_tmp_point_nc.py /dev/shm/hsoh/tmp/tmp_met_nc_11538_0 ../../../../scripts/python/read_met_point_obs /d1/personal/hsoh/MET/test_output/NB/pb2nc/ndas.20120409.t12z.prepbufr.tm00.nc
  python: Python Script:        '/d1/personal/hsoh/git/bugfixes/bugfix_2428_python_from_env_2/MET/share/met/wrappers/write_tmp_point_nc.py'
  python: User Command: '../../../../scripts/python/read_met_point_obs /d1/personal/hsoh/MET/test_output/NB/pb2nc/ndas.20120409.t12z.prepbufr.tm00.nc'
  python: Temporary File:       '/dev/shm/hsoh/tmp/tmp_met_nc_11538_0'
  python: Done python script ../../../../scripts/python/read_met_point_obs took 0:00:00.038250
DEBUG 4: Reading temporary Python point data file: /dev/shm/hsoh/tmp/tmp_met_nc_11538_0
DEBUG 2: Processing 78376 observations at 8465 locations.
  • Do these changes introduce new tools, command line arguments, or configuration file options? [No]

    If yes, please describe:

  • Do these changes modify the structure of existing or add new output data types (e.g. statistic line types or NetCDF variables)? [No]

    If yes, please describe:

Pull Request Testing

  • Describe testing already performed for these changes:

at seneca:

export MET_BASE=/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_main_v11.0/share/met
export MET_PYTHON_EXE=/usr/local/met-python3/bin/python3.8

/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_main_v11.0/bin/plot_point_obs \
   'PYTHON_NUMPY=/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_main_v11.0/scripts/python/read_met_point_obs.py /d1/personal/hsoh/MET/test_output/NB/pb2nc/ndas.20120409.t12z.prepbufr.tm00.nc' \
  pointdata_numpy.ps -dotsize 2.0 -v 4 | grep -v "Plotting location"

unset MET_PYTHON_EXE

/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_main_v11.0/bin/plot_point_obs \
   'PYTHON_NUMPY=/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_main_v11.0/scripts/python/read_met_point_obs.py /d1/personal/hsoh/MET/test_output/NB/pb2nc/ndas.20120409.t12z.prepbufr.tm00.nc' \
  pointdata_numpy.ps -dotsize 2.0 -v 4 | grep -v "Plotting location"

Test from #2428

export MET_BASE=/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/share/met
export MET_PYTHON_EXE=/usr/local/met-python3/bin/python3.8

/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/bin/plot_point_obs \
  "PYTHON_NUMPY=/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/scripts/python/read_ascii_point.py /d1/projects/MET/MET_releases/MET-11.0.0/data/sample_obs/ascii/sample_ascii_obs.txt" \
  test.ps -v 4 | grep -v "Plotting location"
  • Recommend testing for the reviewer(s) to perform, including the location of input datasets, and any additional instructions:

  • Do these changes include sufficient documentation updates, ensuring that no errors or warnings exist in the build of the documentation? [No]

  • Do these changes include sufficient testing updates? [Yes]

Unittest "python_point2grid_pb2nc_TMP_user_python" was added. It should produce the same output with python_point2grid_pb2nc_TMP (pb2nc_TMP.nc and pb2nc_TMP_user_python.nc).

  • Will this PR result in changes to the test suite? [Yes]

    If yes, describe the new output and/or changes to the existing output:

One more output python/pb2nc_TMP_user_python.nc

  • Please complete this pull request review by [Fill in date].

Pull Request Checklist

See the METplus Workflow for details.

  • Review the source issue metadata (required labels, projects, and milestone).
  • Complete the PR definition above.
  • Ensure the PR title matches the feature or bugfix branch name.
  • Define the PR metadata, as permissions allow.
    Select: Reviewer(s)
    Select: Organization level software support Project or Repository level development cycle Project
    Select: Milestone as the version that will include these changes
  • After submitting the PR, select Development issue with the original issue number.
  • After the PR is approved, merge your changes. If permissions do not allow this, request that the reviewer do the merge.
  • Close the linked issue and delete your feature or bugfix branch from GitHub.

Copy link
Collaborator

@georgemccabe georgemccabe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See inline comments

import os
import sys

met_base_dir = os.getenv('MET_BASE',None)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think these 3 lines are necessary since the path is appended using the relative path of the script below.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MET_BASE was removed at read_tmp_point_nc.py and write_tmp_point_nc.py

import sys
import importlib.util

met_base_dir = os.getenv('MET_BASE',None)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think these 3 lines are necessary since the path is appended using the relative path of the script below.


def get_type(self, value):
return 'string' if isinstance('str') else type(value)
if not self.is_numpy_array(self.hdr_typ):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clean up this logic, I suggest putting the is_numpy_array check inside the convert_to_numpy function. If it is already an numpy array, the function could just return the input. I believe the variables are passed by reference so the function could simply return if it is already a numpy array or modify the value if it is not instead of returning a value. It would be good to double check that this works.

    def convert_to_numpy(self, value_list):
        if self.is_numpy_array(value_list):
            return
        value_list = np.array(value_list)

Then replace:

        if not self.is_numpy_array(self.hdr_typ):
            self.hdr_typ = self.convert_to_numpy(self.hdr_typ)

with:

        self.convert_to_numpy(self.hdr_typ)

Copy link
Collaborator Author

@hsoh-u hsoh-u Feb 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the suggestion. I'm not sure it works. Is there a way to pass the reference?
Here are my tests:

def set_to_var(local_var):
    local_var = ['111', '222']
    print('local_var', local_var)

aaa = ['bb','cc']
set_to_var(aaa)
print(aaa)

result

('local_var', ['111', '222'])
['bb', 'cc']

The content of test.py:

class my_class(object):
   def __init__(self):
       self.my_var = [ '111', 'bbb']

   def update_var(self, var_name):
       print('  input at update_var:', var_name)
       var_name = [' abc', 'def' ]
       print('  updated by update_var:', var_name)

   def do_job(self):
       self.update_var(self.my_var)
       print('  after calling update_var:', self.my_var)


test = my_class()
test.do_job()

python3 ./test.py

  input at update_var: ['111', 'bbb']
  updated by update_var: [' abc', 'def']
  after calling update_var: ['111', 'bbb']

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right that it won't work. You are able to change the values of a list or dictionary in a function, but not the entire list itself. Thanks for checking.

def set_to_var(local_var):
  local_var[0] = 'a'
  print('local_var', local_var)

aaa = ['bb','cc']
set_to_var(aaa)
print(aaa)

Result:

local_var ['a', 'cc']
['a', 'cc']

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to know this.

print("{p} User Command:\t".format(p=PROMPT) + repr(' '.join(sys.argv[2:])))
print("{p} Temporary File:\t".format(p=PROMPT) + repr(sys.argv[1]))

tmp_filename = sys.argv[1]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of this logic looks to be the same as other scripts in the data/wrappers directory. We should consider pulling out duplicate code into a function. This isn't required for this PR and could be done during a bigger refactor of the Python Embedding logic.

@DanielAdriaansen
Copy link
Contributor

DanielAdriaansen commented Feb 23, 2023

The test listed in the PR for #2428 does not work for me:

dadriaan@seneca:~$ export MET_BASE=/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/share/met
dadriaan@seneca:~$ export MET_PYTHON_EXE=/usr/local/met-python3/bin/python3.8
dadriaan@seneca:~$ /d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/bin/plot_point_obs   "PYTHON_NUMPY=/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/scripts/python/read_ascii_point.py /d1/projects/MET/MET_releases/MET-11.0.0/data/sample_obs/ascii/sample_ascii_obs.txt"   test.ps -v 4 | grep -v "Plotting location"
DEBUG 1: Start plot_point_obs by dadriaan(15368) at 2023-02-23 20:29:00Z  cmd: /d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/bin/plot_point_obs PYTHON_NUMPY=/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/scripts/python/read_ascii_point.py /d1/projects/MET/MET_releases/MET-11.0.0/data/sample_obs/ascii/sample_ascii_obs.txt test.ps -v 4 
DEBUG 1: Default Config File: /d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/share/met/config/PlotPointObsConfig_default
DEBUG 4: parse_conf_sid_list() -> Station ID "sid_inc" list contains 0 entries.
DEBUG 4: parse_conf_sid_list() -> Station ID "sid_exc" list contains 0 entries.
DEBUG 3: Plotting grid definition: Projection: Lat/Lon Nx: 720 Ny: 361 lat_ll: -90.000 lon_ll: -0.000 delta_lat: 0.500 delta_lon: 0.500 wrapLon: true
DEBUG 1: Reading point observation file: PYTHON_NUMPY=/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/scripts/python/read_ascii_point.py /d1/projects/MET/MET_releases/MET-11.0.0/data/sample_obs/ascii/sample_ascii_obs.txt
DEBUG 3: Initializing MET compile time python instance: /usr/local/met-python3/bin/python3.8
DEBUG 3: Running user-specified python instance (MET_PYTHON_EXE=/usr/local/met-python3/bin/python3.8) to run user's python script (/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/scripts/python/read_ascii_point).
DEBUG 4: Writing temporary Python point data file:
DEBUG 4: 	/usr/local/met-python3/bin/python3.8 /d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/share/met/wrappers/write_tmp_point_nc.py /tmp/tmp_met_nc_21694_0 /d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/scripts/python/read_ascii_point /d1/projects/MET/MET_releases/MET-11.0.0/data/sample_obs/ascii/sample_ascii_obs.txt
  python: Python Script:	'/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/share/met/wrappers/write_tmp_point_nc.py'
  python: User Command:	'/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/scripts/python/read_ascii_point /d1/projects/MET/MET_releases/MET-11.0.0/data/sample_obs/ascii/sample_ascii_obs.txt'
  python: Temporary File:	'/tmp/tmp_met_nc_21694_0'
Python Script:	'/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/scripts/python/read_ascii_point'
Input File:	'/d1/projects/MET/MET_releases/MET-11.0.0/data/sample_obs/ascii/sample_ascii_obs.txt'
     point_data: Data Length:	2140
     point_data: Data Type:	<class 'list'>
 met_point_data: Data Type:	<class 'dict'>
  python:  ==PYTHON_ERROR== obs_var_table is empty (string)
DEBUG 4: Reading temporary Python point data file: /tmp/tmp_met_nc_21694_0
ERROR  : 
ERROR  : process_python_point_data -> The obs_var_table is empty. Please check if python input is processed properly
ERROR  : 

@DanielAdriaansen
Copy link
Contributor

DanielAdriaansen commented Feb 23, 2023

The test listed in the PR for #2428 does not work for me:

The case is MET_PYTHON_EXE is set and is equal to MET_PYTHON_BIN_EXE, which triggers temporary netcdf write/read.

If I unset MET_PYTHON_EXE, then it works, but even with a custom MET_PYTHON_EXE that is different than MET_PYTHON_BIN_EXE it does not work.

So the error is with the write/read of temporary netCDF file somewhere I think.

@hsoh-u hsoh-u requested a review from georgemccabe February 23, 2023 22:27
@hsoh-u
Copy link
Collaborator Author

hsoh-u commented Feb 23, 2023

The test listed in the PR for #2438 does not work for me:

The case is MET_PYTHON_EXE is set and is equal to MET_PYTHON_BIN_EXE, which triggers temporary netcdf write/read.

If I unset MET_PYTHON_EXE, then it works, but even with a custom MET_PYTHON_EXE that is different than MET_PYTHON_BIN_EXE it does not work.

So the error is with the write/read of temporary netCDF file somewhere I think.

Fixed and removed setting from MET_BASE (suggestion from @georgemccabe).
Previous /d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2 was renamed and the new build was done at the same place: /d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2

@DanielAdriaansen
Copy link
Contributor

I am still getting the same error:

dadriaan@seneca:~$ export MET_PYTHON_EXE=/usr/local/met-python3/bin/python3.8
dadriaan@seneca:~$ /d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/bin/plot_point_obs   "PYTHON_NUMPY=/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/scripts/python/read_ascii_point.py /d1/projects/MET/MET_releases/MET-11.0.0/data/sample_obs/ascii/sample_ascii_obs.txt"   test.ps -v 4 | grep -v "Plotting location"
DEBUG 1: Start plot_point_obs by dadriaan(15368) at 2023-02-23 22:36:27Z  cmd: /d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/bin/plot_point_obs PYTHON_NUMPY=/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/scripts/python/read_ascii_point.py /d1/projects/MET/MET_releases/MET-11.0.0/data/sample_obs/ascii/sample_ascii_obs.txt test.ps -v 4 
DEBUG 1: Default Config File: /d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/share/met/config/PlotPointObsConfig_default
DEBUG 4: parse_conf_sid_list() -> Station ID "sid_inc" list contains 0 entries.
DEBUG 4: parse_conf_sid_list() -> Station ID "sid_exc" list contains 0 entries.
DEBUG 3: Plotting grid definition: Projection: Lat/Lon Nx: 720 Ny: 361 lat_ll: -90.000 lon_ll: -0.000 delta_lat: 0.500 delta_lon: 0.500 wrapLon: true
DEBUG 1: Reading point observation file: PYTHON_NUMPY=/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/scripts/python/read_ascii_point.py /d1/projects/MET/MET_releases/MET-11.0.0/data/sample_obs/ascii/sample_ascii_obs.txt
DEBUG 3: Initializing MET compile time python instance: /usr/local/met-python3/bin/python3.8
DEBUG 3: Running user-specified python instance (MET_PYTHON_EXE=/usr/local/met-python3/bin/python3.8) to run user's python script (/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/scripts/python/read_ascii_point).
DEBUG 4: Writing temporary Python point data file:
DEBUG 4: 	/usr/local/met-python3/bin/python3.8 /d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/share/met/wrappers/write_tmp_point_nc.py /tmp/tmp_met_nc_15875_0 /d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/scripts/python/read_ascii_point /d1/projects/MET/MET_releases/MET-11.0.0/data/sample_obs/ascii/sample_ascii_obs.txt
  python: Python Script:	'/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/share/met/wrappers/write_tmp_point_nc.py'
  python: User Command:	'/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/scripts/python/read_ascii_point /d1/projects/MET/MET_releases/MET-11.0.0/data/sample_obs/ascii/sample_ascii_obs.txt'
  python: Temporary File:	'/tmp/tmp_met_nc_15875_0'
Python Script:	'/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/scripts/python/read_ascii_point'
Input File:	'/d1/projects/MET/MET_releases/MET-11.0.0/data/sample_obs/ascii/sample_ascii_obs.txt'
     point_data: Data Length:	2140
     point_data: Data Type:	<class 'list'>
 met_point_data: Data Type:	<class 'dict'>
DEBUG 4: Reading temporary Python point data file: /tmp/tmp_met_nc_15875_0
ERROR  : 
ERROR  : process_python_point_data -> The obs_var_table is empty. Please check if python input is processed properly
ERROR  : 

Can you double check the command I am running is correct after your fix @hsoh-u ?

Copy link
Contributor

@DanielAdriaansen DanielAdriaansen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I performed three tests on seneca:

TEST 1: MET_PYTHON_EXE unset

/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/bin/plot_point_obs   "PYTHON_NUMPY=/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/scripts/python/read_ascii_point.py /d1/projects/MET/MET_releases/MET-11.0.0/data/sample_obs/ascii/sample_ascii_obs.txt"   test.ps -v 4 | grep -v "Plotting location"

TEST 2: MET_PYTHON_EXE set to a user Python instance (different from compile-time Python instance)

export MET_PYTHON_EXE=/home/dadriaan/.conda/envs/icing/bin/python3
dadriaan@seneca:~$ /d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/bin/plot_point_obs   "PYTHON_NUMPY=/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/scripts/python/read_ascii_point.py /d1/projects/MET/MET_releases/MET-11.0.0/data/sample_obs/ascii/sample_ascii_obs.txt"   test.ps -v 4 | grep -v "Plotting location"

TEST 3: MET_PYTHON_EXE set to the MET compile-time Python instance

export MET_PYTHON_EXE=/usr/local/met-python3/bin/python3.8
dadriaan@seneca:~$ /d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/bin/plot_point_obs   "PYTHON_NUMPY=/d1/personal/hsoh/git/pull_request/MET_bugfix_2428_python_from_env_2/scripts/python/read_ascii_point.py /d1/projects/MET/MET_releases/MET-11.0.0/data/sample_obs/ascii/sample_ascii_obs.txt"   test.ps -v 4 | grep -v "Plotting location"

All three behave as I expect:
TEST 1: Python embedding uses the Python instance from MET compile-time (NO writing/reading temporary file) and correctly reports it in the logging at verbosity = 4
TEST 2: Python embedding uses the user installed Python instance (writing/reading temporary file) and correctly reports it in the logging at verbosity = 4
TEST 3: Python embedding uses the Python instance from MET compile-time (writing/reading temporary file) and correctly reports it in the logging at verbosity = 4

In addition, I did not have to set MET_BASE to find met_point_obs.py, or set PYTHONPATH, which is extremely desireable.

I reviewed Appendix F and determined these changes don't require any documentation updates, however I made 1 commit to fix a typo. The documentation for Python embedding will be revisited soon in a separate piece of work.

@hsoh-u hsoh-u merged commit c272ed7 into develop Feb 24, 2023
JohnHalleyGotway added a commit that referenced this pull request Feb 27, 2023
Co-authored-by: johnhg <[email protected]>
Co-authored-by: Lisa Goodrich <[email protected]>
Co-authored-by: jprestop <[email protected]>
Co-authored-by: Seth Linden <[email protected]>
Co-authored-by: Howard Soh <[email protected]>
Co-authored-by: John Halley Gotway <[email protected]>
Co-authored-by: MET Tools Test Account <[email protected]>
Co-authored-by: Dave Albo <[email protected]>
Co-authored-by: j-opatz <[email protected]>
Co-authored-by: George McCabe <[email protected]>
Co-authored-by: Julie Prestopnik <[email protected]>
Co-authored-by: Jonathan Vigh <[email protected]>
Co-authored-by: lisagoodrich <[email protected]>
Co-authored-by: Seth Linden <[email protected]>
Co-authored-by: hsoh-u <[email protected]>
Co-authored-by: davidalbo <[email protected]>
Co-authored-by: Daniel Adriaansen <[email protected]>
fix 2238 link error (#2255)
fix #2271 develop nbrctc (#2272)
fix #2309 develop tcmpr (#2310)
fix #2306 ascii2nc airnow hourly (#2314)
fix_spread_md (#2335)
fix #2389 develop flowchart (#2392)
Fix Python environment issue (#2407)
fix definitions of G172 and G220 based on comments in NOAA-EMC/NCEPLIBS-w3emc#157. (#2406)
fix #2380 develop override (#2382)
fix #2408 develop empty config (#2410)
fix #2390 develop compile zlib (#2404)
fix #2412 develop climo (#2422)
fix #2437 develop convert (#2439)
fix for develop, for #2437, forgot one reference to the search_parent for a dictionary lookup.
fix #2452 develop airnow (#2454)
@JohnHalleyGotway JohnHalleyGotway deleted the bugfix_2428_python_from_env_2 branch February 28, 2023 19:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Status: Done
3 participants