Skip to content

Version

Version

Bases: Representation, String

Represents versions.

Source code in versions/version.py
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
@frozen(repr=False, eq=True, order=True)
class Version(Representation, String):
    """Represents versions."""

    epoch: Epoch = field(factory=Epoch, eq=False, order=False)
    """The *epoch* segment of the version."""

    release: Release = field(factory=Release, eq=False, order=False)
    """The *release* segment of the version."""

    pre: Optional[PreTag] = field(default=None, eq=False, order=False)
    """The *pre-release* tag of the version."""

    post: Optional[PostTag] = field(default=None, eq=False, order=False)
    """The *post-release* tag of the version."""

    dev: Optional[DevTag] = field(default=None, eq=False, order=False)
    """The *dev-release* tag of the version."""

    local: Optional[Local] = field(default=None, eq=False, order=False)
    """The *local* segment of the version."""

    compare_key: CompareKey = field(repr=False, init=False, eq=True, order=True, hash=False)

    @compare_key.default
    def default_compare_key(self) -> CompareKey:
        compare_epoch = self.epoch
        compare_release = self.release

        compare_pre, compare_post, compare_dev = self.compute_compare_tags(
            self.pre, self.post, self.dev
        )

        compare_local = self.compute_compare_local(self.local)

        return (
            compare_epoch,
            compare_release,
            compare_pre,
            compare_post,
            compare_dev,
            compare_local,
        )

    @staticmethod
    def compute_compare_tags(
        pre: Optional[PreTag], post: Optional[PostTag], dev: Optional[DevTag]
    ) -> Tuple[ComparePreTag, ComparePostTag, CompareDevTag]:
        compare_pre: ComparePreTag
        compare_post: ComparePostTag
        compare_dev: CompareDevTag

        if pre is None:
            if post is None and dev is not None:
                compare_pre = negative_infinity

            else:
                compare_pre = infinity

        else:
            compare_pre = pre

        compare_post = negative_infinity if post is None else post
        compare_dev = infinity if dev is None else dev

        return (compare_pre, compare_post, compare_dev)

    @staticmethod
    def compute_compare_local(local: Optional[Local]) -> CompareLocal:
        return negative_infinity if local is None else local

    @classmethod
    def from_string(cls, string: str) -> Self:
        """Parses a [`Version`][versions.version.Version] from `string`.

        Arguments:
            string: The string to parse.

        Returns:
            The parsed version.
        """
        return VersionParser(cls).parse(string)

    def to_string_iterator(self) -> Iterator[str]:
        epoch = self.epoch

        if epoch:
            yield epoch.to_string()
            yield EXCLAMATION

        yield self.release.to_string()

        pre = self.pre

        if pre is not None:
            yield DASH
            yield pre.to_string()

        post = self.post

        if post is not None:
            yield DASH
            yield post.to_string()

        dev = self.dev

        if dev is not None:
            yield DASH
            yield dev.to_string()

        local = self.local

        if local is not None:
            yield PLUS
            yield local.to_string()

    def to_short_string_iterator(self) -> Iterator[str]:
        epoch = self.epoch

        if epoch:
            yield epoch.to_short_string()
            yield EXCLAMATION

        yield self.release.to_short_string()

        pre = self.pre

        if pre is not None:
            yield pre.to_short_string()

        post = self.post

        if post is not None:
            yield DOT
            yield post.to_short_string()

        dev = self.dev

        if dev is not None:
            yield DOT
            yield dev.to_short_string()

        local = self.local

        if local is not None:
            yield PLUS
            yield local.to_short_string()

    def to_string(self) -> str:
        """Converts a [`Version`][versions.version.Version] to its string representation.

        Returns:
            The version string.
        """
        return concat_empty(self.to_string_iterator())

    def to_short_string(self) -> str:
        """Converts a [`Version`][versions.version.Version] to its *short* string representation.

        Returns:
            The *short* version string.
        """
        return concat_empty(self.to_short_string_iterator())

    def to_pep440_string(self) -> str:
        """Converts a [`Version`][versions.version.Version] to its
        [*PEP 440*](https://peps.python.org/pep-0440) representation.

        ```python
        version.to_pep440_string()
        ```

        Is equivalent to the following:

        ```python
        version.normalize().to_short_string()
        ```

        Returns:
            The [*PEP 440*](https://peps.python.org/pep-0440) version string.
        """
        return self.normalize().to_short_string()

    @property
    def precision(self) -> int:
        """The precision of the [`Release`][versions.segments.release.Release]."""
        return self.release.precision

    @property
    def last_index(self) -> int:
        """The last index of the [`Release`][versions.segments.release.Release]."""
        return self.release.last_index

    @property
    def major(self) -> int:
        """The *major* part of the [`Release`][versions.segments.release.Release]."""
        return self.release.major

    @property
    def minor(self) -> int:
        """The *minor* part of the [`Release`][versions.segments.release.Release]."""
        return self.release.minor

    @property
    def micro(self) -> int:
        """The *micro* part of the [`Release`][versions.segments.release.Release]."""
        return self.release.micro

    @property
    def patch(self) -> int:
        """The *patch* part of the [`Release`][versions.segments.release.Release].

        This is equivalent to [`micro`][versions.version.Version.micro].
        """
        return self.release.patch

    @property
    def extra(self) -> Extra:
        """The *extra* parts of the [`Release`][versions.segments.release.Release]."""
        return self.release.extra

    def get_at(self, index: int, default: int = DEFAULT_VALUE) -> int:
        """Gets the [`Release`][versions.segments.release.Release] part at the `index`,
        defaulting to `default`.

        Arguments:
            index: The index of the part to get.
            default: The default value to use.

        Returns:
            The release part at `index` or the `default` value.
        """
        return self.release.get_at(index, default)

    def get_at_unchecked(self, index: int) -> int:
        """Gets the [`Release`][versions.segments.Release] part at the `index`.

        Arguments:
            index: The index of the part to get.

        Raises:
            IndexError: The index is *out-of-bounds*.

        Returns:
            The release part at the `index`.
        """
        return self.release.get_at_unchecked(index)

    def is_semantic(self) -> bool:
        """Checks if the [`Release`][versions.segments.Release]
        matches the *semantic versioning* schema.

        Returns:
            Whether the release matches the [`SemVer`](https://semver.org/) schema.
        """
        return self.release.is_semantic()

    def to_semantic(self) -> Self:
        """Converts the [`Release`][versions.segments.Release]
        to match the [`SemVer`](https://semver.org/) schema.

        Returns:
            The converted version.
        """
        return evolve(self, release=self.release.to_semantic())

    def set_epoch(self, epoch: Epoch) -> Self:
        return evolve(self, epoch=epoch)

    def set_epoch_value(self, value: int) -> Self:
        return self.set_epoch(self.epoch.set_value(value))

    def set_release(self, release: Release) -> Self:
        return evolve(self, release=release)

    def set_release_parts(self, *parts: int) -> Self:
        return self.set_release(self.release.set_parts(*parts))

    def slice(self, index: int) -> Self:
        return self.set_release(self.release.slice(index))

    def set_major(self, value: int) -> Self:
        """Sets the *major* part of the [`Release`][versions.segments.Release] to the `value`.

        Arguments:
            value: The value to set the *major* part to.

        Returns:
            The updated version.
        """
        return self.set_release(self.release.set_major(value))

    def set_minor(self, value: int) -> Self:
        """Sets the *minor* part of the [`Release`][versions.segments.Release] to the `value`.

        Arguments:
            value: The value to set the *minor* part to.

        Returns:
            The updated version.
        """
        return self.set_release(self.release.set_minor(value))

    def set_micro(self, value: int) -> Self:
        """Sets the *micro* part of the [`Release`][versions.segments.Release] to the `value`.

        Arguments:
            value: The value to set the *micro* part to.

        Returns:
            The updated version.
        """
        return self.set_release(self.release.set_micro(value))

    def set_patch(self, value: int) -> Self:
        """Sets the *patch* part of the [`Release`][versions.segments.Release] to the `value`.

        This is equivalent to [`set_micro`][versions.version.Version.set_micro].

        Arguments:
            value: The value to set the *patch* part to.

        Returns:
            The updated version.
        """
        return self.set_release(self.release.set_patch(value))

    def set_at(self, index: int, value: int) -> Self:
        """Sets the [`Release`][versions.segments.Release] part at the `index` to the `value`.

        Arguments:
            index: The index to set the `value` at.
            value: The value to set the part to.

        Returns:
            The updated version.
        """
        return self.set_release(self.release.set_at(index, value))

    def set_at_unchecked(self, index: int, value: int) -> Self:
        """Sets the [`Release`][versions.segments.Release] part at the `index` to the `value`.

        Arguments:
            index: The index to set the `value` at.
            value: The value to set the part to.

        Raises:
            IndexError: The index is *out-of-bounds*.

        Returns:
            The updated version.
        """
        return self.set_release(self.release.set_at_unchecked(index, value))

    def next_epoch(self) -> Self:
        return self.set_epoch(self.epoch.next_value())

    def next_major(self) -> Self:
        """Bumps the *major* part of the [`Release`][versions.segments.Release]
        if the version is stable, otherwise converts the version to be stable.

        Returns:
            The bumped version.
        """
        release = self.release

        if self.is_stable():
            release = release.next_major()

        return self.without_tags_and_local().set_release(release)

    def next_minor(self) -> Self:
        """Bumps the *minor* part of the [`Release`][versions.segments.Release]
        if the version is stable, otherwise converts the version to be stable.

        Returns:
            The bumped version.
        """
        release = self.release

        if self.is_stable():
            release = release.next_minor()

        return self.without_tags_and_local().set_release(release)

    def next_micro(self) -> Self:
        """Bumps the *micro* part of the [`Release`][versions.segments.Release]
        if the version is stable, otherwise converts the version to be stable.

        Returns:
            The bumped version.
        """
        release = self.release

        if self.is_stable():
            release = release.next_micro()

        return self.without_tags_and_local().set_release(release)

    def next_patch(self) -> Self:
        """Bumps the *patch* part of the [`Release`][versions.segments.Release]
        if the version is stable, otherwise converts the version to be stable.

        This is equivalent to [`next_micro`][versions.version.Version.next_micro].

        Returns:
            The bumped version.
        """
        release = self.release

        if self.is_stable():
            release = release.next_patch()

        return self.without_tags_and_local().set_release(release)

    def next_at(self, index: int) -> Self:
        """Bumps the part of the [`Release`][versions.segments.Release] at the `index`
        if the version is stable, otherwise converts the version to be stable.

        Arguments:
            index: The index to bump the part at.

        Returns:
            The bumped version.
        """
        release = self.release

        if self.is_stable():
            release = release.next_at(index)

        return self.without_tags_and_local().set_release(release)

    def has_major(self) -> bool:
        """Checks if the [`Release`][versions.segments.Release] has the *major* part.

        Returns:
            Whether the *major* part is present.
        """
        return self.release.has_major()

    def has_minor(self) -> bool:
        """Checks if the [`Release`][versions.segments.Release] has the *minor* part.

        Returns:
            Whether the *minor* part is present.
        """
        return self.release.has_minor()

    def has_micro(self) -> bool:
        """Checks if the [`Release`][versions.segments.Release] has the *micro* part.

        Returns:
            Whether the *micro* part is present.
        """
        return self.release.has_micro()

    def has_patch(self) -> bool:
        """Checks if the [`Release`][versions.segments.Release] has the *patch* part.

        This is equivalent to [`has_micro`][versions.version.Version.has_micro].

        Returns:
            Whether the *patch* part is present.
        """
        return self.release.has_patch()

    def has_extra(self) -> bool:
        """Checks if the [`Release`][versions.segments.Release] has any *extra* parts.

        Returns:
            Whether the *extra* parts are present.
        """
        return self.release.has_extra()

    def has_at(self, index: int) -> bool:
        """Checks if the [`Release`][versions.segments.Release] has a part at the `index`.

        Returns:
            Whether the part at the `index` is present.
        """
        return self.release.has_at(index)

    def pad_to(self, length: int, padding: int = DEFAULT_PADDING) -> Self:
        """Pads the [`Release`][versions.segments.Release] to the `length` with `padding`.

        Arguments:
            length: The length to pad the release to.
            padding: The padding to use.

        Returns:
            The padded version.
        """
        return self.set_release(self.release.pad_to(length, padding))

    def pad_to_index(self, index: int, padding: int = DEFAULT_PADDING) -> Self:
        """Pads the [`Release`][versions.segments.Release] to the `index` with `padding`.

        Arguments:
            index: The index to pad the release to.
            padding: The padding to use.

        Returns:
            The padded version.
        """
        return self.set_release(self.release.pad_to_index(index, padding))

    def pad_to_next(self, padding: int = DEFAULT_PADDING) -> Self:
        """Pads the [`Release`][versions.segments.Release] to the next index.

        Arguments:
            padding: The padding to use.

        Returns:
            The padded version.
        """
        return self.set_release(self.release.pad_to_next(padding))

    def is_pre_release(self) -> bool:
        """Checks if the version is *pre-release*.

        Returns:
            Whether the version is *pre-release*.
        """
        return self.pre is not None

    def is_post_release(self) -> bool:
        """Checks if the version is *post-release*.

        Returns:
            Whether the version is *post-release*.
        """
        return self.post is not None

    def is_dev_release(self) -> bool:
        """Checks if the version is *dev-release*.

        Returns:
            Whether the version is *dev-release*.
        """
        return self.dev is not None

    def is_local(self) -> bool:
        """Checks if the version is *local*.

        Returns:
            Whether the version is *local*.
        """
        return self.local is not None

    def is_unstable(self) -> bool:
        """Checks if the version is *unstable*.

        Returns:
            Whether the version is *unstable*.
        """
        return self.is_pre_release() or self.is_dev_release()

    def is_stable(self) -> bool:
        """Checks if the version is *stable*.

        Returns:
            Whether the version is *stable*.
        """
        return not self.is_unstable()

    def next_pre(self) -> Self:
        """Bumps the [`PreTag`][versions.segments.PreTag] if it is present,
        otherwise adds one to the version.

        Returns:
            The bumped version.
        """
        pre = self.pre

        if pre is None:
            pre = PreTag()

        else:
            pre = pre.next()

        return self.without_tags_and_local().with_pre(pre)

    def next_pre_phase(self) -> Optional[Self]:
        """Bumps the [`PreTag`][versions.segments.PreTag] phase if it is present (and if possible),
        otherwise adds one to the version.

        Returns:
            The bumped version (if the next [`PreTag`][versions.segments.PreTag] is present).
        """
        pre = self.pre

        if pre is None:
            pre = PreTag()

        else:
            pre = pre.next_phase()

            if pre is None:
                return None

        return self.without_tags_and_local().with_pre(pre)

    def next_post(self) -> Self:
        """Bumps the [`PostTag`][versions.segments.PostTag] if it is present,
        otherwise adds one to the version.

        Returns:
            The bumped version.
        """
        post = self.post

        if post is None:
            post = PostTag()

        else:
            post = post.next()

        return self.with_post(post).without_dev_and_local()

    def next_dev(self) -> Self:
        """Bumps the [`DevTag`][versions.segments.DevTag] if it is present,
        otherwise adds one to the version.

        Returns:
            The bumped version.
        """
        dev = self.dev

        if dev is None:
            dev = DevTag()

        else:
            dev = dev.next()

        return self.with_dev(dev).without_local()

    def set_pre(self, pre: Optional[PreTag]) -> Self:
        return evolve(self, pre=pre)

    def set_post(self, post: Optional[PostTag]) -> Self:
        return evolve(self, post=post)

    def set_dev(self, dev: Optional[DevTag]) -> Self:
        return evolve(self, dev=dev)

    def set_tags(
        self, pre: Optional[PreTag], post: Optional[PostTag], dev: Optional[DevTag]
    ) -> Self:
        return evolve(self, pre=pre, post=post, dev=dev)

    def set_local(self, local: Optional[Local]) -> Self:
        return evolve(self, local=local)

    def set_local_parts(self, *parts: LocalPart) -> Self:
        local = self.local

        local = Local.from_parts(*parts) if local is None else local.set_parts(*parts)

        return self.set_local(local)

    def set_dev_and_local(self, dev: Optional[DevTag], local: Optional[Local]) -> Self:
        return evolve(self, dev=dev, local=local)

    def set_tags_and_local(
        self,
        pre: Optional[PreTag],
        post: Optional[PostTag],
        dev: Optional[DevTag],
        local: Optional[Local],
    ) -> Self:
        return evolve(self, pre=pre, post=post, dev=dev, local=local)

    def with_pre(self, pre: PreTag) -> Self:
        """Updates a version to include [`PreTag`][versions.segments.PreTag].

        Arguments:
            pre: The *pre-release* tag to include.

        Returns:
            The updated version.
        """
        return self.set_pre(pre)

    def with_post(self, post: PostTag) -> Self:
        """Updates a version to include [`PostTag`][versions.segments.PostTag].

        Arguments:
            post: The *post-release* tag to include.

        Returns:
            The updated version.
        """
        return self.set_post(post)

    def with_dev(self, dev: DevTag) -> Self:
        """Updates a version to include [`DevTag`][versions.segments.DevTag].

        Arguments:
            dev: The *dev-release* tag to include.

        Returns:
            The updated version.
        """
        return self.set_dev(dev)

    def with_tags(self, pre: PreTag, post: PostTag, dev: DevTag) -> Self:
        return self.set_tags(pre, post, dev)

    def with_local(self, local: Local) -> Self:
        """Updates a version to include [`Local`][versions.segments.Local].

        Arguments:
            local: The *local* segment to include.

        Returns:
            The updated version.
        """
        return self.set_local(local)

    def with_dev_and_local(self, dev: DevTag, local: Local) -> Self:
        return self.set_dev_and_local(dev, local)

    def with_tags_and_local(self, pre: PreTag, post: PostTag, dev: DevTag, local: Local) -> Self:
        return self.set_tags_and_local(pre, post, dev, local)

    def without_pre(self) -> Self:
        """Updates a version, removing any [`PreTag`][versions.segments.PreTag] from it.

        Returns:
            The updated version.
        """
        return self.set_pre(None)

    def without_post(self) -> Self:
        """Updates a version, removing any [`PostTag`][versions.segments.PostTag] from it.

        Returns:
            The updated version.
        """
        return self.set_post(None)

    def without_dev(self) -> Self:
        """Updates a version, removing any [`DevTag`][versions.segments.DevTag] from it.

        Returns:
            The updated version.
        """
        return self.set_dev(None)

    def without_tags(self) -> Self:
        return self.set_tags(None, None, None)

    def without_local(self) -> Self:
        """Updates a version, removing any [`Local`][versions.segments.Local] segment from it.

        Returns:
            The updated version.
        """
        return self.set_local(None)

    def without_dev_and_local(self) -> Self:
        return self.set_dev_and_local(None, None)

    def without_tags_and_local(self) -> Self:
        return self.set_tags_and_local(None, None, None, None)

    def weaken(self, other: Self) -> Self:
        """Weakens the `other` version for further comparison.

        Arguments:
            other: The version to weaken.

        Returns:
            The weakened version.
        """
        if not self.is_local() and other.is_local():
            other = other.without_local()

        if not self.is_post_release() and other.is_post_release():
            other = other.without_post()

        return other

    def to_stable(self) -> Self:
        """Forces a version to be stable.

        Returns:
            The stable version.
        """
        return self if self.is_stable() else self.to_stable_unchecked()

    def to_stable_unchecked(self) -> Self:
        """Forces a version to be stable, without checking whether it is already stable.

        Returns:
            The stable version.
        """
        return self.without_tags_and_local()

    def next_breaking(self) -> Self:
        """Returns the next breaking version.

        This function is slightly convoluted due to how `0.x.y` and `0.0.z` versions are handled:

        | version | next breaking |
        |---------|---------------|
        | `1.2.3` | `2.0.0`       |
        | `1.2.0` | `2.0.0`       |
        | `1.0.0` | `2.0.0`       |
        | `0.2.3` | `0.3.0`       |
        | `0.0.3` | `0.0.4`       |
        | `0.0.0` | `0.0.1`       |
        | `0.0`   | `0.1.0`       |
        | `0`     | `1.0.0`       |

        Returns:
            The next breaking [`Version`][versions.version.Version].
        """
        if not self.major:
            if self.minor:
                return self.next_minor()

            if self.has_micro():
                return self.next_micro()

            if self.has_minor():
                return self.next_minor()

            return self.next_major()

        return self.to_stable().next_major()

    def normalize(self) -> Self:
        """Normalizes all version tags.

        Returns:
            The normalized version.
        """
        pre = self.pre

        if pre is not None:
            pre = pre.normalize()

        post = self.post

        if post is not None:
            post = post.normalize()

        dev = self.dev

        if dev is not None:
            dev = dev.normalize()

        return self.set_tags(pre, post, dev)

    @classmethod
    def create(
        cls,
        epoch: Optional[Epoch] = None,
        release: Optional[Release] = None,
        pre: Optional[PreTag] = None,
        post: Optional[PostTag] = None,
        dev: Optional[DevTag] = None,
        local: Optional[Local] = None,
    ) -> Self:
        """Creates a [`Version`][versions.version.Version] from `epoch`, `release`,
        `pre`, `post`, `dev` and `local`.

        Arguments:
            epoch: The *epoch* to use.
            release: The *release* to use.
            pre: The *pre-release* tag to use.
            post: The *post-release* tag to use.
            dev: The *dev-release* tag to use.
            local: The *local* segment to use.

        Returns:
            The newly created [`Version`][versions.version.Version].
        """

        if epoch is None:
            epoch = Epoch()

        if release is None:
            release = Release()

        return cls(epoch, release, pre, post, dev, local)

    @classmethod
    def from_parts(
        cls,
        *parts: int,
        epoch: Optional[Epoch] = None,
        pre: Optional[PreTag] = None,
        post: Optional[PostTag] = None,
        dev: Optional[DevTag] = None,
        local: Optional[Local] = None,
    ) -> Self:
        """Creates a [`Version`][versions.version.Version] from `parts`,
        `epoch`, `pre`, `post`, `dev` and `local`.

        Arguments:
            *parts: The parts of the *release* to use.
            epoch: The *epoch* to use.
            pre: The *pre-release* tag to use.
            post: The *post-release* tag to use.
            dev: The *dev-release* tag to use.
            local: The *local* segment to use.

        Returns:
            The newly created [`Version`][versions.version.Version].
        """
        release = Release(parts)

        return cls.create(epoch, release, pre, post, dev, local)

    def matches(self, specification: Specification) -> bool:
        """Checks if a version matches the `specification`.

        Arguments:
            specification: The specification to check the version against.

        Returns:
            Whether the version matches the specification.
        """
        return specification.accepts(self)

