Skip to content

Commit 0e116df

Browse files
authored
Merge pull request #15 from CESNET/cabal_improve
SPHINX VHDL version 0.2.0
2 parents ad75764 + bf4bee5 commit 0e116df

9 files changed

Lines changed: 115 additions & 90 deletions

File tree

.github/workflows/doc.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
- name: Setup and build 🔧
1515
run: |
1616
sudo apt-get install python3-pip
17-
pip3 install sphinx sphinx-vhdl
17+
pip3 install sphinx sphinx-vhdl sphinx_rtd_theme
1818
sphinx-build -M html doc/source public
1919
touch public/html/.nojekyll
2020
- name: Deploy 🚀

.gitlab-ci.yml

Lines changed: 0 additions & 21 deletions
This file was deleted.

README.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
# Sphinx-vhdl
1+
# SPHINX-VHDL
22

33
[![PyPI](https://img.shields.io/pypi/v/sphinx-vhdl)](https://pypi.org/project/sphinx-vhdl/)
4-
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/CESNET/sphinx-vhdl/documentation?label=documentation)](https://cesnet.github.io/sphinx-vhdl/)
4+
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/CESNET/sphinx-vhdl/.github/workflows/doc.yml)](https://cesnet.github.io/sphinx-vhdl/)
55

66
> A [sphinx](https://www.sphinx-doc.org/) domain for semi-automatically documenting VHDL
77
88
This extension for Sphinx allows you to keep your documentation in code and automatically draw it out into your main documentation using just few simple directives.
99

10-
You can see the detailed documentation at https://cesnet.github.io/sphinx-vhdl/, or build it yourself (running `make html` while in the `doc` directory and having `sphinx` installed should be sufficient)
10+
You can see the detailed documentation at https://cesnet.github.io/sphinx-vhdl/, or build it yourself (running `make` while in the `doc` directory and having `sphinx` + `sphinx_rtd_theme` installed should be sufficient)
1111

1212
## Usage
1313

@@ -16,7 +16,9 @@ The python package must be installed with
1616
pip3 install sphinx-vhdl
1717
```
1818

19-
The usage of this extension requires Python >= 3.6 and Sphinx >= 4.0.0.
19+
This extension requires Python >= 3.8 and Sphinx >= 6.0.0.
20+
21+
*Note that your documentation may use multiple sphinx extensions or an alternative theme (such as `sphinx_rtd_theme`), which you must also have installed.*
2022

2123
## Configuration
2224

@@ -27,6 +29,12 @@ extensions = ['sphinxvhdl.vhdl']
2729
vhdl_autodoc_source_path = 'path/to/your/vhdl/sources/root'
2830
```
2931

32+
## Where is the SPHINX-VHDL extension used?
33+
34+
- [Open FPGA Modules (OFM) by CESNET](https://github.com/CESNET/ofm/)
35+
- [NDK Minimal Application by CESNET](https://github.com/CESNET/ndk-app-minimal)
36+
- *Do you use SPHINX-VHDL in your public VHDL repository? Please add a link to this list!*
37+
3038
## Repository maintainer
3139

3240
- Jakub Cabal, cabal@cesnet.cz

doc/Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Minimal makefile for Sphinx documentation
2+
3+
.PHONY: all clean
4+
5+
all:
6+
sphinx-build -M html source build -v -E
7+
8+
clean:
9+
rm -rf ./build

doc/source/conf.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
# -- Project information -----------------------------------------------------
1919

2020
project = 'sphinx-vhdl'
21-
copyright = '2021, Cesnet z.s.p.o.'
21+
copyright = '2024, Cesnet z.s.p.o.'
2222
author = 'Cesnet z.s.p.o.'
2323

2424

@@ -31,7 +31,7 @@
3131
'sphinxvhdl.vhdl'
3232
]
3333

34-
vhdl_autodoc_source_path = 'doc/source'
34+
vhdl_autodoc_source_path = './'
3535

3636
# Add any paths that contain templates here, relative to this directory.
3737
templates_path = ['_templates']
@@ -47,7 +47,7 @@
4747
# The theme to use for HTML and HTML Help pages. See the documentation for
4848
# a list of builtin themes.
4949
#
50-
html_theme = 'alabaster'
50+
html_theme = 'sphinx_rtd_theme'
5151

5252
# Add any paths that contain custom static files (such as style sheets) here,
5353
# relative to this directory. They are copied after the builtin static files,

doc/source/example_built.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Example Documentation
55

66
.. vhdl:autopackage:: math_pack
77
8-
.. vhdl:autofunction:: log2
8+
.. vhdl:autofunction:: log2
99
1010
.. vhdl:autoentity:: counter
1111
.. vhdl:autoconstants:: counter

setup.cfg

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = sphinx-vhdl
3-
version = 0.1.6
3+
version = 0.2.0
44
author = CESNET z.s.p.o.
55
author_email = cabal@cesnet.cz
66
description = A Sphinx domain and autodocumenter for VHDL
@@ -21,7 +21,9 @@ classifiers =
2121
package_dir =
2222
= src
2323
packages = find:
24-
python_requires = >=3.6
24+
python_requires = >=3.8
25+
install_requires =
26+
sphinx >= 6.0
2527

2628
[options.packages.find]
2729
where = src

src/sphinxvhdl/autodoc.py

Lines changed: 27 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# autodoc.py: A basic VHDL parser and documentation extractor
22
# Copyright (C) 2021 CESNET z.s.p.o.
33
# Author(s): Jindrich Dite <xditej01@stud.fit.vutbr.cz>
4+
# Jakub Cabal <cabal@cesnet.cz>
45
#
56
# SPDX-License-Identifier: BSD-3-Clause
67

@@ -10,9 +11,8 @@
1011
from typing import Optional, List
1112
from enum import Enum, auto
1213

13-
import logging
14-
15-
LOG = logging.getLogger('sphinxvhdl-autodoc')
14+
from sphinx.util import logging
15+
logger = logging.getLogger(__name__)
1616

1717
entities = {}
1818
portsignals = defaultdict(dict)
@@ -28,24 +28,14 @@
2828
functions = {}
2929

3030
# Function for parsing line comments
31-
def parse_inline_doc_or_raise(line: str, current_doc: List[str]):
31+
def parse_inline_doc_or_print_error(current_doc, filename, line, lineno):
3232
if '-- ' in line:
3333
if len(current_doc) > 0:
34-
raise ValueError(
35-
'Documented entity has both a pre- and inline documentation; only one is allowed. Offending line:\n' +
36-
line)
34+
logger.warning(f"SPHINX-VHDL: Documented entity has both a pre- and inline documentation; only one is allowed!\n Offending line: {line}", location=f"{filename}:{lineno}")
3735
else:
3836
current_doc.append(line.split('-- ', 1)[1])
3937

4038

41-
def parse_inline_doc_or_print_error(current_doc, filename, line, lineno):
42-
try:
43-
parse_inline_doc_or_raise(line, current_doc)
44-
except ValueError as ex:
45-
LOG.warning(f'Error parsing file {filename} at line {lineno}:')
46-
LOG.warning(ex.args)
47-
48-
4939
class ParseState(Enum):
5040
ENTITY_DECL = auto()
5141
ARCH_DECL = auto()
@@ -79,24 +69,25 @@ def init(path: str) -> None:
7969
for line in source_code:
8070
lineno += 1
8171
line = line.strip()
72+
line_lowercase = line.lower()
8273
# Group parsing logic
8374
if state == ParseState.PORT and group_state == ParseState.GENERIC:
8475
current_group = ""
8576

8677
# Line comments logic
87-
if line.startswith('-- '):
78+
if line_lowercase.startswith('-- '):
8879
# Logic for sampling names of groups of ports and generics
89-
if (state == ParseState.PORT or state == ParseState.GENERIC) and '====' in line:
80+
if (state == ParseState.PORT or state == ParseState.GENERIC) and '====' in line_lowercase:
9081
group_state = state
9182
state = ParseState.GROUPS
9283
current_group = ""
9384
current_doc = []
94-
elif state == ParseState.GROUPS and current_group != '' and '====' not in line:
85+
elif state == ParseState.GROUPS and current_group != '' and '====' not in line_lowercase:
9586
current_doc.append(line[3:])
96-
elif state == ParseState.GROUPS and '====' not in line:
87+
elif state == ParseState.GROUPS and '====' not in line_lowercase:
9788
current_group = current_entity + " " + line[3:].strip()
9889
current_doc = []
99-
elif state == ParseState.GROUPS and '====' in line:
90+
elif state == ParseState.GROUPS and '====' in line_lowercase:
10091
group_definition = current_doc
10192
groups_desc[current_group] = group_definition
10293
state = group_state
@@ -105,12 +96,12 @@ def init(path: str) -> None:
10596
current_doc.append(line[3:])
10697

10798
# If line start with keyword architecture then save name of architecture
108-
elif line.lower().startswith('architecture'):
99+
elif line_lowercase.startswith('architecture'):
109100
state = ParseState.ARCH_DECL
110101
current_constant = line.split()[3]
111102

112103
# If line contains keyword constant and state is not generice then start to collecting constants
113-
elif state == ParseState.ARCH_DECL and 'constant' in line:
104+
elif state == ParseState.ARCH_DECL and 'constant' in line_lowercase:
114105
parse_inline_doc_or_print_error(current_doc, filename, line, lineno)
115106
definition = line.split('--')[0].split(';')[0]
116107
if ':=' not in definition:
@@ -120,30 +111,30 @@ def init(path: str) -> None:
120111
current_doc = []
121112

122113
# If there is -- without gap, then ignore
123-
elif line == '--':
114+
elif line_lowercase == '--':
124115
current_doc.append('')
125116

126117
# If there is word entity then try parse, save entity name and add description of entity to associative array
127118
# ID of ass. array is name of entity. At the end clear current description and change state to entity declaration
128-
elif line.lower().startswith('entity ') and ' is' in line:
119+
elif line_lowercase.startswith('entity ') and ' is' in line_lowercase:
129120
parse_inline_doc_or_print_error(current_doc, filename, line, lineno)
130121
current_entity = line.split()[1]
131122
entities[current_entity.lower()] = current_doc
132123
current_doc = []
133124
state = ParseState.ENTITY_DECL
134125

135126
# Check if there is any port declaration
136-
elif state == ParseState.ENTITY_DECL and line.lower().startswith('port'):
127+
elif state == ParseState.ENTITY_DECL and line_lowercase.startswith('port'):
137128
state = ParseState.PORT
138129
current_doc = []
139130

140131
# Check if there is any generic declaration
141-
elif state == ParseState.ENTITY_DECL and line.lower().startswith('generic'):
132+
elif state == ParseState.ENTITY_DECL and line_lowercase.startswith('generic'):
142133
state = ParseState.GENERIC
143134
current_doc = []
144135

145136
# If there is line which contains ":" then it's one of ports, parse it and save his definition
146-
elif state == ParseState.PORT and ':' in line:
137+
elif state == ParseState.PORT and ':' in line_lowercase:
147138
parse_inline_doc_or_print_error(current_doc, filename, line, lineno)
148139
definition = line.split('--')[0].split(';')[0].split(':=')[0].strip()
149140
if definition.lower().startswith('signal'):
@@ -157,7 +148,7 @@ def init(path: str) -> None:
157148
current_doc = []
158149

159150
# If there is line which contains ":" then it's one of generic, parse it and save his definition
160-
elif state == ParseState.GENERIC and ':' in line:
151+
elif state == ParseState.GENERIC and ':' in line_lowercase:
161152
parse_inline_doc_or_print_error(current_doc, filename, line, lineno)
162153
definition = line.split('--')[0].split(';')[0].strip()
163154
if ':=' not in definition:
@@ -173,27 +164,27 @@ def init(path: str) -> None:
173164
current_doc = []
174165

175166
# End of the entity was found
176-
elif state == ParseState.ENTITY_DECL and line.lower().startswith('end'):
167+
elif state == ParseState.ENTITY_DECL and line_lowercase.startswith('end'):
177168
state = None
178169
group_state = None
179170
current_doc = []
180171

181172
# If there is magic word package then parse package and save his definition
182-
elif (state is None or state is ParseState.PACKAGE) and line.lower().startswith('package'):
173+
elif (state is None or state is ParseState.PACKAGE) and line_lowercase.startswith('package'):
183174
parse_inline_doc_or_print_error(current_doc, filename, line, lineno)
184175
state = ParseState.PACKAGE
185176
current_package = ('' if current_package == '' else (current_package + '.')) + line.split()[1]
186177
packages[current_package.lower()] = current_doc
187178
current_doc = []
188179

189180
# Signalization of end of the package
190-
elif state is ParseState.PACKAGE and line.lower().startswith('end package'):
181+
elif state is ParseState.PACKAGE and line_lowercase.startswith('end package'):
191182
current_package = '.'.join(current_package.split('.')[:-1])
192183
state = None if current_package == '' else ParseState.PACKAGE
193184
current_doc = []
194185

195186
# Package contains type, parse it
196-
elif (state is None or state is ParseState.PACKAGE) and line.lower().startswith('type'):
187+
elif (state is None or state is ParseState.PACKAGE) and line_lowercase.startswith('type'):
197188
if ' record' in line.split('--')[0].lower().split(maxsplit=2)[-1]:
198189
parse_inline_doc_or_print_error(current_doc, filename, line, lineno)
199190
records[line.split()[1]] = current_doc
@@ -212,7 +203,7 @@ def init(path: str) -> None:
212203
current_doc = []
213204

214205
# Signalization of the end of record
215-
elif state is ParseState.RECORD and line.lower().startswith('end record'):
206+
elif state is ParseState.RECORD and line_lowercase.startswith('end record'):
216207
if current_package != '':
217208
state = ParseState.PACKAGE
218209
else:
@@ -228,16 +219,16 @@ def init(path: str) -> None:
228219

229220
# Enumarate parsing
230221
elif state is ParseState.ENUM:
231-
if not line.startswith(')'):
222+
if not line_lowercase.startswith(')'):
232223
parse_inline_doc_or_print_error(current_doc, filename, line, lineno)
233224
enumvals[current_type_name][line.split(',')[0]] = current_doc
234225
current_doc = []
235226

236227
# Function parsing
237-
elif line.lower().startswith('function') and line.split('--')[0].strip().endswith(';'):
228+
elif line_lowercase.startswith('function') and line.split('--')[0].strip().endswith(';'):
238229
parse_inline_doc_or_print_error(current_doc, filename, line, lineno)
239230
return_type = '' if 'return' not in line else (line.split('return')[1].strip()[:-1] + '.')
240-
functions[return_type + line.lower().split()[1]] = current_doc
231+
functions[return_type + line_lowercase.split()[1]] = current_doc
241232
current_doc = []
242233

243234
# Ignore others

0 commit comments

Comments
 (0)