Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
129 commits
Select commit Hold shift + click to select a range
a660bb3
initial code in protocols server
joamag Apr 3, 2018
3270969
Merge branch 'master' into protocols/server
joamag Apr 3, 2018
aafd1e2
new values
joamag Apr 3, 2018
d8d2e37
Merge branch 'master' into protocols/server
joamag Apr 3, 2018
d0dc185
new serve stream
joamag Apr 3, 2018
ba1aeb9
removed unused method
joamag Apr 3, 2018
6e4fcec
remove unused example
joamag Apr 3, 2018
8550eaa
Merge branch 'master' into protocols/server
joamag Apr 3, 2018
b49e435
restored method
joamag Apr 3, 2018
a70160f
new verification
joamag Apr 3, 2018
1f613db
Merge branch 'master' into protocols/server
joamag Apr 3, 2018
b4f8649
Merge branch 'master' into protocols/server
joamag Apr 4, 2018
bb5cdfa
Merge branch 'master' into protocols/server
joamag Apr 4, 2018
cf07db6
Merge branch 'master' into protocols/server
joamag Apr 4, 2018
57c95b9
Merge branch 'master' into protocols/server
joamag Apr 4, 2018
10e8dad
new comments
joamag Apr 4, 2018
b8f61a5
new comment
joamag Apr 5, 2018
9c7c9c3
Merge branch 'master' into protocols/server
joamag Apr 5, 2018
5b2ea42
Merge branch 'master' into protocols/server
joamag Apr 5, 2018
f03606e
Merge branch 'master' into protocols/server
joamag Apr 5, 2018
b49d266
Merge branch 'master' into protocols/server
joamag Apr 7, 2018
9e09776
Merge branch 'master' into protocols/server
joamag Apr 18, 2018
98d6269
Merge branch 'master' into protocols/server
joamag Apr 19, 2018
1561b15
Merge branch 'master' into protocols/server
joamag Apr 20, 2018
ff519a7
Merge branch 'master' into protocols/server
joamag Jul 4, 2018
3ae9205
initial serve support
joamag Jul 4, 2018
a19c8f4
initial _server.py implementation
joamag Jul 4, 2018
df1b20c
Merge branch 'master' into protocols/server
joamag Jul 4, 2018
89ac1a0
better compatibility
joamag Jul 4, 2018
663d5be
renamed instance to service
joamag Jul 4, 2018
ac565b1
new server transport support
joamag Jul 4, 2018
7153148
new comments
joamag Jul 4, 2018
c8c4e65
small service refactor
joamag Jul 5, 2018
d6d720b
new comments
joamag Jul 5, 2018
6d9fcdf
initial pylint file added
joamag Jul 5, 2018
be7922b
better pylint rc
joamag Jul 5, 2018
8d4c122
new pylintrc
joamag Jul 5, 2018
140c2bf
new style coding
joamag Jul 5, 2018
63ae0d1
new pylint
joamag Jul 5, 2018
c7bf92d
better warning disable
joamag Jul 5, 2018
58ffb62
new validations
joamag Jul 5, 2018
4a128e7
small fixes
joamag Jul 5, 2018
d47bd7c
new master
joamag Jul 5, 2018
663a7c8
major code change
joamag Jul 5, 2018
648c7bb
new message format
joamag Jul 5, 2018
3d0aca4
new ignores
joamag Jul 5, 2018
3101736
new disabling of warnings
joamag Jul 5, 2018
5e752b5
new pylint ignores
joamag Jul 5, 2018
9a05777
new if condition
joamag Jul 5, 2018
00d1149
extra space
joamag Jul 5, 2018
4554cfd
reversed change
joamag Jul 5, 2018
c6284df
tiny change
joamag Jul 5, 2018
c074e2e
reversed change
joamag Jul 5, 2018
0fac071
small touch
joamag Jul 5, 2018
f55a490
reversed
joamag Jul 5, 2018
e498722
touch
joamag Jul 5, 2018
89da6ce
reversed
joamag Jul 5, 2018
efacd55
removed master setting
joamag Jul 5, 2018
a5ebef9
excluded python 3.3 from new setuptools
joamag Jul 9, 2018
97a472e
new pip install and setuptools
joamag Jul 10, 2018
277ab5b
Merge branch 'master' into protocols/server-2
joamag Sep 3, 2018
02b65c5
Merge branch 'master' into pylint/fixes
joamag Sep 3, 2018
959155e
Merge branch 'master' into protocols/server
joamag Sep 23, 2018
ff14870
Merge branch 'master' into protocols/server
joamag Feb 6, 2019
26e0874
New EOL
joamag Feb 6, 2019
9448dc9
New EOL
joamag Feb 6, 2019
443212f
New comments added
joamag Feb 6, 2019
d113db8
Support for current tasks also for Python 3.7
joamag Feb 6, 2019
13f1694
Small fix
joamag Feb 6, 2019
efcf032
Small fixes
joamag Feb 6, 2019
f442340
Small code change in HEAD method validation
joamag Feb 8, 2019
45d50bc
Merge branch 'master' into protocols/server-2
joamag Mar 11, 2019
87044c0
Merge branch 'master' into pylint/fixes
joamag Mar 11, 2019
b422759
Removed common
joamag Mar 11, 2019
7fe7a90
Merge branch 'protocols/server-2' into pylint/fixes
joamag Mar 11, 2019
b9e8815
Merge pull request #32 from hivesolutions/pylint/fixes
joamag Mar 11, 2019
aaba7f9
Tiny import change, re-added the common
joamag Mar 11, 2019
5f06c4e
Merge branch 'master' into protocols/server-2
joamag Mar 14, 2019
29392d1
Merge branch 'master' into protocols/server
joamag Aug 22, 2021
d83e0eb
feat: small code refactor
joamag Aug 22, 2021
b6e0774
docs: add documentation in client protocol
joamag Aug 22, 2021
04dbd8a
fix: initial running issue
joamag Aug 22, 2021
7274885
fix issue with generate (random)
joamag Aug 22, 2021
33248c4
feat: add setting.json to ignore
joamag Aug 22, 2021
1c09a74
docs: more documentation and small if
joamag Aug 22, 2021
5173def
docs: small doc fix
joamag Aug 22, 2021
e6bfc2e
Merge branch 'master' into protocols/server
joamag Aug 22, 2021
10329e0
docs: new docs added
joamag Aug 22, 2021
4f3c3b2
fix: callback valication
joamag Aug 22, 2021
773a055
docs: simple doc fixes
joamag Aug 22, 2021
fc63552
feat: made example more lambda driven
joamag Aug 22, 2021
93de879
feat: more API implementation for Server
joamag Aug 22, 2021
d6227a4
feat: support for the global run method
joamag Aug 23, 2021
d01a953
feat: support for no yield coroutine returns
joamag Aug 23, 2021
2f951da
feat: async context manager in server
joamag Aug 23, 2021
32a2898
fix: coroutine issue with python2
joamag Aug 23, 2021
2bd79e3
feat: better runner support for asyncio
joamag Aug 23, 2021
18574df
feat: more consitency in port and host usafe
joamag Aug 23, 2021
3f17846
feat: better protocol handling
joamag Aug 23, 2021
a38334b
feat: support for runners logic (for echo)
joamag Aug 23, 2021
76bf922
feaat: simplified serve logic
joamag Aug 23, 2021
c942189
feat: initial support for protocol based serving in netius
joamag Aug 23, 2021
564b67d
feat: added simple http hello world
joamag Aug 23, 2021
5846bbd
fix: support for protocol factory at server
joamag Aug 23, 2021
f9abd00
feat: better diag in http demo
joamag Aug 23, 2021
1d7843a
feat: more connection close strategy
joamag Aug 23, 2021
5afc1ca
feat: keep alive support in HTTP test
joamag Aug 23, 2021
b237c1d
fix: better socket initialization
joamag Aug 23, 2021
10ad9b4
fix: better receive buffer structure
joamag Aug 23, 2021
95da9fc
fix: made http asyncio example more flexible and
joamag Aug 23, 2021
cc3d673
fix: issue with no service on read
joamag Aug 23, 2021
7b887ad
fix: safer ssl context access
joamag Aug 23, 2021
762cecb
feat: improved compatibility of future object
joamag Aug 23, 2021
a312ff3
fix: issue in setting current task for event loop
joamag Aug 23, 2021
fd6c57a
test: unit testing for futures
joamag Aug 23, 2021
102585d
feat: add new python version to workflows
joamag Aug 23, 2021
1dfbc99
fix: Python 3.4- testing
joamag Aug 24, 2021
0bb3681
feat: support for the env parameter flag to load env variables
joamag Aug 25, 2021
a45bc25
style: moved build connection client up to base
joamag Aug 27, 2021
c81882e
docs: renaming in comments
joamag Aug 27, 2021
eaa3476
docs: more comments renaming
joamag Aug 27, 2021
d151253
fix: removed unused import
joamag Aug 27, 2021
b65de59
feat: support for the start_serving method
joamag Aug 27, 2021
892629b
fix: small doc fix
joamag Jul 6, 2023
8843d2d
Merge branch 'master' into protocols/server
joamag Apr 22, 2024
179f76f
chore: ignore .env file
joamag Apr 22, 2024
b1585b5
Merge branch 'master' into protocols/server
joamag Apr 22, 2024
040825b
Merge branch 'master' into protocols/server
joamag Apr 22, 2024
93022af
Merge branch 'master' into protocols/server
joamag Apr 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,19 @@ jobs:
name: Build
strategy:
matrix:
python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9, "3.10", "3.11", "3.12", latest, 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:
Expand Down
84 changes: 84 additions & 0 deletions examples/echo/echos_tcp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

