{"id":34034075,"url":"https://github.com/pskelecton/straw","last_synced_at":"2026-04-09T00:32:23.770Z","repository":{"id":57455348,"uuid":"355822049","full_name":"pskelecton/straw","owner":"pskelecton","description":"简单的函数调用来处理数据库","archived":false,"fork":false,"pushed_at":"2022-05-26T13:20:14.000Z","size":146,"stargazers_count":2,"open_issues_count":4,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-09-19T11:00:08.960Z","etag":null,"topics":["bean","orm","sql"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pskelecton.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-04-08T08:24:57.000Z","updated_at":"2022-04-24T12:48:01.000Z","dependencies_parsed_at":"2022-09-10T02:24:05.514Z","dependency_job_id":null,"html_url":"https://github.com/pskelecton/straw","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/pskelecton/straw","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pskelecton%2Fstraw","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pskelecton%2Fstraw/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pskelecton%2Fstraw/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pskelecton%2Fstraw/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pskelecton","download_url":"https://codeload.github.com/pskelecton/straw/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pskelecton%2Fstraw/sbom","scorecard":{"id":748239,"data":{"date":"2025-08-11","repo":{"name":"github.com/pskelecton/straw","commit":"66b212512ece076bbd7f5fe3705adf81d00e1790"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.5,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":6,"reason":"4 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-v9hf-5j83-6xpp","Warn: Project is vulnerable to: GHSA-2m57-hf25-phgg","Warn: Project is vulnerable to: PYSEC-2021-333 / GHSA-p5w8-wqhj-9hhf","Warn: Project is vulnerable to: PYSEC-2023-87 / GHSA-rrm6-wvj7-cwh2"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-22T19:30:50.999Z","repository_id":57455348,"created_at":"2025-08-22T19:30:50.999Z","updated_at":"2025-08-22T19:30:50.999Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31579951,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-08T14:31:17.711Z","status":"ssl_error","status_checked_at":"2026-04-08T14:31:17.202Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bean","orm","sql"],"created_at":"2025-12-13T19:31:34.150Z","updated_at":"2026-04-09T00:32:23.762Z","avatar_url":"https://github.com/pskelecton.png","language":"Python","readme":"# Straw 数据管 :zap:\n[![beta:0.9.x](https://img.shields.io/badge/Beta-0.9.8-yellow)](https://pypi.org/project/pstraw/) [![license:MIT](https://img.shields.io/badge/License-MIT-green)](https://github.com/pskelecton/straw/blob/master/pstraw/LICENSE) [![python:\u003e=3.7](https://img.shields.io/badge/Python-%3E%3D%203.7-blue)](https://www.python.org/downloads/) [![SQL@Support:postgres|mysql](https://img.shields.io/badge/SQL%40Support-postgres%20%7C%20mysql-lightgrey)](https://github.com/pskelecton/straw) \n\n**简单的函数调用来处理数据库**\n\n\u003e Straw可以方便的在多个不同的数据库之间传输数据，只需要调用一个方法把数据取出来，再调用一个方法把数据插到另一个数据库中\n\u003e 他可以像\u003ci\u003e\u003cb\u003eMyBatis\u003c/b\u003e\u003c/i\u003e一样，分离sql层和逻辑层，但又不同于\u003ci\u003e\u003cb\u003eMyBatis\u003c/b\u003e\u003c/i\u003e的是你可以在脚本中使用它，你还可以同时连接多个数据库\n\u003e 如果你只想写一个简单的脚本，把爬到的数据插到数据中，\u003cfont color=\"red\"\u003e\u003cb\u003eStraw\u003c/b\u003e\u003c/font\u003e会非常简单\n------------\n\n## 快速开始\n\n- 运行环境\n\n[![python:\u003e=3.7](https://img.shields.io/badge/Python-%3E%3D%203.7-blue)](https://www.python.org/downloads/)\n\n- 安装\n```shell\n# 安装straw库\npip install pstraw\n```\n\n- 快速使用\n\n[![源文件](https://img.shields.io/badge/Link-%E6%BA%90%E7%A0%81-orange)](https://github.com/pskelecton/straw/blob/master/ptest/test_quick_to_use/main.py)\n\n```python\nfrom pstraw import Straw\nfrom dataclasses import dataclass\nimport datetime\n# 实例化straw对象\ndb = Straw(\n    DB_DRIVER='mysql',\n    DB_DATABASE='straw_test',\n    DB_USER='root',\n    DB_PASSWORD='root',\n    DB_HOST='localhost',\n    DB_PORT=8071\n)\n# 创建一个结构体，用于保存数据对象\n@dataclass\nclass USER():\n    ID: int\n    NAME: str\n    USERDESC: str\n    VALID:int\n    CREATEBY: str\n    CREATETIME:datetime\n    UPDATEBY: str\n    UPDATETIME:datetime\n# 绑定一条sql语句，函数的返回值为sql中的参数映射\n@db.sql(USER,SQL='SELECT * FROM USER WHERE NAME = :NAME')\ndef SearchUser(name:str):\n    return {'NAME':name}\n# 通过注解创建一个链接\n@db.conn()\ndef ExecSQL():\n    # 调用函数来执行sql，函数调用的返回值res为sql查询的结果\n    users:list(USER) = SearchUser('Chalk Yu')\n    for userStore in users:\n        print(f'ID={userStore.ID}',f'NAME={userStore.NAME}',f'USERDESC={userStore.USERDESC}',f'CREATETIME={userStore.CREATETIME}')\n\nExecSQL()\n```\n\n## 基本调用\n\n### 通过SQL的方式调用\n\n[![源文件](https://img.shields.io/badge/Link-%E6%BA%90%E7%A0%81-orange)](https://github.com/pskelecton/straw/blob/master/ptest/test_exec_by_sql/main.py)\n\n```python\nfrom pstraw import Straw\nfrom dataclasses import dataclass\nfrom datetime import datetime\n# 实例化straw对象\ndb = Straw(\n    DB_DRIVER='mysql', # 必须输入\n    DB_DATABASE='straw_test', # 必须输入\n    DB_USER='root', # 必须输入3306, # mysql默认值：3306 ， postgres默认值：5432\n    DB_PASSWORD='root', # 必须输入\n    DB_HOST='127.0.0.1', # 默认值：localhost\n    DB_PORT='8071', # mysql默认值：3306 ， postgres默认值：5432\n    USE_BEAN=True # 是否使用结构体用于查询后的数据注入\n)\n'''\n  创建一个结构体，用于保存数据对象\n'''\n@dataclass\nclass USER():\n    ID: int\n    NAME: str\n    USERDESC: str\n    VALID:int\n    CREATEBY: str\n    CREATETIME:datetime\n    UPDATEBY: str\n    UPDATETIME:datetime\n\n@dataclass\nclass CLIENT():\n    ID:int\n    USERID:str\n    PHONE:str\n\n'''\n  @db.sql注解：绑定一个sql方法\n  通过SQL参数绑定一个sql查询语句，@db.sql注解的第一个参数是上面定义的结构体\n  注意：这只有查询的时候才会用到\n'''\n@db.sql(USER,SQL='SELECT * FROM USER WHERE NAME = :NAME AND ID \u003e :MINID')\ndef SearchUser(name:str,minId:int):\n    '''\n      函数返回的参数是个字典，其中字典的key：'USER'对应SQL语句中的:USER\n      如果user='Chalk Yu'，那么这个方法执行的就是：\n      SELECT * FROM USER_TABLE WHERE USER = 'Chalk Yu'\n    '''\n    return {'NAME':name,'MINID':minId}\n\n'''\n    @db.sql注解：绑定一个sql方法\n    插入数据\n'''\n@db.sql(SQL='INSERT INTO CLIENT(USERID,PHONE) VALUES (:USERID,:PHONE)')\ndef AddClient(userId:str,phone:str):\n  return {\n        \"USERID\": userId,\n        \"PHONE\": phone,\n        \"CREATEBY\": 'test_exec_by_sql',\n        \"CREATETIME\": datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"),\n        \"UPDATEBY\":'test_exec_by_sql',\n        \"UPDATETIME\": datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n    }\n'''\n    @db.sql注解：绑定一个sql方法\n    验证插入成功\n'''\n@db.sql(CLIENT,SQL='SELECT ID,USERID,PHONE FROM CLIENT WHERE USERID \u003e :MINID')\ndef SearchClient(minId:int):\n  return {'MINID':minId}\n'''\n  @db.conn注解：创建一个连接\n  注意1：@db.sql注解的方法只能在@db.conn中被调用，但@db.sql可以调任何无注解方法\n  注意2：@db.conn可以调用任何无注解方法，也可以被任何无注解方法调用，但不能调用@db.conn注解的方法\n'''\n# 通过注解创建一个链接\n@db.conn()\ndef ExecSQL():\n    minId = 18\n    clients = SearchClient(minId)\n    print(\"Pre --\u003e \",clients)\n    # 调用函数来执行sql，函数调用的返回值res为sql查询的结果\n    users:list(USER) = SearchUser('Chalk Yu',18)\n    for userStore in users:\n        print(f'ID={userStore.ID}',f'NAME={userStore.NAME}',f'USERDESC={userStore.USERDESC}',f'CREATETIME={userStore.CREATETIME}')\n        AddClient(userStore.ID,13600000000+userStore.ID)\n    clients = SearchClient(minId)\n    print(\"Aft --\u003e \",clients)\n\nExecSQL()\n```\n\n### 通过SQL_NAME指定一个sql文件\n\n[![源文件](https://img.shields.io/badge/Link-%E6%BA%90%E7%A0%81-orange)](https://github.com/pskelecton/straw/blob/master/ptest/test_exec_by_sql_file/main.py)\n\n#### 目录结构如下\n```\n|-- [项目文件夹]\n    | -- test_exec_by_sql_file.py\n    | -- InsertClient.sql\n    | -- SelectClient.sql\n    | -- SelectUser.sql\n```\n#### 代码如下\n - InsertClient.sql\n```sql\n-- 新增CLIENT\nINSERT INTO CLIENT(USERID,PHONE) VALUES (:USERID,:PHONE);\n```\n - SelectClient.sql\n```sql\n-- 查询CLIENT数据\nSELECT ID,USERID,PHONE FROM CLIENT WHERE USERID \u003e :MINID;\n```\n - SelectUser.sql\n```sql\n-- 查询USER数据\nSELECT * FROM USER WHERE NAME = :NAME AND ID \u003e :MINID;\n```\n - test_exec_by_sql_file.py\n```python\nfrom pstraw import Straw\nfrom dataclasses import dataclass\nfrom datetime import datetime\nimport os\n\ncase_dir = os.path.dirname(os.path.abspath(__file__))\n# 实例化straw对象\ndb = Straw(\n    DB_DRIVER='mysql', # 必须输入\n    DB_DATABASE='straw_test', # 必须输入\n    DB_USER='root', # 必须输入3306, # mysql默认值：3306 ， postgres默认值：5432\n    DB_PASSWORD='root', # 必须输入\n    DB_HOST='127.0.0.1', # 默认值：localhost\n    DB_PORT='8071', # mysql默认值：3306 ， postgres默认值：5432\n    SQL_PATH=os.path.join(case_dir,'.'),# 指定sql路径是当前目录，默认是./sql文件夹\n)\n'''\n  创建一个结构体，用于保存数据对象\n'''\n@dataclass\nclass USER():\n    ID: int\n    NAME: str\n    USERDESC: str\n    VALID:int\n    CREATEBY: str\n    CREATETIME:datetime\n    UPDATEBY: str\n    UPDATETIME:datetime\n\n@dataclass\nclass CLIENT():\n    ID:int\n    USERID:str\n    PHONE:str\n\n'''\n  @db.sql注解：绑定一个sql方法\n  SQL_NAME为要读入sql的文件名\n  这里相当于读取./SelectUser.sql文件\n'''\n@db.sql(USER,SQL_NAME='SelectUser')\ndef SearchUser(name:str,minId:int):\n    '''\n      函数返回的参数是个字典，其中字典的key：'USER'对应SQL语句中的:USER\n      如果user='Chalk Yu'，那么这个方法执行的就是：\n      SELECT * FROM USER_TABLE WHERE USER = 'Chalk Yu'\n    '''\n    return {'NAME':name,'MINID':minId}\n\n'''\n    @db.sql注解：绑定一个sql方法\n    插入数据\n'''\n@db.sql(SQL_NAME='InsertClient')\ndef AddClient(userId:str,phone:str):\n  return {\n        \"USERID\": userId,\n        \"PHONE\": phone,\n        \"CREATEBY\": 'test_exec_by_sql',\n        \"CREATETIME\": datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"),\n        \"UPDATEBY\":'test_exec_by_sql',\n        \"UPDATETIME\": datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n    }\n'''\n    @db.sql注解：绑定一个sql方法\n    验证插入成功\n'''\n@db.sql(CLIENT,SQL_NAME='SelectClient')\ndef SearchClient(minId:int):\n  return {'MINID':minId}\n'''\n  @db.conn注解：创建一个连接\n  注意1：@db.sql注解的方法只能在@db.conn中被调用，但@db.sql可以调任何无注解方法\n  注意2：@db.conn可以调用任何无注解方法，也可以被任何无注解方法调用，但不能调用@db.conn注解的方法\n'''\n# 通过注解创建一个链接\n@db.conn()\ndef ExecSQL():\n    minId = 18\n    clients = SearchClient(minId)\n    print(\"Pre --\u003e \",clients)\n    # 调用函数来执行sql，函数调用的返回值res为sql查询的结果\n    users:list(USER) = SearchUser('Chalk Yu',18)\n    for userStore in users:\n        print(f'ID={userStore.ID}',f'NAME={userStore.NAME}',f'USERDESC={userStore.USERDESC}',f'CREATETIME={userStore.CREATETIME}')\n        AddClient(userStore.ID,13600000000+userStore.ID)\n    clients = SearchClient(minId)\n    print(\"Aft --\u003e \",clients)\n\nExecSQL()\n```\n\n### 通过@model(func_name)在一个sql文件中绑定多个方法\n\n- 绑定一个sql文件的一段sql语句 [![源文件](https://img.shields.io/badge/Link-%E6%BA%90%E7%A0%81-orange)](https://github.com/pskelecton/straw/blob/master/ptest/test_sql_section_by_sql_file/main.py)\n\n- 在SQL参数绑定 [![源文件](https://img.shields.io/badge/Link-%E6%BA%90%E7%A0%81-orange)](https://github.com/pskelecton/straw/blob/master/ptest/test_sql_section_by_sql/main.py)\n\n- 一段sql绑定多个方法 [![源文件](https://img.shields.io/badge/Link-%E6%BA%90%E7%A0%81-orange)](https://github.com/pskelecton/straw/blob/master/ptest/test_template_type/main.py)\n\n```python\nfrom pstraw import Straw\nfrom dataclasses import dataclass\nfrom datetime import datetime\nimport os\n\ncase_dir = os.path.dirname(os.path.abspath(__file__))\n# 实例化straw对象\ndb = Straw(\n    DB_DRIVER='mysql', # 必须输入\n    DB_DATABASE='straw_test', # 必须输入\n    DB_USER='root', # 必须输入3306, # mysql默认值：3306 ， postgres默认值：5432\n    DB_PASSWORD='root', # 必须输入\n    DB_HOST='127.0.0.1', # 默认值：localhost\n    DB_PORT='8071', # mysql默认值：3306 ， postgres默认值：5432\n    SQL_PATH=os.path.join(case_dir,'.'),# 指定sql路径是当前目录，默认是./sql文件夹\n)\n'''\n  创建一个结构体，用于保存数据对象\n'''\n@dataclass\nclass USER():\n    ID: int\n    NAME: str\n    USERDESC: str\n    VALID:int\n    CREATEBY: str\n    CREATETIME:datetime\n    UPDATEBY: str\n    UPDATETIME:datetime\n\n@dataclass\nclass CLIENT():\n    ID:int\n    USERID:str\n    PHONE:str\n\n'''\n  @db.sql注解：绑定一个sql方法\n  读取./dml.sql文件，并绑定@model`SearchUser`注解的sql语句\n'''\n@db.sql(USER,SQL_NAME='dml')\ndef SearchUser(name:str,minId:int):\n    '''\n      函数返回的参数是个字典，其中字典的key：'USER'对应SQL语句中的:USER\n      如果user='Chalk Yu'，那么这个方法执行的就是：\n      SELECT * FROM USER_TABLE WHERE USER = 'Chalk Yu'\n    '''\n    return {'NAME':name,'MINID':minId}\n\n'''\n    @db.sql注解：绑定一个sql方法\n    读取./dml.sql文件，并绑定@model`AddClient`注解的sql语句\n'''\n@db.sql(SQL_NAME='dml')\ndef AddClient(userId:str,phone:str):\n  return {\n        \"USERID\": userId,\n        \"PHONE\": phone,\n        \"CREATEBY\": 'test_exec_by_sql',\n        \"CREATETIME\": datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"),\n        \"UPDATEBY\":'test_exec_by_sql',\n        \"UPDATETIME\": datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n    }\n'''\n    @db.sql注解：绑定一个sql方法\n    读取./dml.sql文件，并绑定@model`SearchClient`注解的sql语句\n'''\n@db.sql(CLIENT,SQL_NAME='dml')\ndef SearchClient(minId:int):\n  return {'MINID':minId}\n'''\n  @db.conn注解：创建一个连接\n  注意1：@db.sql注解的方法只能在@db.conn中被调用，但@db.sql可以调任何无注解方法\n  注意2：@db.conn可以调用任何无注解方法，也可以被任何无注解方法调用，但不能调用@db.conn注解的方法\n'''\n# 通过注解创建一个链接\n@db.conn()\ndef ExecSQL():\n    minId = 18\n    clients = SearchClient(minId)\n    print(\"Pre --\u003e \",clients)\n    # 调用函数来执行sql，函数调用的返回值res为sql查询的结果\n    users:list(USER) = SearchUser('Chalk Yu',18)\n    for userStore in users:\n        print(f'ID={userStore.ID}',f'NAME={userStore.NAME}',f'USERDESC={userStore.USERDESC}',f'CREATETIME={userStore.CREATETIME}')\n        AddClient(userStore.ID,13600000000+userStore.ID)\n    clients = SearchClient(minId)\n    print(\"Aft --\u003e \",clients)\n\nExecSQL()\n```\n\n### SQL_TEMPLATE_TYPE选择模板方式\n\n[![源文件](https://img.shields.io/badge/Link-%E6%BA%90%E7%A0%81-orange)](https://github.com/pskelecton/straw/blob/master/ptest/test_template_type/main.py)\n\n```python\nfrom pstraw import Straw\nfrom dataclasses import dataclass\nfrom datetime import datetime\nimport os\n\ncase_dir = os.path.dirname(os.path.abspath(__file__))\n# 实例化straw对象\ndb = Straw(\n    DB_DRIVER='mysql', # 必须输入\n    DB_DATABASE='straw_test', # 必须输入\n    DB_USER='root', # 必须输入3306, # mysql默认值：3306 ， postgres默认值：5432\n    DB_PASSWORD='root', # 必须输入\n    DB_HOST='127.0.0.1', # 默认值：localhost\n    DB_PORT='8071', # mysql默认值：3306 ， postgres默认值：5432\n    SQL_PATH=os.path.join(case_dir,'.'),# 指定sql路径是当前目录，默认是./sql文件夹\n)\n'''\n  创建一个结构体，用于保存数据对象\n'''\n@dataclass\nclass USER():\n    ID: int\n    NAME: str\n    USERDESC: str\n\n'''\n  @db.sql注解：绑定一个sql方法\n  -- SQL_TEMPLATE_TYPE = 1， 通过python字符串的%s占位符替换\n'''\n@db.sql(USER,SQL_NAME='dml',SQL_TEMPLATE_TYPE=1)\ndef TempType1():\n    # 返回值类型是tuple，按位置顺序替换sql中的%s\n    return (\"('Chalk Test 5','Chalk Test 6')\",)\n\n'''\n  @db.sql注解：绑定一个sql方法\n  -- SQL_TEMPLATE_TYPE = 2， 通过参数{0} ~ {n}的形式接收内容\n'''\n@db.sql(USER,SQL_NAME='dml',SQL_TEMPLATE_TYPE=2)\ndef TempType2():\n    # 返回值类型是tuple，以参数的形式传递到sql中\n    return (\"('Chalk Test 5','Chalk Test 6')\",\"USERDESC\")\n\n'''\n  @db.sql注解：绑定一个sql方法\n  -- SQL_TEMPLATE_TYPE = 3， 字典键值匹配\n  -- 例如  :USERDESC1 匹配@sql注解方法返回值{\"USERDESC1\":value1,\"USERDESC2\":value2}中的value1\n'''\n@db.sql(USER,SQL_NAME='dml',SQL_TEMPLATE_TYPE=3)\ndef TempType3():\n    # 返回值类型是dict，按照dict的key来绑定\n    return {\"USERDESC1\":\"'Chalk Test 5'\",\"USERDESC2\":\"'Chalk Test 6'\"}\n\n'''\n  @db.sql注解：绑定一个sql方法\n  -- SQL_TEMPLATE_TYPE = 4， 通过python字符串的%s占位符替换\n'''\n@db.sql(USER,SQL_NAME='dml',SQL_TEMPLATE_TYPE=4)\ndef TempType4():\n    # 返回值类型是tuple，按位置顺序替换sql中的%s，自动填充引号\n    # 组成的sql字符串：SELECT ID,NAME,USERDESC FROM USER WHERE USERDESC IN ('Chalk Test 5','Chalk Test 6');\n    return (\"Chalk Test 5\",\"Chalk Test 6\")\n\n'''\n  @db.sql注解：绑定一个sql方法\n  -- SQL_TEMPLATE_TYPE = 5， 通过参数{0} ~ {n}的形式接收内容\n'''\n@db.sql(USER,SQL_NAME='dml',SQL_TEMPLATE_TYPE=5)\ndef TempType5():\n    # 返回值类型是tuple，以参数的形式传递到sql中，自动填充引号\n    # 组成的sql字符串：SELECT ID,NAME,USERDESC FROM USER WHERE USERDESC IN ('Chalk Test 5','Chalk Test 6');\n    return (\"Chalk Test 5\",\"Chalk Test 6\")\n\n'''\n  @db.sql注解：绑定一个sql方法\n  -- SQL_TEMPLATE_TYPE = 6， 字典键值匹配\n  -- 例如  :USERDESC1 匹配@sql注解方法返回值{\"USERDESC1\":value1,\"USERDESC2\":value2}中的value1\n'''\n@db.sql(USER,SQL_NAME='dml',SQL_TEMPLATE_TYPE=6)\ndef TempType6():\n    # 返回值类型是dict，按照dict的key来绑定，自动填充引号\n    # 组成的sql字符串：SELECT ID,NAME,USERDESC FROM USER WHERE USERDESC IN ('Chalk Test 5','Chalk Test 6');\n    return {\"USERDESC1\":\"Chalk Test 5\",\"USERDESC2\":\"Chalk Test 6\"}\n\n'''\n  @db.sql注解：绑定一个sql方法\n  -- QUOTATION参数改变自动填充的引号类型，默认单引号\n'''\n@db.sql(USER,SQL_NAME='dml',SQL_TEMPLATE_TYPE=5,QUOTATION=\"\\\"\")\ndef quotationType():\n    # 自动填充双引号\n    # 组成的sql字符串：SELECT ID,NAME,USERDESC FROM USER WHERE USERDESC IN (\"Chalk Test 5\",\"Chalk Test 6\");\n    return (\"Chalk Test 5\",\"Chalk Test 6\")\n\n'''\n  @db.sql注解：绑定一个sql方法\n  -- SQL_TEMPLATE_TYPE如果没有指定，默认值：SQL_TEMPLATE_TYPE=6\n'''\n@db.sql(USER,SQL_NAME='dml')\ndef defaultTempType():\n    # 按照SQL_TEMPLATE_TYPE=6的方式解析\n    # 组成的sql字符串：SELECT ID,NAME,USERDESC FROM USER WHERE USERDESC IN ('Chalk Test 5','Chalk Test 6');\n    return {\"USERDESC1\":\"Chalk Test 5\",\"USERDESC2\":\"Chalk Test 6\"}\n\n'''\n  @db.conn注解：创建一个连接\n  注意1：@db.sql注解的方法只能在@db.conn中被调用，但@db.sql可以调任何无注解方法\n  注意2：@db.conn可以调用任何无注解方法，也可以被任何无注解方法调用，但不能调用@db.conn注解的方法\n'''\n# 通过注解创建一个链接\n@db.conn()\ndef ExecSQL():\n  tt1 = TempType1()\n  print(\"TempType1 --\u003e \",tt1)\n  tt2 = TempType2()\n  print(\"TempType2 --\u003e \",tt2)\n  tt3 = TempType3()\n  print(\"TempType3 --\u003e \",tt3)\n  tt4 = TempType4()\n  print(\"TempType4 --\u003e \",tt4)\n  tt5 = TempType5()\n  print(\"TempType5 --\u003e \",tt5)\n  tt6 = TempType6()\n  print(\"TempType6 --\u003e \",tt6)\n  qt = quotationType()\n  print(\"quotationType --\u003e \",qt)\n  dt = defaultTempType()\n  print(\"defaultTempType --\u003e \",dt)\n\nExecSQL()\n```\n\n### ALLOW_ROLLBACK自动回滚和AUTO_COMMIT自动提交\n\n\u003e 在自动提交状态下可以设置数据库异常时是否回滚\n\u003e 手动提交状态下，需要手动调用commit和rollback\n\n## 框架使用\n\n### SQL方法自动绑定\n\n\u003e 通过模块文件路径自动绑定sql文件的路径\n\n### 日志模块化\n\n\u003e 调试模式\n\u003e 外部调用日志打印\n\u003e 外部调用控制台打印\n\u003e DEBUG模式开关\n\n## 服务端引入\n\n### sql文件缓存\n\n\u003e 可以一次性把sql全部加载到内存中，但前期初始化时间较长，建议在服务端使用\n\n## 多数据库传输\n\n### 数据库缓存\n\n\u003e 数据传递很频繁的时候，需要预先配置好多个数据库连接信息，通过@entry注解做连接缓存，但缓存中的数据库不会自动关闭，需要手动关闭\n\n## sqlalchemy参数自定义\n\n\u003e 本项目采用的orm是sqlalchemy库，所以可以直接通过sqlalchemy来指定各种连接功能\n\n### ssl连接\n\n\u003e 通过sqlalchemy的自定义参数实现ssl连接\n\n## 配置加载\n\n### CONF_PATH配置文件读取\n\n\u003e 指定一个配置文件\n\n### ENV_DIR环境切换\n\n\u003e 通过环境类型来指定一个配置文件\n\n## 外部orm扩展\n\n\u003e 利用loader扩展外部orm\n### 外载ORM_LOADER\n\n### 重写loader方法\n\u003e RW_CONNECT / RW_EXECUTE / RW_COMMIT / RW_ROLLBACK / RW_CLOSE / RW_INJECT\n\n### 通过重写loader实现sql脚本生成器\n\n## API接口\n\n### 参数API\n- Straw参数\n\n| 参数 | 类型 | 默认值 | 说明 |\n| ------------ | :------------: | ------------ | ------------ |\n| DB_DRIVER | str | None | 驱动类型 \"mysql\" \\| \"postgres\"\n| DB_DATABASE | str | \"localhost\" | 数据库名\n| DB_USER | str | None | 用户名\n| DB_PASSWORD | str | None  |  密码\n| DB_HOST | str | None |  数据库连接地址\n| DB_PORT | int | 3306 \\| 5432 |  端口号，默认mysql或者postgres的端口\n| SQLITE_PATH | str | None |  sqlite db文件路径\n| ENCODING | str | 'utf-8' |  数据库编码\n| SQLALCHEMY_ARGS | dict | {'create_engine':None,\u003cbr/\u003e'sessionmaker':None,\u003cbr/\u003e'scoped_session':None} | sqlalchemy扩展参数\n| CONF_PATH | str | None |  配置文件路径\n| ENV_DIR | str | \".\" |  环境参数目录\n| SQL_PATH | str | \".\" |  sql文件目录\n| LOG_PATH | str | \".\" |  log文件目录\n| LOG_ON | bool | False |  是否写入log文件\n| ENV_ON | bool | False |  是否使用环境参数\n| ENV_TYPE | str | \"dev\" |  指定名dev.ini的环境配置文件\n| ENV_DIR | str | \"./env\" |  环境配置文件指定的目录\n| DEBUG | bool | False |  是否开启debug模式\n| LOG_MAX_SIZE | int | 10 |   log文件最大mb\n| LOG_BACKUP_CNT | int | 1 |  log文件最大备份数\n| TRACK_SQL_FILE | bool | False |  根据model目录来映射sql路径\n| MODEL_FOLDER_NAME | str | \"straw\" |   model目录名称\n| USE_BEAN | bool | True |  默认是否使用bean\n| ALLOW_ROLLBACK | bool | True |  异常是否自动回滚\n| AUTO_COMMIT | bool | True |  是否自动提交\n| SQL_TEMPLATE_TYPE | int | 6 | 模板类型 1\\|2\\|3\\|4\\|5\\|6\n| MAX_SQL_SIZE | int | 1024*512 | 可识别最大sql长度\n| QUOTATION | str | '\\'' | sql字符串所用的引号类型  \\'\\|\\\"\\|\\`\n| ORM_LOADER | type(OrmLoader) | None |  驱动插件扩展(oracle/sqlserver等)\n| RW_CONNECT | type(FunctionType) | None |  重写loader的connect方法\n| RW_EXECUTE | type(FunctionType) | None |  重写loader的execute方法\n| RW_CLOSE | type(FunctionType) | None |  重写loader的close方法\n| RW_COMMIT | type(FunctionType) | None |  重写loader的commit方法\n| RW_ROLLBACK | type(FunctionType) | None |  重写loader的rollback方法\n| RW_INJECT | type(FunctionType) | None |  重写loader的inject方法\n| HARD_LOAD_SQL | bool | False |  是否每次都重新读取sql文件\n| CACHE_CONNECT | bool | False |  缓存数据库连接，并保持不关闭\n| DB_CONF | dict | None | 缓存数据库连接时，需要配置的数据库信息\u003cbr\u003e{[DbModelName]:{'DB_DRIVER':?,'DB_DATABASE':?,...}}\n\n- @Straw.sql参数\n\n| 参数 | 类型 | 默认值   | 说明 |\n| ------------ | :------------: | ------------ | ------------ |\n| [Bean] | type(Bean) |   | 结构体\n| SQL_TEMPLATE_TYPE | int | 6 | 模板类型 1\\|2\\|3\\|4\\|5\\|6\n| SQL_NAME | str | None |  直接绑定sql文件\n| SQL | str | None |  直接绑定sql语句\n| HARD_LOAD_SQL | bool | False |  是否每次都重新读取sql文件\n\n- @Straw.conn参数\n\n| 参数 | 类型 | 默认值  | 说明 |\n| ------------ | :------------: | ------------ | ------------ |\n| [DbModelName]] | type(Bean) |   | 缓存数据库连接的情况下根据这个名称拿到连接对象\n| ALLOW_ROLLBACK | bool | True | 异常是否自动回滚\n| AUTO_COMMIT | bool | True | 是否自动提交\n\n- @Straw.entry参数\n\n| 参数 | 类型 | 默认值  | 说明 |\n| ------------ | :------------: | ------------ | ------------ |\n| START_GUIDE | bool | False | 启动向导，自动生成文件夹以及模板\n| CACHE_SQLS | bool | False | 是否缓存所有sqls数据（HARD_LOAD_SQL=True不做任何缓存）\n\n### 可调用方法、类\n  - Straw [主类]\n  - Store [数据对象生成类]\n  - ConfStore [配置生成类]\n  - GlobalConfig [全局参数引用对象]\n  - Transition [加载注入SQL工具]\n  - OrmLoader [loader接口类]\n  - Bean [bean接口类]\n\n### Straw对象的方法\n\u003e 初始化调用Straw()返回一个Straw对象，可调用方法如下所示\n \n - 装饰器函数\n\n   - @sql() [sql绑定]\n   - @conn() [数据库连接]\n   - @entry() [入口]\n \n - 数据库操作函数\n  \n   - connect(DB_CONF=DB_CONF) [连接数据库]\n   - execute(connection,sql,sqlAction=None) [执行sql]\n   - commit(connection) [提交]\n   - rollback(connection) [回滚]\n   - close(connection) [关闭数据库]\n   - inject() [实现注入]\n \n - 缓存处理函数\n  \n   - getAccessHeadStr() [获取数据库配置列表]\n   - cacheSqlFiles() [缓存所有的sql文件]\n   - cacheDbConn() [根据数据库配置列表连接所有的数据库，并缓存]\n \n - 向导函数\n  \n   - runGuide() [自动生成框架文件夹与模板]\n \n - 调试、日志、输出\n  \n   - logging(level,msg,*msgs) [输出在日志文件]\n   - print(level,msg,*msgs) [输出在控制台]\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpskelecton%2Fstraw","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpskelecton%2Fstraw","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpskelecton%2Fstraw/lists"}