Skip to content

Commit 541d875

Browse files
committed
added multiple line reading
1 parent 1d28207 commit 541d875

File tree

4 files changed

+49
-14
lines changed

4 files changed

+49
-14
lines changed

README.rst

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,35 @@ Usage
1515
| Usage is very straightforward, and standard csv line endings (newline character), value delimiter (comma), and
1616
quotation character (double quote) are the defaults. These can be changed in the constructor.
1717
|
18+
| The ``get_line()`` and ``get_line_dicts()`` methods return a list of rows.
1819
| Plain text file example:
1920
2021
::
2122

2223
reader = RandomAccessReader('~/myfile.txt')
23-
line = reader.get_line(2)
24+
25+
# single line
26+
line = reader.get_lines(2)[0]
2427
print line
2528

29+
# multiple lines
30+
lines = reader.get_lines(3, 3)
31+
for l in lines:
32+
print l
33+
2634
| Csv example:
2735
2836
::
2937

3038
reader = CsvRandomAccessReader('~/myfile.csv')
31-
line = reader.get_line_dict(5)
39+
40+
# single line
41+
line = reader.get_line_dicts(5)[0]
3242
for x in line:
3343
print x + " = " line[x]
44+
45+
# multiple lines
46+
lines = reader.get_line_dicts(6, 6)
47+
for l in lines:
48+
for x in l:
49+
print x + " = " l[x]

randomAccessReader/__init__.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ def __init__(self, filepath, endline_character='\n'):
3232
def number_of_lines(self):
3333
return len(self._lines)
3434

35+
def get_line_indexes(self):
36+
return range(len(self._lines))
37+
3538
def _get_line_data(self):
3639
f = open(self._filepath)
3740
lines = []
@@ -54,16 +57,20 @@ def _get_line_data(self):
5457
f.close()
5558
return lines
5659

57-
def get_line(self, line_number):
60+
def get_lines(self, line_number, amount=1):
5861
"""
5962
get the contents of a given line in the file
6063
:param line_number: 0-indexed line number
64+
:param amount amount of lines to read
6165
:return: str
6266
"""
67+
lines = []
6368
with open(self._filepath) as f:
64-
line_data = self._lines[line_number]
65-
f.seek(line_data['position'])
66-
return f.read(line_data['length'])
69+
for x in xrange(amount):
70+
line_data = self._lines[line_number]
71+
f.seek(line_data['position'])
72+
lines.append(f.read(line_data['length']))
73+
return lines
6774

6875

6976
class CsvRandomAccessReader(RandomAccessReader):
@@ -76,7 +83,7 @@ def __init__(self, filepath, has_header=True, endline_character='\n', values_del
7683
self._has_header = has_header
7784
if has_header:
7885
reader = RandomAccessReader(filepath, endline_character)
79-
self._headers = self._get_line_values(reader.get_line(0))
86+
self._headers = self._get_line_values(reader.get_lines(0)[0])
8087

8188
def set_headers(self, header_list):
8289
if not hasattr(header_list, '__iter__'):
@@ -94,17 +101,22 @@ def _get_line_values(self, line):
94101
r = csv.reader(b, dialect)
95102
return tuple(r.next())
96103

97-
def get_line_dict(self, line_number):
104+
def get_line_dicts(self, line_number, amount=1):
98105
"""
99106
gets the requested line as a dictionary (header values are the keys)
100107
:param line_number: requested line number, 0-indexed (disregards the header line if present)
108+
:param amount
101109
:return: dict
102110
"""
103111
if not self._headers:
104112
raise ValueError("Headers must be set before requesting a line dictionary")
105113
if self._has_header:
106114
line_number += 1
107-
return dict(zip(self._headers, self._get_line_values(self.get_line(line_number))))
115+
lines = []
116+
text_lines = self.get_lines(line_number, amount)
117+
for x in xrange(amount):
118+
lines.append(dict(zip(self._headers, self._get_line_values(text_lines[x]))))
119+
return lines
108120

109121
class MyDialect(csv.Dialect):
110122
strict = True

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# Versions should comply with PEP440. For a discussion on single-sourcing
1616
# the version across setup.py and the project code, see
1717
# https://packaging.python.org/en/latest/single_source_version.html
18-
version='0.1.1',
18+
version='0.2.0',
1919

2020
description='A python random access file reader',
2121
long_description=long_description,

tests/tests.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,26 @@ class ReaderTest(unittest.TestCase):
88
def test_text_file(self):
99
path = os.path.dirname(os.path.abspath(__file__)) + "/test_file.csv"
1010
reader = RandomAccessReader(path)
11-
line = reader.get_line(5)
12-
self.assertTrue('Learn Tons of Blogging Tips &Tricks' in line)
11+
line = reader.get_lines(5)
12+
self.assertTrue('Learn Tons of Blogging Tips &Tricks' in line[0])
1313

1414
def test_line_count(self):
1515
path = os.path.dirname(os.path.abspath(__file__)) + "/test_file.csv"
1616
reader = RandomAccessReader(path)
1717
self.assertTrue(reader.number_of_lines == 34)
1818

19+
def test_multi_lines(self):
20+
path = os.path.dirname(os.path.abspath(__file__)) + "/test_file.csv"
21+
reader = RandomAccessReader(path)
22+
lines = reader.get_lines(3, 3)
23+
self.assertTrue(len(lines) == 3)
24+
self.assertTrue('Learn Tons of Blogging Tips &Tricks' in lines[-1])
25+
1926

2027
class CsvReaderTest(unittest.TestCase):
2128

2229
def test_csv(self):
2330
path = os.path.dirname(os.path.abspath(__file__)) + "/test_file.csv"
2431
reader = CsvRandomAccessReader(path)
25-
line = reader.get_line_dict(5)
26-
self.assertTrue(line["Description line 1"] == "A Simple, Easy-to-Follow Guide")
32+
line = reader.get_line_dicts(5)
33+
self.assertTrue(line[0]["Description line 1"] == "A Simple, Easy-to-Follow Guide")

0 commit comments

Comments
 (0)