Skip to content

Commit a4071b7

Browse files
committed
Merge branch 'release/4.3.0'
2 parents c66f275 + f0c5fa6 commit a4071b7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+5334
-1283
lines changed

.coveragerc

-25
This file was deleted.

.github/stale.yml

-20
This file was deleted.

.github/workflows/codeql.yml

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: "CodeQL"
2+
3+
on:
4+
push:
5+
branches: [ "develop" ]
6+
pull_request:
7+
branches: [ "develop" ]
8+
schedule:
9+
- cron: "24 21 * * 1"
10+
11+
jobs:
12+
analyze:
13+
name: Analyze
14+
runs-on: ubuntu-latest
15+
permissions:
16+
actions: read
17+
contents: read
18+
security-events: write
19+
20+
strategy:
21+
fail-fast: false
22+
matrix:
23+
language: [ python, javascript ]
24+
25+
steps:
26+
- name: Checkout
27+
uses: actions/checkout@v3
28+
29+
- name: Initialize CodeQL
30+
uses: github/codeql-action/init@v2
31+
with:
32+
languages: ${{ matrix.language }}
33+
queries: +security-and-quality
34+
35+
- name: Autobuild
36+
uses: github/codeql-action/autobuild@v2
37+
if: ${{ matrix.language == 'python' || matrix.language == 'javascript' }}
38+
39+
- name: Perform CodeQL Analysis
40+
uses: github/codeql-action/analyze@v2
41+
with:
42+
category: "/language:${{ matrix.language }}"

.github/workflows/stale.yml

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: Close stale issues and pull requests
2+
3+
on:
4+
workflow_dispatch:
5+
schedule:
6+
- cron: '0 0 * * *' # Run every day at midnight
7+
8+
jobs:
9+
stale:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/stale@v8
13+
with:
14+
days-before-stale: 30
15+
exempt-issue-labels: in-progress,help-wanted,pinned,security,enhancement
16+
exempt-all-pr-assignees: true
17+

.travis.yml

-33
This file was deleted.

MANIFEST.in

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
recursive-exclude *.pyc
2+
recursive-exclude *.pyo
3+
recursive-exclude *.html
14
include AUTHORS.rst
25
include CHANGES.rst
36
include CONTRIBUTING.rst
@@ -7,6 +10,3 @@ include examples.py
710
include requirements.txt
811
include Makefile
912
include pytest.ini
10-
recursive-include tests *
11-
recursive-exclude *.pyc
12-
recursive-exclude *.pyo

README.rst

+93-36
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,19 @@ The progressbar module is very easy to use, yet very powerful. It will also
7272
automatically enable features like auto-resizing when the system supports it.
7373

7474
******************************************************************************
75-
Known issues
75+
Security contact information
7676
******************************************************************************
7777

78-
Due to limitations in both the IDLE shell and the Jetbrains (Pycharm) shells this progressbar cannot function properly within those.
78+
To report a security vulnerability, please use the
79+
`Tidelift security contact <https://tidelift.com/security>`_.
80+
Tidelift will coordinate the fix and disclosure.
81+
82+
******************************************************************************
83+
Known issues
84+
******************************************************************************
7985

86+
- The Jetbrains (PyCharm, etc) editors work out of the box, but for more advanced features such as the `MultiBar` support you will need to enable the "Enable terminal in output console" checkbox in the Run dialog.
8087
- The IDLE editor doesn't support these types of progress bars at all: https://bugs.python.org/issue23220
81-
- The Jetbrains (Pycharm) editors partially work but break with fast output. As a workaround make sure you only write to either `sys.stdout` (regular print) or `sys.stderr` at the same time. If you do plan to use both, make sure you wait about ~200 milliseconds for the next output or it will break regularly. Linked issue: https://github.com/WoLpH/python-progressbar/issues/115
8288
- Jupyter notebooks buffer `sys.stdout` which can cause mixed output. This issue can be resolved easily using: `import sys; sys.stdout.flush()`. Linked issue: https://github.com/WoLpH/python-progressbar/issues/173
8389

