diff --git a/.asf.yaml b/.asf.yaml index 811a2cd79..4990c444e 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -1,3 +1,20 @@ +# 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. + # https://cwiki.apache.org/confluence/display/INFRA/Git+-+.asf.yaml+features github: diff --git a/.claude-plugin/skills/core/SKILL.md b/.claude-plugin/skills/core/SKILL.md index 48c4095c6..6e8f92a78 100644 --- a/.claude-plugin/skills/core/SKILL.md +++ b/.claude-plugin/skills/core/SKILL.md @@ -1,22 +1,3 @@ - - --- name: hamilton-core description: Core Hamilton patterns for creating DAGs, applying decorators, testing, and debugging dataflows. Use for basic Hamilton development tasks. @@ -24,6 +5,7 @@ allowed-tools: Read, Grep, Glob, Bash(python:*), Bash(pytest:*) user-invocable: true disable-model-invocation: false --- + # Hamilton Core Development Assistant diff --git a/.claude-plugin/skills/hamilton-dev-workflow/SKILL.md b/.claude-plugin/skills/hamilton-dev-workflow/SKILL.md index 35a910b21..0da811320 100644 --- a/.claude-plugin/skills/hamilton-dev-workflow/SKILL.md +++ b/.claude-plugin/skills/hamilton-dev-workflow/SKILL.md @@ -1,22 +1,3 @@ - - --- name: hamilton-dev-workflow description: Systematic 5-step workflow for building Hamilton DAGs - DOT graphs, signatures, validation, TDD implementation. Use this workflow when creating new Hamilton modules from scratch. @@ -24,6 +5,7 @@ allowed-tools: Read, Grep, Glob, Bash(python:*), Bash(hamilton:*), Bash(pytest:* user-invocable: true disable-model-invocation: false --- + # Hamilton Development Workflow for Claude Code diff --git a/.claude-plugin/skills/integrations/SKILL.md b/.claude-plugin/skills/integrations/SKILL.md index a4c82a733..a11d1e07d 100644 --- a/.claude-plugin/skills/integrations/SKILL.md +++ b/.claude-plugin/skills/integrations/SKILL.md @@ -1,22 +1,3 @@ - - --- name: hamilton-integrations description: Hamilton integration patterns for Airflow, Dagster, FastAPI, Streamlit, Jupyter notebooks, and other frameworks. Use when integrating Hamilton with other tools. @@ -24,6 +5,7 @@ allowed-tools: Read, Grep, Glob, Bash(python:*), Bash(jupyter:*) user-invocable: true disable-model-invocation: false --- + # Hamilton Integrations diff --git a/.claude-plugin/skills/llm/SKILL.md b/.claude-plugin/skills/llm/SKILL.md index dbf1e03c6..12bf5a9b4 100644 --- a/.claude-plugin/skills/llm/SKILL.md +++ b/.claude-plugin/skills/llm/SKILL.md @@ -1,22 +1,3 @@ - - --- name: hamilton-llm description: LLM and AI workflow patterns for Hamilton including RAG pipelines, embeddings, vector databases, and prompt engineering. Use for building AI applications with Hamilton. @@ -24,6 +5,7 @@ allowed-tools: Read, Grep, Glob, Bash(python:*), Bash(pytest:*) user-invocable: true disable-model-invocation: false --- + # Hamilton for LLM & AI Workflows diff --git a/.claude-plugin/skills/mcp/SKILL.md b/.claude-plugin/skills/mcp/SKILL.md index ead670550..fd90e7850 100644 --- a/.claude-plugin/skills/mcp/SKILL.md +++ b/.claude-plugin/skills/mcp/SKILL.md @@ -1,22 +1,3 @@ - - --- name: hamilton-mcp description: Interactive Hamilton DAG development via MCP tools. Validate, visualize, scaffold, and execute Hamilton pipelines without leaving the conversation. Use when building or debugging Hamilton dataflows interactively. @@ -24,6 +5,7 @@ allowed-tools: Read, Grep, Glob, Bash(hamilton-mcp:*), Bash(python:*), Bash(pip: user-invocable: true disable-model-invocation: false --- + # Hamilton MCP Server -- Interactive DAG Development diff --git a/.claude-plugin/skills/observability/SKILL.md b/.claude-plugin/skills/observability/SKILL.md index 5346f6283..fa430aa24 100644 --- a/.claude-plugin/skills/observability/SKILL.md +++ b/.claude-plugin/skills/observability/SKILL.md @@ -1,22 +1,3 @@ - - --- name: hamilton-observability description: Hamilton UI and SDK patterns for tracking, monitoring, and debugging dataflows. Use for observability, lineage tracking, and production monitoring. @@ -24,6 +5,7 @@ allowed-tools: Read, Grep, Glob, Bash(python:*), Bash(hamilton:*) user-invocable: true disable-model-invocation: false --- + # Hamilton Observability & UI diff --git a/.claude-plugin/skills/scale/SKILL.md b/.claude-plugin/skills/scale/SKILL.md index 104dc1eee..64bd2e0cf 100644 --- a/.claude-plugin/skills/scale/SKILL.md +++ b/.claude-plugin/skills/scale/SKILL.md @@ -1,22 +1,3 @@ - - --- name: hamilton-scale description: Performance and parallelization patterns for Hamilton including async I/O, Spark, Ray, Dask, caching, and multithreading. Use for scaling Hamilton workflows. @@ -24,6 +5,7 @@ allowed-tools: Read, Grep, Glob, Bash(python:*), Bash(pytest:*) user-invocable: true disable-model-invocation: false --- + # Hamilton Scaling & Performance diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..dc92df159 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +# Files below use a short SPDX license identifier instead of the full +# Apache 2.0 header because they are NOT included in official releases +# (sdist / wheel). The `export-ignore` attribute ensures `git archive` +# (and tools that rely on it) will exclude them automatically. + +.github export-ignore diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 691b4afc0..f93a3041f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,3 +1,5 @@ + + --- PR TEMPLATE INSTRUCTIONS (1) --- Looking to submit a Apache Hamilton Dataflow to the sf-hamilton-contrib module? If so go the the `Preview` tab and select the appropriate sub-template: diff --git a/.github/PULL_REQUEST_TEMPLATE/HAMILTON_CONTRIB_PR_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE/HAMILTON_CONTRIB_PR_TEMPLATE.md index 6c7143255..d28484f67 100644 --- a/.github/PULL_REQUEST_TEMPLATE/HAMILTON_CONTRIB_PR_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE/HAMILTON_CONTRIB_PR_TEMPLATE.md @@ -1,3 +1,5 @@ + + [Summary of contribution] ## For new dataflows: diff --git a/.github/workflows/hamilton-lsp.yml b/.github/workflows/hamilton-lsp.yml index eb24724e2..847436636 100644 --- a/.github/workflows/hamilton-lsp.yml +++ b/.github/workflows/hamilton-lsp.yml @@ -23,9 +23,6 @@ jobs: working-directory: dev_tools/language_server steps: - uses: actions/checkout@v3 - - name: Check for missing Apache 2 license headers - run: python3 scripts/check_license_headers.py - working-directory: ${{ github.workspace }} - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: diff --git a/.github/workflows/hamilton-main.yml b/.github/workflows/hamilton-main.yml index ea1c2c5ba..2274860da 100644 --- a/.github/workflows/hamilton-main.yml +++ b/.github/workflows/hamilton-main.yml @@ -14,6 +14,28 @@ on: - 'pyproject.toml' jobs: + static-checks: + name: "Static Checks" + runs-on: ubuntu-latest + env: + UV_PRERELEASE: "allow" + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install uv and set the python version + uses: astral-sh/setup-uv@v6 + with: + python-version: '3.10' + enable-cache: true + cache-dependency-glob: "uv.lock" + activate-environment: true + + - name: Check linting with prek + run: | + uv sync --dev + uv run prek run --all-files --hook-stage pre-merge-commit + test: name: "Unit Tests" runs-on: ${{ matrix.os }} @@ -59,19 +81,6 @@ jobs: cache-dependency-glob: "uv.lock" activate-environment: true - # It's enough to do it on single OS - - name: Check linting with prek - if: ${{ runner.os == 'Linux' }} - run: | - uv sync --dev - uv run prek install - uv run prek run --all-files - - - name: Check for missing Apache 2 license headers - if: ${{ runner.os == 'Linux' }} - run: | - python3 scripts/check_license_headers.py - - name: Test hamilton main package run: | uv sync --group test diff --git a/.github/workflows/hamilton-sdk.yml b/.github/workflows/hamilton-sdk.yml index 774e8a8b6..499423698 100644 --- a/.github/workflows/hamilton-sdk.yml +++ b/.github/workflows/hamilton-sdk.yml @@ -23,9 +23,6 @@ jobs: working-directory: ui/sdk steps: - uses: actions/checkout@v3 - - name: Check for missing Apache 2 license headers - run: python3 scripts/check_license_headers.py - working-directory: ${{ github.workspace }} - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: diff --git a/.github/workflows/hamilton-ui-backend.yml b/.github/workflows/hamilton-ui-backend.yml index 20942ce5f..9b9bb359f 100644 --- a/.github/workflows/hamilton-ui-backend.yml +++ b/.github/workflows/hamilton-ui-backend.yml @@ -36,9 +36,6 @@ jobs: --health-retries 10 steps: - uses: actions/checkout@v3 - - name: Check for missing Apache 2 license headers - run: | - python3 scripts/check_license_headers.py - name: Set up Python uses: actions/setup-python@v4 with: diff --git a/.github/workflows/hamilton-ui-frontend.yml b/.github/workflows/hamilton-ui-frontend.yml index cfecec7fd..e200c9061 100644 --- a/.github/workflows/hamilton-ui-frontend.yml +++ b/.github/workflows/hamilton-ui-frontend.yml @@ -20,9 +20,6 @@ jobs: node-version: [20.x] steps: - uses: actions/checkout@v3 - - name: Check for missing Apache 2 license headers - run: python3 scripts/check_license_headers.py - working-directory: ${{ github.workspace }} - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: diff --git a/.github/workflows/sphinx-docs.yml b/.github/workflows/sphinx-docs.yml index cfc99d76d..cf5315cda 100644 --- a/.github/workflows/sphinx-docs.yml +++ b/.github/workflows/sphinx-docs.yml @@ -41,10 +41,6 @@ jobs: run: | python -m pip install --upgrade --no-cache-dir pip setuptools - - name: Check for missing Apache 2 license headers - run: | - python3 scripts/check_license_headers.py - - name: Install Sphinx and dependencies run: | python -m pip install --upgrade --no-cache-dir sphinx sphinx-rtd-theme sphinx-simplepdf diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 46ac9e593..e33449f34 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,9 +1,27 @@ +# 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. + # pre-commit hooks require a user to have installed `prek`: # $ brew install prek # Then install the hooks within the repo: # $ cd /PATH/TO/REPO # $ prek install exclude: '^docs/code-comparisons/' # skip the code comparisons directory +default_stages: [pre-commit, pre-merge-commit] repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. @@ -25,6 +43,102 @@ repos: - id: requirements-txt-fixer # valid python file - id: check-ast + - repo: https://github.com/Lucas-C/pre-commit-hooks + rev: v1.5.6 + hooks: + - id: insert-license + name: Add license for all Python files + files: \.py$|\.pyi$ + exclude: | + (?x) + ^\.github/| + ^docs/| + ^examples/| + ^dev_tools/language_server/tests/ls_setup\.py$ + args: + - --comment-style + - "|#|" + - --license-filepath + - scripts/ci/license-templates/LICENSE + - --fuzzy-match-generates-todo + - id: insert-license + name: Add license for all YAML files + files: \.ya?ml$ + types: [yaml] + exclude: | + (?x) + ^\.github/| + ^docs/| + ^examples/ + args: + - --comment-style + - "|#|" + - --license-filepath + - scripts/ci/license-templates/LICENSE + - --fuzzy-match-generates-todo + - id: insert-license + name: Add license for all TOML files + files: \.toml$ + exclude: | + (?x) + ^\.github/| + ^docs/| + ^examples/ + args: + - --comment-style + - "|#|" + - --license-filepath + - scripts/ci/license-templates/LICENSE + - --fuzzy-match-generates-todo + - id: insert-license + name: Add license for all Shell files + files: \.bash$|\.sh$ + exclude: | + (?x) + ^\.github/| + ^docs/| + ^examples/ + args: + - --comment-style + - "|#|" + - --license-filepath + - scripts/ci/license-templates/LICENSE + - --fuzzy-match-generates-todo + - id: insert-license + name: Add license for all Markdown files + files: \.md$ + exclude: | + (?x) + ^\.github/.*\.md$| + ^\.claude-plugin/.*SKILL\.md$| + ^docs/| + ^contrib/docs/| + ^examples/| + ^scripts/ci/license-templates/ + args: + - --comment-style + - "" + - --license-filepath + - scripts/ci/license-templates/LICENSE + - --fuzzy-match-generates-todo + - id: insert-license + name: Add short license for agentic Markdown files + files: | + (?x) + ^\.github/.*\.md$| + ^\.claude-plugin/.*SKILL\.md$ + exclude: | + (?x) + ^\.github/ISSUE_TEMPLATE/| + ^scripts/ci/license-templates/ + args: + - --comment-style + - "||" + - --license-filepath + - scripts/ci/license-templates/SHORT_LICENSE.md + - --detect-license-in-X-top-lines + - '8' + - --fuzzy-match-generates-todo - repo: local hooks: - id: validate-example-notebooks diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 5d3261330..c7121221a 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -1,3 +1,20 @@ +# 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. + # .readthedocs.yaml # Read the Docs configuration file # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 30dffb09e..3b89072da 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,19 +1,22 @@ + + 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. + --> # Guidance on how to contribute diff --git a/SECURITY.md b/SECURITY.md index 474e2784a..9f6a459da 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,19 +1,23 @@ + + 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. + --> + # Security Policy The security surface area of Apache Hamilton should be pretty small in comparison to other projects. diff --git a/contrib/docs/blog/authors.yml b/contrib/docs/blog/authors.yml index 6ab3f5ddf..3fb6d20a4 100644 --- a/contrib/docs/blog/authors.yml +++ b/contrib/docs/blog/authors.yml @@ -1,3 +1,20 @@ +# 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. + skrawcz: name: Stefan Krawczyk title: Co-creator of Hamilton and CEO @ DAGWorks Inc. diff --git a/contrib/pyproject.toml b/contrib/pyproject.toml index 7ed0247e1..c6bc54e9d 100644 --- a/contrib/pyproject.toml +++ b/contrib/pyproject.toml @@ -8,7 +8,7 @@ # # http://www.apache.org/licenses/LICENSE-2.0 # -# Unless required by applicable law or agreed to in writing, +# 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 diff --git a/dev_tools/language_server/LICENSE b/dev_tools/language_server/LICENSE index 60a996edb..69f3792df 100644 --- a/dev_tools/language_server/LICENSE +++ b/dev_tools/language_server/LICENSE @@ -226,3 +226,9 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +This product includes test code derived from pygls +(https://github.com/openlawlibrary/pygls): +Copyright (c) Open Law Library. All rights reserved. +Licensed under the Apache License, Version 2.0. +See dev_tools/language_server/tests/ls_setup.py. diff --git a/dev_tools/language_server/pyproject.toml b/dev_tools/language_server/pyproject.toml index 0e2ee1e77..14820afdb 100644 --- a/dev_tools/language_server/pyproject.toml +++ b/dev_tools/language_server/pyproject.toml @@ -8,7 +8,7 @@ # # http://www.apache.org/licenses/LICENSE-2.0 # -# Unless required by applicable law or agreed to in writing, +# 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 diff --git a/dev_tools/language_server/tests/conftest.py b/dev_tools/language_server/tests/conftest.py index 3c0c25d4c..0deab76cf 100644 --- a/dev_tools/language_server/tests/conftest.py +++ b/dev_tools/language_server/tests/conftest.py @@ -1,21 +1,20 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed 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. # -############################################################################ +# 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 pytest from hamilton_lsp.server import HamiltonLanguageServer, register_server_features diff --git a/dev_tools/language_server/tests/ls_setup.py b/dev_tools/language_server/tests/ls_setup.py index f4c08e257..17350a1f3 100644 --- a/dev_tools/language_server/tests/ls_setup.py +++ b/dev_tools/language_server/tests/ls_setup.py @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ + import asyncio import concurrent import os diff --git a/ellipsis.yaml b/ellipsis.yaml index 9442375a5..3590174cb 100644 --- a/ellipsis.yaml +++ b/ellipsis.yaml @@ -1,3 +1,20 @@ +# 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. + version: 1.3 about: diff --git a/scripts/add_license_headers.py b/scripts/add_license_headers.py deleted file mode 100755 index 29fe8ccec..000000000 --- a/scripts/add_license_headers.py +++ /dev/null @@ -1,295 +0,0 @@ -#!/usr/bin/env python3 -# 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. - -"""Script to add Apache 2 license headers to files in the Hamilton repository.""" - -import json -import sys -from pathlib import Path - -# Base Apache 2 license text (without comment characters) -# This is used by all formatters below to generate file-type-specific headers -LICENSE_LINES = [ - "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.", -] - - -def format_hash_comment(lines: list[str]) -> str: - """Format license as # comments (for Python, Shell, etc.).""" - return "\n".join(f"# {line}" if line else "#" for line in lines) + "\n\n" - - -def format_dash_comment(lines: list[str]) -> str: - """Format license as -- comments (for SQL).""" - return "\n".join(f"-- {line}" if line else "--" for line in lines) + "\n\n" - - -def format_c_style_comment(lines: list[str]) -> str: - """Format license as /* */ comments (for TypeScript, JavaScript, etc.).""" - formatted_lines = ["/*"] - for line in lines: - formatted_lines.append(f" * {line}" if line else " *") - formatted_lines.append(" */") - return "\n".join(formatted_lines) + "\n\n" - - -def format_html_comment(lines: list[str]) -> str: - """Format license as HTML comments (for Markdown).""" - formatted_lines = ["") - return "\n".join(formatted_lines) + "\n\n" - - -# Pre-generate common license headers -PYTHON_LICENSE_HEADER = format_hash_comment(LICENSE_LINES) -SQL_LICENSE_HEADER = format_dash_comment(LICENSE_LINES) -TYPESCRIPT_LICENSE_HEADER = format_c_style_comment(LICENSE_LINES) -MARKDOWN_LICENSE_HEADER = format_html_comment(LICENSE_LINES) -# For notebooks, we need just the plain text -NOTEBOOK_LICENSE_TEXT = "\n".join(LICENSE_LINES) - - -def add_license_to_python(content: str) -> str: - """Add Apache 2 license header to Python file content.""" - # Handle shebang lines - preserve them at the top - lines = content.split("\n", 1) - if lines[0].startswith("#!"): - # File has shebang, add license after it - if len(lines) > 1: - return lines[0] + "\n" + PYTHON_LICENSE_HEADER + lines[1] - else: - return lines[0] + "\n" + PYTHON_LICENSE_HEADER - else: - # No shebang, add license at the beginning - return PYTHON_LICENSE_HEADER + content - - -def add_license_to_markdown(content: str) -> str: - """Add Apache 2 license header to Markdown file content.""" - return MARKDOWN_LICENSE_HEADER + content - - -def add_license_to_notebook(content: str) -> str: - """Add Apache 2 license header to Jupyter notebook.""" - try: - notebook = json.loads(content) - except json.JSONDecodeError as e: - raise ValueError(f"Invalid notebook JSON: {e}") from e - - # Create a new markdown cell with the license - license_cell = {"cell_type": "markdown", "metadata": {}, "source": [NOTEBOOK_LICENSE_TEXT]} - - # Insert at the beginning - if "cells" not in notebook: - notebook["cells"] = [] - - notebook["cells"].insert(0, license_cell) - - return json.dumps(notebook, indent=1, ensure_ascii=False) - - -def add_license_to_shell(content: str) -> str: - """Add Apache 2 license header to shell script or Dockerfile. - - Uses same logic as Python files (# comments, handle shebang). - """ - # Handle shebang lines - preserve them at the top - lines = content.split("\n", 1) - if lines[0].startswith("#!"): - # File has shebang, add license after it - if len(lines) > 1: - return lines[0] + "\n" + PYTHON_LICENSE_HEADER + lines[1] - else: - return lines[0] + "\n" + PYTHON_LICENSE_HEADER - else: - # No shebang, add license at the beginning - return PYTHON_LICENSE_HEADER + content - - -def add_license_to_sql(content: str) -> str: - """Add Apache 2 license header to SQL file content.""" - return SQL_LICENSE_HEADER + content - - -def add_license_to_typescript(content: str) -> str: - """Add Apache 2 license header to TypeScript/JavaScript file content.""" - return TYPESCRIPT_LICENSE_HEADER + content - - -def add_license_header(file_path: Path, dry_run: bool = False) -> bool: - """Add Apache 2 license header to a file. - - Args: - file_path: Path to the file - dry_run: If True, only print what would be done without modifying files - - Returns: - True if header was added (or would be added in dry run), False otherwise - """ - try: - with open(file_path, "r", encoding="utf-8") as f: - content = f.read() - except (UnicodeDecodeError, PermissionError) as e: - print(f" ✗ Error reading {file_path}: {e}") - return False - - # Check if file already has a license header (check first 20 lines only) - first_lines = "\n".join(content.split("\n")[:20]) - if ( - "Licensed to the Apache Software Foundation" in first_lines - or "Apache License" in first_lines - ): - print(f" ↷ Skipping {file_path} (already has license header)") - return False - - # Determine file type and add appropriate header - try: - if file_path.suffix == ".py": - new_content = add_license_to_python(content) - elif file_path.suffix == ".md": - new_content = add_license_to_markdown(content) - elif file_path.suffix == ".ipynb": - new_content = add_license_to_notebook(content) - elif file_path.suffix == ".sh": - new_content = add_license_to_shell(content) - elif file_path.suffix == ".sql": - new_content = add_license_to_sql(content) - elif file_path.suffix in {".ts", ".tsx", ".js", ".jsx"}: - new_content = add_license_to_typescript(content) - elif file_path.name == "Dockerfile" or file_path.name.startswith("Dockerfile."): - # Dockerfiles use # comments like shell scripts - new_content = add_license_to_shell(content) - elif file_path.name == "README": - # README files without extension are usually markdown - new_content = add_license_to_markdown(content) - else: - print(f" ✗ Unsupported file type: {file_path.suffix} ({file_path.name})") - return False - except Exception as e: - print(f" ✗ Error processing {file_path}: {e}") - return False - - if dry_run: - print(f" ✓ Would add license header to {file_path}") - return True - - # Write the modified content back - try: - with open(file_path, "w", encoding="utf-8") as f: - f.write(new_content) - print(f" ✓ Added license header to {file_path}") - return True - except (PermissionError, OSError) as e: - print(f" ✗ Error writing {file_path}: {e}") - return False - - -def main(): - """Main function.""" - # Get repository root (parent of scripts directory) - repo_root = Path(__file__).parent.parent - - # Check for dry-run flag - dry_run = "--dry-run" in sys.argv or "-n" in sys.argv - - if dry_run: - print("DRY RUN MODE - No files will be modified\n") - - # Read the list of files from command line or use default - if len(sys.argv) > 1 and not sys.argv[-1].startswith("-"): - list_file = repo_root / sys.argv[-1] - else: - # Try combined list first, fall back to missing_license_headers.txt - list_file = repo_root / "missing_license_headers_combined.txt" - if not list_file.exists(): - list_file = repo_root / "missing_license_headers.txt" - - if not list_file.exists(): - print(f"Error: {list_file} not found!") - print("Run check_license_headers.py first to generate the list.") - print("Or specify a file list: python add_license_headers.py ") - return 1 - - print(f"Using file list: {list_file.name}\n") - - # Parse the file list - files_to_update: list[Path] = [] - with open(list_file, "r") as f: - for line in f: - line = line.strip() - # Skip header lines and empty lines - if ( - not line - or line.startswith("Checking") - or line.startswith("Extensions") - or line.startswith("Found") - or line.startswith("Mode:") - or line.startswith("Excluded") - ): - continue - # Try to parse as a file path - if it exists, add it - # This is more robust than trying to guess if it's a header line - file_path = line - full_path = repo_root / file_path - if full_path.exists() and full_path.is_file(): - files_to_update.append(full_path) - - if not files_to_update: - print("No files to update!") - return 0 - - print(f"Found {len(files_to_update)} files to add license headers to\n") - - # Process each file - success_count = 0 - skip_count = 0 - - for file_path in files_to_update: - result = add_license_header(file_path, dry_run=dry_run) - if result: - success_count += 1 - else: - # Could be a skip or an error - check the output - skip_count += 1 - - # Print summary - print(f"\n{'Would add' if dry_run else 'Added'} license headers to {success_count} files") - if skip_count > 0: - print(f"Skipped {skip_count} files") - - return 0 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/scripts/check_license_headers.py b/scripts/check_license_headers.py deleted file mode 100755 index 3553ffc8c..000000000 --- a/scripts/check_license_headers.py +++ /dev/null @@ -1,261 +0,0 @@ -#!/usr/bin/env python3 -# 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. - -"""Script to find files missing Apache 2 license headers in the Hamilton repository.""" - -import sys -from pathlib import Path - -# License header patterns to check for -# ASF-specific header (our standard) -ASF_LICENSE_PATTERNS = [ - "Licensed to the Apache Software Foundation (ASF)", - "Apache License, Version 2.0", -] - -# Third-party Apache 2.0 headers (also acceptable) -# Note: Some third-party headers may have spaces in the URL -THIRD_PARTY_APACHE_PATTERNS = [ - "Apache License, Version 2.0", - "www.apache.org/licenses/LICENSE-2.0", -] - -# File extensions to EXCLUDE from checking (based on what exists in this repo) -EXCLUDED_EXTENSIONS = { - # Python compiled/generated - ".pyc", - ".pyi", # Type stubs - ".pyx", # Cython - ".pxd", # Cython headers - ".pxi", # Cython includes - # Compiled binaries - ".so", - ".dylib", - ".jar", - # Images and media - ".png", - ".svg", - ".ttf", - ".afm", # Adobe font metrics - # Config/data files - ".json", - ".jsonl", - ".yaml", - ".yml", - ".toml", - ".cfg", # setup.cfg, etc. - ".conf", # nginx.conf, etc. - ".xml", # Test data, config files - ".csv", - ".fwf", # Fixed-width format test data - ".dot", # Graphviz DOT files - ".npy", # NumPy arrays - ".mat", # MATLAB data - ".sav", # SPSS data - ".po", # Gettext translations - ".mo", # Compiled translations - ".template", # Template config files - # Build/generated files - ".map", # Source maps - ".gz", - ".log", - ".typed", # PEP 561 marker - # Web assets (usually don't have license headers) - ".css", - ".scss", - ".html", - # JavaScript config files (these are code but often generated) - ".eslintrc", - ".nycrc", - ".npmignore", - ".editorconfig", - # Template files - ".j2", - ".jinja2", - # Documentation that doesn't need headers - ".txt", - ".rst", - # Other - ".gitkeep", - ".asc", # GPG keys - ".cmd", # Windows batch - ".coffee", # CoffeeScript (if any) - ".mjs", # ES modules (often generated) - ".cjs", # CommonJS modules (often generated) - ".mts", # TypeScript ES modules - ".flow", # Flow type definitions - ".in", # MANIFEST.in, etc. -} - -# Specific filenames to exclude (exact matches) -EXCLUDED_FILENAMES = { - # Lock files - "package-lock.json", - "yarn.lock", - "poetry.lock", - "uv.lock", - # License/legal files - "LICENSE", - "NOTICE", - "CHANGELOG", - # OS files - ".DS_Store", -} - -# Directories to skip -SKIP_DIRS = { - ".git", - "__pycache__", - "node_modules", - ".pytest_cache", - ".mypy_cache", - ".tox", - "venv", - ".venv", - "build", - "dist", - "*.egg-info", - ".eggs", - "htmlcov", - ".coverage", - ".claude", -} - - -def should_skip_path(path: Path) -> bool: - """Check if a path should be skipped.""" - # Skip if any parent directory is in SKIP_DIRS - for part in path.parts: - if part in SKIP_DIRS or part.startswith("."): - return True - - # Skip documentation snippet files (they're embedded in docs via literalinclude) - path_str = str(path) - if "docs" in path.parts and "_snippets" in path_str: - return True - if "docs/code-comparisons" in path_str and "snippets" in path_str: - return True - - return False - - -def has_license_header(file_path: Path, num_lines: int = 20) -> bool: - """Check if a file has an Apache 2 license header (ASF or third-party).""" - try: - with open(file_path, "r", encoding="utf-8") as f: - content = "".join(f.readlines()[:num_lines]) - - # Check if all ASF license patterns are present - has_asf_header = all(pattern in content for pattern in ASF_LICENSE_PATTERNS) - - # Check if all third-party Apache 2.0 patterns are present - has_third_party_header = all(pattern in content for pattern in THIRD_PARTY_APACHE_PATTERNS) - - # Accept either ASF or third-party Apache 2.0 headers - return has_asf_header or has_third_party_header - except (UnicodeDecodeError, PermissionError): - # Skip files that can't be read as text - return True # Assume they're fine to avoid false positives - - -def find_files_without_license(root_dir: Path) -> list[Path]: - """Find all files without Apache 2 license headers. - - Uses an exclusion-based approach: checks all files except those with - excluded extensions or filenames. - - Args: - root_dir: Root directory to search - - Returns: - Sorted list of file paths without license headers - """ - files_without_license = [] - - for file_path in root_dir.rglob("*"): - # Skip directories - if file_path.is_dir(): - continue - - # Skip if in excluded paths - if should_skip_path(file_path): - continue - - # Skip if extension is in exclusion list - if file_path.suffix in EXCLUDED_EXTENSIONS: - continue - - # Skip if filename is in exclusion list - if file_path.name in EXCLUDED_FILENAMES: - continue - - # Skip editor backup files (emacs, vim, etc.) - if ( - file_path.name.startswith("#") - or file_path.name.endswith("~") - or file_path.name.endswith("#") - ): - continue - - # Skip files without extensions that aren't special files - if ( - not file_path.suffix - and not file_path.name.startswith("Dockerfile") - and file_path.name != "README" - ): - continue - - # Check for license header - if not has_license_header(file_path): - files_without_license.append(file_path) - - return sorted(files_without_license) - - -def main(): - """Main function.""" - # Get repository root (parent of scripts directory) - repo_root = Path(__file__).parent.parent - - print(f"Checking for Apache 2 license headers in {repo_root}") - print("Mode: Checking all files except excluded types") - print(f"Excluded extensions: {len(EXCLUDED_EXTENSIONS)} types") - print(f"Excluded filenames: {len(EXCLUDED_FILENAMES)} patterns") - print() - - files_without_license = find_files_without_license(repo_root) - - if not files_without_license: - print("✓ All files have license headers!") - return 0 - - print(f"Found {len(files_without_license)} files without Apache 2 license headers:\n") - - for file_path in files_without_license: - # Print relative path from repo root - try: - rel_path = file_path.relative_to(repo_root) - print(f" {rel_path}") - except ValueError: - print(f" {file_path}") - - return 1 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/scripts/ci/license-templates/LICENSE b/scripts/ci/license-templates/LICENSE new file mode 100644 index 000000000..60b675e31 --- /dev/null +++ b/scripts/ci/license-templates/LICENSE @@ -0,0 +1,16 @@ +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. diff --git a/scripts/ci/license-templates/SHORT_LICENSE.md b/scripts/ci/license-templates/SHORT_LICENSE.md new file mode 100644 index 000000000..089e0c501 --- /dev/null +++ b/scripts/ci/license-templates/SHORT_LICENSE.md @@ -0,0 +1 @@ + diff --git a/ui/backend/pyproject.toml b/ui/backend/pyproject.toml index 88342f569..0e20fff78 100644 --- a/ui/backend/pyproject.toml +++ b/ui/backend/pyproject.toml @@ -8,7 +8,7 @@ # # http://www.apache.org/licenses/LICENSE-2.0 # -# Unless required by applicable law or agreed to in writing, +# 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 diff --git a/ui/backend/tests/__init__.py b/ui/backend/tests/__init__.py index 96c678c64..13a83393a 100644 --- a/ui/backend/tests/__init__.py +++ b/ui/backend/tests/__init__.py @@ -8,7 +8,7 @@ # # http://www.apache.org/licenses/LICENSE-2.0 # -# Unless required by applicable law or agreed to in writing, +# 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 diff --git a/ui/backend/tests/test_build.py b/ui/backend/tests/test_build.py index 61bca504b..e362ee1a2 100644 --- a/ui/backend/tests/test_build.py +++ b/ui/backend/tests/test_build.py @@ -8,7 +8,7 @@ # # http://www.apache.org/licenses/LICENSE-2.0 # -# Unless required by applicable law or agreed to in writing, +# 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 diff --git a/ui/docker-compose-prod.yml b/ui/docker-compose-prod.yml index 8f40dd9c3..d3f253d31 100644 --- a/ui/docker-compose-prod.yml +++ b/ui/docker-compose-prod.yml @@ -1,3 +1,20 @@ +# 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. + # TODO: use extends to avoid duplication version: '3.8' diff --git a/ui/docker-compose.yml b/ui/docker-compose.yml index d7cbeba94..bbe67e55f 100644 --- a/ui/docker-compose.yml +++ b/ui/docker-compose.yml @@ -1,3 +1,20 @@ +# 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. + version: '3.8' services: diff --git a/ui/sdk/.github/workflows/unit-tests.yml b/ui/sdk/.github/workflows/unit-tests.yml index 773c4eec3..c0d202b40 100644 --- a/ui/sdk/.github/workflows/unit-tests.yml +++ b/ui/sdk/.github/workflows/unit-tests.yml @@ -1,3 +1,20 @@ +# 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. + # This workflow will install Python dependencies, run tests and lint with a variety of Python versions # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python diff --git a/ui/sdk/.pre-commit-config.yaml b/ui/sdk/.pre-commit-config.yaml index 002932a4f..9ee352750 100644 --- a/ui/sdk/.pre-commit-config.yaml +++ b/ui/sdk/.pre-commit-config.yaml @@ -1,3 +1,20 @@ +# 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. + # pre-commit hooks require a user to have installed `prek`: # $ brew install prek # Then install the hooks within the repo: diff --git a/ui/sdk/pyproject.toml b/ui/sdk/pyproject.toml index 8c07ed03f..2b57dc0fa 100644 --- a/ui/sdk/pyproject.toml +++ b/ui/sdk/pyproject.toml @@ -8,7 +8,7 @@ # # http://www.apache.org/licenses/LICENSE-2.0 # -# Unless required by applicable law or agreed to in writing, +# 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 diff --git a/ui/sdk/ruff.toml b/ui/sdk/ruff.toml index dce37d81e..5b0111151 100644 --- a/ui/sdk/ruff.toml +++ b/ui/sdk/ruff.toml @@ -1,3 +1,20 @@ +# 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. + line-length = 100