invent_client.py
Go to the documentation of this file.
00001 #! /usr/bin/env python
00002 #
00003 # Software License Agreement (BSD License)
00004 #
00005 # Copyright (c) 2008, Willow Garage, Inc.
00006 # All rights reserved.
00007 #
00008 # Redistribution and use in source and binary forms, with or without
00009 # modification, are permitted provided that the following conditions
00010 # are met:
00011 #
00012 #  * Redistributions of source code must retain the above copyright
00013 #    notice, this list of conditions and the following disclaimer.
00014 #  * Redistributions in binary form must reproduce the above
00015 #    copyright notice, this list of conditions and the following
00016 #    disclaimer in the documentation and/or other materials provided
00017 #    with the distribution.
00018 #  * Neither the name of the Willow Garage nor the names of its
00019 #    contributors may be used to endorse or promote products derived
00020 #    from this software without specific prior written permission.
00021 #
00022 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033 # POSSIBILITY OF SUCH DAMAGE.
00034 
00035 ##\author Scott Hassan, Kevin Watts
00036 ##\brief Client for WG inventory system
00037 
00038 
00039 import os, sys, string, time, re
00040 
00041 import urllib2, cookielib
00042 
00043 import mimetypes
00044 import mimetools
00045 
00046 import neo_cgi, neo_util
00047 import simple_hdfhelp as hdfhelp
00048 import attachment_help
00049 
00050 ##\brief Checks if given serial number is a valid WG SN
00051 def _is_serial_valid(reference):
00052   if len(reference) != 12:
00053     return False
00054 
00055   if not reference.startswith('680'):
00056     return False
00057 
00058   return True
00059 
00060 
00061 ## \brief Stores username and password, provides access to invent
00062 ##
00063 ## Performs all action relating to inventory system
00064 ## Will login automatically before all functions if needed
00065 class Invent(object):
00066   ##@param username str : Username for WG invent system
00067   ##@param password str : Password for WG invent system
00068   def __init__(self, username, password, debug=False):
00069     self.username = username
00070     self.password = password
00071 
00072     self.debug = debug
00073 
00074     self.cj = cookielib.CookieJar()
00075     self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cj))
00076 
00077     self.loggedin = False
00078     self._logged_time = 0
00079 
00080     self.site = "http://invent.willowgarage.com/invent/"
00081     if debug:
00082       self.site = "http://cmi.willowgarage.com/invent/"
00083 
00084   ##\brief Logs into Invent. Returns true if successful
00085   def login(self):
00086     dt = time.time() - self._logged_time
00087     if self.loggedin==False or dt > 3600:
00088       return self._login()
00089     return True
00090 
00091   ## Login to inventory system with given username and password
00092   ## Returns True if successful, False if failure
00093   def _login(self):
00094     username = self.username
00095     password = self.password
00096     url = self.site + "login/signin0.py?Action.Login=1&username=%(username)s&password=%(password)s" % locals()
00097 
00098     fp = self.opener.open(url)
00099     body = fp.read()
00100     fp.close()
00101 
00102     self.loggedin = False
00103     self._logged_time = 0
00104     if body.find("Invalid Login") != -1:
00105       return False
00106 
00107     self.loggedin = True
00108     self._logged_time = time.time()
00109     return True
00110 
00111   ##\brief Reload BoM from PR2 SCDS. Loads barcode association tables
00112   ##
00113   ##\return bool : True if serial is valid, False if not
00114   def reload_pr2scds_bom(self):
00115     self.login()
00116 
00117     url = self.site + "invent/api.py?Action.reloadBom=1&" 
00118     fp = self.opener.open(url)
00119     body = fp.read()
00120     fp.close()
00121     
00122     hdf = neo_util.HDF()
00123     try:
00124       hdf.readString(body)
00125     except Exception, e:
00126       print >> sys.stderr, 'Unable to parse HDF output from inventory system. Output:\n%s' % body
00127       return False
00128 
00129     val = hdf.getValue("CGI.out", "")
00130     return val.lower() == "true"
00131 
00132   ##\brief Check invent DB for serial, make sure it is valid
00133   ##
00134   ##\return bool : True if serial is valid, False if not
00135   def check_serial_valid(self, serial):
00136     if not _is_serial_valid(serial):
00137       return False
00138 
00139     self.login()
00140 
00141     url = self.site + "invent/api.py?Action.isItemValid=1&reference=%s" % (serial,)
00142     fp = self.opener.open(url)
00143     body = fp.read()
00144     fp.close()
00145     
00146     i = string.find(body, "\n<!--")
00147     value = string.strip(body[:i])
00148     
00149     return value.lower() == "true"
00150 
00151   ##\brief Verifies that component is assembled and parts have passed Qual. 
00152   ##
00153   ##
00154   ## Checks that part is assembled against BoM. All sub-parts must be properly associated
00155   ## to the parent part. All sub-parts must have passed qualification.
00156   ##\param serial str : Serial number to check
00157   ##\param recursive bool : Check all sub-assemblies for assembly 
00158   ##\return True if part is assembled
00159   def check_assembled(self, serial, recursive = False):
00160     self.login()
00161 
00162     url = self.site + "invent/api.py?Action.checkAssembled=1&reference=%s" % (serial,)
00163     fp = self.opener.open(url)
00164     body = fp.read()
00165     fp.close()
00166 
00167     hdf = neo_util.HDF()
00168     try:
00169       hdf.readString(body)
00170     except Exception, e:
00171       print >> sys.stderr, 'Unable to parse HDF output from inventory system. Output:\n%s' % body
00172       return False
00173 
00174     val = hdf.getValue("CGI.out", "")
00175 
00176     if not recursive:
00177       return val.lower() == "true"
00178 
00179     # If top-level isn't assembled, abort
00180     if not val.lower() == "true":
00181       return False
00182 
00183     subs = self.get_sub_items(serial)
00184 
00185     for sub in subs:
00186       if not self.check_assembled(sub, recursive):
00187         return False
00188 
00189     return True
00190 
00191 
00192   ##\brief Lookup item by a reference. 
00193   ##
00194   ## Item references are stored as key-values. Ex: { "wan0", "005a86000000" }
00195   ## This returns all items associated with a given reference value.
00196   ##\param str : Reference to lookup
00197   ##\return [ str ] : All items serial numbers that matched reference
00198   def lookup_by_reference(self, ref):
00199     self.login()
00200 
00201     url = self.site + "invent/api.py?Action.lookupByReference=1&reference=%s" % (ref,)
00202     fp = self.opener.open(url)
00203     body = fp.read()
00204     fp.close()
00205 
00206     hdf = neo_util.HDF()
00207     try:
00208       hdf.readString(body)
00209     except Exception, e:
00210       print >> sys.stderr, 'Unable to parse HDF output from inventory system. Output:\n%s' % body
00211       return []
00212 
00213     rv = []
00214     for k,o in hdfhelp.hdf_ko_iterator(hdf.getObj("CGI.cur.items")):
00215       rv.append(o.getValue("reference", ""))
00216 
00217     return rv
00218 
00219   def getItemReferences(self, key):
00220     import warnings
00221     warnings.warn('Using deprecated getItemRefences in wg_invent_client/Invent', DeprecationWarning, stacklevel = 2)
00222     return self.get_item_references(key)
00223 
00224   ## Return any references to an item. References are grouped by
00225   ## name, and are stored as NAME:REFERENCE,... under each item.
00226   ##@param key str : Serial number of item
00227   ##@return { str : str } : { name, reference }
00228   def get_item_references(self, key):
00229     self.login()
00230 
00231     key = key.strip()
00232 
00233     url = self.site + "invent/api.py?Action.getItemReferences=1&key=%s" % (key,)
00234     fp = self.opener.open(url)
00235     body = fp.read()
00236     fp.close()
00237 
00238     hdf = neo_util.HDF()
00239     try:
00240       hdf.readString(body)
00241     except Exception, e:
00242       print >> sys.stderr, 'Unable to parse HDF output from inventory system. Output:\n%s' % body
00243       return {}
00244 
00245     ret = {}
00246     for k,o in hdfhelp.hdf_ko_iterator(hdf.getObj("CGI.cur.refs")):
00247       ret[o.getValue("name", "")] = o.getValue("reference", "")
00248     
00249     return ret
00250 
00251   ##@brief Remove reference from item. 
00252   ##
00253   ##@param key str : Serial number of item
00254   ##@param name str : Reference name
00255   ##@return bool : True if reference was removed. Returns False if no reference found
00256   def remove_item_reference(self, key, name):
00257     self.login()
00258 
00259     key = key.strip()
00260 
00261     url = self.site + "invent/api.py?Action.removeItemReference=1&key=%s&name=%s" % (key,urllib2.quote(name))
00262     fp = self.opener.open(url)
00263     body = fp.read()
00264     fp.close()
00265 
00266     hdf = neo_util.HDF()
00267     try:
00268       hdf.readString(body)
00269     except Exception, e:
00270       print >> sys.stderr, 'Unable to parse HDF output from inventory system. Output:\n%s' % body
00271       return False
00272       
00273     val = hdf.getValue("CGI.out", "")
00274     return val.lower() == "true"
00275 
00276     return True
00277 
00278   ##@brief Add reference to an item
00279   ##
00280   ##@param key str : Serial number of item
00281   ##@param name str : Reference name
00282   ##@param reference str : Reference value
00283   ##@return bool : True if reference is valid 
00284   def addItemReference(self, key, name, reference):
00285     self.login()
00286 
00287     key = key.strip()
00288 
00289     url = self.site + "invent/api.py?Action.addItemReference=1&key=%s&name=%s&reference=%s" % (key,urllib2.quote(name),urllib2.quote(reference))
00290     fp = self.opener.open(url)
00291     body = fp.read()
00292     fp.close()
00293 
00294     hdf = neo_util.HDF()
00295     try:
00296       hdf.readString(body)
00297     except Exception, e:
00298       print >> sys.stderr, 'Unable to parse HDF output from inventory system. Output:\n%s' % body
00299       return False
00300     
00301     val = hdf.getValue("CGI.out", "")
00302     return val.lower() == "true"
00303 
00304     return True
00305 
00306 
00307   ## Generates Willow Garage mac address for item. Used for forearm cameras
00308   ## Does not return mac address
00309   ##@param key str : Serial number of item
00310   ##@param name str : Interface name (ex: "lan0")
00311   def generateWGMacaddr(self, key, name):
00312     self.login()
00313 
00314     key = key.strip()
00315 
00316     url = self.site + "invent/api.py?Action.generateWGMacaddr=1&key=%s&name=%s" % (key,urllib2.quote(name))
00317     fp = self.opener.open(url)
00318     body = fp.read()
00319     fp.close()
00320 
00321   ##\brief Sets notes of component
00322   ## Sets a note value for the component. Allows users to set the text of 
00323   ## a particular note if the noteid parameter is specified. Returns
00324   ## noteid to allow note edits. Returns None if error.
00325   ##@param reference str : Serial number of item
00326   ##@param note str : Text of item
00327   ##@param noteid int (optional) : Note ID, allows programmatic access to note text
00328   def setNote(self, reference, note, noteid = None):
00329     self.login()
00330 
00331     url = self.site + "invent/api.py?Action.AddNoteToItem=1&reference=%s&note=%s" % (reference, urllib2.quote(note))
00332     if noteid:
00333       url = url + "&noteid=%s" % noteid
00334 
00335     fp = self.opener.open(url)
00336     body = fp.read()
00337     fp.close()
00338 
00339     pat = re.compile("rowid=([0-9]+)")
00340     m = pat.search(body)
00341     if m:
00342       noteid = int(m.group(1))
00343       return noteid
00344     return None
00345 
00346   ##\brief Gets notes for an item.
00347   ##
00348   ##\param reference str : Serial number to check
00349   ##\param deleted bool : Retrieve deleted notes in addition to non-deleted notes
00350   ##\return { str : str } : Note ID to note text
00351   def get_item_notes(self, reference, deleted = False):
00352     self.login()
00353 
00354     url = self.site + "invent/api.py?Action.GetItemNotes=1&reference=%s" % (reference)
00355     if deleted:
00356       url += "&deleted=1"
00357     
00358     fp = self.opener.open(url)
00359     body = fp.read()
00360     fp.close()
00361 
00362     hdf = neo_util.HDF()
00363     try:
00364       hdf.readString(body)
00365     except Exception, e:
00366       print >> sys.stderr, 'Unable to parse HDF output from inventory system. Output:\n%s' % body
00367       return {}
00368 
00369     ret = {}
00370     for k,o in hdfhelp.hdf_ko_iterator(hdf.getObj("CGI.cur.notes")):
00371       ret[o.getValue("noteid", "")] = o.getValue("note", "")
00372 
00373     return ret
00374 
00375   ##\brief Delete note for item. 
00376   ##
00377   ## Soft-delete only. Will return True if note has already been deleted
00378   ##\param noteid str : Note to delete
00379   ##\return bool : True if successful
00380   def delete_note(self, noteid):
00381     self.login()
00382     
00383     url = self.site + "invent/api.py?Action.DeleteNote=1&noteid=%s" % (noteid)
00384 
00385     fp = self.opener.open(url)
00386     body = fp.read()
00387     fp.close()
00388 
00389     hdf = neo_util.HDF()
00390     try:
00391       hdf.readString(body)
00392     except Exception, e:
00393       print >> sys.stderr, 'Unable to parse HDF output from inventory system. Output:\n%s' % body
00394       return False
00395     
00396     val = hdf.getValue("CGI.out", "")
00397     return val.lower() == "true"
00398 
00399   ##\brief Restore (un-delete) note for item. 
00400   ##
00401   ## Will return True if note has already been restored
00402   ##\param noteid str : Note to delete
00403   ##\return bool : True if successful
00404   def restore_note(self, noteid):
00405     self.login()
00406     
00407     url = self.site + "invent/api.py?Action.restoreNote=1&noteid=%s" % (noteid)
00408 
00409     fp = self.opener.open(url)
00410     body = fp.read()
00411     fp.close()
00412 
00413     hdf = neo_util.HDF()
00414     try:
00415       hdf.readString(body)
00416     except Exception, e:
00417       print >> sys.stderr, 'Unable to parse HDF output from inventory system. Output:\n%s' % body
00418       return False
00419     
00420     val = hdf.getValue("CGI.out", "")
00421     return val.lower() == "true"
00422 
00423   ##\brief Get information about note. 
00424   ##
00425   ## Returns tuple of note information as strings. Reference is serial number. 
00426   ## Date is UTC format. "deleted" is "1" for deleted, "0" if not.
00427   ##\param noteid str : Note ID
00428   ##\return (reference, note, username, date, deleted) (str, str, str, str, str) : 
00429   def get_note(self, noteid):
00430     self.login()
00431 
00432     url = self.site + "invent/api.py?Action.GetNote=1&noteid=%s" % (noteid)
00433 
00434     fp = self.opener.open(url)
00435     body = fp.read()
00436     fp.close()
00437 
00438     hdf = neo_util.HDF()
00439     try:
00440       hdf.readString(body)
00441     except Exception, e:
00442       print >> sys.stderr, 'Unable to parse HDF output from inventory system. Output:\n%s' % body
00443       return ('', '', '', '', '')
00444     
00445     ref = hdf.getValue("CGI.cur.item.reference", "")
00446     note = hdf.getValue("CGI.cur.note.note", "")
00447     user = hdf.getValue("CGI.cur.note.whom", "")
00448     date = hdf.getValue("CGI.cur.note.date", "")
00449     deleted = hdf.getValue("CGI.cur.note.deleted", "")
00450 
00451     return (ref, note, user, date, deleted)
00452 
00453   ##\brief Set value of component's key
00454   ##
00455   ## Set key-value of component. Ex: setKV(my_ref, 'Test Status', 'PASS')
00456   ##@param reference str : Serial number of component
00457   ##@param key str : Key (name)
00458   ##@param value str : Value
00459   ##@return True if set Key properly
00460   def setKV(self, reference, key, value):
00461     self.login()
00462 
00463     key = key.strip()
00464     value = value.strip()
00465 
00466     if not key:
00467       print >> sys.stderr, "Unable to set empty key into inventory system. Reference: %s, Value: %s" % (reference, value)
00468       return False
00469 
00470     if not value:
00471       print >> sys.stderr, "Unable to set empty value into inventory system. Reference: %s, Key: %s" % (reference, key)
00472       return False
00473 
00474     url = self.site + "invent/api.py?Action.setKeyValue=1&reference=%s&key=%s&value=%s" % (reference, urllib2.quote(key), urllib2.quote(value))
00475 
00476     fp = self.opener.open(url)
00477     fp.read()
00478     fp.close()
00479 
00480     return True
00481 
00482   ##\brief Delete key value for component.
00483   ##
00484   ## Delete key-value of component. 
00485   ##@param reference str : Serial number of component
00486   ##@param key str : Key (name)
00487   ##@return True if deleted key properly
00488   def deleteKV(self, reference, key):
00489     self.login()
00490 
00491     key = key.strip()
00492 
00493     if not key:
00494       print >> sys.stderr, "Unable to set empty key into inventory system. Reference: %s" % (reference)
00495       return False
00496 
00497     url = self.site + "invent/api.py?Action.deleteKeyValue=1&reference=%s&key=%s" % (reference, urllib2.quote(key))
00498 
00499     fp = self.opener.open(url)
00500     body = fp.read()
00501     fp.close()
00502 
00503     hdf = neo_util.HDF()
00504     try:
00505       hdf.readString(body)
00506     except Exception, e:
00507       print >> sys.stderr, 'Unable to parse HDF output from inventory system. Output:\n%s' % body
00508       return False
00509 
00510     val = hdf.getValue("CGI.cur.out", "")
00511 
00512     return val.lower() == "true"
00513 
00514   ##\brief Returns True if part has 'Test Status'='PASS', False otherwise
00515   def get_test_status(self, reference):
00516     return self.getKV(reference, 'Test Status') == 'PASS'
00517 
00518   ##\brief Return value of component's key
00519   ## Get key-value of component. Ex: 'PASS' = getKV(my_ref, 'Test Status')
00520   ##@param reference str : Serial number of component
00521   ##@param key str : Key (name)
00522   ##\return str : Value, or '' if key doesn't exist
00523   def getKV(self, reference, key):
00524     self.login()
00525 
00526     key = key.strip()
00527 
00528     if not key:
00529       raise ValueError, "the key is blank"
00530 
00531     url = self.site + "invent/api.py?Action.getKeyValue=1&reference=%s&key=%s" % (reference, urllib2.quote(key))
00532 
00533     fp = self.opener.open(url)
00534     value = fp.read()
00535     fp.close()
00536 
00537     i = string.find(value, "\n<!--")
00538     value = string.strip(value[:i])
00539     
00540     return value
00541 
00542   ##\brief List Key-Value pairs of component. 
00543   ##
00544   ##\param reference str : Serial number of component
00545   ##\return { str : str } : Key values of component
00546   def listKVs(self, reference):
00547     self.login()
00548 
00549     url = self.site + "invent/api.py?Action.listKeyValues=1&reference=%s" % (reference)
00550 
00551     fp = self.opener.open(url)
00552     body = fp.read()
00553     fp.close()
00554 
00555     hdf = neo_util.HDF()
00556     try:
00557       hdf.readString(body)
00558     except Exception, e:
00559       print >> sys.stderr, 'Unable to parse HDF output from inventory system. Output:\n%s' % body
00560       return {}
00561 
00562     ret = {}
00563     for k,o in hdfhelp.hdf_ko_iterator(hdf.getObj("CGI.cur.kvs")):
00564       ret[o.getValue("key", "")] = o.getValue("value", "")
00565 
00566     return ret
00567 
00568   ##\brief Adds attachment to component
00569   ##
00570   ## Adds file as attachment to component. Attachment it encoded to unicode,
00571   ## then uploaded. Mimetype is optional, but helps users view
00572   ## attachments in window. 
00573   ##@param reference str : Serial number of component
00574   ##@param name str : Attachment filename
00575   ##@param mimetype MIMEType : MIMEType of file
00576   ##@param attachment any : Attachment data
00577   ##@param note str : Note to add with attachment (description)
00578   ##@param aid str : Attachment ID. If set, attempts to overwrite attachment at ID
00579   ##\return str : Attachment ID of set attachment 
00580   def add_attachment(self, reference, name, mimetype, attachment, note = None, aid=None):
00581     self.login()
00582 
00583     if not name:
00584       raise ValueError, "the name is blank"
00585 
00586     theURL = self.site + "invent/api.py"
00587 
00588     fields = []
00589     fields.append(('Action.addAttachment', "1"))
00590     fields.append(('reference', reference))
00591     fields.append(('mimetype', mimetype))
00592     fields.append(('name', name))
00593     if note is not None:
00594       fields.append(('note', note))
00595     if aid is not None:
00596       fields.append(('aid', aid))
00597 
00598     files = []
00599     files.append(("attach", name, attachment))
00600 
00601     input = attachment_help.build_request(theURL, fields, files)
00602 
00603     response = self.opener.open(input).read()
00604 
00605     pat = re.compile("rowid=([0-9]+)")
00606     m = pat.search(response)
00607     if m is not None:
00608       aid = int(m.group(1))
00609       return aid
00610     return None
00611 
00612   ##\brief List all attachments for an item
00613   ##
00614   ##\return { str : str } : Attachment ID to filename
00615   def list_attachments(self, key):
00616     self.login()
00617 
00618     key = key.strip()
00619 
00620     url = self.site + "invent/api.py?Action.getAttachments=1&key=%s" % (key,)
00621     fp = self.opener.open(url)
00622     body = fp.read()
00623     fp.close()
00624 
00625     hdf = neo_util.HDF()
00626     try:
00627       hdf.readString(body)
00628     except Exception, e:
00629       print >> sys.stderr, 'Unable to parse HDF output from inventory system. Output:\n%s' % body
00630       return {}
00631 
00632     ret = {}
00633     for k,o in hdfhelp.hdf_ko_iterator(hdf.getObj("CGI.cur.attachments")):
00634       ret[o.getValue("aid", "")] = o.getValue("name", "")
00635     
00636     return ret
00637 
00638   ##\brief Get attachment info. 
00639   ##
00640   ##\param aid str : Attachment ID
00641   ##\return ( str, str, str, str ) : reference, docname, username, note, date
00642   def get_attachment_info(self, aid):
00643     self.login()
00644 
00645     aid = aid.strip()
00646 
00647     url = self.site + "invent/api.py?Action.getAttachmentInfo=1&aid=%s" % (aid,)
00648     fp = self.opener.open(url)
00649     body = fp.read()
00650     fp.close()
00651 
00652     hdf = neo_util.HDF()
00653     try:
00654       hdf.readString(body)
00655     except Exception, e:
00656       print >> sys.stderr, 'Unable to parse HDF output from inventory system. Output:\n%s' % body
00657       return ('', '', '', '')
00658 
00659     ref = hdf.getValue("CGI.cur.reference", "")
00660     docname = hdf.getValue("CGI.cur.attachment.name", "")
00661     user =  hdf.getValue("CGI.cur.attachment.whom", "")
00662     note = hdf.getValue("CGI.cur.attachment.note", "")
00663     date = hdf.getValue("CGI.cur.attachment.date", "")
00664 
00665     return (ref, docname, user, note, date)
00666 
00667   ##\brief Get attachment
00668   ##
00669   ##\param aid str : Attachment ID
00670   ##\return ( str, str, str, str ) : reference, docname, username, note, date
00671   def get_attachment(self, aid):
00672     self.login()
00673 
00674     aid = aid.strip()
00675 
00676     url = self.site + "invent/api.py?Action.getAttachmentInfo=1&aid=%s" % (aid,)
00677     fp = self.opener.open(url)
00678     body = fp.read()
00679     fp.close()
00680 
00681     hdf = neo_util.HDF()
00682     try:
00683       hdf.readString(body)
00684     except Exception, e:
00685       print >> sys.stderr, 'Unable to parse HDF output from inventory system. Output:\n%s' % body
00686       return ('', '', '', '')
00687 
00688     docname = hdf.getValue("CGI.cur.attachment.name", "")
00689     docref = hdf.getValue("CGI.cur.attachment.docref", "")
00690 
00691     url = self.site + "documents/show.py?reference=%s&name=%s" % (docref, docname)
00692     fp = self.opener.open(url)
00693     doc = fp.read()
00694     fp.close()
00695 
00696     return doc
00697 
00698   ##\brief Deletes attachment. Hard delete. 
00699   ##
00700   ## Returns true if attachment is deleted, or not found.
00701   ##\param aid str : Attachment ID
00702   ##\return bool : True if deleted
00703   def delete_attachment(self, aid):
00704     self.login()
00705     
00706     url = self.site + "invent/api.py?Action.deleteAttachment=1&aid=%s" % (aid)
00707 
00708     fp = self.opener.open(url)
00709     body = fp.read()
00710     fp.close()
00711 
00712     hdf = neo_util.HDF()
00713     try:
00714       hdf.readString(body)
00715     except Exception, e:
00716       print >> sys.stderr, 'Unable to parse HDF output from inventory system. Output:\n%s' % body
00717       return False
00718     
00719     val = hdf.getValue("CGI.out", "")
00720     return val.lower() == "true"
00721 
00722   ##\brief Returns list of sub items (references) for a particular parent
00723   ##
00724   ## In debug mode, Invent can return list of sub parts recursively
00725   ##\param reference str : WG PN of component or assembly
00726   ##\param recursive bool [optional] : Sub-sub-...-sub-parts of reference
00727   ##\return [ str ] : Serial number of sub-assemblies of component
00728   def get_sub_items(self, reference, recursive = False):
00729     self.login()
00730     
00731     reference = reference.strip()
00732 
00733     url = self.site + "invent/api.py?Action.getSubparts=1&reference=%s" % (reference)
00734     if recursive:
00735       url += "&recursive=1"
00736 
00737     fp = self.opener.open(url)
00738     body = fp.read()
00739     fp.close()
00740 
00741     hdf = neo_util.HDF()
00742     try:
00743       hdf.readString(body)
00744     except Exception, e:
00745       print >> sys.stderr, 'Unable to parse HDF output from inventory system. Output:\n%s' % body
00746       return {}
00747 
00748     ret = []
00749     for k,o in hdfhelp.hdf_ko_iterator(hdf.getObj("CGI.cur.items")):
00750       ret.append(o.getValue("reference", ""))
00751     
00752     return ret
00753 
00754   ##\brief Returns parent item (serial number) or location. 
00755   ##
00756   ## Parent may be a location, such as "Recieving", instead of a serial number.
00757   ##\param reference str : Serial number to check
00758   ##\return str : Serial number of parent. None if no parent found
00759   def get_parent_item(self, reference):
00760     self.login()
00761 
00762     url = self.site + "invent/api.py?Action.getParentItem=1&reference=%s" % (reference)
00763     fp = self.opener.open(url)
00764     body = fp.read()
00765     fp.close()
00766 
00767     hdf = neo_util.HDF()
00768     try:
00769       hdf.readString(body)
00770     except Exception, e:
00771       print >> sys.stderr, 'Unable to parse HDF output from inventory system. Output:\n%s' % body
00772       return None
00773 
00774     parent = hdf.getValue("CGI.cur.parent", "")
00775     if not parent:
00776       return None
00777 
00778     return parent
00779 
00780 
00781 
00782 
00783 
00784 


wg_invent_client
Author(s): Scott Hassan, Kevin Watts
autogenerated on Sat Dec 28 2013 17:55:42