[mod] Migrate to django 1.6 and python 3
authormathieui <mathieui@mathieui.net>
Thu, 6 Mar 2014 00:16:32 +0000 (01:16 +0100)
committermathieui <mathieui@mathieui.net>
Thu, 6 Mar 2014 00:16:54 +0000 (01:16 +0100)
15 files changed:
please/manage.py
please/pleaseshare/admin.py
please/pleaseshare/models.py
please/pleaseshare/templates/base.html
please/pleaseshare/templates/home.html
please/pleaseshare/templates/upload_detail.html [moved from please/pleaseshare/templates/single.html with 100% similarity]
please/pleaseshare/tests.py [deleted file]
please/pleaseshare/tests/test.py
please/pleaseshare/torrent/bencode.py
please/pleaseshare/torrent/common.py
please/pleaseshare/torrent/maketorrent.py
please/pleaseshare/views.py
please/settings.py
please/urls.py
requirements.txt

index 1473748..5d85018 100755 (executable)
@@ -1,14 +1,10 @@
-#!/usr/bin/env python2
-from django.core.management import execute_manager
-import imp
-try:
-    imp.find_module('settings') # Assumed to be in the same directory.
-except ImportError:
-    import sys
-    sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n" % __file__)
-    sys.exit(1)
-
-import settings
+#!/usr/bin/env python3
+import os
+import sys
 
 if __name__ == "__main__":
-    execute_manager(settings)
+    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "please.settings")
+
+    from django.core.management import execute_from_command_line
+
+    execute_from_command_line(sys.argv)
index c2589d4..84d3e6a 100644 (file)
@@ -1,4 +1,4 @@
 from django.contrib import admin
-from models import Upload
+from models import Upload
 
 admin.site.register(Upload)
index 8680402..b4ae2a3 100644 (file)
@@ -59,10 +59,5 @@ class Upload(models.Model):
         except OSError:
             res = ''
             log.info('Call to `tree` failed.')
-        tb = res.split('\n')
-        if self.multifile:
-            suffix = '/'
-        else:
-            suffix = ''
-        tb[0] = str(self.name.encode('utf-8') + suffix)
-        return '\n'.join([f.decode('utf-8') for f in tb])
+        tb = res.decode('utf-8').split('\n')
+        return '\n'.join(tb)
index cd572ef..4ab855f 100644 (file)
         <header>
         {% block header %}
             <section class="left">
-            <h1><a href="{% url home %}">PleaseShare</a></h1>
+            <h1><a href="{% url "home" %}">PleaseShare</a></h1>
             </section>
             <section class="right">
             <nav>
-                <a href="{% url Help %}" title="Need help?">Need help?</a> |
-                <a title="About" href="{% url About %}">About</a> |
-                <a title="Terms of Service" href="{% url ToS %}">ToS</a> |
-                <a title="Contact" href="{% url Contact %}">Contact</a>
+                <a href="{% url "Help" %}" title="Need help?">Need help?</a> |
+                <a title="About" href="{% url "About" %}">About</a> |
+                <a title="Terms of Service" href="{% url "ToS" %}">ToS</a> |
+                <a title="Contact" href="{% url "Contact" %}">Contact</a>
             </nav>
             </section>
             <section class="clear"></section>
index 994cae9..6c76e9e 100644 (file)
     <li>Subsequent downloads are at least <strong>as fast as</strong> a direct HTTP download: this server acts as a <strong>webseed</strong> for the created torrent.</li>
 </ul>
 
-<p>PleaseShare is <a href="http://www.gnu.org/philosophy/free-sw.en.html">free software</a>, <a href="https://gitorious.org/pleaseshare">get the code</a>. More about PleaseShare <a href="{% url About %}">here</a>. Need <a href="{% url Help %}">help</a>?</p>
+<p>PleaseShare is <a href="http://www.gnu.org/philosophy/free-sw.en.html">free software</a>, <a href="https://gitorious.org/pleaseshare">get the code</a>. More about PleaseShare <a href="{% url "About" %}">here</a>. Need <a href="{% url "Help" %}">help</a>?</p>
 
 
 <h2>Select a file to upload</h2>
 
-<form method="post" action="{% url upload %}" enctype="multipart/form-data" id="sendform">
+<form method="post" action="{% url "upload" %}" enctype="multipart/form-data" id="sendform">
     {% csrf_token %}
     <div class="center">
         <input type="file" name="please" id="fileselect"/>
