TSVZ 2.57__tar.gz → 2.62__tar.gz

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.
tsvz-2.62/PKG-INFO ADDED
@@ -0,0 +1,48 @@
1
+ Metadata-Version: 2.1
2
+ Name: TSVZ
3
+ Version: 2.62
4
+ Summary: An simple in memory wrapper around a TSV file to function as a database
5
+ Home-page: https://github.com/yufei-pan/TSVZ
6
+ Author: Yufei Pan
7
+ Author-email: pan@zopyr.us
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.6
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+
15
+ This lib provides some helper funtions to interact with tsv ( tab seperated values ) files.
16
+
17
+ TSVZ can also funtion like an in memory DB that is able to perform non-blocking read / write to TSV files.
18
+
19
+ Import as a lib or use console tool:
20
+
21
+ ```bash
22
+ tsvz -h
23
+ ```
24
+
25
+ ```bash
26
+ TSVZ -h
27
+ ```
28
+
29
+ ```bash
30
+ usage: TSVZ [-h] [-c HEADER] [-f] [-v] [-V] filename [{read,append,delete,clear}] [line ...]
31
+
32
+ TSVZed: A TSV file manager
33
+
34
+ positional arguments:
35
+ filename The TSV file to read
36
+ {read,append,delete,clear}
37
+ The operation to perform. Default: read
38
+ line The line to append to the TSV file. it follows as : \{key\} \{value1\} \{value2\} ... if a key without value be
39
+ inserted, the value will get deleted.
40
+
41
+ options:
42
+ -h, --help show this help message and exit
43
+ -c HEADER, --header HEADER
44
+ Perform checks with this header of the TSV file. seperate using \t
45
+ -f, --force Force the operation. Ignore checks for column numbers / headers
46
+ -v, --verbose Print verbose output
47
+ -V, --version show program's version number and exit
48
+ ```
tsvz-2.62/README.md ADDED
@@ -0,0 +1,34 @@
1
+ This lib provides some helper funtions to interact with tsv ( tab seperated values ) files.
2
+
3
+ TSVZ can also funtion like an in memory DB that is able to perform non-blocking read / write to TSV files.
4
+
5
+ Import as a lib or use console tool:
6
+
7
+ ```bash
8
+ tsvz -h
9
+ ```
10
+
11
+ ```bash
12
+ TSVZ -h
13
+ ```
14
+
15
+ ```bash
16
+ usage: TSVZ [-h] [-c HEADER] [-f] [-v] [-V] filename [{read,append,delete,clear}] [line ...]
17
+
18
+ TSVZed: A TSV file manager
19
+
20
+ positional arguments:
21
+ filename The TSV file to read
22
+ {read,append,delete,clear}
23
+ The operation to perform. Default: read
24
+ line The line to append to the TSV file. it follows as : \{key\} \{value1\} \{value2\} ... if a key without value be
25
+ inserted, the value will get deleted.
26
+
27
+ options:
28
+ -h, --help show this help message and exit
29
+ -c HEADER, --header HEADER
30
+ Perform checks with this header of the TSV file. seperate using \t
31
+ -f, --force Force the operation. Ignore checks for column numbers / headers
32
+ -v, --verbose Print verbose output
33
+ -V, --version show program's version number and exit
34
+ ```
@@ -0,0 +1,48 @@
1
+ Metadata-Version: 2.1
2
+ Name: TSVZ
3
+ Version: 2.62
4
+ Summary: An simple in memory wrapper around a TSV file to function as a database
5
+ Home-page: https://github.com/yufei-pan/TSVZ
6
+ Author: Yufei Pan
7
+ Author-email: pan@zopyr.us
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.6
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+
15
+ This lib provides some helper funtions to interact with tsv ( tab seperated values ) files.
16
+
17
+ TSVZ can also funtion like an in memory DB that is able to perform non-blocking read / write to TSV files.
18
+
19
+ Import as a lib or use console tool:
20
+
21
+ ```bash
22
+ tsvz -h
23
+ ```
24
+
25
+ ```bash
26
+ TSVZ -h
27
+ ```
28
+
29
+ ```bash
30
+ usage: TSVZ [-h] [-c HEADER] [-f] [-v] [-V] filename [{read,append,delete,clear}] [line ...]
31
+
32
+ TSVZed: A TSV file manager
33
+
34
+ positional arguments:
35
+ filename The TSV file to read
36
+ {read,append,delete,clear}
37
+ The operation to perform. Default: read
38
+ line The line to append to the TSV file. it follows as : \{key\} \{value1\} \{value2\} ... if a key without value be
39
+ inserted, the value will get deleted.
40
+
41
+ options:
42
+ -h, --help show this help message and exit
43
+ -c HEADER, --header HEADER
44
+ Perform checks with this header of the TSV file. seperate using \t
45
+ -f, --force Force the operation. Ignore checks for column numbers / headers
46
+ -v, --verbose Print verbose output
47
+ -V, --version show program's version number and exit
48
+ ```
@@ -5,4 +5,5 @@ setup.py
5
5
  TSVZ.egg-info/PKG-INFO
