Coverage for /Users/OORDCOR/Documents/code/bump-my-version/bumpversion/cli.py: 0%

1"""bump-my-version Command line interface."""

2 from typing import List, Optional

3

4 import rich_click as click

5 from click.core import Context

6

7 from bumpversion import __version__

8 from bumpversion.aliases import AliasedGroup

9 from bumpversion.bump import do_bump

10 from bumpversion.config import get_configuration

11 from bumpversion.config.files import find_config_file

12 from bumpversion.files import ConfiguredFile, modify_files

13 from bumpversion.show import do_show, log_list

14 from bumpversion.ui import get_indented_logger, print_warning, setup_logging

15 from bumpversion.utils import get_context, get_overrides

16

17 logger = get_indented_logger(__name__)

18

19

20@click.group(

21 cls=AliasedGroup,

22 invoke_without_command=True,

23 context_settings={

24 "ignore_unknown_options": True,

25 "allow_interspersed_args": True,

26 "help_option_names": ["-h", "--help"],

27 },

28 add_help_option=False,

29)

30@click.version_option(version=__version__)

31@click.pass_context

32 def cli(ctx: Context) -> None:

33 """Version bump your Python project."""

34 if ctx.invoked_subcommand is None:

35 ctx.invoke(bump, *ctx.args)

36

37

38 click.rich_click.OPTION_GROUPS = {

39 "bumpversion bump": [

40 {

41 "name": "Configuration",

42 "options": [

43 "--config-file",

44 "--current-version",

45 "--new-version",

46 "--parse",

47 "--serialize",

48 "--search",

49 "--replace",

50 "--no-configured-files",

51 "--ignore-missing-version",

52 ],

53 },

54 {

55 "name": "Output",

56 "options": ["--dry-run", "--verbose"],

57 },

58 {

59 "name": "Committing and tagging",

60 "options": [

61 "--allow-dirty" "--commit",

62 "--commit-args",

63 "--message",

64 "--tag",

65 "--tag-name",

66 "--tag-message",

67 "--sign-tags",

68 ],

69 },

70 ]

71}

72

73

74@cli.command(context_settings={"ignore_unknown_options": True})

75@click.argument("args", nargs=-1, type=str)

76@click.option(

77 "--config-file",

78 metavar="FILE",

79 required=False,

80 envvar="BUMPVERSION_CONFIG_FILE",

81 type=click.Path(exists=True),

82 help="Config file to read most of the variables from.",

83)

84@click.option(

85 "-v",

86 "--verbose",

87 count=True,

88 required=False,

89 envvar="BUMPVERSION_VERBOSE",

90 help="Print verbose logging to stderr. Can specify several times for more verbosity.",

91)

92@click.option(

93 "--allow-dirty/--no-allow-dirty",

94 default=None,

95 required=False,

96 envvar="BUMPVERSION_ALLOW_DIRTY",

97 help="Don't abort if working directory is dirty, or explicitly abort if dirty.",

98)

99@click.option(

100 "--current-version",

101 metavar="VERSION",

102 required=False,

103 envvar="BUMPVERSION_CURRENT_VERSION",

104 help="Version that needs to be updated",

105)

106@click.option(

107 "--new-version",

108 metavar="VERSION",

109 required=False,

110 envvar="BUMPVERSION_NEW_VERSION",

111 help="New version that should be in the files",

112)

113@click.option(

114 "--parse",

115 metavar="REGEX",

116 required=False,

117 envvar="BUMPVERSION_PARSE",

118 help="Regex parsing the version string",

119)

120@click.option(

121 "--serialize",

122 metavar="FORMAT",

123 multiple=True,

124 required=False,

125 envvar="BUMPVERSION_SERIALIZE",

126 help="How to format what is parsed back to a version",

127)

128@click.option(

129 "--search",

130 metavar="SEARCH",

131 required=False,

132 envvar="BUMPVERSION_SEARCH",

133 help="Template for complete string to search",

134)

