HTSeq 2.1.2__cp313-cp313-macosx_10_15_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
HTSeq/utils.py ADDED
@@ -0,0 +1,92 @@
1
+ import os
2
+ import gzip
3
+
4
+
5
+ class FileOrSequence:
6
+ """The construcutor takes one argument, which may either be a string,
7
+ which is interpreted as a file name (possibly with path), or a
8
+ connection, by which we mean a text file opened for reading, or
9
+ any other object that can provide an iterator over strings
10
+ (lines of the file).
11
+
12
+ The advantage of passing a file name instead of an already opened file
13
+ is that if an iterator is requested several times, the file will be
14
+ re-opened each time. If the file is already open, its lines can be read
15
+ only once, and then, the iterator stays exhausted.
16
+
17
+ Furthermore, if a file name is passed that end in ".gz" or ".gzip"
18
+ (case insensitive), it is transparently gunzipped.
19
+ """
20
+
21
+ def __init__(self, filename_or_sequence):
22
+ self.fos = filename_or_sequence
23
+ self.should_close = False
24
+ self.line_no = None
25
+ self.lines = None
26
+
27
+ try:
28
+ os.fspath(self.fos)
29
+ self.fos_is_path = True
30
+ except TypeError:
31
+ # assumed to be a file handle
32
+ self.fos_is_path = False
33
+
34
+ def __enter__(self):
35
+ if self.fos_is_path:
36
+ fos = os.fspath(self.fos)
37
+ self.should_close = True
38
+ if fos.lower().endswith((".gz", ".gzip")):
39
+ lines = gzip.open(self.fos, "rt")
40
+ else:
41
+ lines = open(self.fos)
42
+ else:
43
+ lines = self.fos
44
+
45
+ self.lines = lines
46
+ return self
47
+
48
+ def __exit__(self, type, value, traceback):
49
+ if self.should_close:
50
+ self.lines.close()
51
+ self.lines = None
52
+
53
+ def __iter__(self):
54
+ self.line_no = 1
55
+ if self.lines is None:
56
+ call_exit = True
57
+ self.__enter__()
58
+ else:
59
+ call_exit = False
60
+ lines = self.lines
61
+
62
+ try:
63
+ for line in lines:
64
+ yield line
65
+ self.line_no += 1
66
+ finally:
67
+ if call_exit:
68
+ self.__exit__(None, None, None)
69
+ self.line_no = None
70
+
71
+ def __repr__(self):
72
+ if isinstance(self.fos, str):
73
+ return "<%s object, connected to file name '%s'>" % (
74
+ self.__class__.__name__,
75
+ self.fos,
76
+ )
77
+ else:
78
+ return "<%s object, connected to %s >" % (
79
+ self.__class__.__name__,
80
+ repr(self.fos),
81
+ )
82
+
83
+ def get_line_number_string(self):
84
+ if self.line_no is None:
85
+ if isinstance(self.fos, str):
86
+ return "file %s closed" % self.fos
87
+ else:
88
+ return "file closed"
89
+ if isinstance(self.fos, str):
90
+ return "line %d of file %s" % (self.line_no, self.fos)
91
+ else:
92
+ return "line %d" % self.line_no