255 | | softlimit = hardlimit = None |
256 | | |
257 | | limitby = options["limitby"] |
258 | | if limitby : |
259 | | limitby = limitby.strip().lower() |
260 | | if limitby : |
261 | | if limitby not in ('quota', 'balance', 'noquota', \ |
262 | | 'noprint', 'nochange') : |
263 | | raise PyKotaCommandLineError, _("Invalid limitby value %s") % options["limitby"] |
264 | | if limitby in ('noquota', 'nochange') : |
265 | | options["noquota"] = 1 |
266 | | if (limitby in ('nochange', 'noprint')) and options["groups"] : |
267 | | raise PyKotaCommandLineError, _("Invalid limitby value %s") % options["limitby"] |
268 | | |
269 | | used = options["used"] |
270 | | if used : |
271 | | used = used.strip() |
272 | | try : |
273 | | int(used) |
274 | | except ValueError : |
275 | | raise PyKotaCommandLineError, _("Invalid used value %s.") % used |
| 255 | if options["delete"] : |
| 256 | if not names : |
| 257 | raise PyKotaCommandLineError, _("You have to pass user or group names on the command line") |
| 258 | self.display("Processing...\n") |
| 259 | todelete = getattr(self.storage, "getMatching%ss" % suffix)(",".join(names)) |
| 260 | nbtotal = len(todelete) |
| 261 | for i in range(nbtotal) : |
| 262 | todelete[i].delete() |
| 263 | percent = 100.0 * float(i) / float(nbtotal) |
| 264 | self.display("\r%.02f%%" % percent) |
| 265 | self.display("\r100.00%%\r ") |
| 266 | self.display("\r%s\n" % _("Done.")) |
| 267 | else : |
| 268 | softlimit = hardlimit = None |
| 269 | |
| 270 | limitby = options["limitby"] |
| 271 | if limitby : |
| 272 | limitby = limitby.strip().lower() |
| 273 | if limitby : |
| 274 | if limitby not in ('quota', 'balance', 'noquota', \ |
| 275 | 'noprint', 'nochange') : |
| 276 | raise PyKotaCommandLineError, _("Invalid limitby value %s") % options["limitby"] |
| 277 | if limitby in ('noquota', 'nochange') : |
| 278 | options["noquota"] = 1 |
| 279 | if (limitby in ('nochange', 'noprint')) and options["groups"] : |
| 280 | raise PyKotaCommandLineError, _("Invalid limitby value %s") % options["limitby"] |
| 281 | |
| 282 | used = options["used"] |
| 283 | if used : |
| 284 | used = used.strip() |
| 285 | try : |
| 286 | int(used) |
| 287 | except ValueError : |
| 288 | raise PyKotaCommandLineError, _("Invalid used value %s.") % used |
| 289 | |
| 290 | increase = options["increase"] |
| 291 | if increase : |
| 292 | try : |
| 293 | increase = int(increase.strip()) |
| 294 | except ValueError : |
| 295 | raise PyKotaCommandLineError, _("Invalid increase value %s.") % increase |
| 296 | |
| 297 | if not options["noquota"] : |
| 298 | if options["softlimit"] : |
| 299 | try : |
| 300 | softlimit = int(options["softlimit"].strip()) |
| 301 | if softlimit < 0 : |
| 302 | raise ValueError |
| 303 | except ValueError : |
| 304 | raise PyKotaCommandLineError, _("Invalid softlimit value %s.") % options["softlimit"] |
| 305 | if options["hardlimit"] : |
| 306 | try : |
| 307 | hardlimit = int(options["hardlimit"].strip()) |
| 308 | if hardlimit < 0 : |
| 309 | raise ValueError |
| 310 | except ValueError : |
| 311 | raise PyKotaCommandLineError, _("Invalid hardlimit value %s.") % options["hardlimit"] |
| 312 | if (softlimit is not None) and (hardlimit is not None) and (hardlimit < softlimit) : |
| 313 | # error, exchange them |
| 314 | self.printInfo(_("Hard limit %i is less than soft limit %i, values will be exchanged.") % (hardlimit, softlimit)) |
| 315 | (softlimit, hardlimit) = (hardlimit, softlimit) |
291 | | raise PyKotaCommandLineError, _("Invalid softlimit value %s.") % options["softlimit"] |
292 | | if options["hardlimit"] : |
293 | | try : |
294 | | hardlimit = int(options["hardlimit"].strip()) |
295 | | if hardlimit < 0 : |
296 | | raise ValueError |
297 | | except ValueError : |
298 | | raise PyKotaCommandLineError, _("Invalid hardlimit value %s.") % options["hardlimit"] |
299 | | if (softlimit is not None) and (hardlimit is not None) and (hardlimit < softlimit) : |
300 | | # error, exchange them |
301 | | self.printInfo(_("Hard limit %i is less than soft limit %i, values will be exchanged.") % (hardlimit, softlimit)) |
302 | | (softlimit, hardlimit) = (hardlimit, softlimit) |
303 | | |
304 | | overcharge = options["overcharge"] |
305 | | if overcharge : |
306 | | try : |
307 | | overcharge = float(overcharge.strip()) |
308 | | except (ValueError, AttributeError) : |
309 | | raise PyKotaCommandLineError, _("Invalid overcharge value %s") % options["overcharge"] |
310 | | |
311 | | balance = options["balance"] |
312 | | if balance : |
313 | | balance = balance.strip() |
314 | | try : |
315 | | balancevalue = float(balance) |
316 | | except ValueError : |
317 | | raise PyKotaCommandLineError, _("Invalid balance value %s") % options["balance"] |
318 | | |
319 | | if options["charge"] : |
320 | | try : |
321 | | charges = [float(part) for part in options["charge"].split(',', 1)] |
322 | | except ValueError : |
323 | | raise PyKotaCommandLineError, _("Invalid charge amount value %s") % options["charge"] |
324 | | else : |
325 | | if len(charges) > 2 : |
326 | | charges = charges[:2] |
327 | | if len(charges) != 2 : |
328 | | charges = [charges[0], None] |
329 | | |
330 | | if options["ingroups"] : |
331 | | groupnames = [gname.strip() for gname in options["ingroups"].split(',')] |
332 | | else : |
333 | | groupnames = [] |
334 | | |
335 | | rejectunknown = self.config.getRejectUnknown() |
336 | | printeradded = 0 |
337 | | printers = self.storage.getMatchingPrinters(options["printer"]) |
338 | | if not printers : |
339 | | pname = options["printer"] |
340 | | if options["add"] and pname : |
341 | | if self.isValidName(pname) : |
342 | | printers = [ self.storage.addPrinter(pname) ] |
343 | | if printers[0].Exists : |
344 | | printeradded = 1 |
345 | | else : |
346 | | raise PyKotaToolError, _("Impossible to add printer %s") % pname |
347 | | else : |
348 | | raise PyKotaCommandLineError, _("Invalid printer name %s") % pname |
349 | | else : |
350 | | raise PyKotaCommandLineError, _("There's no printer matching %s") % pname |
351 | | if not names : |
352 | | if options["delete"] : |
353 | | raise PyKotaCommandLineError, _("You have to pass user or group names on the command line") |
354 | | else : |
355 | | names = getattr(self.storage, "getAll%ssNames" % suffix)() # all users or groups |
356 | | |
357 | | printersgroups = [] |
358 | | if options["pgroups"] : |
359 | | printersgroups = self.storage.getMatchingPrinters(options["pgroups"]) |
360 | | |
361 | | if options["prototype"] : |
362 | | protoentry = getattr(self.storage, "get%s" % suffix)(options["prototype"]) |
363 | | if not protoentry.Exists : |
364 | | raise PyKotaCommandLineError, _("Prototype object %s not found in Quota Storage.") % protoentry.Name |
365 | | else : |
366 | | limitby = protoentry.LimitBy |
367 | | balancevalue = protoentry.AccountBalance |
368 | | if balancevalue is not None : |
369 | | balance = str(abs(balancevalue)) |
370 | | else : |
371 | | balance = None |
372 | | overcharge = getattr(protoentry, "OverCharge", None) |
373 | | |
374 | | sys.stdout.write(_("Managing print quotas... (this may take a lot of time)")) |
375 | | sys.stdout.flush() |
376 | | missingusers = {} |
377 | | missinggroups = {} |
378 | | todelete = {} |
379 | | changed = {} # tracks changes made at the user/group level |
380 | | for printer in printers : |
381 | | for pgroup in printersgroups : |
382 | | pgroup.addPrinterToGroup(printer) |
| 330 | raise PyKotaCommandLineError, _("Invalid balance value %s") % options["balance"] |
388 | | if options["prototype"] : |
389 | | protoquota = getattr(self.storage, "get%sPQuota" % suffix)(protoentry, printer) |
390 | | if not protoquota.Exists : |
391 | | self.printInfo(_("Prototype %s not found in Quota Storage for printer %s.") % (protoentry.Name, printer.Name)) |
| 348 | rejectunknown = self.config.getRejectUnknown() |
| 349 | printeradded = 0 |
| 350 | printers = self.storage.getMatchingPrinters(options["printer"]) |
| 351 | if not printers : |
| 352 | pname = options["printer"] |
| 353 | if options["add"] and pname : |
| 354 | if self.isValidName(pname) : |
| 355 | printers = [ self.storage.addPrinter(pname) ] |
| 356 | if printers[0].Exists : |
| 357 | printeradded = 1 |
| 358 | else : |
| 359 | raise PyKotaToolError, _("Impossible to add printer %s") % pname |
| 360 | else : |
| 361 | raise PyKotaCommandLineError, _("Invalid printer name %s") % pname |
| 362 | else : |
| 363 | raise PyKotaCommandLineError, _("There's no printer matching %s") % pname |
| 364 | if not names : |
| 365 | names = getattr(self.storage, "getAll%ssNames" % suffix)() # all users or groups |
| 366 | |
| 367 | printersgroups = [] |
| 368 | if options["pgroups"] : |
| 369 | printersgroups = self.storage.getMatchingPrinters(options["pgroups"]) |
| 370 | |
| 371 | if options["prototype"] : |
| 372 | protoentry = getattr(self.storage, "get%s" % suffix)(options["prototype"]) |
| 373 | if not protoentry.Exists : |
| 374 | raise PyKotaCommandLineError, _("Prototype object %s not found in Quota Storage.") % protoentry.Name |
395 | | if not options["noquota"] : |
396 | | if hardlimit is None : |
397 | | hardlimit = softlimit |
398 | | if hardlimit is not None : |
399 | | self.printInfo(_("Undefined hard limit set to soft limit (%s) on printer %s.") % (str(hardlimit), printer.Name)) |
400 | | if softlimit is None : |
401 | | softlimit = hardlimit |
402 | | if softlimit is not None : |
403 | | self.printInfo(_("Undefined soft limit set to hard limit (%s) on printer %s.") % (str(softlimit), printer.Name)) |
| 393 | if options["charge"] : |
| 394 | (perpage, perjob) = charges |
| 395 | printer.setPrices(perpage, perjob) |
| 396 | |
| 397 | if options["prototype"] : |
| 398 | protoquota = getattr(self.storage, "get%sPQuota" % suffix)(protoentry, printer) |
| 399 | if not protoquota.Exists : |
| 400 | self.printInfo(_("Prototype %s not found in Quota Storage for printer %s.") % (protoentry.Name, printer.Name)) |
| 401 | else : |
| 402 | (softlimit, hardlimit) = (protoquota.SoftLimit, protoquota.HardLimit) |
405 | | if options["add"] : |
406 | | allentries = [] |
407 | | for name in names : |
408 | | email = "" |
409 | | if not options["groups"] : |
410 | | splitname = name.split('/', 1) # username/email |
411 | | if len(splitname) == 1 : |
412 | | splitname.append("") |
413 | | (name, email) = splitname |
414 | | if email and (email.count('@') != 1) : |
415 | | self.printInfo(_("Invalid email address %s") % email) |
416 | | email = "" |
417 | | entry = getattr(self.storage, "get%s" % suffix)(name) |
418 | | if email and not options["groups"] : |
419 | | entry.Email = email |
420 | | entrypquota = getattr(self.storage, "get%sPQuota" % suffix)(entry, printer) |
421 | | allentries.append((entry, entrypquota)) |
422 | | else : |
423 | | allentries = getattr(self.storage, "getPrinter%ssAndQuotas" % suffix)(printer, names) |
424 | | |
425 | | # TODO : do this only once !!! |
426 | | allnames = [entry.Name for (entry, dummy) in allentries] |
427 | | for name in names : |
428 | | if not self.matchString(name, allnames) : |
429 | | if options["groups"] : |
430 | | missinggroups[name] = 1 |
| 404 | if not options["noquota"] : |
| 405 | if hardlimit is None : |
| 406 | hardlimit = softlimit |
| 407 | if hardlimit is not None : |
| 408 | self.printInfo(_("Undefined hard limit set to soft limit (%s) on printer %s.") % (str(hardlimit), printer.Name)) |
| 409 | if softlimit is None : |
| 410 | softlimit = hardlimit |
| 411 | if softlimit is not None : |
| 412 | self.printInfo(_("Undefined soft limit set to hard limit (%s) on printer %s.") % (str(softlimit), printer.Name)) |
| 413 | |
| 414 | if options["add"] : |
| 415 | allentries = [] |
| 416 | for name in names : |
| 417 | email = "" |
| 418 | if not options["groups"] : |
| 419 | splitname = name.split('/', 1) # username/email |
| 420 | if len(splitname) == 1 : |
| 421 | splitname.append("") |
| 422 | (name, email) = splitname |
| 423 | if email and (email.count('@') != 1) : |
| 424 | self.printInfo(_("Invalid email address %s") % email) |
| 425 | email = "" |
| 426 | entry = getattr(self.storage, "get%s" % suffix)(name) |
| 427 | if email and not options["groups"] : |
| 428 | entry.Email = email |
| 429 | entrypquota = getattr(self.storage, "get%sPQuota" % suffix)(entry, printer) |
| 430 | allentries.append((entry, entrypquota)) |
| 431 | else : |
| 432 | allentries = getattr(self.storage, "getPrinter%ssAndQuotas" % suffix)(printer, names) |
| 433 | |
| 434 | # TODO : do this only once !!! |
| 435 | allnames = [entry.Name for (entry, dummy) in allentries] |
| 436 | for name in names : |
| 437 | if not self.matchString(name, allnames) : |
| 438 | if options["groups"] : |
| 439 | missinggroups[name] = 1 |
| 440 | else : |
| 441 | missingusers[name] = 1 |
| 442 | |
| 443 | for (entry, entrypquota) in allentries : |
| 444 | if not changed.has_key(entry.Name) : |
| 445 | changed[entry.Name] = {} |
| 446 | if not options["groups"] : |
| 447 | changed[entry.Name]["ingroups"] = [] |
| 448 | |
| 449 | if not entry.Exists : |
| 450 | # not found |
| 451 | if options["add"] : |
| 452 | # In case we want to add something, it is crucial |
| 453 | # that we DON'T check with the system accounts files |
| 454 | # like /etc/passwd because users may be defined |
| 455 | # only remotely |
| 456 | if self.isValidName(entry.Name) : |
| 457 | reject = 0 |
| 458 | if rejectunknown : |
| 459 | if options["groups"] : |
| 460 | try : |
| 461 | grp.getgrnam(entry.Name) |
| 462 | except KeyError : |
| 463 | self.printInfo(_("Unknown group %s") % entry.Name, "error") |
| 464 | reject = 1 |
| 465 | else : |
| 466 | try : |
| 467 | pwd.getpwnam(entry.Name) |
| 468 | except KeyError : |
| 469 | self.printInfo(_("Unknown user %s") % entry.Name, "error") |
| 470 | reject = 1 |
| 471 | if not reject : |
| 472 | entry = getattr(self.storage, "add%s" % suffix)(entry) |
| 473 | else : |
| 474 | if options["groups"] : |
| 475 | self.printInfo(_("Invalid group name %s") % entry.Name) |
| 476 | else : |
| 477 | self.printInfo(_("Invalid user name %s") % entry.Name) |
| 478 | else : |
| 479 | if options["groups"] : |
| 480 | missinggroups[entry.Name] = 1 |
| 481 | else : |
| 482 | missingusers[entry.Name] = 1 |
| 483 | |
| 484 | if entry.Exists and (not entrypquota.Exists) : |
| 485 | # not found |
| 486 | if options["add"] : |
| 487 | entrypquota = getattr(self.storage, "add%sPQuota" % suffix)(entry, printer) |
| 488 | |
| 489 | if not entrypquota.Exists : |
| 490 | self.printInfo(_("Quota not found for object %s on printer %s.") % (entry.Name, printer.Name)) |
432 | | missingusers[name] = 1 |
433 | | |
434 | | for (entry, entrypquota) in allentries : |
435 | | if not changed.has_key(entry.Name) : |
436 | | changed[entry.Name] = {} |
437 | | if not options["groups"] : |
438 | | changed[entry.Name]["ingroups"] = [] |
| 492 | if options["noquota"] or options["prototype"] \ |
| 493 | or ((softlimit is not None) and (hardlimit is not None)) : |
| 494 | entrypquota.setLimits(softlimit, hardlimit) |
| 495 | if increase : |
| 496 | if (entrypquota.SoftLimit is None) \ |
| 497 | or (entrypquota.HardLimit is None) : |
| 498 | self.printInfo(_("You can't increase limits by %s when no limit is set.") % increase, "error") |
| 499 | else : |
| 500 | newsoft = entrypquota.SoftLimit + increase |
| 501 | newhard = entrypquota.HardLimit + increase |
| 502 | if (newsoft >= 0) and (newhard >= 0) : |
| 503 | entrypquota.setLimits(newsoft, newhard) |
| 504 | else : |
| 505 | self.printInfo(_("You can't set negative limits."), "error") |
| 506 | if limitby : |
| 507 | if changed[entry.Name].get("limitby") is None : |
| 508 | entry.setLimitBy(limitby) |
| 509 | changed[entry.Name]["limitby"] = limitby |
440 | | if not entry.Exists : |
441 | | # not found |
442 | | if options["add"] : |
443 | | # In case we want to add something, it is crucial |
444 | | # that we DON'T check with the system accounts files |
445 | | # like /etc/passwd because users may be defined |
446 | | # only remotely |
447 | | if self.isValidName(entry.Name) : |
448 | | reject = 0 |
449 | | if rejectunknown : |
450 | | if options["groups"] : |
451 | | try : |
452 | | grp.getgrnam(entry.Name) |
453 | | except KeyError : |
454 | | self.printInfo(_("Unknown group %s") % entry.Name, "error") |
455 | | reject = 1 |
456 | | else : |
457 | | try : |
458 | | pwd.getpwnam(entry.Name) |
459 | | except KeyError : |
460 | | self.printInfo(_("Unknown user %s") % entry.Name, "error") |
461 | | reject = 1 |
462 | | if not reject : |
463 | | entry = getattr(self.storage, "add%s" % suffix)(entry) |
464 | | else : |
465 | | if options["groups"] : |
466 | | self.printInfo(_("Invalid group name %s") % entry.Name) |
467 | | else : |
468 | | self.printInfo(_("Invalid user name %s") % entry.Name) |
469 | | else : |
470 | | if options["groups"] : |
471 | | missinggroups[entry.Name] = 1 |
472 | | else : |
473 | | missingusers[entry.Name] = 1 |
474 | | elif options["delete"] : |
475 | | todelete[entry.Name] = entry |
| 511 | if options["reset"] : |
| 512 | entrypquota.reset() |
| 513 | |
| 514 | if options["hardreset"] : |
| 515 | entrypquota.hardreset() |
| 516 | |
| 517 | if not options["groups"] : |
| 518 | if used : |
| 519 | entrypquota.setUsage(used) |
477 | | if entry.Exists and (not entrypquota.Exists) : |
478 | | # not found |
479 | | if options["add"] : |
480 | | entrypquota = getattr(self.storage, "add%sPQuota" % suffix)(entry, printer) |
481 | | |
482 | | if not entrypquota.Exists : |
483 | | self.printInfo(_("Quota not found for object %s on printer %s.") % (entry.Name, printer.Name)) |
484 | | else : |
485 | | if options["noquota"] or options["prototype"] \ |
486 | | or ((softlimit is not None) and (hardlimit is not None)) : |
487 | | entrypquota.setLimits(softlimit, hardlimit) |
488 | | if increase : |
489 | | if (entrypquota.SoftLimit is None) \ |
490 | | or (entrypquota.HardLimit is None) : |
491 | | self.printInfo(_("You can't increase limits by %s when no limit is set.") % increase, "error") |
492 | | else : |
493 | | newsoft = entrypquota.SoftLimit + increase |
494 | | newhard = entrypquota.HardLimit + increase |
495 | | if (newsoft >= 0) and (newhard >= 0) : |
496 | | entrypquota.setLimits(newsoft, newhard) |
497 | | else : |
498 | | self.printInfo(_("You can't set negative limits."), "error") |
499 | | if limitby : |
500 | | if changed[entry.Name].get("limitby") is None : |
501 | | entry.setLimitBy(limitby) |
502 | | changed[entry.Name]["limitby"] = limitby |
503 | | |
504 | | if options["reset"] : |
505 | | entrypquota.reset() |
506 | | |
507 | | if options["hardreset"] : |
508 | | entrypquota.hardreset() |
509 | | |
510 | | if not options["groups"] : |
511 | | if used : |
512 | | entrypquota.setUsage(used) |
| 521 | if overcharge is not None : |
| 522 | if changed[entry.Name].get("overcharge") is None : |
| 523 | entry.setOverChargeFactor(overcharge) |
| 524 | changed[entry.Name]["overcharge"] = overcharge |
| 525 | |
| 526 | if balance : |
| 527 | if changed[entry.Name].get("balance") is None : |
| 528 | if balance.startswith("+") or balance.startswith("-") : |
| 529 | newbalance = float(entry.AccountBalance or 0.0) + balancevalue |
| 530 | newlifetimepaid = float(entry.LifeTimePaid or 0.0) + balancevalue |
| 531 | entry.setAccountBalance(newbalance, newlifetimepaid, options["comment"]) |
| 532 | else : |
| 533 | diff = balancevalue - float(entry.AccountBalance or 0.0) |
| 534 | newlifetimepaid = float(entry.LifeTimePaid or 0.0) + diff |
| 535 | entry.setAccountBalance(balancevalue, newlifetimepaid, options["comment"]) |
| 536 | changed[entry.Name]["balance"] = balance |
| 537 | |
| 538 | for groupname in groupnames : |
| 539 | # not executed if option --ingroups is not used |
| 540 | if groupname not in changed[entry.Name]["ingroups"] : |
| 541 | group = self.storage.getGroup(groupname) |
| 542 | if group.Exists : |
| 543 | self.storage.addUserToGroup(entry, group) |
| 544 | changed[entry.Name]["ingroups"].append(groupname) |
| 545 | else : |
| 546 | self.printInfo(_("Group %s not found in the PyKota Storage.") % groupname) |
514 | | if overcharge is not None : |
515 | | if changed[entry.Name].get("overcharge") is None : |
516 | | entry.setOverChargeFactor(overcharge) |
517 | | changed[entry.Name]["overcharge"] = overcharge |
518 | | |
519 | | if balance : |
520 | | if changed[entry.Name].get("balance") is None : |
521 | | if balance.startswith("+") or balance.startswith("-") : |
522 | | newbalance = float(entry.AccountBalance or 0.0) + balancevalue |
523 | | newlifetimepaid = float(entry.LifeTimePaid or 0.0) + balancevalue |
524 | | entry.setAccountBalance(newbalance, newlifetimepaid, options["comment"]) |
525 | | else : |
526 | | diff = balancevalue - float(entry.AccountBalance or 0.0) |
527 | | newlifetimepaid = float(entry.LifeTimePaid or 0.0) + diff |
528 | | entry.setAccountBalance(balancevalue, newlifetimepaid, options["comment"]) |
529 | | changed[entry.Name]["balance"] = balance |
530 | | |
531 | | for groupname in groupnames : |
532 | | # not executed if option --ingroups is not used |
533 | | if groupname not in changed[entry.Name]["ingroups"] : |
534 | | group = self.storage.getGroup(groupname) |
535 | | if group.Exists : |
536 | | self.storage.addUserToGroup(entry, group) |
537 | | changed[entry.Name]["ingroups"].append(groupname) |
538 | | else : |
539 | | self.printInfo(_("Group %s not found in the PyKota Storage.") % groupname) |
540 | | |
541 | | # Now outputs the list of nonexistent users and groups |
542 | | for name in missingusers.keys() : |
543 | | self.printInfo(_("Nonexistent user %s or missing print quota entry.") % name, level="warn") |
544 | | for name in missinggroups.keys() : |
545 | | self.printInfo(_("Nonexistent group %s or missing print quota entry.") % name, level="warn") |
546 | | |
547 | | # Now delete what has to be deleted |
548 | | for (name, entry) in todelete.items() : |
549 | | entry.delete() |
550 | | sys.stdout.write("\nDone.\n") |
| 548 | # Now outputs the list of nonexistent users and groups |
| 549 | for name in missingusers.keys() : |
| 550 | self.printInfo(_("Nonexistent user %s or missing print quota entry.") % name, level="warn") |
| 551 | for name in missinggroups.keys() : |
| 552 | self.printInfo(_("Nonexistent group %s or missing print quota entry.") % name, level="warn") |
| 553 | |
| 554 | sys.stdout.write("\nDone.\n") |