135@click.option(

136 "--replace",

137 metavar="REPLACE",

138 required=False,

139 envvar="BUMPVERSION_REPLACE",

140 help="Template for complete string to replace",

141)

142@click.option(

143 "--regex/--no-regex",

144 default=False,

145 envvar="BUMPVERSION_REGEX",

146 help="Treat the search parameter as a regular expression or explicitly do not treat it as a regular expression.",

147)

148@click.option(

149 "--no-configured-files",

150 is_flag=True,

151 envvar="BUMPVERSION_NO_CONFIGURED_FILES",

152 help=(

153 "Only replace the version in files specified on the command line, "

154 "ignoring the files from the configuration file."

155 ),

156)

157@click.option(

158 "--ignore-missing-version",

159 is_flag=True,

160 envvar="BUMPVERSION_IGNORE_MISSING_VERSION",

161 help="Ignore any Version Not Found errors when searching and replacing in files.",

162)

163@click.option(

164 "--dry-run",

165 "-n",

166 is_flag=True,

167 envvar="BUMPVERSION_DRY_RUN",

168 help="Don't write any files, just pretend.",

169)

170@click.option(

171 "--commit/--no-commit",

172 default=None,

173 envvar="BUMPVERSION_COMMIT",

174 help="Commit to version control",

175)

176@click.option(

177 "--tag/--no-tag",

178 default=None,

179 envvar="BUMPVERSION_TAG",

180 help="Create a tag in version control",

181)

182@click.option(

183 "--sign-tags/--no-sign-tags",

184 default=None,

185 envvar="BUMPVERSION_SIGN_TAGS",

186 help="Sign tags if created",

187)

188@click.option(

189 "--tag-name",

190 metavar="TAG_NAME",

191 required=False,

192 envvar="BUMPVERSION_TAG_NAME",

193 help="Tag name (only works with --tag)",

194)

195@click.option(

196 "--tag-message",

197 metavar="TAG_MESSAGE",

198 required=False,

199 envvar="BUMPVERSION_TAG_MESSAGE",

200 help="Tag message",

201)

202@click.option(

203 "-m",

204 "--message",

205 metavar="COMMIT_MSG",

206 required=False,

207 envvar="BUMPVERSION_MESSAGE",

208 help="Commit message",

209)

210@click.option(

211 "--commit-args",

212 metavar="COMMIT_ARGS",

213 required=False,

214 envvar="BUMPVERSION_COMMIT_ARGS",

215 help="Extra arguments to commit command",

216)

217@click.option(

218 "--list",

219 "show_list",

220 is_flag=True,

221 help="List machine readable information",

222)

223 def bump(

224 # version_part: str,

225 args: list,

226 config_file: Optional[str],

227 verbose: int,

228 allow_dirty: Optional[bool],

229 current_version: Optional[str],

230 new_version: Optional[str],

231 parse: Optional[str],

232 serialize: Optional[List[str]],

233 search: Optional[str],

234 replace: Optional[str],

235 regex: bool,

236 no_configured_files: bool,

237 ignore_missing_version: bool,

238 dry_run: bool,

239 commit: Optional[bool],

240 tag: Optional[bool],

241 sign_tags: Optional[bool],

242 tag_name: Optional[str],

243 tag_message: Optional[str],

244 message: Optional[str],

245 commit_args: Optional[str],

246 show_list: bool,

247) -> None:

248 """

249 Change the version.

250

251 ARGS may contain any of the following:

252

253 VERSION_PART is the part of the version to increase, e.g. `minor` .

254 Valid values include those given in the `--serialize` / `--parse` option.

255

256 FILES are additional file(s) to modify.

257 If you want to rewrite only files specified on the command line, use with the

258 `--no-configured-files` option.

259 """

260 setup_logging(verbose)

261

262 logger.info("Starting BumpVersion %s", __version__)

263

