[Python-modules-commits] [python-activipy] 01/11: import python-activity 0.1

Wolfgang Borgert debacle at moszumanska.debian.org
Sun Nov 22 22:28:48 UTC 2015


This is an automated email from the git hooks/post-receive script.

debacle pushed a commit to branch master
in repository python-activipy.

commit 9966f144fb19125b3caca789b9552689c454a0ad
Author: W. Martin Borgert <debacle at debian.org>
Date:   Sun Nov 22 20:49:42 2015 +0100

    import python-activity 0.1
---
 .gitignore                               |   26 +
 COPYING                                  |   34 +
 MANIFEST.in                              |    1 +
 README.org                               |   13 +
 activipy.org                             |  836 ++++++++++++++++++++++++
 activipy/__init__.py                     |   18 +
 activipy/activitystreams2-context.jsonld |  333 ++++++++++
 activipy/core.py                         |  627 ++++++++++++++++++
 activipy/demos/__init__.py               |    0
 activipy/demos/checkup.py                |   97 +++
 activipy/demos/dbm.py                    |  175 +++++
 activipy/testcli.py                      |  127 ++++
 activipy/tests/test_core.py              |  481 ++++++++++++++
 activipy/vocab.py                        |  569 +++++++++++++++++
 apache-2.0.txt                           |  202 ++++++
 docs/Makefile                            |  192 ++++++
 docs/source/about.rst                    |  136 ++++
 docs/source/conf.py                      |  287 +++++++++
 docs/source/index.rst                    |   44 ++
 docs/source/tutorial.rst                 | 1017 ++++++++++++++++++++++++++++++
 gpl-3.0.txt                              |  674 ++++++++++++++++++++
 guix.scm                                 |   46 ++
 setup.py                                 |   47 ++
 23 files changed, 5982 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..003f562
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,26 @@
+/dist/
+/bin/
+/develop-eggs/
+/build/
+/eggs/
+/lib/
+/lib64
+/local/
+/include/
+/parts/
+/share/
+/activipy*.egg/
+*.egg-info
+
+# File extensions
+*.pyc
+*.pyo
+*~
+*.swp
+*.mo
+
+__pycache__
+*.pyc
+.cache
+
+docs/build/
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..d686531
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,34 @@
+All code here dual licensed under Apache License v2.0 and GPL v3 or
+later, as published by the Free Software Foundation.
+
+(Why both when Apache v2 and GPLv3 is effectively just Apache v2?
+Well, future compatibility is a minor concern.  Also, the founder of
+this package thinks that being in a camp on one or the other and
+shaking fists at each other is an annoying and self-defeating
+pasttime, so there's a bit of community commentary here: both
+approaches are great, choose strategically!)
+
+You ought to find some copies of those licenses in this directory, as
+long as nobody mucked things up!
+
+When adding new files, please add the following:
+
+## Activipy --- ActivityStreams 2.0 implementation and testing for Python
+## Copyright © 20XX  Your Name <youremail at example.org>
+##
+## This file is part of Activipy, which is GPLv3+ or Apache v2, your option
+## (see COPYING); since that means effectively Apache v2...
+##
+## Apache v2 header:
+##   Licensed under the Apache License, Version 2.0 (the "License");
+##   you may not use this file except in compliance with the License.
+##   You may obtain a copy of the License at
+##
+##       http://www.apache.org/licenses/LICENSE-2.0
+##
+##   Unless required by applicable law or agreed to in writing, software
+##   distributed under the License is distributed on an "AS IS" BASIS,
+##   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+##   See the License for the specific language governing permissions and
+##   limitations under the License.
+
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..ee447db
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1 @@
+include activipy/activitystreams2-context.jsonld
diff --git a/README.org b/README.org
new file mode 100644
index 0000000..9782a54
--- /dev/null
+++ b/README.org
@@ -0,0 +1,13 @@
+#+TITLE: Activipy: ActivityStreams 2.0 stuff for Python
+
+Read the [[http://activipy.readthedocs.org/en/latest/index.html][documentation!]]
+
+* What is this?
+
+Activipy is an implementation of ActivityStreams 2.0 for Python.
+
+It also, hopefully soon, will serve as an ActivityStreams validator.
+
+More things will go here in the future, in the meanwhile maybe see
+[[file:./activipy.org][activipy.org]] in this directory for braindumps and tasks.
+
diff --git a/activipy.org b/activipy.org
new file mode 100644
index 0000000..2202d3a
--- /dev/null
+++ b/activipy.org
@@ -0,0 +1,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 at 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 at identi.ca",
+        "acct:justaguy at 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 at identi.ca",
+           "acct:justaguy at 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 at identi.ca",
+             "acct:justaguy at 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]
+
diff --git a/activipy/__init__.py b/activipy/__init__.py
new file mode 100644
index 0000000..8ddef0c
--- /dev/null
+++ b/activipy/__init__.py
@@ -0,0 +1,18 @@
+## Activipy --- ActivityStreams 2.0 implementation and validator for Python
+## Copyright © 2015 Christopher Allan Webber <cwebber at dustycloud.org>
+##
+## This file is part of Activipy, which is GPLv3+ or Apache v2, your option
+## (see COPYING); since that means effectively Apache v2 here's those headers
+##
+## Apache v2 header:
+##   Licensed under the Apache License, Version 2.0 (the "License");
+##   you may not use this file except in compliance with the License.
+##   You may obtain a copy of the License at
+##
+##       http://www.apache.org/licenses/LICENSE-2.0
+##
+##   Unless required by applicable law or agreed to in writing, software
+##   distributed under the License is distributed on an "AS IS" BASIS,
+##   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+##   See the License for the specific language governing permissions and
+##   limitations under the License.
diff --git a/activipy/activitystreams2-context.jsonld b/activipy/activitystreams2-context.jsonld
new file mode 100644
index 0000000..a374ef1
--- /dev/null
+++ b/activipy/activitystreams2-context.jsonld
... 5148 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-activipy.git



More information about the Python-modules-commits mailing list