mirror of
https://github.com/joshuadavidthomas/django-language-server.git
synced 2025-07-09 21:54:59 +00:00
Add support for system-wide installation (#62)
This commit is contained in:
parent
84d87a8857
commit
b33d3f890d
4 changed files with 122 additions and 17 deletions
|
@ -6,3 +6,5 @@ edition = "2021"
|
|||
[dependencies]
|
||||
pyo3 = { workspace = true }
|
||||
tower-lsp = { workspace = true }
|
||||
|
||||
which = "7.0.1"
|
||||
|
|
|
@ -3,12 +3,15 @@ mod templatetags;
|
|||
pub use templatetags::TemplateTags;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use std::fmt;
|
||||
use std::path::{Path, PathBuf};
|
||||
use tower_lsp::lsp_types::*;
|
||||
use which::which;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DjangoProject {
|
||||
path: PathBuf,
|
||||
env: Option<PythonEnvironment>,
|
||||
template_tags: Option<TemplateTags>,
|
||||
}
|
||||
|
||||
|
@ -16,6 +19,7 @@ impl DjangoProject {
|
|||
pub fn new(path: PathBuf) -> Self {
|
||||
Self {
|
||||
path,
|
||||
env: None,
|
||||
template_tags: None,
|
||||
}
|
||||
}
|
||||
|
@ -36,19 +40,37 @@ impl DjangoProject {
|
|||
}
|
||||
|
||||
pub fn initialize(&mut self) -> PyResult<()> {
|
||||
let python_env = PythonEnvironment::new().ok_or_else(|| {
|
||||
PyErr::new::<pyo3::exceptions::PyRuntimeError, _>("Could not find Python in PATH")
|
||||
})?;
|
||||
|
||||
Python::with_gil(|py| {
|
||||
// Add project to Python path
|
||||
let sys = py.import("sys")?;
|
||||
let py_path = sys.getattr("path")?;
|
||||
py_path.call_method1("append", (self.path.to_str().unwrap(),))?;
|
||||
|
||||
// Setup Django
|
||||
let django = py.import("django")?;
|
||||
django.call_method0("setup")?;
|
||||
if let Some(path_str) = self.path.to_str() {
|
||||
py_path.call_method1("insert", (0, path_str))?;
|
||||
}
|
||||
|
||||
self.template_tags = Some(TemplateTags::from_python(py)?);
|
||||
for path in &python_env.sys_path {
|
||||
if let Some(path_str) = path.to_str() {
|
||||
py_path.call_method1("append", (path_str,))?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
self.env = Some(python_env);
|
||||
|
||||
match py.import("django") {
|
||||
Ok(django) => {
|
||||
django.call_method0("setup")?;
|
||||
self.template_tags = Some(TemplateTags::from_python(py)?);
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Failed to import Django: {}", e);
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -60,3 +82,65 @@ impl DjangoProject {
|
|||
&self.path
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for DjangoProject {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "Project path: {}", self.path.display())?;
|
||||
if let Some(py_env) = &self.env {
|
||||
write!(f, "{}", py_env)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PythonEnvironment {
|
||||
python_path: PathBuf,
|
||||
sys_path: Vec<PathBuf>,
|
||||
sys_prefix: PathBuf,
|
||||
}
|
||||
|
||||
impl PythonEnvironment {
|
||||
fn new() -> Option<Self> {
|
||||
let python_path = which("python").ok()?;
|
||||
let prefix = python_path.parent()?.parent()?;
|
||||
|
||||
let mut sys_path = Vec::new();
|
||||
sys_path.push(prefix.join("bin"));
|
||||
|
||||
if let Some(site_packages) = Self::find_site_packages(prefix) {
|
||||
sys_path.push(site_packages);
|
||||
}
|
||||
|
||||
Some(Self {
|
||||
python_path: python_path.clone(),
|
||||
sys_path,
|
||||
sys_prefix: prefix.to_path_buf(),
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn find_site_packages(prefix: &Path) -> Option<PathBuf> {
|
||||
Some(prefix.join("Lib").join("site-packages"))
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn find_site_packages(prefix: &Path) -> Option<PathBuf> {
|
||||
std::fs::read_dir(prefix.join("lib"))
|
||||
.ok()?
|
||||
.filter_map(Result::ok)
|
||||
.find(|e| e.file_name().to_string_lossy().starts_with("python"))
|
||||
.map(|e| e.path().join("site-packages"))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PythonEnvironment {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "Sys prefix: {}", self.sys_prefix.display())?;
|
||||
writeln!(f, "Sys paths:")?;
|
||||
for path in &self.sys_path {
|
||||
writeln!(f, " {}", path.display())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue