Skip to content
GitLab
Projects Groups Topics Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in
  • logilab-common logilab-common
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributor statistics
    • Graph
    • Compare revisions
  • Issues 8
    • Issues 8
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 6
    • Merge requests 6
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Container Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • open-source
  • logilab-commonlogilab-common
  • Merge requests
  • !16

Fix usage of callable_deprecation on LazyObject that was breaking CW 3.24 (or something like that)

  • Review changes

  • Download
  • Patches
  • Plain diff
Merged Laurent Peuch requested to merge topic/1.6/add-lazy_wraps-because-lazyobject into branch/1.6 May 22, 2020
  • Overview 0
  • Commits 4
  • Pipelines 0
  • Changes 3

So, brace yourself, it's a little bit complicated (don't hesitate to reach me for more explanation).

So, it goes like that:

  • I've introduced the usage of the @wraps decorator from functools.wraps in logilab.common.deprecation.callable_deprecated because this is a good practice
  • turns out if broke francearchives code
  • which is because it uses an old version of CW
  • in this old version of CW, logilab.common.modutils.LazyObject is used (well, inherited) here https://forge.extranet.logilab.fr/cubicweb/cubicweb/blob/3.24.0/cubicweb/schemas/__init__.py#L51
  • LazyObject all you to do something like exists = LazyObject("os.path", "exists") and up until exists is used, the import is not triggered
  • here "used" means "access attributes or call it"
  • so, CW uses (My)LazyObject to prepare to import a bunch of cubes (but not importing them) and mark them as callable_deprecated
  • this allow to raise a deprecation warning if they are used but not add those cubes as dependencies in CW

Now, why is it a problem? Well ...

  • turns out: functools.@wraps actually try to access a bunch of attributes on the wrapped callable to grab __name__, 'dict, '__doc__ to avoid breaking a bunch of stuff
  • going back to before, you might have guessed it: by trying to access those attributes, functools.@wraps triggers the import of those objects
  • which in turns breaks everything because this is supposed to be a lazy import and so it was supposed to handle the case where those dependencies weren't installed
  • and you get an ImportError and your code doesn't work anymore

So, this MR:

  • recreate the behavior of functools.wraps but in a lazy way to solve this issue
  • it also ensure that we never access attributes of the decorated callable before this decorated callable is actually called
  • document LazyObject because pffff

I think it's the first time I had to debug one exception that triggered 3-4 other exceptions ^^'

Also protip: uses pdbpp instead of pdb, it allows to access hidden frames.

Assignee
Assign to
Reviewers
Request review from
Time tracking
Source branch: topic/1.6/add-lazy_wraps-because-lazyobject