Passed
Push — master ( 715ae9...b2e443 )
by P.R.
10:52 queued 11s
created

etlt_mysql.writer.MySqlLoaderWriter   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 184
Duplicated Lines 86.96 %

Test Coverage

Coverage 87.32%

Importance

Changes 0
Metric Value
wmc 17
eloc 74
dl 160
loc 184
rs 10
c 0
b 0
f 0
ccs 62
cts 71
cp 0.8732

12 Methods

Rating   Name   Duplication   Size   Complexity  
A MySqlLoaderWriter.write_uuid() 9 9 1
A MySqlLoaderWriter.writerow() 11 11 2
A MySqlLoaderWriter.write_datetime() 12 12 3
A MySqlLoaderWriter.write_int() 9 9 1
A MySqlLoaderWriter.write_float() 9 9 1
A MySqlLoaderWriter.write_bool() 12 12 2
A MySqlLoaderWriter.get_bulk_load_sql() 19 19 1
A MySqlLoaderWriter.write_decimal() 9 9 1
A MySqlLoaderWriter.write_string() 14 14 2
A MySqlLoaderWriter.write_timedelta() 9 9 1
A MySqlLoaderWriter.write_none() 9 9 1
A MySqlLoaderWriter.write_date() 9 9 1

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 1
import datetime
2 1
import os
3 1
from abc import ABC
4 1
from decimal import Decimal
5 1
from typing import Any, Dict
6
7 1
import pytz
8 1
from etlt.writer.SqlLoaderWriter import SqlLoaderWriter
9
10
11 1 View Code Duplication
class MySqlLoaderWriter(SqlLoaderWriter, ABC):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
12
    """
13
    Writer for storing rows in CSV format optimized for MariaDB and MySQL instances and 'load data local infile'
14
    statement.
15
    """
16
17
    # ------------------------------------------------------------------------------------------------------------------
18 1
    @staticmethod
19 1
    def write_bool(value: bool, file: Any) -> None:
20
        """
21
        Writes a boolean as a field to a CSV file.
22
23
        :param bool value: The boolean.
24
        :param Any file: The file like object
25
        """
26 1
        if value:
27 1
            file.write('1')
28
        else:
29 1
            file.write('0')
30
31
    # ------------------------------------------------------------------------------------------------------------------
32 1
    @staticmethod
33 1
    def write_date(value: datetime.date, file: Any) -> None:
34
        """
35
        Writes a date as a field to a CSV file.
36
37
        :param datetime.date value: The date.
38
        :param Any file: The file like object
39
        """
40 1
        file.write(value.isoformat())
41
42
    # ------------------------------------------------------------------------------------------------------------------
43 1
    @staticmethod
44 1
    def write_datetime(value: datetime.datetime, file: Any) -> None:
45
        """
46
        Writes a datetime as a field to a CSV file.
47
48
        :param datetime.datetime value: The date.
49
        :param Any file: The file like object
50
        """
51 1
        zone = value.tzinfo
52 1
        if zone and zone != pytz.utc:
53
            raise ValueError('Only native and UTC timezone supported')
54 1
        file.write(value.isoformat())
55
56
    # ------------------------------------------------------------------------------------------------------------------
57 1
    @staticmethod
58 1
    def write_timedelta(value: datetime.timedelta, file: Any) -> None:
59
        """
60
        Writes a timedelta as a field to a CSV file.
61
62
        :param datetime.timedelta value: The timedelta.
63
        :param Any file: The file like object
64
        """
65 1
        MySqlLoaderWriter.write_string(str(value), file)
66
67
    # ------------------------------------------------------------------------------------------------------------------
68 1
    @staticmethod
69 1
    def write_decimal(value: Decimal, file: Any) -> None:
70
        """
71
        Writes a decimal as a field to a CSV file.
72
73
        :param Decimal value: The decimal.
74
        :param Any file: The file like object
75
        """
76 1
        file.write(str(value))
77
78
    # ------------------------------------------------------------------------------------------------------------------
79 1
    @staticmethod
80 1
    def write_float(value: float, file: Any) -> None:
81
        """
82
        Writes a float as a field to a CSV file.
83
84
        :param float value: The float.
85
        :param Any file: The file like object
86
        """
87 1
        file.write(str(value))
88
89
    # ------------------------------------------------------------------------------------------------------------------
90 1
    @staticmethod
91 1
    def write_int(value: int, file: Any) -> None:
92
        """
93
        Writes an integer as a field to a CSV file.
94
95
        :param int value: The integer.
96
        :param Any file: The file like object
97
        """
98 1
        file.write(str(value))
99
100
    # ------------------------------------------------------------------------------------------------------------------
101 1
    @staticmethod
102 1
    def write_none(_, file: Any) -> None:
103
        """
104
        Writes None as a field to a CSV file.
105
106
        :param None _: The None object.
107
        :param Any file: The file like object
108
        """
109 1
        file.write('\\N')
110
111
    # ------------------------------------------------------------------------------------------------------------------
112 1
    @staticmethod
113 1
    def write_string(value: str, file: Any) -> None:
114
        """
115
        Writes a string as a field to a CSV file.
116
117
        :param str value: The string.
118
        :param Any file: The file.
119
        """
120 1
        if value == '':
121 1
            file.write('\\N')
122
        else:
123 1
            file.write("'")
124 1
            file.write(value.replace('\\', '\\\\').replace("'", "\\'"))
125 1
            file.write("'")
126
127
    # ------------------------------------------------------------------------------------------------------------------
128 1
    def writerow(self, row: Dict[str, Any]) -> None:
129
        """
130
        Writes a row to the destination file.
131
132
        :param dict[str,Any] row: The row.
133
        """
134 1
        for field in self._fields:
135 1
            self._write_field(row[field])
136 1
            self._file.write(',')
137
138 1
        self._file.write(os.linesep)
139
140
    # ------------------------------------------------------------------------------------------------------------------
141 1
    @staticmethod
142 1
    def write_uuid(value, file: Any) -> None:
143
        """
144
        Writes a UUID as a field to a CSV file.
145
146
        :param uuid.UUID value: The UUID.
147
        :param Any file: The file like object
148
        """
149 1
        MySqlLoaderWriter.write_string(str(value), file)
150
151
    # ------------------------------------------------------------------------------------------------------------------
152 1
    def get_bulk_load_sql(self, table_name: str) -> str:
153
        """
154
        Returns a SQL statement for bulk loading the data into a table.
155
156
        :param str table_name: The name of the table.
157
158
        :rtype: str
159
        """
160
        sql = "load data local infile '{FILENAME}'"
161
        sql += ' into table `{TABLE_NAME}`'
162
        sql += ' character set {ENCODING}'
163
        sql += " fields terminated by ','"
164
        sql += " optionally enclosed by '\\\''"
165
        sql += " escaped by '\\\\'"
166
        sql += " lines terminated by '\\n'"
167
168
        return sql.format(FILENAME=self._filename,  # @todo Quoting of filename
169
                          ENCODING=self._encoding,
170
                          TABLE_NAME=table_name)
171
172
173
# ----------------------------------------------------------------------------------------------------------------------
174 1
MySqlLoaderWriter.register_handler("<class 'bool'>", MySqlLoaderWriter.write_bool)
175 1
MySqlLoaderWriter.register_handler("<class 'datetime.date'>", MySqlLoaderWriter.write_date)
176 1
MySqlLoaderWriter.register_handler("<class 'datetime.datetime'>", MySqlLoaderWriter.write_datetime)
177 1
MySqlLoaderWriter.register_handler("<class 'datetime.timedelta'>", MySqlLoaderWriter.write_timedelta)
178 1
MySqlLoaderWriter.register_handler("<class 'decimal.Decimal'>", MySqlLoaderWriter.write_decimal)
179 1
MySqlLoaderWriter.register_handler("<class 'float'>", MySqlLoaderWriter.write_float)
180 1
MySqlLoaderWriter.register_handler("<class 'int'>", MySqlLoaderWriter.write_int)
181 1
MySqlLoaderWriter.register_handler("<class 'NoneType'>", MySqlLoaderWriter.write_none)
182 1
MySqlLoaderWriter.register_handler("<class 'str'>", MySqlLoaderWriter.write_string)
183
MySqlLoaderWriter.register_handler("<class 'uuid.UUID'>", MySqlLoaderWriter.write_uuid)
184