jrnl.plugins.yaml_exporter   A
last analyzed

Complexity

Total Complexity 25

Size/Duplication

Total Lines 134
Duplicated Lines 17.16 %

Importance

Changes 0
Metric Value
eloc 90
dl 23
loc 134
rs 10
c 0
b 0
f 0
wmc 25

2 Methods

Rating   Name   Duplication   Size   Complexity  
A YAMLExporter.export_journal() 0 10 1
F YAMLExporter.export_entry() 23 101 24

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
#!/usr/bin/env python
2
# encoding: utf-8
3
4
import os
5
import re
6
import sys
7
8
from jrnl.color import ERROR_COLOR
9
from jrnl.color import RESET_COLOR
10
from jrnl.color import WARNING_COLOR
11
12
from .text_exporter import TextExporter
13
14
15
class YAMLExporter(TextExporter):
16
    """This Exporter can convert entries and journals into Markdown formatted text with YAML front matter."""
17
18
    names = ["yaml"]
19
    extension = "md"
20
21
    @classmethod
22
    def export_entry(cls, entry, to_multifile=True):
23
        """Returns a markdown representation of a single entry, with YAML front matter."""
24
        if to_multifile is False:
25
            print(
26
                f"{ERROR_COLOR}ERROR{RESET_COLOR}: YAML export must be to individual files. Please \
27
                specify a directory to export to.",
28
                file=sys.stderr,
29
            )
30
            return
31
32
        date_str = entry.date.strftime(entry.journal.config["timeformat"])
33
        body_wrapper = "\n" if entry.body else ""
34
        body = body_wrapper + entry.body
35
36
        tagsymbols = entry.journal.config["tagsymbols"]
37
        # see also Entry.Entry.rag_regex
38
        multi_tag_regex = re.compile(fr"(?u)^\s*([{tagsymbols}][-+*#/\w]+\s*)+$")
39
40
        """Increase heading levels in body text"""
41
        newbody = ""
42
        heading = "#"
43
        previous_line = ""
44
        warn_on_heading_level = False
45
        for line in body.splitlines(True):
46 View Code Duplication
            if re.match(r"^#+ ", line):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
47
                """ATX style headings"""
48
                newbody = newbody + previous_line + heading + line
49
                if re.match(r"^#######+ ", heading + line):
50
                    warn_on_heading_level = True
51
                line = ""
52
            elif re.match(r"^=+$", line.rstrip()) and not re.match(
53
                r"^$", previous_line.strip()
54
            ):
55
                """Setext style H1"""
56
                newbody = newbody + heading + "# " + previous_line
57
                line = ""
58
            elif re.match(r"^-+$", line.rstrip()) and not re.match(
59
                r"^$", previous_line.strip()
60
            ):
61
                """Setext style H2"""
62
                newbody = newbody + heading + "## " + previous_line
63
                line = ""
64
            elif multi_tag_regex.match(line):
65
                """Tag only lines"""
66
                line = ""
67
            else:
68
                newbody = newbody + previous_line
69
            previous_line = line
70
        newbody = newbody + previous_line  # add very last line
71
72
        # make sure the export ends with a blank line
73
        if previous_line not in ["\r", "\n", "\r\n", "\n\r"]:
74
            newbody = newbody + os.linesep
75
76
        if warn_on_heading_level is True:
77
            print(
78
                "{}WARNING{}: Headings increased past H6 on export - {} {}".format(
79
                    WARNING_COLOR, RESET_COLOR, date_str, entry.title
80
                ),
81
                file=sys.stderr,
82
            )
83
84
        dayone_attributes = ""
85
        if hasattr(entry, "uuid"):
86
            dayone_attributes += "uuid: " + entry.uuid + "\n"
87
        if (
88
            hasattr(entry, "creator_device_agent")
89
            or hasattr(entry, "creator_generation_date")
90
            or hasattr(entry, "creator_host_name")
91
            or hasattr(entry, "creator_os_agent")
92
            or hasattr(entry, "creator_software_agent")
93
        ):
94
            dayone_attributes += "creator:\n"
95
            if hasattr(entry, "creator_device_agent"):
96
                dayone_attributes += f"    device agent: {entry.creator_device_agent}\n"
97
            if hasattr(entry, "creator_generation_date"):
98
                dayone_attributes += "    generation date: {}\n".format(
99
                    str(entry.creator_generation_date)
100
                )
101
            if hasattr(entry, "creator_host_name"):
102
                dayone_attributes += f"    host name: {entry.creator_host_name}\n"
103
            if hasattr(entry, "creator_os_agent"):
104
                dayone_attributes += f"    os agent: {entry.creator_os_agent}\n"
105
            if hasattr(entry, "creator_software_agent"):
106
                dayone_attributes += (
107
                    f"    software agent: {entry.creator_software_agent}\n"
108
                )
109
110
        # TODO: copy over pictures, if present
111
        # source directory is  entry.journal.config['journal']
112
        # output directory is...?
113
114
        return "title: {title}\ndate: {date}\nstarred: {starred}\ntags: {tags}\n{dayone} {body} {space}".format(
115
            date=date_str,
116
            title=entry.title,
117
            starred=entry.starred,
118
            tags=", ".join([tag[1:] for tag in entry.tags]),
119
            dayone=dayone_attributes,
120
            body=newbody,
121
            space="",
122
        )
123
124
    @classmethod
125
    def export_journal(cls, journal):
126
        """Returns an error, as YAML export requires a directory as a target."""
127
        print(
128
            "{}ERROR{}: YAML export must be to individual files. Please specify a directory to export to.".format(
129
                ERROR_COLOR, RESET_COLOR
130
            ),
131
            file=sys.stderr,
132
        )
133
        return
134