def main():
    """Main script to verify modules included."""
    mock_uri = ''
    inventory = fetch_inventory(SphinxApp, mock_uri,
                                OBJECT_INVENTORY_RELPATH)
    sphinx_mods = set(inventory['py:module'].keys())

    library_dir = os.path.join(BASE_DIR, 'gcloud')
    public_mods = get_public_modules(library_dir,
                                     base_package='gcloud')
    public_mods = set(public_mods)

    if not sphinx_mods <= public_mods:
        unexpected_mods = sphinx_mods - public_mods
        message = ['Unexpected error. There were modules referenced by '
                   'Sphinx that are not among the public modules.']
        message.extend(['- %s' % (mod,) for mod in unexpected_mods])
        print('\n'.join(message), file=sys.stderr)
        sys.exit(1)

    undocumented_mods = public_mods - sphinx_mods
    # Remove ignored modules.
    undocumented_mods -= IGNORED_MODULES
    if undocumented_mods:
        message_parts = ['Found undocumented public modules:']
        message_parts.extend(['- ' + mod_name
                              for mod_name in sorted(undocumented_mods)])
        print('\n'.join(message_parts), file=sys.stderr)
        sys.exit(1)
Ejemplo n.º 2
0
def get_inventory(args):
    app = DummyApp()
    inventory = intersphinx.fetch_inventory(app, "", args.uri)
    if args.dump:
        dump_inventory(inventory)
    if args.create_intersphinx_reference:
        with SphinxPage(args.create_intersphinx_reference,
                        "w",
                        app=args.project) as f:
            sections = sorted(inventory.keys())
            for k in sections:
                term_name = k.split(':')[1]
                term = {
                    'attribute': 'attr',
                    'function': 'func'
                }.get(term_name, term_name)
                section = inventory[k]
                f.section(term)
                if term == 'label':
                    pattern_as = "``:ref:{1[0]}:{2}``"
                    pattern_test = ":ref:`{2}`"
                else:
                    pattern_as = "``:{0}:{1[0]}:{2}``"
                    pattern_test = ":{0}:`{2}`"

                entries = sorted(section, key=lambda key: section[key])
                for name in entries:
                    values = section[name]
                    access_as = pattern_as.format(term, values, name)
                    access_test = pattern_test.format(term, values, name)

                    f.writeln("    * {0} : '{1}' ({2})".format(
                        name, access_as, access_test))
                f.writeln("", "")
    return "Success"
Ejemplo n.º 3
0
def update_intersphinx(version_pk):
    version = Version.objects.get(pk=version_pk)
    path = version.project.rtd_build_path(version.slug)
    if not path:
        print "ERR: %s has no path" % version
        return None
    app = DictObj()
    app.srcdir = path
    try:
        inv = fetch_inventory(app, app.srcdir, 'objects.inv')
    except TypeError:
        print "Failed to fetch inventory for %s" % version
        return None
    # I'm entirelty not sure this is even close to correct.
    # There's a lot of info I'm throwing away here; revisit later?
    for keytype in inv:
        for term in inv[keytype]:
            try:
                _, _, url, title = inv[keytype][term]
                if not title or title == '-':
                    if '#' in url:
                        title = url.rsplit('#')[-1]
                    else:
                        title = url
                find_str = "rtd-builds/latest"
                latest = url.find(find_str)
                url = url[latest + len(find_str) + 1:]
                url = "http://%s.readthedocs.org/en/latest/%s" % (
                    version.project.slug, url)
                save_term(version, term, url, title)
                if '.' in term:
                    save_term(version, term.split('.')[-1], url, title)
            except Exception, e:  #Yes, I'm an evil person.
                print "*** Failed updating %s: %s" % (term, e)
Ejemplo n.º 4
0
def fetch_list(version=None):
    """
    For the given version of Python (or all versions if no version is set), this function:

    - Uses the `fetch_inventory` function of :py:mod`sphinx.ext.intersphinx` to
    grab and parse the Sphinx object inventory
    (ie ``http://docs.python.org/<version>/objects.inv``) for the given version.

    - Grabs the names of all of the modules in the parsed inventory data.

    - Writes the sorted list of module names to file (within the `lists` subfolder).

    :param str|None version: A specified version of Python. If not specified, then all
    available versions of Python will have their inventory objects fetched
    and parsed, and have their module names written to file.
    (one of ``"2.6"``, ``"2.7"``, ``"3.2"``, ``"3.3"``, ``"3.4"``, ``"3.5"``, ``"3.6"``, ``"3.7"``, ``"3.8"``, ``"3.9"`` or ``None``)

    """

    if version is None:
        versions = short_versions
    else:
        versions = [get_canonical_version(version)]

    for version in versions:

        url = "http://docs.python.org/{}/objects.inv".format(version)

        modules = sorted(
            list(fetch_inventory(DummyApp(), "", url).get("py:module").keys()))

        with open(os.path.join(list_dir, "{}.txt".format(version)), "w") as f:
            for module in modules:
                f.write(module)
                f.write("\n")
Ejemplo n.º 5
0
def update_intersphinx(version_pk):
    version = Version.objects.get(pk=version_pk)
    path = version.project.rtd_build_path(version.slug)
    if not path:
        print "ERR: %s has no path" % version
        return None
    app = DictObj()
    app.srcdir = path
    try:
        inv = fetch_inventory(app, app.srcdir, 'objects.inv')
    except TypeError:
        print "Failed to fetch inventory for %s" % version
        return None
    # I'm entirelty not sure this is even close to correct.
    # There's a lot of info I'm throwing away here; revisit later?
    for keytype in inv:
        for term in inv[keytype]:
            try:
                _, _, url, title = inv[keytype][term]
                if not title or title == '-':
                    if '#' in url:
                        title = url.rsplit('#')[-1]
                    else:
                        title = url
                find_str = "rtd-builds/latest"
                latest = url.find(find_str)
                url = url[latest + len(find_str) + 1:]
                url = "http://%s.readthedocs.org/en/latest/%s" % (
                    version.project.slug, url)
                save_term(version, term, url, title)
                if '.' in term:
                    save_term(version, term.split('.')[-1], url, title)
            except Exception, e: #Yes, I'm an evil person.
                print "*** Failed updating %s: %s" % (term, e)
def main():
    """Main script to verify modules included."""
    mock_uri = ''
    inventory = fetch_inventory(SphinxApp, mock_uri, OBJECT_INVENTORY_RELPATH)
    sphinx_mods = set(inventory['py:module'].keys())

    library_dir = os.path.join(BASE_DIR, 'gcloud')
    public_mods = get_public_modules(library_dir, base_package='gcloud')
    public_mods = set(public_mods)

    if not sphinx_mods <= public_mods:
        message = ('Unexpected error. There were modules referenced by '
                   'Sphinx that are not among the public modules.')
        print(message, file=sys.stderr)
        sys.exit(1)

    undocumented_mods = public_mods - sphinx_mods
    # Remove ignored modules.
    undocumented_mods -= IGNORED_MODULES
    if undocumented_mods:
        message_parts = ['Found undocumented public modules:']
        message_parts.extend(
            ['- ' + mod_name for mod_name in sorted(undocumented_mods)])
        print('\n'.join(message_parts), file=sys.stderr)
        sys.exit(1)
Ejemplo n.º 7
0
 async def convert(ctx, url: str):
     try:
         intersphinx.fetch_inventory(SphinxConfiguration(), '', url)
     except AttributeError:
         raise commands.BadArgument(f"Failed to fetch Intersphinx inventory from URL `{url}`.")
     except ConnectionError:
         if url.startswith('https'):
             raise commands.BadArgument(
                 f"Cannot establish a connection to `{url}`. Does it support HTTPS?"
             )
         raise commands.BadArgument(f"Cannot connect to host with URL `{url}`.")
     except ValueError:
         raise commands.BadArgument(
             f"Failed to read Intersphinx inventory from URL `{url}`. "
             "Are you sure that it's a valid inventory file?"
         )
     return url
Ejemplo n.º 8
0
 async def convert(ctx: commands.Context, url: str) -> str:
     """Convert url to Intersphinx inventory URL."""
     try:
         intersphinx.fetch_inventory(SPHINX_MOCK_APP, '', url)
     except AttributeError:
         raise commands.BadArgument(f"Failed to fetch Intersphinx inventory from URL `{url}`.")
     except ConnectionError:
         if url.startswith('https'):
             raise commands.BadArgument(
                 f"Cannot establish a connection to `{url}`. Does it support HTTPS?"
             )
         raise commands.BadArgument(f"Cannot connect to host with URL `{url}`.")
     except ValueError:
         raise commands.BadArgument(
             f"""Failed to read Intersphinx inventory from URL `{url}`. 
             Are you sure that it's a valid inventory file?"""
         )
     return url
Ejemplo n.º 9
0
def main():
    for package_name, (uri, inv) in intersphinx_mapping.items():
        if inv is None:
            inv = "objects.inv"
        inv_uri = os.path.join(uri, inv)
        app = App(package_name)
        inventory = intersphinx.fetch_inventory(app, "", inv_uri)
        for k in inventory.keys():
            print(f"{app.name} {k}")
            for name, value in inventory[k].items():
                print("{} {} is <{}:{}>".format(k, value[2], app.name, name))
Ejemplo n.º 10
0
def main():
    for package_name, (uri, inv) in intersphinx_mapping.items():
        if inv is None:
            inv = 'objects.inv'
        inv_uri = os.path.join(uri, inv)
        app = App(package_name)
        inventory = intersphinx.fetch_inventory(app, '', inv_uri)
        for k in inventory.keys():
            print "%s %s" % (app.name, k)
            for name, value in inventory[k].items():
                print "%s %s is <%s:%s>" % (k, value[2], app.name, name)
Ejemplo n.º 11
0
def main():
    for package_name, (uri, inv) in intersphinx_mapping.items():
        if inv is None:
            inv = 'objects.inv'
        inv_uri = os.path.join(uri, inv)
        app = App(package_name)
        inventory = intersphinx.fetch_inventory(app, '', inv_uri)
        for k in inventory.keys():
            print("{} {}".format(app.name, k))
            for name, value in inventory[k].items():
                print("{} {} is <{}:{}>".format(k, value[2], app.name, name))
Ejemplo n.º 12
0
def test_fetch_inventory_redirection(app, status, warning, _read_from_url,
                                     read_inventory_v2):
    _read_from_url(
    ).readline.return_value = '# Sphinx inventory version 2'.encode('utf-8')

    # same uri and inv, not redirected
    _read_from_url(
    ).geturl.return_value = 'http://hostname/' + INVENTORY_FILENAME
    fetch_inventory(app, 'http://hostname/',
                    'http://hostname/' + INVENTORY_FILENAME)
    assert 'intersphinx inventory has moved' not in status.getvalue()
    assert read_inventory_v2.call_args[0][1] == 'http://hostname/'

    # same uri and inv, redirected
    status.seek(0)
    status.truncate(0)
    _read_from_url(
    ).geturl.return_value = 'http://hostname/new/' + INVENTORY_FILENAME

    fetch_inventory(app, 'http://hostname/',
                    'http://hostname/' + INVENTORY_FILENAME)
    assert status.getvalue() == (
        'intersphinx inventory has moved: '
        'http://hostname/%s -> http://hostname/new/%s\n' %
        (INVENTORY_FILENAME, INVENTORY_FILENAME))
    assert read_inventory_v2.call_args[0][1] == 'http://hostname/new'

    # different uri and inv, not redirected
    status.seek(0)
    status.truncate(0)
    _read_from_url(
    ).geturl.return_value = 'http://hostname/new/' + INVENTORY_FILENAME

    fetch_inventory(app, 'http://hostname/',
                    'http://hostname/new/' + INVENTORY_FILENAME)
    assert 'intersphinx inventory has moved' not in status.getvalue()
    assert read_inventory_v2.call_args[0][1] == 'http://hostname/'

    # different uri and inv, redirected
    status.seek(0)
    status.truncate(0)
    _read_from_url(
    ).geturl.return_value = 'http://hostname/other/' + INVENTORY_FILENAME

    fetch_inventory(app, 'http://hostname/',
                    'http://hostname/new/' + INVENTORY_FILENAME)
    assert status.getvalue() == (
        'intersphinx inventory has moved: '
        'http://hostname/new/%s -> http://hostname/other/%s\n' %
        (INVENTORY_FILENAME, INVENTORY_FILENAME))
    assert read_inventory_v2.call_args[0][1] == 'http://hostname/'
