Skip to content

Commit 91febb4

Browse files
authored
Merge branch 'google:master' into package-name
2 parents 3c468d1 + 716bbc2 commit 91febb4

Some content is hidden

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

57 files changed

+426
-697
lines changed

.github/dependabot.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Basic dependabot.yml file with minimum configuration for two package managers
2+
3+
version: 2
4+
updates:
5+
# Enable version updates for python
6+
- package-ecosystem: "pip"
7+
directory: "/"
8+
schedule:
9+
interval: "monthly"
10+
labels: ["dependabot"]
11+
pull-request-branch-name:
12+
separator: "-"
13+
open-pull-requests-limit: 5
14+
reviewers:
15+
- "dbieber"
16+
17+
# Enable version updates for GitHub Actions
18+
- package-ecosystem: "github-actions"
19+
directory: "/"
20+
schedule:
21+
interval: "monthly"
22+
groups:
23+
gh-actions:
24+
patterns:
25+
- "*" # Check all dependencies
26+
labels: ["dependabot"]
27+
pull-request-branch-name:
28+
separator: "-"
29+
open-pull-requests-limit: 5
30+
reviewers:
31+
- "dbieber"

.github/scripts/build.sh

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,15 @@
1717
# Exit when any command fails.
1818
set -e
1919

20-
PYTHON_VERSION=${PYTHON_VERSION:-2.7}
20+
PYTHON_VERSION=${PYTHON_VERSION:-3.7}
2121

22-
pip install --upgrade setuptools pip
23-
pip install --upgrade pylint pytest pytest-pylint pytest-runner
24-
pip install termcolor
25-
pip install hypothesis python-Levenshtein
26-
pip install mock
27-
python setup.py develop
22+
pip install -e .[test]
2823
python -m pytest # Run the tests without IPython.
2924
pip install ipython
3025
python -m pytest # Now run the tests with IPython.
3126
pylint fire --ignore=test_components_py3.py,parser_fuzz_test.py,console
32-
if [[ ${PYTHON_VERSION} == 3.7 ]]; then
33-
# Run type-checking.
34-
pip install pytype;
35-
pytype -x fire/test_components_py3.py;
27+
if [[ ${PYTHON_VERSION} == 3.12 ]]; then
28+
# Run type-checking
29+
pip install ty
30+
python -m ty check --python $(which python) --exclude fire/test_components_py3.py --exclude fire/console/ --exclude fire/formatting_windows.py
3631
fi

.github/workflows/build.yml

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,38 @@
11
name: Python Fire
22

3-
on: [push]
3+
on:
4+
push:
5+
branches: ["master"]
6+
pull_request:
7+
branches: ["master"]
8+
9+
defaults:
10+
run:
11+
shell: bash
412

513
jobs:
614
build:
7-
runs-on: ubuntu-20.04
15+
runs-on: ${{ matrix.os }}
816
strategy:
917
matrix:
10-
python-version: [2.7, 3.5, 3.7, 3.8, 3.9]
18+
os: ["macos-latest", "ubuntu-latest"]
19+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14.0-rc.2"]
20+
include:
21+
- {os: "ubuntu-22.04", python-version: "3.7"}
1122

1223
steps:
1324
# Checkout the repo.
1425
- name: Checkout Python Fire repository
15-
uses: actions/checkout@v3
26+
uses: actions/checkout@v4
1627

1728
# Set up Python environment.
1829
- name: Set up Python ${{ matrix.python-version }}
19-
uses: actions/setup-python@v4
30+
uses: actions/setup-python@v5
2031
with:
2132
python-version: ${{ matrix.python-version }}
2233

2334
# Build Python Fire using the build.sh script.
2435
- name: Run build script
25-
shell: bash
2636
run: ./.github/scripts/build.sh
2737
env:
2838
PYTHON_VERSION: ${{ matrix.python-version }}

CONTRIBUTING.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,13 @@ In addition, the project follows a convention of:
4040
- Maximum line length: 80 characters
4141
- Indentation: 2 spaces (4 for line continuation)
4242
- PascalCase for function and method names.
43-
- No type hints, as described in [PEP 484], to maintain compatibility with
44-
Python versions < 3.5.
4543
- Single quotes around strings, three double quotes around docstrings.
4644

4745
[Google Python Style Guide]: http://google.github.io/styleguide/pyguide.html
48-
[PEP 484]: https://www.python.org/dev/peps/pep-0484
4946

5047
## Testing
5148

