docker-composer 2.17.4__tar.gz → 5.0.2__tar.gz

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.
Files changed (75) hide show
  1. docker_composer-5.0.2/.gitignore +255 -0
  2. {docker_composer-2.17.4 → docker_composer-5.0.2}/PKG-INFO +29 -23
  3. {docker_composer-2.17.4 → docker_composer-5.0.2}/README.md +21 -8
  4. docker_composer-5.0.2/pyproject.toml +71 -0
  5. docker_composer-5.0.2/src/docker_composer/__init__.py +6 -0
  6. {docker_composer-2.17.4 → docker_composer-5.0.2}/src/docker_composer/_utils/argument.py +33 -40
  7. {docker_composer-2.17.4 → docker_composer-5.0.2}/src/docker_composer/_utils/generate_class.py +77 -64
  8. docker_composer-5.0.2/src/docker_composer/_utils/sync_version.py +21 -0
  9. {docker_composer-2.17.4 → docker_composer-5.0.2}/src/docker_composer/base.py +19 -16
  10. docker_composer-5.0.2/src/docker_composer/runner/cmd/__init__.py +0 -0
  11. docker_composer-5.0.2/src/docker_composer/runner/cmd/attach.py +36 -0
  12. docker_composer-5.0.2/src/docker_composer/runner/cmd/build.py +60 -0
  13. docker_composer-5.0.2/src/docker_composer/runner/cmd/commit.py +37 -0
  14. docker_composer-5.0.2/src/docker_composer/runner/cmd/config.py +80 -0
  15. docker_composer-5.0.2/src/docker_composer/runner/cmd/cp.py +38 -0
  16. docker_composer-5.0.2/src/docker_composer/runner/cmd/create.py +51 -0
  17. docker_composer-5.0.2/src/docker_composer/runner/cmd/down.py +38 -0
  18. docker_composer-5.0.2/src/docker_composer/runner/cmd/events.py +33 -0
  19. docker_composer-5.0.2/src/docker_composer/runner/cmd/exec.py +43 -0
  20. docker_composer-5.0.2/src/docker_composer/runner/cmd/export.py +30 -0
  21. docker_composer-5.0.2/src/docker_composer/runner/cmd/images.py +31 -0
  22. docker_composer-5.0.2/src/docker_composer/runner/cmd/kill.py +31 -0
  23. docker_composer-5.0.2/src/docker_composer/runner/cmd/logs.py +46 -0
  24. docker_composer-5.0.2/src/docker_composer/runner/cmd/ls.py +36 -0
  25. docker_composer-5.0.2/src/docker_composer/runner/cmd/pause.py +26 -0
  26. docker_composer-5.0.2/src/docker_composer/runner/cmd/port.py +30 -0
  27. docker_composer-5.0.2/src/docker_composer/runner/cmd/ps.py +54 -0
  28. docker_composer-5.0.2/src/docker_composer/runner/cmd/publish.py +40 -0
  29. docker_composer-5.0.2/src/docker_composer/runner/cmd/pull.py +40 -0
  30. docker_composer-5.0.2/src/docker_composer/runner/cmd/push.py +35 -0
  31. docker_composer-5.0.2/src/docker_composer/runner/cmd/restart.py +31 -0
  32. {docker_composer-2.17.4 → docker_composer-5.0.2}/src/docker_composer/runner/cmd/rm.py +18 -12
  33. docker_composer-5.0.2/src/docker_composer/runner/cmd/run.py +86 -0
  34. docker_composer-5.0.2/src/docker_composer/runner/cmd/scale.py +29 -0
  35. docker_composer-5.0.2/src/docker_composer/runner/cmd/start.py +31 -0
  36. docker_composer-5.0.2/src/docker_composer/runner/cmd/stats.py +43 -0
  37. docker_composer-5.0.2/src/docker_composer/runner/cmd/stop.py +28 -0
  38. docker_composer-5.0.2/src/docker_composer/runner/cmd/top.py +26 -0
  39. docker_composer-5.0.2/src/docker_composer/runner/cmd/unpause.py +26 -0
  40. docker_composer-5.0.2/src/docker_composer/runner/cmd/up.py +113 -0
  41. docker_composer-5.0.2/src/docker_composer/runner/cmd/version.py +31 -0
  42. docker_composer-5.0.2/src/docker_composer/runner/cmd/volumes.py +37 -0
  43. docker_composer-5.0.2/src/docker_composer/runner/cmd/wait.py +29 -0
  44. docker_composer-5.0.2/src/docker_composer/runner/cmd/watch.py +35 -0
  45. {docker_composer-2.17.4 → docker_composer-5.0.2}/src/docker_composer/runner/root.py +491 -119
  46. docker_composer-2.17.4/pyproject.toml +0 -52
  47. docker_composer-2.17.4/src/docker_composer/__init__.py +0 -1
  48. docker_composer-2.17.4/src/docker_composer/runner/cmd/build.py +0 -38
  49. docker_composer-2.17.4/src/docker_composer/runner/cmd/config.py +0 -53
  50. docker_composer-2.17.4/src/docker_composer/runner/cmd/cp.py +0 -29
  51. docker_composer-2.17.4/src/docker_composer/runner/cmd/create.py +0 -39
  52. docker_composer-2.17.4/src/docker_composer/runner/cmd/down.py +0 -29
  53. docker_composer-2.17.4/src/docker_composer/runner/cmd/events.py +0 -23
  54. docker_composer-2.17.4/src/docker_composer/runner/cmd/exec.py +0 -36
  55. docker_composer-2.17.4/src/docker_composer/runner/cmd/images.py +0 -25
  56. docker_composer-2.17.4/src/docker_composer/runner/cmd/kill.py +0 -25
  57. docker_composer-2.17.4/src/docker_composer/runner/cmd/logs.py +0 -38
  58. docker_composer-2.17.4/src/docker_composer/runner/cmd/ls.py +0 -30
  59. docker_composer-2.17.4/src/docker_composer/runner/cmd/pause.py +0 -19
  60. docker_composer-2.17.4/src/docker_composer/runner/cmd/port.py +0 -23
  61. docker_composer-2.17.4/src/docker_composer/runner/cmd/ps.py +0 -35
  62. docker_composer-2.17.4/src/docker_composer/runner/cmd/pull.py +0 -32
  63. docker_composer-2.17.4/src/docker_composer/runner/cmd/push.py +0 -29
  64. docker_composer-2.17.4/src/docker_composer/runner/cmd/restart.py +0 -25
  65. docker_composer-2.17.4/src/docker_composer/runner/cmd/run.py +0 -66
  66. docker_composer-2.17.4/src/docker_composer/runner/cmd/start.py +0 -19
  67. docker_composer-2.17.4/src/docker_composer/runner/cmd/stop.py +0 -21
  68. docker_composer-2.17.4/src/docker_composer/runner/cmd/top.py +0 -19
  69. docker_composer-2.17.4/src/docker_composer/runner/cmd/unpause.py +0 -19
  70. docker_composer-2.17.4/src/docker_composer/runner/cmd/up.py +0 -85
  71. docker_composer-2.17.4/src/docker_composer/runner/cmd/version.py +0 -25
  72. {docker_composer-2.17.4 → docker_composer-5.0.2}/LICENSE.txt +0 -0
  73. {docker_composer-2.17.4 → docker_composer-5.0.2}/src/docker_composer/_utils/__init__.py +0 -0
  74. {docker_composer-2.17.4 → docker_composer-5.0.2}/src/docker_composer/py.typed +0 -0
  75. {docker_composer-2.17.4 → docker_composer-5.0.2}/src/docker_composer/runner/__init__.py +0 -0
