code: def update(self, new_data: Dict[str, ProductVersionInfo]):
      valid_updates: Dict[str, ProductVersionInfo] = {}
      for product, old_product_info in self._product_versions.items():
          old_version = old_product_info.latest_version
          old_sku = old_product_info.sku
  
          new_product_info = new_data.get(product)
  
          if new_product_info is None:
              log.error(
                  f"product {product} does not appear in new data; keeping in existing latest_product_versions"
              )
          else:
              new_version = new_product_info.latest_version
              new_sku = new_product_info.sku
  
              if old_sku is not None and old_sku != new_sku:
                  log.error(
                      f"product {product} does not have the same SKU as is currently in the database ({old_sku}, {new_sku})"
                  )
              elif new_version != old_version:
                  valid_updates[product] = new_product_info
                  log.info(
                      f"updated product version for {product} from {old_version} to {new_version}"
                  )
  
      for product, new_product_info in new_data.items():
          if product not in self._product_versions:
              valid_updates[product] = new_product_info
              log.info(
                  f"added product {product} with version {new_product_info.latest_version} and sku {new_product_info.sku}"
              )
  
      self._product_versions.update(valid_updates)
  
file_path: hail/batch/batch/driver/billing_manager.py
imports: import abc
  import logging
  from dataclasses import dataclass
  from typing import Dict, List, Optional
  from gear import Database, transaction
  from .pricing import Price
label_desc: Use image node_id 5 for calling the ProductVersions obj's underlying member method code with example usage: obj.update(new_data) without return types