Improving Custom PyPI Theme Support In Yaydoc

Yaydoc has been supporting custom themes from nearly it’s inception. Themes, which it could not find locally, it would automatically try to install it via pip and set up appropriate metadata about the themes in the generated conf.py.  It was one of the first major enhancement we provided as compared to when using bare sphinx to generate documentation. Since then, a large number of features have been added to ease the process of documentation generation but the core theming aspects have remained unchanged. To use a theme, sphinx needs the exact name of the theme and the absolute path to it. To obtain these metadata, the existing implementation accessed the __file__ attribute of the imported package to get the absolute path to the __init__.py file, a necessary element of all python packages. From there we searched for a file named theme.conf, and thus the directory containing that file was our required theme. There were a few mistakes in our earlier implementation. For starters, we assumed that the distribution name of the theme in PyPI and the package name which should be imported would be same. This is generally true but is not necessary. One such theme from PyPI is Flask-Sphinx-Themes. While you need to install it using pip install Flask-Sphinx-Themes yet to import it in a module one needs to import flask_sphinx_themes This lead to build errors when specific themes like this was used. To solve this, we used the pkg_resources package. It allows us to get various metadata about a package in an abstract way without needing to specifically handle if the package is zipped or not. try: dist = pkg_resources.get_distribution('{{ html_theme }}') top_level = list(dist._get_metadata('top_level.txt'))[0] dist_path = os.path.join(dist.location, top_level) except (pkg_resources.DistributionNotFound, IndexError): print("\nError with distribution {0}".format('{{ html_theme }}')) html_theme = 'fossasia_theme' html_theme_path = ['_themes'] The idea here is that instead of searching for __init__.py, we read the name of the top_level directory using the first entry of the top_level.txt, a file created by setuptools when installing the package. We build the path by joining the location attribute of the Distribution object and the name of the top_level directory. The advantage with this approach is that we don’t need to import anything and thus no longer need to know the exact package name. With this update, Support for custom themes has been greatly increased. Resources Sphinx - Documentation Generator Setuptools - Official Documentation

Continue ReadingImproving Custom PyPI Theme Support In Yaydoc

Using custom themes with Yaydoc to build documentation

What is Yaydoc? Yaydoc aims to be a one stop solution for all your documentation needs. It is continuously integrated to your repository and builds the site on each commit. One of it's primary aim is to minimize user configuration. It is currently in active development. Why Themes? Themes gives the user ability to generate visually different sites with the same markup documents without any configuration. It is one of the many features Yaydoc inherits from sphinx. Now sphinx comes with 10 built in themes but there are much more custom themes available on PyPI, the official Python package repository. To use these custom themes, sphinx requires some setup. But Yaydoc being an automated system needs to performs those tasks automatically. To use a custom theme which has been installed, sphinx needs to know the name of the theme and where to find it. We do that by specifying two variables in the sphinx configuration file. html_theme and html_theme_path respectively. Custom themes provide a method that can be called to get the html_theme_path of the theme. Usually that method is named get_html_theme_path . But that is not always the case. We have no way find the appropriate method automatically. So how do we get the path of an installed theme just by it’s name and how do we add it to the generated configuration file. The configuration file is generated by the sphinx-quickstart command which Yaydoc uses to initialize the documentation directory. We can override the default generated files by providing our own project templates. The templates are based on the Jinja2 template engine. Firstly, I replaced html_theme = ‘alabaster’ With html_theme = ‘{{ html_theme }}’ This provides us the ability to pass the name of the theme as a parameter to sphinx-quickstart. Now the user has an option to choose between 10 built-in themes. For custom themes however there is a different story. I had to solve two major issues. The name of the package and the theme may differ. We also need the absolute path to the theme. The following code snippet solves the above mentioned problems. {% if html_theme in (['alabaster', 'classic', 'sphinxdoc', 'scrolls', 'agogo', 'traditional', 'nature', 'haiku', 'pyramid', 'bizstyle']) %} # Theme is builtin. Just set the name html_theme = '{{ html_theme }}' {% else %} # Theme is a custom python package. Lets install it. import pip exitcode = pip.main(['install', '{{ html_theme }}']) if exitcode: # Non-zero exit code print("""{0} is not available on pypi. Please ensure the theme can be installed using 'pip install {0}'.""".format('{{ html_theme }}'), file=sys.stderr) else: import {{ html_theme }} def get_path_to_theme(): package_path = os.path.dirname({{ html_theme }}.__file__) for root, dirs, files in os.walk(package_path): if 'theme.conf' in files: return root path_to_theme = get_path_to_theme() if path_to_theme is None: print("\n{0} does not appear to be a sphinx theme.".format('{{ html_theme }}'), file=sys.stderr) html_theme = 'alabaster' else: html_theme = os.path.basename(path_to_theme) html_theme_path = [os.path.abspath(os.path.join(path_to_theme, os.pardir))] {% endif %} It performs the following tasks in order: It first checks if the provided theme is one of the built…

Continue ReadingUsing custom themes with Yaydoc to build documentation