Changeset 266
- Timestamp:
- 12/01/09 18:27:13
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
sodar/branches/scintec-branch/sodar/scintec/maindata.py
r265 r266 10 10 __license__ = 'GPL2' 11 11 12 from datetime import datetime, timedelta 13 12 14 class MainData(list): 13 15 """ … … 20 22 >>> main_data = MainData(good_mnd) 21 23 22 Parse the format header:23 >>> len(main_data._format_header_spec)24 425 >>> main_data._format_header_spec[0]26 'FORMAT-1'27 28 Parse the file header after the format header:29 >>> len(main_data._file_header_body)30 2631 >>> main_data._file_header_body[1]32 '# file information'33 34 24 Parse the profile data: 35 25 >>> len(main_data) … … 39 29 >>> len(main_data[0]) 40 30 39 41 >>> main_data[0].timestamp 42 '2009-11-17 00:30:00 00:30:00' 31 >>> main_data[0].start 32 datetime.datetime(2009, 11, 17, 0, 0) 33 >>> main_data[0].stop 34 datetime.datetime(2009, 11, 17, 0, 30) 43 35 >>> main_data[0].variables 44 36 ['z', 'speed', 'dir', 'W', 'sigW', 'bck', 'error'] … … 47 39 ... 'error':'0'} 48 40 True 41 >>> main_data[0][0].z 42 '10' 43 >>> main_data[0]['10'] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 44 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 45 ... 'error':'0'} 46 True 47 >>> main_data[0]['10'].speed 48 '99.99' 49 49 >>> main_data[0][-1] == {'z':'200', 'speed':'99.99', 'dir':'999.9', 50 50 ... 'W':'-0.07', 'sigW':'99.99', 'bck':'9.99E+37', 51 51 ... 'error':'0'} 52 52 True 53 >>> main_data[0][-1].dir 54 '999.9' 55 >>> main_data[0]['200'] == {'z':'200', 'speed':'99.99', 'dir':'999.9', 56 ... 'W':'-0.07', 'sigW':'99.99', 'bck':'9.99E+37', 57 ... 'error':'0'} 58 True 59 >>> main_data[0]['200'].W 60 '-0.07' 53 61 54 62 Parse the last profile: 55 63 >>> len(main_data[-1]) 56 64 39 57 >>> main_data[-1].timestamp 58 '2009-11-18 00:00:00 00:30:00' 65 >>> main_data[-1].start 66 datetime.datetime(2009, 11, 17, 23, 30) 67 >>> main_data[-1].stop 68 datetime.datetime(2009, 11, 18, 0, 0) 59 69 >>> main_data[-1].variables 60 70 ['z', 'speed', 'dir', 'W', 'sigW', 'bck', 'error'] … … 99 109 """ 100 110 101 super( MainData, self).__init__()111 super(self.__class__, self).__init__() 102 112 103 113 self.file_name = '' … … 113 123 # Divide the data into blocks 114 124 # across boundaries separated by blank lines. 115 self._blocks = [self._block.strip()116 for self._block117 118 if self._block.strip()]125 blocks = [block.strip() 126 for block 127 in mnd.split('\n\n') 128 if block.strip()] 119 129 120 130 # The first block is the specification of the format header. 121 131 # Divide it into lines. 122 self._format_header_spec = [self._line.strip()123 for self._line124 in self._blocks[0].split('\n')125 if self._line.strip()]132 format_header_spec = [line.strip() 133 for line 134 in blocks[0].split('\n') 135 if line.strip()] 126 136 127 137 # The second block is the body of the format header. 128 138 # Divide it into lines. 129 self._file_header_body = [self._line.strip()130 for self._line131 in self._blocks[1].split('\n')132 if self._line.strip()]139 file_header_body = [line.strip() 140 for line 141 in blocks[1].split('\n') 142 if line.strip()] 133 143 134 144 # All the remaing blocks are individual profiles 135 145 # in chronological order. 136 self.extend([Profile([self._line.strip() 137 for self._line 138 in self._block.split('\n') 139 if self._line.strip()]) 140 for self._block 141 in self._blocks[2:]]) 142 143 # No need to haul around bookkeeping storage used for initialization. 144 del self._blocks, self._block, self._line 146 self.extend([Profile([line.strip() 147 for line 148 in block.split('\n') 149 if line.strip()]) 150 for block 151 in blocks[2:]]) 152 145 153 146 154 class Profile(list): … … 153 161 Parse a known good profile block: 154 162 >>> profile = Profile(good_profile) 155 >>> profile.timestamp 156 '2009-11-17 00:30:00 00:30:00' 163 164 Access the timestamp attributes: 165 >>> profile.start 166 datetime.datetime(2009, 11, 17, 0, 0) 167 >>> profile.stop 168 datetime.datetime(2009, 11, 17, 0, 30) 169 170 Access the variable list: 157 171 >>> profile.variables 158 172 ['z', 'speed', 'dir', 'W', 'sigW', 'bck', 'error'] 173 174 Access profiles by sequence number and variables by attribute name: 159 175 >>> profile[0] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 160 176 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 161 177 ... 'error':'0'} 162 178 True 179 >>> profile[0].z 180 '10' 163 181 >>> profile[-1] == {'z':'200', 'speed':'99.99', 'dir':'999.9', 164 182 ... 'W':'-0.07', 'sigW':'99.99', 'bck':'9.99E+37', 165 183 ... 'error':'0'} 166 184 True 185 >>> profile[-1].speed 186 '99.99' 187 188 Access profiles by elevation and variables by attribute name: 189 >>> profile['10'] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 190 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 191 ... 'error':'0'} 192 True 193 >>> profile['10'].dir 194 '999.9' 195 >>> profile['200'] == {'z':'200', 'speed':'99.99', 'dir':'999.9', 196 ... 'W':'-0.07', 'sigW':'99.99', 'bck':'9.99E+37', 197 ... 'error':'0'} 198 True 199 >>> profile['200'].W 200 '-0.07' 167 201 """ 168 202 … … 174 208 175 209 Where: 176 210 177 211 profile_block is a list of str objects containing all the lines 178 212 from a single profile in a Scintec .mnd daily sodar file. 179 213 180 214 Parse a known good profile block: 181 215 >>> profile = Profile(good_profile) 182 >>> profile.timestamp 183 '2009-11-17 00:30:00 00:30:00' 216 217 Access the timestamp attributes: 218 >>> profile.start 219 datetime.datetime(2009, 11, 17, 0, 0) 220 >>> profile.stop 221 datetime.datetime(2009, 11, 17, 0, 30) 222 223 Access the variable list: 184 224 >>> profile.variables 185 225 ['z', 'speed', 'dir', 'W', 'sigW', 'bck', 'error'] 186 >>> profile[0] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 187 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 188 ... 'error':'0'} 189 True 226 227 Access profiles by sequence number and variables by attribute name: 228 >>> profile[0] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 229 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 230 ... 'error':'0'} 231 True 232 >>> profile[0].z 233 '10' 190 234 >>> profile[-1] == {'z':'200', 'speed':'99.99', 'dir':'999.9', 191 235 ... 'W':'-0.07', 'sigW':'99.99', 'bck':'9.99E+37', 192 236 ... 'error':'0'} 193 237 True 194 """ 195 196 super(Profile, self).__init__() 238 >>> profile[-1].speed 239 '99.99' 240 """ 241 242 super(self.__class__, self).__init__() 197 243 198 244 # The first line in the profile block is the timestamp. 199 self.timestamp = profile_block[0] 245 timestamp = profile_block[0] 246 date, stop, duration = timestamp.split() 247 date_year, date_month, date_day = date.split('-') 248 stop_hour, stop_minute, stop_second = stop.split(':') 249 duration_hour, duration_minute, duration_second = duration.split(':') 250 interval = timedelta(0, # days 251 int(duration_second), 252 0, # microseconds 253 0, # milliseconds 254 int(duration_minute), 255 int(duration_hour)) # omit optional weeks 256 self.stop = datetime(int(date_year), 257 int(date_month), 258 int(date_day), 259 int(stop_hour), 260 int(stop_minute), # omit optional microseconds 261 int(stop_second)) # and tzinfo 262 self.start = self.stop - interval 200 263 201 264 # The second line in the profile block is … … 206 269 # individual obervation columns in the same order 207 270 # as the variable names. 208 self.extend([Observation(observation.split(),self.variables) 209 for observation in profile_block[2:]]) 271 super(self.__class__, self).extend([Observation(observation.split(), 272 self.variables) 273 for observation 274 in profile_block[2:]]) 275 276 def __getitem__(self,key): 277 """ 278 Get a profile by elevation. 279 280 profile_instance[elevation] -> <Observation object> 281 282 Where: 283 284 elevation is a str object object representing the elevation 285 (value keyed by 'z') of the Observation object. 286 287 Access profiles by elevation and variables by attribute name: 288 >>> profile = Profile(good_profile) 289 >>> profile['10'] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 290 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 291 ... 'error':'0'} 292 True 293 >>> profile['10'].dir 294 '999.9' 295 >>> profile['200'] == {'z':'200', 'speed':'99.99', 'dir':'999.9', 296 ... 'W':'-0.07', 'sigW':'99.99', 'bck':'9.99E+37', 297 ... 'error':'0'} 298 True 299 >>> profile['200'].W 300 '-0.07' 301 """ 302 303 try: 304 return super(self.__class__, self).__getitem__(key) 305 except TypeError: 306 for observation in self: 307 if observation['z'] == key: 308 return observation 309 return super(self.__class__, self).__getitem__(key) 310 311 def __setitem__(self,key,value): 312 """ 313 Protect items. 314 315 profile_instance[object1] = object2 316 317 Raise an Exception if attempting to mutate a profile: 318 >>> profile = Profile(good_profile) 319 >>> profile[0] = 'OK' 320 Traceback (most recent call last): 321 ... 322 TypeError: 'Profile' instance's items are read-only 323 >>> profile['10'] = 'OK' 324 Traceback (most recent call last): 325 ... 326 TypeError: 'Profile' instance's items are read-only 327 >>> profile[100000] = 'OK' 328 Traceback (most recent call last): 329 ... 330 TypeError: 'Profile' instance's items are read-only 331 >>> profile[100000] 332 Traceback (most recent call last): 333 ... 334 IndexError: list index out of range 335 >>> profile['100000'] = 'OK' 336 Traceback (most recent call last): 337 ... 338 TypeError: 'Profile' instance's items are read-only 339 >>> profile['100000'] 340 Traceback (most recent call last): 341 ... 342 TypeError: list indices must be integers 343 344 Without affecting the observation: 345 >>> profile[0] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 346 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 347 ... 'error':'0'} 348 True 349 >>> profile['10'] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 350 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 351 ... 'error':'0'} 352 True 353 """ 354 355 raise TypeError, ' '.join([repr(self.__class__.__name__), 356 'instance\'s items are read-only',]) 357 358 def __delitem__(self,key): 359 """ 360 Protect items. 361 362 del profile_instance[object] 363 364 Raise an Exception if attempting to mutate a profile: 365 >>> profile = Profile(good_profile) 366 >>> del profile[0] 367 Traceback (most recent call last): 368 ... 369 TypeError: 'Profile' instance's items are read-only 370 >>> del profile['10'] 371 Traceback (most recent call last): 372 ... 373 TypeError: 'Profile' instance's items are read-only 374 >>> del profile[100000] 375 Traceback (most recent call last): 376 ... 377 TypeError: 'Profile' instance's items are read-only 378 >>> del profile['100000'] 379 Traceback (most recent call last): 380 ... 381 TypeError: 'Profile' instance's items are read-only 382 383 Without affecting the observation: 384 >>> profile[0] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 385 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 386 ... 'error':'0'} 387 True 388 >>> profile['10'] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 389 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 390 ... 'error':'0'} 391 True 392 """ 393 394 raise TypeError, ' '.join([repr(self.__class__.__name__), 395 'instance\'s items are read-only',]) 396 397 def __setslice__(self,i,j,seq): 398 """ 399 Protect items. 400 401 profile_instance[i:j] = seq 402 403 Raise an Exception if attempting to mutate a profile: 404 >>> profile = Profile(good_profile) 405 >>> profile[0:10] = 'OK' 406 Traceback (most recent call last): 407 ... 408 TypeError: 'Profile' instance's items are read-only 409 410 Without affecting the observations: 411 >>> profile[0] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 412 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 413 ... 'error':'0'} 414 True 415 >>> profile['10'] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 416 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 417 ... 'error':'0'} 418 True 419 """ 420 421 raise TypeError, ' '.join([repr(self.__class__.__name__), 422 'instance\'s items are read-only',]) 423 424 def __delslice__(self,i,j): 425 """ 426 Protect items. 427 428 del profile_instance[i:j] 429 430 Raise an Exception if attempting to mutate a profile: 431 >>> profile = Profile(good_profile) 432 >>> del profile[0:10] 433 Traceback (most recent call last): 434 ... 435 TypeError: 'Profile' instance's items are read-only 436 437 Without affecting the observations: 438 >>> profile[0] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 439 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 440 ... 'error':'0'} 441 True 442 >>> profile['10'] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 443 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 444 ... 'error':'0'} 445 True 446 """ 447 448 raise TypeError, ' '.join([repr(self.__class__.__name__), 449 'instance\'s items are read-only',]) 450 451 def append(self,item): 452 """ 453 Protect items. 454 455 Raise an Exception if attempting to mutate a profile: 456 >>> profile = Profile(good_profile) 457 >>> profile.append('OK') 458 Traceback (most recent call last): 459 ... 460 TypeError: 'Profile' instance's items are read-only 461 462 Without affecting the observations: 463 >>> profile[0] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 464 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 465 ... 'error':'0'} 466 True 467 """ 468 469 raise TypeError, ' '.join([repr(self.__class__.__name__), 470 'instance\'s items are read-only',]) 471 472 def extend(self,seq): 473 """ 474 Protect items. 475 476 Raise an Exception if attempting to mutate a profile: 477 >>> profile = Profile(good_profile) 478 >>> profile.extend('OK') 479 Traceback (most recent call last): 480 ... 481 TypeError: 'Profile' instance's items are read-only 482 483 Without affecting the observations: 484 >>> profile[0] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 485 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 486 ... 'error':'0'} 487 True 488 """ 489 490 raise TypeError, ' '.join([repr(self.__class__.__name__), 491 'instance\'s items are read-only',]) 492 493 def insert(self,i,item): 494 """ 495 Protect items. 496 497 Raise an Exception if attempting to mutate a profile: 498 >>> profile = Profile(good_profile) 499 >>> profile.insert(0,'OK') 500 Traceback (most recent call last): 501 ... 502 TypeError: 'Profile' instance's items are read-only 503 504 Without affecting the observations: 505 >>> profile[0] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 506 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 507 ... 'error':'0'} 508 True 509 """ 510 511 raise TypeError, ' '.join([repr(self.__class__.__name__), 512 'instance\'s items are read-only',]) 513 514 def pop(self,*args): 515 """ 516 Protect items. 517 518 Raise an Exception if attempting to mutate a profile: 519 >>> profile = Profile(good_profile) 520 >>> profile.pop() 521 Traceback (most recent call last): 522 ... 523 TypeError: 'Profile' instance's items are read-only 524 >>> profile.pop(0) 525 Traceback (most recent call last): 526 ... 527 TypeError: 'Profile' instance's items are read-only 528 529 Without affecting the observations: 530 >>> profile[0] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 531 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 532 ... 'error':'0'} 533 True 534 >>> profile[-1] == {'z':'200', 'speed':'99.99', 'dir':'999.9', 535 ... 'W':'-0.07', 'sigW':'99.99', 'bck':'9.99E+37', 536 ... 'error':'0'} 537 True 538 """ 539 540 raise TypeError, ' '.join([repr(self.__class__.__name__), 541 'instance\'s items are read-only',]) 542 543 def remove(self,i): 544 """ 545 Protect items. 546 547 Raise an Exception if attempting to mutate a profile: 548 >>> profile = Profile(good_profile) 549 >>> observation = profile[0] 550 >>> profile.remove(observation) 551 Traceback (most recent call last): 552 ... 553 TypeError: 'Profile' instance's items are read-only 554 555 Without affecting the observations: 556 >>> profile[0] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 557 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 558 ... 'error':'0'} 559 True 560 """ 561 562 raise TypeError, ' '.join([repr(self.__class__.__name__), 563 'instance\'s items are read-only',]) 564 565 def reverse(self): 566 """ 567 Protect items. 568 569 Raise an Exception if attempting to mutate a profile: 570 >>> profile = Profile(good_profile) 571 >>> profile.reverse() 572 Traceback (most recent call last): 573 ... 574 TypeError: 'Profile' instance's items are read-only 575 576 Without affecting the observations: 577 >>> profile[0] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 578 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 579 ... 'error':'0'} 580 True 581 """ 582 583 raise TypeError, ' '.join([repr(self.__class__.__name__), 584 'instance\'s items are read-only',]) 585 586 def sort(self,**kwargs): 587 """ 588 Protect items. 589 590 Raise an Exception if attempting to mutate a profile: 591 >>> profile = Profile(good_profile) 592 >>> profile.sort() 593 Traceback (most recent call last): 594 ... 595 TypeError: 'Profile' instance's items are read-only 596 >>> profile.sort(cmp=lambda x,y: cmp(x.lower(), y.lower())) 597 Traceback (most recent call last): 598 ... 599 TypeError: 'Profile' instance's items are read-only 600 >>> profile.sort(cmp=lambda x,y: cmp(x.lower(), y.lower()), 601 ... key=str.lower) 602 Traceback (most recent call last): 603 ... 604 TypeError: 'Profile' instance's items are read-only 605 >>> profile.sort(cmp=lambda x,y: cmp(x.lower(), y.lower()), 606 ... key=str.lower, 607 ... reverse=True) 608 Traceback (most recent call last): 609 ... 610 TypeError: 'Profile' instance's items are read-only 611 612 613 Without affecting the observations: 614 >>> profile[0] == {'z':'10', 'speed':'99.99', 'dir':'999.9', 615 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 616 ... 'error':'0'} 617 True 618 """ 619 620 raise TypeError, ' '.join([repr(self.__class__.__name__), 621 'instance\'s items are read-only',]) 210 622 211 623 class Observation(dict): … … 223 635 ... 'error':'0'} 224 636 True 637 638 Access observation variables as attributes: 225 639 >>> observation.z 226 640 '10' … … 257 671 ... 'error':'0'} 258 672 True 673 674 Raise an Exception if more variable names than values: 259 675 >>> extra_variables = good_variables + ['extra'] 260 676 >>> observation = Observation(good_observation,extra_variables) … … 263 679 AttributeError: Same number of attributes and values required in 264 680 'Observation' object 681 682 Raise an Exception if more variable values than names: 265 683 >>> extra_observation = good_observation + ['extra'] 266 684 >>> observation = Observation(extra_observation,good_variables) … … 289 707 observation_instance.variable_name -> variable_value 290 708 709 Access observation variables as attributes: 291 710 >>> observation = Observation(good_observation,good_variables) 292 711 >>> observation.z … … 304 723 >>> observation.error 305 724 '0' 725 726 Raise an Exception for an undefined attribute: 306 727 >>> observation.y 307 728 Traceback (most recent call last): 308 729 ... 309 730 AttributeError: 'Observation' object has no attribute 'y' 731 732 Allow the creation and access of attributes other than variables. 310 733 >>> observation.y = 'OK' 311 734 >>> observation.y 312 735 'OK' 736 737 Without affecting the variables: 313 738 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 314 739 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', … … 332 757 333 758 But retrieve any other bound attribute values. 334 759 760 Raise an Exception if attempting to rebind a variable: 335 761 >>> observation = Observation(good_observation,good_variables) 336 762 >>> observation.z = 'OK' … … 339 765 AttributeError: Rebinding attribute 'z' disallowed in 340 766 'Observation' object 767 768 However, allow attributes other than variables to be bound: 341 769 >>> observation.y = 'OK' 342 770 >>> observation.y 343 771 'OK' 772 773 Without affecting the variables: 344 774 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 345 775 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', … … 366 796 367 797 But delete any other bound attribute values. 368 798 799 Raise an Exception if attempting to unbind a variable: 369 800 >>> observation = Observation(good_observation,good_variables) 370 801 >>> del observation.z … … 373 804 AttributeError: Unbinding attribute 'z' disallowed in 374 805 'Observation' object 806 807 Raise an Exception for attempting to unbind an undefined attribute: 375 808 >>> del observation.y 376 809 Traceback (most recent call last): 377 810 ... 378 811 AttributeError: 'Observation' object has no attribute 'y' 812 813 However, allow attributes other than variables to be unbound: 379 814 >>> observation.y = 'OK' 380 815 >>> del observation.y … … 383 818 ... 384 819 AttributeError: y 820 821 Without affecting the variables: 385 822 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 386 823 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', … … 406 843 observation_instance[variable_name] = variable_value 407 844 845 Raise an Exception if attempting to mutate an observation: 408 846 >>> observation = Observation(good_observation,good_variables) 409 847 >>> observation['z'] = 'OK' 410 848 Traceback (most recent call last): 411 849 ... 412 TypeError: 'Observation' object's items are read-only850 TypeError: 'Observation' instance's items are read-only 413 851 >>> observation['y'] = 'OK' 414 852 Traceback (most recent call last): 415 853 ... 416 TypeError: 'Observation' object's items are read-only 417 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 418 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 419 ... 'error':'0'} 420 True 421 """ 422 423 raise TypeError, ' '.join([repr(self.__class__.__name__), 424 'object\'s items are read-only',]) 854 TypeError: 'Observation' instance's items are read-only 855 >>> observation.y 856 Traceback (most recent call last): 857 ... 858 AttributeError: 'Observation' object has no attribute 'y' 859 >>> observation.y = 'OK' 860 >>> observation['y'] = 'Not OK' 861 Traceback (most recent call last): 862 ... 863 TypeError: 'Observation' instance's items are read-only 864 >>> observation.y 865 'OK' 866 867 Without affecting the variables: 868 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 869 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 870 ... 'error':'0'} 871 True 872 """ 873 874 raise TypeError, ' '.join([repr(self.__class__.__name__), 875 'instance\'s items are read-only',]) 425 876 426 877 def __delitem__(self,key): … … 430 881 observation_instance[variable_name] = variable_value 431 882 883 Raise an Exception if attempting to mutate an observation: 432 884 >>> observation = Observation(good_observation,good_variables) 433 885 >>> del observation['z'] 434 886 Traceback (most recent call last): 435 887 ... 436 TypeError: 'Observation' object's items are read-only 888 TypeError: 'Observation' instance's items are read-only 889 >>> observation.y = 'OK' 437 890 >>> del observation['y'] 438 891 Traceback (most recent call last): 439 892 ... 440 TypeError: 'Observation' object's items are read-only 441 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 442 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 443 ... 'error':'0'} 444 True 445 """ 446 447 raise TypeError, ' '.join([repr(self.__class__.__name__), 448 'object\'s items are read-only',]) 893 TypeError: 'Observation' instance's items are read-only 894 895 Without affecting the variables: 896 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 897 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 898 ... 'error':'0'} 899 True 900 """ 901 902 raise TypeError, ' '.join([repr(self.__class__.__name__), 903 'instance\'s items are read-only',]) 449 904 450 905 def clear(self): … … 452 907 Protect items. 453 908 909 Raise an Exception if attempting to mutate an observation: 454 910 >>> observation = Observation(good_observation,good_variables) 455 911 >>> observation.clear() 456 912 Traceback (most recent call last): 457 913 ... 458 TypeError: 'Observation' object's items are read-only 459 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 460 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 461 ... 'error':'0'} 462 True 463 """ 464 465 raise TypeError, ' '.join([repr(self.__class__.__name__), 466 'object\'s items are read-only',]) 914 TypeError: 'Observation' instance's items are read-only 915 916 Without affecting the variables: 917 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 918 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 919 ... 'error':'0'} 920 True 921 """ 922 923 raise TypeError, ' '.join([repr(self.__class__.__name__), 924 'instance\'s items are read-only',]) 467 925 468 926 def pop(self,key,*args): … … 470 928 Protect items. 471 929 930 Raise an Exception if attempting to mutate an observation: 472 931 >>> observation = Observation(good_observation,good_variables) 473 932 >>> observation.pop('z') 474 933 Traceback (most recent call last): 475 934 ... 476 TypeError: 'Observation' object's items are read-only935 TypeError: 'Observation' instance's items are read-only 477 936 >>> observation.pop('y') 478 937 Traceback (most recent call last): 479 938 ... 480 TypeError: 'Observation' object's items are read-only939 TypeError: 'Observation' instance's items are read-only 481 940 >>> observation.pop('y','OK') 482 941 Traceback (most recent call last): 483 942 ... 484 TypeError: 'Observation' object's items are read-only 485 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 486 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 487 ... 'error':'0'} 488 True 489 """ 490 491 raise TypeError, ' '.join([repr(self.__class__.__name__), 492 'object\'s items are read-only',]) 943 TypeError: 'Observation' instance's items are read-only 944 945 Without affecting the variables: 946 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 947 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 948 ... 'error':'0'} 949 True 950 """ 951 952 raise TypeError, ' '.join([repr(self.__class__.__name__), 953 'instance\'s items are read-only',]) 493 954 494 955 def popitem(self): … … 496 957 Protect items. 497 958 959 Raise an Exception if attempting to mutate an observation: 498 960 >>> observation = Observation(good_observation,good_variables) 499 961 >>> observation.popitem() 500 962 Traceback (most recent call last): 501 963 ... 502 TypeError: 'Observation' object's items are read-only 503 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 504 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 505 ... 'error':'0'} 506 True 507 """ 508 509 raise TypeError, ' '.join([repr(self.__class__.__name__), 510 'object\'s items are read-only',]) 964 TypeError: 'Observation' instance's items are read-only 965 966 Without affecting the variables: 967 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 968 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 969 ... 'error':'0'} 970 True 971 """ 972 973 raise TypeError, ' '.join([repr(self.__class__.__name__), 974 'instance\'s items are read-only',]) 511 975 512 976 def setdefault(self,key,*args): … … 514 978 Protect items. 515 979 980 Raise an Exception if attempting to mutate an observation: 516 981 >>> observation = Observation(good_observation,good_variables) 517 982 >>> observation.setdefault('z') 518 983 Traceback (most recent call last): 519 984 ... 520 TypeError: 'Observation' object's items are read-only985 TypeError: 'Observation' instance's items are read-only 521 986 >>> observation.setdefault('y') 522 987 Traceback (most recent call last): 523 988 ... 524 TypeError: 'Observation' object's items are read-only989 TypeError: 'Observation' instance's items are read-only 525 990 >>> observation.setdefault('y','OK') 526 991 Traceback (most recent call last): 527 992 ... 528 TypeError: 'Observation' object's items are read-only 529 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 530 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 531 ... 'error':'0'} 532 True 533 """ 534 535 raise TypeError, ' '.join([repr(self.__class__.__name__), 536 'object\'s items are read-only',]) 993 TypeError: 'Observation' instance's items are read-only 994 995 Without affecting the variables: 996 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 997 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 998 ... 'error':'0'} 999 True 1000 """ 1001 1002 raise TypeError, ' '.join([repr(self.__class__.__name__), 1003 'instance\'s items are read-only',]) 537 1004 538 1005 def update(self,*args,**kwargs): … … 540 1007 Protect items. 541 1008 1009 Raise an Exception if attempting to mutate an observation: 542 1010 >>> observation = Observation(good_observation,good_variables) 543 1011 >>> observation.update({'UP':'up','DOWN':'down',}) 544 1012 Traceback (most recent call last): 545 1013 ... 546 TypeError: 'Observation' object's items are read-only 547 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 548 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 549 ... 'error':'0'} 550 True 1014 TypeError: 'Observation' instance's items are read-only 1015 1016 Without affecting the variables: 1017 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 1018 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 1019 ... 'error':'0'} 1020 True 1021 1022 Raise an Exception if attempting to mutate an observation: 551 1023 >>> observation.update((('UP','up'),('DOWN','down'),)) 552 1024 Traceback (most recent call last): 553 1025 ... 554 TypeError: 'Observation' object's items are read-only 555 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 556 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 557 ... 'error':'0'} 558 True 1026 TypeError: 'Observation' instance's items are read-only 1027 1028 Without affecting the variables: 1029 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 1030 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 1031 ... 'error':'0'} 1032 True 1033 1034 Raise an Exception if attempting to mutate an observation: 559 1035 >>> observation.update(UP='up',DOWN='down') 560 1036 Traceback (most recent call last): 561 1037 ... 562 TypeError: 'Observation' object's items are read-only 563 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 564 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 565 ... 'error':'0'} 566 True 567 """ 568 569 raise TypeError, ' '.join([repr(self.__class__.__name__), 570 'object\'s items are read-only',]) 1038 TypeError: 'Observation' instance's items are read-only 1039 1040 Without affecting the variables: 1041 >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', 1042 ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', 1043 ... 'error':'0'} 1044 True 1045 """ 1046 1047 raise TypeError, ' '.join([repr(self.__class__.__name__), 1048 'instance\'s items are read-only',]) 571 1049 572 1050 def _test():