Disallow setting the forward compatibility horizon in the past.

If this breaks code you maintain, instead switch to using tf.raw_ops
to directly control what graph ops are emitted from the TF high level
APIs instead of assuming TF will never delete stale branches of forward
compatible code.

PiperOrigin-RevId: 309756416
Change-Id: I47f874423401d974c26e7edc65e8f7a39e8cae0e
This commit is contained in:
Alexandre Passos 2020-05-04 09:15:36 -07:00 committed by TensorFlower Gardener
parent b7e2b82cfa
commit dbe7b589c5
3 changed files with 10 additions and 11 deletions

View File

@ -30,7 +30,6 @@ from six.moves import xrange # pylint: disable=redefined-builtin
from tensorflow.compiler.tests import xla_test from tensorflow.compiler.tests import xla_test
from tensorflow.python.framework import dtypes from tensorflow.python.framework import dtypes
from tensorflow.python.framework import ops from tensorflow.python.framework import ops
from tensorflow.python.framework import test_util
from tensorflow.python.ops import array_ops from tensorflow.python.ops import array_ops
from tensorflow.python.ops import gen_image_ops from tensorflow.python.ops import gen_image_ops
from tensorflow.python.ops import image_ops from tensorflow.python.ops import image_ops
@ -979,7 +978,6 @@ class NonMaxSuppressionTest(xla_test.XLATestCase):
class BatchedNonMaxSuppressionCorrectnessTest(xla_test.XLATestCase): class BatchedNonMaxSuppressionCorrectnessTest(xla_test.XLATestCase):
@test_util.with_forward_compatibility_horizons(None, [2020, 4, 21])
def testBatchedNMSFrom6(self): def testBatchedNMSFrom6(self):
boxes_data = [[[0, 0, 1, 1], [3, 3, 4, 4], [0, 0.4, 1, 1.4], boxes_data = [[[0, 0, 1, 1], [3, 3, 4, 4], [0, 0.4, 1, 1.4],
[0, 0.6, 1, 1.6], [0, 0.8, 1, 1.8], [0, 2, 1, 2]], [0, 0.6, 1, 1.6], [0, 0.8, 1, 1.8], [0, 2, 1, 2]],
@ -1017,7 +1015,6 @@ class BatchedNonMaxSuppressionCorrectnessTest(xla_test.XLATestCase):
indices_output) indices_output)
self.assertAllEqual([5, 4], num_valid_output) self.assertAllEqual([5, 4], num_valid_output)
@test_util.with_forward_compatibility_horizons(None, [2020, 4, 21])
def testBatchedNMSFrom6Max3(self): def testBatchedNMSFrom6Max3(self):
boxes_data = [[[0, 0, 1, 1], [3, 3, 4, 4], [0, 0.4, 1, 1.4], boxes_data = [[[0, 0, 1, 1], [3, 3, 4, 4], [0, 0.4, 1, 1.4],
[0, 0.6, 1, 1.6], [0, 0.8, 1, 1.8], [0, 2, 1, 2]], [0, 0.6, 1, 1.6], [0, 0.8, 1, 1.8], [0, 2, 1, 2]],
@ -1051,7 +1048,6 @@ class BatchedNonMaxSuppressionCorrectnessTest(xla_test.XLATestCase):
self.assertAllEqual([[0, 1, 2], [0, 1, 3]], indices_output) self.assertAllEqual([[0, 1, 2], [0, 1, 3]], indices_output)
self.assertAllEqual([3, 3], num_valid_output) self.assertAllEqual([3, 3], num_valid_output)
@test_util.with_forward_compatibility_horizons(None, [2020, 4, 21])
def testBatchedNMSSingleFrom6Max3(self): def testBatchedNMSSingleFrom6Max3(self):
boxes_data = [[0, 0, 1, 1], [3, 3, 4, 4], [0, 0.4, 1, 1.4], boxes_data = [[0, 0, 1, 1], [3, 3, 4, 4], [0, 0.4, 1, 1.4],
[0, 0.6, 1, 1.6], [0, 0.8, 1, 1.8], [0, 2, 1, 2]] [0, 0.6, 1, 1.6], [0, 0.8, 1, 1.8], [0, 2, 1, 2]]
@ -1082,7 +1078,6 @@ class BatchedNonMaxSuppressionCorrectnessTest(xla_test.XLATestCase):
self.assertAllEqual([0, 1, 2], indices_output) self.assertAllEqual([0, 1, 2], indices_output)
self.assertAllEqual(3, num_valid_output) self.assertAllEqual(3, num_valid_output)
@test_util.with_forward_compatibility_horizons(None, [2020, 4, 21])
def testBatchedNMSSingleFrom6NoPad(self): def testBatchedNMSSingleFrom6NoPad(self):
boxes_data = [[0, 0, 1, 1], [3, 3, 4, 4], [0, 0.4, 1, 1.4], boxes_data = [[0, 0, 1, 1], [3, 3, 4, 4], [0, 0.4, 1, 1.4],
[0, 0.6, 1, 1.6], [0, 0.8, 1, 1.8], [0, 2, 1, 2]] [0, 0.6, 1, 1.6], [0, 0.8, 1, 1.8], [0, 2, 1, 2]]
@ -1112,7 +1107,6 @@ class BatchedNonMaxSuppressionCorrectnessTest(xla_test.XLATestCase):
self.assertAllEqual([0, 1, 2, 4, 5], indices_output) self.assertAllEqual([0, 1, 2, 4, 5], indices_output)
self.assertAllEqual(5, num_valid_output) self.assertAllEqual(5, num_valid_output)
@test_util.with_forward_compatibility_horizons(None, [2020, 4, 21])
def testBatchedNMSBatchDimsFrom6Max3(self): def testBatchedNMSBatchDimsFrom6Max3(self):
boxes_data = [[[[0, 0, 1, 1], [3, 3, 4, 4], [0, 0.4, 1, 1.4], boxes_data = [[[[0, 0, 1, 1], [3, 3, 4, 4], [0, 0.4, 1, 1.4],
[0, 0.6, 1, 1.6], [0, 0.8, 1, 1.8], [0, 2, 1, 2]], [0, 0.6, 1, 1.6], [0, 0.8, 1, 1.8], [0, 2, 1, 2]],
@ -1146,7 +1140,6 @@ class BatchedNonMaxSuppressionCorrectnessTest(xla_test.XLATestCase):
self.assertAllEqual([[[0, 1, 2], [0, 1, 3]]], indices_output) self.assertAllEqual([[[0, 1, 2], [0, 1, 3]]], indices_output)
self.assertAllEqual([[3, 3]], num_valid_output) self.assertAllEqual([[3, 3]], num_valid_output)
@test_util.with_forward_compatibility_horizons(None, [2020, 4, 21])
def testBatchedNMSScoreThresholdFrom6Max3(self): def testBatchedNMSScoreThresholdFrom6Max3(self):
boxes_data = [[[0, 0, 1, 1], [3, 3, 4, 4], [0, 0.4, 1, 1.4], boxes_data = [[[0, 0, 1, 1], [3, 3, 4, 4], [0, 0.4, 1, 1.4],
[0, 0.6, 1, 1.6], [0, 0.8, 1, 1.8], [0, 2, 1, 2]], [0, 0.6, 1, 1.6], [0, 0.8, 1, 1.8], [0, 2, 1, 2]],
@ -1182,7 +1175,6 @@ class BatchedNonMaxSuppressionCorrectnessTest(xla_test.XLATestCase):
self.assertAllEqual([3, 2], num_valid_output) self.assertAllEqual([3, 2], num_valid_output)
self.assertAllEqual([[0, 1, 2], [0, 1, invalid_index]], indices_output) self.assertAllEqual([[0, 1, 2], [0, 1, invalid_index]], indices_output)
@test_util.with_forward_compatibility_horizons(None, [2020, 4, 21])
def testBatchedNMSUnsortedInputFrom6(self): def testBatchedNMSUnsortedInputFrom6(self):
boxes_data = [[[0, 2, 1, 2], [3, 3, 4, 4], [0, 0, 1, 1], boxes_data = [[[0, 2, 1, 2], [3, 3, 4, 4], [0, 0, 1, 1],
[0, 0.4, 1, 1.4], [0, 0.6, 1, 1.6], [0, 0.8, 1, 1.8]], [0, 0.4, 1, 1.4], [0, 0.6, 1, 1.6], [0, 0.8, 1, 1.8]],
@ -1219,7 +1211,6 @@ class BatchedNonMaxSuppressionCorrectnessTest(xla_test.XLATestCase):
indices_output) indices_output)
self.assertAllEqual([5, 4], num_valid_output) self.assertAllEqual([5, 4], num_valid_output)
@test_util.with_forward_compatibility_horizons(None, [2020, 4, 21])
def testBatchedNMSNoncanonicalizedInputFrom6(self): def testBatchedNMSNoncanonicalizedInputFrom6(self):
boxes_data = [[[1, 0, 0, 1], [4, 3, 3, 4], [1, 0.4, 0, 1.4], boxes_data = [[[1, 0, 0, 1], [4, 3, 3, 4], [1, 0.4, 0, 1.4],
[1, 0.6, 0, 1.6], [1, 0.8, 0, 1.8], [1, 2, 0, 2]], [1, 0.6, 0, 1.6], [1, 0.8, 0, 1.8], [1, 2, 0, 2]],
@ -1257,7 +1248,6 @@ class BatchedNonMaxSuppressionCorrectnessTest(xla_test.XLATestCase):
indices_output) indices_output)
self.assertAllEqual([5, 4], num_valid_output) self.assertAllEqual([5, 4], num_valid_output)
@test_util.with_forward_compatibility_horizons(None, [2020, 4, 21])
def testBatchedNMSScoreThresholdCanInputsFrom6Max3(self): def testBatchedNMSScoreThresholdCanInputsFrom6Max3(self):
boxes_data = [[[0, 0, 1, 1], [3, 3, 4, 4], [0, 0.4, 1, 1.4], boxes_data = [[[0, 0, 1, 1], [3, 3, 4, 4], [0, 0.4, 1, 1.4],
[0, 0.6, 1, 1.6], [0, 0.8, 1, 1.8], [0, 2, 1, 2]], [0, 0.6, 1, 1.6], [0, 0.8, 1, 1.8], [0, 2, 1, 2]],
@ -1293,7 +1283,6 @@ class BatchedNonMaxSuppressionCorrectnessTest(xla_test.XLATestCase):
self.assertAllEqual([3, 2], num_valid_output) self.assertAllEqual([3, 2], num_valid_output)
self.assertAllEqual([[0, 1, 2], [0, 1, invalid_index]], indices_output) self.assertAllEqual([[0, 1, 2], [0, 1, invalid_index]], indices_output)
@test_util.with_forward_compatibility_horizons(None, [2020, 4, 21])
def testBatchedNMSFrom6DynamicInput(self): def testBatchedNMSFrom6DynamicInput(self):
boxes_data = [[[0, 0, 1, 1], [3, 3, 4, 4], [0, 0.4, 1, 1.4], boxes_data = [[[0, 0, 1, 1], [3, 3, 4, 4], [0, 0.4, 1, 1.4],
[0, 0.6, 1, 1.6], [0, 0.8, 1, 1.8], [0, 2, 1, 2]], [0, 0.6, 1, 1.6], [0, 0.8, 1, 1.8], [0, 2, 1, 2]],

View File

@ -25,9 +25,11 @@ from __future__ import print_function
import datetime import datetime
import os import os
from tensorflow.python.platform import tf_logging as logging
from tensorflow.python.util import tf_contextlib from tensorflow.python.util import tf_contextlib
from tensorflow.python.util.tf_export import tf_export from tensorflow.python.util.tf_export import tf_export
# This value changes every day with an automatic CL. It can be modified in code # This value changes every day with an automatic CL. It can be modified in code
# via `forward_compatibility_horizon()` or with the environment variable # via `forward_compatibility_horizon()` or with the environment variable
# TF_FORWARD_COMPATIBILITY_DELTA_DAYS, which is added to the compatibility date. # TF_FORWARD_COMPATIBILITY_DELTA_DAYS, which is added to the compatibility date.
@ -53,6 +55,10 @@ def _update_forward_compatibility_date_number(date_to_override=None):
if delta_days: if delta_days:
date += datetime.timedelta(days=int(delta_days)) date += datetime.timedelta(days=int(delta_days))
if date < _FORWARD_COMPATIBILITY_HORIZON:
logging.warning("Trying to set the forward compatibility date to the past"
" date %s. This will be ignored by TensorFlow." % (date))
return
_FORWARD_COMPATIBILITY_DATE_NUMBER = _date_to_date_number( _FORWARD_COMPATIBILITY_DATE_NUMBER = _date_to_date_number(
date.year, date.month, date.day) date.year, date.month, date.day)

View File

@ -40,6 +40,10 @@ class CompatTest(test.TestCase):
self.assertTrue(compat.forward_compatible(*one_day_before)) self.assertTrue(compat.forward_compatible(*one_day_before))
self.assertFalse(compat.forward_compatible(*compatibility_date)) self.assertFalse(compat.forward_compatible(*compatibility_date))
def test_past(self):
with compat.forward_compatibility_horizon(2018, 9, 18):
self.assertTrue(compat.forward_compatible(2020, 4, 4))
def test_decorator(self): def test_decorator(self):
compatibility_date = self._compatibility_date() compatibility_date = self._compatibility_date()
one_day_after = self._n_days_after(1) one_day_after = self._n_days_after(1)