Ejemplo n.º 13
0
def main():
  app = DummyApp()
  # baseurl to use
  uri = ""
  inv = sys.argv[1]
  inventory = intersphinx.fetch_inventory(app, uri, inv)
  for k in inventory.keys():
    print "Type: %s" % k
    for name, value in inventory[k].items():
      print "  %s -> '%s'" % (name, value[2])

  return 0
Ejemplo n.º 14
0
def main():
    for package_name, (uri, inv) in intersphinx_mapping.items():
        if inv is None:
            inv = 'objects.inv'
        inv_uri = os.path.join(uri, inv)
        app = App(package_name)
        inventory = intersphinx.fetch_inventory(app, '', inv_uri)
        for k in inventory.keys():
            print "%s %s" % (app.name, k)
            for name, value in inventory[k].items():
                print "%s %s is <%s:%s>" % (
                    k, value[2], app.name, name)
Ejemplo n.º 15
0
def fetch_local_inventory(inventory_file):
    """Fetch the inventory file from the build output of the source directory."""
    class MockConfig:
        intersphinx_timeout = None
        tls_verify = False
        user_agent = None

    class MockApp:
        srcdir = ""
        config = MockConfig()

    return fetch_inventory(MockApp(), "", str(inventory_file))
Ejemplo n.º 16
0
def make_cache(name, uri):
    dest_dir = join(cache_dir, name)
    if not exists(dest_dir):
        mkdir(dest_dir)
    inv = fetch_inventory(warnings, uri, join(uri, 'objects.inv'))
    for k, v in inv.items():
        filename = join(dest_dir, k.replace(':', '-'))
        line_counter = 0
        with open(filename, 'w+') as f:
            for sk, sv in v.items():
                line_counter +=1
                if line_counter % 100 == 0:
                    print('File: %s, Line: %s' % (basename(filename), line_counter))
                f.write('%s\t%s\n' % (sk, sv))
Ejemplo n.º 17
0
def main():
    app = DummyApp()
    # baseurl to use
    uri = ""
    for invname in conf.intersphinx_mapping.keys():
        # inv = sys.argv[1]
        inv = conf.intersphinx_mapping[invname][0] + "objects.inv"
        inventory = intersphinx.fetch_inventory(app, uri, inv)
        for k in inventory.keys():
            print "Type: %s" % k
            for name, value in inventory[k].items():
                print "  %s -> '%s'" % (name, value[2])

    return 0
Ejemplo n.º 18
0
def test_fetch_inventory_redirection(_read_from_url, InventoryFile, app,
                                     status, warning):
    intersphinx_setup(app)
    _read_from_url().readline.return_value = b'# Sphinx inventory version 2'

    # same uri and inv, not redirected
    _read_from_url().url = 'http://hostname/' + INVENTORY_FILENAME
    fetch_inventory(app, 'http://hostname/',
                    'http://hostname/' + INVENTORY_FILENAME)
    assert 'intersphinx inventory has moved' not in status.getvalue()
    assert InventoryFile.load.call_args[0][1] == 'http://hostname/'

    # same uri and inv, redirected
    status.seek(0)
    status.truncate(0)
    _read_from_url().url = 'http://hostname/new/' + INVENTORY_FILENAME

    fetch_inventory(app, 'http://hostname/',
                    'http://hostname/' + INVENTORY_FILENAME)
    assert status.getvalue() == (
        'intersphinx inventory has moved: '
        'http://hostname/%s -> http://hostname/new/%s\n' %
        (INVENTORY_FILENAME, INVENTORY_FILENAME))
    assert InventoryFile.load.call_args[0][1] == 'http://hostname/new'

    # different uri and inv, not redirected
    status.seek(0)
    status.truncate(0)
    _read_from_url().url = 'http://hostname/new/' + INVENTORY_FILENAME

    fetch_inventory(app, 'http://hostname/',
                    'http://hostname/new/' + INVENTORY_FILENAME)
    assert 'intersphinx inventory has moved' not in status.getvalue()
    assert InventoryFile.load.call_args[0][1] == 'http://hostname/'

    # different uri and inv, redirected
    status.seek(0)
    status.truncate(0)
    _read_from_url().url = 'http://hostname/other/' + INVENTORY_FILENAME

    fetch_inventory(app, 'http://hostname/',
                    'http://hostname/new/' + INVENTORY_FILENAME)
    assert status.getvalue() == (
        'intersphinx inventory has moved: '
        'http://hostname/new/%s -> http://hostname/other/%s\n' %
        (INVENTORY_FILENAME, INVENTORY_FILENAME))
    assert InventoryFile.load.call_args[0][1] == 'http://hostname/'
Ejemplo n.º 19
0
def make_cache(name, uri):
    dest_dir = join(cache_dir, name)
    if not exists(dest_dir):
        mkdir(dest_dir)
    inv = fetch_inventory(warnings, uri, join(uri, 'objects.inv'))
    for k, v in inv.items():
        filename = join(dest_dir, k.replace(':', '-'))
        line_counter = 0
        with open(filename, 'w+') as f:
            for sk, sv in v.items():
                line_counter += 1
                if line_counter % 100 == 0:
                    print('File: %s, Line: %s' %
                          (basename(filename), line_counter))
                f.write('%s\t%s\n' % (sk, sv))
Ejemplo n.º 20
0
def fetch_inventory(uri):
    from sphinx.ext import intersphinx
    import warnings
    """Read a Sphinx inventory file into a dictionary."""
    class MockConfig(object):
        intersphinx_timeout = None  # type: int
        tls_verify = False

    class MockApp(object):
        srcdir = ''
        config = MockConfig()

        def warn(self, msg):
            warnings.warn(msg)

    return intersphinx.fetch_inventory(MockApp(), '', uri)
Ejemplo n.º 21
0
def fetch_local_inventory(source_dir, html_output_dirs):
    """Fetch the inventory file from the build output of the source directory."""
    class MockConfig:
        intersphinx_timeout = None
        tls_verify = False
        user_agent = None

    class MockApp:
        srcdir = ""
        config = MockConfig()

    inventory_file = Path("objects.inv")
    for output_dir in html_output_dirs:
        path = source_dir / output_dir / inventory_file
        if path.exists():
            return fetch_inventory(MockApp(), "", str(path))
    return {}
