1 """In-memory representation of the dependency graph."""
5 network_offline
= 'off-line'
6 network_minimal
= 'minimal'
8 network_levels
= (network_offline
, network_minimal
, network_full
)
10 stability_levels
= {} # Name -> Stability
12 class Stability(object):
13 __slots__
= ['level', 'name', 'description']
14 def __init__(self
, level
, name
, description
):
17 self
.description
= description
18 assert name
not in stability_levels
19 stability_levels
[name
] = self
21 def __cmp__(self
, other
):
22 return cmp(self
.level
, other
.level
)
27 insecure
= Stability(0, 'insecure', 'This is a security risk')
28 buggy
= Stability(5, 'buggy', 'Known to have serious bugs')
29 developer
= Stability(10, 'developer', 'Work-in-progress - bugs likely')
30 testing
= Stability(20, 'testing', 'Stability unknown - please test!')
31 stable
= Stability(30, 'stable', 'Tested - no serious problems found')
32 preferred
= Stability(40, 'preferred', 'Best of all - must be set manually')
34 class Restriction(object):
35 """A Restriction limits the allowed implementations of an Interface."""
37 class Binding(object):
38 """Information about how the choice of a Dependency is made known
39 to the application being run."""
41 class EnvironmentBinding(Binding
):
42 __slots__
= ['name', 'insert']
44 def __init__(self
, name
, insert
):
49 return "<environ %s += %s>" % (self
.name
, self
.insert
)
51 class Dependency(object):
52 """A Dependency indicates that an Implementation requires some additional
53 code to function, specified by another Interface."""
54 __slots__
= ['interface', 'restrictions', 'bindings']
56 def __init__(self
, interface
):
57 assert isinstance(interface
, (str, unicode))
58 self
.interface
= interface
59 self
.restrictions
= []
62 def get_interface(self
):
63 return get_interface(self
.interface
)
66 return "<Dependency on %s; bindings: %d>" % (self
.interface
, len(self
.bindings
))
68 class Implementation(object):
69 """An Implementation is a package which implements an Interface."""
70 __slots__
= ['path', 'arch', 'upstream_stability', 'user_stability',
71 'version', 'size', 'dependencies', '_cached']
73 def __init__(self
, path
):
78 self
.user_stability
= None
79 self
.upstream_stability
= None
82 self
.dependencies
= {} # URI -> Dependency
84 def get_stability(self
):
85 return self
.user_stability
or self
.upstream_stability
or testing
88 if self
._cached
is None:
90 if os
.path
.exists(self
.path
):
91 cache_dir
= cache_for(self
.path
)
92 for x
in os
.listdir(cache_dir
):
93 if x
[0] == '.': continue
94 if x
== 'AppInfo.xml': continue
95 if os
.path
.isfile(os
.path
.join(cache_dir
, x
)):
100 def get_version(self
):
101 return '.'.join(map(str, self
.version
))
106 def __cmp__(self
, other
):
107 return cmp(other
.version
, self
.version
)
109 class Interface(object):
110 """An Interface represents some contract of behaviour."""
111 __slots__
= ['uri', 'implementations', 'name', 'uptodate', 'description', 'summary',
112 'stability_policy', 'last_updated']
115 # Implementations at this level or higher are preferred.
116 # Lower levels are used only if there is no other choice.
119 # The time we last updated the cached information (the time is stored
120 # in the cache). None means we haven't even read the cache yet.
122 def __init__(self
, uri
):
125 self
.implementations
= {} # Path -> Implementation
127 self
.last_updated
= None
128 self
.uptodate
= False
130 self
.description
= None
131 self
.stability_policy
= None
134 return self
.name
or '(' + os
.path
.basename(self
.uri
) + ')'
137 return "<Interface %s>" % self
.uri
139 def get_impl(self
, path
):
140 if path
not in self
.implementations
:
141 self
.implementations
[path
] = Implementation(path
)
142 return self
.implementations
[path
]
144 def set_stability_policy(self
, new
):
145 assert new
is None or isinstance(new
, Stability
)
146 self
.stability_policy
= new
149 for w
in self
.watchers(): w(self
)
151 _interfaces
= {} # URI -> Interface
153 def get_interface(uri
):
156 assert isinstance(uri
, unicode)
157 if uri
not in _interfaces
:
158 _interfaces
[uri
] = Interface(uri
)
159 return _interfaces
[uri
]
162 "Convert each space to %20, etc"
164 return re
.sub('[^-_.a-zA-Z0-9]',
165 lambda match
: '%%%02x' % ord(match
.group(0)),
168 class SafeException(Exception):
172 _cache
= os
.readlink('/uri/0install/.lazyfs-cache')
176 prefix
= '/uri/0install/'
177 if path
.startswith(prefix
) and _cache
:
178 return os
.path
.join(_cache
, path
[len(prefix
):])