Compare commits
	
		
			2 Commits 
		
	
	
		
			81c33bf550
			...
			01f38d2f22
		
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								 | 
						01f38d2f22 | |
| 
							
							
								 | 
						6b3cc72e5c | 
| 
						 | 
				
			
			@ -63,11 +63,11 @@ dev = [
 | 
			
		|||
  "stackscope>=0.2.2,<0.3",
 | 
			
		||||
  # ^ requires this?
 | 
			
		||||
  "typing-extensions>=4.14.1",
 | 
			
		||||
 | 
			
		||||
  "pyperclip>=1.9.0",
 | 
			
		||||
  "prompt-toolkit>=3.0.50",
 | 
			
		||||
  "xonsh>=0.19.2",
 | 
			
		||||
  "psutil>=7.0.0",
 | 
			
		||||
  "platformdirs>=4.4.0",
 | 
			
		||||
]
 | 
			
		||||
# TODO, add these with sane versions; were originally in
 | 
			
		||||
# `requirements-docs.txt`..
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,14 +2,12 @@
 | 
			
		|||
`tractor.log`-wrapping unit tests.
 | 
			
		||||
 | 
			
		||||
'''
 | 
			
		||||
import importlib
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
import shutil
 | 
			
		||||
import sys
 | 
			
		||||
from types import ModuleType
 | 
			
		||||
 | 
			
		||||
import pytest
 | 
			
		||||
import tractor
 | 
			
		||||
from tractor import _code_load
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_root_pkg_not_duplicated_in_logger_name():
 | 
			
		||||
| 
						 | 
				
			
			@ -37,31 +35,6 @@ def test_root_pkg_not_duplicated_in_logger_name():
 | 
			
		|||
    assert 'mod' not in sublog.name
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# ?TODO, move this into internal libs?
 | 
			
		||||
# -[ ] we already use it in `modden.config._pymod` as well
 | 
			
		||||
def load_module_from_path(
 | 
			
		||||
    path: Path,
 | 
			
		||||
    module_name: str|None = None,
 | 
			
		||||
) -> ModuleType:
 | 
			
		||||
    '''
 | 
			
		||||
    Taken from SO,
 | 
			
		||||
    https://stackoverflow.com/a/67208147
 | 
			
		||||
 | 
			
		||||
    which is based on stdlib docs,
 | 
			
		||||
    https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
 | 
			
		||||
 | 
			
		||||
    '''
 | 
			
		||||
    module_name = module_name or path.stem
 | 
			
		||||
    spec = importlib.util.spec_from_file_location(
 | 
			
		||||
        module_name,
 | 
			
		||||
        str(path),
 | 
			
		||||
    )
 | 
			
		||||
    module = importlib.util.module_from_spec(spec)
 | 
			
		||||
    sys.modules[module_name] = module
 | 
			
		||||
    spec.loader.exec_module(module)
 | 
			
		||||
    return module
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_implicit_mod_name_applied_for_child(
 | 
			
		||||
    testdir: pytest.Pytester,
 | 
			
		||||
    loglevel: str,
 | 
			
		||||
| 
						 | 
				
			
			@ -109,7 +82,7 @@ def test_implicit_mod_name_applied_for_child(
 | 
			
		|||
    # XXX NOTE, once the "top level" pkg mod has been
 | 
			
		||||
    # imported, we can then use `import` syntax to
 | 
			
		||||
    # import it's sub-pkgs and modules.
 | 
			
		||||
    pkgmod = load_module_from_path(
 | 
			
		||||
    pkgmod = _code_load.load_module_from_path(
 | 
			
		||||
        Path(pkg / '__init__.py'),
 | 
			
		||||
        module_name=proj_name,
 | 
			
		||||
    )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,48 @@
 | 
			
		|||
# tractor: structured concurrent "actors".
 | 
			
		||||
# Copyright 2018-eternity Tyler Goodlet.
 | 
			
		||||
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU Affero General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU Affero General Public License for more details.
 | 
			
		||||
 | 
			
		||||
# You should have received a copy of the GNU Affero General Public License
 | 
			
		||||
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
'''
 | 
			
		||||
(Hot) coad (re-)load utils for python.
 | 
			
		||||
 | 
			
		||||
