def from_file(cls, filename): """ Loads a file from disk, parses it and constructs a new BlogPost. This method reflects a bit of the insanity of docutils. Basically this is just the docutils.core.publish_doctree function with some modifications to use an html writer and to load a file instead of a string. """ pub = Publisher(destination_class=NullOutput, source=FileInput(source_path=filename), reader=BlogPostReader(), writer=HTMLWriter(), parser=RSTParser()) pub.get_settings() # This is not sane. pub.settings.traceback = True # Damnit pub.publish() meta = pub.document.blog_meta post = cls(meta['title'], meta['post_date'], meta['author'], meta['tags'], pub.writer.parts['html_body']) post.filename = filename return post
def _docutils_rest_to(rest, writer): """ Uses docutils to convert a ReST string to HTML. Returns a tuple containg the HTML string and the list of warning nodes that were removed from the HTML. """ # Make sure any Sphinx polution of docutils has been removed. if Sphinx is not None: for key, value in docutils_roles.items(): if value.__module__.startswith('sphinx'): docutils_roles.pop(key) pub = Publisher(source_class=docutils.io.StringInput, destination_class=docutils.io.StringOutput) pub.set_reader('standalone', None, 'restructuredtext') pub.set_writer(writer) pub.writer.default_stylesheet_path='' pub.get_settings() # Get the default settings pub.settings.halt_level = 6 # Don't halt on errors pub.settings.warning_stream = StringIO() pub.set_source(rest) pub.set_destination() pub.document = pub.reader.read(pub.source, pub.parser, pub.settings) pub.apply_transforms() # Walk the node structure of a docutils document and remove 'problematic' # and 'system_message' nodes. Save the system_message nodes. warning_nodes = [] for node in pub.document.traverse(docutils.nodes.problematic): node.parent.replace(node, node.children[0]) for node in pub.document.traverse(docutils.nodes.system_message): warning_nodes.append(node) node.parent.remove(node) return pub.writer.write(pub.document, pub.destination), warning_nodes
def create_publisher(app: "Sphinx", filetype: str) -> Publisher: reader = SphinxStandaloneReader() reader.setup(app) parser = app.registry.create_source_parser(app, filetype) if parser.__class__.__name__ == 'CommonMarkParser' and parser.settings_spec == ( ): # a workaround for recommonmark # If recommonmark.AutoStrictify is enabled, the parser invokes reST parser # internally. But recommonmark-0.4.0 does not provide settings_spec for reST # parser. As a workaround, this copies settings_spec for RSTParser to the # CommonMarkParser. from docutils.parsers.rst import Parser as RSTParser parser.settings_spec = RSTParser.settings_spec pub = Publisher(reader=reader, parser=parser, writer=SphinxDummyWriter(), source_class=SphinxFileInput, destination=NullOutput()) # Propagate exceptions by default when used programmatically: defaults = {"traceback": True, **app.env.settings} # Set default settings if docutils.__version_info__[:2] >= (0, 19): pub.get_settings(**defaults) # type: ignore[arg-type] else: pub.settings = pub.setup_option_parser( **defaults).get_default_values() # type: ignore return pub
def init_publisher(): from docutils.core import Publisher from docutils.io import StringOutput p = Publisher(destination_class=StringOutput,writer=g_writer) p.get_settings() p.set_components('standalone', 'restructuredtext', 'html') p.set_destination(None, None) return p
def publish(writer_name): reader=None reader_name='standalone' parser=None parser_name='restructuredtext' writer=None settings=None settings_spec=None settings_overrides=options[writer_name] config_section=None enable_exit=1 argv=[] usage=default_usage pub = Publisher(reader, parser, writer, settings=settings) pub.set_components(reader_name, parser_name, writer_name) settings = pub.get_settings(settings_spec=settings_spec, config_section=config_section) if settings_overrides: settings._update(settings_overrides, 'loose') source = file(source_path) pub.set_source(source, source_path) destination_path = 'pg1.' + extensions[writer_name] destination = file(destination_path, 'w') pub.set_destination(destination, destination_path) pub.publish(argv, usage, description, settings_spec, settings_overrides, config_section=config_section, enable_exit=enable_exit)
def check_for_errors(content, filepath=None): """Lint reStructuredText and return errors :param string content: reStructuredText to be linted :param string filepath: Optional path to file, this will be returned as the source :rtype list: List of errors. Each error will contain a line, source (filepath), message (error message), and full message (error message + source lines) """ # Generate a new parser (copying `rst2html.py` flow) # http://repo.or.cz/w/docutils.git/blob/422cede485668203abc01c76ca317578ff634b30:/docutils/tools/rst2html.py # http://repo.or.cz/w/docutils.git/blob/422cede485668203abc01c76ca317578ff634b30:/docutils/docutils/core.py#l348 pub = Publisher(None, None, None, settings=None) pub.set_components('standalone', 'restructuredtext', 'pseudoxml') # Configure publisher # DEV: We cannot use `process_command_line` since it processes `sys.argv` which is for `rst-lint`, not `docutils` # http://repo.or.cz/w/docutils.git/blob/422cede485668203abc01c76ca317578ff634b30:/docutils/docutils/core.py#l201 # http://repo.or.cz/w/docutils.git/blob/422cede485668203abc01c76ca317578ff634b30:/docutils/docutils/core.py#l143 # http://repo.or.cz/w/docutils.git/blob/422cede485668203abc01c76ca317578ff634b30:/docutils/docutils/core.py#l118 settings = pub.get_settings(halt_level=5) pub.set_io() # Prepare a document to parse on # DEV: We avoid the `read` method because when `source` is `None`, it attempts to read from `stdin`. # However, we already know our content. # DEV: We create our document without `parse` because we need to attach observer's before parsing # http://repo.or.cz/w/docutils.git/blob/422cede485668203abc01c76ca317578ff634b30:/docutils/docutils/readers/__init__.py#l66 reader = pub.reader document = utils.new_document(filepath, settings) # Disable stdout # TODO: Find a more proper way to do this # TODO: We might exit the program if a certain error level is reached document.reporter.stream = None # Collect errors via an observer errors = [] def error_collector(data): # Mutate the data since it was just generated data.line = data.get('line') data.source = data['source'] data.level = data['level'] data.type = data['type'] data.message = Element.astext(data.children[0]) data.full_message = Element.astext(data) # Save the error errors.append(data) document.reporter.attach_observer(error_collector) # Parse the content (and collect errors) # http://repo.or.cz/w/docutils.git/blob/422cede485668203abc01c76ca317578ff634b30:/docutils/docutils/readers/__init__.py#l75 reader.parser.parse(content, document) # Apply transforms (and more collect errors) # DEV: We cannot use `apply_transforms` since it has `attach_observer` baked in. We want only our listener. # http://repo.or.cz/w/docutils.git/blob/422cede485668203abc01c76ca317578ff634b30:/docutils/docutils/core.py#l195 # http://repo.or.cz/w/docutils.git/blob/422cede485668203abc01c76ca317578ff634b30:/docutils/docutils/transforms/__init__.py#l159 document.transformer.populate_from_components( (pub.source, pub.reader, pub.reader.parser, pub.writer, pub.destination) ) transformer = document.transformer while transformer.transforms: if not transformer.sorted: # Unsorted initially, and whenever a transform is added. transformer.transforms.sort() transformer.transforms.reverse() transformer.sorted = 1 priority, transform_class, pending, kwargs = transformer.transforms.pop() transform = transform_class(transformer.document, startnode=pending) transform.apply(**kwargs) transformer.applied.append((priority, transform_class, pending, kwargs)) return errors
def get_settings(self, *args, **kwargs): kwargs.setdefault('env', sphinx.env) return Publisher.get_settings(self, *args, **kwargs)
def lint(content, filepath=None): """Lint reStructuredText and return errors :param string content: reStructuredText to be linted :param string filepath: Optional path to file, this will be returned as the source :rtype list: List of errors. Each error will contain a line, source (filepath), message (error message), and full message (error message + source lines) """ # Generate a new parser (copying `rst2html.py` flow) # http://repo.or.cz/w/docutils.git/blob/422cede485668203abc01c76ca317578ff634b30:/docutils/tools/rst2html.py # http://repo.or.cz/w/docutils.git/blob/422cede485668203abc01c76ca317578ff634b30:/docutils/docutils/core.py#l348 pub = Publisher(None, None, None, settings=None) pub.set_components('standalone', 'restructuredtext', 'pseudoxml') # Configure publisher # DEV: We cannot use `process_command_line` since it processes `sys.argv` which is for `rst-lint`, not `docutils` # http://repo.or.cz/w/docutils.git/blob/422cede485668203abc01c76ca317578ff634b30:/docutils/docutils/core.py#l201 # http://repo.or.cz/w/docutils.git/blob/422cede485668203abc01c76ca317578ff634b30:/docutils/docutils/core.py#l143 # http://repo.or.cz/w/docutils.git/blob/422cede485668203abc01c76ca317578ff634b30:/docutils/docutils/core.py#l118 settings = pub.get_settings(halt_level=5) pub.set_io() # Prepare a document to parse on # DEV: We avoid the `read` method because when `source` is `None`, it attempts to read from `stdin`. # However, we already know our content. # DEV: We create our document without `parse` because we need to attach observer's before parsing # http://repo.or.cz/w/docutils.git/blob/422cede485668203abc01c76ca317578ff634b30:/docutils/docutils/readers/__init__.py#l66 reader = pub.reader document = utils.new_document(filepath, settings) # Disable stdout # TODO: Find a more proper way to do this # TODO: We might exit the program if a certain error level is reached document.reporter.stream = None # Collect errors via an observer errors = [] def error_collector(data): # Mutate the data since it was just generated data.line = data.get('line') data.source = data['source'] data.level = data['level'] data.type = data['type'] data.message = Element.astext(data.children[0]) data.full_message = Element.astext(data) # Save the error errors.append(data) document.reporter.attach_observer(error_collector) # Parse the content (and collect errors) # http://repo.or.cz/w/docutils.git/blob/422cede485668203abc01c76ca317578ff634b30:/docutils/docutils/readers/__init__.py#l75 reader.parser.parse(content, document) # Apply transforms (and more collect errors) # DEV: We cannot use `apply_transforms` since it has `attach_observer` baked in. We want only our listener. # http://repo.or.cz/w/docutils.git/blob/422cede485668203abc01c76ca317578ff634b30:/docutils/docutils/core.py#l195 # http://repo.or.cz/w/docutils.git/blob/422cede485668203abc01c76ca317578ff634b30:/docutils/docutils/transforms/__init__.py#l159 document.transformer.populate_from_components( (pub.source, pub.reader, pub.reader.parser, pub.writer, pub.destination)) transformer = document.transformer while transformer.transforms: if not transformer.sorted: # Unsorted initially, and whenever a transform is added. transformer.transforms.sort() transformer.transforms.reverse() transformer.sorted = 1 priority, transform_class, pending, kwargs = transformer.transforms.pop( ) transform = transform_class(transformer.document, startnode=pending) transform.apply(**kwargs) transformer.applied.append( (priority, transform_class, pending, kwargs)) return errors
SPELL_CHECK = False # Rasta Core Library try: from mainWindow import Ui_Rasta except ImportError: sys.exit(_('Please run "setup.py build" first.')) # Log Model for log view from model import LogTableModel TMPFILE = '/tmp/untitled.rst' # Global Publisher for Docutils PUB = Publisher(source_class=docutils.io.StringInput, destination_class=docutils.io.StringOutput) PUB.set_reader('standalone', None, 'restructuredtext') PUB.set_writer('html') PUB.get_settings() PUB.settings.halt_level = 7 PUB.settings.warning_stream = StringIO() def clear_log(log): ''' Removes not needed lines from log output ''' try: log = unicode(log) return re.findall("line\=\"(.*?)\"", log)[0], re.findall("\<paragraph\>(.*?)\<\/paragraph\>", log)[0] except: return 1, _('Rasta parse error: %s' % log)