Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions clcache/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ def __call__(self, parser, namespace, values, optional_string=None):

class RemainderSetAction(argparse.Action):
def __call__(self, parser, namespace, values, optional_string=None):
nonCommand = getattr(namespace, "non_command", None)
if nonCommand:
if nonCommand := getattr(namespace, "non_command", None):
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function main.RemainderSetAction.__call__ refactored with the following changes:

values.insert(0, nonCommand)
setattr(namespace, self.dest, values)

Expand Down
127 changes: 65 additions & 62 deletions clcache/caching.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,13 @@ def childDirectories(path, absolute=True):


def normalizeBaseDir(baseDir):
if baseDir:
baseDir = os.path.normcase(baseDir)
if baseDir.endswith(os.path.sep):
baseDir = baseDir[0:-1]
return baseDir
else:
if not baseDir:
# Converts empty string to None
return None
baseDir = os.path.normcase(baseDir)
if baseDir.endswith(os.path.sep):
baseDir = baseDir[:-1]
return baseDir
Comment on lines -118 to +124
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function normalizeBaseDir refactored with the following changes:



def getCachedCompilerConsoleOutput(path):
Expand Down Expand Up @@ -184,7 +183,7 @@ def __init__(self, manifestSectionDir):
self.lock = CacheLock.forPath(self.manifestSectionDir)

def manifestPath(self, manifestHash):
return os.path.join(self.manifestSectionDir, manifestHash + ".json")
return os.path.join(self.manifestSectionDir, f'{manifestHash}.json')
Comment on lines -187 to +186
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function ManifestSection.manifestPath refactored with the following changes:


def manifestFiles(self):
return filesBeneath(self.manifestSectionDir)
Expand Down Expand Up @@ -298,10 +297,14 @@ def getManifestHash(compilerBinary, commandLine, sourceFile):
for k in sorted(arguments.keys()):
if k in argumentsWithPaths:
commandLine.extend(
["/" + k + collapseBasedirInCmdPath(arg) for arg in arguments[k]]
[
f'/{k}{collapseBasedirInCmdPath(arg)}'
for arg in arguments[k]
]
)

else:
commandLine.extend(["/" + k + arg for arg in arguments[k]])
commandLine.extend([f'/{k}{arg}' for arg in arguments[k]])
Comment on lines -301 to +307
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function ManifestRepository.getManifestHash refactored with the following changes:


commandLine.extend(collapseBasedirInCmdPath(arg) for arg in inputFiles)

Expand Down Expand Up @@ -332,7 +335,7 @@ class CacheLock:
WAIT_TIMEOUT_CODE = 0x00000102

def __init__(self, mutexName, timeoutMs):
self._mutexName = "Local\\" + mutexName
self._mutexName = f'Local\\{mutexName}'
Comment on lines -335 to +338
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function CacheLock.__init__ refactored with the following changes:

self._mutex = None
self._timeoutMs = timeoutMs

Expand Down Expand Up @@ -408,7 +411,7 @@ def hasEntry(self, key):
def setEntry(self, key, artifacts):
cacheEntryDir = self.cacheEntryDir(key)
# Write new files to a temporary directory
tempEntryDir = cacheEntryDir + ".new"
tempEntryDir = f'{cacheEntryDir}.new'
Comment on lines -411 to +414
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function CompilerArtifactsSection.setEntry refactored with the following changes:

# Remove any possible left-over in tempEntryDir from previous executions
rmtree(tempEntryDir, ignore_errors=True)
ensureDirectoryExists(tempEntryDir)
Expand Down Expand Up @@ -984,27 +987,26 @@ def getCompilerHash(compilerBinary):