# Hive Netius System
# Copyright (c) 2008-2018 Hive Solutions Lda.
#
# This file is part of Hive Netius System.
#
# Hive Netius System is free software: you can redistribute it and/or modify
# it under the terms of the Apache License as published by the Apache
# Foundation, either version 2.0 of the License, or (at your option) any
# later version.
#
# Hive Netius System is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# Apache License for more details.
#
# You should have received a copy of the Apache License along with
# Hive Netius System. If not, see <http://www.apache.org/licenses/>.

__author__ = "João Magalhães <joamag@hive.pt>"
""" The author(s) of the module """

__version__ = "1.0.0"
""" The version of the module """

__revision__ = "$LastChangedRevision$"
""" The revision number of the module """

__date__ = "$LastChangedDate$"
""" The last change date of the module """

__copyright__ = "Copyright (c) 2008-2018 Hive Solutions Lda."
""" The copyright for the module """

__license__ = "Apache License, Version 2.0"
""" The license for the module """

import netius

import asyncio

class EchoServerClientProtocol(asyncio.Protocol):
"""
Simple protocol implementation for an echo protocol
that writes back the received message through the
response pipeline. This implementation is inspired by
the Python asyncio documentation example.

:see: https://docs.python.org/3.6/library/asyncio-protocol.html#protocol-examples
"""