6
6
  TSVZ.egg-info/SOURCES.txt
7
7
  TSVZ.egg-info/dependency_links.txt
8
+ TSVZ.egg-info/entry_points.txt
8
9
  TSVZ.egg-info/top_level.txt
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ TSVZ = TSVZ:__main__
3
+ tsvz = TSVZ:__main__
@@ -10,7 +10,32 @@ if os.name == 'nt':
10
10
  elif os.name == 'posix':
11
11
  import fcntl
12
12
 
13
- version = '2.57'
13
+ version = '2.62'
14
+
15
+
16
+ def pretty_format_table(data):
17
+ if not data:
18
+ return
19
+ if type(data) == str:
20
+ data = data.strip('\n').split('\n')
21
+ elif type(data) != list:
22
+ data = list(data)
23
+ num_cols = len(data[0])
24
+ col_widths = [0] * num_cols
25
+ # Calculate the maximum width of each column
26
+ for c in range(num_cols):
27
+ col_items = [str(row[c]) for row in data]
28
+ col_widths[c] = max(len(item) for item in col_items)
29
+ # Build the row format string
30
+ row_format = ' | '.join('{{:<{}}}'.format(width) for width in col_widths)
31
+ # Print the header
32
+ header = data[0]
33
+ outTable = []
34
+ outTable.append(row_format.format(*header))
35
+ outTable.append('-+-'.join('-' * width for width in col_widths))
36
+ for row in data[1:]:
37
+ outTable.append(row_format.format(*row))
38
+ return '\n'.join(outTable) + '\n'
14
39
 
15
40
  def processLine(line,taskDic,correctColumnNum,verbose = False,teeLogger = None,strict = True):
16
41
  """
@@ -138,6 +163,53 @@ def read_last_valid_line(fileName, taskDic, correctColumnNum, verbose=False, tee
138
163
  # Return empty list if no valid line found
139
164
  return last_valid_line
140
165
 
166
+ def formatHeader(header,verbose = False,teeLogger = None):
167
+ """
168
+ Format the header string.
169
+
170
+ Parameters:
171
+ - header (str or list): The header string or list to format.
172
+ - verbose (bool, optional): Whether to print verbose output. Defaults to False.
173
+ - teeLogger (object, optional): The tee logger object for printing output. Defaults to None.
174
+
175
+ Returns:
176
+ str: The formatted header string.
177
+ """
178
+ if type(header) != str:
179
+ try:
180
+ header = '\t'.join(header)
181
+ except:
182
+ if verbose:
183
+ __teePrintOrNot('Invalid header, setting header to empty.','error',teeLogger=teeLogger)
184
+ header = ''
185
+ header = header.strip()
186
+ if header:
187
+ if not header.endswith('\n'):
188
+ header += '\n'
189
+ else:
190
+ header = ''
191
+ return header
192
+
193
+ def __teePrintOrNot(message,level = 'info',teeLogger = None):
194
+ """
195
+ Prints the given message or logs it using the provided teeLogger.
196
+
197
+ Parameters:
198
+ message (str): The message to be printed or logged.
199
+ level (str, optional): The log level. Defaults to 'info'.
200
+ teeLogger (object, optional): The logger object used for logging. Defaults to None.
201
+
202
+ Returns:
203
+ None
204
+ """
205
+ try:
206
+ if teeLogger:
207
+ teeLogger.teelog(message,level)
208
+ else:
209
+ print(message)
210
+ except Exception as e:
211
+ print(message)
212
+
141
213
  def readTSV(fileName,teeLogger = None,header = '',createIfNotExist = False, lastLineOnly = False,verifyHeader = True,verbose = False,taskDic = None,encoding = 'utf8',strict = True):
142
214
  """
143
215
  Read a TSV (Tab-Separated Values) file and return the data as a dictionary.
