glib (2.79.0)

(root)/
share/
glib-2.0/
codegen/
codegen_docbook.py
       1  # -*- Mode: Python -*-
       2  
       3  # GDBus - GLib D-Bus Library
       4  #
       5  # Copyright (C) 2008-2011 Red Hat, Inc.
       6  #
       7  # This library is free software; you can redistribute it and/or
       8  # modify it under the terms of the GNU Lesser General Public
       9  # License as published by the Free Software Foundation; either
      10  # version 2.1 of the License, or (at your option) any later version.
      11  #
      12  # This library is distributed in the hope that it will be useful,
      13  # but WITHOUT ANY WARRANTY; without even the implied warranty of
      14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15  # Lesser General Public License for more details.
      16  #
      17  # You should have received a copy of the GNU Lesser General
      18  # Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      19  #
      20  # Author: David Zeuthen <davidz@redhat.com>
      21  
      22  import re
      23  import textwrap
      24  from os import path
      25  
      26  from . import utils
      27  
      28  
      29  # ----------------------------------------------------------------------------------------------------
      30  
      31  
      32  class ESC[4;38;5;81mDocbookCodeGenerator:
      33      def __init__(self, ifaces):
      34          self.ifaces = ifaces
      35          self.generate_expand_dicts()
      36  
      37      def print_method_prototype(self, i, m, in_synopsis):
      38          max_method_len = 0
      39          if in_synopsis:
      40              for _m in i.methods:
      41                  max_method_len = max(len(_m.name), max_method_len)
      42          else:
      43              max_method_len = max(len(m.name), max_method_len)
      44  
      45          max_signature_len = 0
      46          if in_synopsis:
      47              for _m in i.methods:
      48                  for a in _m.in_args:
      49                      max_signature_len = max(len(a.signature), max_signature_len)
      50                  for a in _m.out_args:
      51                      max_signature_len = max(len(a.signature), max_signature_len)
      52          else:
      53              for a in m.in_args:
      54                  max_signature_len = max(len(a.signature), max_signature_len)
      55              for a in m.out_args:
      56                  max_signature_len = max(len(a.signature), max_signature_len)
      57  
      58          if in_synopsis:
      59              self.out.write(
      60                  '<link linkend="gdbus-method-%s.%s">%s</link>%*s ('
      61                  % (
      62                      utils.dots_to_hyphens(i.name),
      63                      m.name,
      64                      m.name,
      65                      max_method_len - len(m.name),
      66                      "",
      67                  )
      68              )
      69          else:
      70              self.out.write("%s%*s (" % (m.name, max_method_len - len(m.name), ""))
      71          count = 0
      72          for a in m.in_args:
      73              if count > 0:
      74                  self.out.write(",\n%*s" % (max_method_len + 2, ""))
      75              self.out.write(
      76                  "IN  %s%*s %s"
      77                  % (a.signature, max_signature_len - len(a.signature), "", a.name)
      78              )
      79              count = count + 1
      80          for a in m.out_args:
      81              if count > 0:
      82                  self.out.write(",\n%*s" % (max_method_len + 2, ""))
      83              self.out.write(
      84                  "OUT %s%*s %s"
      85                  % (a.signature, max_signature_len - len(a.signature), "", a.name)
      86              )
      87              count = count + 1
      88          self.out.write(");\n")
      89  
      90      def print_signal_prototype(self, i, s, in_synopsis):
      91          max_signal_len = 0
      92          if in_synopsis:
      93              for _s in i.signals:
      94                  max_signal_len = max(len(_s.name), max_signal_len)
      95          else:
      96              max_signal_len = max(len(s.name), max_signal_len)
      97  
      98          max_signature_len = 0
      99          if in_synopsis:
     100              for _s in i.signals:
     101                  for a in _s.args:
     102                      max_signature_len = max(len(a.signature), max_signature_len)
     103          else:
     104              for a in s.args:
     105                  max_signature_len = max(len(a.signature), max_signature_len)
     106  
     107          if in_synopsis:
     108              self.out.write(
     109                  '<link linkend="gdbus-signal-%s.%s">%s</link>%*s ('
     110                  % (
     111                      utils.dots_to_hyphens(i.name),
     112                      s.name,
     113                      s.name,
     114                      max_signal_len - len(s.name),
     115                      "",
     116                  )
     117              )
     118          else:
     119              self.out.write("%s%*s (" % (s.name, max_signal_len - len(s.name), ""))
     120          count = 0
     121          for a in s.args:
     122              if count > 0:
     123                  self.out.write(",\n%*s" % (max_signal_len + 2, ""))
     124              self.out.write(
     125                  "%s%*s %s"
     126                  % (a.signature, max_signature_len - len(a.signature), "", a.name)
     127              )
     128              count = count + 1
     129          self.out.write(");\n")
     130  
     131      def print_property_prototype(self, i, p, in_synopsis):
     132          max_property_len = 0
     133          if in_synopsis:
     134              for _p in i.properties:
     135                  max_property_len = max(len(_p.name), max_property_len)
     136          else:
     137              max_property_len = max(len(p.name), max_property_len)
     138  
     139          max_signature_len = 0
     140          if in_synopsis:
     141              for _p in i.properties:
     142                  max_signature_len = max(len(_p.signature), max_signature_len)
     143          else:
     144              max_signature_len = max(len(p.signature), max_signature_len)
     145  
     146          if in_synopsis:
     147              self.out.write(
     148                  '<link linkend="gdbus-property-%s.%s">%s</link>%*s'
     149                  % (
     150                      utils.dots_to_hyphens(i.name),
     151                      p.name,
     152                      p.name,
     153                      max_property_len - len(p.name),
     154                      "",
     155                  )
     156              )
     157          else:
     158              self.out.write("%s%*s" % (p.name, max_property_len - len(p.name), ""))
     159          if p.readable and p.writable:
     160              access = "readwrite"
     161          elif p.readable:
     162              access = "readable "
     163          else:
     164              access = "writable "
     165          self.out.write("  %s  %s\n" % (access, p.signature))
     166  
     167      def print_synopsis_methods(self, i):
     168          self.out.write('  <refsynopsisdiv role="synopsis">\n')
     169          self.out.write('    <title role="synopsis.title">Methods</title>\n')
     170          self.out.write("    <synopsis>\n")
     171          for m in i.methods:
     172              self.print_method_prototype(i, m, in_synopsis=True)
     173          self.out.write("</synopsis>\n")
     174          self.out.write("  </refsynopsisdiv>\n")
     175  
     176      def print_synopsis_signals(self, i):
     177          self.out.write('  <refsect1 role="signal_proto">\n')
     178          self.out.write('    <title role="signal_proto.title">Signals</title>\n')
     179          self.out.write("    <synopsis>\n")
     180          for s in i.signals:
     181              self.print_signal_prototype(i, s, in_synopsis=True)
     182          self.out.write("</synopsis>\n")
     183          self.out.write("  </refsect1>\n")
     184  
     185      def print_synopsis_properties(self, i):
     186          self.out.write('  <refsect1 role="properties">\n')
     187          self.out.write('    <title role="properties.title">Properties</title>\n')
     188          self.out.write("    <synopsis>\n")
     189          for p in i.properties:
     190              self.print_property_prototype(i, p, in_synopsis=True)
     191          self.out.write("</synopsis>\n")
     192          self.out.write("  </refsect1>\n")
     193  
     194      def print_method(self, i, m):
     195          self.out.write(
     196              '<refsect2 role="method" id="gdbus-method-%s.%s">\n'
     197              % (utils.dots_to_hyphens(i.name), m.name)
     198          )
     199          self.out.write("  <title>The %s() method</title>\n" % (m.name))
     200          self.out.write(
     201              '  <indexterm zone="gdbus-method-%s.%s"><primary sortas="%s.%s">%s.%s()</primary></indexterm>\n'
     202              % (
     203                  utils.dots_to_hyphens(i.name),
     204                  m.name,
     205                  i.name_without_prefix,
     206                  m.name,
     207                  i.name,
     208                  m.name,
     209              )
     210          )
     211          self.out.write("<programlisting>\n")
     212          self.print_method_prototype(i, m, in_synopsis=False)
     213          self.out.write("</programlisting>\n")
     214          self.out.write("%s\n" % (self.expand_paras(m.doc_string, True)))
     215          if m.in_args or m.out_args:
     216              self.out.write('<variablelist role="params">\n')
     217              for a in m.in_args:
     218                  self.out.write("<varlistentry>\n")
     219                  self.out.write(
     220                      "  <term><literal>IN %s <parameter>%s</parameter></literal>:</term>\n"
     221                      % (a.signature, a.name)
     222                  )
     223                  self.out.write(
     224                      "  <listitem>%s</listitem>\n"
     225                      % (self.expand_paras(a.doc_string, True))
     226                  )
     227                  self.out.write("</varlistentry>\n")
     228              for a in m.out_args:
     229                  self.out.write("<varlistentry>\n")
     230                  self.out.write(
     231                      "  <term><literal>OUT %s <parameter>%s</parameter></literal>:</term>\n"
     232                      % (a.signature, a.name)
     233                  )
     234                  self.out.write(
     235                      "  <listitem>%s</listitem>\n"
     236                      % (self.expand_paras(a.doc_string, True))
     237                  )
     238                  self.out.write("</varlistentry>\n")
     239              self.out.write("</variablelist>\n")
     240          if len(m.since) > 0:
     241              self.out.write('<para role="since">Since %s</para>\n' % (m.since))
     242          if m.deprecated:
     243              self.out.write(
     244                  "<warning><para>The %s() method is deprecated.</para></warning>"
     245                  % (m.name)
     246              )
     247          self.out.write("</refsect2>\n")
     248  
     249      def print_signal(self, i, s):
     250          self.out.write(
     251              '<refsect2 role="signal" id="gdbus-signal-%s.%s">\n'
     252              % (utils.dots_to_hyphens(i.name), s.name)
     253          )
     254          self.out.write('  <title>The "%s" signal</title>\n' % (s.name))
     255          self.out.write(
     256              '  <indexterm zone="gdbus-signal-%s.%s"><primary sortas="%s::%s">%s::%s</primary></indexterm>\n'
     257              % (
     258                  utils.dots_to_hyphens(i.name),
     259                  s.name,
     260                  i.name_without_prefix,
     261                  s.name,
     262                  i.name,
     263                  s.name,
     264              )
     265          )
     266          self.out.write("<programlisting>\n")
     267          self.print_signal_prototype(i, s, in_synopsis=False)
     268          self.out.write("</programlisting>\n")
     269          self.out.write("%s\n" % (self.expand_paras(s.doc_string, True)))
     270          if s.args:
     271              self.out.write('<variablelist role="params">\n')
     272              for a in s.args:
     273                  self.out.write("<varlistentry>\n")
     274                  self.out.write(
     275                      "  <term><literal>%s <parameter>%s</parameter></literal>:</term>\n"
     276                      % (a.signature, a.name)
     277                  )
     278                  self.out.write(
     279                      "  <listitem>%s</listitem>\n"
     280                      % (self.expand_paras(a.doc_string, True))
     281                  )
     282                  self.out.write("</varlistentry>\n")
     283              self.out.write("</variablelist>\n")
     284          if len(s.since) > 0:
     285              self.out.write('<para role="since">Since %s</para>\n' % (s.since))
     286          if s.deprecated:
     287              self.out.write(
     288                  '<warning><para>The "%s" signal is deprecated.</para></warning>'
     289                  % (s.name)
     290              )
     291          self.out.write("</refsect2>\n")
     292  
     293      def print_property(self, i, p):
     294          self.out.write(
     295              '<refsect2 role="property" id="gdbus-property-%s.%s">\n'
     296              % (utils.dots_to_hyphens(i.name), p.name)
     297          )
     298          self.out.write('  <title>The "%s" property</title>\n' % (p.name))
     299          self.out.write(
     300              '  <indexterm zone="gdbus-property-%s.%s"><primary sortas="%s:%s">%s:%s</primary></indexterm>\n'
     301              % (
     302                  utils.dots_to_hyphens(i.name),
     303                  p.name,
     304                  i.name_without_prefix,
     305                  p.name,
     306                  i.name,
     307                  p.name,
     308              )
     309          )
     310          self.out.write("<programlisting>\n")
     311          self.print_property_prototype(i, p, in_synopsis=False)
     312          self.out.write("</programlisting>\n")
     313          self.out.write("%s\n" % (self.expand_paras(p.doc_string, True)))
     314          if len(p.since) > 0:
     315              self.out.write('<para role="since">Since %s</para>\n' % (p.since))
     316          if p.deprecated:
     317              self.out.write(
     318                  '<warning><para>The "%s" property is deprecated.</para></warning>'
     319                  % (p.name)
     320              )
     321          self.out.write("</refsect2>\n")
     322  
     323      def expand(self, s, expandParamsAndConstants):
     324          for key in self.expand_member_dict_keys:
     325              s = s.replace(key, self.expand_member_dict[key])
     326          for key in self.expand_iface_dict_keys:
     327              s = s.replace(key, self.expand_iface_dict[key])
     328          if expandParamsAndConstants:
     329              # replace @foo with <parameter>foo</parameter>
     330              s = re.sub(
     331                  "@[a-zA-Z0-9_]*",
     332                  lambda m: "<parameter>" + m.group(0)[1:] + "</parameter>",
     333                  s,
     334              )
     335              # replace e.g. %TRUE with <constant>TRUE</constant>
     336              s = re.sub(
     337                  "%[a-zA-Z0-9_]*",
     338                  lambda m: "<constant>" + m.group(0)[1:] + "</constant>",
     339                  s,
     340              )
     341          return s
     342  
     343      def expand_paras(self, s, expandParamsAndConstants):
     344          s = textwrap.dedent(self.expand(s, expandParamsAndConstants)).rstrip()
     345          res = []
     346          if not s.startswith("<para>"):
     347              res.append("<para>")
     348          for line in s.split("\n"):
     349              line = line.rstrip()
     350              if not line:
     351                  line = "</para><para>"
     352              res.append(line)
     353          if not s.endswith("</para>"):
     354              res.append("</para>")
     355          return "\n".join(res)
     356  
     357      def generate_expand_dicts(self):
     358          self.expand_member_dict = {}
     359          self.expand_iface_dict = {}
     360          for i in self.ifaces:
     361              key = "#%s" % (i.name)
     362              value = '<link linkend="gdbus-interface-%s.top_of_page">%s</link>' % (
     363                  utils.dots_to_hyphens(i.name),
     364                  i.name,
     365              )
     366              self.expand_iface_dict[key] = value
     367              for m in i.methods:
     368                  key = "%s.%s()" % (i.name, m.name)
     369                  value = '<link linkend="gdbus-method-%s.%s">%s()</link>' % (
     370                      utils.dots_to_hyphens(i.name),
     371                      m.name,
     372                      m.name,
     373                  )
     374                  self.expand_member_dict[key] = value
     375              for s in i.signals:
     376                  key = "#%s::%s" % (i.name, s.name)
     377                  value = '<link linkend="gdbus-signal-%s.%s">"%s"</link>' % (
     378                      utils.dots_to_hyphens(i.name),
     379                      s.name,
     380                      s.name,
     381                  )
     382                  self.expand_member_dict[key] = value
     383              for p in i.properties:
     384                  key = "#%s:%s" % (i.name, p.name)
     385                  value = '<link linkend="gdbus-property-%s.%s">"%s"</link>' % (
     386                      utils.dots_to_hyphens(i.name),
     387                      p.name,
     388                      p.name,
     389                  )
     390                  self.expand_member_dict[key] = value
     391          # Make sure to expand the keys in reverse order so e.g. #org.foo.Iface:MediaCompat
     392          # is evaluated before #org.foo.Iface:Media ...
     393          self.expand_member_dict_keys = sorted(
     394              self.expand_member_dict.keys(), reverse=True
     395          )
     396          self.expand_iface_dict_keys = sorted(
     397              self.expand_iface_dict.keys(), reverse=True
     398          )
     399  
     400      def generate(self, docbook, outdir):
     401          for i in self.ifaces:
     402              self.out = open(path.join(outdir, "%s-%s.xml" % (docbook, i.name)), "w")
     403              self.out.write("")
     404              self.out.write('<?xml version="1.0" encoding="utf-8"?>\n')
     405              self.out.write(
     406                  '<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"\n'
     407              )
     408              self.out.write(
     409                  '               "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [\n'
     410              )
     411              self.out.write("]>\n")
     412              self.out.write('<refentry id="gdbus-%s">\n' % (i.name))
     413              self.out.write("  <refmeta>")
     414              self.out.write(
     415                  '    <refentrytitle role="top_of_page" id="gdbus-interface-%s.top_of_page">%s</refentrytitle>\n'
     416                  % (utils.dots_to_hyphens(i.name), i.name)
     417              )
     418              self.out.write(
     419                  '  <indexterm zone="gdbus-interface-%s.top_of_page"><primary sortas="%s">%s</primary></indexterm>\n'
     420                  % (utils.dots_to_hyphens(i.name), i.name_without_prefix, i.name)
     421              )
     422              self.out.write("  </refmeta>")
     423  
     424              self.out.write("  <refnamediv>")
     425              self.out.write("    <refname>%s</refname>" % (i.name))
     426              self.out.write("    <refpurpose>%s</refpurpose>" % (i.doc_string_brief))
     427              self.out.write("  </refnamediv>")
     428  
     429              if len(i.methods) > 0:
     430                  self.print_synopsis_methods(i)
     431              if len(i.signals) > 0:
     432                  self.print_synopsis_signals(i)
     433              if len(i.properties) > 0:
     434                  self.print_synopsis_properties(i)
     435  
     436              self.out.write(
     437                  '<refsect1 role="desc" id="gdbus-interface-%s">\n'
     438                  % (utils.dots_to_hyphens(i.name))
     439              )
     440              self.out.write('  <title role="desc.title">Description</title>\n')
     441              self.out.write("  %s\n" % (self.expand_paras(i.doc_string, True)))
     442              if len(i.since) > 0:
     443                  self.out.write('  <para role="since">Since %s</para>\n' % (i.since))
     444              if i.deprecated:
     445                  self.out.write(
     446                      "<warning><para>The %s interface is deprecated.</para></warning>"
     447                      % (i.name)
     448                  )
     449              self.out.write("</refsect1>\n")
     450  
     451              if len(i.methods) > 0:
     452                  self.out.write(
     453                      '<refsect1 role="details" id="gdbus-methods-%s">\n' % (i.name)
     454                  )
     455                  self.out.write('  <title role="details.title">Method Details</title>\n')
     456                  for m in i.methods:
     457                      self.print_method(i, m)
     458                  self.out.write("</refsect1>\n")
     459  
     460              if len(i.signals) > 0:
     461                  self.out.write(
     462                      '<refsect1 role="details" id="gdbus-signals-%s">\n' % (i.name)
     463                  )
     464                  self.out.write('  <title role="details.title">Signal Details</title>\n')
     465                  for s in i.signals:
     466                      self.print_signal(i, s)
     467                  self.out.write("</refsect1>\n")
     468  
     469              if len(i.properties) > 0:
     470                  self.out.write(
     471                      '<refsect1 role="details" id="gdbus-properties-%s">\n' % (i.name)
     472                  )
     473                  self.out.write(
     474                      '  <title role="details.title">Property Details</title>\n'
     475                  )
     476                  for s in i.properties:
     477                      self.print_property(i, s)
     478                  self.out.write("</refsect1>\n")
     479  
     480              self.out.write("</refentry>\n")
     481              self.out.write("\n")