diff --git a/please/pleaseshare/tests.py b/please/pleaseshare/tests.py
deleted file mode 100644 (file)
index 501deb7..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-"""
-This file demonstrates writing tests using the unittest module. These will pass
-when you run "manage.py test".
-
-Replace this with more appropriate tests for your application.
-"""
-
-from django.test import TestCase
-
-
-class SimpleTest(TestCase):
-    def test_basic_addition(self):
-        """
-        Tests that 1 + 1 always equals 2.
-        """
-        self.assertEqual(1 + 1, 2)
index 52c9e88..eaa96be 100644 (file)
@@ -34,11 +34,15 @@ class TorrentCreationTest(unittest.TestCase):
         """
         c = Client()
 
-        filename = u'répondeur_linkmauve.wav'
+        filename = 'répondeur_linkmauve.wav'
         filepath = join(realpath(dirname(__file__)), 'data', filename)
+        print(filepath)
+
+        import sys
+        sys.stderr.write(repr(filename) + '\n')
 
         # Upload a file
-        with open(filepath, 'r') as fp:
+        with open(filepath, 'rb') as fp:
             response = c.post('/upload', {
                 'please': fp,
                 'trackers': 'udp://share.example.com:80',
@@ -99,15 +103,15 @@ class FunctionsTestCase(unittest.TestCase):
         """
         tab = ['', 'qsd', '', 'sdf', 'koin', '']
         remove_empty_str(tab)
-        self.assertEquals(tab, ['qsd', 'sdf', 'koin'])
+        self.assertEqual(tab, ['qsd', 'sdf', 'koin'])
 
         tab = ['', '', '', '']
         remove_empty_str(tab)
-        self.assertEquals(tab, [])
+        self.assertEqual(tab, [])
 
         tab = ['', 'a', 'b', '']
         remove_empty_str(tab)
-        self.assertEquals(tab, ['a', 'b'])
+        self.assertEqual(tab, ['a', 'b'])
 
     def test_format_trackers(self):
         """
@@ -116,11 +120,11 @@ class FunctionsTestCase(unittest.TestCase):
         tab = ['udp://toto', 'koin://test', 'test://ex']
         new_tab = format_trackers(tab)
         needed = [['udp://toto'], ['koin://test'], ['test://ex']]
-        self.assertEquals(new_tab, needed)
+        self.assertEqual(new_tab, needed)
 
         tab = []
         new_tab = format_trackers(tab)
-        self.assertEquals(new_tab, tab)
+        self.assertEqual(new_tab, tab)
 
     def test_select_extract_func(self):
         """
index 43fa5aa..0f10c37 100644 (file)
@@ -72,9 +72,6 @@ def bdecode(x):
 
     return r
 
-from types import StringType, IntType, LongType, DictType, ListType, TupleType, UnicodeType
-
-
 class Bencached(object):
 
     __slots__ = ['bencoded']
@@ -83,10 +80,10 @@ class Bencached(object):
         self.bencoded = s
 
 def encode_bencached(x,r):
-    r.append(x.bencoded)
+    r.append(x.bencoded.encode())
 
 def encode_int(x, r):
-    r.extend(('i', str(x), 'e'))
+    r.extend((b'i', str(x).encode(), b'e'))
 
 def encode_bool(x, r):
     if x:
@@ -95,44 +92,39 @@ def encode_bool(x, r):
         encode_int(0, r)
 
 def encode_string(x, r):
-    r.extend((str(len(x))':', x))
+    r.extend((str(len(x)).encode(), b':', x))
 
 def encode_utf8(x, r):
     x = x.encode('utf-8')
-    r.extend((str(len(x))':', x))
+    r.extend((str(len(x)).encode(), b':', x))
 
 def encode_list(x, r):
-    r.append('l')
+    r.append(b'l')
     for i in x:
         encode_func[type(i)](i, r)
-    r.append('e')
+    r.append(b'e')
 
 def encode_dict(x,r):
-    r.append('d')
+    r.append(b'd')
     ilist = x.items()
-    ilist.sort()
+    ilist = sorted(ilist)
     for k, v in ilist:
-        r.extend((str(len(k)), ':', k))
+        r.extend((str(len(k)).encode(), b':', k.encode()))
         encode_func[type(v)](v, r)
-    r.append('e')
+    r.append(b'e')
 
 encode_func = {}
 encode_func[Bencached] = encode_bencached
-encode_func[IntType] = encode_int
-encode_func[LongType] = encode_int
-encode_func[StringType] = encode_string
-encode_func[UnicodeType] = encode_utf8
-encode_func[ListType] = encode_list
-encode_func[TupleType] = encode_list
-encode_func[DictType] = encode_dict
-
-try:
-    from types import BooleanType
-    encode_func[BooleanType] = encode_bool
-except ImportError:
-    pass
+encode_func[int] = encode_int
+encode_func[int] = encode_int
+encode_func[bytes] = encode_string
+encode_func[str] = encode_utf8
+encode_func[list] = encode_list
+encode_func[tuple] = encode_list
+encode_func[dict] = encode_dict
+
 
 def bencode(x):
     r = []
     encode_func[type(x)](x, r)
