Skip to content

Commit

Permalink
Merge branch 'master' into visit-try-orelse-finalbody-and-if-orelse
Browse files Browse the repository at this point in the history
  • Loading branch information
tristanlatr authored Jul 6, 2024
2 parents 2dd25e1 + 0743773 commit 4c00191
Show file tree
Hide file tree
Showing 32 changed files with 1,012 additions and 441 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/pydoctor_primer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
with:
path: pydoctor_to_test
fetch-depth: 0
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install pydoctor_primer
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/static.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: '3.8'
python-version: '3.12'

- name: Install tox
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/system.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ jobs:
tox_target: [twisted-apidoc, cpython-summary, python-igraph-apidocs, cpython-apidocs, numpy-apidocs, git-buildpackage-apidocs, pytype-apidocs]

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Set up CPython
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: '3.11'

Expand Down
78 changes: 58 additions & 20 deletions .github/workflows/unit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,36 @@ name: Unit tests and release
on:
push:
branches: [ master ]
tags:
tags:
- '*'
pull_request:
branches: [ master ]


permissions:
contents: read


jobs:
unit_tests:
runs-on: ${{ matrix.os }}

strategy:
matrix:
python-version: [pypy-3.7, 3.7, 3.8, 3.9, '3.10', 3.11, '3.12.0-rc.3']
os: [ubuntu-20.04]
# Re-enable 3.13-dev when https://github.com/zopefoundation/zope.interface/issues/292 is fixed
python-version: [pypy-3.7, 3.7, 3.8, 3.9, '3.10', 3.11, '3.12']
os: [ubuntu-22.04]
include:
- os: windows-latest
python-version: 3.7
python-version: 3.11
- os: macos-latest
python-version: 3.7
python-version: 3.11

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

Expand All @@ -51,23 +57,37 @@ jobs:
tox -e test-latest-twisted
- name: Publish code coverage
continue-on-error: true
run: |
tox -e codecov
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: true
files: ./coverage.xml
name: unit-${{ matrix.os }}-${{matrix.python-version}}
# Check the secret defined in GHA here
# https://github.com/twisted/pydoctor/settings/secrets/actions
# And get it from Codecov.io here
# https://app.codecov.io/gh/twisted/pydoctor/settings
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true

release:

needs: [unit_tests]
runs-on: ubuntu-latest

permissions:
contents: read
# The `id-token` permission is mandatory for trusted publishing
# See https://github.com/pypa/gh-action-pypi-publish
id-token: write

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Set up Python 3.9
uses: actions/setup-python@v2
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.9
python-version: 3.12

