mirror of
				https://github.com/exo-explore/exo.git
				synced 2025-10-23 02:57:14 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			113 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			113 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import os
 | |
| import importlib.metadata
 | |
| import importlib.util
 | |
| import json
 | |
| import sys
 | |
| 
 | |
| 
 | |
| def calc_container(path):
 | |
|   """Calculate total size of a directory or file."""
 | |
|   if os.path.isfile(path):
 | |
|     try:
 | |
|       return os.path.getsize(path)
 | |
|     except (OSError, FileNotFoundError):
 | |
|       return 0
 | |
| 
 | |
|   total_size = 0
 | |
|   for dirpath, dirnames, filenames in os.walk(path):
 | |
|     for f in filenames:
 | |
|       fp = os.path.join(dirpath, f)
 | |
|       try:
 | |
|         total_size += os.path.getsize(fp)
 | |
|       except (OSError, FileNotFoundError):
 | |
|         continue
 | |
|   return total_size
 | |
| 
 | |
| 
 | |
| def get_package_location(package_name):
 | |
|   """Get the actual location of a package's files."""
 | |
|   try:
 | |
|     spec = importlib.util.find_spec(package_name)
 | |
|     if spec is None:
 | |
|       return None
 | |
| 
 | |
|     if spec.submodule_search_locations:
 | |
|       # Return the first location for namespace packages
 | |
|       return spec.submodule_search_locations[0]
 | |
|     elif spec.origin:
 | |
|       # For single-file modules, return the file path itself
 | |
|       return spec.origin
 | |
|   except ImportError:
 | |
|     return None
 | |
| 
 | |
| 
 | |
| def get_package_sizes(min_size_mb=0.1):
 | |
|   """Get sizes of installed packages above minimum size threshold."""
 | |
|   package_sizes = []
 | |
| 
 | |
|   # Get all installed distributions
 | |
|   for dist in importlib.metadata.distributions():
 | |
|     try:
 | |
|       package_name = dist.metadata["Name"]
 | |
|       location = get_package_location(package_name.replace("-", "_"))
 | |
| 
 | |
|       if location and os.path.exists(location):
 | |
|         size = calc_container(location)
 | |
|         size_mb = size / (1024 * 1024)
 | |
| 
 | |
|         if size_mb > min_size_mb:
 | |
|           package_sizes.append((package_name, size))
 | |
|     except Exception as e:
 | |
|       print(
 | |
|         f"Error processing {dist.metadata.get('Name', 'Unknown package')}: {e}"
 | |
|       )
 | |
| 
 | |
|   return package_sizes
 | |
| 
 | |
| 
 | |
| def main():
 | |
|   # Get and sort package sizes
 | |
|   package_sizes = get_package_sizes()
 | |
|   package_sizes.sort(key=lambda x: x[1], reverse=True)
 | |
| 
 | |
|   # Convert sizes to MB and prepare data
 | |
|   table_data = [(name, size/(1024*1024)) for name, size in package_sizes]
 | |
|   total_size = sum(size for _, size in package_sizes)/(1024*1024)
 | |
| 
 | |
|   # Check if --json flag is present
 | |
|   if "--json" in sys.argv:
 | |
|     try:
 | |
|       output_file = sys.argv[sys.argv.index("--json") + 1]
 | |
|       json_data = {
 | |
|         "packages": [{
 | |
|           "name": name,
 | |
|           "size_mb": round(size, 2)
 | |
|         } for name, size in table_data],
 | |
|         "total_size_mb": round(total_size, 2)
 | |
|       }
 | |
| 
 | |
|       with open(output_file, 'w') as f:
 | |
|         json.dump(json_data, f, indent=2)
 | |
|       print(f"JSON data written to {output_file}")
 | |
|       return
 | |
|     except IndexError:
 | |
|       print("Error: Please provide a filename after --json")
 | |
|       sys.exit(1)
 | |
|     except Exception as e:
 | |
|       print(f"Error writing JSON file: {e}")
 | |
|       sys.exit(1)
 | |
| 
 | |
|   # Original table output code
 | |
|   max_name_width = max(len(name) for name, _ in table_data)
 | |
|   max_name_width = max(max_name_width, len("Package"))
 | |
| 
 | |
|   print(f"\n{'Package':<{max_name_width}} | Size (MB)")
 | |
|   print("-" * max_name_width + "-+-" + "-" * 10)
 | |
| 
 | |
|   for name, size in table_data:
 | |
|     print(f"{name:<{max_name_width}} | {size:>8.2f}")
 | |
| 
 | |
|   print(f"\nTotal size: {total_size:.2f} MB\n")
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|   main() | 
