Source code for pydeps.target
# -*- coding: utf-8 -*-
"""
Abstracting the target for pydeps to work on.
"""
from __future__ import print_function
import json
import os
import re
import shutil
import sys
import tempfile
from contextlib import contextmanager
import logging
log = logging.getLogger(__name__)
[docs]
class Target(object):
"""The compilation target.
"""
is_pysource = False
is_module = False
is_dir = False
def __init__(self, path):
# log.debug("CURDIR: %s, path: %s, exists: %s", os.getcwd(), path, os.path.exists(path))
# print("Target::CURDIR: %s, path: %s, exists: %s" % (os.getcwd(), path, os.path.exists(path)))
self.calling_fname = path
self.calling_dir = os.getcwd()
self.exists = os.path.exists(path)
if self.exists:
self.path = os.path.realpath(path)
else: # pragma: nocover
print("No such file or directory:", repr(path), file=sys.stderr)
if os.path.exists(path + '.py'):
print("..did you mean:", path + '.py', '?', file=sys.stderr)
sys.exit(1)
self.is_dir = os.path.isdir(self.path)
self.is_module = self.is_dir and '__init__.py' in os.listdir(self.path)
self.is_pysource = os.path.splitext(self.path)[1] in ('.py', '.pyc', '.pyo', '.pyw')
self.fname = os.path.basename(self.path)
if self.is_dir:
self.dirname = self.fname
self.modname = self.fname
else:
self.dirname = os.path.dirname(self.path)
self.modname = os.path.splitext(self.fname)[0]
if self.is_pysource:
# we will work directly on the file (in-situ)
self.workdir = os.path.dirname(self.path)
else:
self.workdir = os.path.realpath(tempfile.mkdtemp())
self.syspath_dir = self.get_package_root()
# split path such that syspath_dir + relpath == path
self.relpath = self.path[len(self.syspath_dir):].lstrip(os.path.sep)
if self.is_dir:
self.modpath = self.relpath.replace(os.path.sep, '.')
else:
self.modpath = os.path.splitext(self.relpath)[0].replace(os.path.sep, '.')
self.package_root = os.path.join(
self.syspath_dir,
self._path_parts(self.relpath)[0]
)
[docs]
@contextmanager
def chdir_work(self):
try:
os.chdir(self.workdir)
sys.path.insert(0, self.syspath_dir)
yield
finally:
os.chdir(self.calling_dir)
if sys.path[0] == self.syspath_dir:
sys.path = sys.path[1:]
self.close()
[docs]
def get_package_root(self):
for d in self.get_parents():
if '__init__.py' not in os.listdir(d):
return d
raise Exception(
"do you have an __init__.py file at the "
"root of the drive..?") # pragma: nocover
[docs]
def get_parents(self):
def _parent_iter():
parts = self._path_parts(self.path)
for i in range(1, len(parts)):
yield os.path.join(*parts[:-i])
return list(_parent_iter())
def _path_parts(self, pth):
"""Return a list of all directories in the path ``pth``.
"""
res = re.split(r"[\\/]", pth)
if res and os.path.splitdrive(res[0]) == (res[0], ''):
res[0] += os.path.sep
return res
def __del__(self):
self.close()
[docs]
def close(self):
"""Clean up after ourselves.
"""
try:
# make sure we don't delete the user's source file if we're working
# on it in-situ.
if not self.is_pysource and hasattr(self, 'workdir'):
shutil.rmtree(self.workdir)
except OSError:
pass
def __repr__(self): # pragma: nocover
return json.dumps(
{k: v for k, v in self.__dict__.items() if not k.startswith('_')},
indent=4, sort_keys=True
)