You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beam.apache.org by ro...@apache.org on 2016/09/30 23:48:37 UTC
[1/3] incubator-beam git commit: Use keyword arguments in fnc calls
Repository: incubator-beam
Updated Branches:
refs/heads/python-sdk dc92438fa -> 731a77152
Use keyword arguments in fnc calls
Project: http://git-wip-us.apache.org/repos/asf/incubator-beam/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-beam/commit/f94eb53b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-beam/tree/f94eb53b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-beam/diff/f94eb53b
Branch: refs/heads/python-sdk
Commit: f94eb53b8b1fbf405d6fa62baeb9b9ee9090c1de
Parents: 5e87980
Author: Maria Garcia Herrero <ma...@google.com>
Authored: Fri Sep 30 10:41:38 2016 -0700
Committer: Robert Bradshaw <ro...@google.com>
Committed: Fri Sep 30 16:48:05 2016 -0700
----------------------------------------------------------------------
.../apache_beam/utils/annotations_test.py | 51 ++++++++++++--------
1 file changed, 32 insertions(+), 19 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-beam/blob/f94eb53b/sdks/python/apache_beam/utils/annotations_test.py
----------------------------------------------------------------------
diff --git a/sdks/python/apache_beam/utils/annotations_test.py b/sdks/python/apache_beam/utils/annotations_test.py
index af89590..854098c 100644
--- a/sdks/python/apache_beam/utils/annotations_test.py
+++ b/sdks/python/apache_beam/utils/annotations_test.py
@@ -30,10 +30,12 @@ class AnnotationTests(unittest.TestCase):
def fnc_test_deprecated_with_since_current():
return 'lol'
fnc_test_deprecated_with_since_current()
- self.check_annotation(w, 1, DeprecationWarning,
- 'fnc_test_deprecated_with_since_current',
- 'deprecated',
- [('since', True), ('instead', True)])
+ self.check_annotation(warning=w, warning_size=1,
+ warning_type=DeprecationWarning,
+ fnc_name='fnc_test_deprecated_with_since_current',
+ annotation_type='deprecated',
+ label_check_list=[('since', True),
+ ('instead', True)])
def test_deprecated_without_current(self):
with warnings.catch_warnings(record=True) as w:
@@ -41,9 +43,12 @@ class AnnotationTests(unittest.TestCase):
def fnc_test_deprecated_without_current():
return 'lol'
fnc_test_deprecated_without_current()
- self.check_annotation(w, 1, DeprecationWarning,
- 'fnc_test_deprecated_without_current', 'deprecated',
- [('since', True), ('instead', False)])
+ self.check_annotation(warning=w, warning_size=1,
+ warning_type=DeprecationWarning,
+ fnc_name='fnc_test_deprecated_without_current',
+ annotation_type='deprecated',
+ label_check_list=[('since', True),
+ ('instead', False)])
def test_deprecated_without_since_should_fail(self):
with warnings.catch_warnings(record=True) as w:
@@ -61,9 +66,11 @@ class AnnotationTests(unittest.TestCase):
def fnc_test_experimental_with_current():
return 'lol'
fnc_test_experimental_with_current()
- self.check_annotation(w, 1, FutureWarning,
- 'fnc_test_experimental_with_current',
- 'experimental', [('instead', True)])
+ self.check_annotation(warning=w, warning_size=1,
+ warning_type=FutureWarning,
+ fnc_name='fnc_test_experimental_with_current',
+ annotation_type='experimental',
+ label_check_list=[('instead', True)])
def test_experimental_without_current(self):
with warnings.catch_warnings(record=True) as w:
@@ -71,9 +78,11 @@ class AnnotationTests(unittest.TestCase):
def fnc_test_experimental_without_current():
return 'lol'
fnc_test_experimental_without_current()
- self.check_annotation(w, 1, FutureWarning,
- 'fnc_test_experimental_without_current',
- 'experimental', [('instead', False)])
+ self.check_annotation(warning=w, warning_size=1,
+ warning_type=FutureWarning,
+ fnc_name='fnc_test_experimental_without_current',
+ annotation_type='experimental',
+ label_check_list=[('instead', False)])
def test_frequency(self):
"""Tests that the filter 'once' is sufficient to print once per
@@ -89,12 +98,16 @@ class AnnotationTests(unittest.TestCase):
fnc_test_annotate_frequency()
fnc_test_annotate_frequency()
fnc2_test_annotate_frequency()
- self.check_annotation([w[0]], 1, FutureWarning,
- 'fnc_test_annotate_frequency', 'experimental',
- [])
- self.check_annotation([w[1]], 1, FutureWarning,
- 'fnc2_test_annotate_frequency', 'experimental',
- [])
+ self.check_annotation(warning=[w[0]], warning_size=1,
+ warning_type=FutureWarning,
+ fnc_name='fnc_test_annotate_frequency',
+ annotation_type='experimental',
+ label_check_list=[])
+ self.check_annotation(warning=[w[1]], warning_size=1,
+ warning_type=FutureWarning,
+ fnc_name='fnc2_test_annotate_frequency',
+ annotation_type='experimental',
+ label_check_list=[])
# helper function
def check_annotation(self, warning, warning_size, warning_type, fnc_name,
[3/3] incubator-beam git commit: Closes #1001
Posted by ro...@apache.org.
Closes #1001
Project: http://git-wip-us.apache.org/repos/asf/incubator-beam/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-beam/commit/731a7715
Tree: http://git-wip-us.apache.org/repos/asf/incubator-beam/tree/731a7715
Diff: http://git-wip-us.apache.org/repos/asf/incubator-beam/diff/731a7715
Branch: refs/heads/python-sdk
Commit: 731a7715233f91599dd10133c58cdf97c87d6564
Parents: dc92438 f94eb53
Author: Robert Bradshaw <ro...@google.com>
Authored: Fri Sep 30 16:48:15 2016 -0700
Committer: Robert Bradshaw <ro...@google.com>
Committed: Fri Sep 30 16:48:15 2016 -0700
----------------------------------------------------------------------
sdks/python/apache_beam/utils/annotations.py | 99 +++++++++++++++
.../apache_beam/utils/annotations_test.py | 126 +++++++++++++++++++
2 files changed, 225 insertions(+)
----------------------------------------------------------------------
[2/3] incubator-beam git commit: Add annotation to mark deprecated or
experimental APIs via decorators.
Posted by ro...@apache.org.
Add annotation to mark deprecated or experimental APIs via decorators.
Project: http://git-wip-us.apache.org/repos/asf/incubator-beam/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-beam/commit/5e87980b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-beam/tree/5e87980b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-beam/diff/5e87980b
Branch: refs/heads/python-sdk
Commit: 5e87980b3cd19bd62aec585808f3f7a349486a79
Parents: dc92438
Author: Maria Garcia Herrero <ma...@google.com>
Authored: Sat Sep 24 02:05:46 2016 -0700
Committer: Robert Bradshaw <ro...@google.com>
Committed: Fri Sep 30 16:48:05 2016 -0700
----------------------------------------------------------------------
sdks/python/apache_beam/utils/annotations.py | 99 ++++++++++++++++
.../apache_beam/utils/annotations_test.py | 113 +++++++++++++++++++
2 files changed, 212 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-beam/blob/5e87980b/sdks/python/apache_beam/utils/annotations.py
----------------------------------------------------------------------
diff --git a/sdks/python/apache_beam/utils/annotations.py b/sdks/python/apache_beam/utils/annotations.py
new file mode 100644
index 0000000..aa53554
--- /dev/null
+++ b/sdks/python/apache_beam/utils/annotations.py
@@ -0,0 +1,99 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+""" Deprecated and experimental annotations.
+
+Annotations come in two flavors: deprecated and experimental
+
+The 'deprecated' annotation requires a 'since" parameter to specify
+what version deprecated it.
+Both 'deprecated' and 'experimental' annotations can specify the
+current recommended version to use by means of a 'current' parameter.
+
+The following example illustrates how to annotate coexisting versions of the
+same function 'multiply'.
+def multiply(arg1, arg2):
+ print arg1, '*', arg2, '=',
+ return arg1*arg2
+
+# This annotation marks 'old_multiply' as deprecated since 'v.1' and suggests
+# using 'multiply' instead.
+@deprecated(since='v.1', current='multiply')
+def old_multiply(arg1, arg2):
+ result = 0
+ for i in xrange(arg1):
+ result += arg2
+ print arg1, '*', arg2, '(the old way)=',
+ return result
+
+# This annotation marks 'exp_multiply' as experimental and suggests
+# using 'multiply' instead.
+@experimental(since='v.1', current='multiply')
+def exp_multiply(arg1, arg2):
+ print arg1, '*', arg2, '(the experimental way)=',
+ return (arg1*arg2)*(arg1/arg2)*(arg2/arg1)
+
+# Set a warning filter to control how often warnings are produced
+warnings.simplefilter("always")
+print multiply(5, 6)
+print old_multiply(5,6)
+print exp_multiply(5,6)
+"""
+
+import warnings
+from functools import partial
+from functools import wraps
+
+# Produce only the first occurrence of matching warnings regardless of
+# location per line of execution. Since the number of lines of execution
+# depends on the concrete runner, the number of warnings produced will
+# vary depending on the runner.
+warnings.simplefilter("once")
+
+
+def annotate(label, since, current):
+ """Decorates a function with a deprecated or experimental annotation.
+
+ Args:
+ label: the kind of annotation ('deprecated' or 'experimental').
+ since: the version that causes the annotation.
+ current: the suggested replacement function.
+
+ Returns:
+ The decorator for the function.
+ """
+ def _annotate(fnc):
+ @wraps(fnc)
+ def inner(*args, **kwargs):
+ if label == 'deprecated':
+ warning_type = DeprecationWarning
+ else:
+ warning_type = FutureWarning
+ message = '%s is %s' % (fnc.__name__, label)
+ if label == 'deprecated':
+ message += ' since %s' % since
+ message += '. Use %s instead.'% current if current else '.'
+ warnings.warn(message, warning_type)
+ return fnc(*args, **kwargs)
+ return inner
+ return _annotate
+
+# Use partial application to customize each annotation.
+# 'current' will be optional in both deprecated and experimental
+# while 'since' will be mandatory for deprecated.
+deprecated = partial(annotate, label='deprecated', current=None)
+experimental = partial(annotate, label='experimental', current=None, since=None)
http://git-wip-us.apache.org/repos/asf/incubator-beam/blob/5e87980b/sdks/python/apache_beam/utils/annotations_test.py
----------------------------------------------------------------------
diff --git a/sdks/python/apache_beam/utils/annotations_test.py b/sdks/python/apache_beam/utils/annotations_test.py
new file mode 100644
index 0000000..af89590
--- /dev/null
+++ b/sdks/python/apache_beam/utils/annotations_test.py
@@ -0,0 +1,113 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import unittest
+import warnings
+from annotations import deprecated
+from annotations import experimental
+
+
+class AnnotationTests(unittest.TestCase):
+ # Note: use different names for each of the the functions decorated
+ # so that a warning is produced for each of them.
+ def test_deprecated_with_since_current(self):
+ with warnings.catch_warnings(record=True) as w:
+ @deprecated(since='v.1', current='multiply')
+ def fnc_test_deprecated_with_since_current():
+ return 'lol'
+ fnc_test_deprecated_with_since_current()
+ self.check_annotation(w, 1, DeprecationWarning,
+ 'fnc_test_deprecated_with_since_current',
+ 'deprecated',
+ [('since', True), ('instead', True)])
+
+ def test_deprecated_without_current(self):
+ with warnings.catch_warnings(record=True) as w:
+ @deprecated(since='v.1')
+ def fnc_test_deprecated_without_current():
+ return 'lol'
+ fnc_test_deprecated_without_current()
+ self.check_annotation(w, 1, DeprecationWarning,
+ 'fnc_test_deprecated_without_current', 'deprecated',
+ [('since', True), ('instead', False)])
+
+ def test_deprecated_without_since_should_fail(self):
+ with warnings.catch_warnings(record=True) as w:
+ with self.assertRaises(TypeError):
+
+ @deprecated()
+ def fnc_test_deprecated_without_since_should_fail():
+ return 'lol'
+ fnc_test_deprecated_without_since_should_fail()
+ assert len(w) == 0
+
+ def test_experimental_with_current(self):
+ with warnings.catch_warnings(record=True) as w:
+ @experimental(current='multiply')
+ def fnc_test_experimental_with_current():
+ return 'lol'
+ fnc_test_experimental_with_current()
+ self.check_annotation(w, 1, FutureWarning,
+ 'fnc_test_experimental_with_current',
+ 'experimental', [('instead', True)])
+
+ def test_experimental_without_current(self):
+ with warnings.catch_warnings(record=True) as w:
+ @experimental()
+ def fnc_test_experimental_without_current():
+ return 'lol'
+ fnc_test_experimental_without_current()
+ self.check_annotation(w, 1, FutureWarning,
+ 'fnc_test_experimental_without_current',
+ 'experimental', [('instead', False)])
+
+ def test_frequency(self):
+ """Tests that the filter 'once' is sufficient to print once per
+ warning independently of location."""
+ with warnings.catch_warnings(record=True) as w:
+ @experimental()
+ def fnc_test_annotate_frequency():
+ return 'lol'
+
+ @experimental()
+ def fnc2_test_annotate_frequency():
+ return 'lol'
+ fnc_test_annotate_frequency()
+ fnc_test_annotate_frequency()
+ fnc2_test_annotate_frequency()
+ self.check_annotation([w[0]], 1, FutureWarning,
+ 'fnc_test_annotate_frequency', 'experimental',
+ [])
+ self.check_annotation([w[1]], 1, FutureWarning,
+ 'fnc2_test_annotate_frequency', 'experimental',
+ [])
+
+ # helper function
+ def check_annotation(self, warning, warning_size, warning_type, fnc_name,
+ annotation_type, label_check_list):
+ self.assertEqual(1, warning_size)
+ self.assertTrue(issubclass(warning[-1].category, warning_type))
+ self.assertIn(fnc_name + ' is ' + annotation_type, str(warning[-1].message))
+ for label in label_check_list:
+ if label[1] is True:
+ self.assertIn(label[0], str(warning[-1].message))
+ else:
+ self.assertNotIn(label[0], str(warning[-1].message))
+
+
+if __name__ == '__main__': # It doesn't like these 2 lines
+ unittest.main()