Lots of updates to handle file pathing more sanely.

pull/78/head
Eric Holscher 8 years ago
parent 3aa1747795
commit 5e18b65a6c

@ -1,7 +1,7 @@
import re
import os
import fnmatch
from collections import OrderedDict
from collections import OrderedDict, namedtuple
import unidecode
from jinja2 import Environment, FileSystemLoader, TemplateNotFound
@ -10,6 +10,8 @@ from sphinx.util.osutil import ensuredir
from ..settings import API_ROOT
Path = namedtuple('Path', ['absolute', 'relative'])
class PythonMapperBase(object):
@ -47,8 +49,9 @@ class PythonMapperBase(object):
# Create a page in the output for this object.
top_level_object = False
def __init__(self, obj, options=None, jinja_env=None, url_root=None):
def __init__(self, obj, path, options=None, jinja_env=None, url_root=None):
self.obj = obj
self.path = path
self.options = options
if jinja_env:
self.jinja_env = jinja_env
@ -115,14 +118,19 @@ class PythonMapperBase(object):
* Break up the string as paths
'''
slug = self.name
try:
slug = self.name.split('(')[0]
except IndexError:
pass
slug = unidecode.unidecode(slug)
slug = slug.replace('-', '')
slug = re.sub(r'[^\w\.]+', '-', slug).strip('-')
return os.path.join(*slug.split('.'))
return slug.split('.')[-1]
def include_dir(self, root):
"""Return directory of file
"""
return os.path.join(
root,
os.path.dirname(self.path.relative),
self.pathname,
)
@property
def include_path(self):
@ -131,8 +139,7 @@ class PythonMapperBase(object):
This is used in ``toctree`` directives, as Sphinx always expects Unix
path separators
"""
parts = [self.url_root]
parts.extend(self.pathname.split(os.path.sep))
parts = [self.include_dir(root=self.url_root)]
parts.append('index')
return '/'.join(parts)
@ -193,7 +200,7 @@ class SphinxMapperBase(object):
'''
for path in self.find_files(patterns=patterns, dirs=dirs, ignore=ignore):
data = self.read_file(path=path)
data = self.read_file(path=path.absolute)
if data:
self.paths[path] = data
@ -219,11 +226,16 @@ class SphinxMapperBase(object):
if skip:
continue
# Make sure the path is full
if os.path.isabs(filename):
files_to_read.append(filename)
ret_path = filename
else:
files_to_read.append(os.path.join(root, filename))
ret_path = os.path.join(root, filename)
rel_path = ret_path.replace(_dir, '')
path_obj = Path(ret_path, rel_path[1:])
files_to_read.append(path_obj)
for _path in self.app.status_iterator(
files_to_read,
@ -252,7 +264,7 @@ class SphinxMapperBase(object):
def map(self, options=None):
'''Trigger find of serialized sources and build objects'''
for path, data in self.paths.items():
for obj in self.create_class(data, options=options):
for obj in self.create_class(data, options=options, path=path):
self.add_object(obj)
def create_class(self, obj, options=None, **kwargs):
@ -267,18 +279,14 @@ class SphinxMapperBase(object):
for id, obj in self.objects.items():
if not obj or not obj.top_level_object:
print "Skipping {obj} as it isn't a top level object".format(obj=obj)
continue
rst = obj.render()
if not rst:
continue
try:
filename = id.split('(')[0]
except IndexError:
filename = id
filename = filename.replace('#', '-')
detail_dir = os.path.join(root, *filename.split('.'))
detail_dir = obj.include_dir(root=root)
ensuredir(detail_dir)
path = os.path.join(detail_dir, '%s%s' % ('index', source_suffix))
with open(path, 'wb+') as detail_file:

@ -4,6 +4,7 @@ import subprocess
import traceback
import shutil
from collections import defaultdict
import unidecode
import yaml
from sphinx.util.osutil import ensuredir
@ -317,6 +318,27 @@ class DotNetPythonMapper(PythonMapperBase):
return '<{cls} {id}>'.format(cls=self.__class__.__name__,
id=self.id)
@property
def pathname(self):
'''Sluggified path for filenames
Slugs to a filename using the follow steps
* Decode unicode to approximate ascii
* Remove existing hypens
* Substitute hyphens for non-word characters
* Break up the string as paths
'''
slug = self.name
try:
slug = self.name.split('(')[0]
except IndexError:
pass
slug = unidecode.unidecode(slug)
slug = slug.replace('-', '')
slug = re.sub(r'[^\w\.]+', '-', slug).strip('-')
return os.path.join(*slug.split('.'))
@property
def short_name(self):
'''Shorten name property'''

@ -1,4 +1,6 @@
import os
from collections import defaultdict
import textwrap
from .base import PythonMapperBase, SphinxMapperBase
from ..utils import slugify
@ -39,15 +41,18 @@ class PythonSphinxMapper(SphinxMapperBase):
:param data: dictionary data of pydocstyle output
'''
obj_map = dict((cls.type, cls) for cls
in [PythonClass, PythonFunction, PythonModule, PythonMethod])
in [PythonClass, PythonFunction, PythonModule, PythonMethod, PythonPackage])
try:
cls = obj_map[data.kind]
except KeyError:
self.app.warn("Unknown Type: %s" % data.kind)
else:
obj = cls(data, jinja_env=self.jinja_env, options=self.app.config.autoapi_options)
path = kwargs.get('path')
obj = cls(data, jinja_env=self.jinja_env,
options=self.app.config.autoapi_options, path=path
)
for child_data in data.children:
for child_obj in self.create_class(child_data, options=options):
for child_obj in self.create_class(child_data, options=options, path=path):
obj.children.append(child_obj)
self.add_object(child_obj)
yield obj
@ -60,8 +65,14 @@ class PythonPythonMapper(PythonMapperBase):
def __init__(self, obj, **kwargs):
super(PythonPythonMapper, self).__init__(obj, **kwargs)
# Always exist
name = obj.name.split('/')[-1]
# Properly name the object with dot notation
if self.top_level_object:
name = self.path.relative.split('.')[0].replace('/', '.')
else:
name = '.'.join([
os.path.dirname(self.path.relative).replace('/', '.'),
obj.name
])
self.id = slugify(name)
self.name = name
@ -75,6 +86,7 @@ class PythonPythonMapper(PythonMapperBase):
except:
args = ''
self.docstring = obj.docstring or ''
self.docstring = textwrap.dedent(self.docstring)
self.docstring = self.docstring.replace("'''", '').replace('"""', '')
if getattr(obj, 'parent'):
self.inheritance = [obj.parent.name]
@ -84,6 +96,9 @@ class PythonPythonMapper(PythonMapperBase):
# For later
self.item_map = defaultdict(list)
def __repr__(self):
return 'Python {type}: {name}'.format(name=self.name, type=self.type)
@property
def undoc_member(self):
return self.docstring == ''
@ -120,5 +135,10 @@ class PythonModule(PythonPythonMapper):
top_level_object = True
class PythonPackage(PythonPythonMapper):
type = 'package'
top_level_object = True
class PythonClass(PythonPythonMapper):
type = 'class'

Loading…
Cancel
Save