1. Paul Moore
  2. pep376

Commits

Paul Moore  committed 8a088c9 Draft

Start work on record file creation

  • Participants
  • Parent commits f80218c
  • Branches default

Comments (0)

Files changed (2)

File pep376/distribution.py

View file
-import sysconfig
+import hashlib
+import base64
+import os
 
 class Distribution(object):
     def __init__(self, name, version):
         self.name = name
         self.version = version
         self.files = []
-        self.scheme = None
-
-    def set_scheme(self, scheme=None):
-        if scheme and scheme not in sysconfig.get_scheme_names():
-            raise ValueError("Invalid scheme: " + scheme)
-        self.scheme = scheme
+        self.locations = {
+                'purelib': 'xxx',
+                'platlib': 'xxx',
+                'dist-info': 'xxx'
+            }
+        # self.fs = Filesystem()
 
     def get_path(self, path):
-        if self.scheme:
-            return sysconfig.get_path(path, self.scheme)
-        else:
-            return sysconfig.get_path(path)
+        return self.locations[path]
 
     @property
     def filecount(self):
         # neither
         return 'purelib'
 
+    def get_record_data(self, hashtype='md5'):
+        base = self.locations[self.root]
+        for location, filename, content in self.files:
+            path = os.path.join(self.locations[location], filename)
+            path = os.path.normpath(path)
+            if self.relative_ok(location):
+                path = os.path.relpath(path, base)
+                path.replace(os.sep, '/')
+            else:
+                path = path
+            # String, bytes, number!!!
+            yield path, content.hash(hashtype), content.length()
+
     def relative_ok(self, location):
         # Absolute filename
         if location == None:
         return False
 
     def add_file(self, location, filename, content):
-        if location not in sysconfig.get_path_names():
+        if location not in self.locations:
             raise ValueError("Invalid location: {}".format(location))
+        if isinstance(content, bytes):
+            content = BytesContent(content)
         self.files.append((location, filename, content))
 
     def clear(self):
         self.files = []
+
+##     def install(self, writer):
+##         for location, filename, content in self.files:
+##             writer.save(location, filename, content)
+##         writer.save('dist-info', 'METADATA', self.metadata)
+##         writer.save('dist-info', 'INSTALLER', writer.name)
+##         writer.save('dist-info', 'RECORD', self.record_content)
+## 
+class BytesContent:
+    def __init__(self, content):
+        self.content = content
+    def read(self):
+        return self.content
+    def length(self):
+        return len(self.content)
+    def hash(self, name):
+        h = hashlib.new(name)
+        h.update(self.content)
+        if name == 'md5':
+            return h.hexdigest()
+        return name + '=' + base64.urlsafe_b64encode(h.digest()).decode('ascii')
+
+## # Proof of concept - may not be useful in practice as it doesn't implement all
+## # file methods.
+## class HashingFileWrapper(object):
+##     def __init__(self, fd, hashname):
+##         self.fd = fd
+##         self.hash = hashlib.new(hashname)
+##     def read(self, n):
+##         buf = self.fd.read(n)
+##         self.hash.update(buf)
+##         return buf
+##     def hexdigest(self):
+##         return self.hash.hexdigest()
+##     def digest(self):
+##         return self.hash.digest()

File pep376/test/test_distribution.py

View file
 import unittest
+import hashlib
+import base64
 import pep376
+import os
 
 class TestDistribution(unittest.TestCase):
     def setUp(self):
         new_dist = pep376.Distribution('Bar', '1.0')
         new_dist.add_file('platlib', 'foo', b'')
         self.assertEqual(new_dist.root, 'platlib')
-    def test_set_scheme(self):
-        self.assertRaises(ValueError, self.dist.set_scheme, 'foo')
     def test_relative(self):
         self.assertFalse(self.dist.relative_ok(None))
         self.assertTrue(self.dist.relative_ok('purelib'))
         self.dist.add_file('platlib', 'foo', b'')
         self.assertTrue(self.dist.relative_ok('platlib'))
-        self.dist.set_scheme('nt')
+        self.dist.locations['purelib'] = self.dist.locations['platlib']
         self.assertTrue(self.dist.relative_ok('purelib'))
-        # Can't find a way to test when platlib != purelib :-(
+        self.dist.locations['purelib'] = self.dist.locations['platlib'] + 'x'
+        self.assertFalse(self.dist.relative_ok('purelib'))
+    def test_record_data(self):
+        data = b'Hello, world!'
+        h = hashlib.new('md5')
+        h.update(data)
+        data_md5 = h.hexdigest()
+        h = hashlib.new('sha256')
+        h.update(data)
+        data_sha256 = 'sha256=' + base64.urlsafe_b64encode(h.digest()).decode('ascii')
+        self.dist.add_file('platlib', 'foo', data)
+        record = list(self.dist.get_record_data())
+        self.assertEqual(len(record), 1)
+        self.assertEqual(record[0][0], 'foo')
+        self.assertEqual(record[0][1], data_md5)
+        self.assertEqual(record[0][2], len(data))
+        record = list(self.dist.get_record_data('sha256'))
+        self.assertEqual(record[0][0], 'foo')
+        self.assertEqual(record[0][1], data_sha256)
+        self.assertEqual(record[0][2], len(data))
+    def test_record_paths(self):
+        self.dist.locations['purelib'] = '/a/b/c/pure'
+        self.dist.locations['platlib'] = '/a/b/c/plat'
+        self.dist.add_file('purelib', 'foo', b'')
+        self.dist.add_file('platlib', 'bar', b'')
+        record = list(sorted(self.dist.get_record_data()))
+        # Platform specific...
+        barpath = os.path.normpath('/a/b/c/plat/bar')
+        self.assertEqual(record[0][0], barpath)
+        self.assertEqual(record[1][0], 'foo')
+
+
+class DummyWriter:
+    def __init__(self):
+        self.written = {}
+    def save(self, location, filename, data):
+        self.written[(location, filename)] = data