@@ -150,7 +222,7 @@ def readTSV(fileName,teeLogger = None,header = '',createIfNotExist = False, last
150
222
  - lastLineOnly (bool, optional): Whether to read only the last valid line of the file. Defaults to False.
151
223
  - verifyHeader (bool, optional): Whether to verify the header of the file. Defaults to True.
152
224
  - verbose (bool, optional): Whether to print verbose output. Defaults to False.
153
- - taskDic (OrderedDict, optional): The dictionary to store the data. Defaults to None.
225
+ - taskDic (OrderedDict, optional): The dictionary to store the data. Defaults to an empty OrderedDict.
154
226
  - encoding (str, optional): The encoding of the file. Defaults to 'utf8'.
155
227
  - strict (bool, optional): Whether to raise an exception if there is a data format error. Defaults to True.
156
228
 
@@ -162,11 +234,8 @@ def readTSV(fileName,teeLogger = None,header = '',createIfNotExist = False, last
162
234
 
163
235
  """
164
236
  if taskDic is None:
165
- taskDic = OrderedDict()
166
-
167
- header = header.strip() if type(header) == str else '\t'.join(header)
168
- if not header.endswith('\n'):
169
- header += '\n'
237
+ taskDic = {}
238
+ header = formatHeader(header,verbose = verbose,teeLogger = teeLogger)
170
239
  if not os.path.isfile(fileName):
171
240
  if createIfNotExist:
172
241
  with open(fileName, mode ='w',encoding=encoding)as file:
@@ -186,7 +255,8 @@ def readTSV(fileName,teeLogger = None,header = '',createIfNotExist = False, last
186
255
  #assert line.lower().replace(' ','').startswith(header.strip().lower().replace(' ','')), "Data format error!"
187
256
  if not line.lower().replace(' ','').startswith(header.strip().lower().replace(' ','')):
188
257
  __teePrintOrNot(f"Header mismatch: \n{line} \n!= \n{header.strip()}",teeLogger=teeLogger)
189
- raise Exception("Data format error! Header mismatch")
258
+ if strict:
259
+ raise Exception("Data format error! Header mismatch")
190
260
  correctColumnNum = len(header.strip().split('\t'))
191
261
  if verbose:
192
262
  __teePrintOrNot(f"correctColumnNum: {correctColumnNum}",teeLogger=teeLogger)
@@ -201,27 +271,7 @@ def readTSV(fileName,teeLogger = None,header = '',createIfNotExist = False, last
201
271
  correctColumnNum, lineCache = processLine(line,taskDic,correctColumnNum,verbose = verbose,teeLogger = teeLogger,strict = strict)
202
272
  return taskDic
203
273
 
204
- def __teePrintOrNot(message,level = 'info',teeLogger = None):
205
- """
206
- Prints the given message or logs it using the provided teeLogger.
207
-
208
- Parameters:
209
- message (str): The message to be printed or logged.
210
- level (str, optional): The log level. Defaults to 'info'.
211
- teeLogger (object, optional): The logger object used for logging. Defaults to None.
212
-
213
- Returns:
214
- None
215
- """
216
- try:
217
- if teeLogger:
218
- teeLogger.teelog(message,level)
219
- else:
220
- print(message)
221
- except Exception as e:
222
- print(message)
223
-
224
- def appendTSV(fileName,lineToAppend,teeLogger = None,header = '',createIfNotExist = False,verifyHeader = True,verbose = False,encoding = 'utf8'):
274
+ def appendTSV(fileName,lineToAppend,teeLogger = None,header = '',createIfNotExist = False,verifyHeader = True,verbose = False,encoding = 'utf8', strict = True):
225
275
  """
226
276
  Append a line of data to a TSV file.
227
277
  Parameters:
@@ -233,12 +283,12 @@ def appendTSV(fileName,lineToAppend,teeLogger = None,header = '',createIfNotExis
233
283
  - verifyHeader (bool, optional): If True, the function will verify if the existing header matches the provided header. If False, the header will not be verified.
234
284
  - verbose (bool, optional): If True, additional information will be printed during the execution.
235
285
  - encoding (str, optional): The encoding of the file.
286
+ - strict (bool, optional): If True, the function will raise an exception if there is a data format error. If False, the function will ignore the error and continue.
236
287
  Raises:
237
288
  - Exception: If the file does not exist and createIfNotExist is False.
238
289
  - Exception: If the existing header does not match the provided header.
239
290
  """
240
- if not header.endswith('\n'):
241
- header += '\n'
291
+ header = formatHeader(header,verbose = verbose,teeLogger = teeLogger)
242
292
  if not os.path.isfile(fileName):
243
293
  if createIfNotExist:
244
294
  with open(fileName, mode ='w',encoding=encoding)as file:
@@ -262,7 +312,8 @@ def appendTSV(fileName,lineToAppend,teeLogger = None,header = '',createIfNotExis
262
312
  #assert line.lower().replace(' ','').startswith(header.strip().lower().replace(' ','')), "Data format error!"
263
313
  if not line.lower().replace(' ','').startswith(header.strip().lower().replace(' ','')):
264
314
  __teePrintOrNot(f"Header mismatch: \n{line} \n!= \n{header.strip()}",teeLogger=teeLogger)
265
- raise Exception("Data format error! Header mismatch")
315
+ if strict:
316
+ raise Exception("Data format error! Header mismatch")
266
317
  correctColumnNum = len(header.strip().split('\t'))
267
318
  if verbose:
268
319
  __teePrintOrNot(f"correctColumnNum: {correctColumnNum}",teeLogger=teeLogger)
@@ -281,6 +332,39 @@ def appendTSV(fileName,lineToAppend,teeLogger = None,header = '',createIfNotExis
281
332
  if verbose:
282
333
  __teePrintOrNot(f"Appended {lineToAppend} to {fileName}",teeLogger=teeLogger)
283
334
 
335
+ def clearTSV(fileName,teeLogger = None,header = '',verifyHeader = False,verbose = False,encoding = 'utf8'):
336
+ """
337
+ Clear the contents of a TSV file. Will create if not exist.
338
+ Parameters:
339
+ - fileName (str): The path of the TSV file.
340
+ - teeLogger (optional): A logger object for logging messages.
341
+ - header (str, optional): The header line to verify against. If provided, the function will check if the existing header matches the provided header.
342
+ - verifyHeader (bool, optional): If True, the function will verify if the existing header matches the provided header. If False, the header will not be verified.
343
+ - verbose (bool, optional): If True, additional information will be printed during the execution.
344
+ - encoding (str, optional): The encoding of the file.
345
+ """
346
+ header = formatHeader(header,verbose = verbose,teeLogger = teeLogger)
347
+ if not os.path.isfile(fileName):
348
+ with open(fileName, mode ='w',encoding=encoding)as file:
349
+ file.write(header)
350
+ else:
351
+ with open(fileName, mode ='r+',encoding=encoding)as file:
352
+ if header.strip() and verifyHeader:
353
+ line = file.readline().strip()
354
+ if verbose:
355
+ __teePrintOrNot(f"Header: {header.strip()}",teeLogger=teeLogger)
356
+ __teePrintOrNot(f"First line: {line}",teeLogger=teeLogger)
357
+ #assert line.lower().replace(' ','').startswith(header.strip().lower().replace(' ','')), "Data format error!"
358
+ if not line.lower().replace(' ','').startswith(header.strip().lower().replace(' ','')):
359
+ __teePrintOrNot(f"Header mismatch: \n{line} \n!= \n{header.strip()}",teeLogger=teeLogger)
360
+ raise Exception("Data format error! Header mismatch")
361
+ # if the header is correct, only keep the header
362
+ file.truncate()
363
+ else:
364
+ file.write(header)
365
+ if verbose:
366
+ __teePrintOrNot(f"Cleared {fileName}",teeLogger=teeLogger)
367
+
284
368
  # create a tsv class that functions like a ordered dictionary but will update the file when modified
285
369
  class TSVZed(OrderedDict):
286
370
  def __teePrintOrNot(self,message,level = 'info'):
@@ -297,7 +381,7 @@ class TSVZed(OrderedDict):
297
381
  self.version = version
298
382
  self._fileName = fileName
299
383
  self.teeLogger = teeLogger
300
- self.header = header.strip() if type(header) == str else '\t'.join(header)
384
+ self.header = formatHeader(header,verbose = verbose,teeLogger = self.teeLogger)
301
385
  self.correctColumnNum = -1
302
386
  self.createIfNotExist = createIfNotExist
303
387
  self.verifyHeader = verifyHeader
@@ -667,3 +751,42 @@ memoryOnly:{self.memoryOnly}
667
751
  raise e # Re-raise the exception for external handling
668
752
  finally:
669
753
  self.writeLock.release() # Ensure the thread lock is always released
754
+
755
+
756
+ def __main__():
757
+ import argparse
758
+ parser = argparse.ArgumentParser(description='TSVZed: A TSV file manager')
759
+ parser.add_argument('filename', type=str, help='The TSV file to read')
760
+ parser.add_argument('operation', type=str,nargs='?', choices=['read','append','delete','clear'], help='The operation to perform. Default: read', default='read')
761
+ parser.add_argument('line', type=str, nargs='*', help='The line to append to the TSV file. it follows as : \{key\} \{value1\} \{value2\} ... if a key without value be inserted, the value will get deleted.')
762
+ parser.add_argument('-c', '--header', type=str, help='Perform checks with this header of the TSV file. seperate using \\t')
763
+ parser.add_argument('-f', '--force', action='store_true', help='Force the operation. Ignore checks for column numbers / headers')
764
+ parser.add_argument('-v', '--verbose', action='store_true', help='Print verbose output')
765
+ parser.add_argument('-V', '--version', action='version', version=f'%(prog)s {version} by {author}')
766
+ args = parser.parse_args()
767
+
768
+ header = args.header.replace('\\t','\t') if args.header else ''
769
+
770
+ if args.operation == 'read':
771
+ # check if the file exist
772
+ if not os.path.isfile(args.filename):
773
+ print(f"File not found: {args.filename}")
774
+ return
775
+ # read the file
776
+ data = readTSV(args.filename, verifyHeader = False, verbose=args.verbose,strict= not args.force)
777
+ print(pretty_format_table(data.values()))
778
+ elif args.operation == 'append':
779
+ appendTSV(args.filename, args.line,createIfNotExist = True, header=header, verbose=args.verbose, strict= not args.force)
780
+ elif args.operation == 'delete':
781
+ appendTSV(args.filename, args.line[:1],createIfNotExist = True, header=header, verbose=args.verbose, strict= not args.force)
782
+ elif args.operation == 'clear':
783
+ clearTSV(args.filename, header=header, verbose=args.verbose, verifyHeader=not args.force)
784
+ else:
785
+ print("Invalid operation")
786
+ return
787
+
788
+ if __name__ == '__main__':
789
+ __main__()
790
+
791
+
792
+
@@ -2,12 +2,18 @@ from setuptools import setup
2
2
 
3
3
  setup(
4
4
  name='TSVZ',
5
- version='2.57',
5
+ version='2.62',
6
6
  py_modules=['TSVZ'], # List of module names (without .py)
7
7
  description='An simple in memory wrapper around a TSV file to function as a database',
8
8
  author='Yufei Pan',
9
9
  author_email='pan@zopyr.us',
10
10
  url='https://github.com/yufei-pan/TSVZ', # URL to the project’s homepage
11
+ entry_points={
12
+ 'console_scripts': [
13
+ 'TSVZ = TSVZ:__main__',
14
+ 'tsvz = TSVZ:__main__',
15
+ ],
16
+ },
11
17
  classifiers=[
12
18
  'Programming Language :: Python :: 3',
13
19
  'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)',
tsvz-2.57/PKG-INFO DELETED
@@ -1,17 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: TSVZ
3
- Version: 2.57
4
- Summary: An simple in memory wrapper around a TSV file to function as a database
5
- Home-page: https://github.com/yufei-pan/TSVZ
6
- Author: Yufei Pan
7
- Author-email: pan@zopyr.us
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
10
- Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.6
12
- Description-Content-Type: text/markdown
13
- License-File: LICENSE
14
-
15
- This lib provides some helper funtions to interact with tsv ( tab seperated values ) files.
16
-
17
- TSVZ can also funtion like an in memory DB that is able to perform non-blocking read / write to TSV files.
tsvz-2.57/README.md DELETED
@@ -1,3 +0,0 @@
1
- This lib provides some helper funtions to interact with tsv ( tab seperated values ) files.
2
-
3
- TSVZ can also funtion like an in memory DB that is able to perform non-blocking read / write to TSV files.
@@ -1,17 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: TSVZ
3
- Version: 2.57
4
- Summary: An simple in memory wrapper around a TSV file to function as a database
5
- Home-page: https://github.com/yufei-pan/TSVZ
6
- Author: Yufei Pan
7
- Author-email: pan@zopyr.us
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
10
- Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.6
12
- Description-Content-Type: text/markdown
13
- License-File: LICENSE
14
-
15
- This lib provides some helper funtions to interact with tsv ( tab seperated values ) files.
16
-
17
- TSVZ can also funtion like an in memory DB that is able to perform non-blocking read / write to TSV files.
File without changes
File without changes
File without changes