Skip to content

fix authenticate method #30

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sparql-client/tests/testparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@


def _open_datafile(name):
return open(os.path.join(os.path.dirname(__file__), name))
return open(os.path.join(os.path.dirname(__file__), name), encoding="utf-8")


XSD_FAO_MILLION = 'http://aims.fao.org/aos/geopolitical.owl#MillionUSD'
Expand Down
92 changes: 53 additions & 39 deletions sparql.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
Otherwise, the query is read from standard input.
"""

from base64 import encodestring
from base64 import b64encode
from six.moves import input, map
from six.moves.urllib.parse import urlencode
from xml.dom import pulldom
Expand All @@ -58,6 +58,7 @@
import tempfile
import eventlet
import six

if six.PY2:
from eventlet.green import urllib2 as ev_request
import compiler
Expand All @@ -73,19 +74,18 @@
USER_AGENT = "sparql-client/%s +https://www.eionet.europa.eu/software/sparql-client/" % __version__

CONTENT_TYPE = {
'turtle': "application/turtle",
'n3': "application/n3",
'rdfxml': "application/rdf+xml",
'ntriples': "application/n-triples",
'xml': "application/xml"
}

'turtle': "application/turtle",
'n3': "application/n3",
'rdfxml': "application/rdf+xml",
'ntriples': "application/n-triples",
'xml': "application/xml"
}

RESULTS_TYPES = {
'xml': "application/sparql-results+xml",
'xmlschema': "application/x-ms-access-export+xml",
'json': "application/sparql-results+json"
}
'xml': "application/sparql-results+xml",
'xmlschema': "application/x-ms-access-export+xml",
'json': "application/sparql-results+json"
}

# The purpose of this construction is to use shared strings when
# they have the same value. This way comparisons can happen on the
Expand All @@ -103,25 +103,25 @@
XSD_BOOLEAN = 'http://www.w3.org/2001/XMLSchema#boolean'

datatype_dict = {
'': '',
XSD_STRING: XSD_STRING,
XSD_INT: XSD_INT,
XSD_LONG: XSD_LONG,
XSD_DOUBLE: XSD_DOUBLE,
XSD_FLOAT: XSD_FLOAT,
XSD_INTEGER: XSD_INTEGER,
XSD_DECIMAL: XSD_DECIMAL,
XSD_DATETIME: XSD_DATETIME,
XSD_DATE: XSD_DATE,
XSD_TIME: XSD_TIME,
XSD_BOOLEAN: XSD_BOOLEAN
}
'': '',
XSD_STRING: XSD_STRING,
XSD_INT: XSD_INT,
XSD_LONG: XSD_LONG,
XSD_DOUBLE: XSD_DOUBLE,
XSD_FLOAT: XSD_FLOAT,
XSD_INTEGER: XSD_INTEGER,
XSD_DECIMAL: XSD_DECIMAL,
XSD_DATETIME: XSD_DATETIME,
XSD_DATE: XSD_DATE,
XSD_TIME: XSD_TIME,
XSD_BOOLEAN: XSD_BOOLEAN
}

# allow import from RestrictedPython
__allow_access_to_unprotected_subobjects__ = {
'Datatype': 1, 'unpack_row': 1,
'RDFTerm': 1, 'IRI': 1,
'Literal': 1, 'BlankNode': 1
'Datatype': 1, 'unpack_row': 1,
'RDFTerm': 1, 'IRI': 1,
'Literal': 1, 'BlankNode': 1
}


Expand Down Expand Up @@ -183,6 +183,7 @@ def __eq__(self, other):
def n3(self):
return '<%s>' % self.value


_n3_quote_char = re.compile(r'[^ -~]|["\\]')
_n3_quote_map = {
'"': '\\"',
Expand All @@ -198,13 +199,15 @@ def escape(m):
if ch in _n3_quote_map:
return _n3_quote_map[ch]
return "\\u%04x" % ord(ch)

return '"' + _n3_quote_char.sub(escape, string) + '"'


class Literal(RDFTerm):
"""
Literals. These can take a data type or a language code.
"""

def __init__(self, value, datatype=None, lang=None):
self.value = six.text_type(value)
self.lang = lang
Expand Down Expand Up @@ -235,6 +238,7 @@ def n3(self):

class BlankNode(RDFTerm):
""" Blank node. Similar to `IRI` but lacks a stable identifier. """

def __init__(self, value):
self.value = value

Expand All @@ -248,6 +252,7 @@ def __eq__(self, other):
def n3(self):
return '_:%s' % self.value


_n3parser_lang = re.compile(r'@(?P<lang>\w+)$')
_n3parser_datatype = re.compile(r'\^\^<(?P<datatype>[^\^"\'>]+)>$')

Expand Down Expand Up @@ -318,12 +323,14 @@ def parse_n3_term(src):
raise ValueError
assign_node = ast.body[0]

if len(assign_node._fields) != 2:
# type_comment is added since 3.8, discard it from condition check
if len(assign_node._fields) != 2 and len(tuple(f for f in assign_node._fields if f != "type_comment")) != 2:
raise ValueError

value_node = assign_node.value
if len(value_node._fields) != 1:
raise ValueError
if not isinstance(value_node, astcompiler.Constant):
raise ValueError

# if value_node.__class__ != ast.Constant():
# raise ValueError
Expand All @@ -334,6 +341,7 @@ def parse_n3_term(src):

return Literal(value, datatype, lang)


#########################################
#
# _ServiceMixin
Expand Down Expand Up @@ -385,6 +393,7 @@ def prefixes(self):
def headers(self):
return self._headers_map


#########################################
#
# Service
Expand All @@ -398,6 +407,7 @@ class Service(_ServiceMixin):
The user creates a :class:`Service`, then sends a query to it.
If we want to have persistent connections, then open them here.
"""

def __init__(self, endpoint, qs_encoding="utf-8", method="POST",
accept="application/sparql-results+xml"):
_ServiceMixin.__init__(self, endpoint, method, accept)
Expand All @@ -416,9 +426,8 @@ def query(self, query, timeout=0, raw=False):
return q.query(query, timeout, raw=raw)

def authenticate(self, username, password):
# self._headers_map['Authorization'] = "Basic %s" % replace(
# encodestring("%s:%s" % (username, password)), "\012", "")
head = "Basic %s" % encodestring("%s:%s" % (username, password)).replace("\012", "")
cred = b64encode("{}:{}".format(username, password).encode()).decode()
head = "Basic {}".format(cred)
self._headers_map['Authorization'] = head


Expand All @@ -433,13 +442,14 @@ def _parseBoolean(val):
XSD_DOUBLE: float,
XSD_FLOAT: float,
XSD_INTEGER: int, # INTEGER is a DECIMAL, but Python `int` has no size
# limit, so it's safe to use
# limit, so it's safe to use
XSD_DECIMAL: decimal.Decimal,
XSD_BOOLEAN: _parseBoolean,
}

try:
import dateutil.parser

_types[XSD_DATETIME] = dateutil.parser.parse
_types[XSD_DATE] = lambda v: dateutil.parser.parse(v).date()
_types[XSD_TIME] = lambda v: dateutil.parser.parse(v).time()
Expand Down Expand Up @@ -484,6 +494,7 @@ def unpack_row(row, convert=None, convert_type={}):
out.append(value)
return out


#########################################
#
# _Query
Expand Down Expand Up @@ -606,6 +617,7 @@ class RedirectHandler(ev_request.HTTPRedirectHandler):
"""
Subclass the HTTPRedirectHandler to re-contruct request when follow redirect
"""

def redirect_request(self, req, fp, code, msg, headers, newurl):
if code in (301, 302, 303, 307):
raise SparqlException(code, newurl)
Expand All @@ -619,11 +631,11 @@ class _ResultsParser(object):
"""

__allow_access_to_unprotected_subobjects__ = {
'fetchone': 1,
'fetchmany': 1,
'fetchall': 1,
'hasresult': 1,
'variables': 1
'fetchone': 1,
'fetchmany': 1,
'fetchall': 1,
'hasresult': 1,
'variables': 1
}

def __init__(self, fp):
Expand Down Expand Up @@ -773,10 +785,12 @@ def _interactive(endpoint):

class SparqlException(Exception):
""" Sparql Exceptions """

def __init__(self, code, message):
self.code = code
self.message = message


if __name__ == '__main__':
import sys
import codecs
Expand Down