Fix all namings for all folders, add simple test run for progress
Missing: tests for all other functions
This commit is contained in:
23
ReadMe.md
23
ReadMe.md
@@ -8,6 +8,19 @@ This is a pip package that can be installed into any project and covers the foll
|
||||
- jmespath search
|
||||
- dump outputs for data
|
||||
- progress printing
|
||||
- string formatting, time creation, byte formatting
|
||||
|
||||
## Current list
|
||||
|
||||
- csv_handling: csv dict writer helper
|
||||
- debug_handling: various debug helpers like data dumper, timer, utilization, etc
|
||||
- file_handling: crc handling for file content and file names, progress bar
|
||||
- json_handling: jmespath support and json date support
|
||||
- list_dict_handling: list and dictionary handling support (search, fingerprinting, etc)
|
||||
- logging_handling: extend log and also error message handling
|
||||
- requests_handling: requests wrapper for better calls with auth headers
|
||||
- script_handling: pid lock file handling, abort timer
|
||||
- string_handling: byte format, datetime format, hashing, string formats for numbrers, etc
|
||||
|
||||
## How to publish
|
||||
|
||||
@@ -34,6 +47,16 @@ We must set the full index URL here because we run with "--no-project2
|
||||
uv run --with corelibs --index egra-gitea=https://git.egplusww.jp/api/packages/PyPI/pypi/simple/ --no-project --native-tls -- python -c "import corelibs"
|
||||
```
|
||||
|
||||
### Other tests
|
||||
|
||||
In the test folder other tests are located.
|
||||
|
||||
At the moment only a small test for the "progress" module is set
|
||||
|
||||
```sh
|
||||
uv run --native-tls tests/progress/progress_test.py
|
||||
```
|
||||
|
||||
## How to install in another project
|
||||
|
||||
This will also add the index entry
|
||||
|
||||
1
ToDo.md
1
ToDo.md
@@ -1,5 +1,4 @@
|
||||
# ToDo list
|
||||
|
||||
- proper folder names and file names and location of methods
|
||||
- stub files .pyi
|
||||
- fix all remaning check errors
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
# MARK: Project info
|
||||
[project]
|
||||
name = "corelibs"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
description = "Collection of utils for Python scripts"
|
||||
readme = "ReadMe.md"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"jmespath>=1.0.1",
|
||||
"psutil>=7.0.0",
|
||||
"requests>=2.32.4",
|
||||
]
|
||||
# set this to disable publish to pypi (pip)
|
||||
# classifiers = ["Private :: Do Not Upload"]
|
||||
@@ -46,3 +47,6 @@ notes = ["FIXME", "TODO"]
|
||||
notes-rgx = '(FIXME|TODO)(\((TTD-|#)\[0-9]+\))'
|
||||
[tool.flake8]
|
||||
max-line-length = 120
|
||||
[tool.pylint.MASTER]
|
||||
# this is for the tests/etc folders
|
||||
init-hook='import sys; sys.path.append("src/")'
|
||||
|
||||
477
src/CoreLibs/file_handling/progress.py
Normal file
477
src/CoreLibs/file_handling/progress.py
Normal file
@@ -0,0 +1,477 @@
|
||||
"""
|
||||
AUTHOR: Clemens Schwaighofer
|
||||
DATE CREATED: 2009/7/24 (2025/7/2)
|
||||
DESCRIPTION: progress percent class (perl -> python)
|
||||
|
||||
HOW TO USE
|
||||
* load
|
||||
from progress import Progress
|
||||
* init
|
||||
prg = Progress()
|
||||
allowed parameters to pass are (in order)
|
||||
- verbose (0/1/...) : show output
|
||||
- precision (-2~10) : -2 (5%), -1 (10%), 0 (normal 0-100%), 1~10 (100.m~%)
|
||||
- microtime (1/0/-1) : show microtime in eta/run time
|
||||
- wide time (bool) : padd time so all time column doesn't change width of line
|
||||
- prefix line break (bool): add line break before string and not only after
|
||||
prg = Progress(verbose = 1, precision = 2)
|
||||
* settings methods
|
||||
set_wide_time(bool)
|
||||
set_microtime(int -1/0/1)
|
||||
set_prefix_lb(bool)
|
||||
set_verbose(0/1 int)
|
||||
set_precision(-2~10 int)
|
||||
set_linecount(int)
|
||||
set_filesize(int)
|
||||
set_start_time(time optional)
|
||||
set_eta_start_time(time optional)
|
||||
set_end_time(time optional)
|
||||
show_position(file pos optional)
|
||||
"""
|
||||
|
||||
import time
|
||||
from typing import Literal
|
||||
from math import floor
|
||||
from corelibs.string_handling.datetime_helpers import convert_timestamp
|
||||
from corelibs.string_handling.byte_helpers import format_bytes
|
||||
|
||||
|
||||
class Progress():
|
||||
"""
|
||||
file progress output information
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
verbose: int = 0,
|
||||
precision: int = 1,
|
||||
microtime: Literal[-1] | Literal[1] | Literal[0] = 0,
|
||||
wide_time: bool = False,
|
||||
prefix_lb: bool = False
|
||||
):
|
||||
# set default var stuff
|
||||
# max lines in input
|
||||
self.linecount: int = 0
|
||||
# max file size
|
||||
self.filesize: int = 0
|
||||
# * comma after percent
|
||||
self.precision: int = 0
|
||||
# * if flagged 1, then wthe wide 15 char left bound format is used
|
||||
self.wide_time: bool = False
|
||||
# * verbose status from outside
|
||||
self.verbose: bool = False
|
||||
# * microtime output for last run time (1 for enable 0 for auto -1 for disable)
|
||||
self.microtime: Literal[-1] | Literal[1] | Literal[0] = 0
|
||||
# micro time flag for last group
|
||||
self.lg_microtime: bool = False
|
||||
# = flag if output was given
|
||||
self.change = 0
|
||||
# = global start for the full script running time
|
||||
self.start: float | None = None
|
||||
# = for the eta time, can be set after a query or long read in, to not create a wrong ETA time
|
||||
self.start_run: float | None = None
|
||||
# loop start
|
||||
self.start_time: float | None = None
|
||||
# global end
|
||||
self.end: float | None = None
|
||||
# loop end
|
||||
self.end_time: float | None = None
|
||||
# run time in seconds, set when end time method is called
|
||||
self.run_time: float | None = None
|
||||
# = filesize current
|
||||
self.count_size: int | None = None
|
||||
# position current
|
||||
self.count: int = 0
|
||||
# last count (position)
|
||||
self.current_count: int = 0
|
||||
# the current file post
|
||||
self.file_pos: int | None = None
|
||||
# lines processed in the last run
|
||||
self.lines_processed: int = 0
|
||||
# time in th seconds for the last group run (until percent change)
|
||||
self.last_group: float = 0
|
||||
# float value, lines processed per second to the last group run
|
||||
self.lines_in_last_group: float = 0
|
||||
# float values, lines processed per second to complete run
|
||||
self.lines_in_global: float = 0
|
||||
# flaot value, bytes processes per second in the last group run
|
||||
self.bytes_in_last_group: float = 0
|
||||
# float value, bytes processed per second to complete run
|
||||
self.bytes_in_global: float = 0
|
||||
# bytes processed in last run (in bytes)
|
||||
self.size_in_last_group: int = 0
|
||||
# current file position 8size)
|
||||
self.current_size: int = 0
|
||||
# last percent position
|
||||
self.last_percent: int | float = 0
|
||||
# if we have normal % or in steps of 10
|
||||
self.precision_ten_step: int = 0
|
||||
# the default size this is precision + 4
|
||||
self.percent_print: int = 5
|
||||
# this is 1 if it is 1 or 0 for precision or precision size
|
||||
self.percent_precision: int = 1
|
||||
# prefix line with a line break
|
||||
self.prefix_lb: bool = False
|
||||
# estimated time to finish
|
||||
self.eta: float | None = None
|
||||
# run time since start
|
||||
self.full_time_needed: float | None = None
|
||||
# the actual output
|
||||
self.string: str = ''
|
||||
|
||||
# initialize the class
|
||||
self.set_precision(precision)
|
||||
self.set_verbose(verbose)
|
||||
self.set_micro_time(microtime)
|
||||
self.set_wide_time(wide_time)
|
||||
self.set_prefix_lb(prefix_lb)
|
||||
self.set_start_time()
|
||||
|
||||
def reset(self):
|
||||
"""
|
||||
resets the current progress to 0, but keeps the overall start variables set
|
||||
"""
|
||||
# reset what always gets reset
|
||||
self.count = 0
|
||||
self.count_size = None
|
||||
self.current_count = 0
|
||||
self.linecount = 0
|
||||
self.lines_processed = 0
|
||||
self.last_group = 0
|
||||
self.lines_in_last_group = 0
|
||||
self.lines_in_global = 0
|
||||
self.bytes_in_last_group = 0
|
||||
self.bytes_in_global = 0
|
||||
self.size_in_last_group = 0
|
||||
self.filesize = 0
|
||||
self.current_size = 0
|
||||
self.last_percent = 0
|
||||
self.eta = 0
|
||||
self.full_time_needed = 0
|
||||
self.start_run = None
|
||||
self.start_time = None
|
||||
self.end_time = None
|
||||
|
||||
def set_wide_time(self, wide_time: bool) -> bool:
|
||||
"""
|
||||
sets the show wide time flag
|
||||
|
||||
Arguments:
|
||||
wide_time {bool} -- _description_
|
||||
|
||||
Returns:
|
||||
bool -- _description_
|
||||
"""
|
||||
self.wide_time = wide_time
|
||||
return self.wide_time
|
||||
|
||||
def set_micro_time(self, microtime: Literal[-1] | Literal[1] | Literal[0]) -> Literal[-1] | Literal[1] | Literal[0]:
|
||||
"""sets the show microtime -1 OFF, 0 AUTO, 1 ON
|
||||
|
||||
Returns:
|
||||
_type_ -- _description_
|
||||
"""
|
||||
self.microtime = microtime
|
||||
return self.microtime
|
||||
|
||||
def set_prefix_lb(self, prefix_lb: bool) -> bool:
|
||||
"""
|
||||
set prefix line break flag
|
||||
|
||||
Arguments:
|
||||
prefix_lb {bool} -- _description_
|
||||
|
||||
Returns:
|
||||
bool -- _description_
|
||||
"""
|
||||
self.prefix_lb = prefix_lb
|
||||
return self.prefix_lb
|
||||
|
||||
def set_verbose(self, verbose: int) -> bool:
|
||||
"""
|
||||
set the internal verbose flag to 1 if any value higher than 1 is given, else sets it to 0
|
||||
|
||||
Arguments:
|
||||
verbose {int} -- _description_
|
||||
|
||||
Returns:
|
||||
bool -- _description_
|
||||
"""
|
||||
if verbose > 0:
|
||||
self.verbose = True
|
||||
else:
|
||||
self.verbose = False
|
||||
return self.verbose
|
||||
|
||||
def set_precision(self, precision: int) -> int:
|
||||
"""
|
||||
sets the output precision size. If -2 for five step, -1 for ten step
|
||||
else sets the precision normally, for 0, no precision is set, maximum precision is 10
|
||||
|
||||
Arguments:
|
||||
precision {int} -- _description_
|
||||
|
||||
Returns:
|
||||
int -- _description_
|
||||
"""
|
||||
# if not a valid number, we set it to 0
|
||||
if precision < -2 or precision > 10:
|
||||
precision = 0
|
||||
if precision < 0:
|
||||
if precision < -1:
|
||||
self.precision_ten_step = 5
|
||||
else:
|
||||
self.precision_ten_step = 10
|
||||
self.precision = 0 # no comma
|
||||
self.percent_precision = 0 # no print precision
|
||||
self.percent_print = 3 # max 3 length
|
||||
else:
|
||||
# comma values visible
|
||||
self.precision = 10 if precision < 0 or precision > 10 else precision
|
||||
# for calcualtion of precision
|
||||
self.percent_precision = 10 if precision < 0 or precision > 10 else precision
|
||||
# for the format output base is 4, plsut he percent precision length
|
||||
self.percent_print = (3 if precision == 0 else 4) + self.percent_precision
|
||||
# return the set precision
|
||||
return self.precision
|
||||
|
||||
def set_linecount(self, linecount: int) -> int:
|
||||
"""
|
||||
set the maximum lines in this file, if value is smaller than 0 or 0, then it is set to 1
|
||||
|
||||
Arguments:
|
||||
linecount {int} -- _description_
|
||||
|
||||
Returns:
|
||||
int -- _description_
|
||||
"""
|
||||
if linecount > 0:
|
||||
self.linecount = linecount
|
||||
else:
|
||||
self.linecount = 1
|
||||
return self.linecount
|
||||
|
||||
def set_filesize(self, filesize: int) -> int:
|
||||
"""
|
||||
set the maximum filesize for this file, if value is smaller than 0 or 0, then it is set to 1
|
||||
|
||||
Arguments:
|
||||
filesize {int} -- _description_
|
||||
|
||||
Returns:
|
||||
int -- _description_
|
||||
"""
|
||||
if filesize > 0:
|
||||
self.filesize = filesize
|
||||
else:
|
||||
self.filesize = 1
|
||||
return self.filesize
|
||||
|
||||
def set_start_time(self, time_value: float = time.time()) -> None:
|
||||
"""
|
||||
initial set of the start times, auto set
|
||||
|
||||
Keyword Arguments:
|
||||
time_value {float} -- _description_ (default: {time.time()})
|
||||
"""
|
||||
# avoid possible double set of the original start time
|
||||
if not self.start:
|
||||
self.start = time_value
|
||||
self.start_time = time_value
|
||||
self.start_run = time_value
|
||||
|
||||
def set_eta_start_time(self, time_value: float = time.time()) -> None:
|
||||
"""
|
||||
sets the loop % run time, for correct ETA calculation
|
||||
calls set start time, as the main start time is only set once
|
||||
|
||||
Keyword Arguments:
|
||||
time_value {float} -- _description_ (default: {time.time()})
|
||||
"""
|
||||
self.set_start_time(time_value)
|
||||
|
||||
def set_end_time(self, time_value: float = time.time()) -> None:
|
||||
"""
|
||||
set the end time
|
||||
|
||||
Keyword Arguments:
|
||||
time_value {float} -- _description_ (default: {time.time()})
|
||||
"""
|
||||
self.end = time_value
|
||||
self.end_time = time_value
|
||||
if self.start is None:
|
||||
self.start = 0
|
||||
# the overall run time in micro seconds
|
||||
self.run_time = self.end - self.start
|
||||
|
||||
def show_position(self, filepos: int = 0) -> str:
|
||||
"""
|
||||
processes the current position. either based on read the file size pos, or the line count
|
||||
|
||||
Keyword Arguments:
|
||||
filepos {int} -- _description_ (default: {0})
|
||||
|
||||
Returns:
|
||||
str -- _description_
|
||||
"""
|
||||
show_filesize = True # if we print from file size or line count
|
||||
# microtime flags
|
||||
eta_microtime = False
|
||||
ftn_microtime = False
|
||||
lg_microtime = False
|
||||
# percent precision calc
|
||||
# _p_spf = "{:." + str(self.precision) + "f}"
|
||||
# output format for percent
|
||||
_pr_p_spf = "{:>" + str(self.percent_print) + "." + str(self.percent_precision) + "f}"
|
||||
# set the linecount precision based on the final linecount, if not, leave it empty
|
||||
_pr_lc = "{}"
|
||||
if self.linecount:
|
||||
_pr_lc = "{:>" + str(len(str(f"{self.linecount:,}"))) + ",}"
|
||||
# time format, if flag is set, the wide format is used
|
||||
_pr_tf = "{}"
|
||||
if self.wide_time:
|
||||
_pr_tf = "{:>15}"
|
||||
|
||||
# count up
|
||||
self.count += 1
|
||||
# if we have file pos from parameter
|
||||
if filepos != 0:
|
||||
self.file_pos = filepos
|
||||
else:
|
||||
# we did not, so we set internal value
|
||||
self.file_pos = self.count
|
||||
# we also check if the filesize was set now
|
||||
if self.filesize == 0:
|
||||
self.filesize = self.linecount
|
||||
# set ignore filesize output (no data)
|
||||
show_filesize = False
|
||||
# set the count size based on the file pos, is only used if we have filesize
|
||||
self.count_size = self.file_pos
|
||||
# do normal or down to 10 (0, 10, ...) %
|
||||
if self.precision_ten_step:
|
||||
_percent = int((self.file_pos / float(self.filesize)) * 100)
|
||||
mod = _percent % self.precision_ten_step
|
||||
percent = _percent if mod == 0 else self.last_percent
|
||||
else:
|
||||
# calc percent
|
||||
percent = round(((self.file_pos / float(self.filesize)) * 100), self.precision)
|
||||
|
||||
# output
|
||||
if percent != self.last_percent:
|
||||
self.end_time = time.time() # current time (for loop time)
|
||||
if self.start is None:
|
||||
self.start = 0
|
||||
if self.start_time is None:
|
||||
self.start_time = 0
|
||||
# for from the beginning
|
||||
full_time_needed = self.end_time - self.start # how long from the start
|
||||
self.last_group = self.end_time - self.start_time # how long for last loop
|
||||
self.lines_processed = self.count - self.current_count # how many lines processed
|
||||
# lines in last group
|
||||
self.lines_in_last_group = (self.lines_processed / self.last_group) if self.last_group else 0
|
||||
# lines in global
|
||||
self.lines_in_global = (self.count / full_time_needed) if full_time_needed else 0
|
||||
# if we have linecount or not
|
||||
if self.linecount == 0:
|
||||
full_time_per_line = (full_time_needed if full_time_needed else 1) / self.count_size # how long for all
|
||||
# estimate for the rest
|
||||
eta = full_time_per_line * (self.filesize - self.count_size)
|
||||
else:
|
||||
# how long for all
|
||||
full_time_per_line = (full_time_needed if full_time_needed else 1) / self.count
|
||||
# estimate for the rest
|
||||
eta = full_time_per_line * (self.linecount - self.count)
|
||||
# just in case ...
|
||||
if eta < 0:
|
||||
eta = 0
|
||||
# check if to show microtime
|
||||
# ON
|
||||
if self.microtime == 1:
|
||||
eta_microtime = ftn_microtime = lg_microtime = True
|
||||
# AUTO
|
||||
if self.microtime == 0:
|
||||
if eta > 0 and eta < 1:
|
||||
eta_microtime = True
|
||||
if full_time_needed > 0 and full_time_needed < 1:
|
||||
ftn_microtime = True
|
||||
# pre check last group: if pre comma part is same add microtime anyway
|
||||
if self.last_group > 0 and self.last_group < 1:
|
||||
lg_microtime = True
|
||||
if self.last_group == floor(self.last_group):
|
||||
lg_microtime = True
|
||||
self.last_group = floor(self.last_group)
|
||||
# if with filesize or without
|
||||
if show_filesize:
|
||||
# last group size
|
||||
self.size_in_last_group = self.count_size - self.current_size
|
||||
# calc kb/s if there is any filesize data
|
||||
# last group
|
||||
self.bytes_in_last_group = (self.size_in_last_group / self.last_group) if self.last_group else 0
|
||||
# global
|
||||
self.bytes_in_global = (self.count_size / full_time_needed) if full_time_needed else 0
|
||||
# only used if we run with file size for the next check
|
||||
self.current_size = self.count_size
|
||||
|
||||
if self.verbose >= 1:
|
||||
self.string = (
|
||||
f"Processed {_pr_p_spf}% "
|
||||
"[{} / {}] | "
|
||||
f"{_pr_lc} / {_pr_lc} Lines | ETA: {_pr_tf} / TR: {_pr_tf} / "
|
||||
"LR: {:,} "
|
||||
"lines ({:,}) in {}, {:,.2f} ({:,.2f}) lines/s, {} ({}) b/s"
|
||||
).format(
|
||||
float(percent),
|
||||
format_bytes(self.count_size),
|
||||
format_bytes(self.filesize),
|
||||
self.count,
|
||||
self.linecount,
|
||||
convert_timestamp(eta, eta_microtime),
|
||||
convert_timestamp(full_time_needed, ftn_microtime),
|
||||
self.lines_processed,
|
||||
self.size_in_last_group,
|
||||
convert_timestamp(self.last_group, lg_microtime),
|
||||
self.lines_in_global,
|
||||
self.lines_in_last_group,
|
||||
format_bytes(self.bytes_in_global),
|
||||
format_bytes(self.bytes_in_last_group)
|
||||
)
|
||||
else:
|
||||
if self.verbose >= 1:
|
||||
self.string = (
|
||||
f"Processed {_pr_p_spf}% | {_pr_lc} / {_pr_lc} Lines "
|
||||
f"| ETA: {_pr_tf} / TR: {_pr_tf} / "
|
||||
"LR: {:,} lines in {}, {:,.2f} ({:,.2f}) lines/s"
|
||||
).format(
|
||||
float(percent),
|
||||
self.count,
|
||||
self.linecount,
|
||||
convert_timestamp(eta, eta_microtime),
|
||||
convert_timestamp(full_time_needed, ftn_microtime),
|
||||
self.lines_processed,
|
||||
convert_timestamp(self.last_group, lg_microtime),
|
||||
self.lines_in_global,
|
||||
self.lines_in_last_group
|
||||
)
|
||||
# prefix return string with line break if flagged
|
||||
self.string = ("\n" if self.prefix_lb else '') + self.string
|
||||
# print the string if verbose is turned on
|
||||
if self.verbose >= 1:
|
||||
print(self.string)
|
||||
|
||||
# write back vars
|
||||
self.last_percent = percent
|
||||
self.eta = eta
|
||||
self.full_time_needed = full_time_needed
|
||||
self.lg_microtime = lg_microtime
|
||||
# for the next run, check data
|
||||
self.start_time = time.time()
|
||||
self.current_count = self.count
|
||||
# trigger if this is a change
|
||||
self.change = 1
|
||||
else:
|
||||
# trigger if this is a change
|
||||
self.change = 0
|
||||
# return string
|
||||
return self.string
|
||||
# } END OF ShowPosition
|
||||
|
||||
# __END__
|
||||
95
src/CoreLibs/script_handling/script_helpers.py
Normal file
95
src/CoreLibs/script_handling/script_helpers.py
Normal file
@@ -0,0 +1,95 @@
|
||||
"""
|
||||
Helper methods for scripts
|
||||
"""
|
||||
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import psutil
|
||||
|
||||
|
||||
def wait_abort(sleep: int = 5) -> None:
|
||||
"""
|
||||
wait a certain time for an abort command
|
||||
|
||||
Keyword Arguments:
|
||||
sleep {int} -- _description_ (default: {5})
|
||||
"""
|
||||
try:
|
||||
print(f"Waiting {sleep} seconds (Press CTRL +C to abort) [", end="", flush=True)
|
||||
for _ in range(1, sleep):
|
||||
print(".", end="", flush=True)
|
||||
time.sleep(1)
|
||||
print("]", flush=True)
|
||||
except KeyboardInterrupt:
|
||||
print("\nInterrupted by user")
|
||||
sys.exit(0)
|
||||
print("\n\n")
|
||||
|
||||
|
||||
def lock_run(lock_file: Path) -> None:
|
||||
"""
|
||||
lock a script run
|
||||
needed is the lock file name
|
||||
|
||||
Arguments:
|
||||
lock_file {Path} -- _description_
|
||||
|
||||
Raises:
|
||||
IOError: _description_
|
||||
Exception: _description_
|
||||
IOError: _description_
|
||||
"""
|
||||
no_file = False
|
||||
run_pid = os.getpid()
|
||||
# or os.path.isfile()
|
||||
try:
|
||||
with open(lock_file, "r", encoding="UTF-8") as fp:
|
||||
exists = False
|
||||
pid = fp.read()
|
||||
fp.close()
|
||||
if pid:
|
||||
# check if this pid exists
|
||||
for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
|
||||
try:
|
||||
if pid == proc.info['pid']:
|
||||
exists = True
|
||||
break
|
||||
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
||||
# in case we cannot access
|
||||
continue
|
||||
if not exists:
|
||||
# no pid but lock file, unlink
|
||||
try:
|
||||
lock_file.unlink()
|
||||
no_file = True
|
||||
except IOError as e:
|
||||
raise IOError(f"Cannot remove lock_file: {lock_file}: {e}") from e
|
||||
else:
|
||||
raise IOError(f"Script is already running with PID {pid}")
|
||||
except IOError:
|
||||
no_file = True
|
||||
if no_file:
|
||||
try:
|
||||
with open(lock_file, "w", encoding="UTF-8") as fp:
|
||||
fp.write(str(run_pid))
|
||||
fp.close()
|
||||
except IOError as e:
|
||||
raise IOError(f"Cannot open run lock file '{lock_file}' for writing: {e}") from e
|
||||
|
||||
|
||||
def unlock_run(lock_file: Path) -> None:
|
||||
"""
|
||||
removes the lock file
|
||||
|
||||
Arguments:
|
||||
lock_file {Path} -- _description_
|
||||
|
||||
Raises:
|
||||
Exception: _description_
|
||||
"""
|
||||
try:
|
||||
lock_file.unlink()
|
||||
except IOError as e:
|
||||
raise IOError(f"Cannot remove lock_file: {lock_file}: {e}") from e
|
||||
37
src/CoreLibs/string_handling/byte_helpers.py
Normal file
37
src/CoreLibs/string_handling/byte_helpers.py
Normal file
@@ -0,0 +1,37 @@
|
||||
"""
|
||||
Format bytes
|
||||
"""
|
||||
|
||||
|
||||
def format_bytes(byte_value: float | int | str) -> str:
|
||||
"""
|
||||
Format a byte value to a human readable string
|
||||
|
||||
Arguments:
|
||||
byte_value {float | int | str} -- _description_
|
||||
|
||||
Returns:
|
||||
str -- _description_
|
||||
"""
|
||||
# if string exit
|
||||
if isinstance(byte_value, str):
|
||||
return byte_value
|
||||
# empty byte value is set to 0
|
||||
if not byte_value:
|
||||
byte_value = float(0)
|
||||
# if not float, convert to flaot
|
||||
if isinstance(byte_value, int):
|
||||
byte_value = float(byte_value)
|
||||
# loop through valid extensions
|
||||
for unit in ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB"]:
|
||||
# never go into the negativ and check if it is smaller than next set
|
||||
# if it is, print out return string
|
||||
if abs(byte_value) < 1024.0:
|
||||
return f"{byte_value:,.2f} {unit}"
|
||||
# divided for the next loop check
|
||||
byte_value /= 1024.0
|
||||
# if it is too big, return YB
|
||||
return f"{byte_value:,.2f} YB"
|
||||
|
||||
|
||||
# __NED__
|
||||
64
src/CoreLibs/string_handling/datetime_helpers.py
Normal file
64
src/CoreLibs/string_handling/datetime_helpers.py
Normal file
@@ -0,0 +1,64 @@
|
||||
"""
|
||||
Various string based date/time helpers
|
||||
"""
|
||||
|
||||
from math import floor
|
||||
import time
|
||||
|
||||
|
||||
def convert_timestamp(timestamp: float | int, show_micro: bool = True) -> str:
|
||||
"""
|
||||
format timestamp into human readable format
|
||||
|
||||
Arguments:
|
||||
timestamp {float} -- _description_
|
||||
|
||||
Keyword Arguments:
|
||||
show_micro {bool} -- _description_ (default: {True})
|
||||
|
||||
Returns:
|
||||
str -- _description_
|
||||
"""
|
||||
# cut of the ms, but first round them up to four
|
||||
__timestamp_ms_split = str(round(timestamp, 4)).split(".")
|
||||
timestamp = int(__timestamp_ms_split[0])
|
||||
try:
|
||||
ms = int(__timestamp_ms_split[1])
|
||||
except IndexError:
|
||||
ms = 0
|
||||
timegroups = (86400, 3600, 60, 1)
|
||||
output: list[int] = []
|
||||
for i in timegroups:
|
||||
output.append(int(floor(timestamp / i)))
|
||||
timestamp = timestamp % i
|
||||
# output has days|hours|min|sec ms
|
||||
time_string = ""
|
||||
if output[0]:
|
||||
time_string = f"{output[0]}d"
|
||||
if output[0] or output[1]:
|
||||
time_string += f"{output[1]}h "
|
||||
if output[0] or output[1] or output[2]:
|
||||
time_string += f"{output[2]}m "
|
||||
time_string += f"{output[3]}s"
|
||||
if show_micro:
|
||||
time_string += f" {ms}ms" if ms else " 0ms"
|
||||
return time_string
|
||||
|
||||
|
||||
def create_time(timestamp: float, timestamp_format: str = "%Y-%m-%d %H:%M:%S") -> str:
|
||||
"""
|
||||
just takes a timestamp and prints out humand readable format
|
||||
|
||||
Arguments:
|
||||
timestamp {float} -- _description_
|
||||
|
||||
Keyword Arguments:
|
||||
timestamp_format {_type_} -- _description_ (default: {"%Y-%m-%d %H:%M:%S"})
|
||||
|
||||
Returns:
|
||||
str -- _description_
|
||||
"""
|
||||
return time.strftime(timestamp_format, time.localtime(timestamp))
|
||||
|
||||
|
||||
# __END__
|
||||
38
src/CoreLibs/string_handling/hash_helpers.py
Normal file
38
src/CoreLibs/string_handling/hash_helpers.py
Normal file
@@ -0,0 +1,38 @@
|
||||
"""
|
||||
Various hash helpers for strings and things
|
||||
"""
|
||||
|
||||
import re
|
||||
import hashlib
|
||||
|
||||
|
||||
def crc32b_fix(crc: str) -> str:
|
||||
"""
|
||||
fix a CRC32B with wrong order (from old PHP)
|
||||
|
||||
Arguments:
|
||||
crc {str} -- _description_
|
||||
|
||||
Returns:
|
||||
str -- _description_
|
||||
"""
|
||||
# left pad with 0 to 8 chars
|
||||
crc = ("0" * (8 - len(crc))) + crc
|
||||
# flip two chars (byte hex)
|
||||
crc = re.sub(
|
||||
r"^([a-z0-9]{2})([a-z0-9]{2})([a-z0-9]{2})([a-z0-9]{2})$", r"\4\3\2\1", crc
|
||||
)
|
||||
return crc
|
||||
|
||||
|
||||
def sha1_short(string: str) -> str:
|
||||
"""
|
||||
Return a 9 character long SHA1 part
|
||||
|
||||
Arguments:
|
||||
string {str} -- _description_
|
||||
|
||||
Returns:
|
||||
str -- _description_
|
||||
"""
|
||||
return hashlib.sha1(string.encode('utf-8')).hexdigest()[:9]
|
||||
@@ -31,4 +31,56 @@ def shorten_string(string: str, length: int, hard_shorten: bool = False, placeho
|
||||
|
||||
return short_string
|
||||
|
||||
|
||||
def left_fill(string: str, width: int, char: str = " ") -> str:
|
||||
"""
|
||||
left fill for a certain length to fill a max size
|
||||
string is the original string to left padd, width is the maximum width
|
||||
that needs to be filled, char is the filler character
|
||||
|
||||
Arguments:
|
||||
string {str} -- _description_
|
||||
width {int} -- _description_
|
||||
|
||||
Keyword Arguments:
|
||||
char {str} -- _description_ (default: {" "})
|
||||
|
||||
Returns:
|
||||
str -- _description_
|
||||
"""
|
||||
# the width needs to be string
|
||||
if width < 0:
|
||||
width = len(string)
|
||||
# char can only be one length long
|
||||
if len(char) != 1:
|
||||
char = " "
|
||||
return (
|
||||
"{:"
|
||||
f"{char}>{width}"
|
||||
"}"
|
||||
).format(string)
|
||||
|
||||
|
||||
def format_number(number: float, precision: int = 0) -> str:
|
||||
"""
|
||||
format numbers, current trailing zeros does not work
|
||||
use {:,} or {:,.f} or {:,.<N>f} <N> = number instead of this
|
||||
|
||||
Arguments:
|
||||
number {float} -- _description_
|
||||
|
||||
Keyword Arguments:
|
||||
precision {int} -- _description_ (default: {0})
|
||||
|
||||
Returns:
|
||||
str -- _description_
|
||||
"""
|
||||
if precision < 0 and precision > 100:
|
||||
precision = 0
|
||||
return (
|
||||
"{:,."
|
||||
f"{str(precision)}"
|
||||
"f}"
|
||||
).format(number)
|
||||
|
||||
# __END__
|
||||
|
||||
26
tests/progress/data/foo.csv
Normal file
26
tests/progress/data/foo.csv
Normal file
@@ -0,0 +1,26 @@
|
||||
"6275980340000110250","okusuribukuro@kza.biglobe.ne.jp","2260029","神奈川県","横浜市緑区森の台","19−1−808","","御薬袋","功","0459310853","448ウ"
|
||||
"6275980340000110821","tanoshiku-nakayoku@s5.dion.ne.jp","2260026","神奈川県","横浜市緑区長津田町","2469−542","","稲垣","理佐","0459837010ウ","448"
|
||||
"6275980340000111167","snow4136@da2.so-net.ne.jp","2220036","神奈川県","横浜市港北区小机町","279−67","","吉田","幸子","0454765658ウ"","448"
|
||||
"6275980340000111241","kaori-5.29@ka.tnc.ne.jp","4200947","静岡県","静岡市葵区堤町","914−283","","矢口","香緒里","0542711840","448ウ""
|
||||
"6275980340000111324","Taikoowanrd@yahoo.co.jp","2300077","神奈川県","横浜市鶴見区東寺尾","1−15−L106","","菊地","そのへ","045ウ"5715949","448"
|
||||
"6275980340000111407","suzuki37@hotmail.com","2260016","神奈川県","横浜市緑区霧が丘","6−1−1−2−402","","鈴木","三奈","0459223865","448"
|
||||
"6275980340000111738","ajoa@bredband.net","2710067","千葉県","松戸市樋野口","771","J&F \"House DK Matsudo","〓〓","Manw","","448"
|
||||
"6275980340000111993","g7-chiro@mbp.nifty.com","2220031","神奈川県","横浜市港北区太尾町","1166−7","","角田","郁代","0455482822","448"
|
||||
"6275980340000112231","k_hama@w4.dion.ne.jp","2360052","神奈川県","横浜市金沢区富岡西","4−33−15","","浜田","和久","0457754803","448"
|
||||
"6275980340000113064",""reiko_hoshikawa"@hotmail.com","2220026","神奈川県","横浜市港北区","篠原町72-2","コンフォール篠原2-104","茂木","玲子","0454230900","448"
|
||||
"6275980340000113148","ali06@nifty.com","1640011","東京都","中野区中央","4−23−3","","齋藤","亞理","0333843247","448"
|
||||
"6275980340125312757","satokich@hotmail.com","6740094","兵庫県","明石市","二見町西二見1981-1","レーウ"フロンスA202","來田","淳子","","486"
|
||||
"6275980340079774754","m,a,n,a,mail@docomo.ne.jp","2630043","千葉県","千葉市稲毛区小仲台","7−6−1","レクセル稲毛パークス702","横山","雅菜","","447"
|
||||
"6275980340032948677","maya..mama.natsuki@docomo.ne.jp","2210863","神奈川県","横浜市神奈川区","羽沢町984","サンハイツ羽沢2-301","岡部","麻弥","","448"
|
||||
"6275980340032951044","ino.0827.yok@docomo.ne.jp","2310847","神奈川県","横浜市中区","竹之丸55","グリーンヒル山手A-2","猪俣","葉子","0456638634","448"
|
||||
"6275980340032952455","jigoro.ore@ezweb.ne.jp","2400007","神奈川県","横浜市保土ヶ谷区明神台","1−6−903","","土屋","尚子","045-331-5524
|
||||
test
|
||||
|
||||
","448"
|
||||
"6275980340032954196","acchi0819-lucida@docomo.ne.jp","2260006","神奈川県","横浜市緑区鴨居","4−55−1−416","","佐藤","敦","","448"
|
||||
"6275980340032955185","y.t-vs-a.h@docomo.ne.jp","2510052","神奈川県","藤沢市藤沢","1028−1","ミサワホームズ藤沢1106号室","土岐","麻美","0466244345","448"
|
||||
"6275980340076656582","yukko4513@ezweb.ne.jp","2200101","神奈川県","相模原市城山町","町屋4-24-24 ","","中野","幸子","0427825439
|
||||
","448"
|
||||
"6275980340125281648","k-tomomi-6.14@ezweb.ne.jp","6570024","兵庫県","神戸市灘区楠ヶ岡町","1‐2‐6","高羽グリーンハイツ203","神吉","友美","
|
||||
","486"
|
||||
"6275980340059092649","motoyaworld@hotmail.com","2220031","神奈川県","横浜市港北区","太尾町 344−5 ","ウ"ェラ大倉山 205号室","佐藤","基哉","0455470266","448"
|
||||
|
Can't render this file because it contains an unexpected character in line 3 and column 165.
|
29120
tests/progress/data/foo2.csv
Normal file
29120
tests/progress/data/foo2.csv
Normal file
File diff suppressed because it is too large
Load Diff
104
tests/progress/data/foo3.csv
Normal file
104
tests/progress/data/foo3.csv
Normal file
@@ -0,0 +1,104 @@
|
||||
"6275980340000110250","okusuribukuro@kza.biglobe.ne.jp","2260029","神奈川県","横浜市緑区森の台","19−1−808","","御薬袋","功","0459310853","448ウ"
|
||||
"6275980340000110821","tanoshiku-nakayoku@s5.dion.ne.jp","2260026","神奈川県","横浜市緑区長津田町","2469−542","","稲垣","理佐","0459837010ウ","448"
|
||||
"6275980340000111167","snow4136@da2.so-net.ne.jp","2220036","神奈川県","横浜市港北区小机町","279−67","","吉田","幸子","0454765658ウ"","448"
|
||||
"6275980340000111241","kaori-5.29@ka.tnc.ne.jp","4200947","静岡県","静岡市葵区堤町","914−283","","矢口","香緒里","0542711840","448ウ""
|
||||
"6275980340000111324","Taikoowanrd@yahoo.co.jp","2300077","神奈川県","横浜市鶴見区東寺尾","1−15−L106","","菊地","そのへ","045ウ"5715949","448"
|
||||
"6275980340000111407","suzuki37@hotmail.com","2260016","神奈川県","横浜市緑区霧が丘","6−1−1−2−402","","鈴木","三奈","0459223865","448"
|
||||
"6275980340000111738","ajoa@bredband.net","2710067","千葉県","松戸市樋野口","771","J&F \"House DK Matsudo","〓〓","Manw","","448"
|
||||
"6275980340000111993","g7-chiro@mbp.nifty.com","2220031","神奈川県","横浜市港北区太尾町","1166−7","","角田","郁代","0455482822","448"
|
||||
"6275980340000112231","k_hama@w4.dion.ne.jp","2360052","神奈川県","横浜市金沢区富岡西","4−33−15","","浜田","和久","0457754803","448"
|
||||
"6275980340000113064",""reiko_hoshikawa"@hotmail.com","2220026","神奈川県","横浜市港北区","篠原町72-2","コンフォール篠原2-104","茂木","玲子","0454230900","448"
|
||||
"6275980340000113148","ali06@nifty.com","1640011","東京都","中野区中央","4−23−3","","齋藤","亞理","0333843247","448"
|
||||
"6275980340125312757","satokich@hotmail.com","6740094","兵庫県","明石市","二見町西二見1981-1","レーウ"フロンスA202","來田","淳子","","486"
|
||||
"6275980340079774754","m,a,n,a,mail@docomo.ne.jp","2630043","千葉県","千葉市稲毛区小仲台","7−6−1","レクセル稲毛パークス702","横山","雅菜","","447"
|
||||
"6275980340032948677","maya..mama.natsuki@docomo.ne.jp","2210863","神奈川県","横浜市神奈川区","羽沢町984","サンハイツ羽沢2-301","岡部","麻弥","","448"
|
||||
"6275980340032951044","ino.0827.yok@docomo.ne.jp","2310847","神奈川県","横浜市中区","竹之丸55","グリーンヒル山手A-2","猪俣","葉子","0456638634","448"
|
||||
"6275980340032952455","jigoro.ore@ezweb.ne.jp","2400007","神奈川県","横浜市保土ヶ谷区明神台","1−6−903","","土屋","尚子","045-331-5524
|
||||
test
|
||||
|
||||
","448"
|
||||
"6275980340032954196","acchi0819-lucida@docomo.ne.jp","2260006","神奈川県","横浜市緑区鴨居","4−55−1−416","","佐藤","敦","","448"
|
||||
"6275980340032955185","y.t-vs-a.h@docomo.ne.jp","2510052","神奈川県","藤沢市藤沢","1028−1","ミサワホームズ藤沢1106号室","土岐","麻美","0466244345","448"
|
||||
"6275980340076656582","yukko4513@ezweb.ne.jp","2200101","神奈川県","相模原市城山町","町屋4-24-24 ","","中野","幸子","0427825439
|
||||
","448"
|
||||
"6275980340125281648","k-tomomi-6.14@ezweb.ne.jp","6570024","兵庫県","神戸市灘区楠ヶ岡町","1‐2‐6","高羽グリーンハイツ203","神吉","友美","
|
||||
","486"
|
||||
"6275980340059092649","motoyaworld@hotmail.com","2220031","神奈川県","横浜市港北区","太尾町 344−5 ","ウ"ェラ大倉山 205号室","佐藤","基哉","0455470266","448"
|
||||
"6275980340000110250","okusuribukuro@kza.biglobe.ne.jp","2260029","神奈川県","横浜市緑区森の台","19−1−808","","御薬袋","功","0459310853","448ウ"
|
||||
"6275980340000110821","tanoshiku-nakayoku@s5.dion.ne.jp","2260026","神奈川県","横浜市緑区長津田町","2469−542","","稲垣","理佐","0459837010ウ","448"
|
||||
"6275980340000111167","snow4136@da2.so-net.ne.jp","2220036","神奈川県","横浜市港北区小机町","279−67","","吉田","幸子","0454765658ウ"","448"
|
||||
"6275980340000111241","kaori-5.29@ka.tnc.ne.jp","4200947","静岡県","静岡市葵区堤町","914−283","","矢口","香緒里","0542711840","448ウ""
|
||||
"6275980340000111324","Taikoowanrd@yahoo.co.jp","2300077","神奈川県","横浜市鶴見区東寺尾","1−15−L106","","菊地","そのへ","045ウ"5715949","448"
|
||||
"6275980340000111407","suzuki37@hotmail.com","2260016","神奈川県","横浜市緑区霧が丘","6−1−1−2−402","","鈴木","三奈","0459223865","448"
|
||||
"6275980340000111738","ajoa@bredband.net","2710067","千葉県","松戸市樋野口","771","J&F \"House DK Matsudo","〓〓","Manw","","448"
|
||||
"6275980340000111993","g7-chiro@mbp.nifty.com","2220031","神奈川県","横浜市港北区太尾町","1166−7","","角田","郁代","0455482822","448"
|
||||
"6275980340000112231","k_hama@w4.dion.ne.jp","2360052","神奈川県","横浜市金沢区富岡西","4−33−15","","浜田","和久","0457754803","448"
|
||||
"6275980340000113064",""reiko_hoshikawa"@hotmail.com","2220026","神奈川県","横浜市港北区","篠原町72-2","コンフォール篠原2-104","茂木","玲子","0454230900","448"
|
||||
"6275980340000113148","ali06@nifty.com","1640011","東京都","中野区中央","4−23−3","","齋藤","亞理","0333843247","448"
|
||||
"6275980340125312757","satokich@hotmail.com","6740094","兵庫県","明石市","二見町西二見1981-1","レーウ"フロンスA202","來田","淳子","","486"
|
||||
"6275980340079774754","m,a,n,a,mail@docomo.ne.jp","2630043","千葉県","千葉市稲毛区小仲台","7−6−1","レクセル稲毛パークス702","横山","雅菜","","447"
|
||||
"6275980340032948677","maya..mama.natsuki@docomo.ne.jp","2210863","神奈川県","横浜市神奈川区","羽沢町984","サンハイツ羽沢2-301","岡部","麻弥","","448"
|
||||
"6275980340032951044","ino.0827.yok@docomo.ne.jp","2310847","神奈川県","横浜市中区","竹之丸55","グリーンヒル山手A-2","猪俣","葉子","0456638634","448"
|
||||
"6275980340032952455","jigoro.ore@ezweb.ne.jp","2400007","神奈川県","横浜市保土ヶ谷区明神台","1−6−903","","土屋","尚子","045-331-5524
|
||||
test
|
||||
|
||||
","448"
|
||||
"6275980340032954196","acchi0819-lucida@docomo.ne.jp","2260006","神奈川県","横浜市緑区鴨居","4−55−1−416","","佐藤","敦","","448"
|
||||
"6275980340032955185","y.t-vs-a.h@docomo.ne.jp","2510052","神奈川県","藤沢市藤沢","1028−1","ミサワホームズ藤沢1106号室","土岐","麻美","0466244345","448"
|
||||
"6275980340076656582","yukko4513@ezweb.ne.jp","2200101","神奈川県","相模原市城山町","町屋4-24-24 ","","中野","幸子","0427825439
|
||||
","448"
|
||||
"6275980340125281648","k-tomomi-6.14@ezweb.ne.jp","6570024","兵庫県","神戸市灘区楠ヶ岡町","1‐2‐6","高羽グリーンハイツ203","神吉","友美","
|
||||
","486"
|
||||
"6275980340059092649","motoyaworld@hotmail.com","2220031","神奈川県","横浜市港北区","太尾町 344−5 ","ウ"ェラ大倉山 205号室","佐藤","基哉","0455470266","448"
|
||||
"6275980340000110250","okusuribukuro@kza.biglobe.ne.jp","2260029","神奈川県","横浜市緑区森の台","19−1−808","","御薬袋","功","0459310853","448ウ"
|
||||
"6275980340000110821","tanoshiku-nakayoku@s5.dion.ne.jp","2260026","神奈川県","横浜市緑区長津田町","2469−542","","稲垣","理佐","0459837010ウ","448"
|
||||
"6275980340000111167","snow4136@da2.so-net.ne.jp","2220036","神奈川県","横浜市港北区小机町","279−67","","吉田","幸子","0454765658ウ"","448"
|
||||
"6275980340000111241","kaori-5.29@ka.tnc.ne.jp","4200947","静岡県","静岡市葵区堤町","914−283","","矢口","香緒里","0542711840","448ウ""
|
||||
"6275980340000111324","Taikoowanrd@yahoo.co.jp","2300077","神奈川県","横浜市鶴見区東寺尾","1−15−L106","","菊地","そのへ","045ウ"5715949","448"
|
||||
"6275980340000111407","suzuki37@hotmail.com","2260016","神奈川県","横浜市緑区霧が丘","6−1−1−2−402","","鈴木","三奈","0459223865","448"
|
||||
"6275980340000111738","ajoa@bredband.net","2710067","千葉県","松戸市樋野口","771","J&F \"House DK Matsudo","〓〓","Manw","","448"
|
||||
"6275980340000111993","g7-chiro@mbp.nifty.com","2220031","神奈川県","横浜市港北区太尾町","1166−7","","角田","郁代","0455482822","448"
|
||||
"6275980340000112231","k_hama@w4.dion.ne.jp","2360052","神奈川県","横浜市金沢区富岡西","4−33−15","","浜田","和久","0457754803","448"
|
||||
"6275980340000113064",""reiko_hoshikawa"@hotmail.com","2220026","神奈川県","横浜市港北区","篠原町72-2","コンフォール篠原2-104","茂木","玲子","0454230900","448"
|
||||
"6275980340000113148","ali06@nifty.com","1640011","東京都","中野区中央","4−23−3","","齋藤","亞理","0333843247","448"
|
||||
"6275980340125312757","satokich@hotmail.com","6740094","兵庫県","明石市","二見町西二見1981-1","レーウ"フロンスA202","來田","淳子","","486"
|
||||
"6275980340079774754","m,a,n,a,mail@docomo.ne.jp","2630043","千葉県","千葉市稲毛区小仲台","7−6−1","レクセル稲毛パークス702","横山","雅菜","","447"
|
||||
"6275980340032948677","maya..mama.natsuki@docomo.ne.jp","2210863","神奈川県","横浜市神奈川区","羽沢町984","サンハイツ羽沢2-301","岡部","麻弥","","448"
|
||||
"6275980340032951044","ino.0827.yok@docomo.ne.jp","2310847","神奈川県","横浜市中区","竹之丸55","グリーンヒル山手A-2","猪俣","葉子","0456638634","448"
|
||||
"6275980340032952455","jigoro.ore@ezweb.ne.jp","2400007","神奈川県","横浜市保土ヶ谷区明神台","1−6−903","","土屋","尚子","045-331-5524
|
||||
test
|
||||
|
||||
","448"
|
||||
"6275980340032954196","acchi0819-lucida@docomo.ne.jp","2260006","神奈川県","横浜市緑区鴨居","4−55−1−416","","佐藤","敦","","448"
|
||||
"6275980340032955185","y.t-vs-a.h@docomo.ne.jp","2510052","神奈川県","藤沢市藤沢","1028−1","ミサワホームズ藤沢1106号室","土岐","麻美","0466244345","448"
|
||||
"6275980340076656582","yukko4513@ezweb.ne.jp","2200101","神奈川県","相模原市城山町","町屋4-24-24 ","","中野","幸子","0427825439
|
||||
","448"
|
||||
"6275980340125281648","k-tomomi-6.14@ezweb.ne.jp","6570024","兵庫県","神戸市灘区楠ヶ岡町","1‐2‐6","高羽グリーンハイツ203","神吉","友美","
|
||||
","486"
|
||||
"6275980340059092649","motoyaworld@hotmail.com","2220031","神奈川県","横浜市港北区","太尾町 344−5 ","ウ"ェラ大倉山 205号室","佐藤","基哉","0455470266","448"
|
||||
"6275980340000110250","okusuribukuro@kza.biglobe.ne.jp","2260029","神奈川県","横浜市緑区森の台","19−1−808","","御薬袋","功","0459310853","448ウ"
|
||||
"6275980340000110821","tanoshiku-nakayoku@s5.dion.ne.jp","2260026","神奈川県","横浜市緑区長津田町","2469−542","","稲垣","理佐","0459837010ウ","448"
|
||||
"6275980340000111167","snow4136@da2.so-net.ne.jp","2220036","神奈川県","横浜市港北区小机町","279−67","","吉田","幸子","0454765658ウ"","448"
|
||||
"6275980340000111241","kaori-5.29@ka.tnc.ne.jp","4200947","静岡県","静岡市葵区堤町","914−283","","矢口","香緒里","0542711840","448ウ""
|
||||
"6275980340000111324","Taikoowanrd@yahoo.co.jp","2300077","神奈川県","横浜市鶴見区東寺尾","1−15−L106","","菊地","そのへ","045ウ"5715949","448"
|
||||
"6275980340000111407","suzuki37@hotmail.com","2260016","神奈川県","横浜市緑区霧が丘","6−1−1−2−402","","鈴木","三奈","0459223865","448"
|
||||
"6275980340000111738","ajoa@bredband.net","2710067","千葉県","松戸市樋野口","771","J&F \"House DK Matsudo","〓〓","Manw","","448"
|
||||
"6275980340000111993","g7-chiro@mbp.nifty.com","2220031","神奈川県","横浜市港北区太尾町","1166−7","","角田","郁代","0455482822","448"
|
||||
"6275980340000112231","k_hama@w4.dion.ne.jp","2360052","神奈川県","横浜市金沢区富岡西","4−33−15","","浜田","和久","0457754803","448"
|
||||
"6275980340000113064",""reiko_hoshikawa"@hotmail.com","2220026","神奈川県","横浜市港北区","篠原町72-2","コンフォール篠原2-104","茂木","玲子","0454230900","448"
|
||||
"6275980340000113148","ali06@nifty.com","1640011","東京都","中野区中央","4−23−3","","齋藤","亞理","0333843247","448"
|
||||
"6275980340125312757","satokich@hotmail.com","6740094","兵庫県","明石市","二見町西二見1981-1","レーウ"フロンスA202","來田","淳子","","486"
|
||||
"6275980340079774754","m,a,n,a,mail@docomo.ne.jp","2630043","千葉県","千葉市稲毛区小仲台","7−6−1","レクセル稲毛パークス702","横山","雅菜","","447"
|
||||
"6275980340032948677","maya..mama.natsuki@docomo.ne.jp","2210863","神奈川県","横浜市神奈川区","羽沢町984","サンハイツ羽沢2-301","岡部","麻弥","","448"
|
||||
"6275980340032951044","ino.0827.yok@docomo.ne.jp","2310847","神奈川県","横浜市中区","竹之丸55","グリーンヒル山手A-2","猪俣","葉子","0456638634","448"
|
||||
"6275980340032952455","jigoro.ore@ezweb.ne.jp","2400007","神奈川県","横浜市保土ヶ谷区明神台","1−6−903","","土屋","尚子","045-331-5524
|
||||
test
|
||||
|
||||
","448"
|
||||
"6275980340032954196","acchi0819-lucida@docomo.ne.jp","2260006","神奈川県","横浜市緑区鴨居","4−55−1−416","","佐藤","敦","","448"
|
||||
"6275980340032955185","y.t-vs-a.h@docomo.ne.jp","2510052","神奈川県","藤沢市藤沢","1028−1","ミサワホームズ藤沢1106号室","土岐","麻美","0466244345","448"
|
||||
"6275980340076656582","yukko4513@ezweb.ne.jp","2200101","神奈川県","相模原市城山町","町屋4-24-24 ","","中野","幸子","0427825439
|
||||
","448"
|
||||
"6275980340125281648","k-tomomi-6.14@ezweb.ne.jp","6570024","兵庫県","神戸市灘区楠ヶ岡町","1‐2‐6","高羽グリーンハイツ203","神吉","友美","
|
||||
","486"
|
||||
"6275980340059092649","motoyaworld@hotmail.com","2220031","神奈川県","横浜市港北区","太尾町 344−5 ","ウ"ェラ大倉山 205号室","佐藤","基哉","0455470266","448"
|
||||
|
Can't render this file because it contains an unexpected character in line 3 and column 165.
|
91
tests/progress/progress_test.py
Executable file
91
tests/progress/progress_test.py
Executable file
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
Test for progress class
|
||||
"""
|
||||
|
||||
import time
|
||||
from random import randint
|
||||
import sys
|
||||
import io
|
||||
from pathlib import Path
|
||||
from corelibs.file_handling.progress import Progress
|
||||
from corelibs.string_handling.datetime_helpers import convert_timestamp, create_time
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
test run
|
||||
"""
|
||||
# flag for file test or normal run
|
||||
use_file = 1
|
||||
|
||||
# variables for object init
|
||||
verbose = 1
|
||||
precision = -2
|
||||
microtime = 0
|
||||
wide_time = False
|
||||
# object init
|
||||
prg = Progress(
|
||||
verbose=verbose,
|
||||
precision=precision,
|
||||
microtime=microtime,
|
||||
wide_time=wide_time
|
||||
)
|
||||
# prg.SetPrecision(-2)
|
||||
# prg.SetStartTime(time.time())
|
||||
prg.set_start_time()
|
||||
print(
|
||||
f"PRECISION: {prg.precision} | TEN STEP: {prg.precision_ten_step} | "
|
||||
f"WIDE TEME: {prg.wide_time} | MICROTIME: {prg.microtime} | VERBOSE: {prg.verbose}"
|
||||
)
|
||||
|
||||
if use_file:
|
||||
file_name = 'foo2.csv'
|
||||
folder_name = 'data'
|
||||
script_path: Path = Path(__file__).resolve().parent
|
||||
file_path = script_path.joinpath(folder_name, file_name)
|
||||
current_size = 0
|
||||
# , newline=''
|
||||
with open(file_path, 'r', encoding="UTF-8") as fh:
|
||||
fh.seek(0, io.SEEK_END)
|
||||
prg.set_filesize(fh.tell())
|
||||
fh.seek(0, io.SEEK_SET)
|
||||
print(f"Is FH seekable: {fh.seekable()} | Is TTY: {fh.isatty()}")
|
||||
print(
|
||||
f"Buffer size: {io.DEFAULT_BUFFER_SIZE} | "
|
||||
f"Do Buffering: {fh.line_buffering} | "
|
||||
f"File size: {prg.filesize}"
|
||||
)
|
||||
data = fh.readline()
|
||||
while data:
|
||||
current_size += sys.getsizeof(data)
|
||||
# print(f"Data: {data}", end = '', flush = True)
|
||||
# print(f"Lenght: {len(data)} | Size: {sys.getsizeof(data):,}/{current_size:,}/{prg.filesize:,}")
|
||||
# prg.ShowPosition(current_size)
|
||||
# print(f"Tell: {fh.tell()}")
|
||||
# ouput progress with current file pos
|
||||
prg.show_position(fh.tell())
|
||||
data = fh.readline()
|
||||
else:
|
||||
print(f"Starting: {create_time(prg.start if prg.start is not None else 0)}")
|
||||
prg.set_linecount(256)
|
||||
i = 1
|
||||
while i <= prg.linecount:
|
||||
sleep = randint(1, 9)
|
||||
sleep /= 7
|
||||
time.sleep(sleep)
|
||||
# print(f"[{i}] Sleep for {sleep}")
|
||||
prg.show_position()
|
||||
i += 1
|
||||
prg.set_end_time()
|
||||
print(
|
||||
f"Start: {create_time(prg.start if prg.start is not None else 0)}, "
|
||||
f"End: {create_time(prg.end if prg.end is not None else 0)}, "
|
||||
f"Run Time: {convert_timestamp(prg.run_time if prg.run_time is not None else 0)}, "
|
||||
f"Verbose: {prg.verbose}"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
72
uv.lock
generated
72
uv.lock
generated
@@ -3,18 +3,60 @@ revision = 2
|
||||
requires-python = ">=3.13"
|
||||
|
||||
[[package]]
|
||||
name = "corelibs-python"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
name = "certifi"
|
||||
version = "2025.6.15"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/73/f7/f14b46d4bcd21092d7d3ccef689615220d8a08fb25e564b65d20738e672e/certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b", size = 158753, upload-time = "2025-06-15T02:45:51.329Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/84/ae/320161bd181fc06471eed047ecce67b693fd7515b16d495d8932db763426/certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057", size = 157650, upload-time = "2025-06-15T02:45:49.977Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "charset-normalizer"
|
||||
version = "3.4.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e4/33/89c2ced2b67d1c2a61c19c6751aa8902d46ce3dacb23600a283619f5a12d/charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63", size = 126367, upload-time = "2025-05-02T08:34:42.01Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/12/a93df3366ed32db1d907d7593a94f1fe6293903e3e92967bebd6950ed12c/charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0", size = 199622, upload-time = "2025-05-02T08:32:56.363Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/93/bf204e6f344c39d9937d3c13c8cd5bbfc266472e51fc8c07cb7f64fcd2de/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf", size = 143435, upload-time = "2025-05-02T08:32:58.551Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/2a/ea8a2095b0bafa6c5b5a55ffdc2f924455233ee7b91c69b7edfcc9e02284/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e", size = 153653, upload-time = "2025-05-02T08:33:00.342Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b6/57/1b090ff183d13cef485dfbe272e2fe57622a76694061353c59da52c9a659/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1", size = 146231, upload-time = "2025-05-02T08:33:02.081Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/28/ffc026b26f441fc67bd21ab7f03b313ab3fe46714a14b516f931abe1a2d8/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c", size = 148243, upload-time = "2025-05-02T08:33:04.063Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c0/0f/9abe9bd191629c33e69e47c6ef45ef99773320e9ad8e9cb08b8ab4a8d4cb/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691", size = 150442, upload-time = "2025-05-02T08:33:06.418Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/7c/a123bbcedca91d5916c056407f89a7f5e8fdfce12ba825d7d6b9954a1a3c/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0", size = 145147, upload-time = "2025-05-02T08:33:08.183Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/fe/1ac556fa4899d967b83e9893788e86b6af4d83e4726511eaaad035e36595/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b", size = 153057, upload-time = "2025-05-02T08:33:09.986Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/ff/acfc0b0a70b19e3e54febdd5301a98b72fa07635e56f24f60502e954c461/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff", size = 156454, upload-time = "2025-05-02T08:33:11.814Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/92/08/95b458ce9c740d0645feb0e96cea1f5ec946ea9c580a94adfe0b617f3573/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b", size = 154174, upload-time = "2025-05-02T08:33:13.707Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/be/8392efc43487ac051eee6c36d5fbd63032d78f7728cb37aebcc98191f1ff/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148", size = 149166, upload-time = "2025-05-02T08:33:15.458Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/44/96/392abd49b094d30b91d9fbda6a69519e95802250b777841cf3bda8fe136c/charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7", size = 98064, upload-time = "2025-05-02T08:33:17.06Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/b0/0200da600134e001d91851ddc797809e2fe0ea72de90e09bec5a2fbdaccb/charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980", size = 105641, upload-time = "2025-05-02T08:33:18.753Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/94/c5790835a017658cbfabd07f3bfb549140c3ac458cfc196323996b10095a/charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0", size = 52626, upload-time = "2025-05-02T08:34:40.053Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "corelibs"
|
||||
version = "0.3.0"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "jmespath" },
|
||||
{ name = "psutil" },
|
||||
{ name = "requests" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "jmespath", specifier = ">=1.0.1" },
|
||||
{ name = "psutil", specifier = ">=7.0.0" },
|
||||
{ name = "requests", specifier = ">=2.32.4" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.10"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -40,3 +82,27 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/50/e6/eecf58810b9d12e6427369784efe814a1eec0f492084ce8eb8f4d89d6d61/psutil-7.0.0-cp37-abi3-win32.whl", hash = "sha256:ba3fcef7523064a6c9da440fc4d6bd07da93ac726b5733c29027d7dc95b39d99", size = 241053, upload-time = "2025-02-13T21:54:34.31Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/1b/6921afe68c74868b4c9fa424dad3be35b095e16687989ebbb50ce4fceb7c/psutil-7.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:4cf3d4eb1aa9b348dec30105c55cd9b7d4629285735a102beb4441e38db90553", size = 244885, upload-time = "2025-02-13T21:54:37.486Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.32.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "certifi" },
|
||||
{ name = "charset-normalizer" },
|
||||
{ name = "idna" },
|
||||
{ name = "urllib3" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "2.5.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" },
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user