From: Andreas Gerler Date: Thu, 23 Nov 2023 18:43:10 +0000 (+0100) Subject: update x-path-walker X-Git-Url: http://git.bundesbrandschatzamt.de/?a=commitdiff_plain;h=1b891743ed2628b8ac36fe4685a92b65dc7dd862;p=emacsconfig.git update x-path-walker Signed-off-by: Andreas Gerler --- diff --git a/elpa/x-path-walker-20160922.1835/x-path-walker-autoloads.el b/elpa/x-path-walker-20160922.1835/x-path-walker-autoloads.el deleted file mode 100644 index 6801d5f9..00000000 --- a/elpa/x-path-walker-20160922.1835/x-path-walker-autoloads.el +++ /dev/null @@ -1,31 +0,0 @@ -;;; x-path-walker-autoloads.el --- automatically extracted autoloads -;; -;;; Code: - -(add-to-list 'load-path (directory-file-name - (or (file-name-directory #$) (car load-path)))) - - -;;;### (autoloads nil "x-path-walker" "x-path-walker.el" (0 0 0 0)) -;;; Generated autoloads from x-path-walker.el - -(autoload 'helm-x-path-walker "x-path-walker" "\ - - -\(fn)" t nil) - -(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "x-path-walker" '("x-path-"))) - -;;;*** - -;;;### (autoloads nil nil ("x-path-walker-pkg.el") (0 0 0 0)) - -;;;*** - -;; Local Variables: -;; version-control: never -;; no-byte-compile: t -;; no-update-autoloads: t -;; coding: utf-8 -;; End: -;;; x-path-walker-autoloads.el ends here diff --git a/elpa/x-path-walker-20160922.1835/x-path-walker-pkg.el b/elpa/x-path-walker-20160922.1835/x-path-walker-pkg.el deleted file mode 100644 index 550df4b2..00000000 --- a/elpa/x-path-walker-20160922.1835/x-path-walker-pkg.el +++ /dev/null @@ -1,11 +0,0 @@ -(define-package "x-path-walker" "20160922.1835" "Navigation feature for JSON/XML/HTML based on path (imenu like)" - '((helm-core "1.9.2")) - :keywords - '("convenience") - :authors - '((nil . "")) - :maintainer - '(nil . "")) -;; Local Variables: -;; no-byte-compile: t -;; End: diff --git a/elpa/x-path-walker-20160922.1835/x-path-walker.el b/elpa/x-path-walker-20160922.1835/x-path-walker.el deleted file mode 100644 index fbec88f0..00000000 --- a/elpa/x-path-walker-20160922.1835/x-path-walker.el +++ /dev/null @@ -1,129 +0,0 @@ -;;; x-path-walker.el --- Navigation feature for JSON/XML/HTML based on path (imenu like) -*- lexical-binding: t; -*- - -;; Copyright (C) 2015 - -;; Author: -;; Keywords: convenience -;; Package-Requires: ((helm-core "1.9.2")) - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: - -;; - -;;; Code: - -(require 'helm) - -(defvar x-path-walker-source-dir (concat (if load-file-name - (file-name-directory load-file-name) - default-directory))) - -(defvar x-path-walker-objects-separators ".") - -(defun x-path-walker-command () - (list (concat "PYTHONPATH=" x-path-walker-source-dir) - (executable-find "python3") - "-m xpathwalker")) - -(defvar x-path-walker-verbose nil) - -(defun x-path-build-cmd-path (args) - (let ((cmdpython (x-path-walker-command))) - (mapconcat #'identity - (append cmdpython - args) - " "))) - -(defun x-path-run-py-script (args) - (let ((cmd (x-path-build-cmd-path args))) - (shell-command-to-string cmd))) - -(defun x-path-get-mode () - (let ((mm (pcase major-mode - (`json-mode "JSON") - (`xml-mode "XML") - (`nxml-mode "XML") - (`html-mode "HTML") - (`web-mode "HTML") - (code nil)))) - (unless (and (buffer-file-name) mm) - (keyboard-quit)) - mm)) - -(defun x-path-walker-ask () - (interactive) - (if (and (buffer-modified-p) - (yes-or-no-p "Buffer will be linted. Do you want to save the current buffer (required)?")) - (save-current-buffer) - (if (buffer-modified-p) - (keyboard-quit)))) - -(defun x-path-walker-jump-path (path) - (let* ((mode (x-path-get-mode)) - (path (if (not (bound-and-true-p x-path-walker-verbose)) - path - (if (or (string= mode "HTML") - (string= mode "XML")) - (car (split-string path " | ")) - (if (and (string= mode "JSON") ) - (car (cdr (split-string path " | "))) - "")))) - (line (replace-regexp-in-string - "\n$" "" - (x-path-run-py-script `("-x" - ,(shell-quote-argument path) - "-m" - ,mode - ,(buffer-file-name) ))))) - (if (string= mode "JSON") - (progn (x-path-walker-ask) - (erase-buffer) - (shell-command-on-region (point-min) (point-max) - (concat "python3 -m json.tool " - (buffer-file-name)) - (current-buffer)))) - (unless (or (string= "" line)) - (goto-char 0) - (forward-line (1- (string-to-number line))) - (recenter) - (back-to-indentation)))) - -;;;###autoload -(defun helm-x-path-walker() - (interactive) - (let* ((mode (x-path-get-mode)) - (file (buffer-file-name)) - (cmd-line `(,(if (bound-and-true-p x-path-walker-verbose) - "-a" - "") - "-m" - ,mode - ,file )) - (cands (split-string (x-path-run-py-script cmd-line)"\n"))) - (helm - :sources (helm-build-sync-source "PATH-WALKER" - :keymap helm-map - :candidates cands - :candidate-number-limit 500 - :action (helm-make-actions - "Jump to path" 'x-path-walker-jump-path)) - :prompt "Select Path:" - :resume 'noresume - :keymap helm-map - :buffer "*helm path-walker*"))) - -(provide 'x-path-walker) -;;; x-path-walker.el ends here diff --git a/elpa/x-path-walker-20160922.1835/xpathwalker/__init__.py b/elpa/x-path-walker-20160922.1835/xpathwalker/__init__.py deleted file mode 100644 index 894c4e7a..00000000 --- a/elpa/x-path-walker-20160922.1835/xpathwalker/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# xpathwalker - -has_legs = False diff --git a/elpa/x-path-walker-20160922.1835/xpathwalker/__main__.py b/elpa/x-path-walker-20160922.1835/xpathwalker/__main__.py deleted file mode 100755 index 745fbe78..00000000 --- a/elpa/x-path-walker-20160922.1835/xpathwalker/__main__.py +++ /dev/null @@ -1,58 +0,0 @@ -import sys - -from xpathwalker.args import parse_args - - -########################################################################## -# Main # -########################################################################## - -def main(argv): - parse_args(argv) - - -if __name__ == "__main__": - main(sys.argv[1:]) - -# Bench: -# wc -l -# 21302 /mnt/VM/home/lompik/Programmation/Web/d3_Map_GOM/Data/fldunit.json -# with multiproc: -# # string | .features[99].properties.UNIT_AGT_N -# # string | .features[99].properties.VERSION_DA -# # string | .features[99].type -# # string | .features[9].geometry.type -# # string | .features[9].properties.OUTLINE_TY -# # string | .features[9].properties.SDE_TEXT_L -# # string | .features[9].properties.UNIT_AGT_1 -# # string | .features[9].properties.UNIT_AGT_N -# # string | .features[9].properties.VERSION_DA -# # string | .features[9].type -# # string | .type -# # ./xmlxpath.py -a -M 374.99s user 29.73s system 569% cpu 1:11.05 total - -# without multiproc: -# # array | .features[9].geometry.coordinates[1][0][7] -# # number | .features[9].geometry.coordinates[1][0][7][0] -# # number | .features[9].geometry.coordinates[1][0][7][1] -# # array | .features[9].geometry.coordinates[1][0][8] -# # number | .features[9].geometry.coordinates[1][0][8][0] -# # number | .features[9].geometry.coordinates[1][0][8][1] -# # array | .features[9].geometry.coordinates[1][0][9] -# # number | .features[9].geometry.coordinates[1][0][9][0] -# # number | .features[9].geometry.coordinates[1][0][9][1] -# # string | .features[9].geometry.type -# # object | .features[9].properties -# # string | .features[9].properties.OUTLINE_TY -# # string | .features[9].properties.SDE_TEXT_L -# # number | .features[9].properties.SEQUENCE_N -# # number | .features[9].properties.SHAPE_Area -# # number | .features[9].properties.SHAPE_Leng -# # number | .features[9].properties.SN_UNIT_AL -# # number | .features[9].properties.SN_UNIT_OU -# # string | .features[9].properties.UNIT_AGT_1 -# # string | .features[9].properties.UNIT_AGT_N -# # string | .features[9].properties.VERSION_DA -# # string | .features[9].type -# # string | .type -# # ./xmlxpath.py -a 241.04s user 13.05s system 93% cpu 4:31.48 total diff --git a/elpa/x-path-walker-20160922.1835/xpathwalker/args.py b/elpa/x-path-walker-20160922.1835/xpathwalker/args.py deleted file mode 100644 index 85b02cfb..00000000 --- a/elpa/x-path-walker-20160922.1835/xpathwalker/args.py +++ /dev/null @@ -1,75 +0,0 @@ -from argparse import ArgumentParser -import os -import sys - -exts_mode = {'.html': "HTML", '.html': 'HTML', '.xml': 'XML', '.json': 'JSON', '.yaml': 'YAML'} - -def parse_args(argv): - """parse command line arguments - - :param argv: - :returns: Processor class - :rtype: - - """ - default_separator = "." - - parser = ArgumentParser(description="Xpath helper") - parser.add_argument("inputfile", - help="Input FILE", type=str) - parser.add_argument("-x", "--xpath", dest='xpath', - help="Returns line number corresponding to xpath from FILE", type=str) - parser.add_argument("-m", "--mode", dest='mode', - help="Language type", type=str, choices=('XML', 'HTML', 'JSON')) - parser.add_argument("-a", dest='verbosity', action="store_true", default=False, - help="Increase verbosity") - parser.add_argument("-M", dest='multiproc', action="store_true", default=False, - help="Use multiple process when possible") - parser.add_argument("-j", dest='use_jq', action="store_true", default=False, - help="JSON: Use jq for processing") - parser.add_argument("-F", dest='separator', default=default_separator, type=str, - help="Path elements separator") - args = parser.parse_args(argv) - - inputfile = args.inputfile - proc = False - if(not os.path.isfile(inputfile)): - sys.exit(1) - - ext = os.path.splitext(inputfile)[1].lower() - - if(args.mode is None): - if ext not in exts_mode.keys(): - print("Unrecognized file format.") - sys.exit(1) - else: - args.mode = exts_mode[ext] - - if(args.mode == 'HTML'): - from xpathwalker.lxml_Processor import HTML_Processor - proc = HTML_Processor() - if args.xpath: - args.xpath = "/"+args.xpath - elif(args.mode == 'XML'): - from xpathwalker.lxml_Processor import XML_Processor - proc = XML_Processor() - if args.xpath: - args.xpath = "/"+args.xpath - elif(args.mode == 'JSON'): - if(args.use_jq): - from xpathwalker.json_jq_Processor import JSON_jq_Processor - proc = JSON_jq_Processor() - else: - from xpathwalker.json_Processor import JSON_Processor - proc = JSON_Processor() - else: - print("Error in arg parsing") - sys.exit(2) - - proc.separator = args.separator - proc.parse_file(inputfile) - - if(args.xpath is not None): - print(proc.get_path_line_number(args.xpath, args.verbosity)) - else: - print("\n".join(proc.list_paths(args.verbosity))) diff --git a/elpa/x-path-walker-20160922.1835/xpathwalker/json_Processor.py b/elpa/x-path-walker-20160922.1835/xpathwalker/json_Processor.py deleted file mode 100644 index 1a4de78c..00000000 --- a/elpa/x-path-walker-20160922.1835/xpathwalker/json_Processor.py +++ /dev/null @@ -1,98 +0,0 @@ -from xpathwalker.utils import list_compare_idx -from xpathwalker.processor import Processor -from xpathwalker.utils import traverse_and_remove_path,\ - get_dict_from_path, get_class -import json -from collections import MutableSequence, MutableMapping -from collections import OrderedDict - -########################################################################## -# JSON / Python # -########################################################################## - - -class JSON_Processor(Processor): - file_line_number = 0 - - def isValidJsonShorthandPropertyName(self, key): - if not key[0].isalpha() or not key.isalnum(): - return('["' + key + '"]') - else: - return(self.separator + key) - - - def paths(self, obj, dirs=True, leaves=True, path='', skip=False, allow_empty_string_keys=False): - """Yield all paths of the object. - Arguments: - obj -- An object to get paths from. - Keyword Arguments: - dirs -- Yield intermediate paths. - leaves -- Yield the paths with leaf objects. - path -- A list of keys representing the path. - skip -- Skip special keys beginning with '+'. - """ - if isinstance(obj, MutableMapping): - # Python 3 support - # if PY3: - iteritems = obj.items() - - for (k, v) in iteritems: - if issubclass(k.__class__, (str)): - if (not k) and (not allow_empty_string_keys): - print("Empty string keys not allowed without " - "dpath.options.ALLOW_EMPTY_STRING_KEYS=True") - elif (skip and k[0] == '+'): - continue - newpath = path + self.isValidJsonShorthandPropertyName(str(k)) - # validate(newpath) - if dirs: - yield {newpath: {"class": v.__class__}} - for child in self.paths(v, dirs, leaves, newpath, skip): - yield child - - elif isinstance(obj, MutableSequence): - for (i, v) in enumerate(obj): - newpath = path + "[%s]" % i - if issubclass(i.__class__, int): - newpath = path + "[%d]" % i - if dirs: - yield {newpath: {"class": v.__class__}} - for child in self.paths(obj[i], dirs, leaves, newpath, skip): - yield child - elif leaves: - yield path + [[obj, obj.__class__]] - elif not dirs: - yield path - - def serialize_json(self): - res = OrderedDict() - for x in self.paths(self.parsed, leaves=False): - res.update(x) - return(res) - - def list_paths(self, with_attrs=True): - json_paths = self.serialize_json() - if(with_attrs): - return(["%6s | %s" % (get_class(json_paths[x]["class"]), x) for x in json_paths.keys()]) - else: - return([x for x in json_paths.keys()]) - - def get_path_line_number(self, path, with_attrs=False): - path = path.split("| ")[1] if (with_attrs is True) else path - - orig = self.parsed - path = get_dict_from_path(path, self.separator) - res = traverse_and_remove_path(orig, path) - orig = json.dumps(orig, indent=4).split("\n") - - if(len(orig) != self.file_line_number): - raise ValueError("This json file formatting is not compatible. Please run `python -m json.tool file`") - - with_del = json.dumps(res, indent=4).split("\n") - return(list_compare_idx(orig, with_del) + 1) - - def parse_file(self, file): - with open(file) as f: - self.file_line_number = len(f.readlines()) - f.seek(0) - self.parsed = json.load(f, object_pairs_hook=OrderedDict) diff --git a/elpa/x-path-walker-20160922.1835/xpathwalker/json_jq_Processor.py b/elpa/x-path-walker-20160922.1835/xpathwalker/json_jq_Processor.py deleted file mode 100644 index cb5b5bf0..00000000 --- a/elpa/x-path-walker-20160922.1835/xpathwalker/json_jq_Processor.py +++ /dev/null @@ -1,146 +0,0 @@ -import subprocess -import sys -import os -from tempfile import NamedTemporaryFile -from xpathwalker.utils import list_compare_idx -from xpathwalker.processor import Processor - -########################################################################## -# JSON # -########################################################################## - -jq_command = """def safeLookupValue: - if type != "string" then - tostring - else - . - end; -\ -def arrayToLookup: - map(safeLookupValue) - | reduce .[] as $exists ( - {}; - . + { - ($exists): null - } - ); -\ -def lookup(value): - (value | safeLookupValue) as $value - | has($value); -\ -def isWhitelisted(whitelist): - whitelist as $whitelist - | explode - | map( - . as $charCode - | $whitelist - | lookup($charCode) - ) - | all; -\ -def isNumeric: - ("0123456789" | explode | arrayToLookup) as $digits - | isWhitelisted($digits); -\ -def isAlpha: - ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" | explode | arrayToLookup) as $letters - | isWhitelisted($letters); -\ -def isAlphanumeric: - ("0123456789" | explode | arrayToLookup) as $digits - | ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" | explode | arrayToLookup) as $letters - | ("_" | explode | arrayToLookup) as $special - | ($digits + $letters + $special) as $alphanumeric - | isWhitelisted($alphanumeric); -\ -def isValidJsonShorthandPropertyName: - (.[0:1] | isAlpha | not) or (isAlphanumeric | not); -\ -[ - path(..) - | map( - if type == "number" then - ["[",(.|tostring),"]"]|join("") - else - tostring - | if isValidJsonShorthandPropertyName then - "[\\"\\(.)\\"]" - else - . - end - end - ) - | join(".") - | split("." + "[") - | join("[") -] -| unique -| map("." + .) -| .[]""" - -jq_exec = ["jq", "--raw-output"] - -def jq_proc(args): - with NamedTemporaryFile() as f: - try: - proc = subprocess.check_call(args, - stdout=f, - stderr=subprocess.STDOUT) - except subprocess.CalledProcessError: - print(proc.stderr.fseek(0).read().decode('utf-8')) - sys.exit(1) - f.seek(0) - return f.read().decode('utf-8').split('\n') - - -class JSON_jq_Processor(Processor): - file = "" - - def list_paths(self, with_attrs=True, multiproc=False): - if(not os.path.isfile(self.file)): - sys.exit(1) - proc = jq_proc(args=jq_exec + [jq_command, - self.file]) - paths = [x for x in proc if x != ''] - res = [] - if(with_attrs is False): - res = paths - elif with_attrs is True: - if multiproc is False: - for x in paths: - proc = jq_proc(args=jq_exec + ["%s|type" % x, - self.file]) - type = proc[0] - res.append("%6s | %s" % (type[0:6], x)) - else: - def get_types(q, x, file): - proc = jq_proc(args=jq_exec + ["%s|type" % x, - self.file]) - type = proc[0] - q.put("%6s | %s" % (type[0:6], x)) - import queue - import threading - q = queue.PriorityQueue() - for x in paths: - t = threading.Thread(target=get_types, args=(q, x, self.file)) - t. start() - while(q.qsize() > 0): - res.append(q.get()) - return(res) - - def get_path_line_number(self, path, with_attrs=False): - path = path.split("| ")[1] if (with_attrs is True) else path - proc = jq_proc(args=jq_exec + ['.', - self.file]) - orig = proc - proc = jq_proc(args=jq_exec + ['del(%s)' % path, - self.file]) - with_del = proc - return(list_compare_idx(orig, with_del) + 1) - - def parse_file(self, file): - if(not os.path.isfile(file)): - print("File %s: Not Found" % (file)) - sys.exit(1) - self.file = file diff --git a/elpa/x-path-walker-20160922.1835/xpathwalker/lxml_Processor.py b/elpa/x-path-walker-20160922.1835/xpathwalker/lxml_Processor.py deleted file mode 100644 index 342e0480..00000000 --- a/elpa/x-path-walker-20160922.1835/xpathwalker/lxml_Processor.py +++ /dev/null @@ -1,85 +0,0 @@ -from xpathwalker.processor import Processor -import os -import sys -import lxml.etree -import lxml.html - - -class lxmlProcessor(Processor): - """ [X/HT]ML processor - """ - def list_paths(self, with_attrs=False): - if(not self.parsed): - raise ValueError("No data in parsed") - parsed = self.parsed - res = [] - for el in parsed.xpath("//*"): - if(with_attrs): - if el.keys() is None: - res.append("/%s | %s | %s" % (parsed.getelementpath(el), ",".join(el.keys()))) - else: - res.append("/%s | %s" % (parsed.getelementpath(el), - ",".join(["%s: %s" % (attr, el.get(key=attr)) for attr in el.keys()]))) - else: - res.append("/%s" % (parsed.getelementpath(el))) - return(res) - - def handle_namespace_in_xpath(self, xpath): - closinp = len(xpath.split("}")) - if(closinp > 1 and closinp != len(xpath.split("}"))): - return xpath - import re - import string - insidep = r"(?<={)[^}]*" - namesspaces = re.findall(insidep, xpath) - nsdict = {} - - def get_letters(matchobj): - get_letters.counter += 1 - id = string.ascii_letters[get_letters.counter] - nsdict.update({id: namesspaces[get_letters.counter]}) - return id + ":" - get_letters.counter = -1 - par = re.compile(r"{"+insidep+r"}") - xpath = par.sub(get_letters, xpath) - return (xpath, {"namespaces": nsdict}) - - def get_path_line_number(self, xpath, with_attrs=False): - if(not self.parsed): - raise ValueError("No data in parsed") - - parsed = self.parsed - xpath = xpath.split(" | ")[0] if (with_attrs is True or xpath.find(" | ") > -1) else xpath - res = 0 - matchs = [] - - if(xpath.find("{") > -1): # Handle namespace cases - xpath, args = self.handle_namespace_in_xpath(xpath) - matchs = parsed.xpath(xpath, **args) - else: - matchs = parsed.xpath(xpath) - if(len(matchs) > 0): - res = matchs[0].sourceline - return(res) - -class HTML_Processor(lxmlProcessor): - def parse_file(self, file): - """HTML file parse from lxml - - :param file: file path (string) - :returns: null - :rtype: - - """ - self.parsed = lxml.html.parse(file) - -class XML_Processor(lxmlProcessor): - def parse_file(self, file): - """HTML file parse from lxml - - :param file: file path (string) - :returns: null - :rtype: - - """ - self.parsed = lxml.etree.parse(file) diff --git a/elpa/x-path-walker-20160922.1835/xpathwalker/processor.py b/elpa/x-path-walker-20160922.1835/xpathwalker/processor.py deleted file mode 100644 index 9cda9e64..00000000 --- a/elpa/x-path-walker-20160922.1835/xpathwalker/processor.py +++ /dev/null @@ -1,42 +0,0 @@ - - -class Processor: - """An abstract object class to handle the parsing/procesing of files - - """ - separator = "." - - def __init__(self): - super(Processor, self).__init__() - - def list_paths(self, parsed, with_attrs=False): - """Return array of path separated by the separator - - :param parsed: A python type object - :param with_attrs: List additional attributes - :returns: array of paths - :rtype: array - - """ - pass - - def get_path_line_number(self, path, with_attrs=False): - """Returns the line number from the file corresponding `path` - - :param path: Path seeked - :param with_attrs: `True` if `path` is formatted with additional attributes - :returns: line numer corresponding to path - :rtype: int - - """ - pass - - def parse_file(self, file): - """Translate the `file` into python object - - :param file: File path - :returns: Nothing. insternal variable updated. - :rtype: - - """ - pass diff --git a/elpa/x-path-walker-20160922.1835/xpathwalker/utils.py b/elpa/x-path-walker-20160922.1835/xpathwalker/utils.py deleted file mode 100644 index be6b8e2d..00000000 --- a/elpa/x-path-walker-20160922.1835/xpathwalker/utils.py +++ /dev/null @@ -1,102 +0,0 @@ -from collections import OrderedDict - -########################################################################## -# Utils # -########################################################################## - -def get_class(obj): - name = obj.__name__ - if(name == "OrderedDict"): - return("object") - elif(name == "NoneType"): - return("null") - return(name) - -def list_compare_idx(list1, list2): - index = 0 - for idx, origline in enumerate(list1): - if(list2[idx] != origline): - if((list2[idx]+",") != origline): - index = idx - break - return(index) - -def split_path(path, separator, inside_special=False): - first_match = '"]' if inside_special else '["' - i = path.find(first_match) - if i != -1 and inside_special is False: - if(path[0:i] != ''): - return (split_path(path[0:i], - separator=separator, - inside_special=False) + - split_path(path[i+len('["'):], - separator=separator, - inside_special=True)) - else: - return (split_path(path[i+len('["'):], - separator=separator, - inside_special=True)) - if i != -1 and inside_special is True: - if(path[i+len('["'):] != ''): - return ([path[:i], "special"],) + split_path(path[i+len('["'):], - separator=separator, - inside_special=False) - else: - return ([path[:i], "special"],) - else: - i = path.find(separator) - if i == -1: - return (path,) - else: - if(i != 0): - return (path[:i],) + split_path(path[i+1:], separator) - else: - return split_path(path[i+1:], separator) - - -def get_dict_from_path(path, separator): - path = split_path(path, separator) - - res = [] - for x in path: - if not isinstance(x, list): - pos = x.find("[") - while pos != -1: - if pos == 0: - i1 = x.find("]") - x1 = int(x[0:i1].replace("[", "", 1).replace("]", "", 1)) - x = x[i1+1:] - res.append(x1) - else: - res.append(x[0:pos]) - x = x[pos:] - pos = x.find("[") - else: - res.append(x[0]) - return(res) - -def traverse_and_remove_path(obj, path=None, match="First"): - if path is None: - path = [] - if isinstance(obj, dict): - res = OrderedDict() - for k, v in obj.items(): - cmatch = False - if(match and len(path) > 0 and path[0] == k): - cmatch = True - res.update({k: traverse_and_remove_path(v, path=path[1:], match=cmatch)}) - if(len(path) == 1 and path[0] in res.keys() and match): - del res[path[0]] - return res - elif isinstance(obj, list): - res = [] - for i, elem in enumerate(obj): - cmatch = False - if(match and len(path) >= 1 and isinstance(path[0], int) and path[0] < len(obj) and i == path[0]): - cmatch = True - res.append(traverse_and_remove_path(elem, path=path[1:], match=cmatch)) - if(len(path) == 1 and isinstance(path[0], int) and path[0] < len(res) and match): - res.pop(path[0]) - return res - else: - return obj # no container, just values (str, int, float) diff --git a/elpa/x-path-walker-20160922.1835/xpathwalker/yaml_Processor.py b/elpa/x-path-walker-20160922.1835/xpathwalker/yaml_Processor.py deleted file mode 100644 index fd28d37e..00000000 --- a/elpa/x-path-walker-20160922.1835/xpathwalker/yaml_Processor.py +++ /dev/null @@ -1,37 +0,0 @@ -########################################################################## -# YAML # -########################################################################## -import yaml -from xpathwalker.utils import list_compare_idx -from xpathwalker.utils import traverse_and_remove_path, get_dict_from_path, get_class, paths -from collections import OrderedDict -import os - -def parse_yaml(file): - with open(file) as f: - yaml_data = yaml.load(f) - res = OrderedDict() - for x in paths(yaml_data, leaves=False): - res.update(x) - return(res) - -def get_yaml_paths(file, include_type=True): # XXX: ordering is lost - yaml_paths = parse_yaml(file) - if(include_type is True): - return(["%s | %s" % (get_class(yaml_paths[x]['class']), x) for x in yaml_paths.keys()]) - else: - return(yaml_paths.keys()) - -def get_yaml_path_line_python(file, path, include_type=False): - if(not os.path.isfile(file)): - sys.exit(1) - path = path.split("| ")[1] if (include_type is True) else path - orig = "" - with open(file) as f: - orig = yaml.load(f) - path = get_dict_from_path(path) - res = traverse_and_remove_path(orig, path) - yaml_dump_options = {"indent": 4, "default_flow_style": False, "explicit_start": False} - orig = yaml.dump(orig, **yaml_dump_options).split("\n") - with_del = yaml.dump(dict(res), **yaml_dump_options).split("\n") - return(list_compare_idx(orig, with_del) + 1) diff --git a/elpa/x-path-walker-20220714.1056/x-path-walker-autoloads.el b/elpa/x-path-walker-20220714.1056/x-path-walker-autoloads.el new file mode 100644 index 00000000..9790c43e --- /dev/null +++ b/elpa/x-path-walker-20220714.1056/x-path-walker-autoloads.el @@ -0,0 +1,28 @@ +;;; x-path-walker-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "x-path-walker" "x-path-walker.el" (0 0 0 0)) +;;; Generated autoloads from x-path-walker.el + +(autoload 'helm-x-path-walker "x-path-walker" nil t nil) + +(register-definition-prefixes "x-path-walker" '("x-path-")) + +;;;*** + +;;;### (autoloads nil nil ("x-path-walker-pkg.el") (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; x-path-walker-autoloads.el ends here diff --git a/elpa/x-path-walker-20220714.1056/x-path-walker-pkg.el b/elpa/x-path-walker-20220714.1056/x-path-walker-pkg.el new file mode 100644 index 00000000..15b837fc --- /dev/null +++ b/elpa/x-path-walker-20220714.1056/x-path-walker-pkg.el @@ -0,0 +1,13 @@ +(define-package "x-path-walker" "20220714.1056" "Navigation feature for JSON/XML/HTML based on path (imenu like)" + '((helm-core "3.6.0")) + :commit "c91deaaba0d5cc9018008a39c96222deacba3868" :authors + '((nil . "")) + :maintainers + '((nil . "")) + :maintainer + '(nil . "") + :keywords + '("convenience")) +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/elpa/x-path-walker-20220714.1056/x-path-walker.el b/elpa/x-path-walker-20220714.1056/x-path-walker.el new file mode 100644 index 00000000..1a627458 --- /dev/null +++ b/elpa/x-path-walker-20220714.1056/x-path-walker.el @@ -0,0 +1,130 @@ +;;; x-path-walker.el --- Navigation feature for JSON/XML/HTML based on path (imenu like) -*- lexical-binding: t; -*- + +;; Copyright (C) 2015 + +;; Author: +;; Keywords: convenience +;; Package-Requires: ((helm-core "3.6.0")) + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; + +;;; Code: + +(require 'helm-core) + +(defvar x-path-walker-source-dir (concat (if load-file-name + (file-name-directory load-file-name) + default-directory))) + +(defvar x-path-walker-objects-separators ".") + +(defun x-path-walker-command () + (list (concat "PYTHONPATH=" x-path-walker-source-dir) + (executable-find "python3") + "-m xpathwalker")) + +(defvar x-path-walker-verbose nil) + +(defun x-path-build-cmd-path (args) + (let ((cmdpython (x-path-walker-command))) + (mapconcat #'identity + (append cmdpython + args) + " "))) + +(defun x-path-run-py-script (args) + (let ((cmd (x-path-build-cmd-path args))) + (shell-command-to-string cmd))) + +(defun x-path-get-mode () + (let ((mm (pcase major-mode + (`json-mode "JSON") + (`xml-mode "XML") + (`nxml-mode "XML") + (`html-mode "HTML") + (`web-mode "HTML") + (code nil)))) + (unless (and (buffer-file-name) mm) + (keyboard-quit)) + mm)) + +(defun x-path-walker-ask () + (interactive) + (if (and (buffer-modified-p) + (yes-or-no-p "Buffer will be linted. Do you want to save the current buffer (required)?")) + (save-current-buffer) + (if (buffer-modified-p) + (keyboard-quit)))) + +(defun x-path-walker-jump-path (path) + (let* ((mode (x-path-get-mode)) + (path (if (not (bound-and-true-p x-path-walker-verbose)) + path + (if (or (string= mode "HTML") + (string= mode "XML")) + (car (split-string path " | ")) + (if (and (string= mode "JSON") ) + (car (cdr (split-string path " | "))) + "")))) + (line (replace-regexp-in-string + "\n$" "" + (x-path-run-py-script `("-x" + ,(shell-quote-argument path) + "-m" + ,mode + ,(buffer-file-name) ))))) + (if (string= mode "JSON") + (progn (x-path-walker-ask) + (erase-buffer) + (shell-command-on-region (point-min) (point-max) + (concat "python3 -m json.tool " + (buffer-file-name)) + (current-buffer) t + "*x-path-walker-json-error*" t))) + (unless (or (string= "" line)) + (goto-char 0) + (forward-line (1- (string-to-number line))) + (recenter) + (back-to-indentation)))) + +;;;###autoload +(defun helm-x-path-walker() + (interactive) + (let* ((mode (x-path-get-mode)) + (file (buffer-file-name)) + (cmd-line `(,(if (bound-and-true-p x-path-walker-verbose) + "-a" + "") + "-m" + ,mode + ,file )) + (cands (split-string (x-path-run-py-script cmd-line)"\n"))) + (helm + :sources (helm-build-sync-source "PATH-WALKER" + :keymap helm-map + :candidates cands + :candidate-number-limit 500 + :action (helm-make-actions + "Jump to path" 'x-path-walker-jump-path)) + :prompt "Select Path:" + :resume 'noresume + :keymap helm-map + :buffer "*helm path-walker*"))) + +(provide 'x-path-walker) +;;; x-path-walker.el ends here diff --git a/elpa/x-path-walker-20220714.1056/xpathwalker/__init__.py b/elpa/x-path-walker-20220714.1056/xpathwalker/__init__.py new file mode 100644 index 00000000..894c4e7a --- /dev/null +++ b/elpa/x-path-walker-20220714.1056/xpathwalker/__init__.py @@ -0,0 +1,3 @@ +# xpathwalker + +has_legs = False diff --git a/elpa/x-path-walker-20220714.1056/xpathwalker/__main__.py b/elpa/x-path-walker-20220714.1056/xpathwalker/__main__.py new file mode 100755 index 00000000..745fbe78 --- /dev/null +++ b/elpa/x-path-walker-20220714.1056/xpathwalker/__main__.py @@ -0,0 +1,58 @@ +import sys + +from xpathwalker.args import parse_args + + +########################################################################## +# Main # +########################################################################## + +def main(argv): + parse_args(argv) + + +if __name__ == "__main__": + main(sys.argv[1:]) + +# Bench: +# wc -l +# 21302 /mnt/VM/home/lompik/Programmation/Web/d3_Map_GOM/Data/fldunit.json +# with multiproc: +# # string | .features[99].properties.UNIT_AGT_N +# # string | .features[99].properties.VERSION_DA +# # string | .features[99].type +# # string | .features[9].geometry.type +# # string | .features[9].properties.OUTLINE_TY +# # string | .features[9].properties.SDE_TEXT_L +# # string | .features[9].properties.UNIT_AGT_1 +# # string | .features[9].properties.UNIT_AGT_N +# # string | .features[9].properties.VERSION_DA +# # string | .features[9].type +# # string | .type +# # ./xmlxpath.py -a -M 374.99s user 29.73s system 569% cpu 1:11.05 total + +# without multiproc: +# # array | .features[9].geometry.coordinates[1][0][7] +# # number | .features[9].geometry.coordinates[1][0][7][0] +# # number | .features[9].geometry.coordinates[1][0][7][1] +# # array | .features[9].geometry.coordinates[1][0][8] +# # number | .features[9].geometry.coordinates[1][0][8][0] +# # number | .features[9].geometry.coordinates[1][0][8][1] +# # array | .features[9].geometry.coordinates[1][0][9] +# # number | .features[9].geometry.coordinates[1][0][9][0] +# # number | .features[9].geometry.coordinates[1][0][9][1] +# # string | .features[9].geometry.type +# # object | .features[9].properties +# # string | .features[9].properties.OUTLINE_TY +# # string | .features[9].properties.SDE_TEXT_L +# # number | .features[9].properties.SEQUENCE_N +# # number | .features[9].properties.SHAPE_Area +# # number | .features[9].properties.SHAPE_Leng +# # number | .features[9].properties.SN_UNIT_AL +# # number | .features[9].properties.SN_UNIT_OU +# # string | .features[9].properties.UNIT_AGT_1 +# # string | .features[9].properties.UNIT_AGT_N +# # string | .features[9].properties.VERSION_DA +# # string | .features[9].type +# # string | .type +# # ./xmlxpath.py -a 241.04s user 13.05s system 93% cpu 4:31.48 total diff --git a/elpa/x-path-walker-20220714.1056/xpathwalker/args.py b/elpa/x-path-walker-20220714.1056/xpathwalker/args.py new file mode 100644 index 00000000..85b02cfb --- /dev/null +++ b/elpa/x-path-walker-20220714.1056/xpathwalker/args.py @@ -0,0 +1,75 @@ +from argparse import ArgumentParser +import os +import sys + +exts_mode = {'.html': "HTML", '.html': 'HTML', '.xml': 'XML', '.json': 'JSON', '.yaml': 'YAML'} + +def parse_args(argv): + """parse command line arguments + + :param argv: + :returns: Processor class + :rtype: + + """ + default_separator = "." + + parser = ArgumentParser(description="Xpath helper") + parser.add_argument("inputfile", + help="Input FILE", type=str) + parser.add_argument("-x", "--xpath", dest='xpath', + help="Returns line number corresponding to xpath from FILE", type=str) + parser.add_argument("-m", "--mode", dest='mode', + help="Language type", type=str, choices=('XML', 'HTML', 'JSON')) + parser.add_argument("-a", dest='verbosity', action="store_true", default=False, + help="Increase verbosity") + parser.add_argument("-M", dest='multiproc', action="store_true", default=False, + help="Use multiple process when possible") + parser.add_argument("-j", dest='use_jq', action="store_true", default=False, + help="JSON: Use jq for processing") + parser.add_argument("-F", dest='separator', default=default_separator, type=str, + help="Path elements separator") + args = parser.parse_args(argv) + + inputfile = args.inputfile + proc = False + if(not os.path.isfile(inputfile)): + sys.exit(1) + + ext = os.path.splitext(inputfile)[1].lower() + + if(args.mode is None): + if ext not in exts_mode.keys(): + print("Unrecognized file format.") + sys.exit(1) + else: + args.mode = exts_mode[ext] + + if(args.mode == 'HTML'): + from xpathwalker.lxml_Processor import HTML_Processor + proc = HTML_Processor() + if args.xpath: + args.xpath = "/"+args.xpath + elif(args.mode == 'XML'): + from xpathwalker.lxml_Processor import XML_Processor + proc = XML_Processor() + if args.xpath: + args.xpath = "/"+args.xpath + elif(args.mode == 'JSON'): + if(args.use_jq): + from xpathwalker.json_jq_Processor import JSON_jq_Processor + proc = JSON_jq_Processor() + else: + from xpathwalker.json_Processor import JSON_Processor + proc = JSON_Processor() + else: + print("Error in arg parsing") + sys.exit(2) + + proc.separator = args.separator + proc.parse_file(inputfile) + + if(args.xpath is not None): + print(proc.get_path_line_number(args.xpath, args.verbosity)) + else: + print("\n".join(proc.list_paths(args.verbosity))) diff --git a/elpa/x-path-walker-20220714.1056/xpathwalker/json_Processor.py b/elpa/x-path-walker-20220714.1056/xpathwalker/json_Processor.py new file mode 100644 index 00000000..df55a323 --- /dev/null +++ b/elpa/x-path-walker-20220714.1056/xpathwalker/json_Processor.py @@ -0,0 +1,98 @@ +import json +from collections.abc import MutableSequence, MutableMapping +from collections import OrderedDict +from xpathwalker.utils import list_compare_idx +from xpathwalker.processor import Processor +from xpathwalker.utils import traverse_and_remove_path,\ + get_dict_from_path, get_class + +########################################################################## +# JSON / Python # +########################################################################## + + +class JSON_Processor(Processor): + file_line_number = 0 + + def isValidJsonShorthandPropertyName(self, key): + if not key[0].isalpha() or not key.isalnum(): + return('["' + key + '"]') + else: + return(self.separator + key) + + + def paths(self, obj, dirs=True, leaves=True, path='', skip=False, allow_empty_string_keys=False): + """Yield all paths of the object. + Arguments: + obj -- An object to get paths from. + Keyword Arguments: + dirs -- Yield intermediate paths. + leaves -- Yield the paths with leaf objects. + path -- A list of keys representing the path. + skip -- Skip special keys beginning with '+'. + """ + if isinstance(obj, MutableMapping): + # Python 3 support + # if PY3: + iteritems = obj.items() + + for (k, v) in iteritems: + if issubclass(k.__class__, (str)): + if (not k) and (not allow_empty_string_keys): + print("Empty string keys not allowed without " + "dpath.options.ALLOW_EMPTY_STRING_KEYS=True") + elif (skip and k[0] == '+'): + continue + newpath = path + self.isValidJsonShorthandPropertyName(str(k)) + # validate(newpath) + if dirs: + yield {newpath: {"class": v.__class__}} + for child in self.paths(v, dirs, leaves, newpath, skip): + yield child + + elif isinstance(obj, MutableSequence): + for (i, v) in enumerate(obj): + newpath = path + "[%s]" % i + if issubclass(i.__class__, int): + newpath = path + "[%d]" % i + if dirs: + yield {newpath: {"class": v.__class__}} + for child in self.paths(obj[i], dirs, leaves, newpath, skip): + yield child + elif leaves: + yield path + [[obj, obj.__class__]] + elif not dirs: + yield path + + def serialize_json(self): + res = OrderedDict() + for x in self.paths(self.parsed, leaves=False): + res.update(x) + return(res) + + def list_paths(self, with_attrs=True): + json_paths = self.serialize_json() + if(with_attrs): + return(["%6s | %s" % (get_class(json_paths[x]["class"]), x) for x in json_paths.keys()]) + else: + return([x for x in json_paths.keys()]) + + def get_path_line_number(self, path, with_attrs=False): + path = path.split("| ")[1] if (with_attrs is True) else path + + orig = self.parsed + path = get_dict_from_path(path, self.separator) + res = traverse_and_remove_path(orig, path) + orig = json.dumps(orig, indent=4).split("\n") + + if(len(orig) != self.file_line_number): + raise ValueError("This json file formatting is not compatible. Please run `python -m json.tool file`") + + with_del = json.dumps(res, indent=4).split("\n") + return(list_compare_idx(orig, with_del) + 1) + + def parse_file(self, file): + with open(file) as f: + self.file_line_number = len(f.readlines()) + f.seek(0) + self.parsed = json.load(f, object_pairs_hook=OrderedDict) diff --git a/elpa/x-path-walker-20220714.1056/xpathwalker/json_jq_Processor.py b/elpa/x-path-walker-20220714.1056/xpathwalker/json_jq_Processor.py new file mode 100644 index 00000000..cb5b5bf0 --- /dev/null +++ b/elpa/x-path-walker-20220714.1056/xpathwalker/json_jq_Processor.py @@ -0,0 +1,146 @@ +import subprocess +import sys +import os +from tempfile import NamedTemporaryFile +from xpathwalker.utils import list_compare_idx +from xpathwalker.processor import Processor + +########################################################################## +# JSON # +########################################################################## + +jq_command = """def safeLookupValue: + if type != "string" then + tostring + else + . + end; +\ +def arrayToLookup: + map(safeLookupValue) + | reduce .[] as $exists ( + {}; + . + { + ($exists): null + } + ); +\ +def lookup(value): + (value | safeLookupValue) as $value + | has($value); +\ +def isWhitelisted(whitelist): + whitelist as $whitelist + | explode + | map( + . as $charCode + | $whitelist + | lookup($charCode) + ) + | all; +\ +def isNumeric: + ("0123456789" | explode | arrayToLookup) as $digits + | isWhitelisted($digits); +\ +def isAlpha: + ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" | explode | arrayToLookup) as $letters + | isWhitelisted($letters); +\ +def isAlphanumeric: + ("0123456789" | explode | arrayToLookup) as $digits + | ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" | explode | arrayToLookup) as $letters + | ("_" | explode | arrayToLookup) as $special + | ($digits + $letters + $special) as $alphanumeric + | isWhitelisted($alphanumeric); +\ +def isValidJsonShorthandPropertyName: + (.[0:1] | isAlpha | not) or (isAlphanumeric | not); +\ +[ + path(..) + | map( + if type == "number" then + ["[",(.|tostring),"]"]|join("") + else + tostring + | if isValidJsonShorthandPropertyName then + "[\\"\\(.)\\"]" + else + . + end + end + ) + | join(".") + | split("." + "[") + | join("[") +] +| unique +| map("." + .) +| .[]""" + +jq_exec = ["jq", "--raw-output"] + +def jq_proc(args): + with NamedTemporaryFile() as f: + try: + proc = subprocess.check_call(args, + stdout=f, + stderr=subprocess.STDOUT) + except subprocess.CalledProcessError: + print(proc.stderr.fseek(0).read().decode('utf-8')) + sys.exit(1) + f.seek(0) + return f.read().decode('utf-8').split('\n') + + +class JSON_jq_Processor(Processor): + file = "" + + def list_paths(self, with_attrs=True, multiproc=False): + if(not os.path.isfile(self.file)): + sys.exit(1) + proc = jq_proc(args=jq_exec + [jq_command, + self.file]) + paths = [x for x in proc if x != ''] + res = [] + if(with_attrs is False): + res = paths + elif with_attrs is True: + if multiproc is False: + for x in paths: + proc = jq_proc(args=jq_exec + ["%s|type" % x, + self.file]) + type = proc[0] + res.append("%6s | %s" % (type[0:6], x)) + else: + def get_types(q, x, file): + proc = jq_proc(args=jq_exec + ["%s|type" % x, + self.file]) + type = proc[0] + q.put("%6s | %s" % (type[0:6], x)) + import queue + import threading + q = queue.PriorityQueue() + for x in paths: + t = threading.Thread(target=get_types, args=(q, x, self.file)) + t. start() + while(q.qsize() > 0): + res.append(q.get()) + return(res) + + def get_path_line_number(self, path, with_attrs=False): + path = path.split("| ")[1] if (with_attrs is True) else path + proc = jq_proc(args=jq_exec + ['.', + self.file]) + orig = proc + proc = jq_proc(args=jq_exec + ['del(%s)' % path, + self.file]) + with_del = proc + return(list_compare_idx(orig, with_del) + 1) + + def parse_file(self, file): + if(not os.path.isfile(file)): + print("File %s: Not Found" % (file)) + sys.exit(1) + self.file = file diff --git a/elpa/x-path-walker-20220714.1056/xpathwalker/lxml_Processor.py b/elpa/x-path-walker-20220714.1056/xpathwalker/lxml_Processor.py new file mode 100644 index 00000000..342e0480 --- /dev/null +++ b/elpa/x-path-walker-20220714.1056/xpathwalker/lxml_Processor.py @@ -0,0 +1,85 @@ +from xpathwalker.processor import Processor +import os +import sys +import lxml.etree +import lxml.html + + +class lxmlProcessor(Processor): + """ [X/HT]ML processor + """ + def list_paths(self, with_attrs=False): + if(not self.parsed): + raise ValueError("No data in parsed") + parsed = self.parsed + res = [] + for el in parsed.xpath("//*"): + if(with_attrs): + if el.keys() is None: + res.append("/%s | %s | %s" % (parsed.getelementpath(el), ",".join(el.keys()))) + else: + res.append("/%s | %s" % (parsed.getelementpath(el), + ",".join(["%s: %s" % (attr, el.get(key=attr)) for attr in el.keys()]))) + else: + res.append("/%s" % (parsed.getelementpath(el))) + return(res) + + def handle_namespace_in_xpath(self, xpath): + closinp = len(xpath.split("}")) + if(closinp > 1 and closinp != len(xpath.split("}"))): + return xpath + import re + import string + insidep = r"(?<={)[^}]*" + namesspaces = re.findall(insidep, xpath) + nsdict = {} + + def get_letters(matchobj): + get_letters.counter += 1 + id = string.ascii_letters[get_letters.counter] + nsdict.update({id: namesspaces[get_letters.counter]}) + return id + ":" + get_letters.counter = -1 + par = re.compile(r"{"+insidep+r"}") + xpath = par.sub(get_letters, xpath) + return (xpath, {"namespaces": nsdict}) + + def get_path_line_number(self, xpath, with_attrs=False): + if(not self.parsed): + raise ValueError("No data in parsed") + + parsed = self.parsed + xpath = xpath.split(" | ")[0] if (with_attrs is True or xpath.find(" | ") > -1) else xpath + res = 0 + matchs = [] + + if(xpath.find("{") > -1): # Handle namespace cases + xpath, args = self.handle_namespace_in_xpath(xpath) + matchs = parsed.xpath(xpath, **args) + else: + matchs = parsed.xpath(xpath) + if(len(matchs) > 0): + res = matchs[0].sourceline + return(res) + +class HTML_Processor(lxmlProcessor): + def parse_file(self, file): + """HTML file parse from lxml + + :param file: file path (string) + :returns: null + :rtype: + + """ + self.parsed = lxml.html.parse(file) + +class XML_Processor(lxmlProcessor): + def parse_file(self, file): + """HTML file parse from lxml + + :param file: file path (string) + :returns: null + :rtype: + + """ + self.parsed = lxml.etree.parse(file) diff --git a/elpa/x-path-walker-20220714.1056/xpathwalker/processor.py b/elpa/x-path-walker-20220714.1056/xpathwalker/processor.py new file mode 100644 index 00000000..9cda9e64 --- /dev/null +++ b/elpa/x-path-walker-20220714.1056/xpathwalker/processor.py @@ -0,0 +1,42 @@ + + +class Processor: + """An abstract object class to handle the parsing/procesing of files + + """ + separator = "." + + def __init__(self): + super(Processor, self).__init__() + + def list_paths(self, parsed, with_attrs=False): + """Return array of path separated by the separator + + :param parsed: A python type object + :param with_attrs: List additional attributes + :returns: array of paths + :rtype: array + + """ + pass + + def get_path_line_number(self, path, with_attrs=False): + """Returns the line number from the file corresponding `path` + + :param path: Path seeked + :param with_attrs: `True` if `path` is formatted with additional attributes + :returns: line numer corresponding to path + :rtype: int + + """ + pass + + def parse_file(self, file): + """Translate the `file` into python object + + :param file: File path + :returns: Nothing. insternal variable updated. + :rtype: + + """ + pass diff --git a/elpa/x-path-walker-20220714.1056/xpathwalker/utils.py b/elpa/x-path-walker-20220714.1056/xpathwalker/utils.py new file mode 100644 index 00000000..b06c0105 --- /dev/null +++ b/elpa/x-path-walker-20220714.1056/xpathwalker/utils.py @@ -0,0 +1,104 @@ +from collections import OrderedDict + +########################################################################## +# Utils # +########################################################################## + +def get_class(obj): + name = obj.__name__ + if(name == "OrderedDict"): + return("object") + elif(name == "NoneType"): + return("null") + return(name) + +def list_compare_idx(list1, list2): + index = 0 + for idx, origline in enumerate(list1): + if(list2[idx] != origline): + if((list2[idx]+",") != origline): + index = idx + break + return(index) + +def split_path(path, separator, inside_special=False): + first_match = '"]' if inside_special else '["' + i = path.find(first_match) + if i != -1 and inside_special is False: + if(path[0:i] != ''): + return (split_path(path[0:i], + separator=separator, + inside_special=False) + + split_path(path[i+len('["'):], + separator=separator, + inside_special=True)) + else: + return (split_path(path[i+len('["'):], + separator=separator, + inside_special=True)) + if i != -1 and inside_special is True: + if(path[i+len('["'):] != ''): + return ([path[:i], "special"],) + split_path(path[i+len('["'):], + separator=separator, + inside_special=False) + else: + return ([path[:i], "special"],) + else: + i = path.find(separator) + if i == -1: + return (path,) + else: + if(i != 0): + return (path[:i],) + split_path(path[i+1:], separator) + else: + return split_path(path[i+1:], separator) + + +def get_dict_from_path(path, separator): + path = split_path(path, separator) + + res = [] + for x in path: + if isinstance(x, str) and x.find("[") == -1: + res.append(x) + elif not isinstance(x, list): + pos = x.find("[") + while pos != -1: + if pos == 0: + i1 = x.find("]") + x1 = int(x[0:i1].replace("[", "", 1).replace("]", "", 1)) + x = x[i1+1:] + res.append(x1) + else: + res.append(x[0:pos]) + x = x[pos:] + pos = x.find("[") + else: + res.append(x[0]) + return(res) + +def traverse_and_remove_path(obj, path=None, match="First"): + if path is None: + path = [] + if isinstance(obj, dict): + res = OrderedDict() + for k, v in obj.items(): + cmatch = False + if(match and len(path) > 0 and path[0] == k): + cmatch = True + res.update({k: traverse_and_remove_path(v, path=path[1:], match=cmatch)}) + if(len(path) == 1 and path[0] in res.keys() and match): + del res[path[0]] + return res + elif isinstance(obj, list): + res = [] + for i, elem in enumerate(obj): + cmatch = False + if(match and len(path) >= 1 and isinstance(path[0], int) and path[0] < len(obj) and i == path[0]): + cmatch = True + res.append(traverse_and_remove_path(elem, path=path[1:], match=cmatch)) + if(len(path) == 1 and isinstance(path[0], int) and path[0] < len(res) and match): + res.pop(path[0]) + return res + else: + return obj # no container, just values (str, int, float) diff --git a/elpa/x-path-walker-20220714.1056/xpathwalker/yaml_Processor.py b/elpa/x-path-walker-20220714.1056/xpathwalker/yaml_Processor.py new file mode 100644 index 00000000..fd28d37e --- /dev/null +++ b/elpa/x-path-walker-20220714.1056/xpathwalker/yaml_Processor.py @@ -0,0 +1,37 @@ +########################################################################## +# YAML # +########################################################################## +import yaml +from xpathwalker.utils import list_compare_idx +from xpathwalker.utils import traverse_and_remove_path, get_dict_from_path, get_class, paths +from collections import OrderedDict +import os + +def parse_yaml(file): + with open(file) as f: + yaml_data = yaml.load(f) + res = OrderedDict() + for x in paths(yaml_data, leaves=False): + res.update(x) + return(res) + +def get_yaml_paths(file, include_type=True): # XXX: ordering is lost + yaml_paths = parse_yaml(file) + if(include_type is True): + return(["%s | %s" % (get_class(yaml_paths[x]['class']), x) for x in yaml_paths.keys()]) + else: + return(yaml_paths.keys()) + +def get_yaml_path_line_python(file, path, include_type=False): + if(not os.path.isfile(file)): + sys.exit(1) + path = path.split("| ")[1] if (include_type is True) else path + orig = "" + with open(file) as f: + orig = yaml.load(f) + path = get_dict_from_path(path) + res = traverse_and_remove_path(orig, path) + yaml_dump_options = {"indent": 4, "default_flow_style": False, "explicit_start": False} + orig = yaml.dump(orig, **yaml_dump_options).split("\n") + with_del = yaml.dump(dict(res), **yaml_dump_options).split("\n") + return(list_compare_idx(orig, with_del) + 1)