Changeset 4962 for main/waeup.sirp/trunk
- Timestamp:
- 1 Feb 2010, 16:25:15 (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
main/waeup.sirp/trunk/src/waeup/sirp/datacenter.txt
r4920 r4962 257 257 258 258 >>> shutil.rmtree(verynewpath) 259 260 Handling imports261 ================262 263 Data centers can find objects ready for CSV imports and associate264 appropriate importers with them.265 266 Getting importers267 -----------------268 269 To do so, data centers look up their parents for the nearest ancestor,270 that implements `ICSVDataReceivers` and grab all attributes, that271 provide some importer.272 273 We therefore have to setup a proper scenario first.274 275 We start by creating a simple thing that is ready for receiving CSV276 data:277 278 >>> class MyCSVReceiver(object):279 ... pass280 281 Then we create a container for such a CSV receiver:282 283 >>> import grok284 >>> from waeup.sirp.interfaces import ICSVDataReceivers285 >>> from waeup.sirp.datacenter import DataCenter286 >>> class SomeContainer(grok.Container):287 ... grok.implements(ICSVDataReceivers)288 ... def __init__(self):289 ... self.some_receiver = MyCSVReceiver()290 ... self.other_receiver = MyCSVReceiver()291 ... self.datacenter = DataCenter()292 293 By implementing `ICSVDataReceivers`, a pure marker interface, we294 indicate, that we want instances of this class to be searched for CSV295 receivers.296 297 This root container has two CSV receivers.298 299 The datacenter is also an attribute of our root container.300 301 Before we can go into action, we also need an importer, that is able302 to import data into instances of MyCSVReceiver:303 304 >>> from waeup.sirp.csvfile.interfaces import ICSVFile305 >>> from waeup.sirp.interfaces import IWAeUPCSVImporter306 >>> from waeup.sirp.utils.importexport import CSVImporter307 >>> class MyCSVImporter(CSVImporter):308 ... grok.adapts(ICSVFile, MyCSVReceiver)309 ... grok.provides(IWAeUPCSVImporter)310 ... datatype = u'My Stuff'311 ... def doImport(self, filepath, clear_old_data=True,312 ... overwrite=True):313 ... print "Data imported!"314 315 We grok the components to get the importer (which is actually an316 adapter) registered with the component architechture:317 318 >>> grok.testing.grok('waeup')319 >>> grok.testing.grok_component('MyCSVImporter', MyCSVImporter)320 True321 322 Now we can create an instance of `SomeContainer`:323 324 >>> mycontainer = SomeContainer()325 326 As we are not creating real sites and the objects are 'placeless' from327 the ZODB point of view, we fake a location by telling the datacenter,328 that its parent is the container:329 330 >>> mycontainer.datacenter.__parent__ = mycontainer331 >>> datacenter = mycontainer.datacenter332 333 When a datacenter is stored in the ZODB, this step will happen334 automatically.335 336 Before we can go on, we have to set a usable path where we can store337 files without doing harm:338 339 >>> os.mkdir('filestore')340 >>> filestore = os.path.abspath('filestore')341 >>> datacenter.setStoragePath(filestore)342 []343 344 Furthermore we must create a file for possible import, as we will get345 only importers, for which also an importable file is available:346 347 >>> import os348 >>> filepath = os.path.join(datacenter.storage, 'mydata.csv')349 >>> open(filepath, 'wb').write("""col1,col2350 ... 'ATerm','Something'351 ... """)352 353 The datacenter is now able to find the CSV receivers in its parents:354 355 >>> datacenter.getImporters()356 [<MyCSVImporter object at 0x...>, <MyCSVImporter object at 0x...>]357 358 359 Imports with the WAeUP portal360 -----------------------------361 362 The examples above looks complicated, but this is the price for363 modularity. If you create a new container type, you can define an364 importer and it will be used automatically by other components.365 366 In the WAeUP portal the only component that actually provides CSV data367 importables is the `University` object.368 369 370 Getting imports (not: importers)371 --------------------------------372 373 We can get 'imports':374 375 >>> datacenter.getPossibleImports()376 [(<...DataCenterFile object at 0x...>,377 [(<MyCSVImporter object at 0x...>, '...'),378 (<MyCSVImporter object at 0x...>, '...')])]379 380 As we can see, an import is defined here as a tuple of a381 DataCenterFile and a list of available importers with an associated382 data receiver (the thing where the data should go to).383 384 The data receiver is given as an ZODB object id (if the data receiver385 is persistent) or a simple id (if it is not).386 387 Clean up:388 389 >>> import shutil390 >>> shutil.rmtree(filestore)391 392 393 Data center helpers394 ===================395 396 Data centers provide several helper methods to make their usage more397 convenient.398 399 400 Receivers and receiver ids401 --------------------------402 403 As already mentioned above, imports are defined as triples containing404 405 * a file to import,406 407 * an importer to do the import and408 409 * an object, which should be updated by the data file.410 411 The latter normally is some kind of container, like a faculty412 container or similar. This is what we call a ``receiver`` as it413 receives the data from the file via the importer.414 415 The datacenter finds receivers by looking up its parents for a416 component, that implements `ICSVDataReceivers` and scanning that417 component for attributes, that can be adapted to `ICSVImporter`.418 419 I.e., once found an `ICSVDataReceiver` parent, the datacenter gets all420 importers that can be applied to attributes of this component. For421 each attribute there can be at most one importer.422 423 When building the importer list for a certain file, we also check,424 that the headers of the file comply with what the respective importers425 expect. So, if a file contains broken headers, the file won't be426 offered for import at all.427 428 The contexts of the found importers then build our list of available429 receivers. This means also, that for each receiver provided by the430 datacenter, there is also an importer available.431 432 If for a potential receiver no importer can be found, this receiver433 will be skipped.434 435 As one type of importer might be able to serve several receivers, we436 also have to provide a unique id for each receiver. This is, where437 ``receiver ids`` come into play.438 439 Receiver ids of objects are determined as440 441 * the ZODB oid of the object if the object is persistent442 443 * the result of id(obj) otherwise.444 445 The value won this way is a long integer which we turn into a446 string. If the value was get from the ZODB oid, we also prepend it447 with a ``z`` to avoid any clash with non-ZODB objects (they might448 deliver the same id, although this is *very* unlikely).
Note: See TracChangeset for help on using the changeset viewer.