@@ -0,0 +1,255 @@
1
+
2
+ # Created by https://www.toptal.com/developers/gitignore/api/python,pycharm,kate
3
+ # Edit at https://www.toptal.com/developers/gitignore?templates=python,pycharm,kate
4
+
5
+ ### Kate ###
6
+ # Swap Files #
7
+ .*.kate-swp
8
+ .swp.*
9
+
10
+ ### PyCharm ###
11
+ # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
12
+ # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
13
+ .idea/**
14
+ # User-specific stuff
15
+ .idea/**/workspace.xml
16
+ .idea/**/tasks.xml
17
+ .idea/**/usage.statistics.xml
18
+ .idea/**/dictionaries
19
+ .idea/**/shelf
20
+
21
+ # Generated files
22
+ .idea/**/contentModel.xml
23
+
24
+ # Sensitive or high-churn files
25
+ .idea/**/dataSources/
26
+ .idea/**/dataSources.ids
27
+ .idea/**/dataSources.local.xml
28
+ .idea/**/sqlDataSources.xml
29
+ .idea/**/dynamic.xml
30
+ .idea/**/uiDesigner.xml
31
+ .idea/**/dbnavigator.xml
32
+
33
+ # Gradle
34
+ .idea/**/gradle.xml
35
+ .idea/**/libraries
36
+
37
+ # Gradle and Maven with auto-import
38
+ # When using Gradle or Maven with auto-import, you should exclude module files,
39
+ # since they will be recreated, and may cause churn. Uncomment if using
40
+ # auto-import.
41
+ # .idea/artifacts
42
+ # .idea/compiler.xml
43
+ # .idea/jarRepositories.xml
44
+ # .idea/modules.xml
45
+ # .idea/*.iml
46
+ # .idea/modules
47
+ # *.iml
48
+ # *.ipr
49
+
50
+ # CMake
51
+ cmake-build-*/
52
+
53
+ # Mongo Explorer plugin
54
+ .idea/**/mongoSettings.xml
55
+
56
+ # File-based project format
57
+ *.iws
58
+
59
+ # IntelliJ
60
+ out/
61
+
62
+ # mpeltonen/sbt-idea plugin
63
+ .idea_modules/
64
+
65
+ # JIRA plugin
66
+ atlassian-ide-plugin.xml
67
+
68
+ # Cursive Clojure plugin
69
+ .idea/replstate.xml
70
+
71
+ # Crashlytics plugin (for Android Studio and IntelliJ)
72
+ com_crashlytics_export_strings.xml
73
+ crashlytics.properties
74
+ crashlytics-build.properties
75
+ fabric.properties
76
+
77
+ # Editor-based Rest Client
78
+ .idea/httpRequests
79
+
80
+ # Android studio 3.1+ serialized cache file
81
+ .idea/caches/build_file_checksums.ser
82
+
83
+ ### PyCharm Patch ###
84
+ # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
85
+
86
+ # *.iml
87
+ # modules.xml
88
+ # .idea/misc.xml
89
+ # *.ipr
90
+ .out/**
91
+
92
+ # Sonarlint plugin
93
+ # https://plugins.jetbrains.com/plugin/7973-sonarlint
94
+ .idea/**/sonarlint/
95
+
96
+ # SonarQube Plugin
97
+ # https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
98
+ .idea/**/sonarIssues.xml
99
+
100
+ # Markdown Navigator plugin
101
+ # https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
102
+ .idea/**/markdown-navigator.xml
103
+ .idea/**/markdown-navigator-enh.xml
104
+ .idea/**/markdown-navigator/
105
+
106
+ # Cache file creation bug
107
+ # See https://youtrack.jetbrains.com/issue/JBR-2257
108
+ .idea/$CACHE_FILE$
109
+
110
+ # CodeStream plugin
111
+ # https://plugins.jetbrains.com/plugin/12206-codestream
112
+ .idea/codestream.xml
113
+
114
+ ### Python ###
115
+ # Byte-compiled / optimized / DLL files
116
+ __pycache__/
117
+ **__pycache__
118
+ *.py[cod]
119
+ *$py.class
120
+
121
+ # C extensions
122
+ *.so
123
+
124
+ # Distribution / packaging
125
+ .Python
126
+ build/
127
+ develop-eggs/
128
+ dist/
129
+ downloads/
130
+ eggs/
131
+ .eggs/
132
+ lib/
133
+ lib64/
134
+ parts/
135
+ sdist/
136
+ var/
137
+ wheels/
138
+ pip-wheel-metadata/
139
+ share/python-wheels/
140
+ *.egg-info/
141
+ .installed.cfg
142
+ *.egg
143
+ MANIFEST
144
+
145
+ # PyInstaller
146
+ # Usually these files are written by a python script from a template
147
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
148
+ *.manifest
149
+ *.spec
150
+
151
+ # Installer logs
152
+ pip-log.txt
153
+ pip-delete-this-directory.txt
154
+
155
+ # Unit test / coverage reports
156
+ htmlcov/
157
+ .tox/
158
+ .nox/
159
+ .coverage
160
+ .coverage.*
161
+ .cache
162
+ nosetests.xml
163
+ coverage.xml
164
+ *.cover
165
+ *.py,cover
166
+ .hypothesis/
167
+ .pytest_cache/
168
+ pytestdebug.log
169
+
170
+ # Translations
171
+ *.mo
172
+ *.pot
173
+
174
+ # Django stuff:
175
+ *.log
176
+ local_settings.py
177
+ db.sqlite3
178
+ db.sqlite3-journal
179
+
180
+ # Flask stuff:
181
+ instance/
182
+ .webassets-cache
183
+
184
+ # Scrapy stuff:
185
+ .scrapy
186
+
187
+ # Sphinx documentation
188
+ docs/_build/
189
+ doc/_build/
190
+
191
+ # PyBuilder
192
+ target/
193
+
194
+ # Jupyter Notebook
195
+ .ipynb_checkpoints
196
+
197
+ # IPython
198
+ profile_default/
199
+ ipython_config.py
200
+
201
+ # pyenv
202
+ .python-version
203
+
204
+ # pipenv
205
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
206
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
207
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
208
+ # install all needed dependencies.
209
+ #Pipfile.lock
210
+
211
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
212
+ __pypackages__/
213
+
214
+ # Celery stuff
215
+ celerybeat-schedule
216
+ celerybeat.pid
217
+
218
+ # SageMath parsed files
219
+ *.sage.py
220
+
221
+ # Environments
222
+ .env
223
+ .venv
224
+ env/
225
+ venv/
226
+ ENV/
227
+ env.bak/
228
+ venv.bak/
229
+ pythonenv*
230
+
231
+ # Spyder project settings
232
+ .spyderproject
233
+ .spyproject
234
+
235
+ # Rope project settings
236
+ .ropeproject
237
+
238
+ # mkdocs documentation
239
+ /site
240
+
241
+ # mypy
242
+ .mypy_cache/
243
+ .dmypy.json
244
+ dmypy.json
245
+
246
+ # Pyre type checker
247
+ .pyre/
248
+
249
+ # pytype static type analyzer
250
+ .pytype/
251
+
252
+ # profiling data
253
+ .prof
254
+
255
+ # End of https://www.toptal.com/developers/gitignore/api/python,pycharm,kate
@@ -1,27 +1,21 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: docker-composer
3
- Version: 2.17.4
3
+ Version: 5.0.2
4
4
  Summary: Use docker-compose (V2) from within Python
