Skip to content

Commit 19f99da

Browse files
committed
refactor: apply style format and lint, use numpy docstring style
1 parent 4f878ef commit 19f99da

14 files changed

Lines changed: 181 additions & 2220 deletions

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ select = [
7777
"B", # flake8-bugbear
7878
"SIM", # flake8-simplify
7979
]
80+
ignore = [
81+
"E501",
82+
]
8083

8184
[tool.pytest.ini_options]
8285
testpaths = [

scratch.ipynb

Lines changed: 0 additions & 2121 deletions
This file was deleted.

src/onc/modules/_DataProductFile.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,19 @@ class _DataProductFile:
1919
Is able to poll and wait if required
2020
"""
2121

22-
def __init__(self, dpRunId: int, index: str, baseUrl: str, token: str, verbosity: str = "INFO"):
22+
def __init__(
23+
self,
24+
dpRunId: int,
25+
index: str,
26+
baseUrl: str,
27+
token: str,
28+
verbosity: str = "INFO",
29+
):
2330
self.verbosity = verbosity
2431
# Use child logger 'onc.poll' consistent with _PollLog
2532
from ._Messages import setup_logger
26-
self._log = setup_logger('onc.poll', verbosity)
33+
34+
self._log = setup_logger("onc.poll", verbosity)
2735
self._retries = 0
2836
self._status = 202
2937
self._downloaded = False
@@ -78,7 +86,9 @@ def download(
7886
response, outPath, filename, overwrite
7987
)
8088
except FileExistsError:
81-
self._log.info(f' Skipping "{self._filePath}": File already exists.')
89+
self._log.info(
90+
f' Skipping "{self._filePath}": File already exists.'
91+
)
8292
self._status = 777
8393

8494
elif self._status == 202: # Still processing, wait and retry

src/onc/modules/_Messages.py

Lines changed: 58 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,53 @@
11
import logging
22
import re
3-
import requests
43
import time
54

6-
REQ_MSG = "Requested: {}" # get request url
7-
RESPONSE_TIME_MSG = "Response received in {} seconds." # requests.elapsed value.
8-
RESPONSE_MSG = "HTTP Response: {} ({})" # Brief description, status code
9-
MULTIPAGE_MSG = ("The requested data quantity is greater than the "
10-
"supplied row limit and will be downloaded over multiple requests.")
5+
import requests
116

7+
REQ_MSG = "Requested: {}" # get request url
8+
RESPONSE_TIME_MSG = "Response received in {} seconds." # requests.elapsed value.
9+
RESPONSE_MSG = "HTTP Response: {} ({})" # Brief description, status code
10+
MULTIPAGE_MSG = (
11+
"The requested data quantity is greater than the "
12+
"supplied row limit and will be downloaded over multiple requests."
13+
)
1214

1315

1416
LEVEL_MAP = {
15-
'CRITICAL': logging.CRITICAL,
16-
'ERROR': logging.ERROR,
17-
'WARNING': logging.WARNING,
18-
'INFO': logging.INFO,
19-
'DEBUG': logging.DEBUG,
17+
"CRITICAL": logging.CRITICAL,
18+
"ERROR": logging.ERROR,
19+
"WARNING": logging.WARNING,
20+
"INFO": logging.INFO,
21+
"DEBUG": logging.DEBUG,
2022
}
2123

2224

2325
class OnclibFormatter(logging.Formatter):
2426
"""
2527
Custom formatter that removes prefix for INFO level logs.
2628
"""
29+
2730
def format(self, record):
2831
if record.levelno == logging.INFO:
2932
return record.getMessage()
3033
return super().format(record)
3134

3235

33-
def setup_logger(logger_name: str = 'onc',
34-
level: int | str = 'INFO') -> logging.Logger:
36+
def setup_logger(logger_name: str = "onc", level: int | str = "INFO") -> logging.Logger:
3537
"""
3638
Set up a logger object for displaying verbose messages to console.
3739
38-
:param logger_name: The unique logger name to use. Can be shared between modules
39-
:param level: The logging level to use. Default is 'INFO'.
40-
:return: The configured logging.Logger object.
40+
Parameters
41+
----------
42+
logger_name : str, optional
43+
The unique logger name to use. Can be shared between modules.
44+
level : int or str, optional
45+
The logging level to use. Default is 'INFO'.
46+
47+
Returns
48+
-------
49+
logging.Logger
50+
The configured logging.Logger object.
4151
"""
4252

4353
# Ensure level is a valid logging level integer
@@ -55,8 +65,10 @@ def setup_logger(logger_name: str = 'onc',
5565
console.setLevel(level)
5666

5767
# Set the logging format.
58-
dtfmt = '%Y-%m-%dT%H:%M:%S'
59-
strfmt = f'%(asctime)s.%(msecs)03dZ | %(name)-12s | %(levelname)-8s | %(message)s'
68+
dtfmt = "%Y-%m-%dT%H:%M:%S"
69+
strfmt = (
70+
"%(asctime)s.%(msecs)03dZ | %(name)-12s | %(levelname)-8s | %(message)s"
71+
)
6072
fmt = OnclibFormatter(strfmt, datefmt=dtfmt)
6173
fmt.converter = time.gmtime
6274

@@ -70,15 +82,21 @@ def setup_logger(logger_name: str = 'onc',
7082
return logger
7183

7284

73-
7485
def scrub_token(input: str) -> str:
7586
"""
7687
Replace a token in a query URL or other string with the string 'REDACTED'
7788
so that users don't accidentally commit their tokens to public repositories
7889
if ONC Info/Warnings are too verbose.
7990
80-
:param input: An Oceans 3.0 API URL or string with a token query parameter.
81-
:return: A scrubbed url.
91+
Parameters
92+
----------
93+
input : str
94+
An Oceans 3.0 API URL or string with a token query parameter.
95+
96+
Returns
97+
-------
98+
str
99+
A scrubbed url.
82100
"""
83101
return re.sub(r"([?&]token=)[a-f0-9-]{36}", r"\1REDACTED", input)
84102

@@ -87,9 +105,17 @@ def build_error_message(response: requests.Response, redact_token: bool) -> str:
87105
"""
88106
Build an error message from a requests.Response object.
89107
90-
:param response: A requests.Response object.
91-
:param redact_token: If true, redact tokens before returning an error message.
92-
:return: An error message.
108+
Parameters
109+
----------
110+
response : requests.Response
111+
A requests.Response object.
112+
redact_token : bool
113+
If true, redact tokens before returning an error message.
114+
115+
Returns
116+
-------
117+
str
118+
An error message.
93119
"""
94120
payload = response.json()
95121
message = payload.get("message")
@@ -98,15 +124,16 @@ def build_error_message(response: requests.Response, redact_token: bool) -> str:
98124
errors = payload["errors"]
99125
error_messages = []
100126
for error in errors:
101-
emsg = (f"(API Error Code {error['errorCode']}) "
102-
f"{error['errorMessage']} for query parameter(s) "
103-
f"'{error['parameter']}'.")
127+
emsg = (
128+
f"(API Error Code {error['errorCode']}) "
129+
f"{error['errorMessage']} for query parameter(s) "
130+
f"'{error['parameter']}'."
131+
)
104132
error_messages.append(emsg)
105-
error_message = '\n'.join(error_messages)
133+
error_message = "\n".join(error_messages)
106134
else:
107135
error_message = None
108-
msg = '\n'.join([m for m in (message, error_message) if m is not None])
109-
if redact_token is True and 'token=' in msg:
136+
msg = "\n".join([m for m in (message, error_message) if m is not None])
137+
if redact_token is True and "token=" in msg:
110138
msg = scrub_token(msg)
111139
return msg
112-

src/onc/modules/_MultiPage.py

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,39 +4,37 @@
44
from time import time
55

66
import dateutil.parser
7-
import humanize
7+
from onc.modules._Messages import (
8+
setup_logger,
9+
)
810

911
from ._util import _formatDuration
1012

11-
from onc.modules._Messages import (setup_logger, MULTIPAGE_MSG,
12-
build_error_message,
13-
scrub_token,
14-
REQ_MSG,
15-
RESPONSE_TIME_MSG,
16-
RESPONSE_MSG)
17-
18-
1913

2014
# Handles data multi-page downloads (scalardata, rawdata, archivefiles)
2115
class _MultiPage:
2216
def __init__(self, parent: object):
2317
self.parent = weakref.ref(parent)
2418
self.result = None
25-
self._log = setup_logger('onc.multi', self._config('verbosity') or 'INFO')
19+
self._log = setup_logger("onc.multi", self._config("verbosity") or "INFO")
2620

2721
def _config(self, key):
2822
p = self.parent()
2923
if p is None:
3024
return None
31-
if hasattr(p, '_config'):
25+
if hasattr(p, "_config"):
3226
return p._config(key)
3327
return getattr(p, key, None)
3428

3529
def getAllPages(self, service: str, url: str, filters: dict):
3630
"""
3731
Requests all pages from the service, with the url and filters
3832
Multiple pages will be downloaded until completed
39-
@return: Service response with concatenated data for all pages obtained
33+
34+
Returns
35+
-------
36+
dict
37+
Service response with concatenated data for all pages obtained.
4038
"""
4139
# pop archivefiles extension
4240
extension = None
@@ -48,28 +46,38 @@ def getAllPages(self, service: str, url: str, filters: dict):
4846
start = time()
4947
response, responseTime = self._doPageRequest(url, filters, service, extension)
5048

51-
if isinstance(response,dict):
49+
if isinstance(response, dict):
5250
rNext = response["next"]
5351

5452
if rNext is not None:
55-
self._log.info("The requested data quantity is greater than the supplied "
56-
"row limit and will be downloaded over multiple requests.")
53+
self._log.info(
54+
"The requested data quantity is greater than the supplied "
55+
"row limit and will be downloaded over multiple requests."
56+
)
5757

5858
pageCount = 1
5959
pageEstimate = self._estimatePages(response, service)
6060
if pageEstimate > 0:
6161
# Exclude the first page when calculating the time estimation
6262
timeEstimate = _formatDuration((pageEstimate - 1) * responseTime)
63-
self._log.info(f'Download time for page {pageCount}: {round(responseTime,2)} seconds')
64-
self._log.info(f'Est. number of pages remaining for download: {pageEstimate-1}')
65-
self._log.info(f'Est. number of seconds to download remaining data: {timeEstimate}')
63+
self._log.info(
64+
f"Download time for page {pageCount}: {round(responseTime, 2)} seconds"
65+
)
66+
self._log.info(
67+
f"Est. number of pages remaining for download: {pageEstimate - 1}"
68+
)
69+
self._log.info(
70+
f"Est. number of seconds to download remaining data: {timeEstimate}"
71+
)
6672

6773
# keep downloading pages until next is None
6874
while rNext is not None:
6975
pageCount += 1
7076
rowCount = self._rowCount(response, service)
7177

72-
self._log.info(f" Submitting request for page {pageCount} ({rowCount} samples)...")
78+
self._log.info(
79+
f" Submitting request for page {pageCount} ({rowCount} samples)..."
80+
)
7381

7482
nextResponse, nextTime = self._doPageRequest(
7583
url, rNext["parameters"], service, extension
@@ -81,7 +89,9 @@ def getAllPages(self, service: str, url: str, filters: dict):
8189

8290
totalTime = _formatDuration(time() - start)
8391

84-
self._log.info(f" Downloaded {self._rowCount(response, service):d} total samples in {totalTime}.")
92+
self._log.info(
93+
f" Downloaded {self._rowCount(response, service):d} total samples in {totalTime}."
94+
)
8595
response["next"] = None
8696

8797
return response
@@ -92,8 +102,22 @@ def _doPageRequest(
92102
"""
93103
Wraps the _doRequest method
94104
Performs additional processing of the response for certain services
95-
@param extension: Only provide for archivefiles filtering
96-
Returns a tuple (jsonResponse, duration)
105+
106+
Parameters
107+
----------
108+
url : str
109+
API endpoint URL.
110+
filters : dict
111+
Filters for the request.
112+
service : str
113+
Name of the service (e.g. archivefile).
114+
extension : str, optional
115+
Only provide for archivefiles filtering.
116+
117+
Returns
118+
-------
119+
tuple
120+
(jsonResponse, duration)
97121
"""
98122
if service.startswith("archivefile"):
99123
response, duration = self.parent()._doRequest(url, filters, getTime=True)

src/onc/modules/_OncArchive.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from ._MultiPage import _MultiPage
88
from ._OncService import _OncService
9-
from ._util import _createErrorMessage, _formatDuration, saveAsFile
9+
from ._util import _formatDuration, saveAsFile
1010

1111

1212
class _OncArchive(_OncService):
@@ -17,7 +17,6 @@ class _OncArchive(_OncService):
1717
def __init__(self, parent: object):
1818
super().__init__(parent)
1919

20-
2120
def getArchivefileByLocation(self, filters: dict, allPages: bool):
2221
"""
2322
Return a list of archived files for a device category in a location.
@@ -75,6 +74,7 @@ def downloadArchivefile(self, filename: str = "", overwrite: bool = False):
7574

7675
else:
7776
from ._Messages import build_error_message
77+
7878
self._log.error(build_error_message(response, self._config("redact_token")))
7979
response.raise_for_status()
8080

0 commit comments

Comments
 (0)