- name: Log system information
run: |
test -r /etc/os-release && sh -c '. /etc/os-release && echo "OS: $PRETTY_NAME"'
Expand All @@ -84,9 +104,27 @@ jobs:
python setup.py --quiet build check sdist bdist_wheel
ls -alh ./dist/
- name: Publish pydoctor to PyPI on tags
if: startsWith(github.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@master
- name: Publish to PyPI - on tag
if: startsWith(github.ref, 'refs/tags/')
uses: pypa/gh-action-pypi-publish@release/v1

# This is a meta-job to simplify PR CI enforcement configuration in GitHub.
# Inside the GitHub config UI you only configure this job as required.
# All the extra requirements are defined "as code" as part of the `needs`
# list for this job.
gha-required:
name: GHA Required
runs-on: ubuntu-latest
# The `if` condition is very important.
# If not set, the job will be skipped on failing dependencies.
if: ${{ !cancelled() }}
needs:
# This is the list of CI job that we are interested to pass before
# a merge.
# pypi-publish is skipped since this is only executed for a tag.
- unit_tests
steps:
- name: Require all successes
uses: re-actors/alls-green@3a2de129f0713010a71314c74e33c0e3ef90e696
with:
user: __token__
password: ${{ secrets.PYPI_TOKEN }}
jobs: ${{ toJSON(needs) }}
23 changes: 21 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,33 @@ What's New?
in development
^^^^^^^^^^^^^^

* Trigger a warning when several docstrings are detected for the same object.

pydoctor 24.3.3
^^^^^^^^^^^^^^^

* Fix release pipeline.

pydoctor 24.3.0
^^^^^^^^^^^^^^^

This is the last major release to support Python 3.7.

* Drop support for Python 3.6
* Add support for Python 3.12
* Drop support for Python 3.6.
* Add support for Python 3.12.
* Astor is no longer a requirement starting at Python 3.9.
* `ExtRegistrar.register_post_processor()` now supports a `priority` argument that is an int.
Highest priority callables will be called first during post-processing.
* Fix too noisy ``--verbose`` mode (suppres some ambiguous annotations warnings).
* Fix type processing inside restructuredtext consolidated fields.
* Add options ``--cls-member-order`` and ``--mod-member-order`` to customize the presentation
order of class members and module/package members, the supported values are "alphabetical" or "source".
The default behavior is to sort all members alphabetically.
* Make sure the line number coming from ast analysis has precedence over the line of a ``ivar`` field.
* Ensure that all docutils generated css classes have the ``rst-`` prefix, the base theme have been updated accordingly.
* Fix compatibility issue with docutils 0.21.x
* Transform annotations to use python 3.10 style: ``typing.Union[x, y]`` -> ``x | y``; ``typing.Optional[x]`` -> ``x | None``; ``typing.List[x]`` -> ``list[x]``.
* Do not output useless parenthesis when colourizing subscripts.

pydoctor 23.9.1
^^^^^^^^^^^^^^^
Expand Down
10 changes: 8 additions & 2 deletions docs/source/contrib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,15 @@ Read more about reviewing:
Releasing and publishing a new package
--------------------------------------

Publishing to PyPI is done via a GitHub Actions workflow that is triggered when a tag is pushed. Version is configured in the ``setup.cfg``.
Publishing to PyPI is done via a GitHub Actions workflow.
The publish to PyPI is triggered when a tag is pushed.
Version is configured in the ``setup.cfg``.

The following process ensures correct version management:
The `pydoctor PyPI project <https://pypi.org/manage/project/pydoctor/settings/publishing>`_ is configured to accept trusted publishing via GitHub actions from the `unit.yaml` workflow.

If the release is done from another workflow file, the PyPI project management page needs to be updated.

The following process ensures correct version management:

- Create a branch: name it by the name of the new major ``pydoctor`` version, i.e. ``21.9.x``, re-use that same branch for bug-fixes.
- On the branch, update the version and release notes.
Expand Down
4 changes: 2 additions & 2 deletions docs/source/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ It also has support for `zope.interface <https://zopeinterface.readthedocs.io/en

How is it different from ``sphinx-autodoc``
-------------------------------------------

``sphinx-autodoc`` can be complex and the output is sometimes overwhelming, ``pydoctor`` will generate
``sphinx-autodoc`` operates semi-automatic rather than fully automatically. It can not generate documentation solely from Python source files; it always requires a reStructuredText file as well.
It can also be complex and the output is sometimes overwhelming, ``pydoctor`` will generate
one page per class, module and package, it tries to keeps it simple and present information in a efficient way with tables.

Sphinx narrative documentation can seamlessly link to API documentation formatted by pydoctor.
Expand Down
30 changes: 15 additions & 15 deletions pydoctor/astbuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@
Type, TypeVar, Union, Set, cast
)

import astor
from pydoctor import epydoc2stan, model, node2stan, extensions, linker
from pydoctor.epydoc.markup._pyval_repr import colorize_inline_pyval
from pydoctor.astutils import (is_none_literal, is_typing_annotation, is_using_annotations, is_using_typing_final, node2dottedname, node2fullname,
is__name__equals__main__, unstring_annotation, iterassign, extract_docstring_linenum, infer_type, get_parents,
get_docstring_node, NodeVisitor, Parentage, Str)
is__name__equals__main__, unstring_annotation, upgrade_annotation, iterassign, extract_docstring_linenum, infer_type, get_parents,
get_docstring_node, unparse, NodeVisitor, Parentage, Str)


def parseFile(path: Path) -> ast.Module:
Expand Down Expand Up @@ -130,9 +129,9 @@ def visit_Assign(self, node: Union[ast.Assign, ast.AnnAssign]) -> None:
if self._isTypeAlias(attr) is True:
attr.kind = model.DocumentableKind.TYPE_ALIAS
# unstring type aliases
attr.value = unstring_annotation(
attr.value = upgrade_annotation(unstring_annotation(
# this cast() is safe because _isTypeAlias() return True only if value is not None
cast(ast.expr, attr.value), attr, section='type alias')
cast(ast.expr, attr.value), attr, section='type alias'), attr, section='type alias')
elif self._isTypeVariable(attr) is True:
# TODO: unstring bound argument of type variables
attr.kind = model.DocumentableKind.TYPE_VARIABLE
Expand Down Expand Up @@ -286,8 +285,8 @@ def visit_ClassDef(self, node: ast.ClassDef) -> None:
name_node = base_node.value

str_base = '.'.join(node2dottedname(name_node) or \
# Fallback on astor if the expression is unknown by node2dottedname().
[astor.to_source(base_node).strip()])
# Fallback on unparse() if the expression is unknown by node2dottedname().
[unparse(base_node).strip()])

# Store the base as string and as ast.expr in rawbases list.
rawbases += [(str_base, base_node)]
Expand Down Expand Up @@ -790,7 +789,7 @@ def warn(msg: str) -> None:
return

if obj is not None:
obj.docstring = docstring
obj._setDocstringValue(docstring, expr.lineno)
# TODO: It might be better to not perform docstring parsing until
# we have the final docstrings for all objects.
obj.parsed_docstring = None
Expand Down Expand Up @@ -827,7 +826,8 @@ def visit_Assign(self, node: ast.Assign) -> None:
if type_comment is None:
annotation = None
else:
annotation = unstring_annotation(ast.Constant(type_comment, lineno=lineno), self.builder.current)
annotation = upgrade_annotation(unstring_annotation(
ast.Constant(type_comment, lineno=lineno), self.builder.current), self.builder.current)

for target in node.targets:
if isinstance(target, ast.Tuple):
Expand All @@ -839,7 +839,8 @@ def visit_Assign(self, node: ast.Assign) -> None:
self._handleAssignment(target, annotation, expr, lineno)

def visit_AnnAssign(self, node: ast.AnnAssign) -> None:
annotation = unstring_annotation(node.annotation, self.builder.current)
annotation = upgrade_annotation(unstring_annotation(
node.annotation, self.builder.current), self.builder.current)
self._handleAssignment(node.target, annotation, node.value, node.lineno)

def visit_AugAssign(self, node:ast.AugAssign) -> None:
Expand Down Expand Up @@ -1035,9 +1036,7 @@ def _handlePropertyDef(self,
if tag == 'return':
if not pdoc.has_body:
pdoc = field.body()
# Avoid format_summary() going back to the original
# empty-body docstring.
attr.docstring = ''

elif tag == 'rtype':
attr.parsed_type = field.body()
else:
Expand All @@ -1046,7 +1045,7 @@ def _handlePropertyDef(self,
attr.parsed_docstring = pdoc

if node.returns is not None:
attr.annotation = unstring_annotation(node.returns, attr)
attr.annotation = upgrade_annotation(unstring_annotation(node.returns, attr), attr)
attr.decorators = node.decorator_list

return attr
Expand Down Expand Up @@ -1087,7 +1086,8 @@ def _get_all_ast_annotations() -> Iterator[Tuple[str, Optional[ast.expr]]]:
# Include parameter names even if they're not annotated, so that
# we can use the key set to know which parameters exist and warn
# when non-existing parameters are documented.
name: None if value is None else unstring_annotation(value, self.builder.current)
name: None if value is None else upgrade_annotation(unstring_annotation(
value, self.builder.current), self.builder.current)
for name, value in _get_all_ast_annotations()
}

Expand Down
Loading

0 comments on commit 4c00191

Please sign in to comment.