Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.1.0a1 #10

Merged
merged 11 commits into from
Oct 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 9 additions & 2 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
UPCOMING
pass
TODO
Policies declaration via app config (https://www.rabbitmq.com/parameters.html)
Run separate service/consumer as worker
Add ABC to prevent circular import hell

v 1.1.0a1
Pydantic based app settings
Inject arguments to endpoints based on type annotations (FastAPI-like)
Inject logger or other components

v 1.0.11
Make it possible to just register endpoints, without running loop (method `Mela.setup()`)
Expand Down
66 changes: 66 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# COLORS
GREEN := $(shell tput -Txterm setaf 2)
WHITE := $(shell tput -Txterm setaf 7)
YELLOW := $(shell tput -Txterm setaf 3)
RESET := $(shell tput -Txterm sgr0)

.DEFAULT_GOAL := help
.PHONY: help setup run lint type flake8 mypy test testcov run clean

VENV=.venv
PYTHON=$(VENV)/bin/python3

## Initialize venv and install dependencies
setup: $(VENV)/bin/activate
$(VENV)/bin/activate:
python3 -m venv $(VENV)
$(PYTHON) -m pip install pipenv==2022.9.8
$(PYTHON) -m pipenv sync -d

## Analyze project source code for slylistic errors
lint: setup
$(PYTHON) -m flake8 mela tests

## Analyze project source code for typing errors
type: setup
$(PYTHON) -m mypy mela tests

## Run flake8
flake8: setup
$(PYTHON) -m flake8 mela tests

## Run mypy
mypy: setup
$(PYTHON) -m mypy mela tests

## Run project tests
test: setup
$(PYTHON) -m pytest

## Run project tests and open HTML coverage report
testcov: setup
$(PYTHON) -m pytest --cov-report=html
xdg-open htmlcov/index.html

## Clean up project environment
clean:
rm -rf $(VENV) *.egg-info .eggs .coverage htmlcov .pytest_cache
find . -type f -name '*.pyc' -delete

## Show help
help:
@echo ''
@echo 'Usage:'
@echo ' ${YELLOW}make${RESET} ${GREEN}<target>${RESET}'
@echo ''
@echo 'Targets:'
@awk '/^[a-zA-Z\-\_0-9]+:/ { \
helpMessage = match(lastLine, /^## (.*)/); \
if (helpMessage) { \
helpCommand = $$1; sub(/:$$/, "", helpCommand); \
helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \
printf " ${YELLOW}%-$(TARGET_MAX_CHAR_NUM)15s${RESET} ${GREEN}%s${RESET}\n", helpCommand, helpMessage; \
} \
} \
{ lastLine = $$0 }' $(MAKEFILE_LIST)
@echo ''
31 changes: 31 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
aio-pika = "==8.2.1"
envyaml = "==1.10.211231"
pydantic = "==1.10.2"

[dev-packages]
flake8 = "==5.0.4"
flake8-broken-line = "==0.5.0"
flake8-commas = "==2.1.0"
flake8-comprehensions = "==3.10.0"
flake8-eradicate = "==1.3.0"
flake8-isort = "==4.2.0"
flake8-print = "==5.0.0"
pep8-naming = "==0.13.2"
flake8-bandit = "==4.1.1"
flake8-use-fstring = "==1.4"
bandit = "==1.7.4"
mypy = "==0.971"
pytest = "==7.1.3"
pytest-cov = "==3.0.0"
pytest-mock = "==3.8.2"
pytest-asyncio = "==0.19.0"
pytest-clarity = "==1.0.1"

[requires]
python_version = "3.10"
734 changes: 734 additions & 0 deletions Pipfile.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.11
1.1.0a1
5 changes: 2 additions & 3 deletions examples/bridge_between_two_rabbits/app.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from mela import Mela

app = Mela(__name__)
app.read_config_yaml('application.yml')


@app.service("input", "output")
def serve(body, message):
@app.service("bridge")
async def serve(body, message):
return body


Expand Down
46 changes: 20 additions & 26 deletions examples/bridge_between_two_rabbits/application.yml
Original file line number Diff line number Diff line change
@@ -1,30 +1,24 @@
connections:
input_connection:
host: ${RABBIT_INPUT_HOST}
port: 5672
username: rabbitmq-bridge
password: rabbitmq-bridge
connTimeout: 1000
heartbeat: 360
host: $RABBIT_INPUT_HOST
port: ${RABBIT_INPUT_PORT|5672}
username: ${RABBIT_INPUT_USERNAME|rabbitmq-bridge}
password: ${RABBIT_INPUT_PASSWORD|rabbitmq-bridge}
output_connection:
host: ${RABBIT_OUTPUT_HOST}
port: 5672
username: rabbitmq-bridge
password: rabbitmq-bridge
connTimeout: 1000
heartbeat: 360
host: $RABBIT_OUTPUT_HOST
port: ${RABBIT_OUTPUT_PORT|5672}
username: ${RABBIT_OUTPUT_USERNAME|rabbitmq-bridge}
password: ${RABBIT_OUTPUT_PASSWORD|rabbitmq-bridge}

consumers:
input:
connection: input_connection
prefetch_count: 100
routing_key: general-sentiment-q
exchange: general-sentiment-x
queue: general-sentiment-temp-q
decode: json

producers:
output:
connection: output_connection
routing_key: general-sentiment-q
exchange: general-sentiment-x
services:
bridge:
consumer:
connection: input_connection
prefetch_count: ${RABBIT_INPUT_PREFETCH_COUNT|1}
routing_key: ${RABBIT_INPUT_ROUTING_KEY}
exchange: ${RABBIT_INPUT_EXCHANGE}
queue: ${RABBIT_INPUT_QUEUE}
producer:
connection: output_connection
routing_key: ${RABBIT_OUTPUT_ROUTING_KEY}
exchange: ${RABBIT_OUTPUT_EXCHANGE}
18 changes: 7 additions & 11 deletions examples/dead_letter_exchange/app.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
from mela import Mela
from mela.components.exceptions import NackMessageError

app = Mela(__name__)
app.read_config_yaml('application.yml')

i = 0


@app.service("printer")
@app.service("service_with_dlx")
async def printer(body, message):
global i
i += 1
if i % 2 == 0:
raise NotImplementedError("Method is not implemented")
return i
# for obj in body:
# if i % 2 == 0:
# yield obj
# else:
# yield obj, {'routing_key': "test_queue2"}
# raise ConnectionError("something went wrong")
# i += 1
print(body, "NO")
raise NackMessageError("Method is not implemented", requeue=False)
else:
print(body, "YES")
return body


if __name__ == '__main__':
Expand Down
2 changes: 1 addition & 1 deletion examples/dead_letter_exchange/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ connections:
password: admin

services:
printer:
service_with_dlx:
consumer:
exchange: dlx-test-x
routing_key: dlx-test-k
Expand Down
11 changes: 0 additions & 11 deletions examples/error_handler/app.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
from mela import Mela

app = Mela(__name__)
app.read_config_yaml('application.yml')


@app.service("splitter")
async def printer(body, message):
i = 0
i += 1
raise NotImplementedError("Method is not implemented")
return i
# for obj in body:
# if i % 2 == 0:
# yield obj
# else:
# yield obj, {'routing_key': "test_queue2"}
# raise ConnectionError("something went wrong")
# i += 1


if __name__ == '__main__':
Expand Down
4 changes: 1 addition & 3 deletions examples/exchange_type_topic/app.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
from aio_pika import IncomingMessage
from mela import Mela

app = Mela(__name__)
app.read_config_yaml('application.yml')


@app.service("printer")
def printer(body, message: IncomingMessage):
def printer(body, message):
print(body)
print(message.routing_key)
return body
Expand Down
30 changes: 13 additions & 17 deletions examples/extra_publishing_service/app.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,23 @@
from pydantic import BaseModel, Field
from mela import Mela
from mela.components import Publisher
from mela.settings import Settings

app = Mela(__name__)
app.read_config_yaml('application.yml')

logging_publisher = app.publisher()
class Document(BaseModel):
id_: int = Field(alias='id')


app = Mela(__name__)
app.settings = Settings()

SPLITTER_SERVICE_NAME = "splitter"
log_publisher: Publisher = app.publisher_instance('log')


@app.service(SPLITTER_SERVICE_NAME)
async def logger(body, message):
default_routing_key = app.services['splitter'].config['publisher']['routing_key']
i = 0
for obj in body:
if i % 2 == 0:
routing_key = default_routing_key
else:
routing_key = "test_queue2"
yield obj, {'routing_key': routing_key}
# Anyway, we should publish message into logging exchange
await logging_publisher.publish(obj, routing_key='.'.join([SPLITTER_SERVICE_NAME, routing_key]))
i += 1
@app.service('extra_publishing')
async def logger(body: Document):
await log_publisher.publish(body)
return body


if __name__ == '__main__':
Expand Down
4 changes: 2 additions & 2 deletions examples/extra_publishing_service/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ connections:
password: admin

services:
splitter:
extra_publishing:
consumer:
exchange: general-sentiment-x
routing_key: general-sentiment-q
Expand All @@ -16,7 +16,7 @@ services:
routing_key: test_queue

publishers:
default:
log:
exchange: log-x
exchange_type: topic
routing_key: splitter.test_queue
32 changes: 20 additions & 12 deletions examples/rpc/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from mela import Mela

app = Mela(__name__)
app.read_config_yaml('application.yml')


fetcher = app.rpc_client("fetcher")
Expand All @@ -14,26 +13,35 @@
async def main():
# RPC calls over RabbitMQ never were simpler!
res = await fetcher.call({'asdf': 5, 'lol': [3, 8, ["haha", "wow"]]})
print(res)
# res

# we can even gather call results!
g = await asyncio.gather(fetcher.call(url1), fetcher.call(url2))
print(g)

create_bot_result = await bot_manager.call(
{'bot_id': 1, 'bot_username': "LalkaPalka", 'bot_password': "supersecret"},
headers={'method': 'create_bot'}
# g

create_bot_result = await bot_manager.call({
'bot_id': 1,
'bot_username': "LalkaPalka",
'bot_password': "supersecret",
},
headers={'method': 'create_bot'},
)
print(f"create_bot result: {create_bot_result}")
# create_bot result {create_bot_result}

get_bot_result = await bot_manager.call({'bot_id': 1}, headers={'method': 'get_bot'})
print(f"get_bot_result: {get_bot_result}")
# get_bot_result {get_bot_result}

unknown_method_result = await bot_manager.call({'bot_id': 4}, headers={'method': 'getBot'})
print(f"unknown method result: {unknown_method_result}")
# unknown method result: {unknown_method_result}


if __name__ == '__main__':
url1 = 'https://tengrinews.kz/kazakhstan_news/vorvalis-dom-izbili-almatinka-rasskazala-zaderjanii-supruga-459127/'
url2 = 'https://www.inform.kz/ru/skol-ko-lichnyh-podsobnyh-hozyaystv-naschityvaetsya-v-kazahstane_a3896073'
url1 = (
'https://tengrinews.kz/kazakhstan_news/vorvalis-dom-izbili-'
'almatinka-rasskazala-zaderjanii-supruga-459127/'
)
url2 = (
'https://www.inform.kz/ru/skol-ko-lichnyh-podsobnyh-'
'hozyaystv-naschityvaetsya-v-kazahstane_a3896073'
)
app.run(main())
3 changes: 1 addition & 2 deletions examples/rpc/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from mela import Mela

app = Mela(__name__)
app.configure_from_yaml('application.yml')


async def fetch(url):
Expand All @@ -13,7 +12,7 @@ async def fetch(url):
return url


@app.rpc_server("fetcher")
@app.rpc_service("fetcher")
async def fetcher(link, message):
return await fetch(link)

Expand Down
Loading