264 overrides = get_overrides(

265 allow_dirty=allow_dirty,

266 current_version=current_version,

267 parse=parse,

268 serialize=serialize or None,

269 search=search,

270 replace=replace,

271 commit=commit,

272 tag=tag,

273 sign_tags=sign_tags,

274 tag_name=tag_name,

275 tag_message=tag_message,

276 message=message,

277 commit_args=commit_args,

278 ignore_missing_version=ignore_missing_version,

279 regex=regex,

280 )

281

282 found_config_file = find_config_file(config_file)

283 config = get_configuration(found_config_file, **overrides)

284 if args:

285 if args[0] not in config.parts.keys():

286 raise click.BadArgumentUsage(f"Unknown version part: {args[0]}")

287 version_part = args[0]

288 files = args[1:]

289 else:

290 version_part = None

291 files = args

292

293 if show_list:

294 print_warning("DEPRECATED: The --list option is deprecated and will be removed in a future version.")

295 log_list(config, version_part, new_version)

296 return

297

298 config.allow_dirty = allow_dirty if allow_dirty is not None else config.allow_dirty

299 if not config.allow_dirty and config.scm_info.tool:

300 config.scm_info.tool.assert_nondirty()

301

302 if no_configured_files:

303 config.excluded_paths = list(config.resolved_filemap.keys())

304

305 if files:

306 config.add_files(files)

307 config.included_paths = files

308

309 logger.dedent()

310 do_bump(version_part, new_version, config, found_config_file, dry_run)

311

312

313@cli.command()

314@click.argument("args", nargs=-1, type=str)

315@click.option(

316 "--config-file",

317 metavar="FILE",

318 required=False,

319 envvar="BUMPVERSION_CONFIG_FILE",

320 type=click.Path(exists=True),

321 help="Config file to read most of the variables from.",

322)

323@click.option(

324 "-f",

325 "--format",

326 "format_",

327 required=False,

328 envvar="BUMPVERSION_FORMAT",

329 type=click.Choice(["default", "yaml", "json"], case_sensitive=False),

330 default="default",

331 help="Config file to read most of the variables from.",

332)

333@click.option(

334 "-i",

335 "--increment",

336 required=False,

337 envvar="BUMPVERSION_INCREMENT",

338 type=str,

339 help="Increment the version part and add `new_version` to the configuration.",

340)

341 def show(args: List[str], config_file: Optional[str], format_: str, increment: Optional[str]) -> None:

342 """Show current configuration information."""

343 found_config_file = find_config_file(config_file)

344 config = get_configuration(found_config_file)

345

346 if not args:

347 do_show("all", config=config, format_=format_, increment=increment)

348 else:

349 do_show(*args, config=config, format_=format_, increment=increment)

350

351

352@cli.command()

353@click.argument("files", nargs=-1, type=str)

354@click.option(

355 "--config-file",

356 metavar="FILE",

357 required=False,

358 envvar="BUMPVERSION_CONFIG_FILE",

359 type=click.Path(exists=True),

360 help="Config file to read most of the variables from.",

361)

362@click.option(

363 "-v",

364 "--verbose",

365 count=True,

366 required=False,

367 envvar="BUMPVERSION_VERBOSE",

368 help="Print verbose logging to stderr. Can specify several times for more verbosity.",

369)

370@click.option(

371 "--allow-dirty/--no-allow-dirty",

372 default=None,

373 required=False,

374 envvar="BUMPVERSION_ALLOW_DIRTY",

375 help="Don't abort if working directory is dirty, or explicitly abort if dirty.",

376)

377@click.option(

378 "--current-version",

379 metavar="VERSION",

380 required=False,

381 envvar="BUMPVERSION_CURRENT_VERSION",

382 help="Version that needs to be updated",

383)

384@click.option(

385 "--new-version",

386 metavar="VERSION",

387 required=False,

388 envvar="BUMPVERSION_NEW_VERSION",

389 help="New version that should be in the files. If not specified, it will be None.",

390)

