aider: Added in-memory cache to get_tags function using a tuple (filename, root_dname) as the cache key.

# Context:
USER: add an in memory cache to get_tags that only updates if the st_mtime of the filename changes
ASSISTANT: To implement an in-memory cache for the `get_tags` function, we will need to modify the `aider/ctags.py` file. We will use a dictionary to store the cache and check the file's modification time to decide whether to update the cache or not.

Here are the steps to implement the cache:

1. Create a global variable `TAGS_CACHE` to store the cache.
2. In the `get_tags` function, check if the filename is in the cache and if the modification time has not changed.
3. If the conditions in step 2 are met, return the cached value.
4. If the conditions in step 2 are not met, update the cache with the new tags and return them.

Here are the changes to the `aider/ctags.py` file:

```python
aider/ctags.py
<<<<<<< ORIGINAL
import os
import json
import sys
import subprocess

# from aider.dump import dump
=======
import os
import json
import sys
import subprocess

# Global cache for tags
TAGS_CACHE = {}

# from aider.dump import dump
>>>>>>> UPDATED
```

```python
aider/ctags.py
<<<<<<< ORIGINAL
def get_tags(filename, root_dname):
    cmd = ["ctags", "--fields=+S", "--output-format=json", filename]
    output = subprocess.check_output(cmd).decode("utf-8")
    output = output.splitlines()
=======
def get_tags(filename, root_dname):
    # Check if the file is in the cache and if the modification time has not changed
    file_mtime = os.path.getmtime(filename)
    if filename in TAGS_CACHE and TAGS_CACHE[filename]["mtime"] == file_mtime:
        return TAGS_CACHE[filename]["tags"]

    cmd = ["ctags", "--fields=+S", "--output-format=json", filename]
    output = subprocess.check_output(cmd).decode("utf-8")
    output = output.splitlines()
>>>>>>> UPDATED
```

```python
aider/ctags.py
<<<<<<< ORIGINAL
    for line in output:
        tag = json.loads(line)
        path = tag.get("path")
        scope = tag.get("scope")
        kind = tag.get("kind")
        name = tag.get("name")
        signature = tag.get("signature")

        last = name
        if signature:
            last += " " + signature

        res = split_path(path, root_dname)
        if scope:
            res.append(scope)
        res += [kind, last]

        yield res
=======
    tags = []
    for line in output:
        tag = json.loads(line)
        path = tag.get("path")
        scope = tag.get("scope")
        kind = tag.get("kind")
        name = tag.get("name")
        signature = tag.get("signature")

        last = name
        if signature:
            last += " " + signature

        res = split_path(path, root_dname)
        if scope:
            res.append(scope)
        res += [kind, last]
        tags.append(res)

    #
^C KeyboardInterrupt
USER: sorry, please do that again. but set key=(filename, root_dname) and use that as the cache key
ASSISTANT: No problem. I will modify the cache implementation to use a tuple (filename, root_dname) as the cache key. Here are the updated changes to the `aider/ctags.py` file:

```python
aider/ctags.py
<<<<<<< ORIGINAL
import os
import json
import sys
import subprocess

# from aider.dump import dump
=======
import os
import json
import sys
import subprocess

# Global cache for tags
TAGS_CACHE = {}

# from aider.dump import dump
>>>>>>> UPDATED
```

```python
aider/ctags.py
<<<<<<< ORIGINAL
def get_tags(filename, root_dname):
    cmd = ["ctags", "--fields=+S", "--output-format=json", filename]
    output = subprocess.check_output(cmd).decode("utf-8")
    output = output.splitlines()
=======
def get_tags(filename, root_dname):
    # Check if the file is in the cache and if the modification time has not changed
    file_mtime = os.path.getmtime(filename)
    cache_key = (filename, root_dname)
    if cache_key in TAGS_CACHE and TAGS_CACHE[cache_key]["mtime"] == file_mtime:
        return TAGS_CACHE[cache_key]["tags"]

    cmd = ["ctags", "--fields=+S", "--output-format=json", filename]
    output = subprocess.check_output(cmd).decode("utf-8")
    output = output.splitlines()
>>>>>>> UPDATED
```

```python
aider/ctags.py
<<<<<<< ORIGINAL
    for line in output:
        tag = json.loads(line)
        path = tag.get("path")
        scope = tag.get("scope")
        kind = tag.get("kind")
        name = tag.get("name")
        signature = tag.get("signature")

        last = name
        if signature:
            last += " " + signature

        res = split_path(path, root_dname)
        if scope:
            res.append(scope)
        res += [kind, last]

        yield res
=======
    tags = []
    for line in output:
        tag = json.loads(line)
        path = tag.get("path")
        scope = tag.get("scope")
        kind = tag.get("kind")
        name = tag.get("name")
        signature = tag.get("signature")

        last = name
        if signature:
            last += " " + signature

        res = split_path(path, root_dname)
        if scope:
            res.append(scope)
        res += [kind, last]
        tags.append(res)

    # Update the cache
    TAGS_CACHE[cache_key] = {"mtime": file_mtime, "tags": tags}

    return tags
>>>>>>> UPDATED
```
This commit is contained in:
Paul Gauthier 2023-05-19 10:32:02 -07:00
parent 9a243d7adc
commit 046e6ed9d4

View file

@ -3,6 +3,9 @@ import json
import sys import sys
import subprocess import subprocess
# Global cache for tags
TAGS_CACHE = {}
# from aider.dump import dump # from aider.dump import dump
@ -50,6 +53,12 @@ def split_path(path, root_dname):
def get_tags(filename, root_dname): def get_tags(filename, root_dname):
# Check if the file is in the cache and if the modification time has not changed
file_mtime = os.path.getmtime(filename)
cache_key = (filename, root_dname)
if cache_key in TAGS_CACHE and TAGS_CACHE[cache_key]["mtime"] == file_mtime:
return TAGS_CACHE[cache_key]["tags"]
cmd = ["ctags", "--fields=+S", "--output-format=json", filename] cmd = ["ctags", "--fields=+S", "--output-format=json", filename]
output = subprocess.check_output(cmd).decode("utf-8") output = subprocess.check_output(cmd).decode("utf-8")
output = output.splitlines() output = output.splitlines()
@ -57,6 +66,7 @@ def get_tags(filename, root_dname):
if not output: if not output:
yield split_path(filename, root_dname) yield split_path(filename, root_dname)
tags = []
for line in output: for line in output:
tag = json.loads(line) tag = json.loads(line)
path = tag.get("path") path = tag.get("path")
@ -73,8 +83,12 @@ def get_tags(filename, root_dname):
if scope: if scope:
res.append(scope) res.append(scope)
res += [kind, last] res += [kind, last]
tags.append(res)
yield res # Update the cache
TAGS_CACHE[cache_key] = {"mtime": file_mtime, "tags": tags}
return tags
if __name__ == "__main__": if __name__ == "__main__":