def collect_feature_locations(paths, strict=True): """ Collect feature file names by processing list of paths (from command line). A path can be a: * filename (ending with ".feature") * location, ala "{filename}:{line_number}" * features configuration filename, ala "@features.txt" * directory, to discover and collect all "*.feature" files below. :param paths: Paths to process. :return: Feature file locations to use (as list of FileLocations). """ locations = [] for path in paths: if os.path.isdir(path): for dirpath, dirnames, filenames in os.walk(path): dirnames.sort() for filename in sorted(filenames): if filename.endswith(".feature"): location = FileLocation(os.path.join(dirpath, filename)) locations.append(location) elif path.startswith('@'): # -- USE: behave @list_of_features.txt locations.extend(parse_feature_listfile(path[1:])) else: # -- OTHERWISE: Normal filename or location (schema: filename:line) location = FileLocationParser.parse(path) if not location.filename.endswith(".feature"): raise InvalidFilenameError(location.filename) elif location.exists(): locations.append(location) elif strict: raise FileNotFoundError(path) return locations
def collect_feature_locations(paths, strict=True): """ Collect feature file names by processing list of paths (from command line). A path can be a: * filename (ending with ".feature") * location, ala "{filename}:{line_number}" * features configuration filename, ala "@features.txt" * directory, to discover and collect all "*.feature" files below. :param paths: Paths to process. :return: Feature file locations to use (as list of FileLocations). """ locations = [] for path in paths: if os.path.isdir(path): for dirpath, dirnames, filenames in os.walk(path): dirnames.sort() for filename in sorted(filenames): if filename.endswith(".feature"): location = FileLocation(os.path.join(dirpath, filename)) locations.append(location) elif path.startswith('@'): # -- USE: behave @list_of_features.txt locations.extend(FeatureListParser.parse_file(path[1:])) else: # -- OTHERWISE: Normal filename or location (schema: filename:line) location = FileLocationParser.parse(path) if not location.filename.endswith(".feature"): raise InvalidFilenameError(location.filename) elif location.exists(): locations.append(location) elif strict: raise FileNotFoundError(path) return locations
def parse(cls, text): match = cls.pattern.match(text) if match: filename = match.group("filename").strip() line = int(match.group("line")) return FileLocation(filename, line) else: # -- NORMAL PATH/FILENAME: filename = text.strip() return FileLocation(filename)
def parse_features(feature_files, language=None): """ Parse feature files and return list of Feature model objects. Handles: * feature file names, ala "alice.feature" * feature file locations, ala: "alice.feature:10" :param feature_files: List of feature file names to parse. :param language: Default language to use. :return: List of feature objects. """ scenario_collector = FeatureScenarioLocationCollector() features = [] for location in feature_files: if not isinstance(location, FileLocation): assert isinstance(location, basestring) location = FileLocation(os.path.normpath(location)) if location.filename == scenario_collector.filename: scenario_collector.add_location(location) continue elif scenario_collector.feature: # -- ADD CURRENT FEATURE: As collection of scenarios. current_feature = scenario_collector.build_feature() features.append(current_feature) scenario_collector.clear() # -- NEW FEATURE: assert isinstance(location, FileLocation) filename = os.path.abspath(location.filename) feature = parser.parse_file(filename, language=language) if feature: # -- VALID FEATURE: # SKIP CORNER-CASE: Feature file without any feature(s). scenario_collector.feature = feature scenario_collector.add_location(location) # -- FINALLY: if scenario_collector.feature: current_feature = scenario_collector.build_feature() features.append(current_feature) return features