I'd like to document an INI file in my Sphinx documentation. What markup should I use?
Whenever I search the Web I get description of Sphinx configuration fileāconf.py.
The standard domain has some tools to document command-line programs and one could use describe (object) role but as the documentation states "This directive produces the same formatting as the specific ones provided by domains, but does not create index entries or cross-referencing targets".
I need something more specific to describe sections and options and to be able to refer to them.
So having an INI file:
[ui]
username = Mike
e-mail = mike#domain.com
I would like to be able to use something like this:
.. ini:section:: ui
This section contains setting for use interface
.. ini:option:: username
User name
...
Is there better way to do that than writing my own extension?
After studying Sphinx and extensions' source code, this is a minimal solution I came up with. Put the snippet into your conf.py:
from sphinx.application import Sphinx
from sphinx.util.docfields import Field
def setup(app: Sphinx):
app.add_object_type(
'confval',
'confval',
objname='configuration value',
indextemplate='pair: %s; configuration value',
doc_field_types=[
Field('type', label='Type', has_arg=False, names=('type',)),
Field('default', label='Default', has_arg=False, names=('default',)),
]
)
This adds a pair of directive .. confval:: and a role :confval: that mimic the .. option::/:option: or .. envvar::/:envvar: pairs.
Example
Configuration
-------------
For more verbose output, increase the :confval:`verbose` parameter.
To show the traceback, set :confval:`show_traceback = True <show_traceback>`.
.. confval:: verbose
:type: integer
:default: 0
More verbose output.
.. confval:: show_traceback
:type: boolean
:default: ``False``
Show traceback on errors.
.. confval:: output
:type: string
:default: ``-``
Target path to write the output.
renders as
allowing for nice crossrefs throughout the docs.
Related
In Markdown, one can create an inline code link like so
[`dict.update`](https://docs.python.org/3/library/stdtypes.html#dict.update)
Which renders like dict.update. How can get a similar behaviour in reStructuredText / Sphinx? I tried (1) using a converter but it never results in something similar (2) nesting external link `link <link>`_ and inline code block :code:`dict.update`, but that din't work either.
The right way to do this is using the sphinx.ext.intersphinx extension.
In your conf.py add
extensions = [
'sphinx.ext.intersphinx', # the last entry does not use a comma.
# 'sphinx.ext.autodoc', # just for example so there is more than 1 line.
]
intersphinx_mapping = {'python': ('https://docs.python.org/3', None)}
# If you having an `objects.inv` for local builds
# intersphinx_mapping = {"python": ("https://docs.python.org/3", 'objects.inv'),}
Then in your .rst file or in the docstrings in the .py files write a simple cross-reference. Notice that dict.update is a method thus the right role (:py:meth:) should be used when cross-referencing. The following example
A simple text to :meth:`dict.update`
Would give the below HTML output (the tooltip and link of the cross-reference also included in the screenshot)
How can I pass results of a python script to a adoc (AsciiDoc)? I currently can not find a solution. Can someone give me tips or sources on this?
You can copy the output of a Python script (or any program) into a file, and then include that file within a source block.
For example:
[source]
----
include::path/to/python/output.txt[]
----
If the output is in a known format, say JSON, you can include a language hint:
[source,json]
----
include::path/to/python/produced.json[]
----
Depending on the styles in use by your Asciidoc processor, those examples should appear with the same styling as any source code block. If you are using the syntax highlighter, adding the language hint should enable colorized output.
I want to write a script that generates reports for each team in my unit where each report uses the same template, but where the numbers specific to each team is used for each report. The report should be in a format like .pdf that non-programmers know how to open and read. This is in many ways similar to rmarkdown for R, but the reports I want to generate are based on data from code already written in python.
The solution I am looking for does not need to export directly to pdf. It can export to markdown and then I know how to convert. I do not need any fancier formatting than what markdown provides. It does not need to be markdown, but I know how to do everything else in markdown, if I only find a way to dynamically populate numbers and text in a markdown template from python code.
What I need is something that is similar to the code block below, but on a bigger scale and instead of printing output on screen this would saved to a file (.md or .pdf) that can then be shared with each team.
user = {'name':'John Doe', 'email':'jd#example.com'}
print('Name is {}, and email is {}'.format(user["name"], user["email"]))
So the desired functionality heavily influenced by my previous experience using rmarkdown would look something like the code block below, where the the template is a string or a file read as a string, with placeholders that will be populated from variables (or Dicts or objects) from the python code. Then the output can be saved and shared with the teams.
user = {'name':'John Doe', 'email':'jd#example.com'}
template = 'Name is `user["name"]`, and email is `user["email"]`'
output = render(template, user)
When trying to find a rmarkdown equivalent in python, I have found a lot of pointers to Jupyter Notebook which I am familiar with, and very much like, but it is not what I am looking for, as the point is not to share the code, only a rendered output.
Since this question was up-voted I want to answer my own question, as I found a solution that was perfect for me. In the end I shared these reports in a repo, so I write the reports in markdown and do not convert them to PDF. The reason I still think this is an answer to my original quesiton is that this works similar to creating markdown in Rmarkdown which was the core of my question, and markdown can easily be converted to PDF.
I solved this by using a library for backend generated HTML pages. I happened to use jinja2 but there are many other options.
First you need a template file in markdown. Let say this is template.md:
## Overview
**Name:** {{repo.name}}<br>
**URL:** {{repo.url}}
| Branch name | Days since last edit |
|---|---|
{% for branch in repo.branches %}
|{{branch[0]]}}|{{branch[1]}}|
{% endfor %}
And then you have use this in your python script:
from jinja2 import Template
import codecs
#create an dict will all data that will be populate the template
repo = {}
repo.name = 'training-kit'
repo.url = 'https://github.com/github/training-kit'
repo.branches = [
['master',15],
['dev',2]
]
#render the template
with open('template.md', 'r') as file:
template = Template(file.read(),trim_blocks=True)
rendered_file = template.render(repo=repo)
#output the file
output_file = codecs.open("report.md", "w", "utf-8")
output_file.write(rendered_file)
output_file.close()
If you are OK with your dynamic doc being in markdown you are done and the report is written to report.py. If you want PDF you can use pandoc to convert.
I would strongly recommend to install and use the pyFPDF Library, that enables you to write and export PDF files directly from python. The Library was ported from php and offers the same functionality as it's php-variant.
1.) Clone and install pyFPDF
Git-Bash:
git clone https://github.com/reingart/pyfpdf.git
cd pyfpdf
python setup.py install
2.) After successfull installation, you can use python code similar as if you'd work with fpdf in php like:
from fpdf import FPDF
pdf = FPDF()
pdf.add_page()
pdf.set_xy(0, 0)
pdf.set_font('arial', 'B', 13.0)
pdf.cell(ln=0, h=5.0, align='L', w=0, txt="Hello", border=0)
pdf.output('myTest.pdf', 'F')
For more Information, take a look at:
https://pypi.org/project/fpdf/
To work with pyFPDF clone repo from: https://github.com/reingart/pyfpdf
pyFPDF Documentation:
https://pyfpdf.readthedocs.io/en/latest/Tutorial/index.html
I'm trying to extract the DTD information from an XML document using Python and preferably the standard library. At first glance, it seems xml.sax.handler.DTDHandler is the way to go, so I wrote the following example code to extract the DTD of a trivial DocBook v4 document:
import xml.sax
from contextlib import closing
XML_CODE = '''<!DOCTYPE example PUBLIC
"-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
<example><title>Hello World in Python</title>
<programlisting>
print('Hello World!')
</programlisting>
</example>'''
class DTDPrinter(xml.sax.handler.DTDHandler):
def notationDecl(self, name, publicId, systemId):
print('name={}, publicId={}'.format(name, publicId))
if __name__ == '__main__':
with closing(xml.sax.make_parser()) as parser:
parser.setFeature(xml.sax.handler.feature_external_pes, False)
parser.setFeature(xml.sax.handler.feature_validation, False)
parser.setDTDHandler(DTDPrinter())
print('---------- before feed')
parser.feed(XML_CODE)
print('---------- after feed')
My expectation was that when running this code with Python 3.5 the output would be something like:
---------- before feed
name=example, publicId=-//OASIS//DTD DocBook XML V4.1.2//EN
---------- after feed
Instead I get an output with DTD's seemingly related to various image formats but not the one specified in the document:
---------- before feed
name=BMP, publicId=+//ISBN 0-7923-9432-1::Graphic Notation//NOTATION Microsoft Windows bitmap//EN
name=CGM-CHAR, publicId=ISO 8632/2//NOTATION Character encoding//EN
name=CGM-BINARY, publicId=ISO 8632/3//NOTATION Binary encoding//EN
...
name=WMF, publicId=+//ISBN 0-7923-9432-1::Graphic Notation//NOTATION Microsoft Windows Metafile//EN
name=WPG, publicId=None
name=linespecific, publicId=None
---------- after feed
Although maybe the last entry with the name linespecific might refer to the document DTD in a crippled way?
I also noticed a couple of seconds delay after the last output despite the document being trivial. Maybe the parsers attempts to connect to the internet? I tried to disable this by settings the features
parser.setFeature(xml.sax.handler.feature_external_pes, False)
parser.setFeature(xml.sax.handler.feature_validation, False)
but to no avail.
How can I convince the DTDHandler to react to the DTD occurring in the document and not connect to the internet?
As I didn't receive an answer and couldn't get this to work properly in the past 2 weeks I resorted to violence and simply used a regular expression to extract the information. This is ugly and won't be able to properly process all valid ways to express a DTD but is good enough for my purpose.
import re
DTD_REGEX = re.compile(
r'<!DOCTYPE\s+(?P<name>[a-zA-Z][a-zA-Z-]*)\s+PUBLIC\s+"(?P<public_id>.+)"')
dtd_match = DTD_REGEX.match(XML_CODE)
if dtd_match is not None:
public_id = dtd_match.group('public_id')
print(public_id)
I find the default code example font in the PDF generated by Sphinx to be far too large.
I've tried getting my hands dirty in the generated .tex file inserting font size commands like \tiny above the code blocks, but it just makes the line above the code block tiny, not the code block itself.
I'm not sure what else to do - I'm an absolute beginner with LaTeX.
I worked it out. Pygments uses a \begin{Verbatim} block to denote code snippets, which uses the fancyvrb package. The documentation I found (warning: PDF) mentions a formatcom option for the verbatim block.
Pygments' latex writer source indicates an instance variable, verboptions, is stapled to the end of each verbatim block and Sphinx' latex bridge lets you replace the LatexFormatter.
At the top of my conf.py file, I added the following:
from sphinx.highlighting import PygmentsBridge
from pygments.formatters.latex import LatexFormatter
class CustomLatexFormatter(LatexFormatter):
def __init__(self, **options):
super(CustomLatexFormatter, self).__init__(**options)
self.verboptions = r"formatcom=\footnotesize"
PygmentsBridge.latex_formatter = CustomLatexFormatter
\footnotesize was my preference, but a list of sizes is available here
To change Latex Output options in sphinx, set the relevant latex_elements key in the build configuration file, documentation on this is located here.
To change the font size for all fonts use pointsize.
E.g.
latex_elements = {
'pointsize':'10pt'
}
To change other Latex settings that are listed in the documetntation use preamble or use a custom document class in latex_documents.
E.g.
mypreamble='''customlatexstuffgoeshere
'''
latex_elements = {
'papersize':'letterpaper',
'pointsize':'11pt',
'preamble':mypreamble
}
Reading the Sphinx sourcecode by default the code in LatexWriter sets code snippets to the \code latex primitive.
So what you want to do is replace the \code with a suitable replacement.
This is done by including a Latex command like \newcommand{\code}[1]{\texttt{\tiny{#1}}} either as part of the preamble or as part of a custom document class for sphinx that gets set in latex_documents as the documentclass key. An example sphinx document class is avaliable here.
Other than just making it smaller with \tiny you can modify the latex_documents document class or the latex_elements preamble to use the Latex package listings for more fancy code formatting like in the StackOverflow question here.
The package stuff from the linked post would go as a custom document class and the redefinition similar to \newcommand{\code}[1]{\begin{lstlisting} #1 \end{lstlisting}} would be part of the preamble.
Alternatively you could write a sphinx extension that extends the default latex writer with a custom latex writer of your choosing though that is significantly more effort.
Other relevant StackOverflow questions include
Creating Math Macros with Sphinx
How do I disable colors in LaTeX output generated from sphinx?
sphinx customization of latexpdf output?
You can add a modified Verbatim command into your PREAMBLE (Note in this case the font size is changed to tiny)
\renewcommand{\Verbatim}[1][1]{%
% list starts new par, but we don't want it to be set apart vertically
\bgroup\parskip=0pt%
\smallskip%
% The list environement is needed to control perfectly the vertical
% space.
\list{}{%
\setlength\parskip{0pt}%
\setlength\itemsep{0ex}%
\setlength\topsep{0ex}%
\setlength\partopsep{0pt}%
\setlength\leftmargin{10pt}%
}%
\item\MakeFramed {\FrameRestore}%
\tiny % <---------------- To be changed!
\OriginalVerbatim[#1]%
}