epoch: Epoch = field(factory=Epoch, eq=False, order=False) class-attribute instance-attribute

The epoch segment of the version.

release: Release = field(factory=Release, eq=False, order=False) class-attribute instance-attribute

The release segment of the version.

pre: Optional[PreTag] = field(default=None, eq=False, order=False) class-attribute instance-attribute

The pre-release tag of the version.

post: Optional[PostTag] = field(default=None, eq=False, order=False) class-attribute instance-attribute

The post-release tag of the version.

dev: Optional[DevTag] = field(default=None, eq=False, order=False) class-attribute instance-attribute

The dev-release tag of the version.

local: Optional[Local] = field(default=None, eq=False, order=False) class-attribute instance-attribute

The local segment of the version.

precision: int property

The precision of the Release.

last_index: int property

The last index of the Release.

major: int property

The major part of the Release.

minor: int property

The minor part of the Release.

micro: int property

The micro part of the Release.

patch: int property

The patch part of the Release.

This is equivalent to micro.

extra: Extra property

The extra parts of the Release.

from_string(string: str) -> Self classmethod

Parses a Version from string.

Parameters:

Name Type Description Default
string str

The string to parse.

required

Returns:

Type Description
Self

The parsed version.

Source code in versions/version.py
110
111
112
113
114
115
116
117
118
119
120
@classmethod
def from_string(cls, string: str) -> Self:
    """Parses a [`Version`][versions.version.Version] from `string`.

    Arguments:
        string: The string to parse.

    Returns:
        The parsed version.
    """
    return VersionParser(cls).parse(string)

