Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
30 changed files
with
1,795 additions
and
438 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# <https://travis-ci.org/Tiendil/smart-imports> | ||
|
||
language: python | ||
|
||
######################### | ||
# required by python 3.7 | ||
sudo: required | ||
dist: xenial | ||
######################### | ||
|
||
os: | ||
- linux | ||
|
||
python: | ||
- 3.5 | ||
- 3.6 | ||
- 3.7 | ||
|
||
cache: pip | ||
|
||
install: | ||
- pip install . | ||
|
||
script: python -m unittest discover -t . smart_imports | ||
|
||
after_success: | ||
- pip install coveralls && coverage run --source=smart_imports setup.py test && coveralls |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
|
||
########## | ||
Change log | ||
########## | ||
|
||
This document records all notable changes to `smart_imports`. | ||
|
||
----------- | ||
0.2.0 (dev) | ||
----------- | ||
|
||
* Add support for Python 3.6 `gh-1 <https://github.com/Tiendil/smart-imports/issues/1>`_ | ||
* Add support for Python 3.7 `gh-1 <https://github.com/Tiendil/smart-imports/issues/1>`_ | ||
* Implement obtaining modules' source code by standard Python functionality `gh-a142548 <https://github.com/Tiendil/smart-imports/commit/a142548de8dac3c0bedae18dc71d7ad01b2674c2>`_ | ||
* Add string numbers to import error messages `gh-6 <https://github.com/Tiendil/smart-imports/issues/6>`_ | ||
* Refactoring functional rules into class based rules `gh-7 <https://github.com/Tiendil/smart-imports/issues/7>`_ | ||
* Add optional caching `gh-10 <https://github.com/Tiendil/smart-imports/issues/10>`_ | ||
|
||
----- | ||
0.1.0 | ||
----- | ||
|
||
* Initial implementation |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
|
||
####################### | ||
Smart import for Python | ||
####################### | ||
|
||
|pypi| |python_versions| |test_coverege_develop| | ||
|
||
Automatically discovers & imports entities, used in current module. | ||
|
||
No magic or monkey patching. Only standard Python functionality. | ||
|
||
+---------------------------------------------+---------------------------------------------+ | ||
| Before | After | | ||
+=============================================+=============================================+ | ||
|.. code:: python |.. code:: python | | ||
| | | | ||
| import math | import smart_imports | | ||
| from my_project import calc | smart_imports.all() | | ||
| # 100500 other imports | # no any other imports | | ||
| | | | ||
| def my_code(argument, function=calc): | def my_code(argument, function=calc): | | ||
| return math.log(function(argument)) | return math.log(function(argument)) | | ||
| | | | ||
+---------------------------------------------+---------------------------------------------+ | ||
|
||
------------- | ||
Short summary | ||
------------- | ||
|
||
* Get source code of module, from which ``smart_imports`` has called; | ||
* Parse it, find all not initialized variables; | ||
* Search imports, suitable for found variables; | ||
* Import them. | ||
|
||
Process only modules, from which ``smart_imports`` called explicitly. | ||
|
||
-------- | ||
See also | ||
-------- | ||
|
||
- `Gitter chat room <https://gitter.im/smart-imports/discussion>`_ | ||
- `Change log <https://github.com/Tiendil/smart-imports/blob/develop/CHANGELOG.rst>`_ | ||
|
||
|
||
.. |pypi| image:: https://img.shields.io/pypi/v/smart_imports.svg?style=flat-square&label=latest%20stable%20version&reset_github_caches=3 | ||
:target: https://pypi.python.org/pypi/smart_imports | ||
:alt: Latest version released on PyPi | ||
|
||
.. |python_versions| image:: https://img.shields.io/pypi/pyversions/smart_imports.svg?style=flat-square&reset_github_caches=3 | ||
:target: https://pypi.python.org/pypi/smart_imports | ||
:alt: Supported Python versions | ||
|
||
.. |test_coverege_develop| image:: https://coveralls.io/repos/github/Tiendil/smart-imports/badge.svg?branch=develop&reset_github_caches=3 | ||
:target: https://coveralls.io/github/Tiendil/smart-imports?branch=develop | ||
:alt: Test coverage in develop |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
|
||
import os | ||
import pathlib | ||
import hashlib | ||
import warnings | ||
import functools | ||
|
||
from . import constants | ||
|
||
|
||
WARNING_MESSAGE = 'Error while accessing smart imports cache' | ||
|
||
|
||
def get_checksum(source): | ||
return hashlib.sha256(source.encode('utf-8')).hexdigest() | ||
|
||
|
||
def get_cache_path(cache_dir, module_name): | ||
return os.path.join(cache_dir, module_name + '.cache') | ||
|
||
|
||
def ignore_errors(function): | ||
|
||
@functools.wraps(function) | ||
def wrapper(*argv, **kwargs): | ||
try: | ||
return function(*argv, **kwargs) | ||
except Exception as e: | ||
warnings.warn('{}: {}'.format(WARNING_MESSAGE, e), UserWarning, stacklevel=2) | ||
return None | ||
|
||
return wrapper | ||
|
||
|
||
@ignore_errors | ||
def get(cache_dir, module_name, checksum): | ||
|
||
cache_path = get_cache_path(cache_dir, module_name) | ||
|
||
if not os.path.isfile(cache_path): | ||
return None | ||
|
||
with open(cache_path) as f: | ||
protocol_version = f.readline().strip() | ||
|
||
if protocol_version != constants.CACHE_PROTOCOL_VERSION: | ||
return None | ||
|
||
saved_checksum = f.readline().strip() | ||
|
||
if saved_checksum != checksum: | ||
return None | ||
|
||
variables = [variable.strip() for variable in f.readlines()] | ||
|
||
return variables | ||
|
||
|
||
@ignore_errors | ||
def set(cache_dir, module_name, checksum, variables): | ||
pathlib.Path(cache_dir).mkdir(parents=True, exist_ok=True) | ||
|
||
cache_path = get_cache_path(cache_dir, module_name) | ||
|
||
with open(cache_path, 'w') as f: | ||
f.write(constants.CACHE_PROTOCOL_VERSION) | ||
f.write('\n') | ||
|
||
f.write(checksum) | ||
f.write('\n') | ||
|
||
for variable in variables: | ||
f.write(variable) | ||
f.write('\n') | ||
|
||
|
||
class Cache: | ||
__slots__ = ('cache_dir', 'module_name', 'checksum',) | ||
|
||
def __init__(self, cache_dir, module_name, source): | ||
self.cache_dir = cache_dir | ||
self.module_name = module_name | ||
self.checksum = get_checksum(source) | ||
|
||
def get(self): | ||
if self.cache_dir is None: | ||
return None | ||
|
||
return get(cache_dir=self.cache_dir, | ||
module_name=self.module_name, | ||
checksum=self.checksum) | ||
|
||
def set(self, variables): | ||
if self.cache_dir is None: | ||
return None | ||
|
||
set(cache_dir=self.cache_dir, | ||
module_name=self.module_name, | ||
checksum=self.checksum, | ||
variables=variables) |
Oops, something went wrong.