Passed
Pull Request — main (#221)
by
unknown
04:24
created

pocketutils.misc.klgists.smart_log_callback()   B

Complexity

Conditions 6

Size

Total Lines 14
Code Lines 13

Duplication

Lines 12
Ratio 85.71 %

Importance

Changes 0
Metric Value
cc 6
eloc 13
nop 3
dl 12
loc 14
rs 8.6666
c 0
b 0
f 0
1
import typing
0 ignored issues
show
introduced by
Missing module docstring
Loading history...
2
import os, io, shutil, gzip, platform, re
0 ignored issues
show
introduced by
Multiple imports on one line (os, io, shutil, gzip, platform, re)
Loading history...
3
from enum import Enum
4
5
from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError
0 ignored issues
show
Bug introduced by
The name core does not seem to exist in module pocketutils.
Loading history...
6
7
import json, sys
0 ignored issues
show
introduced by
Multiple imports on one line (json, sys)
Loading history...
introduced by
standard import "import json, sys" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
8
import unicodedata
0 ignored issues
show
introduced by
standard import "import unicodedata" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
9
from itertools import chain
0 ignored issues
show
introduced by
standard import "from itertools import chain" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
10
import signal
0 ignored issues
show
introduced by
standard import "import signal" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
11
import operator
0 ignored issues
show
introduced by
standard import "import operator" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
12
from datetime import date, datetime
0 ignored issues
show
introduced by
standard import "from datetime import date, datetime" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
13
from typing import Callable, TypeVar, Iterator, Iterable, Optional, List, Any, Sequence, Mapping, Dict, ItemsView, KeysView, ValuesView, Tuple, Union
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (149/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
introduced by
standard import "from typing import Callable, TypeVar, Iterator, Iterable, Optional, List, Any, Sequence, Mapping, Dict, ItemsView, KeysView, ValuesView, Tuple, Union" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
14
from hurry.filesize import size as hsize
0 ignored issues
show
introduced by
Unable to import 'hurry.filesize'
Loading history...
15
16
from pocketutils.core.exceptions import LookupFailedError, MultipleMatchesError, ParsingError, ResourceError, MissingConfigKeyError, \
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (134/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Bug introduced by
The name core does not seem to exist in module pocketutils.
Loading history...
Unused Code introduced by
Unused MissingConfigKeyError imported from pocketutils.core.exceptions
Loading history...
introduced by
Imports from package pocketutils are not grouped
Loading history...
17
NaturalExpectedError, HashValidationError, FileDoesNotExistError
18
19
import logging
0 ignored issues
show
introduced by
standard import "import logging" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
20
import subprocess
0 ignored issues
show
introduced by
standard import "import subprocess" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
21
from subprocess import Popen, PIPE
0 ignored issues
show
introduced by
standard import "from subprocess import Popen, PIPE" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
22
from queue import Queue
0 ignored issues
show
introduced by
standard import "from queue import Queue" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
23
from threading import Thread
0 ignored issues
show
introduced by
standard import "from threading import Thread" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
24
from deprecated import deprecated
0 ignored issues
show
introduced by
Unable to import 'deprecated'
Loading history...
25
26
import datetime
0 ignored issues
show
Unused Code introduced by
The import datetime was already done on line 12. You should be able to
remove this line.
Loading history...
introduced by
standard import "import datetime" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
27
#from datetime import datetime
28
from subprocess import Popen, PIPE
0 ignored issues
show
Unused Code introduced by
The import Popen was already done on line 21. You should be able to
remove this line.
Loading history...
Unused Code introduced by
The import PIPE was already done on line 21. You should be able to
remove this line.
Loading history...
introduced by
standard import "from subprocess import Popen, PIPE" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
introduced by
Imports from package subprocess are not grouped
Loading history...
29
from infix import shift_infix, mod_infix, sub_infix
0 ignored issues
show
introduced by
Unable to import 'infix'
Loading history...
Unused Code introduced by
Unused mod_infix imported from infix
Loading history...
Unused Code introduced by
Unused sub_infix imported from infix
Loading history...
30
31
from colorama import Fore
0 ignored issues
show
introduced by
Unable to import 'colorama'
Loading history...
32
import shutil
0 ignored issues
show
Unused Code introduced by
The import shutil was already done on line 2. You should be able to
remove this line.
Loading history...
introduced by
standard import "import shutil" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
introduced by
Imports from package shutil are not grouped
Loading history...
33
import argparse
0 ignored issues
show
introduced by
standard import "import argparse" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
34
35
import hashlib
0 ignored issues
show
introduced by
standard import "import hashlib" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
36
import codecs
0 ignored issues
show
introduced by
standard import "import codecs" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
37
import gzip
0 ignored issues
show
Unused Code introduced by
The import gzip was already done on line 2. You should be able to
remove this line.
Loading history...
introduced by
standard import "import gzip" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
introduced by
Imports from package gzip are not grouped
Loading history...
38
39
import struct
0 ignored issues
show
introduced by
standard import "import struct" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
40
from array import array
0 ignored issues
show
Unused Code introduced by
Unused array imported from array
Loading history...
introduced by
standard import "from array import array" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
41
import numpy as np
0 ignored issues
show
introduced by
Unable to import 'numpy'
Loading history...
42
43
def blob_to_byte_array(bytes_obj: bytes):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
44
	return _blob_to_dt(bytes_obj, 'b', 1, np.ubyte) + 128
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
45
def blob_to_float_array(bytes_obj: bytes):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
46
	return _blob_to_dt(bytes_obj, 'f', 4, np.float32)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
47
def blob_to_double_array(bytes_obj: bytes):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
48
	return _blob_to_dt(bytes_obj, 'd', 8, np.float64)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
49
def blob_to_short_array(bytes_obj: bytes):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
50
	return _blob_to_dt(bytes_obj, 'H', 2, np.int16)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
51
def blob_to_int_array(bytes_obj: bytes):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
52
	return _blob_to_dt(bytes_obj, 'I', 4, np.int32)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
53
def blob_to_long_array(bytes_obj: bytes):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
54
	return _blob_to_dt(bytes_obj, 'Q', 8, np.int64)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
55
def _blob_to_dt(bytes_obj: bytes, data_type_str: str, data_type_len: int, dtype):
56
	return np.array(next(iter(struct.iter_unpack('>' + data_type_str * int(len(bytes_obj)/data_type_len), bytes_obj))), dtype=dtype)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (129/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
57
58
class FileHasher:
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
59
60
	def __init__(self, algorithm: Callable[[], Any]=hashlib.sha1, extension: str='.sha1', buffer_size: int = 16*1024):
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (115/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style introduced by
Exactly one space required around keyword argument assignment
Loading history...
61
		self.algorithm = algorithm
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
62
		self.extension = extension
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
63
		self.buffer_size = buffer_size
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
64
65
	def hashsum(self, file_name: str) -> str:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
66
		alg = self.algorithm()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
67
		with open(file_name, 'rb') as f:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "f" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
68
			for chunk in iter(lambda: f.read(self.buffer_size), b''):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
69
				alg.update(chunk)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
70
		return alg.hexdigest()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
71
72
	def add_hash(self, file_name: str) -> None:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
73
		with open(file_name + self.extension, 'w', encoding="utf8") as f:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "f" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
74
			s = self.hashsum(file_name)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "s" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
75
			f.write(s)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
76
77
	def check_hash(self, file_name: str) -> bool:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
78
		if not os.path.isfile(file_name + self.extension): return False 
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
79
		with open(file_name + self.extension, 'r', encoding="utf8") as f:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "f" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
80
			hash_str = f.read().split()[0] # check only the first thing on the line before any spaces
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
81
			return hash_str == self.hashsum(file_name)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
82
83
	def check_and_open(self, file_name: str, *args):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
84
		return self._o(file_name, opener=lambda f: codecs.open(f, encoding='utf-8'), *args)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
85
86
	def check_and_open_gzip(self, file_name: str, *args):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
87
		return self._o(file_name, opener=gzip.open, *args)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
88
89
	def _o(self, file_name: str, opener, *args):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
90
		if not os.path.isfile(file_name + self.extension):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
91
			raise FileDoesNotExistError("Hash for file {} does not exist".format(file_name))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
92
		with open(file_name + self.extension, 'r', encoding="utf8") as f:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "f" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
93
			if f.read() != self.hashsum(file_name):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
94
				raise HashValidationError("Hash for file {} does not match".format(file_name))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
95
		return opener(file_name, *args)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
96
97
def mkdatetime(s: str) -> datetime:
0 ignored issues
show
Coding Style Naming introduced by
Argument name "s" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
introduced by
Missing function or method docstring
Loading history...
98
	return datetime.strptime(s.replace(' ', 'T'), "%Y-%m-%dT%H:%M:%S")
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Bug introduced by
The Module datetime does not seem to have a member named strptime.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
99
100
def now() -> datetime:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
101
	return datetime.datetime.now()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
102
103
def today() -> datetime:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
104
	return datetime.datetime.today()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
105
106
def mkdate(s: str) -> datetime:
0 ignored issues
show
Coding Style Naming introduced by
Argument name "s" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
introduced by
Missing function or method docstring
Loading history...
107
	return datetime.strptime(s, "%Y-%m-%d")
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Bug introduced by
The Module datetime does not seem to have a member named strptime.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
108
109
def this_year(s: str) -> datetime:
0 ignored issues
show
Coding Style Naming introduced by
Argument name "s" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
introduced by
Missing function or method docstring
Loading history...
110
	return datetime.strptime(s, "%Y")
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Bug introduced by
The Module datetime does not seem to have a member named strptime.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
111
112
def year_range(year: int) -> Tuple[datetime.datetime, datetime.datetime]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
113
	return (
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
114
		datetime(year, 1, 1, 0, 0, 0, 0),
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation (remove 4 spaces).
Loading history...
Bug introduced by
datetime does not seem to be callable.
Loading history...
115
		datetime(year, 12, 31, 23, 59, 59, 999)
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation (remove 4 spaces).
Loading history...
Bug introduced by
datetime does not seem to be callable.
Loading history...
116
	)
117
118
@shift_infix
119
def approxeq(a, b):
0 ignored issues
show
Coding Style Naming introduced by
Argument name "a" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Coding Style Naming introduced by
Argument name "b" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
120
	"""This takes 1e-09 * max(abs(a), abs(b)), which may not be appropriate."""
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
121
	"""Example: 5 <<approxeq>> 5.000000000000001"""
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Unused Code introduced by
This string statement has no effect and could be removed.
Loading history...
122
	return abs(a - b) < 1e-09 * max(abs(a), abs(b))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
123
124
class TomlData:
125
	"""A better TOML data structure than a plain dict.
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
126
	Usage examples:
127
		data = TomlData({'x': {'y': {'z': 155}}})
128
		print(data['x.y.z'])   # prints 155
129
		data.sub('x.y')        # returns a new TomlData for {'z': 155}
130
		data.nested_keys()     # returns all keys and sub-keys
131
	"""
132
	def __init__(self, top_level_item: Dict[str, object]):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
133
		assert top_level_item is not None
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
134
		self.top = top_level_item
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
135
136
	def __str__(self) -> str:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
137
		return repr(self)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
138
	def __repr__(self) -> str:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
139
		return "TomlData({})".format(str(self.top))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
140
141
	def __getitem__(self, key: str) -> Dict[str, object]:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
142
		return self.sub(key).top
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
143
144
		def __contains__(self, key: str) -> bool:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Unused Code introduced by
This code does not seem to be reachable.
Loading history...
Unused Code introduced by
The variable __contains__ seems to be unused.
Loading history...
145
			try:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
146
					self.sub(key)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
147
					return True
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
148
			except AttributeError: return False
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
149
150
	def get_str(self, key: str) -> str:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
151
		return str(self.__as(key, str))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
152
153
	def get_int(self, key: str) -> int:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
154
		# noinspection PyTypeChecker
155
		return int(self.__as(key, int))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
156
157
	def get_bool(self, key: str) -> int:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
158
		# noinspection PyTypeChecker
159
		return bool(self.__as(key, bool))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
160
161
	def get_str_list(self, key: str) -> List[str]:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
162
		return self.__as_list(key, str)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
163
164
	def get_int_list(self, key: str) -> List[int]:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
165
		return self.__as_list(key, int)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
166
167
	def get_float_list(self, key: str) -> List[int]:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
168
		return self.__as_list(key, int)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
169
170
	def get_bool_list(self, key: str) -> List[int]:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
171
		return self.__as_list(key, bool)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
172
173
	def get_float(self, key: str) -> int:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
174
		# noinspection PyTypeChecker
175
		return int(self.__as(key, float))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
176
177
	def __as_list(self, key: str, clazz):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
178
		def to(v):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Function name "to" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Coding Style Naming introduced by
Argument name "v" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
179
			if not isinstance(v, clazz):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
180
				raise TypeError("{}={} is a {}, not {}".format(key, v, type(v), clazz))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
181
			return [to(v) for v in self[key]]
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
182
183
	def __as(self, key: str, clazz):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
184
		v = self[key]
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "v" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
185
		if isinstance(v, clazz):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
unused-code introduced by
Unnecessary "else" after "return"
Loading history...
186
			return v
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
187
		else:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
188
			raise TypeError("{}={} is a {}, not {}".format(key, v, type(v), clazz))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
189
190
	def sub(self, key: str):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
191
		"""Returns a new TomlData with its top set to items[1][2]..."""
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
192
		items = key.split('.')
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
193
		item = self.top
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
194
		for i, s in enumerate(items):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "s" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
195
			if s not in item: raise MissingConfigEntry(
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable MissingConfigEntry does not seem to be defined.
Loading history...
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
Comprehensibility Best Practice introduced by
Undefined variable 'MissingConfigEntry'
Loading history...
196
				"{} is not in the TOML; failed at {}"
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block.
Loading history...
197
				.format(key, '.'.join(items[:i+1]))
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block.
Loading history...
198
			)
199
			item = item[s]
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
200
		return TomlData(item)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
201
202
	def items(self) -> ItemsView[str, object]:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
203
		return self.top.items()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
204
205
	def keys(self) -> KeysView[str]:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
206
		return self.top.keys()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
207
208
	def values(self) -> ValuesView[object]:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
209
		return self.top.values()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
210
211
	def nested_keys(self, separator='.') -> Iterator[str]:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
212
		for lst in self.nested_key_lists(self.top):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
213
			yield separator.join(lst)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
214
215
	def nested_key_lists(self, dictionary: Dict[str, object], prefix=None) -> Iterator[List[str]]:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
216
217
		prefix = prefix[:] if prefix else []
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
218
219
		if isinstance(dictionary, dict):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
220
			for key, value in dictionary.items():
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
221
222
				if isinstance(value, dict):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
223
					for result in self.nested_key_lists(value, [key] + prefix): yield result
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
224
				else: yield prefix + [key]
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
225
226
		else: yield dictionary
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
227
228
229
def git_commit_hash(git_repo_dir: str='.') -> str:
0 ignored issues
show
Coding Style introduced by
Exactly one space required around keyword argument assignment
Loading history...
230
	"""Gets the hex of the most recent Git commit hash in git_repo_dir."""
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
231
	p = Popen(['git', 'rev-parse', 'HEAD'], stdout=PIPE, cwd=git_repo_dir)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "p" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
232
	(out, err) = p.communicate()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Unused Code introduced by
The variable err seems to be unused.
Loading history...
233
	exit_code = p.wait()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
234
	if exit_code != 0: raise ValueError("Got nonzero exit code {} from git rev-parse".format(exit_code))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (101/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
235
	return out.decode('utf-8').rstrip()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
236
237
@deprecated(reason="Use klgists.common.flexible_logger instead.")
238
def init_logger(
0 ignored issues
show
best-practice introduced by
Too many arguments (6/5)
Loading history...
239
	log_path: Optional[str]=None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block.
Loading history...
Coding Style introduced by
Exactly one space required around keyword argument assignment
Loading history...
240
	format_str: str='%(asctime)s %(levelname)-8s: %(message)s',
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block.
Loading history...
Coding Style introduced by
Exactly one space required around keyword argument assignment
Loading history...
241
	to_std: bool=True,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block.
Loading history...
Coding Style introduced by
Exactly one space required around keyword argument assignment
Loading history...
242
	child_logger_name: Optional[str]=None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block.
Loading history...
Coding Style introduced by
Exactly one space required around keyword argument assignment
Loading history...
243
	std_level = logging.INFO,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block.
Loading history...
Coding Style introduced by
No space allowed around keyword argument assignment
Loading history...
244
	file_level = logging.DEBUG
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block.
Loading history...
Coding Style introduced by
No space allowed around keyword argument assignment
Loading history...
245
):
246
	"""Initializes a logger that can write to a log file and/or stdout."""
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
247
248
	if log_path is not None and not os.path.exists(os.path.dirname(log_path)):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
249
		os.mkdir(os.path.dirname(log_path))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
250
251
	if child_logger_name is None:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
252
		logger = logging.getLogger()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Comprehensibility Bug introduced by
logger is re-defining a name which is already available in the outer-scope (previously defined on line 297).

It is generally a bad practice to shadow variables from the outer-scope. In most cases, this is done unintentionally and might lead to unexpected behavior:

param = 5

class Foo:
    def __init__(self, param):   # "param" would be flagged here
        self.param = param
Loading history...
253
	else:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
254
		logger = logging.getLogger(child_logger_name)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
255
	logger.setLevel(logging.NOTSET)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
256
257
	formatter = logging.Formatter(format_str)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
258
259
	if log_path is not None:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
260
		handler = logging.FileHandler(log_path, encoding='utf-8')
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
261
		handler.setLevel(file_level)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
262
		handler.setFormatter(formatter)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
263
		logger.addHandler(handler)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
264
265
	if to_std:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
266
		handler = logging.StreamHandler()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
267
		handler.setLevel(std_level)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
268
		handler.setFormatter(formatter)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
269
		logger.addHandler(handler)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
270
271
import datetime
0 ignored issues
show
Unused Code introduced by
The import datetime was already done on line 12. You should be able to
remove this line.
Loading history...
introduced by
Import "import datetime" should be placed at the top of the module
Loading history...
introduced by
standard import "import datetime" should be placed before "from pocketutils.core.exceptions import PathIsNotADirError, MissingResourceError"
Loading history...
introduced by
Imports from package datetime are not grouped
Loading history...
272
def format_time(time: datetime) -> str:
273
	"""Standard timestamp format. Ex: 2016-05-02_22_35_56."""
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
274
	return time.strftime("%Y-%m-%d_%H-%M-%S")
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
275
276
def timestamp() -> str:
277
	"""Standard timestamp of time now. Ex: 2016-05-02_22_35_56."""
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
278
	return format_time(datetime.datetime.now())
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
279
280
def timestamp_path(path: str) -> str:
281
	"""Standard way to label a file path with a timestamp."""
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
282
	return "{}-{}".format(path, timestamp())
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
283
284
285
def nice_time(n_ms: int) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
286
	length = datetime.datetime(1, 1, 1) + datetime.timedelta(milliseconds=n_ms)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
287
	if n_ms < 1000 * 60 * 60 * 24:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
unused-code introduced by
Unnecessary "else" after "return"
Loading history...
288
		return "{}h, {}m, {}s".format(length.hour, length.minute, length.second)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
289
	else:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
290
		return "{}d, {}h, {}m, {}s".format(length.day, length.hour, length.minute, length.second)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
291
292
293
def parse_local_iso_datetime(z: str) -> datetime:
0 ignored issues
show
Coding Style Naming introduced by
Argument name "z" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
introduced by
Missing function or method docstring
Loading history...
294
	return datetime.datetime.strptime(z, '%Y-%m-%dT%H:%M:%S.%f')
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
295
296
297
logger = logging.getLogger(__name__)
298
299
class PipeType(Enum):
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
300
	STDOUT = 1
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
301
	STDERR = 2
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
302
303
def _disp(out, ell, name):
304
	out = out.strip()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
305
	if '\n' in out:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
306
		ell(name + ":\n<<=====\n" + out + '\n=====>>')
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
307
	elif len(out) > 0:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
308
		ell(name + ": <<===== " + out + " =====>>")
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
309
	else:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
310
		ell(name + ": <no output>")
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
311
	
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
312
313
def _log(out, err, ell):
314
	_disp(out, ell, "stdout")
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
315
	_disp(err, ell, "stderr")
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
316
317
	
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
318
def smart_log_callback(source, line, prefix: str = '') -> None:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
Unused Code introduced by
The argument source seems to be unused.
Loading history...
319
	line = line.decode('utf-8')
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
320 View Code Duplication
	if line.startswith('FATAL:'):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
321
		logger.fatal(prefix + line)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
322
	elif line.startswith('ERROR:'):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
323
		logger.error(prefix + line)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
324
	elif line.startswith('WARNING:'):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
325
		logger.warning(prefix + line)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
326
	elif line.startswith('INFO:'):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
327
		logger.info(prefix + line)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
328
	elif line.startswith('DEBUG:'):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
329
		logger.debug(prefix + line)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
330
	else:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
331
		logger.debug(prefix + line)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
332
333
334
def _reader(pipe_type, pipe, queue):
335
	try:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
336
		with pipe:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
337
			for line in iter(pipe.readline, b''):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
338
				queue.put((pipe_type, line))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
339
	finally:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
340
		queue.put(None)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
341
	
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
342
def stream_cmd_call(cmd: List[str], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell_cmd: str=None, cwd: Optional[str] = None, timeout_secs: Optional[float] = None, log_callback: Callable[[PipeType, bytes], None] = None, bufsize: Optional[int] = None) -> None:
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (265/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Coding Style introduced by
Exactly one space required around keyword argument assignment
Loading history...
best-practice introduced by
Too many arguments (8/5)
Loading history...
Unused Code introduced by
The argument stdout seems to be unused.
Loading history...
Unused Code introduced by
The argument stderr seems to be unused.
Loading history...
343
	"""Calls an external command, waits, and throws a ResourceError for nonzero exit codes.
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
344
	Returns (stdout, stderr).
345
	The user can optionally provide a shell to run the command with, e.g. "powershell.exe" 
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
346
	"""
347
	if log_callback is None:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
348
		log_callback = smart_log_callback
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
349
	cmd = [str(p) for p in cmd]
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
350
	if shell_cmd:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
351
		cmd = [shell_cmd] + cmd
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
352
	logger.debug("Streaming '{}'".format(' '.join(cmd)))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Use lazy % formatting in logging functions
Loading history...
353
	
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
354
	p = subprocess.Popen(cmd, stdout=PIPE, stderr=PIPE, cwd=cwd, bufsize=bufsize)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "p" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
355
	try:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
356
		q = Queue()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "q" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
357
		Thread(target=_reader, args=[PipeType.STDOUT, p.stdout, q]).start()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
358
		Thread(target=_reader, args=[PipeType.STDERR, p.stderr, q]).start()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
359
		for _ in range(2):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
360
			for source, line in iter(q.get, None):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
361
				log_callback(source, line)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
362
		exit_code = p.wait(timeout=timeout_secs)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
363
	finally:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
364
		p.kill()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
365
	if exit_code != 0:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
366
		raise ResourceError("Got nonzero exit code {} from '{}'".format(exit_code, ' '.join(cmd)), cmd, exit_code, '<<unknown>>', '<<unknown>>')
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (138/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
367
	
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
368
369
def wrap_cmd_call(cmd: List[str], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell_cmd: str=None, cwd: Optional[str] = None, timeout_secs: Optional[float] = None) -> (str, str):
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (182/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Coding Style introduced by
Exactly one space required around keyword argument assignment
Loading history...
best-practice introduced by
Too many arguments (6/5)
Loading history...
370
	"""Calls an external command, waits, and throws a ResourceError for nonzero exit codes.
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
371
	Returns (stdout, stderr).
372
	The user can optionally provide a shell to run the command with, e.g. "powershell.exe" 
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
373
	"""
374
	cmd = [str(p) for p in cmd]
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
375
	if shell_cmd:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
376
		cmd = [shell_cmd] + cmd
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
377
	logger.debug("Calling '{}'".format(' '.join(cmd)))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Use lazy % formatting in logging functions
Loading history...
378
	p = subprocess.Popen(cmd, stdout=stdout, stderr=stderr, cwd=cwd)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "p" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
379
	out, err, exit_code = None, None, None
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
380
	try:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
381
		(out, err) = p.communicate(timeout=timeout_secs)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
382
		out = out.decode('utf-8')
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
383
		err = err.decode('utf-8')
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
384
		exit_code = p.wait(timeout=timeout_secs)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
385
	except Exception as e:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "e" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
386
		_log(out, err, logger.warning)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
387
		raise e
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
388
	finally:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
389
		p.kill()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
390
	if exit_code != 0:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
391
		_log(out, err, logger.warning)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
392
		raise ResourceError("Got nonzero exit code {} from '{}'".format(exit_code, ' '.join(cmd)), cmd, exit_code, out, err)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (118/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
393
	_log(out, err, logger.debug)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
394
	return out, err
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
395
396
def look(obj: object, attrs: str) -> any:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
397
	if not isinstance(attrs, str) and isinstance(attrs, Iterable): attrs = '.'.join(attrs)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Second argument of isinstance is not a type
Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
398
	try:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
399
		return operator.attrgetter(attrs)(obj)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
400
	except AttributeError: return None
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
401
402
def flatmap(func, *iterable):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
403
	return chain.from_iterable(map(func, *iterable))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
404
405
def flatten(*iterable):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
406
	return list(chain.from_iterable(iterable))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
407
408
class DevNull:
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
409
	def write(self, msg): pass
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
410
411
pjoin = os.path.join
412
pexists = os.path.exists
413
pdir = os.path.isdir
414
pfile = os.path.isfile
415
pis_dir = os.path.isdir
416
fsize = os.path.getsize
417
def pardir(path: str, depth: int=1):
0 ignored issues
show
Coding Style introduced by
Exactly one space required around keyword argument assignment
Loading history...
introduced by
Missing function or method docstring
Loading history...
418
	for _ in range(-1, depth):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
419
		path = os.path.dirname(path)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
420
	return path
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
421
def grandpardir(path: str):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
422
	return pardir(path, 2)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
423
424
425
T = TypeVar('T')
0 ignored issues
show
Coding Style Naming introduced by
Class name "T" doesn't conform to PascalCase naming style ('[^\\W\\da-z][^\\W_]+$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
426
def try_index_of(element: List[T], list_element: T) -> Optional[T]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
427
	try:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
428
		index_element = list_element.index(element)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
429
		return index_element
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
430
	except ValueError:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
431
		return None
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
432
433
def decorator(cls):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
434
	return cls
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
435
436
437
def exists(keep_predicate: Callable[[T], bool], seq: Iterable[T]) -> bool:
438
	"""Efficient existential quantifier for a filter() predicate.
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
439
	Returns true iff keep_predicate is true for one or more elements."""
440
	for e in seq:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "e" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
441
		if keep_predicate(e): return True  # short-circuit
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
442
	return False
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
443
444
445
def zip_strict(*args):
446
	"""Same as zip(), but raises an IndexError if the lengths don't match."""
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
447
	iters = [iter(axis) for axis in args]
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
448
	n_elements = 0
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
449
	failures = []
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
450
	while len(failures) == 0:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
451
		n_elements += 1
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
452
		values = []
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
453
		failures = []
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
454
		for axis, iterator in enumerate(iters):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
455
			try:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
456
				values.append(next(iterator))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
457
			except StopIteration:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
458
				failures.append(axis)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
459
		if len(failures) == 0:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
460
			yield tuple(values)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
461
	if len(failures) == 1:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Unused Code introduced by
Unnecessary "elif" after "raise"
Loading history...
462
		raise IndexError("Too few elements ({}) along axis {}".format(n_elements, failures[0]))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
463
	elif len(failures) < len(iters):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
464
		raise IndexError("Too few elements ({}) along axes {}".format(n_elements, failures))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
465
466
467
def only(sequence: Iterable[Any]) -> Any:
468
	"""
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
469
	Returns either the SINGLE (ONLY) UNIQUE ITEM in the sequence or raises an exception.
470
	Each item must have __hash__ defined on it.
471
	:param sequence: A list of any items (untyped)
472
	:return: The first item the sequence.
473
	:raises: ValarLookupError If the sequence is empty
474
	:raises: MultipleMatchesError If there is more than one unique item.
475
	"""
476
	st = set(sequence)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "st" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
477
	if len(st) > 1:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
478
		raise MultipleMatchesError("More then 1 item in {}".format(sequence))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
479
	if len(st) == 0:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
480
		raise LookupFailedError("Empty sequence")
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
481
	return next(iter(st))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
482
483
484
def read_lines_file(path: str, ignore_comments: bool = False) -> Sequence[str]:
485
	"""
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
486
	Returns a list of lines in a file, potentially ignoring comments.
487
	:param path: Read the file at this local path
488
	:param ignore_comments: Ignore lines beginning with #, excluding whitespace
489
	:return: The lines, with surrounding whitespace stripped
490
	"""
491
	lines = []
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Comprehensibility Bug introduced by
lines is re-defining a name which is already available in the outer-scope (previously defined on line 657).

It is generally a bad practice to shadow variables from the outer-scope. In most cases, this is done unintentionally and might lead to unexpected behavior:

param = 5

class Foo:
    def __init__(self, param):   # "param" would be flagged here
        self.param = param
Loading history...
492
	with open(path) as f:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "f" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
493
		line = f.readline().strip()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
494
		if not ignore_comments or not line.startswith('#'):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
495
			lines.append(line)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
496
	return lines
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
497
498
499
def read_properties_file(path: str) -> Mapping[str, str]:
500
	"""
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
501
	Reads a .properties file, which is a list of lines with key=value pairs (with an equals sign).
502
	Lines beginning with # are ignored.
503
	Each line must contain exactly 1 equals sign.
504
	:param path: Read the file at this local path
505
	:return: A dict mapping keys to values, both with surrounding whitespace stripped
506
	"""
507
	lines = read_lines_file(path, ignore_comments=False)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Comprehensibility Bug introduced by
lines is re-defining a name which is already available in the outer-scope (previously defined on line 657).

It is generally a bad practice to shadow variables from the outer-scope. In most cases, this is done unintentionally and might lead to unexpected behavior:

param = 5

class Foo:
    def __init__(self, param):   # "param" would be flagged here
        self.param = param
Loading history...
508
	dct = {}
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
509
	for i, line in enumerate(lines):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
510
		if line.startswith('#'): continue
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
511
		if line.count('=') != 1:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
512
			raise ParsingError("Bad line {} in {}".format(i+1, path))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
513
		parts = line.split('=')
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
514
		dct[parts[0].strip()] = parts[1].strip()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
515
	return dct
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
516
517
518
class Comparable:
519
	"""A class that's comparable. Just implement __lt__. Credit ot Alex Martelli on https://stackoverflow.com/questions/1061283/lt-instead-of-cmp"""
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (145/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
520
521
	def __eq__(self, other):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
522
		return not self < other and not other < self
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
523
524
	def __ne__(self, other):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
525
		return self < other or other < self
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
526
527
	def __gt__(self, other):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
528
		return other < self
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
529
530
	def __ge__(self, other):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
531
		return not self < other
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
532
533
	def __le__(self, other):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
534
		return not other < self
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
535
536
537
def json_serial(obj):
538
	"""JSON serializer for objects not serializable by default json code.
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
539
	From jgbarah at https://stackoverflow.com/questions/11875770/how-to-overcome-datetime-datetime-not-json-serializable
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (117/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
540
	"""
541
	if isinstance(obj, (datetime, date)):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Second argument of isinstance is not a type
Loading history...
542
		return obj.isoformat()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
543
	try:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
544
		import peewee
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Import outside toplevel (peewee)
Loading history...
545
		if isinstance(obj, peewee.Field):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
546
			return type(obj).__name__
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
547
	except ImportError: pass
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
548
	raise TypeError("Type %s not serializable" % type(obj))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
549
550
def pretty_dict(dct: dict) -> str:
551
	"""Returns a pretty-printed dict, complete with indentation. Will fail on non-JSON-serializable datatypes."""
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (110/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
552
	return json.dumps(dct, default=json_serial, sort_keys=True, indent=4)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
553
554
def pp_dict(dct: dict) -> None:
555
	"""Pretty-prints a dict to stdout."""
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
556
	print(pretty_dict(dct))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
557
558
def pp_size(obj: object) -> None:
559
	"""Prints to stdout a human-readable string of the memory usage of arbitrary Python objects. Ex: 8M for 8 megabytes."""
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (120/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
560
	print(hsize(sys.getsizeof(obj)))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
561
562
def sanitize_str(value: str) -> str:
563
	"""Removes Unicode control (Cc) characters EXCEPT for tabs (\t), newlines (\n only), line separators (U+2028) and paragraph separators (U+2029)."""
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (148/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
564
	return "".join(ch for ch in value if unicodedata.category(ch) != 'Cc' and ch not in {'\t', '\n', '\u2028', '\u2029'})
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (118/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
565
566
def escape_for_properties(value: Any) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
567
	return sanitize_str(str(value).replace('\n', '\u2028'))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
568
569
def escape_for_tsv(value: Any) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
570
	return sanitize_str(str(value).replace('\n', '\u2028').replace('\t', ' '))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
571
	
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
572
class Timeout:
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
573
	def __init__(self, seconds: int = 10, error_message='Timeout'):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
574
		self.seconds = seconds
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
575
		self.error_message = error_message
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
576
	def handle_timeout(self, signum, frame):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
577
		raise TimeoutError(self.error_message)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
578
	def __enter__(self):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
579
		signal.signal(signal.SIGALRM, self.handle_timeout)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
580
		signal.alarm(self.seconds)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
581
	def __exit__(self, type, value, traceback):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Bug Best Practice introduced by
This seems to re-define the built-in type.

It is generally discouraged to redefine built-ins as this makes code very hard to read.

Loading history...
582
		signal.alarm(0)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
583
584
585
class OverwriteChoice(Enum):
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
586
	FAIL = 1
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
587
	WARN = 2
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
588
	IGNORE = 3
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
589
	OVERWRITE = 4
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
590
591
def fix_path(path: str) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
592
	# ffmpeg won't recognize './' and will simply not write images!
593
	# and Python doesn't recognize ~
594
	if '%' in path: raise ValueError(
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
595
		'For technical limitations (regarding ffmpeg), local paths cannot contain a percent sign (%), but "{}" does'.format(path)
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block.
Loading history...
Coding Style introduced by
This line is too long as per the coding-style (123/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
596
	)
597
	if path == '~': return os.environ['HOME']  # prevent out of bounds
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
598
	if path.startswith('~'):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
599
		path = pjoin(os.environ['HOME'], path[2:])
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
600
	return path.replace('./', '')
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
601
602
def fix_path_platform_dependent(path: str) -> str:
603
	"""Modifies path strings to work with Python and external tools.
0 ignored issues
show
Bug introduced by
A suspicious escape sequence \ was found. Did you maybe forget to add an r prefix?

Escape sequences in Python are generally interpreted according to rules similar to standard C. Only if strings are prefixed with r or R are they interpreted as regular expressions.

The escape sequence that was used indicates that you might have intended to write a regular expression.

Learn more about the available escape sequences. in the Python documentation.

Loading history...
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
604
	Replaces a beginning '~' with the HOME environment variable.
605
	Also accepts either / or \ (but not both) as a path separator in windows. 
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
606
	"""
607
	path = fix_path(path)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
608
	# if windows, allow either / or \, but not both
609
	if platform.system() == 'Windows':
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
unused-code introduced by
Unnecessary "else" after "return"
Loading history...
610
		bits = re.split('[/\\\\]', path)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
611
		return pjoin(*bits).replace(":", ":\\")
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
612
	else:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
613
		return path
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
614
615
616
# NTFS doesn't allow these, so let's be safe
617
# Also exclude control characters
618
# 127 is the DEL char
619
_bad_chars = {'/', ':', '<', '>', '"', "'", '\\', '|', '?', '*', chr(127), *{chr(i) for i in range(0, 32)}}
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (107/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
620
assert ' ' not in _bad_chars
621
def _sanitize_bit(p: str) -> str:
0 ignored issues
show
Coding Style Naming introduced by
Argument name "p" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
622
	for b in _bad_chars: p = p.replace(b, '-')
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "b" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
623
	return p
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
624
def pjoin_sanitized_rel(*pieces: Iterable[any]) -> str:
625
	"""Builds a path from a hierarchy, sanitizing the path by replacing /, :, <, >, ", ', \, |, ?, *, <DEL>, and control characters 0–32 with a hyphen-minus (-).
0 ignored issues
show
Bug introduced by
A suspicious escape sequence \, was found. Did you maybe forget to add an r prefix?

Escape sequences in Python are generally interpreted according to rules similar to standard C. Only if strings are prefixed with r or R are they interpreted as regular expressions.

The escape sequence that was used indicates that you might have intended to write a regular expression.

Learn more about the available escape sequences. in the Python documentation.

Loading history...
Coding Style introduced by
This line is too long as per the coding-style (158/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
626
	Each input to pjoin_sanitized must refer only to a single directory or file (cannot contain a path separator).
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (111/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
627
	This means that you cannot have an absolute path (it would begin with os.path (probably /); use pjoin_sanitized_abs for this.
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (126/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
628
	"""
629
	return pjoin(*[_sanitize_bit(str(bit)) for bit in pieces])
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
630
def pjoin_sanitized_abs(*pieces: Iterable[any]) -> str:
631
	"""Same as pjoin_sanitized_rel but starts with os.sep (the root directory)."""
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
632
	return pjoin(os.sep, pjoin_sanitized_rel(*pieces))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
633
634
635
def make_dirs(output_dir: str):
636
	"""Makes a directory if it doesn't exist.
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
637
	May raise a PathIsNotADirError.
638
	"""
639
	if not os.path.exists(output_dir):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
640
		os.makedirs(output_dir)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
641
	elif not os.path.isdir(output_dir):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
642
		raise PathIsNotADirError("{} already exists and is not a directory".format(output_dir))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
643
644
645
def remake_dirs(output_dir: str):
646
	"""Makes a directory, remaking it if it already exists.
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
647
	May raise a PathIsNotADirError.
648
	"""
649
	if os.path.exists(output_dir) and os.path.isdir(output_dir):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
650
		shutil.rmtree(output_dir)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
651
	elif os.path.exists(output_dir):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
652
		raise PathIsNotADirError("{} already exists and is not a directory".format(output_dir))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
653
	make_dirs(output_dir)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
654
655
656
657
def lines(file_name: str, known_encoding='utf-8') -> Iterator[str]:
658
	"""Lazily read a text file or gzipped text file, decode, and strip any newline character (\n or \r).
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (101/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
659
	If the file name ends with '.gz' or '.gzip', assumes the file is Gzipped.
660
	Arguments:
661
		known_encoding: Applied only when decoding gzip
662
	"""
663
	if file_name.endswith('.gz') or file_name.endswith('.gzip'):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
664
		with io.TextIOWrapper(gzip.open(file_name, 'r'), encoding=known_encoding) as f:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "f" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
665
			for line in f: yield line.rstrip('\n\r')
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
666
	else:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
667
		with open(file_name, 'r') as f:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "f" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
668
			for line in f: yield line.rstrip('\n\r')
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
669
670
import dill
0 ignored issues
show
introduced by
Unable to import 'dill'
Loading history...
introduced by
Import "import dill" should be placed at the top of the module
Loading history...
671
672
def pkl(data, path: str):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
673
	with open(path, 'wb') as f:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "f" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
674
		dill.dump(data, f)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
675
676
def unpkl(path: str):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
677
	with open(path, 'rb') as f:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "f" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
678
		return dill.load(f)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
679
680
681
def file_from_env_var(var: str) -> str:
682
	"""
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
683
	Just returns the path of a file specified in an environment variable, checking that it's a file.
684
	Will raise a MissingResourceError error if not set or not a file.
685
	:param var: The environment variable name, not including the $
686
	"""
687
	if var not in os.environ:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
688
		raise MissingResourceError('Environment variable ${} is not set'.format(var))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
689
	config_file_path = fix_path(os.environ[var])
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
690
	if not pexists(config_file_path):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
691
		raise MissingResourceError("{} file {} does not exist".format(var, config_file_path))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
692
	if not pfile(config_file_path):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
693
		raise MissingResourceError("{} file {} is not a file".format(var, config_file_path))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
694
	return config_file_path
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
695
696
697
def is_proper_file(path: str) -> bool:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
698
	name = os.path.split(path)[1]
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
699
	return len(name) > 0 and name[0] not in {'.', '~', '_'}
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
700
701
702
def scantree(path: str, follow_symlinks: bool=False) -> Iterator[str]:
0 ignored issues
show
Coding Style introduced by
Exactly one space required around keyword argument assignment
Loading history...
703
	"""List the full path of every file not beginning with '.', '~', or '_' in a directory, recursively.
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (101/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
704
	.. deprecated Use scan_for_proper_files, which has a better name
705
	"""
706
	for entry in os.scandir(path):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
707
		if entry.is_dir(follow_symlinks=follow_symlinks):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
708
			yield from scantree(entry.path)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
709
		elif is_proper_file(entry.path):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
710
			yield entry.path
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
711
712
scan_for_proper_files = scantree
713
714
715
def scan_for_files(path: str, follow_symlinks: bool=False) -> Iterator[str]:
0 ignored issues
show
Coding Style introduced by
Exactly one space required around keyword argument assignment
Loading history...
716
	"""
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
717
	Using a generator, list all files in a directory or one of its subdirectories.
718
	Useful for iterating over files in a directory recursively if there are thousands of file.
719
	Warning: If there are looping symlinks, follow_symlinks will return an infinite generator.
720
	"""
721
	for d in os.scandir(path):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "d" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
722
		if d.is_dir(follow_symlinks=follow_symlinks):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
723
			yield from scan_for_files(d.path)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
724
		else:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
725
			yield d.path
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
726
727
728
def walk_until(some_dir, until: Callable[[str], bool]) -> Iterator[typing.Tuple[str, str, str]]:
729
	"""Walk but stop recursing after 'until' occurs.
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
730
	Returns files and directories in the same manner as os.walk
731
	"""
732
	some_dir = some_dir.rstrip(os.path.sep)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
733
	assert os.path.isdir(some_dir)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
734
	for root, dirs, files in os.walk(some_dir):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
735
			yield root, dirs, files
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
736
			if until(root):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
737
					del dirs[:]
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
738
739
740
def walk_until_level(some_dir, level: Optional[int]=None) -> Iterator[typing.Tuple[str, str, str]]:
0 ignored issues
show
Coding Style introduced by
Exactly one space required around keyword argument assignment
Loading history...
741
	"""
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
742
	Walk up to a maximum recursion depth.
743
	Returns files and directories in the same manner as os.walk
744
	Taken partly from https://stackoverflow.com/questions/7159607/list-directories-with-a-specified-depth-in-python
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (112/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
745
	:param some_dir:
746
	:param level: Maximum recursion depth, starting at 0
747
	"""
748
	some_dir = some_dir.rstrip(os.path.sep)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
749
	assert os.path.isdir(some_dir)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
750
	num_sep = some_dir.count(os.path.sep)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
751
	for root, dirs, files in os.walk(some_dir):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
752
			yield root, dirs, files
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
753
			num_sep_this = root.count(os.path.sep)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
754
			if level is None or num_sep + level <= num_sep_this:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
755
					del dirs[:]
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
756
757
758
class SubcommandHandler:
759
	"""A convenient wrapper for a program that uses command-line subcommands.
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
760
	Calls any method that belongs to the target
761
	:param parser: Should contain a description and help text, but should NOT contain any arguments.
762
	:param target: An object (or type) that contains a method for each subcommand; a dash (-) in the argument is converted to an underscore.
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (137/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
763
	:param temp_dir: A temporary directory
764
	:param error_handler: Called logging any exception except for KeyboardInterrupt or SystemExit (exceptions in here are ignored)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (127/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
765
	:param cancel_handler: Called after logging a KeyboardInterrupt or SystemExit (exceptions in here are ignored)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (111/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
766
	"""
767
	def __init__(self,
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
best-practice introduced by
Too many arguments (6/5)
Loading history...
768
			parser: argparse.ArgumentParser, target: Any,
0 ignored issues
show
Coding Style introduced by
Wrong continued indentation (remove 3 spaces).
Loading history...
769
			temp_dir: Optional[str] = None,
0 ignored issues
show
Coding Style introduced by
Wrong continued indentation (remove 3 spaces).
Loading history...
770
			error_handler: Callable[[BaseException], None] = lambda e: None,
0 ignored issues
show
Coding Style introduced by
Wrong continued indentation (remove 3 spaces).
Loading history...
771
			cancel_handler: Callable[[Union[KeyboardInterrupt, SystemExit]], None] = lambda e: None
0 ignored issues
show
Coding Style introduced by
Wrong continued indentation (remove 3 spaces).
Loading history...
772
	) -> None:
0 ignored issues
show
Coding Style introduced by
Wrong continued indentation.
Loading history...
773
		parser.add_argument('subcommand', help='Subcommand to run')
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
774
		self.parser = parser
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
775
		self.target = target
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
776
		self.temp_dir = temp_dir
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
777
		self.error_handler = error_handler
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
778
		self.cancel_handler = cancel_handler
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
779
780
781
	def run(self, args: List[str]) -> None:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Missing function or method docstring
Loading history...
782
783
		full_args = self.parser.parse_args(args[1:2])
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
784
		subcommand = full_args.subcommand.replace('-', '_')
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
785
786
		if not hasattr(self.target, subcommand) and not subcommand.startswith('_'):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
787
			print(Fore.RED + 'Unrecognized subcommand {}'.format(subcommand))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
788
			self.parser.print_help()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
789
			return
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
790
791
		# clever; from Chase Seibert: https://chase-seibert.github.io/blog/2014/03/21/python-multilevel-argparse.html
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (111/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
792
		# use dispatch pattern to invoke method with same name
793
		try:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
794
			if self.temp_dir is not None:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
795
				if pexists(self.temp_dir) and pdir(self.temp_dir): shutil.rmtree(self.temp_dir)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
796
				elif pexists(self.temp_dir): raise PathIsNotADirError(self.temp_dir)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
797
				remake_dirs(self.temp_dir)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
798
				logger.debug("Created temp dir at {}".format(self.temp_dir))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Use lazy % formatting in logging functions
Loading history...
799
			getattr(self.target, subcommand)()
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
800
		except NaturalExpectedError as e:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "e" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
801
			pass  # ignore totally
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
802
		except KeyboardInterrupt as e:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "e" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
803
			try:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
804
				logger.fatal("Received cancellation signal", exc_info=True)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
805
				self.cancel_handler(e)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
806
			except BaseException: pass
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Best Practice introduced by
Catching very general exceptions such as BaseException is usually not recommended.

Generally, you would want to handle very specific errors in the exception handler. This ensure that you do not hide other types of errors which should be fixed.

So, unless you specifically plan to handle any error, consider adding a more specific exception.

Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
807
			raise e
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
808
		except SystemExit as e:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "e" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
809
			try:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
810
				logger.fatal("Received system exit signal", exc_info=True)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
811
				self.cancel_handler(e)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
812
			except BaseException: pass
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Best Practice introduced by
Catching very general exceptions such as BaseException is usually not recommended.

Generally, you would want to handle very specific errors in the exception handler. This ensure that you do not hide other types of errors which should be fixed.

So, unless you specifically plan to handle any error, consider adding a more specific exception.

Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
813
			raise e
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
814
		except BaseException as e:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style Naming introduced by
Variable name "e" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
815
			try:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
816
				logger.fatal("{} failed!".format(self.parser.prog), exc_info=True)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Use lazy % formatting in logging functions
Loading history...
817
				self.error_handler(e)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
818
			except BaseException: pass
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Best Practice introduced by
Catching very general exceptions such as BaseException is usually not recommended.

Generally, you would want to handle very specific errors in the exception handler. This ensure that you do not hide other types of errors which should be fixed.

So, unless you specifically plan to handle any error, consider adding a more specific exception.

Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
819
			raise e
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
820
		finally:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
821
			if self.temp_dir is not None:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
822
				if pexists(self.temp_dir):
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
823
					logger.debug("Deleted temp dir at {}".format(self.temp_dir))
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
introduced by
Use lazy % formatting in logging functions
Loading history...
824
					shutil.rmtree(self.temp_dir)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
825
					try:
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
826
						os.remove(self.temp_dir)
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
827
					except IOError: pass
0 ignored issues
show
Coding Style introduced by
Found indentation with tabs instead of spaces
Loading history...
Coding Style introduced by
More than one statement on a single line
Loading history...
828
829
#__all__ = ['scan_for_files', 'walk_until', 'walk_until_level']
830