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
+ [![PyPi](https://img.shields.io/pypi/v/argparse-from-file)](https://pypi.org/project/argparse-from-file/)
16
+ [![AUR](https://img.shields.io/aur/version/python-argparse-from-file)](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,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -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)