Ejemplo n.º 22
0
def test_fetch_inventory_redirection(app, status, warning, _read_from_url, read_inventory):
    intersphinx_setup(app)
    _read_from_url().readline.return_value = "# Sphinx inventory version 2".encode("utf-8")

    # same uri and inv, not redirected
    _read_from_url().url = "http://hostname/" + INVENTORY_FILENAME
    fetch_inventory(app, "http://hostname/", "http://hostname/" + INVENTORY_FILENAME)
    assert "intersphinx inventory has moved" not in status.getvalue()
    assert read_inventory.call_args[0][1] == "http://hostname/"

    # same uri and inv, redirected
    status.seek(0)
    status.truncate(0)
    _read_from_url().url = "http://hostname/new/" + INVENTORY_FILENAME

    fetch_inventory(app, "http://hostname/", "http://hostname/" + INVENTORY_FILENAME)
    assert status.getvalue() == (
        "intersphinx inventory has moved: "
        "http://hostname/%s -> http://hostname/new/%s\n" % (INVENTORY_FILENAME, INVENTORY_FILENAME)
    )
    assert read_inventory.call_args[0][1] == "http://hostname/new"

    # different uri and inv, not redirected
    status.seek(0)
    status.truncate(0)
    _read_from_url().url = "http://hostname/new/" + INVENTORY_FILENAME

    fetch_inventory(app, "http://hostname/", "http://hostname/new/" + INVENTORY_FILENAME)
    assert "intersphinx inventory has moved" not in status.getvalue()
    assert read_inventory.call_args[0][1] == "http://hostname/"

    # different uri and inv, redirected
    status.seek(0)
    status.truncate(0)
    _read_from_url().url = "http://hostname/other/" + INVENTORY_FILENAME

    fetch_inventory(app, "http://hostname/", "http://hostname/new/" + INVENTORY_FILENAME)
    assert status.getvalue() == (
        "intersphinx inventory has moved: "
        "http://hostname/new/%s -> http://hostname/other/%s\n" % (INVENTORY_FILENAME, INVENTORY_FILENAME)
    )
    assert read_inventory.call_args[0][1] == "http://hostname/"
Ejemplo n.º 23
0
def update_intersphinx(version_pk):
    version_data = api.version(version_pk).get()
    del version_data["resource_uri"]
    project_data = version_data["project"]
    del project_data["users"]
    del project_data["resource_uri"]
    del project_data["absolute_url"]
    project = Project(**project_data)
    version_data["project"] = project
    version = Version(**version_data)

    object_file = version.project.find("objects.inv", version.slug)[0]
    path = version.project.rtd_build_path(version.slug)
    if not path:
        print "ERR: %s has no path" % version
        return None
    app = DictObj()
    app.srcdir = path
    try:
        inv = fetch_inventory(app, path, object_file)
    except TypeError:
        print "Failed to fetch inventory for %s" % version
        return None
    # I'm entirelty not sure this is even close to correct.
    # There's a lot of info I'm throwing away here; revisit later?
    for keytype in inv:
        for term in inv[keytype]:
            try:
                _, _, url, title = inv[keytype][term]
                if not title or title == "-":
                    if "#" in url:
                        title = url.rsplit("#")[-1]
                    else:
                        title = url
                find_str = "rtd-builds/latest"
                latest = url.find(find_str)
                url = url[latest + len(find_str) + 1 :]
                url = "http://%s.readthedocs.org/en/latest/%s" % (version.project.slug, url)
                save_term(version, term, url, title)
                if "." in term:
                    save_term(version, term.split(".")[-1], url, title)
            except Exception, e:  # Yes, I'm an evil person.
                print "*** Failed updating %s: %s" % (term, e)
Ejemplo n.º 24
0
def fetch_intersphinx_inventory(uri):
    """
    Fetch and read an intersphinx inventory file at a specified uri, which
    can either be a url (e.g. http://...) or a local file system filename.
    """

    # See https://stackoverflow.com/a/30981554
    class MockConfig(object):
        intersphinx_timeout = None
        tls_verify = False

    class MockApp(object):
        srcdir = ''
        config = MockConfig()

        def warn(self, msg):
            warnings.warn(msg)

    return intersphinx.fetch_inventory(MockApp(), '', uri)
Ejemplo n.º 25
0
def test_fetch_inventory_redirection(_read_from_url, InventoryFile, app, status, warning):
    intersphinx_setup(app)
    _read_from_url().readline.return_value = '# Sphinx inventory version 2'.encode('utf-8')

    # same uri and inv, not redirected
    _read_from_url().url = 'http://hostname/' + INVENTORY_FILENAME
    fetch_inventory(app, 'http://hostname/', 'http://hostname/' + INVENTORY_FILENAME)
    assert 'intersphinx inventory has moved' not in status.getvalue()
    assert InventoryFile.load.call_args[0][1] == 'http://hostname/'

    # same uri and inv, redirected
    status.seek(0)
    status.truncate(0)
    _read_from_url().url = 'http://hostname/new/' + INVENTORY_FILENAME

    fetch_inventory(app, 'http://hostname/', 'http://hostname/' + INVENTORY_FILENAME)
    assert status.getvalue() == ('intersphinx inventory has moved: '
                                 'http://hostname/%s -> http://hostname/new/%s\n' %
                                 (INVENTORY_FILENAME, INVENTORY_FILENAME))
    assert InventoryFile.load.call_args[0][1] == 'http://hostname/new'

    # different uri and inv, not redirected
    status.seek(0)
    status.truncate(0)
    _read_from_url().url = 'http://hostname/new/' + INVENTORY_FILENAME

    fetch_inventory(app, 'http://hostname/', 'http://hostname/new/' + INVENTORY_FILENAME)
    assert 'intersphinx inventory has moved' not in status.getvalue()
    assert InventoryFile.load.call_args[0][1] == 'http://hostname/'

    # different uri and inv, redirected
    status.seek(0)
    status.truncate(0)
    _read_from_url().url = 'http://hostname/other/' + INVENTORY_FILENAME

    fetch_inventory(app, 'http://hostname/', 'http://hostname/new/' + INVENTORY_FILENAME)
    assert status.getvalue() == ('intersphinx inventory has moved: '
                                 'http://hostname/new/%s -> http://hostname/other/%s\n' %
                                 (INVENTORY_FILENAME, INVENTORY_FILENAME))
    assert InventoryFile.load.call_args[0][1] == 'http://hostname/'
