diff --git a/.gitignore b/.gitignore
index 58b56a7..b93bbf7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,23 @@
-__pycache__
-.idea
-database
-logs
+
+# Poetry
+poetry.lock
+.venv/
+dist/
+*.egg-info/
+
+# Python
+__pycache__/
+*.py[cod]
+*$py.class
+.pytest_cache/
+.coverage
+htmlcov/
+
+# IDE
+.vscode/
+.idea/
+
+# Project specific
+logs/
+database/
.pylint_rate
diff --git a/README.md b/README.md
index 80e0482..4d871a5 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@
-
+
diff --git a/config.py b/config.py
index 6eb6941..511d797 100644
--- a/config.py
+++ b/config.py
@@ -96,9 +96,7 @@
# 数据库配置
DATABASE_CONFIG = {
- "path": os.path.join(
- ROOT_DIR, "database", "fund_analysis.v4.db"
- ) # SQLite数据库文件路径
+ "path": os.path.join(ROOT_DIR, "database", "fund_analysis.v4.db") # SQLite数据库文件路径
}
# API配置
diff --git a/data_source/data_source_factory.py b/data_source/data_source_factory.py
index 3dbde39..3a95897 100644
--- a/data_source/data_source_factory.py
+++ b/data_source/data_source_factory.py
@@ -14,9 +14,7 @@ class DataSourceFactory:
@classmethod
def register(cls, source_class: Type[IDataSource]) -> None:
"""注册新的数据源类型"""
- logger.info(
- "注册数据源: %s %s", source_class.get_name(), source_class.get_version()
- )
+ logger.info("注册数据源: %s %s", source_class.get_name(), source_class.get_version())
cls._sources[source_class.get_name()] = source_class
@classmethod
diff --git a/models/fund.py b/models/fund.py
index 8ca612e..e659d44 100644
--- a/models/fund.py
+++ b/models/fund.py
@@ -21,9 +21,7 @@ class Fund(BaseModel):
type = CharField(max_length=20) # 基金类型
issue_date = DateField() # 发行日期
establishment_date = DateField() # 成立日期
- establishment_size = DecimalField(
- max_digits=20, decimal_places=4
- ) # 成立规模(单位:亿份)
+ establishment_size = DecimalField(max_digits=20, decimal_places=4) # 成立规模(单位:亿份)
company = CharField(max_length=100) # 基金管理公司
custodian = CharField(max_length=100) # 基金托管人
fund_manager = CharField(max_length=100) # 基金经理人
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..c33623d
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,43 @@
+[tool.poetry]
+name = "fund-analysis"
+version = "0.1.0"
+description = "基金分析系统"
+authors = ["Fan Yefei "]
+
+[tool.poetry.dependencies]
+python = "~3.10"
+# Web框架
+dash = {version = "^2.18.1", extras = ["compress"]}
+"dash-bootstrap-components" = "^1.5.0"
+plotly = "^5.18.0"
+
+"feffery-antd-components" = "^0.3.8"
+"feffery-dash-utils" = "^0.1.4"
+"feffery-markdown-components" = "^0.3.0rc3"
+"feffery-utils-components" = "^0.2.0rc20"
+
+# 服务端
+Flask = "^3.0.3"
+"flask-restx" = "^1.3.0"
+
+# 网络
+requests = "^2.32.3"
+
+# 数据处理
+pandas = "^2.2.3"
+numpy = "^1.26.2"
+"beautifulsoup4" = "^4.12.3"
+"flask-apscheduler" = "^1.13.1"
+
+# 数据库
+peewee = "^3.17.0"
+
+[tool.poetry.group.dev.dependencies]
+# 开发工具
+black = "^23.11.0" # 代码格式化检查
+pylint = "^3.1.0" # 代码质量检查
+colorama = "^0.4.6" # 测试用
+
+[build-system]
+requires = ["poetry-core>=1.0.0"]
+build-backend = "poetry.core.masonry.api"
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index 515d72d..0000000
--- a/requirements.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-dash[compress]==2.18.1
-feffery_antd_components>=0.3.8
-feffery_dash_utils>=0.1.4
-feffery_markdown_components>=0.3.0rc3
-feffery_utils_components>=0.2.0rc20
-Flask==3.0.3
-pandas>=2.0.0
-numpy>=1.24.0
-plotly>=5.18.0
-dash-bootstrap-components>=1.5.0
-requests~=2.32.3
-flask-restx>=1.3.0
-peewee>=3.17.0
-Flask-APScheduler==1.13.1
-beautifulsoup4==4.12.3
-colorama==0.4.6 # 测试用
-black>=24.2.0 # 代码格式化检查
-pylint>=3.1.0 # 代码质量检查
diff --git a/scheduler/tasks/fund_detail.py b/scheduler/tasks/fund_detail.py
index 0107e74..b8c973c 100644
--- a/scheduler/tasks/fund_detail.py
+++ b/scheduler/tasks/fund_detail.py
@@ -105,7 +105,5 @@ def execute(self, **kwargs) -> Dict[str, Any]:
return fund_data
except Exception as e:
- logger.error(
- "更新基金信息失败: %s", str(e), exc_info=True
- ) # 添加完整的错误堆栈
+ logger.error("更新基金信息失败: %s", str(e), exc_info=True) # 添加完整的错误堆栈
raise
diff --git a/scheduler/tasks/fund_info.py b/scheduler/tasks/fund_info.py
index 3412dcc..aef10e5 100644
--- a/scheduler/tasks/fund_info.py
+++ b/scheduler/tasks/fund_info.py
@@ -112,7 +112,5 @@ def execute(self, **kwargs) -> Dict[str, Any]:
}
except Exception as e:
- logger.error(
- f"更新基金信息失败: {str(e)}", exc_info=True
- ) # 添加完整的错误堆栈
+ logger.error(f"更新基金信息失败: {str(e)}", exc_info=True) # 添加完整的错误堆栈
raise
diff --git a/start.sh b/start.sh
index ef626b0..f34150d 100755
--- a/start.sh
+++ b/start.sh
@@ -57,39 +57,53 @@ activate_conda_env() {
if ! conda activate fund; then
echo -e "${RED}激活conda环境失败${NC}"
read -p "按回车键继续..."
- return 1
+ exit 1
fi
echo -e "${GREEN}conda环境激活成功${NC}"
return 0
}
-
-# 安装依赖
-install_dependencies() {
- echo -e "${YELLOW}检查并安装依赖${NC}"
- if [ -f "requirements.txt" ]; then
- if ! pip install -r requirements.txt; then
- echo -e "${RED}安装依赖失败${NC}"
- read -p "按回车键继续..."
- return 1
- fi
-
- # 安装代码检查工具
- echo -e "${YELLOW}安装代码检查工具...${NC}"
- if ! pip install black pylint; then
- echo -e "${RED}安装代码检查工具失败${NC}"
- read -p "按回车键继续..."
- return 1
+# 检查poetry是否已安装
+check_poetry() {
+ if ! command -v poetry &> /dev/null; then
+ echo -e "${RED}错误: 未找到poetry,正在安装...${NC}"
+ # 获取当前conda环境信息
+ conda_env=$(conda info --envs | grep "*" | awk '{print $1}')
+ echo -e "${YELLOW}当前conda环境: ${conda_env}${NC}"
+ if ! conda install -y poetry; then
+ echo -e "${RED}安装poetry失败${NC}"
+ exit 1
fi
+ fi
+ return 0
+}
- echo -e "${GREEN}依赖安装成功${NC}"
- else
- echo -e "${RED}错误: 未找到requirements.txt文件${NC}"
- read -p "按回车键继续..."
+# 创建并配置环境
+setup_env() {
+ echo -e "${YELLOW}配置开发环境...${NC}"
+ # 获取poetry版本
+ poetry_version=$(poetry --version | cut -d' ' -f3)
+ echo -e "${GREEN}当前poetry版本: $poetry_version${NC}"
+
+ # 配置poetry不使用虚拟环境
+ echo -e "${YELLOW}配置poetry...${NC}"
+ poetry config virtualenvs.create false
+
+ # 安装项目依赖
+ echo -e "${YELLOW}安装项目依赖...${NC}"
+ if ! poetry install; then
+ echo -e "${RED}安装依赖失败${NC}"
+ echo -e "按回车键返回主菜单..."
+ read
return 1
fi
+
+ echo -e "${GREEN}环境配置成功${NC}"
+ read -p "按回车键继续..."
return 0
}
+
+
# 初始化数据库
init_database() {
echo -e "${YELLOW}迁移数据库...${NC}"
@@ -271,7 +285,7 @@ run_code_check() {
echo -e "${RED}无法解析评分信息${NC}"
fi
- # 保存当前评分
+ # 保存当前��分
echo "$curr_rate" > .pylint_rate
has_error=1
@@ -338,7 +352,8 @@ do_full_install() {
check_conda || return 1
setup_conda_env || return 1
activate_conda_env || return 1
- install_dependencies || return 1
+ check_poetry || return 1
+ setup_env || return 1
init_database || return 1
run_code_check || return 1
start_app || return 1
@@ -354,34 +369,35 @@ while true; do
case $choice in
1)
echo -e "${YELLOW}开始初始化环境...${NC}"
- ensure_directories
- check_conda
- setup_conda_env
- activate_conda_env
- install_dependencies
+ ensure_directories || continue
+ check_conda || continue
+ setup_conda_env || continue
+ activate_conda_env || continue
+ check_poetry || continue
+ setup_env || continue
if [ $? -eq 0 ]; then
echo -e "${GREEN}环境初始化完成!${NC}"
fi
;;
2)
echo -e "${YELLOW}开始迁移数据库...${NC}"
- init_database
+ init_database || continue
;;
3)
echo -e "${YELLOW}开始运行代码检查...${NC}"
- run_code_check
+ run_code_check || continue
;;
4)
echo -e "${YELLOW}开始启动应用...${NC}"
- ensure_directories
- activate_conda_env
- start_app
+ ensure_directories || continue
+ activate_conda_env || continue
+ start_app || continue
;;
5)
- do_full_install
+ do_full_install || continue
;;
9)
- start_test
+ start_test || continue
;;
0)
echo -e "${GREEN}再见!${NC}"
@@ -389,13 +405,13 @@ while true; do
;;
*)
echo -e "${RED}无效的选择,请重试${NC}"
- read -p "按回车键继续..."
+ echo -e "按回车键返回主菜单..."
;;
esac
# 如果不是启动应用,则等待用户按回车继续
if [ "$choice" != "4" ] && [ "$choice" != "5" ]; then
echo
- read -p "按回车键继续..."
+ echo -e "按回车键返回主菜单..."
fi
-done
\ No newline at end of file
+done
diff --git a/tests/test_data_source.py b/tests/test_data_source.py
index f87653f..8b43a26 100644
--- a/tests/test_data_source.py
+++ b/tests/test_data_source.py
@@ -71,9 +71,7 @@ def assertIsValidPercentage(self, value, field_name: str):
self.assertIsInstance(float_value, float, "\n".join(error_msg))
except (ValueError, TypeError) as e:
- self.fail(
- f"\n百分比转换失败: {field_name}\n" f"值: {value!r}\n" f"错误: {str(e)}"
- )
+ self.fail(f"\n百分比转换失败: {field_name}\n" f"值: {value!r}\n" f"错误: {str(e)}")
def test_get_fund_detail(self):
"""测试获取基金详情功能"""
diff --git a/tests/test_tasks.py b/tests/test_tasks.py
index b58ca6d..fdb15d5 100644
--- a/tests/test_tasks.py
+++ b/tests/test_tasks.py
@@ -88,15 +88,9 @@ def test_task_execution(self):
self.assertIsNotNone(results["company"], "基金公司不能为空")
# 验证数值字段
- self.assertIsInstance(
- results["establishment_size"], (int, float), "成立规模应为数值类型"
- )
- self.assertIsInstance(
- results["management_fee"], (int, float), "管理费率应为数值类型"
- )
- self.assertIsInstance(
- results["custodian_fee"], (int, float), "托管费率应为数值类型"
- )
+ self.assertIsInstance(results["establishment_size"], (int, float), "成立规模应为数值类型")
+ self.assertIsInstance(results["management_fee"], (int, float), "管理费率应为数值类型")
+ self.assertIsInstance(results["custodian_fee"], (int, float), "托管费率应为数值类型")
self.assertIsInstance(
results["sales_service_fee"], (int, float), "销售服务费率应为数值类型"
)