to_string() -> str

Converts a Version to its string representation.

Returns:

Type Description
str

The version string.

Source code in versions/version.py
187
188
189
190
191
192
193
def to_string(self) -> str:
    """Converts a [`Version`][versions.version.Version] to its string representation.

    Returns:
        The version string.
    """
    return concat_empty(self.to_string_iterator())

to_short_string() -> str

Converts a Version to its short string representation.

Returns:

Type Description
str

The short version string.

Source code in versions/version.py
195
196
197
198
199
200
201
def to_short_string(self) -> str:
    """Converts a [`Version`][versions.version.Version] to its *short* string representation.

    Returns:
        The *short* version string.
    """
    return concat_empty(self.to_short_string_iterator())

to_pep440_string() -> str

Converts a Version to its PEP 440 representation.

version.to_pep440_string()

Is equivalent to the following:

version.normalize().to_short_string()

Returns:

Type Description
str

The PEP 440 version string.

Source code in versions/version.py
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
def to_pep440_string(self) -> str:
    """Converts a [`Version`][versions.version.Version] to its
    [*PEP 440*](https://peps.python.org/pep-0440) representation.

    ```python
    version.to_pep440_string()
    ```

    Is equivalent to the following:

    ```python
    version.normalize().to_short_string()
    ```

    Returns:
        The [*PEP 440*](https://peps.python.org/pep-0440) version string.
    """
    return self.normalize().to_short_string()

get_at(index: int, default: int = DEFAULT_VALUE) -> int

Gets the Release part at the index, defaulting to default.

Parameters:

Name Type Description Default
index int

The index of the part to get.

required
default int

The default value to use.

DEFAULT_VALUE

Returns:

Type Description
int

The release part at index or the default value.

Source code in versions/version.py
260
261
262
263
264
265
266
267
268
269
270
271
def get_at(self, index: int, default: int = DEFAULT_VALUE) -> int:
    """Gets the [`Release`][versions.segments.release.Release] part at the `index`,
    defaulting to `default`.

    Arguments:
        index: The index of the part to get.
        default: The default value to use.

    Returns:
        The release part at `index` or the `default` value.
    """
    return self.release.get_at(index, default)

get_at_unchecked(index: int) -> int

Gets the Release part at the index.

Parameters:

Name Type Description Default
index int

The index of the part to get.

required

Raises:

Type Description
IndexError

The index is out-of-bounds.

Returns:

Type Description
int

The release part at the index.

Source code in versions/version.py
273
274
275
276
277
278
279
280
281
282
283
284
285
def get_at_unchecked(self, index: int) -> int:
    """Gets the [`Release`][versions.segments.Release] part at the `index`.

    Arguments:
        index: The index of the part to get.

    Raises:
        IndexError: The index is *out-of-bounds*.

    Returns:
        The release part at the `index`.
    """
    return self.release.get_at_unchecked(index)

is_semantic() -> bool

Checks if the Release matches the semantic versioning schema.

Returns:

Type Description
bool

Whether the release matches the SemVer schema.

Source code in versions/version.py
287
288
289
290
291
292
293
294
def is_semantic(self) -> bool:
    """Checks if the [`Release`][versions.segments.Release]
    matches the *semantic versioning* schema.

    Returns:
        Whether the release matches the [`SemVer`](https://semver.org/) schema.
    """
    return self.release.is_semantic()

to_semantic() -> Self

Converts the Release to match the SemVer schema.

Returns:

Type Description
Self

The converted version.

Source code in versions/version.py
296
297
298
299
300
301
302
303
def to_semantic(self) -> Self:
    """Converts the [`Release`][versions.segments.Release]
    to match the [`SemVer`](https://semver.org/) schema.

    Returns:
        The converted version.
    """
    return evolve(self, release=self.release.to_semantic())

set_major(value: int) -> Self

Sets the major part of the Release to the value.

Parameters:

Name Type Description Default
value int

The value to set the major part to.

required

Returns:

Type Description
Self

The updated version.

Source code in versions/version.py
320
321
322
323
324
325
326
327
328
329
def set_major(self, value: int) -> Self:
    """Sets the *major* part of the [`Release`][versions.segments.Release] to the `value`.

    Arguments:
        value: The value to set the *major* part to.

    Returns:
        The updated version.
    """
    return self.set_release(self.release.set_major(value))

set_minor(value: int) -> Self

Sets the minor part of the Release to the value.

Parameters:

Name Type Description Default
value int

The value to set the minor part to.

required

Returns:

Type Description
Self

The updated version.

Source code in versions/version.py
331
332
333
334
335
336
337
338
339
340
def set_minor(self, value: int) -> Self:
    """Sets the *minor* part of the [`Release`][versions.segments.Release] to the `value`.

    Arguments:
        value: The value to set the *minor* part to.

    Returns:
        The updated version.
    """
    return self.set_release(self.release.set_minor(value))

set_micro(value: int) -> Self

Sets the micro part of the Release to the value.

Parameters:

Name Type Description Default
value int

The value to set the micro part to.

required

Returns:

Type Description
Self

The updated version.

Source code in versions/version.py
342
343
344
345
346
347
348
349
350
351
def set_micro(self, value: int) -> Self:
    """Sets the *micro* part of the [`Release`][versions.segments.Release] to the `value`.

    Arguments:
        value: The value to set the *micro* part to.

    Returns:
        The updated version.
    """
    return self.set_release(self.release.set_micro(value))

set_patch(value: int) -> Self

Sets the patch part of the Release to the value.

This is equivalent to set_micro.

Parameters:

Name Type Description Default
value int

The value to set the patch part to.

required

Returns:

Type Description
Self

The updated version.

Source code in versions/version.py
353
354
355
356
357
358
359
360
361
362
363
364
def set_patch(self, value: int) -> Self:
    """Sets the *patch* part of the [`Release`][versions.segments.Release] to the `value`.

    This is equivalent to [`set_micro`][versions.version.Version.set_micro].

    Arguments:
        value: The value to set the *patch* part to.

    Returns:
        The updated version.
    """
    return self.set_release(self.release.set_patch(value))

set_at(index: int, value: int) -> Self

Sets the Release part at the index to the value.

Parameters:

Name Type Description Default
index int

The index to set the value at.

required
value int

The value to set the part to.

required

Returns:

Type Description
Self

The updated version.

Source code in versions/version.py
366
367
368
369
370
371
372
373
374
375
376
def set_at(self, index: int, value: int) -> Self:
    """Sets the [`Release`][versions.segments.Release] part at the `index` to the `value`.

    Arguments:
        index: The index to set the `value` at.
        value: The value to set the part to.

    Returns:
        The updated version.
    """
    return self.set_release(self.release.set_at(index, value))

set_at_unchecked(index: int, value: int) -> Self

Sets the Release part at the index to the value.

Parameters:

Name Type Description Default
index int

The index to set the value at.

required
value int

The value to set the part to.

required

Raises:

Type Description
IndexError

The index is out-of-bounds.

Returns:

Type Description
Self

The updated version.

Source code in versions/version.py
378
379
380
381
382
383
384
385
386
387
388
389
390
391
def set_at_unchecked(self, index: int, value: int) -> Self:
    """Sets the [`Release`][versions.segments.Release] part at the `index` to the `value`.

    Arguments:
        index: The index to set the `value` at.
        value: The value to set the part to.

    Raises:
        IndexError: The index is *out-of-bounds*.

    Returns:
        The updated version.
    """
    return self.set_release(self.release.set_at_unchecked(index, value))

next_major() -> Self

Bumps the major part of the Release if the version is stable, otherwise converts the version to be stable.

Returns:

Type Description
Self

The bumped version.

Source code in versions/version.py
396
397
398
399
400
401
402
403
404
405
406
407
408
def next_major(self) -> Self:
    """Bumps the *major* part of the [`Release`][versions.segments.Release]
    if the version is stable, otherwise converts the version to be stable.

    Returns:
        The bumped version.
    """
    release = self.release

    if self.is_stable():
        release = release.next_major()

    return self.without_tags_and_local().set_release(release)

next_minor() -> Self

Bumps the minor part of the Release if the version is stable, otherwise converts the version to be stable.

Returns:

Type Description
Self

The bumped version.

Source code in versions/version.py
410
411
412
413
414
415
416
417
418
419
420
421
422
def next_minor(self) -> Self:
    """Bumps the *minor* part of the [`Release`][versions.segments.Release]
    if the version is stable, otherwise converts the version to be stable.

    Returns:
        The bumped version.
    """
    release = self.release

    if self.is_stable():
        release = release.next_minor()

    return self.without_tags_and_local().set_release(release)

next_micro() -> Self

Bumps the micro part of the Release if the version is stable, otherwise converts the version to be stable.

Returns:

Type Description
Self

The bumped version.

Source code in versions/version.py
424
425
426
427
428
429
430
431
432
433
434
435
436
def next_micro(self) -> Self:
    """Bumps the *micro* part of the [`Release`][versions.segments.Release]
    if the version is stable, otherwise converts the version to be stable.

    Returns:
        The bumped version.
    """
    release = self.release

    if self.is_stable():
        release = release.next_micro()

    return self.without_tags_and_local().set_release(release)

next_patch() -> Self