5
- Home-page: https://github.com/schollm/docker-composer
6
- License: Apache-2.0
7
- Author: Micha
8
- Author-email: schollm-git@gmx.com
9
- Requires-Python: >=3.9,<4.0
5
+ Project-URL: Homepage, https://github.com/schollm/docker-composer
6
+ Project-URL: Repository, https://github.com/schollm/docker-composer
7
+ Author-email: Micha <schollm-git@gmx.com>
8
+ License-Expression: Apache-2.0
9
+ License-File: LICENSE.txt
10
10
  Classifier: Development Status :: 5 - Production/Stable
11
11
  Classifier: Intended Audience :: Developers
12
12
  Classifier: Intended Audience :: System Administrators
13
13
  Classifier: License :: OSI Approved :: Apache Software License
14
14
  Classifier: Operating System :: OS Independent
15
15
  Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.9
17
- Classifier: Programming Language :: Python :: 3.10
18
- Classifier: Programming Language :: Python :: 3.11
19
- Classifier: Programming Language :: Python :: 3
20
16
  Classifier: Topic :: Software Development :: Build Tools
21
17
  Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
22
- Requires-Dist: attrs (>=20.3.0)
23
- Requires-Dist: loguru (>=0.5.3)
24
- Project-URL: Repository, https://github.com/schollm/docker-composer
18
+ Requires-Python: <4.0,>=3.9
25
19
  Description-Content-Type: text/markdown
