Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pandas/io/sas/sasreader.py: 45%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

51 statements  

1""" 

2Read SAS sas7bdat or xport files. 

3""" 

4 

5from __future__ import annotations 

6 

7from abc import ( 

8 ABC, 

9 abstractmethod, 

10) 

11from collections.abc import Iterator 

12from typing import ( 

13 TYPE_CHECKING, 

14 Self, 

15 overload, 

16) 

17 

18from pandas._libs import lib 

19from pandas.util._decorators import set_module 

20 

21from pandas.io.common import stringify_path 

22 

23if TYPE_CHECKING: 

24 from collections.abc import Hashable 

25 from types import TracebackType 

26 

27 from pandas._typing import ( 

28 CompressionOptions, 

29 FilePath, 

30 ReadBuffer, 

31 ) 

32 

33 from pandas import DataFrame 

34 

35 

36@set_module("pandas.api.typing") 

37class SASReader(Iterator["DataFrame"], ABC): 

38 """ 

39 Abstract class for XportReader and SAS7BDATReader. 

40 """ 

41 

42 @abstractmethod 

43 def read(self, nrows: int | None = None) -> DataFrame: ... 

44 

45 @abstractmethod 

46 def close(self) -> None: ... 

47 

48 def __enter__(self) -> Self: 

49 return self 

50 

51 def __exit__( 

52 self, 

53 exc_type: type[BaseException] | None, 

54 exc_value: BaseException | None, 

55 traceback: TracebackType | None, 

56 ) -> None: 

57 self.close() 

58 

59 

60@overload 

61def read_sas( 

62 filepath_or_buffer: FilePath | ReadBuffer[bytes], 

63 *, 

64 format: str | None = ..., 

65 index: Hashable | None = ..., 

66 encoding: str | lib.NoDefault | None = ..., 

67 chunksize: int = ..., 

68 iterator: bool = ..., 

69 compression: CompressionOptions = ..., 

70) -> SASReader: ... 

71 

72 

73@overload 

74def read_sas( 

75 filepath_or_buffer: FilePath | ReadBuffer[bytes], 

76 *, 

77 format: str | None = ..., 

78 index: Hashable | None = ..., 

79 encoding: str | lib.NoDefault | None = ..., 

80 chunksize: None = ..., 

81 iterator: bool = ..., 

82 compression: CompressionOptions = ..., 

83) -> DataFrame | SASReader: ... 

84 

85 

86@set_module("pandas") 

87def read_sas( 

88 filepath_or_buffer: FilePath | ReadBuffer[bytes], 

89 *, 

90 format: str | None = None, 

91 index: Hashable | None = None, 

92 encoding: str | lib.NoDefault | None = lib.no_default, 

93 chunksize: int | None = None, 

94 iterator: bool = False, 

95 compression: CompressionOptions = "infer", 

96) -> DataFrame | SASReader: 