Bumps the patch part of the Release if the version is stable, otherwise converts the version to be stable.

This is equivalent to next_micro.

Returns:

Type Description
Self

The bumped version.

Source code in versions/version.py
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
def next_patch(self) -> Self:
    """Bumps the *patch* part of the [`Release`][versions.segments.Release]
    if the version is stable, otherwise converts the version to be stable.

    This is equivalent to [`next_micro`][versions.version.Version.next_micro].

    Returns:
        The bumped version.
    """
    release = self.release

    if self.is_stable():
        release = release.next_patch()

    return self.without_tags_and_local().set_release(release)

next_at(index: int) -> Self

Bumps the part of the Release at the index if the version is stable, otherwise converts the version to be stable.

Parameters:

Name Type Description Default
index int

The index to bump the part at.

required

Returns:

Type Description
Self

The bumped version.

Source code in versions/version.py
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
def next_at(self, index: int) -> Self:
    """Bumps the part of the [`Release`][versions.segments.Release] at the `index`
    if the version is stable, otherwise converts the version to be stable.

    Arguments:
        index: The index to bump the part at.

    Returns:
        The bumped version.
    """
    release = self.release

    if self.is_stable():
        release = release.next_at(index)

    return self.without_tags_and_local().set_release(release)

has_major() -> bool

Checks if the Release has the major part.

Returns:

Type Description
bool

Whether the major part is present.

Source code in versions/version.py
471
472
473
474
475
476
477
def has_major(self) -> bool:
    """Checks if the [`Release`][versions.segments.Release] has the *major* part.

    Returns:
        Whether the *major* part is present.
    """
    return self.release.has_major()

has_minor() -> bool

Checks if the Release has the minor part.

Returns:

Type Description
bool

Whether the minor part is present.

Source code in versions/version.py
479
480
481
482
483
484
485
def has_minor(self) -> bool:
    """Checks if the [`Release`][versions.segments.Release] has the *minor* part.

    Returns:
        Whether the *minor* part is present.
    """
    return self.release.has_minor()

has_micro() -> bool

Checks if the Release has the micro part.

Returns:

Type Description
bool

Whether the micro part is present.

Source code in versions/version.py
487
488
489
490
491
492
493
def has_micro(self) -> bool:
    """Checks if the [`Release`][versions.segments.Release] has the *micro* part.

    Returns:
        Whether the *micro* part is present.
    """
    return self.release.has_micro()

has_patch() -> bool

Checks if the Release has the patch part.

This is equivalent to has_micro.

Returns:

Type Description
bool

Whether the patch part is present.

Source code in versions/version.py
495
496
497
498
499
500
501
502
503
def has_patch(self) -> bool:
    """Checks if the [`Release`][versions.segments.Release] has the *patch* part.

    This is equivalent to [`has_micro`][versions.version.Version.has_micro].

    Returns:
        Whether the *patch* part is present.
    """
    return self.release.has_patch()

has_extra() -> bool

Checks if the Release has any extra parts.

Returns:

Type Description
bool

Whether the extra parts are present.

Source code in versions/version.py
505
506
507
508
509
510
511
def has_extra(self) -> bool:
    """Checks if the [`Release`][versions.segments.Release] has any *extra* parts.

    Returns:
        Whether the *extra* parts are present.
    """
    return self.release.has_extra()

has_at(index: int) -> bool

Checks if the Release has a part at the index.

Returns:

Type Description
bool

Whether the part at the index is present.

Source code in versions/version.py
513
514
515
516
517
518
519
def has_at(self, index: int) -> bool:
    """Checks if the [`Release`][versions.segments.Release] has a part at the `index`.

    Returns:
        Whether the part at the `index` is present.
    """
    return self.release.has_at(index)

pad_to(length: int, padding: int = DEFAULT_PADDING) -> Self

Pads the Release to the length with padding.

Parameters:

Name Type Description Default
length int

The length to pad the release to.

required
padding int

The padding to use.

DEFAULT_PADDING

Returns:

Type Description
Self

The padded version.

Source code in versions/version.py
521
522
523
524
525
526
527
528
529
530
531
def pad_to(self, length: int, padding: int = DEFAULT_PADDING) -> Self:
    """Pads the [`Release`][versions.segments.Release] to the `length` with `padding`.

    Arguments:
        length: The length to pad the release to.
        padding: The padding to use.

    Returns:
        The padded version.
    """
    return self.set_release(self.release.pad_to(length, padding))

pad_to_index(index: int, padding: int = DEFAULT_PADDING) -> Self

Pads the Release to the index with padding.

Parameters:

Name Type Description Default
index int

The index to pad the release to.

required
padding int

The padding to use.

DEFAULT_PADDING

Returns:

Type Description
Self

The padded version.

Source code in versions/version.py
533
534
535
536
537
538
539
540
541
542
543
def pad_to_index(self, index: int, padding: int = DEFAULT_PADDING) -> Self:
    """Pads the [`Release`][versions.segments.Release] to the `index` with `padding`.

    Arguments:
        index: The index to pad the release to.
        padding: The padding to use.

    Returns:
        The padded version.
    """
    return self.set_release(self.release.pad_to_index(index, padding))

pad_to_next(padding: int = DEFAULT_PADDING) -> Self

Pads the Release to the next index.

Parameters:

Name Type Description Default
padding int

The padding to use.

DEFAULT_PADDING

Returns:

Type Description
Self

The padded version.

Source code in versions/version.py
545
546
547
548
549
550
551
552
553
554
def pad_to_next(self, padding: int = DEFAULT_PADDING) -> Self:
    """Pads the [`Release`][versions.segments.Release] to the next index.

    Arguments:
        padding: The padding to use.

    Returns:
        The padded version.
    """
    return self.set_release(self.release.pad_to_next(padding))

is_pre_release() -> bool

Checks if the version is pre-release.

Returns:

Type Description
bool

Whether the version is pre-release.

Source code in versions/version.py
556
557
558
559
560
561
562
def is_pre_release(self) -> bool:
    """Checks if the version is *pre-release*.

    Returns:
        Whether the version is *pre-release*.
    """
    return self.pre is not None

is_post_release() -> bool

Checks if the version is post-release.

Returns:

Type Description
bool

Whether the version is post-release.

Source code in versions/version.py
564
565
566
567
568
569
570
def is_post_release(self) -> bool:
    """Checks if the version is *post-release*.

    Returns:
        Whether the version is *post-release*.
    """
    return self.post is not None

is_dev_release() -> bool

Checks if the version is dev-release.

Returns:

Type Description
bool

Whether the version is dev-release.

Source code in versions/version.py
572
573
574
575
576
577
578
def is_dev_release(self) -> bool:
    """Checks if the version is *dev-release*.

    Returns:
        Whether the version is *dev-release*.
    """
    return self.dev is not None

is_local() -> bool

