summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDiego Elio Pettenò <flameeyes@flameeyes.eu>2018-12-12 23:53:49 +0100
committerDiego Elio Pettenò <flameeyes@flameeyes.eu>2018-12-12 23:53:49 +0100
commit2dcbe101b49dd942adbc78e61bf8011d3e8e1d5c (patch)
treeedc6805eae41aed89613d87e3d85b48099141627
parentSimplify exceptions hierarchy. (diff)
downloadglucometerutils-2dcbe101b49dd942adbc78e61bf8011d3e8e1d5c.tar
glucometerutils-2dcbe101b49dd942adbc78e61bf8011d3e8e1d5c.tar.gz
glucometerutils-2dcbe101b49dd942adbc78e61bf8011d3e8e1d5c.tar.bz2
glucometerutils-2dcbe101b49dd942adbc78e61bf8011d3e8e1d5c.tar.lz
glucometerutils-2dcbe101b49dd942adbc78e61bf8011d3e8e1d5c.tar.xz
glucometerutils-2dcbe101b49dd942adbc78e61bf8011d3e8e1d5c.tar.zst
glucometerutils-2dcbe101b49dd942adbc78e61bf8011d3e8e1d5c.zip
Diffstat (limited to '')
-rw-r--r--.pylintrc12
-rw-r--r--glucometerutils/common.py9
-rw-r--r--glucometerutils/drivers/accuchek_reports.py57
-rw-r--r--glucometerutils/drivers/fsinsulinx.py2
-rw-r--r--glucometerutils/drivers/fslibre.py2
-rw-r--r--glucometerutils/drivers/fsoptium.py101
-rw-r--r--glucometerutils/drivers/fsprecisionneo.py10
-rw-r--r--glucometerutils/drivers/otultra2.py100
-rw-r--r--glucometerutils/drivers/otverio2015.py6
-rw-r--r--glucometerutils/drivers/otverioiq.py2
-rw-r--r--glucometerutils/drivers/sdcodefree.py21
-rwxr-xr-xglucometerutils/glucometer.py57
-rw-r--r--glucometerutils/support/freestyle.py5
-rw-r--r--glucometerutils/support/hiddevice.py10
-rw-r--r--glucometerutils/support/lifescan.py12
-rw-r--r--glucometerutils/support/lifescan_binary_protocol.py20
-rw-r--r--glucometerutils/support/serial.py4
17 files changed, 228 insertions, 202 deletions
diff --git a/.pylintrc b/.pylintrc
new file mode 100644
index 0000000..34485a1
--- /dev/null
+++ b/.pylintrc
@@ -0,0 +1,12 @@
+[MESSAGE CONTROL]
+disable=
+ duplicate-code,
+ too-few-public-methods,
+ too-many-branches,
+ too-many-locals,
+ too-many-nested-blocks,
+ too-many-return-statements,
+ too-many-statements,
+
+[BASIC]
+good-names = i, j, k, e, _
diff --git a/glucometerutils/common.py b/glucometerutils/common.py
index 8ffa724..7d7f0db 100644
--- a/glucometerutils/common.py
+++ b/glucometerutils/common.py
@@ -6,20 +6,17 @@ __email__ = 'flameeyes@flameeyes.eu'
__copyright__ = 'Copyright © 2013, Diego Elio Pettenò'
__license__ = 'MIT'
-import collections
import datetime
import enum
import textwrap
try:
from typing import Sequence, Text
-except:
+except ImportError:
pass
import attr
-from glucometerutils import exceptions
-
class Unit(enum.Enum):
MG_DL = 'mg/dL'
MMOL_L = 'mmol/L'
@@ -56,8 +53,8 @@ def convert_glucose_unit(value, from_unit, to_unit):
if from_unit == Unit.MG_DL:
return round(value / 18.0, 2)
- else:
- return round(value * 18.0, 0)
+
+ return round(value * 18.0, 0)
@attr.s
class GlucoseReading:
diff --git a/glucometerutils/drivers/accuchek_reports.py b/glucometerutils/drivers/accuchek_reports.py
index 49c698d..a29f0c6 100644
--- a/glucometerutils/drivers/accuchek_reports.py
+++ b/glucometerutils/drivers/accuchek_reports.py
@@ -26,8 +26,8 @@ from glucometerutils import common
from glucometerutils import exceptions
_UNIT_MAP = {
- 'mmol/l': common.Unit.MMOL_L,
- 'mg/dl': common.Unit.MG_DL,
+ 'mmol/l': common.Unit.MMOL_L,
+ 'mg/dl': common.Unit.MG_DL,
}
_DATE_CSV_KEY = 'Date'
@@ -47,17 +47,18 @@ _TIME_FORMAT = '%H:%M'
_DATETIME_FORMAT = ' '.join((_DATE_FORMAT, _TIME_FORMAT))
-class Device(object):
+class Device:
def __init__(self, device):
if not device or not os.path.isdir(device):
raise exceptions.CommandLineError(
- '--device parameter is required, should point to mount path for the '
- 'meter.')
+ '--device parameter is required, should point to mount path '
+ 'for the meter.')
- report_files = glob.glob(os.path.join(device, '*', 'Reports', '*.csv'))
+ reports_path = os.path.join(device, '*', 'Reports', '*.csv')
+ report_files = glob.glob(reports_path)
if not report_files:
raise exceptions.ConnectionFailed(
- 'No report file found in path "%s".' % reports_path)
+ 'No report file found in path "%s".' % reports_path)
self.report_file = report_files[0]
@@ -68,23 +69,28 @@ class Device(object):
next(self.report)
return csv.DictReader(
- self.report, delimiter=';', skipinitialspace=True, quoting=csv.QUOTE_NONE)
+ self.report,
+ delimiter=';',
+ skipinitialspace=True,
+ quoting=csv.QUOTE_NONE)
def connect(self):
- self.report = open(self.report_file, 'r', newline='\r\n', encoding='utf-8')
+ self.report = open(
+ self.report_file, 'r', newline='\r\n', encoding='utf-8')
def disconnect(self):
self.report.close()
def get_meter_info(self):
return common.MeterInfo(
- '%s glucometer' % self.get_model(),
- serial_number=self.get_serial_number(),
- native_unit=self.get_glucose_unit())
+ '%s glucometer' % self.get_model(),
+ serial_number=self.get_serial_number(),
+ native_unit=self.get_glucose_unit())
def get_model(self):
# $device/MODEL/Reports/*.csv
- return os.path.basename(os.path.dirname(os.path.dirname(self.report_file)))
+ return os.path.basename(
+ os.path.dirname(os.path.dirname(self.report_file)))
def get_serial_number(self):
self.report.seek(0)
@@ -99,23 +105,24 @@ class Device(object):
return _UNIT_MAP[record[_UNIT_CSV_KEY]]
def get_datetime(self):
- raise NotImplemented
+ raise NotImplementedError
def set_datetime(self, date=None):
- raise NotImplemented
+ raise NotImplementedError
def zero_log(self):
- raise NotImplemented
+ raise NotImplementedError
- def _extract_datetime(self, record):
+ def _extract_datetime(self, record): # pylint: disable=no-self-use
# Date and time are in separate column, but we want to parse them
# together.
date_and_time = ' '.join((record[_DATE_CSV_KEY], record[_TIME_CSV_KEY]))
return datetime.datetime.strptime(date_and_time, _DATETIME_FORMAT)
- def _extract_meal(self, record):
+ def _extract_meal(self, record): # pylint: disable=no-self-use
if record[_AFTER_MEAL_CSV_KEY] and record[_BEFORE_MEAL_CSV_KEY]:
- raise InvalidResponse('Reading cannot be before and after meal.')
+ raise exceptions.InvalidResponse(
+ 'Reading cannot be before and after meal.')
elif record[_AFTER_MEAL_CSV_KEY]:
return common.Meal.AFTER
elif record[_BEFORE_MEAL_CSV_KEY]:
@@ -129,9 +136,9 @@ class Device(object):
continue
yield common.GlucoseReading(
- self._extract_datetime(record),
- common.convert_glucose_unit(
- float(record[_RESULT_CSV_KEY]),
- _UNIT_MAP[record[_UNIT_CSV_KEY]],
- common.Unit.MG_DL),
- meal=self._extract_meal(record))
+ self._extract_datetime(record),
+ common.convert_glucose_unit(
+ float(record[_RESULT_CSV_KEY]),
+ _UNIT_MAP[record[_UNIT_CSV_KEY]],
+ common.Unit.MG_DL),
+ meal=self._extract_meal(record))
diff --git a/glucometerutils/drivers/fsinsulinx.py b/glucometerutils/drivers/fsinsulinx.py
index 15bc131..fbde9ba 100644
--- a/glucometerutils/drivers/fsinsulinx.py
+++ b/glucometerutils/drivers/fsinsulinx.py
@@ -55,7 +55,7 @@ class Device(freestyle.FreeStyleHidDevice):
'Software version: ' + self._get_version(),),
native_unit=self.get_glucose_unit())
- def get_glucose_unit(self):
+ def get_glucose_unit(self): # pylint: disable=no-self-use
"""Returns the glucose unit of the device."""
return common.Unit.MG_DL
diff --git a/glucometerutils/drivers/fslibre.py b/glucometerutils/drivers/fslibre.py
index 6e3988c..5341573 100644
--- a/glucometerutils/drivers/fslibre.py
+++ b/glucometerutils/drivers/fslibre.py
@@ -205,7 +205,7 @@ class Device(freestyle.FreeStyleHidDevice):
"""Overridden function as the command is not compatible."""
return self._send_text_command(b'$sn?').rstrip('\r\n')
- def get_glucose_unit(self):
+ def get_glucose_unit(self): # pylint: disable=no-self-use
"""Returns the glucose unit of the device."""
# TODO(Flameeyes): figure out how to identify the actual unit on the
# device.
diff --git a/glucometerutils/drivers/fsoptium.py b/glucometerutils/drivers/fsoptium.py
index 395494c..618fffa 100644
--- a/glucometerutils/drivers/fsoptium.py
+++ b/glucometerutils/drivers/fsoptium.py
@@ -29,8 +29,8 @@ from glucometerutils.support import serial
_CLOCK_RE = re.compile(
- r'^Clock:\t(?P<month>[A-Z][a-z]{2}) (?P<day>[0-9]{2}) (?P<year>[0-9]{4})\t'
- r'(?P<time>[0-9]{2}:[0-9]{2}:[0-9]{2})$')
+ r'^Clock:\t(?P<month>[A-Z][a-z]{2}) (?P<day>[0-9]{2}) (?P<year>[0-9]{4})\t'
+ r'(?P<time>[0-9]{2}:[0-9]{2}:[0-9]{2})$')
# The reading can be HI (padded to three-characters by a space) if the value was
# over what the meter was supposed to read. Unlike the "Clock:" line, the months
@@ -38,29 +38,33 @@ _CLOCK_RE = re.compile(
# characters, so accept a space or 'e'/'y' at the end of the month name. Also,
# the time does *not* include seconds.
_READING_RE = re.compile(
- r'^(?P<reading>HI |[0-9]{3}) (?P<month>[A-Z][a-z]{2})[ ey] (?P<day>[0-9]{2}) '
- r'(?P<year>[0-9]{4}) (?P<time>[0-9]{2}:[0-9]{2}) (?P<type>[GK]) 0x00$')
+ r'^(?P<reading>HI |[0-9]{3}) '
+ r'(?P<month>[A-Z][a-z]{2})[ ey] '
+ r'(?P<day>[0-9]{2}) '
+ r'(?P<year>[0-9]{4}) '
+ r'(?P<time>[0-9]{2}:[0-9]{2}) '
+ r'(?P<type>[GK]) 0x00$')
_CHECKSUM_RE = re.compile(
- r'^(?P<checksum>0x[0-9A-F]{4}) END$')
+ r'^(?P<checksum>0x[0-9A-F]{4}) END$')
# There are two date format used by the device. One uses three-letters month
# names, and that's easy enough. The other uses three-letters month names,
# except for (at least) July. So ignore the fourth character.
# explicit mapping. Note that the mapping *requires* a trailing whitespace.
_MONTH_MATCHES = {
- 'Jan': 1,
- 'Feb': 2,
- 'Mar': 3,
- 'Apr': 4,
- 'May': 5,
- 'Jun': 6,
- 'Jul': 7,
- 'Aug': 8,
- 'Sep': 9,
- 'Oct': 10,
- 'Nov': 11,
- 'Dec': 12
+ 'Jan': 1,
+ 'Feb': 2,
+ 'Mar': 3,
+ 'Apr': 4,
+ 'May': 5,
+ 'Jun': 6,
+ 'Jul': 7,
+ 'Aug': 8,
+ 'Sep': 9,
+ 'Oct': 10,
+ 'Nov': 11,
+ 'Dec': 12
}
@@ -99,8 +103,8 @@ class Device(serial.SerialDevice):
logging.debug('Received response: %r', response)
- # We always want to decode the output, and remove stray \r\n. Any failure in
- # decoding means the output is invalid anyway.
+ # We always want to decode the output, and remove stray \r\n. Any
+ # failure in decoding means the output is invalid anyway.
decoded_response = [line.decode('ascii').rstrip('\r\n')
for line in response]
return decoded_response
@@ -109,7 +113,7 @@ class Device(serial.SerialDevice):
self._send_command('xmem') # ignore output this time
self._fetch_device_information()
- def disconnect(self):
+ def disconnect(self): # pylint: disable=no-self-use
return
def _fetch_device_information(self):
@@ -126,13 +130,13 @@ class Device(serial.SerialDevice):
self.device_glucose_unit_ = common.Unit.MMOL_L
else: # I only have a mmol/l device, so I can't be sure.
self.device_glucose_unit_ = common.Unit.MG_DL
- # There are more entries: Clock, Market, ROM and Usage, but we don't care
- # for those here.
+ # There are more entries: Clock, Market, ROM and Usage, but we don't
+ # care for those here.
elif parsed_line[0] == 'CMD OK':
return
- # I have not figured out why this happens, but sometimes it's echoing back
- # the commands and not replying to them.
+ # I have not figured out why this happens, but sometimes it's echoing
+ # back the commands and not replying to them.
raise exceptions.ConnectionFailed()
def get_meter_info(self):
@@ -142,11 +146,11 @@ class Device(serial.SerialDevice):
A common.MeterInfo object.
"""
return common.MeterInfo(
- 'Freestyle Optium glucometer',
- serial_number=self.get_serial_number(),
- version_info=(
- 'Software version: ' + self.get_version(),),
- native_unit=self.get_glucose_unit())
+ 'Freestyle Optium glucometer',
+ serial_number=self.get_serial_number(),
+ version_info=(
+ 'Software version: ' + self.get_version(),),
+ native_unit=self.get_glucose_unit())
def get_version(self):
"""Returns an identifier of the firmware version of the glucometer.
@@ -208,11 +212,6 @@ class Device(serial.SerialDevice):
return self.get_datetime()
def zero_log(self):
- """Zeros out the data log of the device.
-
- This function will clear the memory of the device deleting all the readings
- in an irrecoverable way.
- """
raise NotImplementedError
def get_readings(self):
@@ -221,19 +220,20 @@ class Device(serial.SerialDevice):
Args:
unit: The glucose unit to use for the output.
- Yields:
- A tuple (date, value) of the readings in the glucometer. The value is a
- floating point in the unit specified; if no unit is specified, the default
- unit in the glucometer will be used.
+ Yields: A tuple (date, value) of the readings in the glucometer. The
+ value is a floating point in the unit specified; if no unit is
+ specified, the default unit in the glucometer will be used.
Raises:
- exceptions.InvalidResponse: if the response does not match what expected.
+ exceptions.InvalidResponse: if the response does not match what '
+ expected.
+
"""
data = self._send_command('xmem')
- # The first line is empty, the second is the serial number, the third the
- # version, the fourth the current time, and the fifth the record count.. The
- # last line has a checksum and the end.
+ # The first line is empty, the second is the serial number, the third
+ # the version, the fourth the current time, and the fifth the record
+ # count.. The last line has a checksum and the end.
count = int(data[4])
if count != (len(data) - 6):
raise exceptions.InvalidResponse('\n'.join(data))
@@ -244,12 +244,14 @@ class Device(serial.SerialDevice):
raise exceptions.InvalidResponse('\n'.join(data))
expected_checksum = int(checksum_match.group('checksum'), 16)
- # exclude the last line in the checksum calculation, as that's the checksum
- # itself. The final \r\n is added separately.
- calculated_checksum = sum(ord(c) for c in '\r\n'.join(data[:-1])) + 0xd + 0xa
+ # exclude the last line in the checksum calculation, as that's the
+ # checksum itself. The final \r\n is added separately.
+ calculated_checksum = sum(
+ ord(c) for c in '\r\n'.join(data[:-1])) + 0xd + 0xa
if expected_checksum != calculated_checksum:
- raise exceptions.InvalidChecksum(expected_checksum, calculated_checksum)
+ raise exceptions.InvalidChecksum(
+ expected_checksum, calculated_checksum)
for line in data[5:-1]:
match = _READING_RE.match(line)
@@ -257,7 +259,8 @@ class Device(serial.SerialDevice):
raise exceptions.InvalidResponse(line)
if match.group('type') != 'G':
- logging.warning('Non-glucose readings are not supported, ignoring.')
+ logging.warning(
+ 'Non-glucose readings are not supported, ignoring.')
continue
if match.group('reading') == 'HI ':
@@ -273,6 +276,6 @@ class Device(serial.SerialDevice):
timestamp = datetime.datetime(year, month, day, hour, minute)
- # The reading, if present, is always in mg/dL even if the glucometer is
- # set to mmol/L.
+ # The reading, if present, is always in mg/dL even if the glucometer
+ # is set to mmol/L.
yield common.GlucoseReading(timestamp, value)
diff --git a/glucometerutils/drivers/fsprecisionneo.py b/glucometerutils/drivers/fsprecisionneo.py
index 1153908..87076c2 100644
--- a/glucometerutils/drivers/fsprecisionneo.py
+++ b/glucometerutils/drivers/fsprecisionneo.py
@@ -64,7 +64,7 @@ class Device(freestyle.FreeStyleHidDevice):
'Software version: ' + self._get_version(),),
native_unit=self.get_glucose_unit())
- def get_glucose_unit(self):
+ def get_glucose_unit(self): # pylint: disable=no-self-use
"""Returns the glucose unit of the device."""
return common.Unit.MG_DL
@@ -82,10 +82,10 @@ class Device(freestyle.FreeStyleHidDevice):
# Build a _reading object by parsing each of the entries in the raw
# record
values = []
- for v in record:
- if v == "HI":
- v = float("inf")
- values.append(int(v))
+ for value in record:
+ if value == "HI":
+ value = float("inf")
+ values.append(int(value))
raw_reading = _NeoReading._make(values[:len(_NeoReading._fields)])
timestamp = datetime.datetime(
diff --git a/glucometerutils/drivers/otultra2.py b/glucometerutils/drivers/otultra2.py
index a27d333..f26fc45 100644
--- a/glucometerutils/drivers/otultra2.py
+++ b/glucometerutils/drivers/otultra2.py
@@ -17,7 +17,6 @@ __copyright__ = 'Copyright © 2013-2017, Diego Elio Pettenò'
__license__ = 'MIT'
import datetime
-import logging
import re
from glucometerutils import common
@@ -27,32 +26,32 @@ from glucometerutils.support import serial
# The following two hashes are taken directly from LifeScan's documentation
_MEAL_CODES = {
- 'N': common.Meal.NONE,
- 'B': common.Meal.BEFORE,
- 'A': common.Meal.AFTER,
+ 'N': common.Meal.NONE,
+ 'B': common.Meal.BEFORE,
+ 'A': common.Meal.AFTER,
}
_COMMENT_CODES = {
- '00': '', # would be 'No Comment'
- '01': 'Not Enough Food',
- '02': 'Too Much Food',
- '03': 'Mild Exercise',
- '04': 'Hard Exercise',
- '05': 'Medication',
- '06': 'Stress',
- '07': 'Illness',
- '08': 'Feel Hypo',
- '09': 'Menses',
- '10': 'Vacation',
- '11': 'Other',
+ '00': '', # would be 'No Comment'
+ '01': 'Not Enough Food',
+ '02': 'Too Much Food',
+ '03': 'Mild Exercise',
+ '04': 'Hard Exercise',
+ '05': 'Medication',
+ '06': 'Stress',
+ '07': 'Illness',
+ '08': 'Feel Hypo',
+ '09': 'Menses',
+ '10': 'Vacation',
+ '11': 'Other',
}
_DUMP_HEADER_RE = re.compile(
- r'P ([0-9]{3}),"[0-9A-Z]{9}","(?:MG/DL |MMOL/L)"')
+ r'P ([0-9]{3}),"[0-9A-Z]{9}","(?:MG/DL |MMOL/L)"')
_DUMP_LINE_RE = re.compile(
- r'P (?P<datetime>"[A-Z]{3}","[0-9/]{8}","[0-9:]{8} "),'
- r'"(?P<control>[C ]) (?P<value>[0-9]{3})(?P<parityerror>[\? ])",'
- r'"(?P<meal>[NBA])","(?P<comment>0[0-9]|1[01])", 00')
+ r'P (?P<datetime>"[A-Z]{3}","[0-9/]{8}","[0-9:]{8} "),'
+ r'"(?P<control>[C ]) (?P<value>[0-9]{3})(?P<parityerror>[\? ])",'
+ r'"(?P<meal>[NBA])","(?P<comment>0[0-9]|1[01])", 00')
_RESPONSE_MATCH = re.compile(r'^(.+) ([0-9A-F]{4})\r$')
@@ -94,7 +93,7 @@ def _validate_and_strip_checksum(line):
try:
checksum_given = int(checksum_string, 16)
checksum_calculated = _calculate_checksum(
- bytes(response, 'ascii'))
+ bytes(response, 'ascii'))
if checksum_given != checksum_calculated:
raise exceptions.InvalidChecksum(checksum_given,
@@ -105,7 +104,8 @@ def _validate_and_strip_checksum(line):
return response
_DATETIME_RE = re.compile(
- r'^"[A-Z]{3}","([0-9]{2}/[0-9]{2}/[0-9]{2})","([0-9]{2}:[0-9]{2}:[0-9]{2}) "$')
+ r'^"[A-Z]{3}",'
+ r'"([0-9]{2}/[0-9]{2}/[0-9]{2})","([0-9]{2}:[0-9]{2}:[0-9]{2}) "$')
def _parse_datetime(response):
@@ -136,10 +136,10 @@ class Device(serial.SerialDevice):
BAUDRATE = 9600
DEFAULT_CABLE_ID = '067b:2303' # Generic PL2303 cable.
- def connect(self):
+ def connect(self): # pylint: disable=no-self-use
return
- def disconnect(self):
+ def disconnect(self): # pylint: disable=no-self-use
return
def _send_command(self, cmd):
@@ -159,7 +159,8 @@ class Device(serial.SerialDevice):
cmd: command and parameters to send (without newline)
Returns:
- A single line of text that the glucometer responds, without the checksum.
+ A single line of text that the glucometer responds, without the
+ checksum.
"""
self._send_command(cmd)
@@ -173,11 +174,11 @@ class Device(serial.SerialDevice):
A common.MeterInfo object.
"""
return common.MeterInfo(
- 'OneTouch Ultra 2 glucometer',
- serial_number=self.get_serial_number(),
- version_info=(
- 'Software version: ' + self.get_version(),),
- native_unit=self.get_glucose_unit())
+ 'OneTouch Ultra 2 glucometer',
+ serial_number=self.get_serial_number(),
+ version_info=(
+ 'Software version: ' + self.get_version(),),
+ native_unit=self.get_glucose_unit())
def get_version(self):
"""Returns an identifier of the firmware version of the glucometer.
@@ -215,8 +216,8 @@ class Device(serial.SerialDevice):
serial_number = match.group(1)
- # 'Y' at the far right of the serial number is the indication of a OneTouch
- # Ultra2 device, as per specs.
+ # 'Y' at the far right of the serial number is the indication of a
+ # OneTouch Ultra2 device, as per specs.
if serial_number[-1] != 'Y':
raise lifescan.InvalidSerialNumber(serial_number)
@@ -242,15 +243,15 @@ class Device(serial.SerialDevice):
A datetime object built according to the returned response.
"""
response = self._send_oneliner_command(
- 'DMT' + date.strftime('%m/%d/%y %H:%M:%S'))
+ 'DMT' + date.strftime('%m/%d/%y %H:%M:%S'))
return _parse_datetime(response[2:])
def zero_log(self):
"""Zeros out the data log of the device.
- This function will clear the memory of the device deleting all the readings
- in an irrecoverable way.
+ This function will clear the memory of the device deleting all the
+ readings in an irrecoverable way.
"""
response = self._send_oneliner_command('DMZ')
if response != 'Z':
@@ -268,10 +269,10 @@ class Device(serial.SerialDevice):
Raises:
exceptions.InvalidGlucoseUnit: if the unit is not recognized
- OneTouch meters will always dump data in mg/dL because that's their internal
- storage. They will then provide a separate method to read the unit used for
- display. This is not settable by the user in all modern meters.
-
+ OneTouch meters will always dump data in mg/dL because that's their
+ internal storage. They will then provide a separate method to read the
+ unit used for display. This is not settable by the user in all modern
+ meters.
"""
response = self._send_oneliner_command('DMSU?')
@@ -280,10 +281,11 @@ class Device(serial.SerialDevice):
if unit == 'MG/DL ':
return common.Unit.MG_DL
- elif unit == 'MMOL/L':
+
+ if unit == 'MMOL/L':
return common.Unit.MMOL_L
- else:
- raise exceptions.InvalidGlucoseUnit(string)
+
+ raise exceptions.InvalidGlucoseUnit(response)
def get_readings(self):
"""Iterates over the reading values stored in the glucometer.
@@ -292,12 +294,12 @@ class Device(serial.SerialDevice):
unit: The glucose unit to use for the output.
Yields:
- A tuple (date, value) of the readings in the glucometer. The value is a
- floating point in the unit specified; if no unit is specified, the default
- unit in the glucometer will be used.
+ A GlucoseReading object representing the read value.
Raises:
- exceptions.InvalidResponse: if the response does not match what expected.
+ exceptions.InvalidResponse: if the response does not match what
+ expected.
+
"""
self._send_command('DMP')
data = self.serial_.readlines()
@@ -323,7 +325,7 @@ class Device(serial.SerialDevice):
meal = _MEAL_CODES[line_data['meal']]
comment = _COMMENT_CODES[line_data['comment']]
- # OneTouch2 always returns the data in mg/dL even if the glucometer is set
- # to mmol/L, so there is no conversion required.
+ # OneTouch2 always returns the data in mg/dL even if the glucometer
+ # is set to mmol/L, so there is no conversion required.
yield common.GlucoseReading(
- date, float(line_data['value']), meal=meal, comment=comment)
+ date, float(line_data['value']), meal=meal, comment=comment)
diff --git a/glucometerutils/drivers/otverio2015.py b/glucometerutils/drivers/otverio2015.py
index efd4114..3a73e20 100644
--- a/glucometerutils/drivers/otverio2015.py
+++ b/glucometerutils/drivers/otverio2015.py
@@ -43,7 +43,7 @@ _REGISTER_SIZE = 512
_PACKET = construct.Padded(
_REGISTER_SIZE,
- lifescan_binary_protocol.LifeScanPacket(False))
+ lifescan_binary_protocol.LifeScanPacket(False))
_COMMAND_SUCCESS = construct.Const(b'\x03\x06')
@@ -115,7 +115,7 @@ _READ_RECORD_RESPONSE = construct.Struct(
construct.Padding(4),
)
-class Device(object):
+class Device:
def __init__(self, device):
if not device:
raise exceptions.CommandLineError(
@@ -135,7 +135,7 @@ class Device(object):
raise exceptions.ConnectionFailed(
'Device %s is not a LifeScan glucometer.' % self.device_name_)
- def disconnect(self):
+ def disconnect(self): # pylint: disable=no-self-use
return
def _send_request(self, lba, request_format, request_obj, response_format):
diff --git a/glucometerutils/drivers/otverioiq.py b/glucometerutils/drivers/otverioiq.py
index deafed4..67781a7 100644
--- a/glucometerutils/drivers/otverioiq.py
+++ b/glucometerutils/drivers/otverioiq.py
@@ -176,7 +176,7 @@ class Device(serial.SerialDevice):
return response.timestamp
def set_datetime(self, date=datetime.datetime.now()):
- response = self._send_request(
+ self._send_request(
_WRITE_RTC_REQUEST, {
'timestamp': date,
}, _COMMAND_SUCCESS)
diff --git a/glucometerutils/drivers/sdcodefree.py b/glucometerutils/drivers/sdcodefree.py
index 1eba6e6..8e7b29c 100644
--- a/glucometerutils/drivers/sdcodefree.py
+++ b/glucometerutils/drivers/sdcodefree.py
@@ -139,7 +139,7 @@ class Device(serial.SerialDevice):
logging.debug('sending packet: %s', binascii.hexlify(pkt))
self.serial_.write(pkt)
- def connect(self):
+ def connect(self): # pylint: disable=no-self-use
print("Please connect and turn on the device.")
def disconnect(self):
@@ -148,20 +148,20 @@ class Device(serial.SerialDevice):
if response != _DISCONNECTED_MESSAGE:
raise exceptions.InvalidResponse(response=response)
- def get_meter_info(self):
+ def get_meter_info(self): # pylint: disable=no-self-use
return common.MeterInfo('SD CodeFree glucometer')
- def get_version(self):
+ def get_version(self): # pylint: disable=no-self-use
raise NotImplementedError
- def get_serial_number(self):
+ def get_serial_number(self): # pylint: disable=no-self-use
raise NotImplementedError
- def get_glucose_unit(self):
+ def get_glucose_unit(self): # pylint: disable=no-self-use
# Device does not provide information on glucose unit.
return common.Unit.MG_DL
- def get_datetime(self):
+ def get_datetime(self): # pylint: disable=no-self-use
raise NotImplementedError
def set_datetime(self, date=datetime.datetime.now()):
@@ -189,10 +189,11 @@ class Device(serial.SerialDevice):
self.send_message(_FETCH_MESSAGE)
message = self.read_message()
- r = _READING.parse(message)
- logging.debug('received reading: %r', r)
+ reading = _READING.parse(message)
+ logging.debug('received reading: %r', reading)
yield common.GlucoseReading(
datetime.datetime(
- 2000 + r.year, r.month, r.day, r.hour, r.minute),
- r.value, meal=r.meal)
+ 2000 + reading.year, reading.month,
+ reading.day, reading.hour, reading.minute),
+ reading.value, meal=reading.meal)
diff --git a/glucometerutils/glucometer.py b/glucometerutils/glucometer.py
index 97fe80e..49569b0 100755
--- a/glucometerutils/glucometer.py
+++ b/glucometerutils/glucometer.py
@@ -19,58 +19,59 @@ from glucometerutils import exceptions
def main():
if sys.version_info < (3, 4):
raise Exception(
- 'Unsupported Python version, please use at least Python 3.4')
+ 'Unsupported Python version, please use at least Python 3.4')
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest="action")
parser.add_argument(
- '--driver', action='store', required=True,
- help='Select the driver to use for connecting to the glucometer.')
+ '--driver', action='store', required=True,
+ help='Select the driver to use for connecting to the glucometer.')
parser.add_argument(
- '--device', action='store', required=False,
- help=('Select the path to the glucometer device. Some devices require this '
- 'argument, others will try autodetection.'))
+ '--device', action='store', required=False,
+ help=('Select the path to the glucometer device. Some devices require '
+ 'this argument, others will try autodetection.'))
parser.add_argument(
- '--vlog', action='store', required=False, type=int,
- help=('Python logging level. See the levels at '
- 'https://docs.python.org/3/library/logging.html#logging-levels'))
+ '--vlog', action='store', required=False, type=int,
+ help=('Python logging level. See the levels at '
+ 'https://docs.python.org/3/library/logging.html#logging-levels'))
subparsers.add_parser(
- 'help', help=('Display a description of the driver, including supported '
- 'features and known quirks.'))
+ 'help', help=('Display a description of the driver, including '
+ 'supported features and known quirks.'))
subparsers.add_parser(
- 'info', help='Display information about the meter.')
+ 'info', help='Display information about the meter.')
subparsers.add_parser(
- 'zero', help='Zero out the data log of the meter.')
+ 'zero', help='Zero out the data log of the meter.')
parser_dump = subparsers.add_parser(
- 'dump', help='Dump the readings stored in the device.')
+ 'dump', help='Dump the readings stored in the device.')
parser_dump.add_argument(
- '--unit', action='store',
- choices=[unit.value for unit in common.Unit],
- help='Select the unit to use for the dumped data.')
+ '--unit', action='store',
+ choices=[unit.value for unit in common.Unit],
+ help='Select the unit to use for the dumped data.')
parser_dump.add_argument(
- '--with-ketone', action='store_true', default=False,
- help='Enable ketone reading if available on the glucometer.')
+ '--with-ketone', action='store_true', default=False,
+ help='Enable ketone reading if available on the glucometer.')
parser_date = subparsers.add_parser(
- 'datetime', help='Reads or sets the date and time of the glucometer.')
+ 'datetime', help='Reads or sets the date and time of the glucometer.')
parser_date.add_argument(
- '--set', action='store', nargs='?', const='now', default=None,
- help='Set the date rather than just reading it from the device.')
+ '--set', action='store', nargs='?', const='now', default=None,
+ help='Set the date rather than just reading it from the device.')
args = parser.parse_args()
logging.basicConfig(level=args.vlog)
try:
- driver = importlib.import_module('glucometerutils.drivers.' + args.driver)
+ driver = importlib.import_module(
+ 'glucometerutils.drivers.' + args.driver)
except ImportError as e:
logging.error(
- 'Error importing driver "%s", please check your --driver parameter:\n%s',
- args.driver, e)
+ 'Error importing driver "%s", please check your --driver '
+ 'parameter:\n%s', args.driver, e)
return 1
# This check needs to happen before we try to initialize the device, as the
@@ -91,7 +92,7 @@ def main():
except NotImplementedError:
time_str = 'N/A'
print("{device_info}Time: {time}".format(
- device_info=str(device_info), time=time_str))
+ device_info=str(device_info), time=time_str))
elif args.action == 'dump':
unit = args.unit
if unit is None:
@@ -114,7 +115,8 @@ def main():
new_date = date_parser.parse(args.set)
except ImportError:
logging.error(
- 'Unable to import module "dateutil", please install it.')
+ 'Unable to import module "dateutil", '
+ 'please install it.')
return 1
except ValueError:
logging.error('%s: not a valid date', args.set)
@@ -137,3 +139,4 @@ def main():
return 1
device.disconnect()
+ return 0
diff --git a/glucometerutils/support/freestyle.py b/glucometerutils/support/freestyle.py
index 5822d18..2206821 100644
--- a/glucometerutils/support/freestyle.py
+++ b/glucometerutils/support/freestyle.py
@@ -18,7 +18,7 @@ import re
try:
from typing import Iterator, List, Text, Tuple
-except:
+except ImportError:
pass
import construct
@@ -110,8 +110,7 @@ class FreeStyleHidDevice(hiddevice.HidDevice):
usb_packet = _FREESTYLE_MESSAGE.build(
{'message_type': message_type, 'command': command})
- logging.debug('Sending packet: %r', usb_packet
-)
+ logging.debug('Sending packet: %r', usb_packet)
self._write(usb_packet)
def _read_response(self):
diff --git a/glucometerutils/support/hiddevice.py b/glucometerutils/support/hiddevice.py
index 1c5b58d..12debf8 100644
--- a/glucometerutils/support/hiddevice.py
+++ b/glucometerutils/support/hiddevice.py
@@ -11,13 +11,13 @@ import os
try:
from typing import BinaryIO, Optional, Text
-except:
+except ImportError:
pass
from glucometerutils import exceptions
-class HidDevice(object):
+class HidDevice:
"""A device speaking USB HID protocol driver base.
This class does not implement an actual driver by itself, but provides an
@@ -100,6 +100,6 @@ class HidDevice(object):
"""
if self.handle_:
return bytes(self.handle_.read(size))
- else:
- return bytes(self.hidapi_handle_.read(
- size, timeout_ms=self.TIMEOUT_MS))
+
+ return bytes(self.hidapi_handle_.read(
+ size, timeout_ms=self.TIMEOUT_MS))
diff --git a/glucometerutils/support/lifescan.py b/glucometerutils/support/lifescan.py
index 13529ec..1b5cb2d 100644
--- a/glucometerutils/support/lifescan.py
+++ b/glucometerutils/support/lifescan.py
@@ -12,19 +12,21 @@ from glucometerutils import exceptions
class MissingChecksum(exceptions.InvalidResponse):
"""The response misses the expected 4-digits checksum."""
def __init__(self, response):
- self.message = 'Response is missing checksum: %s' % response
+ super(MissingChecksum, self).__init__(
+ 'Response is missing checksum: %s' % response)
class InvalidSerialNumber(exceptions.Error):
"""The serial number is not as expected."""
def __init__(self, serial_number):
- self.message = 'Serial number %s is invalid.' % serial_number
+ super(InvalidSerialNumber, self).__init__(
+ 'Serial number %s is invalid.' % serial_number)
class MalformedCommand(exceptions.InvalidResponse):
def __init__(self, message):
- exceptions.InvalidResponse.__init__(
- self, 'Malformed command: %s' % message)
+ super(MalformedCommand, self).__init__(
+ 'Malformed command: %s' % message)
def crc_ccitt(data):
@@ -49,4 +51,4 @@ def crc_ccitt(data):
crc ^= (((crc << 8) & 0xffff) << 4) & 0xffff
crc ^= (crc & 0xff) << 5
- return (crc & 0xffff)
+ return crc & 0xffff
diff --git a/glucometerutils/support/lifescan_binary_protocol.py b/glucometerutils/support/lifescan_binary_protocol.py
index 8b37726..e08d39f 100644
--- a/glucometerutils/support/lifescan_binary_protocol.py
+++ b/glucometerutils/support/lifescan_binary_protocol.py
@@ -27,7 +27,7 @@ _LINK_CONTROL = construct.BitStruct(
'sequence_number' / construct.Default(construct.Flag, False),
)
-def LifeScanPacket(include_link_control):
+def LifeScanPacket(include_link_control): # pylint: disable=invalid-name
# type: (bool) -> construct.Struct
if include_link_control:
link_control_construct = _LINK_CONTROL
@@ -36,15 +36,15 @@ def LifeScanPacket(include_link_control):
return construct.Struct(
'data' / construct.RawCopy(
- construct.Struct(
- construct.Const(b'\x02'), # stx
- 'length' / construct.Rebuild(
- construct.Byte, lambda this: len(this.message) + 6),
- 'link_control' / link_control_construct,
- 'message' / construct.Bytes(
- lambda this: this.length - 6),
- construct.Const(b'\x03'), # etx
- ),
+ construct.Struct(
+ construct.Const(b'\x02'), # stx
+ 'length' / construct.Rebuild(
+ construct.Byte, lambda this: len(this.message) + 6),
+ 'link_control' / link_control_construct,
+ 'message' / construct.Bytes(
+ lambda this: this.length - 6),
+ construct.Const(b'\x03'), # etx
+ ),
),
'checksum' / construct.Checksum(
construct.Int16ul, lifescan.crc_ccitt, construct.this.data.data),
diff --git a/glucometerutils/support/serial.py b/glucometerutils/support/serial.py
index c46d819..8dfe297 100644
--- a/glucometerutils/support/serial.py
+++ b/glucometerutils/support/serial.py
@@ -11,7 +11,7 @@ import logging
try:
from typing import Optional, Text
-except:
+except ImportError:
pass
import serial
@@ -19,7 +19,7 @@ import serial
from glucometerutils import exceptions
-class SerialDevice(object):
+class SerialDevice:
"""A Serial-connected glucometer driver base.
This class does not implement an actual driver by itself, but provides an