Add a class-loading module.
[pycfml.git] / classfile / classpath.py
1 import os, zipfile
2 from . import file
3
4 class dir(object):
5     def __init__(self, path):
6         self.path = path
7
8     def get(self, name):
9         if '.' in name:
10             raise FileNotFoundError(name)
11         els = name.split('/')
12         fn = os.path.join(self.path, *els[:-1], els[-1] + ".class")
13         with open(fn, "rb") as fp:
14             return file.classfile.load(fp)
15
16 class jar(object):
17     def __init__(self, filename):
18         self.filename = filename
19
20     def get(self, name):
21         with zipfile.ZipFile(self.filename) as jar:
22             fn = name + ".class"
23             try:
24                 fp = jar.open(fn, "r")
25             except KeyError:
26                 raise FileNotFoundError(name)
27             with fp:
28                 return file.classfile.load(fp)
29
30 class path(object):
31     def __init__(self, *ents, caching=True):
32         self.ents = ents
33         self.cache = {} if caching else None
34
35     def get(self, name):
36         if self.cache is not None and name in self.cache:
37             return self.cache[name]
38         for ent in self.ents:
39             try:
40                 ret = ent.get(name)
41                 break;
42             except FileNotFoundError:
43                 pass
44         else:
45             raise FileNotFoundError(name)
46         if self.cache is not None:
47             self.cache[name] = ret
48         return ret