SQLObject 开发人员指南¶
以下是一些关于开发 SQLObject 的说明。
开发安装¶
首先安装 FormEncode
$ git clone git://github.com/formencode/formencode.git
$ cd formencode
$ sudo python setup.py develop
然后对 SQLObject 执行相同操作
$ git clone git clone git://github.com/sqlobject/sqlobject.git
$ cd sqlobject
$ sudo python setup.py develop
或者更确切地说,fork 它并克隆你的 fork。要开发一个功能或 bug 修复,请创建一个单独的分支,将其推送到你的 fork 并向原始仓库创建一个 pull 请求。这样,CI 将被触发以测试你的代码。
瞧!这些包已全局安装,但检出中的文件并未复制到 site-packages
中。有关更多信息,请参阅 setuptools。
架构¶
SQLObject 中有三种主要类型的对象:表、列和连接。
与表相关联的对象位于 sqlobject/main.py 模块中。有两个主要类:SQLObject
和 sqlmeta
;后者不是元类,而是每个类中 sqlmeta
属性的父类 - 作者尝试将所有与列无关的属性和方法移动到那里,以避免表命名空间混乱。
连接是 DBConnection
类(来自 sqlobject/dbconnection.py)及其具体子类的实例。 DBConnection
包含用于生成 SQL、处理事务等的通用代码。具体连接类(如 PostgresConnection
和 SQLiteConnection
)提供后端特定的功能。
列、验证器和转换器¶
列是 sqlobject/col.py 中类的实例。每列有两个类:一个供用户包含在 SQLObject 实例中,另一个实例由 SQLObject 元类自动创建。这两个类通常命名为 Col
和 SOCol
;例如,BoolCol
和 SOBoolCol
。用户可见类(Col
的子类)很少包含任何代码;列的主要代码在 SOCol
子类和验证器中。
每列都有一个验证器列表。验证器验证输入数据并将输入数据转换为 python 数据,然后再转换回来。每个验证器都必须有 from_python
和 to_python
方法。前者将数据从 python 转换为内部表示,该表示将由转换器转换为 SQL 字符串。后者将数据从 SQL 数据转换为 python。另外请记住,验证器可以接收 None
(对于 SQL NULL
)和 SQLExpression
(表示 SQLObject 表达式的对象);验证器必须原样传递这两个对象。
用户看不到 sqlobject/converters.py 中的转换器。它们在后台用于将验证器返回的对象转换为特定于后端的 SQL 字符串。最详细的转换器是 StringLikeConverter
。是的,它将字符串转换为字符串。它使用特定于后端的引用规则将 python 字符串转换为 SQL 字符串。
我们以 BoolCol
为例进行探讨。真正的 BoolCol
没有任何代码。SOBoolCol
有一个创建 BoolValidator
的方法和创建特定于后端的列类型的方法。BoolValidator
有相同的方法 from_python
和 to_python
;该方法原样传递 None
、SQLExpression
和布尔值;int 和具有 __nonzero__
方法(Python 3 中为 __bool__
)的对象转换为布尔值;其他对象触发验证错误。由调用 from_python
返回的布尔值将由 BoolConverter
转换为 SQL 字符串;来自 to_python
的布尔值(假设它们通过 DB API 驱动程序源自后端)传递给应用程序。
从 from_python
返回的对象必须使用转换器进行注册。另一种 from_python
方法是返回具有 __sqlrepr__
方法的对象。此类对象本身转换为 SQL 字符串,不使用转换器。
分支工作流¶
最初,SQLObject
使用 Subversion
进行开发。即使切换到 git,开发流程也仍然在一定程度上保留了旧的工作流。
在 git 中称为 master
的 trunk
是最先进、最不稳定的分支。这是应用新功能的地方。错误修复应用于 oldstable
和 stable
分支,并向上合并——从 oldstable
到 stable
,从 stable
到 master
。
风格指南¶
一般来说,你应该遵循 PEP 8(Python 风格指南)中的建议。一些需要特别注意的事项
- 除了少数例外,源代码必须是纯 ASCII。包括字符串文字和注释。
- 除了少数例外,源代码必须是 flake8-clean(因此也是 pep8-clean)。请考虑使用通过运行
flake8 --install-hook
安装的预提交钩子。
没有制表符。任何地方都没有。始终使用 4 个空格缩进。
我们不会过分强调行长。但尽量通过使用括号而不是反斜杠(如果可以的话)对行进行分组来换行。像这样断言
assert some_condition(a, b), ( "Some condition failed, %r isn't right!" % a)
但如果你在行长方面遇到问题,也许你应该将表达式拆分为多个语句。
方法之间留空行,除非它们非常小且紧密相连。
永远不要使用
condition and trueValue or falseValue
形式。将其拆分并使用变量。小心命名空间污染。SQLObject 允许
from sqlobject import *
,因此名称应该相当独特,或者它们不应该在sqlobject.__init__
中导出。我们对空格非常挑剔。只有一种正确的方法。好的例子
short = 3 longerVar = 4 if x == 4: do stuff func(arg1='a', arg2='b') func((a + b)*10)
糟糕的例子
short =3 longerVar=4 if x==4: do stuff func(arg1 = 'a', arg2 = 'b') func(a,b) func( a, b ) [ 1, 2, 3 ]
对我们来说,空格使用不当似乎很懒惰。出于这个非常微不足道的理由,我们会降低你代码的评价(无论是否合理)。如果你自己不这样做,我们会为你修复所有代码,因为我们无法忍受杂乱的空格。
使用
@@
标记不理想的内容,或你担心不正确的内容。尝试同时注明日期并在此处放置你的用户名。文档字符串很好。它们应该看起来像
class AClass(object): """ doc string... """
不要使用单引号 (‘’’)。不要费心尝试使字符串在垂直方向上更紧凑。
虽然不是严格要求,但强烈建议使用
reStructuredText
格式的文档字符串。注释应紧挨在它们注释的内容之前。
方法绝不要以大写字母开头。通常只有类才大写。但方法绝对不能大写。
首选混合大小写。
使用
cls
指代类。使用meta
指代元类(它也是一个类,但将元类称为cls
会令人困惑)。使用
isinstance
而不是比较类型。例如:if isinstance(var, str): ... # Bad: if type(var) is StringType: ...
切勿使用两个前导下划线。这很烦人。如果名称冲突是一个问题,请改用名称混淆(例如,
_SO_blahblah
)。这与双下划线本质上是同一回事,只是双下划线模糊了透明度。模块名称在包中应唯一。子包不应与同级包或父包共享模块名称。遗憾的是,
__init__
无法做到这一点,但其他情况很容易做到。模块名称应全部小写,并且可能没有下划线(smushedwords)。
测试¶
测试很重要。测试可以防止一切崩溃。所有新添加的内容都应进行测试。
测试使用 pytest,它是 unittest
的替代方案。它可在 https://pytest.cn/ 和 https://pypi.ac.cn/project/pytest/ 获得。阅读其 入门 文档以了解更多信息。
要实际运行测试,你必须为其提供一个要连接的数据库。你可以使用选项 -D
来执行此操作。你可以提供一个完整的 URI 或几个快捷方式之一,例如 mysql
(这些快捷方式在 tests/dbtest.py
的顶部定义)。
所有测试都是 sqlobject/tests
中的模块。每个模块或多或少地测试一种功能。如果你要测试一个模块,请将测试模块称为 tests/test_modulename.py
- 只有以 test_
开头的模块才会被 pytest 选中。
测试“框架”位于 tests/dbtest
中。有几个重要的函数
setupClass(soClass)
为该类创建表。它会尝试避免在不必要时重新创建表。
supports(featureName)
检查数据库后端是否支持命名的功能。哪些后端支持什么在 dbtest
的顶部定义。
如果您import *
,您还将获得 pytest 版本的 raises,一个可以为您创建实例的 inserts
函数,以及一些其他函数。
如果您提交补丁或在没有测试的情况下实现功能,我们将被迫编写测试。对我们来说,仅仅编写测试并不好玩。所以请编写测试;即使测试非常完整,也至少需要对所有内容进行练习。
我们现在使用 Github Actions 来运行测试。
文档¶
请编写文档。文档应以 reStructuredText
格式保存在 docs/ 目录中。我们使用 Sphinx 将文档转换为 HTML。
贡献¶
- 现在,事实上要求使用 良好的提交消息的标准。
- 推荐使用 常规提交主题行。
- 推荐使用
Markdown
格式的提交消息主体。Github 风格的 Markdown 是允许的。 - 提交消息必须是纯 ASCII。没有花哨的 Unicode 表情符号、引号等。