Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Package should not be a Module/File #11137

Closed
bluetech opened this issue Jun 24, 2023 · 0 comments · Fixed by #11138
Closed

Package should not be a Module/File #11137

bluetech opened this issue Jun 24, 2023 · 0 comments · Fixed by #11138
Assignees
Labels
topic: collection related to the collection phase type: backward compatibility might present some backward compatibility issues which should be carefully noted in the changelog type: proposal proposal for a new feature, often to gather opinions or design the API around the new feature
Milestone

Comments

@bluetech
Copy link
Member

Note: this issue is extracted verbatim from #7777 (comment) so I can refer to it separately

Package is currently a subclass of a Module, with package.path being the __init__.py file.

While technically in terms of the Python data model this is correct, I'm pretty convinced this was the wrong decision in pytest:

Package is a Module with path __init__.py, but it doesn't actually act as a Module behaviorally, it overrides everything that Module does and doesn't call super() on anything.

Module is a nodes.File, which makes Package a nodes.File, but it doesn't act as a file.

The previous points can be rephrased as: Package breaks Liskov substitution -- any code dealing with File or Module generically probably doesn't want Package.

Package is a Module with path __init__.py, but it actually collects a "real" (non-Package) Module for the __init__.py file (if permitted by python_files glob). This is very confusing.

Package and __init__.py necessitates several special-casings because of these points:

  • # Packages are Modules, but _last_failed_paths only contains
    # test-bearing paths and doesn't try to include the paths of their
    # packages, so don't filter them.
    if isinstance(collector, Module) and not isinstance(collector, Package):
  • pytest/src/_pytest/main.py

    Lines 805 to 818 in 24534cd

    # If __init__.py was the only file requested, then the matched
    # node will be the corresponding Package (by default), and the
    # first yielded item will be the __init__ Module itself, so
    # just use that. If this special case isn't taken, then all the
    # files in the package will be yielded.
    if argpath.name == "__init__.py" and isinstance(matching[0], Package):
    try:
    yield next(iter(matching[0].collect()))
    except StopIteration:
    # The package collects nothing with only an __init__.py
    # file in it, which gets ignored by the default
    # "python_files" option.
    pass
    continue
  • fixture_package_name = "{}/{}".format(fixturedef.baseid, "__init__.py")
  • if module_path.name == "__init__.py":
    pkg: Package = Package.from_parent(parent, path=module_path)
    return pkg
  • # Always collect the __init__ first.
    if path_matches_patterns(self.path, self.config.getini("python_files")):
    yield Module.from_parent(self, path=self.path)
    pkg_prefixes: Set[Path] = set()
    for direntry in visit(str(this_path), recurse=self._recurse):
    path = Path(direntry.path)
    # We will visit our own __init__.py file, in which case we skip it.
    if direntry.is_file():
    if direntry.name == "__init__.py" and path.parent == this_path:
    continue

Proposed solution

As part of the breaking Package changes discussed previously in this issue, also make these changes

  • Package no longer inherits from Module (or File by extension), just from FSCollector.
  • Package.path is the package directory, not the __init__.py file.
  • Collecting pkg/__init__.py collects the __init__.py file as a module (file), doesn't collect the entire package.

This also matches the new Directory node, which is the non-Package directory collector. Directory will inherit just from FSCollector and its path will be the directory. It will be much better if they are as similar to each other as possible.

Complication

Currently Package has a setup() method which imports the __init__.py' and runs its setup_module function and registers teardown_module finalizer (in effectively the package scope). If we want to stop having Package as a Module it becomes a bit less natural to implement.

This functionality has some issues:

  • It is undocumented.
  • It doesn't match unittest which doesn't have package functionality
  • The names setup_module and teardown_module conflict with the "real" __init__.py Module setup/teardown; i.e., these methods are executed twice, if the __init__.py is included in the glob. It would have been better to call them setup_package/teardown_package (this is how nose calls them).

It is tempting to just remove it, but it will probably cause some breakage (particularly the __init__.py importing part), so for now I plan to keep it in an ad-hoc manner.

POC

I have an initial implementation of this change here, with all tests passing:
https://github.com/bluetech/pytest/commits/pkg-mod

