class_docstr: Class for running attacks on a dataset with specified parameters. This
  class uses the :class:`~textattack.Attack` to actually run the attacks,
  while also providing useful features such as parallel processing,
  saving/resuming from a checkpint, logging to files and stdout.
  
  Args:
      attack (:class:`~textattack.Attack`):
          :class:`~textattack.Attack` used to actually carry out the attack.
      dataset (:class:`~textattack.datasets.Dataset`):
          Dataset to attack.
      attack_args (:class:`~textattack.AttackArgs`):
          Arguments for attacking the dataset. For default settings, look at the `AttackArgs` class.
  
  Example::
  
      >>> import textattack
      >>> import transformers
  
      >>> model = transformers.AutoModelForSequenceClassification.from_pretrained("textattack/bert-base-uncased-imdb")
      >>> tokenizer = transformers.AutoTokenizer.from_pretrained("textattack/bert-base-uncased-imdb")
      >>> model_wrapper = textattack.models.wrappers.HuggingFaceModelWrapper(model, tokenizer)
  
      >>> attack = textattack.attack_recipes.TextFoolerJin2019.build(model_wrapper)
      >>> dataset = textattack.datasets.HuggingFaceDataset("imdb", split="test")
  
      >>> # Attack 20 samples with CSV logging and checkpoint saved every 5 interval
      >>> attack_args = textattack.AttackArgs(
      ...     num_examples=20,
      ...     log_to_csv="log.csv",
      ...     checkpoint_interval=5,
      ...     checkpoint_dir="checkpoints",
      ...     disable_stdout=True
      ... )
  
      >>> attacker = textattack.Attacker(attack, dataset, attack_args)
      >>> attacker.attack_dataset()
class_docstr_tok: ["Class","for","running","attacks","on","a","dataset","with","specified","parameters",".","This","class","uses","the",":","class",":","`","~textattack.Attack","`","to","actually","run","the","attacks",",","while","also","providing","useful","features","such","as","parallel","processing",",","saving\/resuming","from","a","checkpint",",","logging","to","files","and","stdout",".","Args",":","attack","(",":","class",":","`","~textattack.Attack","`",")",":",":","class",":","`","~textattack.Attack","`","used","to","actually","carry","out","the","attack",".","dataset","(",":","class",":","`","~textattack.datasets.Dataset","`",")",":","Dataset","to","attack",".","attack_args","(",":","class",":","`","~textattack.AttackArgs","`",")",":","Arguments","for","attacking","the","dataset",".","For","default","settings",",","look","at","the","`","AttackArgs","`","class",".","Example",":",":",">",">",">","import","textattack",">",">",">","import","transformers",">",">",">","model","=","transformers.AutoModelForSequenceClassification.from_pretrained","(","``","textattack\/bert-base-uncased-imdb","''",")",">",">",">","tokenizer","=","transformers.AutoTokenizer.from_pretrained","(","``","textattack\/bert-base-uncased-imdb","''",")",">",">",">","model_wrapper","=","textattack.models.wrappers.HuggingFaceModelWrapper","(","model",",","tokenizer",")",">",">",">","attack","=","textattack.attack_recipes.TextFoolerJin2019.build","(","model_wrapper",")",">",">",">","dataset","=","textattack.datasets.HuggingFaceDataset","(","``","imdb","''",",","split=","''","test","''",")",">",">",">","#","Attack","20","samples","with","CSV","logging","and","checkpoint","saved","every","5","interval",">",">",">","attack_args","=","textattack.AttackArgs","(","...","num_examples=20",",","...","log_to_csv=","''","log.csv","''",",","...","checkpoint_interval=5",",","...","checkpoint_dir=","''","checkpoints","''",",","...","disable_stdout=True","...",")",">",">",">","attacker","=","textattack.Attacker","(","attack",",","dataset",",","attack_args",")",">",">",">","attacker.attack_dataset","(",")"]
docstr: Internal method that carries out attack.
  
  No parallel processing is involved.
