Navigation Menu

Skip to content

Commit

Permalink
win10 ⛏️
Browse files Browse the repository at this point in the history
- corrects two bugs happening in Windows
- modifies the build pipeline to build and run tests on Windows
  • Loading branch information
RobertoPrevato committed Sep 26, 2020
1 parent 4b31b1a commit 81077e6
Show file tree
Hide file tree
Showing 18 changed files with 156 additions and 94 deletions.
1 change: 1 addition & 0 deletions .gitattributes
@@ -0,0 +1 @@
* text=auto eol=lf
8 changes: 6 additions & 2 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.2.6] - ...

- Corrects two bugs happening when using `blacksheep` in Windows
- Improves the test suite to be compatible with Windows
- Adds a job running in Windows to the build and validation pipeline

## [0.2.5] - 2020-09-19 💯

- **100% test coverage**, with more than _1000_ tests
Expand Down Expand Up @@ -38,5 +44,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improves code quality
- Improves code for integration tests
- Fixes bug [#37](https://github.com/RobertoPrevato/BlackSheep/issues/37)


9 changes: 9 additions & 0 deletions README.md
Expand Up @@ -190,5 +190,14 @@ loop.run_until_complete(client_example(loop))

```

## Supported platforms and runtimes
The following Python versions are supported and tested by [validation pipeline](./azure-pipelines.yml):
* Python 3.7 (cpython)
* Python 3.8 (cpython)

The following platforms are supported and tested by [validation pipeline](./azure-pipelines.yml):
* Ubuntu 18.04
* Windows 10

## Documentation
Please refer to the [project Wiki](https://github.com/RobertoPrevato/BlackSheep/wiki).
149 changes: 98 additions & 51 deletions azure-pipelines.yml
@@ -1,52 +1,99 @@
# BlackSheep build pipeline

trigger:
- master

pool:
vmImage: 'ubuntu-latest'
strategy:
matrix:
Python37:
python.version: '3.7'
Python38:
python.version: '3.8'

steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '$(python.version)'
displayName: 'Use Python $(python.version)'

- bash: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest pytest-cov pytest-azurepipelines
displayName: 'Install dependencies'

- bash: |
make compile
displayName: 'Compile Cython extensions'

- bash: |
pytest --doctest-modules --junitxml=junit/test-results.xml --cov-report html --cov=blacksheep
displayName: 'tests'

- bash: |
if [ -f "build_info.txt" ]; then rm build_info.txt; fi
echo "Build id: $(Build.BuildId)" >> build_info.txt
echo "Build date: $(date)" >> build_info.txt
echo "Build URL: https://dev.azure.com/robertoprevato/BlackSheep/_build/results?buildId=$(Build.BuildId)&view=results" >> build_info.txt
echo "Build version: $(Build.DefinitionVersion)" >> build_info.txt
displayName: 'writes build id'

- bash: |
python setup.py sdist
displayName: 'create artifacts'

- task: PublishBuildArtifacts@1
displayName: 'publish dist artifacts'
condition: and(succeeded(), eq(variables['python.version'], '3.8'))
inputs:
PathtoPublish: dist
ArtifactName: dist
- master

jobs:
- job: Linux
pool:
vmImage: "ubuntu-latest"
strategy:
matrix:
Python37:
python.version: "3.7"
Python38:
python.version: "3.8"
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: "$(python.version)"
displayName: "Use Python $(python.version)"

- bash: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install uvloop==0.14.0
pip install pytest pytest-cov pytest-azurepipelines
displayName: "Install dependencies"
- bash: |
make compile
displayName: "Compile Cython extensions"
- bash: |
pytest --doctest-modules --junitxml=junit/test-results.xml --cov-report html --cov=blacksheep
displayName: "tests"
- script: |
flake8 blacksheep
flake8 tests
displayName: "flake8 tests"
- bash: |
if [ -f "build_info.txt" ]; then rm build_info.txt; fi
echo "Build id: $(Build.BuildId)" >> build_info.txt
echo "Build date: $(date)" >> build_info.txt
echo "Build URL: https://dev.azure.com/robertoprevato/BlackSheep/_build/results?buildId=$(Build.BuildId)&view=results" >> build_info.txt
echo "Build version: $(Build.DefinitionVersion)" >> build_info.txt
displayName: "writes build id"
- bash: |
python setup.py sdist
displayName: "create artifacts"
- task: PublishBuildArtifacts@1
displayName: "publish dist artifacts"
condition: and(succeeded(), eq(variables['python.version'], '3.8'))
inputs:
PathtoPublish: dist
ArtifactName: dist
- job: Windows
pool:
vmImage: "windows-latest"
strategy:
matrix:
Python37:
python.version: "3.7"
Python38:
python.version: "3.8"
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: "$(python.version)"
displayName: "Use Python $(python.version)"

- script: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest pytest-azurepipelines
displayName: "Install dependencies"
- script: |
cython blacksheep/url.pyx
cython blacksheep/exceptions.pyx
cython blacksheep/headers.pyx
cython blacksheep/cookies.pyx
cython blacksheep/contents.pyx
cython blacksheep/messages.pyx
cython blacksheep/scribe.pyx
cython blacksheep/baseapp.pyx
python setup.py build_ext --inplace
displayName: "Compile Cython extensions"
- script: |
flake8 blacksheep
flake8 tests
displayName: "flake8 tests"
- script: |
pytest --doctest-modules --junitxml=junit/test-results.xml
displayName: "tests"
2 changes: 1 addition & 1 deletion blacksheep/client/cookies.py
@@ -1,7 +1,7 @@
import logging
from datetime import datetime, timedelta
from ipaddress import ip_address
from typing import Any, Optional, Dict, Iterable, TypeVar
from typing import Optional, Dict, Iterable, TypeVar

from blacksheep import URL, Cookie

Expand Down
3 changes: 1 addition & 2 deletions blacksheep/server/controllers.py
@@ -1,6 +1,5 @@
import sys
from types import FrameType
from typing import Any, Callable, Optional
from typing import Any, Optional

from blacksheep import Request, Response
from blacksheep.server.responses import (
Expand Down
3 changes: 2 additions & 1 deletion blacksheep/server/files/dynamic.py
@@ -1,3 +1,4 @@
from blacksheep.utils import join_fragments
from blacksheep.server.authorization import allow_anonymous
import html
import os
Expand Down Expand Up @@ -75,7 +76,7 @@ def get_files_list_html_response(
rel_path = item.get("rel_path")
assert rel_path is not None
full_rel_path = html.escape(
os.path.join(root_path, parent_folder_path, rel_path)
join_fragments(root_path, parent_folder_path, rel_path)
)
info_lines.append(f'<li><a href="/{full_rel_path}">{rel_path}</a></li>')
info = "".join(info_lines)
Expand Down
14 changes: 8 additions & 6 deletions itests/client_fixtures.py
@@ -1,3 +1,4 @@
from itests.utils import get_sleep_time
from blacksheep.client.pool import ClientConnectionPools
import os
import pathlib
Expand Down Expand Up @@ -27,7 +28,7 @@ def event_loop():

@pytest.fixture(scope="module")
def server_host():
return "0.0.0.0"
return "127.0.0.1"


@pytest.fixture(scope="module")
Expand Down Expand Up @@ -58,15 +59,16 @@ def session_alt(event_loop):
event_loop.run_until_complete(session.close())


def start_server():
print(f"[*] Flask app listening on 0.0.0.0:44777")
app.run(host="127.0.0.1", port=44777)


@pytest.fixture(scope="module", autouse=True)
def server(server_host, server_port):
def start_server():
print(f"[*] Flask app listening on {server_host}:{server_port}")
app.run(host=server_host, port=server_port)

server_process = Process(target=start_server)
server_process.start()
sleep(0.5)
sleep(get_sleep_time())

yield 1

Expand Down
23 changes: 13 additions & 10 deletions itests/server_fixtures.py
@@ -1,3 +1,4 @@
import os
import socket
from multiprocessing import Process
from time import sleep
Expand All @@ -7,7 +8,7 @@

from .app import app
from .app_two import app_two
from .utils import ClientSession
from .utils import ClientSession, get_sleep_time


@pytest.fixture(scope="module")
Expand Down Expand Up @@ -44,14 +45,19 @@ def session_two(server_host, server_port_two):
return ClientSession(f"http://{server_host}:{server_port_two}")


def start_server():
uvicorn.run(app, host="127.0.0.1", port=44555, log_level="debug")


def start_server2():
uvicorn.run(app_two, host="127.0.0.1", port=44556, log_level="debug")


@pytest.fixture(scope="module", autouse=True)
def server(server_host, server_port):
def start_server():
uvicorn.run(app, host=server_host, port=server_port, log_level="debug")

server_process = Process(target=start_server)
server_process.start()
sleep(0.5)
sleep(get_sleep_time())

yield 1

Expand All @@ -61,12 +67,9 @@ def start_server():

@pytest.fixture(scope="module", autouse=True)
def server_two(server_host, server_port_two):
def start_server():
uvicorn.run(app_two, host=server_host, port=server_port_two, log_level="debug")

server_process = Process(target=start_server)
server_process = Process(target=start_server2)
server_process.start()
sleep(0.5)
sleep(1.5)

yield 1

Expand Down
2 changes: 1 addition & 1 deletion itests/test_client.py
Expand Up @@ -19,7 +19,7 @@ def ensure_success(response: Response):

@pytest.mark.asyncio
async def test_get_plain_text(session, event_loop):
for i in range(5):
for _ in range(5):
response = await session.get("/hello-world")
ensure_success(response)
text = await response.text()
Expand Down
2 changes: 1 addition & 1 deletion itests/test_server.py
Expand Up @@ -198,7 +198,7 @@ def test_exception_handling_with_details(session):

assert response.status_code == 500
details = response.text
assert "itests/app.py" in details
assert "app.py" in details
assert "itests.utils.CrashTest: Crash Test!" in details


Expand Down
8 changes: 8 additions & 0 deletions itests/utils.py
Expand Up @@ -62,3 +62,11 @@ def assert_file_content_equals(file_path, content):
def get_file_bytes(file_path):
with open(file_path, mode="rb") as file:
return file.read()


def get_sleep_time():
# when starting a server process,
# a longer sleep time is necessary on Windows
if os.name == "nt":
return 1.5
return 0.5
11 changes: 0 additions & 11 deletions profiling.sh

This file was deleted.

1 change: 0 additions & 1 deletion requirements.txt
Expand Up @@ -45,7 +45,6 @@ typed-ast==1.4.1
typing-extensions==3.7.4.1
urllib3==1.25.7
uvicorn==0.11.8
uvloop==0.14.0
wcwidth==0.1.7
websockets==8.1
Werkzeug==0.16.0
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Expand Up @@ -11,14 +11,15 @@ def readme():

setup(
name="blacksheep",
version="0.2.5",
version="0.2.6",
description="Fast web framework and HTTP client for Python asyncio",
long_description=readme(),
long_description_content_type="text/markdown",
classifiers=[
"Development Status :: 4 - Beta",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Operating System :: OS Independent",
"Framework :: AsyncIO",
],
Expand Down
4 changes: 2 additions & 2 deletions tests/test_application.py
Expand Up @@ -2041,7 +2041,7 @@ async def home(request, x_foo: FromHeader[List[UUID]]):
await app(
get_example_scope(
"GET",
f"/",
"/",
[(b"x_foo", str(value_1).encode()), (b"x_foo", str(value_2).encode())],
),
MockReceive(),
Expand Down Expand Up @@ -2494,7 +2494,7 @@ async def home():
await app.start()

await app(
get_example_scope("GET", f"/", []),
get_example_scope("GET", "/", []),
MockReceive(),
MockSend(),
)
Expand Down
1 change: 0 additions & 1 deletion tests/test_controllers.py
@@ -1,4 +1,3 @@
from abc import abstractmethod
from blacksheep.server.application import RequiresServiceContainerError
import pytest
from typing import Optional
Expand Down

0 comments on commit 81077e6

Please sign in to comment.