Drop support for Python 2.3.
[docutils.git] / test / test_writers / test_latex2e.py
blob36accd206eaafe4e5fd6f4a85544ecd184604ed9
1 # -*- coding: utf8 -*-
2 #! /usr/bin/env python
4 # $Id$
5 # Author: engelbert gruber <grubert@users.sourceforge.net>
6 # Copyright: This module has been placed in the public domain.
8 """
9 Tests for latex2e writer.
10 """
12 import string
13 from __init__ import DocutilsTestSupport
15 def suite():
16 settings = {'use_latex_toc': False}
17 s = DocutilsTestSupport.PublishTestSuite('latex', suite_settings=settings)
18 s.generateTests(totest)
19 settings['use_latex_toc'] = True
20 s.generateTests(totest_latex_toc)
21 settings['use_latex_toc'] = False
22 settings['sectnum_xform'] = False
23 s.generateTests(totest_latex_sectnum)
24 settings['sectnum_xform'] = True
25 settings['use_latex_citations'] = True
26 s.generateTests(totest_latex_citations)
27 settings['stylesheet_path'] = 'data/spam,data/ham.tex'
28 s.generateTests(totest_stylesheet)
29 settings['embed_stylesheet'] = True
30 settings['warning_stream'] = ''
31 s.generateTests(totest_stylesheet_embed)
32 return s
34 head_template = string.Template(
35 r"""$head_prefix% generated by Docutils <http://docutils.sourceforge.net/>
36 \usepackage{fixltx2e} % LaTeX patches, \textsubscript
37 \usepackage{cmap} % fix search and cut-and-paste in Acrobat
38 $requirements
39 %%% Custom LaTeX preamble
40 $latex_preamble
41 %%% User specified packages and stylesheets
42 $stylesheet
43 %%% Fallback definitions for Docutils-specific commands
44 $fallbacks$pdfsetup
45 $titledata
46 %%% Body
47 \begin{document}
48 """)
50 parts = dict(
51 head_prefix = r"""\documentclass[a4paper]{article}
52 """,
53 requirements = r"""\usepackage{ifthen}
54 \usepackage[T1]{fontenc}
55 \usepackage[utf8]{inputenc}
56 """,
57 latex_preamble = r"""% PDF Standard Fonts
58 \usepackage{mathptmx} % Times
59 \usepackage[scaled=.90]{helvet}
60 \usepackage{courier}
61 """,
62 stylesheet = '',
63 fallbacks = '',
64 pdfsetup = r"""
65 % hyperlinks:
66 \ifthenelse{\isundefined{\hypersetup}}{
67 \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
68 \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
69 }{}
70 """,
71 titledata = '')
73 head = head_template.substitute(parts)
75 head_table = head_template.substitute(
76 dict(parts, requirements = parts['requirements'] +
77 r"""\usepackage{longtable,ltcaption,array}
78 \setlength{\extrarowheight}{2pt}
79 \newlength{\DUtablewidth} % internal use in tables
80 """))
82 head_textcomp = head_template.substitute(
83 dict(parts, requirements = parts['requirements'] +
84 r"""\usepackage{textcomp} % text symbol macros
85 """))
87 totest = {}
88 totest_latex_toc = {}
89 totest_latex_sectnum = {}
90 totest_latex_citations = {}
91 totest_stylesheet = {}
92 totest_stylesheet_embed = {}
94 totest['url_chars'] = [
95 ["http://nowhere/url_with%28parens%29",
96 head + r"""
97 \url{http://nowhere/url_with\%28parens\%29}
99 \end{document}
100 """],
103 totest['textcomp'] = [
104 ["2 µm is just 2/1000000 m",
105 head_textcomp + r"""
106 2 µm is just 2/1000000 m
108 \end{document}
109 """],
112 totest['spanish quote'] = [
113 [".. role:: language-es\n\nUnd damit :language-es:`basta`!",
114 head_template.substitute(dict(parts, requirements =
115 r"""\usepackage{ifthen}
116 \usepackage[T1]{fontenc}
117 \usepackage[utf8]{inputenc}
118 \usepackage[spanish,english]{babel}
119 \addto\shorthandsspanish{\spanishdeactivate{."~<>}}
120 """)) + r"""
121 Und damit \otherlanguage{spanish}{basta}!
123 \end{document}
124 """],
127 totest['table_of_contents'] = [
128 # input
129 ["""\
130 .. contents:: Table of Contents
132 Title 1
133 =======
134 Paragraph 1.
136 Title 2
137 -------
138 Paragraph 2.
139 """,
140 ## # expected output
141 head_template.substitute(dict(parts,
142 requirements=parts['requirements'] + '\\setcounter{secnumdepth}{0}\n',
143 fallbacks=r"""
144 % title for topics, admonitions, unsupported section levels, and sidebar
145 \providecommand*{\DUtitle}[2][class-arg]{%
146 % call \DUtitle#1{#2} if it exists:
147 \ifcsname DUtitle#1\endcsname%
148 \csname DUtitle#1\endcsname{#2}%
149 \else
150 \smallskip\noindent\textbf{#2}\smallskip%
153 """)) + r"""
154 \phantomsection\label{table-of-contents}
155 \pdfbookmark[1]{Table of Contents}{table-of-contents}
156 \DUtitle[contents]{Table of Contents}
158 \begin{list}{}{}
160 \item \hyperref[title-1]{Title 1}
162 \begin{list}{}{}
164 \item \hyperref[title-2]{Title 2}
166 \end{list}
168 \end{list}
171 \section{Title 1%
172 \label{title-1}%
175 Paragraph 1.
178 \subsection{Title 2%
179 \label{title-2}%
182 Paragraph 2.
184 \end{document}
185 """],
189 totest_latex_toc['no_sectnum'] = [
190 # input
191 ["""\
192 .. contents::
194 first section
195 -------------
196 """,
197 ## # expected output
198 head_template.substitute(dict(parts,
199 requirements=parts['requirements'] + '\\setcounter{secnumdepth}{0}\n'
200 )) + r"""
201 \phantomsection\label{contents}
202 \pdfbookmark[1]{Contents}{contents}
203 \tableofcontents
207 \section{first section%
208 \label{first-section}%
211 \end{document}
212 """],
215 totest_latex_toc['sectnum'] = [
216 # input
217 ["""\
218 .. contents::
219 .. sectnum::
221 first section
222 -------------
223 """,
224 ## # expected output
225 head_template.substitute(dict(parts,
226 requirements=parts['requirements'] + '\\setcounter{secnumdepth}{0}\n'
227 )) + r"""
228 \phantomsection\label{contents}
229 \pdfbookmark[1]{Contents}{contents}
230 \tableofcontents
234 \section{1~~~first section%
235 \label{first-section}%
238 \end{document}
239 """],
243 totest_latex_sectnum['no_sectnum'] = [
244 # input
245 ["""\
246 some text
248 first section
249 -------------
250 """,
251 ## # expected output
252 head_template.substitute(dict(parts, requirements = parts['requirements'] +
253 r"""\setcounter{secnumdepth}{0}
254 """)) + r"""
255 some text
258 \section{first section%
259 \label{first-section}%
262 \end{document}
263 """],
266 totest_latex_sectnum['sectnum'] = [
267 # input
268 ["""\
269 .. sectnum::
271 some text
273 first section
274 -------------
275 """,
276 ## # expected output
277 head_template.substitute(dict(parts,
278 requirements=parts['requirements'] + '\\setcounter{secnumdepth}{0}\n'
279 )) + r"""
280 some text
283 \section{first section%
284 \label{first-section}%
287 \end{document}
288 """],
291 totest_latex_citations['citations_with_underscore'] = [
292 # input
293 ["""\
294 Just a test citation [my_cite2006]_.
296 .. [my_cite2006]
297 The underscore is mishandled.
298 """,
299 ## # expected output
300 head + r"""
301 Just a test citation \cite{my_cite2006}.
303 \begin{thebibliography}{my\_cite2006}
304 \bibitem[my\_cite2006]{my_cite2006}{
305 The underscore is mishandled.
307 \end{thebibliography}
309 \end{document}
310 """],
314 totest_latex_citations['adjacent_citations'] = [
315 # input
316 ["""\
317 Two non-citations: [MeYou2007]_[YouMe2007]_.
319 Need to be separated for grouping: [MeYou2007]_ [YouMe2007]_.
321 Two spaces (or anything else) for no grouping: [MeYou2007]_ [YouMe2007]_.
323 But a line break should work: [MeYou2007]_
324 [YouMe2007]_.
326 .. [MeYou2007] not.
327 .. [YouMe2007] important.
328 """,
329 # expected output
330 head + r"""
331 Two non-citations: {[}MeYou2007{]}\_{[}YouMe2007{]}\_.
333 Need to be separated for grouping: \cite{MeYou2007,YouMe2007}.
335 Two spaces (or anything else) for no grouping: \cite{MeYou2007} \cite{YouMe2007}.
337 But a line break should work: \cite{MeYou2007,YouMe2007}.
339 \begin{thebibliography}{MeYou2007}
340 \bibitem[MeYou2007]{MeYou2007}{
341 not.
343 \bibitem[YouMe2007]{YouMe2007}{
344 important.
346 \end{thebibliography}
348 \end{document}
349 """],
353 totest['enumerated_lists'] = [
354 # input
355 ["""\
356 1. Item 1.
357 2. Second to the previous item this one will explain
359 a) nothing.
360 b) or some other.
362 3. Third is
364 (I) having pre and postfixes
365 (II) in roman numerals.
366 """,
367 # expected output
368 head + r"""\newcounter{listcnt0}
369 \begin{list}{\arabic{listcnt0}.}
371 \usecounter{listcnt0}
372 \setlength{\rightmargin}{\leftmargin}
375 \item Item 1.
377 \item Second to the previous item this one will explain
378 \end{list}
380 \begin{quote}
381 \setcounter{listcnt0}{0}
382 \begin{list}{\alph{listcnt0})}
384 \usecounter{listcnt0}
385 \setlength{\rightmargin}{\leftmargin}
388 \item nothing.
390 \item or some other.
391 \end{list}
393 \end{quote}
394 \setcounter{listcnt0}{0}
395 \begin{list}{\arabic{listcnt0}.}
397 \usecounter{listcnt0}
398 \addtocounter{listcnt0}{2}
399 \setlength{\rightmargin}{\leftmargin}
402 \item Third is
403 \end{list}
405 \begin{quote}
406 \setcounter{listcnt0}{0}
407 \begin{list}{(\Roman{listcnt0})}
409 \usecounter{listcnt0}
410 \setlength{\rightmargin}{\leftmargin}
413 \item having pre and postfixes
415 \item in roman numerals.
416 \end{list}
418 \end{quote}
420 \end{document}
421 """],
424 # BUG: need to test for quote replacing if language is de (ngerman).
426 totest['quote_mangling'] = [
427 # input
428 ["""
429 Depending on language quotes are converted for latex.
430 Expecting "en" here.
432 Inside literal blocks quotes should be left untouched
433 (use only two quotes in test code makes life easier for
434 the python interpreter running the test)::
437 This is left "untouched" also *this*.
440 .. parsed-literal::
442 should get "quotes" and *italics*.
445 Inline ``literal "quotes"`` should be kept.
446 """,
447 head + r"""
448 Depending on language quotes are converted for latex.
449 Expecting ``en'' here.
451 Inside literal blocks quotes should be left untouched
452 (use only two quotes in test code makes life easier for
453 the python interpreter running the test):
455 \begin{quote}{\ttfamily \raggedright \noindent
456 "{}"\\
457 This~is~left~"untouched"~also~*this*.\\
458 "{}"
460 \end{quote}
462 \begin{quote}{\ttfamily \raggedright \noindent
463 should~get~"quotes"~and~\emph{italics}.
465 \end{quote}
467 Inline \texttt{literal "quotes"} should be kept.
469 \end{document}
470 """],
473 totest['table_caption'] = [
474 # input
475 ["""\
476 .. table:: Foo
478 +-----+-----+
479 | | |
480 +-----+-----+
481 | | |
482 +-----+-----+
483 """,
484 head_table + r"""
485 \setlength{\DUtablewidth}{\linewidth}
486 \begin{longtable}[c]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
487 \caption{Foo}\\
488 \hline
489 & \\
490 \hline
491 & \\
492 \hline
493 \end{longtable}
495 \end{document}
496 """],
499 totest['table_class'] = [
500 # input
501 ["""\
502 .. table::
503 :class: borderless
505 +-----+-----+
506 | 1 | 2 |
507 +-----+-----+
508 | 3 | 4 |
509 +-----+-----+
510 """,
511 head_table + r"""
512 \setlength{\DUtablewidth}{\linewidth}
513 \begin{longtable*}[c]{p{0.075\DUtablewidth}p{0.075\DUtablewidth}}
524 \end{longtable*}
526 \end{document}
527 """],
530 # The "[" needs to be protected (otherwise it will be seen as an
531 # option to "\\", "\item", etc. ).
533 totest['brackett_protection'] = [
534 # input
535 ["""\
538 something before to get a end of line.
541 the empty line gets tested too
543 """,
544 head + r"""%
545 \begin{quote}{\ttfamily \raggedright \noindent
546 something~before~to~get~a~end~of~line.\\
547 {[}\\
549 the~empty~line~gets~tested~too\\
552 \end{quote}
554 \end{document}
555 """],
558 totest['raw'] = [
559 [r""".. raw:: latex
561 $E=mc^2$
563 A paragraph.
565 .. |sub| raw:: latex
567 (some raw text)
569 Foo |sub|
570 same paragraph.
571 """,
572 head + r"""
573 $E=mc^2$
575 A paragraph.
577 Foo (some raw text)
578 same paragraph.
580 \end{document}
581 """],
584 totest['title_with_inline_markup'] = [
585 ["""\
586 This is the *Title*
587 ===================
589 This is the *Subtitle*
590 ----------------------
592 This is a *section title*
593 ~~~~~~~~~~~~~~~~~~~~~~~~~
595 This is the *document*.
596 """,
597 head_template.substitute(dict(parts,
598 requirements=parts['requirements'] + '\\setcounter{secnumdepth}{0}\n',
599 pdfsetup=parts['pdfsetup'] + r"""\hypersetup{
600 pdftitle={This is the Title},
602 """, titledata=r"""%%% Title Data
603 \title{\phantomsection%
604 This is the \emph{Title}%
605 \label{this-is-the-title}%
606 \\ % subtitle%
607 \large{This is the \emph{Subtitle}}%
608 \label{this-is-the-subtitle}}
609 \author{}
610 \date{}
611 """)) + r"""\maketitle
614 \section{This is a \emph{section title}%
615 \label{this-is-a-section-title}%
618 This is the \emph{document}.
620 \end{document}
621 """],
624 totest_stylesheet['two-styles'] = [
625 # input
626 ["""two stylesheet links in the header""",
627 head_template.substitute(dict(parts, stylesheet =
628 r"""\usepackage{data/spam}
629 \input{data/ham.tex}
630 """)) + r"""
631 two stylesheet links in the header
633 \end{document}
634 """],
637 totest_stylesheet_embed['two-styles'] = [
638 # input
639 ["""two stylesheets embedded in the header""",
640 head_template.substitute(dict(parts, stylesheet =
641 r"""% Cannot embed stylesheet 'data/spam.sty':
642 % No such file or directory.
643 % embedded stylesheet: data/ham.tex
644 \newcommand{\ham}{wonderful ham}
646 """)) + r"""
647 two stylesheets embedded in the header
649 \end{document}
650 """],
654 if __name__ == '__main__':
655 import unittest
656 unittest.main(defaultTest='suite')