Skip to content

Commit 5cb57cd

Browse files
committed
Adds get_source_file(s)
1 parent 760d3a7 commit 5cb57cd

2 files changed

Lines changed: 109 additions & 9 deletions

File tree

vunit/test/unit/test_ui.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,45 @@ def test_no_exception_on_adding_zero_files_when_allowed(self):
167167
lib = ui.library("lib")
168168
lib.add_source_files(join(dirname(__file__), 'missing.vhd'), allow_empty=True)
169169

170+
def test_get_source_files(self):
171+
ui = self._create_ui()
172+
lib1 = ui.add_library("lib1")
173+
lib2 = ui.add_library("lib2")
174+
file_name = self.create_entity_file()
175+
lib1.add_source_file(file_name)
176+
lib2.add_source_file(file_name)
177+
178+
self.assertEqual(len(ui.get_source_files(file_name)), 2)
179+
self.assertEqual(len(lib1.get_source_files(file_name)), 1)
180+
self.assertEqual(len(lib2.get_source_files(file_name)), 1)
181+
182+
ui.get_source_file(file_name, library_name="lib1")
183+
ui.get_source_file(file_name, library_name="lib2")
184+
lib1.get_source_file(file_name)
185+
lib2.get_source_file(file_name)
186+
187+
def test_get_source_files_errors(self):
188+
ui = self._create_ui()
189+
lib1 = ui.add_library("lib1")
190+
lib2 = ui.add_library("lib2")
191+
file_name = self.create_entity_file()
192+
lib1.add_source_file(file_name)
193+
lib2.add_source_file(file_name)
194+
non_existant_name = "non_existant"
195+
196+
self.assertRaisesRegexp(ValueError, ".*%s.*allow_empty.*" % non_existant_name,
197+
ui.get_source_files, non_existant_name)
198+
self.assertEqual(len(ui.get_source_files(non_existant_name, allow_empty=True)), 0)
199+
200+
self.assertRaisesRegexp(ValueError, ".*named.*%s.*multiple.*library_name.*" % file_name,
201+
ui.get_source_file, file_name)
202+
203+
self.assertRaisesRegexp(ValueError, ".*Found no file named.*%s'" % non_existant_name,
204+
ui.get_source_file, non_existant_name)
205+
206+
self.assertRaisesRegexp(ValueError, ".*Found no file named.*%s.* in library 'lib1'" % non_existant_name,
207+
ui.get_source_file, non_existant_name, "lib1")
208+
170209
def _test_pre_config_helper(self, retval, test_not_entity=False):
171210
"""
172211
Helper method to test pre_config where the pre config can return different values

vunit/ui.py

Lines changed: 70 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import os
1616
import traceback
1717

18-
from os.path import exists, abspath, join, basename, splitext
18+
from os.path import exists, relpath, abspath, join, basename, splitext
1919
from glob import glob
2020
from fnmatch import fnmatch
2121
from vunit.database import PickledDataBase, DataBase
@@ -247,6 +247,47 @@ def disable_ieee_warnings(self):
247247
"""
248248
self._configuration.disable_ieee_warnings(scope=create_scope())
249249

250+
def get_source_file(self, file_name, library_name=None):
251+
"""
252+
Get specific source file in specfic or any library.
253+
Error if multiple matches.
254+
"""
255+
256+
files = self.get_source_files(file_name, library_name, allow_empty=True)
257+
if len(files) > 1:
258+
raise ValueError("Found file named '%s' in multiple-libraries, "
259+
"add explicit library_name." % file_name)
260+
elif len(files) == 0:
261+
if library_name is None:
262+
raise ValueError("Found no file named '%s'" % file_name)
263+
else:
264+
raise ValueError("Found no file named '%s' in library '%s'"
265+
% (file_name, library_name))
266+
return files[0]
267+
268+
def get_source_files(self, pattern="*", library_name=None, allow_empty=False):
269+
"""
270+
Get source files matching wildcard pattern in either a specific
271+
library or all libraries
272+
"""
273+
results = []
274+
for source_file in self._project.get_source_files_in_order():
275+
if library_name is not None:
276+
if source_file.library.name != library_name:
277+
continue
278+
279+
if not (fnmatch(abspath(source_file.name), pattern) or
280+
fnmatch(relpath(source_file.name), pattern)):
281+
continue
282+
283+
results.append(FileFacade(source_file))
284+
285+
if (not allow_empty) and len(results) == 0:
286+
raise ValueError(("Pattern %r did not match any file. "
287+
"Use allow_empty=True to avoid exception,") % pattern)
288+
289+
return FileSetFacade(results)
290+
250291
def add_source_files(self, # pylint: disable=too-many-arguments
251292
pattern, library_name, preprocessors=None, include_dirs=None, allow_empty=False):
252293
"""
@@ -273,10 +314,10 @@ def add_source_file(self, file_name, library_name, preprocessors=None, include_d
273314
add_verilog_include_dir(include_dirs)
274315

275316
file_name = self._preprocess(library_name, abspath(file_name), preprocessors)
276-
return self._project.add_source_file(file_name,
277-
library_name,
278-
file_type=file_type,
279-
include_dirs=include_dirs)
317+
return FileFacade(self._project.add_source_file(file_name,
318+
library_name,
319+
file_type=file_type,
320+
include_dirs=include_dirs))
280321

281322
def _preprocess(self, library_name, file_name, preprocessors):
282323
"""
@@ -566,6 +607,12 @@ def disable_ieee_warnings(self):
566607
"""
567608
self._configuration.disable_ieee_warnings(scope=self._scope)
568609

610+
def get_source_file(self, file_name):
611+
return self._parent.get_source_files(file_name, self._library_name)
612+
613+
def get_source_files(self, pattern="*", allow_empty=False):
614+
return self._parent.get_source_files(pattern, self._library_name, allow_empty)
615+
569616
def add_source_files(self, pattern, preprocessors=None, allow_empty=False):
570617
return self._parent.add_source_files(pattern, self._library_name, preprocessors,
571618
allow_empty=allow_empty)
@@ -754,22 +801,36 @@ def disable_ieee_warnings(self):
754801
self._config.disable_ieee_warnings(scope=self._scope)
755802

756803

757-
class FileSetFacade(object):
804+
class FileSetFacade(list):
758805
"""
759-
A set of one or more files
806+
A set of several files
760807
"""
761808

762809
def __init__(self, source_files):
763-
self._source_files = source_files
810+
list.__init__(self, source_files)
764811

765812
def set_compile_option(self, name, value):
766813
"""
767814
Set compile option
768815
"""
769-
for source_file in self._source_files:
816+
for source_file in self:
770817
source_file.set_compile_option(name, value)
771818

772819

820+
class FileFacade(object):
821+
"""
822+
A single file
823+
"""
824+
def __init__(self, source_file):
825+
self._source_file = source_file
826+
827+
def set_compile_option(self, name, value):
828+
"""
829+
Set compile option
830+
"""
831+
self._source_file.set_compile_option(name, value)
832+
833+
773834
def select_vhdl_standard():
774835
"""
775836
Select VHDL standard according to environment variable VUNIT_VHDL_STANDARD

0 commit comments

Comments
 (0)