Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import sys
2import os
3import pprint
4import inspect
5from logging import getLogger, DEBUG, INFO, WARN, captureWarnings
6from logging import FileHandler, StreamHandler, Formatter
8import json
9import yaml
10import click
11import jsonschema
12from .version import VERSION
13from .drivers import Base, Phantom, Chrome, Firefox, Safari, Edge
14from .drivers import WebKitGTK, Dummy, Ie, Opera, Android, Remote
16drvmap = {
17 "phantom": Phantom,
18 "phantomjs": Phantom,
19 "chrome": Chrome,
20 "firefox": Firefox,
21 "safari": Safari,
22 "edge": Edge,
23 "webkit": WebKitGTK,
24 "dummy": Dummy,
25 "ie": Ie,
26 "opera": Opera,
27 "android": Android,
28 "remote": Remote,
29}
32@click.group(invoke_without_command=True)
33@click.pass_context
34@click.version_option(version=VERSION, prog_name="selenible")
35@click.option("--verbose", is_flag=True)
36@click.option("--quiet", is_flag=True)
37@click.option("--logfile", type=click.Path())
38def cli(ctx, verbose, quiet, logfile):
39 logfmt = "%(asctime)s %(levelname)s %(name)s %(message)s"
40 fmt = Formatter(fmt=logfmt)
41 lg = getLogger()
42 if verbose:
43 lg.setLevel(DEBUG)
44 elif quiet:
45 lg.setLevel(WARN)
46 else:
47 lg.setLevel(INFO)
48 if logfile is not None:
49 newhdl = FileHandler(logfile)
50 newhdl.setFormatter(fmt)
51 lg.addHandler(newhdl)
52 else:
53 newhdl = StreamHandler()
54 newhdl.setFormatter(fmt)
55 lg.addHandler(newhdl)
56 if ctx.invoked_subcommand is None:
57 print(ctx.get_help())
60def loadmodules(driver, extension):
61 def_modules = ["ctrl", "browser", "content", "imageproc"]
62 for i in def_modules:
63 Base.load_modules(i)
64 for ext in extension:
65 Base.load_modules(ext)
66 drvcls = drvmap.get(driver, Phantom)
67 drvcls.load_modules(drvcls.__name__.lower())
68 for ext in extension:
69 drvcls.load_modules(ext)
70 return drvcls
73@cli.command(help="run playbook")
74@click.option("--driver", default="phantom", type=click.Choice(drvmap.keys()))
75@click.option("--extension", "-x", multiple=True)
76@click.option("--step", is_flag=True, default=False)
77@click.option("--screenshot", is_flag=True, default=False)
78@click.option("-e", multiple=True)
79@click.option("--var", type=click.File('r'), required=False)
80@click.argument("input", type=click.File('r'), required=False)
81def run(input, driver, step, screenshot, var, e, extension):
82 captureWarnings(True)
83 drvcls = loadmodules(driver, extension)
84 if input is not None:
85 prog = yaml.safe_load(input)
86 b = drvcls()
87 b.variables["driver"] = driver
88 for k, v in os.environ.items():
89 b.variables[k] = v
90 if var is not None:
91 b.load_vars(var)
92 for x in e:
93 if x.find("=") == -1:
94 b.variables[k] = True
95 else:
96 k, v = x.split("=", 1)
97 try:
98 b.variables[k] = json.loads(v)
99 except Exception:
100 b.variables[k] = v
101 b.step = step
102 b.save_every = screenshot
103 b.run(prog)
104 else:
105 click.echo("show usage: --help")
108@cli.command("list-modules", help="list modules")
109@click.option("--driver", default="phantom", type=click.Choice(drvmap.keys()))
110@click.option("--extension", "-x", multiple=True)
111@click.option("--pattern", default=None)
112def list_modules(driver, extension, pattern):
113 drvcls = loadmodules(driver, extension)
114 from texttable import Texttable
115 table = Texttable()
116 table.set_cols_align(["l", "l"])
117 # table.set_deco(Texttable.HEADER)
118 table.header(["Module", "Description"])
119 mods = drvcls.listmodule()
120 for k in sorted(mods.keys()):
121 if pattern is not None and k.find(pattern) == -1:
122 continue
123 table.add_row([k, mods[k]])
124 print(table.draw())
127@cli.command("dump-schema", help="dump json schema")
128@click.option("--driver", default="phantom", type=click.Choice(drvmap.keys()))
129@click.option("--extension", "-x", multiple=True)
130@click.option("--format", default="yaml", type=click.Choice(["yaml", "json", "python", "pprint"]))
131def dump_schema(driver, extension, format):
132 drvcls = loadmodules(driver, extension)
133 if format == "yaml":
134 yaml.dump(drvcls.schema, sys.stdout, default_flow_style=False)
135 elif format == "json":
136 json.dump(drvcls.schema, fp=sys.stdout, ensure_ascii=False)
137 elif format == "python":
138 print(drvcls.schema)
139 elif format == "pprint":
140 pprint.pprint(drvcls.schema)
141 else:
142 raise Exception("unknown format: %s" % (format))
145@cli.command(help="validate by json schema")
146@click.option("--driver", default="phantom", type=click.Choice(drvmap.keys()))
147@click.option("--extension", "-x", multiple=True)
148@click.argument("input", type=click.File('r'), required=False)
149def validate(driver, extension, input):
150 drvcls = loadmodules(driver, extension)
151 prog = yaml.safe_load(input)
152 try:
153 click.echo("validating...", nl=False)
154 jsonschema.validate(prog, drvcls.schema)
155 click.echo("OK")
156 sys.exit(0)
157 except jsonschema.exceptions.ValidationError as e:
158 click.echo("failed")
159 click.echo(e)
160 sys.exit(1)
163@cli.command("browser-options", help="show browser options")
164@click.option("--driver", default="phantom", type=click.Choice(drvmap.keys()))
165@click.option("--mode", default="example", type=click.Choice(["example", "doc"]))
166def browser_options(driver, mode):
167 drvcls = loadmodules(driver, [])
168 drv = drvcls()
169 if mode == "doc":
170 print(inspect.getdoc(drv.driver.__init__))
171 return
172 opts = drv.get_options()
173 sig = inspect.signature(drv.driver.__init__)
174 res = {}
175 for k, v in sig.parameters.items():
176 res[k] = v.default
177 if opts != {}:
178 res["options"] = {}
179 for f in dir(opts):
180 if f.startswith("__") or f.endswith("__"):
181 continue
182 if callable(getattr(opts, f)):
183 s2 = inspect.signature(getattr(opts, f))
184 res["options"][f] = [str(x) for x in s2.parameters.values()]
185 yaml.dump({"browser_setting": res}, sys.stdout, default_flow_style=False)
188if __name__ == "__main__":
189 cli()