Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
26 changes: 25 additions & 1 deletion mergin/merginproject.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
import os
import re
import shutil
import uuid
import tempfile
import uuid
import weakref
from datetime import datetime
from dateutil.tz import tzlocal

Expand Down Expand Up @@ -41,7 +42,30 @@ class MerginProject:
Linked to existing local directory, with project metadata (mergin.json) and backups located in .mergin directory.
"""

# To make sure we don't have multiple instances for a single project that
# then have out-of-date information, we keep this map of absolute project
# directory paths to instances.
# The dictionary is a WeakValueDictionary so we don't cause memory leaks
# (when the instance is GC'd, the entry is deleted).
project_cache: weakref.WeakValueDictionary[str, "MerginProject"] = weakref.WeakValueDictionary()

def __new__(cls, directory):
directory = os.path.abspath(directory)
if instance := cls.project_cache.get(directory):
return instance

instance = super().__new__(cls)
cls.project_cache[directory] = instance
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to pass project_cache to class directly?

Copy link
Author

Choose a reason for hiding this comment

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

No, it's already there since it's defined as a class property. cls.project_cache here is equivalent to MerginProject.project_cache.

return instance

def __init__(self, directory):
# __init__ still gets called after __new__, even if it returns a
# pre-existing object. Work around this by checking whether we've been
# initialised.
if hasattr(self, "_initialised"):
return
self._initialised = True

self.dir = os.path.abspath(directory)
if not os.path.exists(self.dir):
raise InvalidProject("Project directory does not exist")
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setup(
name="mergin-client",
version="0.11.0",
version="0.12.0",
url="https://github.com/MerginMaps/python-api-client",
license="MIT",
author="Lutra Consulting Ltd.",
Expand Down