File: util.py

package info (click to toggle)
python-releases 2.1.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 352 kB
  • sloc: python: 1,580; makefile: 11
file content (149 lines) | stat: -rw-r--r-- 5,621 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
from pathlib import Path
from unittest.mock import patch, MagicMock as Mock

from pytest import skip  # noqa
from sphinx.application import Sphinx
from docutils.nodes import bullet_list

from releases.util import (
    make_app,
    parse_changelog,
    get_doctree,
    _faux_write_doctree,
)


class parse_changelog_:
    @patch("releases.util.changelog2dict")
    @patch("releases.util.get_doctree")
    @patch("releases.util.construct_releases")
    def _test(
        self, extra_setup, construct_releases, get_doctree, changelog2dict
    ):
        # Setup
        app, doctree = Mock(name="app"), Mock(name="doctree")
        blist = Mock(spec=bullet_list())
        doctree.__getitem__.return_value = [blist]
        releases = Mock(name="releases")
        get_doctree.return_value = app, doctree
        manager = []  # empty iterable
        if extra_setup:
            manager = extra_setup(changelog2dict)
        construct_releases.return_value = releases, manager
        # Do eet (NOTE: also tests that kwargs are passed thru)
        result = parse_changelog("random/changelog.rst", kwarg="value")
        # Calls
        get_doctree.assert_called_once_with(
            "random/changelog.rst", kwarg="value"
        )
        construct_releases.assert_called_once_with(blist.children, app)
        changelog2dict.assert_called_once_with(releases)
        return result, changelog2dict

    def calls_various_methods_and_returns_dict(self):
        result, cl2d = self._test(None)
        assert result is cl2d.return_value

    def omits_unreleased_objects(self):
        # NOTE: this is all a bit slapdash and doesn't 100% represent real
        # return data, just enough to ensure the relevant logic is working
        def extra_setup(cl2d):
            cl2d.return_value = {
                "unreleased_1.2_bugfixes": None,
                "unreleased_1.2_features": None,
                "1.2.3": "stuff!",
            }
            manager = {
                "1": {
                    "unreleased_bugfix": None,
                    "unreleased_feature": "shiny!",
                    "1.2": "hmm",
                },
                "2": {"unreleased_feature": "shinier!", "2.2": "also hmm"},
            }
            return manager

        result, _ = self._test(extra_setup)
        assert result == {
            "1.2": "hmm",
            "1.2.3": "stuff!",
            "2.2": "also hmm",
            "unreleased_1_feature": "shiny!",
            "unreleased_2_feature": "shinier!",
        }


class get_doctree_:
    def setup_method(self):
        self.cwd = Path.cwd()

    @patch("releases.util.make_app")
    def returns_app_and_doctree_for_file_path(self, make_app):
        # NOTE: using relative path and testing that an absolute one is used,
        # as this prevents internal docutils pseudo-bugs
        path = "nonsense/path.rst"
        app = make_app.return_value
        # Expect awful monkeypatch workaround re: assignment/extraction of read
        # doctree
        assert get_doctree(path) == (app, app.builder._read_doctree)
        make_app.assert_called_once_with(srcdir=self.cwd / "nonsense")
        # Ensure our monkeypatch is active
        # NOTE: this doesn't test inside the monkeypatch; integration/util.py
        # should though
        assert app.builder.__class__.write_doctree is _faux_write_doctree
        # NOTE: still enforcing the STRING form of path is handed to read_doc,
        # as it is not yet Pathlib-aware (apparently)
        # NOTE: use of .stem, a change from sphinx 1.x
        app.builder.read_doc.assert_called_once_with(
            str(self.cwd / "nonsense" / "path")
        )

    @patch("releases.util.make_app")
    def passes_kwargs_to_make_app(self, make_app):
        path = "nonsense/path.rst"
        get_doctree(path, whatever="kwargs")
        make_app.assert_called_once_with(
            srcdir=self.cwd / "nonsense", whatever="kwargs"
        )


class make_app_:
    @patch("releases.util.os.rmdir")
    @patch("releases.util.mkdtemp")
    @patch("releases.util.setup")
    def creates_Sphinx_object_with_temp_dirs(
        self, setup, mkdtemp, rmdir, tmpdir
    ):
        tempdirs = [tmpdir.mkdir(x) for x in ["src", "out", "doc"]]
        mkdtemp.side_effect = tempdirs
        app = make_app()
        assert isinstance(app, Sphinx)
        assert app.srcdir == app.confdir == tempdirs[0]
        assert app.outdir == tempdirs[1]
        assert app.doctreedir == tempdirs[2]
        assert app.builder.name == "html"
        for path in tempdirs:
            rmdir.assert_any_call(path)
        setup.assert_called_once_with(app)
        # TODO: the config bits too, tho those are really just implementation
        # details for now?

    def unused_kwargs_become_releases_config_options(self):
        app = make_app(debug=True, document_name="notchangelog")
        assert app.config.releases_debug is True
        assert app.config.releases_document_name == "notchangelog"

    @patch("releases.util.os.rmdir")
    @patch("releases.util.mkdtemp")
    def dirs_can_be_overridden(self, mkdtemp, rmdir, tmpdir):
        tempdirs = [tmpdir.mkdir(x) for x in ["src", "out", "doc"]]
        app = make_app(
            srcdir=tempdirs[0], dstdir=tempdirs[1], doctreedir=tempdirs[2]
        )
        assert not mkdtemp.called
        assert app.srcdir == app.confdir == tempdirs[0]
        assert app.outdir == tempdirs[1]
        assert app.doctreedir == tempdirs[2]
        # Explicitly given dirs are still rmdir'd (but are never rm -rf'd)
        for path in tempdirs:
            rmdir.assert_any_call(path)