def connection_made(self, transport):
peername = transport.get_extra_info("peername")
print("Connection from %s" % str(peername))
self.transport = transport

def data_received(self, data):
message = data.decode()
print("Data received: %s" % message)

print("Sending: %s" % message)
self.transport.write(data)

print("Closing the client socket")
self.transport.close()

loop = netius.get_loop(_compat = True)

coro = loop.create_server(
lambda: EchoServerClientProtocol(),
"127.0.0.1", 8888
)
server = loop.run_until_complete(coro)

print("Serving on %s" % (server.sockets[0].getsockname(),))

try: loop.run_forever()
except KeyboardInterrupt: pass

server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
2 changes: 1 addition & 1 deletion examples/echo/echos_udp.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def datagram_received(self, data, addr):

loop = netius.get_loop(_compat = True)
listen = loop.create_datagram_endpoint(
EchoServerProtocol,
lambda: EchoServerProtocol(),
local_addr = ("127.0.0.1", 9999)
)
transport, protocol = loop.run_until_complete(listen)
Expand Down
78 changes: 78 additions & 0 deletions examples/echo/hello_http.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

# Hive Netius System
# Copyright (c) 2008-2018 Hive Solutions Lda.
#
# This file is part of Hive Netius System.
#
# Hive Netius System is free software: you can redistribute it and/or modify
# it under the terms of the Apache License as published by the Apache
# Foundation, either version 2.0 of the License, or (at your option) any
# later version.
#
# Hive Netius System is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# Apache License for more details.
#
# You should have received a copy of the Apache License along with
# Hive Netius System. If not, see <http://www.apache.org/licenses/>.

__author__ = "João Magalhães <joamag@hive.pt>"
""" The author(s) of the module """

__version__ = "1.0.0"
""" The version of the module """

__revision__ = "$LastChangedRevision$"
""" The revision number of the module """

__date__ = "$LastChangedDate$"
""" The last change date of the module """

__copyright__ = "Copyright (c) 2008-2018 Hive Solutions Lda."
""" The copyright for the module """

__license__ = "Apache License, Version 2.0"
""" The license for the module """

import netius

import asyncio

class HelloHTTPServerProtocol(asyncio.Protocol):

def __init__(self, keep_alive = True):
super().__init__()
self.keep_alive = keep_alive

def connection_made(self, transport):
self.transport = transport
self.peername = transport.get_extra_info("peername")
print("Connection from %s" % str(self.peername))

def connection_lost(self, exc):
print("Connection from %s lost (%s)" % (str(self.peername), str(exc)))

def data_received(self, data):
keep_alive_s = b"keep-alive" if self.keep_alive else b"close"
self.transport.write(b"HTTP/1.1 200 OK\r\nConnection: %s\r\nContent-Type: text/plain\r\nContent-Length: 13\r\n\r\nHello, world!" % keep_alive_s)
if not self.keep_alive: self.transport.close()

loop = netius.get_loop(_compat = True)

coro = loop.create_server(
lambda: HelloHTTPServerProtocol(),
"127.0.0.1", 8888
)
server = loop.run_until_complete(coro)

print("Serving on %s" % (server.sockets[0].getsockname(),))

try: loop.run_forever()
except KeyboardInterrupt: pass

server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
7 changes: 4 additions & 3 deletions examples/http/http_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ def print_http_headers(url, encoding = "utf-8"):
url = urllib.parse.urlsplit(url)

if url.scheme == "https":
connect = asyncio.open_connection(url.hostname, 443, ssl = True)
connect = asyncio.open_connection(url.hostname, url.port or 443, ssl = True)
else:
connect = asyncio.open_connection(url.hostname, 80)
connect = asyncio.open_connection(url.hostname, url.port or 80)

reader, writer = yield from connect
query = "HEAD {path} HTTP/1.0\r\n" + "Host: {hostname}\r\n" + "\r\n"
query = "HEAD {path} HTTP/1.1\r\nConnection: keep-alive\r\nHost: {hostname}\r\n\r\n"
query = query.format(path = url.path or "/", hostname = url.hostname)
writer.write(query.encode(encoding))

Expand All @@ -62,6 +62,7 @@ def print_http_headers(url, encoding = "utf-8"):
if not line: break
line = line.decode(encoding).rstrip()
if line: print(line)
else: break

writer.close()

Expand Down
2 changes: 2 additions & 0 deletions pylintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[messages control]
disable=C0103,C0111,C0121,C0123,C0301,C0302,C0321,C0325,C0326,C0330,C0412,C0413,E1128,W0102,W0106,W0108,W0150,W0201,W0212,W0221,W0401,W0603,W0613,W0621,W0622,W0702,W1113
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ def read_file(path):
"netius.mock",
"netius.pool",
"netius.servers",
"netius.servers.runners",
"netius.sh",
"netius.test"
],
Expand Down
8 changes: 5 additions & 3 deletions src/netius/base/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
from . import protocol
from . import request
from . import server
from . import service
from . import stream
from . import tls
from . import transport
Expand All @@ -66,8 +67,8 @@
SSL_DH_PATH, Base, BaseThread, new_loop_main, new_loop_asyncio, new_loop,\
ensure_main, ensure_asyncio, ensure_loop, get_main, get_loop, get_event_loop,\
stop_loop, compat_loop, get_poll, build_future, ensure, ensure_pool
from .compat import BaseLoop, CompatLoop, is_compat, is_asyncio, build_datagram,\
connect_stream
from .compat import BaseLoop, CompatLoop, is_compat, is_asyncio, run, build_datagram,\
connect_stream, serve_stream
from .config import conf, conf_prefix, conf_suffix, conf_s, conf_r, conf_d, conf_ctx
from .conn import OPEN, CLOSED, PENDING, CHUNK_SIZE, Connection
from .container import Container, ContainerServer
Expand All @@ -79,8 +80,9 @@
from .protocol import Protocol, DatagramProtocol, StreamProtocol
from .request import Request, Response
from .server import Server, DatagramServer, StreamServer
from .service import Service
from .stream import Stream
from .tls import fingerprint, match_fingerprint, match_hostname, dnsname_match,\
dump_certificate
from .transport import Transport, TransportDatagram, TransportStream
from .transport import Transport, TransportDatagram, TransportStream, ServerTransport
from .util import camel_to_underscore, verify
26 changes: 22 additions & 4 deletions src/netius/base/async_neo.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class Future(async_old.Future):
syntax to be used in the future so that it becomes compliant
with the basic Python asyncio strategy for futures.

