This is an automated email from the ASF dual-hosted git repository.

shunping pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git


The following commit(s) were added to refs/heads/master by this push:
     new dfb3f872192 [yaml] : add jinja inheritance example (#37601)
dfb3f872192 is described below

commit dfb3f872192e8f74571b4979b97a267ee13e5137
Author: Derrick Williams <[email protected]>
AuthorDate: Thu Feb 19 14:57:21 2026 -0500

    [yaml] : add jinja inheritance example (#37601)
    
    * add jinja files for inheritance
    
    * add support for new example
    
    * add license
---
 .../yaml/examples/testing/examples_test.py         | 15 +++--
 .../yaml/examples/testing/input_data.py            |  5 ++
 .../transforms/jinja/inheritance/README.md         | 77 ++++++++++++++++++++++
 .../jinja/inheritance/base/base_pipeline.yaml      | 55 ++++++++++++++++
 .../jinja/inheritance/wordCountInheritance.yaml    | 40 +++++++++++
 5 files changed, 188 insertions(+), 4 deletions(-)

diff --git a/sdks/python/apache_beam/yaml/examples/testing/examples_test.py 
b/sdks/python/apache_beam/yaml/examples/testing/examples_test.py
index 4f0516a1ea9..15cf46218e8 100644
--- a/sdks/python/apache_beam/yaml/examples/testing/examples_test.py
+++ b/sdks/python/apache_beam/yaml/examples/testing/examples_test.py
@@ -563,8 +563,11 @@ def _wordcount_minimal_test_preprocessor(
   return _wordcount_random_shuffler(test_spec, all_words, env)
 
 
[email protected]_test_preprocessor(
-    ['test_wordCountInclude_yaml', 'test_wordCountImport_yaml'])
[email protected]_test_preprocessor([
+    'test_wordCountInclude_yaml',
+    'test_wordCountImport_yaml',
+    'test_wordCountInheritance_yaml'
+])
 def _wordcount_jinja_test_preprocessor(
     test_spec: dict, expected: List[str], env: TestEnvironment):
   """
@@ -679,6 +682,7 @@ def _kafka_test_preprocessor(
     'test_anomaly_scoring_yaml',
     'test_wordCountInclude_yaml',
     'test_wordCountImport_yaml',
+    'test_wordCountInheritance_yaml',
     'test_iceberg_to_alloydb_yaml'
 ])
 def _io_write_test_preprocessor(
@@ -1256,8 +1260,11 @@ def _batch_log_analysis_test_preprocessor(
   return test_spec
 
 
[email protected]_test_preprocessor(
-    ['test_wordCountInclude_yaml', 'test_wordCountImport_yaml'])
[email protected]_test_preprocessor([
+    'test_wordCountInclude_yaml',
+    'test_wordCountImport_yaml',
+    'test_wordCountInheritance_yaml'
+])
 def _jinja_preprocessor(raw_spec_string: str, test_name: str):
   """
   Preprocessor for Jinja-based YAML tests.
diff --git a/sdks/python/apache_beam/yaml/examples/testing/input_data.py 
b/sdks/python/apache_beam/yaml/examples/testing/input_data.py
index fb468567355..7fe9b5291e0 100644
--- a/sdks/python/apache_beam/yaml/examples/testing/input_data.py
+++ b/sdks/python/apache_beam/yaml/examples/testing/input_data.py
@@ -86,6 +86,11 @@ def word_count_jinja_template_data(test_name: str) -> 
list[str]:
         'apache_beam/yaml/examples/transforms/jinja/'
         'import/macros/wordCountMacros.yaml'
     ]
+  elif test_name == 'test_wordCountInheritance_yaml':
+    return [
+        'apache_beam/yaml/examples/transforms/jinja/'
+        'inheritance/base/base_pipeline.yaml'
+    ]
   return []
 
 
diff --git 
a/sdks/python/apache_beam/yaml/examples/transforms/jinja/inheritance/README.md 
b/sdks/python/apache_beam/yaml/examples/transforms/jinja/inheritance/README.md
new file mode 100644
index 00000000000..e22e54a5669
--- /dev/null
+++ 
b/sdks/python/apache_beam/yaml/examples/transforms/jinja/inheritance/README.md
@@ -0,0 +1,77 @@
+<!--
+    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.
+-->
+
+# Jinja Inheritance Example
+
+This folder contains an example of how to use Jinja2 inheritance in Beam YAML 
pipelines.
+
+## Files
+
+*   **base/base_pipeline.yaml**: A complete WordCount pipeline (Read -> Split 
-> Explode -> Combine -> MapToFields -> Write). It defines a block 
`extra_steps` between `Explode` and `MapToFields` to allow child pipelines to 
inject additional transforms.
+*   **wordCountInheritance.yaml**: Extends `base/base_pipeline.yaml` and 
injects a `Combine` transform into the `extra_steps` block to combine words.
+
+## Running the Example
+
+To run the child pipeline (which includes the inherited base pipeline logic + 
the new filter):
+
+General setup:
+```sh
+export 
PIPELINE_FILE=apache_beam/yaml/examples/transforms/jinja/inheritance/wordCountInheritance.yaml
+export KINGLEAR="gs://dataflow-samples/shakespeare/kinglear.txt"
+export TEMP_LOCATION="gs://MY-BUCKET/wordCounts/"
+export PROJECT="MY-PROJECT"
+export REGION="MY-REGION"
+
+cd <PATH_TO_BEAM_REPO>/beam/sdks/python
+```
+
+Multiline Run Example:
+```sh
+python -m apache_beam.yaml.main \
+  --project=${PROJECT} \
+  --region=${REGION} \
+  --yaml_pipeline_file="${PIPELINE_FILE}" \
+  --jinja_variables='{
+    "readFromTextTransform": {"path": "'"${KINGLEAR}"'"},
+    "mapToFieldsSplitConfig": {
+      "language": "python",
+      "fields": {
+        "value": "1"
+      }
+    },
+    "explodeTransform": {"fields": "word"},
+    "combineTransform": {
+      "group_by": "word",
+      "combine": {"value": "sum"}
+    },
+    "mapToFieldsCountConfig": {
+      "language": "python",
+      "fields": {"output": "word + \" - \" + str(value)"}
+    },
+    "writeToTextTransform": {"path": "'"${TEMP_LOCATION}"'"}
+  }'
+```
+
+Single Line Run Example:
+```sh
+python -m apache_beam.yaml.main --project=${PROJECT} --region=${REGION} \
+--yaml_pipeline_file="${PIPELINE_FILE}" 
--jinja_variables='{"readFromTextTransform":
+{"path": "'"${KINGLEAR}"'"}, "mapToFieldsSplitConfig": {"language": "python", 
"fields":{"value":"1"}}, "explodeTransform":{"fields":"word"}, 
"combineTransform":{"group_by":"word", "combine":{"value":"sum"}}, 
"mapToFieldsCountConfig":{"language": "python", "fields":{"output":"word + \" - 
\" + str(value)"}}, "writeToTextTransform":{"path":"'"${TEMP_LOCATION}"'"}}'
+```
+
diff --git 
a/sdks/python/apache_beam/yaml/examples/transforms/jinja/inheritance/base/base_pipeline.yaml
 
b/sdks/python/apache_beam/yaml/examples/transforms/jinja/inheritance/base/base_pipeline.yaml
new file mode 100644
index 00000000000..209646b894a
--- /dev/null
+++ 
b/sdks/python/apache_beam/yaml/examples/transforms/jinja/inheritance/base/base_pipeline.yaml
@@ -0,0 +1,55 @@
+#
+# 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.
+#
+
+pipeline:
+  type: chain
+  transforms:
+    - type: ReadFromText
+      config:
+        path: {{readFromTextTransform.path}}
+
+    - type: MapToFields
+      name: Split words
+      config:
+        language: python
+        fields:
+          word:
+            callable: |-
+              import re
+              def my_mapping(row):
+                return re.findall(r'[A-Za-z\']+', row.line.lower())
+          value: {{mapToFieldsSplitConfig.fields.value}}
+    - type: Explode
+      config:
+        fields:
+          - {{explodeTransform.fields}}
+
+    # Inheritance injection point: content added here by child pipelines will 
be executed
+    # after Explode and before MapToFields.
+{% block extra_steps %}
+{% endblock %}
+
+    - type: MapToFields
+      name: Format output
+      config:
+        language: {{mapToFieldsCountConfig.language}}
+        fields:
+          output: {{mapToFieldsCountConfig.fields.output}}
+    - name: Write to GCS
+      type: WriteToText
+      config:
+        path: {{writeToTextTransform.path}}
diff --git 
a/sdks/python/apache_beam/yaml/examples/transforms/jinja/inheritance/wordCountInheritance.yaml
 
b/sdks/python/apache_beam/yaml/examples/transforms/jinja/inheritance/wordCountInheritance.yaml
new file mode 100644
index 00000000000..ad9f44df785
--- /dev/null
+++ 
b/sdks/python/apache_beam/yaml/examples/transforms/jinja/inheritance/wordCountInheritance.yaml
@@ -0,0 +1,40 @@
+#
+# 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.
+#
+
+{% extends 
"apache_beam/yaml/examples/transforms/jinja/inheritance/base/base_pipeline.yaml"
 %}
+
+{% block extra_steps %}
+    - name: Count words
+      type: Combine
+      config:
+        group_by:
+          - {{combineTransform.group_by}}
+        combine:
+          value: {{combineTransform.combine.value}}
+{% endblock %}
+
+# Expected:
+#  Row(output='king - 311')
+#  Row(output='lear - 253')
+#  Row(output='dramatis - 1')
+#  Row(output='personae - 1')
+#  Row(output='of - 483')
+#  Row(output='britain - 2')
+#  Row(output='france - 32')
+#  Row(output='duke - 26')
+#  Row(output='burgundy - 20')
+#  Row(output='cornwall - 75')
\ No newline at end of file

Reply via email to