diff options
author | Michal Minar <miminar@redhat.com> | 2013-11-25 16:30:12 +0100 |
---|---|---|
committer | Michal Minar <miminar@redhat.com> | 2013-11-25 16:30:12 +0100 |
commit | ae309d0a93134f5c0830fe704798d43ec72392b5 (patch) | |
tree | 41a3d20e67524c844943f370efd7e8eef42c3928 /doc | |
parent | 291727ef1cd95cb70d9581df6356a949daef2f7b (diff) | |
download | openlmi-scripts-ae309d0a93134f5c0830fe704798d43ec72392b5.tar.gz openlmi-scripts-ae309d0a93134f5c0830fe704798d43ec72392b5.tar.xz openlmi-scripts-ae309d0a93134f5c0830fe704798d43ec72392b5.zip |
doc: added tutorial page
Diffstat (limited to 'doc')
-rw-r--r-- | doc/Makefile | 16 | ||||
-rw-r--r-- | doc/_static/logicalfile.class.violet | 556 | ||||
-rw-r--r-- | doc/_static/logicalfile.png | bin | 0 -> 32696 bytes | |||
-rw-r--r-- | doc/conf.py | 2 | ||||
-rw-r--r-- | doc/mylf/README.md | 7 | ||||
-rw-r--r-- | doc/mylf/doc/Makefile | 177 | ||||
-rw-r--r-- | doc/mylf/doc/cmdline.rst | 6 | ||||
-rw-r--r-- | doc/mylf/doc/conf.py | 285 | ||||
-rw-r--r-- | doc/mylf/doc/index.rst | 24 | ||||
-rw-r--r-- | doc/mylf/doc/make.bat | 190 | ||||
-rw-r--r-- | doc/mylf/lmi/__init__.py | 27 | ||||
-rw-r--r-- | doc/mylf/lmi/scripts/__init__.py | 27 | ||||
-rw-r--r-- | doc/mylf/lmi/scripts/mylf/__init__.py | 191 | ||||
-rw-r--r-- | doc/mylf/lmi/scripts/mylf/cmd.py | 100 | ||||
-rw-r--r-- | doc/mylf/setup.py | 44 | ||||
-rw-r--r-- | doc/script-development.rst | 10 | ||||
-rw-r--r-- | doc/script-tutorial.rst | 447 |
17 files changed, 2104 insertions, 5 deletions
diff --git a/doc/Makefile b/doc/Makefile index 91bd7f3..0900330 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -2,9 +2,9 @@ # # You can set these variables from the command line. -SPHINXOPTS = +SPHINXOPTS = SPHINXBUILD = sphinx-build -PAPER = +PAPER = BUILDDIR ?= _build PROJECTNAME = OpenLMIScripts COMMANDS_PATH ?= ../commands @@ -17,12 +17,18 @@ PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -n -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +TUTORIAL_SOURCES := mylf/*.md mylf/*.py mylf/lmi/*.py mylf/*/*.py mylf/*/*/*.py \ + mylf/doc/*.py mylf/doc/*.rst mylf/doc/Makefile mylf/doc/_static +TUTORIAL_TARBALL := _static/mylf.tar.gz .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp \ devhelp epub latex latexpdf text man changes linkcheck doctest gettext \ commands.rst -all: html epub latexpdf +export COMMANDS +export INCLUDE_COMMANDS + +all: html help: @echo "Please use \`make <target>' where <target> is one of" @@ -116,8 +122,10 @@ endif figures: +$(TUTORIAL_TARBALL): + tar -czf $@ mylf -html: figures api.rst commands.rst +html: figures api.rst commands.rst $(TUTORIAL_TARBALL) ./build-with-sphinx.sh "$(COMMANDS)" -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." diff --git a/doc/_static/logicalfile.class.violet b/doc/_static/logicalfile.class.violet new file mode 100644 index 0000000..4df1546 --- /dev/null +++ b/doc/_static/logicalfile.class.violet @@ -0,0 +1,556 @@ +<?xml version="1.0" encoding="UTF-8"?> +<java version="1.7.0_60" class="java.beans.XMLDecoder"> + <object class="com.horstmann.violet.ClassDiagramGraph"> + <void method="addNode"> + <object class="com.horstmann.violet.ClassNode" id="ClassNode0"> + <void property="name"> + <void property="text"> + <string>LMI_DataFile</string> + </void> + </void> + </object> + <object class="java.awt.geom.Point2D$Double" id="Point2D$Double0"> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>x</string> + <void method="set"> + <object idref="Point2D$Double0"/> + <double>1016.0</double> + </void> + </void> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>y</string> + <void method="set"> + <object idref="Point2D$Double0"/> + <double>330.0</double> + </void> + </void> + <void method="setLocation"> + <double>1016.0</double> + <double>330.0</double> + </void> + </object> + </void> + <void method="addNode"> + <object class="com.horstmann.violet.ClassNode" id="ClassNode1"> + <void property="attributes"> + <void property="text"> + <string>CIM_Directory REF GroupComponent +CIM_LogicalFile REF PartComponent</string> + </void> + </void> + <void property="name"> + <void property="text"> + <string>LMI_DirectoryContainsFile</string> + </void> + </void> + </object> + <object class="java.awt.geom.Point2D$Double" id="Point2D$Double1"> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>x</string> + <void method="set"> + <object idref="Point2D$Double1"/> + <double>407.0</double> + </void> + </void> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>y</string> + <void method="set"> + <object idref="Point2D$Double1"/> + <double>239.0</double> + </void> + </void> + <void method="setLocation"> + <double>407.0</double> + <double>239.0</double> + </void> + </object> + </void> + <void method="addNode"> + <object class="com.horstmann.violet.ClassNode" id="ClassNode2"> + <void property="name"> + <void property="text"> + <string>LMI_FIFOPipeFile</string> + </void> + </void> + </object> + <object class="java.awt.geom.Point2D$Double" id="Point2D$Double2"> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>x</string> + <void method="set"> + <object idref="Point2D$Double2"/> + <double>742.0</double> + </void> + </void> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>y</string> + <void method="set"> + <object idref="Point2D$Double2"/> + <double>430.0</double> + </void> + </void> + <void method="setLocation"> + <double>742.0</double> + <double>430.0</double> + </void> + </object> + </void> + <void method="addNode"> + <object class="com.horstmann.violet.ClassNode" id="ClassNode3"> + <void property="attributes"> + <void property="text"> + <string>CIM_ManagedElement REF SameElement +CIM_ManagedElement REF SystemElement</string> + </void> + </void> + <void property="name"> + <void property="text"> + <string>LMI_FileIdentity</string> + </void> + </void> + </object> + <object class="java.awt.geom.Point2D$Double" id="Point2D$Double3"> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>x</string> + <void method="set"> + <object idref="Point2D$Double3"/> + <double>676.0</double> + </void> + </void> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>y</string> + <void method="set"> + <object idref="Point2D$Double3"/> + <double>56.0</double> + </void> + </void> + <void method="setLocation"> + <double>676.0</double> + <double>56.0</double> + </void> + </object> + </void> + <void method="addNode"> + <object class="com.horstmann.violet.ClassNode" id="ClassNode4"> + <void property="attributes"> + <void property="text"> + <string>CIM_ManagedElement REF GroupComponent +LMI_UnixDirectory REF PartComponent</string> + </void> + </void> + <void property="name"> + <void property="text"> + <string>LMI_RootDirectory</string> + </void> + </void> + </object> + <object class="java.awt.geom.Point2D$Double" id="Point2D$Double4"> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>x</string> + <void method="set"> + <object idref="Point2D$Double4"/> + <double>128.0</double> + </void> + </void> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>y</string> + <void method="set"> + <object idref="Point2D$Double4"/> + <double>418.0</double> + </void> + </void> + <void method="setLocation"> + <double>128.0</double> + <double>418.0</double> + </void> + </object> + </void> + <void method="addNode"> + <object class="com.horstmann.violet.ClassNode" id="ClassNode5"> + <void property="name"> + <void property="text"> + <string>LMI_SymbolicLink</string> + </void> + </void> + </object> + <object class="java.awt.geom.Point2D$Double" id="Point2D$Double5"> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>x</string> + <void method="set"> + <object idref="Point2D$Double5"/> + <double>923.0</double> + </void> + </void> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>y</string> + <void method="set"> + <object idref="Point2D$Double5"/> + <double>431.0</double> + </void> + </void> + <void method="setLocation"> + <double>923.0</double> + <double>431.0</double> + </void> + </object> + </void> + <void method="addNode"> + <object class="com.horstmann.violet.ClassNode" id="ClassNode6"> + <void property="name"> + <void property="text"> + <string>LMI_UnixDeviceFile</string> + </void> + </void> + </object> + <object class="java.awt.geom.Point2D$Double" id="Point2D$Double6"> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>x</string> + <void method="set"> + <object idref="Point2D$Double6"/> + <double>1020.0</double> + </void> + </void> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>y</string> + <void method="set"> + <object idref="Point2D$Double6"/> + <double>168.0</double> + </void> + </void> + <void method="setLocation"> + <double>1020.0</double> + <double>168.0</double> + </void> + </object> + </void> + <void method="addNode"> + <object class="com.horstmann.violet.ClassNode" id="ClassNode7"> + <void property="name"> + <void property="text"> + <string>LMI_UnixDirectory</string> + </void> + </void> + </object> + <object class="java.awt.geom.Point2D$Double" id="Point2D$Double7"> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>x</string> + <void method="set"> + <object idref="Point2D$Double7"/> + <double>462.0</double> + </void> + </void> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>y</string> + <void method="set"> + <object idref="Point2D$Double7"/> + <double>425.0</double> + </void> + </void> + <void method="setLocation"> + <double>462.0</double> + <double>425.0</double> + </void> + </object> + </void> + <void method="addNode"> + <object class="com.horstmann.violet.ClassNode" id="ClassNode8"> + <void property="attributes"> + <void property="text"> + <string>string FSCreationClassName +string CSName +string CSCreationClassName +string CreationClassName +string FSName +string LFName</string> + </void> + </void> + <void property="name"> + <void property="text"> + <string>LMI_UnixFile</string> + </void> + </void> + </object> + <object class="java.awt.geom.Point2D$Double" id="Point2D$Double8"> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>x</string> + <void method="set"> + <object idref="Point2D$Double8"/> + <double>334.0</double> + </void> + </void> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>y</string> + <void method="set"> + <object idref="Point2D$Double8"/> + <double>36.0</double> + </void> + </void> + <void method="setLocation"> + <double>334.0</double> + <double>36.0</double> + </void> + </object> + </void> + <void method="addNode"> + <object class="com.horstmann.violet.ClassNode" id="ClassNode9"> + <void property="name"> + <void property="text"> + <string>LMI_UnixSocket</string> + </void> + </void> + </object> + <object class="java.awt.geom.Point2D$Double" id="Point2D$Double9"> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>x</string> + <void method="set"> + <object idref="Point2D$Double9"/> + <double>1015.0</double> + </void> + </void> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>y</string> + <void method="set"> + <object idref="Point2D$Double9"/> + <double>254.0</double> + </void> + </void> + <void method="setLocation"> + <double>1015.0</double> + <double>254.0</double> + </void> + </object> + </void> + <void method="addNode"> + <object class="com.horstmann.violet.ClassNode" id="ClassNode10"> + <void property="attributes"> + <void property="text"> + <string>string CreationClassName +string Name</string> + </void> + </void> + <void property="name"> + <void property="text"> + <string>CIM_ComputerSystem</string> + </void> + </void> + </object> + <object class="java.awt.geom.Point2D$Double" id="Point2D$Double10"> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>x</string> + <void method="set"> + <object idref="Point2D$Double10"/> + <double>180.0</double> + </void> + </void> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>y</string> + <void method="set"> + <object idref="Point2D$Double10"/> + <double>245.0</double> + </void> + </void> + <void method="setLocation"> + <double>180.0</double> + <double>245.0</double> + </void> + </object> + </void> + <void method="addNode"> + <object class="com.horstmann.violet.ClassNode" id="ClassNode11"> + <void property="attributes"> + <void property="text"> + <string>string FSCreationClassName +string Name +string CSName +string CSCreationClassName +string CreationClassName +string FSName</string> + </void> + </void> + <void property="name"> + <void property="text"> + <string>CIM_LogicalFile</string> + </void> + </void> + </object> + <object class="java.awt.geom.Point2D$Double" id="Point2D$Double11"> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>x</string> + <void method="set"> + <object idref="Point2D$Double11"/> + <double>707.0</double> + </void> + </void> + <void class="java.awt.geom.Point2D$Double" method="getField"> + <string>y</string> + <void method="set"> + <object idref="Point2D$Double11"/> + <double>209.0</double> + </void> + </void> + <void method="setLocation"> + <double>707.0</double> + <double>209.0</double> + </void> + </object> + </void> + <void method="connect"> + <object class="com.horstmann.violet.ClassRelationshipEdge"> + <void property="bentStyle"> + <object class="com.horstmann.violet.BentStyle" field="HVH"/> + </void> + <void property="endArrowHead"> + <object class="com.horstmann.violet.ArrowHead" field="V"/> + </void> + <void property="endLabel"> + <string>1</string> + </void> + </object> + <object idref="ClassNode4"/> + <object idref="ClassNode10"/> + </void> + <void method="connect"> + <object class="com.horstmann.violet.ClassRelationshipEdge"> + <void property="bentStyle"> + <object class="com.horstmann.violet.BentStyle" field="HVH"/> + </void> + <void property="endArrowHead"> + <object class="com.horstmann.violet.ArrowHead" field="V"/> + </void> + <void property="endLabel"> + <string>1</string> + </void> + </object> + <object idref="ClassNode4"/> + <object idref="ClassNode7"/> + </void> + <void method="connect"> + <object class="com.horstmann.violet.ClassRelationshipEdge"> + <void property="bentStyle"> + <object class="com.horstmann.violet.BentStyle" field="VHV"/> + </void> + <void property="endArrowHead"> + <object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/> + </void> + </object> + <object idref="ClassNode5"/> + <object idref="ClassNode11"/> + </void> + <void method="connect"> + <object class="com.horstmann.violet.ClassRelationshipEdge"> + <void property="bentStyle"> + <object class="com.horstmann.violet.BentStyle" field="VHV"/> + </void> + <void property="endArrowHead"> + <object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/> + </void> + </object> + <object idref="ClassNode6"/> + <object idref="ClassNode11"/> + </void> + <void method="connect"> + <object class="com.horstmann.violet.ClassRelationshipEdge"> + <void property="bentStyle"> + <object class="com.horstmann.violet.BentStyle" field="VHV"/> + </void> + <void property="endArrowHead"> + <object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/> + </void> + </object> + <object idref="ClassNode2"/> + <object idref="ClassNode11"/> + </void> + <void method="connect"> + <object class="com.horstmann.violet.ClassRelationshipEdge"> + <void property="bentStyle"> + <object class="com.horstmann.violet.BentStyle" field="VHV"/> + </void> + <void property="endArrowHead"> + <object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/> + </void> + </object> + <object idref="ClassNode9"/> + <object idref="ClassNode11"/> + </void> + <void method="connect"> + <object class="com.horstmann.violet.ClassRelationshipEdge"> + <void property="bentStyle"> + <object class="com.horstmann.violet.BentStyle" field="VHV"/> + </void> + <void property="endArrowHead"> + <object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/> + </void> + </object> + <object idref="ClassNode0"/> + <object idref="ClassNode11"/> + </void> + <void method="connect"> + <object class="com.horstmann.violet.ClassRelationshipEdge"> + <void property="bentStyle"> + <object class="com.horstmann.violet.BentStyle" field="HVH"/> + </void> + <void property="endArrowHead"> + <object class="com.horstmann.violet.ArrowHead" field="V"/> + </void> + <void property="endLabel"> + <string>1</string> + </void> + </object> + <object idref="ClassNode3"/> + <object idref="ClassNode8"/> + </void> + <void method="connect"> + <object class="com.horstmann.violet.ClassRelationshipEdge"> + <void property="bentStyle"> + <object class="com.horstmann.violet.BentStyle" field="HVH"/> + </void> + <void property="endArrowHead"> + <object class="com.horstmann.violet.ArrowHead" field="V"/> + </void> + <void property="endLabel"> + <string>1</string> + </void> + </object> + <object idref="ClassNode3"/> + <object idref="ClassNode11"/> + </void> + <void method="connect"> + <object class="com.horstmann.violet.ClassRelationshipEdge"> + <void property="endArrowHead"> + <object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/> + </void> + </object> + <object idref="ClassNode7"/> + <object idref="ClassNode11"/> + </void> + <void method="connect"> + <object class="com.horstmann.violet.ClassRelationshipEdge"> + <void property="bentStyle"> + <object class="com.horstmann.violet.BentStyle" field="HVH"/> + </void> + <void property="endArrowHead"> + <object class="com.horstmann.violet.ArrowHead" field="V"/> + </void> + <void property="endLabel"> + <string>1</string> + </void> + </object> + <object idref="ClassNode1"/> + <object idref="ClassNode7"/> + </void> + <void method="connect"> + <object class="com.horstmann.violet.ClassRelationshipEdge"> + <void property="bentStyle"> + <object class="com.horstmann.violet.BentStyle" field="HVH"/> + </void> + <void property="endArrowHead"> + <object class="com.horstmann.violet.ArrowHead" field="V"/> + </void> + <void property="endLabel"> + <string>*</string> + </void> + </object> + <object idref="ClassNode1"/> + <object idref="ClassNode11"/> + </void> + </object> +</java> diff --git a/doc/_static/logicalfile.png b/doc/_static/logicalfile.png Binary files differnew file mode 100644 index 0000000..04633d1 --- /dev/null +++ b/doc/_static/logicalfile.png diff --git a/doc/conf.py b/doc/conf.py index fa61860..424b37d 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -74,7 +74,7 @@ release = '0.2.1' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = [] +exclude_patterns = ['mylf/*'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None diff --git a/doc/mylf/README.md b/doc/mylf/README.md new file mode 100644 index 0000000..b3e7107 --- /dev/null +++ b/doc/mylf/README.md @@ -0,0 +1,7 @@ +MyLF +==== +A complete source for step-by-step tutorial hosted on +https://fedorahosted.org/openlmi/wiki/scripts/tutorial. + +It provides similar functionality as `logicalfile` script and operates upon the +same set of providers. diff --git a/doc/mylf/doc/Makefile b/doc/mylf/doc/Makefile new file mode 100644 index 0000000..5efe803 --- /dev/null +++ b/doc/mylf/doc/Makefile @@ -0,0 +1,177 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build +COMMAND_NAME := mylf + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext cmdregen cmdline.generated + +help: + @echo "Please use \`make <target>' where <target> is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " " + @echo " cmdregen to regenerate cmdline.generated with actual content from installed lmi help" + +cmdregen: cmdline.generated + +cmdline.generated: + if ! python -c 'import lmi.scripts.$(COMMAND_NAME)' >/dev/null; then \ + echo "Please install install the command library first." >&2; \ + exit 1; \ + fi + ( \ + echo ".."; \ + echo " !!!!!!!!!"; \ + echo -n " This is generated file. Use 'make cmdregen' to regenerate it"; \ + echo " from installed 'lmi help <CMD_NAME>'"; \ + echo " !!!!!!!!!"; \ + echo ; \ + for i in `sed -n '/entry_points/,/)/p' ../setup.py | \ + sed -n "s/\s*,\?['\"]\s*\([a-z-]\+\)\s*=.*/\1/p"`; do \ + lmi help $$i | python ../../../tools/help2rst $$i | \ + tr -d '\033' |sed 's/..1034h//'; \ + done \ + ) > $@ + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/OpenLMIMyLFscripts.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/OpenLMIMyLFscripts.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/OpenLMIMyLFscripts" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/OpenLMIMyLFscripts" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/doc/mylf/doc/cmdline.rst b/doc/mylf/doc/cmdline.rst new file mode 100644 index 0000000..ae96494 --- /dev/null +++ b/doc/mylf/doc/cmdline.rst @@ -0,0 +1,6 @@ +LMI command line reference +========================== +.. + Write some description here. + +.. include:: cmdline.generated diff --git a/doc/mylf/doc/conf.py b/doc/mylf/doc/conf.py new file mode 100644 index 0000000..69ac554 --- /dev/null +++ b/doc/mylf/doc/conf.py @@ -0,0 +1,285 @@ +# -*- coding: utf-8 -*- +# +# OpenLMI MyLF scripts documentation build configuration file, created by +# sphinx-quickstart on Wed Oct 2 08:58:25 2013. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.pngmath', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'OpenLMI MyLF scripts' +copyright = u'2013, Michal' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0.0.1' +# The full version, including alpha/beta/rc tags. +release = '0.0.1' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# "<project> v<release> documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a <link> tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'OpenLMIMyLFscriptsdoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'OpenLMIMyLFscripts.tex', u'OpenLMI MyLF scripts Documentation', + u'Michal', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'openlmimylfscripts', u'OpenLMI MyLF scripts Documentation', + [u'Michal'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------------ + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'OpenLMIMyLFscripts', u'OpenLMI MyLF scripts Documentation', + u'Michal', 'OpenLMIMyLFscripts', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + + +# -- Options for Epub output --------------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = u'OpenLMI MyLF scripts' +epub_author = u'Michal' +epub_publisher = u'Michal' +epub_copyright = u'2013, Michal' + +# The language of the text. It defaults to the language option +# or en if the language is not set. +#epub_language = '' + +# The scheme of the identifier. Typical schemes are ISBN or URL. +#epub_scheme = '' + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +#epub_identifier = '' + +# A unique identification for the text. +#epub_uid = '' + +# A tuple containing the cover image and cover page html template filenames. +#epub_cover = () + +# HTML files that should be inserted before the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_pre_files = [] + +# HTML files shat should be inserted after the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_post_files = [] + +# A list of files that should not be packed into the epub file. +#epub_exclude_files = [] + +# The depth of the table of contents in toc.ncx. +#epub_tocdepth = 3 + +# Allow duplicate toc entries. +#epub_tocdup = True diff --git a/doc/mylf/doc/index.rst b/doc/mylf/doc/index.rst new file mode 100644 index 0000000..dc7a55f --- /dev/null +++ b/doc/mylf/doc/index.rst @@ -0,0 +1,24 @@ +.. OpenLMI MyLF scripts documentation master file, created by + sphinx-quickstart on Wed Oct 2 08:58:25 2013. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to OpenLMI MyLF scripts's documentation! +================================================ + +Contents: + +.. toctree:: + :maxdepth: 2 + + cmdline + python + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/doc/mylf/doc/make.bat b/doc/mylf/doc/make.bat new file mode 100644 index 0000000..4fc6844 --- /dev/null +++ b/doc/mylf/doc/make.bat @@ -0,0 +1,190 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^<target^>` where ^<target^> is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\OpenLMIMyLFscripts.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\OpenLMIMyLFscripts.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +:end diff --git a/doc/mylf/lmi/__init__.py b/doc/mylf/lmi/__init__.py new file mode 100644 index 0000000..97eeaa5 --- /dev/null +++ b/doc/mylf/lmi/__init__.py @@ -0,0 +1,27 @@ +# Copyright (c) 2013, Red Hat, Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of the FreeBSD Project. +__import__('pkg_resources').declare_namespace(__name__) diff --git a/doc/mylf/lmi/scripts/__init__.py b/doc/mylf/lmi/scripts/__init__.py new file mode 100644 index 0000000..97eeaa5 --- /dev/null +++ b/doc/mylf/lmi/scripts/__init__.py @@ -0,0 +1,27 @@ +# Copyright (c) 2013, Red Hat, Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of the FreeBSD Project. +__import__('pkg_resources').declare_namespace(__name__) diff --git a/doc/mylf/lmi/scripts/mylf/__init__.py b/doc/mylf/lmi/scripts/mylf/__init__.py new file mode 100644 index 0000000..16c83d8 --- /dev/null +++ b/doc/mylf/lmi/scripts/mylf/__init__.py @@ -0,0 +1,191 @@ +# Copyright (c) 2013, Red Hat, Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of the FreeBSD Project. +import os + +from lmi.shell import LMIInstance, LMIInstanceName +from lmi.scripts.common import errors +from lmi.scripts.common import get_logger + +LOG = get_logger(__name__) + +def logical_file_type_name(file_identity): + """ + Get a name of file type for supplied instance of ``CIM_LogicalFile``. + """ + namemap = { + 'lmi_datafile' : 'file', + 'lmi_unixdevicefile' : 'device', + 'lmi_unixdirectory' : 'directory', + 'lmi_fifopipefile' : 'fifo', + 'lmi_symboliclink' : 'symlink', + 'lmi_unixsocket' : 'socket' + } + try: + return namemap[file_identity.classname.lower()] + except KeyError: + LOG().warn('unhandled logical file class "%s"', + file_identity.classname) + return 'unknown' + +def permission_string(file_identity): + """ + Make a ls-like permission string for supplied instance of + ``CIM_LogicalFile``. + """ + return ''.join(l if getattr(file_identity, a) else '-' + for l, a in zip('rwx', ('Readable', 'Writeable', 'Executable'))) + +def get_computer_system(ns): + """ + :returns: Instance of ``Linux_ComputerSystem``. + """ + if not hasattr(get_computer_system, 'instance'): + get_computer_system.instance = ns.Linux_ComputerSystem.first_instance() + return get_computer_system.instance + +def get_unix_file_instance(ns, path, dereference=False): + """ + :param boolean dereference: Whether to follow symbolic links + :returns: Instance of ``LMI_UnixFile`` corresponding to given *path*. + """ + cs = get_computer_system(ns) + uf_name = ns.LMI_UnixFile.new_instance_name({ + 'CSCreationClassName' : cs.classname, + 'CSName' : cs.name, + 'LFName' : path, + 'LFCreationClassName' : 'ignored', + 'FSCreationClassName' : 'ignored', + 'FSName' : 'ignored', + }) + try: + uf = uf_name.to_instance() + if dereference: + lf = get_logical_file_instance(ns, uf, False) + if logical_file_type_name(lf) == 'symlink': + try: + target = lf.TargetFile + if not os.path.isabs(target): + target = os.path.abspath( + os.path.join(os.path.dirname(lf.Name), target)) + # recursively try to dereference + uf = get_unix_file_instance(ns, target, dereference) + except Exception as err: + LOG.warn('failed to get link target "%s": %s', + lf.TargetLink, err) + return uf + except: + raise errors.LmiFailed('No such file or directory: "%s"' % path) + +def get_logical_file_instance(ns, file_ident, dereference=False): + """ + Get an instance of ``CIM_LogicalFile`` corresponding to given file + identity. + + :param file_ident: Either a file path or an instance of ``LMI_UnixFile``. + :param boolean dereference: Whether to follow symbolic links + """ + if isinstance(file_ident, basestring): + uf = get_unix_file_instance(ns, file_ident, dereference) + elif isinstance(file_ident, LMIInstanceName): + uf = file_ident.to_instance() + else: + uf = file_ident + return uf.first_associator(AssocClass='LMI_FileIdentity') + +def make_directory_instance_name(ns, directory): + """ + Retrieve object path of a directory. + + :type directory: string + :param directory: Full path to the directory. + :rtype: :py:class:`lmi.shell.LMIInstanceName` + """ + if directory != '/': + directory = directory.rstrip('/') + cs = get_computer_system(ns) + return ns.LMI_UnixDirectory.new_instance_name( + { 'CSCreationClassName' : cs.classname + , 'CSName' : cs.name + , 'CreationClassName' : 'LMI_UnixDirectory' + , 'FSCreationClassName' : 'LMI_LocalFileSystem' + , 'FSName' : '' + , 'Name' : directory}) + +def get_directory_instance(ns, directory): + """ + Retrieve instance of `LMI_UnixDirectory`. + + :type directory: string of :py:class:`lmi.shell.LMIInstanceName` + :param directory: Full path to the directory or its instance name. + :rtype: :py:class:`lmi.shell.LMIInstance` + """ + if isinstance(directory, basestring): + directory = make_directory_instance_name(ns, directory) + if isinstance(directory, LMIInstanceName): + directory = directory.to_instance() + return directory + +def list_directory(ns, directory, file_type='any'): + """ + Yields instances of ``CIM_LogicalFile`` representing direct children of the + given directory. + + :param directory: Either a file path or an instance of + ``LMI_UnixDirectory``. + :param file_type: Filter of files made by checking their type. One of: :: + + {'any', 'file', 'device', 'directory', 'fifo', 'symlink', 'socket'} + """ + def _generate_children(): + for child in get_directory_instance(ns, directory).associators( + AssocClass='LMI_DirectoryContainsFile', + Role='GroupComponent', + ResultRole='PartComponent'): + if ( file_type and file_type != 'any' + and logical_file_type_name(child) != file_type): + continue + yield child + return sorted(_generate_children(), key=lambda i: i.Name) + +def create_directory(ns, directory): + """ + Create a directory. + + :type directory: string + :param directory: Full path to the directory. + """ + ns.LMI_UnixDirectory.create_instance( + make_directory_instance_name(ns, directory).path.keybindings) + +def delete_directory(ns, directory): + """ + Delete an empty directory. + + :param directory: Either a file path or an instance of + ``LMI_UnixDirectory``. + """ + get_directory_instance(ns, directory).delete() diff --git a/doc/mylf/lmi/scripts/mylf/cmd.py b/doc/mylf/lmi/scripts/mylf/cmd.py new file mode 100644 index 0000000..1aa0242 --- /dev/null +++ b/doc/mylf/lmi/scripts/mylf/cmd.py @@ -0,0 +1,100 @@ +# Copyright (c) 2013, Red Hat, Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of the FreeBSD Project. + +""" +Read informations about file system structure. + +Usage: + %(cmd)s list [options] <directory> + %(cmd)s show [-L] <file> + %(cmd)s create <directory> + %(cmd)s delete <directory> + +Options: + -t --type <type> Filter listed files by their type. One of: + any, file, device, directory, fifo, symlink, socket. + Defaults to any. + -L --dereference Causes symlink to be followed. +""" + +from lmi.scripts import mylf +from lmi.scripts.common import command +from lmi.scripts.common import errors + +class Show(command.LmiLister): + COLUMNS = ('Attribute', 'Value') + + def transform_options(self, options): + options['<path>'] = options.pop('<file>') + + def execute(self, ns, path, _dereference): + uf = mylf.get_unix_file_instance(ns, path, _dereference) + lf = mylf.get_logical_file_instance(ns, uf, _dereference) + return [ + ('Path' , lf.Name), + ('Type' , mylf.logical_file_type_name(lf)), + ('User ID' , uf.UserID), + ('Group ID' , uf.GroupID), + ('Size' , lf.FileSize), + ('Permissions' , mylf.permission_string(lf)) + ] + +class List(command.LmiInstanceLister): + CALLABLE = mylf.list_directory + PROPERTIES = ( + 'Name', + ('Type', mylf.logical_file_type_name), + ('Permissions', mylf.permission_string), + ('Size', 'FileSize')) + + def verify_options(self, options): + if ( options['--type'] is not None + and not options['--type'].lower() in { + 'any', 'file', 'directory', 'symlink', 'dev', 'socket', 'fifo'}): + raise errors.LmiInvalidOptions( + 'unsupported type: %s' % options['--type']) + + def transform_options(self, options): + file_type = options.pop('--type') + if file_type is None: + file_type = 'any' + options['file-type'] = file_type + +class Create(command.LmiCheckResult): + EXPECT = None + CALLABLE = mylf.create_directory + +class Delete(command.LmiCheckResult): + EXPECT = None + CALLABLE = mylf.delete_directory + +MyLF = command.register_subcommands('MyLF', __doc__, + { 'show' : Show + , 'list' : List + , 'create' : Create + , 'delete' : Delete + }) diff --git a/doc/mylf/setup.py b/doc/mylf/setup.py new file mode 100644 index 0000000..9281962 --- /dev/null +++ b/doc/mylf/setup.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- + +from setuptools import setup + +try: + long_description = open('README.md', 'rt').read() +except IOError: + long_description = '' + +setup( + name='openlmi-scripts-mylf', + version='0.0.1', + description='OpenLMI scripts for LogicalFile profile', + long_description=long_description, + author=u'Michal', + author_email='Minar', + url='https://github.com/openlmi/openlmi-mylf', + download_url='https://github.com/openlmi/openlmi-mylf/tarball/master', + platforms=['Any'], + license="BSD", + classifiers=[ + 'License :: OSI Approved :: BSD License', + 'Operating System :: POSIX :: Linux', + 'Topic :: System :: Systems Administration', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Intended Audience :: Developers', + 'Environment :: Console', + ], + + install_requires=['openlmi-scripts'], + + namespace_packages=['lmi', 'lmi.scripts'], + packages=['lmi', 'lmi.scripts', 'lmi.scripts.mylf'], + include_package_data=True, + + entry_points={ + 'lmi.scripts.cmd': [ + 'mylf = lmi.scripts.mylf.cmd:MyLF', + ], + }, + ) diff --git a/doc/script-development.rst b/doc/script-development.rst index bb4b904..82eca29 100644 --- a/doc/script-development.rst +++ b/doc/script-development.rst @@ -447,6 +447,14 @@ These pages provide more details of some aspects: command-classes command-properties +Tutorial +-------- + +.. toctree:: + :maxdepth: 2 + + script-tutorial + ------------------------------------------------------------------------------- .. seealso:: @@ -457,6 +465,8 @@ These pages provide more details of some aspects: :ref:`command_properties` + :ref:`script_tutorial` + ------------------------------------------------------------------------------- .. [#] Described by a POSIX. diff --git a/doc/script-tutorial.rst b/doc/script-tutorial.rst new file mode 100644 index 0000000..15d6214 --- /dev/null +++ b/doc/script-tutorial.rst @@ -0,0 +1,447 @@ +.. _script_tutorial: + +Script Tutorial +=============== + +This is a step-by-step tutorial on developing script library for +*OpenLMI* providers. + +Required knowledge +------------------ + +You should be familiar with terms like *CIM*, *cimom*, *schema*, +*provider*, *DMTF* profile. +`This <http://fedorahosted.org/openlmi/wiki/ProviderTutorialIntroduction>`_ +short tutorial should be enough to get you started. + +You should also be familiar with scripting in *python* and +`lmishell <http://www.openlmi.org/using_lmishell>`_ which we use heavily +in snippets below. + +Preparation +----------- + +This tutorial assumes you have ``tog-pegasus`` *cimom* up and running +with ``openlmi-logicalfile`` providers installed and registered on +remote host. We will connect to it from client machine which needs the +following installed: + +* ``openlmi-python-base`` +* ``openlmi-tools`` +* ``openlmi-scripts`` + +Installing python dependencies +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For the first two items you may use standard rpms build for Fedora. The +first one is available from ''OpenLMI Nightly'' repository having the +newest builds: + +.. code-block:: sh + + cat > /etc/yum.repos.d/openlmi-nightly.repo + [openlmi-nightly] + name=openlmi-nightly + baseurl=http://openlmi-rnovacek.rhcloud.com/rpm/rawhide/ + gpgcheck=0 + enabled = 1 + ^D + +And then run: + +.. code-block:: sh + + yum install openlmi-python-base openlmi-tools + +Or you may install them to your user directory as python eggs with +``pip``: + +.. code-block:: sh + + pip install openlmi-python openlmi-tools + +The last one can only be installed with ``pip``: + +.. code-block:: sh + + pip install openlmi-scripts + +Or directly from git repository (viz `below <#install_from_git>`_). + +Setting up environment +~~~~~~~~~~~~~~~~~~~~~~ + +We'll stick to the process described +`here <https://github.com/openlmi/openlmi-scripts#developing-lmi-scripts>`_ +that let us develop quickly without the need to reinstall anything while +making changes. + +First let's check out our ``openlmi-scripts`` repository: + +:: + + git clone https://github.com/openlmi/openlmi-scripts.git + cd openlmi-scripts + +Optionally we may install ``openlmi-scripts`` to user directory if not +having done yet: + +.. code-block:: sh + + python setup.py install --user + +Then let's set up the workspace directory: + +.. code-block:: sh + + WSP=~/.python_workspace + mkdir $WSP + # may be added to `$HOME/.profile` or `$HOME/.bashrc` + export PYTHONPATH=$WSP:$PYTHONPATH + export PATH="$PATH:$WSP" + +Making our command structure +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We'll use provided ``commands/make_new.py`` script to create the basic +structure and ``setup.py`` file: + +.. code-block:: sh + + cd commands + # this will ask us additional questions used to create setup.py file + ./make_new.py mylf + +Because a script implementation for ``OpenLMI LogicalFile`` profile is +already present in upstream repository (in ``commands/logicalfile``), we +need to name our library distinctly (e.g. ``mylf``). + +Following structure should be created: + +:: + + mylf + ├── doc + │ ├── _build + │ ├── cmdline.rst + │ ├── conf.py + │ ├── err.log + │ ├── index.rst + │ ├── make.bat + │ ├── _static + │ └── _templates + ├── lmi + │ ├── __init__.py + │ └── scripts + │ ├── __init__.py + │ └── mylf + │ ├── cmd.py + │ └── __init__.py + ├── README.md + └── setup.py + +We should check that everything matches in ``mylf/setup.py`` and correct +any shortcomings. + +OpenLMI LogicalFile introduction +-------------------------------- + +*OpenLMI LogicalFile* is a CIM provider which provides a way to read +information about files and directories. The provider also allows to +traverse the file hierarchy, create and remove empty directories. + +.. figure:: _static/logicalfile.png + :align: center + :alt: LogicalFile model + + LogicalFile model + +It consists mainly of few specializations of ``CIM_LogicalFile`` +representing any type of file on filesystem, ``LMI_UnixFile`` holding +unix specific information for each such file and association classes +between them. ``CIM_LogicalFile`` has following key properties inherited +by ``LMI_*`` subclasses above: + +* **Name** +* **CSName** +* **CSCreationClassName** +* ``FSCreationClassName`` +* ``CreationClassName`` +* ``FSName`` + +Only those shown in **bold** are mandatory. Others are ignored when +requesting an instance of ``CIM_LogicalFile``. This applies also to +``LMI_UnixFile`` with **Name** being replaced with **LFName**. None of +the presented classes supports enumeration of instances. Only references +can be obtained. + +With ``CreateInstance()`` and ``DeleteInstance()`` calls issued on +class/object of ``LMI_UnixDirectory`` we are able to create and delete +directories. + +Writing usage string +~~~~~~~~~~~~~~~~~~~~ + +Usage string is a module's documentation, help message and a +prescription for command line parser all-in-one. Writing it is pretty +straightforward. Let's put it to ``mylf/lmi/scripts/mylf/cmd.py``: + +:: + + """ + Read informations about file system structure. + + Usage: + %(cmd)s list [options] <directory> + %(cmd)s show [-L] <file> + %(cmd)s create <directory> + %(cmd)s delete <directory> + + Options: + -t --type <type> Filter listed files by their type. One of: + any, file, device, directory, fifo, symlink, socket. + Defaults to any. + -L --dereference Causes symlink to be followed. + """ + +The first line provides a short description shown in help of ``lmi`` +meta-command for its registered subcommand. Text under ``Usage:`` and +``Options:`` are parsed by ``doctopt``. Please refer to its +documentation at http://docopt.org for more information. + +**Note** the ``%(cmd)s`` string which needs to be present instead of +``lmi mylf`` or similar command names. + +Let's add one more snippet so we can test it: + +:: + + from lmi.scripts.common import command + + MyLF = command.register_subcommands('MyLF', __doc__, {}) + +This creates a command multiplexer without any children (we'll add them +later). + +And finally let's modify our ``mylf/setup.py`` by adding entry point: + +:: + + entry_points={ + 'lmi.scripts.cmd': [ + 'mylf = lmi.scripts.mylf.cmd:MyLF', + ], + } + +Now we can install it and test it: + +.. code-block:: sh + + # make sure the $WSP is in $PYTHONPATH + python mylf/stup.py develop --install-dir=$WSP + lmi help + lmi help mylf + +We should be able to see the usage string we've written. + +Implementing ``list`` +~~~~~~~~~~~~~~~~~~~~~ + +Most of neccessary functionality has been implemented in previous +snippet for the ``show`` command. Following snippet is enough to +generate all the files in directory. Put it again to +``mylf/lmi/scripts/mylf/__init__.py``. + +:: + + def make_directory_instance_name(ns, directory): + """ + Retrieve object path of a directory. + + :type directory: string + :param directory: Full path to the directory. + :rtype: :py:class:`lmi.shell.LMIInstanceName` + """ + if directory != '/': + directory = directory.rstrip('/') + cs = get_computer_system(ns) + return ns.LMI_UnixDirectory.new_instance_name( + { 'CSCreationClassName' : cs.classname + , 'CSName' : cs.name + , 'CreationClassName' : 'LMI_UnixDirectory' + , 'FSCreationClassName' : 'LMI_LocalFileSystem' + , 'FSName' : '' + , 'Name' : directory}) + + def get_directory_instance(ns, directory): + """ + Retrieve instance of `LMI_UnixDirectory`. + + :type directory: string of :py:class:`lmi.shell.LMIInstanceName` + :param directory: Full path to the directory or its instance name. + :rtype: :py:class:`lmi.shell.LMIInstance` + """ + if isinstance(directory, basestring): + directory = make_directory_instance_name(ns, directory) + if isinstance(directory, LMIInstanceName): + directory = directory.to_instance() + return directory + + def list_directory(ns, directory, file_type='any'): + """ + Yields instances of ``CIM_LogicalFile`` representing direct children of the + given directory. + + :param directory: Either a file path or an instance of + ``LMI_UnixDirectory``. + :param file_type: Filter of files made by checking their type. One of: :: + + {'any', 'file', 'device', 'directory', 'fifo', 'symlink', 'socket'} + """ + def _generate_children(): + for child in get_directory_instance(ns, directory).associators( + AssocClass='LMI_DirectoryContainsFile', + Role='GroupComponent', + ResultRole='PartComponent'): + if ( file_type and file_type != 'any' + and logical_file_type_name(child) != file_type): + continue + yield child + return sorted(_generate_children(), key=lambda i: i.Name) + +Note the ``associators()`` call on ``LMI_UnixDirectory`` instance. It +enumerates all ``CIM_LogicalFile`` instances that are referenced by +``LMI_DirectoryContainsFile`` associations. These represent a relation +of parent directory and its direct children. Parent directory is +referenced with ``GroupComponent`` role while the children with +``PartComponent``. It's advisable to always provide as much information +to calls like: + +- ``associators()`` +- ``associator_names()`` +- ``references()`` +- ``reference_names()`` + +as possible. Without the ``AssocClass`` parameter given, broker would +try to enumerate all instrumented association classes possible, +resulting in very poor performance. Both ``Role`` and ``ResultRole`` +parameters need to be given here, otherwise a parent directory of the +one being enumerated would also appear in output. + +Following subclass of ``LmiInstanceLister`` needs to be added to +``mylf/lmi/scripts/mylf/cmd.py`` and added to ``MyLF`` subcommands +dictionary (omitted for now). + +:: + + class List(command.LmiInstanceLister): + CALLABLE = mylf.list_directory + PROPERTIES = ( + 'Name', + ('Type', mylf.logical_file_type_name), + ('Permissions', mylf.permission_string), + ('Size', 'FileSize')) + + def verify_options(self, options): + if ( options['--type'] is not None + and not options['--type'].lower() in { + 'any', 'file', 'directory', 'symlink', 'dev', 'socket', 'fifo'}): + raise errors.LmiInvalidOptions( + 'unsupported type: %s' % options['--type']) + + def transform_options(self, options): + file_type = options.pop('--type') + if file_type is None: + file_type = 'any' + options['file-type'] = file_type + +Instead of defining our own ``execute()`` method, we just associate +wrapped function defined previously using ``CALLABLE`` property. Thanks +to the ability to transform option names in any way, we are not limited +to the use of arguments as listed in usage string. Apart from renaming +options, we also check for the value of ``--type``. Overriding +``verify_options()`` to check for validity of options is the more +preferred approach compared to delayed checking in associated function. + +Implementing ``create`` and ``delete`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Let's again start with content of ``mylf/lmi/scripts/mylf/__init__.py`` +module. + +:: + + def create_directory(ns, directory): + """ + Create a directory. + + :type directory: string + :param directory: Full path to the directory. + """ + ns.LMI_UnixDirectory.create_instance( + make_directory_instance_name(ns, directory).path.keybindings) + + def delete_directory(ns, directory): + """ + Delete an empty directory. + + :param directory: Either a file path or an instance of + ``LMI_UnixDirectory``. + """ + get_directory_instance(ns, directory).delete() + +``create_instance()`` call of any ``LMIClass`` creates a new instance, +in this case we create an instance of ``LMI_UnixDirectory``. If it +exists already, an exception will be raised. On the other hand, +``delete_directory()`` operates on an ``LMIInstance`` which must exists. +If directory does not exist or it's not empty, an exception will be +raised. + +Now let's move on to ``mylf/lmi/scripts/mylf/cmd.py``: + +:: + + class Create(command.LmiCheckResult): + EXPECT = None + CALLABLE = mylf.create_directory + + class Delete(command.LmiCheckResult): + EXPECT = None + CALLABLE = mylf.delete_directory + +``LmiCheckResult`` is a special command that prints no useful +information. It allows us to check, whether the associated function +returns expected result and prints an error if not. Here we expect +``None``. Associated functions in this case throw an exception upon any +error which have the same effect. For more information please refer to +its +`documentation <http://pythonhosted.org/openlmi-scripts/command-classes.html#lmicheckresult>`_. + +Test it +~~~~~~~ + +:: + + lmi -h $HOST mylf create /root/some_directory + # try it for the second time (it will fail) + lmi -h $HOST mylf create /root/some_directory + # now let's delete it + lmi -h $HOST mylf delete /root/some_directory + # try it for the second time (it will fail) + lmi -h $HOST mylf delete /root/some_directory + +Summary +------- + +Now that the script is ready and tested, we may commit it, push it, do a +pull request (on +`github <https://help.github.com/articles/using-pull-requests>`_) and +host it on `PyPI <https://pypi.python.org/pypi>`_: + +:: + + python setup.py register + python setup.py sdist upload + +You can also download source tarball :download:`tarball <_static/mylf.tar.gz>`. + |