xiaojing 0.0.1__tar.gz → 0.0.2__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.2/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.
@@ -0,0 +1,82 @@
1
+ Metadata-Version: 2.5
2
+ Name: xiaojing
3
+ Version: 0.0.2
4
+ Summary: Convert units of length, mass and temperature.
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
@@ -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.2"
8
+ description = "Convert units of length, mass and temperature."
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:30
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:30
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,3 +0,0 @@
1
- python .\setup.py sdist
2
-
3
- pip install .\dist\xiaojingcc-2.0.0.tar.gz
@@ -1,2 +0,0 @@
1
- from .ii_base_func import *
2
- from .ii_call_func import *
@@ -1,5 +0,0 @@
1
- from .ii_file import *
2
- from .ii_class import *
3
- from .ii_model import *
4
- from .ii_path import *
5
- from .ii_time import *
@@ -1,6 +0,0 @@
1
- import os, sys, re
2
- import sqlite3, time, datetime, sqlite3
3
- import json
4
- import abc
5
- import importlib
6
- from types import FunctionType
@@ -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,6 +0,0 @@
1
- def str_Q2B(m_str: str):
2
- """
3
- 把字符串转换为全角字符
4
- """
5
- return "".join(
6
- chr(ord(i) - 65248) if 65374 >= ord(i) >= 65281 else (chr(32) if ord(i) == 12288 else i) for i in m_str)
@@ -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,3 +0,0 @@
1
- from .ii_judge import *
2
- from .ii_tools import *
3
- from .ii_sqlite import *
@@ -1,6 +0,0 @@
1
- from ..ii_base_func.ii_ant import *
2
- from ..ii_base_func import *
3
- import numpy
4
- import threading
5
- import time
6
- import sys
@@ -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
@@ -1,4 +0,0 @@
1
- [egg_info]
2
- tag_build =
3
- tag_date = 0
4
-
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,7 +0,0 @@
1
- pandas==1.3.5
2
- xlrd==1.2.0
3
- pymysql
4
- requests
5
- openpyxl
6
- sqlalchemy
7
- pymongo
@@ -1 +0,0 @@
1
- ii_common