Ejemplo n.º 26
0
    def handle(self, *args, **options):
        """
        Docs urls for Classes can differ between Django versions.
        This script sets correct urls for specific Classes using bits from
        `sphinx.ext.intersphinx` to fetch docs inventory data.
        """

        for v in self.django_versions:
            cnt = 1

            ver_url = self.django_doc_url.format(version=v)
            ver_inv_url = ver_url + '/' + self.inv_filename

            # get flat list of CBV classes per Django version
            qs_lookups = {'module__project_version__version_number': v}
            ver_classes = Klass.objects.filter(**qs_lookups).values_list(
                'name', flat=True)
            self.bless_prints(v, 'Found {0} classes'.format(len(ver_classes)))
            self.bless_prints(v, 'Getting inventory @ {0}'.format(ver_inv_url))
            # fetch some inventory dataz
            # the arg `r.raw` should be a Sphinx instance object..
            r = requests.get(ver_inv_url, stream=True)
            r.raise_for_status()
            invdata = fetch_inventory(r.raw, ver_url, ver_inv_url)
            # we only want classes..
            for item in invdata[u'py:class']:
                # ..which come from one of our sources
                if any(
                    [source in item
                     for source in settings.CBV_SOURCES.keys()]):
                    # get class name
                    inv_klass = item.split('.')[-1]
                    # save hits to db and update only required classes
                    for vc in ver_classes:
                        if vc == inv_klass:
                            url = invdata[u'py:class'][item][2]
                            qs_lookups.update({'name': inv_klass})
                            Klass.objects.filter(**qs_lookups).update(
                                docs_url=url)
                            cnt += 1
                            continue
            self.bless_prints(v, 'Updated {0} classes\n'.format(cnt))
    def handle(self, *args, **options):
        """
        Docs urls for Classes can differ between Django versions.
        This script sets correct urls for specific Classes using bits from
        `sphinx.ext.intersphinx` to fetch docs inventory data.
        """

        for v in self.django_versions:
            cnt = 1

            ver_url = f'https://docs.djangoproject.com/en/{v}'
            ver_inv_url = ver_url + '/' + self.inv_filename

            # get flat list of CBV classes per Django version
            qs_lookups = {'module__project_version__version_number': v}
            ver_classes = Klass.objects.filter(**qs_lookups).values_list(
                'name', flat=True)
            self.bless_prints(v, f'Found {len(ver_classes)} classes')
            self.bless_prints(v, f'Getting inventory @ {ver_inv_url}')
            # fetch some inventory dataz
            # the arg `r.raw` should be a Sphinx instance object..
            r = requests.get(ver_inv_url, stream=True)
            r.raise_for_status()
            invdata = fetch_inventory(r.raw, ver_url, ver_inv_url)
            # we only want classes..
            for item in invdata['py:class']:
                # ..which come from one of our sources
                if any(source in item for source in settings.CBV_SOURCES.keys()):
                    # get class name
                    inv_klass = item.split('.')[-1]
                    # save hits to db and update only required classes
                    for vc in ver_classes:
                        if vc == inv_klass:
                            url = invdata['py:class'][item][2]
                            qs_lookups.update({
                                'name': inv_klass
                            })
                            Klass.objects.filter(**qs_lookups).update(
                                docs_url=url)
                            cnt += 1
                            continue
            self.bless_prints(v, f'Updated {cnt} classes\n')
Ejemplo n.º 28
0
def fetch_intersphinx_inventory(uri):
    """
    Fetch and read an intersphinx inventory file at a specified uri,
    which can either be a url (e.g. http://...) or a local file system
    filename.
    """

    # See https://stackoverflow.com/a/30981554
    class MockConfig(object):
        intersphinx_timeout = None
        tls_verify = False

    class MockApp(object):
        srcdir = ''
        config = MockConfig()

        def warn(self, msg):
            warnings.warn(msg)

    return intersphinx.fetch_inventory(MockApp(), '', uri)
Ejemplo n.º 29
0
def load_cache_from_url(url):
    """Load some inventory file as raw data.

    Args:
        url (str):
            The website address that points to a objects.inv file.
            e.g. "https://foo_bar_name.readthedocs.io/en/latest/objects.inv".

    Returns:
        dict[str, dict[str, tuple[str, str, str, str]]]:
            Each directive target type, its namespace, and it's file-path/URL information.
            e.g. {
                "py:method": {
                    "fake_project.basic.MyKlass.get_method": (
                        "fake_project",
                        "",
                        "api/fake_project.html#fake_project.basic.MyKlass.get_method",
                        "-",
                    )
                }
            }

    """
    class MockConfiguration(object):  # pylint: disable=too-few-public-methods
        """A fake set of settings for intersphinx to pass-through."""

        intersphinx_timeout = None  # type: int
        tls_verify = False

    class MockApplication(object):  # pylint: disable=too-few-public-methods
        """A fake state machine for intersphinx to consume and pass-through."""

        srcdir = ""
        config = MockConfiguration()

        @staticmethod
        def warn(message):
            """Send a warning if bad-formatted text is encountered."""
            warnings.warn(message)

    return intersphinx.fetch_inventory(MockApplication(), "", url)
    def handle(self, *args, **options):
        """
        Docs urls for Classes can differ between Django versions.
        This script sets correct urls for specific Classes using bits from
        `sphinx.ext.intersphinx` to fetch docs inventory data.
        """

        for v in self.django_versions:
            cnt = 1

            ver_url = self.django_doc_url.format(version=v)
            ver_inv_url = ver_url + '/' + self.inv_filename

            # get flat list of CBV classes per Django version
            qs_lookups = {'module__project_version__version_number': v}
            ver_classes = Klass.objects.filter(**qs_lookups).values_list(
                'name', flat=True)
            self.bless_prints(v, 'Found {0} classes'.format(len(ver_classes)))
            self.bless_prints(v, 'Getting inventory @ {0}'.format(ver_inv_url))
            # fetch some inventory dataz
            # the arg `None` should be a Sphinx instance object..
            invdata = fetch_inventory(None, ver_url, ver_inv_url)
            # we only want classes..
            for item in invdata[u'py:class']:
                # ..which come from one of our sources
                if any ([source in item for source in settings.CBV_SOURCES.keys()]):
                    # get class name
                    inv_klass = item.split('.')[-1]
                    # save hits to db and update only required classes
                    for vc in ver_classes:
                        if vc == inv_klass:
                            url = invdata[u'py:class'][item][2]
                            qs_lookups.update({
                                'name': inv_klass
                            })
                            Klass.objects.filter(**qs_lookups).update(
                                docs_url=url)
                            cnt += 1
                            continue
            self.bless_prints(v, 'Updated {0} classes\n'.format(cnt))
