52 import collections, fnmatch, os, shlex, stat, subprocess, sys
53 from gettext
import gettext
as _
63 return basename.lower().endswith(
'.sym')
or \
64 basename.lower().endswith(
'.sym.xml')
68 Source = collections.namedtuple(
'Source', [
'callback',
'symbols',
'name'])
118 entries = (entry
for entry
in os.listdir(self.
directory)
120 os.stat(os.path.join(self.
directory, entry)).st_mode))
122 entries = (entry
for dirpath, dirnames, filenames
124 for entry
in sorted(filenames))
126 return (entry
for entry
in entries
137 path = os.path.join(self.
directory, symbol)
138 if not os.path.isfile(path):
142 for dirpath, dirnames, filenames
in \
144 if symbol
in filenames:
145 path = os.path.join(dirpath, symbol)
151 raise ValueError,
'symbol "%s" not found in library' % symbol
187 lines = _run_source_command(shlex.split(self.
list_cmd),
188 lambda f: f.readlines())
191 if not line
or line[-1] !=
'\n':
192 raise ValueError,
"Missing newline at end of command output"
194 raise ValueError,
"Command printed an empty line"
196 raise ValueError,
"Command printed line starting with '.'"
198 return (line[:-1]
for line
in lines)
203 return _run_source_command(
204 shlex.split(self.
get_cmd) + [symbol],
206 f,
'<pipe>', load_pixmaps = load_pixmaps))
223 def _run_source_command(args, callback):
224 p = subprocess.Popen(
225 args, bufsize = 4096, executable = executable,
226 stdout = subprocess.PIPE, close_fds =
True)
229 return callback(p.stdout)
236 raise ValueError,
"Library command failed [%s]: " \
237 "Uncaught signal %i" % (args[0], -p.returncode)
238 if p.returncode != 0:
239 raise ValueError,
"Library command failed [%s]: "\
240 "returned exit status %d" % (args[0], p.returncode)
252 def _update_symbol_list(source):
254 symbols =
list(source.callback.list())
256 raise TypeError,
"Failed to scan library [%s]: " \
257 "Python function returned non-list" % source.name
260 for symbol
in symbols:
261 if not isinstance(symbol, str)
and \
262 not isinstance(symbol, unicode):
263 raise TypeError,
"Non-string symbol name " \
264 "while scanning library [%s]" % source.name
266 raise ValueError,
"Duplicate symbol name " \
267 "while scanning library [%s]: %s" % (symbol, source.name)
271 source.symbols[:] = symbols
287 raise ValueError,
"Cannot add source: name not specified"
288 for source
in _sources:
289 if source.name == name:
290 raise ValueError,
"There is already a source called '%s'" % name
293 source =
Source(callback, [], name)
294 _update_symbol_list(source)
295 _sources.insert(0, source)
297 _search_cache.clear()
298 _symbol_cache.clear()
308 for source
in _sources:
309 if source.name == name:
330 newname =
'%s<%i>' % (name, i)
341 for source
in _sources:
342 _update_symbol_list(source)
344 _search_cache.clear()
345 _symbol_cache.clear()
351 _search_cache.clear()
352 _symbol_cache.clear()
365 assert source
is not None
366 assert symbol
is not None
370 return _symbol_cache[id(source), symbol]
375 data = source.callback.get(symbol)
379 raise ValueError,
"Failed to load symbol data [%s] " \
380 "from source [%s]" % (symbol, source.name)
386 _symbol_cache[id(source), symbol] = symbol_
394 del _symbol_cache[id(source), symbol]
410 return _search_cache[pattern, glob]
415 for source
in _sources:
417 for symbol
in fnmatch.filter(source.symbols, pattern):
418 result.append((source, symbol))
419 elif pattern
in source.symbols:
420 result.append((source, pattern))
422 _search_cache[pattern, glob] = result
436 raise ValueError,
"Component [%s] was not found in the " \
437 "component library" % name
440 sys.stderr.write(_(
"More than one component found "
441 "with name [%s]\n")% name)
443 source, symbol = symlist[0]
444 assert symbol == name
468 for ob
in rev.all_objects():
471 and data.symbol
not in symbols:
472 symbols.append(data.symbol)
488 for ob
in rev.all_objects():
494 if data.symbol.embedded:
501 symlist =
search(data.symbol.basename)
504 result.append(symlist[0])
506 result.sort(key =
lambda (source, symbol): symbol)
def list
Scan the directory for symbols.
Reading schematic/symbol files.
Source object representing a directory of symbol files.
def used_symbols0
Return a list of symbols used in a revision.
High-level revision proxy class.
def lookup_symbol_source
Get source for a given symbol name.
def reset
Remove all component library sources.
Source object representing a pair of symbol-generating commands.
def get_symbol
Get symbol object for a given source object and symbol name.
def read
Read a symbol or schematic file.
def lookup_source
Get a component source by name.
def sym_filename_filter
Decide based on filename whether a file in a directory source is considered a symbol.
def invalidate_symbol_data
Invalidate cached data about a symbol.
def uniquify_source_name
Make sure a source name is unique.
High-level proxy classes for the storage backend.
A particular state of the contents of a file.
Referenced symbols and pixmaps.
directory
Path to directory.
def get
Get symbol data for a given symbol name.
def list
Poll the library command for symbols.
def add_source
Add a component source to the library.
def search
Find all symbols matching a pattern.
def used_symbols1
Return a list of symbols used in a revision.
def lookup_symbol
Get symbol object for a given symbol name.
recursive
Whether to recurse into subdirectories.
list_cmd
Command and arguments for listing available symbols.
def get
Get symbol data for a given symbol name.
tuple Source
Named tuple class for storing data about a particular component source.
get_cmd
Command and arguments for retrieving symbol data.
def read_file
Read a symbol or schematic file from a file object.
def refresh
Rescan all available component libraries.