Skip to content

Commit 24846b8

Browse files
committed
Deprecate listdir(), trim its doc section, accept pathlib in search_base
- listdir() now emits DeprecationWarning on every call; use os.walk() + getsize() directly - search_base type annotation widened to str | pathlib.Path; :type field added to module.rst param block - module.rst listdir section cut from 156 to 82 lines: removed the os.walk explainer wall, the reduce() Python 2 holdover, the list() trivial example, and the misplaced versionadded::2.0.0 tag; replaced with one progressive code block covering default, relpath, glob, and sum - Admonition referencing issue #27 ("scheduled for introduction") removed; replaced with deprecated:: 2.1.0 and versionchanged:: 2.0.0 (filter→glob) - test_listdir_filter_kwarg_emits_deprecation_warning updated to expect two DeprecationWarnings now that the function-level warning fires first Closes #27
1 parent 767749a commit 24846b8

3 files changed

Lines changed: 50 additions & 110 deletions

File tree

bitmath/__init__.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,7 +1580,7 @@ def getsize(path: str | pathlib.Path, bestprefix: bool = True, system: int = NIS
15801580

15811581

15821582
def listdir( # pylint: disable=too-many-arguments,too-many-positional-arguments
1583-
search_base: str,
1583+
search_base: str | pathlib.Path,
15841584
followlinks: bool = False,
15851585
glob: str = '*',
15861586
relpath: bool = False,
@@ -1594,7 +1594,8 @@ def listdir( # pylint: disable=too-many-arguments,too-many-positional-arguments
15941594
* The absolute/relative path to a discovered file
15951595
* A bitmath instance representing the "apparent size" of the file.
15961596
1597-
- `search_base` - The directory to begin walking down.
1597+
- `search_base` - The directory to begin walking down. May be a
1598+
plain string or a :class:`pathlib.Path` object.
15981599
- `followlinks` - Whether or not to follow symbolic links to directories
15991600
- `glob` - A glob (see :py:mod:`fnmatch`) to filter results with
16001601
(default: ``*``, everything)
@@ -1605,11 +1606,19 @@ def listdir( # pylint: disable=too-many-arguments,too-many-positional-arguments
16051606
- `system` - Provide a preferred unit system by setting `system`
16061607
to either ``bitmath.NIST`` (default) or ``bitmath.SI``.
16071608
1608-
.. note:: This function does NOT return tuples for directory entities.
1609-
16101609
.. note:: Symlinks to **files** are followed automatically
16111610
1611+
.. deprecated:: 2.1.0
1612+
:func:`bitmath.listdir` is deprecated and will be removed in a future
1613+
release. Use :func:`os.walk` with :func:`bitmath.getsize` directly.
1614+
16121615
"""
1616+
warnings.warn(
1617+
"bitmath.listdir() is deprecated and will be removed in a future release. "
1618+
"Use os.walk() with bitmath.getsize() directly.",
1619+
DeprecationWarning,
1620+
stacklevel=2,
1621+
)
16131622
if 'filter' in kwargs:
16141623
warnings.warn(
16151624
"The 'filter' parameter of listdir() is deprecated as of 2.0.0 and will be "

docsite/source/module.rst

Lines changed: 34 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,9 @@ bitmath.listdir()
9191
* The absolute/relative path to a discovered file
9292
* A bitmath instance representing the *apparent size* of the file
9393

94-
:param string search_base: The directory to begin walking down
94+
:param search_base: The directory to begin walking down. May be a
95+
plain string or a :class:`pathlib.Path` object.
96+
:type search_base: str or pathlib.Path
9597
:param bool followlinks: **Default:** ``False``, do not follow
9698
links. Whether or not to follow symbolic
9799
links to directories. Setting to ``True``
@@ -117,123 +119,53 @@ bitmath.listdir()
117119
``True``
118120
:type system: One of :py:data:`bitmath.NIST` or :py:data:`bitmath.SI`
119121

120-
.. note::
121-
122-
* This function does **not** return tuples for directory
123-
entities. Including directories in results is `scheduled for
124-
introduction <https://github.com/timlnx/bitmath/issues/27>`_
125-
in an upcoming release.
126-
* Symlinks to **files** are followed automatically
122+
.. note:: Symlinks to **files** are followed automatically
127123

124+
.. deprecated:: 2.1.0
128125

129-
When interpreting the results from this function it is *crucial* to
130-
understand exactly which items are being taken into account, what
131-
decisions were made to select those items, and how their sizes are
132-
measured.
126+
:func:`bitmath.listdir` is deprecated and will be removed in a future
127+
release. Use :func:`os.walk` with :func:`bitmath.getsize` directly.
133128

134-
Results from this function may seem invalid when directly compared
135-
to the results from common command line utilities, such as ``du``,
136-
or ``tree``.
137129

138-
Let's pretend we have a directory structure like the following::
130+
Given this directory tree::
139131

140132
some_files/
141133
├── deeper_files/
142-
│   └── second_file
143-
└── first_file
144-
145-
Where ``some_files/`` is a directory, and so is
146-
``some_files/deeper_files/``. There are two regular files in this
147-
tree:
148-
149-
* ``somefiles/first_file`` - 1337 Bytes
150-
* ``some_files/deeper_files/second_file`` - 13370 Bytes
151-
152-
The **total** size of the files in this tree is **1337 + 13370 =
153-
14707** bytes.
154-
155-
.. versionadded:: 2.0.0
156-
157-
By far the simplest way to sum all of the results is using the built-in
158-
:py:func:`sum` function, or :py:func:`bitmath.sum` for additional control
159-
(complete docs on that following this section).
160-
161-
.. code-block:: python
162-
163-
>>> discovered_files = [f[1] for f in bitmath.listdir('./some_files')]
164-
>>> print(discovered_files)
165-
[Byte(1337.0), Byte(13370.0)]
166-
>>> print(sum(discovered_files))
167-
14707.0 B
168-
>>> print(sum(discovered_files).best_prefix())
169-
14.3623046875 KiB
170-
171-
172-
173-
Let's call :py:func:`bitmath.listdir` on the ``some_files/``
174-
directory and see what the results look like. First we'll use all
175-
the default parameters, then we'll set ``relpath`` to ``True``:
134+
│ └── second_file (13370 bytes)
135+
└── first_file (1337 bytes)
176136

177137
.. code-block:: python
178-
:linenos:
179-
:emphasize-lines: 5-6,10-11
180138
181139
>>> import bitmath
182-
>>> for f in bitmath.listdir('./some_files'):
183-
... print(f)
184-
...
185-
('/tmp/tmp.P5lqtyqwPh/some_files/first_file', Byte(1337.0))
186-
('/tmp/tmp.P5lqtyqwPh/some_files/deeper_files/second_file', Byte(13370.0))
187-
>>> for f in bitmath.listdir('./some_files', relpath=True):
188-
... print(f)
189-
...
190-
('some_files/first_file', Byte(1337.0))
191-
('some_files/deeper_files/second_file', Byte(13370.0))
192140
193-
On lines **5** and **6** the results print the full path, whereas
194-
on lines **10** and **11** the path is relative to the present
195-
working directory.
196-
197-
Let's play with the ``glob`` parameter now. Let's say we only
198-
want to include results for files whose name begins with "second":
199-
200-
.. code-block:: python
201-
202-
>>> for f in bitmath.listdir('./some_files', glob='second*'):
203-
... print(f)
204-
...
205-
('/tmp/tmp.P5lqtyqwPh/some_files/deeper_files/second_file', Byte(13370.0))
206-
207-
208-
If we wish to avoid having to write for-loops, we can collect the
209-
results into a list rather simply:
210-
211-
.. code-block:: python
212-
213-
>>> files = list(bitmath.listdir('./some_files'))
214-
>>> print(files)
215-
[('/tmp/tmp.P5lqtyqwPh/some_files/first_file', Byte(1337.0)), ('/tmp/tmp.P5lqtyqwPh/some_files/deeper_files/second_file', Byte(13370.0))]
216-
217-
Here's a more advanced example where we will sum the size of all
218-
the returned results and then play around with the possible
219-
formatting. Recall that a bitmath instance representing the size of
220-
the discovered file is the second item in each returned tuple.
221-
222-
.. code-block:: python
223-
224-
>>> discovered_files = [f[1] for f in bitmath.listdir('./some_files')]
225-
>>> print(discovered_files)
226-
[Byte(1337.0), Byte(13370.0)]
227-
>>> print(reduce(lambda x,y: x+y, discovered_files))
228-
14707.0 B
229-
>>> print(reduce(lambda x,y: x+y, discovered_files).best_prefix())
141+
>>> # Default: absolute paths, Byte instances
142+
>>> for path, size in bitmath.listdir('./some_files'):
143+
... print(path, size)
144+
/tmp/some_files/first_file Byte(1337.0)
145+
/tmp/some_files/deeper_files/second_file Byte(13370.0)
146+
147+
>>> # Relative paths
148+
>>> for path, size in bitmath.listdir('./some_files', relpath=True):
149+
... print(path, size)
150+
some_files/first_file Byte(1337.0)
151+
some_files/deeper_files/second_file Byte(13370.0)
152+
153+
>>> # Filter by glob
154+
>>> for path, size in bitmath.listdir('./some_files', glob='second*'):
155+
... print(path, size)
156+
/tmp/some_files/deeper_files/second_file Byte(13370.0)
157+
158+
>>> # Sum all results
159+
>>> sizes = [size for _, size in bitmath.listdir('./some_files')]
160+
>>> print(sum(sizes).best_prefix())
230161
14.3623046875 KiB
231-
>>> print(reduce(lambda x,y: x+y, discovered_files).best_prefix().format("{value:.3f} {unit}"))
232-
14.362 KiB
233-
234162
235163
.. versionadded:: 1.0.7
236164

165+
.. versionchanged:: 2.0.0
166+
The ``filter`` parameter was renamed to ``glob``. Passing ``filter``
167+
still works but emits a :exc:`DeprecationWarning`.
168+
237169

238170
.. _bitmath_sum:
239171

tests/test_file_size.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -271,10 +271,9 @@ def test_listdir_filter_kwarg_emits_deprecation_warning(self):
271271
with warnings.catch_warnings(record=True) as w:
272272
warnings.simplefilter("always")
273273
list(bitmath.listdir('./tests/listdir_nosymlinks/', filter='*'))
274-
self.assertEqual(len(w), 1)
275-
self.assertTrue(issubclass(w[0].category, DeprecationWarning))
276-
self.assertIn("filter", str(w[0].message))
277-
self.assertIn("glob", str(w[0].message))
274+
messages = [str(warning.message) for warning in w]
275+
self.assertTrue(all(issubclass(warning.category, DeprecationWarning) for warning in w))
276+
self.assertTrue(any("filter" in m and "glob" in m for m in messages))
278277

279278
def test_listdir_filter_kwarg_still_works(self):
280279
"""listdir() with deprecated filter= kwarg returns correct results"""

0 commit comments

Comments
 (0)