aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
author1138-4EB <1138-4EB@users.noreply.github.com>2019-02-23 23:03:41 +0100
committertgingold <tgingold@users.noreply.github.com>2019-02-25 07:28:45 +0100
commitfb6fa7ceced6e74ae02ed24b92a488c6e65d3404 (patch)
treee868b6cb14074b81618d148d9f58077fb308924d
parent5040ad31d9e7ac3f7d459e388b734a917ce412f2 (diff)
downloadghdl-fb6fa7ceced6e74ae02ed24b92a488c6e65d3404.tar.gz
ghdl-fb6fa7ceced6e74ae02ed24b92a488c6e65d3404.tar.bz2
ghdl-fb6fa7ceced6e74ae02ed24b92a488c6e65d3404.zip
doc: add custom directive 'exec', generate releases shields and tables
with json data retrieved from github api"
-rw-r--r--doc/build.sh27
-rw-r--r--doc/conf.py8
-rw-r--r--doc/exec.py36
-rw-r--r--doc/getting/Releases.rst96
-rw-r--r--doc/helpers.py216
-rw-r--r--doc/requirements.txt1
6 files changed, 330 insertions, 54 deletions
diff --git a/doc/build.sh b/doc/build.sh
new file mode 100644
index 000000000..98d9039b9
--- /dev/null
+++ b/doc/build.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+set -e
+
+cd $(dirname $0)/..
+
+$(command -v winpty) docker run --rm -t \
+ -v /$(pwd)://src \
+ -w //src/doc \
+ btdi/sphinx:py3-featured sh -c "$(cat <<-EOF
+pip install -r requirements.txt
+sphinx-build -T -b html -D language=en . _build/html
+sphinx-build -T -b latex -D language=en . _build/latex
+EOF
+)"
+
+$(command -v winpty) docker run --rm -t \
+ -v /$(pwd)://src \
+ -w //src/doc \
+ btdi/latex sh -c "$(cat <<-EOF
+cd _build/latex
+FILE=\"\`ls *.tex | sed -e 's/\.tex//'\`\"
+pdflatex -interaction=nonstopmode \$FILE.tex;
+makeindex -s python.ist \$FILE.idx;
+pdflatex -interaction=nonstopmode \$FILE.tex;
+EOF
+)"
diff --git a/doc/conf.py b/doc/conf.py
index 31b20c948..efa30f23e 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -12,11 +12,7 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
-import sys
-import os
-import shlex
-import re
-import subprocess
+import sys, os, shlex, re, subprocess
# http://docs.readthedocs.io/en/latest/getting_started.html#in-markdown
from recommonmark.parser import CommonMarkParser
@@ -51,6 +47,8 @@ extensions = [
# SphinxContrib extensions
# 'sphinxcontrib.textstyle',
# 'sphinxcontrib.spelling',
+# Other
+ 'exec',
]
# Add any paths that contain templates here, relative to this directory.
diff --git a/doc/exec.py b/doc/exec.py
new file mode 100644
index 000000000..f6ad8a8e8
--- /dev/null
+++ b/doc/exec.py
@@ -0,0 +1,36 @@
+# https://stackoverflow.com/questions/7250659/how-to-use-python-to-programmatically-generate-part-of-sphinx-documentation/18143318
+
+import sys
+from os.path import basename
+
+try:
+ from StringIO import StringIO
+except ImportError:
+ from io import StringIO
+
+from docutils.parsers.rst import Directive
+from docutils import nodes, statemachine
+
+class ExecDirective(Directive):
+ """Execute the specified python code and insert the output into the document"""
+ has_content = True
+
+ def run(self):
+ oldStdout, sys.stdout = sys.stdout, StringIO()
+
+ tab_width = self.options.get('tab-width', self.state.document.settings.tab_width)
+ source = self.state_machine.input_lines.source(self.lineno - self.state_machine.input_offset - 1)
+
+ try:
+ exec('\n'.join(self.content))
+ text = sys.stdout.getvalue()
+ lines = statemachine.string2lines(text, tab_width, convert_whitespace=True)
+ self.state_machine.insert_input(lines, source)
+ return []
+ except Exception:
+ return [nodes.error(None, nodes.paragraph(text = "Unable to execute python code at %s:%d:" % (basename(source), self.lineno)), nodes.paragraph(text = str(sys.exc_info()[1])))]
+ finally:
+ sys.stdout = oldStdout
+
+def setup(app):
+ app.add_directive('exec', ExecDirective)
diff --git a/doc/getting/Releases.rst b/doc/getting/Releases.rst
index 6b85decb5..81286a14a 100644
--- a/doc/getting/Releases.rst
+++ b/doc/getting/Releases.rst
@@ -11,61 +11,51 @@ Releases and sources
Downloading pre-built packages
******************************
-.. |Strect-mcode-gpl| image:: https://img.shields.io/github/downloads/ghdl/ghdl/v0.35/ghdl-gpl-0.35-mcode.tgz.svg?longCache=true&style=flat-square&logo=github
- :target: https://github.com/ghdl/ghdl/releases/download/v0.35/ghdl-gpl-0.35-mcode.tgz
- :alt: ghdl-gpl-0.35-mcode.tgz
-.. |Strect-mcode| image:: https://img.shields.io/github/downloads/ghdl/ghdl/v0.35/ghdl-0.35-mcode-stretch.tgz.svg?longCache=true&style=flat-square&logo=github
- :target: https:// github.com/ghdl/ghdl/releases/download/v0.35/ghdl-0.35-mcode-stretch.tgz
- :alt: ghdl-0.35-mcode-stretch.tgz
-.. |Ubu1404-mcode| image:: https://img.shields.io/github/downloads/ghdl/ghdl/v0.35/ghdl-0.35-mcode-ubuntu14.tgz.svg?longCache=true&style=flat-square&logo=github
- :target: https://github.com/ghdl/ghdl/releases/download/v0.35/ghdl-0.35-mcode-ubuntu14.tgz
- :alt: ghdl-0.35-mcode-ubuntu14.tgz
-.. |Ubu1404-llvm38| image:: https://img.shields.io/github/downloads/ghdl/ghdl/v0.35/ghdl-0.35-llvm-3.8-ubuntu14.tgz.svg?longCache=true&style=flat-square&logo=github
- :target: https://github.com/ghdl/ghdl/releases/download/v0.35/ghdl-0.35-llvm-3.8-ubuntu14.tgz
- :alt: ghdl-0.35-llvm-3.8-ubuntu14.tgz
-.. |Fedora26-mcode| image:: https://img.shields.io/github/downloads/ghdl/ghdl/v0.35/ghdl-0.35-mcode-fedora26.tgz.svg?longCache=true&style=flat-square&logo=github
- :target: https://github.com/ghdl/ghdl/releases/download/v0.35/ghdl-0.35-mcode-fedora26.tgz
- :alt: ghdl-0.35-mcode-fedora26.tgz
-.. |Win32-mcode| image:: https://img.shields.io/github/downloads/ghdl/ghdl/v0.35/ghdl-v0.35-mingw32-mcode.zip.svg?longCache=true&style=flat-square&logo=github
- :target: https://github.com/ghdl/ghdl/releases/download/v0.35/ghdl-v0.35-mingw32-mcode.zip
- :alt: ghdl-v0.35-mingw32-mcode.zip
-.. |Win64-llvm| image:: https://img.shields.io/github/downloads/ghdl/ghdl/v0.35/ghdl-v0.35-mingw64-llvm.zip.svg?longCache=true&style=flat-square&logo=github
- :target: https://github.com/ghdl/ghdl/releases/download/v0.35/ghdl-v0.35-mingw64-llvm.zip
- :alt: ghdl-v0.35-mingw64-llvm.zip
-.. |MacOS-mcode| image:: https://img.shields.io/github/downloads/ghdl/ghdl/v0.35/ghdl-0.35-mcode-macosx.tgz.svg?longCache=true&style=flat-square&logo=github
- :target: https://github.com/ghdl/ghdl/releases/download/v0.35/ghdl-0.35-mcode-macosx.tgz
- :alt: ghdl-0.35-mcode-macosx.tgz
-.. |Sum| image:: https://img.shields.io/github/downloads/ghdl/ghdl/v0.35/total.svg?longCache=true&style=flat-square&logo=github
- :target: https://github.com/ghdl/ghdl/releases/tag/v0.35
- :alt: Downloads of GHDL v0.35
-
-+------------------------+----------+-----------+--------------------+
-| OS | Backend | Filesize | Downloads |
-+========================+==========+===========+====================+
-| Debian 9 (Stretch) GPL | mcode | 2.61 MB | |Strect-mcode-gpl| |
-+------------------------+----------+-----------+--------------------+
-| Debian 9 (Stretch) | mcode | 2.93 MB | |Strect-mcode| |
-+------------------------+----------+-----------+--------------------+
-| Ubuntu 14 (Trusty) | mcode | 3.15 MB | |Ubu1404-mcode| |
-+------------------------+----------+-----------+--------------------+
-| Ubuntu 14 (Trusty) | LLVM | 14.11MB | |Ubu1404-llvm38| |
-+------------------------+----------+-----------+--------------------+
-| Fedora 26 | mcode | 2.83 MB | |Fedora26-mcode| |
-+------------------------+----------+-----------+--------------------+
-| Windows x86 (MinGW32) | mcode | 3.05 MB | |Win32-mcode| |
-+------------------------+----------+-----------+--------------------+
-| Windows x86 (MinGW64) | LLVM | 12.7 MB | |Win64-llvm| |
-+------------------------+----------+-----------+--------------------+
-| Mac OS X | mcode | 2.26 MB | |MacOS-mcode| |
-+------------------------+----------+-----------+--------------------+
-| Sum: | | | |Sum| |
-+------------------------+----------+-----------+--------------------+
+.. TODO How to extend this directive to use `.. only:: html` and `.. only:: html` in the python code passed to it?
+
+.. exec::
+ from helpers import createReleasesShields, printReleaseTab, printReleasesList
+
+ # Optionally, provide a <tag> name to get the assets table of a specific release. By default, the table of 'latest' is returned.
+ data = createReleasesShields()
+
+.. only:: html
+
+ .. exec::
+ from helpers import printReleaseTab
+ printReleaseTab('data')
+
+.. only:: latex
+
+ .. exec::
+ from helpers import printReleaseTab
+ printReleaseTab('data', latex=True)
+
+Pre-built packages of older releases
+====================================
+
+.. only:: html
+
+ .. exec::
+ from helpers import printReleasesList
+ printReleasesList('data')
+
+.. only:: latex
+
+ .. exec::
+ from helpers import printReleasesList
+ printReleasesList('data', latex=True)
.. _RELEASE:Sources:
Downloading Source Files
************************
+.. HINT::
+
+ All the following procedures will retrieve the latest development version of GHDL, i.e., the `master` branch at `github.com/ghdl/ghdl <https://github.com/ghdl/ghdl>`_.
+ We do our best to keep it stable, but bugs can seldom be published. See `HINT` boxes below for instructions to get older releases.
+
.. _RELEASE:Sources:Zip:
Downloading from GitHub
@@ -92,6 +82,10 @@ choose your desired format/version:
| master | |tgz-master| |
+----------+------------------------+
+.. HINT::
+
+ To download a specific version of GHDL, use these alternative URL, where ``<format>`` is ``tar`` or ``zip``: ``https://api.github.com/repos/ghdl/ghdl/<format>ball/<tag>``.
+
.. _RELEASE:Sources:GitClone:
Downloading via ``git clone``
@@ -113,6 +107,10 @@ later instructions or on other pages in this documentation.
| SSH | ssh://git@github.com:ghdl/ghdl.git |
+----------+----------------------------------------+
+.. HINT::
+
+ Execute ``git checkout -b stable <tag>`` after ``git clone``, to checkout a specific version of GHDL.
+
On Linux
--------
diff --git a/doc/helpers.py b/doc/helpers.py
new file mode 100644
index 000000000..dd028037e
--- /dev/null
+++ b/doc/helpers.py
@@ -0,0 +1,216 @@
+# Try to load JSON data from a file. If not found, use the argument as a tag name and retrieve the data from GitHub.
+def getJSON(tag='all'):
+ f = tag
+ tag = '/'+tag
+ if f == 'all':
+ f = 'releases'
+ tag = ''
+
+ import json
+ try:
+ d = json.loads(open(f+'.json', 'r').read())
+ except:
+ from urllib.request import urlopen
+ d = json.loads(urlopen('https://api.github.com/repos/ghdl/ghdl/releases'+tag).read())
+ json.dump(d, open(f+'.json', 'w'), indent=4)
+ return d
+
+#
+# Functions to print table with format `[ [], [], [], ... ]` to reStructuredText
+#
+
+# Print a row of data elements.
+def printTabRow(l, r):
+ printTabItem(l, r, '| ')
+
+# Print a rule. Two characters in 'b' define the type of rule. Expected values are '+-', '+=' or '| '.
+def printTabRule(l, b):
+ printTabItem(l, [b[1] for x in range(len(l))], b)
+
+# Print a full row, be it a rule or data.
+# Extend the width of each field to the size specified in 'l'.
+def printTabItem(l, a, b):
+ for y, z in enumerate(a):
+ print((b + z).ljust(l[y]+3, b[1]), end='')
+ print(b[0])
+
+# Get number of cols from number of elements in row 0.
+# Compute minimum number of characters required for each col.
+def getTabColLens(t):
+ cl = [0 for _ in t[0]]
+ for row in t:
+ for y, z in enumerate(row):
+ cl[y] = max(cl[y], len(z))
+ return cl
+
+# Print a table using the functions above.
+# The first row contains the headers.
+def printTab(t):
+ clens = getTabColLens(t)
+
+ printTabRule(clens, '+-')
+ printTabRow(clens, t[0])
+ printTabRule(clens, '+=')
+ for x in t[1:]:
+ printTabRow(clens, x)
+ printTabRule(clens, '+-')
+ print()
+
+#
+# Print two versions of each shield. Onee for 'html' (`image::`) and one for 'latex' (`replace::`)
+#
+
+# Strip all non-alphanumeric characters when creating the labels
+def stripLabel(label):
+ import re
+ pattern = re.compile('[\W_]+')
+ return pattern.sub('', label)
+
+def printShieldSrc(label, alt, img, target, latex=False):
+ if latex:
+ i = stripLabel(label)
+ if label[-6:] == '/total':
+ label = label[:-6]
+ print('.. |l' + i + '| replace:: `' + label + '`_')
+ print('.. _' + label + ': ' + target + '\n')
+ else:
+ print('.. |' + label + '| image:: '+ img + '\n',
+ ' :target: ' + target + '\n',
+ ' :height: 22\n',
+ ' :alt: ' + alt + '\n')
+
+#
+# Display better OS and Backend names than those represented in the tarball name
+#
+
+def prettyOS(i):
+ if i == 'fedora28':
+ return 'Fedora 28'
+ elif i == 'macosx':
+ return 'Max OS X'
+ elif i == 'mingw32':
+ return 'Windows x86 (MinGW32)'
+ elif i == 'mingw64':
+ return 'Windows x86 (MinGW64)'
+ elif i == 'stretch':
+ return 'Debian 9 (Stretch)'
+ elif i == 'gpl':
+ return 'Debian 9 (Stretch) GPL'
+ elif i == 'ubuntu14':
+ return '14.04 LTS (Trusty Tahr)'
+ return i
+
+def prettyBackend(i):
+ if i == 'llvm':
+ return 'LLVM'
+ if i == 'llvm-3.8':
+ return 'LLVM (3.8)'
+ return i
+
+#
+# Get, extract and process JSON data to create the shields and table with the assets of a release
+#
+
+def createTagShields(data='latest'):
+ if isinstance(data, str):
+ data = getJSON(data)
+
+ assets=[['OS', 'Backend', 'Size', 'Downloads']]
+ tag = data['tag_name']
+ for x in data['assets']:
+ name = x['name']
+ s = []
+
+ p = 'ghdl-gpl-'+tag[1:]
+ if name[0:len(p)] == p:
+ s = ['gpl', 'mcode']
+
+ p = 'ghdl-'+tag[1:]
+ if name[0:len(p)] == p:
+ s = name[len(p)+1:-4].split('-',1)
+
+ if len(s) > 1:
+ assets.append([
+ prettyOS(s[0]),
+ prettyBackend(s[1]),
+ (str(round(x['size']/1024**2, 2))+' MB').rjust(8),
+ '|' + tag + '/' + name + '|']
+ )
+
+ assets.append(['Sum:', '', '', '|'+tag+'/total|'])
+
+ for x in assets[1:-1]:
+ i = x[3][1:-1]
+ for latex in [False, True]:
+ printShieldSrc(i, i,
+ 'https://img.shields.io/github/downloads/ghdl/ghdl/' + i + '.svg?longCache=true&style=flat-square&logo=github&label=%7F',
+ 'https://github.com/ghdl/ghdl/releases/download/' + i, latex=latex)
+
+ return assets
+
+# TODO: Is github.com/ghdl/ghdl/releases/download/<tag>/<file> subject to rate limit? Is there an alternative (not documented) domain?
+
+
+#
+# Get, extract and process JSON data to create the shields and list/table with all the releases except the latest
+#
+
+def createReleasesShields(tag='latest'):
+ d = getJSON()
+ from dateutil.parser import parse as parseTime
+ releases = [['Date', 'Downloads']]
+ if tag == 'latest':
+ t = d[0]
+ for x in d:
+ name = x['tag_name']
+ if tag == name:
+ t = x
+ date = parseTime( x['published_at'] ).strftime("%Y-%m-%d")
+ releases.append([date, '|'+name+'/total|'])
+ i = name
+ for l in [False, True]:
+ printShieldSrc(i+'/total', i+' Total',
+ 'https://img.shields.io/github/downloads/ghdl/ghdl/' + i + '/total.svg?longCache=true&style=flat-square&logo=github&label=%7F',
+ 'https://github.com/ghdl/ghdl/releases/' + i, l)
+
+ out = {'releases': releases, 'assets': createTagShields(t)}
+ import json
+ json.dump(out, open('data.json', 'w'), indent=4)
+ return out
+
+
+#
+# Print the table with all the assets of a release/tag
+#
+
+def printReleaseTab(assets, latex=False):
+ if isinstance(assets, str):
+ assets = getJSON(assets)["assets"]
+
+ if latex:
+ for y, z in enumerate(assets[1:]):
+ assets[y+1] = z[0:3] + ['|l' + stripLabel(z[3][1:-1]) + '|']
+
+ printTab(assets)
+
+#
+# Print list of releases, except the latest (second row)
+#
+
+def printReleasesList(releases, latex=False):
+ if isinstance(releases, str):
+ releases = getJSON(releases)["releases"]
+
+ rs = [releases[0]]
+ rs.extend(releases[2:])
+
+ if latex:
+ rs[0] = ['Release/Tag'] + [rs[0][0]]
+ for x, r in enumerate(rs[1:]):
+ rs[x+1] = ['|l' + stripLabel(r[1][1:-1]) + '|'] + [r[0]]
+ else:
+ rs[0] = ['Release/Tag'] + rs[0]
+ for x, r in enumerate(rs[1:]):
+ rs[x+1] = [r[1][1:-7]] + r
+
+ printTab(rs)
diff --git a/doc/requirements.txt b/doc/requirements.txt
index 42a068479..7e7fe40ed 100644
--- a/doc/requirements.txt
+++ b/doc/requirements.txt
@@ -2,6 +2,7 @@
sphinx>=1.5.2
recommonmark
sphinx_rtd_theme
+python-dateutil
# sphinxcontrib-textstyle>=0.2.1
# sphinxcontrib-spelling>=2.2.0
# changelog>=0.3.5