          if found != 3:
              retval = "No global version found"
              if self._is_conda:
                  retval += ". Check Conda packages for Conda cuDNN"
              return retval
          return "{}.{}.{}".format(major, minor, patchlevel)
  
      @staticmethod
      def _cudnn_checkfiles_linux():
          """ Obtain the location of the files to check for cuDNN location in Linux.
  
          Returns
          str:
              The location of the header files for cuDNN
          """
          chk = os.popen("ldconfig -p | grep -P \"libcudnn.so.\\d+\" | head -n 1").read()
          if "libcudnn.so." not in chk:
              return list()
          chk = chk.strip().replace("libcudnn.so.", "")
          cudnn_vers = chk[0]
          cudnn_path = chk[chk.find("=>") + 3:chk.find("libcudnn") - 1]
          cudnn_path = cudnn_path.replace("lib", "include")
          cudnn_checkfiles = [os.path.join(cudnn_path, "cudnn_v{}.h".format(cudnn_vers)),
                              os.path.join(cudnn_path, "cudnn.h")]
          return cudnn_checkfiles
  
      def _cudnn_checkfiles_windows(self):
          """ Obtain the location of the files to check for cuDNN location in Windows.
  
          Returns
          str:
              The location of the header files for cuDNN
          """
          # TODO A more reliable way of getting the windows location
          if not self._cuda_path and not self._cuda_keys_windows:
              return list()
          if not self._cuda_path:
              self._cuda_path = os.environ[self._cuda_keys_windows[0]]
  
          cudnn_checkfile = os.path.join(self._cuda_path, "include", "cudnn.h")
          return [cudnn_checkfile]
  
      def _get_cuda_path(self):
          """ Obtain the path to Cuda install location.
  
          Returns
          -------
          str
              The path to the install location of Cuda on the system
          """
          if self._is_linux:
              path = self._cuda_path_linux()
          elif self._is_windows:
              path = self._cuda_path_windows()
          else:
              path = None
          return path
  
      @staticmethod
      def _cuda_path_linux():
          """ Obtain the path to Cuda install location on Linux.
  
          Returns
          -------
          str
              The path to the install location of Cuda on a Linux system
          """
          ld_library_path = os.environ.get("LD_LIBRARY_PATH", None)
          chk = os.popen("ldconfig -p | grep -P \"libcudart.so.\\d+.\\d+\" | head -n 1").read()
          if ld_library_path and not chk:
              paths = ld_library_path.split(":")
              for path in paths:
                  chk = os.popen("ls {} | grep -P -o \"libcudart.so.\\d+.\\d+\" | "
                                 "head -n 1".format(path)).read()
                  if chk:
                      break
          if not chk:
              return None
          return chk[chk.find("=>") + 3:chk.find("targets") - 1]
  
      @staticmethod
      def _cuda_path_windows():
          """ Obtain the path to Cuda install location on Windows.
  
          Returns
          -------
          str
              The path to the install location of Cuda on a Windows system
          """
          cuda_path = os.environ.get("CUDA_PATH", None)
          return cuda_path
  
      def _cuda_version_linux(self):
          """ Obtain the installed version of Cuda on a Linux system.
  
          Returns
          -------
          The installed CUDA version on a Linux system
          """
          ld_library_path = os.environ.get("LD_LIBRARY_PATH", None)
          chk = os.popen("ldconfig -p | grep -P \"libcudart.so.\\d+.\\d+\" | head -n 1").read()
          if ld_library_path and not chk:
              paths = ld_library_path.split(":")
              for path in paths:
                  chk = os.popen("ls {} | grep -P -o \"libcudart.so.\\d+.\\d+\" | "
                                 "head -n 1".format(path)).read()
                  if chk:
                      break
          if not chk:
              retval = "No global version found"
              if self._is_conda:
                  retval += ". Check Conda packages for Conda Cuda"
              return retval
          cudavers = chk.strip().replace("libcudart.so.", "")
          return cudavers[:cudavers.find(" ")]
  
      def _cuda_version_windows(self):
          """ Obtain the installed version of Cuda on a Windows system.
  
          Returns
          -------
          The installed CUDA version on a Windows system
          """
          cuda_keys = self._cuda_keys_windows
          if not cuda_keys:
              retval = "No global version found"
              if self._is_conda:
                  retval += ". Check Conda packages for Conda Cuda"
              return retval
          cudavers = [key.lower().replace("cuda_path_v", "").replace("_", ".") for key in cuda_keys]
          return " ".join(cudavers)
  
      def full_info(self):
          """ Obtain extensive system information stats, formatted into a human readable format.
  
          Returns
 
</s> remove         if self.env.ld_library_path and not chk:
            paths = self.env.ld_library_path.split(":")
            for path in paths:
                chk = os.popen("ls {} | grep -P -o \"libcudart.so.\\d+.\\d+\" | "
                               "head -n 1".format(path)).read()
 </s> add         if not chk and os.environ.get("LD_LIBRARY_PATH"):
            for path in os.environ["LD_LIBRARY_PATH"].split(":"):
                chk = os.popen(f"ls {path} | grep -P -o \"libcudart.so.\\d+.\\d+\" | "
                               "head -n 1").read() </s> remove     @staticmethod
    def cudnn_checkfiles_linux():
        """ Return the check-file locations for Linux """
 </s> add         Returns
        -------
        list
            List of header file locations to scan for cuDNN versions
        """ </s> remove             version = re.search(r".*release (?P<cuda>\d+\.\d+)", stdout.decode(self.env.encoding))
            self.env.cuda_version = version.groupdict().get("cuda", None)
            if self.env.cuda_version:
                self.output.info("CUDA version: " + self.env.cuda_version)
                return
        # Failed to load nvcc
        if self.env.os_version[0] == "Linux":
            self.cuda_check_linux()
        elif self.env.os_version[0] == "Windows":
            self.cuda_check_windows()

    def cuda_check_linux(self):
        """ Check Linux CUDA Version """
 </s> add             version = re.search(r".*release (?P<cuda>\d+\.\d+)",
                                stdout.decode(locale.getpreferredencoding()))
            self.cuda_version = version.groupdict().get("cuda", None)
            locate = "where" if self._os == "windows" else "which"
            path = os.popen(f"{locate} nvcc").read()
            if path:
                path = path.split("\n")[0]  # Split multiple entries and take first found
                while True:  # Get Cuda root folder
                    path, split = os.path.split(path)
                    if split == "bin":
                        break
                self.cuda_path = path
            return

        # Failed to load nvcc, manual check
        getattr(self, f"_cuda_check_{self._os}")()

    def _cuda_check_linux(self):
        """ For Linux check the dynamic link loader for libcudart. If not found with ldconfig then
        attempt to find it in LD_LIBRARY_PATH. """ </s> remove         if self._is_linux:
            cudnn_checkfiles = self._cudnn_checkfiles_linux()
        elif self._is_windows:
            cudnn_checkfiles = self._cudnn_checkfiles_windows()
        else:
            retval = "Unsupported OS"
            if self._is_conda:
                retval += ". Check Conda packages for Conda cuDNN"
            return retval

        cudnn_checkfile = None
        for checkfile in cudnn_checkfiles:
            if os.path.isfile(checkfile):
                cudnn_checkfile = checkfile
                break

        if not cudnn_checkfile:
            retval = "No global version found"
            if self._is_conda:
                retval += ". Check Conda packages for Conda cuDNN"
            return retval

        found = 0
        with open(cudnn_checkfile, "r") as ofile:
            for line in ofile:
                if line.lower().startswith("#define cudnn_major"):
                    major = line[line.rfind(" ") + 1:].strip()
                    found += 1
                elif line.lower().startswith("#define cudnn_minor"):
                    minor = line[line.rfind(" ") + 1:].strip()
                    found += 1
                elif line.lower().startswith("#define cudnn_patchlevel"):
                    patchlevel = line[line.rfind(" ") + 1:].strip()
                    found += 1
                if found == 3:
                    break
        if found != 3:
 </s> add         retval = self._cuda_check.cudnn_version
        if not retval: </s> remove     def cuda_check(self):
        """ Check Cuda for Linux or Windows """
 </s> add class CudaCheck():  # pylint:disable=too-few-public-methods
    """ Find the location of system installed Cuda and cuDNN on Windows and Linux. """

    def __init__(self):
        self.cuda_path = None
        self.cuda_version = None
        self.cudnn_version = None

        self._os = platform.system().lower()
        self._cuda_keys = [key for key in os.environ if key.lower().startswith("cuda_path_v")]
        self._cudnn_header_files = ["cudnn_version.h", "cudnn.h"]

        if self._os in ("windows", "linux"):
            self._cuda_check()
            self._cudnn_check()

    def _cuda_check(self):
        """ Obtain the location and version of Cuda and populate :attr:`cuda_version` and
        :attr:`cuda_path`

        Initially just calls `nvcc -V` to get the installed version of Cuda currently in use.
        If this fails, drills down to more OS specific checking methods.
        """
        return retval
          if found != 3:
              retval = "No global version found"
              if self._is_conda:
                  retval += ". Check Conda packages for Conda cuDNN"
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
        return retval
  
      def full_info(self):
          """ Obtain extensive system information stats, formatted into a human readable format.
  
          Returns
keep keep keep keep replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace keep keep keep keep keep
 sysinfo/setup - Standardize cuda/cudnn checks 
lib/sysinfo.py