26
20
 
27
21
  # Docker Composer
@@ -30,6 +24,8 @@ All commands and parameters are exposed as python classes and attributes
30
24
  to allow for full auto-completion of its parameters with IDEs
31
25
  that support it.
32
26
 
27
+ **Runtime footprint:** This library is **stdlib-only** (zero third-party runtime dependencies).
28
+
33
29
 
34
30
  ## Install
35
31
  ```shell script
@@ -70,14 +66,24 @@ print(process.stdout.encode("UTF-8"))
70
66
 
71
67
  ## Develop
72
68
 
73
- ### Coding Standards
69
+ ### Development Setup
74
70
 
75
- | **Type** | Package | Comment |
76
- | -------------- | -------- | ------------------------------- |
77
- | **Linter** | `black` | Also for auto-formatted modules |
78
- | **Logging** | `loguru` | |
79
- | **Packaging** | `poetry` | |
80
- | **Tests** | `pytest` | |
81
- | **Typing** | `mypy` | Type all methods |
82
- | **Imports** | `isort` | |
71
+ When developing, the `_utils` module is available for generating the docker_composer
72
+ module from the `docker compose`CLI help output.
73
+ This is not required for normal package usage.
74
+
75
+ ```bash
76
+ uv sync --group dev
77
+ uv run poe generate
78
+ ```
79
+
80
+ ### Coding Standards
83
81
 
82
+ | **Type** | Package | Comment |
83
+ | -------------- |-----------| ------------------------------- |
84
+ | **Linter** | `ruff` | Also for auto-formatted modules |
85
+ | **Logging** | `logging` | |
86
+ | **Packaging** | `uv` | |
87
+ | **Tests** | `pytest` | |
88
+ | **Typing** | `mypy` | Type all methods |
89
+ | **Imports** | `ruff` | |
@@ -4,6 +4,8 @@ All commands and parameters are exposed as python classes and attributes
4
4
  to allow for full auto-completion of its parameters with IDEs
5
5
  that support it.
6
6
 
7
+ **Runtime footprint:** This library is **stdlib-only** (zero third-party runtime dependencies).
8
+
7
9
 
8
10
  ## Install
9
11
  ```shell script
