@@ -759,6 +759,34 @@ def _is_duplicate_file(db_session, filename, hashes):
759
759
return None
760
760
761
761
762
+ def _get_release_classifiers (db_session , classifiers_data ):
763
+ """
764
+ Go over the classifiers of a release, and add any missing ones
765
+ to the database.
766
+ """
767
+
768
+ # Look up all of the valid classifiers
769
+ all_classifiers = db_session .query (Classifier ).all ()
770
+
771
+ # Get all the classifiers for this release
772
+ release_classifiers = [
773
+ c for c in all_classifiers if c .classifier in classifiers_data
774
+ ]
775
+
776
+ # Determine if we need to add any new classifiers to the database
777
+ missing_classifiers = set (classifiers_data or []) - set (
778
+ c .classifier for c in release_classifiers
779
+ )
780
+
781
+ # Add any new classifiers to the database
782
+ if missing_classifiers :
783
+ for missing_classifier_name in missing_classifiers :
784
+ missing_classifier = Classifier (classifier = missing_classifier_name )
785
+ db_session .add (missing_classifier )
786
+ release_classifiers .append (missing_classifier )
787
+ return release_classifiers
788
+
789
+
762
790
@view_config (
763
791
route_name = "forklift.legacy.file_upload" ,
764
792
uses_session = True ,
@@ -1039,6 +1067,27 @@ def file_upload(request):
1039
1067
) from None
1040
1068
1041
1069
canonical_version = packaging .utils .canonicalize_version (form .version .data )
1070
+
1071
+ form_metadata_fields = {
1072
+ # This is a list of all the fields in the form that we
1073
+ # should pull off and insert into our new release.
1074
+ "version" ,
1075
+ "summary" ,
1076
+ "license" ,
1077
+ "author" ,
1078
+ "author_email" ,
1079
+ "maintainer" ,
1080
+ "maintainer_email" ,
1081
+ "keywords" ,
1082
+ "platform" ,
1083
+ "home_page" ,
1084
+ "download_url" ,
1085
+ "requires_python" ,
1086
+ }
1087
+
1088
+ # Determine if this is a draft release or a published one
1089
+ release_is_draft = bool (request .headers .get ("Is-Draft" , default = False ))
1090
+
1042
1091
try :
1043
1092
release = (
1044
1093
request .db .query (Release )
@@ -1060,30 +1109,10 @@ def file_upload(request):
1060
1109
.one ()
1061
1110
)
1062
1111
except NoResultFound :
1063
-
1064
- # Determine if this is a draft release or a published one
1065
- release_is_draft = bool (request .headers .get ("Is-Draft" , default = False ))
1066
-
1067
- # Look up all of the valid classifiers
1068
- all_classifiers = request .db .query (Classifier ).all ()
1069
-
1070
- # Get all the classifiers for this release
1071
- release_classifiers = [
1072
- c for c in all_classifiers if c .classifier in form .classifiers .data
1073
- ]
1074
-
1075
- # Determine if we need to add any new classifiers to the database
1076
- missing_classifiers = set (form .classifiers .data or []) - set (
1077
- c .classifier for c in release_classifiers
1112
+ release_classifiers = _get_release_classifiers (
1113
+ request .db , form .classifiers .data
1078
1114
)
1079
1115
1080
- # Add any new classifiers to the database
1081
- if missing_classifiers :
1082
- for missing_classifier_name in missing_classifiers :
1083
- missing_classifier = Classifier (classifier = missing_classifier_name )
1084
- request .db .add (missing_classifier )
1085
- release_classifiers .append (missing_classifier )
1086
-
1087
1116
release = Release (
1088
1117
project = project ,
1089
1118
project_name = project .name ,
@@ -1110,25 +1139,7 @@ def file_upload(request):
1110
1139
html = rendered or "" ,
1111
1140
rendered_by = readme .renderer_version (),
1112
1141
),
1113
- ** {
1114
- k : getattr (form , k ).data
1115
- for k in {
1116
- # This is a list of all the fields in the form that we
1117
- # should pull off and insert into our new release.
1118
- "version" ,
1119
- "summary" ,
1120
- "license" ,
1121
- "author" ,
1122
- "author_email" ,
1123
- "maintainer" ,
1124
- "maintainer_email" ,
1125
- "keywords" ,
1126
- "platform" ,
1127
- "home_page" ,
1128
- "download_url" ,
1129
- "requires_python" ,
1130
- }
1131
- },
1142
+ ** {k : getattr (form , k ).data for k in form_metadata_fields },
1132
1143
uploader = request .user ,
1133
1144
uploaded_via = request .user_agent ,
1134
1145
published = None if release_is_draft else datetime .now (tz = timezone .utc ),
@@ -1146,17 +1157,48 @@ def file_upload(request):
1146
1157
submitted_from = request .remote_addr ,
1147
1158
)
1148
1159
)
1149
-
1150
1160
project .record_event (
1151
1161
tag = "project:release:add" ,
1152
1162
ip_address = request .remote_addr ,
1153
1163
additional = {
1154
1164
"submitted_by" : request .user .username ,
1155
1165
"canonical_version" : release .canonical_version ,
1156
- "version_or_draft" : release .version_or_draft ,
1157
1166
},
1158
1167
)
1159
-
1168
+ else :
1169
+ # An existing release was found. Update its metadata if it's a draft.
1170
+ if release .is_draft :
1171
+ release_classifiers = _get_release_classifiers (
1172
+ request .db , form .classifiers .data
1173
+ )
1174
+ for rc in release_classifiers :
1175
+ release ._classifiers = release_classifiers
1176
+ new_dependencies = list (
1177
+ _construct_dependencies (
1178
+ form ,
1179
+ {
1180
+ "requires" : DependencyKind .requires ,
1181
+ "provides" : DependencyKind .provides ,
1182
+ "obsoletes" : DependencyKind .obsoletes ,
1183
+ "requires_dist" : DependencyKind .requires_dist ,
1184
+ "provides_dist" : DependencyKind .provides_dist ,
1185
+ "obsoletes_dist" : DependencyKind .obsoletes_dist ,
1186
+ "requires_external" : DependencyKind .requires_external ,
1187
+ "project_urls" : DependencyKind .project_url ,
1188
+ },
1189
+ )
1190
+ )
1191
+ if new_dependencies :
1192
+ release .dependencies = new_dependencies
1193
+ if form .description .data :
1194
+ release .description .content_type = description_content_type
1195
+ release .description .raw = form .description .data or ""
1196
+ release .description .html = rendered or ""
1197
+ release .description .rendered_by = readme .renderer_version ()
1198
+ for field in form_metadata_fields :
1199
+ field_value = getattr (form , field ).data
1200
+ if field_value :
1201
+ setattr (release , field , field_value )
1160
1202
# TODO: We need a better solution to this than to just do it inline inside
1161
1203
# this method. Ideally the version field would just be sortable, but
1162
1204
# at least this should be some sort of hook or trigger.
@@ -1274,8 +1316,15 @@ def file_upload(request):
1274
1316
"The digest supplied does not match a digest calculated "
1275
1317
"from the uploaded file." ,
1276
1318
)
1277
- # Skip duplicate check for files when it's a draft release
1278
- if not release .is_draft :
1319
+ # Skip duplicate check for files when it's a draft release,
1320
+ # and delete existing files instead
1321
+ if release .is_draft :
1322
+ existing_file = (
1323
+ request .db .query (File ).filter (File .filename == filename ).first ()
1324
+ )
1325
+ if existing_file is not None :
1326
+ request .db .delete (existing_file )
1327
+ else :
1279
1328
# Check to see if the file that was uploaded exists already or not.
1280
1329
is_duplicate = _is_duplicate_file (request .db , filename , file_hashes )
1281
1330
if is_duplicate :
@@ -1363,7 +1412,17 @@ def file_upload(request):
1363
1412
# TODO: This should be handled by some sort of database trigger or a
1364
1413
# SQLAlchemy hook or the like instead of doing it inline in this
1365
1414
# view.
1366
- request .db .add (Filename (filename = filename ))
1415
+ #
1416
+ # If this is a draft release and the filename is
1417
+ # already on the registry, do nothing.
1418
+ if release .is_draft :
1419
+ if (
1420
+ request .db .query (Filename ).filter (Filename .filename == filename ).first ()
1421
+ is None
1422
+ ):
1423
+ request .db .add (Filename (filename = filename ))
1424
+ else :
1425
+ request .db .add (Filename (filename = filename ))
1367
1426
1368
1427
# Store the information about the file in the database.
1369
1428
file_ = File (
0 commit comments