52-
Python Fire uses [Github Actions](https://github.com/google/python-fire/actions) to run tests on each pull request. You can run
49+
Python Fire uses [GitHub Actions](https://github.com/google/python-fire/actions) to run tests on each pull request. You can run
5350
these tests yourself as well. To do this, first install the test dependencies
5451
listed in setup.py (e.g. pytest, mock, termcolor, and hypothesis).
5552
Then run the tests by running `pytest` in the root directory of the repository.

MANIFEST.in

Lines changed: 0 additions & 1 deletion
This file was deleted.

docs/guide.md

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ the program to the command line.
3030
import fire
3131

3232
def hello(name):
33-
return 'Hello {name}!'.format(name=name)
33+
return f'Hello {name}!'
3434

3535
if __name__ == '__main__':
3636
fire.Fire()
@@ -52,7 +52,7 @@ command line.
5252
import fire
5353

5454
def hello(name):
55-
return 'Hello {name}!'.format(name=name)
55+
return f'Hello {name}!'
5656

5757
if __name__ == '__main__':
5858
fire.Fire(hello)
@@ -76,7 +76,7 @@ We can alternatively write this program like this:
7676
import fire
7777

7878
def hello(name):
79-
return 'Hello {name}!'.format(name=name)
79+
return f'Hello {name}!'
8080

8181
def main():
8282
fire.Fire(hello)
@@ -93,7 +93,7 @@ then simply this:
9393
import fire
9494

9595
def hello(name):
96-
return 'Hello {name}!'.format(name=name)
96+
return f'Hello {name}!'
9797

9898
def main():
9999
fire.Fire(hello)
@@ -105,7 +105,7 @@ If you have a file `example.py` that doesn't even import fire:
105105

106106
```python
107107
def hello(name):
108-
return 'Hello {name}!'.format(name=name)
108+
return f'Hello {name}!'
109109
```
110110

111111
Then you can use it with Fire like this:
@@ -589,6 +589,25 @@ default values that you don't want to specify. It is also important to remember
589589
to change the separator if you want to pass `-` as an argument.
590590

591591

592+
##### Async Functions
593+
594+
Fire supports calling async functions too. Here's a simple example.
595+
596+
```python
597+
import asyncio
598+
599+
async def count_to_ten():
600+
for i in range(1, 11):
601+
await asyncio.sleep(1)
602+
print(i)
603+
604+
if __name__ == '__main__':
605+
fire.Fire(count_to_ten)
606+
```
607+
608+
Whenever fire encounters a coroutine function, it runs it, blocking until it completes.
609+
610+
592611
### Argument Parsing
593612

594613
The types of the arguments are determined by their values, rather than by the

examples/widget/widget.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def whack(self, n=1):
2525

2626
def bang(self, noise='bang'):
2727
"""Makes a loud noise."""
28-
return '{noise} bang!'.format(noise=noise)
28+
return f'{noise} bang!'
2929

3030

3131
def main():

fire/__init__.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,7 @@
1414

1515
"""The Python Fire module."""
1616

17-
from __future__ import absolute_import
18-
from __future__ import division
19-
from __future__ import print_function
20-
2117
from fire.core import Fire
2218

2319
__all__ = ['Fire']
24-
__version__ = '0.5.0'
20+
__version__ = '0.7.1'

fire/__main__.py

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,8 @@
1818
This allows using Fire with third-party libraries without modifying their code.
1919
"""
2020

21-
from __future__ import absolute_import
22-
from __future__ import division
23-
from __future__ import print_function
24-
2521
import importlib
22+
from importlib import util
2623
import os
2724
import sys
2825

@@ -57,31 +54,17 @@ def import_from_file_path(path):
5754
"""
5855

5956
if not os.path.exists(path):
60-
raise IOError('Given file path does not exist.')
57+
raise OSError('Given file path does not exist.')
6158

6259
module_name = os.path.basename(path)
6360

64-
if sys.version_info.major == 3 and sys.version_info.minor < 5:
65-
loader = importlib.machinery.SourceFileLoader( # pylint: disable=no-member
66-
fullname=module_name,
67-
path=path,
68-
)
69-
70-
module = loader.load_module(module_name) # pylint: disable=deprecated-method
71-
72-
elif sys.version_info.major == 3:
73-
from importlib import util # pylint: disable=g-import-not-at-top,import-outside-toplevel,no-name-in-module
74-
spec = util.spec_from_file_location(module_name, path)
75-
76-
if spec is None:
77-
raise IOError('Unable to load module from specified path.')
61+
spec = util.spec_from_file_location(module_name, path)
7862

79-
module = util.module_from_spec(spec) # pylint: disable=no-member
80-
spec.loader.exec_module(module) # pytype: disable=attribute-error
63+
if spec is None or spec.loader is None:
64+
raise OSError('Unable to load module from specified path.')
8165

82-
else:
83-
import imp # pylint: disable=g-import-not-at-top,import-outside-toplevel,deprecated-module
84-
module = imp.load_source(module_name, path)
66+
module = util.module_from_spec(spec) # pylint: disable=no-member
67+
spec.loader.exec_module(module)
8568

8669
return module, module_name
8770

@@ -121,7 +104,7 @@ def import_module(module_or_filename):
121104
return import_from_file_path(module_or_filename)
122105

123106
if os.path.sep in module_or_filename: # Use / to detect if it was a filename.
124-
raise IOError('Fire was passed a filename which could not be found.')
107+
raise OSError('Fire was passed a filename which could not be found.')
125108

126109
return import_from_module_name(module_or_filename) # Assume it's a module.
127110

fire/completion.py

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import inspect
2424

2525
from fire import inspectutils
26-
import six
2726

2827

2928
def Script(name, component, default_options=None, shell='bash'):
@@ -104,7 +103,7 @@ def _BashScript(name, commands, default_options=None):
104103
option_already_entered()
105104
{{
106105
local opt
107-
for opt in ${{COMP_WORDS[@]:0:COMP_CWORD}}
106+
for opt in ${{COMP_WORDS[@]:0:$COMP_CWORD}}
108107
do
109108
if [ $1 == $opt ]; then
110109
return 0
@@ -278,10 +277,7 @@ def _FishScript(name, commands, default_options=None):
278277
)
279278

280279
return fish_source.format(
281-
global_options=' '.join(
282-
'"{option}"'.format(option=option)
283-
for option in global_options
284-
)
280+
global_options=' '.join(f'"{option}"' for option in global_options)
285281
)
286282

287283

@@ -308,23 +304,24 @@ def MemberVisible(component, name, member, class_attrs=None, verbose=False):
308304
Returns
309305
A boolean value indicating whether the member should be included.
310306
"""
311-
if isinstance(name, six.string_types) and name.startswith('__'):
307+
if isinstance(name, str) and name.startswith('__'):
312308
return False
313309
if verbose:
314310
return True
315311
if (member is absolute_import
316312
or member is division
317313
or member is print_function):
318314
return False
319-
if isinstance(member, type(absolute_import)) and six.PY34:
315+
if isinstance(member, type(absolute_import)):
320316
return False
321-
if inspect.ismodule(member) and member is six:
322-
# TODO(dbieber): Determine more generally which modules to hide.
317+
# TODO(dbieber): Determine more generally which modules to hide.
318+
modules_to_hide = []
319+
if inspect.ismodule(member) and member in modules_to_hide:
323320
return False
324321
if inspect.isclass(component):
325322
# If class_attrs has not been provided, compute it.
326323
if class_attrs is None:
327-
class_attrs = inspectutils.GetClassAttrsDict(class_attrs) or {}
324+
class_attrs = inspectutils.GetClassAttrsDict(component) or {}
328325
class_attr = class_attrs.get(name)
329326
if class_attr:
330327
# Methods and properties should only be accessible on instantiated
@@ -336,14 +333,7 @@ def MemberVisible(component, name, member, class_attrs=None, verbose=False):
336333
tuplegetter = getattr(collections, '_tuplegetter', type(None))
337334
if isinstance(class_attr.object, tuplegetter):
338335
return False
339-
if (six.PY2 and inspect.isfunction(component)
340-
and name in ('func_closure', 'func_code', 'func_defaults',
341-
'func_dict', 'func_doc', 'func_globals', 'func_name')):
342-
return False
343-
if (six.PY2 and inspect.ismethod(component)
344-
and name in ('im_class', 'im_func', 'im_self')):
345-
return False
346-
if isinstance(name, six.string_types):
336+
if isinstance(name, str):
347337
return not name.startswith('_')
348338
return True # Default to including the member
349339

@@ -392,7 +382,7 @@ def _CompletionsFromArgs(fn_args):
392382
completions = []
393383
for arg in fn_args:
394384
arg = arg.replace('_', '-')
395-
completions.append('--{arg}'.format(arg=arg))
385+
completions.append(f'--{arg}')
396386
return completions
397387

398388

@@ -438,7 +428,7 @@ def _FormatForCommand(token):
438428
Returns:
439429
The transformed token.
440430
"""
441-
if not isinstance(token, six.string_types):
431+
if not isinstance(token, str):
442432
token = str(token)
443433

444434
if token.startswith('_'):

0 commit comments

Comments
 (0)