Skip to content

Instantly share code, notes, and snippets.

@timgluz
Last active December 16, 2015 20:39
Show Gist options
  • Save timgluz/5494080 to your computer and use it in GitHub Desktop.
Save timgluz/5494080 to your computer and use it in GitHub Desktop.
Python Setup parser by using instaparser
(insta/parse parser "install_requires = ['argparse', 'requests>=1.1.0,<1.3.0', 'colorama>=0.9,!=1.1,!=1.2.1,<=1.4.1a3']")
[:PYTHON_SETUP_PARSER
"install_requires"
"="
"["
[:SEQ-OF-REQUIREMENT
[:REQUIREMENT "argparse"]
[:REQUIREMENT
"requests"
[:VERSION_RANGE
[:VERSION_TOKEN [:COMPARATOR ">="] "1.1.0"]
[:VERSION_TOKEN [:COMPARATOR "<"] "1.3.0"]]]
[:REQUIREMENT
"colorama"
[:VERSION_RANGE
[:VERSION_TOKEN [:COMPARATOR ">="] "0.9"]
[:VERSION_TOKEN [:COMPARATOR "!="] "1.1"]
[:VERSION_TOKEN [:COMPARATOR "!="] "1.2.1"]
[:VERSION_TOKEN [:COMPARATOR "<="] "1.4.1a3"]]]]
"]"]
(ns propar.python-setup
(:require [instaparse.core :as insta]))
(def test-data (slurp "resource/examples/setup.py"))
(insta/set-default-output-format! :hiccup)
;;atomic rules
(def whitespace "WHITESPACE = #'\\s*';")
;; rules for parser
(def parser-rules (str "
PYTHON_SETUP_PARSER = 'install_requires' <WHITESPACE> '=' <WHITESPACE> '[' SEQ-OF-REQUIREMENT ']';
SEQ-OF-REQUIREMENT = <WHITESPACE> *{REQUIREMENT ?[<SEQ_SEPARATOR>]};
REQUIREMENT = <APOSTROPHE> MODULE_NAME ?[VERSION_RANGE] <APOSTROPHE>;
MODULE_NAME = (LETTER+ | NUMBER+ | LITERAL_SYMBOL)*;
VERSION_RANGE = (VERSION_TOKEN ?[<SEQ_SEPARATOR>])+;
VERSION_TOKEN = COMPARATOR VERSION_LITERAL;
COMPARATOR = ('<' | '>' | '<=' | '>=' | '==' | '!=');
VERSION_LITERAL = (NUMBER+ | VERSION_SYMBOL)* ?[RELEASE_LITERAL];
RELEASE_LITERAL = (LETTER+ NUMBER*) | 'pre-release' ;
<LETTER> = #'[a-zA-Z]';
<NUMBER> = #'\\d';
<VERSION_SYMBOL> = '.';
<LITERAL_SYMBOL> = '_' | '.';
<SEQ_SEPARATOR> = WHITESPACE ',' WHITESPACE;
<APOSTROPHE> = '\\'' | #'\"' ;
<WHITESPACE> = #'\\s*';"
))
(def parser (insta/parser parser-rules))
(insta/parse parser "install_requires=[]")
(insta/parse parser "install_requires=['a']")
(insta/parse python-setup-parser "install_requires=[\"a\"]")
(insta/parse python-setup-parser "install_requires = ['a'] ")
(insta/parse python-setup-parser "install_requires=['a1']")
(insta/parse python-setup-parser "install_requires=['aa1']")
(insta/parse python-setup-parser "install_requires=['ab_12']")
(insta/parse python-setup-parser "install_requires=['aba234.pdf']")
(insta/parse python-setup-parser "install_requires=['aba234.pdf>0']")
(insta/parse python-setup-parser "install_requires=['aba234.pdf>=0.9']")
(insta/parse python-setup-parser "install_requires=['aba234.pdf>=0.9.1']")
(insta/parse python-setup-parser "install_requires=['aba234.pdf>=0.9.1a']")
(insta/parse python-setup-parser "install_requires=['aba234.pdf>=0.9.1a3']")
(insta/parse python-setup-parser "install_requires=['aba234.pdf>=0.9.1pre-release']")
(insta/parse python-setup-parser "install_requires = ['argparse', 'requests>=1.1.0,<1.3.0', 'colorama']")
(insta/parse parser "install_requires = ['argparse', 'requests>=1.1.0,<1.3.0', 'colorama>=0.9,!=1.1,!=1.2.1,<=1.4.1a3']")
(pprint (transform *1))
(def transformers {:MODULE_NAME str
:VERSION_LITERAL str
:RELEASE_LITERAL str})
(defn transform [parser-output]
(insta/transform transformers parser-output))
@reiz
Copy link

reiz commented May 1, 2013

Looks pretty clean.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment