Автор оригинала: Kyle J. Roux.
Цель
Чтобы ответить на неизбежный первый вопрос “почему”, я делаю этот учебник, потому что в последнее время я пишу все больше и больше JavaScript , и я использую paver , который является модулем Python, для автоматизации моих задач сборки JavaScript (например, компиляция CoffeeScript и минификация.)
Теперь, в попытке свести к минимуму фактический объем JavaScript, который я пишу, я хотел бы добавить ng-аннотацию в качестве шага в процессе сборки. Это позволит мне написать весь мой угловой код, не думая о его внедрении зависимостей, но все же используя его преимущества. Однако в настоящее время нет модуля Python, который я мог бы использовать для запуска кода через ng-annotate , который является библиотекой JavaScript.
PyExecJS
Как мы будем писать кросс-языковые модули?
С модулем Python PyExecJS
! PyExecJS
позволяет нам писать функции на JavaScript, которые мы затем можем вызывать из нашего кода Python. Функции JavaScript, которые мы пишем, могут возвращать данные прямо в наш код Python. PyExecJS
также позволяет нам выбрать движок JavaScript для использования, что помогает , поскольку нам нужно будет использовать движок узлов для работы с ng-annotate , поскольку ng-annotate является модулем узла.
Итак, для начала давайте использовать pip для установки библиотеки pyexecjs:
$ pip install pyexecjs
Далее мы запустим наш файл модуля (который мы будем называть ng_annotate.py
) путем импорта функции get
из execjs, которая позволяет нам запрашивать определенный движок JavaScript для запуска нашего кода.
from execjs import get import os runtime = get('Node')
Теперь, когда у нас есть механизм выполнения для работы, у нас есть то, что нам нужно.
Далее, нам нужно будет убедиться, что если кто-то установит это, у него будет доступ к модулю узла ng-annotate . Итак, создайте файл с именем package.json и поместите в него это:
{ "dependencies":{ "ng-annotate":"*" } }
Наконец, нам просто нужно добавить инструкцию для запуска npm install
перед ее использованием.
А теперь вернемся в наш файл модуля, нам нужно написать нашу функцию JavaScript, которую будет использовать наш модуль, а также убедиться, что он может получить доступ к папке node_modules , которая будет добавлена npm install
. Мы делаем это, оборачивая ваш JavaScript в вызов runtime.compile
, чтобы мы могли получить доступ к функциям внутри нашего кода Python.
context = runtime.compile(''' module.paths.push('%s'); ng = require('ng-annotate'); function annotate(src,cfg){ return ng(src,cfg); } ''' % os.path.join(os.path.dirname(__file__),'node_modules'))
Теперь мы можем вызвать функцию annotate
из нашего кода Python с помощью context.call('annotate',*args)
, и она вернет результат точно так же, как в JavaScript. Поэтому, чтобы превратить это в стандартную функцию Python, которую мы можем использовать, это так же просто, как:
def ng_annotate(src,cfg=None): if cfg is None: cfg = dict(add=True) return context.call('annotate',src,cfg)
Теперь мы можем использовать его из нашего кода Python с помощью from ng_annotate import ng_annotate
и вызова этой функции, но давайте также сделаем его удобным инструментом командной строки:
import sys def main(): print ng_annotate(open(sys.argv[-1],'r').read()) if __name__ == "__main__": main()
Вот и все ng_annotate.py файл для справки:
import os import sys from execjs import get runtime = get('Node') context = runtime.compile(''' module.paths.push('%s'); var ng = require('ng-annotate'); function annotate(src,cfg){ return ng(src,cfg); } ''' % os.path.join(os.path.dirname(__file__),'node_modules')) def ng_annotate(src,cfg=None): if cfg is None: cfg = dict(add=True) return context.call('annotate',src,cfg) def main(): print ng_annotate(open(sys.argv[-1],'r').read()) if __name__ == "__main__": main()