Exemple #1
0
def test_change(fs):
    doc = """---
title: An Examination of the Navel
---

#personal #book-draft
# Preface: Reasons for #journaling

As I have explained at length in [another note](../Another%20Note.md) and also
published about online (see [this article](http://example.com/blahblah) and
[this one](http://example.com/blah) among many others), ...
"""
    expected = """---
created: 2019-06-04 10:12:13-08:00
title: A Close Examination of the Navel
---

#personal #book-draft
# Preface: Reasons for #journaling

As I have explained at length in [another note](moved/another-note.md) and also
published about online (see [this article](http://example.com/blahblah) and
[this one](https://example.com/meh) among many others), ...
"""
    path = '/fakenotes/test.md'
    fs.create_file(path, contents=doc)
    acc = MarkdownAccessor(path)
    acc.edit(ReplaceHrefCmd(path, '../Another%20Note.md', 'moved/another-note.md'))
    acc.edit(ReplaceHrefCmd(path, 'http://example.com/blah', 'https://example.com/meh'))
    acc.edit(SetTitleCmd(path, 'A Close Examination of the Navel'))
    acc.edit(SetCreatedCmd(path, datetime(2019, 6, 4, 10, 12, 13, 0, timezone(timedelta(hours=-8)))))
    assert acc.save()
    assert Path(path).read_text() == expected
Exemple #2
0
def test_change(fs, capsys):
    nd_setup(fs)
    fs.create_file('/notes/cwd/foo.md', contents='some text')
    assert cli.main([
        'change', '-p', '-a', 'tag1,tag2', '-c', '2012-02-03', '-t',
        'A Bland Note', 'foo.md'
    ]) == 0
    assert Path('/notes/cwd/foo.md').read_text() == 'some text'
    out, err = capsys.readouterr()
    lines = set(out.splitlines())
    # It's a little weird that we generate Cmds with relative paths, when most of the time the repos deal with
    # fully resolved paths. I don't think it affects anything right now, but may need to change at some point.
    assert lines == {
        str(AddTagCmd('foo.md', 'tag1')),
        str(AddTagCmd('foo.md', 'tag2')),
        str(SetTitleCmd('foo.md', 'A Bland Note')),
        str(SetCreatedCmd('foo.md', datetime(2012, 2, 3)))
    }

    assert cli.main([
        'change', '-a', 'tag1,tag2', '-c', '2012-02-03', '-t', 'A Bland Note',
        'foo.md'
    ]) == 0
    assert Path('/notes/cwd/foo.md').read_text() == """---
created: 2012-02-03 00:00:00
keywords:
- tag1
- tag2
title: A Bland Note
...
some text"""
    assert cli.main(['change', '-d', 'tag1', '-t', 'A Better Note',
                     'foo.md']) == 0
    assert Path('/notes/cwd/foo.md').read_text() == """---
Exemple #3
0
    def backfill(self) -> (List[str], List[Exception]):
        """Finds all files missing title or created metadata, and attempts to set that metadata.

        Missing titles are set to the filename, minus the file extension.
        Missing created dates are set based on the birthtime or ctime of the file.

        Returns a list of all successfully changed files, and a list of exceptions encountered for other files.
        """
        modified = []
        exceptions = []
        for info in self.repo.query(fields=FileInfoReq(path=True, title=True, created=True)):
            edits = []
            if not info.title:
                _, filename = os.path.split(info.path)
                title, _ = os.path.splitext(filename)
                edits.append(SetTitleCmd(info.path, title))
            if not info.created:
                edits.append(SetCreatedCmd(info.path, info.guess_created()))
            if edits:
                try:
                    self.repo.change(edits)
                    modified.append(info.path)
                except Exception as ex:
                    exceptions.append(ex)
        return modified, exceptions
Exemple #4
0
def test_change(fs):
    fs.cwd = '/notes'
    path1 = '/notes/one.md'
    path2 = '/notes/two.md'
    path3 = '/notes/moved.md'
    fs.create_file(path1, contents='[1](old)')
    fs.create_file(path2, contents='[2](foo)')
    edits = [SetTitleCmd(path1, 'New Title'),
             ReplaceHrefCmd(path1, 'old', 'new'),
             MoveCmd(path1, path3),
             ReplaceHrefCmd(path2, 'foo', 'bar')]
    repo = config().instantiate()
    repo.change(edits)
    assert not Path(path1).exists()
    assert Path(path3).read_text() == '---\ntitle: New Title\n...\n[1](new)'
    assert Path(path2).read_text() == '[2](bar)'
    assert repo.info(path1, FileInfoReq.full()) == FileInfo(path1)
    assert repo.info(path3, FileInfoReq.full()) == FileInfo(path3, title='New Title', links=[LinkInfo(path3, 'new')])
    assert repo.info(path2, FileInfoReq.full()) == FileInfo(path2, links=[LinkInfo(path2, 'bar')])
    assert repo.info('old', FileInfoReq.full()) == FileInfo('/notes/old')
    assert repo.info('foo', FileInfoReq.full()) == FileInfo('/notes/foo')
    assert repo.info('new', FileInfoReq.full()) == FileInfo('/notes/new', backlinks=[LinkInfo(path3, 'new')])
    assert repo.info('bar', FileInfoReq.full()) == FileInfo('/notes/bar', backlinks=[LinkInfo(path2, 'bar')])
    # regression test for bug where invalidate removed entries for files that were referred to
    # only by files that had not been changed
    repo.invalidate()
    assert repo.info('new', FileInfoReq.full()) == FileInfo('/notes/new', backlinks=[LinkInfo(path3, 'new')])
    assert repo.info('bar', FileInfoReq.full()) == FileInfo('/notes/bar', backlinks=[LinkInfo(path2, 'bar')])
Exemple #5
0
def test_change(fs):
    doc = """<html>
    <head>
        <title>fdsalkhflsdakjsdhfaslkjdhfalkj</title>
        <meta name="created" content="2001-01-01 02:02:02 +0000" />
    </head>
    <body>
        <p>Hi! Here's a <a href="../Mediocre%20Note.md">link</a> and a <img src="http://example.com/foo.png" title="picture"/>.</p>

        <video controls src="media/something.weird">a video element</video>
        <audio controls src="media/something.weird">an audio element</audio>
        <audio controls><source src="media/something.weird">another audio element</audio>

        <p>Here's an <a href="../Mediocre%20Note.html">unaffected link</a>.</p>
    </body>
</html>"""
    expected = """<html>
    <head>
        <title>A Delightful Note</title>
        <meta name="created" content="2019-06-04 10:12:13 -0800" />
    </head>
    <body>
        <p>Hi! Here's a <a href="../archive/Mediocre%20Note.md">link</a> and a <img src="http://example.com/bar.png" title="picture"/>.</p>

        <video controls src="content/something.cool">a video element</video>
        <audio controls src="content/something.cool">an audio element</audio>
        <audio controls><source src="content/something.cool">another audio element</audio>

        <p>Here's an <a href="../Mediocre%20Note.html">unaffected link</a>.</p>
    </body>
</html>"""
    path = Path('/fakenotes/test.html')
    fs.create_file(path, contents=doc)
    acc = HTMLAccessor(str(path))
    acc.edit(SetTitleCmd(str(path), 'A Delightful Note'))
    acc.edit(
        SetCreatedCmd(
            str(path),
            datetime(2019, 6, 4, 10, 12, 13, 0,
                     timezone(timedelta(hours=-8)))))
    acc.edit(
        ReplaceHrefCmd(str(path), '../Mediocre%20Note.md',
                       '../archive/Mediocre%20Note.md'))
    acc.edit(
        ReplaceHrefCmd(str(path), 'http://example.com/foo.png',
                       'http://example.com/bar.png'))
    acc.edit(
        ReplaceHrefCmd(str(path), 'media/something.weird',
                       'content/something.cool'))
    assert acc.save()
    assert BeautifulSoup(
        path.read_text(),
        'lxml',
    ) == BeautifulSoup(expected, 'lxml')
Exemple #6
0
def test_change(fs):
    fs.create_file('/notes/one.md', contents='[1](old)')
    fs.create_file('/notes/two.md', contents='[2](foo)')
    edits = [SetTitleCmd('/notes/one.md', 'New Title'),
             ReplaceHrefCmd('/notes/one.md', 'old', 'new'),
             MoveCmd('/notes/one.md', '/notes/moved.md'),
             ReplaceHrefCmd('/notes/two.md', 'foo', 'bar')]
    repo = DirectRepoConf(root_paths={'/notes'}).instantiate()
    repo.change(edits)
    assert not Path('/notes/one.md').exists()
    assert Path('/notes/moved.md').read_text() == '---\ntitle: New Title\n...\n[1](new)'
    assert Path('/notes/two.md').read_text() == '[2](bar)'
Exemple #7
0
    def change(self, paths: Set[str], add_tags=Set[str], del_tags=Set[str], title=Optional[str],
               created=Optional[datetime]) -> None:
        """Applies all the specified changes to the specified paths.

        This is a convenience method that wraps :meth:`notesdir.repos.base.Repo.change`
        """
        edits = []
        for path in paths:
            edits.extend(AddTagCmd(path, t.lower()) for t in add_tags)
            edits.extend(DelTagCmd(path, t.lower()) for t in del_tags)
            if title is not None:
                edits.append(SetTitleCmd(path, title))
            if created is not None:
                edits.append(SetCreatedCmd(path, created))
        self.repo.change(edits)
Exemple #8
0
def test_change_from_missing_attributes(fs):
    doc = """<html>
    <body>Hi!</body>