8490
******************************************************************************
@@ -152,6 +158,38 @@ In most cases the following will work as well, as long as you initialize the
152158
logging.error('Got %d', i)
153159
time.sleep(0.2)
154160
161+
Multiple (threaded) progressbars
162+
==============================================================================
163+
164+
.. code:: python
165+
166+
import random
167+
import threading
168+
import time
169+
170+
import progressbar
171+
172+
BARS = 5
173+
N = 50
174+
175+
176+
def do_something(bar):
177+
for i in bar(range(N)):
178+
# Sleep up to 0.1 seconds
179+
time.sleep(random.random() * 0.1)
180+
181+
# print messages at random intervals to show how extra output works
182+
if random.random() > 0.9:
183+
bar.print('random message for bar', bar, i)
184+
185+
186+
with progressbar.MultiBar() as multibar:
187+
for i in range(BARS):
188+
# Get a progressbar
189+
bar = multibar[f'Thread label here {i}']
190+
# Create a thread and pass the progressbar
191+
threading.Thread(target=do_something, args=(bar,)).start()
192+
155193
Context wrapper
156194
==============================================================================
157195
.. code:: python
@@ -238,55 +276,72 @@ Bar with wide Chinese (or other multibyte) characters
238276
for i in bar(range(10)):
239277
time.sleep(0.1)
240278
241-
Showing multiple (threaded) independent progress bars in parallel
279+
Showing multiple independent progress bars in parallel
242280
==============================================================================
243281

244-
While this method works fine and will continue to work fine, a smarter and
245-
fully automatic version of this is currently being made:
246-
https://github.com/WoLpH/python-progressbar/issues/176
247-
248282
.. code:: python
249283
250284
import random
251285
import sys
252-
import threading
253286
import time
254287
255288
import progressbar
256289
257-
output_lock = threading.Lock()
290+
BARS = 5
291+
N = 100
292+
293+
# Construct the list of progress bars with the `line_offset` so they draw
294+
# below each other
295+
bars = []
296+
for i in range(BARS):
297+
bars.append(
298+
progressbar.ProgressBar(
299+
max_value=N,
300+
# We add 1 to the line offset to account for the `print_fd`
301+
line_offset=i + 1,
302+
max_error=False,
303+
)
304+
)
258305
306+
# Create a file descriptor for regular printing as well
307+
print_fd = progressbar.LineOffsetStreamWrapper(sys.stdout, 0)
259308
260-
class LineOffsetStreamWrapper:
261-
UP = '\033[F'
262-
DOWN = '\033[B'
309+
# The progress bar updates, normally you would do something useful here
310+
for i in range(N * BARS):
311+
time.sleep(0.005)
263312
264-
def __init__(self, lines=0, stream=sys.stderr):
265-
self.stream = stream
266-
self.lines = lines
313+
# Increment one of the progress bars at random
314+
bars[random.randrange(0, BARS)].increment()
267315
268-
def write(self, data):
269-
with output_lock:
270-
self.stream.write(self.UP * self.lines)
271-
self.stream.write(data)
272-
self.stream.write(self.DOWN * self.lines)
273-
self.stream.flush()
316+
# Print a status message to the `print_fd` below the progress bars
317+
print(f'Hi, we are at update {i+1} of {N * BARS}', file=print_fd)
274318
275-
def __getattr__(self, name):
276-
return getattr(self.stream, name)
319+
# Cleanup the bars
320+
for bar in bars:
321+
bar.finish()
277322
323+
# Add a newline to make sure the next print starts on a new line
324+
print()
278325
279-
bars = []
280-
for i in range(5):
281-
bars.append(
282-
progressbar.ProgressBar(
283-
fd=LineOffsetStreamWrapper(i),
284-
max_value=1000,
285-
)
286-
)
326+
******************************************************************************
287327

288-
if i:
289-
print('Reserve a line for the progressbar')
328+
Naturally we can do this from separate threads as well:
329+
330+
.. code:: python
331+
332+
import random
333+
import threading
334+
import time
335+
336+
import progressbar
337+
338+
BARS = 5
339+
N = 100
340+
341+
# Create the bars with the given line offset
342+
bars = []
343+
for line_offset in range(BARS):
344+
bars.append(progressbar.ProgressBar(line_offset=line_offset, max_value=N))
290345
291346
292347
class Worker(threading.Thread):
@@ -295,10 +350,12 @@ https://github.com/WoLpH/python-progressbar/issues/176
295350
self.bar = bar
296351
297352
def run(self):
298-
for i in range(1000):
299-
time.sleep(random.random() / 100)
353+
for i in range(N):
354+
time.sleep(random.random() / 25)
300355
self.bar.update(i)
301356
302357
303358
for bar in bars:
304359
Worker(bar).start()
360+
361+
print()

0 commit comments

Comments
 (0)