1919#
2020#
2121
22+ import json
2223import os
23- import sys
24+ import urllib . parse
2425from hashlib import blake2b
26+ from importlib .metadata import Distribution , PackageNotFoundError
27+ from typing import Optional
2528
2629import synapse
2730from synapse .synapse_rust import get_rust_file_digest
@@ -32,22 +35,17 @@ def check_rust_lib_up_to_date() -> None:
3235 be rebuilt.
3336 """
3437
35- if not _dist_is_editable ():
36- return
37-
38- synapse_dir = os .path .dirname (synapse .__file__ )
39- synapse_root = os .path .abspath (os .path .join (synapse_dir , ".." ))
40-
41- # Double check we've not gone into site-packages...
42- if os .path .basename (synapse_root ) == "site-packages" :
43- return
44-
45- # ... and it looks like the root of a python project.
46- if not os .path .exists ("pyproject.toml" ):
47- return
38+ # Get the location of the editable install.
39+ synapse_root = get_synapse_source_directory ()
40+ if synapse_root is None :
41+ return None
4842
4943 # Get the hash of all Rust source files
50- hash = _hash_rust_files_in_directory (os .path .join (synapse_root , "rust" , "src" ))
44+ rust_path = os .path .join (synapse_root , "rust" , "src" )
45+ if not os .path .exists (rust_path ):
46+ return None
47+
48+ hash = _hash_rust_files_in_directory (rust_path )
5149
5250 if hash != get_rust_file_digest ():
5351 raise Exception ("Rust module outdated. Please rebuild using `poetry install`" )
@@ -82,10 +80,55 @@ def _hash_rust_files_in_directory(directory: str) -> str:
8280 return hasher .hexdigest ()
8381
8482
85- def _dist_is_editable () -> bool :
86- """Is distribution an editable install?"""
87- for path_item in sys .path :
88- egg_link = os .path .join (path_item , "matrix-synapse.egg-link" )
89- if os .path .isfile (egg_link ):
90- return True
91- return False
83+ def get_synapse_source_directory () -> Optional [str ]:
84+ """Try and find the source directory of synapse for editable installs (like
85+ those used in development).
86+
87+ Returns None if not an editable install (or otherwise can't find the source
88+ directory).
89+ """
90+
91+ # Try and find the installed matrix-synapse package.
92+ try :
93+ package = Distribution .from_name ("matrix-synapse" )
94+ except PackageNotFoundError :
95+ # The package is not found, so it's not installed and so must be being
96+ # pulled out from a local directory (usually the current one).
97+ synapse_dir = os .path .dirname (synapse .__file__ )
98+ synapse_root = os .path .abspath (os .path .join (synapse_dir , ".." ))
99+
100+ # Double check we've not gone into site-packages...
101+ if os .path .basename (synapse_root ) == "site-packages" :
102+ return None
103+
104+ # ... and it looks like the root of a python project.
105+ if not os .path .exists ("pyproject.toml" ):
106+ return None
107+
108+ return synapse_root
109+
110+ # Read the `direct_url.json` metadata for the package. This won't exist for
111+ # packages installed via a repository/etc.
112+ # c.f. https://packaging.python.org/en/latest/specifications/direct-url/
113+ direct_url_json = package .read_text ("direct_url.json" )
114+ if direct_url_json is None :
115+ return None
116+
117+ # c.f. https://packaging.python.org/en/latest/specifications/direct-url/ for
118+ # the format
119+ direct_url_dict : dict = json .loads (direct_url_json )
120+
121+ # `url` must exist as a key, and point to where we fetched the repo from.
122+ project_url = urllib .parse .urlparse (direct_url_dict ["url" ])
123+
124+ # If its not a local file then we must have built the rust libs either a)
125+ # after we downloaded the package, or b) we built the download wheel.
126+ if project_url .scheme != "file" :
127+ return None
128+
129+ # And finally if its not an editable install then the files can't have
130+ # changed since we installed the package.
131+ if not direct_url_dict .get ("dir_info" , {}).get ("editable" , False ):
132+ return None
133+
134+ return project_url .path
0 commit comments