跳转到主要内容

此包通过Calmjs框架将RequireJS集成到Python环境中,以便通过Python包提供的JavaScript源代码以及从npm或其他类似的包仓库中获取的标准JavaScript或Node.js包,提供可重复的工作流程以生成可部署的工件。

项目描述

calmjs.rjs

通过Calmjs框架将RequireJS集成到Python环境中的包,通过Python包提供的JavaScript源代码以及从npm或其他类似的包仓库中获取的标准JavaScript或Node.js包,提供可重复的工作流程以生成可部署的工件。

https://travis-ci.org/calmjs/calmjs.rjs.svg?branch=2.0.1 https://ci.appveyor.com/api/projects/status/jbta6dfdynk5ke59/branch/2.0.1?svg=true https://coveralls.io/repos/github/calmjs/calmjs.rjs/badge.svg?branch=2.0.1

简介

可以使用任何语言创建Web应用程序,然而它们提供的交互式前端用户界面最终依赖于某种形式的JavaScript。提供前端功能的Python Web应用程序框架或系统,为了测试可能提供的JavaScript代码,采用了Node.js,并且使用npm(或bower)作为获取所需JavaScript包的包管理器。这通常导致了原本单一的包依赖配置被分割成多个不同的配置;通常这也导致包被分割成两部分,以适应所使用的分发渠道(PyPI与npm等)。

这种结果最终对Python包管理造成问题,因为增加了在所有相关包管理渠道上传播包版本和依赖信息的一致性、可移植性和可重复性的难度。另一个问题是,用于资产管理或工件生成的配置文件通常与特定系统紧密耦合,使得下游包难以重用这些配置来生成与它们的其它上游包保持一致的组合工件。

一些其他包管理器试图通过完全通用来解决这一问题,但它们缺乏对本地Python包(如本地环境中已安装的Python wheel)的认识,因此涉及Bower的构建过程通常依赖于公共基础设施,而将它们转移到私有基础设施或重用本地可用工件/包的选项需要额外的配置,从而抵消了这些系统提供的优势。此外,这些构建脚本紧密耦合到特定项目,不具有可移植性。

Calmjs框架的目标是通过提供方法来暴露Python包中包含的JavaScript源代码,使用此包calmjs.rjs,提供从这些导出的源文件生成可部署工件的功能,以及从npm或其他相关Node.js包管理系统获取的其他声明的外部包。

特性

calmjs.rjs是如何工作的

Calmjs框架提供框架,允许Python包声明它们需要的依赖项,针对基于npm的包提供的JavaScript代码,同时也允许Python包声明哪些模块导出了可重用的JavaScript源代码。

calmjs.rjs中包含的实用工具提供了一种方法来消费这些声明,将JavaScript文件视为源文件和编译目标,并通过requirejs包的r.js生成最终的可部署工件。

目前,源文件可以同时使用AMD和CommonJS模块格式编写,尽管由于大多数系统对其广泛支持,并且calmjs.rjs提供了将JavaScript源代码转换为与r.js优化器兼容的格式的转换和配置生成工具,因此推荐使用CommonJS格式。然而,源文件中的exports语句在目前不应该包含在module.exports中。AMD头部和尾部也可以省略,因为calmjs rjs转换器将添加所需的所有头部和尾部(例如,将require导入为正确的源,或将exports映射到module.exports),以便最终脚本可以用于目标平台或格式。

生成的源代码将放置在构建目录中,包括从Node.js包管理器或仓库中获取的所有声明的捆绑源。然后生成一个构建文件,该文件将包括所有相关源,以便通过r.js生成最终工件文件。然后可以将这些部署到适当的平台,或者将上述整个过程作为现有Python后端功能的一部分。

最终,calmjs.rjs的目标是通过将客户端JavaScript与服务器端Python之间的集成和交互简化,通过将这两组源代码在一个共享的包和环境中进行构建、分发和部署来简化任务。Calmjs框架提供了这两个环境之间的链接,并且该框架提供的工具将有助于设置一个共同的、可重复的本地Node.js环境。

最后,为了质量控制,该包与calmjs.dev集成,它提供了设置测试环境和运行Python包中JavaScript测试所需的工具。然而,该包并未作为直接依赖项声明,因为并非所有用例都需要该包。请参阅安装部分以获取详细信息。

请注意,在初始实现中,此框架支持的JavaScript源文件松散地遵循某些定义,这些定义仅模仿ES6想要提供的功能(如前面所述)。即使如此,由于将JavaScript在Python包中作为编译目标(即可部署的工件文件)的源文件处理,calmjs.rjs生成的输入源文件和导出的路径并不是为直接供网络客户端(如网络浏览器)使用而设计的。此框架产生的工件将通过AMD API使用。

安装

建议本地环境至少已安装Node.js和npm,以便能够安装requirejs(如果尚未安装和可用)。此外,Python的版本必须是2.7或3.3+;支持PyPy,但由于上游包在目前稳定的PyPy3版本2.4中无法正常工作,因此必须使用PyPy3版本5.2.0-alpha1。

要将calmjs.rjs安装到给定的Python环境中,可以使用以下命令直接从PyPI进行安装

$ pip install calmjs.rjs

使用calmjs安装/使用RequireJS

要为当前工作目录(例如项目)中的Python包建立支持r.js的开发/构建环境,可以通过以下命令执行

$ calmjs npm --install calmjs.rjs

在运行 npm install requirejs (以及其他由 calmjs.rjs 声明并需要的相关包)时,可以达到相同的效果,但请注意,Calmjs 框架使得 npm 依赖可以向下传递到依赖的包;这样,如果一个声明了 calmjs.rjs 作为依赖项的 Python 包(无论是通过 install_requires 还是其 setup.py 中的 extras_require)可能会使用以下命令安装其完整的 npm 依赖集(假设包名为 example.package

$ calmjs npm --install example.package

现在,将通过相关工具将 example.package 的所有标准 JavaScript 和 Node.js 依赖项安装到当前目录。此过程还将通过 npmrequirejs 安装其他由 example.package 所依赖的 Python 包声明的所有其他依赖项。

有关所有这些如何工作的更详细信息,请参阅 calmjs 的文档。否则,请继续到 使用 部分。

替代安装方法(高级用户)

关于 calmjs.rjs 的开发仍在进行中,要获取最新功能和错误修复,可以通过 git 安装开发版本,如下所示

$ pip install calmjs
$ pip install git+https://github.com/calmjs/calmjs.rjs.git#egg=calmjs.rjs

或者,可以直接克隆 git 仓库,在源目录的根目录中执行 python setup.py develop

请注意,在执行 calmjs.rjs 源树中的 setup.py 之前,calmjs 必须可用,因为它需要 calmjs 中的 package_json 写入功能。或者,如果在调用 setup.py 时出现有关 Unknown distribution option: 的任何消息,请执行 python setup.py egg_info

由于 calmjs 被声明为命名空间和包,因此在工作 Python 环境中需要进行某些低级设置,以确保所有模块都可以正确定位。然而,早于 v31.0.0setuptools 版本在使用此开发安装方法与在同一命名空间内使用 pip install 混合安装包时不会创建所需的包命名空间声明。因此,对于 calmjs 命名空间下的任何模块都可能发生不一致的导入失败。例如

>>> import calmjs.rjs
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named 'calmjs.rjs'
>>> import calmjs.base
>>> import calmjs.rjs
>>>

如果此行为(和解决方法)不受欢迎,请确保所有与 calmjs 相关的包遵循相同的方法(即,对于所有包,要么使用 python setup.py develop,要么使用通过 pip 获得的 wheel),或者将 setuptools 升级到 31 或更高版本并重新安装所有受影响的包。

测试安装

最后,要验证 calmjs.rjs 的成功安装,可以通过以下命令执行包含的测试

$ python -m unittest calmjs.rjs.tests.make_suite

但是,如果遵循了将外部 Node.js 依赖项安装到当前目录的步骤,则可以指定当前目录为 CALMJS_TEST_ENV 环境变量。在 POSIX 兼容的 shell 中,可以在该目录中执行以下操作

$ CALMJS_TEST_ENV=. python -m unittest calmjs.rjs.tests.make_suite

请注意,如果 calmjs.dev 包不可用,则将跳过一些测试。为了避免这种情况,可以单独安装该包,或者像这样使用其附加依赖项声明安装 calmjs.rjs

$ pip install calmjs.rjs[dev]

使用

要从当前环境中已安装的通过Calmjs模块注册系统公开的JavaScript代码的包生成一个RequireJS工件,只需执行以下命令:

$ calmjs rjs example.package

本文档的以下部分将概述如何通过Calmjs模块注册系统为给定的Python包启用JavaScript模块导出功能。然而,关于这个主题的更详细描述可以在calmjs包提供的README中找到,在从Python包导出JavaScript代码这一节中。

为Python声明JavaScript导出

通过calmjs.module注册系统公开的任何JavaScript代码都将被捕获并编译成可工作的RequireJS工件。例如,给定一个名为example的包定义的以下注册入口点:

[calmjs.module]
example = example

这是适用于与导入位置提供的名称相同的包的最基本的声明。

以下是一个针对具有嵌套子模块(称为example.libexample.app)的包的示例

[calmjs.module]
example.lib = example.lib
example.app = example.app

虽然声明的导入位置看起来就像Python模块(遵循Python入口点的规则),但calmjs.module注册系统将使用CommonJS/ES6风格的导入路径(即'example/lib''example/app')来展示它们,因此需要使用这些JavaScript模块的用户需要确保他们require这些字符串。

请注意,默认源提取器将提取那些目录中的所有JavaScript文件。最后,由于导入的方式,建议不要使用相对导入。

如果手头的包没有直接声明对calmjs的依赖,可能需要在包的setup函数中显式声明calmjs_module_registry=['calmjs.module'],以确保使用此默认模块注册来获取JavaScript源代码。

将此内容组合起来,setup.py文件应包含以下内容:

setup(
    name='example',
    # ... plus other declarations
    # This is one of the recommended options, even though the
    # project will not be importing from Calmjs.
    license='gpl',
    install_requires=[
        'calmjs>=3.0.0,<4',
        'calmjs.rjs>=2.0.0,<3',
        # plus other installation requirements
    ],
    # If the usage of the GPL is impossible for the project, or
    # declaring a direct dependency on calmjs packages is impossible
    # for the project for whatever other reasons (even though the
    # project itself will NOT be required to include/import ANY code
    # from the calmjs namespace), setup_requires may be used instead
    # of install_requires, and the following should also be included
    # as well:
    package_json={
        "devDependencies": {
            "requirejs": "~2.1.17",
        }
    },
    calmjs_module_registry=['calmjs.module'],
    # the entry points are required to allow calmjs to pick this up
    entry_points="""
    [calmjs.module]
    example = example
    example.lib = example.lib
    example.app = example.app
    """,
)

对于RequireJS工件的构建,calmjs rjs命令将自动从所选Python包的依赖中提取所有相关源文件到一个临时构建目录中,其中也将生成构建清单以调用r.js构建工件。一个示例运行:

$ calmjs rjs example

Tracing dependencies for: /home/user/example.js

/home/user/example.js
----------------
/tmp/tmp_build/build/example/lib/form.js
/tmp/tmp_build/build/example/lib/ui.js
/tmp/tmp_build/build/example/lib/main.js
/tmp/tmp_build/build/example/app/index.js

calmjs.rjs使用的构建过程是在单独的构建目录中完成的,因此必须将Node.js模块系统中的所有导入声明为extras_calmjs。例如,如果example/app/index需要像这样使用jqueryunderscore模块:

var $ = require('jquery'),
    _ = require('underscore');

它需要声明从npm源中获取的目标位置以及依赖项的package_json,它需要在它的setup.py中声明这一点

setup(
    # ...
    package_json={
        "dependencies": {
            "jquery": "~3.1.0",
            "underscore": "~1.8.0",
        },
    },
    extras_calmjs = {
        'node_modules': {
            'jquery': 'jquery/dist/jquery.js',
            'underscore': 'underscore/underscore.js',
        },
    },
)

完成这些后,重新运行python setup.py egg_info将新鲜声明的元数据写入包的egg-info目录,以便在环境中使用。现在可以调用calmjs npm --installnpm依赖项安装到当前目录;允许calmjs.rjs找到从npm源获取的所需文件,并将它们放入构建目录以便r.js定位它们。

生成的 calmjs 运行结果可能看起来像这样:

$ calmjs rjs example

Tracing dependencies for: /home/user/example.js

/home/user/example.js
----------------
/tmp/tmp_build/build/jquery.js
/tmp/tmp_build/build/underscore.js
/tmp/tmp_build/build/example/lib/form.js
/tmp/tmp_build/build/example/lib/ui.js
/tmp/tmp_build/build/example/lib/main.js
/tmp/tmp_build/build/example/app/index.js

转换器会添加适当的样板文件,因此通过 requirejs 添加的 require 语句将从 node_modules 导入,如果已声明 extras_calmjs。然而,在某些情况下,所需的工件应仅包含 Python 包的源代码,而不包含 extras 或反之亦然(因为库可通过另一个已部署的工件获取),这通过 r.jsempty: 方案支持,要为 calmjs rjs 启用它,可以这样做:

$ calmjs rjs example --bundlepath-method empty --export-filename main.js

Tracing dependencies for: /home/user/main.js

/home/user/main.js
----------------
/tmp/tmp_build/build/example/lib/form.js
/tmp/tmp_build/build/example/lib/ui.js
/tmp/tmp_build/build/example/lib/main.js
/tmp/tmp_build/build/example/app/index.js

$ calmjs rjs example --sourcepath-method empty --export-filename deps.js

Tracing dependencies for: /home/user/deps.js

/home/user/deps.js
----------------
/tmp/tmp_build/build/jquery.js
/tmp/tmp_build/build/underscore.js

上面的例子展示了生成两个独立的工件,一个包含已声明在 calmjs.module 注册表中的 Python 包 example 的源代码,另一个仅包含外部额外的源代码。

如果上述操作触发了 r.js 的依赖关系跟踪错误,可以使用最后的手段 --empty 标志;请注意,这将完全禁用 r.js 的跟踪功能,因为它启动了一个类似的跟踪过程,以定位所有导入的模块名称,并在生成的配置文件中使用 empty: 方案进行存根。确保生成的工件所需的模块在其它的地方都提供了所需的模块。

显式 extras_calmjs 声明也支持通过 bower 使用(通过 calmjs.bower 支持);而不是使用 node_modules 作为键,应使用 bower_components

除了 calmjs.module 之外,还可以使用 --source-registry 标志指定其他注册表。假设当前环境中注册了名为 myreg1myreg2 的注册表,并且 example 包已向它们注册了源代码,构建包含这两个注册表的包的命令可以是:

$ calmjs rjs --source-registry=myreg1,myreg2 example

处理 RequireJS 加载器插件

RequireJS 定义的 AMD 系统有加载器插件的概念,其中提供的模块名可以作为参数后缀,由插件处理。由于字符串提供的内容对整个 requirejs 系统来说是透明的,因此直接由前面的插件处理,所需的资源将特定于插件本身。因为它可能通过 requirejs 系统加载资源,所以任何需要配置的路径都需要完成配置。

为了解决这个问题,calmjs.rjs 引入了加载器插件处理器和注册表系统来处理这个问题。给定的 RJSToolchain 将分配一个默认的加载器插件注册表,但可以通过指定用于注册表的特定标识符(覆盖默认的 'calmjs.rjs.loader_plugin')来覆盖它,这将允许处理特定项目的非常定制的加载器。请参阅 calmjs.rjs.registry 模块以获取有关如何构建和设置该系统的更多详细信息。

默认情况下,text处理器已注册到默认的加载插件注册表中,这应该涵盖< span class="docutils literal">calmjs框架遇到的大多数常见用例。请注意,包仍需要在它们的package_json中向插件声明它们的(开发)依赖项,理想情况下使用良好的约束版本,以确保所有最终用户都获得一致的建设体验。

测试独立的、最终化的RequireJS工件

使用标准的calmjs rjs工具链运行时生成的AMD工件可以使用由calmjs.dev包提供的calmjs karma运行时进行测试。给定一个实现example包提供的功能的example.js,可以使用以下命令使用example包提供的测试对该工件进行测试:

$ calmjs karma run \
    -t calmjs.rjs \
    --artifact=example.js \
    example

上述命令使用calmjs.rjs设置调用独立的Karma运行器,以测试example.js工件文件,使用由example包提供的测试。测试执行与开发过程中的测试类似。

声明Python包的预构建JavaScript工件

最后,为了完成Python包部署的故事,该过程应包括自动生成和包含结果Python wheel中的JavaScript工件。这可以通过在calmjs.artifacts注册表中指定一个条目来实现,键是工件文件的名称,值是到构建器的导入位置。在calmjs.rjs.artifact:complete_rjs提供的默认构建器函数将启用为Python包生成完整的RequireJS工件。例如:

[calmjs.artifacts]
example.package.rjs.js = calmjs.rjs.artifact:complete_rjs

一旦安装了那些入口点,运行calmjs artifact build example.package将使用RequireJS工具链并构建位于元数据目录内的calmjs_artifacts目录中的example.package.rjs.js工件。作为替代方案,对于更与setuptools集成的解决方案,setup.py中的setup函数还应启用build_calmjs_artifacts标志,以便setup.py build也会触发构建过程。这对于自动生成并将工件作为轮构建过程的一部分包括在内非常有用。考虑以下setup.py

setup(
    name='example.package',
    # ... other required fields truncated
    build_calmjs_artifacts=True,
    entry_points="""
    # ... other entry points truncated
    [calmjs.module]
    example.package = example.package

    [calmjs.artifacts]
    example.package.rjs.js = calmjs.rjs.artifact:complete_rjs
    """,
)

使用setup.py构建轮可能产生类似的结果。请注意,r.js的执行是过程的一部分,然后元数据(egg-info)目录被构建到轮中。

$ python setup.py bdist_wheel
running bdist_wheel
running build
...
running build_calmjs_artifacts
automatically picked registries ['calmjs.module'] for sourcepaths
using loaderplugin registry 'calmjs.rjs.loader_plugin'
...
/src/example.package.egg-info/calmjs_artifacts/example.package.rjs.js
----------------
/tmp/tmpm_2jf151/build/example/package/index.js
...
running install_egg_info
Copying src/example.package.egg-info to build/.../wheel/example.package...
running install_scripts
creating build/.../wheel/example.package-1.0.dist-info/WHEEL

为了测试包工件,应在calmjs.artifacts.tests注册表中指定以下入口点,这样运行calmjs artifact karma example.package将执行由example.package声明的JavaScript测试,针对在calmjs.artifacts中声明的工件。

[calmjs.artifacts.tests]
example.package.rjs.js = calmjs.rjs.artifact:test_complete_rjs

故障排除

以下是与该包及其与其他Python/Node.js包的集成有关的一些已知问题。

在调用calmjs rjs时遇到ENOENT错误。

通常这是由于源包或注册表中引用了在构建目录中不可用的JavaScript模块的源文件导致的。通过 calmjs 框架的一个可能原因是,Python包未能声明它可能需要的 extras_calmjs,或者显式选择的映射方法和/或源注册没有将所有必需的源加载到构建目录中。

如果缺失的源文件是故意为之,则可以在 rjs 工具上应用 --empty-e 标志,以从包中省略所有缺失的模块;请注意,这将导致生成的工件包不包含其执行所需的所有模块。应将生成的工件包与提供所需依赖项结果的其它工件包一起使用。

RJSRuntimeError: 无法找到‘r.js’

这意味着当前的Node.js环境缺少来自 npm 的 requirejs 包;可以手动安装它,或者通过此包的 calmjs 来安装。如果特定的Python包需要使用 requirejs 生成包,则其 package_json 应声明此信息,或者声明对 calmjs.rjs 的依赖。

UserWarning: 未知分发选项

在开发方法设置和安装期间,如果显示此警告信息,请确保在源目录中运行 python setup.py egg_info 以正确生成 egg 元数据,因为当设置脚本最初执行时,calmjs 不可用。

贡献

变更日志

2.0.1 (2018-05-03)

  • 更新了 export_target 生产和使用 working_dir,使其与 calmjs-3.1.0 预期的保持一致。[ #3 ]

2.0.0 (2018-01-12)

  • 支持 calmjs-3.0.0 特性和破坏性更改。

  • 加载器插件框架已迁移到上游;使用它们的下游包应不再在 extras_calmjs 中声明显式条目,以允许更广泛的可移植性。

  • 为替代 slimit 的使用,改为使用 calmjscalmjs.parse 现在提供的功能。

  • 已更改 calmjs rjs 运行时的标志,以消除一些命名混淆,主要是由于 sourcemap,同时也为了与其他 calmjs 工具保持一致性。

    • 已弃用 --bundle-map-method,改为 --bundlepath-method;将在 3.0.0 中完全移除

    • 已弃用 --source-map-method,改为 --sourcepath-method;将在 3.0.0 中完全移除

  • calmjs.artifacts 注册表提供通用的包级工件构建器,以及相应的 calmjs.artifacts.tests 注册表的测试器。

1.0.2 (2017-05-22)

  • 修复了使用 empty: 方案取消映射插件时触发的 FileNotFoundError 问题。

1.0.1 (2017-01-27)

  • 在依赖项中也加载非测试文件,而不是将其作为测试的一部分自动包含。

  • 测试文件应按照惯例以test开头。

1.0.0 (2016-11-18)

  • 初始实现支持从Python包中包含的JavaScript源代码(及其通过npm或其他支持的工具声明的依赖项)生成AMD工件(包),通过calmjs框架实现。

  • 启用了calmjs rjs工具入口点。

  • 此外,通过纠正正确的钩子,与calmjs.dev进行集成,以便可以使用此包作为对通过此包生成的工件执行的测试的建议包。

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪一个,请了解有关安装包的更多信息。

源分布

calmjs.rjs-2.0.1.zip (92.2 kB 查看哈希)

上传时间

构建分布

calmjs.rjs-2.0.1-py2.py3-none-any.whl (67.5 kB 查看哈希)

上传时间 Python 2 Python 3

由以下机构支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误日志 StatusPage StatusPage 状态页面