xiaojing 0.0.1__tar.gz → 0.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- xiaojing-0.0.3/LICENSE +21 -0
- xiaojing-0.0.3/PKG-INFO +82 -0
- xiaojing-0.0.3/README.md +62 -0
- xiaojing-0.0.3/pyproject.toml +37 -0
- xiaojing-0.0.3/src/xiaojing/__init__.py +76 -0
- xiaojing-0.0.3/src/xiaojing/py.typed +0 -0
- xiaojing-0.0.3/tests/test_xiaojing.py +53 -0
- xiaojing-0.0.1/PKG-INFO +0 -16
- xiaojing-0.0.1/README.md +0 -3
- xiaojing-0.0.1/ii_common/__init__.py +0 -2
- xiaojing-0.0.1/ii_common/ii_base_func/__init__.py +0 -5
- xiaojing-0.0.1/ii_common/ii_base_func/ii_ant.py +0 -6
- xiaojing-0.0.1/ii_common/ii_base_func/ii_class.py +0 -30
- xiaojing-0.0.1/ii_common/ii_base_func/ii_file.py +0 -35
- xiaojing-0.0.1/ii_common/ii_base_func/ii_model.py +0 -57
- xiaojing-0.0.1/ii_common/ii_base_func/ii_path.py +0 -41
- xiaojing-0.0.1/ii_common/ii_base_func/ii_str.py +0 -6
- xiaojing-0.0.1/ii_common/ii_base_func/ii_time.py +0 -75
- xiaojing-0.0.1/ii_common/ii_call_func/__init__.py +0 -3
- xiaojing-0.0.1/ii_common/ii_call_func/ii_ant.py +0 -6
- xiaojing-0.0.1/ii_common/ii_call_func/ii_judge.py +0 -21
- xiaojing-0.0.1/ii_common/ii_call_func/ii_sqlite.py +0 -145
- xiaojing-0.0.1/ii_common/ii_call_func/ii_tools.py +0 -119
- xiaojing-0.0.1/setup.cfg +0 -4
- xiaojing-0.0.1/setup.py +0 -29
- xiaojing-0.0.1/xiaojing.egg-info/PKG-INFO +0 -16
- xiaojing-0.0.1/xiaojing.egg-info/SOURCES.txt +0 -21
- xiaojing-0.0.1/xiaojing.egg-info/dependency_links.txt +0 -1
- xiaojing-0.0.1/xiaojing.egg-info/requires.txt +0 -7
- xiaojing-0.0.1/xiaojing.egg-info/top_level.txt +0 -1
xiaojing-0.0.3/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 lqxnjk
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
xiaojing-0.0.3/PKG-INFO
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: xiaojing
|
|
3
|
+
Version: 0.0.3
|
|
4
|
+
Summary: 长度、质量与温度的单位换算。
|
|
5
|
+
Project-URL: Homepage, https://pypi.org/project/xiaojing/
|
|
6
|
+
Author-email: lqxnjk <lqxnjk@qq.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Keywords: convert,length,mass,temperature,unit
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Classifier: Typing :: Typed
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# xiaojing
|
|
22
|
+
|
|
23
|
+
[English](#english) | 中文
|
|
24
|
+
|
|
25
|
+
长度、质量与温度的单位换算。
|
|
26
|
+
|
|
27
|
+
## 安装
|
|
28
|
+
|
|
29
|
+
```console
|
|
30
|
+
pip install xiaojing
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 用法
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from xiaojing import convert
|
|
37
|
+
|
|
38
|
+
convert(1, "km", "m") # 1000.0
|
|
39
|
+
convert(1, "mile", "km") # 1.609344
|
|
40
|
+
convert(1, "kg", "lb") # 2.204622...
|
|
41
|
+
convert(100, "c", "f") # 212.0
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 说明
|
|
45
|
+
|
|
46
|
+
长度与质量走「先归一到基准单位再换算」,所以任意两个受支持单位之间都能互转;温度单独处理,因为它不是线性缩放而是带偏移。未知单位抛 `KeyError`,不做模糊匹配。
|
|
47
|
+
|
|
48
|
+
## 许可证
|
|
49
|
+
|
|
50
|
+
MIT
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
<a id="english"></a>
|
|
55
|
+
## English
|
|
56
|
+
|
|
57
|
+
Convert units of length, mass and temperature.
|
|
58
|
+
|
|
59
|
+
## Install
|
|
60
|
+
|
|
61
|
+
```console
|
|
62
|
+
pip install xiaojing
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Usage
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
from xiaojing import convert
|
|
69
|
+
|
|
70
|
+
convert(1, "km", "m") # 1000.0
|
|
71
|
+
convert(1, "mile", "km") # 1.609344
|
|
72
|
+
convert(1, "kg", "lb") # 2.204622...
|
|
73
|
+
convert(100, "c", "f") # 212.0
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Notes
|
|
77
|
+
|
|
78
|
+
Length and mass convert through a base unit, so any supported pair works. Temperature is handled separately because it carries an offset, not just a scale. An unknown unit raises `KeyError` rather than being guessed.
|
|
79
|
+
|
|
80
|
+
## License
|
|
81
|
+
|
|
82
|
+
MIT
|
xiaojing-0.0.3/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# xiaojing
|
|
2
|
+
|
|
3
|
+
[English](#english) | 中文
|
|
4
|
+
|
|
5
|
+
长度、质量与温度的单位换算。
|
|
6
|
+
|
|
7
|
+
## 安装
|
|
8
|
+
|
|
9
|
+
```console
|
|
10
|
+
pip install xiaojing
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 用法
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from xiaojing import convert
|
|
17
|
+
|
|
18
|
+
convert(1, "km", "m") # 1000.0
|
|
19
|
+
convert(1, "mile", "km") # 1.609344
|
|
20
|
+
convert(1, "kg", "lb") # 2.204622...
|
|
21
|
+
convert(100, "c", "f") # 212.0
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 说明
|
|
25
|
+
|
|
26
|
+
长度与质量走「先归一到基准单位再换算」,所以任意两个受支持单位之间都能互转;温度单独处理,因为它不是线性缩放而是带偏移。未知单位抛 `KeyError`,不做模糊匹配。
|
|
27
|
+
|
|
28
|
+
## 许可证
|
|
29
|
+
|
|
30
|
+
MIT
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
<a id="english"></a>
|
|
35
|
+
## English
|
|
36
|
+
|
|
37
|
+
Convert units of length, mass and temperature.
|
|
38
|
+
|
|
39
|
+
## Install
|
|
40
|
+
|
|
41
|
+
```console
|
|
42
|
+
pip install xiaojing
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Usage
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from xiaojing import convert
|
|
49
|
+
|
|
50
|
+
convert(1, "km", "m") # 1000.0
|
|
51
|
+
convert(1, "mile", "km") # 1.609344
|
|
52
|
+
convert(1, "kg", "lb") # 2.204622...
|
|
53
|
+
convert(100, "c", "f") # 212.0
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Notes
|
|
57
|
+
|
|
58
|
+
Length and mass convert through a base unit, so any supported pair works. Temperature is handled separately because it carries an offset, not just a scale. An unknown unit raises `KeyError` rather than being guessed.
|
|
59
|
+
|
|
60
|
+
## License
|
|
61
|
+
|
|
62
|
+
MIT
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "xiaojing"
|
|
7
|
+
version = "0.0.3"
|
|
8
|
+
description = "长度、质量与温度的单位换算。"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "lqxnjk", email = "lqxnjk@qq.com" }]
|
|
13
|
+
keywords = ["unit", "convert", "length", "mass", "temperature"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Operating System :: OS Independent",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
21
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
22
|
+
"Typing :: Typed",
|
|
23
|
+
]
|
|
24
|
+
dependencies = []
|
|
25
|
+
|
|
26
|
+
[project.urls]
|
|
27
|
+
Homepage = "https://pypi.org/project/xiaojing/"
|
|
28
|
+
|
|
29
|
+
[tool.pytest.ini_options]
|
|
30
|
+
pythonpath = ["src"]
|
|
31
|
+
testpaths = ["tests"]
|
|
32
|
+
|
|
33
|
+
[tool.hatch.build.targets.wheel]
|
|
34
|
+
packages = ["src/xiaojing"]
|
|
35
|
+
|
|
36
|
+
[tool.hatch.build.targets.sdist]
|
|
37
|
+
include = ["src/xiaojing", "tests", "README.md", "LICENSE"]
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Author: lqxnjk <lqxnjk@qq.com>
|
|
3
|
+
Created: 2026-10-23 11:08
|
|
4
|
+
Modified: 2026-10-23 11:55
|
|
5
|
+
Python Version: 3.10
|
|
6
|
+
Unit conversion for length, mass and temperature.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
__all__ = ["convert", "units"]
|
|
12
|
+
|
|
13
|
+
# 基准单位:长度米、质量千克
|
|
14
|
+
_LENGTH = {
|
|
15
|
+
"mm": 0.001, "cm": 0.01, "m": 1.0, "km": 1000.0,
|
|
16
|
+
"inch": 0.0254, "foot": 0.3048, "mile": 1609.344,
|
|
17
|
+
}
|
|
18
|
+
_MASS = {
|
|
19
|
+
"mg": 1e-6, "g": 0.001, "kg": 1.0, "t": 1000.0,
|
|
20
|
+
"oz": 0.028349523125, "lb": 0.45359237,
|
|
21
|
+
}
|
|
22
|
+
_TABLES = {"length": _LENGTH, "mass": _MASS}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def units() -> dict[str, tuple[str, ...]]:
|
|
26
|
+
"""Return the supported unit names grouped by family."""
|
|
27
|
+
return {
|
|
28
|
+
"length": tuple(_LENGTH),
|
|
29
|
+
"mass": tuple(_MASS),
|
|
30
|
+
"temperature": ("c", "f", "k"),
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _temperature(m_value: float, m_from: str, m_to: str) -> float:
|
|
35
|
+
if m_from == m_to:
|
|
36
|
+
return m_value
|
|
37
|
+
if m_from == "c":
|
|
38
|
+
celsius = m_value
|
|
39
|
+
elif m_from == "f":
|
|
40
|
+
celsius = (m_value - 32.0) * 5.0 / 9.0
|
|
41
|
+
else:
|
|
42
|
+
celsius = m_value - 273.15
|
|
43
|
+
if m_to == "c":
|
|
44
|
+
return celsius
|
|
45
|
+
if m_to == "f":
|
|
46
|
+
return celsius * 9.0 / 5.0 + 32.0
|
|
47
|
+
return celsius + 273.15
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def convert(m_value: float, m_from: str, m_to: str) -> float:
|
|
51
|
+
"""Convert ``m_value`` between two units.
|
|
52
|
+
|
|
53
|
+
Units are case insensitive. Mixing families (``km`` to ``kg``) raises
|
|
54
|
+
``ValueError``; an unknown unit raises ``KeyError``.
|
|
55
|
+
"""
|
|
56
|
+
source = m_from.strip().lower()
|
|
57
|
+
target = m_to.strip().lower()
|
|
58
|
+
|
|
59
|
+
temperatures = ("c", "f", "k")
|
|
60
|
+
if source in temperatures or target in temperatures:
|
|
61
|
+
if source not in temperatures or target not in temperatures:
|
|
62
|
+
raise ValueError(f"cannot mix temperature with {m_from}/{m_to}")
|
|
63
|
+
return _temperature(float(m_value), source, target)
|
|
64
|
+
|
|
65
|
+
for table in _TABLES.values():
|
|
66
|
+
if source not in table or target not in table:
|
|
67
|
+
continue
|
|
68
|
+
return float(m_value) * table[source] / table[target]
|
|
69
|
+
|
|
70
|
+
source_family = next((name for name, table in _TABLES.items() if source in table), None)
|
|
71
|
+
target_family = next((name for name, table in _TABLES.items() if target in table), None)
|
|
72
|
+
if source_family is None:
|
|
73
|
+
raise KeyError(f"unknown unit: {m_from!r}")
|
|
74
|
+
if target_family is None:
|
|
75
|
+
raise KeyError(f"unknown unit: {m_to!r}")
|
|
76
|
+
raise ValueError(f"cannot convert {source_family} to {target_family}")
|
|
File without changes
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Author: lqxnjk <lqxnjk@qq.com>
|
|
3
|
+
Created: 2026-10-23 11:08
|
|
4
|
+
Modified: 2026-10-23 11:55
|
|
5
|
+
Python Version: 3.10
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
|
|
10
|
+
from xiaojing import convert, units
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_length() -> None:
|
|
14
|
+
assert convert(1, "km", "m") == 1000.0
|
|
15
|
+
assert convert(1, "mile", "km") == pytest.approx(1.609344)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_mass() -> None:
|
|
19
|
+
assert convert(1, "kg", "g") == 1000.0
|
|
20
|
+
assert convert(1, "kg", "lb") == pytest.approx(2.2046226218, rel=1e-9)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_temperature() -> None:
|
|
24
|
+
assert convert(100, "c", "f") == pytest.approx(212.0)
|
|
25
|
+
assert convert(32, "f", "c") == pytest.approx(0.0)
|
|
26
|
+
assert convert(0, "c", "k") == pytest.approx(273.15)
|
|
27
|
+
assert convert(5, "c", "c") == 5
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_case_insensitive() -> None:
|
|
31
|
+
assert convert(1, "KM", "M") == 1000.0
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_mixing_families_raises() -> None:
|
|
35
|
+
with pytest.raises(ValueError):
|
|
36
|
+
convert(1, "km", "kg")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_temperature_mixed_with_length_raises() -> None:
|
|
40
|
+
with pytest.raises(ValueError):
|
|
41
|
+
convert(1, "c", "km")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_unknown_unit() -> None:
|
|
45
|
+
with pytest.raises(KeyError):
|
|
46
|
+
convert(1, "parsec", "m")
|
|
47
|
+
with pytest.raises(KeyError):
|
|
48
|
+
convert(1, "m", "parsec")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_units_listing() -> None:
|
|
52
|
+
assert "length" in units()
|
|
53
|
+
assert "c" in units()["temperature"]
|
xiaojing-0.0.1/PKG-INFO
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: xiaojing
|
|
3
|
-
Version: 0.0.1
|
|
4
|
-
Summary: 皛鲸的工具箱
|
|
5
|
-
Home-page: https://xiaojing.cc/python
|
|
6
|
-
Author: liuxiaojing
|
|
7
|
-
Author-email: lqxnjk@qq.com
|
|
8
|
-
License: MIT
|
|
9
|
-
Classifier: Topic :: Software Development :: Libraries
|
|
10
|
-
Classifier: Programming Language :: Python
|
|
11
|
-
Requires-Python: >=3.7
|
|
12
|
-
Description-Content-Type: text/markdown
|
|
13
|
-
|
|
14
|
-
python .\setup.py sdist
|
|
15
|
-
|
|
16
|
-
pip install .\dist\xiaojingcc-2.0.0.tar.gz
|
xiaojing-0.0.1/README.md
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
from .ii_ant import *
|
|
2
|
-
|
|
3
|
-
__all__ = ["Singleton", "Shape"]
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class Singleton(type):
|
|
7
|
-
"""类的单例模式"""
|
|
8
|
-
_instances = {}
|
|
9
|
-
|
|
10
|
-
def __call__(cls, *args, **kwargs):
|
|
11
|
-
"""
|
|
12
|
-
:param cls: 类
|
|
13
|
-
:param args: 位置参数
|
|
14
|
-
:param kwargs: 关键字参数
|
|
15
|
-
"""
|
|
16
|
-
if cls not in cls._instances:
|
|
17
|
-
cls._instances[cls] = super().__call__(*args, **kwargs)
|
|
18
|
-
return cls._instances[cls]
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class Shape(abc.ABC):
|
|
22
|
-
"""抽象基类"""
|
|
23
|
-
|
|
24
|
-
@abc.abstractmethod
|
|
25
|
-
def area(self):
|
|
26
|
-
pass
|
|
27
|
-
|
|
28
|
-
@abc.abstractmethod
|
|
29
|
-
def perimeter(self):
|
|
30
|
-
pass
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
from .ii_ant import *
|
|
2
|
-
|
|
3
|
-
__all__ = ["FileInfo", "get_file_size_str"]
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class FileInfo:
|
|
7
|
-
def __init__(self, m_path):
|
|
8
|
-
"""
|
|
9
|
-
获取文件信息
|
|
10
|
-
:param m_path: 文件路径
|
|
11
|
-
"""
|
|
12
|
-
self.size = get_file_size_str(m_path)
|
|
13
|
-
self.ctime = datetime.datetime.fromtimestamp(os.path.getctime(m_path)).strftime('%Y-%m-%d %H:%M:%S')
|
|
14
|
-
self.mtime = datetime.datetime.fromtimestamp(os.path.getmtime(m_path)).strftime('%Y-%m-%d %H:%M:%S')
|
|
15
|
-
|
|
16
|
-
def __str__(self):
|
|
17
|
-
"""
|
|
18
|
-
返回文件信息
|
|
19
|
-
"""
|
|
20
|
-
return json.dumps({"size": self.size, "ctime": self.ctime, "mtime": self.mtime}, ensure_ascii=False)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def get_file_size_str(m_path):
|
|
24
|
-
"""
|
|
25
|
-
获取文件大小字符串
|
|
26
|
-
:param m_path: 文件路径
|
|
27
|
-
:return: 文件大小字符串
|
|
28
|
-
"""
|
|
29
|
-
ff_file_size = os.path.getsize(m_path)
|
|
30
|
-
for unit in ['B', 'KB', 'MB', 'GB']:
|
|
31
|
-
if abs(ff_file_size) < 1024.0:
|
|
32
|
-
return "{:3.1f} {}".format(ff_file_size, unit)
|
|
33
|
-
ff_file_size /= 1024.0
|
|
34
|
-
# 如果文件大小大于最大单位,则返回 GB 单位的文件大小字符串
|
|
35
|
-
return "{:.1f}GB".format(ff_file_size)
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
from .ii_ant import *
|
|
2
|
-
|
|
3
|
-
__all__ = ["func_mapping"]
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class FuncMapping:
|
|
7
|
-
def __init__(self):
|
|
8
|
-
self.__model_mapping = {}
|
|
9
|
-
|
|
10
|
-
def add_by_path(self, m_path, m_func, m_name):
|
|
11
|
-
"""
|
|
12
|
-
添加模型
|
|
13
|
-
:param m_path: 模块路径
|
|
14
|
-
:param m_func: 模块中函数名
|
|
15
|
-
:param m_name: 模块中函数名
|
|
16
|
-
"""
|
|
17
|
-
if not m_path.endswith(".py"):
|
|
18
|
-
raise Exception("Module path must be a .py file")
|
|
19
|
-
ff_path, ff_name = os.path.split(m_path)
|
|
20
|
-
sys.path.append(ff_path)
|
|
21
|
-
ff_func = getattr(importlib.import_module(os.path.splitext(ff_name)[0]), m_func)
|
|
22
|
-
if not isinstance(ff_func, FunctionType):
|
|
23
|
-
raise Exception("Model function must be a function")
|
|
24
|
-
self.__model_mapping[m_name] = ff_func
|
|
25
|
-
|
|
26
|
-
def add_by_func(self, m_name, m_func):
|
|
27
|
-
"""
|
|
28
|
-
添加模型
|
|
29
|
-
:param m_name: 模型名称
|
|
30
|
-
:param m_func: 模型函数
|
|
31
|
-
"""
|
|
32
|
-
if not isinstance(m_func, FunctionType):
|
|
33
|
-
raise Exception("Model function must be a function")
|
|
34
|
-
self.__model_mapping[m_name] = m_func
|
|
35
|
-
|
|
36
|
-
def get_func(self, m_name):
|
|
37
|
-
"""
|
|
38
|
-
获取模型
|
|
39
|
-
:param m_name: 模型名称
|
|
40
|
-
"""
|
|
41
|
-
return self.__model_mapping.get(m_name)
|
|
42
|
-
|
|
43
|
-
def remove_func(self, m_name):
|
|
44
|
-
"""
|
|
45
|
-
移除模型
|
|
46
|
-
:param m_name: 模型名称
|
|
47
|
-
"""
|
|
48
|
-
self.__model_mapping.pop(m_name)
|
|
49
|
-
|
|
50
|
-
def clear_all(self):
|
|
51
|
-
"""
|
|
52
|
-
清空模型
|
|
53
|
-
"""
|
|
54
|
-
self.__model_mapping.clear()
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
func_mapping = FuncMapping()
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
from .ii_ant import *
|
|
2
|
-
|
|
3
|
-
__all__ = ["path_to_abs", "path_to_rel", "PathSplit"]
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def path_to_abs(m_path):
|
|
7
|
-
"""
|
|
8
|
-
将相对路径转换为绝对路径
|
|
9
|
-
:param m_path: 相对路径
|
|
10
|
-
:return: 绝对路径
|
|
11
|
-
"""
|
|
12
|
-
if not os.path.isabs(m_path):
|
|
13
|
-
m_path = os.path.abspath(os.path.join(os.getcwd(), m_path))
|
|
14
|
-
return m_path
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def path_to_rel(m_path, m_origin=os.getcwd()):
|
|
18
|
-
"""
|
|
19
|
-
将绝对路径转换为相对路径
|
|
20
|
-
:param m_path: 绝对路径
|
|
21
|
-
:param m_origin: 相对路径的起始目录
|
|
22
|
-
:return: 相对路径
|
|
23
|
-
"""
|
|
24
|
-
if os.path.isabs(m_path):
|
|
25
|
-
m_path = os.path.relpath(m_path, start=m_origin)
|
|
26
|
-
return m_path
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class PathSplit:
|
|
30
|
-
"""
|
|
31
|
-
路径分割
|
|
32
|
-
"""
|
|
33
|
-
|
|
34
|
-
def __init__(self, m_path):
|
|
35
|
-
"""
|
|
36
|
-
初始化
|
|
37
|
-
:param m_path: 路径
|
|
38
|
-
"""
|
|
39
|
-
self.path = os.path.split(m_path)[0]
|
|
40
|
-
self.name, self.suffix = os.path.splitext(os.path.basename(m_path))
|
|
41
|
-
self.suffix = self.suffix.strip(".")
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
from .ii_ant import *
|
|
2
|
-
|
|
3
|
-
__all__ = ["time_now", "time_format"]
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def time_now(n_kind: str = None, n_out_format: str = None) -> str:
|
|
7
|
-
"""
|
|
8
|
-
获取当前时间
|
|
9
|
-
:param n_kind: 格式化类型(n,ny,nyr,s,sf,sfm,name)
|
|
10
|
-
:param n_out_format: 输出时间的格式化
|
|
11
|
-
"""
|
|
12
|
-
return time_format(
|
|
13
|
-
m_time=datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=8))),
|
|
14
|
-
n_kind=n_kind,
|
|
15
|
-
n_out_format=n_out_format,
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def time_format(m_time, n_kind: str = None, n_in_format: str = None, n_out_format: str = None) -> str:
|
|
20
|
-
"""
|
|
21
|
-
格式化时间
|
|
22
|
-
:param m_time: 待格式化的时间
|
|
23
|
-
:param n_kind: 格式化类型(n,ny,nyr,s,sf,sfm,name)
|
|
24
|
-
:param n_in_format: 输入时间的格式化
|
|
25
|
-
:param n_out_format: 输出时间的格式化
|
|
26
|
-
"""
|
|
27
|
-
time_pattern = r"(Mon|Tue|Wed|Thu|Fri|Sat|Sun), (\d+) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) (\d{2}:\d{2}:\d{2}) "
|
|
28
|
-
if n_out_format is None:
|
|
29
|
-
if n_kind == "n":
|
|
30
|
-
n_out_format = "%Y"
|
|
31
|
-
elif n_kind == "ny":
|
|
32
|
-
n_out_format = "%Y%m"
|
|
33
|
-
elif n_kind == "nyr":
|
|
34
|
-
n_out_format = "%Y%m%d"
|
|
35
|
-
elif n_kind == "s":
|
|
36
|
-
n_out_format = "%Y%m%d%H"
|
|
37
|
-
elif n_kind == "sf":
|
|
38
|
-
n_out_format = "%Y%m%d%H%M"
|
|
39
|
-
elif n_kind == "sfm":
|
|
40
|
-
n_out_format = "%Y%m%d%H%M%S"
|
|
41
|
-
elif n_kind == "name":
|
|
42
|
-
n_out_format = "%Y%m%d-%H%M%S-%f"
|
|
43
|
-
elif n_kind is None:
|
|
44
|
-
n_out_format = "%Y-%m-%d %H:%M:%S.%f"
|
|
45
|
-
else:
|
|
46
|
-
n_out_format = n_kind
|
|
47
|
-
if n_in_format is not None:
|
|
48
|
-
return datetime.datetime.strptime(m_time, n_in_format).strftime(n_out_format)
|
|
49
|
-
elif type(m_time) is datetime.datetime:
|
|
50
|
-
return m_time.strftime(n_out_format)
|
|
51
|
-
elif type(m_time) is time.struct_time:
|
|
52
|
-
return time.strftime(n_out_format, m_time)
|
|
53
|
-
elif type(m_time) is str and re.match(time_pattern, m_time):
|
|
54
|
-
original_dt = datetime.datetime.strptime(m_time, "%a, %d %b %Y %H:%M:%S %Z") # 解析原始时间字符串
|
|
55
|
-
timestamp = time.mktime(original_dt.timetuple()) # 计算原始时间的UTC时间戳
|
|
56
|
-
beijing_timestamp = timestamp + 8 * 3600 # 计算北京时间的时间戳
|
|
57
|
-
beijing_dt = datetime.datetime.fromtimestamp(beijing_timestamp)
|
|
58
|
-
return beijing_dt.strftime(n_out_format) # 按指定格式输出北京时间字符串
|
|
59
|
-
elif type(m_time) is float:
|
|
60
|
-
return datetime.datetime.fromtimestamp(m_time).strftime(n_out_format)
|
|
61
|
-
elif type(m_time) is str and re.match("^[0-9]{4}$", m_time):
|
|
62
|
-
return datetime.datetime.strptime(m_time, "%Y").strftime(n_out_format)
|
|
63
|
-
elif type(m_time) is str and re.match("^[0-9]{8}$", m_time):
|
|
64
|
-
return datetime.datetime.strptime(m_time, "%Y%m%d").strftime(n_out_format)
|
|
65
|
-
elif type(m_time) is str and re.match("^[0-9]{4}-[0-9]{2}-[0-9]{2}$", m_time):
|
|
66
|
-
return datetime.datetime.strptime(m_time, "%Y-%m-%d").strftime(n_out_format)
|
|
67
|
-
elif type(m_time) is str and re.match(
|
|
68
|
-
"^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$", m_time):
|
|
69
|
-
return datetime.datetime.strptime(m_time[:19], "%Y-%m-%d %H:%M:%S").strftime(n_out_format)
|
|
70
|
-
elif type(m_time) is str and re.match("^[0-9]{8}-[0-9]{6}-[0-9]{6}$", m_time):
|
|
71
|
-
return datetime.datetime.strptime(m_time[:19], "%Y%m%d-%H%M%S-%f").strftime(n_out_format)
|
|
72
|
-
elif type(m_time) is str and re.match("^[0-9]{8}-[0-9]{6}$", m_time):
|
|
73
|
-
return datetime.datetime.strptime(m_time[:19], "%Y%m%d-%H%M%S").strftime(n_out_format)
|
|
74
|
-
elif type(m_time) is str and re.match("^[0-9]{14}$", m_time):
|
|
75
|
-
return datetime.datetime.strptime(m_time[:19], "%Y%m%d%H%M%S").strftime(n_out_format)
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
from .ii_ant import *
|
|
2
|
-
|
|
3
|
-
__all__ = ["not_none", "is_none"]
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def not_none(m_data):
|
|
7
|
-
"""
|
|
8
|
-
判断是否为空
|
|
9
|
-
:param m_data: 数据
|
|
10
|
-
"""
|
|
11
|
-
return not is_none(m_data)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def is_none(m_data):
|
|
15
|
-
"""
|
|
16
|
-
判断是否为空
|
|
17
|
-
:param m_data: 数据
|
|
18
|
-
"""
|
|
19
|
-
if isinstance(m_data, (float, int, complex)):
|
|
20
|
-
return numpy.isnan(m_data)
|
|
21
|
-
return not m_data
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
from .ii_ant import *
|
|
2
|
-
|
|
3
|
-
__all__ = ["SqliteDB"]
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class SqliteDB:
|
|
7
|
-
"""
|
|
8
|
-
sqlite数据库操作类
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
def __init__(self, m_path):
|
|
12
|
-
"""
|
|
13
|
-
初始化
|
|
14
|
-
:param m_path: 数据库文件路径
|
|
15
|
-
"""
|
|
16
|
-
self.db = m_path
|
|
17
|
-
self.cn = sqlite3.connect(database=self.db)
|
|
18
|
-
self.cs = self.cn.cursor()
|
|
19
|
-
self.tb = self.crud(self.cn, "SELECT name FROM `sqlite_master` WHERE type='table'")
|
|
20
|
-
self.fi = dict(json.loads(FileInfo(self.db).__str__()))
|
|
21
|
-
|
|
22
|
-
def __str__(self):
|
|
23
|
-
"""
|
|
24
|
-
返回字符串, 方便打印
|
|
25
|
-
"""
|
|
26
|
-
return json.dumps({"db": self.db, "fi": self.fi, "tb": self.tb}, ensure_ascii=False, default=str)
|
|
27
|
-
|
|
28
|
-
def cursor(self):
|
|
29
|
-
"""
|
|
30
|
-
获取游标, 开始事务
|
|
31
|
-
"""
|
|
32
|
-
ff_cursor = self.cn.cursor()
|
|
33
|
-
ff_cursor.execute('BEGIN')
|
|
34
|
-
return ff_cursor
|
|
35
|
-
|
|
36
|
-
@staticmethod
|
|
37
|
-
def commit(m_curs):
|
|
38
|
-
"""
|
|
39
|
-
提交事务
|
|
40
|
-
"""
|
|
41
|
-
m_curs.execute('COMMIT')
|
|
42
|
-
|
|
43
|
-
def vacuum(self):
|
|
44
|
-
"""
|
|
45
|
-
优化数据库, 释放空间
|
|
46
|
-
"""
|
|
47
|
-
self.cs.execute('VACUUM;')
|
|
48
|
-
self.cn.commit()
|
|
49
|
-
|
|
50
|
-
@staticmethod
|
|
51
|
-
def crud(m_curs, m_sql: str, n_value=None):
|
|
52
|
-
"""
|
|
53
|
-
执行sql语句方法
|
|
54
|
-
:param m_curs: 游标
|
|
55
|
-
:param m_sql: 查询语句
|
|
56
|
-
:param n_value: 查询参数
|
|
57
|
-
"""
|
|
58
|
-
if n_value is None: # X执行sql语句方法
|
|
59
|
-
ff_queried = m_curs.execute(m_sql)
|
|
60
|
-
elif type(n_value) is list:
|
|
61
|
-
ff_queried = m_curs.executemany(m_sql, n_value)
|
|
62
|
-
else:
|
|
63
|
-
ff_queried = m_curs.execute(m_sql, n_value)
|
|
64
|
-
ff_rows = ff_queried.fetchall() # X获取表名
|
|
65
|
-
if ff_rows:
|
|
66
|
-
columns = [description[0] for description in ff_queried.description]
|
|
67
|
-
ff_mid_rows = []
|
|
68
|
-
for row in ff_rows:
|
|
69
|
-
ff_mid_rows.append(dict(zip(columns, row)))
|
|
70
|
-
ff_rows = ff_mid_rows
|
|
71
|
-
return ff_rows
|
|
72
|
-
|
|
73
|
-
def create(self, m_dict, m_tb, n_primary: str = None, n_unique: list = None):
|
|
74
|
-
"""
|
|
75
|
-
创建表
|
|
76
|
-
:param m_dict: 字段名和类型
|
|
77
|
-
:param m_tb: 表名
|
|
78
|
-
:param n_primary: 主键
|
|
79
|
-
:param n_unique: 唯一键
|
|
80
|
-
"""
|
|
81
|
-
columns = "`" + "`,`".join(m_dict.keys()) + "`" # 获取所有的键(字段名),并用逗号分隔
|
|
82
|
-
if n_primary is None:
|
|
83
|
-
n_primary = list(m_dict.keys())[0]
|
|
84
|
-
create_sql = f"CREATE TABLE IF NOT EXISTS {m_tb} ({columns})".replace(
|
|
85
|
-
f"`{n_primary}`,", f"`{n_primary}` PRIMARY KEY,"
|
|
86
|
-
)
|
|
87
|
-
if n_unique is not None:
|
|
88
|
-
create_sql = create_sql[:-1] + f',UNIQUE({",".join(n_unique)}))'
|
|
89
|
-
self.crud(m_curs=self.cs, m_sql=create_sql)
|
|
90
|
-
|
|
91
|
-
def insert_one_json(self, m_curs, m_tb: str, m_dict: dict):
|
|
92
|
-
"""
|
|
93
|
-
插入一条数据
|
|
94
|
-
:param m_curs: 游标
|
|
95
|
-
:param m_tb: 表名
|
|
96
|
-
:param m_dict: 数据
|
|
97
|
-
"""
|
|
98
|
-
ff_columns_str = ", ".join(m_dict.keys())
|
|
99
|
-
ff_values_list = [m_dict.get(key, None) for key in m_dict]
|
|
100
|
-
ff_placeholder_str = ", ".join("?" * len(ff_values_list))
|
|
101
|
-
ff_insert_sql = f"INSERT OR IGNORE INTO {m_tb} ({ff_columns_str}) VALUES ({ff_placeholder_str})"
|
|
102
|
-
self.crud(m_curs=m_curs, m_sql=ff_insert_sql, n_value=tuple(ff_values_list))
|
|
103
|
-
|
|
104
|
-
def insert_many_json(self, m_curs, m_tb: str, m_list: list):
|
|
105
|
-
"""
|
|
106
|
-
插入多条数据
|
|
107
|
-
:param m_curs: 游标
|
|
108
|
-
:param m_tb: 表名
|
|
109
|
-
:param m_list: 数据
|
|
110
|
-
"""
|
|
111
|
-
ff_columns_set = set()
|
|
112
|
-
for ff_item in m_list:
|
|
113
|
-
ff_columns_set.update(ff_item.keys())
|
|
114
|
-
ff_columns_list = sorted(list(ff_columns_set))
|
|
115
|
-
ff_columns_str = ", ".join(ff_columns_list)
|
|
116
|
-
ff_placeholder_str = ", ".join("?" for i in range(len(ff_columns_list)))
|
|
117
|
-
ff_insert_sql = f"INSERT OR IGNORE INTO {m_tb} ({ff_columns_str}) VALUES ({ff_placeholder_str})"
|
|
118
|
-
ff_values_list = []
|
|
119
|
-
for ff_item in m_list:
|
|
120
|
-
ff_row_data = [ff_item.get(column, None) for column in ff_columns_list]
|
|
121
|
-
ff_row_data = [(json.dumps(i, ensure_ascii=False) if type(i) in [dict, list] else i) for i in ff_row_data]
|
|
122
|
-
ff_values_list.append(tuple(ff_row_data))
|
|
123
|
-
self.crud(m_curs=m_curs, m_sql=ff_insert_sql, n_value=ff_values_list)
|
|
124
|
-
|
|
125
|
-
def query_many_json(self, m_curs, m_tb, n_keys: list = None, n_mapping=None, n_skip=0, n_limit='-1'):
|
|
126
|
-
"""
|
|
127
|
-
查询多条数据
|
|
128
|
-
:param m_curs: 游标
|
|
129
|
-
:param m_tb: 表名
|
|
130
|
-
:param n_keys: 查询的字段名
|
|
131
|
-
:param n_mapping: 查询条件
|
|
132
|
-
:param n_skip: 跳过多少条
|
|
133
|
-
:param n_limit: 查询多少条
|
|
134
|
-
"""
|
|
135
|
-
if n_keys is None:
|
|
136
|
-
n_keys = "*"
|
|
137
|
-
else:
|
|
138
|
-
n_keys = ",".join(n_keys)
|
|
139
|
-
if n_mapping is None:
|
|
140
|
-
n_mapping = ""
|
|
141
|
-
else:
|
|
142
|
-
n_mapping = "where " + " and ".join([f"{k}='{v}'" for k, v in n_mapping.items()])
|
|
143
|
-
ff_sql_query = f"select {n_keys} from {m_tb} {n_mapping} limit {n_skip},{n_limit}"
|
|
144
|
-
self.crud(m_curs=m_curs, m_sql=ff_sql_query)
|
|
145
|
-
pass
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
from .ii_ant import *
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class Tqdm:
|
|
5
|
-
"""
|
|
6
|
-
进度条
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
def __init__(self, m_iterable, n_desc="Processing", n_interval=0.23):
|
|
10
|
-
"""
|
|
11
|
-
:param m_iterable: 可迭代对象
|
|
12
|
-
:param n_desc: 描述
|
|
13
|
-
:param n_interval: 更新间隔
|
|
14
|
-
"""
|
|
15
|
-
# 将传入的可迭代对象赋值给实例变量ff_iterable
|
|
16
|
-
self.ff_iterable = m_iterable
|
|
17
|
-
# 将可迭代对象转换为列表并赋值给实例变量ff_keys
|
|
18
|
-
self.ff_keys = list(m_iterable)
|
|
19
|
-
# 计算ff_keys的长度并赋值给实例变量ff_total
|
|
20
|
-
self.ff_total = len(self.ff_keys)
|
|
21
|
-
# 将传入的描述赋值给实例变量ff_desc
|
|
22
|
-
self.ff_desc = n_desc
|
|
23
|
-
# 初始化当前进度为0
|
|
24
|
-
self.ff_current = 0
|
|
25
|
-
# 初始化进度条宽度为40
|
|
26
|
-
self.ff_width = 40
|
|
27
|
-
# 创建一个线程锁并赋值给实例变量ff_lock
|
|
28
|
-
self.ff_lock = threading.Lock()
|
|
29
|
-
# 初始化总时间为0
|
|
30
|
-
self.ff_total_time = 0
|
|
31
|
-
# 记录开始时间
|
|
32
|
-
self.ff_start_time = time.monotonic()
|
|
33
|
-
# 初始化已用时间为0
|
|
34
|
-
self.ff_elapsed_time = 0
|
|
35
|
-
# 初始化平均时间为0
|
|
36
|
-
self.ff_avg_time = 0
|
|
37
|
-
# 将传入的更新间隔赋值给实例变量ff_update_interval
|
|
38
|
-
self.ff_update_interval = n_interval
|
|
39
|
-
# 创建一个线程并指定线程执行的目标方法为progress_bar
|
|
40
|
-
self.ff_progress_thread = threading.Thread(target=self.progress_bar, daemon=True)
|
|
41
|
-
# 启动进度条线程
|
|
42
|
-
self.ff_progress_thread.start()
|
|
43
|
-
|
|
44
|
-
def progress_bar(self):
|
|
45
|
-
"""
|
|
46
|
-
子线程更新进度条
|
|
47
|
-
"""
|
|
48
|
-
# 记录上次更新时间
|
|
49
|
-
last_update_time = time.monotonic()
|
|
50
|
-
while True:
|
|
51
|
-
with self.ff_lock:
|
|
52
|
-
# 计算进度
|
|
53
|
-
progress = self.ff_current / self.ff_total if self.ff_total > 0 else 0
|
|
54
|
-
# 转换为百分比
|
|
55
|
-
percentage = int(progress * 100)
|
|
56
|
-
# 生成进度条字符串
|
|
57
|
-
bar = "|" + "\033[32m" + "#" * int(progress * self.ff_width) + "-" * (
|
|
58
|
-
self.ff_width - int(progress * self.ff_width)) + "\033[0m" + "|"
|
|
59
|
-
# 生成消息字符串
|
|
60
|
-
msg = "\033[34m" + f"{self.ff_desc}: {self.ff_current}/{self.ff_total} ({percentage}%)" + "\033[0m"
|
|
61
|
-
# 获取当前时间
|
|
62
|
-
current_time = time.monotonic()
|
|
63
|
-
# 计算已用时间
|
|
64
|
-
self.ff_elapsed_time += current_time - last_update_time
|
|
65
|
-
# 更新上次更新时间
|
|
66
|
-
last_update_time = current_time
|
|
67
|
-
# 如果当前进度大于0,则计算平均时间
|
|
68
|
-
if self.ff_current > 1:
|
|
69
|
-
self.ff_avg_time = self.ff_total_time / (self.ff_current - 1)
|
|
70
|
-
# 格式化平均时间字符串
|
|
71
|
-
time_per_item = f"{self.ff_avg_time:.2f}s/item"
|
|
72
|
-
# 生成已用时间消息字符串
|
|
73
|
-
elapsed_msg = "\033[35m" + f"Elapsed: {self.ff_elapsed_time:.2f}s ({time_per_item})" + "\033[0m"
|
|
74
|
-
# 计算剩余时间
|
|
75
|
-
remaining_time = (self.ff_total - self.ff_current) * self.ff_avg_time if self.ff_current > 0 else 0
|
|
76
|
-
# 将剩余时间转换为日期时间格式
|
|
77
|
-
remaining_datetime = datetime.datetime.fromtimestamp(time.time() + remaining_time)
|
|
78
|
-
# 生成预计剩余时间消息字符串
|
|
79
|
-
remaining_msg = "\033[36m" + f"ETA: {remaining_datetime.strftime('%F %T')}" + "\033[0m"
|
|
80
|
-
# 输出进度条和相关信息到控制台
|
|
81
|
-
sys.stdout.write(f"\r{msg} {bar} {elapsed_msg} {remaining_msg}")
|
|
82
|
-
sys.stdout.flush()
|
|
83
|
-
# 如果当前进度达到总进度,则跳出循环
|
|
84
|
-
if self.ff_current >= self.ff_total:
|
|
85
|
-
break
|
|
86
|
-
# 休眠一段时间
|
|
87
|
-
time.sleep(self.ff_update_interval)
|
|
88
|
-
# 输出换行符
|
|
89
|
-
sys.stdout.write("\n")
|
|
90
|
-
|
|
91
|
-
def __iter__(self):
|
|
92
|
-
return self
|
|
93
|
-
|
|
94
|
-
def __next__(self):
|
|
95
|
-
"""
|
|
96
|
-
:return: 返回下一个元素
|
|
97
|
-
"""
|
|
98
|
-
with self.ff_lock:
|
|
99
|
-
# 如果当前进度小于总进度
|
|
100
|
-
if self.ff_current < self.ff_total:
|
|
101
|
-
# 记录开始时间
|
|
102
|
-
start_time = self.ff_start_time
|
|
103
|
-
# 当前进度加1
|
|
104
|
-
self.ff_current += 1
|
|
105
|
-
# 获取当前进度的元素
|
|
106
|
-
result = self.ff_keys[self.ff_current - 1]
|
|
107
|
-
# 记录结束时间
|
|
108
|
-
end_time = time.monotonic()
|
|
109
|
-
# 计算当前元素的处理时间
|
|
110
|
-
item_time = end_time - start_time
|
|
111
|
-
# 累加总处理时间
|
|
112
|
-
self.ff_total_time += item_time
|
|
113
|
-
# 更新开始时间为当前时间
|
|
114
|
-
self.ff_start_time = time.monotonic()
|
|
115
|
-
# 返回当前元素
|
|
116
|
-
return result
|
|
117
|
-
else:
|
|
118
|
-
# 如果当前进度已经达到总进度,则抛出停止迭代的异常
|
|
119
|
-
raise StopIteration
|
xiaojing-0.0.1/setup.cfg
DELETED
xiaojing-0.0.1/setup.py
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
from setuptools import setup, find_packages
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def read_file(filename: str) -> str:
|
|
5
|
-
with open(filename, mode='r', encoding='utf-8') as input_file:
|
|
6
|
-
return input_file.read()
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
setup(
|
|
10
|
-
name='xiaojing',
|
|
11
|
-
version='0.0.1',
|
|
12
|
-
description='皛鲸的工具箱',
|
|
13
|
-
author='liuxiaojing',
|
|
14
|
-
author_email='lqxnjk@qq.com',
|
|
15
|
-
url='https://xiaojing.cc/python',
|
|
16
|
-
long_description=read_file("README.md"), # 详细说明
|
|
17
|
-
long_description_content_type="text/markdown", # 详细说明使用标记类型
|
|
18
|
-
classifiers=['Topic :: Software Development :: Libraries',
|
|
19
|
-
'Programming Language :: Python'],
|
|
20
|
-
license='MIT',
|
|
21
|
-
install_requires=[
|
|
22
|
-
"pandas==1.3.5", "xlrd==1.2.0",
|
|
23
|
-
"pymysql", "requests", "openpyxl", "sqlalchemy", "pymongo"
|
|
24
|
-
],
|
|
25
|
-
python_requires='>=3.7',
|
|
26
|
-
packages=find_packages(),
|
|
27
|
-
package_data={'': ['*.json', '*.ui', '*.svg', '*.qss', '*.xml', '*.png', '*.dot', '*.ini', '*.csv'],
|
|
28
|
-
'resources': ['*.json', '*.db', '*.xlsx', 'icons/*.*', 'private/*.*', 'templates/*.ini']},
|
|
29
|
-
)
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: xiaojing
|
|
3
|
-
Version: 0.0.1
|
|
4
|
-
Summary: 皛鲸的工具箱
|
|
5
|
-
Home-page: https://xiaojing.cc/python
|
|
6
|
-
Author: liuxiaojing
|
|
7
|
-
Author-email: lqxnjk@qq.com
|
|
8
|
-
License: MIT
|
|
9
|
-
Classifier: Topic :: Software Development :: Libraries
|
|
10
|
-
Classifier: Programming Language :: Python
|
|
11
|
-
Requires-Python: >=3.7
|
|
12
|
-
Description-Content-Type: text/markdown
|
|
13
|
-
|
|
14
|
-
python .\setup.py sdist
|
|
15
|
-
|
|
16
|
-
pip install .\dist\xiaojingcc-2.0.0.tar.gz
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
README.md
|
|
2
|
-
setup.py
|
|
3
|
-
ii_common/__init__.py
|
|
4
|
-
ii_common/ii_base_func/__init__.py
|
|
5
|
-
ii_common/ii_base_func/ii_ant.py
|
|
6
|
-
ii_common/ii_base_func/ii_class.py
|
|
7
|
-
ii_common/ii_base_func/ii_file.py
|
|
8
|
-
ii_common/ii_base_func/ii_model.py
|
|
9
|
-
ii_common/ii_base_func/ii_path.py
|
|
10
|
-
ii_common/ii_base_func/ii_str.py
|
|
11
|
-
ii_common/ii_base_func/ii_time.py
|
|
12
|
-
ii_common/ii_call_func/__init__.py
|
|
13
|
-
ii_common/ii_call_func/ii_ant.py
|
|
14
|
-
ii_common/ii_call_func/ii_judge.py
|
|
15
|
-
ii_common/ii_call_func/ii_sqlite.py
|
|
16
|
-
ii_common/ii_call_func/ii_tools.py
|
|
17
|
-
xiaojing.egg-info/PKG-INFO
|
|
18
|
-
xiaojing.egg-info/SOURCES.txt
|
|
19
|
-
xiaojing.egg-info/dependency_links.txt
|
|
20
|
-
xiaojing.egg-info/requires.txt
|
|
21
|
-
xiaojing.egg-info/top_level.txt
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
ii_common
|