robotframework-libtoc 1.2.8__tar.gz → 1.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {robotframework_libtoc-1.2.8 → robotframework_libtoc-1.4.0}/PKG-INFO +15 -8
- {robotframework_libtoc-1.2.8 → robotframework_libtoc-1.4.0}/README.md +12 -7
- {robotframework_libtoc-1.2.8 → robotframework_libtoc-1.4.0}/pyproject.toml +2 -1
- robotframework_libtoc-1.4.0/robotframework_libtoc/libtoc.py +400 -0
- robotframework_libtoc-1.2.8/robotframework_libtoc/libtoc.py +0 -251
- {robotframework_libtoc-1.2.8 → robotframework_libtoc-1.4.0}/LICENSE +0 -0
- {robotframework_libtoc-1.2.8 → robotframework_libtoc-1.4.0}/robotframework_libtoc/__init__.py +0 -0
- {robotframework_libtoc-1.2.8 → robotframework_libtoc-1.4.0}/robotframework_libtoc/homepage_template.html +0 -0
- {robotframework_libtoc-1.2.8 → robotframework_libtoc-1.4.0}/robotframework_libtoc/toc_template.html +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: robotframework-libtoc
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: Docs and TOC generator for Robot Framework resources and libs
|
|
5
5
|
Home-page: https://github.com/amochin/robotframework-libtoc
|
|
6
6
|
License: Apache-2.0
|
|
@@ -13,13 +13,15 @@ Classifier: Programming Language :: Python :: 3.8
|
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.9
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Requires-Dist: importlib-resources (>=5.12,<5.13)
|
|
16
18
|
Requires-Dist: robotframework (>=4)
|
|
17
19
|
Description-Content-Type: text/markdown
|
|
18
20
|
|
|
19
21
|
## Robot Framework LibTOC
|
|
20
22
|
|
|
21
23
|
## What it does
|
|
22
|
-
This tool generates docs using Robot Framework [Libdoc](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#libdoc) for an entire folder with Robot Framework resources/libs and creates a TOC (table of contents) file for them
|
|
24
|
+
This tool generates docs using Robot Framework [Libdoc](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#libdoc) for an entire folder (or multiple folders) with Robot Framework resources/libs and creates a TOC (table of contents) file for them
|
|
23
25
|
|
|
24
26
|
## Why use it
|
|
25
27
|
The Robot Framework Libdoc tool normally generates a HTML file for a single keyword library or a resource file.
|
|
@@ -34,10 +36,11 @@ in the intranet or uploaded as CI artifact - so everybody can easily access the
|
|
|
34
36
|

|
|
35
37
|
|
|
36
38
|
## How it works
|
|
37
|
-
- The tool goes through the specified
|
|
39
|
+
- The tool goes through the specified folders with RF resources and it's **direct** subfolders
|
|
38
40
|
- It looks for the **config files** named `.libtoc` which contain items you would like to create docs for:
|
|
39
41
|
1. Paths to resource files in [glob format](https://en.wikipedia.org/wiki/Glob_(programming))
|
|
40
|
-
2.
|
|
42
|
+
2. Paths to resources files in [glob format](https://en.wikipedia.org/wiki/Glob_(programming)) inside packages loaded from the pythonpath
|
|
43
|
+
3. Installed RF libraries - names and necessary import params like described in [libdoc user guide](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#general-usage)
|
|
41
44
|
> Other libdoc CLI options (e.g. version or name of the output file) are not supported
|
|
42
45
|
- Then it generates the docs using `libdoc` - both for files paths, resolved from the glob patterns, and for the installed libraries. The created HTML files are placed in the **libtoc output_dir** - keeping the original subfolder structure of resources
|
|
43
46
|
- Finally it generates a **TOC (Table of Contents)** HTML page with links to all the generated HTML files.
|
|
@@ -50,6 +53,9 @@ in the intranet or uploaded as CI artifact - so everybody can easily access the
|
|
|
50
53
|
**/*.resource
|
|
51
54
|
**/*.py
|
|
52
55
|
|
|
56
|
+
[packages]
|
|
57
|
+
example_package:resources/**/*.resource
|
|
58
|
+
|
|
53
59
|
[libs]
|
|
54
60
|
# Use RF library names with params - like for libdoc
|
|
55
61
|
SeleniumLibrary
|
|
@@ -57,7 +63,7 @@ Remote::http://10.0.0.42:8270
|
|
|
57
63
|
# You can use environment variables in lib params
|
|
58
64
|
SomeLib::$some_env_var/somepath
|
|
59
65
|
```
|
|
60
|
-
> The config file must contain at least one of the sections - `[paths]`, `[libs]`
|
|
66
|
+
> The config file must contain at least one of the sections - `[paths]`, `[libs]`, `[packages]`
|
|
61
67
|
## How to install it
|
|
62
68
|
### System requirements
|
|
63
69
|
- Python >=3.7
|
|
@@ -69,7 +75,7 @@ pip install robotframework-libtoc
|
|
|
69
75
|
|
|
70
76
|
## How to use it
|
|
71
77
|
- Create the `.libtoc` config files in the *root of the resources folder* and/or in *direct subfolders* where you need docs to be created.
|
|
72
|
-
- Run `libtoc`. The last `
|
|
78
|
+
- Run `libtoc`. The last `resources_dirs` parameter is mandatory, it takes any number of paths. Other params are optional:
|
|
73
79
|
- `-d, --output_dir`
|
|
74
80
|
- `--config_file`
|
|
75
81
|
- `--toc_file`
|
|
@@ -80,15 +86,16 @@ pip install robotframework-libtoc
|
|
|
80
86
|
Examples:
|
|
81
87
|
```shell
|
|
82
88
|
libtoc example_resources
|
|
89
|
+
libtoc 'example_resources/SUT X' 'example_resources/SUT Y'
|
|
83
90
|
libtoc --output_dir docs example_resources
|
|
84
91
|
libtoc --output_dir docs --toc_file MY_SPECIAL_NAME_FOR_DOCS.html example_resources
|
|
85
92
|
libtoc --toc_template MY_CUSTOM_TOC.html --homepage_template MY_CUSTOM_HOMEPAGE.html example_resources
|
|
86
93
|
```
|
|
87
94
|
|
|
88
|
-
- Open the created file, e.g. `docs
|
|
95
|
+
- Open the created file, e.g. `docs/keyword_docs.html`
|
|
89
96
|
|
|
90
97
|
## How to change the TOC and the homepage HTML templates
|
|
91
|
-
The default HTML template files are located in the python installation directory (usually something like `<python_dir
|
|
98
|
+
The default HTML template files are located in the python installation directory (usually something like `<python_dir>/lib/site-packages/robotframework_libtoc`) and can be changed if necessary.
|
|
92
99
|
It's also possible to provide custom HTML template files using the `--toc_template` and `--homepage_template` options.
|
|
93
100
|
|
|
94
101
|
## How to set the Python Path
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
## Robot Framework LibTOC
|
|
2
2
|
|
|
3
3
|
## What it does
|
|
4
|
-
This tool generates docs using Robot Framework [Libdoc](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#libdoc) for an entire folder with Robot Framework resources/libs and creates a TOC (table of contents) file for them
|
|
4
|
+
This tool generates docs using Robot Framework [Libdoc](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#libdoc) for an entire folder (or multiple folders) with Robot Framework resources/libs and creates a TOC (table of contents) file for them
|
|
5
5
|
|
|
6
6
|
## Why use it
|
|
7
7
|
The Robot Framework Libdoc tool normally generates a HTML file for a single keyword library or a resource file.
|
|
@@ -16,10 +16,11 @@ in the intranet or uploaded as CI artifact - so everybody can easily access the
|
|
|
16
16
|

|
|
17
17
|
|
|
18
18
|
## How it works
|
|
19
|
-
- The tool goes through the specified
|
|
19
|
+
- The tool goes through the specified folders with RF resources and it's **direct** subfolders
|
|
20
20
|
- It looks for the **config files** named `.libtoc` which contain items you would like to create docs for:
|
|
21
21
|
1. Paths to resource files in [glob format](https://en.wikipedia.org/wiki/Glob_(programming))
|
|
22
|
-
2.
|
|
22
|
+
2. Paths to resources files in [glob format](https://en.wikipedia.org/wiki/Glob_(programming)) inside packages loaded from the pythonpath
|
|
23
|
+
3. Installed RF libraries - names and necessary import params like described in [libdoc user guide](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#general-usage)
|
|
23
24
|
> Other libdoc CLI options (e.g. version or name of the output file) are not supported
|
|
24
25
|
- Then it generates the docs using `libdoc` - both for files paths, resolved from the glob patterns, and for the installed libraries. The created HTML files are placed in the **libtoc output_dir** - keeping the original subfolder structure of resources
|
|
25
26
|
- Finally it generates a **TOC (Table of Contents)** HTML page with links to all the generated HTML files.
|
|
@@ -32,6 +33,9 @@ in the intranet or uploaded as CI artifact - so everybody can easily access the
|
|
|
32
33
|
**/*.resource
|
|
33
34
|
**/*.py
|
|
34
35
|
|
|
36
|
+
[packages]
|
|
37
|
+
example_package:resources/**/*.resource
|
|
38
|
+
|
|
35
39
|
[libs]
|
|
36
40
|
# Use RF library names with params - like for libdoc
|
|
37
41
|
SeleniumLibrary
|
|
@@ -39,7 +43,7 @@ Remote::http://10.0.0.42:8270
|
|
|
39
43
|
# You can use environment variables in lib params
|
|
40
44
|
SomeLib::$some_env_var/somepath
|
|
41
45
|
```
|
|
42
|
-
> The config file must contain at least one of the sections - `[paths]`, `[libs]`
|
|
46
|
+
> The config file must contain at least one of the sections - `[paths]`, `[libs]`, `[packages]`
|
|
43
47
|
## How to install it
|
|
44
48
|
### System requirements
|
|
45
49
|
- Python >=3.7
|
|
@@ -51,7 +55,7 @@ pip install robotframework-libtoc
|
|
|
51
55
|
|
|
52
56
|
## How to use it
|
|
53
57
|
- Create the `.libtoc` config files in the *root of the resources folder* and/or in *direct subfolders* where you need docs to be created.
|
|
54
|
-
- Run `libtoc`. The last `
|
|
58
|
+
- Run `libtoc`. The last `resources_dirs` parameter is mandatory, it takes any number of paths. Other params are optional:
|
|
55
59
|
- `-d, --output_dir`
|
|
56
60
|
- `--config_file`
|
|
57
61
|
- `--toc_file`
|
|
@@ -62,15 +66,16 @@ pip install robotframework-libtoc
|
|
|
62
66
|
Examples:
|
|
63
67
|
```shell
|
|
64
68
|
libtoc example_resources
|
|
69
|
+
libtoc 'example_resources/SUT X' 'example_resources/SUT Y'
|
|
65
70
|
libtoc --output_dir docs example_resources
|
|
66
71
|
libtoc --output_dir docs --toc_file MY_SPECIAL_NAME_FOR_DOCS.html example_resources
|
|
67
72
|
libtoc --toc_template MY_CUSTOM_TOC.html --homepage_template MY_CUSTOM_HOMEPAGE.html example_resources
|
|
68
73
|
```
|
|
69
74
|
|
|
70
|
-
- Open the created file, e.g. `docs
|
|
75
|
+
- Open the created file, e.g. `docs/keyword_docs.html`
|
|
71
76
|
|
|
72
77
|
## How to change the TOC and the homepage HTML templates
|
|
73
|
-
The default HTML template files are located in the python installation directory (usually something like `<python_dir
|
|
78
|
+
The default HTML template files are located in the python installation directory (usually something like `<python_dir>/lib/site-packages/robotframework_libtoc`) and can be changed if necessary.
|
|
74
79
|
It's also possible to provide custom HTML template files using the `--toc_template` and `--homepage_template` options.
|
|
75
80
|
|
|
76
81
|
## How to set the Python Path
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "robotframework-libtoc"
|
|
3
|
-
version = "1.
|
|
3
|
+
version = "1.4.0"
|
|
4
4
|
description = "Docs and TOC generator for Robot Framework resources and libs"
|
|
5
5
|
authors = ["Andre Mochinin"]
|
|
6
6
|
license = "Apache-2.0"
|
|
@@ -11,6 +11,7 @@ include = ["robotframework_libtoc/*template.html"]
|
|
|
11
11
|
[tool.poetry.dependencies]
|
|
12
12
|
python = ">=3.7"
|
|
13
13
|
robotframework = ">=4"
|
|
14
|
+
importlib-resources = "~5.12"
|
|
14
15
|
|
|
15
16
|
[tool.poetry.scripts]
|
|
16
17
|
libtoc = "robotframework_libtoc.libtoc:main"
|
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import glob
|
|
3
|
+
import os
|
|
4
|
+
import shutil
|
|
5
|
+
import sys
|
|
6
|
+
from datetime import datetime
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
import importlib_resources
|
|
10
|
+
import robot.libdoc
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class LibdocException(Exception):
|
|
14
|
+
def __init__(self, broken_file):
|
|
15
|
+
self.broken_file = broken_file
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def toc(links, timestamp, home_page_path, template_file=""):
|
|
19
|
+
"""
|
|
20
|
+
Returns a HTML source code for TOC (table of contents) page, based on the template and including
|
|
21
|
+
the provided `links`, generation `timestamp` and the `home_page_path` HTML file as a landing page.
|
|
22
|
+
"""
|
|
23
|
+
if template_file == "":
|
|
24
|
+
template_file = os.path.join(os.path.dirname(__file__), "toc_template.html")
|
|
25
|
+
with open(template_file, encoding="utf8") as f:
|
|
26
|
+
html_template = f.read()
|
|
27
|
+
|
|
28
|
+
# double all brackets to make the further formatting work
|
|
29
|
+
html_with_escaped_braces = html_template.replace("{", "{{")
|
|
30
|
+
html_with_escaped_braces = html_with_escaped_braces.replace("}", "}}")
|
|
31
|
+
|
|
32
|
+
# and convert the formatting brackets back
|
|
33
|
+
html_with_escaped_braces = html_with_escaped_braces.replace("{{}}", "{}")
|
|
34
|
+
|
|
35
|
+
return html_with_escaped_braces.format(home_page_path, links, timestamp)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def homepage(timestamp, template_file=""):
|
|
39
|
+
"""
|
|
40
|
+
Returns a HTML source code for a landing page, based on the template and includig the provided `timestamp`.
|
|
41
|
+
"""
|
|
42
|
+
if template_file == "":
|
|
43
|
+
template_file = os.path.join(
|
|
44
|
+
os.path.dirname(__file__), "homepage_template.html"
|
|
45
|
+
)
|
|
46
|
+
with open(template_file, encoding="utf_8") as f:
|
|
47
|
+
html_template = f.read()
|
|
48
|
+
return html_template.format(timestamp)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def read_config(config_file):
|
|
52
|
+
"""
|
|
53
|
+
Parses the content of the `config_file` and returns a dictionary `{"paths":[values], "libs":[values]}`.
|
|
54
|
+
|
|
55
|
+
The `paths` values are glob patterns, which can be resolved in real paths and used for generating docs using `libdoc`.
|
|
56
|
+
The `libs` values are names of Robot Framework libraries with necessary import params - in the way to be also used for docs generation using `libdoc`.
|
|
57
|
+
|
|
58
|
+
The config file must be formatted like this:
|
|
59
|
+
```
|
|
60
|
+
# Comments starting with # are ignored
|
|
61
|
+
[Paths]
|
|
62
|
+
*.resource
|
|
63
|
+
**/my_subfolder/*.py
|
|
64
|
+
|
|
65
|
+
[Libs]
|
|
66
|
+
SeleniumLibrary
|
|
67
|
+
SomeLibrary::some_import_param
|
|
68
|
+
```
|
|
69
|
+
"""
|
|
70
|
+
sections = {
|
|
71
|
+
"paths": {"markers": ["[paths]"], "values": []},
|
|
72
|
+
"packages": {"markers": ["[packages]"], "values": []},
|
|
73
|
+
"libs": {"markers": ["[libs]", "[libraries]"], "values": []},
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
with open(config_file, encoding="utf8") as f:
|
|
77
|
+
section_to_add = ""
|
|
78
|
+
lines = f.readlines()
|
|
79
|
+
for line in lines:
|
|
80
|
+
stripped_line = line.strip()
|
|
81
|
+
if len(stripped_line) > 0:
|
|
82
|
+
if not stripped_line.startswith("#"): # comments
|
|
83
|
+
skip_line = False
|
|
84
|
+
for section_name, section_content in sections.items():
|
|
85
|
+
if stripped_line.lower() in section_content["markers"]:
|
|
86
|
+
section_to_add = section_name
|
|
87
|
+
skip_line = True
|
|
88
|
+
break
|
|
89
|
+
if not skip_line and section_to_add:
|
|
90
|
+
sections[section_to_add]["values"].append(stripped_line)
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
"paths": sections["paths"]["values"],
|
|
94
|
+
"packages": sections["packages"]["values"],
|
|
95
|
+
"libs": sections["libs"]["values"],
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def add_files_from_folder(folder, base_dir_path, root=True):
|
|
100
|
+
"""
|
|
101
|
+
Creates a HTML source code with links to all HTML files in the `folder` and all it's subfolders.
|
|
102
|
+
The links contain file paths relative to the `base_dir_path`.
|
|
103
|
+
|
|
104
|
+
The `root` parameter is needed for internal usage only - it's set to False during deeper recursive calls.
|
|
105
|
+
"""
|
|
106
|
+
result_str = ""
|
|
107
|
+
if not root: # means we're in the root - no collapsible need in this case
|
|
108
|
+
result_str += """<button class="collapsible">{}</button>
|
|
109
|
+
""".format(
|
|
110
|
+
os.path.basename(folder)
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
result_str += """<div class="collapsible_content">
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
for item in os.listdir(folder):
|
|
117
|
+
item_path = os.path.abspath(os.path.join(folder, item))
|
|
118
|
+
if item.endswith(".html"):
|
|
119
|
+
name_without_ext = os.path.splitext(item)[0]
|
|
120
|
+
result_str += """<a class="link_not_selected" href="{}" target="targetFrame">{}</a>
|
|
121
|
+
""".format(
|
|
122
|
+
os.path.relpath(item_path, base_dir_path), name_without_ext
|
|
123
|
+
)
|
|
124
|
+
else:
|
|
125
|
+
if os.path.isdir(item_path):
|
|
126
|
+
result_str += add_files_from_folder(
|
|
127
|
+
item_path, base_dir_path, root=False
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
if not root:
|
|
131
|
+
# end of the "collapsible_content"
|
|
132
|
+
result_str += """</div>
|
|
133
|
+
"""
|
|
134
|
+
return result_str
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def create_docs_for_dir(resource_dir, output_dir, config_file):
|
|
138
|
+
"""
|
|
139
|
+
Creates HTML docs using Robot Framework module `libdoc` for all resources and libraries in the `resource_dir`.
|
|
140
|
+
Generated files are placed inside the `output_dir`, keeping the original subfolder tree structure.
|
|
141
|
+
|
|
142
|
+
Paths of resource/python files and libraries, which the docs should be generated for, are configured using the `config_file`.
|
|
143
|
+
|
|
144
|
+
The `config_file` must be formatted like this:
|
|
145
|
+
```
|
|
146
|
+
# Comments starting with # are ignored
|
|
147
|
+
[Paths]
|
|
148
|
+
*.resource
|
|
149
|
+
**/my_subfolder/*.py
|
|
150
|
+
|
|
151
|
+
[Libs]
|
|
152
|
+
SeleniumLibrary
|
|
153
|
+
SomeLibrary::some_import_param
|
|
154
|
+
```
|
|
155
|
+
"""
|
|
156
|
+
target_dir = os.path.join(
|
|
157
|
+
os.path.abspath(output_dir), os.path.basename(resource_dir)
|
|
158
|
+
)
|
|
159
|
+
doc_config = read_config(config_file)
|
|
160
|
+
|
|
161
|
+
resource_path_patterns = doc_config["paths"]
|
|
162
|
+
if resource_path_patterns:
|
|
163
|
+
print(">> Processing paths")
|
|
164
|
+
broken_files = []
|
|
165
|
+
for path_pattern in resource_path_patterns:
|
|
166
|
+
for real_path in glob.glob(
|
|
167
|
+
os.path.join(resource_dir, path_pattern), recursive=True
|
|
168
|
+
):
|
|
169
|
+
relative_path = os.path.relpath(real_path, resource_dir)
|
|
170
|
+
target_path = os.path.join(
|
|
171
|
+
target_dir, relative_path.rpartition(".")[0] + ".html"
|
|
172
|
+
)
|
|
173
|
+
print(f">>> Processing file: {relative_path}")
|
|
174
|
+
return_code = robot.libdoc.libdoc(real_path, target_path, quiet=True)
|
|
175
|
+
if return_code > 0:
|
|
176
|
+
broken_files.append(relative_path)
|
|
177
|
+
|
|
178
|
+
package_definitions = doc_config["packages"]
|
|
179
|
+
if package_definitions:
|
|
180
|
+
print("---")
|
|
181
|
+
packages = {}
|
|
182
|
+
broken_packages = []
|
|
183
|
+
for package_definition in package_definitions:
|
|
184
|
+
package_name, path_pattern = package_definition.split(":", 1)
|
|
185
|
+
if package_name not in packages:
|
|
186
|
+
packages[package_name] = []
|
|
187
|
+
packages[package_name].append(path_pattern)
|
|
188
|
+
|
|
189
|
+
for package_name, paths_patterns in packages.items():
|
|
190
|
+
print(f">> Processing package: {package_name}")
|
|
191
|
+
try:
|
|
192
|
+
package_anchor = importlib_resources.files(package_name)
|
|
193
|
+
except ModuleNotFoundError as e:
|
|
194
|
+
print(f"Importing package '{package_name}' failed: {e}")
|
|
195
|
+
broken_packages.append(package_name)
|
|
196
|
+
else:
|
|
197
|
+
with importlib_resources.as_file(package_anchor) as package_path:
|
|
198
|
+
for path_pattern in paths_patterns:
|
|
199
|
+
package_resource_files = package_path.glob(path_pattern)
|
|
200
|
+
for real_path in package_resource_files:
|
|
201
|
+
relative_path = Path(package_name) / real_path.relative_to(
|
|
202
|
+
package_path
|
|
203
|
+
)
|
|
204
|
+
target_path = os.path.join(
|
|
205
|
+
target_dir, relative_path.with_suffix(".html")
|
|
206
|
+
)
|
|
207
|
+
print(f">>> Processing file: {relative_path}")
|
|
208
|
+
return_code = robot.libdoc.libdoc(
|
|
209
|
+
real_path, target_path, quiet=True
|
|
210
|
+
)
|
|
211
|
+
if return_code > 0:
|
|
212
|
+
broken_packages.append(relative_path)
|
|
213
|
+
|
|
214
|
+
libs = doc_config["libs"]
|
|
215
|
+
if libs:
|
|
216
|
+
print("---")
|
|
217
|
+
print(">> Processing libraries")
|
|
218
|
+
broken_libs = []
|
|
219
|
+
for lib in libs:
|
|
220
|
+
lib_str_with_resolved_vars = os.path.expandvars(lib)
|
|
221
|
+
target_path = os.path.join(
|
|
222
|
+
target_dir, lib_str_with_resolved_vars.partition("::")[0] + ".html"
|
|
223
|
+
)
|
|
224
|
+
print(f">>> Processing lib: {lib_str_with_resolved_vars}")
|
|
225
|
+
return_code = robot.libdoc.libdoc(
|
|
226
|
+
lib_str_with_resolved_vars, target_path, quiet=True
|
|
227
|
+
)
|
|
228
|
+
if return_code > 0:
|
|
229
|
+
broken_libs.append(lib_str_with_resolved_vars)
|
|
230
|
+
return broken_files, broken_packages, broken_libs
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def create_toc(
|
|
234
|
+
html_docs_dir,
|
|
235
|
+
toc_file="keyword_docs.html",
|
|
236
|
+
homepage_file="homepage.html",
|
|
237
|
+
toc_template="",
|
|
238
|
+
homepage_template="",
|
|
239
|
+
):
|
|
240
|
+
"""
|
|
241
|
+
Generates a `toc_file` (Table of Contents) HTML page with links to all HTML files inside the `html_docs_dir` and all it's subfolders.
|
|
242
|
+
|
|
243
|
+
The navigation tree structure in the TOC repeats the folder tree structure.
|
|
244
|
+
It also creates a `homepage_file` shown as a landing page when opening the TOC.
|
|
245
|
+
|
|
246
|
+
All the content of the `html_docs_dir` will be moved in the new `src` subfolder, leaving only the `toc_file` directly inside.
|
|
247
|
+
"""
|
|
248
|
+
print(f"> Creating TOC in: {os.path.abspath(html_docs_dir)}")
|
|
249
|
+
# move all subfolders and files into "src"
|
|
250
|
+
src_subdir = os.path.join(html_docs_dir, "src")
|
|
251
|
+
os.makedirs(src_subdir, exist_ok=True)
|
|
252
|
+
all_docs = os.listdir(html_docs_dir)
|
|
253
|
+
for doc_element in all_docs:
|
|
254
|
+
if doc_element == "src":
|
|
255
|
+
continue
|
|
256
|
+
src = os.path.join(html_docs_dir, doc_element)
|
|
257
|
+
target = os.path.join(src_subdir, doc_element)
|
|
258
|
+
shutil.move(src, target)
|
|
259
|
+
|
|
260
|
+
# create homepage in "src"
|
|
261
|
+
homepage_path = os.path.join(src_subdir, homepage_file)
|
|
262
|
+
current_date_time = datetime.now().strftime("%d.%m.%Y %H:%M:%S")
|
|
263
|
+
doc_files_links = add_files_from_folder(src_subdir, os.path.abspath(html_docs_dir))
|
|
264
|
+
with open(homepage_path, "w", encoding="utf8") as f:
|
|
265
|
+
f.write(homepage(current_date_time, homepage_template))
|
|
266
|
+
|
|
267
|
+
# create TOC
|
|
268
|
+
toc_file_path = os.path.join(html_docs_dir, toc_file)
|
|
269
|
+
with open(toc_file_path, "w", encoding="utf8") as f:
|
|
270
|
+
f.write(
|
|
271
|
+
toc(
|
|
272
|
+
doc_files_links,
|
|
273
|
+
current_date_time,
|
|
274
|
+
os.path.relpath(homepage_path, os.path.abspath(html_docs_dir)),
|
|
275
|
+
toc_template,
|
|
276
|
+
)
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
print("---")
|
|
280
|
+
print("TOC finished. Output file: {}".format(os.path.abspath(toc_file_path)))
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def main():
|
|
284
|
+
parser = argparse.ArgumentParser(
|
|
285
|
+
description="Generates keyword docs using libdoc based on config files in direct subfolders of the resources dir and creates a TOC"
|
|
286
|
+
)
|
|
287
|
+
parser.add_argument(
|
|
288
|
+
"resources_dirs", nargs="+", help="Folders with resources and keywords files"
|
|
289
|
+
)
|
|
290
|
+
parser.add_argument(
|
|
291
|
+
"-d", "--output_dir", default="docs", help="Folder to create the docs in"
|
|
292
|
+
)
|
|
293
|
+
parser.add_argument(
|
|
294
|
+
"--config_file",
|
|
295
|
+
default=".libtoc",
|
|
296
|
+
help="File in each folder with docs generation configs",
|
|
297
|
+
)
|
|
298
|
+
parser.add_argument(
|
|
299
|
+
"--toc_file", default="keyword_docs.html", help="Name of the TOC file generated"
|
|
300
|
+
)
|
|
301
|
+
parser.add_argument(
|
|
302
|
+
"--toc_template", default="", help="Custom HTML template for the TOC file"
|
|
303
|
+
)
|
|
304
|
+
parser.add_argument(
|
|
305
|
+
"--homepage_template",
|
|
306
|
+
default="",
|
|
307
|
+
help="Custom HTML template for the homepage file",
|
|
308
|
+
)
|
|
309
|
+
parser.add_argument(
|
|
310
|
+
"-P",
|
|
311
|
+
"--pythonpath",
|
|
312
|
+
default="",
|
|
313
|
+
help="Additional locations where to search for libraries and resources similarly as when running tests",
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
args = parser.parse_args()
|
|
317
|
+
|
|
318
|
+
if args.pythonpath:
|
|
319
|
+
sys.path.insert(0, args.pythonpath)
|
|
320
|
+
|
|
321
|
+
if os.path.isdir(args.output_dir):
|
|
322
|
+
print(f"Output dir already exists, deleting it: {args.output_dir}")
|
|
323
|
+
shutil.rmtree(args.output_dir)
|
|
324
|
+
total_broken_files = []
|
|
325
|
+
total_broken_packages = []
|
|
326
|
+
total_broken_libs = []
|
|
327
|
+
|
|
328
|
+
for resources_dir in args.resources_dirs:
|
|
329
|
+
print("")
|
|
330
|
+
print(f"> Creating docs for dir: {os.path.abspath(resources_dir)}")
|
|
331
|
+
for child_element in os.listdir(resources_dir):
|
|
332
|
+
child_element_path = os.path.join(resources_dir, child_element)
|
|
333
|
+
current_broken_files = []
|
|
334
|
+
current_broken_packages = []
|
|
335
|
+
current_broken_libs = []
|
|
336
|
+
if os.path.isdir(child_element_path):
|
|
337
|
+
config_file = os.path.join(child_element_path, args.config_file)
|
|
338
|
+
if os.path.isfile(config_file):
|
|
339
|
+
(
|
|
340
|
+
current_broken_files,
|
|
341
|
+
current_broken_packages,
|
|
342
|
+
current_broken_libs,
|
|
343
|
+
) = create_docs_for_dir(
|
|
344
|
+
child_element_path,
|
|
345
|
+
args.output_dir,
|
|
346
|
+
os.path.abspath(config_file),
|
|
347
|
+
)
|
|
348
|
+
elif child_element == args.config_file:
|
|
349
|
+
current_broken_files, current_broken_packages, current_broken_libs = (
|
|
350
|
+
create_docs_for_dir(
|
|
351
|
+
resources_dir,
|
|
352
|
+
args.output_dir,
|
|
353
|
+
os.path.abspath(os.path.join(resources_dir, args.config_file)),
|
|
354
|
+
)
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
total_broken_files += current_broken_files
|
|
358
|
+
total_broken_packages += current_broken_packages
|
|
359
|
+
total_broken_libs += current_broken_libs
|
|
360
|
+
|
|
361
|
+
if total_broken_files:
|
|
362
|
+
print("")
|
|
363
|
+
print(
|
|
364
|
+
f"---> !!! Errors occurred while generating docs for {len(total_broken_files)} files (see details above):"
|
|
365
|
+
)
|
|
366
|
+
for f in total_broken_files:
|
|
367
|
+
print(f" - {f}")
|
|
368
|
+
|
|
369
|
+
if total_broken_packages:
|
|
370
|
+
print("")
|
|
371
|
+
print(
|
|
372
|
+
f"---> !!! Errors occurred while generating docs for {len(total_broken_packages)} packages (see details above):"
|
|
373
|
+
)
|
|
374
|
+
for f in total_broken_packages:
|
|
375
|
+
print(f" - {f}")
|
|
376
|
+
|
|
377
|
+
if total_broken_libs:
|
|
378
|
+
print("")
|
|
379
|
+
print(
|
|
380
|
+
f"---> !!! Errors occurred while generating docs for {len(total_broken_libs)} libs (see details above):"
|
|
381
|
+
)
|
|
382
|
+
for l in total_broken_libs:
|
|
383
|
+
print(f" - {l}")
|
|
384
|
+
|
|
385
|
+
if os.path.isdir(args.output_dir):
|
|
386
|
+
print("")
|
|
387
|
+
create_toc(
|
|
388
|
+
args.output_dir,
|
|
389
|
+
args.toc_file,
|
|
390
|
+
toc_template=args.toc_template,
|
|
391
|
+
homepage_template=args.homepage_template,
|
|
392
|
+
)
|
|
393
|
+
else:
|
|
394
|
+
print("No docs were created!")
|
|
395
|
+
|
|
396
|
+
print("")
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
if __name__ == "__main__":
|
|
400
|
+
main()
|
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import sys
|
|
3
|
-
import shutil
|
|
4
|
-
import glob
|
|
5
|
-
import argparse
|
|
6
|
-
from datetime import datetime
|
|
7
|
-
import robot.libdoc
|
|
8
|
-
|
|
9
|
-
class LibdocException(Exception):
|
|
10
|
-
def __init__(self, broken_file):
|
|
11
|
-
self.broken_file = broken_file
|
|
12
|
-
|
|
13
|
-
def toc(links, timestamp, home_page_path, template_file=""):
|
|
14
|
-
"""
|
|
15
|
-
Returns a HTML source code for TOC (table of contents) page, based on the template and including
|
|
16
|
-
the provided `links`, generation `timestamp` and the `home_page_path` HTML file as a landing page.
|
|
17
|
-
"""
|
|
18
|
-
if template_file == "":
|
|
19
|
-
template_file = os.path.join(os.path.dirname(__file__), "toc_template.html")
|
|
20
|
-
with open(template_file, encoding="utf8") as f:
|
|
21
|
-
html_template = f.read()
|
|
22
|
-
|
|
23
|
-
# double all brackets to make the further formatting work
|
|
24
|
-
html_with_escaped_braces = html_template.replace('{', '{{')
|
|
25
|
-
html_with_escaped_braces = html_with_escaped_braces.replace('}', '}}')
|
|
26
|
-
|
|
27
|
-
# and convert the formatting brackets back
|
|
28
|
-
html_with_escaped_braces = html_with_escaped_braces.replace('{{}}', '{}')
|
|
29
|
-
|
|
30
|
-
return html_with_escaped_braces.format(home_page_path, links, timestamp)
|
|
31
|
-
|
|
32
|
-
def homepage(timestamp, template_file=""):
|
|
33
|
-
"""
|
|
34
|
-
Returns a HTML source code for a landing page, based on the template and includig the provided `timestamp`.
|
|
35
|
-
"""
|
|
36
|
-
if template_file == "":
|
|
37
|
-
template_file = os.path.join(os.path.dirname(__file__), "homepage_template.html")
|
|
38
|
-
with open(template_file, encoding="utf_8") as f:
|
|
39
|
-
html_template = f.read()
|
|
40
|
-
return html_template.format(timestamp)
|
|
41
|
-
|
|
42
|
-
def read_config(config_file):
|
|
43
|
-
"""
|
|
44
|
-
Parses the content of the `config_file` and returns a dictionary `{"paths":[values], "libs":[values]}`.
|
|
45
|
-
|
|
46
|
-
The `paths` values are glob patterns, which can be resolved in real paths and used for generating docs using `libdoc`.
|
|
47
|
-
The `libs` values are names of Robot Framework libraries with necessary import params - in the way to be also used for docs generation using `libdoc`.
|
|
48
|
-
|
|
49
|
-
The config file must be formatted like this:
|
|
50
|
-
```
|
|
51
|
-
# Comments starting with # are ignored
|
|
52
|
-
[Paths]
|
|
53
|
-
*.resource
|
|
54
|
-
**/my_subfolder/*.py
|
|
55
|
-
|
|
56
|
-
[Libs]
|
|
57
|
-
SeleniumLibrary
|
|
58
|
-
SomeLibrary::some_import_param
|
|
59
|
-
```
|
|
60
|
-
"""
|
|
61
|
-
sections = {
|
|
62
|
-
"paths": {"markers":["[paths]"], "values":[]},
|
|
63
|
-
"libs": {"markers": ["[libs]", "[libraries]"], "values":[]}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
with open(config_file, encoding="utf8") as f:
|
|
67
|
-
section_to_add = ""
|
|
68
|
-
lines = f.readlines()
|
|
69
|
-
for line in lines:
|
|
70
|
-
stripped_line = line.strip()
|
|
71
|
-
if len(stripped_line) > 0:
|
|
72
|
-
if not stripped_line.startswith('#'): # comments
|
|
73
|
-
skip_line = False
|
|
74
|
-
for section_name, section_content in sections.items():
|
|
75
|
-
if stripped_line.lower() in section_content["markers"]:
|
|
76
|
-
section_to_add = section_name
|
|
77
|
-
skip_line = True
|
|
78
|
-
break
|
|
79
|
-
if not skip_line and section_to_add:
|
|
80
|
-
sections[section_to_add]["values"].append(stripped_line)
|
|
81
|
-
|
|
82
|
-
return {"paths": sections["paths"]["values"], "libs": sections["libs"]["values"]}
|
|
83
|
-
|
|
84
|
-
def add_files_from_folder(folder, base_dir_path, root=True):
|
|
85
|
-
"""
|
|
86
|
-
Creates a HTML source code with links to all HTML files in the `folder` and all it's subfolders.
|
|
87
|
-
The links contain file paths relative to the `base_dir_path`.
|
|
88
|
-
|
|
89
|
-
The `root` parameter is needed for internal usage only - it's set to False during deeper recursive calls.
|
|
90
|
-
"""
|
|
91
|
-
result_str = ""
|
|
92
|
-
if not root: # means we're in the root - no collapsible need in this case
|
|
93
|
-
result_str += """<button class="collapsible">{}</button>
|
|
94
|
-
""".format(os.path.basename(folder))
|
|
95
|
-
|
|
96
|
-
result_str += """<div class="collapsible_content">
|
|
97
|
-
"""
|
|
98
|
-
|
|
99
|
-
for item in os.listdir(folder):
|
|
100
|
-
item_path = os.path.abspath(os.path.join(folder, item))
|
|
101
|
-
if item.endswith(".html"):
|
|
102
|
-
name_without_ext = os.path.splitext(item)[0]
|
|
103
|
-
result_str += """<a class="link_not_selected" href="{}" target="targetFrame">{}</a>
|
|
104
|
-
""".format(os.path.relpath(item_path, base_dir_path), name_without_ext)
|
|
105
|
-
else:
|
|
106
|
-
if os.path.isdir(item_path):
|
|
107
|
-
result_str += add_files_from_folder(item_path, base_dir_path, root=False)
|
|
108
|
-
|
|
109
|
-
if not root:
|
|
110
|
-
# end of the "collapsible_content"
|
|
111
|
-
result_str += """</div>
|
|
112
|
-
"""
|
|
113
|
-
return result_str
|
|
114
|
-
|
|
115
|
-
def create_docs_for_dir(resource_dir, output_dir, config_file):
|
|
116
|
-
"""
|
|
117
|
-
Creates HTML docs using Robot Framework module `libdoc` for all resources and libraries in the `resource_dir`.
|
|
118
|
-
Generated files are placed inside the `output_dir`, keeping the original subfolder tree structure.
|
|
119
|
-
|
|
120
|
-
Paths of resource/python files and libraries, which the docs should be generated for, are configured using the `config_file`.
|
|
121
|
-
|
|
122
|
-
The `config_file` must be formatted like this:
|
|
123
|
-
```
|
|
124
|
-
# Comments starting with # are ignored
|
|
125
|
-
[Paths]
|
|
126
|
-
*.resource
|
|
127
|
-
**/my_subfolder/*.py
|
|
128
|
-
|
|
129
|
-
[Libs]
|
|
130
|
-
SeleniumLibrary
|
|
131
|
-
SomeLibrary::some_import_param
|
|
132
|
-
```
|
|
133
|
-
"""
|
|
134
|
-
target_dir = os.path.join(os.path.abspath(output_dir), os.path.basename(resource_dir))
|
|
135
|
-
doc_config = read_config(config_file)
|
|
136
|
-
|
|
137
|
-
resource_path_patterns = doc_config["paths"]
|
|
138
|
-
broken_files = []
|
|
139
|
-
for path_pattern in resource_path_patterns:
|
|
140
|
-
for real_path in glob.glob(os.path.join(resource_dir, path_pattern), recursive=True):
|
|
141
|
-
relative_path = os.path.relpath(real_path, resource_dir)
|
|
142
|
-
target_path = os.path.join(target_dir, relative_path.rpartition('.')[0] + ".html")
|
|
143
|
-
print(f">> Generating docs for resource: {relative_path}")
|
|
144
|
-
return_code = robot.libdoc.libdoc(real_path, target_path)
|
|
145
|
-
if return_code > 0:
|
|
146
|
-
broken_files.append(relative_path)
|
|
147
|
-
|
|
148
|
-
libs = doc_config["libs"]
|
|
149
|
-
broken_libs = []
|
|
150
|
-
for lib in libs:
|
|
151
|
-
lib_str_with_resolved_vars = os.path.expandvars(lib)
|
|
152
|
-
target_path = os.path.join(target_dir, lib_str_with_resolved_vars.partition("::")[0] + ".html")
|
|
153
|
-
print(f">> Generating docs for library: {lib_str_with_resolved_vars}")
|
|
154
|
-
return_code = robot.libdoc.libdoc(lib_str_with_resolved_vars, target_path)
|
|
155
|
-
if return_code > 0:
|
|
156
|
-
broken_libs.append(lib_str_with_resolved_vars)
|
|
157
|
-
return broken_files, broken_libs
|
|
158
|
-
|
|
159
|
-
def create_toc(html_docs_dir, toc_file="keyword_docs.html", homepage_file="homepage.html", toc_template="", homepage_template=""):
|
|
160
|
-
"""
|
|
161
|
-
Generates a `toc_file` (Table of Contents) HTML page with links to all HTML files inside the `html_docs_dir` and all it's subfolders.
|
|
162
|
-
|
|
163
|
-
The navigation tree structure in the TOC repeats the folder tree structure.
|
|
164
|
-
It also creates a `homepage_file` shown as a landing page when opening the TOC.
|
|
165
|
-
|
|
166
|
-
All the content of the `html_docs_dir` will be moved in the new `src` subfolder, leaving only the `toc_file` directly inside.
|
|
167
|
-
"""
|
|
168
|
-
print(f">>> Creating TOC in: {os.path.abspath(html_docs_dir)}")
|
|
169
|
-
# move all subfolders and files into "src"
|
|
170
|
-
src_subdir = os.path.join(html_docs_dir, "src")
|
|
171
|
-
os.makedirs(src_subdir, exist_ok=True)
|
|
172
|
-
all_docs = os.listdir(html_docs_dir)
|
|
173
|
-
for doc_element in all_docs:
|
|
174
|
-
if doc_element == "src":
|
|
175
|
-
continue
|
|
176
|
-
src = os.path.join(html_docs_dir, doc_element)
|
|
177
|
-
target = os.path.join(src_subdir, doc_element)
|
|
178
|
-
shutil.move(src, target)
|
|
179
|
-
|
|
180
|
-
# create homepage in "src"
|
|
181
|
-
homepage_path = os.path.join(src_subdir, homepage_file)
|
|
182
|
-
current_date_time = datetime.now().strftime('%d.%m.%Y %H:%M:%S')
|
|
183
|
-
doc_files_links = add_files_from_folder(src_subdir, os.path.abspath(html_docs_dir))
|
|
184
|
-
with open(homepage_path, 'w', encoding="utf8") as f:
|
|
185
|
-
f.write(homepage(current_date_time, homepage_template))
|
|
186
|
-
|
|
187
|
-
# create TOC
|
|
188
|
-
toc_file_path = os.path.join(html_docs_dir, toc_file)
|
|
189
|
-
with open(toc_file_path, 'w', encoding="utf8") as f:
|
|
190
|
-
f.write(toc(doc_files_links, current_date_time, os.path.relpath(homepage_path, os.path.abspath(html_docs_dir)), toc_template))
|
|
191
|
-
|
|
192
|
-
print("TOC finished. Output file: {}".format(os.path.abspath(toc_file_path)))
|
|
193
|
-
|
|
194
|
-
def main():
|
|
195
|
-
parser = argparse.ArgumentParser(description="Generates keyword docs using libdoc based on config files in direct subfolders of the resources dir and creates a TOC")
|
|
196
|
-
parser.add_argument("resources_dir", help="Folder with resources and keywords files")
|
|
197
|
-
parser.add_argument("-d", "--output_dir", default="docs", help="Folder to create the docs in")
|
|
198
|
-
parser.add_argument("--config_file", default=".libtoc", help="File in each folder with docs generation configs")
|
|
199
|
-
parser.add_argument("--toc_file", default="keyword_docs.html", help="Name of the TOC file generated")
|
|
200
|
-
parser.add_argument("--toc_template", default="", help = "Custom HTML template for the TOC file")
|
|
201
|
-
parser.add_argument("--homepage_template", default="", help = "Custom HTML template for the homepage file")
|
|
202
|
-
parser.add_argument("-P", "--pythonpath", default="", help="Additional locations where to search for libraries and resources similarly as when running tests")
|
|
203
|
-
|
|
204
|
-
args = parser.parse_args()
|
|
205
|
-
|
|
206
|
-
if args.pythonpath:
|
|
207
|
-
sys.path.insert(0, args.pythonpath)
|
|
208
|
-
|
|
209
|
-
print(f"Creating docs for: {os.path.abspath(args.resources_dir)}")
|
|
210
|
-
|
|
211
|
-
if os.path.isdir(args.output_dir):
|
|
212
|
-
print(f"Output dir already exists, deleting it: {args.output_dir}")
|
|
213
|
-
shutil.rmtree(args.output_dir)
|
|
214
|
-
total_broken_files = []
|
|
215
|
-
total_broken_libs = []
|
|
216
|
-
for child_element in os.listdir(args.resources_dir):
|
|
217
|
-
child_element_path = os.path.join(args.resources_dir, child_element)
|
|
218
|
-
current_broken_files = []
|
|
219
|
-
current_broken_libs = []
|
|
220
|
-
if os.path.isdir(child_element_path):
|
|
221
|
-
config_file = os.path.join(child_element_path, args.config_file)
|
|
222
|
-
if os.path.isfile(config_file):
|
|
223
|
-
current_broken_files, current_broken_libs = create_docs_for_dir(child_element_path, args.output_dir, os.path.abspath(config_file))
|
|
224
|
-
elif child_element == args.config_file:
|
|
225
|
-
current_broken_files, current_broken_libs = create_docs_for_dir(args.resources_dir, args.output_dir, os.path.abspath(os.path.join(args.resources_dir, args.config_file)))
|
|
226
|
-
|
|
227
|
-
total_broken_files += current_broken_files
|
|
228
|
-
total_broken_libs += current_broken_libs
|
|
229
|
-
|
|
230
|
-
if total_broken_files:
|
|
231
|
-
print("")
|
|
232
|
-
print(f"---> !!! Errors occurred while generating docs for {len(total_broken_files)} files (see details above):")
|
|
233
|
-
for f in total_broken_files:
|
|
234
|
-
print(f" - {f}")
|
|
235
|
-
|
|
236
|
-
if total_broken_libs:
|
|
237
|
-
print("")
|
|
238
|
-
print(f"---> !!! Errors occurred while generating docs for {len(total_broken_libs)} libs (see details above):")
|
|
239
|
-
for l in total_broken_libs:
|
|
240
|
-
print(f" - {l}")
|
|
241
|
-
|
|
242
|
-
if os.path.isdir(args.output_dir):
|
|
243
|
-
print("")
|
|
244
|
-
create_toc(args.output_dir, args.toc_file, toc_template=args.toc_template, homepage_template=args.homepage_template)
|
|
245
|
-
else:
|
|
246
|
-
print("No docs were created!")
|
|
247
|
-
|
|
248
|
-
print("")
|
|
249
|
-
|
|
250
|
-
if __name__ == "__main__":
|
|
251
|
-
main()
|
|
File without changes
|
{robotframework_libtoc-1.2.8 → robotframework_libtoc-1.4.0}/robotframework_libtoc/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{robotframework_libtoc-1.2.8 → robotframework_libtoc-1.4.0}/robotframework_libtoc/toc_template.html
RENAMED
|
File without changes
|