Skip to content

Commit

Permalink
Merge branch 'master' into protocols/smtp_client
Browse files Browse the repository at this point in the history
  • Loading branch information
joamag committed Apr 22, 2024
2 parents 587cb68 + 75e2bdf commit c3ad6c7
Show file tree
Hide file tree
Showing 45 changed files with 612 additions and 203 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
container: python:${{ matrix.python-version }}
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v4
- run: python --version
- run: pip install -r requirements.txt
- run: HTTPBIN=httpbin.bemisc.com python setup.py test
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ jobs:
name: Build
strategy:
matrix:
python-version: [2.7, 3.5, 3.6, 3.7, rc]
python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9, "3.10", "3.11", "3.12", latest, rc]
runs-on: ubuntu-latest
container: python:${{ matrix.python-version }}
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v4
- run: python --version
- run: pip install -r requirements.txt
- run: HTTPBIN=httpbin.bemisc.com python setup.py test
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ session.shelve*

.DS_Store

/.vscode/settings.json

net.ca
fs.data

/.venv

/dist
/build
/src/netius.egg-info
Expand Down
3 changes: 0 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,9 @@ python:
- "3.4"
- "3.5"
- "3.6"
- "nightly"
- "pypy3"
matrix:
include:
- python: 3.7
dist: xenial
- python: 3.8
dist: xenial
- python: pypy
Expand Down
4 changes: 0 additions & 4 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@
"name": "Python",
"type": "python",
"request": "launch",
"python": "${command:python.interpreterPath}",
"program": "${file}",
"debugOptions": [
"RedirectOutput"
],
"env": {
"PYTHONPATH": "${workspaceRoot}/src:{env.PYTHONPATH}"
}
Expand Down
50 changes: 50 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,56 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

*

## [1.19.3] - 2024-01-18

### Changed

* Improved the structure of the Postmaster message

### Fixed

* Context information `tos` in the Postmaster email handling
* Critical issue with the SMTP client when connecting with SMTP servers with older versions of OpenSSL

## [1.19.2] - 2024-01-17

### Added

* Support for Postmaster email in SMTP relay using the `POSTMASTER` configuration value
* Support for the `exception` event in the `Connection` triggered when a exception is raised in the connection domain

## [1.19.1] - 2022-10-15

### Added

* Support for `allowed_froms` in SMTP relay

### Changed

* Improved support in the `legacy.py` module

## [1.19.0] - 2022-05-02

### Added

* Support for `SSL_CONTEXT_OPTIONS` to netius SSL context creation

## [1.18.4] - 2022-04-26

### Added

* Better debug support for connection address

### Fixed

* Custom listing using both `apache` and `legacy` for `LIST_ENGINE`

## [1.18.3] - 2021-11-01

### Added

* Better debug support for connection address

## [1.18.2] - 2021-05-01

### Added
Expand Down
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@

**Fast and readable async non-blocking network apps**

Netius is a Python network library that can be used for the rapid creation of asynchronous non-blocking
Netius is a Python network library that can be used for the rapid creation of asynchronous, non-blocking
servers and clients. It has no dependencies, it's cross-platform, and brings some sample netius-powered
servers out of the box, namely a production-ready WSGI server.

Simplicity and performance are the main drivers of this project. The codebase adheres to very strict
code standards, and is extensively commented; and as far as performance is concerned, it aims to
be up to par with equivalent native implementations, where [PyPy](http://pypy.org) can be used to
Simplicity and performance are the main drivers of this project. The codebase adheres to rigorous
code standards and is extensively commented on. As far as performance is concerned, it aims to
be up to par with equivalent native implementations, where [PyPy](http://pypy.org) can
provide the extra boost to raise performance up to these standards.

Bear in mind that although netius is non-blocking, it will naturally still block if the operations
performed within the event loop are blocking, like reading or writing a file, which are both blocking
operations in the Python standard library. Running multiple netius instances in parallel, and having
a fast server like [NGINX](http://nginx.org) act as their reverse proxy, is one way of minimising the
a fast server like [NGINX](http://nginx.org) acts as their reverse proxy, which is one way of minimizing the
perceptibility of such blockages.

## Installation
Expand All @@ -25,9 +25,9 @@ pip install netius

Or download the source from [GitHub](https://github.com/hivesolutions/netius).

Netius has no dependencies, and is therefore cross-platform. It's compatible with [PyPy](http://pypy.org),
with which it benefits of performance increases up to 1.5x - 2.5x faster in most environments, when
compared with running it with the cPython interpreter.
Netius has no dependencies and is, therefore cross-platform. It's compatible with [PyPy](http://pypy.org),
with which its benefits of performance increase up to 1.5x - 2.5x faster in most environments when
compared with running it with the CPython interpreter.

## Usage

Expand Down Expand Up @@ -112,7 +112,7 @@ Netius is currently licensed under the [Apache License, Version 2.0](http://www.

## Build Automation

[![Build Status](https://travis-ci.com/hivesolutions/netius.svg?branch=master)](https://travis-ci.com/hivesolutions/netius)
[![Build Status](https://app.travis-ci.com/hivesolutions/netius.svg?branch=master)](https://travis-ci.com/github/hivesolutions/netius)
[![Build Status GitHub](https://github.com/hivesolutions/netius/workflows/Main%20Workflow/badge.svg)](https://github.com/hivesolutions/netius/actions)
[![Coverage Status](https://coveralls.io/repos/hivesolutions/netius/badge.svg?branch=master)](https://coveralls.io/r/hivesolutions/netius?branch=master)
[![PyPi Status](https://img.shields.io/pypi/v/netius.svg)](https://pypi.python.org/pypi/netius)
Expand Down
2 changes: 1 addition & 1 deletion doc/advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ The results are a result of executing the benchmark on `servidor4.hive`.

The `h2spec` tools allows proper verification of the RFC 5741 statements on a quick fashion.

```
```bash
scu install go
export GOPATH=~/go
mkdir -p ~/go
Expand Down
33 changes: 17 additions & 16 deletions doc/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,23 @@

#### SSL

| Name | Type | Description |
| ------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **CER_FILE** | `str` | The path to the certificate file to be used for SSL (PEM format). |
| **KEY_FILE** | `str` | The path to the private key file to be used for SSL (PEM format). |
| **CA_FILE** | `str` | The path to the CA (certificate authority) file to be used for SSL (PEM format). |
| **CA_ROOT** | `bool` | If the default CA file/files should be loaded from the current environment (defaults to `True`). |
| **SSL_VERIFY** | `bool` | If the standard SSL verification process (CA) should be performed for the connection, if the current instance is a client the host verification will also be performed for the server side host. |
| **SSL_HOST** | `str` | The hostname that is going to be used in for domain verification, this value is only user in server to be able to verify client certificates against an expected host. |
| **SSL_FINGERPRINT** | `str` | The fingerprint (SHA1 digest of certificate) that is going to be used to verify the integrity of a peer/client certificate against the expected one. |
| **SSL_DUMP** | `bool` | If the certificate information should be dumped to the directory specified by the `SSL_PATH` configuration value (defaults to `False`). |
| **SSL_PATH** | `str` | Path to the directory where the SSL dump information is going to be placed, in case the directory does not exist it's created (defaults to `/tmp/ssl`). |
| **SSL_SECURE** | `int` | The level of security to be used for the suite of SSL (eg: some protocols removed) (defaults to `1`). |
| **SSL_CONTEXTS** | `dict` | The dictionary that associates the various domains that may be served with different context values (certificate, key, etc) for such domain. |
| **CER_DATA** | `str` | Equivalent to `CER_FILE` but with explicit (data) contents of the file (`\n` escaped). |
| **KEY_DATA** | `str` | Equivalent to `KEY_FILE` but with explicit (data) contents of the file (`\n` escaped). |
| **CA_DATA** | `str` | Equivalent to `CA_FILE` but with explicit (data) contents of the file (`\n` escaped). |
| Name | Type | Description |
| ----------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **CER_FILE** | `str` | The path to the certificate file to be used for SSL (PEM format). |
| **KEY_FILE** | `str` | The path to the private key file to be used for SSL (PEM format). |
| **CA_FILE** | `str` | The path to the CA (certificate authority) file to be used for SSL (PEM format). |
| **CA_ROOT** | `bool` | If the default CA file/files should be loaded from the current environment (defaults to `True`). |
| **SSL_VERIFY** | `bool` | If the standard SSL verification process (CA) should be performed for the connection, if the current instance is a client the host verification will also be performed for the server side host. |
| **SSL_HOST** | `str` | The hostname that is going to be used in for domain verification, this value is only user in server to be able to verify client certificates against an expected host. |
| **SSL_FINGERPRINT** | `str` | The fingerprint (SHA1 digest of certificate) that is going to be used to verify the integrity of a peer/client certificate against the expected one. |
| **SSL_DUMP** | `bool` | If the certificate information should be dumped to the directory specified by the `SSL_PATH` configuration value (defaults to `False`). |
| **SSL_PATH** | `str` | Path to the directory where the SSL dump information is going to be placed, in case the directory does not exist it's created (defaults to `/tmp/ssl`). |
| **SSL_SECURE** | `int` | The level of security to be used for the suite of SSL (eg: some protocols removed) (defaults to `1`). |
| **SSL_CONTEXT_OPTIONS** | `list` | List of strings that defined the options to be used in the SSL context creation (eg: `OP_NO_SSLv2`) for more information check [ssl module documentation](https://docs.python.org/3/library/ssl.html) (defaults to `[]`). |
| **SSL_CONTEXTS** | `dict` | The dictionary that associates the various domains that may be served with different context values (certificate, key, etc) for such domain. |
| **CER_DATA** | `str` | Equivalent to `CER_FILE` but with explicit (data) contents of the file (`\n` escaped). |
| **KEY_DATA** | `str` | Equivalent to `KEY_FILE` but with explicit (data) contents of the file (`\n` escaped). |
| **CA_DATA** | `str` | Equivalent to `CA_FILE` but with explicit (data) contents of the file (`\n` escaped). |

#### File Serving

Expand Down
2 changes: 1 addition & 1 deletion doc/leak.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Memory Leaking

Memory leaking is one of the major issues when creating a service infra-structure. A correct detection of tese
Memory leaking is one of the major issues when creating a service infra-structure. A correct detection of these
type of problems is important to provide a stable production environment.

## Status
Expand Down
9 changes: 7 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def read_file(path):
netius.common.ensure_setup()
setuptools.setup(
name = "netius",
version = "1.18.2",
version = "1.19.3",
author = "Hive Solutions Lda.",
author_email = "[email protected]",
description = "Netius System",
Expand Down Expand Up @@ -105,7 +105,12 @@ def read_file(path):
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7"
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12"
],
long_description = read_file("README.rst")
)
16 changes: 16 additions & 0 deletions src/netius/adapters/base.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from typing import Any, BinaryIO, Sequence

class BaseAdapter:
def set(self, value: Any, owner: str = ...): ...
def get(self, key: str) -> bytes | None: ...
def get_file(self, key: str, mode: str = ...) -> BinaryIO: ...
def delete(self, key: str, owner: str = ...): ...
def append(self, key: str, value: Any): ...
def truncate(self, key: str, count: int): ...
def size(self, key: str) -> int: ...
def sizes(self, owner: str | None = ...) -> list[int]: ...
def total(self, owner: str | None = ...) -> int: ...
def reserve(self, owner: str = ...): ...
def count(self, owner: str | None = ...) -> int: ...
def list(self, owner: str | None = ...) -> Sequence[str]: ...
def generate(self) -> str: ...
11 changes: 11 additions & 0 deletions src/netius/adapters/fs.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from os import PathLike

from netius import BaseAdapter

class FsAdapter(BaseAdapter):
base_path: str

def __init__(self, base_path: str | None = ...): ...
def _path(self, owner: str | None = ...) -> str: ...
def _ensure(self, owner: str) -> str: ...
def _symlink(self, source: PathLike[str], target: PathLike[str]): ...
8 changes: 8 additions & 0 deletions src/netius/adapters/memory.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from typing import Any, BinaryIO, Callable, Mapping

from netius import BaseAdapter

class MemoryAdapter(BaseAdapter):
def __init__(self): ...
def _ensure(self, owner: str) -> Mapping[str, Any]: ...
def _build_close(self, file: BinaryIO, key: str) -> Callable[[], None]: ...
4 changes: 4 additions & 0 deletions src/netius/adapters/mongo.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from netius import BaseAdapter

class MongoAdapter(BaseAdapter):
pass
4 changes: 4 additions & 0 deletions src/netius/adapters/null.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from netius import BaseAdapter

class NullAdapter(BaseAdapter):
pass
8 changes: 8 additions & 0 deletions src/netius/auth/address.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from typing import Sequence

from netius import Auth

class AddressAuth(Auth):
def __init__(self, allowed: Sequence[str] = ..., *args, **kwargs): ...
@classmethod
def auth(cls, allowed: Sequence[str] = ..., *args, **kwargs) -> bool: ...
4 changes: 4 additions & 0 deletions src/netius/auth/allow.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from netius import Auth

class AllowAuth(Auth):
pass
4 changes: 4 additions & 0 deletions src/netius/auth/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ def __init__(self, *args, **kwargs):
def auth(cls, *args, **kwargs):
raise netius.NotImplemented("Missing implementation")

@classmethod
def meta(cls, *args, **kwargs):
return {}

@classmethod
def auth_assert(cls, *args, **kwargs):
result = cls.auth(*args, **kwargs)
Expand Down
28 changes: 28 additions & 0 deletions src/netius/auth/base.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from os import PathLike
from typing import Any, Literal, Mapping, NoReturn

HashType = Literal["plain", "md5", "sha1", "sha256", "sha512"]

class Auth:
def __init__(self, *args, **kwargs): ...
@classmethod
def auth(cls, *args, **kwargs) -> bool: ...
@classmethod
def meta(cls, *args, **kwargs) -> Mapping[str, Any]: ...
@classmethod
def auth_assert(cls, *args, **kwargs) -> NoReturn: ...
@classmethod
def verify(cls, encoded: str, decoded: str) -> bool: ...
@classmethod
def generate(cls, password: str, type: HashType = ..., salt: str = ...) -> str: ...
@classmethod
def unpack(cls, password) -> tuple[HashType, str | None, str, str | None]: ...
@classmethod
def get_file(
cls, path: PathLike[str], cache: bool = ..., encoding: str | None = ...
) -> str | bytes: ...
@classmethod
def is_simple(cls) -> bool: ...
def auth_i(self, *args, **kwargs) -> bool: ...
def auth_assert_i(self, *args, **kwargs) -> NoReturn: ...
def is_simple_i(self) -> bool: ...
4 changes: 4 additions & 0 deletions src/netius/auth/deny.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from netius import Auth

class DenyAuth(Auth):
pass
6 changes: 6 additions & 0 deletions src/netius/auth/dummy.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from netius import Auth

class DummyAuth(Auth):
def __init__(self, value: bool = ..., *args, **kwargs): ...
@classmethod
def auth(cls, value: bool = ..., *args, **kwargs) -> bool: ...
8 changes: 8 additions & 0 deletions src/netius/auth/memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,19 @@ def __init__(self, registry = None, *args, **kwargs):
@classmethod
def auth(cls, username, password, registry = None, *args, **kwargs):
registry = registry or cls.get_registry()
if not registry: return False
register = registry.get(username, None)
if not register: return False
_password = register.get("password")
return cls.verify(_password, password)

@classmethod
def meta(cls, username, registry = None, *args, **kwargs):
registry = registry or cls.get_registry()
if not registry: return {}
register = registry.get(username, {})
return register

@classmethod
def get_registry(cls):
if hasattr(cls, "registry"): return cls.registry
Expand Down
Loading

0 comments on commit c3ad6c7

Please sign in to comment.