@@ -1273,6 +1273,100 @@ def add_pipfile_entry_to_pipfile(self, name, normalized_name, entry, category=No
1273
1273
self .write_toml (parsed_pipfile )
1274
1274
return newly_added , category , normalized_name
1275
1275
1276
+ def add_packages_to_pipfile_batch (self , packages_data , dev = False , categories = None ):
1277
+ """
1278
+ Add multiple packages to Pipfile in a single operation for better performance.
1279
+
1280
+ Args:
1281
+ packages_data: List of tuples (package, pip_line) or list of dicts with package info
1282
+ dev: Whether to add to dev-packages section
1283
+ categories: List of categories to add packages to
1284
+
1285
+ Returns:
1286
+ List of tuples (newly_added, category, normalized_name) for each package
1287
+ """
1288
+ if not packages_data :
1289
+ return []
1290
+
1291
+ # Determine target categories
1292
+ if categories is None :
1293
+ categories = ["dev-packages" if dev else "packages" ]
1294
+ elif isinstance (categories , str ):
1295
+ categories = [categories ]
1296
+
1297
+ # Read Pipfile once
1298
+ parsed_pipfile = self .parsed_pipfile
1299
+ results = []
1300
+
1301
+ # Ensure all categories exist
1302
+ for category in categories :
1303
+ if category not in parsed_pipfile :
1304
+ parsed_pipfile [category ] = {}
1305
+
1306
+ # Process all packages
1307
+ for package_data in packages_data :
1308
+ if isinstance (package_data , tuple ) and len (package_data ) == 2 :
1309
+ package , pip_line = package_data
1310
+
1311
+ # Generate entry for this package
1312
+ name , normalized_name , entry = self .generate_package_pipfile_entry (
1313
+ package , pip_line , category = categories [0 ]
1314
+ )
1315
+
1316
+ # Add to each specified category
1317
+ for category in categories :
1318
+ newly_added = False
1319
+
1320
+ # Remove any existing entries with different casing
1321
+ section = parsed_pipfile .get (category , {})
1322
+ for entry_name in section .copy ().keys ():
1323
+ if entry_name .lower () == normalized_name .lower ():
1324
+ del parsed_pipfile [category ][entry_name ]
1325
+
1326
+ # Check if this is a new package
1327
+ if normalized_name not in parsed_pipfile [category ]:
1328
+ newly_added = True
1329
+
1330
+ # Add the package
1331
+ parsed_pipfile [category ][normalized_name ] = entry
1332
+ results .append ((newly_added , category , normalized_name ))
1333
+
1334
+ elif isinstance (package_data , dict ):
1335
+ # Handle pre-processed package data
1336
+ name = package_data .get ("name" )
1337
+ normalized_name = package_data .get ("normalized_name" )
1338
+ entry = package_data .get ("entry" )
1339
+
1340
+ if name and normalized_name and entry :
1341
+ for category in categories :
1342
+ newly_added = False
1343
+
1344
+ # Remove any existing entries with different casing
1345
+ section = parsed_pipfile .get (category , {})
1346
+ for entry_name in section .copy ().keys ():
1347
+ if entry_name .lower () == normalized_name .lower ():
1348
+ del parsed_pipfile [category ][entry_name ]
1349
+
1350
+ # Check if this is a new package
1351
+ if normalized_name not in parsed_pipfile [category ]:
1352
+ newly_added = True
1353
+
1354
+ # Add the package
1355
+ parsed_pipfile [category ][normalized_name ] = entry
1356
+ results .append ((newly_added , category , normalized_name ))
1357
+
1358
+ # Sort categories if requested
1359
+ if self .settings .get ("sort_pipfile" ):
1360
+ for category in categories :
1361
+ if category in parsed_pipfile :
1362
+ parsed_pipfile [category ] = self ._sort_category (
1363
+ parsed_pipfile [category ]
1364
+ )
1365
+
1366
+ # Write Pipfile once at the end
1367
+ self .write_toml (parsed_pipfile )
1368
+ return results
1369
+
1276
1370
def src_name_from_url (self , index_url ):
1277
1371
location = urllib .parse .urlsplit (index_url ).netloc
1278
1372
if "." in location :
0 commit comments