mirror of
https://github.com/lvgl/lvgl.git
synced 2026-02-06 22:22:24 +08:00
Some checks failed
Arduino Lint / lint (push) Has been cancelled
Build Examples with C++ Compiler / build-examples (push) Has been cancelled
MicroPython CI / Build esp32 port (push) Has been cancelled
MicroPython CI / Build rp2 port (push) Has been cancelled
MicroPython CI / Build stm32 port (push) Has been cancelled
MicroPython CI / Build unix port (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_NORMAL_8BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_SDL - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build ESP IDF ESP32S3 (push) Has been cancelled
C/C++ CI / Run tests with 32bit build (push) Has been cancelled
C/C++ CI / Run tests with 64bit build (push) Has been cancelled
BOM Check / bom-check (push) Has been cancelled
Verify that lv_conf_internal.h matches repository state / verify-conf-internal (push) Has been cancelled
Verify the widget property name / verify-property-name (push) Has been cancelled
Verify code formatting / verify-formatting (push) Has been cancelled
Compare file templates with file names / template-check (push) Has been cancelled
Build docs / build-and-deploy (push) Has been cancelled
Test API JSON generator / Test API JSON (push) Has been cancelled
Install LVGL using CMake / build-examples (push) Has been cancelled
Check Makefile / Build using Makefile (push) Has been cancelled
Check Makefile for UEFI / Build using Makefile for UEFI (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/benchmark_results_comment/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/filter_docker_logs/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/serialize_results/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 32b - lv_conf_perf32b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 64b - lv_conf_perf64b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Save PR Number (push) Has been cancelled
Hardware Performance Test / Hardware Performance Benchmark (push) Has been cancelled
Hardware Performance Test / HW Benchmark - Save PR Number (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_32B - Ubuntu (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_64B - Ubuntu (push) Has been cancelled
Port repo release update / run-release-branch-updater (push) Has been cancelled
Verify Font License / verify-font-license (push) Has been cancelled
Verify Kconfig / verify-kconfig (push) Has been cancelled
562 lines
19 KiB
Python
Executable File
562 lines
19 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
""" example_list.py -- Build `examples.rst`
|
|
|
|
`examples.rst` is built by gathering all examples recursively under
|
|
`lvgl/examples/`. The recognized directives in that file are then
|
|
processed by Sphinx using `lvgl/docs/src/_ext/lv_example.py`.
|
|
|
|
Subsection names within `examples.rst` are made up of the capitalized
|
|
directory names ('_' and '-' characters are converted to spaces) or
|
|
are spelled out in `index.rst` files if the subsection names should be
|
|
spelled differently. See "index.rst Format" section below for details.
|
|
|
|
An "example" is defined as:
|
|
|
|
- being anywhere under the `lvgl/examples/` directory,
|
|
- the presence of an `index.rst` in a directory with examples, and
|
|
- example C code in file names typically starting with "lv_example_".
|
|
|
|
That C code and a live, interactive running example, is pulled into each
|
|
example in the EXAMPLES HTML page, as well as every doc where such
|
|
examples are included, by a directive like this:
|
|
|
|
.. code::
|
|
|
|
.. include:: /examples/layouts/flex/index.rst
|
|
|
|
Note that in the intermediate dir (from which LVGL user docs are generated),
|
|
``./examples/`` is a top-level subdirectory, so no relative "../../.." etc.
|
|
is required in the path. Using a path starting at "root" tells Sphinx to
|
|
start at the top-level directory where the docs are being generated,
|
|
typically ``lvgl/docs/intermediate/``.
|
|
|
|
See `build.py` for more information about the intermediate directory.
|
|
|
|
If a subdirectory is included in the `avoid_dirs` list herein, it will
|
|
not generate any output in the resulting `examples.rst` file.
|
|
Example: `lvgl/examples/assets/`.
|
|
|
|
|
|
Usage
|
|
*****
|
|
|
|
.. code::
|
|
|
|
import example_list
|
|
example_list.make_warnings_into_errors() # Optional
|
|
example_list.DEBUG_MODE = True # Optional
|
|
example_list.exec(intermediate_dir)
|
|
|
|
or run it directly:
|
|
|
|
.. code:: bash
|
|
|
|
python3 example_list.py "/home/lvgl/docs/intermediate"
|
|
|
|
In both cases, the `intermediate_dir` passed is expected to have
|
|
an `./examples/` directory in it (copy of `lvgl/examples/`) as a
|
|
top-level subdirectory.
|
|
|
|
|
|
Examples Directory Requirements
|
|
*******************************
|
|
|
|
.. code:: text
|
|
|
|
lvgl/examples/
|
|
index.rst (.. dir_order: pseudo-directive since sub-dirs
|
|
are not presented in alphabetical order)
|
|
anim/
|
|
index.rst (see below for expected contents)
|
|
lv_example_anim_1.c
|
|
lv_example_anim_2.c
|
|
lv_example_anim_3.c
|
|
lv_example_anim_4.c
|
|
lv_example_anim_timeline_1.c
|
|
...
|
|
layouts/
|
|
flex/
|
|
index.rst (see below for expected contents)
|
|
lv_example_flex_1.c
|
|
lv_example_flex_2.c
|
|
lv_example_flex_3.c
|
|
etc.
|
|
grid/
|
|
etc.
|
|
libs/
|
|
index.rst (section-heading name: "3rd-Party Libraries"
|
|
[since it is different than parent directory name])
|
|
barcode/
|
|
index.rst (see below for expected contents)
|
|
lv_example_barcode_1.c
|
|
lv_example_barcode_1.h
|
|
bmp/
|
|
etc.
|
|
etc.
|
|
etc.
|
|
|
|
.. note:: The above shows only 2 levels of directories but deeper
|
|
levels are supported (up to 5 below document title).
|
|
|
|
|
|
index.rst Format
|
|
****************
|
|
|
|
Examples
|
|
--------
|
|
Examples are included in `index.rst` files when they are sibling files with
|
|
the example C code.
|
|
|
|
.. code::
|
|
|
|
Example 1 Title <-- required for each example
|
|
--------------- <-- required for each example
|
|
<-- blank lines are ignored
|
|
.. lv_example:: anim/lv_example_anim_1 <-- path relative to the `lvgl/examples/` dir
|
|
:language: c
|
|
|
|
Repeat the above pattern for each example in the current directory. That number
|
|
may be zero (0) for directories like `libs/` in which all examples are in directories
|
|
below that level. See directory structure above.
|
|
|
|
For paths outside the current directory, simply provide the path to the code example
|
|
relative to the `lvgl/examples/` directory. Example from
|
|
`lvgl/examples/widgets/scale/index.rst`:
|
|
|
|
.. code::
|
|
|
|
...
|
|
|
|
A round scale style simulating a compass
|
|
----------------------------------------
|
|
|
|
.. lv_example:: widgets/scale/lv_example_scale_12
|
|
:language: c
|
|
|
|
Axis ticks and labels with scrolling on a chart
|
|
-----------------------------------------------
|
|
|
|
.. lv_example:: widgets/chart/lv_example_chart_2 <-- path is outside scale/ dir
|
|
:language: c
|
|
|
|
.. note::
|
|
|
|
Starting the example code filename with `lv_example_` is not a requirement of the
|
|
this script, but does make it clear that it is an example, so this pattern should
|
|
be preserved for new and changed examples.
|
|
|
|
|
|
Custom Section Headings
|
|
-----------------------
|
|
If a section heading needs to be spelled differently than the capitalized name of the
|
|
parent directory, then an `index.rst` file in that directory may contain the desired
|
|
section-heading name in an ``.. example_heading`` pseudo-directive. Example from
|
|
`lvgl/examples/libs/index.rst`:
|
|
|
|
.. code::
|
|
|
|
.. example_heading: 3rd-Party Libraries
|
|
|
|
|
|
Directory Reordering
|
|
--------------------
|
|
There are cases where it is not appropriate to present the contents of a
|
|
set of subdirectories in alphabetical order. When this is the case, a
|
|
pseudo-directive in the `index.rst` file in the parent directory can be specified
|
|
to govern the sequence its subdirectories are processed. The example below
|
|
is from `lvgl/examples/widgets/index.rst`. It is provided in order to
|
|
cause the "Base Widget" (obj) directory to be processed first (and thus
|
|
included in the output first).
|
|
|
|
.. code::
|
|
|
|
.. dir_order:
|
|
|
|
obj
|
|
animimg
|
|
arc
|
|
arclabel
|
|
bar
|
|
button
|
|
buttonmatrix
|
|
etc.
|
|
|
|
.. note::
|
|
|
|
A warning is issued if either:
|
|
|
|
- a subdirectory is named that does not exist, or
|
|
- a subdirectory exists that is not in the list and not in the `avoid_dirs` list.
|
|
|
|
|
|
Making Warnings into Errors
|
|
***************************
|
|
|
|
If `make_warnings_into_errors()` was called, if there were any warnings
|
|
issued, after the output is completely generated, this script will exit
|
|
with a non-zero exit code. This can be done by client modules like this:
|
|
|
|
.. code::
|
|
|
|
import example_list
|
|
example_list.make_warnings_into_errors()
|
|
example_list.exec(intermediate_dir)
|
|
|
|
To turn it off:
|
|
|
|
.. code::
|
|
|
|
example_list.make_warnings_into_errors(False)
|
|
|
|
|
|
Debug Output
|
|
************
|
|
|
|
Enable debug output like this:
|
|
|
|
.. code::
|
|
|
|
example_list.DEBUG_MODE = True
|
|
|
|
Suppressing DEBUG_MODE is the default.
|
|
|
|
|
|
"""
|
|
import os
|
|
import sys
|
|
from io import TextIOWrapper
|
|
from announce import *
|
|
|
|
# -------------------------------------------------------------------------
|
|
# This is the order that LVGL documentation uses for the section heading
|
|
# levels. header_defs[0] is the highest and header_defs[5] is the lowest.
|
|
# If this order is not kept in the reST files Sphinx will complain, and
|
|
# have difficulty formatting the TOC correctly.
|
|
# -------------------------------------------------------------------------
|
|
TITLE = '='
|
|
CHAPTER = '*'
|
|
SECTION = '-'
|
|
SUBSECTION = '~'
|
|
SUBSUBSECTION = '^'
|
|
SUBSUBSUBSECTION = "'"
|
|
|
|
header_defs = [
|
|
TITLE,
|
|
CHAPTER,
|
|
SECTION,
|
|
SUBSECTION,
|
|
SUBSUBSECTION,
|
|
SUBSUBSUBSECTION,
|
|
]
|
|
|
|
LV_EXAMPLE_DIRECTIVE = '.. lv_example::'
|
|
EXAMPLE_HEADING_DIRECTIVE = '.. example_heading:'
|
|
DIR_ORDER_DIRECTIVE = '.. dir_order:'
|
|
DIR_SEP = os.sep
|
|
INDEX_FILENAME = 'index.rst'
|
|
MAKE_WARNINGS_INTO_ERRORS = False
|
|
DEBUG_MODE = False
|
|
THIS_FILE = os.path.basename(__file__)
|
|
_warning_issued = False
|
|
_top_level_heading_count = 0
|
|
|
|
avoid_dirs = [
|
|
os.path.join('examples', 'arduino'),
|
|
os.path.join('examples', 'assets'),
|
|
]
|
|
|
|
|
|
def make_warnings_into_errors(val: bool = True):
|
|
global MAKE_WARNINGS_INTO_ERRORS
|
|
MAKE_WARNINGS_INTO_ERRORS = val
|
|
|
|
|
|
def _default_section_heading(level: int, path: str, is_file: bool) -> str:
|
|
if is_file:
|
|
dir_path = os.path.dirname(path)
|
|
else:
|
|
dir_path = path
|
|
|
|
parent_dir = os.path.basename(dir_path)
|
|
|
|
# Compose default section heading based on capitalized words in `parent_dir`.
|
|
word_list = parent_dir.replace('_', ' ').replace('-', ' ').split(' ')
|
|
result = ''
|
|
|
|
for word in word_list:
|
|
result += ' ' + word.capitalize()
|
|
|
|
# Remove leading space.
|
|
if result:
|
|
result = result[1:]
|
|
|
|
return result
|
|
|
|
|
|
def _warn(msg: str):
|
|
global _warning_issued
|
|
if MAKE_WARNINGS_INTO_ERRORS:
|
|
warning_type = 'Error'
|
|
else:
|
|
warning_type = 'Warning'
|
|
|
|
if is_silent_mode():
|
|
print(f'{THIS_FILE}: ' + '\x1b[31m' + f'>>> {warning_type}: ' + msg + '\x1b[0m')
|
|
else:
|
|
announce_colored(THIS_FILE, 'red', f'>>> {warning_type}: ' + msg)
|
|
|
|
_warning_issued = True
|
|
|
|
|
|
def _in_avoid_dirs_list(dir_bep: str) -> bool:
|
|
result = False
|
|
|
|
for avoid_dir in avoid_dirs:
|
|
if avoid_dir in dir_bep:
|
|
result = True
|
|
break
|
|
|
|
return result
|
|
|
|
|
|
def _validate_sub_dirs(sub_dirs: list[str], index_rst_path: str) -> bool:
|
|
""" Validate sub-dirs that come from an `index.rst` `.. dir_order:` directive.
|
|
|
|
1. Check that that each one is an existing directory.
|
|
2. Check that there are none missing except those in `avoid_dirs`.
|
|
|
|
Issue warning if either fails and set `_warning_issued`.
|
|
If MAKE_WARNINGS_INTO_ERRORS, this will make script exit with an error
|
|
code at the end.
|
|
|
|
:param sub_dirs: List of sub-dirs to validate
|
|
:param index_rst_path: Path to index.rst file
|
|
:return: Whether `sub_dirs` is valid per 1 and 2 above
|
|
"""
|
|
result = True
|
|
|
|
# Check that each sub-dir is an existing directory.
|
|
for sub_dir in sub_dirs:
|
|
if not os.path.isdir(sub_dir):
|
|
result = False
|
|
_warn(f'Dir-order directive in {index_rst_path} contains dir [{sub_dir}] that does not exist.')
|
|
# We won't break here so that all such dirs can be listed.
|
|
|
|
# Check that there are none missing except those in `avoid_dirs`.
|
|
dir_path = os.path.dirname(index_rst_path)
|
|
actual_dirs = []
|
|
|
|
for dir_item in os.listdir(dir_path):
|
|
path_bep = os.path.join(dir_path, dir_item)
|
|
if os.path.isdir(path_bep):
|
|
actual_dirs.append(path_bep)
|
|
|
|
# Are there any missing that are not in `avoid_dirs` list?
|
|
# If so, issue warning about each directory missing.
|
|
for sub_dir in actual_dirs:
|
|
if sub_dir not in sub_dirs:
|
|
if not _in_avoid_dirs_list(sub_dir):
|
|
_warn(f'Dir-order directive in {index_rst_path} is missing dir [{sub_dir}].')
|
|
result = False
|
|
|
|
return result
|
|
|
|
|
|
def _emit_heading(level: int, hdg: str, f: TextIOWrapper):
|
|
"""
|
|
Emit reST heading using `header_defs`.
|
|
|
|
:param level: Directory depth below the top directory in tree. [0-5]
|
|
:param hdg: Heading text
|
|
:param f: Output file (examples.rst)
|
|
:return:
|
|
"""
|
|
assert 0 <= level < len(header_defs), "level out of range"
|
|
global _top_level_heading_count
|
|
underline = header_defs[level] * len(hdg)
|
|
announce(__file__, f'Section heading [{hdg}] at level [{level}].')
|
|
|
|
if level == 0:
|
|
_top_level_heading_count += 1
|
|
if _top_level_heading_count > 1:
|
|
f.write('\n\n\n') # 3 extra lines above (doc) root titles, except 1st
|
|
f.write(underline)
|
|
f.write('\n')
|
|
elif level == 1:
|
|
f.write('\n\n') # 2 extra lines above chapters
|
|
elif level == 2:
|
|
f.write('\n') # 1 extra line above sections
|
|
|
|
f.write(hdg)
|
|
f.write('\n')
|
|
f.write(underline)
|
|
f.write('\n\n')
|
|
|
|
|
|
def _generate_output_from_dir(level: int,
|
|
root_len: int,
|
|
file_or_dir: str,
|
|
is_file: bool,
|
|
orig_dir_list: list[str],
|
|
f: TextIOWrapper) -> list[str]:
|
|
""" Output to `f` based on contents of `file_or_dir`.
|
|
|
|
:param level: Directory depth below the top directory in tree. [0-4]
|
|
:param root_len: Length of root path -- is deleted from paths so that
|
|
paths are relative to the `lvgl/examples/` dir.
|
|
:param file_or_dir: Path to "thing" being processed.
|
|
:param is_file: True if `file_or_dir` is an `index.rst` file.
|
|
:param orig_dir_list: List of sub-dirs below dir being processed.
|
|
Will be returned from this function if a
|
|
dir-order directive is NOT found in index file.
|
|
:param f: Output file (examples.rst)
|
|
:return: `orig_dir_list` or `dir_order_override` if a
|
|
dir-order directive is found in index file.
|
|
"""
|
|
dir_order_override = []
|
|
result_dir_list = orig_dir_list
|
|
|
|
# It is an error to proceed with `level` out of range. Clamping it to be in
|
|
# range is also an error because it would cause the output to be corrupted with
|
|
# an invalid section-heading underscore, which would generate an error later.
|
|
if 0 <= level and level + 1 < len(header_defs):
|
|
section_heading = _default_section_heading(level, file_or_dir, is_file)
|
|
example_tuples = []
|
|
relative_dir = ''
|
|
|
|
if is_file:
|
|
announce(__file__, f'Processing file [{file_or_dir}]...')
|
|
# We are processing an index.rst file.
|
|
with open(file_or_dir, 'r', encoding='utf-8') as fidx:
|
|
# It is important that this is NOT fidx.readlines() because
|
|
# it leaves blank lines containing '\n' instead of ''.
|
|
lines = fidx.read().split('\n')
|
|
|
|
example_title = ''
|
|
prev_line = ''
|
|
dir_path = os.path.dirname(file_or_dir)
|
|
in_dir_order_directive = False
|
|
|
|
# Accumulate data from `index.rst`. This needs to be done
|
|
# first in case it overrides the default section heading.
|
|
for line in lines:
|
|
if in_dir_order_directive:
|
|
leading_non_blank = (len(line) > 0) and not (line[0] == ' ' or line[0] == '\t')
|
|
|
|
if leading_non_blank:
|
|
# Leading non-blank character ends dir-order directive.
|
|
in_dir_order_directive = False
|
|
else:
|
|
# Still in dir-order directive.
|
|
stripped_line = line.strip()
|
|
if stripped_line:
|
|
dir_order_override.append(os.path.join(dir_path, stripped_line))
|
|
continue
|
|
|
|
stripped_line = line.strip()
|
|
|
|
if not stripped_line:
|
|
continue # Skip blank line.
|
|
elif stripped_line.startswith(EXAMPLE_HEADING_DIRECTIVE):
|
|
new_heading = stripped_line.replace(EXAMPLE_HEADING_DIRECTIVE, '').strip()
|
|
announce(__file__, f'Default section heading [{section_heading}] replaced with [{new_heading}]...')
|
|
section_heading = new_heading
|
|
elif stripped_line.startswith('---'):
|
|
example_title = prev_line
|
|
announce(__file__, f'Found example [{example_title}]...')
|
|
elif stripped_line.startswith(LV_EXAMPLE_DIRECTIVE):
|
|
rel_path_from_examples_dir = stripped_line.replace(LV_EXAMPLE_DIRECTIVE, '').strip()
|
|
announce(__file__, f' [{rel_path_from_examples_dir}]')
|
|
example_tuples.append( (example_title, rel_path_from_examples_dir) )
|
|
elif not in_dir_order_directive and stripped_line.startswith(DIR_ORDER_DIRECTIVE):
|
|
in_dir_order_directive = True
|
|
announce(__file__, f'Found DIR-ORDER directive.')
|
|
|
|
prev_line = stripped_line
|
|
|
|
# Output section heading. This occurs even when we have descended into an
|
|
# empty directory with example sub-dirs below it.
|
|
_emit_heading(level, section_heading, f)
|
|
|
|
# Output examples, if any. Will be empty when we are in an empty directory
|
|
# with example sub-dirs below it.
|
|
for example_tuple in example_tuples:
|
|
example_title = example_tuple[0]
|
|
rel_path_from_examples_dir = example_tuple[1]
|
|
example_hdg_underline = header_defs[level + 1] * len(example_title)
|
|
announce(__file__, f'Writing example [{rel_path_from_examples_dir}]...')
|
|
_emit_heading(level + 1, example_title, f)
|
|
f.write(LV_EXAMPLE_DIRECTIVE + ' ' + rel_path_from_examples_dir)
|
|
f.write('\n\n')
|
|
|
|
if dir_order_override:
|
|
_validate_sub_dirs(dir_order_override, file_or_dir)
|
|
result_dir_list = dir_order_override
|
|
|
|
return result_dir_list
|
|
|
|
|
|
def process_dir_recursively(level: int, root_len: int, dir_bep: str, f: TextIOWrapper):
|
|
""" Process dir `dir_bep` recursively, avoiding sub-dirs in `avoid_dirs`.
|
|
|
|
:param level: Directory depth below the top directory in tree.
|
|
:param root_len: Length of root path (gets removed from full path)
|
|
:param dir_bep: Directory *being processed*
|
|
:param f: Output file (examples.rst)
|
|
"""
|
|
announce(__file__, f'Processing dir [{dir_bep}]...')
|
|
sub_dirs = []
|
|
idx_files = []
|
|
|
|
if not os.path.isdir(dir_bep):
|
|
_warn(f'process_dir_recursively: `dir_bep` [{dir_bep}] does not exist.')
|
|
return
|
|
|
|
# For each "thing" found in `dir_bep`, build lists: sub_dirs and idx_files.
|
|
for dir_item in os.listdir(dir_bep):
|
|
path_bep = os.path.join(dir_bep, dir_item)
|
|
if os.path.isdir(path_bep):
|
|
sub_dirs.append(path_bep)
|
|
elif path_bep.endswith(INDEX_FILENAME):
|
|
idx_files.append(path_bep)
|
|
|
|
if idx_files:
|
|
sub_dirs = _generate_output_from_dir(level, root_len, idx_files[0], True, sub_dirs, f)
|
|
# `sub_dirs` can be replaced if `index.rst` contains a dir-order directive.
|
|
else:
|
|
_generate_output_from_dir(level, root_len, dir_bep, False, sub_dirs, f)
|
|
|
|
# Now recursively process sub_dirs.
|
|
for subdir in sub_dirs:
|
|
if not _in_avoid_dirs_list(subdir):
|
|
process_dir_recursively(level + 1, root_len, subdir, f)
|
|
|
|
|
|
def exec(intermediate_dir):
|
|
announce_set_silent_mode(not DEBUG_MODE)
|
|
output_path = os.path.join(intermediate_dir, 'examples.rst')
|
|
input_paths = [
|
|
os.path.join('..', 'examples'),
|
|
# os.path.join('..', 'demos')
|
|
]
|
|
|
|
with open(output_path, 'w', encoding='utf-8') as f:
|
|
f.write('.. _examples:\n')
|
|
f.write('\n')
|
|
|
|
# Recursively walk the directories in `input_paths` array for
|
|
# ``index.rst`` files.
|
|
for root_path in input_paths:
|
|
root_len = len(root_path) + 1
|
|
process_dir_recursively(0, root_len, root_path, f)
|
|
|
|
if MAKE_WARNINGS_INTO_ERRORS and _warning_issued:
|
|
exit(1)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
"""Make module run-able as well as importable."""
|
|
base_dir = os.path.abspath(os.path.dirname(__file__))
|
|
os.chdir(base_dir)
|
|
exec(sys.argv[1])
|