docstr_tok: ["Internal","method","that","carries","out","attack",".","No","parallel","processing","is","involved","."]
code: def _attack(self):
      """Internal method that carries out attack.
  
      No parallel processing is involved.
      """
      if torch.cuda.is_available():
          self.attack.cuda_()
  
      if self._checkpoint:
          num_remaining_attacks = self._checkpoint.num_remaining_attacks
          worklist = self._checkpoint.worklist
          worklist_candidates = self._checkpoint.worklist_candidates
          logger.info(
              f"Recovered from checkpoint previously saved at {self._checkpoint.datetime}."
          )
      else:
          if self.attack_args.num_successful_examples:
              num_remaining_attacks = (
                  self.attack_args.num_successful_examples
              )
              # We make `worklist` deque (linked-list) for easy pop and append.
              # Candidates are other samples we can attack if we need more samples.
              worklist, worklist_candidates = self._get_worklist(
                  self.attack_args.num_examples_offset,
                  len(self.dataset),
                  self.attack_args.num_successful_examples,
                  self.attack_args.shuffle,
              )
          else:
              num_remaining_attacks = self.attack_args.num_examples
              # We make `worklist` deque (linked-list) for easy pop and append.
              # Candidates are other samples we can attack if we need more samples.
              worklist, worklist_candidates = self._get_worklist(
                  self.attack_args.num_examples_offset,
                  len(self.dataset),
                  self.attack_args.num_examples,
                  self.attack_args.shuffle,
              )
  
      if not self.attack_args.silent:
          print(self.attack, "\n")
  
      pbar = tqdm.tqdm(
          total=num_remaining_attacks, smoothing=0, dynamic_ncols=True
      )
      if self._checkpoint:
          num_results = self._checkpoint.results_count
          num_failures = self._checkpoint.num_failed_attacks
          num_skipped = self._checkpoint.num_skipped_attacks
          num_successes = self._checkpoint.num_successful_attacks
      else:
          num_results = 0
          num_failures = 0
          num_skipped = 0
          num_successes = 0
  
      sample_exhaustion_warned = False
      while worklist:
          idx = worklist.popleft()
          try:
              example, ground_truth_output = self.dataset[idx]
          except IndexError:
              continue
          example = textattack.shared.AttackedText(example)
          if self.dataset.label_names is not None:
              example.attack_attrs[
                  "label_names"
              ] = self.dataset.label_names
          try:
              result = self.attack.attack(example, ground_truth_output)
          except Exception as e:
              raise e
          if (
              isinstance(result, SkippedAttackResult)
              and self.attack_args.attack_n
          ) or (
              not isinstance(result, SuccessfulAttackResult)
              and self.attack_args.num_successful_examples
          ):
              if worklist_candidates:
                  next_sample = worklist_candidates.popleft()
                  worklist.append(next_sample)
              else:
                  if not sample_exhaustion_warned:
                      logger.warn("Ran out of samples to attack!")
                      sample_exhaustion_warned = True
          else:
              pbar.update(1)
  
          self.attack_log_manager.log_result(result)
          if (
              not self.attack_args.disable_stdout
              and not self.attack_args.silent
          ):
              print("\n")
          num_results += 1
  
          if isinstance(result, SkippedAttackResult):
              num_skipped += 1
          if isinstance(
              result, (SuccessfulAttackResult, MaximizedAttackResult)
          ):
              num_successes += 1
          if isinstance(result, FailedAttackResult):
              num_failures += 1
          pbar.set_description(
              f"[Succeeded / Failed / Skipped / Total] {num_successes} / {num_failures} / {num_skipped} / {num_results}"
          )
  
          if (
              self.attack_args.checkpoint_interval
              and len(self.attack_log_manager.results)
              % self.attack_args.checkpoint_interval
              == 0
          ):
              new_checkpoint = textattack.shared.AttackCheckpoint(
                  self.attack_args,
                  self.attack_log_manager,
                  worklist,
                  worklist_candidates,
              )
              new_checkpoint.save()
              self.attack_log_manager.flush()
  
      pbar.close()
      print()
      # Enable summary stdout
      if (
          not self.attack_args.silent
          and self.attack_args.disable_stdout
      ):
          self.attack_log_manager.enable_stdout()
  
      if self.attack_args.enable_advance_metrics:
          self.attack_log_manager.enable_advance_metrics = True
  
      self.attack_log_manager.log_summary()
      self.attack_log_manager.flush()
      print()
  
imports: import collections
  import logging
  import multiprocessing
  import os
  import queue
  import random
  import traceback
  import torch
  import tqdm
  import textattack
  from textattack.attack_results import FailedAttackResult, MaximizedAttackResult, SkippedAttackResult, SuccessfulAttackResult
  from textattack.shared.utils import logger
  from .attack import Attack
  from .attack_args import AttackArgs
label_desc: Use image node_id 3 for calling the Attacker obj's underlying member method code with example usage: obj._attack() without return types