Skip to content

Commit

Permalink
Merge pull request #9 from pomponchik/develop
Browse files Browse the repository at this point in the history
0.0.20
  • Loading branch information
pomponchik committed Sep 5, 2023
2 parents 72c2c3e + 715a41e commit 535b90f
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 42 deletions.
15 changes: 10 additions & 5 deletions .github/workflows/tests_and_coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,19 @@ jobs:
shell: bash
run: python setup.py install

- name: Print all libs
shell: bash
run: pip list

- name: Run tests and show coverage on the command line
run: coverage run --source=installed --omit="*tests*" -m pytest --cache-clear && coverage report -m
run: coverage run --source=installed --omit="*tests*" -m pytest --cache-clear --assert=plain && coverage report -m

- name: Upload reports to codecov
env:
CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}}
if: runner.os == 'Linux'
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true # optional (default = false)
run: |
curl -Os https://uploader.codecov.io/latest/linux/codecov
find . -iregex "codecov.*"
chmod +x codecov
./codecov -t ${CODECOV_TOKEN}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ dist
*.egg-info
test.py
.coverage
.coverage.*
tests/cli/data/chpok
tests/cli/data/pok
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

# INSTLD: the simplest package management

[![Downloads](https://pepy.tech/badge/instld/month)](https://pepy.tech/project/instld)
[![Downloads](https://pepy.tech/badge/instld)](https://pepy.tech/project/instld)
[![Downloads](https://static.pepy.tech/badge/instld/month)](https://pepy.tech/project/instld)
[![Downloads](https://static.pepy.tech/badge/instld)](https://pepy.tech/project/instld)
[![codecov](https://codecov.io/gh/pomponchik/installed/branch/main/graph/badge.svg)](https://codecov.io/gh/pomponchik/instld)
[![Test-Package](https://github.com/pomponchik/instld/actions/workflows/coverage.yml/badge.svg)](https://github.com/pomponchik/instld/actions/workflows/coverage.yml)
[![Test-Package](https://github.com/pomponchik/instld/actions/workflows/tests_and_coverage.yml/badge.svg)](https://github.com/pomponchik/instld/actions/workflows/tests_and_coverage.yml)
[![Python versions](https://img.shields.io/pypi/pyversions/instld.svg)](https://pypi.python.org/pypi/instld)
[![PyPI version](https://badge.fury.io/py/instld.svg)](https://badge.fury.io/py/instld)

Expand Down
3 changes: 2 additions & 1 deletion installed/cli/parsing_arguments/get_python_file.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import os
import sys


def get_python_file():
if len(sys.argv) < 2:
print('usage: instld python_file.py [argv ...]', file=sys.stderr)
exit(1)
sys.exit(1)

return sys.argv[1]
3 changes: 3 additions & 0 deletions installed/cli/traceback_cutting/cutting.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import io
import os
import sys
import traceback
from contextlib import redirect_stderr

from installed.cli.traceback_cutting.traceback_utils import cut_base_of_traceback

Expand Down
1 change: 0 additions & 1 deletion installed/module/context_manager.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import os
import sys
import tempfile
import subprocess
from functools import partial

from io import StringIO
Expand Down
2 changes: 1 addition & 1 deletion requirements_dev.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pytest==7.4.0
pytest==7.4.1
coverage==7.2.7
twine==4.0.2
wheel==0.40.0
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

setup(
name='instld',
version='0.0.19',
version='0.0.20',
author='Evgeniy Blinov',
author_email='zheni-b@yandex.ru',
description='The simplest package management',
Expand Down
84 changes: 54 additions & 30 deletions tests/cli/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
import pytest


@pytest.mark.timeout(60)
def test_cli_where():
@pytest.mark.timeout(180)
def test_cli_where(main_runner):
strings = [
rf'import is_odd # instld: where {os.path.join("tests", "cli", "data", "pok")}',
rf'import is_even # instld: where {os.path.join("tests", "cli", "data", "chpok")}',
Expand All @@ -20,37 +20,39 @@ def test_cli_where():
with open(script, 'w') as file:
file.write('\n'.join(strings))

result = subprocess.run(['instld', script])
for runner in (main_runner, subprocess.run):
result = runner(['instld', script], stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=10000)

result.check_returncode()
result.check_returncode()

base_libs_paths = {
os.path.join('tests', 'cli', 'data', 'pok'): 'is_odd',
os.path.join('tests', 'cli', 'data', 'chpok'): 'is_even',
}
base_libs_paths = {
os.path.join('tests', 'cli', 'data', 'pok'): 'is_odd',
os.path.join('tests', 'cli', 'data', 'chpok'): 'is_even',
}

for path, library_name in base_libs_paths.items():
full_path_to_the_lib = os.path.join(path, 'lib')
if sys.platform.lower() not in ('win32',):
full_path_to_the_lib = os.path.join(full_path_to_the_lib, os.path.basename(os.listdir(path=full_path_to_the_lib)[0]), 'site-packages')
full_path_to_the_lib = os.path.join(full_path_to_the_lib, library_name)
for path, library_name in base_libs_paths.items():
full_path_to_the_lib = os.path.join(path, 'lib')
if sys.platform.lower() not in ('win32',):
full_path_to_the_lib = os.path.join(full_path_to_the_lib, os.path.basename(os.listdir(path=full_path_to_the_lib)[0]), 'site-packages')
full_path_to_the_lib = os.path.join(full_path_to_the_lib, library_name)

assert os.path.isdir(full_path_to_the_lib)
assert os.path.isdir(full_path_to_the_lib)

shutil.rmtree(path)
shutil.rmtree(path)

os.remove(script)


def test_run_command_without_arguments():
result = subprocess.run(['instld'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=100)
def test_run_command_without_arguments(main_runner):
for runner in (main_runner, subprocess.run):
result = runner(['instld'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=100, universal_newlines=True)

assert result.returncode == 1
assert result.stdout.decode('utf-8') == ''
assert result.stderr.decode('utf-8') == f'usage: instld python_file.py [argv ...]{os.linesep}'
assert result.returncode == 1
assert result.stdout == ''
assert result.stderr == f'usage: instld python_file.py [argv ...]\n'


def test_run_command_with_arguments():
def test_run_command_with_arguments(main_runner):
strings = [
'import json, sys',
'print(json.dumps(sys.argv), file=sys.stdout)',
Expand All @@ -67,22 +69,44 @@ def test_run_command_with_arguments():
['-l', 'kek'],
)

for extra_arguments in extra_arguments_options:
expected_arguments_without_command = [script] + extra_arguments
result = subprocess.run(['instld', *expected_arguments_without_command], stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=200)
for runner in (main_runner, subprocess.run):
for extra_arguments in extra_arguments_options:
expected_arguments_without_command = [script] + extra_arguments
result = runner(['instld', *expected_arguments_without_command], stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=200)

result.check_returncode()
assert result.stderr.decode('utf-8') == ''
result.check_returncode()
assert result.stderr.decode('utf-8') == ''

arguments_from_file = json.loads(result.stdout.decode('utf-8'))
arguments_from_file_without_command = arguments_from_file[1:]
arguments_from_file = json.loads(result.stdout.decode('utf-8'))
arguments_from_file_without_command = arguments_from_file[1:]

assert arguments_from_file_without_command == expected_arguments_without_command
assert arguments_from_file_without_command == expected_arguments_without_command

os.remove(script)


def test_exceptions_are_similar_with_just_python_command():
def test_exceptions_are_similar_with_just_python_command(main_runner):
errors = [
'ValueError',
'ValueError("message")',
]

for runner in (subprocess.run, main_runner):
for error in errors:
script = os.path.join('tests', 'cli', 'data', 'main.py')
with open(script, 'w') as file:
file.write(f'raise {error}')

result_1 = runner(['instld', os.path.abspath(script)], stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=500)
result_2 = subprocess.run(['python', os.path.abspath(script)], stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=500)

assert result_1.returncode == result_2.returncode
assert result_1.stdout == result_2.stdout
assert result_1.stderr == result_2.stderr

os.remove(script)

def test_exceptions_are_similar_with_just_python_command_2():
errors = [
'ValueError',
'ValueError("message")',
Expand Down
82 changes: 82 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import io
import os
import sys
import traceback
from typing import List, Dict, Any, Optional
from dataclasses import dataclass
from subprocess import CalledProcessError
from contextlib import redirect_stdout, redirect_stderr

import pytest

from installed.cli.main import start


@dataclass
class MainRunResult:
stdout: bytes
stderr: bytes
before_stderr: bytes
returncode: int
command: List[str]

def check_returncode(self):
if self.returncode != 0:
raise CalledProcessError(self.returncode, self.command)

@pytest.fixture
def main_runner():
def runner_function(arguments: List[str], env: Optional[Dict[str, str]] = None, universal_newlines: Optional[bool] = None, **kwargs: Any):
old_excepthook = sys.excepthook
old_argv = sys.argv
old_environ = os.environ
old_exit = sys.exit
old_env = os.environ

if env is not None:
os.environ = env

sys.argv = arguments

class LocalError(Exception): pass
def exit_handler(number): raise LocalError
sys.exit = exit_handler

stdout_buffer = io.StringIO()
stderr_buffer = io.StringIO()
returncode = 0
with redirect_stdout(stdout_buffer) as stdout, redirect_stderr(stderr_buffer) as stderr:
try:
start()
stdout = stdout_buffer.getvalue()
stderr = stderr_buffer.getvalue()
before_stderr = str.encode(stderr)
except LocalError:
returncode = 1
stdout = stdout_buffer.getvalue()
stderr = stderr_buffer.getvalue()
before_stderr = str.encode(stderr)
except Exception as e:
returncode = 1
sys.excepthook(type(e), e, e.__traceback__)
stdout = stdout_buffer.getvalue()
stderr = stderr_buffer.getvalue()
before_stderr = str.encode(stderr)
if sys.platform.lower() in ('win32',):
stdout = stdout.replace('\n', os.linesep).replace('\r\r', '\r')
stderr = stderr.replace('\n', os.linesep).replace('\r\r', '\r')
finally:
if not (universal_newlines is not None and universal_newlines):
stdout = str.encode(stdout)
stderr = str.encode(stderr)
result = MainRunResult(command=arguments, stdout=stdout, stderr=stderr, before_stderr=before_stderr, returncode=returncode)

sys.excepthook = old_excepthook
sys.argv = old_argv
os.environ = old_environ
sys.exit = old_exit
os.environ = old_env

return result

return runner_function

0 comments on commit 535b90f

Please sign in to comment.