Как управлять зависимостями модуля в jq - PullRequest
2 голосов
/ 06 июня 2019

Начиная с версии 1.5, язык обработки данных jq имеет библиотечную систему . Модуль состоит из дополнительных метаданных и набора функций. Например

module { name: "util", version: "1.0.0" };
def digitsum: tostring|split("")|map(tonumber)|add;

хранится в виде файла util.jq можно использовать так:

$ echo '789' | jq -L. 'include "util"; digitsum'
24

Модули могут использовать другие модули, а зависимости отслеживаются директивой modulemeta, но как выразить и проверить минимальную версию номера модуля? Например:

module {
  name: "math",
  version: "0.1.0",
};

include "util"; # TODO: require at least version 1.0.0!

def digitroot:
  (.|digitsum) as $sum |
  if $sum<10 then $sum else $sum|digitroot end;

1 Ответ

2 голосов
/ 06 июня 2019

Поддержка модулей в jq в настоящее время (июнь 2019 г.) все еще очень минимальна, хотя на github есть система управления модулями для jq: https://github.com/joelpurra/jqnpm

Без использования такой внешней системы управления модулями, что можно сделать в самом jq? Расширяя данный пример, нижеследующее иллюстрирует один подход к поддержке требований к версии. Обратите внимание на дополнительный ключ с именем dependencies в метаданных модуля math. (В настоящее время этот ключ не может быть назван deps, поскольку jq перезаписывает его.)

Файлы

dependencies.jq

# Recursively check specified version constraints 

module { name: "dependencies", version: "0.0.2" };

# parents of a module as defined by its .deps
def parents:
  . as $in
  | if type == "array" then map(parents) | add
    else modulemeta | .deps | map(.relpath)
    end ;

# ancestors of a single module or an array of modules.
# The array of "ancestors" of a module includes itself.
def ancestors:
  # input and $visited should be arrays of strings
  def ancestors($visited):
    . as $in
    | ($in - $visited) as $new
    | if $new == [] then $visited
      else $new | parents | ancestors($visited + $new | unique)
      end;
  if type == "array" then . else [.] end
  | ancestors([]) ;

def versionsort:
  def parse:
    sub("(?<a>(alpha|beta|gamma))"; "\(.a).")
    | [splits("[-.]")]
    | map(tonumber? // .) ;
  sort_by(parse);

# Input: a module name
# Emit empty if the constraints for the given module are satisfied, otherwise raise an error
def dependencies($version):
  def le($y):  (. == $y) or ([.,$y] | . == versionsort);

  modulemeta
  | .version as $mv
  | if (($mv == null) or ($version | le($mv))) then empty
    else ("module \(.name) dependencies version \($version) vs \($mv)" | error)
    end ;

# Input: a module name or array of module names
# Check the module-version dependencies in .dependencies, proceeding up the chain as defined by .deps
def dependencies:
  def check:
    modulemeta
    | select(has("dependencies"))
    | all( .dependencies | to_entries[];
           .key as $m | .value as $v | ($m | dependencies($v) ))
    | empty;
  ancestors[] | check;

util.jq

module { name: "util", version: "1.0.0" };

def digitsum: tostring|split("")|map(tonumber)|add;

math.jq

module { 
   name: "math",
   version: "0.1.0",
   dependencies: {"util": "1.0.0"} };

include "util" ;

def digitroot:
  digitsum as $sum
  | if $sum<10 then $sum
    else $sum|digitroot
    end;

1020 * Воззвание * jq -n -L . ' include "dependencies"; include "math"; "math" | dependencies, (123|digitroot) '

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...