97 """ 

98 Read SAS files stored as either XPORT or SAS7BDAT format files. 

99 

100 The file format is inferred from the file extension if not explicitly 

101 specified. Supports both full reads and chunked iteration. 

102 

103 Parameters 

104 ---------- 

105 filepath_or_buffer : str, path object, or file-like object 

106 String, path object (implementing ``os.PathLike[str]``), or file-like 

107 object implementing a binary ``read()`` function. The string could be 

108 a URL. Valid URL schemes include http, ftp, s3, and file. For file 

109 URLs, a host is expected. A local file could be: 

110 ``file://localhost/path/to/table.sas7bdat``. 

111 

112 Certain URL schemes may require additional packages. For example, S3 

113 URLs require the ``s3fs`` library. See 

114 :ref:`install.optional_dependencies` for a full list. 

115 format : str {'xport', 'sas7bdat'} or None 

116 If None, file format is inferred from file extension. If 'xport' or 

117 'sas7bdat', uses the corresponding format. 

118 index : identifier of index column, defaults to None 

119 Identifier of column that should be used as index of the DataFrame. 

120 encoding : str, 'infer' or None, default is None 

121 Encoding for text data. If None, text data are stored as raw bytes. 

122 ``'infer'`` decodes SAS7BDAT files using the encoding recorded in the 

123 file header, falling back to latin-1 if the header does not name one 

124 pandas recognizes; XPORT files record no encoding, so ``'infer'`` 

125 means ISO-8859-1 there. 

126 

127 .. deprecated:: 3.1.0 

128 The default will change from ``None`` to ``'infer'``, so text data 

129 will be decoded rather than returned as bytes. Pass ``None`` 

130 explicitly to keep the current behavior. 

131 chunksize : int 

132 Read file `chunksize` lines at a time, returns iterator. 

133 iterator : bool, defaults to False 

134 If True, returns an iterator for reading the file incrementally. 

135 compression : str or dict, default 'infer' 

136 For on-the-fly decompression of on-disk data. If 'infer' and 

137 'filepath_or_buffer' is path-like, then detect compression from the 

138 following extensions: '.gz', '.bz2', '.zip', '.xz', '.zst', '.tar', 

139 '.tar.gz', '.tar.xz' or '.tar.bz2' (otherwise no compression). 

140 Set to ``None`` for no decompression. 

141 Can also be a dict with key ``'method'`` set to one of {``'zip'``, 

142 ``'gzip'``, ``'bz2'``, ``'zstd'``, ``'xz'``, ``'tar'``} and other 

143 key-value pairs are forwarded to ``zipfile.ZipFile``, 

144 ``gzip.GzipFile``, ``bz2.BZ2File``, ``zstandard.ZstdCompressor``, 

145 ``lzma.LZMAFile`` or ``tarfile.TarFile``, respectively. 

146 As an example, the following could be passed for faster compression 

147 and to create a reproducible gzip archive: 

148 ``compression={'method': 'gzip', 'compresslevel': 1, 'mtime': 1}``. 

149 

150 Returns 

151 ------- 

152 DataFrame, SAS7BDATReader, or XportReader 

153 DataFrame if iterator=False and chunksize=None, else SAS7BDATReader 

154 or XportReader, file format is inferred from file extension. 

155 

156 See Also 

157 -------- 

158 read_csv : Read a comma-separated values (csv) file into a DataFrame. 

159 read_excel : Read an Excel file into a pandas DataFrame. 

160 read_spss : Read an SPSS file into a pandas DataFrame. 

161 read_orc : Load an ORC object into a pandas DataFrame. 

162 read_feather : Load a feather-format object into a pandas DataFrame. 

163 

164 Examples 

165 -------- 

166 >>> df = pd.read_sas("sas_data.sas7bdat") # doctest: +SKIP 

167 """ 

168 if format is None: 

169 buffer_error_msg = ( 

170 "If this is a buffer object rather " 

171 "than a string name, you must specify a format string" 

172 ) 

173 filepath_or_buffer = stringify_path(filepath_or_buffer) 

174 if not isinstance(filepath_or_buffer, str): 

175 raise ValueError(buffer_error_msg) 

176 fname = filepath_or_buffer.lower() 

177 if ".xpt" in fname: 

178 format = "xport" 

179 elif ".sas7bdat" in fname: 

180 format = "sas7bdat" 

181 else: 

182 raise ValueError( 

183 f"unable to infer format of SAS file from filename: {fname!r}" 

184 ) 

185 

186 reader: SASReader 

187 if format.lower() == "xport": 

188 from pandas.io.sas.sas_xport import XportReader 

189 

190 reader = XportReader( 

191 filepath_or_buffer, 

192 index=index, 

193 encoding=encoding, 

194 chunksize=chunksize, 

195 compression=compression, 

196 ) 

197 elif format.lower() == "sas7bdat": 

198 from pandas.io.sas.sas7bdat import SAS7BDATReader 

199 

200 reader = SAS7BDATReader( 

201 filepath_or_buffer, 

202 index=index, 

203 encoding=encoding, 

204 chunksize=chunksize, 

205 compression=compression, 

206 ) 

207 else: 

208 raise ValueError("unknown SAS format") 

209 

210 if iterator or chunksize: 

211 return reader 

212 

213 with reader: 

214 return reader.read()