docs: def checkForChanges(f, sde, isTable):
      """
      returns False if there are no changes
  
      """
      # try simple feature count first
      fCount = int(arcpy.GetCount_management(f).getOutput(0))
      sdeCount = int(arcpy.GetCount_management(sde).getOutput(0))
      if fCount != sdeCount:
          return True
  
      fields = [fld.name for fld in arcpy.ListFields(f)]
  
      # filter out shape fields
      if not isTable:
          fields = filter_fields(fields)
  
          d = arcpy.Describe(f)
          shapeType = d.shapeType
          if shapeType == 'Polygon':
              shapeToken = 'SHAPE@AREA'
          elif shapeType == 'Polyline':
              shapeToken = 'SHAPE@LENGTH'
          elif shapeType == 'Point':
              shapeToken = 'SHAPE@XY'
          else:
              shapeToken = 'SHAPE@JSON'
          fields.append(shapeToken)
  
          def parseShape(shapeValue):
              if shapeValue is None:
                  return 0
              elif shapeType in ['Polygon', 'Polyline']:
                  return shapeValue
              elif shapeType == 'Point':
                  if shapeValue[0] is not None and shapeValue[1] is not None:
                      return shapeValue[0] + shapeValue[1]
                  else:
                      return 0
              else:
                  return shapeValue
  
          outputSR = arcpy.Describe(f).spatialReference
      else:
          outputSR = None
  
      changed = False
      with arcpy.da.SearchCursor(f, fields, sql_clause=(None, 'ORDER BY OBJECTID')) as fCursor, \
              arcpy.da.SearchCursor(sde, fields, sql_clause=(None, 'ORDER BY OBJECTID'),
                                    spatial_reference=outputSR) as sdeCursor:
          for fRow, sdeRow in izip(fCursor, sdeCursor):
              if fRow != sdeRow:
                  # check shapes first
                  if fRow[-1] != sdeRow[-1] and not isTable:
                      if shapeType not in ['Polygon', 'Polyline', 'Point']:
                          changed = True
                          break
                      fShape = parseShape(fRow[-1])
                      sdeShape = parseShape(sdeRow[-1])
                      try:
                          assert_almost_equal(fShape, sdeShape, -1)
                          # trim off shapes
                          fRow = list(fRow[:-1])
                          sdeRow = list(sdeRow[:-1])
                      except AssertionError:
                          changed = True
                          break
  
                  # trim microseconds since they can be off by one between file and sde databases
                  for i in range(len(fRow)):
                      if type(fRow[i]) is datetime:
                          fRow = list(fRow)
                          sdeRow = list(sdeRow)
                          fRow[i] = fRow[i].replace(microsecond=0)
                          try:
                              sdeRow[i] = sdeRow[i].replace(microsecond=0)
                          except:
                              pass
  
                  # compare all values except OBJECTID
                  if fRow[1:] != sdeRow[1:]:
                      changed = True
                      break
  
      return changed