Ejemplo n.º 31
0
def load_cache(path):
    """Load some inventory file as raw data.

    Args:
        path (str):
            The absolute path where an inventory file can be found.

    Returns:
        dict[str, dict[str, tuple[str, str, str, str]]]:
            Each directive target type, its namespace, and it's file-path/URL information.
            e.g. {
                "py:method": {
                    "fake_project.basic.MyKlass.get_method": (
                        "fake_project",
                        "",
                        "api/fake_project.html#fake_project.basic.MyKlass.get_method",
                        "-",
                    )
                }
            }

    """
    class MockConfiguration(object):  # pylint: disable=too-few-public-methods
        """A fake set of settings for intersphinx to pass-through."""

        intersphinx_timeout = None  # type: int
        tls_verify = False

    class MockApplication(object):  # pylint: disable=too-few-public-methods
        """A fake state machine for intersphinx to consume and pass-through."""

        srcdir = ""
        config = MockConfiguration()

        @staticmethod
        def warn(message):
            """Send a warning if bad-formatted text is encountered."""
            warnings.warn(message)

    return intersphinx.fetch_inventory(MockApplication(), "", path)
Ejemplo n.º 32
0
def get_known_blocks():
    from sphinx.ext.intersphinx import fetch_inventory #@UnresolvedImport
    
    ''' Returns a map block -> url '''
    
    bases = [
        'http://andreacensi.github.com/be1008/',
        'http://andreacensi.github.com/procgraph/',
        'http://andreacensi.github.com/procgraph_rawseeds/']
    
    result = {}
    for base in bases:
        url = base + '/objects.inv'
        map = fetch_inventory(None, base, url);
        labels = map['std:label']
        for key in labels:
            if key.startswith('block:'):
                block = key[6:]
                url = labels[key][2].split()[0]
                result[block] = url
        
    return result
Ejemplo n.º 33
0
def verify_modules(build_root="_build"):
    """Verify modules included.

    :type build_root: str
    :param build_root: The root of the directory where docs are built into.
                       Defaults to ``_build``.
    """
    object_inventory_relpath = os.path.join(build_root, "html", "objects.inv")

    mock_uri = ""
    inventory = fetch_inventory(SphinxApp, mock_uri, object_inventory_relpath)
    sphinx_mods = set(inventory["py:module"].keys())

    public_mods = set()
    for package in PACKAGES:
        library_dir = os.path.join(BASE_DIR, package, "google", "cloud")
        package_mods = get_public_modules(library_dir,
                                          base_package="google.cloud")
        public_mods.update(package_mods)

    if not sphinx_mods <= public_mods:
        unexpected_mods = sphinx_mods - public_mods
        message = [
            "Unexpected error. There were modules referenced by "
            "Sphinx that are not among the public modules."
        ]
        message.extend(["- %s" % (mod, ) for mod in unexpected_mods])
        print("\n".join(message), file=sys.stderr)
        sys.exit(1)

    undocumented_mods = public_mods - sphinx_mods
    # Remove ignored modules.
    undocumented_mods -= IGNORED_MODULES
    if undocumented_mods:
        message_parts = ["Found undocumented public modules:"]
        message_parts.extend(
            ["- " + mod_name for mod_name in sorted(undocumented_mods)])
        print("\n".join(message_parts), file=sys.stderr)
        sys.exit(1)
Ejemplo n.º 34
0
def verify_modules(build_root='_build'):
    """Verify modules included.

    :type build_root: str
    :param build_root: The root of the directory where docs are built into.
                       Defaults to ``_build``.
    """
    object_inventory_relpath = os.path.join(build_root, 'html', 'objects.inv')

    mock_uri = ''
    inventory = fetch_inventory(SphinxApp, mock_uri, object_inventory_relpath)
    sphinx_mods = set(inventory['py:module'].keys())

    public_mods = set()
    for package in PACKAGES:
        library_dir = os.path.join(PROJECT_ROOT, package, 'google', 'cloud')
        package_mods = get_public_modules(library_dir,
                                          base_package='google.cloud')
        public_mods.update(package_mods)

    if not sphinx_mods <= public_mods:
        unexpected_mods = sphinx_mods - public_mods
        message = [
            'Unexpected error. There were modules referenced by '
            'Sphinx that are not among the public modules.'
        ]
        message.extend(['- %s' % (mod, ) for mod in unexpected_mods])
        print('\n'.join(message), file=sys.stderr)
        sys.exit(1)

    undocumented_mods = public_mods - sphinx_mods
    # Remove ignored modules.
    undocumented_mods -= IGNORED_MODULES
    if undocumented_mods:
        message_parts = ['Found undocumented public modules:']
        message_parts.extend(
            ['- ' + mod_name for mod_name in sorted(undocumented_mods)])
        print('\n'.join(message_parts), file=sys.stderr)
        sys.exit(1)