def getFileHashes(filePaths):
if "CLCACHE_SERVER" in os.environ:
pipeName = r"\\.\pipe\clcache_srv"
while True:
try:
with open(pipeName, "w+b") as f:
f.write("\n".join(filePaths).encode("utf-8"))
f.write(b"\x00")
response = f.read()
if response.startswith(b"!"):
raise pickle.loads(response[1:-1])
return response[:-1].decode("utf-8").splitlines()
except OSError as e:
if (
e.errno == errno.EINVAL
and windll.kernel32.GetLastError() == ERROR_PIPE_BUSY
):
windll.kernel32.WaitNamedPipeW(pipeName, NMPWAIT_WAIT_FOREVER)
else:
raise
else:
if "CLCACHE_SERVER" not in os.environ:
return [getFileHash(filePath) for filePath in filePaths]
pipeName = r"\\.\pipe\clcache_srv"
while True:
try:
with open(pipeName, "w+b") as f:
f.write("\n".join(filePaths).encode("utf-8"))
f.write(b"\x00")
response = f.read()
if response.startswith(b"!"):
raise pickle.loads(response[1:-1])
return response[:-1].decode("utf-8").splitlines()
except OSError as e:
if (
e.errno == errno.EINVAL
and windll.kernel32.GetLastError() == ERROR_PIPE_BUSY
):
windll.kernel32.WaitNamedPipeW(pipeName, NMPWAIT_WAIT_FOREVER)
else:
raise
Comment on lines -987 to +1009
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function getFileHashes refactored with the following changes:



def getFileHash(filePath, additionalData=None):
Expand All @@ -1027,29 +1029,28 @@ def getStringHash(dataString):

def expandBasedirPlaceholder(path):
baseDir = normalizeBaseDir(os.environ.get("CLCACHE_BASEDIR"))
if path.startswith(BASEDIR_REPLACEMENT):
if not baseDir:
print(
"No CLCACHE_BASEDIR set, but found relative path " + path,
file=sys.stderr,
)
sys.exit(1)
return path.replace(BASEDIR_REPLACEMENT, baseDir, 1)
else:
if not path.startswith(BASEDIR_REPLACEMENT):
return path
if not baseDir:
print(
f'No CLCACHE_BASEDIR set, but found relative path {path}',
file=sys.stderr,
)

sys.exit(1)
return path.replace(BASEDIR_REPLACEMENT, baseDir, 1)
Comment on lines -1030 to +1041
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function expandBasedirPlaceholder refactored with the following changes:



def collapseBasedirToPlaceholder(path):
baseDir = normalizeBaseDir(os.environ.get("CLCACHE_BASEDIR"))
if baseDir is None:
return path
assert path == os.path.normcase(path)
assert baseDir == os.path.normcase(baseDir)
if path.startswith(baseDir):
return path.replace(baseDir, BASEDIR_REPLACEMENT, 1)
else:
assert path == os.path.normcase(path)
assert baseDir == os.path.normcase(baseDir)
if path.startswith(baseDir):
return path.replace(baseDir, BASEDIR_REPLACEMENT, 1)
else:
return path
return path
Comment on lines +1048 to +1053
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function collapseBasedirToPlaceholder refactored with the following changes:



def ensureDirectoryExists(path):
Expand Down Expand Up @@ -1078,7 +1079,7 @@ def copyOrLink(srcFilePath, dstFilePath, writeCache=False):
# If hardlinking fails for some reason (or it's not enabled), just
# fall back to moving bytes around. Always to a temporary path first to
# lower the chances of corrupting it.
tempDst = dstFilePath + ".tmp"
tempDst = f'{dstFilePath}.tmp'
Comment on lines -1081 to +1082
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function copyOrLink refactored with the following changes:


if "CLCACHE_COMPRESS" in os.environ:
if "CLCACHE_COMPRESSLEVEL" in os.environ:
Expand Down Expand Up @@ -1170,10 +1171,9 @@ def _parseBackslash(self):
self._pos += 1
numBackslashes += 1

followedByDoubleQuote = (
if followedByDoubleQuote := (
self._pos < len(self._content) and self._content[self._pos] == '"'
)
if followedByDoubleQuote:
):
Comment on lines -1173 to +1176
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function CommandLineTokenizer._parseBackslash refactored with the following changes:

