Compare commits
10 commits
e0e12c0184
...
75b75a1d55
| Author | SHA1 | Date | |
|---|---|---|---|
| 75b75a1d55 | |||
| 013e79cd6b | |||
| 0881f43d85 | |||
| 0d66651c5c | |||
| 81d5621785 | |||
| 9803730675 | |||
| 5a06d78a65 | |||
| eb4e381022 | |||
| 019bba23f2 | |||
| 6fe7e5e5a6 |
8 changed files with 90 additions and 10 deletions
2
setup.py
2
setup.py
|
|
@ -3,7 +3,7 @@ import setuptools
|
|||
setuptools.setup(
|
||||
name='voussoirkit',
|
||||
packages=setuptools.find_packages(),
|
||||
version='0.0.74',
|
||||
version='0.0.76',
|
||||
author='voussoir',
|
||||
author_email='pypi@voussoir.net',
|
||||
description='voussoir\'s toolkit',
|
||||
|
|
|
|||
|
|
@ -518,8 +518,13 @@ def make_helptext(
|
|||
|
||||
# PUT IT ALL TOGETHER
|
||||
|
||||
if command_name is None:
|
||||
header_name = program_name
|
||||
else:
|
||||
header_name = f'{program_name} {command_name}'
|
||||
|
||||
parts = [
|
||||
niceprints.equals_header(program_name) if do_headline else None,
|
||||
niceprints.equals_header(header_name) if do_headline else None,
|
||||
program_description,
|
||||
main_invocation,
|
||||
'\n\n'.join(argument_helps),
|
||||
|
|
|
|||
|
|
@ -309,7 +309,7 @@ def prepare_plan(
|
|||
if do_head:
|
||||
# I'm using a GET instead of an actual HEAD here because some servers respond
|
||||
# differently, even though they're not supposed to.
|
||||
head = request('get', url, stream=True, headers=temp_headers, auth=auth)
|
||||
head = request('get', url, stream=True, headers=temp_headers, auth=auth, verify_ssl=verify_ssl)
|
||||
remote_total_bytes = head.headers.get('content-length', None)
|
||||
remote_total_bytes = None if remote_total_bytes is None else int(remote_total_bytes)
|
||||
server_respects_range = (head.status_code == 206 and 'content-range' in head.headers)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import exifread
|
|||
import io
|
||||
import PIL.ExifTags
|
||||
import PIL.Image
|
||||
import PIL.ImageCms
|
||||
import re
|
||||
|
||||
from voussoirkit import pathclass
|
||||
|
|
@ -40,6 +41,20 @@ def checkerboard_image(color_1, color_2, image_size, checker_size) -> PIL.Image:
|
|||
offset = not offset
|
||||
return image
|
||||
|
||||
def convert_to_srgb(image):
|
||||
'''
|
||||
Thank you Andriy Makukha
|
||||
https://stackoverflow.com/a/50623824
|
||||
'''
|
||||
icc = image.info.get('icc_profile', '')
|
||||
if icc:
|
||||
image = PIL.ImageCms.profileToProfile(
|
||||
image,
|
||||
inputProfile=PIL.ImageCms.ImageCmsProfile(io.BytesIO(icc)),
|
||||
outputProfile=PIL.ImageCms.createProfile('sRGB'),
|
||||
)
|
||||
return image
|
||||
|
||||
def fit_into_bounds(
|
||||
image_width,
|
||||
image_height,
|
||||
|
|
|
|||
|
|
@ -249,7 +249,14 @@ def main_log_context(subject, level, **kwargs):
|
|||
log = vlogging.getLogger()
|
||||
handler = LogHandler(subject, **kwargs)
|
||||
handler.setLevel(level)
|
||||
handler.setFormatter(vlogging.Formatter('{levelname}:{name}:{message}', style='{'))
|
||||
datefmt = '%Y-%m-%dT%H:%M:%S'
|
||||
formatter = vlogging.Formatter(
|
||||
'[{asctime}.{msecs:03.0f}] {levelname}:{name}:{message}',
|
||||
style='{',
|
||||
datefmt=datefmt,
|
||||
)
|
||||
formatter.default_msec_format = '%s.%03d'
|
||||
handler.setFormatter(formatter)
|
||||
context = LogHandlerContext(log, handler)
|
||||
return context
|
||||
|
||||
|
|
|
|||
|
|
@ -54,12 +54,15 @@ def add_loud(log):
|
|||
|
||||
def add_root_handler(level):
|
||||
handler = StreamHandler()
|
||||
datefmt = '%Y-%m-%dT%H:%M:%S'
|
||||
if level <= LOUD:
|
||||
handler.setFormatter(Formatter('{levelname}:{name}.{funcName}.{lineno}:{message}', style='{'))
|
||||
formatter = Formatter('[{asctime}.{msecs:03.0f}] {levelname}:{name}.{funcName}.{lineno}:{message}', style='{', datefmt=datefmt)
|
||||
elif level <= DEBUG:
|
||||
handler.setFormatter(Formatter('{levelname}:{name}.{funcName}:{message}', style='{'))
|
||||
formatter = Formatter('[{asctime}.{msecs:03.0f}] {levelname}:{name}.{funcName}:{message}', style='{', datefmt=datefmt)
|
||||
else:
|
||||
handler.setFormatter(Formatter('{levelname}:{name}:{message}', style='{'))
|
||||
formatter = Formatter('[{asctime}.{msecs:03.0f}] {levelname}:{name}:{message}', style='{', datefmt=datefmt)
|
||||
formatter.default_msec_format = '%s.%03d'
|
||||
handler.setFormatter(formatter)
|
||||
handler.setLevel(level)
|
||||
root.addHandler(handler)
|
||||
return handler
|
||||
|
|
|
|||
|
|
@ -651,15 +651,16 @@ class DatabaseWithCaching(Database, metaclass=abc.ABCMeta):
|
|||
object_table = object_class.table
|
||||
object_cache = self.caches.get(object_class, None)
|
||||
|
||||
if object_cache is None:
|
||||
log.loud('The %s table is not cached. Returning new instance.', object_class.table)
|
||||
return object_class(self, db_row)
|
||||
|
||||
if isinstance(db_row, (dict, sqlite3.Row)):
|
||||
object_id = db_row['id']
|
||||
else:
|
||||
object_index = self.COLUMN_INDEX[object_table]
|
||||
object_id = db_row[object_index['id']]
|
||||
|
||||
if object_cache is None:
|
||||
return object_class(self, db_row)
|
||||
|
||||
try:
|
||||
instance = object_cache[object_id]
|
||||
except KeyError:
|
||||
|
|
@ -807,6 +808,7 @@ class Object(metaclass=abc.ABCMeta):
|
|||
'''
|
||||
Your subclass should call super().__init__(database).
|
||||
'''
|
||||
super().__init__()
|
||||
# Used for transaction
|
||||
self._worms_database = database
|
||||
self.deleted = False
|
||||
|
|
|
|||
|
|
@ -71,6 +71,54 @@ function join_and_trail(list, separator)
|
|||
return list.join(separator) + separator
|
||||
}
|
||||
|
||||
common.hms_render_colons =
|
||||
function hms_render_colons(hours, minutes, seconds)
|
||||
{
|
||||
const parts = [];
|
||||
if (hours !== null)
|
||||
{
|
||||
parts.push(hours.toLocaleString(undefined, {minimumIntegerDigits: 2}));
|
||||
}
|
||||
if (minutes !== null)
|
||||
{
|
||||
parts.push(minutes.toLocaleString(undefined, {minimumIntegerDigits: 2}));
|
||||
}
|
||||
parts.push(seconds.toLocaleString(undefined, {minimumIntegerDigits: 2}));
|
||||
return parts.join(":")
|
||||
}
|
||||
|
||||
common.seconds_to_hms =
|
||||
function seconds_to_hms({
|
||||
seconds,
|
||||
renderer=common.hms_render_colons,
|
||||
force_minutes=false,
|
||||
force_hours=false,
|
||||
})
|
||||
{
|
||||
if (seconds > 0 && seconds < 1)
|
||||
{
|
||||
seconds = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
seconds = Math.round(seconds);
|
||||
}
|
||||
let minutes = Math.floor(seconds / 60);
|
||||
seconds = seconds % 60;
|
||||
let hours = Math.floor(minutes / 60);
|
||||
minutes = minutes % 60;
|
||||
|
||||
if (hours == 0 && force_hours == false)
|
||||
{
|
||||
hours = null;
|
||||
}
|
||||
if (minutes == 0 && force_minutes == false)
|
||||
{
|
||||
minutes = null;
|
||||
}
|
||||
return renderer(hours, minutes, seconds);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// HTML & DOM //////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
Loading…
Reference in a new issue