Checks if the version is local.

Returns:

Type Description
bool

Whether the version is local.

Source code in versions/version.py
580
581
582
583
584
585
586
def is_local(self) -> bool:
    """Checks if the version is *local*.

    Returns:
        Whether the version is *local*.
    """
    return self.local is not None

is_unstable() -> bool

Checks if the version is unstable.

Returns:

Type Description
bool

Whether the version is unstable.

Source code in versions/version.py
588
589
590
591
592
593
594
def is_unstable(self) -> bool:
    """Checks if the version is *unstable*.

    Returns:
        Whether the version is *unstable*.
    """
    return self.is_pre_release() or self.is_dev_release()

is_stable() -> bool

Checks if the version is stable.

Returns:

Type Description
bool

Whether the version is stable.

Source code in versions/version.py
596
597
598
599
600
601
602
def is_stable(self) -> bool:
    """Checks if the version is *stable*.

    Returns:
        Whether the version is *stable*.
    """
    return not self.is_unstable()

next_pre() -> Self

Bumps the PreTag if it is present, otherwise adds one to the version.

Returns:

Type Description
Self

The bumped version.

Source code in versions/version.py
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
def next_pre(self) -> Self:
    """Bumps the [`PreTag`][versions.segments.PreTag] if it is present,
    otherwise adds one to the version.

    Returns:
        The bumped version.
    """
    pre = self.pre

    if pre is None:
        pre = PreTag()

    else:
        pre = pre.next()

    return self.without_tags_and_local().with_pre(pre)

next_pre_phase() -> Optional[Self]

Bumps the PreTag phase if it is present (and if possible), otherwise adds one to the version.

Returns:

Type Description
Optional[Self]

The bumped version (if the next PreTag is present).

Source code in versions/version.py
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
def next_pre_phase(self) -> Optional[Self]:
    """Bumps the [`PreTag`][versions.segments.PreTag] phase if it is present (and if possible),
    otherwise adds one to the version.

    Returns:
        The bumped version (if the next [`PreTag`][versions.segments.PreTag] is present).
    """
    pre = self.pre

    if pre is None:
        pre = PreTag()

    else:
        pre = pre.next_phase()

        if pre is None:
            return None

    return self.without_tags_and_local().with_pre(pre)

next_post() -> Self

Bumps the PostTag if it is present, otherwise adds one to the version.

Returns:

Type Description
Self

The bumped version.

Source code in versions/version.py
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
def next_post(self) -> Self:
    """Bumps the [`PostTag`][versions.segments.PostTag] if it is present,
    otherwise adds one to the version.

    Returns:
        The bumped version.
    """
    post = self.post

    if post is None:
        post = PostTag()

    else:
        post = post.next()

    return self.with_post(post).without_dev_and_local()

next_dev() -> Self

Bumps the DevTag if it is present, otherwise adds one to the version.

Returns:

Type Description
Self

The bumped version.

Source code in versions/version.py
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
def next_dev(self) -> Self:
    """Bumps the [`DevTag`][versions.segments.DevTag] if it is present,
    otherwise adds one to the version.

    Returns:
        The bumped version.
    """
    dev = self.dev

    if dev is None:
        dev = DevTag()

    else:
        dev = dev.next()

    return self.with_dev(dev).without_local()

with_pre(pre: PreTag) -> Self

Updates a version to include PreTag.

Parameters:

Name Type Description Default
pre PreTag

The pre-release tag to include.

required

Returns:

Type Description
Self

The updated version.

Source code in versions/version.py
711
712
713
714
715
716
717
718
719
720
def with_pre(self, pre: PreTag) -> Self:
    """Updates a version to include [`PreTag`][versions.segments.PreTag].

    Arguments:
        pre: The *pre-release* tag to include.

    Returns:
        The updated version.
    """
    return self.set_pre(pre)

with_post(post: PostTag) -> Self

Updates a version to include PostTag.

Parameters:

Name Type Description Default
post PostTag

The post-release tag to include.

required

Returns:

Type Description
Self

The updated version.

Source code in versions/version.py
722
723
724
725
726
727
728
729
730
731
def with_post(self, post: PostTag) -> Self:
    """Updates a version to include [`PostTag`][versions.segments.PostTag].

    Arguments:
        post: The *post-release* tag to include.

    Returns:
        The updated version.
    """
    return self.set_post(post)

with_dev(dev: DevTag) -> Self

Updates a version to include DevTag.

Parameters:

Name Type Description Default
dev DevTag

The dev-release tag to include.

required

Returns:

Type Description
Self

The updated version.

Source code in versions/version.py
733
734
735
736
737
738
739
740
741
742
def with_dev(self, dev: DevTag) -> Self:
    """Updates a version to include [`DevTag`][versions.segments.DevTag].

    Arguments:
        dev: The *dev-release* tag to include.

    Returns:
        The updated version.
    """
    return self.set_dev(dev)

with_local(local: Local) -> Self

Updates a version to include Local.

Parameters:

Name Type Description Default
local Local

The local segment to include.

required

Returns:

Type Description
Self

The updated version.

Source code in versions/version.py
747
748
749
750
751
752
753
754
755
756
def with_local(self, local: Local) -> Self:
    """Updates a version to include [`Local`][versions.segments.Local].

    Arguments:
        local: The *local* segment to include.

    Returns:
        The updated version.
    """
    return self.set_local(local)

without_pre() -> Self

Updates a version, removing any PreTag from it.

Returns:

Type Description
Self

The updated version.

Source code in versions/version.py
764
765
766
767
768
769
770
def without_pre(self) -> Self:
    """Updates a version, removing any [`PreTag`][versions.segments.PreTag] from it.

    Returns:
        The updated version.
    """
    return self.set_pre(None)

without_post() -> Self

Updates a version, removing any PostTag from it.

Returns:

Type Description
Self

The updated version.

Source code in versions/version.py
772
773
774
775
776
777
778
def without_post(self) -> Self:
    """Updates a version, removing any [`PostTag`][versions.segments.PostTag] from it.

    Returns:
        The updated version.
    """
    return self.set_post(None)

without_dev() -> Self

Updates a version, removing any DevTag from it.

Returns:

Type Description
Self

The updated version.

Source code in versions/version.py
780
781
782
783
784
785
786
def without_dev(self) -> Self:
    """Updates a version, removing any [`DevTag`][versions.segments.DevTag] from it.

    Returns:
        The updated version.
    """
    return self.set_dev(None)

without_local() -> Self

Updates a version, removing any Local segment from it.

Returns:

Type Description
Self

The updated version.

Source code in versions/version.py
791
792
793
794
795
796
797
def without_local(self) -> Self:
    """Updates a version, removing any [`Local`][versions.segments.Local] segment from it.

    Returns:
        The updated version.
    """
    return self.set_local(None)

weaken(other: Self) -> Self

