@@ -237,6 +237,16 @@ def setup_instparser(instparser):
237
237
"releaseargs" , nargs = argparse .REMAINDER , help = extraargs_help ("pytest" )
238
238
)
239
239
240
+ patchreleaseparser = subparsers .add_parser (
241
+ "update_patch_versions" ,
242
+ help = "Updates version numbers during patch release, used by maintainers and CI" ,
243
+ )
244
+ patchreleaseparser .set_defaults (func = patch_release_args )
245
+ patchreleaseparser .add_argument ("--stable_version" , required = True )
246
+ patchreleaseparser .add_argument ("--unstable_version" , required = True )
247
+ patchreleaseparser .add_argument ("--stable_version_prev" , required = True )
248
+ patchreleaseparser .add_argument ("--unstable_version_prev" , required = True )
249
+
240
250
fmtparser = subparsers .add_parser (
241
251
"format" ,
242
252
help = "Formats all source code with black and isort." ,
@@ -655,6 +665,27 @@ def update_dependencies(targets, version, packages):
655
665
)
656
666
657
667
668
+ def update_patch_dependencies (targets , version , prev_version , packages ):
669
+ print ("updating patch dependencies" )
670
+ if "all" in packages :
671
+ packages .extend (targets )
672
+
673
+ # PEP 508 allowed specifier operators
674
+ operators = ["==" , "!=" , "<=" , ">=" , "<" , ">" , "===" , "~=" , "=" ]
675
+ operators_pattern = "|" .join (re .escape (op ) for op in operators )
676
+
677
+ for pkg in packages :
678
+ search = rf"({ basename (pkg )} [^,]*?)(\s?({ operators_pattern } )\s?)(.*{ prev_version } )"
679
+ replace = r"\g<1>\g<2>" + version
680
+ print (f"{ search = } \t { replace = } \t { pkg = } " )
681
+ update_files (
682
+ targets ,
683
+ "pyproject.toml" ,
684
+ search ,
685
+ replace ,
686
+ )
687
+
688
+
658
689
def update_files (targets , filename , search , replace ):
659
690
errors = False
660
691
for target in targets :
@@ -687,10 +718,12 @@ def release_args(args):
687
718
versions = args .versions
688
719
updated_versions = []
689
720
721
+ # remove excluded packages
690
722
excluded = cfg ["exclude_release" ]["packages" ].split ()
691
723
targets = [
692
724
target for target in targets if basename (target ) not in excluded
693
725
]
726
+
694
727
for group in versions .split ("," ):
695
728
mcfg = cfg [group ]
696
729
version = mcfg ["version" ]
@@ -707,6 +740,40 @@ def release_args(args):
707
740
update_changelogs ("-" .join (updated_versions ))
708
741
709
742
743
+ def patch_release_args (args ):
744
+ print ("preparing patch release" )
745
+
746
+ rootpath = find_projectroot ()
747
+ targets = list (find_targets_unordered (rootpath ))
748
+ cfg = ConfigParser ()
749
+ cfg .read (str (find_projectroot () / "eachdist.ini" ))
750
+
751
+ # remove excluded packages
752
+ excluded = cfg ["exclude_release" ]["packages" ].split ()
753
+ targets = [
754
+ target for target in targets if basename (target ) not in excluded
755
+ ]
756
+
757
+ # stable
758
+ mcfg = cfg ["stable" ]
759
+ packages = mcfg ["packages" ].split ()
760
+ print (f"update stable packages to { args .stable_version } " )
761
+
762
+ update_patch_dependencies (
763
+ targets , args .stable_version , args .stable_version_prev , packages
764
+ )
765
+ update_version_files (targets , args .stable_version , packages )
766
+
767
+ # prerelease
768
+ mcfg = cfg ["prerelease" ]
769
+ packages = mcfg ["packages" ].split ()
770
+ print (f"update prerelease packages to { args .unstable_version } " )
771
+ update_patch_dependencies (
772
+ targets , args .unstable_version , args .unstable_version_prev , packages
773
+ )
774
+ update_version_files (targets , args .unstable_version , packages )
775
+
776
+
710
777
def test_args (args ):
711
778
clean_remainder_args (args .pytestargs )
712
779
execute_args (
0 commit comments