MilanM commited on
Commit
b95dce5
·
verified ·
1 Parent(s): b92572c

Update main_app.py

Browse files
Files changed (1) hide show
  1. main_app.py +185 -0
main_app.py CHANGED
@@ -785,6 +785,191 @@ def _(create_yaml_tempfile, deployment_client, package_meta):
785
 
786
  return pe_metadata, yaml_file_path
787
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
788
 
789
  @app.cell
790
  def _(
 
785
 
786
  return pe_metadata, yaml_file_path
787
 
788
+ @app.cell(hide_code=True)
789
+ def _():
790
+ ### Helper function for checking if a python library is in the standard software spec.
791
+ def analyze_software_spec(sw_spec_response, required_libraries, return_full_sw_package_list=False):
792
+ """
793
+ Analyzes a software specification against a list of required libraries.
794
+
795
+ Args:
796
+ sw_spec_response (dict): The software specification response from the API
797
+ required_libraries (list): List of required libraries in format ["package_name", "package_name==version", etc.]
798
+ return_full_sw_package_list (bool): Whether to return the complete package list from sw_spec
799
+
800
+ Returns:
801
+ dict: A dictionary with analysis results containing:
802
+ - not_present: Dict of libraries not found in the software spec
803
+ - version_mismatch: Dict of libraries with version mismatches, with [sw_version, required_version] as values
804
+ - present: Dict of libraries that are present with matching versions
805
+ - sw_packages: (Optional) Complete dict of all packages in the software spec
806
+ """
807
+ result = {
808
+ "present": {},
809
+ "not_present": {},
810
+ "version_mismatch": {}
811
+ }
812
+
813
+ # Extract all packages from the software specification
814
+ sw_packages = {}
815
+
816
+ try:
817
+ # Extract packages from included_packages in the software specification
818
+ included_packages = sw_spec_response["entity"]["software_specification"]["software_configuration"]["included_packages"]
819
+
820
+ # Create a dictionary of all packages in the software specification
821
+ for package in included_packages:
822
+ package_name = package["name"]
823
+ package_version = package["version"]
824
+ sw_packages[package_name] = package_version
825
+ except KeyError as e:
826
+ raise ValueError(f"Invalid software specification format: {e}")
827
+
828
+ # Parse required libraries
829
+ for lib in required_libraries:
830
+ if "==" in lib:
831
+ lib_name, lib_version = lib.split("==", 1)
832
+ lib_name = lib_name.strip()
833
+ lib_version = lib_version.strip()
834
+ else:
835
+ lib_name = lib.strip()
836
+ lib_version = None
837
+
838
+ # Check if library is present in software specification
839
+ if lib_name not in sw_packages:
840
+ result["not_present"][lib_name] = None
841
+ elif lib_version is not None and lib_version != sw_packages[lib_name]:
842
+ # Check version mismatch
843
+ result["version_mismatch"][lib_name] = [sw_packages[lib_name], lib_version]
844
+ else:
845
+ # Library is present with matching version (or no specific version required)
846
+ result["present"][lib_name] = sw_packages[lib_name]
847
+
848
+ if return_full_sw_package_list:
849
+ # Extract just the library names from required_libraries
850
+ req_libs_names = [lib.split("==")[0].strip() if "==" in lib else lib.strip() for lib in required_libraries]
851
+
852
+ def sort_key(pkg_name):
853
+ if pkg_name in result["not_present"]:
854
+ return (0, pkg_name) # Missing packages first
855
+ elif pkg_name in result["version_mismatch"]:
856
+ return (1, pkg_name) # Version mismatch second
857
+ elif pkg_name in req_libs_names:
858
+ return (2, pkg_name) # Required packages that match third
859
+ else:
860
+ return (3, pkg_name) # All other packages last
861
+
862
+ # Sort sw_packages using the custom sorting key
863
+ result["sw_packages"] = {k: sw_packages[k] for k in sorted(sw_packages.keys(), key=sort_key)}
864
+
865
+ # Add missing packages to the top of sw_packages
866
+ for pkg in result["not_present"]:
867
+ result["sw_packages"] = {pkg: None, **result["sw_packages"]}
868
+
869
+
870
+ return result
871
+
872
+ def visualize_software_spec(analysis_result, required_libraries=None):
873
+ """
874
+ Visualizes the results of analyze_software_spec in a DataFrame with status indicators.
875
+ For use in Marimo notebooks.
876
+
877
+ Args:
878
+ analysis_result (dict): The result from analyze_software_spec function
879
+ required_libraries (list, optional): The original list of required libraries
880
+ used in analyze_software_spec
881
+
882
+ Returns:
883
+ pandas.DataFrame: A DataFrame showing the analysis results with status indicators
884
+ """
885
+ import pandas as pd
886
+
887
+ # Parse required libraries to get the exact names for lookup
888
+ req_libs_parsed = {}
889
+ if required_libraries:
890
+ for lib in required_libraries:
891
+ if "==" in lib:
892
+ lib_name, lib_version = lib.split("==", 1)
893
+ lib_name = lib_name.strip()
894
+ lib_version = lib_version.strip()
895
+ req_libs_parsed[lib_name] = lib_version
896
+ else:
897
+ lib_name = lib.strip()
898
+ req_libs_parsed[lib_name] = None
899
+
900
+ # Determine if we have the full sw_packages list
901
+ has_full_list = "sw_packages" in analysis_result
902
+
903
+ # Create a DataFrame based on available data
904
+ if has_full_list:
905
+ # Use the full package list
906
+ packages = analysis_result["sw_packages"]
907
+
908
+ # Prepare data rows
909
+ rows = []
910
+ for package, version in packages.items():
911
+ if package in analysis_result.get("not_present", {}):
912
+ status = "❌ Missing"
913
+ priority = 0 # Top priority
914
+ elif package in analysis_result.get("version_mismatch", {}):
915
+ status = "⚠️ Version Mismatch"
916
+ priority = 1 # Second priority
917
+ elif package in req_libs_parsed:
918
+ status = "✅ Present"
919
+ priority = 2 # Third priority
920
+ else:
921
+ status = "Other"
922
+ priority = 3 # Lowest priority
923
+
924
+ rows.append({
925
+ "Package": package,
926
+ "Version": version if version is not None else "Not Present",
927
+ "Status": status,
928
+ "_priority": priority # Temporary field for sorting
929
+ })
930
+
931
+ df = pd.DataFrame(rows)
932
+
933
+ # Sort by priority and then package name
934
+ df = df.sort_values(by=["_priority", "Package"]).drop("_priority", axis=1).reset_index(drop=True)
935
+
936
+ else:
937
+ # Only use the packages mentioned in required_libraries
938
+ packages = set(list(analysis_result.get("not_present", {}).keys()) +
939
+ list(analysis_result.get("version_mismatch", {}).keys()) +
940
+ list(analysis_result.get("present", {}).keys()))
941
+
942
+ # Create dataframe rows
943
+ rows = []
944
+ for package in packages:
945
+ if package in analysis_result.get("not_present", {}):
946
+ version = "Not Present"
947
+ status = "❌ Missing"
948
+ priority = 0 # Top priority
949
+ elif package in analysis_result.get("version_mismatch", {}):
950
+ version = analysis_result["version_mismatch"][package][0] # sw_spec version
951
+ status = "⚠️ Version Mismatch"
952
+ priority = 1 # Second priority
953
+ else:
954
+ version = analysis_result["present"][package]
955
+ status = "✅ Present"
956
+ priority = 2 # Third priority
957
+
958
+ rows.append({
959
+ "Package": package,
960
+ "Version": version,
961
+ "Status": status,
962
+ "_priority": priority # Temporary field for sorting
963
+ })
964
+
965
+ df = pd.DataFrame(rows)
966
+
967
+ # Sort by priority and then package name
968
+ df = df.sort_values(by=["_priority", "Package"]).drop("_priority", axis=1).reset_index(drop=True)
969
+
970
+ return df
971
+ return analyze_software_spec, visualize_software_spec
972
+
973
 
974
  @app.cell
975
  def _(