@bluetech bluetech added type: proposal proposal for a new feature, often to gather opinions or design the API around the new feature topic: collection related to the collection phase type: backward compatibility might present some backward compatibility issues which should be carefully noted in the changelog labels Jun 24, 2023
@bluetech bluetech added this to the 8.0 milestone Jun 24, 2023
@bluetech bluetech self-assigned this Jun 24, 2023
bluetech added a commit to bluetech/pytest that referenced this issue Jun 24, 2023
bluetech added a commit to bluetech/pytest that referenced this issue Jun 24, 2023
bluetech added a commit to bluetech/pytest that referenced this issue Jul 28, 2023
bluetech added a commit to bluetech/pytest that referenced this issue Jul 28, 2023
romainkomorndatadog added a commit to DataDog/dd-trace-py that referenced this issue Feb 21, 2024
Addresses #8220 and fixes
an issue with `pytest` `8.x` and above
(brought by pytest-dev/pytest#11137 ) where
`pytest.Package` objects no longer have an attached `module` attribute.

This also changes the testing matrix to include version `~=8.0`, but
maintains `~=7.0` as a separate testing environment.

## Checklist

- [x] Change(s) are motivated and described in the PR description
- [x] Testing strategy is described if automated tests are not included
in the PR
- [x] Risks are described (performance impact, potential for breakage,
maintainability)
- [x] Change is maintainable (easy to change, telemetry, documentation)
- [x] [Library release note
guidelines](https://ddtrace.readthedocs.io/en/stable/releasenotes.html)
are followed or label `changelog/no-changelog` is set
- [x] Documentation is included (in-code, generated user docs, [public
corp docs](https://github.com/DataDog/documentation/))
- [x] Backport labels are set (if
[applicable](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting))
- [x] If this PR changes the public interface, I've notified
`@DataDog/apm-tees`.
- [x] If change touches code that signs or publishes builds or packages,
or handles credentials of any kind, I've requested a review from
`@DataDog/security-design-and-guidance`.

## Reviewer Checklist

- [x] Title is accurate
- [x] All changes are related to the pull request's stated goal
- [x] Description motivates each change
- [x] Avoids breaking
[API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces)
changes
- [x] Testing strategy adequately addresses listed risks
- [x] Change is maintainable (easy to change, telemetry, documentation)
- [x] Release note makes sense to a user of the library
- [x] Author has acknowledged and discussed the performance implications
of this PR as reported in the benchmarks PR comment
- [x] Backport labels are set in a manner that is consistent with the
[release branch maintenance
policy](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting)

---------

Co-authored-by: Munir Abdinur <munir.abdinur@datadoghq.com>
github-actions bot pushed a commit to DataDog/dd-trace-py that referenced this issue Feb 21, 2024
Addresses #8220 and fixes
an issue with `pytest` `8.x` and above
(brought by pytest-dev/pytest#11137 ) where
`pytest.Package` objects no longer have an attached `module` attribute.

This also changes the testing matrix to include version `~=8.0`, but
maintains `~=7.0` as a separate testing environment.

## Checklist

- [x] Change(s) are motivated and described in the PR description
- [x] Testing strategy is described if automated tests are not included
in the PR
- [x] Risks are described (performance impact, potential for breakage,
maintainability)
- [x] Change is maintainable (easy to change, telemetry, documentation)
- [x] [Library release note
guidelines](https://ddtrace.readthedocs.io/en/stable/releasenotes.html)
are followed or label `changelog/no-changelog` is set
- [x] Documentation is included (in-code, generated user docs, [public
corp docs](https://github.com/DataDog/documentation/))
- [x] Backport labels are set (if
[applicable](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting))
- [x] If this PR changes the public interface, I've notified
`@DataDog/apm-tees`.
- [x] If change touches code that signs or publishes builds or packages,
or handles credentials of any kind, I've requested a review from
`@DataDog/security-design-and-guidance`.

## Reviewer Checklist

- [x] Title is accurate
- [x] All changes are related to the pull request's stated goal
- [x] Description motivates each change
- [x] Avoids breaking
[API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces)
changes
- [x] Testing strategy adequately addresses listed risks
- [x] Change is maintainable (easy to change, telemetry, documentation)
- [x] Release note makes sense to a user of the library
- [x] Author has acknowledged and discussed the performance implications
of this PR as reported in the benchmarks PR comment
- [x] Backport labels are set in a manner that is consistent with the
[release branch maintenance
policy](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting)

---------

Co-authored-by: Munir Abdinur <munir.abdinur@datadoghq.com>
(cherry picked from commit 78d5b98)
mabdinur pushed a commit to DataDog/dd-trace-py that referenced this issue Feb 21, 2024
Backport 78d5b98 from #8357 to 2.6.

Addresses #8220 and fixes
an issue with `pytest` `8.x` and above
(brought by pytest-dev/pytest#11137 ) where
`pytest.Package` objects no longer have an attached `module` attribute.

This also changes the testing matrix to include version `~=8.0`, but
maintains `~=7.0` as a separate testing environment.

## Checklist

- [x] Change(s) are motivated and described in the PR description
- [x] Testing strategy is described if automated tests are not included
in the PR
- [x] Risks are described (performance impact, potential for breakage,
maintainability)
- [x] Change is maintainable (easy to change, telemetry, documentation)
- [x] [Library release note
guidelines](https://ddtrace.readthedocs.io/en/stable/releasenotes.html)
are followed or label `changelog/no-changelog` is set
- [x] Documentation is included (in-code, generated user docs, [public
corp docs](https://github.com/DataDog/documentation/))
- [x] Backport labels are set (if
[applicable](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting))
- [x] If this PR changes the public interface, I've notified
`@DataDog/apm-tees`.
- [x] If change touches code that signs or publishes builds or packages,
or handles credentials of any kind, I've requested a review from
`@DataDog/security-design-and-guidance`.

## Reviewer Checklist

- [x] Title is accurate
- [x] All changes are related to the pull request's stated goal
- [x] Description motivates each change
- [x] Avoids breaking
[API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces)
changes
- [x] Testing strategy adequately addresses listed risks
- [x] Change is maintainable (easy to change, telemetry, documentation)
- [x] Release note makes sense to a user of the library
- [x] Author has acknowledged and discussed the performance implications
of this PR as reported in the benchmarks PR comment
- [x] Backport labels are set in a manner that is consistent with the
[release branch maintenance
policy](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting)

Co-authored-by: Romain Komorn <136473744+romainkomorndatadog@users.noreply.github.com>
romainkomorndatadog added a commit to DataDog/dd-trace-py that referenced this issue Feb 22, 2024
Backport 78d5b98 from #8357 to 2.5.

Addresses #8220 and fixes
an issue with `pytest` `8.x` and above
(brought by pytest-dev/pytest#11137 ) where
`pytest.Package` objects no longer have an attached `module` attribute.

This also changes the testing matrix to include version `~=8.0`, but
maintains `~=7.0` as a separate testing environment.

## Checklist

- [x] Change(s) are motivated and described in the PR description
- [x] Testing strategy is described if automated tests are not included
in the PR
- [x] Risks are described (performance impact, potential for breakage,
maintainability)
- [x] Change is maintainable (easy to change, telemetry, documentation)
- [x] [Library release note
guidelines](https://ddtrace.readthedocs.io/en/stable/releasenotes.html)
are followed or label `changelog/no-changelog` is set
- [x] Documentation is included (in-code, generated user docs, [public
corp docs](https://github.com/DataDog/documentation/))
- [x] Backport labels are set (if
[applicable](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting))
- [x] If this PR changes the public interface, I've notified
`@DataDog/apm-tees`.
- [x] If change touches code that signs or publishes builds or packages,
or handles credentials of any kind, I've requested a review from
`@DataDog/security-design-and-guidance`.

## Reviewer Checklist

- [x] Title is accurate
- [x] All changes are related to the pull request's stated goal
- [x] Description motivates each change
- [x] Avoids breaking
[API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces)
changes
- [x] Testing strategy adequately addresses listed risks
- [x] Change is maintainable (easy to change, telemetry, documentation)
- [x] Release note makes sense to a user of the library
- [x] Author has acknowledged and discussed the performance implications
of this PR as reported in the benchmarks PR comment
- [x] Backport labels are set in a manner that is consistent with the
[release branch maintenance
policy](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting)

Co-authored-by: Federico Mon <federico.mon@datadoghq.com>
romainkomorndatadog added a commit to DataDog/dd-trace-py that referenced this issue Feb 22, 2024
Backport 78d5b98 from #8357 to 2.4.

Addresses #8220 and fixes
an issue with `pytest` `8.x` and above
(brought by pytest-dev/pytest#11137 ) where
`pytest.Package` objects no longer have an attached `module` attribute.

This also changes the testing matrix to include version `~=8.0`, but
maintains `~=7.0` as a separate testing environment.

## Checklist

- [x] Change(s) are motivated and described in the PR description
- [x] Testing strategy is described if automated tests are not included
in the PR
- [x] Risks are described (performance impact, potential for breakage,
maintainability)
- [x] Change is maintainable (easy to change, telemetry, documentation)
- [x] [Library release note
guidelines](https://ddtrace.readthedocs.io/en/stable/releasenotes.html)
are followed or label `changelog/no-changelog` is set
- [x] Documentation is included (in-code, generated user docs, [public
corp docs](https://github.com/DataDog/documentation/))
- [x] Backport labels are set (if
[applicable](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting))
- [x] If this PR changes the public interface, I've notified
`@DataDog/apm-tees`.
- [x] If change touches code that signs or publishes builds or packages,
or handles credentials of any kind, I've requested a review from
`@DataDog/security-design-and-guidance`.

## Reviewer Checklist

- [x] Title is accurate
- [x] All changes are related to the pull request's stated goal
- [x] Description motivates each change
- [x] Avoids breaking
[API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces)
changes
- [x] Testing strategy adequately addresses listed risks
- [x] Change is maintainable (easy to change, telemetry, documentation)
- [x] Release note makes sense to a user of the library
- [x] Author has acknowledged and discussed the performance implications
of this PR as reported in the benchmarks PR comment
- [x] Backport labels are set in a manner that is consistent with the
[release branch maintenance
policy](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting)

Co-authored-by: Federico Mon <federico.mon@datadoghq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: collection related to the collection phase type: backward compatibility might present some backward compatibility issues which should be carefully noted in the changelog type: proposal proposal for a new feature, often to gather opinions or design the API around the new feature
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant