Skip to content

Commit

Permalink
spelling
Browse files Browse the repository at this point in the history
  • Loading branch information
Tiendil committed Mar 21, 2020
1 parent 9bd9225 commit 744187e
Showing 1 changed file with 48 additions and 49 deletions.
97 changes: 48 additions & 49 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,69 +41,69 @@ Process only modules, from which ``smart_imports`` called explicitly.
Main idea
---------

With time every complex project develop own naming comvention. If we translate that convention into more formal rules, we will be able to make automatic imports every entity knowing only its name and place of import.
With time every complex project develops own naming convention. If we translate that convention into more formal rules, we will be able to make automatic imports of every entity, knowing only its name.

For example, we will have no need to write ``import math`` to call ``math.pi``, since out system will be able to understand that ``math`` is the module of standard library.
For example, we will have no need to write ``import math`` to call ``math.pi``, since our system will understand that ``math`` is the module of standard library.

------------
How it works
------------

So, code from header works in such way:
Code from the header works in such way:

- ``smart_imports.all()`` build AST of module from wich it has called.
- Library analyse AST and searches for not initialized variables.
- Name of every found variable went thought chain of rules to determine correct module (or its attribute) to import. If rule found target module, chain breaks and next rules do not processed.
- Library load found modules and make imports into global namespace..
- ``smart_imports.all()`` builds AST of module from wich it has called.
- Library analyses AST and searches for not initialized variables.
- Name of every found variable processed thought chain of rules to determine correct module (or its attribute) to import. If rule finds target module, chain breaks and next rules will not be processed.
- Library load found modules and add imported enities into global namespace.

SmartImports search not initialized variables in every part of code (including new Pyton syntax).
SmartImports searchs not initialized variables in every part of code (including new Python syntax).

Automatic importing turns on only for modules, that do explicit call to ``smart_imports.all()``
Automatic importing turns on only for modules, that do explicit call of ``smart_imports.all()``

Moreover, you can use normal imports with SmartImports at the same time with. It help to integrate library step by step.
Moreover, you can use normal imports with SmartImports at the same time. That helps to integrate library step by step.

You can notice, that AST of module builts two times:

- when CPython imports module;
- when SmartSmports process call of ``smart_imports.all()``.
- when SmartImports process call of ``smart_imports.all()``.

We can bould AST once (for that we can add hook into process of importing modules with help of `PEP-0302 <https://www.python.org/dev/peps/pep-0302/>`_), but it will make import event slower. I think that it is because at import time CPython build AST in terms of its internal structures (probably inplemented in C). Convertation from them to Python AST cost more then building new AST from scratch.
We can bould AST once (for that we can add hook into process of importing modules with help of `PEP-0302 <https://www.python.org/dev/peps/pep-0302/>`_), but it will make import event slower. I think that it is because at import time CPython builds AST in terms of its internal structures (probably inplemented in C). Convertation from them to Python AST cost more than building new AST from scratch.

Needless, SmartImports build AST once for every module for every launch.
SmartImports build AST only once for every module.

--------------------
Default import rules
--------------------

SmartImports can be used without configuration. By default it uses such rules:

#. By exact match looking for module with required name neare current module (in same folder).
#. Check standard library has module with required name.
#. By exact match looks for module with required name in folder of current module.
#. Checks if standard library has module with required name.

#. By exact match looking for top-level package with required name (``math`` for example).
#. For subpackages and modules check complex name with dots replaces by underscores (For example, ``os.path`` will be imported for name ``os_path``).
#. By exact match with top-level packages (for example, ``math`` ).
#. For subpackages and modules checks complex name with dots replaced by underscores (for example, ``os.path`` will be imported for name ``os_path``).

#. By exact match looking for installed packages with required name (``requests`` for example).
#. By exact match looks for installed packages with required name (for example, ``requests`` ).

-----------
Performance
-----------

SmartImports does not slow down runtime, but increases startup time.

Becouse of building AST, startup time increased in 1.5-2 times. For small projects it is inconsequential. At same time, startup time of large projects depend mostly from architecture and dependences between modules, than from time of module import.
Becouse of building AST, startup time increased in 1.5-2 times. For small projects it is inconsequential. At same time, startup time of large projects depend mostly from architecture and dependences between modules, than from time of modules import.

In fute, part of SmartImports can be rewriten to C — it should eliminate startup delays.
In futere, part of SmartImports can be rewriten in C — it should eliminate startup delays.

To speedup startup time, results of AST processing can be cached on file system. That behaviour can be turned on in config. Cache invalidated on file chages.
To speedup startup time, results of AST processing can be cached on file system. That behaviour can be turned on in config. SmartImport invalidates cache when module source code changes.

Also, SmartImports work time highly depends from rules and their sequence. You can reduce these costs with modifying configs. For example, you can specify explicit import path for name with rule `Rule 4: Custom names`_.
Also, SmartImports work time highly depends from rules and their sequence. You can reduce these costs by modifying configs. For example, you can specify explicit import path for name with `Rule 4: custom names`_.

-------------
Configuration
-------------

Default configuration was already described. It should be enough for work with standard library.
Logic of default configuration was already described. It should be enough for work with standard library.

Default config:

Expand All @@ -122,7 +122,7 @@ If necessary, a more complex config can be put on file system.

`Example of complex config <https://github.com/the-tale/the-tale/blob/develop/src/the_tale/the_tale/smart_imports.json>`_ (from my pet project).

At the time of call ``smart_import.all()`` library detects location of config file by searching file ``smart_imports.json`` from current folder to root. If file has found, it become config for current module.
At the time of call ``smart_import.all()`` library detects location of config file by searching file ``smart_imports.json`` from current folder up to root. If file will be found, it will become config for current module.

You can use multiple config files (place them in different folders).

Expand All @@ -143,16 +143,15 @@ There are few config parameters now:
Import rules
------------

Sequence of rules in configs determine order of their application. First success rule stop processing and make import.

Rule ``rule_predefined_names`` will be often used in examples below. It required for correct processing of default names like ``print``.
Sequence of rules in configs determines order of their application. First success rule stop processing and make import.

Rule `Rule 1: predefined names`_ will be often used in examples below. It required for correct processing of default names like ``print``.

~~~~~~~~~~~~~~~~~~~~~~~~
Rule 1: predefined names
~~~~~~~~~~~~~~~~~~~~~~~~

Rule silences import searching for predefined names like ``__file__`` and builtins like ``print``.
Rule silences import search for predefined names like ``__file__`` and builtins like ``print``.

.. code-block:: python
Expand All @@ -174,7 +173,7 @@ Rule silences import searching for predefined names like ``__file__`` and builti
Rule 2: local modules
~~~~~~~~~~~~~~~~~~~~~

Rule checks if module with required name exists near current module (in the same folder). If module found, it will be imported.
Rule checks if module with required name exists in folder of current module. If module found, it will be imported.

.. code-block:: python
Expand Down Expand Up @@ -227,7 +226,7 @@ Rule tries to import module by name.
~~~~~~~~~~~~~~~~~~~~
Rule 4: Custom names
Rule 4: custom names
~~~~~~~~~~~~~~~~~~~~

Rule links name to specified module and its attribute (optionaly).
Expand All @@ -253,12 +252,12 @@ Rule links name to specified module and its attribute (optionaly).
~~~~~~~~~~~~~~~~~~~~~~~~
Rule 5: Standard library
Rule 5: standard library
~~~~~~~~~~~~~~~~~~~~~~~~

Rule checks if standard library has module with such name. For example ``math`` or ``os.path`` wich will be imported for name ``os_path``.
Rule checks if standard library has module with required name. For example ``math`` or ``os.path`` wich will be imported for name ``os_path``.

That rule works fuster than `Rule 3: global modules`_, since it search module by cached list. Lists of modules for every python version was taken from here: github.com/jackmaney/python-stdlib-list
That rule works faster than `Rule 3: global modules`_, since it searchs module by predefined list. Lists of modules for every Python version was taken from here: github.com/jackmaney/python-stdlib-list

.. code-block:: python
Expand All @@ -276,10 +275,10 @@ That rule works fuster than `Rule 3: global modules`_, since it search module by
~~~~~~~~~~~~~~~~~~~~~~~~
Rule 6: Import by prefix
Rule 6: import by prefix
~~~~~~~~~~~~~~~~~~~~~~~~

Rule imports module by name form package, wich associated with name prefix. Can be helpfull, when you have package used in whole project. For example, you can access modules from package ``utils`` with prefix ``utils_``.
Rule imports module by name from package, wich associated with name prefix. Can be helpfull, when you have package used in whole project. For example, you can access modules from package ``utils`` with prefix ``utils_``.

.. code-block:: python
Expand Down Expand Up @@ -313,10 +312,10 @@ Rule imports module by name form package, wich associated with name prefix. Can
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Rule 7: Modules from parent package
Rule 7: modules from parent package
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If you have subpackages with same name in different parts of you project (for example, ``tests`` or ``migrations``), you can allow for hem to search modules by name in parent packages.
If you have subpackages with same name in different parts of your project (for example, ``tests`` or ``migrations``), you can allow for them to search modules by name in parent packages.

.. code-block:: python
Expand Down Expand Up @@ -346,10 +345,10 @@ If you have subpackages with same name in different parts of you project (for ex
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Rule 8: Modules from namespace
Rule 8: modules from namespace
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Rule allow for modules from specified package to import by names modules from other package.
Rule allow for modules from specified package to import by name modules from other package.

.. code-block:: python
Expand Down Expand Up @@ -380,7 +379,7 @@ Rule allow for modules from specified package to import by names modules from ot
print(b)
~~~~~~~~~~~~~~~~~~~~~~~
How to add custom rules
How to add custom rule?
~~~~~~~~~~~~~~~~~~~~~~~

#. Subclass ``smart_imports.rules.BaseRule``.
Expand All @@ -392,22 +391,22 @@ How to add custom rules

Look into implementation of current rules, if you need example.

~~~~~
-----
Plans
~~~~~
-----

I love the idea of determining code property by used names. So, I will try to develop it in borders of SmartImports and other projects.
I love the idea of determining code properties by used names. So, I will try to develop it in borders of SmartImports and other projects.

What I planning for SmartImports:

- Patch it for new versions of Python.
- Research using of type annotations to import automatization.
- Continue support and patch it for new versions of Python.
- Research usage of type annotations to import automatization.
- Try to implement lazy imports.
- Implement utilites for automatic config generation and refactoring.
- Rewrite part of code to C, to speedup AST construction.
- Implement integrations with most popular IDE.
- Implement utilites for automatic config generation and code refactoring.
- Rewrite part of code in C, to speedup AST construction.
- Implement integrations with popular IDEs.

I open for your sugestions.
I open for your sugestions. Feel free to contact me in any way.


.. |pypi| image:: https://img.shields.io/pypi/v/smart_imports.svg?style=flat-square&label=latest%20stable%20version&reset_github_caches=6
Expand Down

0 comments on commit 744187e

Please sign in to comment.