1// PyView.cpp -- 2// $Id: PyView.cpp 1230 2007-03-09 15:58:53Z jcw $ 3// This is part of MetaKit, the homepage is http://www.equi4.com/metakit.html 4// Copyright (C) 1999-2004 Gordon McMillan and Jean-Claude Wippler. 5// 6// View class implementation 7// setsize method added by J. Barnard 8 9#include "PyView.h" 10#include "PyProperty.h" 11#include "PyRowRef.h" 12#include <PWOMSequence.h> 13#include <PWONumber.h> 14#include <PWOMapping.h> 15#include <PWOCallable.h> 16 17// see pep 353 at http://www.python.org/dev/peps/pep-0353/ 18#if PY_VERSION_HEX < 0x02050000 19typedef int Py_ssize_t; 20#define PY_SSIZE_T_MAX INT_MAX 21#define PY_SSIZE_T_MIN INT_MIN 22#endif 23 24static void MustBeView(PyObject *o) { 25 if (!PyGenericView_Check(o)) 26 Fail(PyExc_TypeError, "Arg must be a view object"); 27} 28 29static char *setsize__doc = 30 "setsize(nrows) -- adjust the number of rows in a view"; 31 32static PyObject *PyView_setsize(PyView *o, PyObject *_args) { 33 try { 34 PWOSequence args(_args); 35 if (args.len() != 1) 36 Fail(PyExc_TypeError, "setsize() takes exactly one argument"); 37 PWONumber nrows = PWONumber(args[0]); 38 o->SetSize((int)nrows); 39 return nrows.disOwn(); 40 } catch (...) { 41 return 0; 42 } 43} 44 45static char *structure__doc = "structure() -- return list of properties"; 46 47static PyObject *PyView_structure(PyView *o, PyObject *_args) { 48 try { 49 PWOSequence args(_args); 50 if (args.len() != 0) 51 Fail(PyExc_TypeError, "method takes no arguments"); 52 return o->structure(); 53 } catch (...) { 54 return 0; 55 } 56} 57 58static char *properties__doc = 59 "properties() -- return a dictionary mapping property names to property objects"; 60 61static PyObject *PyView_properties(PyView *o, PyObject *_args) { 62 try { 63 PWOSequence args(_args); 64 if (args.len() != 0) 65 Fail(PyExc_TypeError, "method takes no arguments"); 66 return o->properties(); 67 } catch (...) { 68 return 0; 69 } 70} 71 72static char *insert__doc = 73 "insert(position, obj) -- coerce obj (or keyword args) to row and insert before position"; 74 75static PyObject *PyView_insert(PyView *o, PyObject *_args, PyObject *kwargs) { 76 try { 77 PWOSequence args(_args); 78 int argcount = args.len(); 79 if (argcount == 0 || argcount > 2) { 80 Fail(PyExc_TypeError, 81 "insert() takes exactly two arguments, or one argument and keyword arguments"); 82 } else { 83 int size = PWONumber(o->GetSize()), ndx = PWONumber(args[0]); 84 if (ndx < 0) { 85 ndx += size; 86 if (ndx < 0) { 87 ndx = 0; 88 } 89 } else if (ndx > size) { 90 ndx = size; 91 } 92 if (argcount == 1) 93 o->insertAt(ndx, kwargs); 94 else if (argcount == 2) 95 o->insertAt(ndx, args[1]); 96 Py_INCREF(Py_None); 97 return Py_None; 98 } 99 } catch (...){} 100 return 0; /* satisfy compiler */ 101} 102 103static char *append__doc = 104 "append(obj) -- coerce obj (or keyword args) to row and append, returns position"; 105 106static PyObject *PyView_append(PyView *o, PyObject *_args, PyObject *kwargs) { 107 try { 108 PWOSequence args(_args); 109 PWONumber ndx(o->GetSize()); 110 int argcount = args.len(); 111 if (argcount == 0) 112 o->insertAt(ndx, kwargs); 113 else if (argcount == 1) 114 o->insertAt(ndx, args[0]); 115 else 116 Fail(PyExc_TypeError, 117 "append() takes exactly one argument, or multiple keyword arguments"); 118 return ndx.disOwn(); 119 } catch (...) { 120 return 0; 121 } 122} 123 124static char *delete__doc = 125 "delete(position) -- delete row at specified position"; 126 127static PyObject *PyView_delete(PyView *o, PyObject *_args) { 128 try { 129 PWOSequence args(_args); 130 int ndx = PWONumber(args[0]); 131 PWOTuple seq; 132 o->setSlice(ndx, ndx + 1, seq); 133 Py_INCREF(Py_None); 134 return Py_None; 135 } catch (...) { 136 return 0; 137 } 138} 139 140static char *addproperty__doc = 141 "addproperty(property) -- add temp column to view (use getas() for persistent columns)"; 142 143static PyObject *PyView_addproperty(PyView *o, PyObject *_args) { 144 try { 145 PWOSequence args(_args); 146 PWOBase prop(args[0]); 147 if (!PyProperty_Check((PyObject*)prop)) 148 Fail(PyExc_TypeError, "Not a Property object"); 149 PWONumber rslt(o->AddProperty(*(PyProperty*)(PyObject*)prop)); 150 return rslt.disOwn(); 151 } catch (...) { 152 return 0; 153 } 154} 155 156static char *select__doc = 157 "select(criteria) -- return virtual view with selected rows\n" 158 "select(crit_lo, crit_hi) -- select rows in specified range (inclusive)\n" 159 " criteria may be keyword args or dictionary"; 160 161static PyObject *PyView_select(PyView *o, PyObject *_args, PyObject *kwargs) { 162 try { 163 c4_Row temp; 164 PWOSequence args(_args); 165 if (args.len() == 0) { 166 o->makeRow(temp, kwargs, false); 167 return new PyView(o->Select(temp), o, o->computeState(NOTIFIABLE)); 168 } 169 if (args.len() == 1) { 170 o->makeRow(temp, args[0], false); 171 return new PyView(o->Select(temp), o, o->computeState(NOTIFIABLE)); 172 } 173 174 if (PyObject_Length(args[0]) > 0) 175 o->makeRow(temp, args[0], false); 176 177 c4_Row temp2; // force an error if neither boundary has useful values 178 if (temp.Container().NumProperties() == 0 || PyObject_Length(args[1]) > 0) 179 o->makeRow(temp2, args[1], false); 180 181 return new PyView(o->SelectRange(temp, temp2), o, o->computeState 182 (NOTIFIABLE)); 183 } catch (...) { 184 return 0; 185 } 186} 187 188static char *sort__doc = 189 "sort() -- return virtual sorted view (native key order)\n" 190 "sort(property...) -- sort on the specified properties"; 191 192static PyObject *PyView_sort(PyView *o, PyObject *_args) { 193 try { 194 PWOSequence args(_args); 195 if (args.len()) { 196 PyView crit; 197 crit.addProperties(args); 198 return new PyView(o->SortOn(crit), o, o->computeState(FINALNOTIFIABLE)); 199 } 200 return new PyView(o->Sort(), o, o->computeState(FINALNOTIFIABLE)); 201 } catch (...) { 202 return 0; 203 } 204} 205 206static char *sortrev__doc = 207 "sortrev(props,propsdown) -- return sorted view, with optional reversed order\n"" arguments are lists of properties"; 208 209static PyObject *PyView_sortrev(PyView *o, PyObject *_args) { 210 try { 211 PWOSequence args(_args); 212 213 PWOSequence all(args[0]); 214 PyView propsAll; 215 propsAll.addProperties(all); 216 217 PWOSequence down(args[1]); 218 PyView propsDown; 219 propsDown.addProperties(down); 220 221 return new PyView(o->SortOnReverse(propsAll, propsDown), 0, o->computeState 222 (FINALNOTIFIABLE)); 223 } catch (...) { 224 return 0; 225 } 226} 227 228static char *project__doc = 229 "project(property...) -- returns virtual view with only the named columns"; 230 231static PyObject *PyView_project(PyView *o, PyObject *_args) { 232 try { 233 PWOSequence args(_args); 234 PyView crit; 235 crit.addProperties(args); 236 return new PyView(o->Project(crit), 0, o->computeState(NOTIFIABLE)); 237 } catch (...) { 238 return 0; 239 } 240} 241 242static char *flatten__doc = 243 "flatten(subview_property, outer) -- produces 'flat' view from nested view\n" 244 " outer defaults to 0"; 245 246static PyObject *PyView_flatten(PyView *o, PyObject *_args, PyObject *_kwargs) { 247 try { 248 PWOSequence args(_args); 249 PWOMapping kwargs; 250 if (_kwargs) 251 kwargs = PWOBase(_kwargs); 252 if (!PyProperty_Check((PyObject*)args[0])) 253 Fail(PyExc_TypeError, 254 "First arg must be a property object identifying the subview"); 255 const c4_Property &subview = *(PyProperty*)(PyObject*)args[0]; 256 bool outer = false; 257 if (args.len() > 1) { 258 PWONumber flag(args[1]); 259 if ((int)flag > 0) 260 outer = true; 261 } 262 if (kwargs.hasKey("outer")) { 263 if (int(PWONumber(kwargs["outer"]))) 264 outer = true; 265 } 266 return new PyView(o->JoinProp((const c4_ViewProp &)subview, outer), 0, o 267 ->computeState(ROVIEWER)); 268 } catch (...) { 269 return 0; 270 } 271} 272 273static char *join__doc = 274 "join(otherview, property..., outer) -- join views on properties of same name and type\n"" outer defaults to 0"; 275 276static PyObject *PyView_join(PyView *o, PyObject *_args, PyObject *_kwargs) { 277 PWOMapping kwargs; 278 try { 279 PWOSequence args(_args); 280 if (_kwargs) 281 kwargs = PWOBase(_kwargs); 282 MustBeView(args[0]); 283 PyView *other = (PyView*)(PyObject*)args[0]; 284 bool outer = false; 285 int last = args.len(); 286 if (PyInt_Check((PyObject*)args[last - 1])) { 287 PWONumber flag(args[--last]); 288 if ((int)flag > 0) 289 outer = true; 290 } 291 if (kwargs.hasKey("outer")) { 292 if (int(PWONumber(kwargs["outer"]))) 293 outer = true; 294 } 295 PyView crit; 296 crit.addProperties(args.getSlice(1, last)); 297 return new PyView(o->Join(crit, *other, outer), 0, o->computeState 298 (ROVIEWER)); 299 } catch (...) { 300 return 0; 301 } 302} 303 304static char *groupby__doc = 305 "groupby(property..., 'subname') -- group by given properties, creating subviews"; 306 307static PyObject *PyView_groupby(PyView *o, PyObject *_args) { 308 try { 309 PWOSequence args(_args); 310 int last = args.len(); 311 PWOString subname(args[--last]); 312 PyView crit; 313 crit.addProperties(args.getSlice(0, last)); 314 c4_ViewProp sub(subname); 315 return new PyView(o->GroupBy(crit, sub), 0, o->computeState(ROVIEWER)); 316 } catch (...) { 317 return 0; 318 } 319} 320 321static char *counts__doc = 322 "counts(property..., 'name') -- group by given properties, adding a count property"; 323 324static PyObject *PyView_counts(PyView *o, PyObject *_args) { 325 try { 326 PWOSequence args(_args); 327 int last = args.len(); 328 PWOString name(args[--last]); 329 PyView crit; 330 crit.addProperties(args.getSlice(0, last)); 331 c4_IntProp count(name); 332 return new PyView(o->Counts(crit, count), 0, o->computeState(ROVIEWER)); 333 } catch (...) { 334 return 0; 335 } 336} 337 338static char *rename__doc = 339 "rename('oldname', 'newname') -- derive a view with one property renamed"; 340 341static PyObject *PyView_rename(PyView *o, PyObject *_args) { 342 try { 343 PWOSequence args(_args); 344 345 PWOString oldName(args[0]); 346 int n = o->FindPropIndexByName(oldName); 347 if (n < 0) 348 Fail(PyExc_TypeError, "Property not found in view"); 349 const c4_Property &oProp = o->NthProperty(n); 350 351 PWOString newName(args[1]); 352 c4_Property nProp(oProp.Type(), newName); 353 354 return new PyView(o->Rename(oProp, nProp), 0, o->computeState(RWVIEWER)); 355 } catch (...) { 356 return 0; 357 } 358} 359 360static char *unique__doc = 361 "unique() -- returns a view without duplicate rows, i.e. a set"; 362 363static PyObject *PyView_unique(PyView *o, PyObject *_args) { 364 try { 365 return new PyView(o->Unique(), 0, o->computeState(ROVIEWER)); 366 } catch (...) { 367 return 0; 368 } 369} 370 371static char *product__doc = 372 "product(view2) -- produce the cartesian product of both views"; 373 374static PyObject *PyView_product(PyView *o, PyObject *_args) { 375 try { 376 PWOSequence args(_args); 377 MustBeView(args[0]); 378 return new PyView(o->Product(*(PyView*)(PyObject*)args[0]), 0, o 379 ->computeState(ROVIEWER)); 380 } catch (...) { 381 return 0; 382 } 383} 384 385static char *union__doc = "union(view2) -- produce the set union of both views"; 386 387static PyObject *PyView_union(PyView *o, PyObject *_args) { 388 try { 389 PWOSequence args(_args); 390 MustBeView(args[0]); 391 return new PyView(o->Union(*(PyView*)(PyObject*)args[0]), 0, o 392 ->computeState(ROVIEWER)); 393 } catch (...) { 394 return 0; 395 } 396} 397 398static char *intersect__doc = 399 "intersect(view2) -- produce the set intersection of both views"; 400 401static PyObject *PyView_intersect(PyView *o, PyObject *_args) { 402 try { 403 PWOSequence args(_args); 404 MustBeView(args[0]); 405 return new PyView(o->Intersect(*(PyView*)(PyObject*)args[0]), 0, o 406 ->computeState(ROVIEWER)); 407 } catch (...) { 408 return 0; 409 } 410} 411 412static char *different__doc = 413 "different(view2) -- produce the set difference of both views (XOR)"; 414 415static PyObject *PyView_different(PyView *o, PyObject *_args) { 416 try { 417 PWOSequence args(_args); 418 MustBeView(args[0]); 419 return new PyView(o->Different(*(PyView*)(PyObject*)args[0]), 0, o 420 ->computeState(ROVIEWER)); 421 } catch (...) { 422 return 0; 423 } 424} 425 426static char *minus__doc = "minus(view2) -- all rows in view, but not in view2"; 427 428static PyObject *PyView_minus(PyView *o, PyObject *_args) { 429 try { 430 PWOSequence args(_args); 431 MustBeView(args[0]); 432 return new PyView(o->Minus(*(PyView*)(PyObject*)args[0]), 0, o 433 ->computeState(ROVIEWER)); 434 } catch (...) { 435 return 0; 436 } 437} 438 439static char *remapwith__doc = 440 "remapwith(view2) -- remap rows according to first (int) prop in view2"; 441 442static PyObject *PyView_remapwith(PyView *o, PyObject *_args) { 443 try { 444 PWOSequence args(_args); 445 MustBeView(args[0]); 446 return new PyView(o->RemapWith(*(PyView*)(PyObject*)args[0]), 0, o 447 ->computeState(RWVIEWER)); 448 } catch (...) { 449 return 0; 450 } 451} 452 453static char *pair__doc = 454 "pair(view2) -- concatenate rows pairwise, side by side"; 455 456static PyObject *PyView_pair(PyView *o, PyObject *_args) { 457 try { 458 PWOSequence args(_args); 459 MustBeView(args[0]); 460 return new PyView(o->Pair(*(PyView*)(PyObject*)args[0]), 0, o->computeState 461 (MVIEWER)); 462 } catch (...) { 463 return 0; 464 } 465} 466 467static char *hash__doc = 468 "hash(mapview,numkeys) -- create a hashed view mapping\n" 469 " numkeys defaults to 1\n" 470 " without args, creates a temporary hash on one key"; 471 472static PyObject *PyView_hash(PyView *o, PyObject *_args) { 473 try { 474 PWOSequence args(_args); 475 476 c4_View map; 477 if (args.len() > 0) { 478 MustBeView(args[0]); 479 map = *(PyView*)(PyObject*)args[0]; 480 } 481 int numkeys = args.len() <= 1 ? 1 : (int)PWONumber(args[1]); 482 return new PyView(o->Hash(map, numkeys), 0, o->computeState(MVIEWER)); 483 } catch (...) { 484 return 0; 485 } 486} 487 488static char *blocked__doc = 489 "blocked() -- create a blocked/balanced view mapping"; 490 491static PyObject *PyView_blocked(PyView *o, PyObject *_args) { 492 try { 493 return new PyView(o->Blocked(), 0, o->computeState(MVIEWER)); 494 } catch (...) { 495 return 0; 496 } 497} 498 499static char *ordered__doc = 500 "ordered(numkeys) -- create a order-maintaining view mapping\n" 501 " numkeys defaults to 1"; 502 503static PyObject *PyView_ordered(PyView *o, PyObject *_args) { 504 try { 505 PWOSequence args(_args); 506 int numkeys = args.len() <= 0 ? 1 : (int)PWONumber(args[0]); 507 return new PyView(o->Ordered(numkeys), 0, o->computeState(MVIEWER)); 508 } catch (...) { 509 return 0; 510 } 511} 512 513static char *indexed__doc = 514 "indexed(map, property..., unique) -- create a mapped view which manages an index\n"" unique defaults to 0 (not unique)"; 515 516static PyObject *PyView_indexed(PyView *o, PyObject *_args) { 517 try { 518 PWOSequence args(_args); 519 MustBeView(args[0]); 520 PyView *other = (PyView*)(PyObject*)args[0]; 521 bool unique = false; 522 int last = args.len(); 523 if (PyInt_Check((PyObject*)args[last - 1])) { 524 PWONumber flag(args[--last]); //XXX kwargs? 525 if ((int)flag > 0) 526 unique = true; 527 } 528 PyView crit; 529 crit.addProperties(args.getSlice(1, last)); 530 return new PyView(o->Indexed(crit, *other, unique), 0, o->computeState 531 (MVIEWER)); 532 } catch (...) { 533 return 0; 534 } 535} 536 537static char *find__doc = 538 "find(criteria, start) -- return index of row found, matching criteria\n" 539 " criteria maybe keyword args, or a dictionary"; 540 541static PyObject *PyView_find(PyView *o, PyObject *_args, PyObject *_kwargs) { 542 PWONumber start(0); 543 PWOMapping crit; 544 try { 545 PWOSequence args(_args); 546 if (_kwargs) { 547 PWOMapping kwargs(_kwargs); 548 if (kwargs.hasKey("start")) { 549 start = kwargs["start"]; 550 kwargs.delItem("start"); 551 } 552 crit = kwargs; 553 } 554 int numargs = args.len(); 555 for (int i = 0; i < numargs; ++i) { 556 if (PyNumber_Check((PyObject*)args[i])) 557 start = args[i]; 558 else 559 crit = args[i]; 560 } 561 c4_Row temp; 562 o->makeRow(temp, crit, false); 563 return PWONumber(o->Find(temp, start)).disOwn(); 564 } catch (...) { 565 return 0; 566 } 567} 568 569static char *search__doc = 570 "search(criteria) -- binary search (native view order), returns match or insert pos"; 571 572static PyObject *PyView_search(PyView *o, PyObject *_args, PyObject *kwargs) { 573 try { 574 PWOSequence args(_args); 575 if (args.len() != 0) 576 kwargs = args[0]; 577 c4_Row temp; 578 o->makeRow(temp, kwargs, false); 579 return PWONumber(o->Search(temp)).disOwn(); 580 } catch (...) { 581 return 0; 582 } 583} 584 585static char *locate__doc = 586 "locate(criteria) -- binary search, returns tuple with pos and count"; 587 588static PyObject *PyView_locate(PyView *o, PyObject *_args, PyObject *kwargs) { 589 try { 590 PWOSequence args(_args); 591 if (args.len() != 0) 592 kwargs = args[0]; 593 c4_Row temp; 594 o->makeRow(temp, kwargs, false); 595 int pos = 0; 596 PWONumber n(o->Locate(temp, &pos)); 597 PWONumber r(pos); 598 PWOTuple tmp(2); 599 tmp.setItem(0, r); 600 tmp.setItem(1, n); 601 return tmp.disOwn(); 602 } catch (...) { 603 return 0; 604 } 605} 606 607static char *access__doc = 608 "access(memoprop, rownum, offset, length=0) -- get (partial) memo property contents"; 609 610static PyObject *PyView_access(PyView *o, PyObject *_args) { 611 try { 612 PWOSequence args(_args); 613 if (!PyProperty_Check((PyObject*)args[0])) 614 Fail(PyExc_TypeError, "First arg must be a property"); 615 616 c4_BytesProp &prop = *(c4_BytesProp*)(c4_Property*)(PyProperty*)(PyObject*) 617 args[0]; 618 619 int index = PyInt_AsLong(args[1]); 620 if (index < 0 || index >= o->GetSize()) 621 Fail(PyExc_IndexError, "Index out of range"); 622 623 c4_RowRef row = o->GetAt(index); 624 625 long offset = PyInt_AsLong(args[2]); 626 int length = args.len() == 3 ? 0 : PyInt_AsLong(args[3]); 627 if (length <= 0) { 628 length = prop(row).GetSize() - offset; 629 if (length < 0) 630 length = 0; 631 } 632 633 PyObject *buffer = PyString_FromStringAndSize(0, length); 634 int o = 0; 635 636 while (o < length) { 637 c4_Bytes buf = prop(row).Access(offset + o, length - o); 638 int n = buf.Size(); 639 if (n == 0) 640 break; 641 memcpy(PyString_AS_STRING(buffer) + o, buf.Contents(), n); 642 o += n; 643 } 644 645 if (o < length) 646 _PyString_Resize(&buffer, o); 647 648 return buffer; 649 } catch (...) { 650 return 0; 651 } 652} 653 654static char *modify__doc = 655 "modify(memoprop, rownum, string, offset, diff=0) -- store (partial) memo contents\n""diff removes (<0) or inserts (>0) bytes, and is adjusted to within sensible range"; 656 657static PyObject *PyView_modify(PyView *o, PyObject *_args) { 658 try { 659 PWOSequence args(_args); 660 if (!PyProperty_Check((PyObject*)args[0])) 661 Fail(PyExc_TypeError, "First arg must be a property"); 662 663 c4_BytesProp &prop = *(c4_BytesProp*)(c4_Property*)(PyProperty*)(PyObject*) 664 args[0]; 665 666 int index = PWONumber(args[1]); 667 if (index < 0 || index >= o->GetSize()) 668 Fail(PyExc_IndexError, "Index out of range"); 669 670 c4_RowRef row = o->GetAt(index); 671 672 PWOString buffer(args[2]); 673 c4_Bytes data((void*)(const char*)buffer, buffer.len()); 674 675 long offset = PWONumber(args[3]); 676 int diff = args.len() == 4 ? 0 : (int)PWONumber(args[4]); 677 678 if (!prop(row).Modify(data, offset, diff)) 679 Fail(PyExc_TypeError, "Failed to modify memo field"); 680 681 Py_INCREF(Py_None); 682 return Py_None; 683 } catch (...) { 684 return 0; 685 } 686} 687 688static char *itemsize__doc = 689 "itemsize(prop, rownum=0) -- return size of item (rownum only needed for S/B/M types)\n""with integer fields, a result of -1/-2/-4 means 1/2/4 bits per value, respectively"; 690 691static PyObject *PyView_itemsize(PyView *o, PyObject *_args) { 692 try { 693 PWOSequence args(_args); 694 if (!PyProperty_Check((PyObject*)args[0])) 695 Fail(PyExc_TypeError, "First arg must be a property"); 696 697 c4_BytesProp &prop = *(c4_BytesProp*)(c4_Property*)(PyProperty*)(PyObject*) 698 args[0]; 699 int index = args.len() == 1 ? 0 : (int)PWONumber(args[1]); 700 if (index < 0 || index >= o->GetSize()) 701 Fail(PyExc_IndexError, "Index out of range"); 702 703 return PWONumber(prop(o->GetAt(index)).GetSize()).disOwn(); 704 } catch (...) { 705 return 0; 706 } 707} 708 709static char *relocrows__doc = 710 "relocrows(from, count, dest, pos) -- relocate rows within views of same storage\n""from is source offset, count is number of rows, pos is destination offset\n""both views must have a compatible structure (field names may differ)"; 711 712static PyObject *PyView_relocrows(PyView *o, PyObject *_args) { 713 try { 714 PWOSequence args(_args); 715 if (!PyView_Check((PyObject*)args[2])) 716 Fail(PyExc_TypeError, "Third arg must be a view object"); 717 718 PyView &dest = *(PyView*)(PyObject*)args[2]; 719 720 int from = PWONumber(args[0]); 721 if (from < 0) 722 from += o->GetSize(); 723 int count = PWONumber(args[1]); 724 if (from < 0 || count < 0 || from + count > o->GetSize()) 725 Fail(PyExc_IndexError, "Source index out of range"); 726 727 int pos = PWONumber(args[3]); 728 if (pos < 0) 729 pos += dest.GetSize(); 730 if (pos < 0 || pos > dest.GetSize()) 731 Fail(PyExc_IndexError, "Destination index out of range"); 732 733 if (!o->IsCompatibleWith(dest)) 734 Fail(PyExc_TypeError, "Views are not compatible"); 735 736 o->RelocateRows(from, count, dest, pos); 737 738 Py_INCREF(Py_None); 739 return Py_None; 740 } catch (...) { 741 return 0; 742 } 743} 744 745static char *map__doc = 746 "map(func, subset=None) -- apply func to each row of view,\n" 747 "or (if subset specified) to each row in view that is also in subset.\n" 748 "Returns None: view is mutated\n" 749 "func must have the signature func(row), and may mutate row.\n" 750 "subset must be a subset of view: eg, customers.map(func, customers.select(....)).\n"; 751 752static PyObject *PyView_map(PyView *o, PyObject *_args) { 753 try { 754 PWOSequence args(_args); 755 PWOCallable func(args[0]); 756 if (args.len() > 1) { 757 if (!PyView_Check((PyObject*)args[1])) 758 Fail(PyExc_TypeError, "Second arg must be a view object"); 759 760 PyView &subset = *(PyView*)(PyObject*)args[1]; 761 762 o->map(func, subset); 763 } else 764 o->map(func); 765 766 Py_INCREF(Py_None); 767 return Py_None; 768 } catch (...) { 769 return 0; 770 } 771} 772 773static char *filter__doc = 774 "filter(func) -- return a new view containing the indices of those rows satisfying func.\n"" func must have the signature func(row), and should return a false value to omit row."; 775 776static PyObject *PyView_filter(PyView *o, PyObject *_args) { 777 try { 778 PWOSequence args(_args); 779 PWOCallable func(args[0]); 780 return o->filter(func); 781 } catch (...) { 782 return 0; 783 } 784} 785 786static char *reduce__doc = 787 "reduce(func, start=0) -- return the result of applying func(row, lastresult) to\n""each row in view.\n"; 788 789static PyObject *PyView_reduce(PyView *o, PyObject *_args) { 790 try { 791 PWOSequence args(_args); 792 PWOCallable func(args[0]); 793 PWONumber start(0); 794 if (args.len() > 1) 795 start = args[1]; 796 return o->reduce(func, start); 797 } catch (...) { 798 return 0; 799 } 800} 801 802static char *remove__doc = 803 "remove(indices) -- remove all rows whose indices are in subset from view\n" 804 "Not the same as minus, because unique is not required, and view is not reordered.\n"; 805 806static PyObject *PyView_remove(PyView *o, PyObject *_args) { 807 try { 808 PWOSequence args(_args); 809 MustBeView(args[0]); 810 811 PyView &subset = *(PyView*)(PyObject*)args[0]; 812 o->remove(subset); 813 Py_INCREF(Py_None); 814 return Py_None; 815 } catch (...) { 816 return 0; 817 } 818} 819 820static char *indices__doc = 821 "indices(subset) -- returns a view containing the indices in view of the rows of subset"; 822 823static PyObject *PyView_indices(PyView *o, PyObject *_args) { 824 try { 825 PWOSequence args(_args); 826 MustBeView(args[0]); 827 828 PyView &subset = *(PyView*)(PyObject*)args[0]; 829 return o->indices(subset); 830 } catch (...) { 831 return 0; 832 } 833} 834 835static char *copy__doc = "copy() -- returns a copy of the view\n"; 836 837static PyObject *PyView_copy(PyView *o, PyObject *_args) { 838 try { 839 return new PyView(o->Duplicate()); 840 } catch (...) { 841 return 0; 842 } 843} 844 845static PyMethodDef ViewMethods[] = { 846 { 847 "setsize", (PyCFunction)PyView_setsize, METH_VARARGS, setsize__doc 848 } 849 , { 850 "insert", (PyCFunction)PyView_insert, METH_VARARGS | METH_KEYWORDS, 851 insert__doc 852 } 853 , { 854 "append", (PyCFunction)PyView_append, METH_VARARGS | METH_KEYWORDS, 855 append__doc 856 } 857 , { 858 "delete", (PyCFunction)PyView_delete, METH_VARARGS, delete__doc 859 } 860 , { 861 "structure", (PyCFunction)PyView_structure, METH_VARARGS, structure__doc 862 } 863 , { 864 "select", (PyCFunction)PyView_select, METH_VARARGS | METH_KEYWORDS, 865 select__doc 866 } 867 , { 868 "addproperty", (PyCFunction)PyView_addproperty, METH_VARARGS, 869 addproperty__doc 870 } 871 , { 872 "sort", (PyCFunction)PyView_sort, METH_VARARGS, sort__doc 873 } 874 , { 875 "sortrev", (PyCFunction)PyView_sortrev, METH_VARARGS, sortrev__doc 876 } 877 , { 878 "project", (PyCFunction)PyView_project, METH_VARARGS, project__doc 879 } 880 , { 881 "flatten", (PyCFunction)PyView_flatten, METH_VARARGS | METH_KEYWORDS, 882 flatten__doc 883 } 884 , { 885 "join", (PyCFunction)PyView_join, METH_VARARGS | METH_KEYWORDS, join__doc 886 } 887 , { 888 "groupby", (PyCFunction)PyView_groupby, METH_VARARGS, groupby__doc 889 } 890 , { 891 "counts", (PyCFunction)PyView_counts, METH_VARARGS, counts__doc 892 } 893 , { 894 "product", (PyCFunction)PyView_product, METH_VARARGS, product__doc 895 } 896 , { 897 "union", (PyCFunction)PyView_union, METH_VARARGS, union__doc 898 } 899 , { 900 "intersect", (PyCFunction)PyView_intersect, METH_VARARGS, intersect__doc 901 } 902 , { 903 "different", (PyCFunction)PyView_different, METH_VARARGS, different__doc 904 } 905 , { 906 "minus", (PyCFunction)PyView_minus, METH_VARARGS, minus__doc 907 } 908 , { 909 "remapwith", (PyCFunction)PyView_remapwith, METH_VARARGS, remapwith__doc 910 } 911 , { 912 "pair", (PyCFunction)PyView_pair, METH_VARARGS, pair__doc 913 } 914 , { 915 "rename", (PyCFunction)PyView_rename, METH_VARARGS, rename__doc 916 } 917 , { 918 "unique", (PyCFunction)PyView_unique, METH_VARARGS, unique__doc 919 } 920 , { 921 "hash", (PyCFunction)PyView_hash, METH_VARARGS, hash__doc 922 } 923 , { 924 "blocked", (PyCFunction)PyView_blocked, METH_VARARGS, blocked__doc 925 } 926 , { 927 "ordered", (PyCFunction)PyView_ordered, METH_VARARGS, ordered__doc 928 } 929 , { 930 "indexed", (PyCFunction)PyView_indexed, METH_VARARGS, indexed__doc 931 } 932 , { 933 "find", (PyCFunction)PyView_find, METH_VARARGS | METH_KEYWORDS, find__doc 934 } 935 , { 936 "search", (PyCFunction)PyView_search, METH_VARARGS | METH_KEYWORDS, 937 search__doc 938 } 939 , { 940 "locate", (PyCFunction)PyView_locate, METH_VARARGS | METH_KEYWORDS, 941 locate__doc 942 } 943 , { 944 "access", (PyCFunction)PyView_access, METH_VARARGS, access__doc 945 } 946 , { 947 "modify", (PyCFunction)PyView_modify, METH_VARARGS, modify__doc 948 } 949 , { 950 "itemsize", (PyCFunction)PyView_itemsize, METH_VARARGS, itemsize__doc 951 } 952 , 953 // {"relocrows", (PyCFunction)PyView_relocrows, METH_VARARGS, relocrows__doc}, 954 { 955 "map", (PyCFunction)PyView_map, METH_VARARGS, map__doc 956 } 957 , { 958 "filter", (PyCFunction)PyView_filter, METH_VARARGS, filter__doc 959 } 960 , { 961 "reduce", (PyCFunction)PyView_reduce, METH_VARARGS, reduce__doc 962 } 963 , { 964 "remove", (PyCFunction)PyView_remove, METH_VARARGS, remove__doc 965 } 966 , { 967 "indices", (PyCFunction)PyView_indices, METH_VARARGS, indices__doc 968 } 969 , { 970 "copy", (PyCFunction)PyView_copy, METH_VARARGS, copy__doc 971 } 972 , { 973 "properties", (PyCFunction)PyView_properties, METH_VARARGS, properties__doc 974 } 975 , { 976 0, 0, 0, 0 977 } 978}; 979static PyMethodDef ViewerMethods[] = { 980 { 981 "structure", (PyCFunction)PyView_structure, METH_VARARGS, structure__doc 982 } 983 , { 984 "select", (PyCFunction)PyView_select, METH_VARARGS | METH_KEYWORDS, 985 select__doc 986 } 987 , { 988 "addproperty", (PyCFunction)PyView_addproperty, METH_VARARGS, 989 addproperty__doc 990 } 991 , { 992 "sort", (PyCFunction)PyView_sort, METH_VARARGS, sort__doc 993 } 994 , { 995 "sortrev", (PyCFunction)PyView_sortrev, METH_VARARGS, sortrev__doc 996 } 997 , { 998 "project", (PyCFunction)PyView_project, METH_VARARGS, project__doc 999 } 1000 , { 1001 "flatten", (PyCFunction)PyView_flatten, METH_VARARGS | METH_KEYWORDS, 1002 flatten__doc 1003 } 1004 , { 1005 "join", (PyCFunction)PyView_join, METH_VARARGS | METH_KEYWORDS, join__doc 1006 } 1007 , { 1008 "groupby", (PyCFunction)PyView_groupby, METH_VARARGS, groupby__doc 1009 } 1010 , { 1011 "counts", (PyCFunction)PyView_counts, METH_VARARGS, counts__doc 1012 } 1013 , { 1014 "product", (PyCFunction)PyView_product, METH_VARARGS, product__doc 1015 } 1016 , { 1017 "union", (PyCFunction)PyView_union, METH_VARARGS, union__doc 1018 } 1019 , { 1020 "intersect", (PyCFunction)PyView_intersect, METH_VARARGS, intersect__doc 1021 } 1022 , { 1023 "different", (PyCFunction)PyView_different, METH_VARARGS, different__doc 1024 } 1025 , { 1026 "minus", (PyCFunction)PyView_minus, METH_VARARGS, minus__doc 1027 } 1028 , { 1029 "remapwith", (PyCFunction)PyView_remapwith, METH_VARARGS, remapwith__doc 1030 } 1031 , { 1032 "pair", (PyCFunction)PyView_pair, METH_VARARGS, pair__doc 1033 } 1034 , { 1035 "rename", (PyCFunction)PyView_rename, METH_VARARGS, rename__doc 1036 } 1037 , { 1038 "unique", (PyCFunction)PyView_unique, METH_VARARGS, unique__doc 1039 } 1040 , { 1041 "hash", (PyCFunction)PyView_hash, METH_VARARGS, hash__doc 1042 } 1043 , { 1044 "blocked", (PyCFunction)PyView_blocked, METH_VARARGS, blocked__doc 1045 } 1046 , { 1047 "ordered", (PyCFunction)PyView_ordered, METH_VARARGS, ordered__doc 1048 } 1049 , { 1050 "indexed", (PyCFunction)PyView_indexed, METH_VARARGS, indexed__doc 1051 } 1052 , { 1053 "find", (PyCFunction)PyView_find, METH_VARARGS | METH_KEYWORDS, find__doc 1054 } 1055 , { 1056 "search", (PyCFunction)PyView_search, METH_VARARGS | METH_KEYWORDS, 1057 search__doc 1058 } 1059 , { 1060 "locate", (PyCFunction)PyView_locate, METH_VARARGS | METH_KEYWORDS, 1061 locate__doc 1062 } 1063 , { 1064 "access", (PyCFunction)PyView_access, METH_VARARGS, access__doc 1065 } 1066 , { 1067 "modify", (PyCFunction)PyView_modify, METH_VARARGS, modify__doc 1068 } 1069 , { 1070 "itemsize", (PyCFunction)PyView_itemsize, METH_VARARGS, itemsize__doc 1071 } 1072 , 1073 //{"map", (PyCFunction)PyView_map, METH_VARARGS, map__doc}, 1074 { 1075 "filter", (PyCFunction)PyView_filter, METH_VARARGS, filter__doc 1076 } 1077 , { 1078 "reduce", (PyCFunction)PyView_reduce, METH_VARARGS, reduce__doc 1079 } 1080 , { 1081 "indices", (PyCFunction)PyView_indices, METH_VARARGS, indices__doc 1082 } 1083 , { 1084 "copy", (PyCFunction)PyView_copy, METH_VARARGS, copy__doc 1085 } 1086 , { 1087 "properties", (PyCFunction)PyView_properties, METH_VARARGS, properties__doc 1088 } 1089 , { 1090 0, 0, 0, 0 1091 } 1092}; 1093 1094/* 1095Duplicate(deep=0) (__copy__ and __deepcopy__ as methods, too) 1096Clone() 1097 */ 1098static Py_ssize_t PyView_length(PyObject *_o) { 1099 PyView *o = (PyView*)_o; 1100 1101 try { 1102 return o->GetSize(); 1103 } catch (...) { 1104 return - 1; 1105 } 1106} 1107 1108static PyObject *PyView_concat(PyObject *_o, PyObject *_other) { 1109 PyView *o = (PyView*)_o; 1110 PyView *other = (PyView*)_other; 1111 1112 try { 1113 if (!PyGenericView_Check(other)) 1114 Fail(PyExc_TypeError, "Not a PyView(er)"); 1115 return new PyView(o->Concat(*other), 0, o->computeState(RWVIEWER)); 1116 } catch (...) { 1117 return 0; 1118 } 1119} 1120 1121static PyObject *PyView_repeat(PyObject *_o, Py_ssize_t n) { 1122 PyView *o = (PyView*)_o; 1123 1124 try { 1125 PyView *tmp = new PyView(*o, 0, o->computeState(RWVIEWER)); 1126 while (--n > 0) { 1127 //!! a huge stack of views? 1128 PyView *tmp1 = new PyView(tmp->Concat(*o), 0, o->computeState(RWVIEWER)); 1129 delete tmp; 1130 tmp = tmp1; 1131 } 1132 return tmp; 1133 } catch (...) { 1134 return 0; 1135 } 1136} 1137 1138static PyObject *PyView_getitem(PyObject *_o, Py_ssize_t n) { 1139 PyView *o = (PyView*)_o; 1140 1141 try { 1142 PyObject *rslt = o->getItem(n); 1143 if (rslt == 0) 1144 PyErr_SetString(PyExc_IndexError, "row index out of range"); 1145 return rslt; 1146 } catch (...) { 1147 return 0; 1148 } 1149} 1150 1151static PyObject *PyView_getslice(PyObject *_o, Py_ssize_t s, Py_ssize_t e) { 1152 PyView *o = (PyView*)_o; 1153 1154 try { 1155 return o->getSlice(s, e); 1156 } catch (...) { 1157 return 0; 1158 } 1159} 1160 1161static int PyView_setitem(PyObject *_o, Py_ssize_t n, PyObject *v) { 1162 PyView *o = (PyView*)_o; 1163 1164 try { 1165 if (n < 0) 1166 n += o->GetSize(); 1167 if (n >= o->GetSize() || n < 0) 1168 Fail(PyExc_IndexError, "Index out of range"); 1169 if (v == 0) { 1170 o->RemoveAt(n); 1171 return 0; 1172 } 1173 1174 return o->setItem(n, v); 1175 } catch (...) { 1176 return - 1; 1177 } 1178} 1179 1180static int PyView_setslice(PyObject *_o, Py_ssize_t s, Py_ssize_t e, PyObject 1181 *v) { 1182 PyView *o = (PyView*)_o; 1183 1184 try { 1185 if (v == 0) { 1186 PWOTuple seq; 1187 return o->setSlice(s, e, seq); 1188 } 1189 1190 PWOSequence seq(v); 1191 return o->setSlice(s, e, seq); 1192 } catch (...) { 1193 return - 1; 1194 } 1195} 1196 1197static PySequenceMethods ViewAsSeq = { 1198 PyView_length, //sq_length 1199 PyView_concat, //sq_concat 1200 PyView_repeat, //sq_repeat 1201 PyView_getitem, //sq_item 1202 PyView_getslice, //sq_slice 1203 PyView_setitem, //sq_ass_item 1204 PyView_setslice, //sq_ass_slice 1205}; 1206 1207static PySequenceMethods ViewerAsSeq = { 1208 PyView_length, //sq_length 1209 PyView_concat, //sq_concat 1210 PyView_repeat, //sq_repeat 1211 PyView_getitem, //sq_item 1212 PyView_getslice, //sq_slice 1213 0, //sq_ass_item 1214 0, //sq_ass_slice 1215}; 1216 1217static void PyView_dealloc(PyView *o) { 1218 //o->~PyView(); 1219 delete o; 1220} 1221 1222static int PyView_print(PyView *o, FILE *f, int) { 1223 fprintf(f, "<PyView object at %p>", (void*)o); 1224 return 0; 1225} 1226 1227static int PyViewer_print(PyView *o, FILE *f, int) { 1228 fprintf(f, "<PyViewer object at %p>", (void*)o); 1229 return 0; 1230} 1231 1232static int PyROViewer_print(PyView *o, FILE *f, int) { 1233 fprintf(f, "<PyROViewer object at %p>", (void*)o); 1234 return 0; 1235} 1236 1237static PyObject *PyView_getattr(PyView *o, char *nm) { 1238 PyObject *rslt; 1239 try { 1240 rslt = Py_FindMethod(ViewMethods, o, nm); 1241 if (rslt) 1242 return rslt; 1243 PyErr_Clear(); 1244 int ndx = o->FindPropIndexByName(nm); 1245 if (ndx > - 1) 1246 return new PyProperty(o->NthProperty(ndx)); 1247 Fail(PyExc_AttributeError, nm); 1248 } catch (...) { 1249 return 0; 1250 } 1251 return 0; 1252} 1253 1254static PyObject *PyViewer_getattr(PyView *o, char *nm) { 1255 PyObject *rslt; 1256 try { 1257 rslt = Py_FindMethod(ViewerMethods, o, nm); 1258 if (rslt) 1259 return rslt; 1260 PyErr_Clear(); 1261 int ndx = o->FindPropIndexByName(nm); 1262 if (ndx > - 1) 1263 return new PyProperty(o->NthProperty(ndx)); 1264 Fail(PyExc_AttributeError, nm); 1265 } catch (...) { 1266 return 0; 1267 } 1268 return 0; 1269} 1270 1271 1272PyTypeObject PyViewtype = { 1273 PyObject_HEAD_INIT(&PyType_Type)0, "PyView", sizeof(PyView), 0, (destructor) 1274 PyView_dealloc, /*tp_dealloc*/ 1275 (printfunc)PyView_print, /*tp_print*/ 1276 (getattrfunc)PyView_getattr, /*tp_getattr*/ 1277 0, /*tp_setattr*/ 1278 (cmpfunc)0, /*tp_compare*/ 1279 (reprfunc)0, /*tp_repr*/ 1280 0, /*tp_as_number*/ 1281 &ViewAsSeq, /*tp_as_sequence*/ 1282 0, /*tp_as_mapping*/ 1283}; 1284PyTypeObject PyViewertype = { 1285 PyObject_HEAD_INIT(&PyType_Type)0, "PyViewer", sizeof(PyView), 0, (destructor) 1286 PyView_dealloc, /*tp_dealloc*/ 1287 (printfunc)PyViewer_print, /*tp_print*/ 1288 (getattrfunc)PyViewer_getattr, /*tp_getattr*/ 1289 0, /*tp_setattr*/ 1290 (cmpfunc)0, /*tp_compare*/ 1291 (reprfunc)0, /*tp_repr*/ 1292 0, /*tp_as_number*/ 1293 &ViewerAsSeq, /*tp_as_sequence*/ 1294 0, /*tp_as_mapping*/ 1295}; 1296PyTypeObject PyROViewertype = { 1297 PyObject_HEAD_INIT(&PyType_Type)0, "PyROViewer", sizeof(PyView), 0, 1298 (destructor)PyView_dealloc, /*tp_dealloc*/ 1299 (printfunc)PyROViewer_print, /*tp_print*/ 1300 (getattrfunc)PyViewer_getattr, /*tp_getattr*/ 1301 0, /*tp_setattr*/ 1302 (cmpfunc)0, /*tp_compare*/ 1303 (reprfunc)0, /*tp_repr*/ 1304 0, /*tp_as_number*/ 1305 &ViewerAsSeq, /*tp_as_sequence*/ 1306 0, /*tp_as_mapping*/ 1307}; 1308int PyView::computeState(int targettype) { 1309 int newtype = _state | targettype; 1310 if (newtype > FINALNOTIFIABLE) 1311 newtype = ROVIEWER; 1312 if (_state == FINALNOTIFIABLE) 1313 newtype = ROVIEWER; 1314 return newtype; 1315} 1316 1317PyTypeObject *getTypeObject(int type) { 1318 switch (type) { 1319 case BASE: 1320 case MVIEWER: 1321 return &PyViewtype; 1322 break; 1323 case NOTIFIABLE: 1324 case RWVIEWER: 1325 case FINALNOTIFIABLE: 1326 return &PyViewertype; 1327 case ROVIEWER: 1328 return &PyROViewertype; 1329 } 1330 return &PyViewtype; 1331} 1332 1333 1334PyObject *PyView_new(PyObject *o, PyObject *_args) { 1335 return new PyView; 1336} 1337 1338PyView::PyView(): PyHead(PyViewtype), _base(0), _state(BASE){} 1339 1340PyView::PyView(const c4_View &o, PyView *owner, int state): PyHead(PyViewtype), 1341 c4_View(o), _base(owner), _state(state) { 1342 ob_type = getTypeObject(_state); 1343 if (owner && owner->_base) 1344 _base = owner->_base; 1345} 1346 1347/* For dicts, use the Python names so MK's case insensitivity works */ 1348void PyView::makeRowFromDict(c4_Row &tmp, PyObject *o, bool useDefaults) { 1349 PWOMapping dict(o); 1350 PWOList keys = dict.keys(); 1351 for (int i = 0; i < dict.len(); ++i) { 1352 PWOString key = keys[i]; 1353 int ndx = FindPropIndexByName(key); 1354 if (ndx > - 1) { 1355 const c4_Property &prop = NthProperty(ndx); 1356 PyRowRef::setFromPython(tmp, prop, dict[(const char*)key]); 1357 } 1358 } 1359} 1360 1361void PyView::makeRow(c4_Row &tmp, PyObject *o, bool useDefaults) { 1362 /* can't just check if mapping type; strings are mappings in Python 2.3 1363 (but not in 2.2 or earlier) */ 1364 if (o && PyDict_Check(o)) 1365 makeRowFromDict(tmp, o, useDefaults); 1366 else { 1367 enum { 1368 instance, sequence, none 1369 } pyobject_type = none; 1370 int n = NumProperties(); 1371 1372 if (!o) { 1373 pyobject_type = none; 1374 } else if (PyInstance_Check(o)) { 1375 /* instances of new-style classes (Python 2.2+) do not return true */ 1376 pyobject_type = instance; 1377 } else if (PySequence_Check(o)) { 1378 int seq_length = PyObject_Length(o); 1379 if (seq_length > n) { 1380 PyErr_Format(PyExc_IndexError, 1381 "Sequence has %d elements; view has %d properties", seq_length, n); 1382 throw PWDPyException; 1383 } 1384 n = seq_length; 1385 pyobject_type = sequence; 1386 } else { 1387 /* new-style class, not a number */ 1388 if (PyObject_HasAttrString(o, "__class__") && !PyNumber_Check(o)) { 1389 pyobject_type = instance; 1390 } else { 1391 Fail(PyExc_TypeError, 1392 "Argument is not an instance, sequence or dictionary: cannot be coerced to row"); 1393 } 1394 } 1395 1396 for (int i = 0; i < n; i++) { 1397 const c4_Property &prop = NthProperty(i); 1398 PyObject *attr = 0; 1399 if (pyobject_type == instance) { 1400 attr = PyObject_GetAttrString(o, (char*)prop.Name()); 1401 if (attr == 0 && i == 0 && NumProperties() == 1) { 1402 PyErr_Clear(); 1403 attr = o; 1404 Py_XINCREF(attr); 1405 } 1406 } else if (pyobject_type == sequence) { 1407 attr = PySequence_GetItem(o, i); 1408 } 1409 if (attr) { 1410 try { 1411 PyRowRef::setFromPython(tmp, prop, attr); 1412 } catch (...) { 1413 Py_DECREF(attr); 1414 throw; 1415 } 1416 Py_DECREF(attr); 1417 } else { 1418 PyErr_Clear(); 1419 if (useDefaults) 1420 PyRowRef::setDefault(tmp, prop); 1421 } 1422 } 1423 } 1424 if (!useDefaults) 1425 if (tmp.Container().NumProperties() == 0) 1426 Fail(PyExc_ValueError, "Object has no usable attributes"); 1427} 1428 1429void PyView::insertAt(int i, PyObject *o) { 1430 if (PyGenericView_Check(o)) 1431 InsertAt(i, *(PyView*)o); 1432 else { 1433 c4_Row temp; 1434 makeRow(temp, o); 1435 InsertAt(i, temp); 1436 } 1437} 1438 1439PyObject *PyView::structure() { 1440 int n = NumProperties(); 1441 // PyObject* list=PyList_New(n); 1442 // for (int i = 0; i < n; i++) 1443 // PyList_SET_ITEM(list, i, new PyProperty(NthProperty(i))); 1444 // return list; 1445 PWOList rslt(n); 1446 for (int i = 0; i < n; i++) { 1447 PyProperty *prop = new PyProperty(NthProperty(i)); 1448 rslt.setItem(i, prop); 1449 } 1450 return rslt.disOwn(); 1451} 1452 1453 1454PyObject *PyView::properties() { 1455 int n = NumProperties(); 1456 PWOMapping rslt; 1457 for (int i = 0; i < n; i++) { 1458 PyProperty *item = new PyProperty(NthProperty(i)); 1459 rslt.setItem(item->Name(), item); 1460 Py_DECREF(item); 1461 } 1462 return rslt.disOwn(); 1463} 1464 1465 1466PyView *PyView::getSlice(int s, int e) { 1467 int sz = GetSize(); 1468 if (s < 0) 1469 s += sz; 1470 if (e < 0) 1471 e += sz; 1472 if (e > sz) 1473 e = sz; 1474 if (s >= 0 && s < sz) 1475 if (e > s && e <= sz) 1476 return new PyView(Slice(s, e), 0, computeState(RWVIEWER)); 1477 return new PyView(Clone()); 1478} 1479 1480int PyView::setSlice(int s, int e, const PWOSequence &lst) { 1481 int sz = GetSize(); 1482 if (s < 0) 1483 s += sz; 1484 if (e < 0) 1485 e += sz; 1486 if (e > sz) 1487 e = sz; 1488 int i = 0; 1489 for (; i < lst.len() && s < e; i++, s++) 1490 setItem(s, lst[i]); 1491 for (; i < lst.len(); i++, s++) { 1492 if (_base) 1493 Fail(PyExc_RuntimeError, "Can't insert in this view"); 1494 insertAt(s, lst[i]); 1495 } 1496 if (s < e) 1497 if (_base) 1498 while (s < e) { 1499 int ndx = _base->GetIndexOf(GetAt(s)); 1500 _base->RemoveAt(ndx, 1); 1501 --e; 1502 } else 1503 RemoveAt(s, e-s); 1504 return 0; 1505} 1506 1507PyRowRef *PyView::getItem(int i) { 1508 if (i < 0) 1509 i += GetSize(); 1510 if (i >= GetSize() || i < 0) 1511 return 0; 1512 if (_base && !(_state &IMMUTABLEROWS)) { 1513 c4_RowRef derived = GetAt(i); 1514 int ndx = _base->GetIndexOf(derived); 1515 if (ndx >= 0) 1516 return new PyRowRef(_base->GetAt(ndx), _state &IMMUTABLEROWS); 1517 } 1518 return new PyRowRef(GetAt(i), _state &IMMUTABLEROWS); 1519} 1520 1521int PyView::setItem(int i, PyObject *v) { 1522 if (PyGenericRowRef_Check(v)) 1523 return setItemRow(i, *(PyRowRef*)v); 1524 c4_Row temp; 1525 makeRow(temp, v, false); 1526 return setItemRow(i, temp); 1527} 1528 1529void PyView::addProperties(const PWOSequence &lst) { 1530 for (int i = 0; i < lst.len(); i++) { 1531 if (PyProperty_Check((PyObject*)lst[i])) { 1532 AddProperty(*(PyProperty*)(PyObject*)lst[i]); 1533 } 1534 } 1535} 1536 1537void PyView::map(const PWOCallable &func) { 1538 PWOTuple tmp(1); 1539 for (int i = 0; i < GetSize(); ++i) { 1540 PyRowRef *row = new PyRowRef(GetAt(i)); 1541 PWOBase r2(row); 1542 tmp.setItem(0, r2); 1543 func.call(tmp); 1544 Py_DECREF(row); 1545 } 1546} 1547 1548void PyView::map(const PWOCallable &func, const PyView &subset) { 1549 int sz = subset.GetSize(); 1550 PWOTuple tmp(1); 1551 for (int i = 0; i < sz; ++i) { 1552 PyRowRef *row = new PyRowRef(GetAt(GetIndexOf(subset.GetAt(i)))); 1553 PWOBase r2(row); 1554 tmp.setItem(0, r2); 1555 func.call(tmp); 1556 Py_DECREF(row); 1557 } 1558} 1559 1560static c4_IntProp _index("index"); 1561 1562PyView *PyView::indices(const PyView &subset) { 1563 c4_View tmp(_index); 1564 tmp.SetSize(subset.GetSize()); 1565 c4_Row row; 1566 for (int i = 0; i < subset.GetSize(); ++i) { 1567 _index(row) = GetIndexOf(subset.GetAt(i)); 1568 tmp.SetAt(i, row); 1569 } 1570 return new PyView(tmp); 1571} 1572 1573void PyView::remove(const PyView &indices) { 1574 c4_View tmp = indices.Sort(); 1575 for (int i = indices.GetSize() - 1; i >= 0; --i) 1576 RemoveAt(_index(tmp.GetAt(i))); 1577} 1578 1579PyView *PyView::filter(const PWOCallable &func) { 1580 c4_View indices(_index); 1581 c4_Row ndx; 1582 PWOTuple tmp(1); 1583 for (int i = 0; i < GetSize(); ++i) { 1584 PyRowRef *row = new PyRowRef(GetAt(i)); 1585 PWOBase r2(row); 1586 tmp.setItem(0, r2); 1587 PWOBase rslt(func.call(tmp)); 1588 if (rslt.isTrue()) { 1589 _index(ndx) = i; 1590 indices.Add(ndx); 1591 } 1592 Py_DECREF(row); 1593 } 1594 return new PyView(indices); 1595} 1596 1597PyObject *PyView::reduce(const PWOCallable &func, PWONumber &start) { 1598 PWONumber accum = start; 1599 PWOTuple tmp(2); 1600 for (int i = 0; i < GetSize(); ++i) { 1601 PyRowRef *row = new PyRowRef(GetAt(i)); 1602 PWOBase r2(row); 1603 tmp.setItem(0, r2); 1604 tmp.setItem(1, accum); 1605 PWOBase rslt(func.call(tmp)); 1606 accum = rslt; 1607 Py_DECREF(row); 1608 } 1609 return accum; 1610} 1611