argparse-from-file 1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: argparse-from-file
|
|
3
|
+
Version: 1.0
|
|
4
|
+
Summary: Wrapper for Python's argparse to also read arguments from a file
|
|
5
|
+
Author-email: Mark Blakeney <mark.blakeney@bullet-systems.net>
|
|
6
|
+
License-Expression: GPL-3.0-or-later
|
|
7
|
+
Project-URL: Homepage, https://github.com/bulletmark/argparse-from-file
|
|
8
|
+
Keywords: argparse,ConfigArgParse
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Requires-Python: >=3.8
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: platformdirs
|
|
13
|
+
|
|
14
|
+
# ARGPARSE-FROM-FILE
|
|
15
|
+
[](https://pypi.org/project/argparse-from-file/)
|
|
16
|
+
[](https://aur.archlinux.org/packages/python-argparse-from-file/)
|
|
17
|
+
|
|
18
|
+
`argparse-from-file` is a lightweight wrapper for Python's standard
|
|
19
|
+
[`argparse`][argparse] module. It allows your program to read default arguments
|
|
20
|
+
from a configuration file, which are prepended to arguments provided on the
|
|
21
|
+
command line.
|
|
22
|
+
|
|
23
|
+
The latest version of this document and code is available at
|
|
24
|
+
https://github.com/bulletmark/argparse-from-file.
|
|
25
|
+
|
|
26
|
+
## Features
|
|
27
|
+
|
|
28
|
+
* **Drop-in replacement:** Simply change `import argparse` to `import
|
|
29
|
+
argparse_from_file as argparse`. No other code changes are needed for basic
|
|
30
|
+
functionality.
|
|
31
|
+
* **Automatic configuration:** By default, it loads arguments from
|
|
32
|
+
`<program_name>-flags.conf` in the user's configuration directory (e.g.,
|
|
33
|
+
`~/.config/` on Linux). The exact path is determined using the
|
|
34
|
+
[`platformdirs`][platformdirs] library to respect OS conventions.
|
|
35
|
+
* **Custom configuration file:** Specify a custom file path with the
|
|
36
|
+
`from_file` argument to [`ArgumentParser()`][argparser].
|
|
37
|
+
* **Simple file format:** The configuration file is a simple text file with
|
|
38
|
+
options specified on one or more lines. Blank lines and lines starting with
|
|
39
|
+
`#` are ignored.
|
|
40
|
+
* **Informative help text:** The program's help message is automatically
|
|
41
|
+
updated to show the path to the configuration file.
|
|
42
|
+
|
|
43
|
+
## Usage
|
|
44
|
+
|
|
45
|
+
To get started, replace the standard [`argparse`][argparse] import in your project:
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
# import argparse
|
|
49
|
+
import argparse_from_file as argparse
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
That's it! Your application will now automatically look for a default
|
|
53
|
+
configuration file and use the default arguments provided therein.
|
|
54
|
+
|
|
55
|
+
To specify a custom configuration file, use the `from_file` keyword argument,
|
|
56
|
+
which is the only addition to the standard
|
|
57
|
+
[`ArgumentParser()`][argparser] API:
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
# Use a specific file path
|
|
61
|
+
parser = argparse.ArgumentParser(from_file='/path/to/my/config', ..)
|
|
62
|
+
|
|
63
|
+
# Use a file relative to the user's config directory
|
|
64
|
+
parser = argparse.ArgumentParser(from_file='my-app.conf', ..)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The `from_file` argument accepts a string or a [`pathlib.Path`][pathlib].
|
|
68
|
+
Relative paths are resolved relative to the user's configuration directory as
|
|
69
|
+
determined by `platformdirs`.
|
|
70
|
+
|
|
71
|
+
## Configuration File Format
|
|
72
|
+
|
|
73
|
+
Arguments in the configuration file are best specified one per line so they can
|
|
74
|
+
easily be commented out. It is also recommended to use long-form options for
|
|
75
|
+
clarity.
|
|
76
|
+
|
|
77
|
+
Example `~/.config/myprog-flags.conf`:
|
|
78
|
+
```
|
|
79
|
+
--verbose
|
|
80
|
+
|
|
81
|
+
# Always run with foo set to 123
|
|
82
|
+
--foo 123
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Customizing the Help Message
|
|
86
|
+
|
|
87
|
+
`argparse-from-file` automatically adds an `epilog` to the help message
|
|
88
|
+
indicating the configuration file path. If you instead provide a custom `epilog`
|
|
89
|
+
(or `usage` or `description`), you can embed the `#FROM_FILE_PATH#` placeholder,
|
|
90
|
+
and it will be replaced with the actual path used.
|
|
91
|
+
|
|
92
|
+
## Example
|
|
93
|
+
|
|
94
|
+
Here is a simple example program (`myprog.py`):
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
#!/usr/bin/python3
|
|
98
|
+
import argparse_from_file as argparse
|
|
99
|
+
|
|
100
|
+
parser = argparse.ArgumentParser()
|
|
101
|
+
parser.add_argument('--foo', type=int, default=42, help='foo help')
|
|
102
|
+
opts = parser.parse_args()
|
|
103
|
+
|
|
104
|
+
print(f"foo is: {opts.foo}")
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
If `~/.config/myprog-flags.conf` contains `--foo=123`, the output is:
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
$ python myprog.py
|
|
111
|
+
foo is: 123
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The help text (`epilog`) is also automatically added as seen below:
|
|
115
|
+
```
|
|
116
|
+
$ python myprog.py -h
|
|
117
|
+
usage: myprog.py [-h] [--foo FOO]
|
|
118
|
+
|
|
119
|
+
options:
|
|
120
|
+
-h, --help show this help message and exit
|
|
121
|
+
--foo FOO foo help
|
|
122
|
+
|
|
123
|
+
Note you can set default starting options in /home/user/.config/myprog-flags.conf.
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Installation
|
|
127
|
+
|
|
128
|
+
Arch Linux users can install `python-argparse-from-file` from the
|
|
129
|
+
[AUR](https://aur.archlinux.org/packages/python-argparse-from-file/).
|
|
130
|
+
|
|
131
|
+
Alternatively, `argparse-from-file` is available on
|
|
132
|
+
[PyPI](https://pypi.org/project/argparse-from-file/) and can be installed with
|
|
133
|
+
pip:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
pip install argparse-from-file
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## License
|
|
140
|
+
|
|
141
|
+
Copyright (C) 2025 Mark Blakeney. This program is distributed under the terms
|
|
142
|
+
of the GNU General Public License. This program is free software: you can
|
|
143
|
+
redistribute it and/or modify it under the terms of the GNU General Public
|
|
144
|
+
License as published by the Free Software Foundation, either version 3 of the
|
|
145
|
+
License, or any later version. This program is distributed in the hope that it
|
|
146
|
+
will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
147
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
148
|
+
License at <https://opensource.org/license/gpl-3-0> for more details.
|
|
149
|
+
|
|
150
|
+
[argparse]: https://docs.python.org/3/library/argparse.html
|
|
151
|
+
[platformdirs]: https://github.com/tox-dev/platformdirs
|
|
152
|
+
[argparser]: https://docs.python.org/3/library/argparse.html#argumentparser-objects
|
|
153
|
+
[pathlib]: https://docs.python.org/3/library/pathlib.html
|
|
154
|
+
<!-- vim: se ai syn=markdown: -->
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
argparse_from_file.py,sha256=19CjAx6MZZgdtHrY-Brl7z7F5M7OwofBGymRRDGpKpk,2724
|
|
2
|
+
argparse_from_file-1.0.dist-info/METADATA,sha256=ZHwjobsEsXjG7c4vcmIL31AVfXVF_3ZxID7oz2kfmpE,5420
|
|
3
|
+
argparse_from_file-1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
4
|
+
argparse_from_file-1.0.dist-info/top_level.txt,sha256=8JxJArcqZ5CZzytAonnblZ3Y8-zq2DDZXYzcTJf9k70,19
|
|
5
|
+
argparse_from_file-1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
argparse_from_file
|
argparse_from_file.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A very light wrapper around Python's argparse module to prepend a program's
|
|
3
|
+
argument list with default options and arguments read from a user configuration
|
|
4
|
+
file.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import argparse
|
|
8
|
+
import shlex
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
import platformdirs
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ArgumentParser(argparse.ArgumentParser):
|
|
16
|
+
def __init__(self, *args, **kwargs):
|
|
17
|
+
self._argv = []
|
|
18
|
+
|
|
19
|
+
# from_file = 'path-to/file': Use this as "from file" name/path. If
|
|
20
|
+
# relative then wrt platform specific user config dir.
|
|
21
|
+
# from_file = '': Do not use a "from file".
|
|
22
|
+
# from_file = None: Create default "from file" path.
|
|
23
|
+
if (from_file := kwargs.pop('from_file', None)) is None:
|
|
24
|
+
from_file = Path(sys.argv[0]).stem + '-flags.conf'
|
|
25
|
+
|
|
26
|
+
if from_file:
|
|
27
|
+
from_file_path = platformdirs.user_config_path(from_file)
|
|
28
|
+
from_file_path_str = str(from_file_path)
|
|
29
|
+
# epilog = 'text string': Set this as epilog, replacing any
|
|
30
|
+
# '#FROM_FILE_PATH#' with the above determined "from file" path.
|
|
31
|
+
# epilog = '': Do not set an epilog.
|
|
32
|
+
# epilog = None: create default epilog with "from file" path.
|
|
33
|
+
if (epilog := kwargs.pop('epilog', None)) is None:
|
|
34
|
+
epilog = f'Note you can set default starting options in {from_file_path_str}.'
|
|
35
|
+
else:
|
|
36
|
+
epilog = epilog.replace('#FROM_FILE_PATH#', from_file_path_str)
|
|
37
|
+
|
|
38
|
+
if epilog:
|
|
39
|
+
kwargs['epilog'] = epilog
|
|
40
|
+
|
|
41
|
+
# Also replace any '#FROM_FILE_PATH#' in usage and description.
|
|
42
|
+
for kw in 'usage', 'description':
|
|
43
|
+
if v := kwargs.get(kw):
|
|
44
|
+
kwargs[kw] = v.replace('#FROM_FILE_PATH#', from_file_path_str)
|
|
45
|
+
|
|
46
|
+
# Create list of default args from user file.
|
|
47
|
+
if from_file_path.is_file():
|
|
48
|
+
with from_file_path.open() as fp:
|
|
49
|
+
self._argv.extend(
|
|
50
|
+
ln
|
|
51
|
+
for line in fp
|
|
52
|
+
if (ln := line.strip()) and not ln.startswith('#')
|
|
53
|
+
)
|
|
54
|
+
else:
|
|
55
|
+
from_file_path = None
|
|
56
|
+
|
|
57
|
+
self.from_file_path = from_file_path
|
|
58
|
+
return super().__init__(*args, **kwargs)
|
|
59
|
+
|
|
60
|
+
def parse_args(self, args=None, namespace=None): # type: ignore[override]
|
|
61
|
+
if args is None and self._argv:
|
|
62
|
+
# Combine args from file and command line, to be parsed
|
|
63
|
+
argstr = ' '.join(self._argv).strip()
|
|
64
|
+
args = shlex.split(argstr) + sys.argv[1:]
|
|
65
|
+
|
|
66
|
+
del self._argv
|
|
67
|
+
return super().parse_args(args, namespace)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def __getattr__(name: str):
|
|
71
|
+
"Proxy all other attributes from argparse module."
|
|
72
|
+
return getattr(argparse, name)
|