|
@@ -9,25 +9,26 @@ logger = logging.getLogger()
|
|
|
|
|
|
def get_fname(url):
|
|
|
m = hashlib.md5()
|
|
|
- m.update(url.encode('utf8'))
|
|
|
+ m.update(url.encode("utf8"))
|
|
|
return m.hexdigest()
|
|
|
|
|
|
|
|
|
class Store:
|
|
|
def __init__(self, basedir: Path = None):
|
|
|
if basedir is None:
|
|
|
- basedir = Path('~/.local/share/marxbook/bookmarks/').expanduser()
|
|
|
+ basedir = Path("~/.local/share/marxbook/bookmarks/").expanduser()
|
|
|
self.basedir = basedir
|
|
|
self.serializer = Serializer()
|
|
|
|
|
|
- def add(self, url: str, title=None, tag=[], description=''):
|
|
|
+ def add(self, url: str, title=None, tag=[], description=""):
|
|
|
dest = self.basedir
|
|
|
dest.mkdir(parents=True, exist_ok=True)
|
|
|
fname = get_fname(url)
|
|
|
fpath = dest / fname
|
|
|
- content = self.serializer.encode(dict(
|
|
|
- url=url, title=title, tags=tag, description=description))
|
|
|
- with fpath.open('w') as buf:
|
|
|
+ content = self.serializer.encode(
|
|
|
+ dict(url=url, title=title, tags=tag, description=description)
|
|
|
+ )
|
|
|
+ with fpath.open("w") as buf:
|
|
|
buf.write(content)
|
|
|
|
|
|
def get(self, path: str):
|
|
@@ -36,27 +37,26 @@ class Store:
|
|
|
return self.serializer.decode(buf.read())
|
|
|
|
|
|
def find(self, prefix_path: str) -> Path:
|
|
|
- '''
|
|
|
+ """
|
|
|
prefix_path is a special form of contraction. Let's say prefix_path=utils/time/5e
|
|
|
If there is a single file starting with 5e inside utils/time, then that's found!
|
|
|
- '''
|
|
|
+ """
|
|
|
if os.path.exists(prefix_path):
|
|
|
return prefix_path
|
|
|
-
|
|
|
- candidates = list(self.basedir.glob(prefix_path + '*'))
|
|
|
+
|
|
|
+ candidates = list(self.basedir.glob(prefix_path + "*"))
|
|
|
if not candidates:
|
|
|
raise FileNotFoundError("%s not found" % prefix_path)
|
|
|
if len(candidates) > 1:
|
|
|
raise ValueError("Ambiguous prefix %s" % prefix_path)
|
|
|
return candidates[0]
|
|
|
-
|
|
|
|
|
|
def __iter__(self):
|
|
|
- for urlfile in self.basedir.glob('**/*'):
|
|
|
+ for urlfile in self.basedir.glob("**/*"):
|
|
|
if not urlfile.is_file():
|
|
|
continue
|
|
|
data = self.get(urlfile)
|
|
|
- ret = { 'Path': str(urlfile.relative_to(self.basedir)) }
|
|
|
+ ret = {"Path": str(urlfile.relative_to(self.basedir))}
|
|
|
ret.update(data)
|
|
|
yield ret
|
|
|
|
|
@@ -64,7 +64,7 @@ class Store:
|
|
|
return Store(self.basedir / folder)
|
|
|
|
|
|
|
|
|
-HEADER_LINE = re.compile(r'^([^:]+): (.*)$')
|
|
|
+HEADER_LINE = re.compile(r"^([^:]+): (.*)$")
|
|
|
|
|
|
|
|
|
class Serializer:
|
|
@@ -72,17 +72,17 @@ class Serializer:
|
|
|
pass
|
|
|
|
|
|
def encode(self, data: dict) -> str:
|
|
|
- m = ''
|
|
|
- tags = data.pop('tag', []) # those are special!
|
|
|
+ m = ""
|
|
|
+ tags = data.pop("tag", []) # those are special!
|
|
|
for key in data:
|
|
|
- m += '%s: %s\n' % (key.title(), str(data[key]).replace('\n', ' '))
|
|
|
+ m += "%s: %s\n" % (key.title(), str(data[key]).replace("\n", " "))
|
|
|
for tag in tags:
|
|
|
- m += '%s: %s\n' % ('Tag', tag)
|
|
|
+ m += "%s: %s\n" % ("Tag", tag)
|
|
|
return m
|
|
|
|
|
|
def decode(self, content: str) -> dict:
|
|
|
- d: dict = {'Tag': []}
|
|
|
- for num, line in enumerate(content.split('\n'), 1):
|
|
|
+ d: dict = {"Tag": []}
|
|
|
+ for num, line in enumerate(content.split("\n"), 1):
|
|
|
if not line.strip():
|
|
|
continue
|
|
|
m = HEADER_LINE.match(line)
|
|
@@ -91,15 +91,16 @@ class Serializer:
|
|
|
continue
|
|
|
key, value = m.groups()
|
|
|
key = key.title()
|
|
|
- if key == 'Tag':
|
|
|
+ if key == "Tag":
|
|
|
d[key].append(value)
|
|
|
else:
|
|
|
d[key] = value
|
|
|
return d
|
|
|
|
|
|
|
|
|
-if __name__ == '__main__':
|
|
|
+if __name__ == "__main__":
|
|
|
import sys
|
|
|
+
|
|
|
s = Store()
|
|
|
# print(s.get(sys.argv[1]))
|
|
|
for line in s.list(sys.argv[1]):
|