Ivan Markeyev avatar Ivan Markeyev committed 742565d Draft

+setup script

Comments (0)

Files changed (7)

py4shared/__init__.py

+__author__ = 'markeyev'

py4shared/soap.py

+# -*- coding: utf-8 -*-
+
+__doc__ = """4Shared SOAP API wrapper."""
+
+from suds.client import Client
+from suds import WebFault
+
+
+BASE_URL = 'https://api.4shared.com/jax3/DesktopApp?wsdl'
+
+
+class SOAP4Shared(object):
+    service = Client(BASE_URL).service
+
+    def __init__(self, login, password):
+        self._login = login
+        self._password = password
+
+    # Account
+    def signup(self):
+        '''Creates new User and sends confirmation email.
+        Returns: error message if any. None if all ok.'''
+        return self.service.signup(self._login, self._password)
+
+    def signupUsername(self, username):
+        '''Creates new User with specified login(email), short username for
+        easing login and password and sends confirmation email.'''
+        try:
+            return self.service.signupUsername(self._login, self._password,
+                                               username)
+        except WebFault, e:
+            return str(e)
+
+    def login(self):
+        '''None if all ok, diagnostic message otherwise.'''
+        try:
+            return self.service.login(self._login, self._password)
+        except WebFault, e:
+            return str(e)
+
+    def isAccountActive(self):
+        '''Checks account availability.
+        Returns: true if account is active.'''
+        return self.service.isAccountActive(self._login, self._password)
+
+    def isAccountPremium(self):
+        '''Checks if user account is premium.
+        Returns: true of user has premium account.'''
+        return self.service.isAccountPremium(self._login, self._password)
+
+    def isAccountBanned(self):
+        '''Checks if user account is banned.
+        Returns: true if user accont is banned.'''
+        return self.service.isAccountBanned(self._login, self._password)
+
+    def isExistsLoginPassword(self):
+        '''True/False version of login.
+        Returns: True if login was successful.'''
+        try:
+            return self.service.isExistsLoginPassword(self._login,
+                self._password)
+        except WebFault, e:
+            return str(e)
+
+    # Upload
+    def hasRightUpload(self):
+        '''Whether upload feature is on.'''
+        return self.service.hasRightUpload(self._login, self._password)
+
+    def getMaxFileSize(self):
+        '''Maximum allowed file size in bytes.'''
+        return self.service.getMaxFileSize(self._login, self._password)
+
+    def getFreeSpace(self):
+        '''Free space left for user in bytes.'''
+        return self.service.getFreeSpace(self._login, self._password)
+
+    def getSpaceLimit(self):
+        '''Returns user space limit in bytes.'''
+        return self.service.getSpaceLimit(self._login, self._password)
+
+    def getUploadFormUrl(self, dataCenterID, sessionKey):
+        '''Returns url to upload file to.'''
+        return self.service.getUploadFormUrl(dataCenterID, sessionKey)
+
+    def getNewFileDataCenter(self):
+        '''Returns: datacenter id to upload new files to.'''
+        return self.service.getNewFileDataCenter(self._login, self._password)
+
+    def createUploadSessionKey(self, dirId):
+        '''Creates session key for uploading file.
+        Returns: session key.'''
+        return self.service.createUploadSessionKey(self._login, self._password,
+            dirId)
+
+    def uploadStartFile(self, dirId, name, fullSize):
+        '''Resumable upload - start.
+        Parameters: dirId - (-1) means upload to user's root dir
+        Returns: fileId to pass as parameter in all subsequent partial
+        uploads.'''
+        return self.service.uploadStartFile(self._login, self._password, dirId,
+            name, fullSize)
+
+    def uploadStartFileUpdate(self, updateFileId, name, fullSize):
+        '''Update file.
+        Parameters:
+         - updateFileId - it of original file to be updated
+         - name - empty string means don't change existing name
+         - fullSize -
+        Returns: id of temporary file uploading of which will cause update of
+        original file.'''
+        return self.service.uploadStartFileUpdate(self._login, self._password,
+            updateFileId, name, fullSize)
+
+    def uploadStartedFileExists(self, fileId):
+        '''Checks if file was partially uploaded.
+        fileId - id of file to be checked
+        Returns: true if there is part of file already uploaded.'''
+        return self.service.uploadStartedFileExists(self._login,
+            self._password, fileId)
+
+    def uploadCancelFile(self, fileId):
+        '''Call if upload was canceled.'''
+        return self.service.uploadCancelFile(self._login, self._password,
+            fileId)
+
+    def uploadFinishFile(self, fileId, md5):
+        '''Complete resumable upload.
+        fileId - returned from initial call to uploadStartFile() - existing
+                 file in 'being uploaded by parts' state.
+        md5 - original file MD5 to verify file consistency at server side.
+        Returns: empty string if success or error message.'''
+        return self.service.uploadFinishFile(self._login, self._password,
+            fileId, md5)
+
+    # File
+    def getFiles(self, fileIds=None):
+        '''Returns account items for file ids.'''
+        return self.service.getFiles(self._login, self._password,
+            fileIds)
+
+    def setFileDescription(self, fileId, title, tags, newDescription,
+                           setAsDefault, applyToAll):
+        '''Sets file title, tags and description for dedicated file or account
+        as a whole.'''
+        return self.service.setFileDescription(self._login,
+            self._password, fileId, title, tags, newDescription, setAsDefault,
+            applyToAll)
+
+    def getFileDescription(self, fileId):
+        '''Returns file title, tags and description if any.'''
+        return self.service.getFileDescription(self._login, self._password,
+            fileId)
+
+    def renameFile(self, fileId, newName):
+        '''Renames specified file.
+        Returns:
+            -1 if file exists,
+            0 in case of other failures,
+            fileId if rename was successful'''
+        return self.service.renameFile(self._login, self._password, fileId,
+            newName)
+
+    def deleteFile(self, fileId):
+        '''Removes file to recycle bin or from recycle bin if it is already
+        there.'''
+        return self.service.deleteFile(self._login, self._password, fileId)
+
+    def deleteFileFinal(self, fileId):
+        '''Remove file once and for all.'''
+        return self.service.deleteFileFinal(self._login, self._password, fileId)
+
+    def restoreFile(self, fileId):
+        '''Restores file from Recycle Bin. If folder still exists restores
+        to it, in other cases will restore to special RESTORED FILES folder
+        which will be created if not already exists.'''
+        return self.service.restoreFile(self._login, self._password,
+            fileId)
+
+    def restoreFiles(self, fileIds):
+        '''Restores group of files from Recycle Bin. If folder still exists
+        restores to it, in other cases will restore to special RESTORED FILES
+        folder which will be created if not already exists.
+        fileIds - Array of file ids to be restored.'''
+        return self.service.restoreFiles(self._login, self._password, fileIds)
+
+    def getFileInfo(self, fileIds):
+        '''Returns info about file.'''
+        return self.service.getFileInfo(self._login, self._password, fileIds)
+
+    def getExifFileInf(self, fileLink):
+        '''Return image info for specified file link if any.'''
+        return self.service.getExifFileInf(self._login, self._password,
+            fileLink)
+
+    def getExifFileInfos(self, dirId):
+        '''Returns @see ExifInfo for all image files in specified folder.'''
+        return self.service.getExifFileInfos(self._login, self._password, dirId)
+
+    def getMp3FileInfo(self, fileLink):
+        '''Return audio info for specified file link if any.'''
+        return self.service.getMp3FileInfo(self._login, self._password,
+            fileLink)
+
+    def getMp3FileInfos(self, dirId):
+        '''Returns audio info for all audio files in folder.'''
+        return self.service.getMp3FileInfos(self._login, self._password, dirId)
+
+    def getPreviewLink(self, fileId):
+        '''Return link to small preview image, or to flv preview for video
+        files.'''
+        return self.service.getPreviewLink(self._login, self._password, fileId)
+
+    def getVideoPreviewLink(self, fileId):
+        '''Return link to video preview.'''
+        return self.service.getVideoPreviewLink(self._login, self._password,
+            fileId)
+
+    # Folder
+    def createNewFolder(self, dirId, folderName):
+        '''Creates new folder as dirId subfolder.
+        dirId - id of the directory to create folder in.
+        folderName - new folder name.
+        Returns:
+            0 - if creation denied, newly created dir ID otherwise
+            -1 - already exists
+            -2 - attempt to create folder in removed parent'''
+        return self.service.createNewFolder(self._login, self._password, dirId,
+            folderName)
+
+    def setDirDescription(self, dirId, newDescription, setAsDefault,
+                          applyToAll):
+        '''Sets folder description for dedicated folder or account as a whole.
+        '''
+        return self.service.setDirDescription(self._login,
+            self._password, dirId, newDescription, setAsDefault, applyToAll)
+
+    def getDirDescription(self, dirId):
+        '''Returns folder description.'''
+        return self.service.getDirDescription(self._login, self._password,
+            dirId)
+
+    def renameFolder(self, dirId, newName):
+        '''Renames specified folder.
+        dirID - id of folder to be name
+        newName - new name of folder.
+        Returns:
+            -1 if file exists,
+            0 in case of other failures,
+            dirId if rename was successful'''
+        return self.service.renameFolder(self._login, self._password, dirId,
+            newName)
+
+    def deleteFolder(self, dirId):
+        '''Completely removes folder and puts all of it contents to recycle
+        bin.'''
+        return self.service.deleteFolder(self._login, self._password, dirId)
+
+    def deleteFolderFinal(self, dirId):
+        '''Removes files and subfolders from recycle bin.'''
+        return self.service.deleteFolderFinal(self._login, self._password,
+            dirId)
+
+    def emptyRecycleBin(self, dirId):
+        '''Empties recycle bean for specified user.'''
+        return self.service.emptyRecycleBin(self._login, self._password, dirId)
+
+    def getDirInfo(self, dirId):
+        '''Return info about specified folder.'''
+        return self.service.getDirInfo(self._login, self._password, dirId)
+
+    def getRoot(self):
+        '''Returns account item for user's root directory.'''
+        return self.service.getRoot(self._login, self._password)
+
+    def getAllFolders(self):
+        '''Returns all of the folders in user's root directory.
+        Returns: Array of info records about user's root folder subfolders.'''
+        return self.service.getAllFolders(self._login, self._password)
+
+    def getHistory(self, dirId):
+        '''Returns history of operations in specified folder and subfolders.
+        For operation field meanings see getOperationDescriptions().
+        Returns: Array of folder changes. May be null or empty.'''
+        return self.service.getHistory(self._login, self._password, dirId)
+
+    def getHistoryFromId(self, dirId, fromId):
+        '''Returns history of operations which occurs in specified folder and
+        subfolders with history id more then specified. For operation field
+        meanings see getOperationDescriptions().
+        dirId - id of folder to take history for
+        fromId - id floor of history
+        Returns: Array of folder changes. May be null or empty.'''
+        return self.service.getHistoryFromId(self._login, self._password, dirId,
+            fromId)
+
+    def markSynchronized(self, dirId):
+        '''Informs 4shared to write folder and subfolders usage history.'''
+        return self.service.markSynchronized(self._login, self._password, dirId)
+
+    def getOperationDescriptions(self):
+        '''Returns array of OperationEnum names. Array index corresponds to
+        values which can be returned as DirHistoryDTO.getOperation(). Array is
+        supposed to be zero-based.
+        Returns: array of OperationEnum names.'''
+        return self.service.getOperationDescriptions()
+
+    #Items (Files or folders)
+    def getItemInfo(self, itemId, dir):
+        '''Common method for getFileInfo(String, String, long) and
+        getDirInfo(String, String, long) distinguished by value of dir
+        parameter.
+        itemId - id of element
+        dir - if true then supplied Id is folder and file otherwise
+        '''
+        return self.service.getItemInfo(self._login, self._password, itemId,
+            dir)
+
+    def getItems(self, dirId):
+        '''Returns array of infos about contents of specified dir.
+        dirId - id of folder to list (-1 for root).'''
+        return self.service.getItems(self._login, self._password, dirId)
+
+    def getAllItems(self):
+        '''Returns info about all items in user's root folder.
+        Returns: Array of info records about user's root folder content.'''
+        return self.service.getAllItems(self._login, self._password)
+
+    def getItemsPartial(self, dirId, startIndex, count):
+        '''Get specified count folders' items ordered by name, folders first
+        starting from startIndex.'''
+        return self.service.getItemsPartial(self._login, self._password, dirId,
+            startIndex, count)
+
+    def getItemsCount(self, dirId):
+        '''Returns item count for dirId (-1 for root folder).'''
+        return self.service.getItemsCount(self._login, self._password, dirId)
+
+    def getSharedDirItems(self, dirId, dirPassword, userDirPassword):
+        '''Return content of possibly not owned shared folder.
+        dirId - id of folder to view
+        dirPassword - 4shared generated dir password
+        userDirPassword - user set dir password if needed.
+        Returns: content of specified shared folder or null.'''
+        return self.service.getSharedDirItems(self._login, self._password,
+            dirId, dirPassword, userDirPassword)
+
+    def getRecycleBinItems(self):
+        '''Returns info about files in recycle bin.'''
+        return self.service.getRecycleBinItems(self._login, self._password)
+
+    def pasteFilesDirs(self, toFolderId, makeCopy, fileIds, dirIds):
+        '''Copy-pastes or cut-pastes a group of files and dirs. Use this to
+        copy or move a group of files to another directory.
+        toFolderId - target folder id
+        makeCopy - - exec copy+paste if true, exec cut+paste if false
+        fileIds - ids of file to be moved/copied
+        dirIds - ids of folders to be moved/copied.
+        Returns: diagnostic message or empty string if all ok.'''
+        return self.service.pasteFilesDirs(self._login, self._password,
+            toFolderId, makeCopy, fileIds, dirIds)
+
+    def decodeId(self, encodedId):
+        '''Turns new encoded folder id into form id+"/"+4shared_password for
+        shared folder browsing encoded folder id can be found as 8-symbol group
+        of folder url right after /dir/ regexp:
+        http://www.4shared.com/dir/(.{8,8})/.*'''
+        return self.service.decodeId(self._login, self._password, encodedId)
+
+    def decodeLink(self, link):
+        '''Used to get item id from item link.'''
+        return self.service.decodeLink(self._login, self._password, link)
+
+    # Download
+    def getDirectLink(self, link):
+        '''Returns link to start immediate downloading. Not always possible
+        however, because we are ads-supported mostly. Returns link starting
+        with "http" if ok.'''
+        return self.service.getDirectLink(self._login, self._password, link)
+
+    def getFileDownloadLink(self, fileId):
+        '''Returns download link for user owned file. Download link or empty
+        string if some errors occurs.'''
+        return self.service.getFileDownloadLink(self._login, self._password,
+            fileId)
+
+    def downloadFinished(self, fileId):
+        '''Have to be called after full file download.
+        fileId - id of the file which was downloaded'''
+        return self.service.downloadFinished(self._login, self._password,
+            fileId)
+
+    def getNotOwnedSizeLimit(self):
+        '''Max file size which can be downloaded without speed limit.'''
+        return self.service.getNotOwnedSizeLimit(self._login, self._password)
+
+    # Share
+    def addToFavorites(self, fileId):
+        '''Adds file to user favorites.'''
+        return self.service.addToFavorites(self._login, self._password, fileId)
+
+    def removeFromFavorites(self, fileId):
+        return self.service.removeFromFavorites(self._login, self._password,
+            fileId)
+
+    def getFavorites(self):
+        '''Returns user favored files.'''
+        return self.service.getFavorites(self._login, self._password)
+
+    def addToMyAccount(self, dirId, link):
+        '''Adds file or folder identified by supplied link to user's account in
+        folder identified by dirId.'''
+        return self.service.addToMyAccount(self._login, self._password, dirId,
+            link)
+
+    def checkSubdomain(self, dirId, subdomainName):
+        '''Checks if subdomain can be set for specified folder.
+        dirId - id of the directory
+        subdomainName - name to be set
+        Returns: Empty string or null if everything is ok and error message
+        otherwise.'''
+        return self.service.checkSubdomain(self._login, self._password, dirId,
+            subdomainName)
+
+    def checkSharedDirAccess(self, dirId, dirPassword, userDirPassword):
+        '''Checks if directory can be accessed by specified user with specified
+        passwords.
+        dirId - id of the directory to be accessed
+        dirPassword - generated password to view contents of not owned folders
+        userDirPassword - user specified password
+        Returns:status.
+            0 ok
+            1 no such dir
+            2 owner inactive
+            3 abused dir
+            4 incorrect dirPassword
+            5 dir is not shared
+            6 owner is banned
+            8 incorrect userDirPassword'''
+        return self.service.checkSharedDirAccess(self._login, self._password,
+            dirId, dirPassword, userDirPassword)
+
+    def setFolderSharingProperties(self, dirId, folderProperties):
+        '''dirId - id of folder to set properties for
+        folderProperties - new properties values
+        Returns: Diagnostic message or empty string if all is ok.'''
+        return self.service.setFolderSharingProperties(self._login,
+            self._password, dirId, folderProperties)
+
+    def getFolderSharingProperties(self, dirId):
+        '''Returns folder sharing properties. Output is two element array:
+        res[0] - actual values.
+        res[1] - properties which can be set for this user is marked as true.'''
+        return self.service.getFolderSharingProperties(self._login,
+            self._password, dirId)
+
+    # Misc
+    def getCurrentUploaderVersion(self):
+        '''Returns last uploader version. If this increase you should consider
+        to look at online api documentation to check changes. We will try to
+        maintain backward compatibility but this is not guaranteed.
+        Returns: Uploader version.'''
+        return self.service.getCurrentUploaderVersion(self._login,
+            self._password)
+
+    def syncFinished(self, fileId):
+        '''Should be called in the end of each sync operation.
+        fileId - which file was synced. -1 if not applicable.'''
+        return self.service.syncFinished(self._login, self._password, fileId)

