@@ -160,3 +160,52 @@ def test_private_module_alias_import() -> None:
160
160
161
161
for target , message in zip (_PRIVATE_MODULE_ALIAS_TARGETS , messages ):
162
162
assert message .endswith (f"Use { target .__name__ } instead." )
163
+
164
+
165
+ def test_dir_contains_public_attributes () -> None :
166
+ """All public attributes of the git module are present when dir() is called on it.
167
+
168
+ This is naturally the case, but some ways of adding dynamic attribute access
169
+ behavior can change it, especially if __dir__ is defined but care is not taken to
170
+ preserve the contents that should already be present.
171
+
172
+ Note that dir() should usually automatically list non-public attributes if they are
173
+ actually "physically" present as well, so the approach taken here to test it should
174
+ not be reproduced if __dir__ is added (instead, a call to globals() could be used,
175
+ as its keys list the automatic values).
176
+ """
177
+ expected_subset = set (git .__all__ )
178
+ actual = set (dir (git ))
179
+ assert expected_subset <= actual
180
+
181
+
182
+ def test_dir_does_not_contain_util () -> None :
183
+ """The util attribute is absent from the dir() of git.
184
+
185
+ Because this behavior is less confusing than including it, where its meaning would
186
+ be assumed by users examining the dir() for what is available.
187
+ """
188
+ assert "util" not in dir (git )
189
+
190
+
191
+ def test_dir_does_not_contain_private_module_aliases () -> None :
192
+ """Names from inside index and refs only pretend to be there and are not in dir().
193
+
194
+ The reason for omitting these is not that they are private, since private members
195
+ are usually included in dir() when actually present. Instead, these are only sort
196
+ of even there, no longer being imported and only being resolved dynamically for the
197
+ time being. In addition, it would be confusing to list these because doing so would
198
+ obscure the module structure of GitPython.
199
+ """
200
+ expected_absent = {
201
+ "head" ,
202
+ "log" ,
203
+ "reference" ,
204
+ "symbolic" ,
205
+ "tag" ,
206
+ "base" ,
207
+ "fun" ,
208
+ "typ" ,
209
+ }
210
+ actual = set (dir (git ))
211
+ assert not (expected_absent & actual ), "They should be completely disjoint."
0 commit comments