edi-core 0.7.0__tar.gz → 0.8.0rc1__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.

Potentially problematic release.


This version of edi-core might be problematic. Click here for more details.

Files changed (31) hide show
  1. edi_core-0.8.0rc1/PKG-INFO +27 -0
  2. edi_core-0.8.0rc1/pyproject.toml +32 -0
  3. edi_core-0.8.0rc1/src/edi_core/cloud/README.md +1 -0
  4. edi_core-0.8.0rc1/src/edi_core/cloud/oss.py +64 -0
  5. edi_core-0.8.0rc1/src/edi_core/file/audio.py +36 -0
  6. {edi_core-0.7.0 → edi_core-0.8.0rc1}/src/edi_core/file/file.py +8 -0
  7. edi_core-0.8.0rc1/src/edi_core/scm/git.py +6 -0
  8. edi_core-0.7.0/PKG-INFO +0 -28
  9. edi_core-0.7.0/pyproject.toml +0 -27
  10. edi_core-0.7.0/src/edi_core/ai/writesonic/__init__.py +0 -8
  11. edi_core-0.7.0/src/edi_core/ai/writesonic/chatsonic.py +0 -110
  12. edi_core-0.7.0/src/edi_core/algo/silder_puzzle.py +0 -25
  13. edi_core-0.7.0/src/edi_core/cloud/aliyun.py +0 -0
  14. edi_core-0.7.0/src/edi_core/parser/__init__.py +0 -0
  15. edi_core-0.7.0/src/edi_core/parser/toml_parser.py +0 -15
  16. edi_core-0.7.0/src/edi_core/util/__init__.py +0 -0
  17. edi_core-0.7.0/src/edi_core/util/pyproject.py +0 -13
  18. {edi_core-0.7.0 → edi_core-0.8.0rc1}/README.md +0 -0
  19. {edi_core-0.7.0 → edi_core-0.8.0rc1}/src/edi_core/__init__.py +0 -0
  20. {edi_core-0.7.0/src/edi_core/ai → edi_core-0.8.0rc1/src/edi_core/auto}/__init__.py +0 -0
  21. {edi_core-0.7.0 → edi_core-0.8.0rc1}/src/edi_core/auto/control.py +0 -0
  22. {edi_core-0.7.0/src/edi_core/algo → edi_core-0.8.0rc1/src/edi_core/cloud}/__init__.py +0 -0
  23. {edi_core-0.7.0/src/edi_core/auto → edi_core-0.8.0rc1/src/edi_core/db}/__init__.py +0 -0
  24. {edi_core-0.7.0 → edi_core-0.8.0rc1}/src/edi_core/db/tinydb.py +0 -0
  25. {edi_core-0.7.0/src/edi_core/cloud → edi_core-0.8.0rc1/src/edi_core/file}/__init__.py +0 -0
  26. {edi_core-0.7.0 → edi_core-0.8.0rc1}/src/edi_core/file/filetype.py +0 -0
  27. {edi_core-0.7.0 → edi_core-0.8.0rc1}/src/edi_core/file/hash.py +0 -0
  28. {edi_core-0.7.0/src/edi_core/db → edi_core-0.8.0rc1/src/edi_core/scm}/__init__.py +0 -0
  29. {edi_core-0.7.0/src/edi_core/file → edi_core-0.8.0rc1/src/edi_core/util}/__init__.py +0 -0
  30. {edi_core-0.7.0 → edi_core-0.8.0rc1}/src/edi_core/util/datetime.py +0 -0
  31. {edi_core-0.7.0 → edi_core-0.8.0rc1}/src/edi_core/util/environment.py +0 -0
