@@ -842,8 +842,11 @@ class NugetVersionRange(MavenVersionRange):
842
842
843
843
844
844
class ComposerVersionRange (VersionRange ):
845
- # TODO composer may need its own scheme see https//github.com/aboutcode-org/univers/issues/5
846
- # and https//getcomposer.org/doc/articles/versions.md
845
+ """
846
+ Composer version range as documented at
847
+ https://getcomposer.org/doc/articles/versions.md
848
+ """
849
+
847
850
scheme = "composer"
848
851
version_class = versions .ComposerVersion
849
852
@@ -856,6 +859,75 @@ class ComposerVersionRange(VersionRange):
856
859
"=" : "=" , # This is not a native composer-semver comparator, but is used in the gitlab version range for composer packages.
857
860
}
858
861
862
+ @classmethod
863
+ def from_native (cls , string ):
864
+ """
865
+ Parse a Composer version range string into a version range object.
866
+ """
867
+ string = string .strip ()
868
+
869
+ if string .startswith ("^" ):
870
+ base_version = string [1 :]
871
+ base_version_obj = cls .version_class (base_version )
872
+ base_parts = base_version .split ("." )
873
+ if base_parts [0 ] == "0" :
874
+ upper_constraint = VersionConstraint (
875
+ comparator = "<" , version = cls .version_class (f"0.{ int (base_parts [1 ]) + 1 } .0" )
876
+ )
877
+ else :
878
+ upper_constraint = VersionConstraint (
879
+ comparator = "<" , version = cls .version_class (f"{ int (base_parts [0 ]) + 1 } .0.0" )
880
+ )
881
+ lower_constraint = VersionConstraint (comparator = ">=" , version = base_version_obj )
882
+ return cls (constraints = [lower_constraint , upper_constraint ])
883
+
884
+ if string .startswith ("~" ):
885
+ base_version = string [1 :]
886
+ base_version_obj = cls .version_class (base_version )
887
+ base_parts = base_version .split ("." )
888
+
889
+ if len (base_parts ) == 3 :
890
+ upper_constraint = VersionConstraint (
891
+ comparator = "<" ,
892
+ version = cls .version_class (f"{ base_parts [0 ]} .{ int (base_parts [1 ]) + 1 } .0" ),
893
+ )
894
+ else :
895
+ upper_constraint = VersionConstraint (
896
+ comparator = "<" , version = cls .version_class (f"{ int (base_parts [0 ]) + 1 } .0.0" )
897
+ )
898
+
899
+ lower_constraint = VersionConstraint (comparator = ">=" , version = base_version_obj )
900
+ return cls (constraints = [lower_constraint , upper_constraint ])
901
+
902
+ if ".*" in string :
903
+ base_version = string .replace (".*" , ".0" )
904
+ base_version_obj = cls .version_class (base_version )
905
+ base_parts = base_version .split ("." )
906
+ upper_constraint = VersionConstraint (
907
+ comparator = "<" ,
908
+ version = cls .version_class (f"{ base_parts [0 ]} .{ int (base_parts [1 ]) + 1 } .0" ),
909
+ )
910
+ lower_constraint = VersionConstraint (comparator = ">=" , version = base_version_obj )
911
+ return cls (constraints = [lower_constraint , upper_constraint ])
912
+
913
+ constraints = []
914
+
915
+ segments = string .split ("||" )
916
+
917
+ for segment in segments :
918
+ if not any (op in string for op in cls .vers_by_native_comparators ):
919
+ segment = "==" + segment
920
+ specifiers = SpecifierSet (segment )
921
+ for spec in specifiers :
922
+ operator = spec .operator
923
+ version = spec .version
924
+ version = cls .version_class (version )
925
+ comparator = cls .vers_by_native_comparators .get (operator , "=" )
926
+ constraint = VersionConstraint (comparator = comparator , version = version )
927
+ constraints .append (constraint )
928
+
929
+ return cls (constraints = constraints )
930
+
859
931
860
932
class RpmVersionRange (VersionRange ):
861
933
# http://ftp.rpm.org/api/4.4.2.2/dependencies.html
@@ -942,7 +1014,7 @@ def from_natives(cls, strings):
942
1014
943
1015
class GolangVersionRange (VersionRange ):
944
1016
"""
945
- Go modules use strict semver with pseudo numbering for Git repos
1017
+ Go modules use strict semver with pseudo numbering for Git commits.
946
1018
https://go.dev/doc/modules/version-numbers
947
1019
"""
948
1020
@@ -958,6 +1030,39 @@ class GolangVersionRange(VersionRange):
958
1030
"=" : "=" , # This is not a native golang-semver comparator, but is used in the gitlab version range for go packages.
959
1031
}
960
1032
1033
+ @classmethod
1034
+ def from_native (cls , string ):
1035
+ """
1036
+ Parse a native GoLang version range into a set of constraints.
1037
+ """
1038
+ constraints = []
1039
+
1040
+ segments = string .split ("||" )
1041
+ for segment in segments :
1042
+
1043
+ if not any (op in string for op in cls .vers_by_native_comparators ):
1044
+ segment = "==" + segment
1045
+
1046
+ specifiers = SpecifierSet (segment )
1047
+ for spec in specifiers :
1048
+ operator = spec .operator
1049
+ version = spec .version
1050
+ version = cls .version_class (version )
1051
+ comparator = cls .vers_by_native_comparators .get (operator , "=" )
1052
+ constraint = VersionConstraint (comparator = comparator , version = version )
1053
+ constraints .append (constraint )
1054
+
1055
+ return cls (constraints = constraints )
1056
+
1057
+ @classmethod
1058
+ def from_natives (cls , strings ):
1059
+ if isinstance (strings , str ):
1060
+ return cls .from_native (strings )
1061
+ constraints = []
1062
+ for rel in strings :
1063
+ constraints .extend (cls .from_native (rel ).constraints )
1064
+ return cls (constraints = constraints )
1065
+
961
1066
962
1067
class GenericVersionRange (VersionRange ):
963
1068
scheme = "generic"
0 commit comments