Skip to content
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
2 changes: 1 addition & 1 deletion benchmarks/aa_overhead_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,6 @@ def measure_overhead(measure, title: str):
def os_id():
if sys.platform.lower() == "darwin":
return "macOS"
elif sys.platform.lower() == "win32":
if sys.platform.lower() == "win32":
return "Windows"
return "Linux"
13 changes: 5 additions & 8 deletions examples/as_app/talk_bot/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def convert_currency(amount, from_currency, to_currency):
base_url = "https://api.exchangerate-api.com/v4/latest/"

# Fetch latest exchange rates
response = requests.get(base_url + from_currency)
response = requests.get(base_url + from_currency, timeout=60)
data = response.json()

if "rates" in data:
Expand All @@ -30,12 +30,9 @@ def convert_currency(amount, from_currency, to_currency):

if from_currency in rates and to_currency in rates:
conversion_rate = rates[to_currency] / rates[from_currency]
converted_amount = amount * conversion_rate
return converted_amount
else:
raise ValueError("Invalid currency!")
else:
raise ValueError("Unable to fetch exchange rates!")
return amount * conversion_rate
raise ValueError("Invalid currency!")
raise ValueError("Unable to fetch exchange rates!")


def currency_talk_bot_process_request(message: talk_bot.TalkBotMessage):
Expand All @@ -55,7 +52,7 @@ def currency_talk_bot_process_request(message: talk_bot.TalkBotMessage):
CURRENCY_BOT.send_message(f"{r.group(2)} {r.group(3)} is equal to {converted_amount} {r.group(4)}", message)
except Exception as e:
# In production, it is better to write to log, than in the chat ;)
CURRENCY_BOT.send_message(f"Exception: {str(e)}", message)
CURRENCY_BOT.send_message(f"Exception: {e}", message)


@APP.post("/currency_talk_bot")
Expand Down
8 changes: 4 additions & 4 deletions examples/as_app/talk_bot_multi/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,21 @@
@APP.post("/bot1")
async def bot1(message: Annotated[talk_bot.TalkBotMessage, Depends(talk_bot_app)]):
if message.object_name != "message":
return
return None
r = re.search(r"@bot\sone.*", message.object_content["message"], re.IGNORECASE)
if r is None and re.search(r"@bots!", message.object_content["message"], re.IGNORECASE) is None:
return
return None
BOT1.send_message("I am here, my Lord!", message)
return requests.Response()


@APP.post("/bot2")
async def bot2(message: Annotated[talk_bot.TalkBotMessage, Depends(talk_bot_app)]):
if message.object_name != "message":
return
return None
r = re.search(r"@bot\stwo.*", message.object_content["message"], re.IGNORECASE)
if r is None and re.search(r"@bots!", message.object_content["message"], re.IGNORECASE) is None:
return
return None
BOT2.send_message("I am here, my Lord!", message)
return requests.Response()

Expand Down
8 changes: 4 additions & 4 deletions nc_py_api/_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

