diff --git a/scripts/check_for_valid_readme.py b/scripts/check_for_valid_readme.py index edf94d9c3..d555b4fa2 100644 --- a/scripts/check_for_valid_readme.py +++ b/scripts/check_for_valid_readme.py @@ -10,7 +10,7 @@ def is_valid_rst(path): """Checks if RST can be rendered on PyPI.""" with open(path) as readme_file: markup = readme_file.read() - return readme_renderer.rst.render(markup) is not None + return readme_renderer.rst.render(markup, stream=sys.stderr) is not None def parse_args(): diff --git a/scripts/coverage.sh b/scripts/coverage.sh index 97f537f38..8055adb0d 100755 --- a/scripts/coverage.sh +++ b/scripts/coverage.sh @@ -12,8 +12,23 @@ function cov { ${1} } +PYTHON_VERSION=$(python -c 'import sys; print(".".join(map(str, sys.version_info[:3])))') +PYTHON_VERSION_INFO=(${PYTHON_VERSION//./ }) coverage erase -coverage report +cov exporter/opentelemetry-exporter-datadog +cov instrumentation/opentelemetry-instrumentation-flask +cov instrumentation/opentelemetry-instrumentation-requests +cov instrumentation/opentelemetry-instrumentation-wsgi + +# aiohttp is only supported on Python 3.5+. +if [ ${PYTHON_VERSION_INFO[1]} -gt 4 ]; then + cov instrumentation/opentelemetry-instrumentation-aiohttp-client +# ext-asgi is only supported on Python 3.5+. +if [ ${PYTHON_VERSION_INFO[1]} -gt 4 ]; then + cov instrumentation/opentelemetry-instrumentation-asgi +fi + +coverage report --show-missing coverage xml diff --git a/scripts/eachdist.py b/scripts/eachdist.py index 8b1dbfada..cfa1764ab 100755 --- a/scripts/eachdist.py +++ b/scripts/eachdist.py @@ -1,12 +1,15 @@ #!/usr/bin/env python3 import argparse +import os +import re import shlex import shutil import subprocess import sys from collections import namedtuple from configparser import ConfigParser +from datetime import datetime from inspect import cleandoc from itertools import chain from pathlib import Path, PurePath @@ -205,6 +208,7 @@ def parse_args(args=None): setup_instparser(instparser) instparser.add_argument("--editable", "-e", action="store_true") + instparser.add_argument("--with-test-deps", action="store_true") instparser.add_argument("--with-dev-deps", action="store_true") instparser.add_argument("--eager-upgrades", action="store_true") @@ -214,7 +218,10 @@ def parse_args(args=None): ) setup_instparser(devparser) devparser.set_defaults( - editable=True, with_dev_deps=True, eager_upgrades=True + editable=True, + with_dev_deps=True, + eager_upgrades=True, + with_test_deps=True, ) lintparser = subparsers.add_parser( @@ -232,6 +239,15 @@ def parse_args(args=None): "pytestargs", nargs=argparse.REMAINDER, help=extraargs_help("pytest") ) + releaseparser = subparsers.add_parser( + "release", help="Prepares release, used by maintainers and CI", + ) + releaseparser.set_defaults(func=release_args) + releaseparser.add_argument("--version", required=True) + releaseparser.add_argument( + "releaseargs", nargs=argparse.REMAINDER, help=extraargs_help("pytest") + ) + return parser.parse_args(args) @@ -322,7 +338,7 @@ def find_targets(mode, rootpath): if ".egg-info" not in str(newentry) and newentry.exists() ] - return targets + return list(unique(targets)) def runsubprocess(dry_run, params, *args, **kwargs): @@ -436,7 +452,17 @@ def install_args(args): check=True, ) - allfmt = "-e 'file://{}'" if args.editable else "'file://{}'" + allfmt = "-e 'file://{}" if args.editable else "'file://{}" + # packages should provide an extra_requires that is named + # 'test', to denote test dependencies. + extras = [] + if args.with_test_deps: + extras.append("test") + if extras: + allfmt += "[{}]".format(",".join(extras)) + # note the trailing single quote, to close the quote opened above. + allfmt += "'" + execute_args( parse_subargs( args, @@ -502,6 +528,118 @@ def lint_args(args): ) +def update_changelog(path, version, new_entry): + unreleased_changes = False + try: + with open(path) as changelog: + text = changelog.read() + if "## Version {}".format(version) in text: + raise AttributeError( + "{} already contans version {}".format(path, version) + ) + with open(path) as changelog: + for line in changelog: + if line.startswith("## Unreleased"): + unreleased_changes = False + elif line.startswith("## "): + break + elif len(line.strip()) > 0: + unreleased_changes = True + + except FileNotFoundError: + print("file missing: {}".format(path)) + return + + if unreleased_changes: + print("updating: {}".format(path)) + text = re.sub("## Unreleased", new_entry, text) + with open(path, "w") as changelog: + changelog.write(text) + + +def update_changelogs(targets, version): + print("updating CHANGELOG") + today = datetime.now().strftime("%Y-%m-%d") + new_entry = "## Unreleased\n\n## Version {}\n\nReleased {}".format( + version, today + ) + errors = False + for target in targets: + try: + update_changelog( + "{}/CHANGELOG.md".format(target), version, new_entry + ) + except Exception as err: # pylint: disable=broad-except + print(str(err)) + errors = True + + if errors: + sys.exit(1) + + +def find(name, path): + for root, _, files in os.walk(path): + if name in files: + return os.path.join(root, name) + return None + + +def update_version_files(targets, version): + print("updating version.py files") + update_files( + targets, + version, + "version.py", + "__version__ .*", + '__version__ = "{}"'.format(version), + ) + + +def update_dependencies(targets, version): + print("updating dependencies") + update_files( + targets, + version, + "setup.cfg", + r"(opentelemetry-.*)==(.*)", + r"\1== " + version, + ) + + +def update_files(targets, version, filename, search, replace): + errors = False + for target in targets: + curr_file = find(filename, target) + if curr_file is None: + print("file missing: {}/{}".format(target, filename)) + continue + + with open(curr_file) as _file: + text = _file.read() + + if version in text: + print("{} already contans version {}".format(curr_file, version)) + errors = True + continue + + with open(curr_file, "w") as _file: + _file.write(re.sub(search, replace, text)) + + if errors: + sys.exit(1) + + +def release_args(args): + print("preparing release") + + rootpath = find_projectroot() + targets = list(find_targets_unordered(rootpath)) + version = args.version + update_dependencies(targets, version) + update_version_files(targets, version) + update_changelogs(targets, version) + + def test_args(args): clean_remainder_args(args.pytestargs) execute_args(