comparison apps/bundle/tasks.py @ 151:c7be7def8b57

Bundles! (basic functionality) Changes made in this commit: * Added new dependencies (see pip-requirements) * Added new dependency and setup information to README * Deleted the included mptt app (in apps/mptt) in favour of just adding the dependency to pip-requirements (makes it easier to update, etc) * Changed the import convention to use `from apps.bundle.models import Bundle` rather than `from agora.apps.bundle.models import Bundle` because Celery was having problems with the latter style. Everything should still work. * Moved the syntax-highlighting and related code for snippets into separate HTML files so that they can be used by the bundle app And, of course, the ability to upload bundles. But wait! There's more! Changes still to come, for only $19.95 a month: * Bundle versioning * Automatic license integration (i.e. adding headers to files) * The ability to download bundles (zip, tar, etc) * Rating bundles * And much, much more! Batteries not included.
author dellsystem <ilostwaldo@gmail.com>
date Mon, 15 Oct 2012 00:52:00 -0400
parents
children 27de4f31f9d5
comparison
equal deleted inserted replaced
150:3db897f5acdc 151:c7be7def8b57
1 import mimetypes
2 import os
3
4 import archive
5 import magic
6 from celery import task
7
8 from apps.bundle.models import Bundle, BundleFile
9
10
11 mimetypes.add_type('application/x-gzip', '.tgz')
12 mimetypes.add_type('application/x-bzip2', '.tz2')
13 archive_extensions = ('.zip', '.tgz', '.tar', '.tz2')
14
15
16 def process_files_in_dir(bundle, dir_name, parent_dir):
17 """
18 Go through all the subdirectories and files (in that order) in this
19 directory.
20 """
21 dir_contents = [os.path.join(dir_name, f) for f in os.listdir(dir_name)]
22 dirs = filter(os.path.isdir, dir_contents)
23 files = filter(os.path.isfile, dir_contents)
24 print "Directories: %s" % ", ".join(dirs)
25 print "Files: %s" % ", ".join(files)
26
27 for file_path in sorted(dirs) + sorted(files):
28 filename = os.path.basename(file_path)
29 full_path = file_path[len(bundle.get_temp_path()) + 1:]
30 bundle_file = BundleFile(bundle=bundle, name=filename,
31 parent=parent_dir, full_path=full_path)
32
33 if file_path in files:
34 bundle_file.is_dir = False
35 bundle_file.file_size = os.path.getsize(file_path)
36
37 # Only highlight the file contents if it's plain text
38 mime_type = magic.from_file(file_path, mime=True)
39 if mime_type.startswith('text/'):
40 with open(file_path, 'rt') as file:
41 # Store the contents of the file in the code field
42 bundle_file.save_file_contents(file)
43
44 bundle_file.save()
45 else:
46 # It's a directory - call this function on it recursively
47 bundle_file.is_dir = True
48 bundle_file.save()
49 process_files_in_dir(bundle, file_path, bundle_file)
50
51 @task()
52 def handle_bundle_upload(bundle_id):
53 bundle = Bundle.objects.get(pk=bundle_id)
54 file = bundle.get_temp_path()
55
56 # Figure out the most likely mime-type
57 mime_type = magic.from_file(file, mime=True)
58 extension = mimetypes.guess_extension(mime_type)
59
60 print "mime type: %s" % mime_type
61 print "extension: %s" % extension
62
63 if extension in archive_extensions:
64 new_path = file + extension
65 # Treat it as an archive. Rename it to that, then extract
66 os.rename(file, new_path)
67
68 try:
69 # Extract it to a directory, same path as the filename
70 archive.extract(new_path, to_path=file)
71
72 # Now go through the extracted files, make BundleFiles from them
73 process_files_in_dir(bundle, file, None)
74 except archive.ArchiveException:
75 print "Archive exception"
76 pass
77 elif mime_type.startswith('text/'):
78 # Should be a plain text file - create a CodeFile for it
79 bundle_file = BundleFile(bundle=bundle, name=bundle.file_name,
80 full_path=bundle.file_name, file_size=os.path.getsize(file))
81 bundle_file.save_file_contents(open(file, 'rt'),
82 original_filename=bundle.file_name)
83
84 print "Done uploading!"
85 bundle.done_uploading = True
86 bundle.save()