'''
 | 
			
		||||
import importlib
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
import sys
 | 
			
		||||
from types import ModuleType
 | 
			
		||||
 | 
			
		||||
# ?TODO, move this into internal libs?
 | 
			
		||||
# -[ ] we already use it in `modden.config._pymod` as well
 | 
			
		||||
def load_module_from_path(
 | 
			
		||||
    path: Path,
 | 
			
		||||
    module_name: str|None = None,
 | 
			
		||||
) -> ModuleType:
 | 
			
		||||
    '''
 | 
			
		||||
    Taken from SO,
 | 
			
		||||
    https://stackoverflow.com/a/67208147
 | 
			
		||||
 | 
			
		||||
    which is based on stdlib docs,
 | 
			
		||||
    https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
 | 
			
		||||
 | 
			
		||||
    '''
 | 
			
		||||
    module_name = module_name or path.stem
 | 
			
		||||
    spec = importlib.util.spec_from_file_location(
 | 
			
		||||
        module_name,
 | 
			
		||||
        str(path),
 | 
			
		||||
    )
 | 
			
		||||
    module = importlib.util.module_from_spec(spec)
 | 
			
		||||
    sys.modules[module_name] = module
 | 
			
		||||
    spec.loader.exec_module(module)
 | 
			
		||||
    return module
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +22,6 @@ from __future__ import annotations
 | 
			
		|||
from contextvars import (
 | 
			
		||||
    ContextVar,
 | 
			
		||||
)
 | 
			
		||||
import os
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
from typing import (
 | 
			
		||||
    Any,
 | 
			
		||||
| 
						 | 
				
			
			@ -30,6 +29,7 @@ from typing import (
 | 
			
		|||
    TYPE_CHECKING,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
import platformdirs
 | 
			
		||||
from trio.lowlevel import current_task
 | 
			
		||||
 | 
			
		||||
if TYPE_CHECKING:
 | 
			
		||||
| 
						 | 
				
			
			@ -172,22 +172,31 @@ def current_ipc_ctx(
 | 
			
		|||
    return ctx
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# std ODE (mutable) app state location
 | 
			
		||||
_rtdir: Path = Path(os.environ['XDG_RUNTIME_DIR'])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_rt_dir(
 | 
			
		||||
    subdir: str = 'tractor'
 | 
			
		||||
    subdir: str|Path|None = None,
 | 
			
		||||
) -> Path:
 | 
			
		||||
    '''
 | 
			
		||||
    Return the user "runtime dir" where most userspace apps stick
 | 
			
		||||
    their IPC and cache related system util-files; we take hold
 | 
			
		||||
    of a `'XDG_RUNTIME_DIR'/tractor/` subdir by default.
 | 
			
		||||
    Return the user "runtime dir", the file-sys location where most
 | 
			
		||||
    userspace apps stick their IPC and cache related system
 | 
			
		||||
    util-files.
 | 
			
		||||
 | 
			
		||||
    On linux we take use a `'${XDG_RUNTIME_DIR}/tractor/` subdir by
 | 
			
		||||
    default but equivalents are mapped for each platform using
 | 
			
		||||
    the lovely `platformdirs`.
 | 
			
		||||
 | 
			
		||||
    '''
 | 
			
		||||
    rtdir: Path = _rtdir / subdir
 | 
			
		||||
    _rt_dir: Path = Path(
 | 
			
		||||
        platformdirs.user_runtime_dir(
 | 
			
		||||
            appname='tractor',
 | 
			
		||||
        ),
 | 
			
		||||
    )
 | 
			
		||||
    if subdir:
 | 
			
		||||
        rtdir: Path = _rt_dir / subdir
 | 
			
		||||
 | 
			
		||||
    if not rtdir.is_dir():
 | 
			
		||||
        rtdir.mkdir()
 | 
			
		||||
 | 
			
		||||
    return rtdir
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										13
									
								
								uv.lock
								
								
								
								
							
							
						
						
									
										13
									
								
								uv.lock
								
								
								
								
							| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
version = 1
 | 
			
		||||
revision = 2
 | 
			
		||||
revision = 3
 | 
			
		||||
requires-python = ">=3.11"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
| 
						 | 
				
			
			@ -236,6 +236,15 @@ wheels = [
 | 
			
		|||
    { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" },
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "platformdirs"
 | 
			
		||||
version = "4.4.0"
 | 
			
		||||
source = { registry = "https://pypi.org/simple" }
 | 
			
		||||
sdist = { url = "https://files.pythonhosted.org/packages/23/e8/21db9c9987b0e728855bd57bff6984f67952bea55d6f75e055c46b5383e8/platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf", size = 21634, upload-time = "2025-08-26T14:32:04.268Z" }
 | 
			
		||||
wheels = [
 | 
			
		||||
    { url = "https://files.pythonhosted.org/packages/40/4b/2028861e724d3bd36227adfa20d3fd24c3fc6d52032f4a93c133be5d17ce/platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85", size = 18654, upload-time = "2025-08-26T14:32:02.735Z" },
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "pluggy"
 | 
			
		||||
version = "1.5.0"
 | 
			
		||||
| 
						 | 
				
			
			@ -387,6 +396,7 @@ dependencies = [
 | 
			
		|||
dev = [
 | 
			
		||||
    { name = "greenback" },
 | 
			
		||||
    { name = "pexpect" },
 | 
			
		||||
    { name = "platformdirs" },
 | 
			
		||||
    { name = "prompt-toolkit" },
 | 
			
		||||
    { name = "psutil" },
 | 
			
		||||
    { name = "pyperclip" },
 | 
			
		||||
| 
						 | 
				
			
			@ -412,6 +422,7 @@ requires-dist = [
 | 
			
		|||
dev = [
 | 
			
		||||
    { name = "greenback", specifier = ">=1.2.1,<2" },
 | 
			
		||||
    { name = "pexpect", specifier = ">=4.9.0,<5" },
 | 
			
		||||
    { name = "platformdirs", specifier = ">=4.4.0" },
 | 
			
		||||
    { name = "prompt-toolkit", specifier = ">=3.0.50" },
 | 
			
		||||
    { name = "psutil", specifier = ">=7.0.0" },
 | 
			
		||||
    { name = "pyperclip", specifier = ">=1.9.0" },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue