1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836
|
* Braindump
Python is an imperative language; we won't try to be "purely
functional" but "hidden state" could really screw us, so we'll try to
reduce that as much as possible.
We need:
- Use a gdbm backed activitystreams object storage
- For extensions, pyld
- verifiers
- method dispatch
DMD store should store in a dictionary like:
... with the key being the "@id" of the toplevel activitystreams
object.
#+BEGIN_SRC python
{"asobj": {"@type": "Object",
"@id": "uuid:d773cb99-078b-496b-b3f0-012d3ade5930",
"blah": "blah"},
"private": {"blah": "blah"}}
#+END_SRC
We are going to have to handle inheritance manually, because there can
be multiple types. We can't use python's inheritance system.
We need an "ASVocab" system to operate within. This one should have
a memoized version of the json-ld expansion of the default
activitystreams vocabulary, but it should also have a mapping of
type URIs to ASClass objects.
The store will be used separately, should provide simple store and
retrieve mechanisms.
Some complexity comes from the fact that in a "real world" system, we
don't just store and receive what's been given to us. We need a way
to trigger application-specific hooks.
* Tasks
** TODO Add optional thunk to ASType constructor: get_default_env
Should return the default vocabulary if none specified.
** TODO Handle all @context edges
*** Brainstorming
Probably what we ought to do is enforce that everything in an ASObj
share a common @context setup.
This means, it doesn't matter what's on an @context coming into
ASObj(), we slice it off and replace it with @context after the
deepcopy_in (and all child objects, we don't need an @context at all).
But we do need to be able to "ingest foreign material", which means we
should provide an Environment.ingest() method (or .ingest_foreign())
As for how to combine multiple contexts, it can be done via an array;
see the [[http://www.w3.org/TR/json-ld/#dfn-local-context][local context]] part of the docs.
So that solves how to do things! (Though there may be some minor
question as to what to do if the application's @context is also an
array... do we merge them? Will it work as-is?)
*** DONE Add extra_context field to Environment
CLOSED: [2015-10-29 Thu 13:42]
**** DONE Add to init structure
CLOSED: [2015-10-29 Thu 13:20]
**** DONE Add on expansion
CLOSED: [2015-10-29 Thu 13:20]
**** DONE Oh wait remove on expansion
CLOSED: [2015-10-29 Thu 13:42]
That didn't make sense, because the extra context gets added to the
asobj, so it doesn't need to be implicit.
*** TODO Handling when creating new ASObj()
Basically, strip off the existing @context recursively with
deepcopy_in, and add our context instead, if any exists.
*** TODO Environment.ingest(jsonld, imply_asvocab=True)
This should expand out a json-ld document then compact it to the
Environment's own context.
The question is, can we use the "grafted-on @context" required in the
above description, or do we have
*** TODO breaking off a child ASObj
Basically attach an @context to the json we have of it (though I guess
this will happen automatically)
** TODO Maybe rename MethodId to MethodSpec
** TODO Switch from method "object symbols" to strings?
Currently we require setting up "object symbols" which self-document
what a method does and etc, but they're also slightly unwieldy to set
up. It will be less precise, but maybe easier, to just use strings to
represent what a method is.
** TODO Add memoization
*** TODO General memoization function
*** TODO Property memoization
** TODO Switch ASObj.__getitem__ to use deepcopy_jsobj_out
Or rather, we should specify both a deepcopy_jsobj_in and a deepcopy_jsobj_out :)
So, if we're accessing a key value pair where the value is a list of
activitystreams objects, we'd like the activitystreams objects
converted to ASObj objects as well.
*** DONE Add deepcopy_jsobj_out
CLOSED: [2015-10-29 Thu 14:07]
*** DONE Use it in ASObj.__getitem__
CLOSED: [2015-10-29 Thu 14:07]
*** DONE Rename deepcopy_jsobj -> deepcopy_jsobj_in
CLOSED: [2015-10-29 Thu 14:07]
*** TODO Add tests
** TODO Add ASProp
** TODO Add demos section
*** DONE Vocab demo
CLOSED: [2015-11-01 Sun 10:30]
RoyalCheckin or CheckUp
- checkup:CheckIn
- checkup:RoyalStatus
- checkup:Coupon
*** TODO linter/validator
We can use the method dispatch system to handle this.
*** Archive :ARCHIVE:
**** DONE Easy GDBM based storage system
CLOSED: [2015-10-28 Wed 17:17]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-28 Wed 17:21
:END:
** TODO Documentation basics
*** TODO Tutorial
*** TODO Document basic "types" structure
*** Archive :ARCHIVE:
**** DONE Add sphinx basic structure
CLOSED: [2015-10-22 Thu 13:01]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-28 Wed 17:21
:END:
**** DONE Documentation structure
CLOSED: [2015-10-28 Wed 17:17]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-28 Wed 17:21
:END:
- Intro
- About ActiviPy
- Tutorial
- Core types
- Vocabulary
- Extending the environment
- Advanced Examples
** TODO Rename CheckUp demo to VisitIt everywhere
*** TODO code
*** TODO docs
** TODO Make ASVocab more useful
How to do this?
We want to:
- probably preload a json-ld context
- Somehow make ASVocab objects useful for a
- make ourself more useful to ASObj objects
** TODO Tests
*** TODO Test all types.py stuff
**** TODO ASVocab
**** TODO ASObj
**** TODO ASEnvironment
**** Archive :ARCHIVE:
***** DONE ASType
CLOSED: [2015-10-12 Mon 16:37]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-28 Wed 17:21
:END:
*** TODO Basic vocabs stuff
*** Archive :ARCHIVE:
**** DONE Basic test infrastructure
CLOSED: [2015-10-12 Mon 16:37]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-28 Wed 17:21
:END:
** TODO Consider rename to Pydraulics?
After all, I'm the one who started that project, and it's abandoned...
** TODO Investigate restructuring ASType instances via metaclassing
Basically, the main reason is that we'd like to be able to do:
#+BEGIN_SRC python
help(CollectionPage)
#+END_SRC
and get the appropriate useful info.
However, it's still true that calling CollectionPage() should return a
ASObj object, not a CollectionPage() object. Reason being that
ActivityStreams objects can have multiple "@type" fields.
** Archive :ARCHIVE:
*** DONE Add license stuff
CLOSED: [2015-10-07 Wed 15:01]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-07 Wed 15:01
:END:
**** DONE Add license files
CLOSED: [2015-10-07 Wed 14:29]
**** DONE Add note on why both apache v2 and gplv3 to COPYING
CLOSED: [2015-10-07 Wed 14:33]
**** DONE Add copyright headers and a note on convention
CLOSED: [2015-10-07 Wed 15:01]
*** DONE Fill in complete vocabulary
CLOSED: [2015-10-12 Mon 15:36]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-12 Mon 15:41
:END:
*** CANCELED Switch to pyrsistent for ASObj structures?
CLOSED: [2015-10-12 Mon 15:35]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-12 Mon 15:41
:END:
https://github.com/tobgu/pyrsistent
We more or less force/fake immutability right now, and maybe it makes
more sense to just use something that *is* immutable
*UPDATE:* Canceled. [[https://gist.github.com/datagrok/2199506][More info]] on why Pyrsistent has a promising future,
but can't work for now.
*** CANCELED Command line test suite
CLOSED: [2015-10-12 Mon 22:45]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-15 Thu 21:05
:END:
This is [[https://github.com/evanp/a2test][its own project]] now. See [[https://github.com/w3c-social/activipy/issues/1][this issue]].
**** Relevant parts of convo
<evanpro> paroneayea: so, a couple of questions on that
<evanpro> Does having a single package that is a producer and a consumer make
sense? Or multiple packages? [12:18]
<paroneayea> evanpro: my first goal is to make a library for the purpose of
tests, basically along the lines of how you suggested... it'll
just store @id's to a gdbm store. But I'll design it in a way
that afterwards, it can be used for something like pypump, and
for using as2 stuff
<paroneayea> but my first goal is: fulfill the test requirements
<evanpro> Whoa!
<paroneayea> while working towards something more general
<paroneayea> gdbm is oldschool I know
<evanpro> Wait what's the GDBM for?
<evanpro> I don't understand what you need persistence for [12:19]
<paroneayea> well it could also just be a dictionary
<evanpro> Wouldn't an AS2 library do something like
<paroneayea> I was going along with your suggestion that you have a
command-line submission tool
<evanpro> JSON -> native language object
<evanpro> and native language object -> JSON
<paroneayea> evanpro: yes
<paroneayea> evanpro: ok well maybe it can be in-memory only [12:20]
<paroneayea> evanpro: my main concern is get the thing working
<evanpro> 1s
<evanpro> So I was thinking that a test command-line app might look like this
<evanpro> https://gist.github.com/evanp/b49c3fc37caa21a323a1
<strugee> hey, would it be useful if I created next week's meeting page and
filled it with the stuff on the agenda that we didn't get to?
<strugee> e.g. we missed branching models
<evanpro> strugee: YES! [12:23]
<evanpro> Nice
<paroneayea> evanpro: that might work nicely
<strugee> will do
<paroneayea> evanpro: okay, I will probably do something like that [12:24]
<evanpro> paroneayea: and then a test driver would work like this
<evanpro> https://gist.github.com/evanp/5d80c0aa3f168465d84d
<evanpro> So that way you could call "testdriver.py dumpactivitytype.py"
[12:25]
<evanpro> as well as "testdriver.py dumpactivitytype.rb"
<paroneayea> evanpro: ok
<paroneayea> evanpro: I see
<paroneayea> evanpro: we also want a way to show mutations [12:26]
<paroneayea> evanpro: and side effects
<paroneayea> eg update verbs should actually update the thing in store
<evanpro> That might be too much for a data format to deal with
<paroneayea> evanpro: I mean, for the test suite
<evanpro> Yes, that's what I'm saying
<paroneayea> we want to be sure that activities can actually do the things
they promise
<evanpro> What I'm saying is that no we don't [12:27]
<evanpro> When we're testing the social API, definitely
<paroneayea> evanpro: this is why I was saying that there's not much to do as
in terms of a test suite
<evanpro> But I think an activity streams library should just parse from JSON
and export to JSON
<paroneayea> the only thing your example checks really is that it's valid
right?
<paroneayea> that it's json, has the right fields, in the right types
<evanpro> It checks that the activitystreams implementation library (the one
that the dumpactivitytype.py script imports) can find the type of an
activity [12:28]
<evanpro> I realize that it appears to be really trivial
<evanpro> But you'd need dozens of such test scripts [12:29]
<evanpro> dumpactivityactortype.py
<evanpro> dumpactivityactorid.py
<evanpro> That kind of thing
<paroneayea> evanpro: okay, so I'll definitely support this.
<evanpro> Another possibility is using command-line arguments
<paroneayea> evanpro: though, one of the things is, the activitystreams
vocabulary *does* describe things with side effects
<paroneayea> I might test for that too, but I won't make it so complex that
you can't do the simple tsts you ahve [12:30]
<evanpro> That's probably a fair point
<evanpro> I would really, really strongly recommend that you first publish
your intentions for the test format
<paroneayea> evanpro: to the list?
<evanpro> And that you concentrate on the bare minimum first
<evanpro> Yes
<paroneayea> evanpro: okay I'll do that
<evanpro> to the list [12:31]
<paroneayea> evanpro: I was planning on working on deployment stuff this week,
but it seems like this has become really urgent
<paroneayea> so I'll make it priority #1
<evanpro> So, one thing we can do when we have even a rudimentary test suite
<evanpro> Is that we can start testing libraries
<evanpro> And so we can start writing libraries [12:32]
<paroneayea> evanpro: right
<evanpro> We could even have a hackathon to implement in a lot of different
languages
<evanpro> And push implementations to npm, Ruby gems, pypi, etc.
<paroneayea> evanpro: anyway, maybe now you can see why I was looking at gdbm;
if we do have a command line test thing and we *do* promise to
deliver tests on side effects
<paroneayea> we need some way to persist things
<paroneayea> but
<paroneayea> I agree
<paroneayea> there are tests that don't need that
<evanpro> Right, I hear you
<paroneayea> focus on the other stuff first.
<evanpro> They seem trivial but they are so important [12:33]
<evanpro> Probably the big thing is defining what the interface between
testdriver script and the tested script is
<paroneayea> (and the reason why gdbm is even though it's oldschool, it's also
dead easy to get working because it's so "dumb")
<paroneayea> evanpro: right.
<evanpro> Oh, yeah, GDBM is fine there
<evanpro> I might suggest using command-line args, too [12:34]
<paroneayea> evanpro: I get why you had a "don't engineer this, chris!"
reaction though :)
<evanpro> maybe something like this
<paroneayea> er
<paroneayea> overengineer
<evanpro> <dumpscript> --activity-part actor --part-property id <filename>
<evanpro> <dumpscript> --activity-part=actor --part-property=id <filename>
[12:35]
<evanpro> Those are crummy names but :shrug:
<evanpro> That way implementers don't have to write 50 different testing shims
<paroneayea> evanpro: I hear you
<paroneayea> evanpro: well, it may even be easier [12:36]
<evanpro> It may also be worthwhile to have a producer test
<paroneayea> --extract ["actor"]["@id"]
<evanpro> That takes in some parameters and outputs some JSON
<evanpro> Sure
<evanpro> I'd be a little worried about defining a query language
<evanpro> But yeah
<paroneayea> evanpro: it's probably equally complex to define a billion
arguments
<evanpro> So a producer script might take arguments like this
<paroneayea> for the different components [12:37]
<evanpro> agreed!
<evanpro> <buildscript> --actor-id=urn:test:whatever --actor-name="Evan
Prodromou" --activity-type="Like" --object-id=urn:test:whatever2
--object-name="This terrible test" [12:38]
<evanpro> But yeah pretty nightmarish
<paroneayea> evanpro: so is the idea that this should spit out a
success/failure code or
<evanpro> Oh, no!
<evanpro> It should spit out JSON!
<paroneayea> just extract the right part?
<paroneayea> okay
<paroneayea> evanpro: and it should validate, right? [12:39]
<evanpro> dumpscript == take JSON, just spit out some extracted part of it
<evanpro> buildscript = take params, spit out JSON
<paroneayea> oh I see.
<paroneayea> okay that makes much more sense.
<paroneayea> echoscript == take json, dump out json
<paroneayea> sorry ;)
<evanpro> dumpscript and buildscript are provided by the implementer to test
the implementation [12:40]
<evanpro> and there's a test driver to run them
<evanpro> so "testdriver dumpscript.py buildscript.py"
<evanpro> Would run all the tests
<evanpro> Or something like that
<paroneayea> hm ok....
<paroneayea> evanpro: I don't understand testdriver [12:41]
<paroneayea> what does it do?
<evanpro> Something like https://gist.github.com/evanp/5d80c0aa3f168465d84d
**** CANCELED dumpscript
CLOSED: [2015-10-12 Mon 22:45]
<evanpro> dumpscript == take JSON, just spit out some extracted part of it
#+BEGIN_SRC python
import activitystreams
json = parseCommandLineFileArgument()
activity = Activity.fromJSON(json)
print activity.type
#+END_SRC
<evanpro> <dumpscript> --activity-part=actor --part-property=id <filename>
<evanpro> <dumpscript> --activity-part=actor --part-property=id <filename>
<evanpro> Those are crummy names but :shrug:
<evanpro> That way implementers don't have to write 50 different testing shims
<paroneayea> evanpro: I hear you
<paroneayea> evanpro: well, it may even be easier [12:36]
<evanpro> It may also be worthwhile to have a producer test
<paroneayea> --extract ["actor"]["@id"]
<evanpro> That takes in some parameters and outputs some JSON
<evanpro> Sure
<evanpro> I'd be a little worried about defining a query language
<evanpro> But yeah
<paroneayea> evanpro: it's probably equally complex to define a billion
arguments
<evanpro> So a producer script might take arguments like this
<paroneayea> for the different components [12:37]
<evanpro> agreed!
<evanpro> <buildscript> --actor-id=urn:test:whatever --actor-name="Evan
Prodromou" --activity-type="Like" --object-id=urn:test:whatever2
--object-name="This terrible test" [12:38]
<evanpro> But yeah pretty nightmarish
**** CANCELED buildscript
CLOSED: [2015-10-12 Mon 22:45]
<evanpro> buildscript = take params, spit out JSON
**** CANCELED testdriver
CLOSED: [2015-10-12 Mon 22:45]
<evanpro> so "testdriver dumpscript.py buildscript.py"
*** DONE Hook up pyld
CLOSED: [2015-10-20 Tue 15:56]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-20 Tue 15:58
:END:
**** Brainstorm
Okay, so what do we want to do here?
- Vocabularies might provide an "implied context". That's the
biggest issue, because otherwise it can be inferred unambiguously
from expanding the document.
- Mostly, we might not want to re-read things?
This last one is a good goal but maybe we shouldn't worry about it
immediately.
Here's the options from the JsonLdProcessor code:
#+BEGIN_SRC python
class JsonLdProcessor(object):
"""
A JSON-LD processor.
"""
# [...]
def expand(self, input_, options):
"""
Performs JSON-LD expansion.
:param input_: the JSON-LD input to expand.
:param options: the options to use.
[base] the base IRI to use.
[expandContext] a context to expand with.
[keepFreeFloatingNodes] True to keep free-floating nodes,
False not to (default: False).
[documentLoader(url)] the document loader
(default: _default_document_loader).
:return: the expanded JSON-LD output.
"""
#+END_SRC
- we probably want to be able to set expandContext.
- the documentLoader could thus possibly come with some context
preloaded. But that's kind of an optimization.
At least we know the two main steps now?
*Update:* It turns out the first of these is much simpler than we
originally were thinking! There's only one implied context in
ActivityStreams, so we can hardcode the expandContext.
**** DONE Handle the implied context
CLOSED: [2015-10-19 Mon 21:26]
Should be passed into the environment, but possibly built out of the
vocabulary.
**** DONE cache things in the documentLoader
CLOSED: [2015-10-20 Tue 15:55]
The documentLoader seems to just be a function accepting a URI, and
raising JsonLdError if something goes badly.
#+BEGIN_SRC python
{
'contextUrl': None,
'documentUrl': url,
'document': data.decode('utf8')
}
#+END_SRC
So we could write a factory function that takes a mapping of
{url: document}
#+BEGIN_SRC python
def make_simple_loader(url_map, load_unknown_urls=True):
def loader(url):
# foo
return loaded_url
return loader
#+END_SRC
**** DONE Provide a side-effect free environment option
CLOSED: [2015-10-20 Tue 15:55]
**** DONE Easily build expandContext and documentLoader based on supplied vocabulary?
CLOSED: [2015-10-20 Tue 15:56]
One way or another we want to reduce the amount of data duplicated
from the building of the Environment
*** DONE Maybe rename types.py to core.py
CLOSED: [2015-10-22 Thu 09:34]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-22 Thu 09:35
:END:
*** DONE Fix how ASType.__call__() handles long vs short URIs
CLOSED: [2015-10-21 Wed 17:39]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-22 Thu 09:35
:END:
*** DONE ActivityStreams "classes"
CLOSED: [2015-10-22 Thu 09:36]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-22 Thu 09:36
:END:
Note that normal python classes can't work here.
**** DONE ASObj
CLOSED: [2015-10-22 Thu 09:35]
***** DONE Finish all those TODO methods
CLOSED: [2015-10-22 Thu 09:35]
***** Archive :ARCHIVE:
****** DONE Construction: Do deep copy of asjson manually
CLOSED: [2015-10-11 Sun 11:33]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-12 Mon 15:41
:END:
This way we can catch any asobj types
****** DONE Better inheritance order
CLOSED: [2015-10-17 Sat 14:05]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-17 Sat 14:05
:END:
We should do this like in the ANSI Common Lisp book, where we remove
duplicates, but we remove duplictes but keep the *last* appearance of
a "class"
**** Archive :ARCHIVE:
***** DONE Add inheritance / method dispatch system
CLOSED: [2015-10-10 Sat 18:49]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-10 Sat 18:49
:END:
This is trickier than one may think; we can't do Python style
method resolution because an activity may have multiple types.
***** DONE Easy ASType->ASObj constructor interface
CLOSED: [2015-10-12 Mon 15:14]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-12 Mon 15:41
:END:
Something like:
#+BEGIN_SRC python
from activipy import vocab
root_beer_note = vocab.Create(
actor=vocab.Person(
"http://tsyesika.co.uk",
displayName="Jessica Tallon"),
to=["acct:cwebber@identi.ca"],
object=vocab.Note(
"http://tsyesika.co.uk/chat/sup-yo/",
content="Up for some root beer floats?"))
#+END_SRC
This should be able to flow pretty naturally out of our types.py
interface.
*** DONE "environment" w/ method dispatch and object sugar
CLOSED: [2015-10-26 Mon 13:49]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-26 Mon 13:49
:END:
**** Brainstorm
So here's how this thing works.
There's an environment, which has a mapping between tuples of
(method_symbol, Vocab) and method_to_call.
#+BEGIN_SRC python
# method name description invocation method
save = Method("save", "Save things", handle_one)
gather_something = Method("gather_something", "Accrues some info", handle_map)
myenv = Enviroment(
mapping={
(save, Note): note_save,
(save, Object): basic_save,
})
handle_one(myobj, save, db)
#+END_SRC
This way, using the inheritance_chain() method, we can handle
various types of method handling:
- handle_one
- handle_map
- handle_fold
However, we have enough metadata here to provide some sugar.
#+BEGIN_SRC python
myenv = Environment(
mapping={bla bla},
vocab=vocab)
activity = Environment.c.Activity("http://oh/snap")
activity.m.save(db)
# or maybe even just activity.save()
#+END_SRC
This would have to mean that ASObj gets a method dispatch keyword
option on construction, which might be a-ok.
I think this is a pretty good approach.
**** DONE Add Environment and method dispatch
CLOSED: [2015-10-26 Mon 13:48]
**** DONE Add vocabulary + method-class sugar
CLOSED: [2015-10-26 Mon 13:49]
**** Archive :ARCHIVE:
***** DONE Clean up method dispatch plan based on convo w/ steve
CLOSED: [2015-10-15 Thu 13:29]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-15 Thu 13:31
:END:
#+BEGIN_SRC python
save_object = Method("save things", "handle_one")
myenv = Enviroment(
mapping={
(save_object, Note): note_save,
})
handle_one(myobj, "save_object", db)
handle_one(myobj, save_object, db)
# more pythonic optional interface
# a bit leaky though
myenv = MetaEnviroment(
mapping={
(save_object, Note): note_save,
}
vocab=[BasicVocab]
)
myenv.Person("foo")
Person()
#+END_SRC
*** CANCELED Pass environment into methods?
CLOSED: [2015-10-28 Wed 17:16]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-28 Wed 17:19
:END:
Should methods be able to themselves take advantage of method dispatch?
If so, they will need "env" as first argument.
*** DONE Add ASObj.type_astype()
CLOSED: [2015-10-28 Wed 17:17]
:PROPERTIES:
:ARCHIVE_TIME: 2015-10-28 Wed 17:19
:END:
**** Brainstorm
Here's the problem.
Assume we made an activity like this:
#+BEGIN_SRC python
ROOT_BEER_NOTE_VOCAB = vocab.Create(
"http://tsyesika.co.uk/act/foo-id-here/",
actor=vocab.Person(
"http://tsyesika.co.uk/",
displayName="Jessica Tallon"),
to=["acct:cwebber@identi.ca",
"acct:justaguy@rhiaro.co.uk"],
object=vocab.Note(
"htp://tsyesika.co.uk/chat/sup-yo/",
content="Up for some root beer floats?"))
#+END_SRC
Now assume we made one like this:
#+BEGIN_SRC python
ROOT_BEER_NOTE_JSOBJ = types.ASObj({
"@type": "Create",
"@id": "http://tsyesika.co.uk/act/foo-id-here/",
"actor": {
"@type": "Person",
"@id": "http://tsyesika.co.uk/",
"displayName": "Jessica Tallon"},
"to": ["acct:cwebber@identi.ca",
"acct:justaguy@rhiaro.co.uk"],
"object": {
"@type": "Note",
"@id": "htp://tsyesika.co.uk/chat/sup-yo/",
"content": "Up for some root beer floats?"}})
#+END_SRC
Now even worse:
#+BEGIN_SRC python
ROOT_BEER_NOTE_JSOBJ = types.ASObj({
# AAAAAAAAAAA
"@type": "http://www.w3.org/ns/activitystreams#Create",
"@id": "http://tsyesika.co.uk/act/foo-id-here/",
"actor": {
"@type": "Person",
"@id": "http://tsyesika.co.uk/",
"displayName": "Jessica Tallon"},
"to": ["acct:cwebber@identi.ca",
"acct:justaguy@rhiaro.co.uk"],
"object": {
"@type": "Note",
"@id": "htp://tsyesika.co.uk/chat/sup-yo/",
"content": "Up for some root beer floats?"}})
#+END_SRC
So...
- we really need to know about the whole set of vocabularies in order
to do ASObj.type_astype()
- Obviously, we also need to for method dispatch also
- It could be then that we don't load ASObj.vocab, but ASObj.env
- Also, in general you can always do env.asobj_astypes(asobj)
- Thus, we should also provide env.asobj_method(asobj, method_symbol)
- Which means also, more obviously, and as a precedent, we must
provide Environment.asobj_astype_chain(asobj)!
This also means that users should, in general, not use
ASObj.type_astype(), unless they're using the "sugar" edition
which comes from supplying an environment.
We might want to also provide an expanded=True argument to some of those methods.
OR, maybe we can do "cheapest available" determination of an ASType.
What are the ways we might go about pulling down an ASType?
- By short ID... but this requires this short ID be marked "safe"
for short expansion
- By already known URI
- By json-ld examination (most expensive!)
Do we really want an expand=None? Maybe that's kind of dumb
**** DONE From short id
CLOSED: [2015-10-28 Wed 17:17]
The question is, where do we mark whether its safe to consider the
short_id as a safe representation from? Is it in the environment
or in the vocab?
The vocab may make sense because we could do a
shortids=load_from_vocabs((Vocab1, None), (GMGVocab, "gmg:"))
**** DONE From known URI
CLOSED: [2015-10-28 Wed 17:17]
**** DONE By json-ld examination
CLOSED: [2015-10-28 Wed 17:17]
|