66 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			66 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Python
		
	
	
	
 | 
						|
def pytest_addoption(parser):
 | 
						|
    group = parser.getgroup("general")
 | 
						|
    group._addoption('-k',
 | 
						|
        action="store", dest="keyword", default='',
 | 
						|
        help="only run test items matching the given "
 | 
						|
             "space separated keywords.  precede a keyword with '-' to negate. "
 | 
						|
             "Terminate the expression with ':' to treat a match as a signal "
 | 
						|
             "to run all subsequent tests. ")
 | 
						|
 | 
						|
def pytest_collection_modifyitems(items, config):
 | 
						|
    keywordexpr = config.option.keyword
 | 
						|
    if not keywordexpr:
 | 
						|
        return
 | 
						|
    selectuntil = False
 | 
						|
    if keywordexpr[-1] == ":":
 | 
						|
        selectuntil = True
 | 
						|
        keywordexpr = keywordexpr[:-1]
 | 
						|
 | 
						|
    remaining = []
 | 
						|
    deselected = []
 | 
						|
    for colitem in items:
 | 
						|
        if keywordexpr and skipbykeyword(colitem, keywordexpr):
 | 
						|
            deselected.append(colitem)
 | 
						|
        else:
 | 
						|
            remaining.append(colitem)
 | 
						|
            if selectuntil:
 | 
						|
                keywordexpr = None
 | 
						|
 | 
						|
    if deselected:
 | 
						|
        config.hook.pytest_deselected(items=deselected)
 | 
						|
        items[:] = remaining
 | 
						|
 | 
						|
def skipbykeyword(colitem, keywordexpr):
 | 
						|
    """ return True if they given keyword expression means to
 | 
						|
        skip this collector/item.
 | 
						|
    """
 | 
						|
    if not keywordexpr:
 | 
						|
        return
 | 
						|
    chain = colitem.listchain()
 | 
						|
    for key in filter(None, keywordexpr.split()):
 | 
						|
        eor = key[:1] == '-'
 | 
						|
        if eor:
 | 
						|
            key = key[1:]
 | 
						|
        if not (eor ^ matchonekeyword(key, chain)):
 | 
						|
            return True
 | 
						|
 | 
						|
def matchonekeyword(key, chain):
 | 
						|
    elems = key.split(".")
 | 
						|
    # XXX O(n^2), anyone cares?
 | 
						|
    chain = [item.keywords for item in chain if item.keywords]
 | 
						|
    for start, _ in enumerate(chain):
 | 
						|
        if start + len(elems) > len(chain):
 | 
						|
            return False
 | 
						|
        for num, elem in enumerate(elems):
 | 
						|
            for keyword in chain[num + start]:
 | 
						|
                ok = False
 | 
						|
                if elem in keyword:
 | 
						|
                    ok = True
 | 
						|
                    break
 | 
						|
            if not ok:
 | 
						|
                break
 | 
						|
        if num == len(elems) - 1 and ok:
 | 
						|
            return True
 | 
						|
    return False
 |