@@ -44,13 +46,24 @@ print(process.stdout.encode("UTF-8"))
44
46
 
45
47
  ## Develop
46
48
 
49
+ ### Development Setup
50
+
51
+ When developing, the `_utils` module is available for generating the docker_composer
52
+ module from the `docker compose`CLI help output.
53
+ This is not required for normal package usage.
54
+
55
+ ```bash
56
+ uv sync --group dev
57
+ uv run poe generate
58
+ ```
59
+
47
60
  ### Coding Standards
48
61
 
49
- | **Type** | Package | Comment |
50
- | -------------- | -------- | ------------------------------- |
51
- | **Linter** | `black` | Also for auto-formatted modules |
52
- | **Logging** | `loguru` | |
53
- | **Packaging** | `poetry` | |
54
- | **Tests** | `pytest` | |
55
- | **Typing** | `mypy` | Type all methods |
56
- | **Imports** | `isort` | |
62
+ | **Type** | Package | Comment |
63
+ | -------------- |-----------| ------------------------------- |
64
+ | **Linter** | `ruff` | Also for auto-formatted modules |
65
+ | **Logging** | `logging` | |
66
+ | **Packaging** | `uv` | |
67
+ | **Tests** | `pytest` | |
68
+ | **Typing** | `mypy` | Type all methods |
69
+ | **Imports** | `ruff` | |
@@ -0,0 +1,71 @@
1
+ [project]
2
+ name = "docker-composer"
3
+ version = "5.0.2"
4
+ description = "Use docker-compose (V2) from within Python"
5
+ authors = [{ name = "Micha", email = "schollm-git@gmx.com" }]
6
+ requires-python = ">=3.9,<4.0"
7
+ readme = "README.md"
8
+ license = "Apache-2.0"
9
+ classifiers = [
10
+ "Intended Audience :: Developers",
11
+ "Intended Audience :: System Administrators",
12
+ "License :: OSI Approved :: Apache Software License",
13
+ "Programming Language :: Python :: 3",
14
+ "Topic :: Software Development :: Build Tools",
15
+ "Topic :: Software Development :: Libraries :: Application Frameworks",
16
+ "Operating System :: OS Independent",
17
+ "Development Status :: 5 - Production/Stable",
18
+ ]
19
+ dependencies = []
20
+
21
+ [project.urls]
22
+ Homepage = "https://github.com/schollm/docker-composer"
23
+ Repository = "https://github.com/schollm/docker-composer"
24
+
25
+ [dependency-groups]
26
+ dev = [
27
+ "black>=25.1.0",
28
+ "isort>=6.0.1",
29
+ "poethepoet>=0.30.0",
30
+ "pytest>=6.1.2",
31
+ "pytest-cov>=6.1.1",
32
+ "ruff>=0.11.10",
33
+ ]
34
+
35
+ [tool.hatch.build.targets.sdist]
36
+ include = ["src/docker_composer"]
37
+
38
+ [tool.hatch.build.targets.wheel]
39
+ include = ["src/docker_composer"]
40
+ exclude = ["src/docker_composer/_utils"]
41
+
42
+ [tool.hatch.build.targets.wheel.sources]
43
+ "src/docker_composer" = "docker_composer"
44
+
45
+ [build-system]
46
+ requires = ["hatchling"]
47
+ build-backend = "hatchling.build"
48
+
49
+ [tool.pytest.ini_options]
50
+ addopts = """
51
+ --junit-xml=.out/junit-pytest.xml
52
+ --cov=src/docker_composer
53
+ --cov-report=xml:.out/coverage.xml
54
+ --cov-report=html:.out/coverage-html
55
+ --cov-report term-missing:skip-covered
56
+ --cov-branch
57
+ --doctest-modules
58
+ """
59
+
60
+ [tool.poe.tasks]
61
+ ruff-check = { cmd = "uv run ruff check" }
62
+ ruff-format-check = { cmd = "uv run ruff format --check" }
63
+ pytest = { cmd = "uv run pytest" }
64
+ format = { cmd = "uv run ruff format" }
65
+ build = { cmd = "uv build" }
66
+ publish-dist = { cmd = "uv publish" }
67
+ generate-code = { cmd = "uv run python -m docker_composer._utils.generate_class" }
68
+ sync-version = { cmd = "uv run python -m docker_composer._utils.sync_version" }
69
+ publish = { sequence = ["build", "publish-dist"] }
70
+ test = { sequence = ["ruff-check", "ruff-format-check", "pytest $POE_EXTRA_ARGS"] }
71
+ generate = { sequence = ["generate-code", "sync-version"] }
@@ -0,0 +1,6 @@
1
+ try:
2
+ from docker_composer.runner.root import DockerComposeRoot as DockerCompose
3
+ except ImportError:
4
+ pass
5
+
6
+ __all__ = ["DockerCompose"]
@@ -1,8 +1,12 @@
1
- from typing import Any, Iterable, Iterator, List, Optional, Tuple, Type
1
+ """Helper modules to parse docker compoose --help arguments"""
2
2
 
