From 7a9abe3ec5295ff31aa7b164a3998bb0e429512a Mon Sep 17 00:00:00 2001 From: "martin.gano" Date: Tue, 8 Sep 2020 15:11:16 +0200 Subject: [PATCH] add chart of version support to version.rst --- .gitlab-ci.yml | 2 +- SUPPORT_POLICY.md | 2 +- docs/chart.png | Bin 63342 -> 0 bytes docs/conf_common.py | 1 + docs/en/versions.rst | 44 ++++++- docs/generate_chart.py | 216 +++++++++++++++++++++++++++++++++ docs/requirements.txt | 5 + generate_chart.py | 265 ----------------------------------------- idf_versions.js | 96 --------------- 9 files changed, 267 insertions(+), 364 deletions(-) delete mode 100644 docs/chart.png create mode 100644 docs/generate_chart.py delete mode 100644 generate_chart.py delete mode 100644 idf_versions.js diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7fbceeb1fa..4c74067585 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -46,7 +46,7 @@ variables: CI_TARGET_TEST_CONFIG_FILE: "$CI_PROJECT_DIR/tools/ci/config/target-test.yml" # Versioned esp-idf-doc env image to use for all document building jobs - ESP_IDF_DOC_ENV_IMAGE: "$CI_DOCKER_REGISTRY/esp-idf-doc-env:v5" + ESP_IDF_DOC_ENV_IMAGE: "$CI_DOCKER_REGISTRY/esp-idf-doc-env:v6" # before each job, we need to check if this job is filtered by bot stage/job filter diff --git a/SUPPORT_POLICY.md b/SUPPORT_POLICY.md index eed44025da..ec8a68e29e 100644 --- a/SUPPORT_POLICY.md +++ b/SUPPORT_POLICY.md @@ -25,7 +25,7 @@ reserved for features which are needed to meet particular regulatory requirements or standards for new products, and which carry a very low risk of introducing regressions.) -During the Maintenace period, the version is still supported but only bugfixes +During the Maintenance period, the version is still supported but only bugfixes for high severity issues or security issues will be applied. Using an “In Service” version is recommended when starting a new project. diff --git a/docs/chart.png b/docs/chart.png deleted file mode 100644 index 25475313af7cd1cec59038271c5fa82e67d9f3d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63342 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 F{{f=4#b*Ej diff --git a/docs/conf_common.py b/docs/conf_common.py index dd4cc9ee20..61024719ef 100644 --- a/docs/conf_common.py +++ b/docs/conf_common.py @@ -54,6 +54,7 @@ extensions = ['breathe', 'sphinxcontrib.nwdiag', 'sphinxcontrib.rackdiag', 'sphinxcontrib.packetdiag', + 'sphinxcontrib.cairosvgconverter', 'extensions.html_redirects', 'extensions.toctree_filter', diff --git a/docs/en/versions.rst b/docs/en/versions.rst index 6abec3dabf..b2b6730050 100644 --- a/docs/en/versions.rst +++ b/docs/en/versions.rst @@ -70,7 +70,49 @@ As a general guideline: - If possible, periodically update the project to a new major or minor ESP-IDF version (for example, once a year.) The update process should be straightforward for Minor updates, but may require some planning and checking of the release notes for Major updates. - Always plan to update to a newer release before the release you are using becomes End of Life. -.. image:: ../chart.png +Each ESP-IDF major and minor release (V4.1, V4.2, etc) is supported for +30 months after the initial stable release date. + +Supported means that the ESP-IDF team will continue to apply bug fixes, +security fixes, etc to the release branch on GitHub, and periodically +make new bugfix releases as needed. + +Support period is divided into "Service" and "Maintenance" period: + ++-------------+--------------+---------------------------------------+ +| Period | Duration | Recommended for new projects? | ++=============+==============+=======================================+ +| Service | 12 months | Yes | ++-------------+--------------+---------------------------------------+ +| Maintenance | 18 months | No | ++-------------+--------------+---------------------------------------+ + +During the Service period, bugfixes releases are more frequent. In some cases, +support for new features may be added during the Service period (this is +reserved for features which are needed to meet particular regulatory +requirements or standards for new products, and which carry a very low risk of +introducing regressions.) + +During the Maintenance period, the version is still supported but only bugfixes +for high severity issues or security issues will be applied. + +Using an “In Service” version is recommended when starting a new project. + +Users are encouraged to upgrade all projects to a newer ESP-IDF release before +the support period finishes and the release becomes End of Life (EOL). It is our +policy to not continue fixing bugs in End of Life releases. + +Pre-release versions (betas, previews, `-rc` and `-dev` versions, etc) +are not covered by any support period. Sometimes a particular feature is +marked as "Preview" in a release, which means it is also not covered +by the support period. + +The ESP-IDF Programming Guide has information about the +`different versions of ESP-IDF `_ +(major, minor, bugfix, etc). + + +.. image:: https://dl.espressif.com/dl/esp-idf/support-periods.svg Checking the Current Version diff --git a/docs/generate_chart.py b/docs/generate_chart.py new file mode 100644 index 0000000000..6d855b53cd --- /dev/null +++ b/docs/generate_chart.py @@ -0,0 +1,216 @@ +#!/usr/bin/env python + +# Copyright 2020 Espressif Systems (Shanghai) PTE LTD +# +# 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. +# +import argparse +import datetime as dt +import json + +import numpy as np +import requests +import matplotlib.dates +import matplotlib.patches as mpatches +import matplotlib.pyplot as plt +from matplotlib.dates import MONTHLY, DateFormatter, RRuleLocator, rrulewrapper +from dateutil import parser +from dateutil.relativedelta import relativedelta + + +class Version(object): + def __init__(self, version_name, explicit_start_date, explicit_end_date, explicit_end_service_date=None): + self.version_name = version_name + + self._start_date = parser.parse(explicit_start_date) + self._end_of_life_date = parser.parse(explicit_end_date) + self._end_service_date = parser.parse( + explicit_end_service_date) if explicit_end_service_date is not None else self.compute_end_service_date() + + self.start_date_matplotlib_format = matplotlib.dates.date2num(self._start_date) + self.end_of_life_date_matplotlib_format = matplotlib.dates.date2num(self._end_of_life_date) + + self.end_service_date_matplotlib_format = matplotlib.dates.date2num(self._end_service_date) + + @staticmethod + def add_months(source_date, months): + return source_date + relativedelta(months=+months) + + def get_start_date(self): + return self._start_date + + def get_end_of_life_date(self): + return self._end_of_life_date + + def get_end_service_date(self): + return self._end_service_date + + def compute_end_service_date(self): + return self.add_months(self._start_date, 12) + + +class ChartVersions(object): + def __init__(self, url=None, filename=None): + self._releases = self._get_releases_from_url(url=url, filename=filename) + self.sorted_releases_supported = sorted(self.filter_old_versions(self._releases), key=lambda x: x.version_name, + reverse=True) + + def get_releases_as_json(self): + return { + x.version_name: { + "start_date": x.get_start_date().strftime("%Y-%m-%d"), + "end_service": x.get_end_service_date().strftime("%Y-%m-%d"), + "end_date": x.get_end_of_life_date().strftime("%Y-%m-%d") + } for x in self.sorted_releases_supported + } + + @staticmethod + def parse_chart_releases_from_js(js_as_string): + return json.loads(js_as_string[js_as_string.find("RELEASES: ") + len("RELEASES: "):js_as_string.rfind("};")]) + + def _get_all_version_from_url(self, url=None, filename=None): + releases_file = requests.get(url).text if url is not None else "".join(open(filename).readlines()) + return self.parse_chart_releases_from_js(releases_file) + + def _get_releases_from_url(self, url=None, filename=None): + all_versions = self._get_all_version_from_url(url, filename) + return [ + Version(version_name=x, + explicit_start_date=all_versions[x]['start_date'], + explicit_end_date=all_versions[x]['end_date'] if 'end_date' in all_versions[x].keys() else None, + explicit_end_service_date=all_versions[x]['end_service'] if 'end_service' in all_versions[ + x].keys() else None) + for x in all_versions.keys() + ] + + @staticmethod + def filter_old_versions(versions): + return list( + filter(lambda x: x.get_end_of_life_date() >= dt.datetime.now(x.get_end_of_life_date().tzinfo), versions)) + + @staticmethod + def months_timedelta(datetime_1, datetime2): + datetime_1, datetime2 = (datetime2, datetime_1) if datetime_1 > datetime2 else (datetime_1, datetime2) + return (datetime2.year * 12 + datetime2.month) - (datetime_1.year * 12 + datetime_1.month) + + @staticmethod + def find_next_multiple_of_power_two(number, initial=3): + """ + Computes the next multiple of the number by some power of two. + >>> ChartVersions.find_next_multiple_of_power_two(7, 3) + 12 + """ + msb = number.bit_length() + return 3 if number <= 1 else initial << msb - 2 << (1 & number >> msb - 2) + + def find_nearest_multiple_of_power_two(self, number, initial=3, prefer_next=False): + next_num = self.find_next_multiple_of_power_two(number=number - 1, initial=initial) + previous_num = next_num >> 1 + return next_num if abs(next_num - number) < (abs(previous_num - number) + int(prefer_next)) else previous_num + + def create_chart(self, + figure_size=(41.8330013267, 16.7332005307), + subplot=111, + step_size=0.5, + bar_height=0.3, + version_alpha=0.8, + lts_service_color='darkred', + lts_maintenance_color='red', + bar_align='center', + date_interval=None, + output_chart_name='docs/chart', + output_chart_extension='.png', + months_surrounding_chart=4, + service_period_label='Service period (Recommended for new designs)', + maintenance_period_text='Maintenance period'): + fig = plt.figure(figsize=figure_size) + ax = fig.add_subplot(subplot) + + labels_count = len(self.sorted_releases_supported) + + pos = np.arange(step_size, labels_count * step_size + step_size, step_size) + + for release, i in zip(self.sorted_releases_supported, range(labels_count)): + start_date = release.start_date_matplotlib_format + end_of_service_date = release.end_service_date_matplotlib_format + + end_date = release.end_of_life_date_matplotlib_format + + ax.barh((i * step_size) + step_size, (end_of_service_date or end_date) - start_date, left=start_date, + height=bar_height, align=bar_align, + color=lts_service_color, + alpha=version_alpha, + edgecolor=lts_service_color) + if end_of_service_date is not None: + ax.barh((i * step_size) + step_size, end_date - end_of_service_date, left=end_of_service_date, + height=bar_height, align=bar_align, + color=lts_maintenance_color, alpha=version_alpha, edgecolor=lts_maintenance_color) + + ax.set_ylim(bottom=0, ymax=labels_count * step_size + step_size) + + max_ax_date = Version.add_months( + max(self.sorted_releases_supported, + key=lambda version: version.get_end_of_life_date().replace(tzinfo=None)).get_end_of_life_date(), + months_surrounding_chart + 1).replace(day=1) + + min_ax_date = Version.add_months( + min(self.sorted_releases_supported, + key=lambda version: version.get_start_date().replace(tzinfo=None)).get_start_date(), + -months_surrounding_chart).replace(day=1) + + x_ax_interval = date_interval or self.find_nearest_multiple_of_power_two( + self.months_timedelta(max_ax_date, min_ax_date) // 10) + + ax.set_xlim(xmin=min_ax_date, xmax=max_ax_date) + + ax.grid(color='g', linestyle=':') + ax.xaxis_date() + + rule = rrulewrapper(MONTHLY, interval=x_ax_interval) + loc = RRuleLocator(rule) + formatter = DateFormatter("%b %Y") + + ax.xaxis.set_major_locator(loc) + ax.xaxis.set_major_formatter(formatter) + x_labels = ax.get_xticklabels() + plt.ylabel('ESP-IDF Release', size=12) + + ax.invert_yaxis() + fig.autofmt_xdate() + + darkred_patch = mpatches.Patch(color=lts_service_color, label=service_period_label) + red_patch = mpatches.Patch(color=lts_maintenance_color, label=maintenance_period_text) + + plt.setp(plt.yticks(pos, map(lambda x: x.version_name, self.sorted_releases_supported))[1], rotation=0, + fontsize=10, family='Tahoma') + plt.setp(x_labels, rotation=30, fontsize=11, family='Tahoma') + plt.legend(handles=[darkred_patch, red_patch], prop={'size': 10, 'family': 'Tahoma'}, + bbox_to_anchor=(1.01, 1.165), loc='upper right') + fig.set_size_inches(11, 5, forward=True) + plt.savefig(output_chart_name + output_chart_extension, bbox_inches='tight') + print("Saved into " + output_chart_name + output_chart_extension) + + +if __name__ == '__main__': + arg_parser = argparse.ArgumentParser( + description="Create chart of version support. Set the url or filename with versions." + "If you set both filename and url the script will prefer filename.") + arg_parser.add_argument("--url", metavar="URL", default="https://dl.espressif.com/dl/esp-idf/idf_versions.js") + arg_parser.add_argument("--filename", + help="Set the name of the source file, if is set, the script ignores the url.") + arg_parser.add_argument("--output-format", help="Set the output format of the image.", default="svg") + arg_parser.add_argument("--output-file", help="Set the name of the output file.", default="docs/chart") + args = arg_parser.parse_args() + + ChartVersions(url=args.url if args.filename is None else None, filename=args.filename).create_chart( + output_chart_extension="." + args.output_format.lower()[-3:], output_chart_name=args.output_file) diff --git a/docs/requirements.txt b/docs/requirements.txt index 5b0b97b4c0..1a331e7c98 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,6 +1,10 @@ # This is a list of python packages used to generate documentation. This file is used with pip: # pip install --user -r requirements.txt # +# matplotlib is currently required only by the script generate_chart.py +matplotlib==3.3.1 ; python_version>="3" +matplotlib==2.0.1 ; python_version=="2.7" +cairosvg==2.4.2 # required by sphinxcontrib-svg2pdfconverter[CairoSVG] sphinx==2.3.1 breathe==4.14.1 sphinx-copybutton==0.3.0 @@ -10,6 +14,7 @@ sphinxcontrib-seqdiag==2.0.0 sphinxcontrib-actdiag==2.0.0 sphinxcontrib-nwdiag==2.0.0 sphinxcontrib-wavedrom==2.0.0 +sphinxcontrib-svg2pdfconverter[CairoSVG]==1.1.0 nwdiag==2.0.0 recommonmark future>=0.16.0 # for ../tools/gen_esp_err_to_name.py diff --git a/generate_chart.py b/generate_chart.py deleted file mode 100644 index d1f61743dc..0000000000 --- a/generate_chart.py +++ /dev/null @@ -1,265 +0,0 @@ -#!/usr/bin/env python -import datetime as dt -import requests -import json -import os -import re - -import matplotlib.dates -import matplotlib.font_manager as font_manager -import matplotlib.patches as mpatches -import matplotlib.pyplot as plt -import numpy as np -from dateutil import parser -from dateutil.relativedelta import relativedelta -from matplotlib.dates import WEEKLY, DateFormatter, RRuleLocator, rrulewrapper - - -class Version(object): - def __init__(self, version_name, - explicit_start_date=None, - explicit_end_date=None, - explicit_end_service_date=None, - is_lts=None): - self.version_name = version_name - - self.is_lts = is_lts or self.is_version_lts() - - self.is_major_minor = Version.is_minor_major_version(self.version_name) - - self._start_date = parser.parse( - explicit_start_date) if explicit_start_date is not None else self._retrieve_start_date() - self._end_of_life_date = parser.parse( - explicit_end_date) if explicit_end_date is not None else self._retrieve_end_of_life_date() - self._end_service_date = parser.parse( - explicit_end_service_date) if explicit_end_service_date is not None else self.get_end_service_date() - - self.start_date_matplotlib_format = matplotlib.dates.date2num(self._start_date) - self.end_of_life_date_matplotlib_format = matplotlib.dates.date2num(self._end_of_life_date) - - self.end_service_date_matplotlib_format = matplotlib.dates.date2num( - self._end_service_date) if self._end_service_date is not None else None - - @staticmethod - def get_config(config_path): - return json.load(open(config_path)) - - @staticmethod - def add_months(source_date, months): - return source_date + relativedelta(months=+months) - - @staticmethod - def is_minor_major_version(version_name): - return True if len(version_name.split(".")) <= 2 else False - - def is_version_lts(self): - version = self.version_name - return version >= 'v4.1' - - def get_start_date(self): - return self._start_date - - def get_end_of_life_date(self): - return self._end_of_life_date - - def _retrieve_start_date(self): - return parser.parse(os.popen("git log -1 --format=%ai " + self.version_name)) - - def _retrieve_end_of_life_date(self): - return self.add_months(self._start_date, 30 if self.is_lts else 18) - - def get_end_service_date(self): - return self.add_months(self._start_date, 12) - - -class ChartVersions(object): - def __init__(self): - self.all_versions = self.get_all_versions_from_git() - - self._releases = self._get_releases_from_url(url="https://dl.espressif.com/dl/esp-idf/idf_versions.js") - self._patches = self._get_patches_from_url(url="https://dl.espressif.com/dl/esp-idf/idf_versions.js") - - self.sorted_releases_supported = sorted(self.filter_old_versions(self._releases), key=lambda x: x.version_name) - self.patches_supported = self.filter_old_versions(self._patches) - - # TODO test higher versions - # self.sorted_releases_supported.append(Version(version_name='v4.1', explicit_start_date="28-9-2020")) - # self.sorted_releases_supported.append(Version(version_name='v4.2', explicit_start_date="28-5-2021")) - - def get_releases_as_json(self): - return { - x.version_name: { - "start_date": x.get_start_date().strftime("%Y-%m-%d"), - "end_date": x.get_end_of_life_date().strftime("%Y-%m-%d"), - "is_lts": x.is_lts - } for x in self.sorted_releases_supported + self.patches_supported - } - - @staticmethod - def parse_chart_releases_from_js(js_as_string): - return json.loads(js_as_string[js_as_string.find("RELEASES: ") + len("RELEASES: "):js_as_string.rfind("};")]) - - def _get_all_version_from_url(self, url=None, filename=None): - releases_file = requests.get(url).text if url is not None else "".join(open(filename).readlines()) - return self.parse_chart_releases_from_js(releases_file) - - def _get_releases_from_url(self, url=None, filename=None): - all_versions = self._get_all_version_from_url(url, filename) - return [ - Version(version_name=x, - explicit_start_date=all_versions[x]['start_date'], - explicit_end_date=all_versions[x]['end_date'] if 'end_date' in all_versions[x].keys() else None, - explicit_end_service_date=all_versions[x]['end_service'] if 'end_service' in all_versions[x].keys() else None) - for x in all_versions.keys() if Version.is_minor_major_version(x) - ] - - def _get_patches_from_url(self, url=None, filename=None): - all_versions = self._get_all_version_from_url(url, filename) - return [ - Version(version_name=x, - explicit_start_date=all_versions[x]['start_date'], - explicit_end_date=all_versions[x]['end_date'] if 'end_date' in all_versions[x].keys() else None, - is_lts=all_versions[x]['new_policy'] if 'new_policy' in all_versions[x].keys() else None) - for x in all_versions.keys() if not Version.is_minor_major_version(x) - ] - - def _get_releases(self, all_versions): - return [Version(release) for release in self._get_releases_names(all_versions)] - - def _get_patches(self, all_versions): - return [Version(patch, explicit_end_date=self.get_super_end_date_as_string(patch), - is_lts=self.get_super_lts_state(patch)) for patch in self._get_patches_names(all_versions)] - - @staticmethod - def _get_releases_names(all_versions): - return list(filter(lambda x: Version.is_minor_major_version(x), all_versions)) - - @staticmethod - def _get_patches_names(all_versions): - return list(filter(lambda x: not Version.is_minor_major_version(x), all_versions)) - - def get_super_version(self, patch): - return list(filter(lambda x: x.version_name == self.get_super_version_name(patch), self._releases))[0] - - def get_super_end_date_as_string(self, patch): - return self.get_super_version(patch).get_end_of_life_date().strftime("%m/%d/%Y, %H:%M:%S") - - def get_super_lts_state(self, patch): - return self.get_super_version(patch).is_lts - - @staticmethod - def get_all_versions_from_git(): - """ - :returns: list of string variables meaning name of the versions or patches (e.g. v4.1, v3.3.1, etc.) - """ - all_git_tags = os.popen("git tag") - stable_releases_regex = "(?:^|)(v\d+\.\d+(?:\.\d+){0,1})(?=\n|$)" - - results = [re.match(stable_releases_regex, line) for line in all_git_tags] - all_versions = [regex_result.group(1) for regex_result in results if regex_result is not None] - return all_versions - - @staticmethod - def filter_old_versions(versions): - return list( - filter(lambda x: x.get_end_of_life_date() >= dt.datetime.now(x.get_end_of_life_date().tzinfo), versions)) - - @staticmethod - def get_super_version_name(version_name): - return ".".join(version_name.split(".")[:2]) - - def create_chart(self, - figure_size=(20, 8), - subplot=111, - step_size=0.5, - bar_height=0.3, - version_alpha=0.8, - patch_width=1, - lts_service_color='darkred', - lts_maintenance_color='red', - bar_align='center', - patch_color='black', - patch_alpha=1, - date_interval=10, - output_chart_name='docs/chart', - output_chart_extension='.png', - months_surrounding_chart=5): - fig = plt.figure(figsize=figure_size) - ax = fig.add_subplot(subplot) - - labels_count = len(self.sorted_releases_supported) - - pos = np.arange(step_size, labels_count * step_size + step_size, step_size) - mapping_releases_index = {release.version_name: i for release, i in - zip(self.sorted_releases_supported, range(labels_count))} - - for release, i in zip(self.sorted_releases_supported, range(labels_count)): - start_date = release.start_date_matplotlib_format - end_of_service_date = release.end_service_date_matplotlib_format - - end_date = release.end_of_life_date_matplotlib_format - - ax.barh((i * step_size) + step_size, (end_of_service_date or end_date) - start_date, left=start_date, - height=bar_height, align=bar_align, - color=lts_service_color, - alpha=version_alpha, - edgecolor=lts_service_color) - if end_of_service_date is not None: - ax.barh((i * step_size) + step_size, end_date - end_of_service_date, left=end_of_service_date, - height=bar_height, align=bar_align, - color=lts_maintenance_color, alpha=version_alpha, edgecolor=lts_maintenance_color) - - for patch, i in zip(self.patches_supported, range(len(self.patches_supported))): - start_date = patch.start_date_matplotlib_format - - ax.barh(mapping_releases_index[self.get_super_version_name(patch.version_name)] * step_size + step_size, - patch_width, left=start_date, height=bar_height, align=bar_align, color=patch_color, - alpha=patch_alpha, - edgecolor=patch_color) - ax.text(start_date - 5, mapping_releases_index[ - self.get_super_version_name(patch.version_name)] * step_size + step_size - 0.2, - patch.version_name.split('.')[-1], - fontsize='xx-small', color='darkred') - - plt.setp(plt.yticks(pos, map(lambda x: x.version_name, self.sorted_releases_supported))[1], fontsize=14) - - ax.set_ylim(bottom=0, ymax=labels_count * step_size + step_size) - - ax.set_xlim( - xmin=Version.add_months( - min(self.sorted_releases_supported, - key=lambda version: version.get_start_date().replace(tzinfo=None)).get_start_date(), - -months_surrounding_chart), - xmax=Version.add_months( - max(self.sorted_releases_supported, - key=lambda version: version.get_end_of_life_date().replace(tzinfo=None)).get_end_of_life_date(), - months_surrounding_chart)) - - ax.grid(color='g', linestyle=':') - ax.xaxis_date() - - rule = rrulewrapper(WEEKLY, interval=date_interval) - loc = RRuleLocator(rule) - formatter = DateFormatter("%d-%b '%y") - - ax.xaxis.set_major_locator(loc) - ax.xaxis.set_major_formatter(formatter) - x_labels = ax.get_xticklabels() - plt.setp(x_labels, rotation=30, fontsize=10) - - ax.legend(loc=1, prop=font_manager.FontProperties(size='small')) - - ax.invert_yaxis() - fig.autofmt_xdate() - - darkred_patch = mpatches.Patch(color='darkred', label='Service period (Recommended for new designs)') - red_patch = mpatches.Patch(color='red', label='Maintenance period') - - plt.legend(handles=[darkred_patch, red_patch], prop={'size': 6}) - fig.set_size_inches(10, 5, forward=True) - plt.savefig(output_chart_name + output_chart_extension) - plt.show() - - -if __name__ == '__main__': - ChartVersions().create_chart() diff --git a/idf_versions.js b/idf_versions.js deleted file mode 100644 index d36ec3182c..0000000000 --- a/idf_versions.js +++ /dev/null @@ -1,96 +0,0 @@ -var DOCUMENTATION_VERSIONS = { - DEFAULTS: { - has_targets: false, - supported_targets: ["esp32"] - }, - VERSIONS: [{ - name: "latest", - has_targets: true, - supported_targets: ["esp32", "esp32s2"] - }, - { - name: "v4.1-rc", - pre_release: true - }, - { - name: "v4.0.1", - old: false - }, - { - name: "v4.0", - old: true - }, - { - name: "v3.3.2" - }, - { - name: "v3.3.1", - old: true - }, - { - name: "v3.3", - old: true - }, - { - name: "v3.2.3", - old: false - }, - { - name: "v3.1.7", - old: false - }, - { - name: "v3.1.6", - old: true - }, - { - name: "v3.0.9", - old: true - }, - { - name: "release-v4.2", - pre_release: true, - has_targets: true, - supported_targets: ["esp32", "esp32s2"] - }, - { - name: "release-v4.1", - pre_release: true - }, - { - name: "release-v4.0", - pre_release: true - }, - { - name: "release-v3.3", - pre_release: true - }, - { - name: "release-v3.2", - pre_release: true - }, - { - name: "release-v3.1", - pre_release: true - } - ], - RELEASES: { - "v3.1": { - "start_date": "2018-09-07", - "end_date": "2020-10-31" - }, - "v3.2": { - "start_date": "2019-04-11", - "end_date": "2020-10-31" - }, - "v3.3": { - "start_date": "2019-09-05", - "end_date": "2022-03-31" - }, - "v4.0": { - "start_date": "2020-02-11", - "end_service": "2021-02-11", - "end_date": "2021-10-31" - } - } -};