-    return ''.join(r)
+    return b''.join(r)
index 2a58e69..f9bc280 100644 (file)
@@ -38,7 +38,7 @@
 """Common functions for various parts of Deluge to use."""
 
 import os
-from urllib import quote_plus
+from urllib.parse import quote_plus
 
 def create_magnet_uri(infohash, name=None, trackers=[]):
     """
index eeee457..a1d8e54 100644 (file)
@@ -38,8 +38,8 @@ import sys
 import os
 from hashlib import sha1 as sha
 
-from common import get_path_size, create_magnet_uri
-from bencode import bencode, bdecode
+from common import get_path_size, create_magnet_uri
+from bencode import bencode, bdecode
 
 class InvalidPath(Exception):
     """
@@ -175,12 +175,12 @@ class TorrentMetadata(object):
             fs = []
             pieces = []
             # Create the piece hashes
-            buf = ""
+            buf = b""
             for size, path in files:
                 path = [s.encode("UTF-8") for s in path]
                 fs.append({"length": size, "path": path})
-                if path[-1].startswith("_____padding_file_"):
-                    buf += "\0" * size
+                if path[-1].startswith(b"_____padding_file_"):
+                    buf += b"\0" * size
                     pieces.append(sha(buf).digest())
                     buf = ""
                     fs[-1]["attr"] = "p"
@@ -194,7 +194,7 @@ class TorrentMetadata(object):
                             # Run the progress function if necessary
                             if progress:
                                 progress(len(pieces), num_pieces)
-                            buf = ""
+                            buf = b""
                         else:
                             break
                         r = fd.read(piece_size - len(buf))
@@ -206,7 +206,7 @@ class TorrentMetadata(object):
                     progress(len(pieces), num_pieces)
                 buf = ""
 
-            torrent["info"]["pieces"] = ''.join(pieces)
+            torrent["info"]["pieces"] = b''.join(pieces)
             torrent["info"]["files"] = fs
 
         elif os.path.isfile(self.data_path):
@@ -223,7 +223,7 @@ class TorrentMetadata(object):
 
                 r = fd.read(piece_size)
 
-            torrent["info"]["pieces"] = ''.join(pieces)
+            torrent["info"]["pieces"] = b''.join(pieces)
 
         # Write out the torrent file
         wr = open(torrent_path, 'wb')
index d4fe622..b4ae8eb 100644 (file)
@@ -6,18 +6,28 @@ from django.shortcuts import render_to_response, get_object_or_404
 from django.contrib.sites.models import Site
 from django.conf import settings
 
+
+# why do I even need this, fuck you django
+from django.views.generic import TemplateView
+
+def direct_to_template(template):
+    class cls(TemplateView):
+        template_name = template
+    return cls.as_view()
+
+
 # system imports
 from os import mkdir, path, walk, remove, chmod, symlink
 from shutil import rmtree
 from uuid import uuid4
-from urllib import quote
+from urllib.parse import quote
 import tarfile
 import zipfile
 import logging
 
 # local imports
-from models import Upload
-from torrent import maketorrent
+from models import Upload
+from torrent import maketorrent
 
 if settings.LOG_FILE:
     logging.basicConfig(filename=settings.LOG_FILE, level=logging.INFO, format='%(asctime)s %(message)s')
@@ -178,7 +188,7 @@ def handle_uploaded_file(f, extract=False, trackers=None, webseeds=None, private
     """
     id = str(uuid4())
     folder = path.join(settings.MEDIA_ROOT, id)
-    f.name = f.name.encode('utf8')
+    #f.name = f.name.encode('utf8')
     mkdir(folder)
     if extract:
         fun = select_extract_func(f.name)
@@ -254,7 +264,7 @@ def extract_tar(f, folder):
         else:
             tar = tarfile.open(_file, mode='r:')
     except:
-        log.info('Error opening tarfile: %s' % f.name)
+        log.info('Error opening tarfile: %s' % f.name, exc_info=True)
         return (_file, False)
     else:
         if not _file:
@@ -267,10 +277,11 @@ def extract_tar(f, folder):
     name = f.name.split('.')[0]
     rep = path.join(folder, name)
     mkdir(rep)
+    print(rep)
     try:
         proceed_tar_extraction(tar, rep)
     except: # extraction failed, remove leftover files
-        log.info('Extraction of %s failed, falling back to single-file upload' % f.name)
+        log.info('Extraction of %s failed, falling back to single-file upload' % f.name, exc_info=True)
         rmtree(rep)
         return (_file, False)
     # remove old tar file
@@ -286,14 +297,12 @@ def proceed_tar_extraction(tar, dir):
         # test against files named by stupid people
         if not member.name.startswith('/') and not \
                 '..' in member.name:
-            member.name = member.name.decode('utf-8')
-            tar.extract(member, dir)
+            tar.extract(member, dir, set_attrs=False)
             try:
                 # python has no option to use umask while extracting, so…
-                chmod(path.join(dir, member.name), 0755)
+                chmod(path.join(dir, member.name), 0o755)
             except:
-                log.info('Error chmoding %s' % member.name)
-                pass
+                log.info('Error chmoding %s' % member.name, exc_info=True)
 
 def extract_zip(f, folder):
     """
@@ -309,7 +318,7 @@ def extract_zip(f, folder):
         else:
             zip = zipfile.ZipFile(_file, mode='r', compression=zipfile.ZIP_STORED)
     except:
-        log.info('Error opening zipfile: %s' % f.name)
+        log.info('Error opening zipfile: %s' % f.name, exc_info=True)
         return (_file, False)
     else:
         if not _file:
@@ -322,10 +331,11 @@ def extract_zip(f, folder):
     name = f.name.split('.')[0]
     rep = path.join(folder, name)
     mkdir(rep)
+    chmod(rep, 0o711)
     try:
         proceed_zip_extraction(zip, rep)
     except: # extraction failed, remove leftover files
-        log.info('Extraction of %s failed, falling back to single-file upload' % f.name)
+        log.info('Extraction of %s failed, falling back to single-file upload' % f.name, exc_info=True)
         rmtree(rep)
         return (_file, False)
     # remove old zip file
@@ -344,9 +354,9 @@ def proceed_zip_extraction(zip, dir):
             zip.extract(member, dir)
             try:
                 # python has no option to use umask while extracting, so…
-                chmod(path.join(dir, member.filename), 0755)
+                chmod(path.join(dir, member.filename), 0o755)
             except:
-                log.info('Error chmoding %s' % member.filename)
+                log.info('Error chmoding %s' % member.filename, exc_info=True)
                 pass
 
 def select_extract_func(name):
index 387a2d9..6246229 100644 (file)
@@ -104,6 +104,10 @@ MIDDLEWARE_CLASSES = (
 
 ROOT_URLCONF = 'please.urls'
 
+
+DEFAULT_CHARSET='utf-8'
+
+
 TEMPLATE_DIRS = (
     # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
     # Always use forward slashes, even on Windows.
index b3f7ccf..98242ab 100644 (file)
@@ -1,7 +1,7 @@
-from django.conf.urls.defaults import patterns, include, url
+from django.conf.urls import patterns, include, url
 from django.conf import settings
-from django.views.generic.simple import direct_to_template
-from django.views.generic import list_detail
+from pleaseshare.views import direct_to_template
+from django.views.generic import DetailView
 from django.views.static import serve
 from pleaseshare.models import Upload
 
@@ -10,17 +10,17 @@ from django.contrib import admin
 admin.autodiscover()
 
 urlpatterns = patterns('',
-    url(r'^$', direct_to_template, {'template': 'home.html'}, name='home'),
+    url(r'^$', direct_to_template('home.html'), name='home'),
     url(r'^(?P<msg>[0-9]+)$', 'pleaseshare.views.err_msg', name='err'),
     url(r'^upload/?$', 'pleaseshare.views.upload_file', name='upload'),
     url(r'^delete/?$', 'pleaseshare.views.delete_file', name='delete'),
-    url(r'^view/(?P<object_id>[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})/?$', list_detail.object_detail, {'queryset': Upload.objects.all(), 'template_name': 'single.html'},  name='single'),
+    url(r'^view/(?P<pk>[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})/?$', DetailView.as_view(model=Upload, template_name="upload_detail.html"), name='single'),
 
     # static files
-    url(r'^contact/?$', direct_to_template, {'template': 'contact.html'}, name='Contact'),
-    url(r'^about/?$', direct_to_template, {'template': 'about.html'}, name='About'),
-    url(r'^tos/?$', direct_to_template, {'template': 'tos.html'}, name='ToS'),
-    url(r'^help/?$', direct_to_template, {'template': 'help.html'}, name='Help'),
+    url(r'^contact/?$', direct_to_template('contact.html'), name='Contact'),
+    url(r'^about/?$', direct_to_template('about.html'), name='About'),
+    url(r'^tos/?$', direct_to_template('tos.html'), name='ToS'),
+    url(r'^help/?$', direct_to_template('help.html'), name='Help'),
 
     url(r'^admin/', include(admin.site.urls)),
 )
index 9f0826b..ff98b75 100644 (file)
@@ -1,2 +1,2 @@
-Django==1.3
-South==0.7.3
+Django==1.6
+South==0.8