@@ -0,0 +1,27 @@
1
+ Metadata-Version: 2.4
2
+ Name: edi-core
3
+ Version: 0.8.0rc1
4
+ Summary:
5
+ License: MIT
6
+ Author: LtttAZ
7
+ Author-email: louis_zhang_1303@126.com
8
+ Requires-Python: ==3.13.2
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Requires-Dist: alibabacloud-oss-v2 (>=1.2.0,<2.0.0)
12
+ Requires-Dist: filetype (>=1.2.0,<2.0.0)
13
+ Requires-Dist: gitpython (>=3.1.45,<4.0.0)
14
+ Requires-Dist: loguru (>=0.7.3,<0.8.0)
15
+ Requires-Dist: matplotlib (>=3.10.7,<4.0.0)
16
+ Requires-Dist: packaging (>=25.0,<26.0)
17
+ Requires-Dist: pendulum (>=3.1.0,<4.0.0)
18
+ Requires-Dist: pyautogui (>=0.9.54,<0.10.0)
19
+ Requires-Dist: pydantic (>=2.12.3,<3.0.0)
20
+ Requires-Dist: python-dotenv (>=1.2.1,<2.0.0)
21
+ Requires-Dist: requests (>=2.32.5,<3.0.0)
22
+ Requires-Dist: tinydb (>=4.8.2,<5.0.0)
23
+ Description-Content-Type: text/markdown
24
+
25
+ # EDI
26
+
27
+ [PYPI](https://pypi.org/project/edi-core/)
@@ -0,0 +1,32 @@
1
+ [tool.poetry]
2
+ name = "edi-core"
3
+ version = "0.8.0-rc1"
4
+ description = ""
5
+ authors = ["LtttAZ <louis_zhang_1303@126.com>"]
6
+ license = "MIT"
7
+ readme = "README.md"
8
+ package-mode = true
9
+
10
+ [tool.poetry.dependencies]
11
+ python = "3.13.2"
12
+ tinydb = "^4.8.2"
13
+ requests = "^2.32.5"
14
+ filetype = "^1.2.0"
15
+ pendulum = "^3.1.0"
16
+ matplotlib = "^3.10.7"
17
+ pyautogui = "^0.9.54"
18
+ loguru = "^0.7.3"
19
+ alibabacloud-oss-v2 = "^1.2.0"
20
+ pydantic = "^2.12.3"
21
+ gitpython = "^3.1.45"
22
+ packaging = "^25.0"
23
+ python-dotenv = "^1.2.1"
24
+
25
+ [tool.poetry.group.dev.dependencies]
26
+ pytest = "^8.4.2"
27
+ pytest-dotenv = "^0.5.2"
28
+ requests-mock = "^1.12.1"
29
+
30
+ [build-system]
31
+ requires = ["poetry-core"]
32
+ build-backend = "poetry.core.masonry.api"
@@ -0,0 +1 @@
1
+ https://help.aliyun.com/zh/oss/developer-reference/get-started-with-oss-sdk-for-python-v2?spm=a2c4g.11186623.help-menu-31815.d_5_2_2_0_0.31152f8dIqy5FD
@@ -0,0 +1,64 @@
1
+ from abc import ABC
2
+
3
+ import alibabacloud_oss_v2 as oss
4
+ from alibabacloud_oss_v2 import GetObjectMetaRequest, GetObjectMetaResult, GetObjectRequest
5
+ from loguru import logger as log
6
+
7
+
8
+ class OssClient(ABC):
9
+ def get_object_metadata(self, key: str):
10
+ pass
11
+
12
+ def get_object(self, key: str, target_path: str):
13
+ pass
14
+
15
+ def put_object(self, source_path: str, key: str):
16
+ pass
17
+
18
+ def delete_object(self, key: str):
19
+ pass
20
+
21
+
22
+ class AliCloudOssClient(OssClient):
23
+ _config: oss.Config
24
+ _client: oss.Client
25
+ _bucket: str
26
+
27
+ def __init__(self, region: str, access_key: str, secret_key: str, endpoint: str, bucket: str):
28
+ config = oss.config.load_default()
29
+ config.region = region
30
+ config.credentials_provider = oss.credentials.StaticCredentialsProvider(access_key_id=access_key,
31
+ access_key_secret=secret_key)
32
+ config.endpoint = endpoint
33
+ self._config = config
34
+ self.print_config()
35
+ self._client = oss.Client(self._config)
36
+ self._bucket = bucket
37
+
38
+ def get_config(self) -> oss.Config:
39
+ return self._config
40
+
41
+ def get_object_metadata(self, key: str) -> GetObjectMetaResult:
42
+ request = GetObjectMetaRequest(bucket=self._bucket, key=key)
43
+ return self._client.get_object_meta(request)
44
+
45
+ def get_object(self, key: str, target_path: str):
46
+ log.debug(f"downloading {key} to {target_path}")
47
+ request = GetObjectRequest(bucket=self._bucket, key=key)
48
+ result = self._client.get_object(request)
49
+ with result.body as body_stream:
50
+ data = body_stream.read()
51
+ with open(target_path, 'wb') as f:
52
+ f.write(data)
53
+ log.debug(f"finished downloading {key} to {target_path}")
54
+
55
+ def put_object(self, source_path: str, key: str):
56
+ pass
57
+
58
+ def delete_object(self, key: str):
59
+ pass
60
+
61
+ def print_config(self):
62
+ config_attrs = vars(self._config)
63
+ config_str = "\n".join(f"{key}={value}" for key, value in config_attrs.items())
64
+ log.debug(f"OSS Config: {config_str}")
@@ -0,0 +1,36 @@
1
+ import os
2
+ import subprocess
3
+
4
+ from edi_core.file.file import isdir, get_file_name_without_extension
5
+
6
+
7
+ def extract_audio(file_path: str, output_path: str):
8
+ result = subprocess.run(
9
+ ['ffmpeg', '-i', file_path, '-q:a', '0', '-map', 'a', output_path],
10
+ stdout=subprocess.PIPE,
11
+ stderr=subprocess.PIPE
12
+ )
13
+ if result.returncode != 0:
14
+ raise RuntimeError(f"Failed to extract audio: {result.stderr.decode()}")
15
+
16
+
17
+ def split_audio(source_file: str, dest_dir: str, seconds: int):
18
+ if not os.path.isfile(source_file):
19
+ raise ValueError(f"Source file does not exist: {source_file}")
20
+ if not isdir(dest_dir):
21
+ os.makedirs(dest_dir, exist_ok=True)
22
+
23
+ base_name = get_file_name_without_extension(source_file)
24
+ segment_pattern = os.path.join(dest_dir, f"{base_name}_%03d.mp3")
25
+
26
+ result = subprocess.run(
27
+ ['ffmpeg', '-i', source_file, '-f', 'segment', '-segment_time', str(seconds), '-c', 'copy', segment_pattern],
28
+ stdout=subprocess.PIPE,
29
+ stderr=subprocess.PIPE
30
+ )
31
+
32
+ if result.returncode != 0:
33
+ raise RuntimeError(f"Failed to split audio: {result.stderr.decode()}")
34
+
35
+ return sorted([os.path.join(dest_dir, f) for f in os.listdir(dest_dir) if f.startswith(base_name)],
36
+ key=lambda x: x.lower())
@@ -17,3 +17,11 @@ def move(src, dest):
17
17
  def delete_file(path: str):
18
18
  if isfile(path):
19
19
  os.remove(path)
20
+
21
+ def get_file_name_without_extension(path: str) -> str:
22
+ base_name = os.path.basename(path)
23
+ name_without_extension, _ = os.path.splitext(base_name)
24
+ return name_without_extension
25
+
26
+ def get_file_name_with_extension(path: str) -> str:
27
+ return os.path.basename(path)
@@ -0,0 +1,6 @@
1
+ import git
2
+
3
+
4
+ def clone_and_checkout(path, url, branch):
5
+ repo = git.Repo.clone_from(url=url, to_path=path)
6
+ repo.create_head(branch).checkout()
edi_core-0.7.0/PKG-INFO DELETED
@@ -1,28 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: edi-core
3
- Version: 0.7.0
4
- Summary:
5
- License: MIT
6
- Author: LtttAZ
7
- Author-email: louis_zhang_1303@126.com
8
- Requires-Python: >=3.11,<4.0
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.11
12
- Classifier: Programming Language :: Python :: 3.12
13
- Requires-Dist: dataclass-wizard (>=0.23.0,<0.24.0)
14
- Requires-Dist: filetype (>=1.2.0,<2.0.0)
15
- Requires-Dist: matplotlib (>=3.8.4,<4.0.0)
16
- Requires-Dist: pendulum (>=3.0.0,<4.0.0)
17
- Requires-Dist: pyautogui (>=0.9.54,<0.10.0)
18
- Requires-Dist: pytest (>=8.1.1,<9.0.0)
19
- Requires-Dist: requests (>=2.32.3,<3.0.0)
20
- Requires-Dist: requests-mock (>=1.12.1,<2.0.0)
21
- Requires-Dist: tinydb (>=4.8.0,<5.0.0)
22
- Requires-Dist: toml (>=0.10.2,<0.11.0)
23
- Requires-Dist: tomlkit (>=0.13.0,<0.14.0)
24
- Description-Content-Type: text/markdown
25
-
26
- # EDI
27
-
28
- [PYPI](https://pypi.org/project/edi-core/)
@@ -1,27 +0,0 @@
1
- [tool.poetry]
2
- name = "edi-core"
3
- version = "0.7.0"
4
- description = ""
5
- authors = ["LtttAZ <louis_zhang_1303@126.com>"]
6
- license = "MIT"
7
- readme = "README.md"
8
- package-mode = true
9
-
10
- [tool.poetry.dependencies]
11
- python = "^3.11"
12
- tinydb = "^4.8.0"
13
- requests = "^2.32.3"
14
- dataclass-wizard = "^0.23.0"
15
- requests-mock = "^1.12.1"
16
- pytest = "^8.1.1"
17
- toml = "^0.10.2"
18
- tomlkit = "^0.13.0"
19
- filetype = "^1.2.0"
20
- pendulum = "^3.0.0"
21
- matplotlib = "^3.8.4"
22
- pyautogui = "^0.9.54"
23
-
24
-
25
- [build-system]
26
- requires = ["poetry-core"]
27
- build-backend = "poetry.core.masonry.api"
@@ -1,8 +0,0 @@
1
- WRITESONIC_BASE_URL = 'https://api.writesonic.com'
2
- CHATSONIC_URL_PATH = '/v2/business/content/chatsonic'
3
- WRITESONIC_ENGINE_PREMIUM = 'premium'
4
- WRITESONIC_ENGINE_SUPERIOR = 'superior'
5
- WRITESONIC_ENGINES = (WRITESONIC_ENGINE_PREMIUM, WRITESONIC_ENGINE_SUPERIOR)
6
- WRITESONIC_LANGUAGE_ENGLISH = 'en'
7
- WRITESONIC_LANGUAGE_CHINESE = 'zh'
8
- WRITESONIC_LANGUAGES = (WRITESONIC_LANGUAGE_ENGLISH, WRITESONIC_LANGUAGE_CHINESE)
@@ -1,110 +0,0 @@
1
- import dataclasses
2
- import os
3
- from dataclasses import dataclass, field
4
- from typing import List
5
-
6
- import requests
7
- from edi_core.ai.writesonic import *
8
-
9
-
10
- @dataclass(kw_only=True)
11
- class ChatSonicConfig:
12
- api_key: str = os.environ.get("SONIC_KEY")
13
- base_url: str = WRITESONIC_BASE_URL
14
- path: str = CHATSONIC_URL_PATH
15
- engine: str = WRITESONIC_ENGINE_PREMIUM
16
- language: str = WRITESONIC_LANGUAGE_ENGLISH
17
- enable_memory: bool = False
18
- enable_google_results: bool = False
19
-
20
- def __post_init__(self):
21
- if not self.api_key:
22
- raise ValueError("token is required")
23
- if self.engine not in WRITESONIC_ENGINES:
24
- raise ValueError("engine is invalid")
25
- if self.language not in WRITESONIC_LANGUAGES:
26
- raise ValueError("language is invalid")
27
-
28
- def get_request_url(self):
29
- return f'{self.base_url}{self.path}'
30
-
31
-
32
- @dataclass
33
- class ChatSonicRequest:
34
- @dataclass
35
- class Message:
36
- is_sent: bool
37
- message: str
38
-
39
- input_text: str
40
- history_data: List[Message] = field(default_factory=list)
41
- enable_memory: bool = False
42
- enable_google_results: bool = False
43
-
44
- def push_response(self, message: str):
45
- message_sent = self.Message(is_sent=True, message=self.input_text)
46
- message_received = self.Message(is_sent=False, message=message)
47
- self.history_data.append(message_sent)
48
- self.history_data.append(message_received)
49
- self.input_text = ''
50
-
51
- def set_config(self, config: ChatSonicConfig):
52
- self.enable_memory = config.enable_memory
53
- self.enable_google_results = config.enable_google_results
54
-
55
- def to_dict(self):
56
- return dataclasses.asdict(self)
57
-
58
-
59
- @dataclass
60
- class ChatSonicResponse:
61
- message: str
62
- image_urls: List[str] = field(default_factory=list)
63
-
64
- @staticmethod
65
- def from_json(json_data):
66
- return ChatSonicResponse(
67
- message=json_data['message'],
68
- image_urls=json_data['image_urls']
69
- )
70
-
71
-
72
- class ChatSonic:
73
- _config: ChatSonicConfig
74
- _session = requests.Session()
75
-
76
- def __init__(self, config: ChatSonicConfig):
77
- self._config = config
78
-
79
- def call(self, payload: ChatSonicRequest) -> (ChatSonicResponse, ChatSonicRequest):
80
- url = self._config.get_request_url()
81
- payload.set_config(self._config)
82
-
83
- raw_response = self._session.post(
84
- url=url,
85
- headers=self.get_request_headers(),
86
- params=self.get_request_params(),
87
- json=payload.to_dict(),
88
- timeout=60
89
- )
90
-
91
- raw_response.raise_for_status()
92
-
93
- response = ChatSonicResponse.from_json(raw_response.json())
94
- payload.push_response(response.message)
95
-
96
- return response, payload
97
-
98
- def chat(self, message: str, history_data: List[ChatSonicRequest.Message] = []) -> (
99
- ChatSonicResponse, ChatSonicRequest):
100
- payload = ChatSonicRequest(input_text=message, history_data=history_data)
101
- return self.call(payload)
102
-
103
- def get_request_headers(self):
104
- return {'X-API-KEY': self._config.api_key}
105
-
106
- def get_request_params(self):
107
- return {
108
- 'engine': self._config.engine,
109
- 'language': self._config.language
110
- }
@@ -1,25 +0,0 @@
1
- directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
2
-
3
-
4
- class SliderPuzzle:
5
-
6
- def solve(self):
7
- return
8
-
9
-
10
- class SearchNode:
11
- board: list
12
- free: tuple
13
-
14
- step: 0
15
-
16
- def get_distance(self):
17
- distance = 0
18
- for i in range(len(self.board)):
19
- for j in range(len(self.board[i])):
20
- if self.board[i][j] != i * len(self.board[i]) + j + 1:
21
- distance += abs(i - (self.board[i][j] - 1) // len(self.board[i])) + abs(
22
- j - (self.board[i][j] - 1) % len(self.board[i]))
23
- return distance + self.step
24
-
25
-
File without changes
File without changes
@@ -1,15 +0,0 @@
1
- import toml
2
-
3
-
4
- def parse_toml_file(toml_file_path: str) -> dict:
5
- with open(toml_file_path, 'r') as file:
6
- return toml.load(file)
7
-
8
-
9
- def parse_toml_str(toml_str: str) -> dict:
10
- return toml.loads(toml_str)
11
-
12
-
13
- def save_to_toml_file(path: str, data: dict):
14
- with open(path, 'w') as file:
15
- toml.dump(data, file)
File without changes
@@ -1,13 +0,0 @@
1
- from typing import Dict, Any
2
-
3
- from edi_core.parser.toml_parser import parse_toml_file
4
-
5
-
6
- class PyProject:
7
- _root: str
8
- _config: Dict[str, Any]
9
- _config_file_name = "pyproject.toml"
10
-
11
- def __init__(self, path: str):
12
- self.path = path
13
- self._config = parse_toml_file(f'{path}/{self._config_file_name}')
File without changes