mirror of
https://github.com/davidhalter/typeshed.git
synced 2026-05-04 12:35:49 +08:00
[vobject] Improve stubs (#14299)
This commit is contained in:
@@ -9,8 +9,6 @@ vobject.win32tz
|
||||
# python2 compat
|
||||
vobject.base.basestring
|
||||
vobject.base.str_
|
||||
vobject.base.to_unicode
|
||||
vobject.base.to_basestring
|
||||
vobject.base.unicode_type
|
||||
|
||||
# implementation details that users shouldn't depend on
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from .base import VERSION as VERSION, Component
|
||||
|
||||
__version__ = VERSION
|
||||
from . import icalendar as icalendar, vcard as vcard
|
||||
from .base import VERSION as VERSION, Component, readComponents as readComponents, readOne as readOne
|
||||
|
||||
def iCalendar() -> Component: ...
|
||||
def vCard() -> Component: ...
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
import logging
|
||||
from _typeshed import Incomplete, SupportsWrite
|
||||
from collections.abc import Iterable, Iterator
|
||||
from typing import Any, Final, Literal, TypeVar, overload
|
||||
import re
|
||||
from _typeshed import Incomplete, MaybeNone, SupportsWrite
|
||||
from collections.abc import Generator, Iterator
|
||||
from typing import Any, AnyStr, Final, Literal, TypeVar, overload
|
||||
from typing_extensions import Self
|
||||
|
||||
_V = TypeVar("_V", bound=VBase)
|
||||
_W = TypeVar("_W", bound=SupportsWrite[bytes])
|
||||
|
||||
VERSION: Final[str]
|
||||
|
||||
def to_unicode(value: str | bytes | bytearray) -> str: ...
|
||||
def to_basestring(s: str | bytes) -> bytes: ...
|
||||
|
||||
logger: logging.Logger
|
||||
DEBUG: bool
|
||||
CR: str
|
||||
@@ -15,8 +22,6 @@ SPACE: str
|
||||
TAB: str
|
||||
SPACEORTAB: str
|
||||
|
||||
VERSION: Final[str]
|
||||
|
||||
class VBase:
|
||||
group: Incomplete | None
|
||||
behavior: Incomplete | None
|
||||
@@ -41,44 +46,53 @@ class VBase:
|
||||
@overload
|
||||
def serialize(self, buf: _W, lineLength: int = 75, validate: bool = True, behavior=None, *args: Any, **kwargs: Any) -> _W: ...
|
||||
|
||||
def toVName(name, stripNum: int = 0, upper: bool = False): ...
|
||||
def toVName(name: str, stripNum: int = 0, upper: bool = False) -> str: ...
|
||||
|
||||
class ContentLine(VBase):
|
||||
name: Incomplete
|
||||
encoded: Incomplete
|
||||
params: Incomplete
|
||||
singletonparams: Incomplete
|
||||
isNative: Incomplete
|
||||
lineNumber: Incomplete
|
||||
value: Incomplete
|
||||
name: str
|
||||
encoded: bool
|
||||
params: dict[Incomplete, list[Incomplete]]
|
||||
singletonparams: list[Incomplete]
|
||||
isNative: bool
|
||||
lineNumber: int | None
|
||||
value: str
|
||||
def __init__(
|
||||
self, name, params, value, group=None, encoded: bool = False, isNative: bool = False, lineNumber=None, *args, **kwds
|
||||
self,
|
||||
name: str,
|
||||
params: dict[Incomplete, list[Incomplete]],
|
||||
value: str,
|
||||
group=None,
|
||||
encoded: bool = False,
|
||||
isNative: bool = False,
|
||||
lineNumber: int | None = None,
|
||||
*args,
|
||||
**kwds,
|
||||
) -> None: ...
|
||||
@classmethod
|
||||
def duplicate(cls, copyit): ...
|
||||
def duplicate(cls, copyit) -> Self: ...
|
||||
def copy(self, copyit) -> None: ...
|
||||
def __eq__(self, other): ...
|
||||
def __getattr__(self, name: str): ...
|
||||
def __setattr__(self, name: str, value) -> None: ...
|
||||
def __delattr__(self, name: str) -> None: ...
|
||||
def valueRepr(self): ...
|
||||
def valueRepr(self) -> str: ...
|
||||
def __unicode__(self) -> str: ...
|
||||
def prettyPrint(self, level: int = 0, tabwidth: int = 3) -> None: ...
|
||||
|
||||
class Component(VBase):
|
||||
contents: dict[str, list[VBase]]
|
||||
name: Incomplete
|
||||
name: str
|
||||
useBegin: bool
|
||||
def __init__(self, name=None, *args, **kwds) -> None: ...
|
||||
def __init__(self, name: str | None = None, *args, **kwds) -> None: ...
|
||||
@classmethod
|
||||
def duplicate(cls, copyit): ...
|
||||
def duplicate(cls, copyit) -> Self: ...
|
||||
def copy(self, copyit) -> None: ...
|
||||
def setProfile(self, name) -> None: ...
|
||||
def setProfile(self, name: str) -> None: ...
|
||||
def __getattr__(self, name: str): ...
|
||||
normal_attributes: Incomplete
|
||||
normal_attributes: list[str]
|
||||
def __setattr__(self, name: str, value) -> None: ...
|
||||
def __delattr__(self, name: str) -> None: ...
|
||||
def getChildValue(self, childName, default=None, childNumber: int = 0): ...
|
||||
def getChildValue(self, childName: str, default=None, childNumber: int = 0): ...
|
||||
@overload
|
||||
def add(self, objOrName: _V, group: str | None = None) -> _V: ...
|
||||
@overload
|
||||
@@ -91,45 +105,47 @@ class Component(VBase):
|
||||
def add(self, objOrName: str, group: str | None = None) -> Any: ... # returns VBase sub-class
|
||||
def remove(self, obj) -> None: ...
|
||||
def getChildren(self) -> list[Incomplete]: ...
|
||||
def components(self) -> Iterable[Component]: ...
|
||||
def lines(self): ...
|
||||
def sortChildKeys(self): ...
|
||||
def getSortedChildren(self): ...
|
||||
def components(self) -> Generator[Component]: ...
|
||||
def lines(self) -> Generator[ContentLine]: ...
|
||||
def sortChildKeys(self) -> list[Incomplete]: ...
|
||||
def getSortedChildren(self) -> list[Incomplete]: ...
|
||||
def setBehaviorFromVersionLine(self, versionLine) -> None: ...
|
||||
def transformChildrenToNative(self) -> None: ...
|
||||
def transformChildrenFromNative(self, clearBehavior: bool = True) -> None: ...
|
||||
def prettyPrint(self, level: int = 0, tabwidth: int = 3) -> None: ...
|
||||
|
||||
class VObjectError(Exception):
|
||||
msg: Incomplete
|
||||
lineNumber: Incomplete
|
||||
def __init__(self, msg, lineNumber=None) -> None: ...
|
||||
msg: str
|
||||
lineNumber: int
|
||||
def __init__(self, msg: str, lineNumber: int | None = None) -> None: ...
|
||||
|
||||
class ParseError(VObjectError): ...
|
||||
class ValidateError(VObjectError): ...
|
||||
class NativeError(VObjectError): ...
|
||||
|
||||
patterns: Incomplete
|
||||
param_values_re: Incomplete
|
||||
params_re: Incomplete
|
||||
line_re: Incomplete
|
||||
begin_re: Incomplete
|
||||
patterns: dict[str, str]
|
||||
param_values_re: re.Pattern[str]
|
||||
params_re: re.Pattern[str]
|
||||
line_re: re.Pattern[str]
|
||||
begin_re: re.Pattern[str]
|
||||
|
||||
def parseParams(string): ...
|
||||
def parseLine(line, lineNumber=None): ...
|
||||
def parseParams(string: str) -> list[list[Any]]: ... # Any was taken from re module stubs
|
||||
def parseLine(
|
||||
line: str, lineNumber: int | None = None
|
||||
) -> tuple[str, list[list[Any]], str | MaybeNone, str | MaybeNone]: ... # Any is result of parseParams()
|
||||
|
||||
wrap_re: Incomplete
|
||||
logical_lines_re: Incomplete
|
||||
wrap_re: re.Pattern[str]
|
||||
logical_lines_re: re.Pattern[str]
|
||||
testLines: str
|
||||
|
||||
def getLogicalLines(fp, allowQP: bool = True) -> None: ...
|
||||
def textLineToContentLine(text, n=None): ...
|
||||
def dquoteEscape(param): ...
|
||||
def foldOneLine(outbuf, input, lineLength: int = 75) -> None: ...
|
||||
def defaultSerialize(obj, buf, lineLength): ...
|
||||
def getLogicalLines(fp, allowQP: bool = True) -> Generator[tuple[str, int]]: ...
|
||||
def textLineToContentLine(text, n: int | None = None) -> ContentLine: ...
|
||||
def dquoteEscape(param: str) -> str: ...
|
||||
def foldOneLine(outbuf: SupportsWrite[AnyStr], input: AnyStr, lineLength: int = 75) -> None: ...
|
||||
def defaultSerialize(obj: Component | ContentLine, buf, lineLength: int): ...
|
||||
|
||||
class Stack:
|
||||
stack: Incomplete
|
||||
stack: list[Incomplete]
|
||||
def __len__(self) -> int: ...
|
||||
def top(self): ...
|
||||
def topName(self): ...
|
||||
@@ -141,7 +157,7 @@ def readComponents(
|
||||
streamOrString, validate: bool = False, transform: bool = True, ignoreUnreadable: bool = False, allowQP: bool = False
|
||||
) -> Iterator[Component]: ...
|
||||
def readOne(stream, validate: bool = False, transform: bool = True, ignoreUnreadable: bool = False, allowQP: bool = False): ...
|
||||
def registerBehavior(behavior, name=None, default: bool = False, id=None) -> None: ...
|
||||
def getBehavior(name, id=None): ...
|
||||
def newFromBehavior(name, id=None): ...
|
||||
def backslashEscape(s): ...
|
||||
def registerBehavior(behavior, name: str | None = None, default: bool = False, id=None) -> None: ...
|
||||
def getBehavior(name: str, id=None): ...
|
||||
def newFromBehavior(name: str, id=None) -> Component | ContentLine: ...
|
||||
def backslashEscape(s: str) -> str: ...
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
import datetime
|
||||
import optparse
|
||||
from collections.abc import Sequence
|
||||
from typing import Final, Literal
|
||||
|
||||
def change_tz(cal, new_timezone, default, utc_only: bool = False, utc_tz=...) -> None: ...
|
||||
from .base import Component
|
||||
|
||||
version: Final[str]
|
||||
|
||||
def change_tz(
|
||||
cal: Component,
|
||||
new_timezone: datetime._TzInfo | None,
|
||||
default: datetime._TzInfo | None,
|
||||
utc_only: bool = False,
|
||||
utc_tz: datetime._TzInfo | None = ...,
|
||||
) -> None: ...
|
||||
def show_timezones() -> None: ...
|
||||
def convert_events(utc_only: bool, args: Sequence[str]) -> None: ...
|
||||
def main() -> None: ...
|
||||
|
||||
version: str
|
||||
|
||||
def get_options(): ...
|
||||
def get_options() -> tuple[optparse.Values, Literal[False]] | tuple[optparse.Values, list[str]]: ...
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import datetime
|
||||
from _typeshed import Incomplete
|
||||
from datetime import timedelta
|
||||
from typing import Any, Final
|
||||
from collections.abc import Iterable
|
||||
from datetime import timedelta, tzinfo
|
||||
from typing import Final, Literal, overload
|
||||
|
||||
from .base import Component
|
||||
from .behavior import Behavior
|
||||
@@ -15,11 +16,14 @@ FREQUENCIES: Final[tuple[str, ...]]
|
||||
ZERO_DELTA: Final[timedelta]
|
||||
twoHours: Final[timedelta]
|
||||
|
||||
@overload
|
||||
def toUnicode(s: None) -> None: ...
|
||||
@overload
|
||||
def toUnicode(s: str | bytes) -> str: ...
|
||||
def registerTzid(tzid, tzinfo) -> None: ...
|
||||
def getTzid(tzid, smart: bool = True): ...
|
||||
def registerTzid(tzid: str | bytes, tzinfo) -> None: ...
|
||||
def getTzid(tzid: str, smart: bool = True): ...
|
||||
|
||||
utc: Any # dateutil.tz.tz.tzutc
|
||||
utc: tzinfo # dateutil.tz.tz.tzutc (subclass of tzinfo)
|
||||
|
||||
class TimezoneComponent(Component):
|
||||
isNative: bool
|
||||
@@ -29,16 +33,16 @@ class TimezoneComponent(Component):
|
||||
useBegin: bool
|
||||
def __init__(self, tzinfo=None, *args, **kwds) -> None: ...
|
||||
@classmethod
|
||||
def registerTzinfo(cls, tzinfo): ...
|
||||
def registerTzinfo(cls, tzinfo) -> str | None: ...
|
||||
def gettzinfo(self): ...
|
||||
tzid: Incomplete
|
||||
daylight: Incomplete
|
||||
standard: Incomplete
|
||||
def settzinfo(self, tzinfo, start: int = 2000, end: int = 2030): ...
|
||||
def settzinfo(self, tzinfo, start: int = 2000, end: int = 2030) -> None: ...
|
||||
normal_attributes: Incomplete
|
||||
@staticmethod
|
||||
def pickTzid(tzinfo, allowUTC: bool = False): ...
|
||||
def prettyPrint(self, level, tabwidth) -> None: ... # type: ignore[override]
|
||||
def pickTzid(tzinfo, allowUTC: bool = False) -> str | None: ...
|
||||
def prettyPrint(self, level: int, tabwidth: int) -> None: ... # type: ignore[override]
|
||||
|
||||
class RecurringComponent(Component):
|
||||
isNative: bool
|
||||
@@ -203,26 +207,30 @@ class FreeBusy(PeriodBehavior):
|
||||
|
||||
class RRule(Behavior): ...
|
||||
|
||||
utcDateTimeList: Incomplete
|
||||
dateTimeOrDateList: Incomplete
|
||||
textList: Incomplete
|
||||
utcDateTimeList: list[str]
|
||||
dateTimeOrDateList: list[str]
|
||||
textList: list[str]
|
||||
|
||||
def numToDigits(num, places): ...
|
||||
def timedeltaToString(delta): ...
|
||||
def timeToString(dateOrDateTime): ...
|
||||
def dateToString(date): ...
|
||||
def dateTimeToString(dateTime, convertToUTC: bool = False): ...
|
||||
def deltaToOffset(delta): ...
|
||||
def numToDigits(num: float | None, places: int) -> str: ...
|
||||
def timedeltaToString(delta: datetime.timedelta) -> str: ...
|
||||
def timeToString(dateOrDateTime: datetime.date | datetime.datetime) -> str: ...
|
||||
def dateToString(date: datetime.date) -> str: ...
|
||||
def dateTimeToString(dateTime: datetime.datetime, convertToUTC: bool = False) -> str: ...
|
||||
def deltaToOffset(delta: datetime.timedelta) -> str: ...
|
||||
def periodToString(period, convertToUTC: bool = False): ...
|
||||
def isDuration(s): ...
|
||||
def stringToDate(s): ...
|
||||
def stringToDateTime(s, tzinfo: datetime.tzinfo | None = None, strict: bool = False) -> datetime.datetime: ...
|
||||
def isDuration(s: str) -> bool: ...
|
||||
def stringToDate(s: str) -> datetime.date: ...
|
||||
def stringToDateTime(s: str, tzinfo: datetime._TzInfo | None = None, strict: bool = False) -> datetime.datetime: ...
|
||||
|
||||
escapableCharList: str
|
||||
|
||||
def stringToTextValues(s, listSeparator: str = ",", charList=None, strict: bool = False): ...
|
||||
def stringToDurations(s, strict: bool = False): ...
|
||||
def stringToTextValues(
|
||||
s: str, listSeparator: str = ",", charList: Iterable[str] | None = None, strict: bool = False
|
||||
) -> list[str]: ...
|
||||
def stringToDurations(s: str, strict: bool = False) -> list[datetime.timedelta]: ...
|
||||
def parseDtstart(contentline, allowSignatureMismatch: bool = False): ...
|
||||
def stringToPeriod(s, tzinfo=None): ...
|
||||
def getTransition(transitionTo, year, tzinfo): ...
|
||||
def tzinfo_eq(tzinfo1, tzinfo2, startYear: int = 2000, endYear: int = 2020): ...
|
||||
def stringToPeriod(s: str, tzinfo=None): ...
|
||||
def getTransition(transitionTo: Literal["daylight", "standard"], year: int, tzinfo: datetime._TzInfo): ...
|
||||
def tzinfo_eq(
|
||||
tzinfo1: datetime._TzInfo | None, tzinfo2: datetime._TzInfo | None, startYear: int = 2000, endYear: int = 2020
|
||||
) -> bool: ...
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
def getSortKey(component): ...
|
||||
def sortByUID(components): ...
|
||||
def deleteExtraneous(component, ignore_dtstamp: bool = False) -> None: ...
|
||||
import optparse
|
||||
from collections.abc import Iterable
|
||||
from typing import Literal
|
||||
|
||||
from .base import Component
|
||||
|
||||
def getSortKey(component: Component) -> str: ...
|
||||
def sortByUID(components: Iterable[Component]) -> list[Component]: ...
|
||||
def deleteExtraneous(component: Component, ignore_dtstamp: bool = False) -> None: ...
|
||||
def diff(left, right): ...
|
||||
def prettyDiff(leftObj, rightObj) -> None: ...
|
||||
def main() -> None: ...
|
||||
def getOptions(): ...
|
||||
def getOptions() -> tuple[Literal[False], Literal[False]] | tuple[optparse.Values, list[str]]: ...
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
from _typeshed import Incomplete
|
||||
from typing import AnyStr
|
||||
|
||||
from .base import ContentLine
|
||||
from .behavior import Behavior
|
||||
|
||||
class Name:
|
||||
family: Incomplete
|
||||
given: Incomplete
|
||||
additional: Incomplete
|
||||
prefix: Incomplete
|
||||
suffix: Incomplete
|
||||
family: str | list[str]
|
||||
given: str | list[str]
|
||||
additional: str | list[str]
|
||||
prefix: str | list[str]
|
||||
suffix: str | list[str]
|
||||
def __init__(
|
||||
self,
|
||||
family: str | list[str] = "",
|
||||
@@ -17,17 +18,17 @@ class Name:
|
||||
suffix: str | list[str] = "",
|
||||
) -> None: ...
|
||||
@staticmethod
|
||||
def toString(val): ...
|
||||
def __eq__(self, other): ...
|
||||
def toString(val: str | list[str] | tuple[str, ...]) -> str: ...
|
||||
def __eq__(self, other: object) -> bool: ...
|
||||
|
||||
class Address:
|
||||
box: Incomplete
|
||||
extended: Incomplete
|
||||
street: Incomplete
|
||||
city: Incomplete
|
||||
region: Incomplete
|
||||
code: Incomplete
|
||||
country: Incomplete
|
||||
box: str | list[str]
|
||||
extended: str | list[str]
|
||||
street: str | list[str]
|
||||
city: str | list[str]
|
||||
region: str | list[str]
|
||||
code: str | list[str]
|
||||
country: str | list[str]
|
||||
def __init__(
|
||||
self,
|
||||
street: str | list[str] = "",
|
||||
@@ -39,29 +40,29 @@ class Address:
|
||||
extended: str | list[str] = "",
|
||||
) -> None: ...
|
||||
@staticmethod
|
||||
def toString(val, join_char: str = "\n"): ...
|
||||
lines: Incomplete
|
||||
one_line: Incomplete
|
||||
def __eq__(self, other): ...
|
||||
def toString(val: str | list[str] | tuple[str, ...], join_char: str = "\n") -> str: ...
|
||||
lines: tuple[str, ...]
|
||||
one_line: tuple[str, ...]
|
||||
def __eq__(self, other: object) -> bool: ...
|
||||
|
||||
class VCardTextBehavior(Behavior):
|
||||
allowGroup: bool
|
||||
base64string: str
|
||||
@classmethod
|
||||
def decode(cls, line) -> None: ...
|
||||
def decode(cls, line: ContentLine) -> None: ...
|
||||
@classmethod
|
||||
def encode(cls, line) -> None: ...
|
||||
def encode(cls, line: ContentLine) -> None: ...
|
||||
|
||||
class VCardBehavior(Behavior):
|
||||
allowGroup: bool
|
||||
defaultBehavior: Incomplete
|
||||
defaultBehavior: type[VCardTextBehavior]
|
||||
|
||||
class VCard3_0(VCardBehavior):
|
||||
name: str
|
||||
description: str
|
||||
versionString: str
|
||||
isComponent: bool
|
||||
sortFirst: Incomplete
|
||||
sortFirst: tuple[str, ...]
|
||||
@classmethod
|
||||
def generateImplicitParameters(cls, obj) -> None: ...
|
||||
|
||||
@@ -82,17 +83,17 @@ class Photo(VCardTextBehavior):
|
||||
name: str
|
||||
description: str
|
||||
@classmethod
|
||||
def valueRepr(cls, line): ...
|
||||
def valueRepr(cls, line: ContentLine) -> str: ...
|
||||
@classmethod
|
||||
def serialize(cls, obj, buf, lineLength, validate, *args, **kwargs) -> None: ... # type: ignore[override]
|
||||
|
||||
def toListOrString(string): ...
|
||||
def splitFields(string): ...
|
||||
def toList(stringOrList): ...
|
||||
def toListOrString(string: str) -> str | list[str]: ...
|
||||
def splitFields(string: str) -> list[str | list[str]]: ...
|
||||
def toList(stringOrList: AnyStr | list[AnyStr]) -> list[AnyStr]: ...
|
||||
def serializeFields(obj, order=None): ...
|
||||
|
||||
NAME_ORDER: Incomplete
|
||||
ADDRESS_ORDER: Incomplete
|
||||
NAME_ORDER: tuple[str, ...]
|
||||
ADDRESS_ORDER: tuple[str, ...]
|
||||
|
||||
class NameBehavior(VCardBehavior):
|
||||
hasNative: bool
|
||||
|
||||
@@ -1,23 +1,27 @@
|
||||
import datetime
|
||||
import sys
|
||||
import winreg
|
||||
from _typeshed import Incomplete
|
||||
from typing import Any, SupportsIndex
|
||||
|
||||
if sys.platform == "win32":
|
||||
handle: Incomplete
|
||||
tzparent: Incomplete
|
||||
parentsize: Incomplete
|
||||
localkey: Incomplete
|
||||
WEEKS: Incomplete
|
||||
def list_timezones(): ...
|
||||
handle: winreg.HKEYType
|
||||
tzparent: winreg.HKEYType
|
||||
parentsize: int
|
||||
localkey: winreg.HKEYType
|
||||
WEEKS: datetime.timedelta
|
||||
def list_timezones() -> list[str]: ...
|
||||
|
||||
class win32tz(datetime.tzinfo):
|
||||
data: Incomplete
|
||||
def __init__(self, name) -> None: ...
|
||||
def utcoffset(self, dt): ...
|
||||
def dst(self, dt): ...
|
||||
def tzname(self, dt): ...
|
||||
data: win32tz_data
|
||||
def __init__(self, name: str | None) -> None: ...
|
||||
def utcoffset(self, dt: datetime.datetime) -> datetime.timedelta: ... # type: ignore[override]
|
||||
def dst(self, dt: datetime.datetime) -> datetime.timedelta: ... # type: ignore[override]
|
||||
def tzname(self, dt: datetime.datetime) -> str | None: ... # type: ignore[override]
|
||||
|
||||
def pickNthWeekday(year, month, dayofweek, hour, minute, whichweek): ...
|
||||
def pickNthWeekday(
|
||||
year: SupportsIndex, month: SupportsIndex, dayofweek: int, hour: SupportsIndex, minute: SupportsIndex, whichweek: int
|
||||
) -> datetime.datetime | None: ...
|
||||
|
||||
class win32tz_data:
|
||||
display: Incomplete
|
||||
@@ -35,6 +39,6 @@ if sys.platform == "win32":
|
||||
dstweeknumber: Incomplete
|
||||
dsthour: Incomplete
|
||||
dstminute: Incomplete
|
||||
def __init__(self, path) -> None: ...
|
||||
def __init__(self, path: str | None) -> None: ...
|
||||
|
||||
def valuesToDict(key): ...
|
||||
def valuesToDict(key: winreg._KeyType) -> dict[str, Any]: ...
|
||||
|
||||
Reference in New Issue
Block a user