class_docstr: A training job represents a Sagemaker training job within an experiment.
class_docstr_tok: ["A","training","job","represents","a","Sagemaker","training","job","within","an","experiment","."]
docstr: Pulls the training job's logs such that subsequent accesses to the
  `logs` property are noops.
code: def pull_logs(self) -> list[str]:
      """
      Pulls the training job's logs such that subsequent accesses to the
      `logs` property are noops.
      """
      # Check if the logs are already available locally
      log_file = self._cache_dir() / "logs.txt"
      if log_file.exists():
          with log_file.open("r") as f:
              return f.read().split("\n")
  
      # If not, fetch them
      client = default_session().client("logs")
      streams = client.describe_log_streams(
          logGroupName="/aws/sagemaker/TrainingJobs",
          logStreamNamePrefix=self.info["TrainingJobName"],
      )
      res = []
      for stream in streams["logStreams"]:
          params = {
              "logGroupName": "/aws/sagemaker/TrainingJobs",
              "logStreamName": stream["logStreamName"],
              "startFromHead": True,
          }
          result = client.get_log_events(**params)
          res.extend([event["message"] for event in result["events"]])
          while "nextForwardToken" in result:
              next_token = result["nextForwardToken"]
              result = client.get_log_events(
                  nextToken=next_token, **params
              )
              if result["nextForwardToken"] == next_token:
                  # The same token as before indicates end of stream, see
                  # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/logs.html#CloudWatchLogs.Client.get_log_events
                  break
              res.extend(
                  [event["message"] for event in result["events"]]
              )
  
      # Store them
      log_file.parent.mkdir(parents=True, exist_ok=True)
      with log_file.open("w") as f:
          f.write("\n".join(res))
  
      # And return them
      return res
  
imports: from __future__ import annotations
  import datetime
  import json
  import logging
  import re
  import shutil
  import tempfile
  import time
  from collections import Counter
  from functools import cached_property, lru_cache
  from pathlib import Path
  from typing import Any, Callable, cast, Dict, Iterator, List, Tuple, Union
  import boto3
  import numpy
  from botocore.exceptions import ClientError
  from .session import default_session
label_desc: Use image node_id 6 for calling the TrainingJob obj's underlying member method code with example usage: obj.pull_logs() and returns: res, f