self._token += "\\" * (numBackslashes // 2)
if numBackslashes % 2 == 0:
self._pos -= 1
Expand Down Expand Up @@ -1248,7 +1248,7 @@ def __len__(self):
return len(self.name)

def __str__(self):
return "/" + self.name
return f'/{self.name}'
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function Argument.__str__ refactored with the following changes:


def __eq__(self, other):
return type(self) == type(other) and self.name == other.name
Expand Down Expand Up @@ -1328,11 +1328,14 @@ class CommandLineAnalyzer:

@staticmethod
def _getParameterizedArgumentType(cmdLineArgument):
# Sort by length to handle prefixes
for arg in CommandLineAnalyzer.argumentsWithParameterSorted:
if cmdLineArgument.startswith(arg.name, 1):
return arg
return None
return next(
(
arg
for arg in CommandLineAnalyzer.argumentsWithParameterSorted
if cmdLineArgument.startswith(arg.name, 1)
),
None,
)
Comment on lines -1331 to +1338
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function CommandLineAnalyzer._getParameterizedArgumentType refactored with the following changes:

  • Use the built-in function next instead of a for-loop (use-next)

This removes the following comments ( why? ):

# Sort by length to handle prefixes


@staticmethod
def parseArgumentsAndInputFiles(cmdline):
Expand Down Expand Up @@ -1435,10 +1438,11 @@ def analyze(cmdline: List[str]) -> Tuple[List[Tuple[str, str]], List[str]]:
if objectFiles is None:
# Generate from .c/.cpp filenames
objectFiles = [
os.path.join(prefix, basenameWithoutExtension(f)) + ".obj"
f'{os.path.join(prefix, basenameWithoutExtension(f))}.obj'
for f, _ in inputFiles
]

Comment on lines 1438 to 1444
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function CommandLineAnalyzer.analyze refactored with the following changes:


printTraceStatement("Compiler source files: {}".format(inputFiles))
printTraceStatement("Compiler object file: {}".format(objectFiles))
return inputFiles, objectFiles
Expand Down Expand Up @@ -1662,11 +1666,10 @@ def createManifestEntry(manifestHash, includePaths):
def run(cache, compiler, compiler_args, env):
printTraceStatement("Found real compiler binary at '{0!s}'".format(compiler))

if "CLCACHE_DISABLE" in os.environ:
exit_code, out, err = invokeRealCompiler(compiler, compiler_args, env)
return exit_code, [out], [err]
else:
if "CLCACHE_DISABLE" not in os.environ:
return processCompileRequest(cache, compiler, compiler_args, env)
exit_code, out, err = invokeRealCompiler(compiler, compiler_args, env)
return exit_code, [out], [err]
Comment on lines -1665 to +1672
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function run refactored with the following changes:



cache = None
Expand Down Expand Up @@ -1762,7 +1765,7 @@ def processCompileRequest(cache, compiler, args, env):
def filterSourceFiles(
cmdLine: List[str], sourceFiles: List[Tuple[str, str]]
) -> Iterator[str]:
setOfSources = set(sourceFile for sourceFile, _ in sourceFiles)
setOfSources = {sourceFile for sourceFile, _ in sourceFiles}
Comment on lines -1765 to +1768
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function filterSourceFiles refactored with the following changes:

skippedArgs = ("/Tc", "/Tp", "-Tp", "-Tc")
return (
arg
Expand Down
11 changes: 4 additions & 7 deletions clcache/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def connect(self, server):
deserializer=python_memcache_deserializer,
timeout=5,
connect_timeout=5,
key_prefix=(getStringHash(self.fileStrategy.dir) + "_").encode("UTF-8"),
key_prefix=f'{getStringHash(self.fileStrategy.dir)}_'.encode("UTF-8"),
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function CacheMemcacheStrategy.connect refactored with the following changes:

)
# XX key_prefix ties fileStrategy cache to memcache entry
# because tests currently the integration tests use this to start with clean cache
Expand Down Expand Up @@ -213,8 +213,7 @@ def getEntry(self, key):
if self.localCache.hasEntry(key):
printTraceStatement("Getting object {} from local cache".format(key))
return self.localCache.getEntry(key)
remote = self.remoteCache.getEntry(key)
if remote:
if remote := self.remoteCache.getEntry(key):
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function CacheFileWithMemcacheFallbackStrategy.getEntry refactored with the following changes:

printTraceStatement("Getting object {} from remote cache".format(key))
return remote
return None
Expand All @@ -229,14 +228,12 @@ def setManifest(self, manifestHash, manifest):
self.remoteCache.setManifest(manifestHash, manifest)

def getManifest(self, manifestHash):
local = self.localCache.getManifest(manifestHash)
if local:
if local := self.localCache.getManifest(manifestHash):
printTraceStatement(
"{} local manifest hit for {}".format(self, manifestHash)
)
return local
remote = self.remoteCache.getManifest(manifestHash)
if remote:
if remote := self.remoteCache.getManifest(manifestHash):
Comment on lines -232 to +236
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function CacheFileWithMemcacheFallbackStrategy.getManifest refactored with the following changes:

with self.localCache.manifestLockFor(manifestHash):
self.localCache.setManifest(manifestHash, remote)
printTraceStatement(
Expand Down
6 changes: 2 additions & 4 deletions tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,8 @@ def testRecompileObjectSetOtherDir(self):

def testPipedOutput(self):
def debugLinebreaks(text):
out = []
lines = text.splitlines(True)
for line in lines:
out.append(line.replace("\r", "<CR>").replace("\n", "<LN>"))
out = [line.replace("\r", "<CR>").replace("\n", "<LN>") for line in lines]
Comment on lines -159 to +160
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function TestCompileRuns.testPipedOutput.debugLinebreaks refactored with the following changes:

return "\n".join(out)

commands = [
Expand Down Expand Up @@ -845,7 +843,7 @@ def testOutput(self):
clcache.Cache(tempDir)
customEnv = self._createEnv(tempDir)
cmd = CLCACHE_CMD + ["/nologo", "/EHsc", "/c"]
mpFlag = "/MP" + str(len(sources))
mpFlag = f'/MP{len(sources)}'
Comment on lines -848 to +846
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function RunParallelBase.testOutput refactored with the following changes:

out = subprocess.check_output(cmd + [mpFlag] + sources, env=customEnv).decode("ascii")
# print the output so that it shows up in py.test
print(out)
Expand Down
7 changes: 4 additions & 3 deletions tests/test_performance.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ def setUpClass(cls):
os.path.join(ASSETS_DIR, 'concurrency', 'file{:02d}.cpp'.format(i+1))
)

cls.sources = []
for i in range(1, TestConcurrency.NUM_SOURCE_FILES+1):
cls.sources.append(os.path.join(ASSETS_DIR, 'concurrency', 'file{:02d}.cpp'.format(i)))
cls.sources = [
os.path.join(ASSETS_DIR, 'concurrency', 'file{:02d}.cpp'.format(i))
for i in range(1, TestConcurrency.NUM_SOURCE_FILES + 1)
]
Comment on lines -48 to +51
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function TestConcurrency.setUpClass refactored with the following changes:


def testConcurrentHitsScaling(self):
with tempfile.TemporaryDirectory() as tempDir:
Expand Down
6 changes: 1 addition & 5 deletions tests/test_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -521,10 +521,6 @@ def _testSourceFilesOk(self, cmdLine):
except AnalysisError as err:
if isinstance(err, NoSourceFileError):
self.fail("analyze() unexpectedly raised an NoSourceFileError")
else:
# We just want to know if we got a proper source file.
# Other AnalysisErrors are ignored.
pass
Comment on lines -524 to -527
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function TestAnalyzeCommandLine._testSourceFilesOk refactored with the following changes:

This removes the following comments ( why? ):

# Other AnalysisErrors are ignored.
# We just want to know if we got a proper source file.


def _testFailure(self, cmdLine, expectedExceptionClass):
self.assertRaises(expectedExceptionClass, lambda: CommandLineAnalyzer.analyze(cmdLine))
Expand Down Expand Up @@ -1133,7 +1129,7 @@ def assertEntrySizeIsCorrect(self, expectedSize):
srcFilePath = os.path.join(self.testDir, "src")
dstFilePath = os.path.join(self.testDir, "dst")
with open(srcFilePath, "wb") as f:
for i in range(0, 999):
for i in range(999):
Comment on lines -1136 to +1132
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function TestCompression.assertEntrySizeIsCorrect refactored with the following changes:

f.write(b"%d" % i)
copyOrLink(srcFilePath, dstFilePath, True)
size = os.path.getsize(dstFilePath)
Expand Down