For internal use, prototypes can change between versions.
"""
import secrets
from base64 import b64decode
from datetime import datetime, timezone
from random import choice
from string import ascii_lowercase, ascii_uppercase, digits
from string import ascii_letters, digits
from typing import Callable, Union

from ._exceptions import NextcloudMissingCapabilities
Expand Down Expand Up @@ -65,8 +65,8 @@ def check_capabilities(capabilities: Union[str, list[str]], srv_capabilities: di

def random_string(size: int) -> str:
"""Generates a random ASCII string of the given size."""
letters = ascii_lowercase + ascii_uppercase + digits
return "".join(choice(letters) for _ in range(size))
char_string = ascii_letters + digits
return "".join(secrets.choice(char_string) for _ in range(size))


def nc_iso_time_to_datetime(iso8601_time: str) -> datetime:
Expand Down
4 changes: 2 additions & 2 deletions nc_py_api/files/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,11 @@ def __str__(self):
if self.info.is_version:
return (
f"File version: `{self.name}` for FileID={self.file_id}"
f" last modified at {str(self.info.last_modified)} with {self.info.content_length} bytes size."
f" last modified at {self.info.last_modified} with {self.info.content_length} bytes size."
)
return (
f"{'Dir' if self.is_dir else 'File'}: `{self.name}` with id={self.file_id}"
f" last modified at {str(self.info.last_modified)} and {self.info.permissions} permissions."
f" last modified at {self.info.last_modified} and {self.info.permissions} permissions."
)

def __eq__(self, other):
Expand Down
7 changes: 2 additions & 5 deletions nc_py_api/files/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
from io import BytesIO
from json import dumps, loads
from pathlib import Path
from random import choice
from string import ascii_lowercase, digits
from typing import Optional, Union
from urllib.parse import unquote
from xml.etree import ElementTree
Expand All @@ -16,7 +14,7 @@
from httpx import Response

from .._exceptions import NextcloudException, NextcloudExceptionNotFound, check_error
from .._misc import clear_from_params_empty, require_capabilities
from .._misc import clear_from_params_empty, random_string, require_capabilities
from .._session import NcSessionBasic
from . import FsNode, SystemTag
from .sharing import _FilesSharingAPI
Expand Down Expand Up @@ -694,8 +692,7 @@ def __download2stream(self, path: str, fp, **kwargs) -> None:
fp.write(data_chunk)

def __upload_stream(self, path: str, fp, **kwargs) -> FsNode:
_rnd_folder = "".join(choice(digits + ascii_lowercase) for _ in range(64))
_dav_path = self._dav_get_obj_path(self._session.user, _rnd_folder, root_path="/uploads")
_dav_path = self._dav_get_obj_path(self._session.user, random_string(64), root_path="/uploads")
response = self._session.dav("MKCOL", _dav_path)
check_error(response.status_code)
try:
Expand Down
2 changes: 1 addition & 1 deletion nc_py_api/talk_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def _sign_send_request(self, method: str, url_suffix: str, data: dict, data_to_s

def get_bot_secret(callback_url: str) -> typing.Union[bytes, None]:
"""Returns the bot's secret from an environment variable or from the application's configuration on the server."""
sha_1 = hashlib.sha1()
sha_1 = hashlib.sha1(usedforsecurity=False)
string_to_hash = os.environ["APP_ID"] + "_" + callback_url
sha_1.update(string_to_hash.encode("UTF-8"))
secret_key = sha_1.hexdigest()
Expand Down
4 changes: 2 additions & 2 deletions nc_py_api/weather_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ def set_location(
) -> bool:
"""Sets the user's location on the Nextcloud server.