def verify_modules(build_root='_build'):
    """Verify modules included.

    :type build_root: str
    :param build_root: The root of the directory where docs are built into.
                       Defaults to ``_build``.
    """
    object_inventory_relpath = os.path.join(build_root, 'html', 'objects.inv')

    mock_uri = ''
    inventory = fetch_inventory(SphinxApp, mock_uri,
                                object_inventory_relpath)
    sphinx_mods = set(inventory['py:module'].keys())

    public_mods = set()
    for package in PACKAGES:
        library_dir = os.path.join(PROJECT_ROOT, package, 'google', 'cloud')
        package_mods = get_public_modules(library_dir,
                                          base_package='google.cloud')
        public_mods.update(package_mods)

    if not sphinx_mods <= public_mods:
        unexpected_mods = sphinx_mods - public_mods
        message = ['Unexpected error. There were modules referenced by '
                   'Sphinx that are not among the public modules.']
        message.extend(['- %s' % (mod,) for mod in unexpected_mods])
        print('\n'.join(message), file=sys.stderr)
        sys.exit(1)

    undocumented_mods = public_mods - sphinx_mods
    # Remove ignored modules.
    undocumented_mods -= IGNORED_MODULES
    if undocumented_mods:
        message_parts = ['Found undocumented public modules:']
        message_parts.extend(['- ' + mod_name
                              for mod_name in sorted(undocumented_mods)])
        print('\n'.join(message_parts), file=sys.stderr)
        sys.exit(1)
def main():
    """Main script to verify modules included."""
    mock_uri = ""
    inventory = fetch_inventory(SphinxApp, mock_uri, OBJECT_INVENTORY_RELPATH)
    sphinx_mods = set(inventory["py:module"].keys())

    library_dir = os.path.join(BASE_DIR, "gcloud")
    public_mods = get_public_modules(library_dir, base_package="gcloud")
    public_mods = set(public_mods)

    if not sphinx_mods <= public_mods:
        message = "Unexpected error. There were modules referenced by " "Sphinx that are not among the public modules."
        print(message, file=sys.stderr)
        sys.exit(1)

    undocumented_mods = public_mods - sphinx_mods
    # Remove ignored modules.
    undocumented_mods -= IGNORED_MODULES
    if undocumented_mods:
        message_parts = ["Found undocumented public modules:"]
        message_parts.extend(["- " + mod_name for mod_name in sorted(undocumented_mods)])
        print("\n".join(message_parts), file=sys.stderr)
        sys.exit(1)
Ejemplo n.º 37
0
def update_intersphinx(version_pk):
    version_data = api.version(version_pk).get()
    del version_data['resource_uri']
    project_data = version_data['project']
    del project_data['users']
    del project_data['resource_uri']
    del project_data['absolute_url']
    project = Project(**project_data)
    version_data['project'] = project
    version = Version(**version_data)

    object_file = version.project.find('objects.inv', version.slug)[0]
    path = version.project.rtd_build_path(version.slug)
    if not path:
        log.warning("%s has no path" % version)
        return None
    app = DictObj()
    app.srcdir = path
    try:
        inv = fetch_inventory(app, path, object_file)
    except TypeError, e:
        log.error("Failed to fetch inventory for %s" % version, exc_info=True)
        return None
Ejemplo n.º 38
0
def update_intersphinx(version_pk):
    version_data = api.version(version_pk).get()
    del version_data['resource_uri']
    project_data = version_data['project']
    del project_data['users']
    del project_data['resource_uri']
    del project_data['absolute_url']
    project = Project(**project_data)
    version_data['project'] = project
    version = Version(**version_data)

    object_file = version.project.find('objects.inv', version.slug)[0]
    path = version.project.rtd_build_path(version.slug)
    if not path:
        log.warning("%s has no path" % version)
        return None
    app = DictObj()
    app.srcdir = path
    try:
        inv = fetch_inventory(app, path, object_file)
    except TypeError, e:
        log.error("Failed to fetch inventory for %s" % version, exc_info=True)
        return None
def get_python_standard_modules(version=None):
    version = '{}.{}'.format(sys.version_info[0],
                             sys.version_info[1]) if not version else version
    module_cache_file = 'python{}_modules.csv'.format(version.replace(
        '.', '_'))
    if os.path.exists(module_cache_file):
        print('read python {} standard modules'.format(version))
        modules = list()
        with open(module_cache_file, 'r') as fr:
            while True:
                line = fr.readline()
                if not line:
                    break
                modules.append(line.strip())
    else:
        from sphinx.ext.intersphinx import fetch_inventory
        print('fetch python {} standard modules'.format(version))
        url = "http://docs.python.org/{}/objects.inv".format(version)

        modules = sorted(
            list(fetch_inventory(DummyApp(), "", url).get("py:module").keys()))
        with open(module_cache_file, 'w') as fw:
            fw.write('\n'.join(modules))
    return modules
Ejemplo n.º 40
0
    def __prase_inv_file(filename):
        class MockConfig:
            intersphinx_timeout: int = None
            tls_verify = False
            user_agent = None

        class MockApp:
            srcdir = ''
            config = MockConfig()

            def warn(self, msg: str) -> None:
                print(msg, file=sys.stderr)

        invdata = fetch_inventory(MockApp(), '', filename)  # type: ignore
        result = {}
        for key in sorted(invdata or {}):
            result[key] = {}
            data = result[key]
            for entry, einfo in sorted(invdata[key].items()):
                data[entry] = {
                    "title": einfo[3] if einfo[3] != '-' else '',
                    "link": einfo[2]
                }
        return result
Ejemplo n.º 41
0
 def assert_fetch_inventory_success(self, filename):
     app = MockApp()
     inv_data = fetch_inventory(app, '', filename)
     self.assertEqual(0, app.warning_count, app.warnings)
     self.assertIsInstance(inv_data, dict)
     return inv_data
Ejemplo n.º 42
0
    logging.basicConfig(level=level, format="[%(levelname)s]: %(message)s")

    # Be kind and cache results while we're woking on this locally.
    requests_cache.install_cache("sphinx-doc")

    # Rather than trying to use Sphinx directly, just mock out the bare minimum.
    app = mock_app()

    # objects.inv is amazing, it's useful in so many ways! With it we can
    # - automatically discover all the (documented!) roles and directives that Sphinx provides.
    # - ensure all cross-referencing roles resolve correctly, by providing implementations that
    #   use it look up the correct url.
    # - ensure all descriptive directives produce sections with sensible ids we can use when
    #   selecting subsections of doctrees to render out.
    base_url = "https://www.sphinx-doc.org/en/master/"
    objects_inv = fetch_inventory(app, base_url, f"{base_url}objects.inv")

    # Register mocks for the additional roles and directives that Sphinx provides
    directives_, roles_ = mock_directives_roles(app, objects_inv)

    files = [
        ("directives.json", "rst:directive", directives_),
        ("roles.json", "rst:role", roles_),
    ]
    for filename, obj_type, objects in files:
        logger.info("Generating %s documentation", obj_type)

        mapping = build_map(base_url, objects_inv, obj_type)
        docs = generate_documentation(mapping, objects)

        with (out / filename).open("w") as f:
