[ https://issues.apache.org/jira/browse/CMIS-972?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Laurent Mignon updated CMIS-972: -------------------------------- Description: I've improved the checkin method to allow to update the content stream and the properties {code} >From cbca562e4cfce685c2cc60ee2ad0d73182d3cb5f Mon Sep 17 00:00:00 2001 From: Laurent Mignon <laurent.mig...@acsone.eu> Date: Fri, 9 Sep 2016 18:53:05 +0200 Subject: [PATCH] Support content and properties paramaters on method checkin --- src/cmislib/atompub/binding.py | 23 ++++++++++++++++------- src/cmislib/browser/binding.py | 34 ++++++++++++++++++++-------------- src/cmislib/domain.py | 9 +++------ src/tests/cmislibtest.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 27 deletions(-) diff --git a/src/cmislib/atompub/binding.py b/src/cmislib/atompub/binding.py index f1a629f..2eee222 100644 --- a/src/cmislib/atompub/binding.py +++ b/src/cmislib/atompub/binding.py @@ -2362,7 +2362,8 @@ def getCheckedOutBy(self): self.reload() return self.getProperties()['cmis:versionSeriesCheckedOutBy'] - def checkin(self, checkinComment=None, **kwargs): + def checkin(self, checkinComment=None, contentFile=None, contentType=None, + properties=None, **kwargs): """ Checks in this :class:`Document` which must be a private @@ -2378,10 +2379,7 @@ def checkin(self, checkinComment=None, **kwargs): >>> doc.isCheckedOut() False - The following optional arguments are supported: - - major - - properties - - contentStream + The following optional arguments are NOT supported: - policies - addACEs - removeACEs @@ -2395,8 +2393,19 @@ def checkin(self, checkinComment=None, **kwargs): kwargs['checkin'] = 'true' kwargs['checkinComment'] = checkinComment - # Build an empty ATOM entry - entryXmlDoc = getEmptyXmlDoc() + if not properties and not contentFile: + # Build an empty ATOM entry + entryXmlDoc = getEmptyXmlDoc() + else: + # the getEntryXmlDoc function may need the object type + objectTypeId = None + if self.properties.has_key('cmis:objectTypeId') and not properties.has_key('cmis:objectTypeId'): + objectTypeId = self.properties['cmis:objectTypeId'] + self.logger.debug('This object type is:%s', objectTypeId) + + # build the entry based on the properties provided + entryXmlDoc = getEntryXmlDoc( + self._repository, objectTypeId, properties, contentFile, contentType) # Get the self link # Do a PUT of the empty ATOM to the self link diff --git a/src/cmislib/browser/binding.py b/src/cmislib/browser/binding.py index 7d7d758..c300e5e 100644 --- a/src/cmislib/browser/binding.py +++ b/src/cmislib/browser/binding.py @@ -1755,7 +1755,8 @@ def getCheckedOutBy(self): self.reload() return self.getProperties()['cmis:versionSeriesCheckedOutBy'] - def checkin(self, checkinComment=None, **kwargs): + def checkin(self, checkinComment=None, contentFile=None, contentType=None, + properties=None, **kwargs): """ Checks in this :class:`Document` which must be a private @@ -1772,9 +1773,6 @@ def checkin(self, checkinComment=None, **kwargs): False The following optional arguments are NOT supported: - - major - - properties - - contentStream - policies - addACEs - removeACEs @@ -1784,21 +1782,29 @@ def checkin(self, checkinComment=None, **kwargs): if not kwargs.has_key('major'): kwargs['major'] = 'true' - kwargs['checkinComment'] = checkinComment - - ciUrl = self._repository.getRootFolderUrl() + else: + kwargs['major'] = 'false' + props = { + 'checkinComment': checkinComment or "", + } + props.update(kwargs) + propCount = 0 + properties = properties or {} + for key, value in properties.iteritems(): + props["propertyId[%s]" % propCount] = key + props["propertyValue[%s]" % propCount] = value + propCount += 1 + + ciUrl = self._repository.getRootFolderUrl() + "?objectId=" + self.id + "&cmisaction=checkin" - # TODO don't hardcode major flag - props = {"objectId": self.id, - "cmisaction": "checkIn"} + contentType, body = encode_multipart_formdata(props, contentFile, contentType) # invoke the URL result = self._cmisClient.binding.post(ciUrl.encode('utf-8'), - safe_urlencode(props), - 'application/x-www-form-urlencoded', + body, + contentType, self._cmisClient.username, - self._cmisClient.password, - **kwargs) + self._cmisClient.password) return getSpecializedObject(BrowserCmisObject(self._cmisClient, self._repository, data=result)) diff --git a/src/cmislib/domain.py b/src/cmislib/domain.py index a2f7a25..3b4175c 100644 --- a/src/cmislib/domain.py +++ b/src/cmislib/domain.py @@ -1240,7 +1240,8 @@ def getCheckedOutBy(self): pass - def checkin(self, checkinComment=None, **kwargs): + def checkin(self, checkinComment=None, contentFile=None, contentType=None, + properties=None, **kwargs): """ Checks in this :class:`Document` which must be a private @@ -1256,15 +1257,11 @@ def checkin(self, checkinComment=None, **kwargs): >>> doc.isCheckedOut() False - The following optional arguments are supported: - - major - - properties - - contentStream + The following optional arguments are NOT supported: - policies - addACEs - removeACEs """ - pass def getLatestVersion(self, **kwargs): diff --git a/src/tests/cmislibtest.py b/src/tests/cmislibtest.py index a81be56..4ad13a4 100644 --- a/src/tests/cmislibtest.py +++ b/src/tests/cmislibtest.py @@ -898,6 +898,48 @@ def testCheckinComment(self): if testDoc.isCheckedOut(): pwcDoc.delete() + def testCheckinContentAndProperties(self): + """Checkin a document with a new content a modifed properties""" + testFilename = settings.TEST_BINARY_1.split('/')[-1] + contentFile = open(testFilename, 'rb') + props = {'cmis:objectTypeId': settings.VERSIONABLE_TYPE_ID} + testDoc = self._testFolder.createDocument(testFilename, contentFile=contentFile, properties=props) + contentFile.close() + self.assertEquals(testFilename, testDoc.getName()) + if not 'canCheckOut' in testDoc.allowableActions.keys(): + print 'The test doc cannot be checked out...skipping' + return + pwcDoc = testDoc.checkout() + + try: + self.assertTrue(testDoc.isCheckedOut()) + testFile2 = settings.TEST_BINARY_2 + testFile2Size = os.path.getsize(testFile2) + exportFile2 = testFile2.replace('.', 'export.') + contentFile2 = open(testFile2, 'rb') + props = {'cmis:name': 'testDocument2'} + testDoc = pwcDoc.checkin( + contentFile=contentFile2, + properties=props) + contentFile2.close() + self.assertFalse(testDoc.isCheckedOut()) + self.assertEqual('testDocument2', testDoc.getName()) + + # expport the result + result = testDoc.getContentStream() + outfile = open(exportFile2, 'wb') + outfile.write(result.read()) + result.close() + outfile.close() + + # the file we exported should be the same size as the file we + # originally created + self.assertEquals(testFile2Size, os.path.getsize(exportFile2)) + + finally: + if testDoc.isCheckedOut(): + pwcDoc.delete() + def testCheckinAfterGetPWC(self): """Create a document in a test folder, check it out, call getPWC, then checkin""" if not self._repo.getCapabilities()['PWCUpdatable'] == True: {code} https://github.com/apache/chemistry-cmislib/pull/5 was: I've improved the checkin method to allow to update the content stream and the properties {code} diff --git a/src/cmislib/browser/binding.py b/src/cmislib/browser/binding.py index c9cc8a3..b340eda 100644 --- a/src/cmislib/browser/binding.py +++ b/src/cmislib/browser/binding.py @@ -1743,7 +1743,8 @@ class BrowserDocument(BrowserCmisObject): self.reload() return self.getProperties()['cmis:versionSeriesCheckedOutBy'] - def checkin(self, checkinComment=None, **kwargs): + def checkin(self, checkinComment=None, contentFile=None, contentType=None,ntStream - policies - addACEs - removeACEs """ - # TODO implement optional arguments - # major = true is supposed to be the default but inmemory 0.9 is throwing an error 500 without it if not kwargs.has_key('major'): kwargs['major'] = 'true' + else: + kwargs['major'] = 'false' + props = { + 'checkinComment': checkinComment, + } + props.update(kwargs) + propCount = 0 + properties = properties or {} + for key, value in properties.iteritems(): + props["propertyId[%s]" % propCount] = key + props["propertyValue[%s]" % propCount] = value + propCount += 1 - kwargs['checkinComment'] = checkinComment - - ciUrl = self._repository.getRootFolderUrl() + ciUrl = self._repository.getRootFolderUrl() + "?objectId=" + self.id + "&cmisaction=checkin" - # TODO don't hardcode major flag - props = {"objectId": self.id, - "cmisaction": "checkIn"} + contentType, body = encode_multipart_formdata(props, contentFile, contentType) # invoke the URL result = self._cmisClient.binding.post(ciUrl.encode('utf-8'), - urlencode(props), - 'application/x-www-form-urlencoded', + body, + contentType, self._cmisClient.username, - self._cmisClient.password, - **kwargs) + self._cmisClient.password) return getSpecializedObject(BrowserCmisObject(self._cmisClient, self._repository, data=result)) {code} https://github.com/lmignon/python-cmislib/commit/c1ff31b82c6768148e18e766a9cbc5d62bfb5b23?diff=unified > Implement contentStream and properties update in BrowserDocument.checkin > method > ------------------------------------------------------------------------------- > > Key: CMIS-972 > URL: https://issues.apache.org/jira/browse/CMIS-972 > Project: Chemistry > Issue Type: Improvement > Components: python-cmislib > Environment: Linux, python 2.7.x, Alfresco 5.0.x > Reporter: Laurent Mignon > Assignee: Jeff Potts > > I've improved the checkin method to allow to update the content stream and > the properties > {code} > From cbca562e4cfce685c2cc60ee2ad0d73182d3cb5f Mon Sep 17 00:00:00 2001 > From: Laurent Mignon <laurent.mig...@acsone.eu> > Date: Fri, 9 Sep 2016 18:53:05 +0200 > Subject: [PATCH] Support content and properties paramaters on method checkin > --- > src/cmislib/atompub/binding.py | 23 ++++++++++++++++------- > src/cmislib/browser/binding.py | 34 ++++++++++++++++++++-------------- > src/cmislib/domain.py | 9 +++------ > src/tests/cmislibtest.py | 42 > ++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 81 insertions(+), 27 deletions(-) > diff --git a/src/cmislib/atompub/binding.py b/src/cmislib/atompub/binding.py > index f1a629f..2eee222 100644 > --- a/src/cmislib/atompub/binding.py > +++ b/src/cmislib/atompub/binding.py > @@ -2362,7 +2362,8 @@ def getCheckedOutBy(self): > self.reload() > return self.getProperties()['cmis:versionSeriesCheckedOutBy'] > > - def checkin(self, checkinComment=None, **kwargs): > + def checkin(self, checkinComment=None, contentFile=None, > contentType=None, > + properties=None, **kwargs): > > """ > Checks in this :class:`Document` which must be a private > @@ -2378,10 +2379,7 @@ def checkin(self, checkinComment=None, **kwargs): > >>> doc.isCheckedOut() > False > > - The following optional arguments are supported: > - - major > - - properties > - - contentStream > + The following optional arguments are NOT supported: > - policies > - addACEs > - removeACEs > @@ -2395,8 +2393,19 @@ def checkin(self, checkinComment=None, **kwargs): > kwargs['checkin'] = 'true' > kwargs['checkinComment'] = checkinComment > > - # Build an empty ATOM entry > - entryXmlDoc = getEmptyXmlDoc() > + if not properties and not contentFile: > + # Build an empty ATOM entry > + entryXmlDoc = getEmptyXmlDoc() > + else: > + # the getEntryXmlDoc function may need the object type > + objectTypeId = None > + if self.properties.has_key('cmis:objectTypeId') and not > properties.has_key('cmis:objectTypeId'): > + objectTypeId = self.properties['cmis:objectTypeId'] > + self.logger.debug('This object type is:%s', objectTypeId) > + > + # build the entry based on the properties provided > + entryXmlDoc = getEntryXmlDoc( > + self._repository, objectTypeId, properties, contentFile, > contentType) > > # Get the self link > # Do a PUT of the empty ATOM to the self link > diff --git a/src/cmislib/browser/binding.py b/src/cmislib/browser/binding.py > index 7d7d758..c300e5e 100644 > --- a/src/cmislib/browser/binding.py > +++ b/src/cmislib/browser/binding.py > @@ -1755,7 +1755,8 @@ def getCheckedOutBy(self): > self.reload() > return self.getProperties()['cmis:versionSeriesCheckedOutBy'] > > - def checkin(self, checkinComment=None, **kwargs): > + def checkin(self, checkinComment=None, contentFile=None, > contentType=None, > + properties=None, **kwargs): > > """ > Checks in this :class:`Document` which must be a private > @@ -1772,9 +1773,6 @@ def checkin(self, checkinComment=None, **kwargs): > False > > The following optional arguments are NOT supported: > - - major > - - properties > - - contentStream > - policies > - addACEs > - removeACEs > @@ -1784,21 +1782,29 @@ def checkin(self, checkinComment=None, **kwargs): > if not kwargs.has_key('major'): > kwargs['major'] = 'true' > > - kwargs['checkinComment'] = checkinComment > - > - ciUrl = self._repository.getRootFolderUrl() > + else: > + kwargs['major'] = 'false' > + props = { > + 'checkinComment': checkinComment or "", > + } > + props.update(kwargs) > + propCount = 0 > + properties = properties or {} > + for key, value in properties.iteritems(): > + props["propertyId[%s]" % propCount] = key > + props["propertyValue[%s]" % propCount] = value > + propCount += 1 > + > + ciUrl = self._repository.getRootFolderUrl() + "?objectId=" + self.id > + "&cmisaction=checkin" > > - # TODO don't hardcode major flag > - props = {"objectId": self.id, > - "cmisaction": "checkIn"} > + contentType, body = encode_multipart_formdata(props, contentFile, > contentType) > > # invoke the URL > result = self._cmisClient.binding.post(ciUrl.encode('utf-8'), > - safe_urlencode(props), > - > 'application/x-www-form-urlencoded', > + body, > + contentType, > self._cmisClient.username, > - self._cmisClient.password, > - **kwargs) > + self._cmisClient.password) > > return getSpecializedObject(BrowserCmisObject(self._cmisClient, > self._repository, data=result)) > > diff --git a/src/cmislib/domain.py b/src/cmislib/domain.py > index a2f7a25..3b4175c 100644 > --- a/src/cmislib/domain.py > +++ b/src/cmislib/domain.py > @@ -1240,7 +1240,8 @@ def getCheckedOutBy(self): > > pass > > - def checkin(self, checkinComment=None, **kwargs): > + def checkin(self, checkinComment=None, contentFile=None, > contentType=None, > + properties=None, **kwargs): > > """ > Checks in this :class:`Document` which must be a private > @@ -1256,15 +1257,11 @@ def checkin(self, checkinComment=None, **kwargs): > >>> doc.isCheckedOut() > False > > - The following optional arguments are supported: > - - major > - - properties > - - contentStream > + The following optional arguments are NOT supported: > - policies > - addACEs > - removeACEs > """ > - > pass > > def getLatestVersion(self, **kwargs): > diff --git a/src/tests/cmislibtest.py b/src/tests/cmislibtest.py > index a81be56..4ad13a4 100644 > --- a/src/tests/cmislibtest.py > +++ b/src/tests/cmislibtest.py > @@ -898,6 +898,48 @@ def testCheckinComment(self): > if testDoc.isCheckedOut(): > pwcDoc.delete() > > + def testCheckinContentAndProperties(self): > + """Checkin a document with a new content a modifed properties""" > + testFilename = settings.TEST_BINARY_1.split('/')[-1] > + contentFile = open(testFilename, 'rb') > + props = {'cmis:objectTypeId': settings.VERSIONABLE_TYPE_ID} > + testDoc = self._testFolder.createDocument(testFilename, > contentFile=contentFile, properties=props) > + contentFile.close() > + self.assertEquals(testFilename, testDoc.getName()) > + if not 'canCheckOut' in testDoc.allowableActions.keys(): > + print 'The test doc cannot be checked out...skipping' > + return > + pwcDoc = testDoc.checkout() > + > + try: > + self.assertTrue(testDoc.isCheckedOut()) > + testFile2 = settings.TEST_BINARY_2 > + testFile2Size = os.path.getsize(testFile2) > + exportFile2 = testFile2.replace('.', 'export.') > + contentFile2 = open(testFile2, 'rb') > + props = {'cmis:name': 'testDocument2'} > + testDoc = pwcDoc.checkin( > + contentFile=contentFile2, > + properties=props) > + contentFile2.close() > + self.assertFalse(testDoc.isCheckedOut()) > + self.assertEqual('testDocument2', testDoc.getName()) > + > + # expport the result > + result = testDoc.getContentStream() > + outfile = open(exportFile2, 'wb') > + outfile.write(result.read()) > + result.close() > + outfile.close() > + > + # the file we exported should be the same size as the file we > + # originally created > + self.assertEquals(testFile2Size, os.path.getsize(exportFile2)) > + > + finally: > + if testDoc.isCheckedOut(): > + pwcDoc.delete() > + > def testCheckinAfterGetPWC(self): > """Create a document in a test folder, check it out, call getPWC, > then checkin""" > if not self._repo.getCapabilities()['PWCUpdatable'] == True: > {code} > https://github.com/apache/chemistry-cmislib/pull/5 -- This message was sent by Atlassian JIRA (v6.3.4#6332)