</html>"""
    expected = """<html><head><title>A Delightful Note</title><meta name="created" content="2019-06-04 10:12:13 -0800"/></head>
    <body>Hi!</body>
</html>"""
    path = Path('/fakenotes/test.html')
    fs.create_file(path, contents=doc)
    acc = HTMLAccessor(str(path))
    acc.edit(SetTitleCmd(str(path), 'A Delightful Note'))
    acc.edit(
        SetCreatedCmd(
            str(path),
            datetime(2019, 6, 4, 10, 12, 13, 0,
                     timezone(timedelta(hours=-8)))))
    assert acc.save()
    assert BeautifulSoup(path.read_text(),
                         'lxml') == BeautifulSoup(expected, 'lxml')
Exemple #9
0
def test_meta_body_separation(fs):
    # MarkdownAccessor does not preserve blank lines between meta and body.
    # This test formally recognizes this, and verifies our convention of
    # always separating meta and body by one blank line.

    # one blank line between meta and body
    expected = """---
title: new title
---

body
"""
    # no blank line between meta and body
    doc1 = """---
title: title
---
body
"""
    # one blank line between meta and body
    doc2 = """---
title: title
---

body
"""
    # two blank lines between meta and body
    doc3 = """---
title: title
---


body
"""
    Path('/fakenotes').mkdir()
    for doc in [doc1, doc2, doc3]:
        path = '/fakenotes/doc.md'
        Path(path).write_text(doc)
        acc = MarkdownAccessor(path)
        # change title to trigger a save
        acc.edit(SetTitleCmd(path, 'new title'))
        acc.save()
        assert Path(path).read_text() == expected
Exemple #10
0
def test_change(fs):
    path = str(Path(__file__).parent.joinpath('test.pdf'))
    fs.add_real_file(path, read_only=False)
    acc = PDFAccessor(path)
    acc.edit(SetTitleCmd(path, 'Why Donuts Are Great'))
    acc.edit(
        SetCreatedCmd(path,
                      datetime.fromisoformat('1999-02-04T06:08:10+00:00')))
    acc.edit(AddTagCmd(path, 'tag3'))
    acc.edit(DelTagCmd(path, 'tag2'))
    assert acc.save()
    with open(path, 'rb') as file:
        pdf = PdfFileReader(file)
        assert 'I like donuts' in pdf.getPage(0).extractText()
        # Make sure we didn't destroy preexisting metadata
        assert pdf.getDocumentInfo()['/Creator'] == 'Pages'
    info = PDFAccessor(path).info()
    assert info.title == 'Why Donuts Are Great'
    assert info.created == datetime.fromisoformat('1999-02-04T06:08:10+00:00')
    assert info.tags == {'tag1', 'tag3'}
Exemple #11
0
 def set_title(self, path: str, title: str) -> None:
     """Convenience method equivalent to calling change with one :class:`notesdir.models.SetTitleCmd`"""
     self.change([SetTitleCmd(path, title)])