63 lines
2.5 KiB
Python
63 lines
2.5 KiB
Python
#!/usr/bin/env python3.6
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
IO stuff.
|
|
"""
|
|
import copy
|
|
import inspect
|
|
import os
|
|
|
|
|
|
__all__ = ('in_here',)
|
|
|
|
|
|
def in_here(first_path_bit: str, *path_bits: str, stack_depth: int=0) -> str:
|
|
"""
|
|
A somewhat voodooish and weird piece of code. This enables us to
|
|
directly refer to a file in the same directory as the code that
|
|
calls this method, without any due regard for where in the file
|
|
system tree it is.
|
|
|
|
Apart from that, this will behave just like os.path.join, meaning
|
|
that varaidic strings will be joined with the appropriate
|
|
directory separator for the current platform.
|
|
|
|
This works by inspecting the stack frame for the caller.
|
|
If you are planning on nesting this call in another utility and wish
|
|
for the stack to refer to that caller, you should increment
|
|
the ``stack_depth`` arg for each nested call you make. By default,
|
|
you can ignore this and it will default to 0.
|
|
|
|
:param first_path_bit: the initial path bit to operate with. This is
|
|
required.
|
|
:param path_bits: additional bits of path to construct relative to here.
|
|
These are entirely optional.
|
|
:param stack_depth: optional, defaults to 0. How many nested calls
|
|
we expect this to be called in. Affects the relative directory
|
|
that is used.
|
|
:returns: the absolute path to the given relative path provided.
|
|
"""
|
|
try:
|
|
frame = inspect.stack()[1 + stack_depth]
|
|
except IndexError:
|
|
raise RuntimeError('Could not find a stack record. Interpreter has '
|
|
'been shot.')
|
|
else:
|
|
module = inspect.getmodule(frame[0])
|
|
assert hasattr(module, '__file__'), 'No `__file__\' attr, welp.'
|
|
|
|
# https://docs.python.org/3/library/inspect.html#the-interpreter-stack
|
|
# If Python caches strings rather than copying when we move them
|
|
# around or modify them, then this may cause a referential cycle which
|
|
# will consume more memory and stop the garbage collection system
|
|
# from working correctly. Best thing to do here is deepcopy anything
|
|
# we need and prevent this occuring. Del the references to allow them
|
|
# to be freed.
|
|
file = module.__file__
|
|
file = copy.deepcopy(file)
|
|
del module, frame
|
|
dir_name = os.path.dirname(file)
|
|
abs_dir_name = os.path.abspath(dir_name)
|
|
pathish = os.path.join(abs_dir_name, first_path_bit, *path_bits)
|
|
return pathish
|