3
dl:                 @   s~   d dl mZ d dl mZ d dl mZ d dlmZmZ dZd dlm	Z	m
Z
mZ d dlmZ d dlmZ d	gZG d
d	 d	eZdS )    )absolute_import)division)print_function)	text_typePY3a$  
The :class:`~rdflib.resource.Resource` class wraps a
:class:`~rdflib.graph.Graph`
and a resource reference (i.e. a :class:`rdflib.term.URIRef` or
:class:`rdflib.term.BNode`) to support a resource-oriented way of
working with a graph.

It contains methods directly corresponding to those methods of the Graph
interface that relate to reading and writing data. The difference is that a
Resource also binds a resource identifier, making it possible to work without
tracking both the graph and a current subject. This makes for a "resource
oriented" style, as compared to the triple orientation of the Graph API.

Resulting generators are also wrapped so that any resource reference values
(:class:`rdflib.term.URIRef`s and :class:`rdflib.term.BNode`s) are in turn
wrapped as Resources. (Note that this behaviour differs from the corresponding
methods in :class:`~rdflib.graph.Graph`, where no such conversion takes place.)


Basic Usage Scenario
--------------------

Start by importing things we need and define some namespaces::

    >>> from rdflib import *
    >>> FOAF = Namespace("http://xmlns.com/foaf/0.1/")
    >>> CV = Namespace("http://purl.org/captsolo/resume-rdf/0.2/cv#")

Load some RDF data::

    >>> graph = Graph().parse(format='n3', data='''
    ... @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
    ... @prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
    ... @prefix foaf: <http://xmlns.com/foaf/0.1/> .
    ... @prefix cv: <http://purl.org/captsolo/resume-rdf/0.2/cv#> .
    ...
    ... @base <http://example.org/> .
    ...
    ... </person/some1#self> a foaf:Person;
    ...     rdfs:comment "Just a Python & RDF hacker."@en;
    ...     foaf:depiction </images/person/some1.jpg>;
    ...     foaf:homepage <http://example.net/>;
    ...     foaf:name "Some Body" .
    ...
    ... </images/person/some1.jpg> a foaf:Image;
    ...     rdfs:label "some 1"@en;
    ...     rdfs:comment "Just an image"@en;
    ...     foaf:thumbnail </images/person/some1-thumb.jpg> .
    ...
    ... </images/person/some1-thumb.jpg> a foaf:Image .
    ...
    ... [] a cv:CV;
    ...     cv:aboutPerson </person/some1#self>;
    ...     cv:hasWorkHistory [ cv:employedIn </#company>;
    ...             cv:startDate "2009-09-04"^^xsd:date ] .
    ... ''')

Create a Resource::

    >>> person = Resource(
    ...     graph, URIRef("http://example.org/person/some1#self"))

Retrieve some basic facts::

    >>> person.identifier
    rdflib.term.URIRef(u'http://example.org/person/some1#self')

    >>> person.value(FOAF.name)
    rdflib.term.Literal(u'Some Body')

    >>> person.value(RDFS.comment)
    rdflib.term.Literal(u'Just a Python & RDF hacker.', lang=u'en')

Resources can be sliced (like graphs, but the subject is fixed)::

    >>> for name in person[FOAF.name]:
    ...     print(name)
    Some Body
    >>> person[FOAF.name : Literal("Some Body")]
    True

Resources as unicode are represented by their identifiers as unicode::

    >>> %(unicode)s(person)  #doctest: +SKIP
    u'Resource(http://example.org/person/some1#self'

Resource references are also Resources, so you can easily get e.g. a qname
for the type of a resource, like::

    >>> person.value(RDF.type).qname()
    u'foaf:Person'

Or for the predicates of a resource::

    >>> sorted(
    ...     p.qname() for p in person.predicates()
    ... )  #doctest: +NORMALIZE_WHITESPACE +SKIP
    [u'foaf:depiction', u'foaf:homepage',
     u'foaf:name', u'rdf:type', u'rdfs:comment']

Follow relations and get more data from their Resources as well::

    >>> for pic in person.objects(FOAF.depiction):
    ...     print(pic.identifier)
    ...     print(pic.value(RDF.type).qname())
    ...     print(pic.label())
    ...     print(pic.comment())
    ...     print(pic.value(FOAF.thumbnail).identifier)
    http://example.org/images/person/some1.jpg
    foaf:Image
    some 1
    Just an image
    http://example.org/images/person/some1-thumb.jpg

    >>> for cv in person.subjects(CV.aboutPerson):
    ...     work = list(cv.objects(CV.hasWorkHistory))[0]
    ...     print(work.value(CV.employedIn).identifier)
    ...     print(work.value(CV.startDate))
    http://example.org/#company
    2009-09-04

It's just as easy to work with the predicates of a resource::

    >>> for s, p in person.subject_predicates():
    ...     print(s.value(RDF.type).qname())
    ...     print(p.qname())
    ...     for s, o in p.subject_objects():
    ...         print(s.value(RDF.type).qname())
    ...         print(o.value(RDF.type).qname())
    cv:CV
    cv:aboutPerson
    cv:CV
    foaf:Person

This is useful for e.g. inspection::

    >>> thumb_ref = URIRef("http://example.org/images/person/some1-thumb.jpg")
    >>> thumb = Resource(graph, thumb_ref)
    >>> for p, o in thumb.predicate_objects():
    ...     print(p.qname())
    ...     print(o.qname())
    rdf:type
    foaf:Image

Similarly, adding, setting and removing data is easy::

    >>> thumb.add(RDFS.label, Literal("thumb"))
    >>> print(thumb.label())
    thumb
    >>> thumb.set(RDFS.label, Literal("thumbnail"))
    >>> print(thumb.label())
    thumbnail
    >>> thumb.remove(RDFS.label)
    >>> list(thumb.objects(RDFS.label))
    []


Schema Example
--------------

With this artificial schema data::

    >>> graph = Graph().parse(format='n3', data='''
    ... @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
    ... @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
    ... @prefix owl: <http://www.w3.org/2002/07/owl#> .
    ... @prefix v: <http://example.org/def/v#> .
    ...
    ... v:Artifact a owl:Class .
    ...
    ... v:Document a owl:Class;
    ...     rdfs:subClassOf v:Artifact .
    ...
    ... v:Paper a owl:Class;
    ...     rdfs:subClassOf v:Document .
    ...
    ... v:Choice owl:oneOf (v:One v:Other) .
    ...
    ... v:Stuff a rdf:Seq; rdf:_1 v:One; rdf:_2 v:Other .
    ...
    ... ''')

From this class::

    >>> artifact = Resource(graph, URIRef("http://example.org/def/v#Artifact"))

we can get at subclasses::

    >>> subclasses = list(artifact.transitive_subjects(RDFS.subClassOf))
    >>> [c.qname() for c in subclasses]
    [u'v:Artifact', u'v:Document', u'v:Paper']

and superclasses from the last subclass::

    >>> [c.qname() for c in subclasses[-1].transitive_objects(RDFS.subClassOf)]
    [u'v:Paper', u'v:Document', u'v:Artifact']

Get items from the Choice::

    >>> choice = Resource(graph, URIRef("http://example.org/def/v#Choice"))
    >>> [it.qname() for it in choice.value(OWL.oneOf).items()]
    [u'v:One', u'v:Other']

And the sequence of Stuff::

    >>> stuff = Resource(graph, URIRef("http://example.org/def/v#Stuff"))
    >>> [it.qname() for it in stuff.seq()]
    [u'v:One', u'v:Other']

On add, other resources are auto-unboxed:
    >>> paper = Resource(graph, URIRef("http://example.org/def/v#Paper"))
    >>> paper.add(RDFS.subClassOf, artifact)
    >>> artifact in paper.objects(RDFS.subClassOf) # checks Resource instance
    True
    >>> (paper._identifier, RDFS.subClassOf, artifact._identifier) in graph
    True


Technical Details
-----------------

Comparison is based on graph and identifier::

    >>> g1 = Graph()
    >>> t1 = Resource(g1, URIRef("http://example.org/thing"))
    >>> t2 = Resource(g1, URIRef("http://example.org/thing"))
    >>> t3 = Resource(g1, URIRef("http://example.org/other"))
    >>> t4 = Resource(Graph(), URIRef("http://example.org/other"))

    >>> t1 is t2
    False

    >>> t1 == t2
    True
    >>> t1 != t2
    False

    >>> t1 == t3
    False
    >>> t1 != t3
    True

    >>> t3 != t4
    True

    >>> t3 < t1 and t1 > t3
    True
    >>> t1 >= t1 and t1 >= t3
    True
    >>> t1 <= t1 and t3 <= t1
    True

    >>> t1 < t1 or t1 < t3 or t3 > t1 or t3 > t3
    False

Hash is computed from graph and identifier::

    >>> g1 = Graph()
    >>> t1 = Resource(g1, URIRef("http://example.org/thing"))

    >>> hash(t1) == hash(Resource(g1, URIRef("http://example.org/thing")))
    True

    >>> hash(t1) == hash(Resource(Graph(), t1.identifier))
    False
    >>> hash(t1) == hash(Resource(Graph(), URIRef("http://example.org/thing")))
    False

The Resource class is suitable as a base class for mapper toolkits. For
example, consider this utility for accessing RDF properties via qname-like
attributes::

    >>> class Item(Resource):
    ...
    ...     def __getattr__(self, p):
    ...         return list(self.objects(self._to_ref(*p.split('_', 1))))
    ...
    ...     def _to_ref(self, pfx, name):
    ...         return URIRef(self._graph.store.namespace(pfx) + name)

It works as follows::

    >>> graph = Graph().parse(format='n3', data='''
    ... @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
    ... @prefix foaf: <http://xmlns.com/foaf/0.1/> .
    ...
    ... @base <http://example.org/> .
    ... </person/some1#self>
    ...     foaf:name "Some Body";
    ...     foaf:depiction </images/person/some1.jpg> .
    ... </images/person/some1.jpg> rdfs:comment "Just an image"@en .
    ... ''')

    >>> person = Item(graph, URIRef("http://example.org/person/some1#self"))

    >>> print(person.foaf_name[0])
    Some Body

The mechanism for wrapping references as resources cooperates with subclasses.
Therefore, accessing referenced resources automatically creates new ``Item``
objects::

    >>> isinstance(person.foaf_depiction[0], Item)
    True

    >>> print(person.foaf_depiction[0].rdfs_comment[0])
    Just an image

)NodeBNodeURIRef)RDF)PathResourcec               @   sd  e Zd Zdd Zedd Zedd Zdd Zdd	 Zd
d Z	dd Z
dd Zdd Zdd Zdd ZerpeZdd ZdNddZdd ZdOddZdPdd ZdQd!d"Zd#d$ Zd%d& Zd'd( Zejddd)fd*d+Zd,d- Zd.d/ Zd0d1 ZdRd2d3ZdSd4d5Z d6d7 Z!d8d9 Z"d:d; Z#d<d= Z$d>d? Z%d@dA Z&dBdC Z'dDdE Z(dFdG Z)dHdI Z*dJdK ZdLdM Z+dS )Tr   c             C   s   || _ || _d S )N)_graph_identifier)selfgraphsubject r   1/tmp/pip-build-7vycvbft/rdflib/rdflib/resource.py__init__H  s    zResource.__init__c             C   s   | j S )N)r   )r   r   r   r   <lambda>L  s    zResource.<lambda>c             C   s   | j S )N)r   )r   r   r   r   r   N  s    c             C   s   t tt | jA t | jA S )N)hashr   r   r   )r   r   r   r   __hash__P  s    zResource.__hash__c             C   s"   t |to | j|jko | j|jkS )N)
isinstancer   r   r   )r   otherr   r   r   __eq__S  s    
zResource.__eq__c             C   s
   | |k S )Nr   )r   r   r   r   r   __ne__X  s    zResource.__ne__c             C   s   t |tr| j|jk S dS d S )NF)r   r   r   )r   r   r   r   r   __lt__Z  s    
zResource.__lt__c             C   s   | |k p| |k S )Nr   )r   r   r   r   r   __gt__`  s    zResource.__gt__c             C   s   | |k p| |kS )Nr   )r   r   r   r   r   __le__b  s    zResource.__le__c             C   s
   | |k  S )Nr   )r   r   r   r   r   __ge__d  s    zResource.__ge__c             C   s
   t | jS )N)r   r   )r   r   r   r   __unicode__f  s    zResource.__unicode__c             C   s(   t |tr|j}| jj| j||f d S )N)r   r   r   r   add)r   por   r   r   r!   l  s    
zResource.addNc             C   s(   t |tr|j}| jj| j||f d S )N)r   r   r   r   remove)r   r"   r#   r   r   r   r$   r  s    
zResource.removec             C   s(   t |tr|j}| jj| j||f d S )N)r   r   r   r   set)r   r"   r#   r   r   r   r%   x  s    
zResource.setc             C   s   | j | jj|| jS )N)
_resourcesr   subjectsr   )r   	predicater   r   r   r'   ~  s    zResource.subjectsc             C   s&   t |tr|j}| j| jj| j|S )N)r   r   r   r&   r   
predicates)r   r#   r   r   r   r)     s    
zResource.predicatesc             C   s   | j | jj| j|S )N)r&   r   objectsr   )r   r(   r   r   r   r*     s    zResource.objectsc             C   s   | j | jj| jS )N)_resource_pairsr   subject_predicatesr   )r   r   r   r   r,     s    zResource.subject_predicatesc             C   s   | j | jj| jS )N)r+   r   subject_objectsr   )r   r   r   r   r-     s    zResource.subject_objectsc             C   s   | j | jj| jS )N)r+   r   predicate_objectsr   )r   r   r   r   r.     s    zResource.predicate_objectsTc             C   s,   t |tr|j}| j| jj| j||||S )N)r   r   r   _castr   value)r   r"   r#   defaultanyr   r   r   r0     s    
zResource.valuec             C   s   | j j| jS )N)r   labelr   )r   r   r   r   r3     s    zResource.labelc             C   s   | j j| jS )N)r   commentr   )r   r   r   r   r4     s    zResource.commentc             C   s   | j | jj| jS )N)r&   r   itemsr   )r   r   r   r   r5     s    zResource.itemsc             C   s   | j | jj| j||S )N)r&   r   transitive_objectsr   )r   r(   rememberr   r   r   r6     s    
zResource.transitive_objectsc             C   s   | j | jj|| j|S )N)r&   r   transitive_subjectsr   )r   r(   r7   r   r   r   r8     s    
zResource.transitive_subjectsc             C   s   | j | jj| jS )N)r&   r   seqr   )r   r   r   r   r9     s    zResource.seqc             C   s   | j j| jS )N)r   qnamer   )r   r   r   r   r:     s    zResource.qnamec             c   s,   x&|D ]\}}| j || j |fV  qW d S )N)r/   )r   pairss1s2r   r   r   r+     s    zResource._resource_pairsc             c   s6   x0|D ](\}}}| j || j || j |fV  qW d S )N)r/   )r   triplessr"   r#   r   r   r   _resource_triples  s    zResource._resource_triplesc             c   s   x|D ]}| j |V  qW d S )N)r/   )r   Znodesnoder   r   r   r&     s    
zResource._resourcesc             C   s    t |ttfr| j|S |S d S )N)r   r   r	   _new)r   rA   r   r   r   r/     s    
zResource._castc             C   s   | j | jj| jd d fS )N)r@   r   r>   
identifier)r   r   r   r   __iter__  s    zResource.__iter__c             C   s   t |tr|jrtd|j|j }}t |tr6|j}t |trF|j}|d kr^|d kr^| j S |d krp| j	|S |d kr| j
|S | j||f| jkS n,t |ttfr| j
|S td|t|f d S )NzSResources fix the subject for slicing, and can only be sliced by predicate/object. z[You can only index a resource by a single rdflib term, a slice of rdflib terms, not %s (%s))r   slicestep	TypeErrorstartstopr   r   r.   r)   r*   rC   r   r   r   type)r   itemr"   r#   r   r   r   __getitem__  s$    





zResource.__getitem__c             C   s   | j || d S )N)r%   )r   rK   r0   r   r   r   __setitem__  s    zResource.__setitem__c             C   s   t | | j|S )N)rJ   r   )r   r   r   r   r   rB     s    zResource._newc             C   s
   d| j  S )NzResource(%s))r   )r   r   r   r   __str__  s    zResource.__str__c             C   s   d| j | jf S )NzResource(%s,%s))r   r   )r   r   r   r   __repr__  s    zResource.__repr__)N)N)N)N)N)N),__name__
__module____qualname__r   propertyr   rC   r   r   r   r   r   r   r   r    r   rN   r!   r$   r%   r'   r)   r*   r,   r-   r.   r
   r0   r3   r4   r5   r6   r8   r9   r:   r+   r@   r&   r/   rD   rL   rM   rB   rO   r   r   r   r   r   F  sP   





N)
__future__r   r   r   sixr   r   __doc__Zrdflib.termr   r   r	   Zrdflib.namespacer
   Zrdflib.pathsr   __all__objectr   r   r   r   r   <module>   s     9