my.fbmessenger: move fbmessenger.py into fbmessenger/export.py

keeping it backwards compatible + conditional warning similar to https://github.com/karlicoss/HPI/pull/179

follow up for https://github.com/seanbreckenridge/HPI/pull/18
for now without the __path__ hacking, will do it in bulk later

too lazy to run test_import_warnings.sh on CI for now, but figured I'd commit it for the reference anyway
This commit is contained in:
Dima Gerasimov 2022-02-02 21:51:34 +00:00 committed by karlicoss
parent e30953195c
commit d1f791dee8
3 changed files with 121 additions and 2 deletions

View file

@ -0,0 +1,56 @@
"""
This is here temporarily, for backwards compatibility purposes
It should be removed in the future, and you should replace any imports
like:
from my.fbmessenger import ...
to:
from my.fbmessenger.export import ...
since that allows for easier overriding using namespace packages
https://github.com/karlicoss/HPI/issues/102
"""
# TODO ^^ later, replace the above with from my.fbmessenger.all, when we add more data sources
# For now, including this here, since importing the module
# causes .export to be imported, which requires fbmessengerexport
REQUIRES = [
'git+https://github.com/karlicoss/fbmessengerexport',
]
import re
import inspect
mname = 'fbmessenger' # todo infer from __name__?
# allow stuff like 'import my.module.submodule' and such
imported_as_parent = False
# allow stuff like 'from my.module import submodule'
importing_submodule = False
# some hacky traceback to inspect the current stack
# to see if the user is using the old style of importing
for f in inspect.stack():
# seems that when a submodule is imported, at some point it'll call some internal import machinery
# with 'parent' set to the parent module
# if parent module is imported first (i.e. in case of deprecated usage), it won't be the case
args = inspect.getargvalues(f.frame)
if args.locals.get('parent') == f'my.{mname}':
imported_as_parent = True
# this we can only detect from the code I guess
line = '\n'.join(f.code_context or [])
if re.match(rf'from\s+my\.{mname}\s+import\s+export', line):
# todo 'export' is hardcoded, not sure how to infer allowed objects anutomatically..
importing_submodule = True
warn = not (imported_as_parent or importing_submodule)
if warn:
from my.core import warnings as W
# TODO: add link to instructions to migrate
W.high("DEPRECATED! Instead of my.fbmessengerexport, import from my.fbmessengerexport.export")
from .export import *

View file

@ -10,11 +10,12 @@ REQUIRES = [
from pathlib import Path from pathlib import Path
from typing import Iterator from typing import Iterator
from .core import PathIsh from ..core import PathIsh
import fbmessengerexport.dal as messenger import fbmessengerexport.dal as messenger
from my.config import fbmessenger as config from my.config import fbmessenger as config
# TODO migrate this config to my.fbmessenger.export
def _dal() -> messenger.DAL: def _dal() -> messenger.DAL:
@ -28,7 +29,7 @@ def messages() -> Iterator[messenger.Message]:
yield from t.iter_messages() yield from t.iter_messages()
from .core import stat, Stats from ..core import stat, Stats
def stats() -> Stats: def stats() -> Stats:
return stat(messages) return stat(messages)

View file

@ -0,0 +1,62 @@
#!/bin/bash
set -eu
errors=0
function expect_warn () {
echo "check: " "$@"
[[ $(2>&1 "$@" | grep -c DEPRECATED) -gt 0 ]] || {
echo "ERROR: " "$@"
errors=1
}
}
function expect_ok () {
echo "check: " "$@"
[[ $(2>&1 "$@" | grep -c DEPRECATED) -eq 0 ]] || {
echo "ERROR: " "$@"
errors=1
}
}
# TODO actually this one might be ok? nothing wrong with it in principle
expect_warn python3 -c 'from my import fbmessenger'
echo 'from my import fbmessenger' > /tmp/script.py
expect_warn python3 /tmp/script.py
expect_warn python3 -c 'from my.fbmessenger import messages'
echo 'from my.fbmessenger import messages' > /tmp/script.py
expect_warn python3 /tmp/script.py
expect_warn python3 -c 'from my.fbmessenger import *'
echo 'from my.fbmessenger import *' > /tmp/script.py
expect_warn python3 /tmp/script.py
expect_warn python3 -c 'import my.fbmessenger'
echo 'import my.fbmessenger' > /tmp/script.py
expect_warn python3 /tmp/script.py
expect_warn python3 -m my.core query my.fbmessenger.messages
expect_warn python3 -m my.core doctor my.fbmessenger
expect_ok python3 -c 'from my.fbmessenger.export import *'
echo 'from my.fbmessenger.export import *' > /tmp/script.py
expect_ok python3 /tmp/script.py
# TODO kinda annoying: this doesn't work, and doesn't seem like traceback has anything
# guess it's fine, kind of a border case
# expect_ok python3 -c 'from my.fbmessenger import export'
echo 'from my.fbmessenger import export' > /tmp/script.py
expect_ok python3 /tmp/script.py
expect_ok python3 -c 'import my.fbmessenger.export'
echo 'import my.fbmessenger.export' > /tmp/script.py
expect_ok python3 /tmp/script.py
expect_ok python3 -m my.core query my.fbmessenger.export.messages
expect_ok python3 -m my.core doctor my.fbmessenger.export
exit $errors