Skip to content

Commit

Permalink
my.fbmessenger: move fbmessenger.py into fbmessenger/export.py
Browse files Browse the repository at this point in the history
keeping it backwards compatible + conditional warning similar to #179

follow up for seanbreckenridge/HPI#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
  • Loading branch information
karlicoss committed Feb 2, 2022
1 parent e309531 commit c12f829
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 2 deletions.
58 changes: 58 additions & 0 deletions my/fbmessenger/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"""
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)

# TODO: add link to instructions to migrate
if warn:
from my.core import warnings as W
W.high("DEPRECATED! Instead of my.fbmessengerexport, import from my.fbmessengerexport.export")


from .export import *
5 changes: 3 additions & 2 deletions my/fbmessenger.py → my/fbmessenger/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@
from pathlib import Path
from typing import Iterator

from .core import PathIsh
from ..core import PathIsh

import fbmessengerexport.dal as messenger

from my.config import fbmessenger as config
# TODO migrate this config to my.fbmessenger.export


def _dal() -> messenger.DAL:
Expand All @@ -28,7 +29,7 @@ def messages() -> Iterator[messenger.Message]:
yield from t.iter_messages()


from .core import stat, Stats
from ..core import stat, Stats
def stats() -> Stats:
return stat(messages)

Expand Down
62 changes: 62 additions & 0 deletions tests/test_import_warnings.sh
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit c12f829

Please sign in to comment.