Ejemplo n.º 43
0
def _create_intersphinx_data(version, commit, build):
    """
    Create intersphinx data for this version.

    :param version: Version instance
    :param commit: Commit that updated path
    :param build: Build id
    """
    if not version.is_sphinx_type:
        return

    html_storage_path = version.project.get_storage_path(
        type_='html', version_slug=version.slug, include_file=False
    )
    json_storage_path = version.project.get_storage_path(
        type_='json', version_slug=version.slug, include_file=False
    )

    object_file = build_media_storage.join(html_storage_path, 'objects.inv')
    if not build_media_storage.exists(object_file):
        log.debug('No objects.inv, skipping intersphinx indexing.')
        return

    type_file = build_media_storage.join(json_storage_path, 'readthedocs-sphinx-domain-names.json')
    types = {}
    titles = {}
    if build_media_storage.exists(type_file):
        try:
            data = json.load(build_media_storage.open(type_file))
            types = data['types']
            titles = data['titles']
        except Exception:
            log.exception('Exception parsing readthedocs-sphinx-domain-names.json')

    # These classes are copied from Sphinx
    # https://github.com/sphinx-doc/sphinx/blob/d79d041f4f90818e0b495523fdcc28db12783caf/sphinx/ext/intersphinx.py#L400-L403  # noqa
    class MockConfig:
        intersphinx_timeout = None
        tls_verify = False
        user_agent = None

    class MockApp:
        srcdir = ''
        config = MockConfig()

        def warn(self, msg):
            log.warning('Sphinx MockApp.', msg=msg)

    # Re-create all objects from the new build of the version
    object_file_url = build_media_storage.url(object_file)
    if object_file_url.startswith('/'):
        # Filesystem backed storage simply prepends MEDIA_URL to the path to get the URL
        # This can cause an issue if MEDIA_URL is not fully qualified
        object_file_url = settings.RTD_INTERSPHINX_URL + object_file_url

    invdata = intersphinx.fetch_inventory(MockApp(), '', object_file_url)
    for key, value in sorted(invdata.items() or {}):
        domain, _type = key.split(':', 1)
        for name, einfo in sorted(value.items()):
            # project, version, url, display_name
            # ('Sphinx', '1.7.9', 'faq.html#epub-faq', 'Epub info')
            try:
                url = einfo[2]
                if '#' in url:
                    doc_name, anchor = url.split(
                        '#',
                        # The anchor can contain ``#`` characters
                        maxsplit=1
                    )
                else:
                    doc_name, anchor = url, ''
                display_name = einfo[3]
            except Exception:
                log.exception(
                    'Error while getting sphinx domain information. Skipping...',
                    project_slug=version.project.slug,
                    version_slug=version.slug,
                    sphinx_domain='{domain}->{name}',
                )
                continue

            # HACK: This is done because the difference between
            # ``sphinx.builders.html.StandaloneHTMLBuilder``
            # and ``sphinx.builders.dirhtml.DirectoryHTMLBuilder``.
            # They both have different ways of generating HTML Files,
            # and therefore the doc_name generated is different.
            # More info on: http://www.sphinx-doc.org/en/master/usage/builders/index.html#builders
            # Also see issue: https://github.com/readthedocs/readthedocs.org/issues/5821
            if doc_name.endswith('/'):
                doc_name += 'index.html'

            html_file = HTMLFile.objects.filter(
                project=version.project, version=version,
                path=doc_name, build=build,
            ).first()

            if not html_file:
                log.debug(
                    'HTMLFile object not found.',
                    project_slug=version.project.slug,
                    version_slug=version.slug,
                    build_id=build,
                    doc_name=doc_name
                )

                # Don't create Sphinx Domain objects
                # if the HTMLFile object is not found.
                continue

            SphinxDomain.objects.create(
                project=version.project,
                version=version,
                html_file=html_file,
                domain=domain,
                name=name,
                display_name=display_name,
                type=_type,
                type_display=types.get(f'{domain}:{_type}', ''),
                doc_name=doc_name,
                doc_display=titles.get(doc_name, ''),
                anchor=anchor,
                commit=commit,
                build=build,
            )
Ejemplo n.º 44
0
    version_data['project'] = project
    version = Version(**version_data)

    try:
        object_file = version.project.find('objects.inv', version.slug)[0]
    except IndexError, e:
        print "Failed to find objects file"
        return None
    path = version.project.rtd_build_path(version.slug)
    if not path:
        log.warning("%s has no path" % version)
        return None
    app = DictObj()
    app.srcdir = path
    try:
        inv = fetch_inventory(app, path, object_file)
    except TypeError, e:
        log.error("Failed to fetch inventory for %s" % version, exc_info=True)
        return None
    # TODO: I'm entirelty not sure this is even close to correct.
    # There's a lot of info I'm throwing away here; revisit later?
    for keytype in inv:
        for term in inv[keytype]:
            try:
                _, _, url, title = inv[keytype][term]
                if not title or title == '-':
                    if '#' in url:
                        title = url.rsplit('#')[-1]
                    else:
                        title = url
                find_str = "rtd-builds/latest"
Ejemplo n.º 45
0

class FakeConfig:
    intersphinx_timeout = None
    tls_verify = True


class FakeApp:
    srcdir = ""
    config = FakeConfig()


for version_info in VERSIONS:
    version = ".".join(version_info)
    url = URL.format(version)
    invdata = fetch_inventory(FakeApp(), "", url)

    modules = set()
    for module in invdata["py:module"]:
        root, *_ = module.split(".")
        if root not in ["__future__", "__main__"]:
            modules.add(root)

    path = PATH.format("".join(version_info))
    with open(path, "w") as fp:
        docstring = DOCSTRING.format(version)
        fp.write('"""{}"""\n\n'.format(docstring))
        fp.write("stdlib = [\n")
        for module in sorted(modules):
            fp.write('    "{}",\n'.format(module))
        fp.write("]\n")