Passed
Push — 2.x ( 908061...0c6678 )
by Ramon
27:59 queued 21:19
created

senaite.core.schema.coordinatefield   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 111
Duplicated Lines 25.23 %

Importance

Changes 0
Metric Value
wmc 15
eloc 55
dl 28
loc 111
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A LatitudeCoordinateField._validate() 9 9 3
A CoordinateField.set() 0 15 3
A LongitudeCoordinateField._validate() 9 9 3
A CoordinateField.__init__() 0 4 1
A CoordinateField._validate() 0 18 5

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
# -*- coding: utf-8 -*-
2
#
3
# This file is part of SENAITE.CORE.
4
#
5
# SENAITE.CORE is free software: you can redistribute it and/or modify it under
6
# the terms of the GNU General Public License as published by the Free Software
7
# Foundation, version 2.
8
#
9
# This program is distributed in the hope that it will be useful, but WITHOUT
10
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
# details.
13
#
14
# You should have received a copy of the GNU General Public License along with
15
# this program; if not, write to the Free Software Foundation, Inc., 51
16
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
#
18
# Copyright 2018-2024 by it's authors.
19
# Some rights reserved, see README and LICENSE.
20
21
import copy
22
from bika.lims import api
23
from bika.lims import senaiteMessageFactory as _
24
from senaite.core.i18n import translate as t
25
from senaite.core.schema.fields import BaseField
26
from senaite.core.schema.interfaces import ICoordinateField
27
from zope.interface import implementer
28
from zope.schema import Dict
29
30
31
SUBFIELDS = ("degrees", "minutes", "seconds", "bearing")
32
33
34
@implementer(ICoordinateField)
35
class CoordinateField(Dict, BaseField):
36
    """A field that handles location coordinates (deg, min, sec, bearing)
37
    """
38
    bearing = list("NSWE")
39
40
    def __init__(self, **kwargs):
41
        default = kwargs.get("default")
42
        kwargs["default"] = default or dict.fromkeys(SUBFIELDS, "")
43
        super(CoordinateField, self).__init__(**kwargs)
44
45
    def set(self, object, value):
46
        """Set the coordinate field value
47
        """
48
        # ensure the value is a valid dict
49
        coordinate = copy.deepcopy(self.default)
50
        if value:
51
            coordinate.update(value)
52
53
        # convert values to strings preserving the whole fraction, if any
54
        for key in coordinate.keys():
55
            val = coordinate[key]
56
            coordinate[key] = api.float_to_string(val, default=val)
57
58
        # store the value
59
        super(CoordinateField, self).set(object, coordinate)
60
61
    def _validate(self, value):
62
        super(CoordinateField, self)._validate(value)
63
64
        # check minutes are within 0 and 59
65
        minutes = value.get("minutes", 0)
66
        minutes = api.to_int(minutes, default=0)
67
        if minutes < 0 or minutes > 59:
68
            msg = t(_("Value for minutes must be within 0 and 59"))
69
            raise ValueError(msg)
70
71
        # check seconds are within 0 and 59.9999. With 4 decimal places, the
72
        # max precision is ~100mm (individual humans can be unambiguously
73
        # recognized at this scale)
74
        seconds = value.get("seconds", 0)
75
        seconds = api.to_float(seconds, default=0)
76
        if seconds < 0 or seconds >= 60:
77
            msg = t(_("Value for seconds must be within 0 and 59.9999"))
78
            raise ValueError(msg)
79
80
81 View Code Duplication
class LatitudeCoordinateField(CoordinateField):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
82
    """A field that handles latitude coordinates (deg, min, sec, bearing)
83
    """
84
    bearing = list("NS")
85
86
    def _validate(self, value):
87
        super(LatitudeCoordinateField, self)._validate(value)
88
89
        # check degrees are within 0 and 90
90
        degrees = value.get("degrees")
91
        degrees = api.to_int(degrees, default=0)
92
        if degrees < 0 or degrees > 90:
93
            msg = t(_("Value for degrees must be within 0 and 90"))
94
            raise ValueError(msg)
95
96
97 View Code Duplication
class LongitudeCoordinateField(CoordinateField):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
98
    """A field that handles longitude coordinates (deg, min, sec, bearing)
99
    """
100
    bearing = list("WE")
101
102
    def _validate(self, value):
103
        super(LongitudeCoordinateField, self)._validate(value)
104
105
        # check degrees are within 0 and 180
106
        degrees = value.get("degrees")
107
        degrees = api.to_int(degrees, default=0)
108
        if degrees < 0 or degrees > 180:
109
            msg = t(_("Value for degrees must be within 0 and 180"))
110
            raise ValueError(msg)
111