@gen.engine
def Start(callback):
  assert options.options.apple or options.options.testflight, \
         'You must specify exactly one of --apple or --testflight'
  assert options.options.search_days > 0

  # Exceptions are surfaced from both file parsers.
  if options.options.apple:
    assert not options.options.testflight, 'You must specify exactly one of --apple or --testflight'
    devices = AppleProvisioningProfile(options.options.apple).Devices()
  else:
    devices = TestFlightDevices(options.options.testflight).Devices()

  logs_paths = logs_util.ServerLogsPaths('viewfinder', 'full')
  merged_store = ObjectStore.GetInstance(logs_paths.MERGED_LOGS_BUCKET)
  # +1 because the start_date is exclusive.
  start_time = time.time() - (options.options.search_days + 1) * constants.SECONDS_PER_DAY
  start_date = util.TimestampUTCToISO8601(start_time)

  files = yield GetFileList(merged_store, start_date)

  logging.info((len(devices), len(files)) % 'Looking for %d devices UDIDs in %d files')
  last_seen = yield GetUDIDTimestamps(merged_store, files)

  missing = []
  by_age = []
  valid = []
  now = time.time()
  for d in devices:
    if d not in last_seen:
      missing.append(d)
    else:
      age = (now - last_seen[d]) / constants.SECONDS_PER_DAY
      if age > options.options.inactive_days:
        by_age.append((age, d))
      else:
        valid.append(d)
  by_age.sort()

  print 'Devices still active: %d' % len(valid)

  print 'Devices not seen in %d days: %d' % (options.options.search_days, len(missing))
  if missing:
    print '  ' + '\n  '.join(missing)

  print 'Inactive devices (and days since last seen): %d' % len(by_age)
  for (age, device) in by_age:
    print '  %3d %s' % (age, device)

  callback()
dataset/ETHPy150Open viewfinderco/viewfinder/scripts/find_unused_provisioned_devices.py/Start/swapped operands of `%`