Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
Change log
**********

x.x.x
#####

Changes

* The ``:filename:`` input is now resolved only to the ``conf.py`` directory (``srcdir`` in Sphinx)

0.6.0
#####

Expand Down
4 changes: 2 additions & 2 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ To document a file that is not part of a module, use :filename:
:func: my_func_that_returns_a_parser
:prog: script.py

The 'filename' option could be absolute path or a relative path under current
working dir.
The 'filename' option can be an absolute path or a relative one.
When a relative path is provided, the Sphinx ``srcdir`` will be taken as the base, which is the directory housing the active ``conf.py`` file.

\:module\:
Module name, where the function is located
Expand Down
38 changes: 23 additions & 15 deletions sphinxarg/ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import importlib
import operator
import os
import shutil
import sys
from argparse import ArgumentParser
from typing import TYPE_CHECKING, ClassVar, cast
Expand Down Expand Up @@ -492,24 +491,33 @@ def _nested_parse_paragraph(self, text):
self.state.nested_parse(StringList(text.split('\n')), 0, content)
return content

@property
def _srcdir(self):
"""Internal property for source root-dir.

This is a property such that we can easily mock it during tests.
"""
return self.env.srcdir

def _open_filename(self):
file = self.options['filename']

# If the provided path is not absolute, we consider it relative to the docs
# conf dir:
if not os.path.isabs(file):
file = os.path.realpath(
os.path.join(self._srcdir, file)
) # Resolve things like ".." to make clear where we're searching

# try open with given path
try:
return open(self.options['filename'])
return open(file)
except OSError:
pass
# try open with abspath
try:
return open(os.path.abspath(self.options['filename']))
except OSError:
pass
# try open with shutil which
try:
return open(shutil.which(self.options['filename']))
except (OSError, TypeError):
pass
# raise exception
raise FileNotFoundError(self.options['filename'])
msg = (
f'Failed to find provided source file `{self.options["filename"]}` '
f'(resolved to `{file}`)'
)
raise FileNotFoundError(msg) from None

def _print_subcommands(self, data, nested_content, markdown_help=False, settings=None):
"""
Expand Down
14 changes: 14 additions & 0 deletions test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,25 @@
from lxml import etree as lxmltree
from sphinx.testing.util import SphinxTestApp

from sphinxarg.ext import ArgParseDirective

pytest_plugins = 'sphinx.testing.fixtures'

etree_cache: dict[str, str] = {}


@pytest.fixture(autouse=True)
def mock_argparse_src_dir(monkeypatch):
"""Fixture to mock the source root dir in `ArgParseDirective`.

Auto-used, i.e. applied to all tests by default.
Without this, the source .py files will be searched inside the pytest temp
directory, where our .py files won't be copied into.
"""
tests_dir = Path(__file__).parent.absolute()
monkeypatch.setattr(ArgParseDirective, '_srcdir', str(tests_dir))


@pytest.fixture(scope='session')
def rootdir():
return Path(__file__).parent.absolute() / 'roots'
Expand Down
2 changes: 1 addition & 1 deletion test/roots/test-argparse-directive/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Fails to parse
==============

.. argparse::
:filename: test/sample-directive-opts.py
:filename: sample-directive-opts.py
:prog: sample-directive-opts
:func: get_parser
:index-groups: Needs; Commas
2 changes: 1 addition & 1 deletion test/roots/test-command-by-group-index/sample.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Sample
======

.. argparse::
:filename: test/sample-directive-opts.py
:filename: sample-directive-opts.py
:prog: sample-directive-opts
:func: get_parser
:nosubcommands:
Expand Down
2 changes: 1 addition & 1 deletion test/roots/test-command-by-group-index/subcommand-a.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Command A
=========

.. argparse::
:filename: test/sample-directive-opts.py
:filename: sample-directive-opts.py
:prog: sample-directive-opts
:func: get_parser
:path: A
Expand Down
2 changes: 1 addition & 1 deletion test/roots/test-command-by-group-index/subcommand-b.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Command B
=========

.. argparse::
:filename: test/sample-directive-opts.py
:filename: sample-directive-opts.py
:prog: sample-directive-opts
:func: get_parser
:path: B
Expand Down
2 changes: 1 addition & 1 deletion test/roots/test-command-index/sample.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ Sample
======

.. argparse::
:filename: test/sample-directive-opts.py
:filename: sample-directive-opts.py
:prog: sample-directive-opts
:func: get_parser
2 changes: 1 addition & 1 deletion test/roots/test-command-index/subcommand-a.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Command A
=========

.. argparse::
:filename: test/sample-directive-opts.py
:filename: sample-directive-opts.py
:prog: sample-directive-opts
:func: get_parser
:path: A
2 changes: 1 addition & 1 deletion test/roots/test-command-index/subcommand-b.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Command B
=========

.. argparse::
:filename: test/sample-directive-opts.py
:filename: sample-directive-opts.py
:prog: sample-directive-opts
:func: get_parser
:path: B
2 changes: 1 addition & 1 deletion test/roots/test-conf-opts-html/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ Sample
======

.. argparse::
:filename: test/sample-directive-opts.py
:filename: sample-directive-opts.py
:prog: sample-directive-opts
:func: get_parser
2 changes: 1 addition & 1 deletion test/roots/test-conf-opts-html/subcommand-a.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Command A
=========

.. argparse::
:filename: test/sample-directive-opts.py
:filename: sample-directive-opts.py
:prog: sample-directive-opts
:func: get_parser
:path: A
2 changes: 1 addition & 1 deletion test/roots/test-default-html/default-suppressed.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ Default suppressed
==================

.. argparse::
:filename: test/sample-default-supressed.py
:filename: sample-default-supressed.py
:prog: sample-default-suppressed
:func: get_parser
2 changes: 1 addition & 1 deletion test/roots/test-default-html/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Sample
######

.. argparse::
:filename: test/sample-directive-opts.py
:filename: sample-directive-opts.py
:prog: sample-directive-opts
:func: get_parser

Expand Down
2 changes: 1 addition & 1 deletion test/roots/test-default-html/special-characters.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ Special Characters
==================

.. argparse::
:filename: test/sample-directive-special.py
:filename: sample-directive-special.py
:func: get_parser
2 changes: 1 addition & 1 deletion test/roots/test-default-html/subcommand-a.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Command A
=========

.. argparse::
:filename: test/sample-directive-opts.py
:filename: sample-directive-opts.py
:prog: sample-directive-opts
:func: get_parser
:path: A