15

Using Apache Airflow they install plugins by modifying sys.modules like this:

 sys.modules[operators_module.__name__] = operators_module

Which is how they get python classes from their plugins folder to be imported via

from airflow.operators.plugin_name import Operator

even though the class Operator exists inside

airflow/plugins/Operators.py

This makes it impossible for PyCharm to understand the above import statement because it is a non-traditional way of generating module/module name.

Is there any way to get PyCharm to have something like a module/package alias for situations like these?

Stephen
  • 8,508
  • 12
  • 56
  • 96
jhnclvr
  • 9,137
  • 5
  • 50
  • 55
  • Did you have any progress with this? I'm also struggling with PyCharm in this regard. – Hexworks May 08 '18 at 14:11
  • I did have some luck with symlinks, I think, but I can't remember for sure. Put a link in site-packages that points to your plugins folder, and the link needs to have the same structure as your import. – jhnclvr May 15 '18 at 13:51
  • @Hexworks take a look at my answer with two imports. It works well for a single repository projects. – Tautvydas May 22 '18 at 09:36

4 Answers4

5

If your plugin is in the same repository as the dag you can wrap you import in try-except block:

try:
   # local development
   from plugin_name import Operator
except ImportError:
   from airflow.operators.plugin_name import Operator

my_operator = Operator(...)

And mark plugins directory as sources in your PyCharm Project Structure.
Afterwards PyCharm picks up your plugin source code and works nicely with autocompletion and so on.

Tautvydas
  • 2,027
  • 3
  • 25
  • 38
  • 2
    Well the way Airflow works is that `from plugin_name import MyOperator` actually works at runtime too since anything in the plugins folder is available. So chances are that the `from airflow.operators.plugin_name import MyOperator` never gets invoked and it doesn't matter either. I think the plugin registration mechanism is more useful when importing plugins from a non airflow package but then we are back to square one when it comes to PyCharm. – Ustaman Sangat Sep 04 '19 at 18:08
4

Airflow loads plugins by searching the plugins directory for AirflowPlugin subclasses, then binding the operators etc. stored in attributes of those subclasses to new modules under the airflow namespace.

Resolving code transforming classes into modules is beyond PyCharm's capabilities, so unless you want to override this behavior by adding the plugins directory to sys.path and importing the contents directly, the best solution is to whitelist the modules airflow creates through Settings -> Editor -> Inspections -> Python -> Unresolved references and adding airflow.operators.plugin_name to the Ignore references list. Then, using the module like so:

from airflow.operators import plugin_name
task = plugin_name.Operator()

will no longer raise any errors, although you still won't get the benefits of code completion.

apteryx
  • 1,105
  • 7
  • 14
0

So far the best solution I've found (which is not a very good solution) is to simply ignore all unresolved attributes in each DAG file. You can do this if you hover over the error, select "More actions..." and then "Mark all unresolved attributes of [DAG FILE NAME] as ignored." Screenshots below.

This is not a very good solution because it sort of defeats the purpose of an IDE, so I'm hoping eventually somebody who understands the issue better will think of a better solution and post it here :)

enter image description here

enter image description here

Stephen
  • 8,508
  • 12
  • 56
  • 96
0

Maybe other solutions exist but referencing @stephen answer you that can

simply ignore all unresolved attributes in each DAG file.

but I found that marking the dags directory as sources_root resolves the issue of unresolved attributes in an IDE (I am using specifically IntelliJ and Pycharm but could work for other IDEs as well)

enter image description here

John Kitonyo
  • 2,109
  • 1
  • 14
  • 17