You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by lm...@apache.org on 2018/07/29 16:55:46 UTC
svn commit: r1836994 [1/2] - in /chemistry/cmislib/branches/py3_compat: ./
src/cmislib/ src/cmislib/atompub/ src/cmislib/browser/ src/tests/
Author: lmignon
Date: Sun Jul 29 16:55:46 2018
New Revision: 1836994
URL: http://svn.apache.org/viewvc?rev=1836994&view=rev
Log:
py3compat: replace httplib2 by requests and fix StringIO->BytesIO
Removed:
chemistry/cmislib/branches/py3_compat/src/cmislib/net.py
Modified:
chemistry/cmislib/branches/py3_compat/.travis.yml
chemistry/cmislib/branches/py3_compat/setup.py
chemistry/cmislib/branches/py3_compat/src/cmislib/atompub/binding.py
chemistry/cmislib/branches/py3_compat/src/cmislib/browser/binding.py
chemistry/cmislib/branches/py3_compat/src/cmislib/cmis_services.py
chemistry/cmislib/branches/py3_compat/src/cmislib/domain.py
chemistry/cmislib/branches/py3_compat/src/cmislib/exceptions.py
chemistry/cmislib/branches/py3_compat/src/cmislib/model.py
chemistry/cmislib/branches/py3_compat/src/cmislib/util.py
chemistry/cmislib/branches/py3_compat/src/tests/test_document.py
chemistry/cmislib/branches/py3_compat/src/tests/test_query.py
chemistry/cmislib/branches/py3_compat/src/tests/test_repository.py
chemistry/cmislib/branches/py3_compat/tox.ini
Modified: chemistry/cmislib/branches/py3_compat/.travis.yml
URL: http://svn.apache.org/viewvc/chemistry/cmislib/branches/py3_compat/.travis.yml?rev=1836994&r1=1836993&r2=1836994&view=diff
==============================================================================
--- chemistry/cmislib/branches/py3_compat/.travis.yml (original)
+++ chemistry/cmislib/branches/py3_compat/.travis.yml Sun Jul 29 16:55:46 2018
@@ -7,6 +7,9 @@ language: python
python:
- "2.7"
+ - "3.4"
+ - "3.5"
+ - "3.6"
services:
- docker
Modified: chemistry/cmislib/branches/py3_compat/setup.py
URL: http://svn.apache.org/viewvc/chemistry/cmislib/branches/py3_compat/setup.py?rev=1836994&r1=1836993&r2=1836994&view=diff
==============================================================================
--- chemistry/cmislib/branches/py3_compat/setup.py (original)
+++ chemistry/cmislib/branches/py3_compat/setup.py Sun Jul 29 16:55:46 2018
@@ -19,7 +19,7 @@
import os
from setuptools import setup, find_packages
-version = '0.6.0'
+version = '0.7.0.dev1'
def read(fname):
return open(os.path.join(os.path.dirname(__file__), fname)).read()
@@ -30,7 +30,8 @@ setup(
version = version,
install_requires = [
'iso8601',
- 'httplib2'
+ 'requests',
+ 'requests-toolbelt',
],
author = 'Apache Chemistry Project',
author_email = 'dev@chemistry.apache.org',
@@ -39,14 +40,17 @@ setup(
package_dir = {'':'src'},
packages = find_packages('src', exclude=['tests']),
#include_package_data = True,
- exclude_package_data = {'':['tests']},
+ exclude_package_data = {'': ['tests']},
long_description = read('README.txt'),
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: Apache Software License",
"Operating System :: OS Independent",
- "Programming Language :: Python",
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
"Topic :: Software Development :: Libraries",
],
)
Modified: chemistry/cmislib/branches/py3_compat/src/cmislib/atompub/binding.py
URL: http://svn.apache.org/viewvc/chemistry/cmislib/branches/py3_compat/src/cmislib/atompub/binding.py?rev=1836994&r1=1836993&r2=1836994&view=diff
==============================================================================
--- chemistry/cmislib/branches/py3_compat/src/cmislib/atompub/binding.py (original)
+++ chemistry/cmislib/branches/py3_compat/src/cmislib/atompub/binding.py Sun Jul 29 16:55:46 2018
@@ -21,11 +21,13 @@
Module containing the Atom Pub binding-specific objects used to work with a CMIS
provider.
"""
-import sys
+import base64
import datetime
import logging
import mimetypes
import re
+import sys
+from io import BytesIO
from xml.dom import minidom
from xml.parsers.expat import ExpatError
@@ -36,16 +38,14 @@ from cmislib.domain import CmisId, CmisO
from cmislib.exceptions import CmisException, \
ObjectNotFoundException, InvalidArgumentException, \
NotSupportedException
-from cmislib.net import RESTService as Rest
from cmislib.util import multiple_replace, parsePropValue, parseBoolValue, \
- toCMISValue, parseDateTimeValue, safe_quote
+ toCMISValue, parseDateTimeValue, safe_quote, to_native
if sys.version_info >= (3,):
from urllib.parse import urlparse, urlunparse
- import io as StringIO
+ unicode = str
else:
from urlparse import urlparse, urlunparse
- import StringIO
moduleLogger = logging.getLogger('cmislib.atompub.binding')
@@ -109,11 +109,21 @@ class AtomPubBinding(Binding):
def __init__(self, **kwargs):
self.extArgs = kwargs
+ self.user_agent = 'cmislib/atompub +http://chemistry.apache.org/'
def getRepositoryService(self):
return RepositoryService()
- def get(self, url, username, password, **kwargs):
+ def _get_http_headers(self, **kwargs):
+ headers = {}
+ if kwargs:
+ if 'headers' in kwargs:
+ headers = kwargs['headers']
+ del kwargs['headers']
+ headers['User-Agent'] = self.user_agent
+ return headers
+
+ def get(self, url, session, **kwargs):
"""
Does a get against the CMIS service. More than likely, you will not
@@ -130,20 +140,16 @@ class AtomPubBinding(Binding):
if len(self.extArgs) > 0:
kwargs.update(self.extArgs)
- resp, content = Rest().get(url,
- username=username,
- password=password,
- **kwargs)
- if resp['status'] != '200':
- self._processCommonErrors(resp, url)
- return content
- else:
+ headers = self._get_http_headers(**kwargs)
+ response = session.get(url, params=kwargs, headers=headers)
+ if '+xml' in response.headers.get('content-type'):
try:
- return minidom.parseString(content)
+ return minidom.parse(BytesIO(response.content))
except ExpatError:
raise CmisException('Could not parse server response', url)
+ return response
- def delete(self, url, username, password, **kwargs):
+ def delete(self, url, session, **kwargs):
"""
Does a delete against the CMIS service. More than likely, you will not
@@ -157,17 +163,11 @@ class AtomPubBinding(Binding):
if len(self.extArgs) > 0:
kwargs.update(self.extArgs)
- resp, content = Rest().delete(url,
- username=username,
- password=password,
- **kwargs)
- if resp['status'] != '200' and resp['status'] != '204':
- self._processCommonErrors(resp, url)
- return content
- else:
- pass
+ headers = self._get_http_headers(**kwargs)
+ response = session.delete(url, params=kwargs, headers=headers)
+ return response
- def post(self, url, username, password, payload, contentType, **kwargs):
+ def post(self, url, session, payload, contentType, **kwargs):
"""
Does a post against the CMIS service. More than likely, you will not
@@ -181,28 +181,18 @@ class AtomPubBinding(Binding):
# merge the cmis client extended args with the ones that got passed in
if len(self.extArgs) > 0:
kwargs.update(self.extArgs)
-
- resp, content = Rest().post(url,
- payload,
- contentType,
- username=username,
- password=password,
- **kwargs)
- if resp['status'] == '200':
- try:
- return minidom.parseString(content)
- except ExpatError:
- raise CmisException('Could not parse server response', url)
- elif resp['status'] == '201':
+ headers = self._get_http_headers(**kwargs)
+ headers['Content-Type'] = contentType
+ result = session.post(
+ url, params=kwargs, data=payload, headers=headers)
+ if result.text:
try:
- return minidom.parseString(content)
+ return minidom.parse(BytesIO(result.content))
except ExpatError:
raise CmisException('Could not parse server response', url)
- else:
- self._processCommonErrors(resp, url)
- return resp
+ return None
- def put(self, url, username, password, payload, contentType, **kwargs):
+ def put(self, url, session, payload, contentType, **kwargs):
"""
Does a put against the CMIS service. More than likely, you will not
@@ -217,21 +207,16 @@ class AtomPubBinding(Binding):
if len(self.extArgs) > 0:
kwargs.update(self.extArgs)
- resp, content = Rest().put(url,
- payload,
- contentType,
- username=username,
- password=password,
- **kwargs)
- if resp['status'] != '200' and resp['status'] != '201':
- self._processCommonErrors(resp, url)
- return content
- else:
+ headers = self._get_http_headers(**kwargs)
+ headers['Content-Type'] = contentType
+ response = session.put(url, data=payload, params=kwargs, headers=headers)
+ if response.text:
try:
- return minidom.parseString(content)
+ return minidom.parseString(response.text)
except ExpatError:
# This may happen and is normal
return None
+ return None
class RepositoryService(RepositoryServiceIfc):
@@ -249,9 +234,8 @@ class RepositoryService(RepositoryServic
""" Reloads the state of the repository object."""
self.logger.debug('Reload called on object')
- obj.xmlDoc = obj._cmisClient.binding.get(obj._cmisClient.repositoryUrl.encode('utf-8'),
- obj._cmisClient.username,
- obj._cmisClient.password)
+ obj.xmlDoc = obj._cmisClient.binding.get(obj._cmisClient.repositoryUrl,
+ obj._cmisClient.session)
obj._initData()
def getRepository(self, client, repositoryId):
@@ -260,7 +244,7 @@ class RepositoryService(RepositoryServic
Get the repository for the specified repositoryId.
"""
- doc = client.binding.get(client.repositoryUrl, client.username, client.password, **client.extArgs)
+ doc = client.binding.get(client.repositoryUrl, client.session, **client.extArgs)
workspaceElements = doc.getElementsByTagNameNS(APP_NS, 'workspace')
for workspaceElement in workspaceElements:
@@ -276,7 +260,7 @@ class RepositoryService(RepositoryServic
Get all of the repositories provided by the server.
"""
- result = client.binding.get(client.repositoryUrl, client.username, client.password, **client.extArgs)
+ result = client.binding.get(client.repositoryUrl, client.session, **client.extArgs)
workspaceElements = result.getElementsByTagNameNS(APP_NS, 'workspace')
# instantiate a Repository object using every workspace element
@@ -296,7 +280,7 @@ class RepositoryService(RepositoryServic
Returns the default repository for the server via the AtomPub binding.
"""
- doc = client.binding.get(client.repositoryUrl, client.username, client.password, **client.extArgs)
+ doc = client.binding.get(client.repositoryUrl, client.session, **client.extArgs)
workspaceElements = doc.getElementsByTagNameNS(APP_NS, 'workspace')
# instantiate a Repository object with the first workspace
# element we find
@@ -396,9 +380,8 @@ class AtomPubCmisObject(CmisObject):
# fill in the template
byObjectIdUrl = multiple_replace(params, template)
- self.xmlDoc = self._cmisClient.binding.get(byObjectIdUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ self.xmlDoc = self._cmisClient.binding.get(byObjectIdUrl,
+ self._cmisClient.session,
**addOptions)
self._initData()
@@ -456,9 +439,8 @@ class AtomPubCmisObject(CmisObject):
raise NotSupportedException('Root folder does not support getObjectParents')
# invoke the URL
- result = self._cmisClient.binding.get(parentUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.get(parentUrl,
+ self._cmisClient.session,
**kwargs)
# return the result set
@@ -668,9 +650,8 @@ class AtomPubCmisObject(CmisObject):
self.logger.debug('xmlEntryDoc:' + xmlEntryDoc.toxml())
# do a PUT of the entry
- updatedXmlDoc = self._cmisClient.binding.put(selfUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ updatedXmlDoc = self._cmisClient.binding.put(selfUrl,
+ self._cmisClient.session,
xmlEntryDoc.toxml(encoding='utf-8'),
ATOM_XML_TYPE,
**args)
@@ -699,9 +680,8 @@ class AtomPubCmisObject(CmisObject):
args = {"sourceFolderId": sourceFolder.id}
# post the Atom entry
- self._cmisClient.binding.post(postUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ self._cmisClient.binding.post(postUrl,
+ self._cmisClient.session,
self.xmlDoc.toxml(encoding='utf-8'),
ATOM_XML_ENTRY_TYPE,
**args)
@@ -721,9 +701,8 @@ class AtomPubCmisObject(CmisObject):
"""
url = self._getSelfLink()
- self._cmisClient.binding.delete(url.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ self._cmisClient.binding.delete(url,
+ self._cmisClient.session,
**kwargs)
def applyPolicy(self, policyId):
@@ -763,9 +742,8 @@ class AtomPubCmisObject(CmisObject):
url = self._getLink(RELATIONSHIPS_REL)
assert url is not None, 'Could not determine relationships URL'
- result = self._cmisClient.binding.post(url.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.post(url,
+ self._cmisClient.session,
xmlDoc.toxml(encoding='utf-8'),
ATOM_XML_TYPE)
@@ -800,9 +778,8 @@ class AtomPubCmisObject(CmisObject):
url = self._getLink(RELATIONSHIPS_REL)
assert url is not None, 'Could not determine relationships URL'
- result = self._cmisClient.binding.get(url.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.get(url,
+ self._cmisClient.session,
**kwargs)
# return the result set
@@ -848,9 +825,8 @@ class AtomPubCmisObject(CmisObject):
# if the ACL capability is discover or manage, this must be
# supported
aclUrl = self._getLink(ACL_REL)
- result = self._cmisClient.binding.get(aclUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password)
+ result = self._cmisClient.binding.get(aclUrl,
+ self._cmisClient.session)
return AtomPubACL(xmlDoc=result)
else:
raise NotSupportedException
@@ -877,9 +853,8 @@ class AtomPubCmisObject(CmisObject):
raise CmisException('The ACL to apply must be an instance of the ACL class.')
aclUrl = self._getLink(ACL_REL)
assert aclUrl, "Could not determine the object's ACL URL."
- result = self._cmisClient.binding.put(aclUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.put(aclUrl,
+ self._cmisClient.session,
acl.getXmlDoc().toxml(encoding='utf-8'),
CMIS_ACL_TYPE)
return AtomPubACL(xmlDoc=result)
@@ -980,9 +955,8 @@ class AtomPubRepository(object):
repository.
"""
self.logger.debug('Reload called on object')
- self.xmlDoc = self._cmisClient.binding.get(self._cmisClient.repositoryUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password)
+ self.xmlDoc = self._cmisClient.binding.get(self._cmisClient.repositoryUrl,
+ self._cmisClient.session)
self._initData()
def _initData(self):
@@ -1322,9 +1296,8 @@ class AtomPubRepository(object):
if typeId:
targetType = self.getTypeDefinition(typeId)
childrenUrl = targetType.getLink(DOWN_REL, ATOM_XML_FEED_TYPE_P)
- typesXmlDoc = self._cmisClient.binding.get(childrenUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password)
+ typesXmlDoc = self._cmisClient.binding.get(childrenUrl,
+ self._cmisClient.session)
entryElements = typesXmlDoc.getElementsByTagNameNS(ATOM_NS, 'entry')
types = []
for entryElement in entryElements:
@@ -1393,9 +1366,8 @@ class AtomPubRepository(object):
if not descendUrl:
raise NotSupportedException("Could not determine the type descendants URL")
- typesXmlDoc = self._cmisClient.binding.get(descendUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ typesXmlDoc = self._cmisClient.binding.get(descendUrl,
+ self._cmisClient.session,
**kwargs)
entryElements = typesXmlDoc.getElementsByTagNameNS(ATOM_NS, 'entry')
types = []
@@ -1424,8 +1396,7 @@ class AtomPubRepository(object):
typesUrl = self.getCollectionLink(TYPES_COLL)
typesXmlDoc = self._cmisClient.binding.get(typesUrl,
- self._cmisClient.username,
- self._cmisClient.password,
+ self._cmisClient.session,
**kwargs)
entryElements = typesXmlDoc.getElementsByTagNameNS(ATOM_NS, 'entry')
types = []
@@ -1587,9 +1558,8 @@ class AtomPubRepository(object):
byObjectPathUrl = multiple_replace(params, template)
# do a GET against the URL
- result = self._cmisClient.binding.get(byObjectPathUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.get(byObjectPathUrl,
+ self._cmisClient.session,
**addOptions)
# instantiate CmisObject objects with the results and return the list
@@ -1651,9 +1621,8 @@ class AtomPubRepository(object):
# do the POST
# print 'posting:%s' % xmlDoc.toxml(encoding='utf-8')
- result = self._cmisClient.binding.post(queryUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.post(queryUrl,
+ self._cmisClient.session,
xmlDoc.toxml(encoding='utf-8'),
CMIS_QUERY_TYPE)
@@ -1710,9 +1679,8 @@ class AtomPubRepository(object):
raise NotSupportedException(messages.NO_CHANGE_LOG_SUPPORT)
changesUrl = self.getLink(CHANGE_LOG_REL)
- result = self._cmisClient.binding.get(changesUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.get(changesUrl,
+ self._cmisClient.session,
**kwargs)
# return the result set
@@ -1748,8 +1716,7 @@ class AtomPubRepository(object):
else:
# this repo requires fileable objects to be filed
raise InvalidArgumentException
-
- return parentFolder.createDocument(name, properties, StringIO.StringIO(contentString),
+ return parentFolder.createDocument(name, properties, BytesIO(contentString.encode('utf-8')),
contentType, contentEncoding)
def createDocument(self,
@@ -1814,9 +1781,8 @@ class AtomPubRepository(object):
contentType, contentEncoding)
# post the Atom entry
- result = self._cmisClient.binding.post(postUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.post(postUrl,
+ self._cmisClient.session,
xmlDoc.toxml(encoding='utf-8'),
ATOM_XML_ENTRY_TYPE)
@@ -1959,9 +1925,8 @@ class AtomPubRepository(object):
elif collectionType == TYPES_COLL:
return self.getTypeDefinitions()
- result = self._cmisClient.binding.get(self.getCollectionLink(collectionType).encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.get(self.getCollectionLink(collectionType),
+ self._cmisClient.session,
**kwargs)
# return the result set
@@ -2078,9 +2043,8 @@ class AtomPubResultSet(ResultSet):
"""
link = self._getLink(rel)
if link:
- result = self._cmisClient.binding.get(link.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password)
+ result = self._cmisClient.binding.get(link,
+ self._cmisClient.session)
# return the result
self._xmlDoc = result
@@ -2302,9 +2266,8 @@ class AtomPubDocument(AtomPubCmisObject)
entryXmlDoc = getEntryXmlDoc(self._repository, properties=properties)
# post it to to the checkedout collection URL
- result = self._cmisClient.binding.post(checkoutUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.post(checkoutUrl,
+ self._cmisClient.session,
entryXmlDoc.toxml(encoding='utf-8'),
ATOM_XML_ENTRY_TYPE)
@@ -2434,9 +2397,8 @@ class AtomPubDocument(AtomPubCmisObject)
# Get the self link
# Do a PUT of the empty ATOM to the self link
url = self._getSelfLink()
- result = self._cmisClient.binding.put(url.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.put(url,
+ self._cmisClient.session,
entryXmlDoc.toxml(encoding='utf-8'),
ATOM_XML_TYPE,
**kwargs)
@@ -2503,9 +2465,8 @@ class AtomPubDocument(AtomPubCmisObject)
versionsUrl = self._getLink(VERSION_HISTORY_REL)
# invoke the URL
- result = self._cmisClient.binding.get(versionsUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.get(versionsUrl,
+ self._cmisClient.session,
**kwargs)
# return the result set
@@ -2546,13 +2507,9 @@ class AtomPubDocument(AtomPubCmisObject)
srcUrl = contentElements[0].attributes['src'].value
# the cmis client class parses non-error responses
- result, content = Rest().get(srcUrl.encode('utf-8'),
- username=self._cmisClient.username,
- password=self._cmisClient.password,
- **self._cmisClient.extArgs)
- if result['status'] != '200':
- raise CmisException(result['status'])
- return StringIO.StringIO(content)
+ response = self._cmisClient.binding.get(
+ srcUrl, self._cmisClient.session)
+ return BytesIO(response.content)
else:
# otherwise, try to return the value of the content element
if contentElements[0].childNodes:
@@ -2595,9 +2552,8 @@ class AtomPubDocument(AtomPubCmisObject)
args = {"changeToken": self.properties['cmis:changeToken']}
# put the content file
- result = self._cmisClient.binding.put(srcUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.put(srcUrl,
+ self._cmisClient.session,
contentFile.read(),
mimetype,
**args)
@@ -2634,9 +2590,8 @@ class AtomPubDocument(AtomPubCmisObject)
args = {"changeToken": self.properties['cmis:changeToken']}
# delete the content stream
- self._cmisClient.binding.delete(srcUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ self._cmisClient.binding.delete(srcUrl,
+ self._cmisClient.session,
**args)
checkedOut = property(isCheckedOut)
@@ -2654,9 +2609,8 @@ class AtomPubDocument(AtomPubCmisObject)
raise NotSupportedException('Root folder does not support getObjectParents')
# invoke the URL
- result = self._cmisClient.binding.get(parentUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.get(parentUrl,
+ self._cmisClient.session,
filter='cmis:path',
includeRelativePathSegment=True)
@@ -2721,9 +2675,8 @@ class AtomPubFolder(AtomPubCmisObject):
entryXml = getEntryXmlDoc(self._repository, properties=properties)
# post the Atom entry
- result = self._cmisClient.binding.post(postUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.post(postUrl,
+ self._cmisClient.session,
entryXml.toxml(encoding='utf-8'),
ATOM_XML_ENTRY_TYPE)
@@ -2826,9 +2779,8 @@ class AtomPubFolder(AtomPubCmisObject):
# get the appropriate 'down' link
childrenUrl = self.getChildrenLink()
# invoke the URL
- result = self._cmisClient.binding.get(childrenUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.get(childrenUrl,
+ self._cmisClient.session,
**kwargs)
# return the result set
@@ -2911,9 +2863,8 @@ class AtomPubFolder(AtomPubCmisObject):
descendantsUrl = self.getDescendantsLink()
# invoke the URL
- result = self._cmisClient.binding.get(descendantsUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.get(descendantsUrl,
+ self._cmisClient.session,
**kwargs)
# return the result set
@@ -2948,9 +2899,8 @@ class AtomPubFolder(AtomPubCmisObject):
# Get the descendants link and do a GET against it
url = self._getLink(FOLDER_TREE_REL)
assert url is not None, 'Unable to determine folder tree link'
- result = self._cmisClient.binding.get(url.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.get(url,
+ self._cmisClient.session,
**kwargs)
# return the result set
@@ -2966,9 +2916,8 @@ class AtomPubFolder(AtomPubCmisObject):
# get the appropriate 'up' link
parentUrl = self._getLink(UP_REL)
# invoke the URL
- result = self._cmisClient.binding.get(parentUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password)
+ result = self._cmisClient.binding.get(parentUrl,
+ self._cmisClient.session)
# return the result set
return AtomPubFolder(self._cmisClient, self._repository, xmlDoc=result)
@@ -2996,9 +2945,8 @@ class AtomPubFolder(AtomPubCmisObject):
# Get the descendants link and do a DELETE against it
url = self._getLink(DOWN_REL, CMIS_TREE_TYPE_P)
- result = self._cmisClient.binding.delete(url.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.delete(url,
+ self._cmisClient.session,
**kwargs)
def addObject(self, cmisObject, **kwargs):
@@ -3030,9 +2978,8 @@ class AtomPubFolder(AtomPubCmisObject):
postUrl = self.getChildrenLink()
# post the Atom entry
- self._cmisClient.binding.post(postUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ self._cmisClient.binding.post(postUrl,
+ self._cmisClient.session,
cmisObject.xmlDoc.toxml(encoding='utf-8'),
ATOM_XML_ENTRY_TYPE,
**kwargs)
@@ -3052,9 +2999,8 @@ class AtomPubFolder(AtomPubCmisObject):
args = {"removeFrom": self.getObjectId()}
# post the Atom entry to the unfiled collection
- self._cmisClient.binding.post(postUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ self._cmisClient.binding.post(postUrl,
+ self._cmisClient.session,
cmisObject.xmlDoc.toxml(encoding='utf-8'),
ATOM_XML_ENTRY_TYPE,
**args)
@@ -3320,9 +3266,8 @@ class AtomPubObjectType(ObjectType):
template = templates['typebyid']['template']
params = {'{id}': self._typeId}
byTypeIdUrl = multiple_replace(params, template)
- result = self._cmisClient.binding.get(byTypeIdUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.get(byTypeIdUrl,
+ self._cmisClient.session,
**kwargs)
# instantiate CmisObject objects with the results and return the list
@@ -3752,9 +3697,8 @@ class AtomPubChangeEntry(ChangeEntry):
if len(aclEls) == 1:
return AtomPubACL(aceList=aclEls[0])
elif aclUrl:
- result = self._cmisClient.binding.get(aclUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password)
+ result = self._cmisClient.binding.get(aclUrl,
+ self._cmisClient.session)
return AtomPubACL(xmlDoc=result)
def getChangeTime(self):
@@ -4015,13 +3959,12 @@ def getEntryXmlDoc(repo=None, objectType
# and that element takes precedence over ATOM_NS content if it is
# present, so it seems reasonable to use CMIS_RA content for now
# and encode everything.
-
- fileData = contentFile.read().encode("base64")
+ fileData = base64.b64encode(contentFile.read())
mediaElement = entryXmlDoc.createElementNS(CMISRA_NS, 'cmisra:mediatype')
mediaElementText = entryXmlDoc.createTextNode(mimetype)
mediaElement.appendChild(mediaElementText)
base64Element = entryXmlDoc.createElementNS(CMISRA_NS, 'cmisra:base64')
- base64ElementText = entryXmlDoc.createTextNode(fileData)
+ base64ElementText = entryXmlDoc.createTextNode(to_native(fileData))
base64Element.appendChild(base64ElementText)
contentElement = entryXmlDoc.createElementNS(CMISRA_NS, 'cmisra:content')
contentElement.appendChild(mediaElement)
Modified: chemistry/cmislib/branches/py3_compat/src/cmislib/browser/binding.py
URL: http://svn.apache.org/viewvc/chemistry/cmislib/branches/py3_compat/src/cmislib/browser/binding.py?rev=1836994&r1=1836993&r2=1836994&view=diff
==============================================================================
--- chemistry/cmislib/branches/py3_compat/src/cmislib/browser/binding.py (original)
+++ chemistry/cmislib/branches/py3_compat/src/cmislib/browser/binding.py Sun Jul 29 16:55:46 2018
@@ -23,8 +23,10 @@ provider.
"""
import json
import logging
-import sys
-import time
+from collections import OrderedDict
+from io import BytesIO
+
+from requests_toolbelt.multipart.encoder import MultipartEncoder
from cmislib import messages
from cmislib.cmis_services import Binding, RepositoryServiceIfc
@@ -32,17 +34,8 @@ from cmislib.domain import CmisId, CmisO
ChangeEntry
from cmislib.exceptions import CmisException, InvalidArgumentException, \
NotSupportedException, ObjectNotFoundException
-from cmislib.net import RESTService as Rest
-from cmislib.util import parsePropValueByType, parseDateTimeValue, safe_quote, \
- safe_urlencode, iteritems, itervalues
-
-if sys.version_info >= (3,):
- import io as StringIO
-else:
- import StringIO
-
-
-CMIS_FORM_TYPE = 'application/x-www-form-urlencoded;charset=utf-8'
+from cmislib.util import parsePropValueByType, parseDateTimeValue, iteritems, \
+ itervalues
moduleLogger = logging.getLogger('cmislib.browser.binding')
@@ -57,11 +50,21 @@ class BrowserBinding(Binding):
def __init__(self, **kwargs):
self.extArgs = kwargs
+ self.user_agent = 'cmislib/browser +http://chemistry.apache.org/'
def getRepositoryService(self):
return RepositoryService()
- def get(self, url, username, password, **kwargs):
+ def _get_http_headers(self, **kwargs):
+ headers = {}
+ if kwargs:
+ if 'headers' in kwargs:
+ headers = kwargs['headers']
+ del kwargs['headers']
+ headers['User-Agent'] = self.user_agent
+ return headers
+
+ def get(self, url, session, **kwargs):
"""
Does a get against the CMIS service. More than likely, you will not
@@ -78,18 +81,13 @@ class BrowserBinding(Binding):
if len(self.extArgs) > 0:
kwargs.update(self.extArgs)
- resp, content = Rest().get(url,
- username=username,
- password=password,
- **kwargs)
- result = None
- if resp['status'] != '200':
- self._processCommonErrors(resp, url)
- else:
- result = json.loads(content)
- return result
+ headers = self._get_http_headers(**kwargs)
+ response = session.get(url, params=kwargs, headers=headers)
+ if 'application/json' in response.headers.get('content-type'):
+ return response.json()
+ return response
- def post(self, url, payload, contentType, username, password, **kwargs):
+ def post(self, url, session, payload, contentType, **kwargs):
"""
Does a post against the CMIS service. More than likely, you will not
@@ -103,19 +101,13 @@ class BrowserBinding(Binding):
# merge the cmis client extended args with the ones that got passed in
if len(self.extArgs) > 0:
kwargs.update(self.extArgs)
-
- result = None
- resp, content = Rest().post(url,
- payload,
- contentType,
- username=username,
- password=password,
- **kwargs)
- if resp['status'] != '200' and resp['status'] != '201':
- self._processCommonErrors(resp, url)
- elif content is not None and content != "":
- result = json.loads(content)
- return result
+ headers = self._get_http_headers(**kwargs)
+ headers['Content-Type'] = contentType
+ result = session.post(
+ url, params=kwargs, data=payload, headers=headers)
+ if result.text:
+ return result.json()
+ return None
class RepositoryService(RepositoryServiceIfc):
@@ -130,7 +122,7 @@ class RepositoryService(RepositoryServic
Gets the repository for the specified repository ID.
"""
- result = client.binding.get(client.repositoryUrl, client.username, client.password, **client.extArgs)
+ result = client.binding.get(client.repositoryUrl, client.session, **client.extArgs)
if repositoryId in result:
return BrowserRepository(client, result[repositoryId])
@@ -143,7 +135,7 @@ class RepositoryService(RepositoryServic
Gets all of the repositories for this client.
"""
- result = client.binding.get(client.repositoryUrl, client.username, client.password, **client.extArgs)
+ result = client.binding.get(client.repositoryUrl, client.session, **client.extArgs)
repositories = []
for repo in itervalues(result):
@@ -159,7 +151,7 @@ class RepositoryService(RepositoryServic
list.
"""
- result = client.binding.get(client.repositoryUrl, client.username, client.password, **client.extArgs)
+ result = client.binding.get(client.repositoryUrl, client.session, **client.extArgs)
# instantiate a Repository object with the first workspace
# element we find
repository = None
@@ -218,12 +210,15 @@ class BrowserCmisObject(object):
self._extArgs.update(kwargs)
else:
self._extArgs = kwargs
-
- byObjectIdUrl = self._repository.getRootFolderUrl() + "?objectId=" + self.getObjectId() + "&cmisselector=object"
- self.data = self._cmisClient.binding.get(byObjectIdUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
- **self._extArgs)
+ params = {
+ 'objectId': self.getObjectId(),
+ 'cmisselector': 'object',
+ }
+ params.update(self._extArgs)
+ url = self._repository.getRootFolderUrl()
+ self.data = self._cmisClient.binding.get(url,
+ self._cmisClient.session,
+ **params)
self._initData()
# if a returnVersion arg was passed in, it is possible we got back
@@ -265,11 +260,15 @@ class BrowserCmisObject(object):
if not self.getAllowableActions()['canGetObjectParents']:
raise NotSupportedException('Object does not support getObjectParents')
- byObjectIdUrl = self._repository.getRootFolderUrl() + "?objectId=" + self.getObjectId() + "&cmisselector=parents"
- result = self._cmisClient.binding.get(byObjectIdUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
- **kwargs)
+ url = self._repository.getRootFolderUrl()
+ params = {
+ 'objectId': self.getObjectId(),
+ 'cmisselector': 'parents',
+ }
+ params.update(kwargs)
+ result = self._cmisClient.binding.get(url,
+ self._cmisClient.session,
+ **params)
# return the result set
return BrowserResultSet(self._cmisClient, self._repository, {'objects': result}, serializer=ChildrenSerializer())
@@ -376,18 +375,17 @@ class BrowserCmisObject(object):
"""
# get the root folder URL
- updateUrl = self._repository.getRootFolderUrl() + "?objectId=" + self.id
-
- props = {"cmisaction": "update"}
-
+ url = self._repository.getRootFolderUrl()
+ props = {
+ "objectId": self.id,
+ "cmisaction": "update"}
setProps(properties, props, initialIndex=0)
-
+ data = encode_multipart_formdata(props, None, None)
# invoke the URL
- result = self._cmisClient.binding.post(updateUrl.encode('utf-8'),
- safe_urlencode(props),
- 'application/x-www-form-urlencoded',
- self._cmisClient.username,
- self._cmisClient.password)
+ result = self._cmisClient.binding.post(url,
+ self._cmisClient.session,
+ data,
+ data.content_type)
self.data = result
self._initData()
@@ -404,19 +402,18 @@ class BrowserCmisObject(object):
>>> doc.move(sub1, sub2)
"""
- moveUrl = self._repository.getRootFolderUrl()
+ url = self._repository.getRootFolderUrl()
props = {"objectId": self.id,
"cmisaction": "move",
"sourceFolderId": sourceFolder.id,
"targetFolderId": targetFolder.id}
-
+ data = encode_multipart_formdata(props, None, None)
# invoke the URL
- self._cmisClient.binding.post(moveUrl.encode('utf-8'),
- safe_urlencode(props),
- 'application/x-www-form-urlencoded',
- self._cmisClient.username,
- self._cmisClient.password)
+ self._cmisClient.binding.post(url,
+ self._cmisClient.session,
+ data,
+ data.content_type)
return
@@ -434,17 +431,16 @@ class BrowserCmisObject(object):
The optional allVersions argument is supported.
"""
- delUrl = self._repository.getRootFolderUrl()
+ url = self._repository.getRootFolderUrl()
props = {"objectId": self.id,
"cmisaction": "delete"}
-
+ data = encode_multipart_formdata(props, None, None)
# invoke the URL
- self._cmisClient.binding.post(delUrl.encode('utf-8'),
- safe_urlencode(props),
- 'application/x-www-form-urlencoded',
- self._cmisClient.username,
- self._cmisClient.password,
+ self._cmisClient.binding.post(url,
+ self._cmisClient.session,
+ data,
+ data.content_type,
**kwargs)
return
@@ -482,13 +478,12 @@ class BrowserCmisObject(object):
'cmis:targetId': targetObj.getObjectId(),
'cmis:objectTypeId': relTypeId
}, props)
-
+ data = encode_multipart_formdata(props, None, None)
# invoke the URL
- result = self._cmisClient.binding.post(url.encode('utf-8'),
- safe_urlencode(props),
- 'application/x-www-form-urlencoded',
- self._cmisClient.username,
- self._cmisClient.password)
+ result = self._cmisClient.binding.post(url,
+ self._cmisClient.session,
+ data,
+ data.content_type)
return getSpecializedObject(BrowserCmisObject(self._cmisClient, self._repository, data=result))
def getRelationships(self, **kwargs):
@@ -514,11 +509,15 @@ class BrowserCmisObject(object):
- includeAllowableActions
"""
- byObjectIdUrl = self._repository.getRootFolderUrl() + "?objectId=" + self.getObjectId() + "&cmisselector=relationships"
- result = self._cmisClient.binding.get(byObjectIdUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
- **kwargs)
+ url = self._repository.getRootFolderUrl()
+ params = {
+ 'objectId': self.getObjectId(),
+ 'cmisselector': 'relationships',
+ }
+ params.update(kwargs)
+ result = self._cmisClient.binding.get(url,
+ self._cmisClient.session,
+ **params)
# return the result set
return BrowserResultSet(self._cmisClient, self._repository, result, serializer=RelationShipsSerializer())
@@ -553,10 +552,15 @@ class BrowserCmisObject(object):
if self._repository.getCapabilities()['ACL']:
# if the ACL capability is discover or manage, this must be
# supported
- aclUrl = self._repository.getRootFolderUrl() + "?cmisselector=object&objectId=" + self.getObjectId() + "&includeACL=true"
- result = self._cmisClient.binding.get(aclUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password)
+ url = self._repository.getRootFolderUrl()
+ params = {
+ 'objectId': self.getObjectId(),
+ 'cmisselector': 'object',
+ 'includeACL': True
+ }
+ result = self._cmisClient.binding.get(url,
+ self._cmisClient.session,
+ **params)
return BrowserACL(data=result['acl'])
else:
raise NotSupportedException
@@ -581,26 +585,28 @@ class BrowserCmisObject(object):
if not isinstance(acl, ACL):
raise CmisException('The ACL to apply must be an instance of the ACL class.')
# get the root folder URL
- aclUrl = self._repository.getRootFolderUrl() + "?objectId=" + self.id + "&cmisaction=applyACL"
+ url = self._repository.getRootFolderUrl()
- fields = {}
+ props = {
+ 'objectId': self.id,
+ 'cmisaction': 'applyACL'
+ }
for i, entry in enumerate(acl.getAddedAces()):
- fields['addACEPrincipal[%d]' % i] = entry.principalId
+ props['addACEPrincipal[%d]' % i] = entry.principalId
for j, perm in enumerate(entry.permissions):
- fields['addACEPermission[%d][%d]' % (i, j)] = perm
+ props['addACEPermission[%d][%d]' % (i, j)] = perm
for i, entry in enumerate(acl.getRemovedAces()):
- fields['removeACEPrincipal[%d]' % i] = entry.principalId
+ props['removeACEPrincipal[%d]' % i] = entry.principalId
for j, perm in enumerate(entry.permissions):
- fields['removeACEPermission[%d][%d]' % (i, j)] = perm
+ props['removeACEPermission[%d][%d]' % (i, j)] = perm
- contentType, body = encode_multipart_formdata(fields, None, None)
+ data = encode_multipart_formdata(props, None, None)
# invoke the URL
- result = self._cmisClient.binding.post(aclUrl.encode('utf-8'),
- body,
- contentType,
- self._cmisClient.username,
- self._cmisClient.password)
+ result = self._cmisClient.binding.post(url,
+ self._cmisClient.session,
+ data,
+ data.content_type)
# return the result set
return BrowserACL(data=result)
@@ -777,11 +783,14 @@ class BrowserRepository(object):
- includeAllowableActions
"""
- byPathUrl = self.getRootFolderUrl() + safe_quote(path) + "?cmisselector=object"
- result = self._cmisClient.binding.get(byPathUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
- **kwargs)
+ url = self.getRootFolderUrl() + path
+ params = {
+ 'cmisselector': 'object',
+ }
+ params.update(kwargs)
+ result = self._cmisClient.binding.get(url,
+ self._cmisClient.session,
+ **params)
return getSpecializedObject(BrowserCmisObject(self._cmisClient, self, data=result, **kwargs), **kwargs)
def getSupportedPermissions(self):
@@ -985,15 +994,16 @@ class BrowserRepository(object):
cmis:policy
"""
- typesUrl = self.getRepositoryUrl() + "?cmisselector=typeChildren"
-
+ url = self.getRepositoryUrl()
+ params = {
+ 'cmisselector': 'typeChildren',
+ }
if typeId is not None:
- typesUrl += "&typeId=%s" % (safe_quote(typeId))
-
- result = self._cmisClient.binding.get(typesUrl,
- self._cmisClient.username,
- self._cmisClient.password,
- **kwargs)
+ params["typeId"] = typeId
+ params.update(kwargs)
+ result = self._cmisClient.binding.get(url,
+ self._cmisClient.session,
+ **params)
types = []
for res in result['types']:
objectType = BrowserObjectType(self._cmisClient,
@@ -1045,17 +1055,19 @@ class BrowserRepository(object):
17
"""
- typesUrl = self.getRepositoryUrl() + "?cmisselector=typeDescendants"
-
+ url = self.getRepositoryUrl()
+ params = {
+ 'cmisselector': 'typeDescendants',
+ }
if typeId is not None:
- typesUrl += "&typeId=%s" % (safe_quote(typeId))
+ params['typeId'] = typeId
if depth is not None:
- typesUrl += "&depth=%s" % (depth)
+ params['depth'] = depth
+ params.update(kwargs)
- result = self._cmisClient.binding.get(typesUrl,
- self._cmisClient.username,
- self._cmisClient.password,
- **kwargs)
+ result = self._cmisClient.binding.get(url,
+ self._cmisClient.session,
+ **params)
serializer = TreeSerializer(treeType='type')
types = serializer.getEntries(self._cmisClient, self, result)
return types
@@ -1076,12 +1088,14 @@ class BrowserRepository(object):
cmis:policy
"""
- typesUrl = self.getRepositoryUrl() + "?cmisselector=typeChildren"
-
- result = self._cmisClient.binding.get(typesUrl,
- self._cmisClient.username,
- self._cmisClient.password,
- **kwargs)
+ url = self.getRepositoryUrl()
+ params = {
+ 'cmisselector': 'typeChildren',
+ }
+ params.update(kwargs)
+ result = self._cmisClient.binding.get(url,
+ self._cmisClient.session,
+ **params)
types = []
for res in result['types']:
objectType = BrowserObjectType(self._cmisClient,
@@ -1099,11 +1113,14 @@ class BrowserRepository(object):
>>> folderType = repo.getTypeDefinition('cmis:folder')
"""
# localhost:8080/chemistry/browser/A1?cmisselector=typeDefinition&typeId=cmis:folder
- typesUrl = self.getRepositoryUrl() + "?cmisselector=typeDefinition" + \
- "&typeId=" + typeId
- result = self._cmisClient.binding.get(typesUrl,
- self._cmisClient.username,
- self._cmisClient.password)
+ url = self.getRepositoryUrl()
+ params = {
+ 'cmisselector': 'typeDefinition',
+ 'typeId': typeId
+ }
+ result = self._cmisClient.binding.get(url,
+ self._cmisClient.session,
+ **params)
return BrowserObjectType(self._cmisClient,
self,
@@ -1135,12 +1152,14 @@ class BrowserRepository(object):
- includeAllowableActions
"""
- typesUrl = self.getRepositoryUrl() + "?cmisselector=checkedOut"
-
- result = self._cmisClient.binding.get(typesUrl,
- self._cmisClient.username,
- self._cmisClient.password,
- **kwargs)
+ url = self.getRepositoryUrl()
+ params = {
+ 'cmisselector': 'checkedOut',
+ }
+ params.update(kwargs)
+ result = self._cmisClient.binding.get(url,
+ self._cmisClient.session,
+ **params)
return BrowserResultSet(self._cmisClient,
self,
@@ -1213,14 +1232,16 @@ class BrowserRepository(object):
"""
# build the CMIS query XML that we're going to POST
- queryUrl = self.getRepositoryUrl() + "?cmisaction=query&q=" + safe_quote(statement)
-
+ props = {
+ 'cmisaction': 'query',
+ 'q': statement
+ }
+ data = encode_multipart_formdata(props, None, None)
# do the POST
- result = self._cmisClient.binding.post(queryUrl.encode('utf-8'),
- None,
- CMIS_FORM_TYPE,
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.post(self.getRepositoryUrl(),
+ self._cmisClient.session,
+ data,
+ data.content_type,
**kwargs)
# return the result set
@@ -1274,12 +1295,14 @@ class BrowserRepository(object):
if self.getCapabilities()['Changes'] is None:
raise NotSupportedException(messages.NO_CHANGE_LOG_SUPPORT)
- changesUrl = self.getRepositoryUrl() + "?cmisselector=contentChanges"
-
- result = self._cmisClient.binding.get(changesUrl,
- self._cmisClient.username,
- self._cmisClient.password,
- **kwargs)
+ url = self.getRepositoryUrl()
+ params = {
+ 'cmisselector': 'contentChanges',
+ }
+ params.update(kwargs)
+ result = self._cmisClient.binding.get(url,
+ self._cmisClient.session,
+ **params)
return BrowserResultSet(self._cmisClient,
self,
@@ -1299,9 +1322,6 @@ class BrowserRepository(object):
the repository supports unfiled objects, you do not have to pass in
a parent :class:`Folder` otherwise it is required.
- This method is essentially a convenience method that wraps your string
- with a StringIO and then calls createDocument.
-
>>> repo.createDocumentFromString('testdoc5', parentFolder=testFolder, contentString='Hello, World!', contentType='text/plain')
<cmislib.model.Document object at 0x101352ed0>
"""
@@ -1317,7 +1337,7 @@ class BrowserRepository(object):
# this repo requires fileable objects to be filed
raise InvalidArgumentException
- return parentFolder.createDocument(name, properties, StringIO.StringIO(contentString),
+ return parentFolder.createDocument(name, properties, contentString,
contentType, contentEncoding)
def createDocument(self,
@@ -1351,7 +1371,6 @@ class BrowserRepository(object):
- addACEs
- removeACEs
"""
-
# if you didn't pass in a parent folder
if parentFolder is None:
# if the repository doesn't require fileable objects to be filed
@@ -1363,7 +1382,7 @@ class BrowserRepository(object):
raise InvalidArgumentException
# get the root folder URL
- createDocUrl = self.getRootFolderUrl()
+ url = self.getRootFolderUrl()
props = {"objectId": parentFolder.id,
"cmisaction": "createDocument",
@@ -1379,16 +1398,10 @@ class BrowserRepository(object):
setProps(properties, props, initialIndex=2)
- contentType, body = encode_multipart_formdata(props, contentFile, contentType)
+ data = encode_multipart_formdata(props, contentFile, contentType)
- # invoke the URL
- result = self._cmisClient.binding.post(createDocUrl.encode('utf-8'),
- body,
- contentType,
- self._cmisClient.username,
- self._cmisClient.password)
-
- # return the result set
+ result = self._cmisClient.binding.post(
+ url, self._cmisClient.session, data, data.content_type)
return BrowserDocument(self._cmisClient, self, data=result)
def createDocumentFromSource(self,
@@ -1693,17 +1706,16 @@ class BrowserDocument(BrowserCmisObject)
True
"""
- coUrl = self._repository.getRootFolderUrl()
+ url = self._repository.getRootFolderUrl()
props = {"objectId": self.id,
"cmisaction": "checkOut"}
-
+ data = encode_multipart_formdata(props, None, None)
# invoke the URL
- result = self._cmisClient.binding.post(coUrl.encode('utf-8'),
- safe_urlencode(props),
- 'application/x-www-form-urlencoded',
- self._cmisClient.username,
- self._cmisClient.password)
+ result = self._cmisClient.binding.post(url,
+ self._cmisClient.session,
+ data,
+ data.content_type)
return getSpecializedObject(BrowserCmisObject(self._cmisClient, self._repository, data=result))
@@ -1720,17 +1732,16 @@ class BrowserDocument(BrowserCmisObject)
False
"""
- coUrl = self._repository.getRootFolderUrl()
+ url = self._repository.getRootFolderUrl()
props = {"objectId": self.id,
"cmisaction": "cancelCheckOut"}
-
+ data = encode_multipart_formdata(props, None, None)
# invoke the URL
- self._cmisClient.binding.post(coUrl.encode('utf-8'),
- safe_urlencode(props),
- 'application/x-www-form-urlencoded',
- self._cmisClient.username,
- self._cmisClient.password)
+ self._cmisClient.binding.post(url,
+ self._cmisClient.session,
+ data,
+ data.content_type)
return
@@ -1818,6 +1829,8 @@ class BrowserDocument(BrowserCmisObject)
kwargs['major'] = 'false'
props = {
+ 'objectId': self.id,
+ 'cmisaction': 'checkin',
'checkinComment': checkinComment or "",
}
props.update(kwargs)
@@ -1828,16 +1841,15 @@ class BrowserDocument(BrowserCmisObject)
props["propertyValue[%s]" % propCount] = value
propCount += 1
- ciUrl = self._repository.getRootFolderUrl() + "?objectId=" + self.id + "&cmisaction=checkin"
+ url = self._repository.getRootFolderUrl()
- contentType, body = encode_multipart_formdata(props, contentFile, contentType)
+ data = encode_multipart_formdata(props, contentFile, contentType)
# invoke the URL
- result = self._cmisClient.binding.post(ciUrl.encode('utf-8'),
- body,
- contentType,
- self._cmisClient.username,
- self._cmisClient.password)
+ result = self._cmisClient.binding.post(url,
+ self._cmisClient.session,
+ data,
+ data.content_type)
return getSpecializedObject(BrowserCmisObject(self._cmisClient, self._repository, data=result))
@@ -1899,13 +1911,16 @@ class BrowserDocument(BrowserCmisObject)
"""
# get the version history link
- versionsUrl = self._repository.getRootFolderUrl() + '?cmisselector=versions' + '&objectId=' + self.getObjectId()
-
+ url = self._repository.getRootFolderUrl()
+ params = {
+ 'objectId': self.getObjectId(),
+ 'cmisselector': 'versions',
+ }
+ params.update(kwargs)
# invoke the URL
- result = self._cmisClient.binding.get(versionsUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
- **kwargs)
+ result = self._cmisClient.binding.get(url,
+ self._cmisClient.session,
+ **params)
# return the result set
return BrowserResultSet(self._cmisClient, self._repository, data={'objects': result}, serializer=VersionsSerializer())
@@ -1932,14 +1947,15 @@ class BrowserDocument(BrowserCmisObject)
if not self.getAllowableActions()['canGetContentStream']:
return None
- contentUrl = self._repository.getRootFolderUrl() + "?objectId=" + self.getObjectId() + "&cmisselector=content"
- result, content = Rest().get(contentUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
- **self._cmisClient.extArgs)
- if result['status'] != '200':
- raise CmisException(result['status'])
- return StringIO.StringIO(content)
+ url = self._repository.getRootFolderUrl()
+ params = {
+ 'objectId': self.getObjectId(),
+ 'cmisselector': 'content',
+ }
+ result = self._cmisClient.binding.get(url,
+ self._cmisClient.session,
+ **params)
+ return BytesIO(result.content)
def setContentStream(self, contentFile, contentType=None):
@@ -1951,16 +1967,18 @@ class BrowserDocument(BrowserCmisObject)
"""
# get the root folder URL
- createDocUrl = self._repository.getRootFolderUrl() + "?objectId=" + self.id + "&cmisaction=setContent"
-
- contentType, body = encode_multipart_formdata(None, contentFile, contentType)
+ url = self._repository.getRootFolderUrl()
+ params = {
+ 'objectId': self.id,
+ 'cmisaction': 'setContent'
+ }
+ data = encode_multipart_formdata(params, contentFile, contentType)
# invoke the URL
- result = self._cmisClient.binding.post(createDocUrl.encode('utf-8'),
- body,
- contentType,
- self._cmisClient.username,
- self._cmisClient.password)
+ result = self._cmisClient.binding.post(url,
+ self._cmisClient.session,
+ data,
+ data.content_type)
# return the result set
return BrowserDocument(self._cmisClient, self._repository, data=result)
@@ -1974,20 +1992,19 @@ class BrowserDocument(BrowserCmisObject)
if not self.allowableActions['canDeleteContentStream']:
raise CmisException('Not allowed to delete the content stream')
- delUrl = self._repository.getRootFolderUrl()
+ url = self._repository.getRootFolderUrl()
props = {"objectId": self.id,
"cmisaction": "deleteContent"}
if 'cmis:changeToken' in self.properties:
props["changeToken"] = self.properties['cmis:changeToken']
-
+ data = encode_multipart_formdata(props, None, None)
# invoke the URL
- self._cmisClient.binding.post(delUrl.encode('utf-8'),
- safe_urlencode(props),
- 'application/x-www-form-urlencoded',
- self._cmisClient.username,
- self._cmisClient.password)
+ self._cmisClient.binding.post(url,
+ self._cmisClient.session,
+ data,
+ data.content_type)
return
@@ -2011,16 +2028,15 @@ class BrowserDocument(BrowserCmisObject)
renditions = []
- contentUrl = self._repository.getRootFolderUrl() + "?objectId=" + self.getObjectId() + "&cmisselector=renditions&renditionFilter=*"
- result, content = Rest().get(contentUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
- **self._cmisClient.extArgs)
- if result['status'] != '200':
- raise CmisException(result['status'])
-
- resultObj = json.loads(content)
- for rendObj in resultObj:
+ url = self._repository.getRootFolderUrl()
+ params = {
+ 'objectId': self.getObjectId(),
+ 'cmisselector': 'renditions',
+ 'renditionFilter': '*'
+ }
+ result = self._cmisClient.binding.get(
+ url, self._cmisClient.session, **params)
+ for rendObj in result:
renditions.append(BrowserRendition(rendObj))
return renditions
@@ -2034,10 +2050,15 @@ class BrowserDocument(BrowserCmisObject)
of cmis:path with the relativePathSegment.
"""
- byObjectIdUrl = self._repository.getRootFolderUrl() + "?objectId=" + self.getObjectId() + "&cmisselector=parents&includerelativepathsegment=true"
- result = self._cmisClient.binding.get(byObjectIdUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password)
+ url = self._repository.getRootFolderUrl()
+ params = {
+ 'objectId': self.getObjectId(),
+ 'cmisselector': 'parents',
+ 'includerelativepathsegment': True
+ }
+ result = self._cmisClient.binding.get(url,
+ self._cmisClient.session,
+ **params)
paths = []
@@ -2084,7 +2105,7 @@ class BrowserFolder(BrowserCmisObject):
"""
# get the root folder URL
- createFolderUrl = self._repository.getRootFolderUrl()
+ url = self._repository.getRootFolderUrl()
props = {"objectId": self.id,
"cmisaction": "createFolder",
@@ -2100,12 +2121,12 @@ class BrowserFolder(BrowserCmisObject):
setProps(properties, props, initialIndex=2)
+ data = encode_multipart_formdata(props, None, None)
# invoke the URL
- result = self._cmisClient.binding.post(createFolderUrl.encode('utf-8'),
- safe_urlencode(props),
- 'application/x-www-form-urlencoded',
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.post(url,
+ self._cmisClient.session,
+ data,
+ data.content_type,
**kwargs)
# return the result set
@@ -2123,9 +2144,6 @@ class BrowserFolder(BrowserCmisObject):
the repository supports unfiled objects, you do not have to pass in
a parent :class:`Folder` otherwise it is required.
- This method is essentially a convenience method that wraps your string
- with a StringIO and then calls createDocument.
-
>>> testFolder.createDocumentFromString('testdoc3', contentString='hello, world', contentType='text/plain')
"""
@@ -2207,11 +2225,16 @@ class BrowserFolder(BrowserCmisObject):
- includePathSegment
"""
- byObjectIdUrl = self._repository.getRootFolderUrl() + "?objectId=" + self.getObjectId() + "&cmisselector=children"
- result = self._cmisClient.binding.get(byObjectIdUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
- **kwargs)
+ url = self._repository.getRootFolderUrl()
+ params = {
+ 'objectId': self.getObjectId(),
+ 'cmisselector': 'children',
+ }
+ params.update(kwargs)
+
+ result = self._cmisClient.binding.get(url,
+ self._cmisClient.session,
+ **params)
# return the result set
return BrowserResultSet(self._cmisClient, self._repository, result, serializer=ChildrenSerializer())
@@ -2247,11 +2270,15 @@ class BrowserFolder(BrowserCmisObject):
"""
- byObjectIdUrl = self._repository.getRootFolderUrl() + "?objectId=" + self.getObjectId() + "&cmisselector=descendants"
- result = self._cmisClient.binding.get(byObjectIdUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
- **kwargs)
+ url = self._repository.getRootFolderUrl()
+ params = {
+ 'objectId': self.getObjectId(),
+ 'cmisselector': 'descendants',
+ }
+ params.update(kwargs)
+ result = self._cmisClient.binding.get(url,
+ self._cmisClient.session,
+ **params)
# return the result set
return BrowserResultSet(self._cmisClient, self._repository, result, serializer=TreeSerializer())
@@ -2281,11 +2308,16 @@ class BrowserFolder(BrowserCmisObject):
u'subfolder'
"""
- byObjectIdUrl = self._repository.getRootFolderUrl() + "?objectId=" + self.getObjectId() + "&cmisselector=foldertree"
- result = self._cmisClient.binding.get(byObjectIdUrl.encode('utf-8'),
- self._cmisClient.username,
- self._cmisClient.password,
- **kwargs)
+ url = self._repository.getRootFolderUrl()
+ params = {
+ 'objectId': self.getObjectId(),
+ 'cmisselector': 'foldertree',
+ }
+ params.update(kwargs)
+
+ result = self._cmisClient.binding.get(url,
+ self._cmisClient.session,
+ **params)
# return the result set
return BrowserResultSet(self._cmisClient, self._repository, result, serializer=TreeSerializer())
@@ -2313,17 +2345,16 @@ class BrowserFolder(BrowserCmisObject):
- continueOnFailure
"""
- delUrl = self._repository.getRootFolderUrl()
+ url = self._repository.getRootFolderUrl()
props = {"objectId": self.id,
"cmisaction": "deleteTree"}
-
+ data = encode_multipart_formdata(props, None, None)
# invoke the URL
- self._cmisClient.binding.post(delUrl.encode('utf-8'),
- safe_urlencode(props),
- 'application/x-www-form-urlencoded',
- self._cmisClient.username,
- self._cmisClient.password,
+ self._cmisClient.binding.post(url,
+ self._cmisClient.session,
+ data,
+ data.content_type,
**kwargs)
return
@@ -2352,18 +2383,17 @@ class BrowserFolder(BrowserCmisObject):
"""
# TODO need to add support (and unit test) for allVersions
- addUrl = self._repository.getRootFolderUrl()
+ url = self._repository.getRootFolderUrl()
props = {"folderId": self.id,
"cmisaction": "addObjectToFolder",
"objectId": cmisObject.id}
-
+ data = encode_multipart_formdata(props, None, None)
# invoke the URL
- result = self._cmisClient.binding.post(addUrl.encode('utf-8'),
- safe_urlencode(props),
- 'application/x-www-form-urlencoded',
- self._cmisClient.username,
- self._cmisClient.password,
+ result = self._cmisClient.binding.post(url,
+ self._cmisClient.session,
+ data,
+ data.content_type,
**kwargs)
return getSpecializedObject(BrowserCmisObject(self._cmisClient, self._repository, data=result))
@@ -2375,18 +2405,17 @@ class BrowserFolder(BrowserCmisObject):
support unfiling for this to work.
"""
- remUrl = self._repository.getRootFolderUrl()
+ url = self._repository.getRootFolderUrl()
props = {"folderId": self.id,
"cmisaction": "removeObjectFromFolder",
"objectId": cmisObject.id}
-
+ data = encode_multipart_formdata(props, None, None)
# invoke the URL
- result = self._cmisClient.binding.post(remUrl.encode('utf-8'),
- safe_urlencode(props),
- 'application/x-www-form-urlencoded',
- self._cmisClient.username,
- self._cmisClient.password)
+ result = self._cmisClient.binding.post(url,
+ self._cmisClient.session,
+ data,
+ data.content_type)
return getSpecializedObject(BrowserCmisObject(self._cmisClient, self._repository, data=result))
@@ -2622,8 +2651,7 @@ class BrowserObjectType(ObjectType):
kwargs['cmisselector'] = 'typeDefinition'
kwargs['typeId'] = self.getTypeId()
result = self._cmisClient.binding.get(typesUrl,
- self._cmisClient.username,
- self._cmisClient.password,
+ self._cmisClient.session,
**kwargs)
self.data = result
@@ -3210,7 +3238,7 @@ def setProps(properties, props, initialI
i = initialIndex
for key, val in properties.items():
props["propertyId[%s]" % i] = key
- if hasattr(val, '__iter__'):
+ if isinstance(val, (list, tuple) ):
j = 0
for v in val:
props["propertyValue[%s][%s]" % (i, j)] = v
@@ -3252,36 +3280,22 @@ def encode_multipart_formdata(fields, co
"""
fields is a sequence of (name, value) elements for regular form fields.
files is a sequence of (name, filename, value) elements for data to be uploaded as files
- Return (content_type, body) ready for httplib.HTTP instance
+ Return MultipartEncoder for requests.post method
"""
-
- boundary = 'aPacHeCheMIStrycMisLIb%s' % (int(time.time()))
- crlf = '\r\n'
- L = []
+ _fields = OrderedDict()
fileName = None
if fields:
for (key, value) in iteritems(fields):
- if key == 'cmis:name':
- fileName = value
- L.append('--' + boundary)
- L.append('Content-Disposition: form-data; name="%s"' % key)
- L.append('Content-Type: text/plain; charset=utf-8')
- L.append('')
- L.append(value.encode('utf-8'))
-
+ if contentFile and value == 'cmis:name':
+ fileName = fields['propertyValue' + key[-3:]]
+ _fields[key] = (None, value, 'text/plain;charset=utf-8')
if contentFile:
- L.append('--' + boundary)
- L.append('Content-Disposition: form-data; name="%s"; filename=%s' % ('content', fileName))
- L.append('Content-Type: %s' % contentType)
- L.append('Content-Transfer-Encoding: binary')
- L.append('')
- L.append(contentFile.read())
-
- L.append('--' + boundary + '--')
- L.append('')
- body = crlf.join(L)
- content_type = 'multipart/form-data; boundary=%s' % boundary
- return content_type, body
+ _fields['content'] = (fileName or '', contentFile, contentType or 'application/binary')
+
+ m = MultipartEncoder(
+ fields=_fields
+ )
+ return m
class ResultsSerializer(object):
Modified: chemistry/cmislib/branches/py3_compat/src/cmislib/cmis_services.py
URL: http://svn.apache.org/viewvc/chemistry/cmislib/branches/py3_compat/src/cmislib/cmis_services.py?rev=1836994&r1=1836993&r2=1836994&view=diff
==============================================================================
--- chemistry/cmislib/branches/py3_compat/src/cmislib/cmis_services.py (original)
+++ chemistry/cmislib/branches/py3_compat/src/cmislib/cmis_services.py Sun Jul 29 16:55:46 2018
@@ -41,30 +41,31 @@ class Binding(object):
pass
- def _processCommonErrors(self, error, url):
+ def _processCommonErrors(self, response):
"""
Maps HTTPErrors that are common to all to exceptions. Only errors
that are truly global, like 401 not authorized, should be handled
here. Callers should handle the rest.
"""
-
- if error['status'] == '401':
- raise PermissionDeniedException(error['status'], url)
- elif error['status'] == '400':
- raise InvalidArgumentException(error['status'], url)
- elif error['status'] == '404':
- raise ObjectNotFoundException(error['status'], url)
- elif error['status'] == '403':
- raise PermissionDeniedException(error['status'], url)
- elif error['status'] == '405':
- raise NotSupportedException(error['status'], url)
- elif error['status'] == '409':
- raise UpdateConflictException(error['status'], url)
- elif error['status'] == '500':
- raise RuntimeException(error['status'], url)
+ status_code = response.status_code
+ url = response.url
+ if status_code == 401:
+ raise PermissionDeniedException(status_code, url, response.text)
+ elif status_code == 400:
+ raise InvalidArgumentException(status_code, url, response.text)
+ elif status_code == 404:
+ raise ObjectNotFoundException(status_code, url, response.text)
+ elif status_code == 403:
+ raise PermissionDeniedException(status_code, url, response.text)
+ elif status_code == 405:
+ raise NotSupportedException(status_code, url, response.text)
+ elif status_code == 409:
+ raise UpdateConflictException(status_code, url, response.text)
+ elif status_code == 500:
+ raise RuntimeException(status_code, url, response.text)
else:
- raise CmisException(error['status'], url)
+ raise CmisException(status_code, url, response.text)
class RepositoryServiceIfc(object):
Modified: chemistry/cmislib/branches/py3_compat/src/cmislib/domain.py
URL: http://svn.apache.org/viewvc/chemistry/cmislib/branches/py3_compat/src/cmislib/domain.py?rev=1836994&r1=1836993&r2=1836994&view=diff
==============================================================================
--- chemistry/cmislib/branches/py3_compat/src/cmislib/domain.py (original)
+++ chemistry/cmislib/branches/py3_compat/src/cmislib/domain.py Sun Jul 29 16:55:46 2018
@@ -2026,14 +2026,14 @@ class ACE(object):
"""Getter for permissions"""
return self._permissions
- def __cmp__(self, other):
+ def __eq__(self, other):
if (
isinstance(other, self.__class__) and
self.principalId == other.principalId and
self.direct == other.direct and
not(set(self.permissions) ^ set(other.permissions))):
- return 0
- return -1
+ return True
+ return False
def copy(self):
"""