diff --git a/.gitignore b/.gitignore index c46f9328b..1cf231c84 100644 --- a/.gitignore +++ b/.gitignore @@ -2,9 +2,9 @@ .* *.mo -# sphinx build directories +# Sphinx build files _build/ -# venv -bin/ -include/ -lib/ +extensions/odoo_theme/static/style.css + +# Dependencies +odoo diff --git a/Makefile b/Makefile index 829c29461..a3ddf23ac 100644 --- a/Makefile +++ b/Makefile @@ -1,194 +1,78 @@ # Makefile for Sphinx documentation -# -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = _build -LESSOPTS = - -# User-friendly check for sphinx-build -ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) -$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed; then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively, you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +# Pass WORKERS=auto for parallel build +ifndef WORKERS + WORKERS = 1 endif -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . -ALLI18NSPHINXOPTS = -d $(BUILDDIR)/doctrees/$(LANG) $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) -D language=$(LANG) . -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +SPHINX_BUILD = sphinx-build +CONFIG_DIR = . +SPHINXOPTS = -D project_root=$(ROOT) -D canonical_version=$(CANONICAL_VERSION) \ + -D versions=$(VERSIONS) -D languages=$(LANGUAGES) -D language=$(CURRENT_LANG) \ + -D is_remote_build=$(IS_REMOTE_BUILD) \ + -A google_analytics_key=$(GOOGLE_ANALYTICS_KEY) \ + -j $(WORKERS) +SOURCE_DIR = content +BUILD_DIR = _build -lessfiles = _extensions/odoo/static/*.less -_extensions/odoo/static/style.css: $(lessfiles) - lessc $(LESSOPTS) $(subst .css,.less,$@) $@ +HTML_BUILD_DIR = $(BUILD_DIR)/html +ifdef VERSIONS + HTML_BUILD_DIR := $(HTML_BUILD_DIR)/12.0 +endif +ifneq ($(CURRENT_LANG),en) + HTML_BUILD_DIR := $(HTML_BUILD_DIR)/$(CURRENT_LANG) +endif -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext +#=== Standard rules ===# + +# In first position to build the documentation from scratch by default +all: html -# Displays list of commands help: - @echo "Please use \`make ' where is one of" - @echo " clean to delete the build" - @echo " html to make standalone HTML files" - @echo " i18nhtml to make standalone translated HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and an HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " xml to make Docutils-native XML files" - @echo " pseudoxml to make pseudoxml-XML files for display purposes" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo "Please use 'make ' where is one of" + @echo " html to build the documentation to HTML" + @echo " fast to build the documentation to HTML with shallow menu (faster)" + @echo " clean to delete the build files" -# Deletes the build clean: - rm -rf $(BUILDDIR)/* + @echo "Cleaning build files..." + rm -rf $(BUILD_DIR)/* + rm extensions/odoo_theme/static/style.css + @echo "Cleaning finished." -# These commands are used to create files or run tests -html: _extensions/odoo/static/style.css - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -i18nhtml: _extensions/odoo/static/style.css - $(SPHINXBUILD) -b html $(ALLI18NSPHINXOPTS) $(BUILDDIR)/html/$(LANG) - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html/$(LANG)." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished. Now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished. Now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished. Now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished. Now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/UnderstandingAccountingForEntrepreneurs.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/UnderstandingAccountingForEntrepreneurs.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo +html: extensions/odoo_theme/static/style.css + @echo "Starting build..." + $(SPHINX_BUILD) -c $(CONFIG_DIR) -b html $(SPHINXOPTS) $(SOURCE_DIR) $(HTML_BUILD_DIR) @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/UnderstandingAccountingForEntrepreneurs" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/UnderstandingAccountingForEntrepreneurs" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished. The LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." +# To call *after* `make html` +# Binary dependencies (Debian): texlive-fonts-recommended texlive-latex-extra +# texlive-generic-recommended texlive-fonts-extra latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished. The PDF files are in $(BUILDDIR)/latex." - cp $(BUILDDIR)/latex/*.pdf $(BUILDDIR)/html/ + @echo "Starting build..." + $(SPHINX_BUILD) -c $(CONFIG_DIR) -b latex $(SPHINXOPTS) $(SOURCE_DIR) $(BUILD_DIR)/latex + $(MAKE) -C $(BUILD_DIR)/latex + cp $(BUILD_DIR)/latex/*.pdf $(BUILD_DIR)/html/ + @echo "Build finished." -latexpdfja: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through platex and dvipdfmx..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja - @echo "pdflatex finished. The PDF files are in $(BUILDDIR)/latex." +l10n: + @echo "Generating translatable files..." + $(SPHINX_BUILD) -c $(CONFIG_DIR) -b gettext $(SOURCE_DIR) $(BUILD_DIR)/gettext + @echo "Generation finished." + @echo "Localizing translation strings..." + sphinx-intl update -p $(BUILD_DIR)/gettext -l $(L10N_LANGUAGES) + @echo "Localization finished." -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." +extensions/odoo_theme/static/style.css: extensions/odoo_theme/static/style.scss extensions/odoo_theme/static/scss/*.scss + @echo "Compiling stylesheets..." + pysassc $(subst .css,.scss,$@) $@ + @echo "Compilation finished." -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." +#=== Development and debugging rules ===# -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." +fast: SPHINXOPTS += -A collapse_menu=True -j auto +fast: html -info: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished. The Info files are in $(BUILDDIR)/texinfo." - -gettext: - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) locale/sources - @echo - @echo "Build finished. The message catalogs are in locale/sources." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete. Look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished. Look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." - -xml: - $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml - @echo - @echo "Build finished. The XML files are in $(BUILDDIR)/xml." - -pseudoxml: - $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml - @echo - @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." +static: extensions/odoo_theme/static/style.css + cp -r extensions/odoo_theme/static/* _build/html/_static/ + cp -r static/* _build/html/_static/ diff --git a/_extensions/demo_link.py b/_extensions/demo_link.py deleted file mode 100644 index 9038d8040..000000000 --- a/_extensions/demo_link.py +++ /dev/null @@ -1,207 +0,0 @@ -import collections -import threading -import werkzeug - -try: - import xmlrpclib -except ImportError: - # P3 - import xmlrpc.client as xmlrpclib - -try: - import Queue -except ImportError: - # P3 - import queue as Queue - -from xml.etree import ElementTree as ET - -from docutils import nodes, utils -from docutils.parsers.rst import Directive, directives -from sphinx.domains import Domain - -def setup(app): - app.add_domain(OdooDemoDomain) - -class Fields(Directive): - """Fetches and lists the fields linked to a specific action. - - Required argument: external ID of the action - - Options: - - view - defaults to "form" - fields - comma-separated whitelist of fields. By default, lists all - fields returned by fields_view_get - """ - required_arguments = 1 - option_spec = { - 'view': directives.unchanged, - 'only': directives.unchanged, - } - def __init__(self, name, arguments, options, content, lineno, - content_offset, block_text, state, state_machine): - super(Fields, self).__init__( - name, arguments, options, content, lineno, - content_offset, block_text, state, state_machine) - xid = arguments[0] - self.future_fields = self._get_fields(xid, options.get('view') or 'form') - - def run(self): - try: - fields = self.future_fields.get(timeout=30) - except Queue.Empty: - return [self.state_machine.reporter.error( - "Timed out while fetching fields related to action [%s]" % self.arguments[0] - )] - if fields is None: - return [self.state_machine.reporter.warning( - "Could not find any field related to the action [%s]" % self.arguments[0] - )] - if isinstance(fields, str): - return [self.state_machine.reporter.warning( - "Error while fetching fields related to the action [%s]: %s" % ( - self.arguments[0], fields))] - - whitelist = set(self.options.get('only', '').split()) - return [nodes.field_list('', *( - nodes.field('', - nodes.field_name(text=v['string'] or k), - nodes.field_body('', - # keep help formatting around (e.g. newlines for lists) - nodes.line_block('', *( - nodes.line(text=line) - for line in v['help'].split('\n') - )) - ) - ) - for k, v in fields.items() - # if there's a whitelist, only display whitelisted fields - if not whitelist or k in whitelist - # only display if there's a help text - if v.get('help') - ))] - - def _get_fields(self, xid, view='form'): - q = Queue.Queue(1) - _submit(q, xid, view) - return q - -class Action(Directive): - required_arguments = 1 - final_argument_whitespace = True - has_content = True - - def run(self): - self.assert_has_content() - external_id = self.arguments[0] - text = "action button" - node = nodes.reference( - refuri='https://demo.odoo.com?{}'.format(werkzeug.urls.url_encode({ - 'module': external_id - })), - classes=['btn', 'btn-primary', 'btn-lg', 'btn-block', 'center-block'] - ) - self.state.nested_parse(self.content, self.content_offset, node) - return [node] - -class OdooDemoDomain(Domain): - name = 'demo' - label = 'Odoo Demo' - directives = { - 'fields': Fields, - 'action': Action, - } - -FETCH_THREADS = 4 -launcher_lock = threading.Lock() -launcher = None -work_queue = Queue.Queue() -Task = collections.namedtuple('Task', 'result xid view') -def _submit(result_queue, xid, view='form'): - global launcher - # enqueue task before checking launcher, that way if the launcher - # is already started (likely) a worker can immediately get to work - work_queue.put(Task(result_queue, xid, view)) - - with launcher_lock: - if launcher is None: - launcher = threading.Thread(target=_launcher, name="Fetch threads launcher") - launcher.daemon = True - launcher.start() - -def _launcher(): - try: - info = xmlrpclib.ServerProxy('https://demo.odoo.com/start').start() - except xmlrpclib.Fault as e: - threading.Thread( - target=_fault_requests, - args=["Demo start() failed: %s" % e.faultString], - name="fields_get login failed").start() - return - url, db, username, password = \ - info['host'], info['database'], info['user'], info['password'] - - uid = xmlrpclib.ServerProxy('{}/xmlrpc/2/common'.format(url))\ - .authenticate(db, username, password, {}) - - for i in range(FETCH_THREADS): - # daemon because Launcher is daemon - threading.Thread(target=_fetch_fields, kwargs={ - 'db': db, - 'uid': uid, - 'password': password, - 'url': '{}/xmlrpc/2/object'.format(url) - }, name="fields_get fetcher thread %d/%d" % (i, FETCH_THREADS)).start() - -def _fault_requests(error): - while True: - task = work_queue.get() - task.result.put(error) - work_queue.task_done() - -def _fetch_fields(url, db, uid, password): - server = xmlrpclib.ServerProxy(url) - while True: - task = work_queue.get() - - # resolve xid - model, id_ = server.execute_kw( - db, uid, password, - 'ir.model.data', 'xmlid_to_res_model_res_id', [task.xid]) - if not id_: # didn't find xid - result = None - elif model != 'ir.actions.act_window': # we only handle action windows, rest is unknown - result = None - else: - action = server.execute_kw(db, uid, password, model, 'read', [id_, ['res_model', 'views']]) - view_id = next((id_ for type, id_ in action[0]['views'] if type == task.view), False) - fvg = server.execute_kw( - db, uid, password, - action[0]['res_model'], 'fields_view_get', [], { - 'view_id': view_id, - 'view_type': task.view - }) - result = collections.OrderedDict() - # reorder fields to be in view order, and add @help from view if any - arch = ET.fromstring(fvg['arch']) - for node in arch.iter(tag='field'): - field = node.get('name') - - result[field] = fvg['fields'][field] - # bit trashy but should work well enough to update - # @string and @help - result[field].update(node.attrib) - if node.get('nolabel'): - # native @string suppressed, look for