Contact: fumanchu@aminus.org

Log in as guest/dejavu to create tickets

I think I've seen this ORM somewhere before...

Changeset 17

Show
Ignore:
Timestamp:
10/13/04 23:55:22
Author:
fumanchu
Message:

1. Fixed a mutex bug in UnitCollection?.
2. Doc updates.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/doc/modeling.html

    r16 r17  
    1111<body> 
    1212 
    13 <h2>Application Developers: Using Dejavu to Construct a Model</h2> 
     13<h2>Application Developers: Using Dejavu to Construct a Domain Model</h2> 
    1414 
    1515<h3>Units</h3> 
     
    593593for more information.</p> 
    594594 
     595 
    595596<h3>Unit Engines</h3> 
    596 <p></p> 
     597<p>Once you've created and associated your Unit classes, you can begin to 
     598write "business logic" code (mostly inside those classes, we hope), and 
     599"presentation logic" code (mostly outside those classes). In most cases, 
     600you will construct Expressions within your own code manually to retrieve 
     601Units. Sometimes, however, you need to persist query parameters from your 
     602users; in other cases, you might store a list of Units which match a query 
     603(regardless of who formed the necessary Expression). Finally, you might 
     604wish to manipulate lists of Units as sets: differences, intersections, 
     605and unions. The <tt>engines</tt> module addresses all of these needs.</p> 
     606 
     607<h4>Collections: Lists of Units</h4> 
     608<p>The <tt>UnitCollection</tt> class provides a means of storing a list 
     609of Units, or rather, a list of Unit ID's. You use its <tt>Type</tt> 
     610property to indicate the class of the indexed Units. That value should be 
     611the <b>name</b> of the Unit Class, <b>not</b> the class object itself 
     612(this is different than most other calls in Dejavu). If you need to 
     613retrieve the actual Unit class, call <tt>UnitCollection().unit_class()</tt>.</p> 
     614 
     615<p><tt>UnitCollection</tt> itself subclasses <tt>dejavu.Unit</tt>; you can 
     616therefore persist Unit Collections via Dejavu Storage Managers (most SM's, 
     617anyway; it's recommended that SM's handle Unit Collections, but not 
     618required. Check your SM to see if it does).</p> 
     619 
     620<p>Each Collection has a thread lock (an RLock, actually) which you should 
     621<tt>acquire()</tt> before you add an ID to the set, and <tt>release()</tt> 
     622afterward. If you use the <tt>add(ID)</tt> method, this locking is done 
     623for you.</p> 
     624 
     625<p>When you need to retrieve the actual Units which are indexed by the 
     626Collection, call the <tt>units(quota=None)</tt> method, which will 
     627look up the Units and return them in a list. Since the Collection only 
     628stores ID's, it is possible that one of the indexed Units may have been 
     629destroyed since the list was built. The <tt>units</tt> method simply 
     630passes over these "phantom" Units. You can inspect the full list of IDs 
     631in the Collection (whether they reference existing Units or not) with 
     632the <tt>ids()</tt> method.</p> 
     633 
     634<p>Collections also provide a convenience function for grouping Units 
     635by attribute: <tt>xdict(attr)</tt>. This function will look up each Unit 
     636in the Collection, inspect the attribute that you specify, and return 
     637a dictionary of the form <tt>{attr_val1: [Unit, Unit, ...]}</tt>. 
     638Each distinct attribute value will have its own key, with a list of 
     639matching Units as the value.</p> 
     640 
     641<h4>Engines</h4> 
     642<p>You can form Collections by hand, but a more powerful technique is 
     643the <tt>UnitEngine</tt>, a factory for Collections. Engines are very 
     644simple: they possess a set of <i>rules</i> which are executed when 
     645you want to take a <i>snapshot</i> of Units. The snapshot which is 
     646produced is a <tt>UnitCollection</tt> object. Whenever you call 
     647<tt>take_snapshot()</tt>, the Engine will maintain an association 
     648to the resulting Collection. You can access past snapshots with the 
     649<tt>snapshots()</tt> method.</p> 
     650 
     651<p>Engines are themselves Units, and can be persisted via Storage Managers. 
     652The only properties they possess are: an <tt>ID</tt>, a <tt>Name</tt>, 
     653an <tt>Owner</tt>, a <tt>FinalClassName</tt>, and <tt>Created</tt>, 
     654the creation date of the Engine.</p> 
     655 
     656<p>The <tt>Owner</tt> property should either be a user name, or one of the 
     657reserved names: "Public" and "System". By default, the <tt>permit()</tt> 
     658method allows a user read-access to the Engine if they are the Owner, or 
     659the Owner is "Public" or "System". Write-access is permitted if the user 
     660is the Owner, or the Owner is "Public". Feel free to override 
     661<tt>permit()</tt> in a subclass to provide different behaviors.</p> 
     662 
     663<p>The <tt>FinalClassName</tt> is set for you as you add Rules to the 
     664Engine. You can use the value of this property, for example, to tell 
     665your users, "Engine #23569 is an 'Armadillo' engine," when it produces 
     666Collections of <tt>Armadillo</tt> Units. The only time you might want to 
     667set this value is when you first create the Engine, before you have added 
     668any Rules.</p> 
     669 
     670<h4>Rules</h4> 
     671<p>Just like Collections and Engines, <tt>UnitEngineRule</tt> is <i>also</i> 
     672a subclass of <tt>Unit</tt>, and can be persisted via Storage Managers. All 
     673three work together to provide a complete, dynamic, application-level query 
     674generator.</p> 
     675 
     676<p>Okay, so what are Rules? You might say they're a "little language", 
     677with the following primitives, or "operations":</p> 
     678<table> 
     679<tr><th>Operation</th><th>Operand(s)</th><th>Description</th></tr> 
     680<tr><th colspan='3'>Operations on a single set</th></tr> 
     681<tr> 
     682    <td>CREATE</td> 
     683    <td>The classname of the new Type</td> 
     684    <td>Creates a new Set of the specified Type. All Units of that Type 
     685        are included in the new Set.</td> 
     686</tr> 
     687<tr> 
     688    <td>FILTER</td> 
     689    <td>A <tt>logic.Expression</tt></td> 
     690    <td>Removes Units from the current Set which do not match the 
     691        Expression.</td> 
     692</tr> 
     693<tr> 
     694    <td>FUNCTION</td> 
     695    <td>The name of a function in the <tt>Arena.engine_functions</tt> 
     696        dict</td> 
     697    <td>Calls the function, passing the current Set. The function 
     698        should modify the Set.</td> 
     699</tr> 
     700<tr> 
     701    <td>TRANSFORM</td> 
     702    <td>The classname of the new Type</td> 
     703    <td>Transform the current Set into a Set of associated Units 
     704        (of another Type). The association must be present in the 
     705        <tt>Arena.associations</tt> graph.</td> 
     706</tr> 
     707<tr> 
     708    <td>RETURN</td> 
     709    <td></td> 
     710    <td>Optional. If omitted, the last Set handled is returned as the 
     711        snapshot. If supplied, the ID of the Set to return.</td> 
     712</tr> 
     713<tr><th colspan='3'>Operations on two sets</th></tr> 
     714<tr> 
     715    <td>COPY</td> 
     716    <td>The Set ID of the new Set</td> 
     717    <td>Copies the current Set to a new Set. The current Set is unchanged.</td> 
     718</tr> 
     719<tr> 
     720    <td>DIFFERENCE</td> 
     721    <td>The ID of the Set to mix in</td> 
     722    <td>Removes IDs from the current Set which exist in the second Set.</td> 
     723</tr> 
     724<tr> 
     725    <td>INTERSECTION</td> 
     726    <td>The ID of the Set to mix in</td> 
     727    <td>Removes IDs from the current Set which <i>do not</i> exist in the 
     728        second Set.</td> 
     729</tr> 
     730<tr> 
     731    <td>UNION</td> 
     732    <td>The ID of the Set to mix in</td> 
     733    <td>Adds any IDs to the current Set which exist in the second Set.</td> 
     734</tr> 
     735</table> 
     736 
     737<p>Each Rule has an <tt>Operation</tt> property (a string, one of the above), 
     738a <tt>SetID</tt>, and an <tt>Operand</tt>.</p> 
    597739 
    598740<h4>Engine Functions</h4> 
  • trunk/engines.py

    r16 r17  
    7272    def ids(self): 
    7373        self.acquire() 
    74         for eachID in self._IDs: 
    75             yield eachID 
    76         self.release() 
     74        try: 
     75            return self._IDs.copy() 
     76        finally: 
     77            self.release() 
    7778     
    7879    def units(self, quota=None): 
    7980        cls = self.unit_class() 
     81        output = [] 
    8082        self.acquire() 
    81         for i, eachID in enumerate(self._IDs): 
    82             if quota and i >= quota: 
    83                 break 
    84             unit = self.sandbox.unit(cls, ID=eachID) 
    85             if unit: 
    86                 yield unit 
    87         self.release() 
     83        try: 
     84            for i, eachID in enumerate(self._IDs): 
     85                if quota and i >= quota: 
     86                    break 
     87                unit = self.sandbox.unit(cls, ID=eachID) 
     88                if unit: 
     89                    output.append(unit) 
     90        finally: 
     91            self.release() 
     92        return output 
    8893     
    8994    def xdict(self, attr): 
     
    129134        """kw: Operation, SetID, Operand=(Type | logic.Expression | otherSet) 
    130135         
    131         Expressions: 
    132             If the Operation is a logic.Expression, then the snapshot 
    133             will consist of the IDs of units which match the Expression. 
     136        FILTER: 
     137            If the Operation is 'FILTER', the Operand shall be a 
     138            logic.Expression, and the snapshot will consist of the IDs of 
     139            Units which match the Expression. 
    134140         
    135141        Everything else: