Skip to content
This repository was archived by the owner on Nov 3, 2023. It is now read-only.

Commit 7e800fe

Browse files
authored
Merge pull request #222 from Nurdok/feature/private-modules
Modules starting with a single leading underscore are considered private
2 parents 511b2c3 + a5b0353 commit 7e800fe

File tree

5 files changed

+69
-1
lines changed

5 files changed

+69
-1
lines changed

docs/error_codes.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,9 @@ check only error codes that are part of the `PEP257
1616

1717
All of the above error codes are checked for by default except for D203,
1818
D212, D213 and D404.
19+
20+
21+
Publicity
22+
---------
23+
24+
.. include:: snippets/publicity.rst

docs/release_notes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ New Features
2323
Bug Fixes
2424

2525
* Made parser more robust to bad source files (#168, #214)
26+
* Modules are now considered private if their name starts with a single
27+
underscore. This is a bugfix where "public module" (D100) was reported
28+
regardless of module name (#199, #222).
2629

2730
1.1.1 - October 4th, 2016
2831
-------------------------

docs/snippets/publicity.rst

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
The D1xx group of errors deals with missing docstring in public constructs:
2+
modules, classes, methods, etc. It is important to note how publicity is
3+
determined and what its effects are.
4+
5+
6+
How publicity is determined
7+
===========================
8+
9+
Publicity for all constructs is determined as follows: a construct is
10+
considered *public* if -
11+
12+
1. Its immediate parent is public *and*
13+
2. Its name does not contain a single leading underscore.
14+
15+
A construct's immediate parent is the construct that contains it. For example,
16+
a method's parent is a class object. A class' parent is usually a module, but
17+
might also be a function, method, etc. A module can either have no parent, or
18+
it can have a parent that is a package.
19+
20+
In order for a construct to be considered public, its immediate parent must
21+
also be public. Since this definition is recursive, it means that *all* of its
22+
parents need to be public. The corollary is that if a construct is considered
23+
private, then all of its descendants are also considered private. For example,
24+
a class called ``_Foo`` is considered private. A method ``bar`` in ``_Foo`` is
25+
also considered private since its parent is a private class, even though its
26+
name does not begin with a single underscore.
27+
28+
29+
How publicity affects error reports
30+
===================================
31+
32+
The immediate effect of a construct being determined as private is that no
33+
D1xx errors will be reported for it (or its children, as the previous section
34+
explains). A private method, for instance, will not generate a D102 error, even
35+
if it has no docstring.
36+
37+
However, it is important to note that while docstring are optional for private
38+
construct, they are still required to adhere to your style guide. So if a
39+
private module `_foo.py` does not have a docstring, it will not generate a
40+
D100 error, but if it *does* have a docstring, that docstring might generate
41+
other errors.

src/pydocstyle/parser.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,14 @@ class Module(Definition):
103103
_fields = ('name', '_source', 'start', 'end', 'decorators', 'docstring',
104104
'children', 'parent', '_all', 'future_imports',
105105
'skipped_error_codes')
106-
is_public = True
107106
_nest = staticmethod(lambda s: {'def': Function, 'class': Class}[s])
108107
module = property(lambda self: self)
109108
all = property(lambda self: self._all)
110109

110+
@property
111+
def is_public(self):
112+
return not self.name.startswith('_') or self.name.startswith('__')
113+
111114
def __str__(self):
112115
return 'at module level'
113116

src/tests/parser_test.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,3 +276,18 @@ def test_raise_from():
276276
parser = Parser()
277277
code = CodeSnippet("raise ValueError() from None")
278278
parser.parse(code, 'file_path')
279+
280+
281+
def test_module_publicity():
282+
"""Test that a module that has a single leading underscore is private."""
283+
parser = Parser()
284+
code = CodeSnippet("")
285+
286+
module = parser.parse(code, "filepath")
287+
assert module.is_public
288+
289+
module = parser.parse(code, "_filepath")
290+
assert not module.is_public
291+
292+
module = parser.parse(code, "__filepath")
293+
assert module.is_public

0 commit comments

Comments
 (0)