Using this future, it should be possible to `await Future()`
Using this future it should be possible to `await Future()`
for a simpler usage.
"""

Expand Down Expand Up @@ -258,22 +258,40 @@ def wait(*args, **kwargs):
def coroutine_return(coroutine):
"""
Allows for the abstraction of the return value of a coroutine
object to be the result of the future yield as the first element
object to be the result of the future yielded as the last element
of the generator.

This allows the possibility of providing compatibility with the legacy
not return allowed generators.

In case no value is yielded then an invalid value is returned as the
result of the async coroutine.

:type coroutine: CoroutineObject
:param coroutine: The coroutine object that is going to be yield back
:param coroutine: The coroutine object that is going to yield back
and have its last future result returned from the generator.
"""

generator = _coroutine_return(coroutine)
return AwaitWrapper(generator)

def _coroutine_return(coroutine):
# unsets the initial future reference value, this
# way it's possible to avoid future based return
# statement in case the coroutine is "empty"
future = None

# iterates over the coroutine generator yield
# the values (should be future instances) and
# ignoring possible invalid values, the last
# value yielded is considered to be future
# that is going to be set as the return value
for value in coroutine:
if value == None: continue
yield value
future = value
return future.result()

# in case at least one valid future was yielded
# then set the result of such future as the result
# of the current coroutine (return statement)
return future.result() if future else None
25 changes: 22 additions & 3 deletions src/netius/base/async_old.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ class Future(object):
:see: https://en.wikipedia.org/wiki/Futures_and_promises
"""

_asyncio_future_blocking = True

def __init__(self, loop = None):
self.status = 0
self._loop = loop
Expand Down Expand Up @@ -117,6 +119,18 @@ def add_ready_callback(self, function):
def add_closed_callback(self, function):
self.closed_callbacks.append(function)

def remove_done_callback(self, function):
self.done_callbacks.remove(function)

def remove_partial_callback(self, function):
self.partial_callbacks.remove(function)

def remove_ready_callback(self, function):
self.ready_callbacks.remove(function)

def remove_closed_callback(self, function):
self.closed_callbacks.remove(function)

def approve(self, cleanup = True):
self.set_result(None, cleanup = cleanup)

Expand Down Expand Up @@ -336,15 +350,20 @@ def notify(event, data = None):
def coroutine_return(coroutine):
"""
Allows for the abstraction of the return value of a coroutine
object to be the result of the future yield as the first element
object to be the result of the future yielded as the last element
of the generator.

This allows the possibility of providing compatibility
with the legacy not return allowed generators.

In case no value is yielded then an invalid value is returned as the
result of the async coroutine.

:type coroutine: CoroutineObject
:param coroutine: The coroutine object that is going to be yield back
:param coroutine: The coroutine object that is going to yield back
and have its last future result returned from the generator.
"""

for value in coroutine: yield value
for value in coroutine:
if value == None: continue
yield value
4 changes: 2 additions & 2 deletions src/netius/base/asynchronous.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@
# imports the base (old) version of the async implementation
# that should be compatible with all the available python
# interpreters, base collection of async library
from .async_old import * #@UnusedWildImport
from .async_old import * #@UnusedWildImport pylint: disable=W0614

# verifies if the current python interpreter version supports
# the new version of the async implementation and if that's the
# case runs the additional import of symbols, this should override
# most of the symbols that have just been created
if is_neo(): from .async_neo import * #@UnusedWildImport
if is_neo(): from .async_neo import * #@UnusedWildImport pylint: disable=W0614
4 changes: 2 additions & 2 deletions src/netius/base/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -689,13 +689,13 @@ def connect(
# ensures that the proper socket family is defined in case the
# requested host value is unix socket oriented, this step greatly
# simplifies the process of created unix socket based clients
family = socket.AF_UNIX if host == "unix" else family
family = socket.AF_UNIX if host == "unix" else family #@UndefinedVariable pylint: disable=E1101

# verifies the kind of socket that is going to be used for the
# connect operation that is going to be performed, note that the
# unix type should be used with case as it does not exist in every
# operative system and may raised an undefined exceptions
is_unix = hasattr(socket, "AF_UNIX") and family == socket.AF_UNIX
is_unix = hasattr(socket, "AF_UNIX") and family == socket.AF_UNIX #@UndefinedVariable pylint: disable=E1101
is_inet = family in (socket.AF_INET, socket.AF_INET6)

# runs a series of default operation for the SSL related attributes
Expand Down
Loading