Skip to content

Commit

Permalink
Move setup order check back to pre-commit (apache#9010)
Browse files Browse the repository at this point in the history
* Move setup order check back to pre-commit

The order check used to be working from pre-commit but then it
was moved to be regular test case. That was a mistake

The test is super-fast and actually making it use assertEquals
was not very useful and it was very late when you found it out.

I changed it to be normal python script which made it works again
(it did not work when it was a test because pre-commit does not
run tests - it runs python scripts).

The messages printed now are much more informative as well.
  • Loading branch information
potiuk authored May 26, 2020
1 parent 2a88955 commit 7883885
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 144 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ metastore_browser/templates/.*\\.html$|.*\\.jinja2"
files: ^setup.py$
pass_filenames: false
require_serial: true
entry: tests/test_order_setup.py
entry: ./scripts/ci/pre_commit_check_order_setup.py
- id: update-breeze-file
name: Update output of breeze command in BREEZE.rst
entry: "./scripts/ci/pre_commit_breeze_cmd_line.sh"
Expand Down Expand Up @@ -315,7 +315,7 @@ metastore_browser/templates/.*\\.html$|.*\\.jinja2"
files: "config.yml$|default_airflow.cfg$|default.cfg$"
pass_filenames: false
require_serial: false
entry: scripts/ci/pre_commit_yaml_to_cfg.py
entry: ./scripts/ci/pre_commit_yaml_to_cfg.py
additional_dependencies: ['pyyaml']
- id: mypy
name: Run mypy
Expand Down
4 changes: 2 additions & 2 deletions requirements/requirements-python3.6.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Flask-JWT-Extended==3.24.1
Flask-Login==0.4.1
Flask-OAuthlib==0.9.5
Flask-OpenID==1.2.5
Flask-SQLAlchemy==2.4.1
Flask-SQLAlchemy==2.4.2
Flask-WTF==0.14.3
Flask==1.1.2
GitPython==3.1.2
Expand All @@ -22,7 +22,7 @@ Markdown==2.6.11
MarkupSafe==1.1.1
PyHive==0.6.2
PyJWT==1.7.1
PyNaCl==1.3.0
PyNaCl==1.4.0
PySmbClient==0.1.5
PyYAML==5.3.1
Pygments==2.6.1
Expand Down
8 changes: 4 additions & 4 deletions requirements/requirements-python3.7.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Flask-JWT-Extended==3.24.1
Flask-Login==0.4.1
Flask-OAuthlib==0.9.5
Flask-OpenID==1.2.5
Flask-SQLAlchemy==2.4.1
Flask-SQLAlchemy==2.4.2
Flask-WTF==0.14.3
Flask==1.1.2
GitPython==3.1.2
Expand All @@ -22,7 +22,7 @@ Markdown==2.6.11
MarkupSafe==1.1.1
PyHive==0.6.2
PyJWT==1.7.1
PyNaCl==1.3.0
PyNaCl==1.4.0
PySmbClient==0.1.5
PyYAML==5.3.1
Pygments==2.6.1
Expand All @@ -45,7 +45,7 @@ apispec==1.3.3
appdirs==1.4.4
argcomplete==1.11.1
asn1crypto==1.3.0
astroid==2.3.3
astroid==2.4.1
async-generator==1.10
async-timeout==3.0.1
atlasclient==1.0.0
Expand Down Expand Up @@ -371,7 +371,7 @@ virtualenv==20.0.21
watchtower==0.7.3
wcwidth==0.1.9
websocket-client==0.57.0
wrapt==1.11.2
wrapt==1.12.1
xmltodict==0.12.0
yamllint==1.23.0
yandexcloud==0.39.0
Expand Down
2 changes: 1 addition & 1 deletion requirements/setup-3.6.md5
Original file line number Diff line number Diff line change
@@ -1 +1 @@
aa30d51f3388ba898dfeeabc4df5f16b /opt/airflow/setup.py
92aca7dc7f21d787c2e1a638d0355a00 /opt/airflow/setup.py
2 changes: 1 addition & 1 deletion requirements/setup-3.7.md5
Original file line number Diff line number Diff line change
@@ -1 +1 @@
aa30d51f3388ba898dfeeabc4df5f16b /opt/airflow/setup.py
92aca7dc7f21d787c2e1a638d0355a00 /opt/airflow/setup.py
165 changes: 165 additions & 0 deletions scripts/ci/pre_commit_check_order_setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
#!/usr/bin/env python
#
# 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.
"""
Test for an order of dependencies in setup.py
"""

import os
import re
import sys
from os.path import abspath, dirname
from typing import List

errors = []


def _check_list_sorted(the_list: List[str], message: str) -> None:
sorted_list = sorted(the_list)
if the_list == sorted_list:
print(f"{message} is ok")
return
i = 0
while sorted_list[i] == the_list[i]:
i += 1
print(f"{message} NOK")
errors.append(f"ERROR in {message}. First wrongly sorted element"
f" {the_list[i]}. Should be {sorted_list[i]}")


def setup() -> str:
setup_py_file_path = abspath(os.path.join(dirname(__file__), os.pardir, os.pardir, 'setup.py'))
with open(setup_py_file_path) as setup_file:
setup_context = setup_file.read()
return setup_context


def check_main_dependent_group(setup_context: str) -> None:
"""
Test for an order of dependencies groups between mark
'# Start dependencies group' and '# End dependencies group' in setup.py
"""
pattern_main_dependent_group = re.compile(
'# Start dependencies group\n(.*)# End dependencies group', re.DOTALL)
main_dependent_group = pattern_main_dependent_group.findall(setup_context)[0]

pattern_sub_dependent = re.compile(' = \\[.*?\\]\n', re.DOTALL)
main_dependent = pattern_sub_dependent.sub(',', main_dependent_group)

src = main_dependent.strip(',').split(',')
_check_list_sorted(src, "Order of dependencies")


def check_sub_dependent_group(setup_context: str) -> None:
"""
Test for an order of each dependencies groups declare like
`^dependent_group_name = [.*?]\n` in setup.py
"""
pattern_dependent_group_name = re.compile('^(\\w+) = \\[', re.MULTILINE)
dependent_group_names = pattern_dependent_group_name.findall(setup_context)

pattern_dependent_version = re.compile('[~|><=;].*')

for group_name in dependent_group_names:
pattern_sub_dependent = re.compile(
'{group_name} = \\[(.*?)\\]'.format(group_name=group_name), re.DOTALL)
sub_dependent = pattern_sub_dependent.findall(setup_context)[0]
pattern_dependent = re.compile('\'(.*?)\'')
dependent = pattern_dependent.findall(sub_dependent)

src = [pattern_dependent_version.sub('', p) for p in dependent]
_check_list_sorted(src, f"Order of sub-dependencies group: {group_name}")


def check_alias_dependent_group(setup_context: str) -> None:
"""
Test for an order of each dependencies groups declare like
`alias_dependent_group = dependent_group_1 + ... + dependent_group_n` in setup.py
"""
pattern = re.compile('^\\w+ = (\\w+ \\+.*)', re.MULTILINE)
dependents = pattern.findall(setup_context)

for dependent in dependents:
src = dependent.split(' + ')
_check_list_sorted(src, f"Order of alias dependencies group: {dependent}")


def check_install_and_setup_requires(setup_context: str) -> None:
"""
Test for an order of dependencies in function do_setup section
install_requires and setup_requires in setup.py
"""
pattern_install_and_setup_requires = re.compile(
'(setup_requires) ?= ?\\[(.*?)\\]', re.DOTALL)
install_and_setup_requires = pattern_install_and_setup_requires.findall(setup_context)

for dependent_requires in install_and_setup_requires:
pattern_dependent = re.compile('\'(.*?)\'')
dependent = pattern_dependent.findall(dependent_requires[1])
pattern_dependent_version = re.compile('[~|><=;].*')

src = [pattern_dependent_version.sub('', p) for p in dependent]
_check_list_sorted(src, f"Order of dependencies in do_setup section: {dependent_requires[0]}")


def check_extras_require(setup_context: str) -> None:
"""
Test for an order of dependencies in function do_setup section
extras_require in setup.py
"""
pattern_extras_requires = re.compile(
r'EXTRAS_REQUIREMENTS: Dict\[str, Iterable\[str\]] = {(.*?)}', re.DOTALL)
extras_requires = pattern_extras_requires.findall(setup_context)[0]

pattern_dependent = re.compile('\'(.*?)\'')
src = pattern_dependent.findall(extras_requires)
_check_list_sorted(src, "Order of dependencies in: extras_require")


def check_provider_requirements(setup_context: str) -> None:
"""
Test for an order of dependencies in function do_setup section
providers_require in setup.py
"""
pattern_extras_requires = re.compile(
r'PROVIDERS_REQUIREMENTS: Dict\[str, Iterable\[str\]\] = {(.*?)}', re.DOTALL)
extras_requires = pattern_extras_requires.findall(setup_context)[0]

pattern_dependent = re.compile('"(.*?)"')
src = pattern_dependent.findall(extras_requires)
_check_list_sorted(src, "Order of dependencies in: providers_require")


if __name__ == '__main__':
setup_context_main = setup()
check_main_dependent_group(setup_context_main)
check_alias_dependent_group(setup_context_main)
check_sub_dependent_group(setup_context_main)
check_install_and_setup_requires(setup_context_main)
check_extras_require(setup_context_main)
check_provider_requirements(setup_context_main)

print()
print()
for error in errors:
print(error)

print()

if errors:
sys.exit(1)
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,8 @@ def write_version(filename: str = os.path.join(*[my_dir, "airflow", "git_version
file.write(text)


# 'Start dependencies group' and 'Start dependencies group' are mark for ./test/test_order_setup.py
# If you change this mark you should also change ./test/test_order_setup.py function test_main_dependent_group
# 'Start dependencies group' and 'Start dependencies group' are mark for ./scripts/ci/check_order_setup.py
# If you change this mark you should also change ./scripts/ci/check_order_setup.py
# Start dependencies group
amazon = [
'boto3>=1.12.0,<2.0.0',
Expand Down Expand Up @@ -502,8 +502,8 @@ def write_version(filename: str = os.path.join(*[my_dir, "airflow", "git_version
"dingding": [],
"discord": [],
"docker": docker,
"email": [],
"elasticsearch": [],
"email": [],
"exasol": exasol,
"facebook": facebook,
"ftp": [],
Expand Down
131 changes: 0 additions & 131 deletions tests/test_order_setup.py

This file was deleted.

0 comments on commit 7883885

Please sign in to comment.