kindle manager
This commit is contained in:
@@ -75,6 +75,7 @@ b['1']['2'] = {'3':1} # OK
|
|||||||
|
|
||||||
# feature plan
|
# feature plan
|
||||||
## 20200528
|
## 20200528
|
||||||
- first abstract from kindle hard / local directory for different OS
|
- first abstract from kindle hard / local directory for different OS **done**
|
||||||
- add GUI use QT **done**
|
- add GUI use QT **done**
|
||||||
|
- new thread to check kindle connection status
|
||||||
|
|
||||||
|
|||||||
2
cui
2
cui
@@ -1,2 +1,2 @@
|
|||||||
pyuic mainwindow.ui -o mainwindow.py
|
pyuic mainwindow.ui -o mainwindow.py --no-protection
|
||||||
pyside2-rcc -binary kmanapp.qrc -o kmanapp_rc.py
|
pyside2-rcc -binary kmanapp.qrc -o kmanapp_rc.py
|
||||||
|
|||||||
128
kman.py
128
kman.py
@@ -8,7 +8,9 @@
|
|||||||
#########################################################
|
#########################################################
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import os
|
||||||
import json
|
import json
|
||||||
|
import time
|
||||||
import logging
|
import logging
|
||||||
import platform
|
import platform
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
@@ -107,7 +109,28 @@ r'''
|
|||||||
(\d{1,2}:\d{1,2}:\d{1,2}) #group6 - time
|
(\d{1,2}:\d{1,2}:\d{1,2}) #group6 - time
|
||||||
''', flags=re.X )
|
''', flags=re.X )
|
||||||
|
|
||||||
def parse_section(s,i):
|
class kMan:
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
self.hlnum = 0
|
||||||
|
self.ntnum = 0
|
||||||
|
self.refleshtime = '2020/10/10 10:00:00'
|
||||||
|
self.status = self.status_info()
|
||||||
|
|
||||||
|
def status_info(self):
|
||||||
|
s1 = u'Hightlight: {} Note: {} RefleshTime: {}'. \
|
||||||
|
format(self.hlnum,self.ntnum,self.refleshtime)
|
||||||
|
kp = self.get_kindle_path()
|
||||||
|
|
||||||
|
if not kp:
|
||||||
|
s2 = u'Disconnected'
|
||||||
|
else:
|
||||||
|
with open(kp+'/system/version.txt' , 'r', encoding='utf8', errors='ignore') as f:
|
||||||
|
s2 = u'Connected ({}) version {}'.format(kp,f.read().strip())
|
||||||
|
|
||||||
|
return [s1,s2]
|
||||||
|
|
||||||
|
def parse_section(self,s,i):
|
||||||
"""parse section
|
"""parse section
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -182,7 +205,7 @@ def parse_section(s,i):
|
|||||||
|
|
||||||
return section
|
return section
|
||||||
|
|
||||||
def format_time(ds):
|
def format_time(self,ds):
|
||||||
""" format date
|
""" format date
|
||||||
Args:
|
Args:
|
||||||
ds: 2020年1月13日 星期一 上午 8:11:05
|
ds: 2020年1月13日 星期一 上午 8:11:05
|
||||||
@@ -197,7 +220,7 @@ def format_time(ds):
|
|||||||
|
|
||||||
return ymd+tm
|
return ymd+tm
|
||||||
|
|
||||||
def format_data(bks, ft='MD'):
|
def format_data(self,bks, ft='MD'):
|
||||||
""" format data for MD & CSV
|
""" format data for MD & CSV
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -221,11 +244,12 @@ def format_data(bks, ft='MD'):
|
|||||||
for ks, vs in vb.items():
|
for ks, vs in vb.items():
|
||||||
if ks in ['author', 'lines']: continue
|
if ks in ['author', 'lines']: continue
|
||||||
secs.append(DELIMITER.join([vs['type'],kb,author, \
|
secs.append(DELIMITER.join([vs['type'],kb,author, \
|
||||||
format_time(' '.join([vs['day'],vs['week'],vs['meridiem'],vs['time']])),vs['content']]))
|
self.format_time(' '.join([vs['day'],vs['week'],\
|
||||||
|
vs['meridiem'],vs['time']])),vs['content']]))
|
||||||
|
|
||||||
return hd+secs
|
return hd+secs
|
||||||
|
|
||||||
def format_out(bks, fnpref, ft='MD'):
|
def format_out(self,bks, fnpref, ft='MD'):
|
||||||
"""format output and write to file
|
"""format output and write to file
|
||||||
markdown format:
|
markdown format:
|
||||||
TYPE | bookname | author | marktime | content
|
TYPE | bookname | author | marktime | content
|
||||||
@@ -252,13 +276,13 @@ def format_out(bks, fnpref, ft='MD'):
|
|||||||
if ft=='JSON':
|
if ft=='JSON':
|
||||||
fw.write(json.dumps(bks, indent=4, sort_keys=True, ensure_ascii=False))
|
fw.write(json.dumps(bks, indent=4, sort_keys=True, ensure_ascii=False))
|
||||||
elif ft in ['MD','CSV']:
|
elif ft in ['MD','CSV']:
|
||||||
for s in format_data(bks, ft):
|
for s in self.format_data(bks, ft):
|
||||||
fw.write(s)
|
fw.write(s)
|
||||||
fw.write('\n')
|
fw.write('\n')
|
||||||
else:
|
else:
|
||||||
fw.write(json.dumps(bks)) # only for load back
|
fw.write(json.dumps(bks)) # only for load back
|
||||||
|
|
||||||
def drop_duplicate(bks):
|
def drop_duplicate(self,bks):
|
||||||
""" drop duplicated section
|
""" drop duplicated section
|
||||||
|
|
||||||
If I mark second time in same place, kindle will create two note,
|
If I mark second time in same place, kindle will create two note,
|
||||||
@@ -290,7 +314,7 @@ def drop_duplicate(bks):
|
|||||||
|
|
||||||
return bks
|
return bks
|
||||||
|
|
||||||
def add_note_to_highlight(bks):
|
def add_note_to_highlight(self,bks):
|
||||||
""" append note content to corresponding highlight
|
""" append note content to corresponding highlight
|
||||||
and remove NT sections
|
and remove NT sections
|
||||||
|
|
||||||
@@ -312,7 +336,7 @@ def add_note_to_highlight(bks):
|
|||||||
|
|
||||||
return bks
|
return bks
|
||||||
|
|
||||||
def search_clip(bks, s, t='ALL', p='ALL'):
|
def search_clip(self,bks, s, t='ALL', p='ALL'):
|
||||||
"""search clip, searching scope may be title/author/content
|
"""search clip, searching scope may be title/author/content
|
||||||
Args:
|
Args:
|
||||||
input: bks: books dict
|
input: bks: books dict
|
||||||
@@ -348,11 +372,11 @@ def search_clip(bks, s, t='ALL', p='ALL'):
|
|||||||
|
|
||||||
return [nu,nbks]
|
return [nu,nbks]
|
||||||
|
|
||||||
# to be implement
|
# to be implement
|
||||||
def statistic(bks):
|
def statistic(self,bks):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def dict2json(d):
|
def dict2json(self,d):
|
||||||
"""convert dict to json
|
"""convert dict to json
|
||||||
Args: d is the dict
|
Args: d is the dict
|
||||||
Return: json string
|
Return: json string
|
||||||
@@ -360,7 +384,7 @@ def dict2json(d):
|
|||||||
jstr = json.dumps(d)
|
jstr = json.dumps(d)
|
||||||
return jstr
|
return jstr
|
||||||
|
|
||||||
def json2dict(jf):
|
def json2dict(self,jf):
|
||||||
"""convert dict to json
|
"""convert dict to json
|
||||||
Args: jf is the file saved json string
|
Args: jf is the file saved json string
|
||||||
Return: dict
|
Return: dict
|
||||||
@@ -370,12 +394,48 @@ def json2dict(jf):
|
|||||||
d=json.load(f)
|
d=json.load(f)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def import_clips():
|
def get_kindle_path(self):
|
||||||
# 4 lines for each section seperated with '======='
|
"""check and return kindle device path
|
||||||
# so read 4 lines before '======='
|
Args:
|
||||||
|
Return:
|
||||||
|
if kindle connected, return path string of kindle device
|
||||||
|
else return false
|
||||||
|
"""
|
||||||
|
cmd = "wmic logicaldisk get name,volumename" if os.name=='nt'\
|
||||||
|
else ("ls /Volumes/Kindle" if os.name=='posix' else '')
|
||||||
|
|
||||||
|
# not test for windows & linux
|
||||||
|
with os.popen(cmd) as s:
|
||||||
|
r = s.read()
|
||||||
|
if os.name == 'nt': # windows
|
||||||
|
for d in r.split('\n'):
|
||||||
|
if 'Kindle' in d: return d.split('\s+')[0]
|
||||||
|
elif os.name == 'posix': # mac os
|
||||||
|
if r: return('/Volumes/Kindle')
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def import_clips(self, tp='local'):
|
||||||
|
"""import clips from local file or kindle
|
||||||
|
4 lines for each section seperated with '======='
|
||||||
|
so read 4 lines before '======='
|
||||||
|
|
||||||
|
Args: tp: 'local' local clipping file
|
||||||
|
'kindle' kindle clipping file
|
||||||
|
Return: 0 - want to import kindle but kindle is not connected
|
||||||
|
books dict
|
||||||
|
"""
|
||||||
|
if tp=='kindle':
|
||||||
|
kp = get_kindle_path()
|
||||||
|
if not kp: return 0
|
||||||
|
else: path = kp
|
||||||
|
else:
|
||||||
|
path = CLIPPATH
|
||||||
|
|
||||||
# loop to fill books dict
|
# loop to fill books dict
|
||||||
with open(CLIPPATH, 'r', encoding='utf8', errors='ignore') as f:
|
with open(path, 'r', encoding='utf8', errors='ignore') as f:
|
||||||
bks = defaultdict(dict)
|
bks = defaultdict(dict)
|
||||||
secd = defaultdict(dict)
|
secd = defaultdict(dict)
|
||||||
sidx = 0
|
sidx = 0
|
||||||
@@ -399,7 +459,7 @@ def import_clips():
|
|||||||
sidx += 1
|
sidx += 1
|
||||||
|
|
||||||
# parsing section & fill data structure
|
# parsing section & fill data structure
|
||||||
secd = parse_section(sec,sidx)
|
secd = self.parse_section(sec,sidx)
|
||||||
|
|
||||||
if secd:
|
if secd:
|
||||||
bn = secd['bookname']
|
bn = secd['bookname']
|
||||||
@@ -414,40 +474,44 @@ def import_clips():
|
|||||||
if tpy=='NT' and bks[bn][str(sidx-1)]['type']=='HL':
|
if tpy=='NT' and bks[bn][str(sidx-1)]['type']=='HL':
|
||||||
bks[bn][str(sidx-1)]['content'] += str(NTPREF+sec[2])
|
bks[bn][str(sidx-1)]['content'] += str(NTPREF+sec[2])
|
||||||
"""
|
"""
|
||||||
|
if tpy=='HL': self.hlnum += 1
|
||||||
|
elif tpy=='NT': self.ntnum += 1
|
||||||
|
|
||||||
else: # BM or not correct format section
|
else: # BM or not correct format section
|
||||||
sidx -= 1
|
sidx -= 1
|
||||||
|
|
||||||
# initial section for next section loop
|
# initial section for next section loop
|
||||||
sec = []
|
sec = []
|
||||||
return bks
|
|
||||||
|
|
||||||
|
self.refleshtime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
||||||
|
|
||||||
|
return bks
|
||||||
|
|
||||||
if __name__=='__main__':
|
if __name__=='__main__':
|
||||||
#books = defaultdict(dict)
|
#books = defaultdict(dict)
|
||||||
books = import_clips()
|
km = kMan()
|
||||||
|
books = km.import_clips('local')
|
||||||
|
|
||||||
# remove duplication
|
# remove duplication
|
||||||
drop_duplicate(books)
|
km.drop_duplicate(books)
|
||||||
|
|
||||||
# test search note function
|
# test search note function
|
||||||
searchnote = search_clip(books, '三大都市圈', 'ALL', 'CONTENT')
|
searchnote = km.search_clip(books, '三大都市圈', 'ALL', 'CONTENT')
|
||||||
if searchnote[0] > 0: format_out(searchnote[1], 'searchcontent', ft='MD')
|
if searchnote[0] > 0: km.format_out(searchnote[1], 'searchcontent', ft='MD')
|
||||||
searchnote = search_clip(books, '经济', 'ALL', 'TITLE')
|
searchnote = km.search_clip(books, '经济', 'ALL', 'TITLE')
|
||||||
if searchnote[0] > 0: format_out(searchnote[1], 'searchtitle', ft='MD')
|
if searchnote[0] > 0: km.format_out(searchnote[1], 'searchtitle', ft='MD')
|
||||||
searchnote = search_clip(books, '巴曙松', 'ALL', 'AUTHOR')
|
searchnote = km.search_clip(books, '巴曙松', 'ALL', 'AUTHOR')
|
||||||
if searchnote[0] > 0: format_out(searchnote[1], 'searchauthor', ft='MD')
|
if searchnote[0] > 0: km.format_out(searchnote[1], 'searchauthor', ft='MD')
|
||||||
|
|
||||||
# add note content to hightlight, then delete note
|
# add note content to hightlight, then delete note
|
||||||
add_note_to_highlight(books)
|
km.add_note_to_highlight(books)
|
||||||
|
|
||||||
# test dict json convert
|
# test dict json convert
|
||||||
with open('./xx', 'w', encoding='utf8', errors='ignore') as fw:
|
with open('./xx', 'w', encoding='utf8', errors='ignore') as fw:
|
||||||
fw.write(dict2json(books))
|
fw.write(km.dict2json(books))
|
||||||
if json2dict('./xx')==books: print( 'test OK')
|
if km.json2dict('./xx')==books: print( 'test OK')
|
||||||
|
|
||||||
format_out(books, OUTPREF, ft='MD')
|
km.format_out(books, OUTPREF, ft='MD')
|
||||||
|
|
||||||
# print data with json format
|
# print data with json format
|
||||||
logger.debug(json.dumps(books, indent=4, sort_keys=True, ensure_ascii=False))
|
logger.debug(json.dumps(books, indent=4, sort_keys=True, ensure_ascii=False))
|
||||||
|
|
||||||
|
|||||||
80
kmanapp.py
80
kmanapp.py
@@ -1,5 +1,10 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
from time import sleep
|
||||||
|
from threading import Thread
|
||||||
|
import _thread
|
||||||
|
import threading
|
||||||
|
|
||||||
from PySide2.QtWidgets import QApplication
|
from PySide2.QtWidgets import QApplication
|
||||||
from PySide2.QtWidgets import QMainWindow
|
from PySide2.QtWidgets import QMainWindow
|
||||||
|
|
||||||
@@ -16,6 +21,8 @@ from kman import *
|
|||||||
# import binary resource file(kmanapp_rc.py)
|
# import binary resource file(kmanapp_rc.py)
|
||||||
import kmanapp_rc
|
import kmanapp_rc
|
||||||
|
|
||||||
|
ONLY_TEST = 0
|
||||||
|
|
||||||
class kmanWindow(QMainWindow):
|
class kmanWindow(QMainWindow):
|
||||||
"""
|
"""
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
@@ -26,13 +33,26 @@ class kmanWindow(QMainWindow):
|
|||||||
|
|
||||||
self.stat_str = 'status information'
|
self.stat_str = 'status information'
|
||||||
self.search_str = ''
|
self.search_str = ''
|
||||||
|
self.local_fn = CLIPPATH
|
||||||
|
|
||||||
# create ui and initial it
|
# create ui and initial it
|
||||||
ui = Ui_MainWindow()
|
ui = Ui_MainWindow()
|
||||||
ui.setupUi(self)
|
ui.setupUi(self)
|
||||||
self.ui = ui
|
self.ui = ui
|
||||||
|
|
||||||
self.books = import_clips()
|
self.km = kMan()
|
||||||
|
self.books = self.km.import_clips('local')
|
||||||
|
|
||||||
|
# loop check kindle is connected or not
|
||||||
|
# to be implement
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
#_thread.start_new_thread(self.check_kindle_status)
|
||||||
|
t1 = threading.Thread(target=check_kindle_status)
|
||||||
|
t1.start()
|
||||||
|
except:
|
||||||
|
print ("Error: can not start thread")
|
||||||
|
"""
|
||||||
|
|
||||||
# connect action/toolbutton to slot functions
|
# connect action/toolbutton to slot functions
|
||||||
ui.actionimportkindle.triggered.connect(lambda: self.import_kindle(self.books))
|
ui.actionimportkindle.triggered.connect(lambda: self.import_kindle(self.books))
|
||||||
@@ -54,7 +74,7 @@ class kmanWindow(QMainWindow):
|
|||||||
def add_ui_component(self):
|
def add_ui_component(self):
|
||||||
self.ui.searchComboBox.addItems(['ALL','bookname','content','author'])
|
self.ui.searchComboBox.addItems(['ALL','bookname','content','author'])
|
||||||
|
|
||||||
#inert test data xxxxxxxx
|
if not ONLY_TEST: # XXXXXXXXXXXXX
|
||||||
model = QStandardItemModel()
|
model = QStandardItemModel()
|
||||||
rootItem = model.invisibleRootItem()
|
rootItem = model.invisibleRootItem()
|
||||||
idx = 0
|
idx = 0
|
||||||
@@ -96,7 +116,6 @@ class kmanWindow(QMainWindow):
|
|||||||
|
|
||||||
self.ui.treeView.setModel(model)
|
self.ui.treeView.setModel(model)
|
||||||
|
|
||||||
|
|
||||||
def clicked_items(self):
|
def clicked_items(self):
|
||||||
print( 'call clicked_items()' )
|
print( 'call clicked_items()' )
|
||||||
|
|
||||||
@@ -110,15 +129,46 @@ class kmanWindow(QMainWindow):
|
|||||||
#print(search_clip(self.books,s,'ALL',p[t]))
|
#print(search_clip(self.books,s,'ALL',p[t]))
|
||||||
print('call search_scope_change()')
|
print('call search_scope_change()')
|
||||||
|
|
||||||
|
def check_kindle_status(self):
|
||||||
|
while True:
|
||||||
|
self.show_status_info()
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
def show_status_info(self):
|
||||||
|
""" show status information on statusbar
|
||||||
|
Args:
|
||||||
|
conn: 1 if kindle is connected else 0
|
||||||
|
Return:
|
||||||
|
conn
|
||||||
|
"""
|
||||||
|
status = self.km.status_info()
|
||||||
|
self.ui.statusbar.showMessage(status[0],0)
|
||||||
|
clabel = QLabel(status[1])
|
||||||
|
if not self.km.status:
|
||||||
|
pe = QPalette()
|
||||||
|
pe.setColor(QPalette.WindowText,Qt.red)
|
||||||
|
#clabel.setAutoFillBackground(True)
|
||||||
|
clabel.setPalette(pe)
|
||||||
|
self.ui.statusbar.addPermanentWidget(clabel, stretch=0)
|
||||||
|
|
||||||
# define slot functions
|
# define slot functions
|
||||||
def import_kindle(self,bks):
|
def import_kindle(self,bks):
|
||||||
print("call slot importkindle()")
|
status = self.km.status_info()
|
||||||
|
self.show_status_info()
|
||||||
|
|
||||||
print(bks)
|
print(bks)
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def import_local(self):
|
def import_local(self):
|
||||||
print("call slot importlocal()")
|
fn, ft = QFileDialog.getOpenFileName(self,
|
||||||
pass
|
"choose file to import",
|
||||||
|
'./', # 起始路径
|
||||||
|
"All Files (*);;Text Files (*.txt)") # 设置文件扩展名过滤,用双分号间隔
|
||||||
|
self.fn = fn
|
||||||
|
|
||||||
|
#print('filename ', fn, 'filetype ', ft)
|
||||||
|
if fn == "": return False
|
||||||
|
|
||||||
def config(self):
|
def config(self):
|
||||||
print("call slot config()")
|
print("call slot config()")
|
||||||
@@ -137,6 +187,12 @@ class kmanWindow(QMainWindow):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def about(self):
|
def about(self):
|
||||||
|
self.messagebox('\n'+ \
|
||||||
|
' kindle management tool \n\n' + \
|
||||||
|
' v1.0.4\n\n' + \
|
||||||
|
' Author: chengan\n\n' + \
|
||||||
|
' douboer@gmail.com')
|
||||||
|
|
||||||
print("call slot about()")
|
print("call slot about()")
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -144,8 +200,15 @@ class kmanWindow(QMainWindow):
|
|||||||
print("call slot flush()")
|
print("call slot flush()")
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def messageBox(self, showInfo):
|
# unify messagebox
|
||||||
box = QMessageBox.about(self, 'Kindle Management', showInfo)
|
def messagebox(self, showinfo):
|
||||||
|
msgBox = QMessageBox()
|
||||||
|
msgBox.setText(showinfo)
|
||||||
|
msgBox.setInformativeText("")
|
||||||
|
msgBox.setIcon(QMessageBox.Information)
|
||||||
|
msgBox.setStandardButtons(QMessageBox.Cancel | QMessageBox.Ok)
|
||||||
|
msgBox.setBaseSize(QSize(600, 300))
|
||||||
|
r = msgBox.exec()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
@@ -157,3 +220,4 @@ if __name__ == "__main__":
|
|||||||
kmw.show()
|
kmw.show()
|
||||||
app.exec_()
|
app.exec_()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
6
searchtitle.md
Normal file
6
searchtitle.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
TYPE|BOOKNAME|AUTHOR|MARKTIME|CONTENT
|
||||||
|
--|--|--|--|--
|
||||||
|
HL|薛兆丰经济学讲义 |薛兆丰|2020/1/13 8:11:05|么到底什么叫边际?边际就是“新增”带来的“新增”。 例如,边际成本就是每新增一个单位产品所需要付出的新增成本;边际收入是每多卖一个产品能够带来的新增收入;边际产量是每新增一份投入所带来的新增产量;边际效用是每消耗一个单位的商品所能带来的新增享受。
|
||||||
|
HL|薛兆丰经济学讲义 |薛兆丰|2020/1/30 10:23:58|一个国家很大,贫富有差距,并非每个学校和家长都能负担得起这样标准的校车。标准太高,就会逼着很多学校,尤其是农村的学校放弃提供校车,家长们就只能使用安全性能更低的交通工具,比如自己骑自行车或雇用黑车等,结果是孩子们享受到的安全保障反而降低了。
|
||||||
|
NT|薛兆丰经济学讲义 |薛兆丰|2020/1/30 10:26:31|山寨 假货 问题
|
||||||
|
HL|薛兆丰经济学讲义 |薛兆丰|2020/1/30 10:29:41|为了克服信息不对称,建立互信,人类社会构想出了各种各样有趣的解决方案,从重复交易到第三方背书,从质保、延保,再到收益共享。此外,还有三种非常接近的建立信任的办法:付出沉没成本、给出人质或者给出抵押。
|
||||||
@@ -116,7 +116,6 @@ class TestKman(unittest.TestCase):
|
|||||||
self.assertEqual(t_ds, '2020/1/13 20:11:05')
|
self.assertEqual(t_ds, '2020/1/13 20:11:05')
|
||||||
|
|
||||||
# test function format_data
|
# test function format_data
|
||||||
def test_format_data(self):
|
|
||||||
def test_format_data(self):
|
def test_format_data(self):
|
||||||
t_books = self.cre_tbooks()
|
t_books = self.cre_tbooks()
|
||||||
t_out = format_data(t_books, ft='MD')
|
t_out = format_data(t_books, ft='MD')
|
||||||
@@ -125,6 +124,11 @@ class TestKman(unittest.TestCase):
|
|||||||
self.assertEqual(t_out[2], 'HL|薛兆丰经济学讲义 |薛兆丰|2020/1/13 8:11:05|边际就是“新增”带来的“新增”。\n')
|
self.assertEqual(t_out[2], 'HL|薛兆丰经济学讲义 |薛兆丰|2020/1/13 8:11:05|边际就是“新增”带来的“新增”。\n')
|
||||||
t_out.clear()
|
t_out.clear()
|
||||||
|
|
||||||
|
def test_add_note_to_highlight(self):
|
||||||
|
t_books = self.cre_tbooks()
|
||||||
|
t_books_remove_nt = add_note_to_highlight(t_books)
|
||||||
|
for k in t_books_remove_nt.keys():
|
||||||
|
bn = k
|
||||||
self.assertEqual((t_books_remove_nt[bn]['1']['content']).replace('\n',''),\
|
self.assertEqual((t_books_remove_nt[bn]['1']['content']).replace('\n',''),\
|
||||||
'边际就是“新增”带来的“新增”。'+NTPREF+ '山寨 假货 问题')
|
'边际就是“新增”带来的“新增”。'+NTPREF+ '山寨 假货 问题')
|
||||||
|
|
||||||
|
|||||||
1
xx
Normal file
1
xx
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"\u859b\u5146\u4e30\u7ecf\u6d4e\u5b66\u8bb2\u4e49 ": {"author": "\u859b\u5146\u4e30", "1": {"type": "HL", "position": "1408-1410", "day": "2020\u5e741\u670813\u65e5", "week": "\u661f\u671f\u4e00", "meridiem": "\u4e0a\u5348", "time": "8:11:05", "content": "\u4e48\u5230\u5e95\u4ec0\u4e48\u53eb\u8fb9\u9645\uff1f\u8fb9\u9645\u5c31\u662f\u201c\u65b0\u589e\u201d\u5e26\u6765\u7684\u201c\u65b0\u589e\u201d\u3002 \u4f8b\u5982\uff0c\u8fb9\u9645\u6210\u672c\u5c31\u662f\u6bcf\u65b0\u589e\u4e00\u4e2a\u5355\u4f4d\u4ea7\u54c1\u6240\u9700\u8981\u4ed8\u51fa\u7684\u65b0\u589e\u6210\u672c\uff1b\u8fb9\u9645\u6536\u5165\u662f\u6bcf\u591a\u5356\u4e00\u4e2a\u4ea7\u54c1\u80fd\u591f\u5e26\u6765\u7684\u65b0\u589e\u6536\u5165\uff1b\u8fb9\u9645\u4ea7\u91cf\u662f\u6bcf\u65b0\u589e\u4e00\u4efd\u6295\u5165\u6240\u5e26\u6765\u7684\u65b0\u589e\u4ea7\u91cf\uff1b\u8fb9\u9645\u6548\u7528\u662f\u6bcf\u6d88\u8017\u4e00\u4e2a\u5355\u4f4d\u7684\u5546\u54c1\u6240\u80fd\u5e26\u6765\u7684\u65b0\u589e\u4eab\u53d7\u3002"}, "2": {"type": "HL", "position": "4284-4286", "day": "2020\u5e741\u670830\u65e5", "week": "\u661f\u671f\u56db", "meridiem": "\u4e0a\u5348", "time": "10:23:58", "content": "\u4e00\u4e2a\u56fd\u5bb6\u5f88\u5927\uff0c\u8d2b\u5bcc\u6709\u5dee\u8ddd\uff0c\u5e76\u975e\u6bcf\u4e2a\u5b66\u6821\u548c\u5bb6\u957f\u90fd\u80fd\u8d1f\u62c5\u5f97\u8d77\u8fd9\u6837\u6807\u51c6\u7684\u6821\u8f66\u3002\u6807\u51c6\u592a\u9ad8\uff0c\u5c31\u4f1a\u903c\u7740\u5f88\u591a\u5b66\u6821\uff0c\u5c24\u5176\u662f\u519c\u6751\u7684\u5b66\u6821\u653e\u5f03\u63d0\u4f9b\u6821\u8f66\uff0c\u5bb6\u957f\u4eec\u5c31\u53ea\u80fd\u4f7f\u7528\u5b89\u5168\u6027\u80fd\u66f4\u4f4e\u7684\u4ea4\u901a\u5de5\u5177\uff0c\u6bd4\u5982\u81ea\u5df1\u9a91\u81ea\u884c\u8f66\u6216\u96c7\u7528\u9ed1\u8f66\u7b49\uff0c\u7ed3\u679c\u662f\u5b69\u5b50\u4eec\u4eab\u53d7\u5230\u7684\u5b89\u5168\u4fdd\u969c\u53cd\u800c\u964d\u4f4e\u4e86\u3002--CG\u6ce8:\u5c71\u5be8 \u5047\u8d27 \u95ee\u9898"}, "4": {"type": "HL", "position": "4382-4384", "day": "2020\u5e741\u670830\u65e5", "week": "\u661f\u671f\u56db", "meridiem": "\u4e0a\u5348", "time": "10:29:41", "content": "\u4e3a\u4e86\u514b\u670d\u4fe1\u606f\u4e0d\u5bf9\u79f0\uff0c\u5efa\u7acb\u4e92\u4fe1\uff0c\u4eba\u7c7b\u793e\u4f1a\u6784\u60f3\u51fa\u4e86\u5404\u79cd\u5404\u6837\u6709\u8da3\u7684\u89e3\u51b3\u65b9\u6848\uff0c\u4ece\u91cd\u590d\u4ea4\u6613\u5230\u7b2c\u4e09\u65b9\u80cc\u4e66\uff0c\u4ece\u8d28\u4fdd\u3001\u5ef6\u4fdd\uff0c\u518d\u5230\u6536\u76ca\u5171\u4eab\u3002\u6b64\u5916\uff0c\u8fd8\u6709\u4e09\u79cd\u975e\u5e38\u63a5\u8fd1\u7684\u5efa\u7acb\u4fe1\u4efb\u7684\u529e\u6cd5\uff1a\u4ed8\u51fa\u6c89\u6ca1\u6210\u672c\u3001\u7ed9\u51fa\u4eba\u8d28\u6216\u8005\u7ed9\u51fa\u62b5\u62bc\u3002"}, "lines": 4}}
|
||||||
Reference in New Issue
Block a user