391@click.option(

392 "--parse",

393 metavar="REGEX",

394 required=False,

395 envvar="BUMPVERSION_PARSE",

396 help="Regex parsing the version string",

397)

398@click.option(

399 "--serialize",

400 metavar="FORMAT",

401 multiple=True,

402 required=False,

403 envvar="BUMPVERSION_SERIALIZE",

404 help="How to format what is parsed back to a version",

405)

406@click.option(

407 "--search",

408 metavar="SEARCH",

409 required=False,

410 envvar="BUMPVERSION_SEARCH",

411 help="Template for complete string to search",

412)

413@click.option(

414 "--replace",

415 metavar="REPLACE",

416 required=False,

417 envvar="BUMPVERSION_REPLACE",

418 help="Template for complete string to replace",

419)

420@click.option(

421 "--regex/--no-regex",

422 default=False,

423 envvar="BUMPVERSION_REGEX",

424 help="Treat the search parameter as a regular expression or explicitly do not treat it as a regular expression.",

425)

426@click.option(

427 "--no-configured-files",

428 is_flag=True,

429 envvar="BUMPVERSION_NO_CONFIGURED_FILES",

430 help=(

431 "Only replace the version in files specified on the command line, "

432 "ignoring the files from the configuration file."

433 ),

434)

435@click.option(

436 "--ignore-missing-version",

437 is_flag=True,

438 envvar="BUMPVERSION_IGNORE_MISSING_VERSION",

439 help="Ignore any Version Not Found errors when searching and replacing in files.",

440)

441@click.option(

442 "--dry-run",

443 "-n",

444 is_flag=True,

445 envvar="BUMPVERSION_DRY_RUN",

446 help="Don't write any files, just pretend.",

447)

448 def replace(

449 files: list,

450 config_file: Optional[str],

451 verbose: int,

452 allow_dirty: Optional[bool],

453 current_version: Optional[str],

454 new_version: Optional[str],

455 parse: Optional[str],

456 serialize: Optional[List[str]],

457 search: Optional[str],

458 replace: Optional[str],

459 regex: bool,

460 no_configured_files: bool,

461 ignore_missing_version: bool,

462 dry_run: bool,

463) -> None:

464 """

465 Replace the version in files.

466

467 FILES are additional file(s) to modify.

468 If you want to rewrite only files specified on the command line, use with the

469 `--no-configured-files` option.

470 """

471 setup_logging(verbose)

472

473 logger.info("Starting BumpVersion %s", __version__)

474

475 overrides = get_overrides(

476 allow_dirty=allow_dirty,

477 current_version=current_version,

478 new_version=new_version,

479 parse=parse,

480 serialize=serialize or None,

481 commit=False,

482 tag=False,

483 sign_tags=False,

484 tag_name=None,

485 tag_message=None,

486 message=None,

487 commit_args=None,

488 ignore_missing_version=ignore_missing_version,

489 regex=regex,

490 )

491

492 found_config_file = find_config_file(config_file)

493 config = get_configuration(found_config_file, **overrides)

494

495 config.allow_dirty = allow_dirty if allow_dirty is not None else config.allow_dirty

496 if not config.allow_dirty and config.scm_info.tool:

497 config.scm_info.tool.assert_nondirty()

498

499 if no_configured_files:

500 config.excluded_paths = list(config.resolved_filemap.keys())

501

502 if files:

503 config.add_files(files)

504 config.included_paths = files

505

506 configured_files = [

507 ConfiguredFile(file_cfg, config.version_config, search, replace) for file_cfg in config.files_to_modify

508 ]

509

510 version = config.version_config.parse(config.current_version)

511 if new_version:

512 next_version = config.version_config.parse(new_version)

513 else:

514 next_version = None

515

516 ctx = get_context(config, version, next_version)

517

518 modify_files(configured_files, version, next_version, ctx, dry_run)