py4shared/soap_tests.py

+import os
+import hashlib
+import logging
+import logging.handlers
+from random import randint
+import requests
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
+from py4shared.soap import SOAP4Shared
+
+
+LOG_FILENAME = 'py4shared.log'
+logger = logging.getLogger('suds.client')
+logger.setLevel(logging.DEBUG)
+handler = logging.handlers.WatchedFileHandler(LOG_FILENAME)
+logger.addHandler(handler)
+
+
+def md5sum(fileName):
+    """Compute md5 hash of the specified file"""
+    m = hashlib.md5()
+    try:
+        fd = open(fileName,"rb")
+    except IOError:
+        print "Unable to open the file in readmode:", fileName
+        return
+    content = fd.readlines()
+    fd.close()
+    for eachLine in content:
+        m.update(eachLine)
+    return m.hexdigest()
+
+class SOAP4SharedTestCase(unittest.TestCase):
+    def setUp(self):
+        # Using per user configuration dictionary:
+        self.params = {
+            'user1': {
+                'login': 'a307@mail.ru',
+                'password': '6Nn590Ad'
+            },
+            'user2': {
+                'login': 'ivanov@mail.ru',
+                'password': 'Easwwerf'
+            }
+        }
+
+        # Using per user api wrapper instance:
+        self.soapapi1 = SOAP4Shared(self.params['user1']['login'],
+                                    self.params['user1']['password'])
+        self.soapapi2 = SOAP4Shared(self.params['user2']['login'],
+                                    self.params['user2']['password'])
+
+        # Initializing per user upload params
+
+
+    def test_001_accounts(self):
+        # New user test
+        self.params['user3'] = {
+            'login': 'a%d@mail.ru' % randint(0, 999),
+            'password': '6Nn%dAd' % randint(0, 999)
+        }
+
+        logger.info('Create user with login "%s" and password "%s" ' % \
+                    (self.params['user3']['login'],
+                     self.params['user3']['password']))
+        self.soapapi3 = SOAP4Shared(self.params['user3']['login'],
+                                    self.params['user3']['password'])
+        if self.soapapi3.isExistsLoginPassword() is True:
+            self.assertEqual(self.soapapi3.isExistsLoginPassword(),
+                "Server raised fault: 'The Login and/or Password did not \
+match our records'")
+        else:
+            self.assertEqual(self.soapapi3.signup(), None)
+            # FIXME: Turn me on:
+            self.assertEqual(self.soapapi3.\
+                        signupUsername(self.params['user3']['login']), None)
+            self.assertEqual(self.soapapi3.login(), None)
+            self.assertTrue(self.soapapi3.isAccountActive())
+            self.assertFalse(self.soapapi3.isAccountPremium())
+            self.assertFalse(self.soapapi3.isAccountBanned())
+
+        # Test existing user.
+        self.assertEqual(self.soapapi1.login(), None)
+        self.assertTrue(self.soapapi1.isExistsLoginPassword())
+        self.assertTrue(self.soapapi1.isAccountActive())
+        self.assertFalse(self.soapapi1.isAccountPremium())
+        self.assertFalse(self.soapapi1.isAccountBanned())
+
+        # Test non existing user.
+        self.assertEqual(self.soapapi2.login(), "Server raised fault: \
+'The Login and/or Password did not match our records'")
+
+    def test_002_uploads(self):
+        # hasRightUpload
+        self.assertTrue(self.soapapi1.hasRightUpload())
+
+        # getMaxFileSize - what is upload limit for user (per file)
+        self.assertGreaterEqual(self.soapapi1.getMaxFileSize(), 2147483648)
+
+        # getFreeSpace - check if you have enough free space in user account
+        self.assertLessEqual(self.soapapi1.getFreeSpace(), 16106127360)
+
+        # getSpaceLimit
+        self.assertLessEqual(self.soapapi1.getSpaceLimit(), 16106127360)
+
+        # getNewFileDataCenter
+        dataCenterID = self.soapapi1.getNewFileDataCenter()
+        # dirID - (-1) means upload to user's root dir
+
+        # createUploadSessionKey
+        sessionKey = self.soapapi1.createUploadSessionKey(-1)
+        # getUploadFormUrl - get URL for upload using session and datacenter
+        uploadUrl = self.soapapi1.getUploadFormUrl(dataCenterID, sessionKey)
+        # Returned string is only valid if it starts with http
+        self.assertTrue(uploadUrl.startswith('http://'))
+
+        # uploadStartFile
+        filename = 'requirements.pip'
+        f = open(filename)
+        uploadFileId =  self.soapapi1.uploadStartFile(-1, filename,
+                                          os.path.getsize(filename))
+        # dirID - (-1) means upload to user's root dir
+        self.assertGreater(uploadFileId, 0)
+
+        # TODO: uploadStartFileUpdate
+
+        # UPLOAD FILE
+        response = requests.post(uploadUrl, files={filename: f})
+        self.assertEqual(response.status_code, requests.codes.ok)
+
+        # uploadStartedFileExists
+        self.assertTrue(self.soapapi1.uploadStartedFileExists(uploadFileId))
+
+        # TODO: uploadCancelFile
+
+        # FIXME: uploadFinishFile
+        self.assertEqual(self.soapapi1.uploadFinishFile(uploadFileId,
+                                                        md5sum(filename)), '')
+        f.close()
+
+    def test_003_files(self):
+        # TODO: getFiles
+        # TODO: setFileDescription
+        # TODO: getFileDescription
+        # TODO: renameFile
+        # TODO: deleteFile
+        # TODO: deleteFileFinal
+        # TODO: restoreFile
+        # TODO: restoreFiles
+        # TODO: getFileInfo
+        # TODO: getExifFileInf
+        # TODO: getExifFileInfos
+        # TODO: getMp3FileInfo
+        # TODO: getMp3FileInfos
+        # TODO: getPreviewLink
+        # TODO: getVideoPreviewLink
+        pass
+
+    def test_004_folders(self):
+        # TODO: createNewFolder
+        # TODO: setDirDescription
+        # TODO: getDirDescription
+        # TODO: renameFolder
+        # TODO: deleteFolder
+        # TODO: deleteFolderFinal
+        # TODO: emptyRecycleBin
+        # TODO: getRoot
+        # TODO: getAllFolders
+        # TODO: getHistory
+        # TODO: getHistoryFromId
+        # TODO: markSynchronized
+        # TODO: getOperationDescriptions
+        pass
+
+    def test_005_items(self):
+        # TODO: getItemInfo
+        # TODO: getItems
+        # TODO: getAllItems
+        # TODO: getItemsPartial
+        # TODO: getItemsCount
+        # TODO: getSharedDirItems
+        # TODO: getRecycleBinItems
+        # TODO: pasteFilesDirs
+        # TODO: decodeId
+        # TODO: decodeLink
+        pass
+
+    def test_006_downloads(self):
+        # TODO: getDirectLink
+        # TODO: getFileDownloadLink
+        # TODO: downloadFinished
+        # TODO: getNotOwnedSizeLimit
+        pass
+
+    def test_007_shares(self):
+        # TODO: addToFavorites
+        # TODO: removeFromFavorites
+        # TODO: getFavorites
+        # TODO: addToMyAccount
+        # TODO: checkSubdomain
+        # TODO: checkSharedDirAccess
+        # TODO: setFolderSharingProperties
+        # TODO: getFolderSharingProperties
+        pass
+
+    def test_008_miscs(self):
+        # TODO: getCurrentUploaderVersion
+        # TODO: syncFinished
+        pass
+
+if __name__ == '__main__':
+    unittest.main()
 suds==0.4
+requests==0.13.1
 #/usr/bin/env python
-from setuptools import setup, find_packages
- 
+from setuptools import setup
+
+
 setup(
     name='py4shared',
     version='0.0.1',
     author='Ivan Markeyev',
     author_email='markeev@gmail.com',
     url='http://bitbucket.org/markeyev/py4shared/',
-    packages=find_packages(),
+    packages=['py4shared'],
     classifiers=[
         'Development Status :: 1 - Alpha',
         'Environment :: Web Environment',
         'Operating System :: OS Independent',
         'Programming Language :: Python'
     ],
-    include_package_data=True,
+    include_package_data=False,
     zip_safe=False,
-    setup_requires=['setuptools_hg']
+    setup_requires=['setuptools_hg', 'suds']
 )

soap.py

-# -*- coding: utf-8 -*-
-
-__doc__ = """4Shared SOAP API wrapper."""
-
-from suds.client import Client
-from suds import WebFault
-
-
-BASE_URL = 'https://api.4shared.com/jax3/DesktopApp?wsdl'
-
-
-class SOAP4Shared(object):
-    service = Client(BASE_URL).service
-
-    def __init__(self, login, password):
-        self._login = login
-        self._password = password
-
-    # Account
-    def signup(self):
-        '''Creates new User and sends confirmation email.
-        Returns: error message if any. None if all ok.'''
-        return self.service.signup(self._login, self._password)
-
-    def signupUsername(self, username):
-        '''Creates new User with specified login(email), short username for
-        easing login and password and sends confirmation email.'''
-        return self.service.signupUsername(self._login, self._password,
-            username)
-
-    def login(self):
-        '''None if all ok, diagnostic message otherwise.'''
-        try:
-            return self.service.login(self._login, self._password)
-        except WebFault, e:
-            return str(e)
-
-    def isAccountActive(self):
-        '''Checks account availability.
-        Returns: true if account is active.'''
-        return self.service.isAccountActive(self._login, self._password)
-
-    def isAccountPremium(self):
-        '''Checks if user account is premium.
-        Returns: true of user has premium account.'''
-        return self.service.isAccountPremium(self._login, self._password)
-
-    def isAccountBanned(self):
-        '''Checks if user account is banned.
-        Returns: true if user accont is banned.'''
-        return self.service.isAccountBanned(self._login, self._password)
-
-    def isExistsLoginPassword(self):
-        '''True/False version of login.
-        Returns: True if login was successful.'''
-        try:
-            return self.service.isExistsLoginPassword(self._login,
-                self._password)
-        except WebFault, e:
-            return str(e)
-
-    # Upload
-    def hasRightUpload(self):
-        '''Whether upload feature is on.'''
-        return self.service.hasRightUpload(self._login, self._password)
-
-    def getMaxFileSize(self):
-        '''Maximum allowed file size in bytes.'''
-        return self.service.getMaxFileSize(self._login, self._password)
-
-    def getFreeSpace(self):
-        '''Free space left for user in bytes.'''
-        return self.service.getFreeSpace(self._login, self._password)
-
-    def getSpaceLimit(self):
-        '''Returns user space limit in bytes.'''
-        return self.service.getSpaceLimit(self._login, self._password)
-
-    def getUploadFormUrl(self, dataCenterID, sessionKey):
-        '''Returns url to upload file to.'''
-        return self.service.getUploadFormUrl(dataCenterID, sessionKey)
-
-    def getNewFileDataCenter(self):
-        '''Returns: datacenter id to upload new files to.'''
-        return self.service.getNewFileDataCenter(self._login, self._password)
-
-    def createUploadSessionKey(self, dirId):
-        '''Creates session key for uploading file.
-        Returns: session key.'''
-        return self.service.createUploadSessionKey(self._login, self._password,
-            dirId)
-
-    def uploadStartFile(self, dirId, fullSize):
-        '''Resumable upload - start.
-        Parameters: dirId - (-1) means upload to user's root dir
-        Returns: fileId to pass as parameter in all subsequent partial
-        uploads.'''
-        return self.service.uploadStartFile(self._login, self._password, dirId,
-            fullSize)
-
-    def uploadStartFileUpdate(self, updateFileId, name, fullSize):
-        '''Update file.
-        Parameters:
-         - updateFileId - it of original file to be updated
-         - name - empty string means don't change existing name
-         - fullSize -
-        Returns: id of temporary file uploading of which will cause update of
-        original file.'''
-        return self.service.uploadStartFileUpdate(self._login, self._password,
-            updateFileId, name, fullSize)
-
-    def uploadStartedFileExists(self, fileId):
-        '''Checks if file was partially uploaded.
-        fileId - id of file to be checked
-        Returns: true if there is part of file already uploaded.'''
-        return self.service.uploadStartedFileExists(self._login,
-            self._password, fileId)
-
-    def uploadCancelFile(self, fileId):
-        '''Call if upload was canceled.'''
-        return self.service.uploadCancelFile(self._login, self._password,
-            fileId)
-
-    def uploadFinishFile(self, fileId, md5):
-        '''Complete resumable upload.
-        fileId - returned from initial call to uploadStartFile() - existing
-                 file in 'being uploaded by parts' state.
-        md5 - original file MD5 to verify file consistency at server side.
-        Returns: empty string if success or error message.'''
-        return self.service.uploadFinishFile(self._login, self._password,
-            fileId, md5)
-
-    # File
-    def getFiles(self, fileIds):
-        '''Returns account items for file ids.'''
-        return self.service.getFiles(self._login, self._password,
-            fileIds)
-
-    def setFileDescription(self, fileId, title, tags, newDescription,
-                           setAsDefault, applyToAll):
-        '''Sets file title, tags and description for dedicated file or account
-        as a whole.'''
-        return self.service.setFileDescription(self._login,
-            self._password, fileId, title, tags, newDescription, setAsDefault,
-            applyToAll)
-
-    def getFileDescription(self, fileId):
-        '''Returns file title, tags and description if any.'''
-        return self.service.getFileDescription(self._login, self._password,
-            fileId)
-
-    def renameFile(self, fileId, newName):
-        '''Renames specified file.
-        Returns:
-            -1 if file exists,
-            0 in case of other failures,
-            fileId if rename was successful'''
-        return self.service.renameFile(self._login, self._password, fileId,
-            newName)
-
-    def deleteFile(self, fileId):
-        '''Removes file to recycle bin or from recycle bin if it is already
-        there.'''
-        return self.service.deleteFile(self._login, self._password, fileId)
-
-    def deleteFileFinal(self, fileId):
-        '''Remove file once and for all.'''
-        return self.service.deleteFileFinal(self._login, self._password, fileId)
-
-    def restoreFile(self, fileId):
-        '''Restores file from Recycle Bin. If folder still exists restores
-        to it, in other cases will restore to special RESTORED FILES folder
-        which will be created if not already exists.'''
-        return self.service.restoreFile(self._login, self._password,
-            fileId)
-
-    def restoreFiles(self, fileIds):
-        '''Restores group of files from Recycle Bin. If folder still exists
-        restores to it, in other cases will restore to special RESTORED FILES
-        folder which will be created if not already exists.
-        fileIds - Array of file ids to be restored.'''
-        return self.service.restoreFiles(self._login, self._password, fileIds)
-
-    def getFileInfo(self, fileIds):
-        '''Returns info about file.'''
-        return self.service.getFileInfo(self._login, self._password, fileIds)
-
-    def getExifFileInf(self, fileLink):
-        '''Return image info for specified file link if any.'''
-        return self.service.getExifFileInf(self._login, self._password,
-            fileLink)
-
-    def getExifFileInfos(self, dirId):
-        '''Returns @see ExifInfo for all image files in specified folder.'''
-        return self.service.getExifFileInfos(self._login, self._password, dirId)
-
-    def getMp3FileInfo(self, fileLink):
-        '''Return audio info for specified file link if any.'''
-        return self.service.getMp3FileInfo(self._login, self._password,
-            fileLink)
-
-    def getMp3FileInfos(self, dirId):
-        '''Returns audio info for all audio files in folder.'''
-        return self.service.getMp3FileInfos(self._login, self._password, dirId)
-
-    def getPreviewLink(self, fileId):
-        '''Return link to small preview image, or to flv preview for video
-        files.'''
-        return self.service.getPreviewLink(self._login, self._password, fileId)
-
-    def getVideoPreviewLink(self, fileId):
-        '''Return link to video preview.'''
-        return self.service.getVideoPreviewLink(self._login, self._password,
-            fileId)
-
-    # Folder
-    def createNewFolder(self, dirId, folderName):
-        '''Creates new folder as dirId subfolder.
-        dirId - id of the directory to create folder in.
-        folderName - new folder name.
-        Returns:
-            0 - if creation denied, newly created dir ID otherwise
-            -1 - already exists
-            -2 - attempt to create folder in removed parent'''
-        return self.service.createNewFolder(self._login, self._password, dirId,
-            folderName)
-
-    def setDirDescription(self, dirId, newDescription, setAsDefault,
-                          applyToAll):
-        '''Sets folder description for dedicated folder or account as a whole.
-        '''
-        return self.service.setDirDescription(self._login,
-            self._password, dirId, newDescription, setAsDefault, applyToAll)
-
-    def getDirDescription(self, dirId):
-        '''Returns folder description.'''
-        return self.service.getDirDescription(self._login, self._password,
-            dirId)
-
-    def renameFolder(self, dirId, newName):
-        '''Renames specified folder.
-        dirID - id of folder to be name
-        newName - new name of folder.
-        Returns:
-            -1 if file exists,
-            0 in case of other failures,
-            dirId if rename was successful'''
-        return self.service.renameFolder(self._login, self._password, dirId,
-            newName)
-
-    def deleteFolder(self, dirId):
-        '''Completely removes folder and puts all of it contents to recycle
-        bin.'''
-        return self.service.deleteFolder(self._login, self._password, dirId)
-
-    def deleteFolderFinal(self, dirId):
-        '''Removes files and subfolders from recycle bin.'''
-        return self.service.deleteFolderFinal(self._login, self._password,
-            dirId)
-
-    def emptyRecycleBin(self, dirId):
-        '''Empties recycle bean for specified user.'''
-        return self.service.emptyRecycleBin(self._login, self._password, dirId)
-
-    def getDirInfo(self, dirId):
-        '''Return info about specified folder.'''
-        return self.service.getDirInfo(self._login, self._password, dirId)
-
-    def getRoot(self):
-        '''Returns account item for user's root directory.'''
-        return self.service.getRoot(self._login, self._password)
-
-    def getAllFolders(self):
-        '''Returns all of the folders in user's root directory.
-        Returns: Array of info records about user's root folder subfolders.'''
-        return self.service.getAllFolders(self._login, self._password)
-
-    def getHistory(self, dirId):
-        '''Returns history of operations in specified folder and subfolders.
-        For operation field meanings see getOperationDescriptions().
-        Returns: Array of folder changes. May be null or empty.'''
-        return self.service.getHistory(self._login, self._password, dirId)
-
-    def getHistoryFromId(self, dirId, fromId):
-        '''Returns history of operations which occurs in specified folder and
-        subfolders with history id more then specified. For operation field
-        meanings see getOperationDescriptions().
-        dirId - id of folder to take history for
-        fromId - id floor of history
-        Returns: Array of folder changes. May be null or empty.'''
-        return self.service.getHistoryFromId(self._login, self._password, dirId,
-            fromId)
-
-    def markSynchronized(self, dirId):
-        '''Informs 4shared to write folder and subfolders usage history.'''
-        return self.service.markSynchronized(self._login, self._password, dirId)
-
-    def getOperationDescriptions(self):
-        '''Returns array of OperationEnum names. Array index corresponds to
-        values which can be returned as DirHistoryDTO.getOperation(). Array is
-        supposed to be zero-based.
-        Returns: array of OperationEnum names.'''
-        return self.service.getOperationDescriptions()
-
-    #Items (Files or folders)
-    def getItemInfo(self, itemId, dir):
-        '''Common method for getFileInfo(String, String, long) and
-        getDirInfo(String, String, long) distinguished by value of dir
-        parameter.
-        itemId - id of element
-        dir - if true then supplied Id is folder and file otherwise
-        '''
-        return self.service.getItemInfo(self._login, self._password, itemId,
-            dir)
-
-    def getItems(self, dirId):
-        '''Returns array of infos about contents of specified dir.
-        dirId - id of folder to list (-1 for root).'''
-        return self.service.getItems(self._login, self._password, dirId)
-
-    def getAllItems(self):
-        '''Returns info about all items in user's root folder.
-        Returns: Array of info records about user's root folder content.'''
-        return self.service.getAllItems(self._login, self._password)
-
-    def getItemsPartial(self, dirId, startIndex, count):
-        '''Get specified count folders' items ordered by name, folders first
-        starting from startIndex.'''
-        return self.service.getItemsPartial(self._login, self._password, dirId,
-            startIndex, count)
-
-    def getItemsCount(self, dirId):
-        '''Returns item count for dirId (-1 for root folder).'''
-        return self.service.getItemsCount(self._login, self._password, dirId)
-
-    def getSharedDirItems(self, dirId, dirPassword, userDirPassword):
-        '''Return content of possibly not owned shared folder.
-        dirId - id of folder to view
-        dirPassword - 4shared generated dir password
-        userDirPassword - user set dir password if needed.
-        Returns: content of specified shared folder or null.'''
-        return self.service.getSharedDirItems(self._login, self._password,
-            dirId, dirPassword, userDirPassword)
-
-    def getRecycleBinItems(self):
-        '''Returns info about files in recycle bin.'''
-        return self.service.getRecycleBinItems(self._login, self._password)
-
-    def pasteFilesDirs(self, toFolderId, makeCopy, fileIds, dirIds):
-        '''Copy-pastes or cut-pastes a group of files and dirs. Use this to
-        copy or move a group of files to another directory.
-        toFolderId - target folder id
-        makeCopy - - exec copy+paste if true, exec cut+paste if false
-        fileIds - ids of file to be moved/copied
-        dirIds - ids of folders to be moved/copied.
-        Returns: diagnostic message or empty string if all ok.'''
-        return self.service.pasteFilesDirs(self._login, self._password,
-            toFolderId, makeCopy, fileIds, dirIds)
-
-    def decodeId(self, encodedId):
-        '''Turns new encoded folder id into form id+"/"+4shared_password for
-        shared folder browsing encoded folder id can be found as 8-symbol group
-        of folder url right after /dir/ regexp:
-        http://www.4shared.com/dir/(.{8,8})/.*'''
-        return self.service.decodeId(self._login, self._password, encodedId)
-
-    def decodeLink(self, link):
-        '''Used to get item id from item link.'''
-        return self.service.decodeLink(self._login, self._password, link)
-
-    # Download
-    def getDirectLink(self, link):
-        '''Returns link to start immediate downloading. Not always possible
-        however, because we are ads-supported mostly. Returns link starting
-        with "http" if ok.'''
-        return self.service.getDirectLink(self._login, self._password, link)
-
-    def getFileDownloadLink(self, fileId):
-        '''Returns download link for user owned file. Download link or empty
-        string if some errors occurs.'''
-        return self.service.getFileDownloadLink(self._login, self._password,
-            fileId)
-
-    def downloadFinished(self, fileId):
-        '''Have to be called after full file download.
-        fileId - id of the file which was downloaded'''
-        return self.service.downloadFinished(self._login, self._password,
-            fileId)
-
-    def getNotOwnedSizeLimit(self):
-        '''Max file size which can be downloaded without speed limit.'''
-        return self.service.getNotOwnedSizeLimit(self._login, self._password)
-
-    # Share
-    def addToFavorites(self, fileId):
-        '''Adds file to user favorites.'''
-        return self.service.addToFavorites(self._login, self._password, fileId)
-
-    def removeFromFavorites(self, fileId):
-        return self.service.removeFromFavorites(self._login, self._password,
-            fileId)
-
-    def getFavorites(self):
-        '''Returns user favored files.'''
-        return self.service.getFavorites(self._login, self._password)
-
-    def addToMyAccount(self, dirId, link):
-        '''Adds file or folder identified by supplied link to user's account in
-        folder identified by dirId.'''
-        return self.service.addToMyAccount(self._login, self._password, dirId,
-            link)
-
-    def checkSubdomain(self, dirId, subdomainName):
-        '''Checks if subdomain can be set for specified folder.
-        dirId - id of the directory
-        subdomainName - name to be set
-        Returns: Empty string or null if everything is ok and error message
-        otherwise.'''
-        return self.service.checkSubdomain(self._login, self._password, dirId,
-            subdomainName)
-
-    def checkSharedDirAccess(self, dirId, dirPassword, userDirPassword):
-        '''Checks if directory can be accessed by specified user with specified
-        passwords.
-        dirId - id of the directory to be accessed
-        dirPassword - generated password to view contents of not owned folders
-        userDirPassword - user specified password
-        Returns:status.
-            0 ok
-            1 no such dir
-            2 owner inactive
-            3 abused dir
-            4 incorrect dirPassword
-            5 dir is not shared
-            6 owner is banned
-            8 incorrect userDirPassword'''
-        return self.service.checkSharedDirAccess(self._login, self._password,
-            dirId, dirPassword, userDirPassword)
-
-    def setFolderSharingProperties(self, dirId, folderProperties):
-        '''dirId - id of folder to set properties for
-        folderProperties - new properties values
-        Returns: Diagnostic message or empty string if all is ok.'''
-        return self.service.setFolderSharingProperties(self._login,
-            self._password, dirId, folderProperties)
-
-    def getFolderSharingProperties(self, dirId):
-        '''Returns folder sharing properties. Output is two element array:
-        res[0] - actual values.
-        res[1] - properties which can be set for this user is marked as true.'''
-        return self.service.getFolderSharingProperties(self._login,
-            self._password, dirId)
-
-    # Misc
-    def getCurrentUploaderVersion(self):
-        '''Returns last uploader version. If this increase you should consider
-        to look at online api documentation to check changes. We will try to
-        maintain backward compatibility but this is not guaranteed.
-        Returns: Uploader version.'''
-        return self.service.getCurrentUploaderVersion(self._login,
-            self._password)
-
-    def syncFinished(self, fileId):
-        '''Should be called in the end of each sync operation.
-        fileId - which file was synced. -1 if not applicable.'''
-        return self.service.syncFinished(self._login, self._password, fileId)