:param latitude: northsouth position of a point on the surface of the Earth.
:param longitude: eastwest position of a point on the surface of the Earth.
:param latitude: north-south position of a point on the surface of the Earth.
:param longitude: east-west position of a point on the surface of the Earth.
:param address: city, index(*optional*) and country, e.g. "Paris, 75007, France"
"""
require_capabilities("weather_status.enabled", self._session.capabilities)
Expand Down
8 changes: 4 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ preview = true
[tool.ruff]
line-length = 120
target-version = "py39"
select = ["A", "B", "C", "D", "E", "F", "G", "I", "UP", "SIM", "Q", "W"]
extend-ignore = ["D107", "D105", "D203", "D213", "D401", "I001"]
select = ["A", "B", "C", "D", "E", "F", "G", "I", "S", "SIM", "Q", "RET", "RUF", "UP" , "W"]
extend-ignore = ["D107", "D105", "D203", "D213", "D401", "I001", "RUF100"]

[tool.ruff.per-file-ignores]
"nc_py_api/__init__.py" = ["F401"]
Expand All @@ -114,8 +114,8 @@ extend-ignore = ["D107", "D105", "D203", "D213", "D401", "I001"]
[tool.ruff.extend-per-file-ignores]
"benchmarks/**/*.py" = ["D"]
"docs/**/*.py" = ["D"]
"examples/**/*.py" = ["D"]
"tests/**/*.py" = ["D", "E402", "UP"]
"examples/**/*.py" = ["D", "S106"]
"tests/**/*.py" = ["D", "E402", "S", "UP"]

[tool.ruff.mccabe]
max-complexity = 16
Expand Down
2 changes: 1 addition & 1 deletion tests/actual_tests/files_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def test_list_user_root_self_exclude(nc):
user_root = nc.files.listdir()
user_root_with_self = nc.files.listdir(exclude_self=False)
assert len(user_root_with_self) == 1 + len(user_root)
self_res = [i for i in user_root_with_self if not i.user_path][0]
self_res = next(i for i in user_root_with_self if not i.user_path)
for i in user_root:
assert self_res != i
assert self_res.has_extra
Expand Down
24 changes: 16 additions & 8 deletions tests/actual_tests/talk_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,11 @@ def test_get_conversations_include_status(nc, nc_client):
try:
conversations = nc.talk.get_user_conversations(include_status=False)
assert conversations
first_conv = [i for i in conversations if i.conversation_id == conversation.conversation_id][0]
first_conv = next(i for i in conversations if i.conversation_id == conversation.conversation_id)
assert not first_conv.status_type
conversations = nc.talk.get_user_conversations(include_status=True)
assert conversations
first_conv = [i for i in conversations if i.conversation_id == conversation.conversation_id][0]
first_conv = next(i for i in conversations if i.conversation_id == conversation.conversation_id)
assert first_conv.status_type == "away"
finally:
nc.talk.leave_conversation(conversation.token)
Expand Down Expand Up @@ -194,7 +194,7 @@ def test_list_bots(nc, nc_app):
if nc_app.talk.bots_available is False:
pytest.skip("Need Talk bots support")
nc_app.register_talk_bot("/some_url", "some bot name", "some desc")
registered_bot = [i for i in nc.talk.list_bots() if i.bot_name == "some bot name"][0]
registered_bot = next(i for i in nc.talk.list_bots() if i.bot_name == "some bot name")
assert isinstance(registered_bot.bot_id, int)
assert registered_bot.url.find("/some_url") != -1
assert registered_bot.description == "some desc"
Expand All @@ -218,11 +218,15 @@ def test_chat_bot_receive_message(nc_app):
talk_bot_inst.enabled_handler(True, nc_app)
conversation = nc_app.talk.create_conversation(talk.ConversationType.GROUP, "admin")
try:
coverage_bot = [i for i in nc_app.talk.list_bots() if i.url.endswith("/talk_bot_coverage")][0]
c_bot_info = [i for i in nc_app.talk.conversation_list_bots(conversation) if i.bot_id == coverage_bot.bot_id][0]
coverage_bot = next(i for i in nc_app.talk.list_bots() if i.url.endswith("/talk_bot_coverage"))
c_bot_info = next(
i for i in nc_app.talk.conversation_list_bots(conversation) if i.bot_id == coverage_bot.bot_id
)
assert c_bot_info.state == 0
nc_app.talk.enable_bot(conversation, coverage_bot)
c_bot_info = [i for i in nc_app.talk.conversation_list_bots(conversation) if i.bot_id == coverage_bot.bot_id][0]
c_bot_info = next(
i for i in nc_app.talk.conversation_list_bots(conversation) if i.bot_id == coverage_bot.bot_id
)
assert c_bot_info.state == 1
with pytest.raises(ValueError):
nc_app.talk.send_message("Here are the msg!")
Expand All @@ -234,10 +238,14 @@ def test_chat_bot_receive_message(nc_app):
msg_from_bot = messages[-1]
break
assert msg_from_bot
c_bot_info = [i for i in nc_app.talk.conversation_list_bots(conversation) if i.bot_id == coverage_bot.bot_id][0]
c_bot_info = next(
i for i in nc_app.talk.conversation_list_bots(conversation) if i.bot_id == coverage_bot.bot_id
)
assert c_bot_info.state == 1
nc_app.talk.disable_bot(conversation, coverage_bot)
c_bot_info = [i for i in nc_app.talk.conversation_list_bots(conversation) if i.bot_id == coverage_bot.bot_id][0]
c_bot_info = next(
i for i in nc_app.talk.conversation_list_bots(conversation) if i.bot_id == coverage_bot.bot_id
)
assert c_bot_info.state == 0
finally:
nc_app.talk.delete_conversation(conversation.token)
Expand Down