Package: pyshellwrapper
python-shell-cmd-wrapperBased on one of the parts of my bachelor thesis testing framework. Enables to call shell programs seamlessly within Python workflow. Derived from mybachelor thesis.MotivationWhilst working with not very widespread libraries/commands one might struggle using them without proper Python wrapper. Oftentimes nothing fancy is really required, simple abstraction layer is all that is needed. I encountered this very problem in my bachelor thesis when trying to automate image compression pipeline (JPEG2000) using various libraries. This package builds abstraction layer over base set of libraries, at the same time enabling users to easily add new ones.Installationpip install pyshellwrapperRequires Python>=3.7.Introductory NotesTypical CLI use certain naming convension for prompt values.wget google.com -o log.txtwgetis a command,google.comis a parameter and-ois switch/flag. In this package, everything is considered to be a flag.Every library is controlled by a special type ofjsondocument calledblueprint. There, each flag is described and is used as foundation for flag transformation. Structure is going to discussed later.There are three type of flags:fixed,variable,auxiliary. Fixed flags are constant throughout program cycle (input file or logging), variable are meant to be changed (output file or color profile) and auxiliary are simple appended at the end without any transformation. Program cycle is denoted by callingconstruct()method; it can also be tweaked, more on that later. Default behavior is to callset_fixed()once since all flags are directly transformed to output format. However it is possible to callset_fixedmultiple times in program cycle if each flag is set only once, otherwiseValueErroris raised. Variable flags are set byset_variable()in the same manner or list/tuple can be used to specify all options from one place.BlueprintUsed for describing flags/parameters of a command. Each blueprint has two mandatory items:settingsandflags.{"settings":{"commands":["kdu_compress","opj_compress"],"required_flags":["input","output"]}}Here is a typicalsettingsportion of a blueprint. First arerequired_flags. Most of the programs have at least one so it is logical to require specification to avoid unnecessary error at execution.commandsare used for distinguishing between multiple commands in single blueprint.{"flags":{"input":[{"flag":"-i","unifier":null,"format":{"number":1,"preset":"1"}},{"flag":"-i","unifier":null,"format":{"number":1,"preset":"1"}}],}}Individualflagshave following structure. Flag name can by selected at user's will; semantic meaning is advised to be preserved. Its value is array for multiple options, this structure is unchanged not matter how many commands is there to maintain consistency. This example would takeinput="path/to/file"and transform it to-i /path/to/file. Sometimes naming of a flag is not needed. If further manipulation of given flag is desired (variable) set"flag": null, otherwise useset_auxiliary(). Flag can have parameters that are paired by location (directly follows)-flag paramor by certain unifier-flag=param. Format specifies flag parameter;countis used for transformation purposes,presetare predefined format for user convenience.PresetInputTransformed1input="input.txt"-i input.txtq1qinput="input.txt"-i 'input.txt'dq1dqinput="input.txt"-i "input.txt"2,point=(20,45)--point 20,45[2,]point=(20,45)--point [20,45](2,)point=(20,45)--point (20,45){2,}point=(20,45)--point {20,45}Please not that for the purposes of this exampledividerandflagswere not specified, focus on format presets. Moreover, starting from version0.2user can define custom format presets with following structure:"preset":{"left":"?","divider":"-","right":">"}Parameter/s are wrapper from both sides byleftandright, withdividerseparating parts. Previously,unifierwas defined as astringwith option to be left blank manifesting as a space/new list item in final output. Here, onlystringsare allowed to not intefere withlistfunctionality. Number of parts is variable according tonumberinformat.Number vs. ListDistinction might be unclear.numberis a number of parameter's parts that constitute compoment. Input file always has one part (file name), point in 2D space have 2x,yand so on. Parameter can consist of multiple compoment, e.g. start points for a game--points=[0,0],[50,20],[880,50]. Thereforelistis a list of components that are composed of parts (with given number)."points":[{"flag":"--points","unifier":"=","format":{"number":2,"preset":"[2,]"},"list":{"divider":","}}]Example ofpointsflag. Please notelistare to be fully supported in version (0.4).Basic usageLet us look onto basic usage of a command (wget) with predefinedblueprint.PyShellWrapperis main class of package wrapping functionality.frompyshellwrapper.wrapperimportPyShellWrapperwget=PyShellWrapper(blueprint='wget')wget.set_fixed(output='out.html')wget.set_variable(source=['google.com','yahoo.com','bing.com'])forvariantinwget.construct():print(variant)Which results to:['wget','--output_document="out.html"','google.com']['wget','--output_document="out.html"','yahoo.com']['wget','--output_document="out.html"','bing.com']