Initial Setup
=============

Give test user the Manager role and login:

  >>> from Testing.ZopeTestCase import user_name, user_password, folder_name
  >>> self.setRoles(['Manager'])
  >>> self.login(user_name)
  >>> request = self.portal.REQUEST

Managed File
============

A Managed File points to a path on the filesystem, though it's not
guaranteed that it will point to a valid and readable file. We store
the relative path to the file and the repository id on the 'stub'
persistent object. When asked for the filename, we compute the real
path by joining those two paths.

Create one object not passing any path info. Should work, but will be
pointing to a non-file. This is required so you can add stuff from
Plone by specifying just the id:

  >>> import os
  >>> from Products.CMFManagedFile.config import *
  >>> obj = self.makeOne(id='test')
  >>> print obj.getPortalTypeName()
  AT Managed File

  >>> expected = os.path.join(DEFAULT_PATH, 'portal', 'test')
  >>> obj.getFilepath(request) == expected
  True

Check object default delete policy:

  >>> obj.deletePolicy == DELETE_MANUAL
  True

Check we can get and set the deletePolicy through PropertySheet API,
and that the available policies for the object are at least a subset
of the ones in the tool:

  >>> value = obj.getProperty('deletePolicy', None)
  >>> value is not None
  True

  >>> value == DELETE_MANUAL
  True

  >>> obj._updateProperty('deletePolicy', DELETE_DEFERRED)
  >>> obj.getProperty('deletePolicy') == DELETE_DEFERRED
  True

  >>> del_policies = self.tool.availableDeletePolicies()
  >>> for p in obj.getDeletePolicies():
  ...     if p in del_policies:
  ...        print 'Match'
  ...
  Match
  Match
  ...

Check for other properties:

  >>> print obj.getProperty('filename')
  test

  >>> print obj.getProperty('basedir')
  <BLANKLINE>

  >>> print obj.getProperty('repository')
  default

There are various different cases we want to test here. There are a
couple parameters the factory can take, and several combinations are
allowed.

Let's create a file first, to make sure we have something to point to:

  >>> import os
  >>> import tempfile
  >>> tmp_dir = tempfile.mkdtemp()
  >>> sub_dir = os.path.join(tmp_dir, 'sub')
  >>> os.mkdir(sub_dir)

  >>> test_file = tempfile.NamedTemporaryFile(dir=tmp_dir)
  >>> fname = test_file.name
  >>> parts = os.path.split(fname)

And let's also set the default repository path to point to the tmp_dir
containing that file:

  >>> self.tool.getRepository('default').edit(path=tmp_dir,
  ...                                         path_policy=FS_BASE)

Create a test repository with a different filename policy to test
filename generation:

  >>> from Products.CMFManagedFile.policies import filename_policies
  >>> def xxx(filename):
  ...     return '.'.join(('xxx', filename, 'xxx'))

  >>> TEST_XXX_POLICY = 'TestXXXPolicy'
  >>> filename_policies.register(xxx, name=TEST_XXX_POLICY)

  >>> repo = self.tool.addRepository('test',
  ...   path=sub_dir,
  ...   path_policy=FS_BASE,
  ...   filename_policy=TEST_XXX_POLICY)

1. Only the target_filepath parameter is specified - a Managed File
instance is created, pointing to the file specified by default
repository path + target_filepath.

  >>> rel_path = parts[-1]
  >>> obj = self.makeOne(id='file1', target_filepath=rel_path)
  >>> obj.getProperty('filename') == parts[-1]
  True

  >>> obj.getProperty('basedir') == ''
  True

  >>> obj.getProperty('repository') == 'default'
  True

  >>> obj.getFilepath() == fname
  True

2. target_filepath and repository parameters are specified - A
CMFManagedFile instance is created pointint to the file specified by
the repository path + target_filepath.

  >>> obj = self.makeOne(id='file2', target_filepath=rel_path,
  ...                    repository='test')
  >>> obj.getProperty('filename') == xxx(parts[-1])
  True

  >>> obj.getProperty('basedir') == ''
  True

  >>> obj.getProperty('repository') == 'test'
  True

  >>> generated = (sub_dir, xxx(parts[-1]))
  >>> obj.getFilepath() == os.path.join(*generated)
  True

3. Only the upload_file parameter is specified - the filename
attribute of the upload_file parameter object will be used to identify
the name of the file, and the default repository will be used to
determine the file system path.  The upload_file content will be
written to the path specified by the repository under the file name
derived from the filename attribute.

  >>> test_file.seek(0)
  >>> obj = self.makeOne(id='file3', upload_file=test_file)
  >>> obj.getProperty('filename') == parts[-1]
  True

  >>> obj.getProperty('basedir') == ''
  True

  >>> obj.getProperty('repository') == 'default'
  True

  >>> obj.getFilepath() == fname
  True

4. upload_file and repository parameters are specified - the filename
attribute of the upload_file parameter object will be used to identify
the name of the file, and the repository parameter will be used to
determine the file system path.  The upload_file content will be
written to the path specified by the repository under the file name
derived from the filename attribute.

  >>> test_file.seek(0)
  >>> obj = self.makeOne(id='file4', upload_file=test_file,
  ...                    repository='test')
  >>> obj.getProperty('filename') == xxx(parts[-1])
  True

  >>> obj.getProperty('basedir') == ''
  True

  >>> obj.getProperty('repository') == 'test'
  True

  >>> generated = (sub_dir, xxx(parts[-1]))
  >>> obj.getFilepath() == os.path.join(*generated)
  True

5. target_filepath and upload_file parameters are specified - the
content of the upload_file object will be written out to the file
specified by the target_filepath parameter.

  >>> test_file.seek(0)
  >>> obj = self.makeOne(id='file5', target_filepath=parts[-1],
  ...                    upload_file=test_file)

  >>> obj.getProperty('filename') == os.path.basename(fname)
  True

  >>> obj.getProperty('basedir') == ''
  True

  >>> print obj.getProperty('repository')
  default

  >>> obj.getFilepath() == fname
  True

Editing Managed Files
---------------------

When editing managed files, should be possible to change the
repository they are stored into, upload a new file and also change the
delete policy.

  >>> test_file.seek(0)
  >>> obj = self.makeOne(id='file6', upload_file=test_file)

  >>> print obj.getProperty('repository')
  default

  >>> obj.getProperty('deletePolicy') == DELETE_MANUAL
  True

  >>> fp = obj.getFilepath()
  >>> os.path.exists(fp)
  True

  >>> test_file.seek(0)
  >>> obj.edit(repository='test', file=test_file, delete_policy=DELETE_IMMEDIATE)

  >>> obj.getProperty('deletePolicy') == DELETE_IMMEDIATE
  True

  >>> obj.getFilepath() == fp
  False

  >>> os.path.exists(fp)
  False

  >>> os.path.exists(obj.getFilepath())
  True

Now check for a simple repository move:

  >>> fp = obj.getFilepath()

  >>> obj.edit(repository='default')

  >>> obj.getFilepath() == fp
  False

  >>> os.path.exists(fp)
  False

  >>> os.path.exists(obj.getFilepath())
  True

  >>> self.portal.manage_delObjects(ids=[obj.getId()])
  >>> os.path.exists(obj.getFilepath())
  False

Close the temp file:

  >>> try:
  ...   test_file.close()
  ... except OSError:
  ...   pass

Cleanup the temp directory:

  >>> import shutil
  >>> shutil.rmtree(tmp_dir, ignore_errors=True)

Clean the registered filename policy:

  >>> del filename_policies[TEST_XXX_POLICY]