Weakens the other version for further comparison.

Parameters:

Name Type Description Default
other Self

The version to weaken.

required

Returns:

Type Description
Self

The weakened version.

Source code in versions/version.py
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
def weaken(self, other: Self) -> Self:
    """Weakens the `other` version for further comparison.

    Arguments:
        other: The version to weaken.

    Returns:
        The weakened version.
    """
    if not self.is_local() and other.is_local():
        other = other.without_local()

    if not self.is_post_release() and other.is_post_release():
        other = other.without_post()

    return other

to_stable() -> Self

Forces a version to be stable.

Returns:

Type Description
Self

The stable version.

Source code in versions/version.py
822
823
824
825
826
827
828
def to_stable(self) -> Self:
    """Forces a version to be stable.

    Returns:
        The stable version.
    """
    return self if self.is_stable() else self.to_stable_unchecked()

to_stable_unchecked() -> Self

Forces a version to be stable, without checking whether it is already stable.

Returns:

Type Description
Self

The stable version.

Source code in versions/version.py
830
831
832
833
834
835
836
def to_stable_unchecked(self) -> Self:
    """Forces a version to be stable, without checking whether it is already stable.

    Returns:
        The stable version.
    """
    return self.without_tags_and_local()

next_breaking() -> Self

Returns the next breaking version.

This function is slightly convoluted due to how 0.x.y and 0.0.z versions are handled:

version next breaking
1.2.3 2.0.0
1.2.0 2.0.0
1.0.0 2.0.0
0.2.3 0.3.0
0.0.3 0.0.4
0.0.0 0.0.1
0.0 0.1.0
0 1.0.0

Returns:

Type Description
Self

The next breaking Version.

Source code in versions/version.py
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
def next_breaking(self) -> Self:
    """Returns the next breaking version.

    This function is slightly convoluted due to how `0.x.y` and `0.0.z` versions are handled:

    | version | next breaking |
    |---------|---------------|
    | `1.2.3` | `2.0.0`       |
    | `1.2.0` | `2.0.0`       |
    | `1.0.0` | `2.0.0`       |
    | `0.2.3` | `0.3.0`       |
    | `0.0.3` | `0.0.4`       |
    | `0.0.0` | `0.0.1`       |
    | `0.0`   | `0.1.0`       |
    | `0`     | `1.0.0`       |

    Returns:
        The next breaking [`Version`][versions.version.Version].
    """
    if not self.major:
        if self.minor:
            return self.next_minor()

        if self.has_micro():
            return self.next_micro()

        if self.has_minor():
            return self.next_minor()

        return self.next_major()

    return self.to_stable().next_major()

normalize() -> Self

Normalizes all version tags.

Returns:

Type Description
Self

The normalized version.

Source code in versions/version.py
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
def normalize(self) -> Self:
    """Normalizes all version tags.

    Returns:
        The normalized version.
    """
    pre = self.pre

    if pre is not None:
        pre = pre.normalize()

    post = self.post

    if post is not None:
        post = post.normalize()

    dev = self.dev

    if dev is not None:
        dev = dev.normalize()

    return self.set_tags(pre, post, dev)

create(epoch: Optional[Epoch] = None, release: Optional[Release] = None, pre: Optional[PreTag] = None, post: Optional[PostTag] = None, dev: Optional[DevTag] = None, local: Optional[Local] = None) -> Self classmethod

Creates a Version from epoch, release, pre, post, dev and local.

Parameters:

Name Type Description Default
epoch Optional[Epoch]

The epoch to use.

None
release Optional[Release]

The release to use.

None
pre Optional[PreTag]

The pre-release tag to use.

None
post Optional[PostTag]

The post-release tag to use.

None
dev Optional[DevTag]

The dev-release tag to use.

None
local Optional[Local]

The local segment to use.

None

Returns:

Type Description
Self

The newly created Version.

Source code in versions/version.py
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
@classmethod
def create(
    cls,
    epoch: Optional[Epoch] = None,
    release: Optional[Release] = None,
    pre: Optional[PreTag] = None,
    post: Optional[PostTag] = None,
    dev: Optional[DevTag] = None,
    local: Optional[Local] = None,
) -> Self:
    """Creates a [`Version`][versions.version.Version] from `epoch`, `release`,
    `pre`, `post`, `dev` and `local`.

    Arguments:
        epoch: The *epoch* to use.
        release: The *release* to use.
        pre: The *pre-release* tag to use.
        post: The *post-release* tag to use.
        dev: The *dev-release* tag to use.
        local: The *local* segment to use.

    Returns:
        The newly created [`Version`][versions.version.Version].
    """

    if epoch is None:
        epoch = Epoch()

    if release is None:
        release = Release()

    return cls(epoch, release, pre, post, dev, local)

from_parts(*parts: int, epoch: Optional[Epoch] = None, pre: Optional[PreTag] = None, post: Optional[PostTag] = None, dev: Optional[DevTag] = None, local: Optional[Local] = None) -> Self classmethod

Creates a Version from parts, epoch, pre, post, dev and local.

Parameters:

Name Type Description Default
*parts int

The parts of the release to use.

()
epoch Optional[Epoch]

The epoch to use.

None
pre Optional[PreTag]

The pre-release tag to use.

None
post Optional[PostTag]

The post-release tag to use.

None
dev Optional[DevTag]

The dev-release tag to use.

None
local Optional[Local]

The local segment to use.

None

Returns:

Type Description
Self

The newly created Version.

Source code in versions/version.py
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
@classmethod
def from_parts(
    cls,
    *parts: int,
    epoch: Optional[Epoch] = None,
    pre: Optional[PreTag] = None,
    post: Optional[PostTag] = None,
    dev: Optional[DevTag] = None,
    local: Optional[Local] = None,
) -> Self:
    """Creates a [`Version`][versions.version.Version] from `parts`,
    `epoch`, `pre`, `post`, `dev` and `local`.

    Arguments:
        *parts: The parts of the *release* to use.
        epoch: The *epoch* to use.
        pre: The *pre-release* tag to use.
        post: The *post-release* tag to use.
        dev: The *dev-release* tag to use.
        local: The *local* segment to use.

    Returns:
        The newly created [`Version`][versions.version.Version].
    """
    release = Release(parts)

    return cls.create(epoch, release, pre, post, dev, local)

matches(specification: Specification) -> bool

Checks if a version matches the specification.

Parameters:

Name Type Description Default
specification Specification

The specification to check the version against.

required

Returns:

Type Description
bool

Whether the version matches the specification.

Source code in versions/version.py
955
956
957
958
959
960
961
962
963
964
def matches(self, specification: Specification) -> bool:
    """Checks if a version matches the `specification`.

    Arguments:
        specification: The specification to check the version against.

    Returns:
        Whether the version matches the specification.
    """
    return specification.accepts(self)