soap_tests.py

-import logging
-import logging.handlers
-from random import randint
-try:
-    import unittest2 as unittest
-except ImportError:
-    import unittest
-
-from soap import SOAP4Shared
-
-
-LOG_FILENAME = 'python4shared.log'
-logger = logging.getLogger('suds.client')
-logger.setLevel(logging.DEBUG)
-handler = logging.handlers.WatchedFileHandler(LOG_FILENAME)
-logger.addHandler(handler)
-
-
-class SOAP4SharedTestCase(unittest.TestCase):
-    def setUp(self):
-        user1_login, user1_password = 'a307@mail.ru', '6Nn590Ad'
-        user2_login, user2_password = 'ivanov@mail.ru', 'Easwwerf'
-
-        self.soapapi1 = SOAP4Shared(user1_login, user1_password)
-        self.soapapi2 = SOAP4Shared(user2_login, user2_password)
-
-    def test_accounts(self):
-        # New user test
-        user3_login = 'a%d@mail.ru' % randint(0, 999)
-        user3_password = '6Nn%dAd' % randint(0, 999)
-        logger.info('Create user with login %s and password %s ' % \
-                    (user3_login, user3_password))
-        self.soapapi3 = SOAP4Shared(user3_login, user3_password)
-        if self.soapapi3.isExistsLoginPassword() is True:
-            self.assertEqual(self.soapapi3.isExistsLoginPassword(),
-                "Server raised fault: 'The Login and/or Password did not \
-match our records'")
-        else:
-            self.assertEqual(self.soapapi3.signup(), None)
-            # FIXME: Turn me on:
-            self.assertEqual(self.soapapi3.signupUsername(user3_login), None)
-            self.assertEqual(self.soapapi3.login(), None)
-            self.assertTrue(self.soapapi3.isAccountActive())
-            self.assertFalse(self.soapapi3.isAccountPremium())
-            self.assertFalse(self.soapapi3.isAccountBanned())
-
-        # Test existing user.
-        self.assertEqual(self.soapapi1.login(), None)
-        self.assertTrue(self.soapapi1.isExistsLoginPassword())
-        self.assertTrue(self.soapapi1.isAccountActive())
-        self.assertFalse(self.soapapi1.isAccountPremium())
-        self.assertFalse(self.soapapi1.isAccountBanned())
-
-        # Test non existing user.
-        self.assertEqual(self.soapapi2.login(), "Server raised fault: \
-'The Login and/or Password did not match our records'")
-
-    def test_uploads(self):
-        self.assertTrue(self.soapapi1.hasRightUpload())
-        self.assertGreaterEqual(self.soapapi1.getMaxFileSize(), 2147483648)
-        self.assertLessEqual(self.soapapi1.getFreeSpace(), 16106127360)
-        self.assertLessEqual(self.soapapi1.getSpaceLimit(), 16106127360)
-        dataCenterID = self.soapapi1.getNewFileDataCenter()
-        # dirID - (-1) means upload to user's root dir
-        sessionKey = self.soapapi1.createUploadSessionKey(-1)
-        self.assertEqual(
-            len(self.soapapi1.getUploadFormUrl(dataCenterID, sessionKey)),
-            len('http://dc531.4shared.com/main/upload4Desktop.jsp?sId='
-                'vFc9holjIXWi5aox'))
-        # TODO: uploadStartFile
-        # TODO: uploadStartFileUpdate
-        # TODO: uploadStartedFileExists
-        # TODO: uploadCancelFile
-        # TODO: uploadFinishFile
-
-    def test_files(self):
-        # TODO: getFiles
-        # TODO: setFileDescription
-        # TODO: getFileDescription
-        # TODO: renameFile
-        # TODO: deleteFile
-        # TODO: deleteFileFinal
-        # TODO: restoreFile
-        # TODO: restoreFiles
-        # TODO: getFileInfo
-        # TODO: getExifFileInf
-        # TODO: getExifFileInfos
-        # TODO: getMp3FileInfo
-        # TODO: getMp3FileInfos
-        # TODO: getPreviewLink
-        # TODO: getVideoPreviewLink
-        pass
-
-    def test_folders(self):
-        # TODO: createNewFolder
-        # TODO: setDirDescription
-        # TODO: getDirDescription
-        # TODO: renameFolder
-        # TODO: deleteFolder
-        # TODO: deleteFolderFinal
-        # TODO: emptyRecycleBin
-        # TODO: getDirInfo
-        # TODO: getRoot
-        # TODO: getAllFolders
-        # TODO: getHistory
-        # TODO: getHistoryFromId
-        # TODO: markSynchronized
-        # TODO: getOperationDescriptions
-        pass
-
-    def test_items(self):
-        # TODO: getItemInfo
-        # TODO: getItems
-        # TODO: getAllItems
-        # TODO: getItemsPartial
-        # TODO: getItemsCount
-        # TODO: getSharedDirItems
-        # TODO: getRecycleBinItems
-        # TODO: pasteFilesDirs
-        # TODO: decodeId
-        # TODO: decodeLink
-        pass
-
-    def test_downloads(self):
-        # TODO: getDirectLink
-        # TODO: getFileDownloadLink
-        # TODO: downloadFinished
-        # TODO: getNotOwnedSizeLimit
-        pass
-
-    def test_shares(self):
-        # TODO: addToFavorites
-        # TODO: removeFromFavorites
-        # TODO: getFavorites
-        # TODO: addToMyAccount
-        # TODO: checkSubdomain
-        # TODO: checkSharedDirAccess
-        # TODO: setFolderSharingProperties
-        # TODO: getFolderSharingProperties
-        pass
-
-    def test_miscs(self):
-        # TODO: getCurrentUploaderVersion
-        # TODO: syncFinished
-        pass
-
-if __name__ == '__main__':
-    unittest.main()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.