3
- import attr
4
- from loguru import logger
3
+ from __future__ import annotations
4
+ from typing import Iterable, Iterator
5
5
 
6
+ import logging
7
+ from dataclasses import dataclass
8
+
9
+ logger = logging.getLogger(__name__)
6
10
  OPTION = "OPTION"
7
11
 
8
12
  _TYPE_CONVERSIONS = {
@@ -16,7 +20,6 @@ _TYPE_CONVERSIONS = {
16
20
  "LEVEL": int,
17
21
  "MEM": int,
18
22
  "NAME": str,
19
- OPTION: bool,
20
23
  "PATH": str,
21
24
  "SERVICE": str,
22
25
  "SIGNAL": int,
@@ -24,28 +27,34 @@ _TYPE_CONVERSIONS = {
24
27
  "TIMEOUT": int,
25
28
  "TLS_KEY_PATH": str,
26
29
  "USER": str,
27
- "type": str,
28
- "string": str,
30
+ "bytes": int,
31
+ "docker": bool,
32
+ "filter": str,
29
33
  "int": int,
30
34
  "list": list,
35
+ "scale": int,
31
36
  "str": str,
37
+ "string": str,
32
38
  "stringArray": list[str],
39
+ "type": str,
33
40
  "volumes": list[str],
34
- "docker": bool,
41
+ OPTION: bool,
35
42
  }
36
43
 
37
44
 
38
- @attr.s(auto_attribs=True, frozen=True)
45
+ @dataclass(frozen=True)
39
46
  class Argument:
40
47
  arg: str
41
48
  type_desc: str
42
- type: Type
49
+ type_: type
43
50
  description: str
44
51
  default: str = ""
45
52
 
46
53
  @property
47
54
  def type_str(self) -> str:
48
- return "Any" if self.type == object else self.type.__name__
55
+ if self.type_ is object:
56
+ raise ValueError(self.type_)
57
+ return self.type_.__name__
49
58
 
50
59
  @property
51
60
  def is_option(self) -> bool:
@@ -55,20 +64,7 @@ class Argument:
55
64
  def from_line(line: str) -> "Argument":
56
65
  if " " in line:
57
66
  return _from_line_has_sep(line)
58
-
59
- words = iter(line.split())
60
- has_more = True
61
- while has_more:
62
- arg, default_str, has_more = _parse_arg(next(words))
63
- type_desc = next(words)
64
- type_from_default = _get_type_name_from_default(default_str)
65
- desc = " ".join(words)
66
- if type_desc[1:].islower() and "=" not in type_desc:
67
- desc = f"{type_desc} {desc}"
68
- type_desc = type_from_default
69
-
70
- type_ = _get_type(type_from_default if default_str else type_desc)
71
- return Argument(arg, type_desc, type_, desc, default_str)
67
+ raise ValueError(line)
72
68
 
73
69
 
74
70
  def _collect_arguments(arguments: Iterable[str]) -> Iterator[str]:
@@ -83,7 +79,7 @@ def _collect_arguments(arguments: Iterable[str]) -> Iterator[str]:
83
79
  yield res.strip()
84
80
 
85
81
 
86
- def parse_dc_argument(lines: List[str]) -> List[Argument]:
82
+ def parse_dc_argument(lines: list[str]) -> list[Argument]:
87
83
  """
88
84
  Parse arguments from lines of docker-compose specifications
89
85
  :param lines: Lines of the Options sections from `docker-compose --help`.
@@ -93,18 +89,18 @@ def parse_dc_argument(lines: List[str]) -> List[Argument]:
93
89
  return [Argument.from_line(line) for line in iter_lines if "--version" not in line]
94
90
 
95
91
 
96
- def _get_type(type_name) -> Type:
92
+ def _get_type(type_name) -> type:
97
93
  res = _TYPE_CONVERSIONS.get(type_name, None)
98
94
  if res is None:
99
95
  if "=" in type_name:
100
96
  res = dict
101
97
  else:
102
- logger.warning("Unknown type {}, use str", type_name)
98
+ logger.warning("Unknown type %s, use str", type_name)
103
99
  res = str
104
100
  return res
105
101
 
106
102
 
107
- def _parse_arg(arg: str) -> Tuple[str, str, bool]:
103
+ def _parse_arg(arg: str) -> tuple[str, str, bool]:
108
104
  while arg.startswith("-"):
109
105
  arg = arg[1:]
110
106
  # if argument ends with a comma, it is followed by an alias. (usually -f, --foo)
@@ -130,11 +126,7 @@ def _get_type_name_from_default(default: str) -> str:
130
126
  elif default == "proto":
131
127
  return "str"
132
128
  else:
133
- try:
134
- return eval(default).__class__.__name__
135
- except NameError:
136
- logger.warning("Could not get type for value '{}'", default)
137
- return "str"
129
+ raise NotImplementedError(default)
138
130
 
139
131
 
140
132
  def _from_line_has_sep(line) -> "Argument":
@@ -145,17 +137,18 @@ def _from_line_has_sep(line) -> "Argument":
145
137
  :param line: a single line with the description separated from the definition by at least two blanks
146
138
  :return: Argument
147
139
  """
148
- desc_idx = line[4:].index(" ")
149
- desc = line[desc_idx + 2 + 4 :].strip()
150
- args = iter(line[: desc_idx + 4].split())
140
+ min_arg_chars = 2 # Simple argument with single dash (e.g. -x)
141
+ min_full_chars = 4 # Named argument with double-dash (e.g. --xy)
142
+ desc_idx = line[min_arg_chars:].index(" ")
143
+ # Help output can wrap differently depending on terminal width.
144
+ # Normalize all whitespace so wrapped descriptions are stable.
145
+ desc = line[desc_idx + min_full_chars :].strip()
146
+ args = iter(line[: desc_idx + min_full_chars].split())
151
147
  arg, default, has_more = "", "", True
152
148
  while has_more:
153
149
  arg, default, has_more = _parse_arg(next(args))
154
150
  type_from_default = _get_type_name_from_default(default)
155
- try:
156
- type_desc = next(args)
157
- except StopIteration:
158
- type_desc = type_from_default
151
+ type_desc = next(args, type_from_default)
159
152
 
160
153
  type_ = _get_type(type_from_default if default else type_desc)
161
154
  return Argument(arg, type_desc, type_, desc, default=default)