├── pymantic ├── scripts │ ├── __init__.py │ ├── named_graph_to_nquads │ └── bnf2html ├── tests │ ├── __init__.py │ ├── turtle_tests │ │ ├── test-00.ttl │ │ ├── bad-00.ttl │ │ ├── bad-08.ttl │ │ ├── test-08.ttl │ │ ├── test-19.ttl │ │ ├── test-24.ttl │ │ ├── test-26.out │ │ ├── bad-13.ttl │ │ ├── test-07.ttl │ │ ├── test-20.ttl │ │ ├── test-21.ttl │ │ ├── test-22.ttl │ │ ├── test-23.out │ │ ├── bad-03.ttl │ │ ├── bad-09.ttl │ │ ├── test-17.out │ │ ├── bad-10.ttl │ │ ├── bad-11.ttl │ │ ├── bad-12.ttl │ │ ├── test-06.ttl │ │ ├── test-27.out │ │ ├── bad-06.ttl │ │ ├── test-19.out │ │ ├── bad-02.ttl │ │ ├── bad-07.ttl │ │ ├── test-02.ttl │ │ ├── test-26.ttl │ │ ├── bad-05.ttl │ │ ├── test-03.ttl │ │ ├── test-06.out │ │ ├── test-13.ttl │ │ ├── test-20.out │ │ ├── test-23.ttl │ │ ├── bad-01.ttl │ │ ├── bad-04.ttl │ │ ├── test-08.out │ │ ├── test-04.ttl │ │ ├── test-17.ttl │ │ ├── test-13.out │ │ ├── bad-14.ttl │ │ ├── test-27.ttl │ │ ├── test-00.out │ │ ├── test-04.out │ │ ├── test-05.ttl │ │ ├── test-18.ttl │ │ ├── test-24.out │ │ ├── test-01.ttl │ │ ├── test-18.out │ │ ├── test-02.out │ │ ├── test-03.out │ │ ├── test-01.out │ │ ├── test-05.out │ │ ├── test-11.out │ │ ├── test-21.out │ │ ├── test-22.out │ │ ├── test-10.ttl │ │ ├── test-12.out │ │ ├── test-09.ttl │ │ ├── test-25.ttl │ │ ├── test-12.ttl │ │ ├── test-29.out │ │ ├── test-29.ttl │ │ ├── test-11.ttl │ │ ├── test-09.out │ │ ├── test-07.out │ │ ├── test-30.ttl │ │ ├── test-10.out │ │ ├── test-25.out │ │ ├── test-30.out │ │ ├── test-28-out.ttl │ │ ├── README.txt │ │ ├── rdfq-results.ttl │ │ ├── test-28.out │ │ ├── test-28.ttl │ │ ├── manifest-bad.ttl │ │ ├── rdfq-results.out │ │ ├── rdf-schema.ttl │ │ ├── rdfs-namespace.ttl │ │ ├── manifest.ttl │ │ ├── rdf-schema.out │ │ ├── rdfs-namespace.out │ │ └── Overview.html │ ├── test_util.py │ ├── test_SPARQL.py │ ├── test_turtle.py │ ├── test_parsers.py │ ├── test_primitives.py │ └── test_serializers.py ├── vocab │ ├── __init__.py │ └── skos.py ├── __init__.py ├── uri_schemes.py ├── util.py ├── change_tracking.py ├── serializers.py └── sparql.py ├── setup.cfg ├── .gitignore ├── docs ├── modules │ ├── rdf.rst │ └── primitives.rst ├── contents.rst ├── index.rst ├── Makefile └── conf.py ├── .hgignore ├── pymantic.wpr ├── examples └── foaf-bond.ttl ├── README.rst ├── setup.py └── LICENSE /pymantic/scripts/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pymantic/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pymantic/vocab/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [egg_info] 2 | tag_build = dev 3 | tag_svn_revision = true 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-00.ttl: -------------------------------------------------------------------------------- 1 | @prefix : <#> . 2 | [] :x :y . 3 | -------------------------------------------------------------------------------- /pymantic/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | version = '0.1.1' 3 | release = version + 'alpha' 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/bad-00.ttl: -------------------------------------------------------------------------------- 1 | # prefix name must end in a : 2 | @prefix a <#> . 3 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/bad-08.ttl: -------------------------------------------------------------------------------- 1 | @keywords something. 2 | # @keywords is not in turtle 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | pymantic.egg-info 2 | *.pyc 3 | *.so 4 | include 5 | lib 6 | share 7 | docs/_build 8 | build 9 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-08.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :a :b ( ) . 3 | 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-19.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | 3 | :a :b 1.0 . 4 | 5 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-24.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :a :b true . 3 | :c :d false . 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-26.out: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /docs/modules/rdf.rst: -------------------------------------------------------------------------------- 1 | :mod:`pymantic.rdf` 2 | ------------------- 3 | 4 | .. automodule:: pymantic.rdf 5 | :members: 6 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/bad-13.ttl: -------------------------------------------------------------------------------- 1 | # <= is not in turtle 2 | @prefix : . 3 | :a <= :b . 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-07.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :a :b ( "apple" "banana" ) . 3 | 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-20.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | 3 | :a :b "" . 4 | 5 | :c :d """""" . 6 | 7 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-21.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :a :b 1.0 . 3 | :c :d 1 . 4 | :e :f 1.0e0 . 5 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-22.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :a :b -1.0 . 3 | :c :d -1 . 4 | :e :f -1.0e0 . 5 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-23.out: -------------------------------------------------------------------------------- 1 | "John said: \"Hello World!\"" . 2 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/bad-03.ttl: -------------------------------------------------------------------------------- 1 | # 'a' only allowed as a predicate 2 | @prefix : . 3 | a :a :b . 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/bad-09.ttl: -------------------------------------------------------------------------------- 1 | # implies is not in turtle 2 | @prefix : . 3 | :a => :b . 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-17.out: -------------------------------------------------------------------------------- 1 | "a long\n\tliteral\nwith\nnewlines" . 2 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/bad-10.ttl: -------------------------------------------------------------------------------- 1 | # equivalence is not in turtle 2 | @prefix : . 3 | :a = :b . 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/bad-11.ttl: -------------------------------------------------------------------------------- 1 | # @forAll is not in turtle 2 | @prefix : . 3 | @forAll :x . 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/bad-12.ttl: -------------------------------------------------------------------------------- 1 | # @forSome is not in turtle 2 | @prefix : . 3 | @forSome :x . 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-06.ttl: -------------------------------------------------------------------------------- 1 | # 'a' only allowed as a predicate 2 | @prefix : . 3 | :a a :b . 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-27.out: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/bad-06.ttl: -------------------------------------------------------------------------------- 1 | # is and of are not in turtle 2 | @prefix : . 3 | :a is :b of :c . 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-19.out: -------------------------------------------------------------------------------- 1 | "1.0"^^ . 2 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/bad-02.ttl: -------------------------------------------------------------------------------- 1 | # Forbidden by RDF - predicate cannot be blank 2 | @prefix : . 3 | :a [] :b . 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/bad-07.ttl: -------------------------------------------------------------------------------- 1 | # paths are not in turtle 2 | @prefix : . 3 | :a.:b.:c . 4 | :a^:b^:c . 5 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-02.ttl: -------------------------------------------------------------------------------- 1 | # Test , operator 2 | @prefix : . 3 | :a :b :c, 4 | :d, 5 | :e . 6 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-26.ttl: -------------------------------------------------------------------------------- 1 | # comment line with no final newline test 2 | @prefix : . 3 | :a :b :c . 4 | #foo 5 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/bad-05.ttl: -------------------------------------------------------------------------------- 1 | # N3 {}s are not in Turtle 2 | @prefix : . 3 | { :a :b :c . } :d :e . 4 | 5 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-03.ttl: -------------------------------------------------------------------------------- 1 | # Test ; operator 2 | @prefix : . 3 | :a :b :c ; 4 | :d :e ; 5 | :f :g . 6 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-06.out: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-13.ttl: -------------------------------------------------------------------------------- 1 | # Test for : allowed 2 | @prefix : . 3 | 4 | [] : [] . 5 | 6 | : : : . 7 | 8 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-20.out: -------------------------------------------------------------------------------- 1 | "" . 2 | "" . 3 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-23.ttl: -------------------------------------------------------------------------------- 1 | # Test long literal 2 | @prefix : . 3 | :a :b """John said: "Hello World!\"""" . 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/bad-01.ttl: -------------------------------------------------------------------------------- 1 | # Forbidden by RDF - predicate cannot be blank 2 | @prefix : . 3 | :a [ :b :c ] :d . 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/bad-04.ttl: -------------------------------------------------------------------------------- 1 | # No comma is allowed in collections 2 | @prefix : . 3 | :a :b ( "apple", "banana" ) . 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-08.out: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-04.ttl: -------------------------------------------------------------------------------- 1 | # Test empty [] operator; not allowed as predicate 2 | @prefix : . 3 | [] :a :b . 4 | :c :d [] . 5 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-17.ttl: -------------------------------------------------------------------------------- 1 | # Test long literal 2 | @prefix : . 3 | :a :b """a long 4 | literal 5 | with 6 | newlines""" . 7 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-13.out: -------------------------------------------------------------------------------- 1 | _:genid1 _:genid2 . 2 | . 3 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/bad-14.ttl: -------------------------------------------------------------------------------- 1 | # Test long literals with missing end 2 | @prefix : . 3 | :a :b """a long 4 | literal 5 | with 6 | newlines 7 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-27.ttl: -------------------------------------------------------------------------------- 1 | @prefix foo: . 2 | @prefix foo: . 3 | 4 | foo:blah foo:blah foo:blah . 5 | 6 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-00.out: -------------------------------------------------------------------------------- 1 | _:genid1 . 2 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-04.out: -------------------------------------------------------------------------------- 1 | _:genid1 . 2 | _:genid2 . 3 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-05.ttl: -------------------------------------------------------------------------------- 1 | # Test non empty [] operator; not allowed as predicate 2 | @prefix : . 3 | [ :a :b ] :c :d . 4 | :e :f [ :g :h ] . 5 | -------------------------------------------------------------------------------- /.hgignore: -------------------------------------------------------------------------------- 1 | syntax: glob 2 | *.pyc 3 | *~ 4 | *.wpu 5 | build 6 | _build 7 | include 8 | data 9 | dist 10 | lib 11 | bin 12 | *.swp 13 | *.db 14 | .DS_Store 15 | pymantic.egg-info 16 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-18.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | 3 | :a :b """\nthis \ris a \U00015678long\t 4 | literal\uABCD 5 | """ . 6 | 7 | :d :e """\tThis \uABCDis\r \U00015678another\n 8 | one 9 | """ . 10 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-24.out: -------------------------------------------------------------------------------- 1 | "true"^^ . 2 | "false"^^ . 3 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-01.ttl: -------------------------------------------------------------------------------- 1 | # Test @prefix and qnames 2 | @prefix : . 3 | @prefix a: . 4 | @prefix b: . 5 | :a :b :c . 6 | a:a a:b a:c . 7 | :a a:a b:a . 8 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-18.out: -------------------------------------------------------------------------------- 1 | "\nthis \ris a \U00015678long\t\nliteral\uABCD\n" . 2 | "\tThis \uABCDis\r \U00015678another\n\none\n" . 3 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-02.out: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | . 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-03.out: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | . 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-01.out: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | . 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-05.out: -------------------------------------------------------------------------------- 1 | _:genid1 . 2 | _:genid1 . 3 | _:genid2 . 4 | _:genid2 . 5 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-11.out: -------------------------------------------------------------------------------- 1 | "a" . 2 | "b" . 3 | "c" . 4 | "d" . 5 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-21.out: -------------------------------------------------------------------------------- 1 | "1.0"^^ . 2 | "1"^^ . 3 | "1.0e0"^^ . 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-22.out: -------------------------------------------------------------------------------- 1 | "-1.0"^^ . 2 | "-1"^^ . 3 | "-1.0e0"^^ . 4 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-10.ttl: -------------------------------------------------------------------------------- 1 | 000000 . 2 | 0 . 3 | 000001 . 4 | 2 . 5 | 4 . 6 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-12.out: -------------------------------------------------------------------------------- 1 | "1" . 2 | "2" . 3 | "def" . 4 | "678" . 5 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-09.ttl: -------------------------------------------------------------------------------- 1 | # Test integer datatyped literals using an OWL cardinality constraint 2 | @prefix owl: . 3 | 4 | # based on examples in the OWL Reference 5 | 6 | _:hasParent a owl:ObjectProperty . 7 | 8 | [] a owl:Restriction ; 9 | owl:onProperty _:hasParent ; 10 | owl:maxCardinality 2 . 11 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-25.ttl: -------------------------------------------------------------------------------- 1 | # comment test 2 | @prefix : . 3 | :a :b :c . # end of line comment 4 | :d # ignore me 5 | :e # and me 6 | :f # and me 7 | . 8 | :g :h #ignore me 9 | :i, # and me 10 | :j . # and me 11 | 12 | :k :l :m ; #ignore me 13 | :n :o ; # and me 14 | :p :q . # and me 15 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-12.ttl: -------------------------------------------------------------------------------- 1 | # Tests for rdf:_ and other qnames starting with _ 2 | @prefix rdf: . 3 | @prefix ex: . 4 | @prefix : . 5 | 6 | ex:foo rdf:_1 "1" . 7 | ex:foo rdf:_2 "2" . 8 | ex:foo :_abc "def" . 9 | ex:foo :_345 "678" . 10 | -------------------------------------------------------------------------------- /docs/contents.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | Pymantic documentation contents 3 | =============================== 4 | 5 | .. toctree:: 6 | :maxdepth: 3 7 | 8 | index 9 | modules/primitives 10 | modules/rdf 11 | 12 | 13 | Indices, glossary and tables 14 | ============================ 15 | 16 | * :ref:`genindex` 17 | * :ref:`modindex` 18 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-29.out: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-29.ttl: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-11.ttl: -------------------------------------------------------------------------------- 1 | # Tests for - and _ in names, qnames 2 | @prefix ex1: . 3 | @prefix ex-2: . 4 | @prefix ex3_: . 5 | @prefix ex4-: . 6 | 7 | ex1:foo-bar ex1:foo_bar "a" . 8 | ex-2:foo-bar ex-2:foo_bar "b" . 9 | ex3_:foo-bar ex3_:foo_bar "c" . 10 | ex4-:foo-bar ex4-:foo_bar "d" . 11 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-09.out: -------------------------------------------------------------------------------- 1 | _:hasParent . 2 | _:genid1 . 3 | _:genid1 _:hasParent . 4 | _:genid1 "2"^^ . 5 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-07.out: -------------------------------------------------------------------------------- 1 | _:genid1 "banana" . 2 | _:genid1 . 3 | _:genid2 "apple" . 4 | _:genid2 _:genid1 . 5 | _:genid2 . 6 | -------------------------------------------------------------------------------- /pymantic/vocab/skos.py: -------------------------------------------------------------------------------- 1 | from pymantic.rdf import Resource, register_class 2 | 3 | SKOS_NS = "http://www.w3.org/2004/02/skos/core#" 4 | NS_DICT = dict(skos = SKOS_NS) 5 | 6 | class SKOSResource(Resource): 7 | namespaces = NS_DICT 8 | 9 | scaler = ['skos:prefLabel'] 10 | 11 | @register_class("skos:Concept") 12 | class Concept(SKOSResource): 13 | pass 14 | 15 | @register_class("skos:ConceptScheme") 16 | class ConceptScheme(SKOSResource): 17 | pass 18 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-30.ttl: -------------------------------------------------------------------------------- 1 | # In-scope base URI is http://www.w3.org/2001/sw/DataAccess/df1/tests/ at this point 2 | . 3 | @base . 4 | # In-scope base URI is http://example.org/ns/ at this point 5 | . 6 | @base . 7 | # In-scope base URI is http://example.org/ns/foo/ at this point 8 | . 9 | @prefix : . 10 | :a4 :b4 :c4 . 11 | @prefix : . 12 | :a5 :b5 :c5 . 13 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-10.out: -------------------------------------------------------------------------------- 1 | "000000"^^ . 2 | "0"^^ . 3 | "000001"^^ . 4 | "2"^^ . 5 | "4"^^ . 6 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-25.out: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | . 4 | . 5 | . 6 | . 7 | . 8 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-30.out: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | . 4 | . 5 | . 6 | -------------------------------------------------------------------------------- /pymantic.wpr: -------------------------------------------------------------------------------- 1 | #!wing 2 | #!version=4.0 3 | ################################################################## 4 | # Wing IDE project file # 5 | ################################################################## 6 | [project attributes] 7 | proj.directory-list = [{'dirloc': loc('.'), 8 | 'excludes': (), 9 | 'filter': '*', 10 | 'include_hidden': False, 11 | 'recursive': True, 12 | 'watch_for_changes': True}] 13 | proj.file-type = 'shared' 14 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-28-out.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix rdf: <../../../../../1999/02/22-rdf-syntax-ns#> . 3 | 4 | 5 | 2.345, 1, 1.0, 1., 1.000000000, 2.3, 2.234000005, 2.2340000005, 2.23400000005, 2.234000000005, 2.2340000000005, 2.23400000000005, 2.234000000000005, 2.2340000000000005, 2.23400000000000005, 2.234000000000000005, 2.2340000000000000005, 2.23400000000000000005, 2.234000000000000000005, 2.2340000000000000000005, 2.23400000000000000000005, 1.2345678901234567890123457890 . 6 | 7 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/README.txt: -------------------------------------------------------------------------------- 1 | These are the tests for the Turtle Terse RDF Triple Language 2 | that must be passed by conformant systems. See 3 | http://www.dajobe.org/2004/01/turtle/ 4 | for the full conformance information. 5 | 6 | The format is a set of good tests and bad tests. 7 | 8 | Good tests are a pair of files: 9 | abc.ttl abc.out 10 | which are the input Turtle file and the expected output RDF triples, 11 | written in N-Triples. 12 | 13 | bad tests are of the form 14 | bad-XX.ttl 15 | which must fail. 16 | 17 | The tests should be performed with an assumed base URI 18 | of http://www.w3.org/2001/sw/DataAccess/df1/tests/ 19 | 20 | Dave 21 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. _index: 2 | 3 | ******** 4 | Pymantic 5 | ******** 6 | 7 | Pymantic is a pythonic and easy-to-use library for working with `Resource Description Framework (RDF) `_ data. 8 | 9 | Examples 10 | ======== 11 | 12 | 13 | Reading RDF data in N-Triples 14 | ----------------------------- 15 | .. doctest:: 16 | 17 | from pymantic.parsers import * 18 | 19 | with open("triples.nt") as f: 20 | graph = parse_ntriples(f) 21 | 22 | 23 | .. _getting_involved: 24 | 25 | Getting Involved 26 | ================ 27 | 28 | 29 | GitHub project page 30 | ------------------- 31 | 32 | Fork it, add features, wallow in the code, find out what is being worked on 33 | 34 | `github.com/norcalrdf/pymantic `_. 35 | 36 | Feedback (Bugs) 37 | --------------- 38 | 39 | Submit bugs in our `issue tracker `_. 40 | 41 | Discuss 42 | ------- 43 | 44 | * `pymantic users mailing list `_. 45 | * `pymantic development mailing list `_. 46 | -------------------------------------------------------------------------------- /pymantic/uri_schemes.py: -------------------------------------------------------------------------------- 1 | """A complete list of URI schemes registered as of Sept 26th, 2008, used when 2 | parsing CURIEs to differentiate explicit URIs from CURIEs.""" 3 | 4 | schemes = ['aaa', 5 | 'aaas', 6 | 'acap', 7 | 'cap', 8 | 'cid', 9 | 'crid', 10 | 'data', 11 | 'dav', 12 | 'dict', 13 | 'dns', 14 | 'fax', 15 | 'file', 16 | 'ftp', 17 | 'go', 18 | 'gopher', 19 | 'h323', 20 | 'http', 21 | 'https', 22 | 'icap', 23 | 'im', 24 | 'imap', 25 | 'info', 26 | 'ipp', 27 | 'iris', 28 | 'iris.beep', 29 | 'iris.xpc', 30 | 'iris.xpcs', 31 | 'iris.lwz', 32 | 'ldap', 33 | 'mailto', 34 | 'mid', 35 | 'modem', 36 | 'msrp', 37 | 'msrps', 38 | 'mtqp', 39 | 'mupdate', 40 | 'news', 41 | 'nfs', 42 | 'nntp', 43 | 'opaquelocktoken', 44 | 'pop', 45 | 'pres', 46 | 'rtsp', 47 | 'service', 48 | 'shttp', 49 | 'sip', 50 | 'sips', 51 | 'snmp', 52 | 'soap.beep', 53 | 'soap.beeps', 54 | 'tag', 55 | 'tel', 56 | 'telnet', 57 | 'tftp', 58 | 'thismessage', 59 | 'tip', 60 | 'tv', 61 | 'urn', 62 | 'vemmi', 63 | 'xmlrpc.beep', 64 | 'xmlrpc.beeps', 65 | 'xmpp', 66 | 'z39.50r', 67 | 'z39.50s', 68 | 'afs', 69 | 'dtn', 70 | 'iax', 71 | 'mailserver', 72 | 'pack', 73 | 'tn3270', 74 | 'prospero', 75 | 'snews', 76 | 'videotex', 77 | 'wais',] 78 | -------------------------------------------------------------------------------- /examples/foaf-bond.ttl: -------------------------------------------------------------------------------- 1 | # First, we declare some useful URL prefixes. 2 | 3 | @prefix rdf: . 4 | @prefix rdfs: . 5 | @prefix foaf: . 6 | @prefix : . 7 | 8 | # Second, we declare enough of a class hierarchy to get us somewhere. 9 | 10 | foaf:Agent a rdfs:Class ; 11 | rdfs:subClassOf rdf:Resource . 12 | 13 | foaf:Person a rdfs:Class ; 14 | rdfs:subClassOf foaf:Agent . 15 | 16 | foaf:Organization a rdfs:Class ; 17 | rdfs:subClassOf foaf:Agent . 18 | 19 | # Finally, we're ready to declare our data. 20 | 21 | :HMSS a foaf:Organization ; 22 | foaf:name "Her Majesty's Secret Service" ; 23 | foaf:nick "HMSS" ; 24 | foaf:member :M ; 25 | foaf:member :Q ; 26 | foaf:member :Bond ; 27 | foaf:member :Kerim . 28 | 29 | :M a foaf:Person ; 30 | foaf:name "M" ; 31 | foaf:knows :Q ; 32 | foaf:knows :Bond ; 33 | foaf:knows :Kerim . 34 | 35 | :Q a foaf:Person ; 36 | foaf:name "Q" ; 37 | foaf:knows :M ; 38 | foaf:knows :Bond . 39 | 40 | :Bond a foaf:Person ; 41 | foaf:name "James Bond" ; 42 | foaf:knows :M ; 43 | foaf:knows :Q . 44 | 45 | :Kerim a foaf:Person ; 46 | foaf:name "Darko Kerim" ; 47 | foaf:knows :M . 48 | -------------------------------------------------------------------------------- /pymantic/scripts/named_graph_to_nquads: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import optparse 3 | import os.path 4 | import pymantic 5 | import rdflib 6 | import urllib 7 | 8 | if __name__ == '__main__': 9 | usage = """usage: %prog [options] filename1 filename2 ... 10 | Reads in RDF graphs and reserializes them as nquads to stdout, using the basename of each filename as the graph name.""" 11 | parser = optparse.OptionParser(usage = usage) 12 | 13 | parser.add_option('-f', '--input-format', dest='input_format', default='application/rdf+xml', 14 | help='The content type of the input graphs. Default: application/rdf+xml') 15 | parser.add_option('-p', '--plain-filenames', dest='unquote', 16 | default=True, action='store_false', 17 | help="Are the filenames graph names, or do they need to be urllib.unquote'd?") 18 | 19 | (options, args) = parser.parse_args() 20 | 21 | for filename in args: 22 | graph_name = urllib.unquote(os.path.basename(filename)) if options.unquote\ 23 | else os.path.basename(filename) 24 | graph = rdflib.ConjunctiveGraph() 25 | rdf_in = open(filename, 'rb') 26 | graph.parse(rdf_in, publicID=graph_name, 27 | format=pymantic.content_type_to_rdflib_format[options.input_format]) 28 | print graph.serialize(format = 'nq') 29 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ======== 2 | Pymantic 3 | ======== 4 | --------------------------------------- 5 | Semantic Web and RDF library for Python 6 | --------------------------------------- 7 | 8 | 9 | Quick Start 10 | =========== 11 | :: 12 | 13 | >>> from pymantic.rdf import * 14 | >>> from pymantic.parsers import turtle_parser 15 | >>> from urllib2 import urlopen 16 | >>> Resource.prefixes['foaf'] = Prefix('http://xmlns.com/foaf/0.1/') 17 | >>> graph = turtle_parser.parse(urlopen('https://raw.github.com/norcalrdf/pymantic/master/examples/foaf-bond.ttl')) 18 | >>> bond_james = Resource(graph, 'http://example.org/stuff/Bond') 19 | >>> print "%s knows:" % (bond_james.get_scalar('foaf:name'),) 20 | >>> for person in bond_james['foaf:knows']: 21 | print person.get_scalar('foaf:name') 22 | 23 | 24 | 25 | Requirements 26 | ============ 27 | 28 | Pymantic requires Python 2.6 or higher. Lepl is used for the Turtle and NTriples parser. httplib2 is used for HTTP 29 | requests and the SPARQL client. simplejson and lxml are required by the SPARQL client as well. 30 | 31 | 32 | Install 33 | ======= 34 | 35 | :: 36 | 37 | $ python setup.py install 38 | 39 | This will install Pymantic and all its dependencies. 40 | 41 | 42 | Documentation 43 | ============= 44 | 45 | Generating a local copy of the documentation requires Sphinx: 46 | 47 | :: 48 | 49 | $ easy_install Sphinx 50 | 51 | 52 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/rdfq-results.ttl: -------------------------------------------------------------------------------- 1 | # from http://www.w3.org/2003/03/rdfqr-tests/recording-query-results.html 2 | 3 | @prefix rdf: . 4 | @prefix rs: . 5 | 6 | 7 | <> rdf:type rs:ResultSet ; 8 | rs:size 4 ; 9 | rs:resultVariable "x" ; rs:resultVariable "y" ; 10 | rs:solution 11 | [ rdf:type rs:ResultSolution ; 12 | rs:binding [ rs:variable "x" ; rs:value 123 ] ; 13 | rs:binding [ rs:variable "y" ; rs:value ] 14 | ] ; 15 | 16 | rs:solution 17 | [ rdf:type rs:ResultSolution ; 18 | rs:binding [ rs:variable "x" ; 19 | rs:value "2003-01-21" ] ; 20 | rs:binding [ rs:variable "y" ; 21 | rs:value ] 22 | ] ; 23 | 24 | rs:solution 25 | [ rdf:type rs:ResultSolution ; 26 | rs:binding [ rs:variable "x" ; 27 | rs:value "anon1" ] ; 28 | rs:binding [ rs:variable "y" ; 29 | rs:value _:a ] 30 | ] ; 31 | 32 | rs:solution 33 | [ rdf:type rs:ResultSolution ; 34 | rs:binding [ rs:variable "x" ; 35 | rs:value "anon2" ] ; 36 | rs:binding [ rs:variable "y" ; 37 | rs:value _:a ] 38 | ] ; 39 | . 40 | -------------------------------------------------------------------------------- /pymantic/tests/test_util.py: -------------------------------------------------------------------------------- 1 | from nose.tools import * 2 | from pymantic.util import * 3 | 4 | def test_normalize_iri_no_escapes(): 5 | uri = 'http://example.com/foo/bar?garply=aap&maz=bies' 6 | normalized = normalize_iri(uri) 7 | assert normalized == u'http://example.com/foo/bar?garply=aap&maz=bies' 8 | assert normalized == normalize_iri(normalized) 9 | assert quote_normalized_iri(normalized) == uri 10 | 11 | def test_normalize_iri_escaped_slash(): 12 | uri = 'http://example.com/foo%2Fbar?garply=aap&maz=bies' 13 | normalized = normalize_iri(uri) 14 | print normalized 15 | assert normalized == u'http://example.com/foo%2Fbar?garply=aap&maz=bies' 16 | assert normalized == normalize_iri(normalized) 17 | assert quote_normalized_iri(normalized) == uri 18 | 19 | def test_normalize_iri_escaped_ampersand(): 20 | uri = 'http://example.com/foo/bar?garply=aap%26yak&maz=bies' 21 | normalized = normalize_iri(uri) 22 | assert normalized == u'http://example.com/foo/bar?garply=aap%26yak&maz=bies' 23 | assert normalized == normalize_iri(normalized) 24 | assert quote_normalized_iri(normalized) == uri 25 | 26 | def test_normalize_iri_escaped_international(): 27 | uri = 'http://example.com/foo/bar?garply=aap&maz=bi%C3%89s' 28 | normalized = normalize_iri(uri) 29 | print repr(normalized) 30 | assert normalized == u'http://example.com/foo/bar?garply=aap&maz=bi\u00C9s' 31 | assert normalized == normalize_iri(normalized) 32 | assert quote_normalized_iri(normalized) == uri 33 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import sys, os 2 | 3 | from setuptools import setup 4 | 5 | from pymantic import version 6 | 7 | setup(name='pymantic', 8 | version=version, 9 | description="Semantic Web and RDF library for Python", 10 | long_description="""""", 11 | classifiers=['Development Status :: 3 - Alpha', 12 | 'Intended Audience :: Developers', 13 | 'License :: OSI Approved :: BSD License', 14 | 'Topic :: Internet :: WWW/HTTP', 15 | 'Topic :: Scientific/Engineering :: Information Analysis', 16 | 'Topic :: Text Processing :: Markup', 17 | ], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers 18 | keywords='RDF N3 Turtle Semantics Web3.0', 19 | author='Gavin Carothers, Nick Pilon', 20 | author_email='gavin@carothers.name, npilon@gmail.com', 21 | url='http://github.com/oreillymedia/pymantic', 22 | license='BSD', 23 | packages=['pymantic'], 24 | include_package_data=True, 25 | zip_safe=False, 26 | test_suite='nose.collector', 27 | install_requires=[ 28 | 'httplib2', 29 | 'lxml', 30 | 'mock_http', 31 | 'pytz', 32 | 'simplejson', 33 | 'lepl', 34 | 'rdflib' 35 | ], 36 | entry_points=""" 37 | # -*- Entry points: -*- 38 | """, 39 | scripts = [ 40 | 'pymantic/scripts/named_graph_to_nquads', 41 | 'pymantic/scripts/bnf2html', 42 | ], 43 | ) 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009-2011, O'Reilly Media, Inc, Gavin Carothers, Nick Pilon 2 | and contributors 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | * Neither the name of the author or contributors nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without 15 | specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 21 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 24 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /docs/modules/primitives.rst: -------------------------------------------------------------------------------- 1 | :mod:`pymantic.primitives` 2 | -------------------------- 3 | 4 | This module provides a Python implementation of the 5 | `RDF Interfaces `_ defined by the W3C. 6 | Also extends that API in places to allow for Datasets and Quads. The goal is to 7 | provide a simple API for working directly with Triples, and RDF Terms. 8 | 9 | .. automodule:: pymantic.primitives 10 | 11 | Data Structures 12 | =============== 13 | 14 | .. warning:: Currently Pyamntic does *NOT* restrict data structures to the RDF data model. 15 | For example Literals are allowed in the subject and predicate position, seralizing 16 | these is imposible 17 | 18 | .. autoclass:: Triple 19 | 20 | .. autoclass:: Graph 21 | :members: 22 | 23 | Non-RDF Interfaces Classes 24 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ 25 | 26 | .. autoclass:: Quad 27 | 28 | .. autoclass:: Dataset 29 | :members: 30 | 31 | RDF Terms 32 | ========= 33 | 34 | .. autoclass:: Literal 35 | 36 | .. autoclass:: NamedNode 37 | 38 | .. autoclass:: BlankNode 39 | 40 | 41 | RDF Enviroment Interfaces 42 | ========================= 43 | 44 | .. autoclass:: RDFEnvironment 45 | :show-inheritance: 46 | :members: 47 | :undoc-members: 48 | 49 | .. autoclass:: PrefixMap 50 | :members: 51 | 52 | .. autoclass:: TermMap 53 | :members: 54 | 55 | .. autoclass:: Profile 56 | :members: 57 | 58 | Helper Functions 59 | ================ 60 | 61 | .. autofunction:: is_language 62 | 63 | .. autofunction:: lang_match 64 | 65 | .. autofunction:: parse_curie 66 | 67 | .. autofunction:: parse_curies 68 | 69 | .. autofunction:: to_curie 70 | 71 | -------------------------------------------------------------------------------- /pymantic/util.py: -------------------------------------------------------------------------------- 1 | """Utility functions used throughout pymantic.""" 2 | 3 | __all__ = ['en', 'de', 'one_or_none', 'normalize_iri', 'quote_normalized_iri',] 4 | 5 | import re 6 | from urllib import quote 7 | 8 | def en(value): 9 | """Returns an RDF literal from the en language for the given value.""" 10 | from pymantic.primitives import Literal 11 | return Literal(value, language='en') 12 | 13 | def de(value): 14 | """Returns an RDF literal from the de language for the given value.""" 15 | from pymantic.primitives import Literal 16 | return Literal(value, language='de') 17 | 18 | def one_or_none(values): 19 | """Fetch the first value from values, or None if values is empty. Raises 20 | ValueError if values has more than one thing in it.""" 21 | if not values: 22 | return None 23 | if len(values) > 1: 24 | raise ValueError('Got more than one value.') 25 | return values[0] 26 | 27 | percent_encoding_re = re.compile(r'(?:%[a-fA-F0-9][a-fA-F0-9])+') 28 | 29 | reserved_in_iri = ["%", ":", "/", "?", "#", "[", "]", "@", "!", "$", "&", "'",\ 30 | "(", ")", "*", "+", ",", ";", "="] 31 | 32 | def percent_decode(regmatch): 33 | encoded = '' 34 | for group in regmatch.group(0)[1:].split('%'): 35 | encoded += chr(int(group, 16)) 36 | uni = encoded.decode('utf-8') 37 | for res in reserved_in_iri: 38 | uni = uni.replace(res, '%%%02X' % ord(res)) 39 | return uni 40 | 41 | def normalize_iri(iri): 42 | """Normalize an IRI using the Case Normalization (5.3.2.1) and 43 | Percent-Encoding Normalization (5.3.2.3) from RFC 3987. The IRI should be a 44 | unicode object.""" 45 | return percent_encoding_re.sub(percent_decode, iri) 46 | 47 | def percent_encode(char): 48 | return ''.join('%%%02X' % ord(char) for char in char.encode('utf-8')) 49 | 50 | def quote_normalized_iri(normalized_iri): 51 | """Percent-encode a normalized IRI; IE, all reserved characters are presumed 52 | to be themselves and not percent encoded. All other unsafe characters are 53 | percent-encoded.""" 54 | normalized_uri = ''.join(percent_encode(char) if ord(char) > 127 else char for\ 55 | char in normalized_iri) 56 | return quote(normalized_uri, safe=''.join(reserved_in_iri)) 57 | -------------------------------------------------------------------------------- /pymantic/change_tracking.py: -------------------------------------------------------------------------------- 1 | from primitives import Graph, BlankNode, Triple 2 | from rdf import Resource, register_class 3 | 4 | 5 | class ChangeTrackingGraph(Graph): 6 | 7 | def __init__(self, graph_uri=None): 8 | super(Graph, self).__init__() 9 | self._added = set() 10 | self._removed = set() 11 | 12 | def add(self, triple): 13 | if not self.contains(triple): 14 | super(Graph, self).add(triple) 15 | self._added.add(triple) 16 | 17 | def remove(self, triple): 18 | if self.contains(triple): 19 | super(Graph, self).remove(triple) 20 | self._removed.add(triple) 21 | 22 | def changes(self, cls=Changes): 23 | return cls(added=frozenset(self._added), 24 | removed=frozenset(self._removed)) 25 | 26 | 27 | class ChangeSet(object): 28 | 29 | def __init__(self, added, removed): 30 | self.added = added 31 | self.removed = removed 32 | 33 | CHANGESET_NS = "http://purl.org/vocab/changeset/schema#" 34 | NS_DICT = dict(cs=CHANGESET_NS) 35 | 36 | 37 | class CSR(Resource): 38 | namespaces = NS_DICT 39 | 40 | 41 | @register_class("cs:ChangeSet") 42 | class CS(CSR): 43 | scalars = ["cs:subjectOfChange"] 44 | 45 | 46 | @register_class("rdf:Statement") 47 | class Statement(CSR): 48 | scalars = ["rdf:subject", "rdf:predicate", "rdf:object"] 49 | 50 | @classmethod 51 | def from_triple(cls, graph, triple): 52 | statement = Statement.new(graph) 53 | statement["rdf:subject"] = triple.subject 54 | statement["rdf:predicate"] = triple.predicate 55 | statement["rdf:object"] = triple.object 56 | return statement 57 | 58 | 59 | class ChangeSetGraph(ChangeSet): 60 | 61 | def as_resource(self): 62 | change_graph = Graph() 63 | cs = CS.new(change_graph) 64 | addition_statements = set() 65 | for triple in self.added: 66 | addition_statements.add(Statement.from_triple(change_graph, triple)) 67 | cs["cs:addition"] = addition_statements 68 | removal_statements = set() 69 | for triple in self.removed: 70 | removal_statements.add(Statement.from_triple(change_graph, triple)) 71 | cs["cs:removal"] = removal_statements 72 | return cs 73 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-28.out: -------------------------------------------------------------------------------- 1 | "2.345"^^ . 2 | "1.0"^^ . 3 | "1.0"^^ . 4 | "1.0"^^ . 5 | "1.0"^^ . 6 | "2.30"^^ . 7 | "2.234000005"^^ . 8 | "2.2340000005"^^ . 9 | "2.23400000005"^^ . 10 | "2.234000000005"^^ . 11 | "2.2340000000005"^^ . 12 | "2.23400000000005"^^ . 13 | "2.234000000000005"^^ . 14 | "2.2340000000000005"^^ . 15 | "2.234"^^ . 16 | "2.234"^^ . 17 | "2.234"^^ . 18 | "2.234"^^ . 19 | "2.234"^^ . 20 | "2.234"^^ . 21 | "2.234"^^ . 22 | "1.2345678901234567"^^ . 23 | -------------------------------------------------------------------------------- /pymantic/tests/test_SPARQL.py: -------------------------------------------------------------------------------- 1 | import urllib 2 | import unittest 3 | from nose import SkipTest 4 | 5 | import mock_http 6 | 7 | # from pymantic.sparql import SPARQLServer, SPARQLQueryException 8 | 9 | class TestSparql(unittest.TestCase): 10 | def setUp(self): 11 | raise SkipTest 12 | self.mock_port = 48558 13 | self.mock_endpoint = mock_http.MockHTTP(self.mock_port) 14 | 15 | def testMockSPARQL(self): 16 | """Test a SPARQL query against a mocked-up endpoint.""" 17 | test_query = """PREFIX dc: 18 | SELECT ?product ?title WHERE { ?product dc:title ?title } LIMIT 10""" 19 | test_json = '{"head": {"vars": ["product", "title"]}, "results": {"bindings": [{"product": {"type": "uri", "value": "test_product"}, "title": {"xml:lang": "en", "type": "literal", "value": "Test Title"}}]}}' 20 | 21 | self.mock_endpoint.expects( 22 | method='POST', times=mock_http.once, path='/tenuki/sparql', 23 | headers={'Content-Type': 'application/x-www-form-urlencoded',}, 24 | params={'query': test_query, 'output': 'json',}).will( 25 | body=test_json, headers={'content-type': 'application/sparql-results+json'}) 26 | sparql = SPARQLServer('http://localhost:%d/tenuki/sparql' % self.mock_port) 27 | try: 28 | results = sparql.query(test_query) 29 | finally: 30 | self.assert_(self.mock_endpoint.verify()) 31 | self.assertEqual(results['results']['bindings'][0]['product']['value'], 32 | 'test_product') 33 | self.assertEqual(results['results']['bindings'][0]['title']['value'], 34 | 'Test Title') 35 | 36 | def testMockSPARQLError(self): 37 | """Test a SPARQL query against a mocked-up endpoint.""" 38 | test_query = """PREFIX dc: 39 | SELECT ?product ?title WHERE { ?product dc:title ?title } LIMIT 10""" 40 | self.mock_endpoint.expects( 41 | method='POST', times=mock_http.once, path='/tenuki/sparql', 42 | headers={'Content-Type': 'application/x-www-form-urlencoded',}, 43 | params={'query': test_query, 'output': 'json',}).will( 44 | http_code=500) 45 | sparql = SPARQLServer('http://localhost:%d/tenuki/sparql' % self.mock_port) 46 | try: 47 | self.assertRaises(SPARQLQueryException, sparql.query, test_query) 48 | finally: 49 | self.assert_(self.mock_endpoint.verify()) 50 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/test-28.ttl: -------------------------------------------------------------------------------- 1 | "2.345"^^ . 2 | "1"^^ . 3 | "1.0"^^ . 4 | "1."^^ . 5 | "1.000000000"^^ . 6 | "2.3"^^ . 7 | "2.234000005"^^ . 8 | "2.2340000005"^^ . 9 | "2.23400000005"^^ . 10 | "2.234000000005"^^ . 11 | "2.2340000000005"^^ . 12 | "2.23400000000005"^^ . 13 | "2.234000000000005"^^ . 14 | "2.2340000000000005"^^ . 15 | "2.23400000000000005"^^ . 16 | "2.234000000000000005"^^ . 17 | "2.2340000000000000005"^^ . 18 | "2.23400000000000000005"^^ . 19 | "2.234000000000000000005"^^ . 20 | "2.2340000000000000000005"^^ . 21 | "2.23400000000000000000005"^^ . 22 | "1.2345678901234567890123457890"^^ . 23 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/manifest-bad.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix rdfs: . 3 | @prefix mf: . 4 | @prefix qt: . 5 | 6 | <> rdf:type mf:Manifest ; 7 | rdfs:comment "Turtle bad syntax test cases (must fail)" ; 8 | mf:entries 9 | ( 10 | 11 | [ mf:name "bad-00" ; 12 | rdfs:comment "prefix name must end in a :" ; 13 | mf:action [ qt:data ] ; 14 | ] 15 | 16 | [ mf:name "bad-01" ; 17 | rdfs:comment "blank predicate forbidden" ; 18 | mf:action [ qt:data ] ; 19 | ] 20 | 21 | [ mf:name "bad-02" ; 22 | rdfs:comment "blank predicate forbidden" ; 23 | mf:action [ qt:data ] ; 24 | ] 25 | 26 | [ mf:name "bad-03" ; 27 | rdfs:comment "a forbidden as subject" ; 28 | mf:action [ qt:data ] ; 29 | ] 30 | 31 | [ mf:name "bad-04" ; 32 | rdfs:comment ", not allowed in collections" ; 33 | mf:action [ qt:data ] ; 34 | ] 35 | 36 | [ mf:name "bad-05" ; 37 | rdfs:comment "{} not allowed in Turtle" ; 38 | mf:action [ qt:data ] ; 39 | ] 40 | 41 | [ mf:name "bad-06" ; 42 | rdfs:comment "is and of not allowed in Turtle" ; 43 | mf:action [ qt:data ] ; 44 | ] 45 | 46 | [ mf:name "bad-07" ; 47 | rdfs:comment "paths not allowed in Turtle" ; 48 | mf:action [ qt:data ] ; 49 | ] 50 | 51 | [ mf:name "bad-08" ; 52 | rdfs:comment "@keywords not allowed in Turtle" ; 53 | mf:action [ qt:data ] ; 54 | ] 55 | 56 | [ mf:name "bad-09" ; 57 | rdfs:comment "=> not allowed in Turtle" ; 58 | mf:action [ qt:data ] ; 59 | ] 60 | 61 | [ mf:name "bad-10" ; 62 | rdfs:comment "= not allowed in Turtle" ; 63 | mf:action [ qt:data ] ; 64 | ] 65 | 66 | [ mf:name "bad-11" ; 67 | rdfs:comment "@forAll not allowed in Turtle" ; 68 | mf:action [ qt:data ] ; 69 | ] 70 | 71 | [ mf:name "bad-12" ; 72 | rdfs:comment "@forSome not allowed in Turtle" ; 73 | mf:action [ qt:data ] ; 74 | ] 75 | 76 | [ mf:name "bad-13" ; 77 | rdfs:comment "<= not allowed in Turtle" ; 78 | mf:action [ qt:data ] ; 79 | ] 80 | 81 | [ mf:name "bad-14" ; 82 | rdfs:comment "long literal with missing end" ; 83 | mf:action [ qt:data ] ; 84 | ] 85 | 86 | 87 | # End of tests 88 | ). 89 | -------------------------------------------------------------------------------- /pymantic/tests/test_turtle.py: -------------------------------------------------------------------------------- 1 | import os.path 2 | import unittest 3 | from pymantic.parsers import turtle_parser, ntriples_parser 4 | import pymantic.rdf as rdf 5 | 6 | turtle_tests_url = 'http://dvcs.w3.org/hg/rdf/raw-file/default/rdf-turtle/tests/' 7 | 8 | prefixes = { 9 | 'mf': 'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#', 10 | 'qt': 'http://www.w3.org/2001/sw/DataAccess/tests/test-query#', 11 | } 12 | 13 | @rdf.register_class('mf:Manifest') 14 | class Manifest(rdf.Resource): 15 | prefixes = prefixes 16 | 17 | scalars = frozenset(('rdfs:comment','mf:entries')) 18 | 19 | class ManifestEntry(rdf.Resource): 20 | prefixes = prefixes 21 | 22 | scalars = frozenset(('mf:name', 'rdfs:comment', 'mf:action', 'mf:result')) 23 | 24 | class Action(rdf.Resource): 25 | prefixes = prefixes 26 | 27 | scalars = frozenset(('qt:data',)) 28 | 29 | class MetaRDFTest(type): 30 | def __new__(mcs, name, bases, dict): 31 | manifest_name = dict['manifest'] 32 | with open(manifest_name, 'r') as f: 33 | manifest_turtle = f.read() 34 | manifest_graph = turtle_parser.parse(manifest_turtle, base=dict['base']) 35 | manifest = Manifest(manifest_graph, dict['base']) 36 | entries = manifest['mf:entries'].as_(rdf.List) 37 | for entry in entries: 38 | entry = entry.as_(ManifestEntry) 39 | test_name = entry['mf:name'].value.replace('-', '_') 40 | if not test_name.startswith('test_'): 41 | test_name = 'test_' + test_name 42 | dict[test_name] = lambda self, entry=entry: self.execute(entry) 43 | # Doesn't look right in tracebacks, but looks fine in nose output. 44 | dict[test_name].func_name = test_name 45 | return type.__new__(mcs, name, bases, dict) 46 | 47 | class TurtleTests(unittest.TestCase): 48 | __metaclass__ = MetaRDFTest 49 | 50 | base = os.path.join(os.path.dirname(__file__), 'turtle_tests/') 51 | 52 | manifest = os.path.join(base, 'manifest.ttl') 53 | 54 | def execute(self, entry): 55 | with open(unicode(entry['mf:action'].as_(Action)['qt:data']), 'r') as f: 56 | in_data = f.read() 57 | with open(unicode(entry['mf:result'])) as f: 58 | compare_data = f.read() 59 | test_graph = turtle_parser.parse(in_data) 60 | compare_graph = ntriples_parser.parse_string(compare_data) 61 | 62 | class BadTurtleTests(unittest.TestCase): 63 | __metaclass__ = MetaRDFTest 64 | 65 | base = os.path.join(os.path.dirname(__file__), 'turtle_tests/') 66 | 67 | manifest = os.path.join(base, 'manifest-bad.ttl') 68 | 69 | def execute(self, entry): 70 | with open(unicode(entry['mf:action'].as_(Action)['qt:data']), 'r') as f: 71 | in_data = f.read() 72 | print in_data 73 | try: 74 | test_graph = turtle_parser.parse(in_data) 75 | except: 76 | pass 77 | else: 78 | self.fail('should not have parsed') 79 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/rdfq-results.out: -------------------------------------------------------------------------------- 1 | _:genid1 "x" . 2 | _:genid1 "123"^^ . 3 | _:genid2 "y" . 4 | _:genid2 . 5 | _:genid3 . 6 | _:genid3 _:genid1 . 7 | _:genid3 _:genid2 . 8 | _:genid4 "x" . 9 | _:genid4 "2003-01-21" . 10 | _:genid5 "y" . 11 | _:genid5 . 12 | _:genid6 . 13 | _:genid6 _:genid4 . 14 | _:genid6 _:genid5 . 15 | _:genid7 "x" . 16 | _:genid7 "anon1" . 17 | _:genid8 "y" . 18 | _:genid8 _:a . 19 | _:genid9 . 20 | _:genid9 _:genid7 . 21 | _:genid9 _:genid8 . 22 | _:genid10 "x" . 23 | _:genid10 "anon2" . 24 | _:genid11 "y" . 25 | _:genid11 _:a . 26 | _:genid12 . 27 | _:genid12 _:genid10 . 28 | _:genid12 _:genid11 . 29 | . 30 | "4"^^ . 31 | "x" . 32 | "y" . 33 | _:genid3 . 34 | _:genid6 . 35 | _:genid9 . 36 | _:genid12 . 37 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/rdf-schema.ttl: -------------------------------------------------------------------------------- 1 | # RDF Namespace document converted into Turtle 2 | 3 | @prefix : . 4 | @prefix rdf: . 5 | 6 | rdf:type a rdf:Property; 7 | :comment "Indicates membership of a class"; 8 | :label "type"@en, 9 | "type"@fr; 10 | :range :Class . 11 | 12 | :Class a :Class; 13 | :comment "The concept of Class"; 14 | :label "Class"@en, 15 | "Classe"@fr; 16 | :subClassOf :Resource . 17 | 18 | :ConstraintProperty a :Class; 19 | :comment "Properties used to express RDF Schema constraints."; 20 | :label "ConstraintProperty"@en, 21 | "Propri\u00E9t\u00E9Contrainte"@fr; 22 | :subClassOf :ConstraintResource, 23 | rdf:Property . 24 | 25 | :ConstraintResource a :Class, 26 | :Class; 27 | :comment "Resources used to express RDF Schema constraints."; 28 | :label "ConstraintResource"@en, 29 | "RessourceContrainte"@fr; 30 | :subClassOf :Resource . 31 | 32 | :Container a :Class; 33 | :comment "This represents the set Containers."; 34 | :label "Container"@en, 35 | "Enveloppe"@fr; 36 | :subClassOf :Resource . 37 | 38 | :ContainerMembershipProperty a :Class; 39 | :label "ContainerMembershipProperty"@en; 40 | :subClassOf rdf:Property . 41 | 42 | :Literal a :Class, 43 | :Class; 44 | :comment "This represents the set of atomic values, eg. textual strings."; 45 | :label "Literal"@en, 46 | "Litt\u00E9ral"@fr . 47 | 48 | :Resource a :Class; 49 | :comment "The most general class"; 50 | :label "Resource"@en, 51 | "Ressource"@fr . 52 | 53 | :comment a rdf:Property; 54 | :comment "Use this for descriptions"; 55 | :domain :Resource; 56 | :label "comment"@en, 57 | "commentaire"@fr; 58 | :range :Literal . 59 | 60 | :domain a :ConstraintProperty; 61 | :comment "This is how we associate a class with properties that its instances can have"; 62 | :label "domain"@en, 63 | "domaine"@fr . 64 | 65 | :isDefinedBy a rdf:Property; 66 | :comment "Indicates a resource containing and defining the subject resource."; 67 | :domain :Resource; 68 | :label "esD\u00E9finiPar"@fr, 69 | "isDefinedBy"@en; 70 | :range :Resource; 71 | :subPropertyOf :seeAlso . 72 | 73 | :label a rdf:Property; 74 | :comment "Provides a human-readable version of a resource name."; 75 | :domain :Resource; 76 | :label "label"@en, 77 | "label"@fr; 78 | :range :Literal . 79 | 80 | :range a :ConstraintProperty; 81 | :comment "Properties that can be used in a schema to provide constraints"; 82 | :domain rdf:Property; 83 | :label "range"@en, 84 | "\u00E9tendue"@fr; 85 | :range :Class . 86 | 87 | :seeAlso a rdf:Property; 88 | :comment "Indicates a resource that provides information about the subject resource."; 89 | :domain :Resource; 90 | :label "seeAlso"@en, 91 | "voirAussi"@fr; 92 | :range :Resource . 93 | 94 | :subClassOf a rdf:Property; 95 | :comment "Indicates membership of a class"; 96 | :domain :Class; 97 | :label "sousClasseDe"@fr, 98 | "subClassOf"@en; 99 | :range :Class . 100 | 101 | :subPropertyOf a rdf:Property; 102 | :comment "Indicates specialization of properties"; 103 | :domain rdf:Property; 104 | :label "sousPropri\u00E9t\u00E9De"@fr, 105 | "subPropertyOf"@en; 106 | :range rdf:Property . 107 | 108 | rdf:Alt a :Class; 109 | :label "Alt"@en, 110 | "Choix"@fr; 111 | :subClassOf :Container . 112 | 113 | rdf:Bag a :Class; 114 | :label "Bag"@en, 115 | "Ensemble"@fr; 116 | :subClassOf :Container . 117 | 118 | rdf:Property a :Class; 119 | :comment "The concept of a property."; 120 | :label "Property"@en, 121 | "Propri\u00E9t\u00E9"@fr; 122 | :subClassOf :Resource . 123 | 124 | rdf:Seq a :Class; 125 | :label "Sequence"@en, 126 | "S\u00E9quence"@fr; 127 | :subClassOf :Container . 128 | 129 | rdf:Statement a :Class; 130 | :comment "This represents the set of reified statements."; 131 | :label "D\u00E9claration"@fr, 132 | "Statement"@en; 133 | :subClassOf :Resource . 134 | 135 | rdf:object a rdf:Property; 136 | :domain rdf:Statement; 137 | :label "object"@en, 138 | "objet"@fr . 139 | 140 | rdf:predicate a rdf:Property; 141 | :domain rdf:Statement; 142 | :label "predicate"@en, 143 | "pr\u00E9dicat"@fr; 144 | :range rdf:Property . 145 | 146 | rdf:subject a rdf:Property; 147 | :domain rdf:Statement; 148 | :label "subject"@en, 149 | "sujet"@fr; 150 | :range :Resource . 151 | 152 | rdf:value a rdf:Property; 153 | :label "object"@en, 154 | "value"@fr . 155 | 156 | : :seeAlso . 157 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 14 | 15 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest 16 | 17 | help: 18 | @echo "Please use \`make ' where is one of" 19 | @echo " html to make standalone HTML files" 20 | @echo " dirhtml to make HTML files named index.html in directories" 21 | @echo " singlehtml to make a single large HTML file" 22 | @echo " pickle to make pickle files" 23 | @echo " json to make JSON files" 24 | @echo " htmlhelp to make HTML files and a HTML help project" 25 | @echo " qthelp to make HTML files and a qthelp project" 26 | @echo " devhelp to make HTML files and a Devhelp project" 27 | @echo " epub to make an epub" 28 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 29 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 30 | @echo " text to make text files" 31 | @echo " man to make manual pages" 32 | @echo " changes to make an overview of all changed/added/deprecated items" 33 | @echo " linkcheck to check all external links for integrity" 34 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 35 | 36 | clean: 37 | -rm -rf $(BUILDDIR)/* 38 | 39 | html: 40 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 41 | @echo 42 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 43 | 44 | dirhtml: 45 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 46 | @echo 47 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 48 | 49 | singlehtml: 50 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 51 | @echo 52 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 53 | 54 | pickle: 55 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 56 | @echo 57 | @echo "Build finished; now you can process the pickle files." 58 | 59 | json: 60 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 61 | @echo 62 | @echo "Build finished; now you can process the JSON files." 63 | 64 | htmlhelp: 65 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 66 | @echo 67 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 68 | ".hhp project file in $(BUILDDIR)/htmlhelp." 69 | 70 | qthelp: 71 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 72 | @echo 73 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 74 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 75 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Pymantic.qhcp" 76 | @echo "To view the help file:" 77 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Pymantic.qhc" 78 | 79 | devhelp: 80 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 81 | @echo 82 | @echo "Build finished." 83 | @echo "To view the help file:" 84 | @echo "# mkdir -p $$HOME/.local/share/devhelp/Pymantic" 85 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Pymantic" 86 | @echo "# devhelp" 87 | 88 | epub: 89 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 90 | @echo 91 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 92 | 93 | latex: 94 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 95 | @echo 96 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 97 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 98 | "(use \`make latexpdf' here to do that automatically)." 99 | 100 | latexpdf: 101 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 102 | @echo "Running LaTeX files through pdflatex..." 103 | make -C $(BUILDDIR)/latex all-pdf 104 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 105 | 106 | text: 107 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 108 | @echo 109 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 110 | 111 | man: 112 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 113 | @echo 114 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 115 | 116 | changes: 117 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 118 | @echo 119 | @echo "The overview file is in $(BUILDDIR)/changes." 120 | 121 | linkcheck: 122 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 123 | @echo 124 | @echo "Link check complete; look for any errors in the above output " \ 125 | "or in $(BUILDDIR)/linkcheck/output.txt." 126 | 127 | doctest: 128 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 129 | @echo "Testing of doctests in the sources finished, look at the " \ 130 | "results in $(BUILDDIR)/doctest/output.txt." 131 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/rdfs-namespace.ttl: -------------------------------------------------------------------------------- 1 | # RDFS Namespace document converted into Turtle 2 | 3 | @prefix : . 4 | @prefix rdf: . 5 | 6 | rdf:type a rdf:Property; 7 | :comment "Indicates membership of a class"; 8 | :domain :Resource; 9 | :isDefinedBy rdf:; 10 | :label "type"@en; 11 | :range :Class . 12 | 13 | rdf:Alt a :Class; 14 | :comment "A collection of alternatives."@en; 15 | :isDefinedBy rdf:; 16 | :label "Alt"@en; 17 | :subClassOf :Container . 18 | 19 | rdf:Bag a :Class; 20 | :comment "An unordered collection."@en; 21 | :isDefinedBy rdf:; 22 | :label "Bag"@en; 23 | :subClassOf :Container . 24 | 25 | rdf:Property a :Class; 26 | :comment "The concept of a property."; 27 | :isDefinedBy rdf:; 28 | :label "Property"@en; 29 | :subClassOf :Resource . 30 | 31 | rdf:Seq a :Class; 32 | :comment "An ordered collection."@en; 33 | :isDefinedBy rdf:; 34 | :label "Seq"@en; 35 | :subClassOf :Container . 36 | 37 | rdf:Statement a :Class; 38 | :comment "The class of RDF statements."; 39 | :isDefinedBy rdf:; 40 | :label "Statement"@en; 41 | :subClassOf :Resource . 42 | 43 | rdf:object a rdf:Property; 44 | :comment "The object of an RDF statement."; 45 | :domain rdf:Statement; 46 | :isDefinedBy rdf:; 47 | :label "object"@en . 48 | 49 | rdf:predicate a rdf:Property; 50 | :comment "the predicate of an RDF statement."; 51 | :domain rdf:Statement; 52 | :isDefinedBy rdf:; 53 | :label "predicate"@en; 54 | :range rdf:Property . 55 | 56 | rdf:subject a rdf:Property; 57 | :comment "The subject of an RDF statement."; 58 | :domain rdf:Statement; 59 | :isDefinedBy rdf:; 60 | :label "subject"@en; 61 | :range :Resource . 62 | 63 | rdf:value a rdf:Property; 64 | :comment "Identifies the principal value (usually a string) of a property when the property value is a structured resource"; 65 | :domain :Resource; 66 | :isDefinedBy rdf:; 67 | :label "value"@en . 68 | 69 | : :seeAlso . 70 | 71 | :Class a :Class; 72 | :comment "The concept of Class"; 73 | :isDefinedBy :; 74 | :label "Class"@en; 75 | :subClassOf :Resource . 76 | 77 | :Container a :Class; 78 | :comment "This represents the set Containers."; 79 | :isDefinedBy :; 80 | :label "Container"@en; 81 | :subClassOf :Resource . 82 | 83 | :ContainerMembershipProperty a :Class; 84 | :comment "The container membership properties, rdf:1, rdf:2, ..., all of which are sub-properties of 'member'."; 85 | :isDefinedBy :; 86 | :label "ContainerMembershipProperty"@en; 87 | :subClassOf rdf:Property . 88 | 89 | :Literal a :Class; 90 | :comment "This represents the set of atomic values, eg. textual strings."; 91 | :isDefinedBy :; 92 | :label "Literal"@en . 93 | 94 | :Resource a :Class; 95 | :comment "The class resource, everything."; 96 | :isDefinedBy :; 97 | :label "Resource"@en . 98 | 99 | :comment a rdf:Property; 100 | :comment "Use this for descriptions"; 101 | :domain :Resource; 102 | :isDefinedBy :; 103 | :label "comment"@en; 104 | :range :Literal . 105 | 106 | :domain a rdf:Property; 107 | :comment "A domain class for a property type"; 108 | :domain rdf:Property; 109 | :isDefinedBy :; 110 | :label "domain"@en; 111 | :range :Class . 112 | 113 | :isDefinedBy a rdf:Property; 114 | :comment "Indicates the namespace of a resource"; 115 | :domain :Resource; 116 | :isDefinedBy :; 117 | :label "isDefinedBy"@en; 118 | :range :Resource; 119 | :subPropertyOf :seeAlso . 120 | 121 | :label a rdf:Property; 122 | :comment "Provides a human-readable version of a resource name."; 123 | :domain :Resource; 124 | :isDefinedBy :; 125 | :label "label"@en; 126 | :range :Literal . 127 | 128 | :member a rdf:Property; 129 | :comment "a member of a container"; 130 | :domain :Container; 131 | :isDefinedBy :; 132 | :label "member"@en . 133 | 134 | :range a rdf:Property; 135 | :comment "A range class for a property type"; 136 | :domain rdf:Property; 137 | :isDefinedBy :; 138 | :label "range"@en; 139 | :range :Class . 140 | 141 | :seeAlso a rdf:Property; 142 | :comment "A resource that provides information about the subject resource"; 143 | :domain :Resource; 144 | :isDefinedBy :; 145 | :label "seeAlso"@en; 146 | :range :Resource . 147 | 148 | :subClassOf a rdf:Property; 149 | :comment "Indicates membership of a class"; 150 | :domain :Class; 151 | :isDefinedBy :; 152 | :label "subClassOf"@en; 153 | :range :Class . 154 | 155 | :subPropertyOf a rdf:Property; 156 | :comment "Indicates specialization of properties"; 157 | :domain rdf:Property; 158 | :isDefinedBy :; 159 | :label "subPropertyOf"@en; 160 | :range rdf:Property . 161 | -------------------------------------------------------------------------------- /pymantic/tests/test_parsers.py: -------------------------------------------------------------------------------- 1 | from cStringIO import StringIO 2 | from nose.tools import * 3 | from nose.plugins.skip import Skip, SkipTest 4 | from pymantic.parsers import * 5 | from pymantic.primitives import * 6 | 7 | def test_parse_ntriples_named_nodes(): 8 | test_ntriples = """ . 9 | . 10 | """ 11 | g = Graph() 12 | ntriples_parser.parse(StringIO(test_ntriples), g) 13 | assert len(g) == 2 14 | assert Triple(NamedNode('http://example.com/objects/1'), 15 | NamedNode('http://example.com/predicates/1'), 16 | NamedNode('http://example.com/objects/2')) in g 17 | assert Triple(NamedNode('http://example.com/objects/2'), 18 | NamedNode('http://example.com/predicates/2'), 19 | NamedNode('http://example.com/objects/1')) in g 20 | 21 | def test_parse_ntriples_bare_literals(): 22 | test_ntriples = """ "Foo" . 23 | "Bar" . 24 | """ 25 | g = Graph() 26 | ntriples_parser.parse(StringIO(test_ntriples), g) 27 | assert len(g) == 2 28 | assert Triple(NamedNode('http://example.com/objects/1'), 29 | NamedNode('http://example.com/predicates/1'), 30 | Literal("Foo")) in g 31 | assert Triple(NamedNode('http://example.com/objects/2'), 32 | NamedNode('http://example.com/predicates/2'), 33 | Literal("Bar")) in g 34 | 35 | def test_parse_ntriples_language_literals(): 36 | test_ntriples = """ "Foo"@en-US . 37 | "Bar"@fr . 38 | """ 39 | g = Graph() 40 | ntriples_parser.parse(StringIO(test_ntriples), g) 41 | assert len(g) == 2 42 | assert Triple(NamedNode('http://example.com/objects/1'), 43 | NamedNode('http://example.com/predicates/1'), 44 | Literal("Foo", language='en-US')) in g 45 | assert Triple(NamedNode('http://example.com/objects/2'), 46 | NamedNode('http://example.com/predicates/2'), 47 | Literal("Bar", language='fr')) in g 48 | 49 | def test_parse_ntriples_datatyped_literals(): 50 | test_ntriples = """ "Foo"^^ . 51 | "9.99"^^ . 52 | """ 53 | g = Graph() 54 | ntriples_parser.parse(StringIO(test_ntriples), g) 55 | assert len(g) == 2 56 | assert Triple(NamedNode('http://example.com/objects/1'), 57 | NamedNode('http://example.com/predicates/1'), 58 | Literal("Foo", datatype=NamedNode('http://www.w3.org/2001/XMLSchema#string'))) in g 59 | assert Triple(NamedNode('http://example.com/objects/2'), 60 | NamedNode('http://example.com/predicates/2'), 61 | Literal("9.99", datatype=NamedNode('http://www.w3.org/2001/XMLSchema#decimal'))) in g 62 | 63 | def test_parse_ntriples_mixed_literals(): 64 | test_ntriples = """ "Foo"@en-US . 65 | "9.99"^^ . 66 | """ 67 | g = Graph() 68 | ntriples_parser.parse(StringIO(test_ntriples), g) 69 | assert len(g) == 2 70 | assert Triple(NamedNode('http://example.com/objects/1'), 71 | NamedNode('http://example.com/predicates/1'), 72 | Literal("Foo", language='en-US')) in g 73 | assert Triple(NamedNode('http://example.com/objects/2'), 74 | NamedNode('http://example.com/predicates/2'), 75 | Literal("9.99", datatype=NamedNode('http://www.w3.org/2001/XMLSchema#decimal'))) in g 76 | 77 | def test_parse_ntriples_bnodes(): 78 | test_ntriples = """ _:A1 . 79 | _:A1 . 80 | """ 81 | g = Graph() 82 | ntriples_parser.parse(StringIO(test_ntriples), g) 83 | assert len(g) == 2 84 | #assert Triple(NamedNode('http://example.com/objects/1'), 85 | #NamedNode('http://example.com/predicates/1'), 86 | #NamedNode('http://example.com/objects/2')) in g 87 | #assert Triple(NamedNode('http://example.com/objects/2'), 88 | #NamedNode('http://example.com/predicates/2'), 89 | #NamedNode('http://example.com/objects/1')) in g 90 | 91 | def test_parse_turtle_example_1(): 92 | ttl = """@prefix rdf: . 93 | @prefix dc: . 94 | @prefix ex: . 95 | 96 | 97 | dc:title "RDF/XML Syntax Specification (Revised)" ; 98 | ex:editor [ 99 | ex:fullname "Dave Beckett"; 100 | ex:homePage 101 | ] .""" 102 | g = Graph() 103 | turtle_parser.parse(data=ttl, sink=g) 104 | assert len(g) == 4 105 | 106 | -------------------------------------------------------------------------------- /pymantic/serializers.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | 3 | import re 4 | import warnings 5 | 6 | def nt_escape(node_string): 7 | """Properly escape strings for n-triples and n-quads serialization.""" 8 | output_string = '' 9 | for char in node_string: 10 | if char == u'\u0009': 11 | output_string += '\\t' 12 | elif char == u'\u000A': 13 | output_string += '\\n' 14 | elif char == u'\u000D': 15 | output_string += '\\r' 16 | elif char == u'\u0022': 17 | output_string += '\\"' 18 | elif char == u'\u005C': 19 | output_string += '\\\\' 20 | elif char >= u'\u0020' and char <= u'\u0021' or\ 21 | char >= u'\u0023' and char <= u'\u005B' or\ 22 | char >= u'\u005D' and char <= u'\u007E': 23 | output_string += char.encode('utf-8') 24 | elif char >= u'\u007F' and char <= u'\uFFFF': 25 | output_string += '\\u%04X' % ord(char) 26 | elif char >= u'\U00010000' and char <= u'\U0010FFFF': 27 | output_string += '\\U%08X' % ord(char) 28 | return output_string 29 | 30 | def serialize_ntriples(graph, f): 31 | for triple in graph: 32 | f.write(str(triple)) 33 | 34 | def serialize_nquads(dataset, f): 35 | for quad in dataset: 36 | f.write(str(quad)) 37 | 38 | def default_bnode_name_generator(): 39 | i = 0 40 | while True: 41 | yield '_b' + str(i) 42 | i += 1 43 | 44 | def escape_prefix_local(prefix): 45 | prefix, colon, local = prefix.partition(':') 46 | for esc_char in "~.-!$&'()*+,;=:/?#@%_": 47 | local = local.replace(esc_char, '\\' + esc_char) 48 | return ''.join((prefix,colon,local)) 49 | 50 | def turtle_string_escape(string): 51 | """Escape a string appropriately for output in turtle form.""" 52 | from pymantic.parsers import TurtleParser 53 | 54 | for escaped, value in TurtleParser.echar_map.iteritems(): 55 | string = string.replace(value, '\\' + escaped) 56 | return '"' + string + '"' 57 | 58 | def turtle_repr(node, profile, name_map, bnode_name_maker): 59 | """Turn a node in an RDF graph into its turtle representation.""" 60 | if node.interfaceName == 'NamedNode': 61 | name = profile.prefixes.shrink(node) 62 | if name == node: 63 | name = '<' + unicode(node) + '>' 64 | else: 65 | escape_prefix_local(name) 66 | elif node.interfaceName == 'BlankNode': 67 | if node in name_map: 68 | name = name_map[node] 69 | else: 70 | name = bnode_name_maker.next() 71 | name_map[node] = name 72 | elif node.interfaceName == 'Literal': 73 | if node.datatype == profile.resolve('xsd:string'): 74 | # Simple string. 75 | name = turtle_string_escape(node.value) 76 | elif node.datatype == None: 77 | # String with language. 78 | name = turtle_string_escape(node.value) 79 | name += '@' + node.language 80 | elif node.datatype == profile.resolve('xsd:integer'): 81 | name = node.value 82 | elif node.datatype == profile.resolve('xsd:decimal'): 83 | name = node.value 84 | elif node.datatype == profile.resolve('xsd:double'): 85 | name = node.value 86 | elif node.datatype == profile.resolve('xsd:boolean'): 87 | name = node.value 88 | else: 89 | # Unrecognized data-type. 90 | name = turtle_string_escape(node.value) 91 | name += '^' + turtle_repr(node.datatype, profile, None, None) 92 | return name 93 | 94 | def turtle_sorted_names(l, name_maker): 95 | """Sort a list of nodes in a graph by turtle name.""" 96 | return sorted((name_maker(n), n) for n in l) 97 | 98 | def serialize_turtle(graph, f, base=None, profile=None, 99 | bnode_name_generator=default_bnode_name_generator): 100 | """Serialize some turtle from a graph to f, optionally using base IRI base 101 | and prefix map from profile. If provided, subject_key will be used to order 102 | subjects, and predicate_key predicates within a subject.""" 103 | 104 | if base is not None: 105 | f.write('@base <' + base + '> .\n') 106 | if profile is None: 107 | from pymantic.primitives import Profile 108 | profile = Profile() 109 | for prefix, iri in profile.prefixes.iteritems(): 110 | if prefix != 'rdf': 111 | f.write('@prefix ' + prefix + ': <' + iri + '> .\n') 112 | 113 | name_map = OrderedDict() 114 | output_order = [] 115 | bnode_name_maker = bnode_name_generator() 116 | 117 | name_maker = lambda n: turtle_repr(n, profile, name_map, bnode_name_maker) 118 | 119 | from pymantic.rdf import List 120 | 121 | subjects = [subj for subj in graph.subjects() if not List.is_list(subj, graph)] 122 | 123 | for subject_name, subject in turtle_sorted_names(subjects, name_maker): 124 | subj_indent_size = len(subject_name) + 1 125 | f.write(subject_name + ' ') 126 | predicates = set(t.predicate for t in graph.match(subject = subject)) 127 | sorted_predicates = turtle_sorted_names(predicates, name_maker) 128 | for i, (predicate_name, predicate) in enumerate(sorted_predicates): 129 | if i != 0: 130 | f.write(' ' * subj_indent_size) 131 | pred_indent_size = subj_indent_size + len(predicate_name) + 1 132 | f.write(predicate_name + ' ') 133 | for j, triple in enumerate(graph.match(subject = subject, 134 | predicate = predicate)): 135 | if j != 0: 136 | f.write(',\n' + ' ' * pred_indent_size) 137 | if List.is_list(triple.object, graph): 138 | f.write('(') 139 | for k, o in enumerate(List(graph, triple.object)): 140 | if k != 0: 141 | f.write(' ') 142 | f.write(name_maker(o)) 143 | f.write(')') 144 | else: 145 | f.write(name_maker(triple.object)) 146 | f.write(' ;\n') 147 | f.write(' ' * subj_indent_size + '.\n\n') 148 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Pymantic documentation build configuration file, created by 4 | # sphinx-quickstart on Tue Mar 29 15:08:35 2011. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this 9 | # autogenerated file. 10 | # 11 | # All configuration values have a default; values that are commented out 12 | # serve to show the default. 13 | 14 | import sys, os 15 | 16 | try: 17 | from pymantic import version, release 18 | except ImportError: 19 | # The version info for the project you're documenting, acts as replacement for 20 | # |version| and |release|, also used in various other places throughout the 21 | # built documents. 22 | # 23 | # The short X.Y version. 24 | version = '0.1' 25 | # The full version, including alpha/beta/rc tags. 26 | release = version + 'alpha' 27 | 28 | # If extensions (or modules to document with autodoc) are in another directory, 29 | # add these directories to sys.path here. If the directory is relative to the 30 | # documentation root, use os.path.abspath to make it absolute, like shown here. 31 | #sys.path.insert(0, os.path.abspath('.')) 32 | 33 | # -- General configuration ----------------------------------------------------- 34 | 35 | # If your documentation needs a minimal Sphinx version, state it here. 36 | #needs_sphinx = '1.0' 37 | 38 | # Add any Sphinx extension module names here, as strings. They can be extensions 39 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 40 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.viewcode', 'sphinx.ext.doctest'] 41 | 42 | # Add any paths that contain templates here, relative to this directory. 43 | templates_path = ['_templates'] 44 | 45 | # The suffix of source filenames. 46 | source_suffix = '.rst' 47 | 48 | # The encoding of source files. 49 | #source_encoding = 'utf-8-sig' 50 | 51 | # The master toctree document. 52 | master_doc = 'contents' 53 | 54 | # General information about the project. 55 | project = u'Pymantic' 56 | copyright = u'2011, Gavin Carothers, Nick Pilon' 57 | 58 | 59 | # The language for content autogenerated by Sphinx. Refer to documentation 60 | # for a list of supported languages. 61 | #language = None 62 | 63 | # There are two options for replacing |today|: either, you set today to some 64 | # non-false value, then it is used: 65 | #today = '' 66 | # Else, today_fmt is used as the format for a strftime call. 67 | #today_fmt = '%B %d, %Y' 68 | 69 | # List of patterns, relative to source directory, that match files and 70 | # directories to ignore when looking for source files. 71 | exclude_patterns = ['_build'] 72 | 73 | # The reST default role (used for this markup: `text`) to use for all documents. 74 | #default_role = None 75 | 76 | # If true, '()' will be appended to :func: etc. cross-reference text. 77 | add_function_parentheses = True 78 | 79 | # If true, the current module name will be prepended to all description 80 | # unit titles (such as .. function::). 81 | add_module_names = True 82 | 83 | # If true, sectionauthor and moduleauthor directives will be shown in the 84 | # output. They are ignored by default. 85 | #show_authors = False 86 | 87 | # The name of the Pygments (syntax highlighting) style to use. 88 | pygments_style = 'sphinx' 89 | 90 | # A list of ignored prefixes for module index sorting. 91 | #modindex_common_prefix = [] 92 | 93 | 94 | # -- Options for HTML output --------------------------------------------------- 95 | 96 | # The theme to use for HTML and HTML Help pages. See the documentation for 97 | # a list of builtin themes. 98 | html_theme = 'haiku' 99 | 100 | # Theme options are theme-specific and customize the look and feel of a theme 101 | # further. For a list of options available for each theme, see the 102 | # documentation. 103 | #html_theme_options = {} 104 | 105 | # Add any paths that contain custom themes here, relative to this directory. 106 | #html_theme_path = [] 107 | 108 | # The name for this set of Sphinx documents. If None, it defaults to 109 | # " v documentation". 110 | #html_title = None 111 | 112 | # A shorter title for the navigation bar. Default is the same as html_title. 113 | #html_short_title = None 114 | 115 | # The name of an image file (relative to this directory) to place at the top 116 | # of the sidebar. 117 | #html_logo = None 118 | 119 | # The name of an image file (within the static path) to use as favicon of the 120 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 121 | # pixels large. 122 | #html_favicon = None 123 | 124 | # Add any paths that contain custom static files (such as style sheets) here, 125 | # relative to this directory. They are copied after the builtin static files, 126 | # so a file named "default.css" will overwrite the builtin "default.css". 127 | html_static_path = ['_static'] 128 | 129 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 130 | # using the given strftime format. 131 | html_last_updated_fmt = '%b %d, %Y' 132 | 133 | # If true, SmartyPants will be used to convert quotes and dashes to 134 | # typographically correct entities. 135 | html_use_smartypants = True 136 | 137 | # Custom sidebar templates, maps document names to template names. 138 | #html_sidebars = {} 139 | 140 | # Additional templates that should be rendered to pages, maps page names to 141 | # template names. 142 | #html_additional_pages = {} 143 | 144 | # If false, no module index is generated. 145 | #html_domain_indices = True 146 | 147 | # If false, no index is generated. 148 | #html_use_index = True 149 | 150 | # If true, the index is split into individual pages for each letter. 151 | #html_split_index = False 152 | 153 | # If true, links to the reST sources are added to the pages. 154 | #html_show_sourcelink = True 155 | 156 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 157 | #html_show_sphinx = True 158 | 159 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 160 | #html_show_copyright = True 161 | 162 | # If true, an OpenSearch description file will be output, and all pages will 163 | # contain a tag referring to it. The value of this option must be the 164 | # base URL from which the finished HTML is served. 165 | #html_use_opensearch = '' 166 | 167 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 168 | #html_file_suffix = None 169 | 170 | # Output file base name for HTML help builder. 171 | htmlhelp_basename = 'Pymanticdoc' 172 | 173 | -------------------------------------------------------------------------------- /pymantic/tests/test_primitives.py: -------------------------------------------------------------------------------- 1 | from nose.tools import * 2 | from pymantic.primitives import * 3 | import random 4 | 5 | def en(s): 6 | return Literal(s, "en") 7 | 8 | def test_to_curie_multi_match(): 9 | """Test that the longest match for prefix is used""" 10 | namespaces = {'short': "aa", 'long': "aaa"} 11 | curie = to_curie("aaab", namespaces) 12 | print curie 13 | assert curie == 'long:b' 14 | 15 | def test_simple_add(): 16 | t = Triple(NamedNode("http://example.com"), NamedNode("http://purl.org/dc/terms/issued"),en("Never!")) 17 | g = Graph() 18 | g.add(t) 19 | assert t in g 20 | 21 | def test_simple_remove(): 22 | t = Triple(NamedNode("http://example.com"), NamedNode("http://purl.org/dc/terms/issued"),en("Never!")) 23 | g = Graph() 24 | g.add(t) 25 | g.remove(t) 26 | assert t not in g 27 | 28 | def test_match_VVV_pattern(): 29 | t = Triple(NamedNode("http://example.com"), NamedNode("http://purl.org/dc/terms/issued"),en("Never!")) 30 | g = Graph() 31 | g.add(t) 32 | matches = g.match(None, None, None) 33 | assert t in matches 34 | 35 | def test_match_sVV_pattern(): 36 | t = Triple(NamedNode("http://example.com"), NamedNode("http://purl.org/dc/terms/issued"),en("Never!")) 37 | g = Graph() 38 | g.add(t) 39 | matches = g.match(NamedNode("http://example.com"), None, None) 40 | assert t in matches 41 | 42 | def test_match_sVo_pattern(): 43 | t = Triple(NamedNode("http://example.com"), NamedNode("http://purl.org/dc/terms/issued"),en("Never!")) 44 | g = Graph() 45 | g.add(t) 46 | matches = g.match(NamedNode("http://example.com"), None, en("Never!")) 47 | assert t in matches 48 | 49 | def test_match_spV_pattern(): 50 | t = Triple(NamedNode("http://example.com"), NamedNode("http://purl.org/dc/terms/issued"),en("Never!")) 51 | g = Graph() 52 | g.add(t) 53 | matches = g.match(NamedNode("http://example.com"), NamedNode("http://purl.org/dc/terms/issued"), None) 54 | assert t in matches 55 | 56 | def test_match_Vpo_pattern(): 57 | t = Triple(NamedNode("http://example.com"), NamedNode("http://purl.org/dc/terms/issued"),en("Never!")) 58 | g = Graph() 59 | g.add(t) 60 | matches = g.match(None, NamedNode("http://purl.org/dc/terms/issued"), en("Never!")) 61 | assert t in matches 62 | 63 | def test_match_VVo_pattern(): 64 | t = Triple(NamedNode("http://example.com"), NamedNode("http://purl.org/dc/terms/issued"),en("Never!")) 65 | g = Graph() 66 | g.add(t) 67 | matches = g.match(None, None, en("Never!")) 68 | assert t in matches 69 | 70 | def test_match_VpV_pattern(): 71 | t = Triple(NamedNode("http://example.com"), NamedNode("http://purl.org/dc/terms/issued"),en("Never!")) 72 | g = Graph() 73 | g.add(t) 74 | matches = g.match(None, NamedNode("http://purl.org/dc/terms/issued"), None) 75 | assert t in matches 76 | 77 | def generate_triples(n=10): 78 | for i in range(1,n): 79 | yield Triple(NamedNode("http://example/" + str(random.randint(1,1000))), 80 | NamedNode("http://example/terms/" + str(random.randint(1,1000))), 81 | Literal(random.randint(1,1000))) 82 | 83 | def test_10000_triples(): 84 | n = 10000 85 | g = Graph() 86 | for t in generate_triples(n): 87 | g.add(t) 88 | assert len(g) > n * .9 89 | matches = g.match(NamedNode("http://example.com/42"), None, None) 90 | matches = g.match(None, NamedNode("http://example/terms/42"), None) 91 | matches = g.match(None, None, Literal(42)) 92 | 93 | def test_iter_10000_triples(): 94 | n = 10000 95 | g = Graph() 96 | triples = set() 97 | for t in generate_triples(n): 98 | g.add(t) 99 | triples.add(t) 100 | assert len(g) > n * .9 101 | for t in g: 102 | triples.remove(t) 103 | assert len(triples) == 0 104 | 105 | # Dataset Tests 106 | 107 | def test_add_quad(): 108 | q = Quad(NamedNode("http://example.com/graph"),NamedNode("http://example.com"), NamedNode("http://purl.org/dc/terms/issued"),Literal("Never!")) 109 | ds = Dataset() 110 | ds.add(q) 111 | assert q in ds 112 | 113 | def test_remove_quad(): 114 | q = Quad(NamedNode("http://example.com/graph"),NamedNode("http://example.com"), NamedNode("http://purl.org/dc/terms/issued"),Literal("Never!")) 115 | ds = Dataset() 116 | ds.add(q) 117 | ds.remove(q) 118 | assert q not in ds 119 | 120 | def test_ds_len(): 121 | n = 10 122 | ds = Dataset() 123 | for q in generate_quads(n): 124 | ds.add(q) 125 | assert len(ds) == 10 126 | 127 | def test_match_ds_sVV_pattern(): 128 | q = Quad(NamedNode("http://example.com"), 129 | NamedNode("http://purl.org/dc/terms/issued"),Literal("Never!"), 130 | NamedNode("http://example.com/graph")) 131 | ds = Dataset() 132 | ds.add(q) 133 | matches = ds.match(subject=NamedNode("http://example.com")) 134 | assert q in matches 135 | 136 | def test_match_ds_quad_pattern(): 137 | q = Quad(NamedNode("http://example.com"), 138 | NamedNode("http://purl.org/dc/terms/issued"),Literal("Never!"), 139 | NamedNode("http://example.com/graph")) 140 | ds = Dataset() 141 | ds.add(q) 142 | matches = ds.match(graph="http://example.com/graph") 143 | assert q in matches 144 | 145 | def test_add_graph(): 146 | t = Triple(NamedNode("http://example.com"), NamedNode("http://purl.org/dc/terms/issued"),Literal("Never!")) 147 | g = Graph("http://example.com/graph") 148 | g.add(t) 149 | ds = Dataset() 150 | ds.add_graph(g) 151 | assert t in ds 152 | 153 | def generate_quads(n): 154 | for i in range(n): 155 | yield Quad(NamedNode("http://example/" + str(random.randint(1,1000))), 156 | NamedNode("http://purl.org/dc/terms/" + str(random.randint(1,100))), 157 | Literal(random.randint(1,1000)), 158 | NamedNode("http://example/graph/"+str(random.randint(1,1000)))) 159 | 160 | def test_10000_quads(): 161 | n = 10000 162 | ds = Dataset() 163 | for q in generate_quads(n): 164 | ds.add(q) 165 | assert len(ds) > n * .9 166 | matches = ds.match(subject=NamedNode("http://example.com/42"), 167 | graph=NamedNode("http://example/graph/42")) 168 | 169 | def test_iter_10000_quads(): 170 | n = 10000 171 | ds = Dataset() 172 | quads = set() 173 | for q in generate_quads(n): 174 | ds.add(q) 175 | quads.add(q) 176 | assert len(ds) > n * .9 177 | for quad in ds: 178 | quads.remove(quad) 179 | assert len(quads) == 0 180 | 181 | def test_interfaceName(): 182 | assert Literal("Bob", "en").interfaceName == "Literal" 183 | assert NamedNode().interfaceName == "NamedNode" 184 | 185 | def test_BlankNode_id(): 186 | b1 = BlankNode() 187 | b2 = BlankNode() 188 | assert b1.value != b2.value 189 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/manifest.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix rdfs: . 3 | @prefix mf: . 4 | @prefix qt: . 5 | 6 | <> rdf:type mf:Manifest ; 7 | rdfs:comment "Turtle good syntax test cases (must pass)" ; 8 | mf:entries 9 | ( 10 | [ mf:name "test-00" ; 11 | rdfs:comment "Blank subject" ; 12 | mf:action [ qt:data ] ; 13 | mf:result 14 | ] 15 | 16 | [ mf:name "test-01" ; 17 | rdfs:comment "@prefix and qnames" ; 18 | mf:action [ qt:data ] ; 19 | mf:result 20 | ] 21 | 22 | [ mf:name "test-02" ; 23 | rdfs:comment ", operator" ; 24 | mf:action [ qt:data ] ; 25 | mf:result 26 | ] 27 | 28 | [ mf:name "test-03" ; 29 | rdfs:comment "; operator" ; 30 | mf:action [ qt:data ] ; 31 | mf:result 32 | ] 33 | 34 | [ mf:name "test-04" ; 35 | rdfs:comment "empty [] as subject and object" ; 36 | mf:action [ qt:data ] ; 37 | mf:result 38 | ] 39 | 40 | [ mf:name "test-05" ; 41 | rdfs:comment "non-empty [] as subject and object" ; 42 | mf:action [ qt:data ] ; 43 | mf:result 44 | ] 45 | 46 | [ mf:name "test-06" ; 47 | rdfs:comment "'a' as predicate" ; 48 | mf:action [ qt:data ] ; 49 | mf:result 50 | ] 51 | 52 | [ mf:name "test-07" ; 53 | rdfs:comment "simple collection" ; 54 | mf:action [ qt:data ] ; 55 | mf:result 56 | ] 57 | 58 | [ mf:name "test-08" ; 59 | rdfs:comment "empty collection" ; 60 | mf:action [ qt:data ] ; 61 | mf:result 62 | ] 63 | 64 | [ mf:name "test-09" ; 65 | rdfs:comment "integer datatyped literal" ; 66 | mf:action [ qt:data ] ; 67 | mf:result 68 | ] 69 | 70 | [ mf:name "test-10" ; 71 | rdfs:comment "decimal integer canonicalization" ; 72 | mf:action [ qt:data ] ; 73 | mf:result 74 | ] 75 | 76 | [ mf:name "test-11" ; 77 | rdfs:comment "- and _ in names and qnames" ; 78 | mf:action [ qt:data ] ; 79 | mf:result 80 | ] 81 | 82 | [ mf:name "test-12" ; 83 | rdfs:comment "tests for rdf:_ and other qnames starting with _" ; 84 | mf:action [ qt:data ] ; 85 | mf:result 86 | ] 87 | 88 | [ mf:name "test-13" ; 89 | rdfs:comment "bare : allowed" ; 90 | mf:action [ qt:data ] ; 91 | mf:result 92 | ] 93 | 94 | [ mf:name "test-14" ; 95 | rdfs:comment "10000 triples, more than the default Bison stack size" ; 96 | mf:action [ qt:data ] ; 97 | mf:result 98 | ] 99 | 100 | [ mf:name "test-15" ; 101 | rdfs:comment "10000 triple objects (10000 triples)" ; 102 | mf:action [ qt:data ] ; 103 | mf:result 104 | ] 105 | 106 | [ mf:name "test-16" ; 107 | rdfs:comment "10000 items (10000 triples)" ; 108 | mf:action [ qt:data ] ; 109 | mf:result 110 | ] 111 | 112 | [ mf:name "test-17" ; 113 | rdfs:comment "simple long literal" ; 114 | mf:action [ qt:data ] ; 115 | mf:result 116 | ] 117 | 118 | [ mf:name "test-18" ; 119 | rdfs:comment "long literals with escapes" ; 120 | mf:action [ qt:data ] ; 121 | mf:result 122 | ] 123 | 124 | [ mf:name "test-19" ; 125 | rdfs:comment "floating point number" ; 126 | mf:action [ qt:data ] ; 127 | mf:result 128 | ] 129 | 130 | [ mf:name "test-20" ; 131 | rdfs:comment "empty literals, normal and long variant" ; 132 | mf:action [ qt:data ] ; 133 | mf:result 134 | ] 135 | 136 | [ mf:name "test-21" ; 137 | rdfs:comment "positive integer, decimal and doubles" ; 138 | mf:action [ qt:data ] ; 139 | mf:result 140 | ] 141 | 142 | [ mf:name "test-22" ; 143 | rdfs:comment "negative integer, decimal and doubles" ; 144 | mf:action [ qt:data ] ; 145 | mf:result 146 | ] 147 | 148 | [ mf:name "test-23" ; 149 | rdfs:comment "long literal ending in double quote" ; 150 | mf:action [ qt:data ] ; 151 | mf:result 152 | ] 153 | 154 | [ mf:name "test-24" ; 155 | rdfs:comment "boolean literals" ; 156 | mf:action [ qt:data ] ; 157 | mf:result 158 | ] 159 | 160 | [ mf:name "test-25" ; 161 | rdfs:comment "comments" ; 162 | mf:action [ qt:data ] ; 163 | mf:result 164 | ] 165 | 166 | [ mf:name "test-26" ; 167 | rdfs:comment "no final mewline" ; 168 | mf:action [ qt:data ] ; 169 | mf:result 170 | ] 171 | 172 | [ mf:name "test-27" ; 173 | rdfs:comment "duplicate prefix" ; 174 | mf:action [ qt:data ] ; 175 | mf:result 176 | ] 177 | 178 | [ mf:name "test-28" ; 179 | rdfs:comment "decimal data types (serializing test)" ; 180 | mf:action [ qt:data ] ; 181 | mf:result 182 | ] 183 | 184 | [ mf:name "test-29" ; 185 | rdfs:comment "Escaping U+0001 to U+007F in a URI" ; 186 | mf:action [ qt:data ] ; 187 | mf:result 188 | ] 189 | 190 | [ mf:name "test-30" ; 191 | rdfs:comment "@base" ; 192 | mf:action [ qt:data ] ; 193 | mf:result 194 | ] 195 | 196 | [ mf:name "rdf-schema" ; 197 | rdfs:comment "RDF Namespace document converted into Turtle" ; 198 | mf:action [ qt:data ] ; 199 | mf:result 200 | ] 201 | 202 | [ mf:name "rdfs-namespace" ; 203 | rdfs:comment "RDFS Namespace document converted into Turtle" ; 204 | mf:action [ qt:data ] ; 205 | mf:result 206 | ] 207 | 208 | [ mf:name "rdfq-results" ; 209 | rdfs:comment "Example query result from http://www.w3.org/2003/03/rdfqr-tests/recording-query-results.html" ; 210 | mf:action [ qt:data ] ; 211 | mf:result 212 | ] 213 | 214 | # End of tests 215 | ). 216 | -------------------------------------------------------------------------------- /pymantic/tests/test_serializers.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | 3 | from cStringIO import StringIO 4 | from nose.tools import * 5 | from pymantic.parsers import * 6 | from pymantic.primitives import * 7 | from pymantic.serializers import * 8 | 9 | def test_parse_ntriples_named_nodes(): 10 | test_ntriples = """ . 11 | . 12 | """ 13 | g = Graph() 14 | ntriples_parser.parse(StringIO(test_ntriples), g) 15 | f = StringIO() 16 | serialize_ntriples(g, f) 17 | f.seek(0) 18 | g2 = Graph() 19 | ntriples_parser.parse(f, g2) 20 | assert len(g) == 2 21 | assert Triple(NamedNode('http://example.com/objects/1'), 22 | NamedNode('http://example.com/predicates/1'), 23 | NamedNode('http://example.com/objects/2')) in g2 24 | assert Triple(NamedNode('http://example.com/objects/2'), 25 | NamedNode('http://example.com/predicates/2'), 26 | NamedNode('http://example.com/objects/1')) in g2 27 | 28 | class TestTurtleRepresentation(TestCase): 29 | def setUp(self): 30 | from pymantic.serializers import turtle_repr 31 | self.turtle_repr = turtle_repr 32 | import pymantic.primitives 33 | self.primitives = pymantic.primitives 34 | self.profile = self.primitives.Profile() 35 | 36 | def test_integer(self): 37 | lit = self.primitives.Literal(value='42', datatype=self.profile.resolve('xsd:integer')) 38 | name = self.turtle_repr(node = lit, profile = self.profile, name_map = None, bnode_name_maker = None) 39 | self.assertEqual(name, '42') 40 | 41 | def test_decimal(self): 42 | lit = self.primitives.Literal(value='4.2', datatype=self.profile.resolve('xsd:decimal')) 43 | name = self.turtle_repr(node = lit, profile = self.profile, name_map = None, bnode_name_maker = None) 44 | self.assertEqual(name, '4.2') 45 | 46 | def test_double(self): 47 | lit = self.primitives.Literal(value='4.2e1', datatype=self.profile.resolve('xsd:double')) 48 | name = self.turtle_repr(node = lit, profile = self.profile, name_map = None, bnode_name_maker = None) 49 | self.assertEqual(name, '4.2e1') 50 | 51 | def test_boolean(self): 52 | lit = self.primitives.Literal(value='true', datatype=self.profile.resolve('xsd:boolean')) 53 | name = self.turtle_repr(node = lit, profile = self.profile, name_map = None, bnode_name_maker = None) 54 | self.assertEqual(name, 'true') 55 | 56 | def test_bare_string(self): 57 | lit = self.primitives.Literal(value='Foo', datatype=self.profile.resolve('xsd:string')) 58 | name = self.turtle_repr(node = lit, profile = self.profile, name_map = None, bnode_name_maker = None) 59 | self.assertEqual(name, '"Foo"') 60 | 61 | def test_language_string(self): 62 | lit = self.primitives.Literal(value='Foo', language="en") 63 | name = self.turtle_repr(node = lit, profile = self.profile, name_map = None, bnode_name_maker = None) 64 | self.assertEqual(name, '"Foo"@en') 65 | 66 | def test_random_datatype_bare_url(self): 67 | lit = self.primitives.Literal(value='Foo', datatype=self.primitives.NamedNode("http://example.com/garply")) 68 | name = self.turtle_repr(node = lit, profile = self.profile, name_map = None, bnode_name_maker = None) 69 | self.assertEqual(name, '"Foo"^') 70 | 71 | def test_random_datatype_prefixed(self): 72 | self.profile.setPrefix('ex', self.primitives.NamedNode('http://example.com/')) 73 | lit = self.primitives.Literal(value='Foo', datatype=self.primitives.NamedNode("http://example.com/garply")) 74 | name = self.turtle_repr(node = lit, profile = self.profile, name_map = None, bnode_name_maker = None) 75 | self.assertEqual(name, '"Foo"^ex:garply') 76 | 77 | def test_named_node_bare(self): 78 | node = self.primitives.NamedNode('http://example.com/foo') 79 | name = self.turtle_repr(node = node, profile = self.profile, name_map = None, bnode_name_maker = None) 80 | self.assertEqual(name, '') 81 | 82 | def test_named_node_prefixed(self): 83 | self.profile.setPrefix('ex', self.primitives.NamedNode('http://example.com/')) 84 | node = self.primitives.NamedNode('http://example.com/foo') 85 | name = self.turtle_repr(node = node, profile = self.profile, name_map = None, bnode_name_maker = None) 86 | self.assertEqual(name, 'ex:foo') 87 | 88 | class TestTurtleSerializer(TestCase): 89 | def setUp(self): 90 | from pymantic.parsers import turtle_parser 91 | from pymantic.serializers import serialize_turtle 92 | self.turtle_parser = turtle_parser 93 | self.serialize_turtle = serialize_turtle 94 | import pymantic.primitives 95 | self.primitives = pymantic.primitives 96 | self.profile = self.primitives.Profile() 97 | 98 | def testSimpleSerialization(self): 99 | from cStringIO import StringIO 100 | basic_turtle = """@prefix dc: . 101 | @prefix example: . 102 | 103 | example:foo dc:title "Foo" . 104 | example:bar dc:title "Bar" . 105 | example:baz dc:subject example:foo .""" 106 | 107 | graph = self.turtle_parser.parse(basic_turtle) 108 | f = StringIO() 109 | self.profile.setPrefix('ex', self.primitives.NamedNode('http://example.com/')) 110 | self.profile.setPrefix('dc', self.primitives.NamedNode('http://purl.org/dc/terms/')) 111 | self.serialize_turtle(graph = graph, f = f, profile = self.profile) 112 | f.seek(0) 113 | graph2 = self.turtle_parser.parse(f.read()) 114 | f.seek(0) 115 | self.assertEqual(f.read().strip(), """@prefix ex: . 116 | @prefix xsd: . 117 | @prefix dc: . 118 | ex:bar dc:title "Bar" ; 119 | . 120 | 121 | ex:baz dc:subject ex:foo ; 122 | . 123 | 124 | ex:foo dc:title "Foo" ; 125 | .""") 126 | 127 | def testMultiplePredicates(self): 128 | from cStringIO import StringIO 129 | basic_turtle = """@prefix dc: . 130 | @prefix example: . 131 | 132 | example:foo dc:title "Foo" ; 133 | dc:author "Bar" ; 134 | dc:subject example:yesfootoo . 135 | 136 | example:garply dc:title "Garply" ; 137 | dc:author "Baz" ; 138 | dc:subject example:thegarply .""" 139 | 140 | graph = self.turtle_parser.parse(basic_turtle) 141 | f = StringIO() 142 | self.profile.setPrefix('ex', self.primitives.NamedNode('http://example.com/')) 143 | self.profile.setPrefix('dc', self.primitives.NamedNode('http://purl.org/dc/terms/')) 144 | self.serialize_turtle(graph = graph, f = f, profile = self.profile) 145 | f.seek(0) 146 | graph2 = self.turtle_parser.parse(f.read()) 147 | f.seek(0) 148 | self.assertEqual(f.read().strip(), """@prefix ex: . 149 | @prefix xsd: . 150 | @prefix dc: . 151 | ex:foo dc:author "Bar" ; 152 | dc:subject ex:yesfootoo ; 153 | dc:title "Foo" ; 154 | . 155 | 156 | ex:garply dc:author "Baz" ; 157 | dc:subject ex:thegarply ; 158 | dc:title "Garply" ; 159 | .""") 160 | 161 | def testListSerialization(self): 162 | from cStringIO import StringIO 163 | basic_turtle = """@prefix dc: . 164 | @prefix example: . 165 | 166 | example:foo dc:author ("Foo" "Bar" "Baz") .""" 167 | 168 | graph = self.turtle_parser.parse(basic_turtle) 169 | f = StringIO() 170 | self.profile.setPrefix('ex', self.primitives.NamedNode('http://example.com/')) 171 | self.profile.setPrefix('dc', self.primitives.NamedNode('http://purl.org/dc/terms/')) 172 | self.serialize_turtle(graph = graph, f = f, profile = self.profile) 173 | f.seek(0) 174 | print f.read() 175 | f.seek(0) 176 | graph2 = self.turtle_parser.parse(f.read()) 177 | f.seek(0) 178 | self.assertEqual(f.read().strip(), """@prefix ex: . 179 | @prefix xsd: . 180 | @prefix dc: . 181 | ex:foo dc:author ("Foo" "Bar" "Baz") ; 182 | .""") 183 | 184 | -------------------------------------------------------------------------------- /pymantic/scripts/bnf2html: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """Copyright © 2012 World Wide Web Consortium, (Massachusetts Institute of Technology, European Research Consortium for Informatics and Mathematics, Keio University). All Rights Reserved. This work is distributed under the W3C® Software License [1] in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 4 | 5 | [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 6 | """ 7 | 8 | import re 9 | import sys 10 | import argparse 11 | import logging 12 | 13 | from mako.template import Template 14 | 15 | logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG) 16 | 17 | prefix = None 18 | 19 | def main(): 20 | global prefix 21 | parser = argparse.ArgumentParser(description='Convert a BNF grammar into an HTML fragment') 22 | parser.add_argument('bnf', type=argparse.FileType('r'), help="BNF grammar") 23 | parser.add_argument('-p', '--prefix', help="prefix to prepend to @id of generated elements") 24 | args = parser.parse_args() 25 | prefix = args.prefix 26 | to_HTML(args.bnf) 27 | 28 | def to_HTML(lines): 29 | """print a HTML version of the lines of a BNF file 30 | """ 31 | token = False 32 | productions = [] 33 | terminals = [] 34 | for r in each_rule(lines): 35 | logging.debug(r) 36 | if r == '@terminals': token = True 37 | else: 38 | num, sym, expr = rule_parts(r) 39 | row = as_HTML(num, sym, expr, token, r) 40 | if not token: 41 | productions.append(row) 42 | else: 43 | terminals.append(row) 44 | print TABLE_TEMPLATE.render(productions=productions, terminals=terminals, prefix=prefix) 45 | 46 | 47 | ROW_TEMPLATE = Template(""" 48 | [${num}] 49 | ${sym} 50 | ::= 51 | ${hexpr} 52 | """) 53 | 54 | TABLE_TEMPLATE = Template(""" 55 | 56 | %for row in productions: 57 | ${row} 58 | %endfor 59 | 60 | 61 | %for row in terminals: 62 | ${row} 63 | %endfor 64 | 65 |
""") 66 | 67 | 68 | def as_HTML(num, sym, expr, isToken, orig): 69 | css_class = "" 70 | hexpr = html_expr(expr) 71 | return ROW_TEMPLATE.render(num=num, sym=sym, expr=escape(expr), hexpr=hexpr, isToken=isToken, orig=escape(orig), prefix=prefix) 72 | 73 | 74 | def html_expr(expr, nested=False): 75 | global prefix 76 | op, args = expr 77 | if op == '*': 78 | return "({})*".format(html_expr(args)) 79 | elif op == 'id': 80 | return "{0}".format(args, prefix + '-' if prefix else '') 81 | elif op == '|': 82 | content = " | ".join([html_expr(a, nested=True) for a in args]) 83 | return content 84 | elif op == ',': 85 | if nested: 86 | content = " ".join([html_expr(a) for a in args]) 87 | return "({})".format(content) 88 | else: 89 | return " ".join([html_expr(a) for a in args]) 90 | elif op == "'": 91 | if "'" in args: 92 | return '"{}"'.format(escape(args)) 93 | else: 94 | return "'{}'".format(escape(args)) 95 | elif op == '?': 96 | return "({})?".format(html_expr(args)) 97 | elif op == '+': 98 | return "({})+".format(html_expr(args)) 99 | elif op == '[': 100 | return "[{}]".format(args) 101 | elif op == '-': 102 | lh = args[0] 103 | rh = args[1] 104 | return "{}-{}".format(html_expr(lh), html_expr(rh)) 105 | elif op == '#': 106 | return "{}".format(escape(args)) 107 | else: 108 | return repr(expr) 109 | 110 | def each_rule(lines): 111 | """turn an iterator over lines into an iterator over rule strings. 112 | 113 | a line that starts with [ or @ starts a new rule 114 | """ 115 | 116 | r = '' 117 | for l in lines: 118 | if l.startswith("/*"): continue 119 | if l.startswith('[') or l.startswith('@'): 120 | if r: yield r 121 | r = l.strip() 122 | else: 123 | r += l.strip() 124 | if r: yield r 125 | 126 | 127 | def rule_parts(r): 128 | """parse a rule into a rule number, a symbol, and an expression 129 | 130 | >>> ruleParts("[2] Prolog ::= BaseDecl? PrefixDecl*") 131 | ('2', 'Prolog', (',', [('?', ('id', 'BaseDecl')), ('*', ('id', 'PrefixDecl'))])) 132 | 133 | """ 134 | 135 | assert r.find(']') > 0 136 | num, r = r.split(']', 1) 137 | num = num[1:] 138 | rhs, r = r.split('::=', 1) 139 | rhs = rhs.strip() 140 | return (num, rhs, ebnf(r)[0]) 141 | 142 | 143 | def ebnf(s): 144 | """parse a string into an expression tree and a remaining string 145 | 146 | >>> ebnf("a b c") 147 | ((',', [('id', 'a'), ('id', 'b'), ('id', 'c')]), '') 148 | 149 | >>> ebnf("a? b+ c*") 150 | ((',', [('?', ('id', 'a')), ('+', ('id', 'b')), ('*', ('id', 'c'))]), '') 151 | 152 | >>> ebnf(" | x xlist") 153 | (('|', [(',', []), (',', [('id', 'x'), ('id', 'xlist')])]), '') 154 | 155 | >>> ebnf("a | (b - c)") 156 | (('|', [('id', 'a'), ('-', [('id', 'b'), ('id', 'c')])]), '') 157 | 158 | >>> ebnf("a b | c d") 159 | (('|', [(',', [('id', 'a'), ('id', 'b')]), (',', [('id', 'c'), ('id', 'd')])]), '') 160 | 161 | >>> ebnf("a | b | c") 162 | (('|', [('id', 'a'), ('id', 'b'), ('id', 'c')]), '') 163 | 164 | >>> ebnf("a) b c") 165 | (('id', 'a'), ' b c') 166 | 167 | >>> ebnf("BaseDecl? PrefixDecl*") 168 | ((',', [('?', ('id', 'BaseDecl')), ('*', ('id', 'PrefixDecl'))]), '') 169 | 170 | """ 171 | 172 | e, s = alt(s) 173 | if s: 174 | t, ss = token(s) 175 | if t[0] == ')': 176 | return e, ss 177 | return e, s 178 | 179 | 180 | def alt(s): 181 | """parse alt 182 | 183 | >>> alt("a | b | c") 184 | (('|', [('id', 'a'), ('id', 'b'), ('id', 'c')]), '') 185 | 186 | """ 187 | 188 | args = [] 189 | while s: 190 | e, s = seq(s) 191 | if not e: 192 | if args: break 193 | e = (',', []) # empty sequence 194 | args.append(e) 195 | if s: 196 | t, ss = token(s) 197 | if not t[0] == '|': break 198 | s = ss 199 | if len(args) > 1: 200 | return ('|', args), s 201 | else: 202 | return e, s 203 | 204 | 205 | def seq(s): 206 | """parse seq 207 | 208 | >>> seq("a b c") 209 | ((',', [('id', 'a'), ('id', 'b'), ('id', 'c')]), '') 210 | 211 | >>> seq("a b? c") 212 | ((',', [('id', 'a'), ('?', ('id', 'b')), ('id', 'c')]), '') 213 | 214 | """ 215 | 216 | args = [] 217 | while s: 218 | e, ss = diff(s) 219 | if e: 220 | args.append(e) 221 | s = ss 222 | else: break 223 | if len(args) > 1: 224 | return (',', args), s 225 | elif len(args) == 1: 226 | return args[0], s 227 | else: 228 | return None, s 229 | 230 | 231 | def diff(s): 232 | """parse diff 233 | 234 | >>> diff("a - b") 235 | (('-', [('id', 'a'), ('id', 'b')]), '') 236 | 237 | """ 238 | 239 | e1, s = postfix(s) 240 | if e1: 241 | if s: 242 | t, ss = token(s) 243 | if t[0] == '-': 244 | s = ss 245 | e2, s = primary(s) 246 | if e2: 247 | return ('-', [e1, e2]), s 248 | else: 249 | raise SyntaxError 250 | 251 | return e1, s 252 | 253 | 254 | def postfix(s): 255 | """parse postfix 256 | 257 | >>> postfix("a b c") 258 | (('id', 'a'), ' b c') 259 | 260 | >>> postfix("a? b c") 261 | (('?', ('id', 'a')), ' b c') 262 | """ 263 | 264 | e, s = primary(s) 265 | if not e: return None, s 266 | 267 | if s: 268 | t, ss = token(s) 269 | if t[0] in '?*+': 270 | return (t[0], e), ss 271 | 272 | return e, s 273 | 274 | def primary(s): 275 | """parse primary 276 | 277 | >>> primary("a b c") 278 | (('id', 'a'), ' b c') 279 | """ 280 | 281 | t, s = token(s) 282 | if t[0] == 'id' or t[0] == "'" or t[0] == '[' or t[0] == '#': 283 | return t, s 284 | 285 | elif t[0] is '(': 286 | e, s = ebnf(s) 287 | return e, s 288 | 289 | else: 290 | return None, s 291 | 292 | 293 | def token(s): 294 | """parse one token; return the token and the remaining string 295 | 296 | A token is represented as a tuple whose 1st item gives the type; 297 | some types have additional info in the tuple. 298 | 299 | >>> token("'abc' def") 300 | (("'", 'abc'), ' def') 301 | """ 302 | 303 | s = s.strip() 304 | if s.startswith("'"): 305 | l, s = s[1:].split("'", 1) 306 | return ("'", l), s 307 | elif s.startswith('"'): 308 | l, s = s[1:].split('"', 1) 309 | return ("'", l), s 310 | elif s.startswith("["): 311 | l, s = s[1:].split("]", 1) 312 | return ("[", l), s 313 | elif s.startswith("#"): 314 | i = re.match("\w+", s[1:]).end(0) + 1 315 | return (('#', s[:i]), s[i:]) 316 | elif s[0].isalpha(): 317 | i = re.match("\w+", s).end(0) 318 | return (('id', s[:i]), s[i:]) 319 | elif s.startswith("@"): 320 | i = re.match("\w+", s[1:]).end(0) + 1 321 | return (('@', s[1:i]), s[i:]) 322 | elif s[0] in '(?)*+|-': 323 | return ((s[0],) , s[1:]) 324 | else: 325 | raise ValueError, "unrecognized token: %s" % s 326 | 327 | 328 | 329 | 330 | def escape(s): 331 | escape_map_full = {ord('&'): u'&', ord('<'): u'<', ord('>'): u'>', ord('"'): u'"', ord('\''): u'''} 332 | return unicode(s).translate(escape_map_full) 333 | 334 | if __name__ == '__main__': 335 | main() 336 | -------------------------------------------------------------------------------- /pymantic/sparql.py: -------------------------------------------------------------------------------- 1 | """Provide an interface to SPARQL query endpoints.""" 2 | 3 | from cStringIO import StringIO 4 | import datetime 5 | import urllib 6 | import urlparse 7 | 8 | import httplib2 9 | from lxml import objectify 10 | import pytz 11 | import rdflib 12 | import simplejson 13 | 14 | import logging 15 | 16 | log = logging.getLogger(__name__) 17 | 18 | class SPARQLQueryException(Exception): 19 | """Raised when the SPARQL store returns an HTTP status code other than 200 OK.""" 20 | pass 21 | 22 | class UnknownSPARQLReturnTypeException(Exception): 23 | """Raised when the SPARQL store provides a response with an unrecognized content-type.""" 24 | pass 25 | 26 | class _SelectOrUpdate(object): 27 | """A server that can run SPARQL queries.""" 28 | 29 | def __init__(self, server, sparql, default_graph=None, named_graph=None, *args, **kwargs): 30 | self.server = server 31 | self.sparql = sparql 32 | self.default_graphs=default_graph 33 | self.named_graphs=named_graph 34 | self.headers = dict() 35 | self.params = dict() 36 | 37 | # abstract methods, see Select for the idea 38 | def default_graph_uri(self): 39 | pass 40 | 41 | def named_graph_uri(self): 42 | pass 43 | 44 | def query_or_update(self): 45 | pass 46 | 47 | def directContentType(self): 48 | pass 49 | 50 | def postQueries(self): 51 | pass 52 | 53 | def execute(self): 54 | http = httplib2.Http() 55 | 56 | log.debug("Querying: %s with: %r", self.server.query_url, self.sparql) 57 | 58 | sparql = self.sparql.encode('utf-8') 59 | 60 | if self.default_graphs: 61 | self.params[self.default_graph_uri()] = self.default_graphs 62 | if self.named_graphs: 63 | self.params[self.named_graph_uri()] = self.named_graphs 64 | 65 | if self.server.post_directly: 66 | self.headers["Content-Type"] = self.directContentType() + "; charset=utf-8" 67 | uri_params = urllib.urlencode(self.params, doseq=True) 68 | body = sparql 69 | method='POST' 70 | elif self.postQueries(): 71 | self.headers["Content-Type"] = "application/x-www-form-urlencoded" 72 | uri_params = None 73 | self.params[self.query_or_update()] = sparql 74 | body = urllib.urlencode(self.params, doseq=True) 75 | method='POST' 76 | else: 77 | # select only 78 | self.params[self.query_or_update()] = sparql 79 | uri_params = urllib.urlencode(self.params, doseq=True) 80 | body = None 81 | method='GET' 82 | 83 | uri = self.server.query_url 84 | if uri_params: 85 | uri = uri + "?" + uri_params 86 | response, content = http.request(uri=uri, method=method, headers=self.headers, body=body) 87 | if response['status'] == '204': 88 | return True 89 | if response['status'] != '200': 90 | raise SPARQLQueryException('%s: %s\nQuery: %s' % (response, content, self.sparql)) 91 | return response, content 92 | 93 | class _Select(_SelectOrUpdate): 94 | 95 | acceptable_xml_responses = [ 96 | 'application/rdf+xml', 97 | 'application/sparql-results+xml', 98 | ] 99 | 100 | acceptable_json_responses = [ 101 | 'application/sparql-results+json', 102 | 'text/turtle', 103 | ] 104 | 105 | def __init__(self, server, query, timeout, output='json', *args,**kwargs): 106 | super(_Select,self).__init__(server, query, *args,**kwargs) 107 | if output=='xml': 108 | self.headers['Accept'] = ','.join(self.acceptable_xml_responses) 109 | else: 110 | self.headers['Accept'] = ','.join(self.acceptable_json_responses) 111 | 112 | if timeout is not None: 113 | self.headers['X-BIGDATA-MAX-QUERY-MILLIS'] = str(timeout) 114 | 115 | def default_graph_uri(self): 116 | return 'default-graph-uri' 117 | 118 | def named_graph_uri(self): 119 | return 'named-graph-uri' 120 | 121 | def query_or_update(self): 122 | return 'query' 123 | 124 | def directContentType(self): 125 | return 'application/sparql-query' 126 | 127 | def postQueries(self): 128 | return self.server.post_queries 129 | 130 | def execute(self): 131 | response, content = super(_Select,self).execute() 132 | format = None 133 | if response['content-type'].startswith('application/rdf+xml'): 134 | format = 'xml' 135 | elif response['content-type'].startswith('text/turtle'): 136 | format = 'turtle' 137 | 138 | if format: 139 | graph = rdflib.ConjunctiveGraph() 140 | graph.parse(StringIO(content), self.query_url, format=format) 141 | return graph 142 | elif response['content-type'].startswith('application/sparql-results+json'): 143 | # See http://stackoverflow.com/a/19366580/2276263 144 | # for justification of unicode() below 145 | return simplejson.loads(unicode(content, "utf-8")) 146 | elif response['content-type'].startswith('application/sparql-results+xml'): 147 | return objectify.parse(StringIO(content)) 148 | else: 149 | raise UnknownSPARQLReturnTypeException('Got content of type: %s' % 150 | response['content-type']) 151 | 152 | class _Update(_SelectOrUpdate): 153 | def default_graph_uri(self): 154 | return 'using-graph-uri' 155 | 156 | def named_graph_uri(self): 157 | return 'using-named-graph-uri' 158 | 159 | def query_or_update(self): 160 | return 'update' 161 | 162 | def directContentType(self): 163 | return 'application/sparql-update' 164 | 165 | def postQueries(self): 166 | return True 167 | 168 | class SPARQLServer(object): 169 | """A server that can run SPARQL queries.""" 170 | 171 | def __init__(self, query_url, post_queries=False, post_directly=False): 172 | self.query_url = query_url 173 | self.post_queries = post_queries 174 | self.post_directly = post_directly 175 | 176 | acceptable_sparql_responses = [ 177 | 'application/sparql-results+json', 178 | 'application/rdf+xml', 179 | 'application/sparql-results+xml', 180 | ] 181 | 182 | def query(self, sparql, timeout=None, *args, **kwargs): 183 | """Executes a SPARQL query. The return type varies based on what the 184 | SPARQL store responds with: 185 | 186 | * application/rdf+xml: an rdflib.ConjunctiveGraph 187 | * application/sparql-results+json: A dictionary from simplejson 188 | * application/sparql-results+xml: An lxml.objectify structure 189 | 190 | :param sparql: The SPARQL to execute. 191 | :returns: The results of the query from the SPARQL store.""" 192 | return _Select(self, sparql, timeout, *args, **kwargs).execute() 193 | 194 | def update(self, sparql, **kwargs): 195 | """Executes a SPARQL update. 196 | 197 | :param sparql: The SPARQL Update request to execute.""" 198 | return _Update(self, sparql, **kwargs).execute() 199 | 200 | class UpdateableGraphStore(SPARQLServer): 201 | """SPARQL server class that is capable of interacting with SPARQL 1.1 202 | graph stores.""" 203 | 204 | def __init__(self, query_url, dataset_url, param_style = True, **kwargs): 205 | super(UpdateableGraphStore, self).__init__(query_url, **kwargs) 206 | self.dataset_url = dataset_url 207 | self.param_style = param_style 208 | 209 | acceptable_graph_responses = [ 210 | 'text/plain', 211 | 'application/rdf+xml', 212 | 'text/turtle', 213 | 'text/rdf+n3', 214 | ] 215 | 216 | def request_url(self, graph_uri): 217 | if self.param_style: 218 | return self.dataset_url + '?' + urllib.urlencode({'graph': graph_uri}) 219 | else: 220 | return urlparse.urljoin(self.dataset_url, urllib.quote_plus(graph_uri)) 221 | 222 | def get(self, graph_uri): 223 | h = httplib2.Http() 224 | resp, content = h.request( 225 | uri = self.request_url(graph_uri), method = 'GET', 226 | headers = {'Accept': ','.join(self.acceptable_graph_responses),},) 227 | if resp['status'] != '200': 228 | raise Exception('Error from Graph Store (%s): %s' %\ 229 | (resp['status'], content)) 230 | graph = rdflib.ConjunctiveGraph() 231 | if resp['content-type'].startswith('text/plain'): 232 | graph.parse(StringIO(content), publicID=graph_uri, format='nt') 233 | elif resp['content-type'].startswith('application/rdf+xml'): 234 | graph.parse(StringIO(content), publicID=graph_uri, format='xml') 235 | elif resp['content-type'].startswith('text/turtle'): 236 | graph.parse(StringIO(content), publicID=graph_uri, format='turtle') 237 | elif resp['content-type'].startswith('text/rdf+n3'): 238 | graph.parse(StringIO(content), publicID=graph_uri, format='n3') 239 | return graph 240 | 241 | def delete(self, graph_uri): 242 | h = httplib2.Http() 243 | resp, content = h.request(uri = self.request_url(graph_uri), 244 | method = 'DELETE') 245 | if resp['status'] != '200' and resp['status'] != '202': 246 | raise Exception('Error from Graph Store (%s): %s' %\ 247 | (resp['status'], content)) 248 | 249 | def put(self, graph_uri, graph): 250 | h = httplib2.Http() 251 | graph_triples = graph.serialize(format = 'nt') 252 | resp, content = h.request(uri = self.request_url(graph_uri), 253 | method = 'PUT', body = graph_triples, 254 | headers = {'content-type': 'text/plain',},) 255 | if resp['status'] not in ('200', '201', '204'): 256 | raise Exception('Error from Graph Store (%s): %s' %\ 257 | (resp['status'], content)) 258 | 259 | def post(self, graph_uri, graph): 260 | h = httplib2.Http() 261 | graph_triples = graph.serialize(format = 'nt') 262 | if graph_uri != None: 263 | resp, content = h.request(uri = self.request_url(graph_uri), 264 | method = 'POST', body = graph_triples, 265 | headers = {'content-type': 'text/plain',},) 266 | if resp['status'] not in ('200', '201', '204'): 267 | raise Exception('Error from Graph Store (%s): %s' %\ 268 | (resp['status'], content)) 269 | else: 270 | resp, content = h.request(uri = self.dataset_url, method = 'POST', 271 | body = graph_triples, 272 | headers = {'content-type': 'text/plain',},) 273 | if resp['status'] != '201': 274 | raise Exception('Error from Graph Store (%s): %s' %\ 275 | (resp['status'], content)) 276 | 277 | class PatchableGraphStore(UpdateableGraphStore): 278 | """A graph store that supports the optional PATCH method of updating 279 | RDF graphs.""" 280 | 281 | def patch(self, graph_uri, changeset): 282 | h = httplib2.Http() 283 | graph_xml = changeset.serialize(format = 'xml', encoding='utf-8') 284 | resp, content = h.request( 285 | uri = self.request_url(graph_uri), method = 'PATCH', body = graph_xml, 286 | headers = {'content-type': 'application/vnd.talis.changeset+xml',},) 287 | if resp['status'] not in ('200', '201', '204'): 288 | raise Exception('Error from Graph Store (%s): %s' %\ 289 | (resp['status'], content)) 290 | return True 291 | 292 | def changeset(a,b, graph_uri): 293 | """Create an RDF graph with the changeset between graphs a and b""" 294 | cs = rdflib.Namespace("http://purl.org/vocab/changeset/schema#") 295 | graph = rdflib.Graph() 296 | graph.namespace_manager.bind("cs", cs) 297 | removal, addition = differences(a,b) 298 | change_set = rdflib.BNode() 299 | graph.add((change_set, rdflib.RDF.type, cs["ChangeSet"])) 300 | graph.add((change_set, cs["createdDate"], rdflib.Literal(datetime.datetime.now(pytz.UTC).isoformat()))) 301 | graph.add((change_set, cs["subjectOfChange"], rdflib.URIRef(graph_uri))) 302 | 303 | for stmt in removal: 304 | statement = reify(graph, stmt) 305 | graph.add((change_set, cs["removal"], statement)) 306 | for stmt in addition: 307 | statement = reify(graph, stmt) 308 | graph.add((change_set, cs["addition"], statement)) 309 | return graph 310 | 311 | def reify(graph, statement): 312 | """Add reifed statement to graph""" 313 | s,p,o = statement 314 | statement_node = rdflib.BNode() 315 | graph.add((statement_node, rdflib.RDF.type, rdflib.RDF.Statement)) 316 | graph.add((statement_node, rdflib.RDF.subject,s)) 317 | graph.add((statement_node, rdflib.RDF.predicate, p)) 318 | graph.add((statement_node, rdflib.RDF.object, o)) 319 | return statement_node 320 | 321 | def differences(a, b, exclude=[]): 322 | """Return (removes,adds) excluding statements with a predicate in exclude""" 323 | exclude = [rdflib.URIRef(excluded) for excluded in exclude] 324 | return ([s for s in a if s not in b and s[1] not in exclude], 325 | [s for s in b if s not in a and s[1] not in exclude]) 326 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/rdf-schema.out: -------------------------------------------------------------------------------- 1 | . 2 | "Indicates membership of a class" . 3 | "type"@en . 4 | "type"@fr . 5 | . 6 | . 7 | "The concept of Class" . 8 | "Class"@en . 9 | "Classe"@fr . 10 | . 11 | . 12 | "Properties used to express RDF Schema constraints." . 13 | "ConstraintProperty"@en . 14 | "Propri\u00E9t\u00E9Contrainte"@fr . 15 | . 16 | . 17 | . 18 | . 19 | "Resources used to express RDF Schema constraints." . 20 | "ConstraintResource"@en . 21 | "RessourceContrainte"@fr . 22 | . 23 | . 24 | "This represents the set Containers." . 25 | "Container"@en . 26 | "Enveloppe"@fr . 27 | . 28 | . 29 | "ContainerMembershipProperty"@en . 30 | . 31 | . 32 | . 33 | "This represents the set of atomic values, eg. textual strings." . 34 | "Literal"@en . 35 | "Litt\u00E9ral"@fr . 36 | . 37 | "The most general class" . 38 | "Resource"@en . 39 | "Ressource"@fr . 40 | . 41 | "Use this for descriptions" . 42 | . 43 | "comment"@en . 44 | "commentaire"@fr . 45 | . 46 | . 47 | "This is how we associate a class with properties that its instances can have" . 48 | "domain"@en . 49 | "domaine"@fr . 50 | . 51 | "Indicates a resource containing and defining the subject resource." . 52 | . 53 | "esD\u00E9finiPar"@fr . 54 | "isDefinedBy"@en . 55 | . 56 | . 57 | . 58 | "Provides a human-readable version of a resource name." . 59 | . 60 | "label"@en . 61 | "label"@fr . 62 | . 63 | . 64 | "Properties that can be used in a schema to provide constraints" . 65 | . 66 | "range"@en . 67 | "\u00E9tendue"@fr . 68 | . 69 | . 70 | "Indicates a resource that provides information about the subject resource." . 71 | . 72 | "seeAlso"@en . 73 | "voirAussi"@fr . 74 | . 75 | . 76 | "Indicates membership of a class" . 77 | . 78 | "sousClasseDe"@fr . 79 | "subClassOf"@en . 80 | . 81 | . 82 | "Indicates specialization of properties" . 83 | . 84 | "sousPropri\u00E9t\u00E9De"@fr . 85 | "subPropertyOf"@en . 86 | . 87 | . 88 | "Alt"@en . 89 | "Choix"@fr . 90 | . 91 | . 92 | "Bag"@en . 93 | "Ensemble"@fr . 94 | . 95 | . 96 | "The concept of a property." . 97 | "Property"@en . 98 | "Propri\u00E9t\u00E9"@fr . 99 | . 100 | . 101 | "Sequence"@en . 102 | "S\u00E9quence"@fr . 103 | . 104 | . 105 | "This represents the set of reified statements." . 106 | "D\u00E9claration"@fr . 107 | "Statement"@en . 108 | . 109 | . 110 | . 111 | "object"@en . 112 | "objet"@fr . 113 | . 114 | . 115 | "predicate"@en . 116 | "pr\u00E9dicat"@fr . 117 | . 118 | . 119 | . 120 | "subject"@en . 121 | "sujet"@fr . 122 | . 123 | . 124 | "object"@en . 125 | "value"@fr . 126 | . 127 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/rdfs-namespace.out: -------------------------------------------------------------------------------- 1 | . 2 | "Indicates membership of a class" . 3 | . 4 | . 5 | "type"@en . 6 | . 7 | . 8 | "A collection of alternatives."@en . 9 | . 10 | "Alt"@en . 11 | . 12 | . 13 | "An unordered collection."@en . 14 | . 15 | "Bag"@en . 16 | . 17 | . 18 | "The concept of a property." . 19 | . 20 | "Property"@en . 21 | . 22 | . 23 | "An ordered collection."@en . 24 | . 25 | "Seq"@en . 26 | . 27 | . 28 | "The class of RDF statements." . 29 | . 30 | "Statement"@en . 31 | . 32 | . 33 | "The object of an RDF statement." . 34 | . 35 | . 36 | "object"@en . 37 | . 38 | "the predicate of an RDF statement." . 39 | . 40 | . 41 | "predicate"@en . 42 | . 43 | . 44 | "The subject of an RDF statement." . 45 | . 46 | . 47 | "subject"@en . 48 | . 49 | . 50 | "Identifies the principal value (usually a string) of a property when the property value is a structured resource" . 51 | . 52 | . 53 | "value"@en . 54 | . 55 | . 56 | "The concept of Class" . 57 | . 58 | "Class"@en . 59 | . 60 | . 61 | "This represents the set Containers." . 62 | . 63 | "Container"@en . 64 | . 65 | . 66 | "The container membership properties, rdf:1, rdf:2, ..., all of which are sub-properties of 'member'." . 67 | . 68 | "ContainerMembershipProperty"@en . 69 | . 70 | . 71 | "This represents the set of atomic values, eg. textual strings." . 72 | . 73 | "Literal"@en . 74 | . 75 | "The class resource, everything." . 76 | . 77 | "Resource"@en . 78 | . 79 | "Use this for descriptions" . 80 | . 81 | . 82 | "comment"@en . 83 | . 84 | . 85 | "A domain class for a property type" . 86 | . 87 | . 88 | "domain"@en . 89 | . 90 | . 91 | "Indicates the namespace of a resource" . 92 | . 93 | . 94 | "isDefinedBy"@en . 95 | . 96 | . 97 | . 98 | "Provides a human-readable version of a resource name." . 99 | . 100 | . 101 | "label"@en . 102 | . 103 | . 104 | "a member of a container" . 105 | . 106 | . 107 | "member"@en . 108 | . 109 | "A range class for a property type" . 110 | . 111 | . 112 | "range"@en . 113 | . 114 | . 115 | "A resource that provides information about the subject resource" . 116 | . 117 | . 118 | "seeAlso"@en . 119 | . 120 | . 121 | "Indicates membership of a class" . 122 | . 123 | . 124 | "subClassOf"@en . 125 | . 126 | . 127 | "Indicates specialization of properties" . 128 | . 129 | . 130 | "subPropertyOf"@en . 131 | . 132 | -------------------------------------------------------------------------------- /pymantic/tests/turtle_tests/Overview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Index of /TR/2011/WD-turtle-20110809/tests 6 | 7 | 8 | 15 |

Turtle Tests

16 | 17 |

These are the tests for the Turtle Terse RDF Triple Language 18 | that must be passed by conformant systems. See 19 | http://www.w3.org/TR/2011/WD-turtle-20110809/tests/ 20 | 21 | for the full conformance information.

22 | 23 |

The format is a set of good tests and bad tests.

24 | 25 |

Good tests are a pair of files: 26 | abc.ttl abc.out 27 | which are the input Turtle file and the expected output RDF triples, 28 | written in N-Triples.

29 | 30 |

bad tests are of the form 31 | bad-XX.ttl 32 | 33 | which must fail.

34 | 35 |

The tests should be performed with an assumed base URI 36 | of http://www.w3.org/2001/sw/DataAccess/df1/tests/.

37 | 38 |

Test Coverage

39 | 40 |

The following table associates test labels with the features those tests are supposed to cover. Every test covers the basic syntax features so they are not listed.

41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 |
nameresultintended coverage
base1base1.outResolution of a relative URI against an absolute base.
base2base2.outResolution of a relative URI against a relative base.
prefix1prefix1.outSubstitution of a simple prefix.
escapedPrefix1escapedPrefix1.outstruck Substitution of a prefix containing some escaped characters.
escapedNamespace1escapedNamespace1.outSubstitution of namespace containing some escaped characters for a prefix.
defaultdefault.outSubstitution of a prefix which is the empty string.
typetype.outSubstitution of rdf:type for the keyword a.
58 | 59 |

Test Directory Listing

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 |
[ICO]NameLast modifiedSizeDescription

[DIR]Parent Directory  -  
[TXT]README.txt25-Mar-2010 03:23 552  
[TXT]bad-00.ttl25-Mar-2010 03:23 46  
[TXT]bad-01.ttl25-Mar-2010 03:23 104  
[TXT]bad-02.ttl25-Mar-2010 03:23 97  
[TXT]bad-03.ttl25-Mar-2010 03:23 83  
[TXT]bad-04.ttl25-Mar-2010 03:23 111  
[TXT]bad-05.ttl25-Mar-2010 03:23 95  
[TXT]bad-06.ttl25-Mar-2010 03:23 91  
[TXT]bad-07.ttl25-Mar-2010 03:23 92  
[TXT]bad-08.ttl25-Mar-2010 03:23 50  
[TXT]bad-09.ttl25-Mar-2010 03:23 82  
[TXT]bad-10.ttl25-Mar-2010 03:23 85  
[TXT]bad-11.ttl25-Mar-2010 03:23 84  
[TXT]bad-12.ttl25-Mar-2010 03:23 86  
[TXT]bad-13.ttl25-Mar-2010 03:23 77  
[TXT]bad-14.ttl25-Mar-2010 03:23 115  
[   ]base1.out10-Mar-2011 16:10 183  
[TXT]base1.ttl10-Mar-2011 16:10 324  
[   ]base2.out10-Mar-2011 16:10 183  
[TXT]base2.ttl10-Mar-2011 16:10 423  
[   ]default.out10-Mar-2011 16:10 183  
[TXT]default.ttl10-Mar-2011 16:10 324  
[TXT]default1.ttl25-Mar-2010 03:23 242  
[   ]escapedNamespace1.out10-Mar-2011 16:10 100  
[TXT]escapedNamespace1.ttl10-Mar-2011 16:10 315  
[   ]escapedPrefix1.out10-Mar-2011 16:10 100  
[TXT]escapedPrefix1.ttl10-Mar-2011 16:10 298  
[TXT]manifest-bad.ttl25-Mar-2010 03:23 2.4K 
[TXT]manifest.ttl25-Mar-2010 03:23 6.3K 
[   ]prefix1.out10-Mar-2011 16:10 100  
[TXT]prefix1.ttl10-Mar-2011 16:10 259  
[   ]rdf-schema.out25-Mar-2010 03:23 17K 
[TXT]rdf-schema.ttl25-Mar-2010 03:23 4.3K 
[   ]rdfq-results.out25-Mar-2010 03:23 3.3K 
[TXT]rdfq-results.ttl25-Mar-2010 03:23 1.2K 
[   ]rdfs-namespace.out25-Mar-2010 03:23 18K 
[TXT]rdfs-namespace.ttl25-Mar-2010 03:23 4.3K 
[   ]test-00.out25-Mar-2010 03:23 137  
[TXT]test-00.ttl25-Mar-2010 03:23 27  
[   ]test-01.out25-Mar-2010 03:23 267  
[TXT]test-01.ttl25-Mar-2010 03:23 187  
[   ]test-02.out25-Mar-2010 03:23 258  
[TXT]test-02.ttl25-Mar-2010 03:23 88  
[   ]test-03.out25-Mar-2010 03:23 258  
[TXT]test-03.ttl25-Mar-2010 03:23 90  
[   ]test-04.out25-Mar-2010 03:23 134  
[TXT]test-04.ttl25-Mar-2010 03:23 112  
[   ]test-05.out25-Mar-2010 03:23 268  
[TXT]test-05.ttl25-Mar-2010 03:23 130  
[   ]test-06.out25-Mar-2010 03:23 108  
[TXT]test-06.ttl25-Mar-2010 03:23 83  
[   ]test-07.out25-Mar-2010 03:23 398  
[TXT]test-07.ttl25-Mar-2010 03:23 74  
[   ]test-08.out25-Mar-2010 03:23 117  
[TXT]test-08.ttl25-Mar-2010 03:23 57  
[   ]test-09.out25-Mar-2010 03:23 388  
[TXT]test-09.ttl25-Mar-2010 03:23 276  
[   ]test-10.out25-Mar-2010 03:23 525  
[TXT]test-10.ttl25-Mar-2010 03:23 295  
[   ]test-11.out25-Mar-2010 03:23 288  
[TXT]test-11.ttl25-Mar-2010 03:23 331  
[   ]test-12.out25-Mar-2010 03:23 302  
[TXT]test-12.ttl25-Mar-2010 03:23 288  
[   ]test-13.out25-Mar-2010 03:23 122  
[TXT]test-13.ttl25-Mar-2010 03:23 82  
[   ]test-14.out25-Mar-2010 03:23 895K 
[TXT]test-14.ttl25-Mar-2010 03:23 212K 
[   ]test-15.out25-Mar-2010 03:23 819K 
[TXT]test-15.ttl25-Mar-2010 03:23 77K 
[   ]test-16.out25-Mar-2010 03:23 819K 
[TXT]test-16.ttl25-Mar-2010 03:23 136K 
[   ]test-17.out25-Mar-2010 03:23 90  
[TXT]test-17.ttl25-Mar-2010 03:23 102  
[   ]test-18.out25-Mar-2010 03:23 209  
[TXT]test-18.ttl25-Mar-2010 03:23 157  
[   ]test-19.out25-Mar-2010 03:23 100  
[TXT]test-19.ttl25-Mar-2010 03:23 50  
[   ]test-20.out25-Mar-2010 03:23 106  
[TXT]test-20.ttl25-Mar-2010 03:23 64  
[   ]test-21.out25-Mar-2010 03:23 293  
[TXT]test-21.ttl25-Mar-2010 03:23 70  
[   ]test-22.out25-Mar-2010 03:23 296  
[TXT]test-22.ttl25-Mar-2010 03:23 73  
[   ]test-23.out25-Mar-2010 03:23 84  
[TXT]test-23.ttl25-Mar-2010 03:23 99  
[   ]test-24.out25-Mar-2010 03:23 199  
[TXT]test-24.ttl25-Mar-2010 03:23 61  
[   ]test-25.out25-Mar-2010 03:23 518  
[TXT]test-25.ttl25-Mar-2010 03:23 258  
[   ]test-26.out25-Mar-2010 03:23 74  
[TXT]test-26.ttl25-Mar-2010 03:23 93  
[   ]test-27.out25-Mar-2010 03:23 92  
[TXT]test-27.ttl25-Mar-2010 03:23 115  
[TXT]test-28-out.ttl25-Mar-2010 03:23 553  
[   ]test-28.out25-Mar-2010 03:23 2.3K 
[TXT]test-28.ttl25-Mar-2010 03:23 2.4K 
[   ]test-29.out25-Mar-2010 03:23 345  
[TXT]test-29.ttl25-Mar-2010 03:23 345  
[   ]test-30.out25-Mar-2010 03:23 529  
[TXT]test-30.ttl25-Mar-2010 03:23 415  
[   ]type.out10-Mar-2011 16:10 183  
[TXT]type.ttl10-Mar-2011 16:10 246  

193 | 194 | --------------------------------------------------------------------------------