Changeset 174:dd31c7cd639e in livinglogic.python.orasql

Show
Ignore:
Timestamp:
09/06/06 19:13:03 (13 years ago)
Author:
Walter Doerwald <walter@…>
Branch:
default
Message:

Make Function objects callable.

Files:
4 modified

Legend:

Unmodified
Added
Removed
  • NEWS.xml

    r172 r174  
     1<section><title>Changes in 1.12 (released 09/06/2006)</title> 
     2<ulist> 
     3<item><class>Function</class> objects are now callable too. They return 
     4the return value and a <class>Record</class> containing the modified 
     5input parameters.</item> 
     6</ulist> 
     7</section> 
     8 
     9 
    110<section><title>Changes in 1.11.1 (released 08/29/2006)</title> 
    211<ulist> 
  • setup.py

    r170 r174  
    4747args=dict( 
    4848    name="ll-orasql", 
    49     version="1.11.1", 
     49    version="1.12", 
    5050    description="Utilities for working with cx_Oracle", 
    5151    long_description=DESCRIPTION, 
     
    7474    ], 
    7575    install_requires=[ 
    76         "ll-core >= 1.3", 
     76        "ll-core >= 1.4", 
    7777        "cx_Oracle >= 4.1.2", 
    7878    ], 
  • src/ll/orasql/__init__.py

    r170 r174  
    17331733 
    17341734 
    1735 class Function(MixinNormalDates, MixinCodeDDL, Object): 
    1736     """ 
    1737     Models a function in the database. 
    1738     """ 
    1739     type = "function" 
    1740  
    1741  
    17421735class Argument(object): 
    17431736    """ 
     
    17591752 
    17601753 
    1761 class Procedure(MixinNormalDates, MixinCodeDDL, Object): 
    1762     """ 
    1763     Models a procedure  in the database. A <class>Procedure</class> object can be 
    1764     used as a wrapper for calling the procedure with keyword arguments. 
    1765     """ 
    1766  
    1767     type = "procedure" 
     1754class Callable(MixinNormalDates, MixinCodeDDL, Object): 
     1755    """ 
     1756    Models a callable object in the database, i.e. functions and procedures. 
     1757    """ 
    17681758 
    17691759    _ora2cx = { 
     
    17801770        self._argsbypos = None 
    17811771        self._argsbyname = None 
     1772        self._returnvalue = None 
    17821773 
    17831774    def _calcargs(self, cursor): 
    17841775        if self._argsbypos is None: 
    1785             cursor.execute("select object_id from all_objects where owner=nvl(:owner, user) and lower(object_name)=lower(:name) and object_type='PROCEDURE'", owner=self.owner, name=self.name) 
     1776            cursor.execute("select object_id from all_objects where owner=nvl(:owner, user) and lower(object_name)=lower(:name) and object_type=:type", owner=self.owner, name=self.name, type=self.type.upper()) 
    17861777            if cursor.fetchone() is None: 
    17871778                raise SQLObjectNotFoundError(self) 
     
    17891780            self._argsbyname = {} 
    17901781            cursor.execute("select lower(argument_name) as name, lower(in_out) as in_out, lower(data_type) as datatype from all_arguments where owner=nvl(:owner, user) and lower(object_name)=lower(:name) and data_level=0 order by sequence", owner=self.owner, name=self.name) 
    1791             for (i, record) in enumerate(cursor): 
     1782            i = 0 # argument position (skip return value) 
     1783            for record in cursor: 
    17921784                arginfo = Argument(record.name, i, record.datatype, "in" in record.in_out, "out" in record.in_out) 
    1793                 self._argsbypos.append(arginfo) 
    1794                 self._argsbyname[arginfo.name] = arginfo 
    1795  
    1796     def __call__(self, cursor, *args, **kwargs): 
    1797         """ 
    1798         Call the procedure with arguments <arg>args</arg> and keyword arguments 
    1799         <arg>kwargs</arg>. <arg>cursor</arg> must be a <module>cx_Oracle</module> 
    1800         or <module>ll.orasql</module> cursor. This will return a 
    1801         <pyref class="Record"><class>Record</class></pyref> object containing 
    1802         the result of the call (i.e. this record will contain all in and out 
    1803         parameters). 
    1804         """ 
    1805         self._calcargs(cursor) 
    1806  
     1785                if record.name is None: # this is the return value 
     1786                    self._returnvalue = arginfo 
     1787                else: 
     1788                    self._argsbypos.append(arginfo) 
     1789                    self._argsbyname[arginfo.name] = arginfo 
     1790                    i += 1 
     1791 
     1792    def _getparamarray(self, cursor, *args, **kwargs): 
    18071793        # Get preinitialized parameter array 
    18081794        la = len(args) 
     
    18401826                var.setvalue(0, realarg) 
    18411827                realargs[arginfo.position] = var 
    1842  
    1843         if self.owner is None: 
    1844             name = self.name 
    1845         else: 
    1846             name = "%s.%s" % (self.owner, self.name) 
    1847  
    1848         result = Record() 
    1849         for (i, value) in enumerate(cursor.callproc(name, realargs)): 
    1850             result[self._argsbypos[i].name] = value 
    1851         return result 
     1828        return realargs 
    18521829 
    18531830    def iterarguments(self, connection=None): 
    18541831        """ 
    1855         <par>Generator that yields all <pyref class="ArgumentInfo">arguments</pyref> of the procedure <self/>.</par> 
     1832        <par>Generator that yields all <pyref class="ArgumentInfo">arguments</pyref> of the function/procedure <self/>.</par> 
    18561833        """ 
    18571834        (connection, cursor) = self.getcursor(connection) 
     
    18651842        if mode == "detail": 
    18661843            yield "-iterarguments()" 
     1844 
     1845 
     1846class Procedure(Callable): 
     1847    """ 
     1848    Models a procedure in the database. A <class>Procedure</class> object can be 
     1849    used as a wrapper for calling the procedure with keyword arguments. 
     1850    """ 
     1851 
     1852    type = "procedure" 
     1853 
     1854    def __call__(self, cursor, *args, **kwargs): 
     1855        """ 
     1856        Call the procedure with arguments <arg>args</arg> and keyword arguments 
     1857        <arg>kwargs</arg>. <arg>cursor</arg> must be a <module>cx_Oracle</module> 
     1858        or <module>ll.orasql</module> cursor. This will return a 
     1859        <pyref class="Record"><class>Record</class></pyref> object containing 
     1860        the result of the call (i.e. this record will contain all in and out 
     1861        parameters). 
     1862        """ 
     1863        self._calcargs(cursor) 
     1864 
     1865        # Get preinitialized parameter array 
     1866        realargs = self._getparamarray(cursor, *args, **kwargs) 
     1867 
     1868        if self.owner is None: 
     1869            name = self.name 
     1870        else: 
     1871            name = "%s.%s" % (self.owner, self.name) 
     1872 
     1873        result = Record() 
     1874        for (i, value) in enumerate(cursor.callproc(name, realargs)): 
     1875            result[self._argsbypos[i].name] = value 
     1876        return result 
     1877 
     1878 
     1879class Function(Callable): 
     1880    """ 
     1881    Models a function in the database. A <class>Function</class> object can be 
     1882    used as a wrapper for calling the function with keyword arguments. 
     1883    """ 
     1884    type = "function" 
     1885 
     1886    def __call__(self, cursor, *args, **kwargs): 
     1887        """ 
     1888        Call the function with arguments <arg>args</arg> and keyword arguments 
     1889        <arg>kwargs</arg>. <arg>cursor</arg> must be a <module>cx_Oracle</module> 
     1890        or <module>ll.orasql</module> cursor. This will return a tuple containing 
     1891        the result and a <pyref class="Record"><class>Record</class></pyref> object 
     1892        containing the modified parameters  (i.e. this record will contain all in 
     1893        and out parameters). 
     1894        """ 
     1895        self._calcargs(cursor) 
     1896 
     1897        # Get preinitialized parameter array 
     1898        realargs = self._getparamarray(cursor, *args, **kwargs) 
     1899 
     1900        if self.owner is None: 
     1901            name = self.name 
     1902        else: 
     1903            name = "%s.%s" % (self.owner, self.name) 
     1904 
     1905        returnvalue = cursor.callfunc(name, self._ora2cx[self._returnvalue.datatype], realargs) 
     1906        result = Record() 
     1907        for (i, value) in enumerate(realargs): 
     1908            result[self._argsbypos[i].name] = value 
     1909        return (returnvalue, result) 
    18671910 
    18681911 
  • test/test_orasql.py

    r170 r174  
    233233def test_callprocedure(): 
    234234    db = orasql.connect(dbname) 
    235     proc = orasql.Procedure("orasql_test") 
     235    proc = orasql.Procedure("orasql_testprocedure") 
    236236    result = proc(db.cursor(), p_in=42, p_inout=17) 
    237237    assert result.p_in == 42 
    238238    assert result.p_out == 17 
    239239    assert result.p_inout == 40 
     240 
     241 
     242def test_callfunction(): 
     243    db = orasql.connect(dbname) 
     244    func = orasql.Function("orasql_testfunction") 
     245    result = func(db.cursor(), p_in=42, p_inout=17) 
     246    assert result[0] == "gurk" 
     247    assert result[1].p_in == 42 
     248    assert result[1].p_out == 17 
     249    assert result[1].p_inout == 40