11from __future__ import annotations
22
33import argparse
4+ import json
45import os
56import sys
67
8+ from typing import Any
9+
710from setuptools_scm import Configuration
811from setuptools_scm ._file_finders import find_files
912from setuptools_scm ._get_version_impl import _get_version
1013from setuptools_scm .discover import walk_potential_roots
1114
1215
13- def main (args : list [str ] | None = None ) -> None :
16+ def main (args : list [str ] | None = None ) -> int :
1417 opts = _get_cli_opts (args )
1518 inferred_root : str = opts .root or "."
1619
@@ -38,11 +41,8 @@ def main(args: list[str] | None = None) -> None:
3841 raise SystemExit ("ERROR: no version found for" , opts )
3942 if opts .strip_dev :
4043 version = version .partition (".dev" )[0 ]
41- print (version )
4244
43- if opts .command == "ls" :
44- for fname in find_files (config .root ):
45- print (fname )
45+ return command (opts , version , config )
4646
4747
4848def _get_cli_opts (args : list [str ] | None ) -> argparse .Namespace :
@@ -69,6 +69,30 @@ def _get_cli_opts(args: list[str] | None) -> argparse.Namespace:
6969 action = "store_true" ,
7070 help = "remove the dev/local parts of the version before printing the version" ,
7171 )
72+ parser .add_argument (
73+ "-N" ,
74+ "--no-version" ,
75+ action = "store_true" ,
76+ help = "do not include package version in the output" ,
77+ )
78+ output_formats = ["json" , "plain" , "key-value" ]
79+ parser .add_argument (
80+ "-f" ,
81+ "--format" ,
82+ type = str .casefold ,
83+ default = "plain" ,
84+ help = "specify output format" ,
85+ choices = output_formats ,
86+ )
87+ parser .add_argument (
88+ "-q" ,
89+ "--query" ,
90+ type = str .casefold ,
91+ nargs = "*" ,
92+ help = "display setuptools_scm settings according to query, "
93+ "e.g. dist_name, do not supply an argument in order to "
94+ "print a list of valid queries." ,
95+ )
7296 parser .add_argument (
7397 "--force-write-version-files" ,
7498 action = "store_true" ,
@@ -77,11 +101,80 @@ def _get_cli_opts(args: list[str] | None) -> argparse.Namespace:
77101 )
78102 sub = parser .add_subparsers (title = "extra commands" , dest = "command" , metavar = "" )
79103 # We avoid `metavar` to prevent printing repetitive information
80- desc = "List files managed by the SCM "
104+ desc = "List information about the package, e.g. included files "
81105 sub .add_parser ("ls" , help = desc [0 ].lower () + desc [1 :], description = desc )
82106 return parser .parse_args (args )
83107
84108
109+ # flake8: noqa: C901
110+ def command (opts : argparse .Namespace , version : str , config : Configuration ) -> int :
111+ data : dict [str , Any ] = {}
112+
113+ if opts .command == "ls" :
114+ opts .query = ["files" ]
115+
116+ if opts .query == []:
117+ opts .no_version = True
118+ sys .stderr .write ("Available queries:\n \n " )
119+ opts .query = ["queries" ]
120+ data ["queries" ] = ["files" , * config .__dataclass_fields__ ]
121+
122+ if opts .query is None :
123+ opts .query = []
124+
125+ if not opts .no_version :
126+ data ["version" ] = version
127+
128+ if "files" in opts .query :
129+ data ["files" ] = find_files (config .root )
130+
131+ for q in opts .query :
132+ if q in ["files" , "queries" , "version" ]:
133+ continue
134+
135+ try :
136+ if q .startswith ("_" ):
137+ raise AttributeError ()
138+ data [q ] = getattr (config , q )
139+ except AttributeError :
140+ sys .stderr .write (f"Error: unknown query: '{ q } '\n " )
141+ return 1
142+
143+ if opts .format == "json" :
144+ print (json .dumps (data , indent = 2 ))
145+
146+ if opts .format == "plain" :
147+ _print_plain (data )
148+
149+ if opts .format == "key-value" :
150+ _print_key_value (data )
151+
152+ return 0
153+
154+
155+ def _print_plain (data : dict [str , Any ]) -> None :
156+ version = data .pop ("version" , None )
157+ if version :
158+ print (version )
159+ files = data .pop ("files" , [])
160+ for file_ in files :
161+ print (file_ )
162+ queries = data .pop ("queries" , [])
163+ for query in queries :
164+ print (query )
165+ if data :
166+ print ("\n " .join (data .values ()))
167+
168+
169+ def _print_key_value (data : dict [str , Any ]) -> None :
170+ for key , value in data .items ():
171+ if isinstance (value , str ):
172+ print (f"{ key } = { value } " )
173+ else :
174+ str_value = "\n " .join (value )
175+ print (f"{ key } = { str_value } " )
176+
177+
85178def _find_pyproject (parent : str ) -> str :
86179 for directory in walk_potential_roots (os .path .abspath (parent )):
87180 pyproject = os .path .join (directory , "pyproject.toml" )
0 commit comments