Contact: fumanchu@aminus.org

Log in as guest/dejavu to create tickets

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

root/branches/ldap/schemas.py

Revision 378 (checked in by fumanchu, 6 years ago)

Changed the sync code to allow discovery of database metadata to be optional. See StorageManagerDB.auto_discover. New "alias" method on Table and IndexSet?. Also broke autoclass into a separate storage.db.Modeler object.

  • Property svn:eol-style set to native
Line 
1
2 from dejavu import errors, units
3
4
5 __all__ = ['DeployedVersion', 'Schema',
6            ]
7
8
9 class DeployedVersion(units.Unit):
10     """Which schema version the current deployment has reached."""
11     ID = units.UnitProperty(unicode)
12     Version = units.UnitProperty(int)
13     sequencer = units.UnitSequencer()
14
15
16 class Schema(object):
17     """Schema versioning tool for Dejavu Units.
18     
19     Make a subclass of this base class to manage changes to your model layer
20     (Units and UnitProperties) as your application grows. Each time you make
21     a change to your model, add a new upgrade_to_X method to your subclass,
22     and increment the "latest" attribute to match:
23     
24     class MySchema(dejavu.Schema):
25         
26         latest = 1
27         
28         def upgrade_to_1(self):
29             # Remove Employee.ZipCode and add .StartDate
30             self.arena.drop_property(Employee, "ZipCode")
31             self.arena.add_property(Employee, "StartDate")
32     
33     Then, in your deployment scripts, you can choose how much you want to
34     automate control of the schema.
35     
36         schema = MySchema(myarena)
37         
38         if cmd == 'upgrade':
39             schema.upgrade()
40         elif cmd == 'install':
41             schema.assert_storage()
42         else:
43             schema.assert_version()
44     """
45    
46     guid = ""
47     latest = 0
48     stage = None
49    
50     def __init__(self, arena):
51         # Since schema upgrades may take some time, we keep track of our
52         # own processing state. Legal values are:
53         #   None              = not working on an upgrade
54         #   0 to self.latest  = working on an upgrade to this version
55         self.stage = None
56        
57         self.arena = arena
58         arena.register(DeployedVersion)
59         self._deployed_unit = None
60    
61     def deployed_unit(self, default=None):
62         """Retrieve our DeployedVersion unit, optionally creating it."""
63         if not self.arena.has_storage(DeployedVersion):
64             self.arena.create_storage(DeployedVersion)
65        
66         if self._deployed_unit is None:
67             box = self.arena.new_sandbox()
68             try:
69                 du = box.unit(DeployedVersion, ID=self.guid)
70                 if du is None:
71                     if default is None:
72                         raise errors.DejavuError("Missing DeployedVersion unit.")
73                     else:
74                         du = DeployedVersion(ID=self.guid, Version=default)
75                         box.memorize(du)
76                 self._deployed_unit = du
77             finally:
78                 box.flush_all()
79         return self._deployed_unit
80    
81     def versioned(self):
82         """Return True if this installation has a DeployedVersion, false otherwise."""
83         box = self.arena.new_sandbox()
84         try:
85             return bool(box.unit(DeployedVersion, ID=self.guid))
86         finally:
87             box.flush_all()
88    
89     def _get_dep(self):
90         # Note that we default the Version to latest.
91         # This allows new installs to skip all the upgrade steps,
92         # and just use the latest class definitions when they call
93         # assert_storage. However, it means that if you deploy your
94         # apps for a while without a Schema, and then introduce one
95         # later, you must manually decrement DeployedVersion from
96         # "latest" to the actual deployed version *before* running
97         # your app for the first time (or things will break due to
98         # the difference between the latest and deployed schema).
99         return self.deployed_unit(self.latest).Version
100    
101     def _set_dep(self, newvalue):
102         depunit = self.deployed_unit(newvalue)
103         depunit.Version = newvalue
104         # Skip the sandbox, so we can save without repress
105         self.arena.storage(DeployedVersion).save(depunit, forceSave=True)
106    
107     deployed = property(_get_dep, _set_dep, doc="Deployed version")
108    
109     def upgrade(self, version=None):
110         """Upgrade deployment to version arg [latest]. Idempotent."""
111         if version is None:
112             version = self.latest
113        
114         # Run upgrade_to_X methods.
115         if self.deployed > version:
116             raise errors.DejavuError("Deployed version is greater than latest version.")
117         for step in range(self.deployed, version):
118             self.stage = step
119             procedure = getattr(self, "upgrade_to_%s" % (step + 1), None)
120             if procedure:
121                 procedure()
122             self.deployed = step + 1
123        
124         self.stage = None
125    
126     def upgrade_to_0(self):
127         pass
128    
129     def assert_storage(self):
130         """Assert that each class has storage reserved for it.
131         
132         You may choose to call this method in an admin script (at the
133         discretion of the deployer), or on application startup. If you
134         call this method on every application start, you should do it
135         after calling upgrade(). Once all of the upgrade methods are done,
136         you can then safely use this method to assert the _final_ schemas
137         for all classes. Note that, if the DeployedVersion unit was just
138         created (our actual deployed version was unknown), then some of
139         the upgrade methods may fail. However, they could fail just as
140         easily if you run assert_storage before the upgrade methods.
141         """
142        
143         classes = self.arena._registered_classes.keys()
144         if DeployedVersion in classes:
145             classes.remove(DeployedVersion)
146        
147         for cls in classes:
148             if not self.arena.has_storage(cls):
149                 self.arena.create_storage(cls)
150    
151     def assert_version(self):
152         """Die if schema version is missing or out of sync."""
153         msg = None
154         if not self.versioned:
155             msg = ("This application now uses a versioned schema, but the "
156                    "installed version could not be determined. You must "
157                    "either install the application or manually set the "
158                    "version number.")
159         if self.deployed > self.latest:
160             msg = "Deployed version is greater than the latest version!?!"
161         if self.deployed < self.latest:
162             msg = ("Deployed version is less than the latest version. "
163                    "You must upgrade before proceeding.")
164         if msg:
165             raise errors.DejavuError(msg)
166
Note: See TracBrowser for help on using the browser.