updated: 2025-12-05T17:41:33.976811096-08:00[America/Los_Angeles]
README
ry
A growing collection of Python shims around Rust crates; fast, async-first, and ergonomic.
DOCS: ryo3.dev (WIP)
API: ryo3.dev/api
This is a work in progress ~ feedback and PRs are welcome.
Highlights
- Async-first HTTP client: Built on
reqwest, with afetch-like API. Supports streaming, zero-copy IO via the buffer protocol, timeouts, redirect-following, and native JSON parsing viajiter. - Async file I/O: Built on
tokio, with anAsyncFileAPI similar toaiofilesandanyio’s async-file api. Supports buffered reads/writes, truncation, streaming reads, andanyiocompatibility. - (de)compression: (de)compression tools for
zstd,brotli,gzip, andbzip2. - Datetime utilities via
jiff: Fast, accurate, timezone-aware datetime parsing and formatting, withdatetimeinterop and much more - Miscellaneous bindings: Includes crates like
globset,walkdir,sqlformat,unindent,twox-hash, and more. - Designed for ergonomics: Async where it matters. Simple where possible. Python-native behavior with minimal friction.
- Type Annotated: All public APIs are (painstakingly) type annotated.
- Performant: Speed without the words “blazingly fast.” 1
Install
pip install ry
uv add ry
# check install
python -m ry
Quickstart
Check out the examples directory for some quickstart examples.
What?
ry– the python packageryo3-*– the rust crates that are used byryand possibly your ownpyo3-based python package
Who?
- jessekrubin jessekrubin@gmail.com
- possibly you!?
FAQ
(aka: questions that I have been asking myself)
- Q: Why?
- A: I (jesse) needed several hashing functions for python and then kept adding things as I needed them
- Q: Does this have anything to do with the (excellent) package manager
rye?- A: short answer: no. long answer: no, it does not.
- Q: Why is the repo split into
ryandryo3?- A:
ryis the python package,ryo3is a rust crate setup to let you “register” functions you may want if you were writing your own pyo3-python bindings library; maybe someday theryo3::libsmodule will be split up into separate packages
- A:
Crate bindings
| crate | ryo3-crate |
|---|---|
std | ryo3-std |
bytes | ryo3-bytes |
bzip2 | ryo3-bzip2 |
dirs | ryo3-dirs |
glob | ryo3-glob |
heck | ryo3-heck |
http | ryo3-http |
jiter | ryo3-jiter |
reqwest | ryo3-reqwest |
serde | ryo3-serde |
shlex | ryo3-shlex |
size | ryo3-size |
sqlformat | ryo3-sqlformat |
tokio | ryo3-tokio |
ulid | ryo3-ulid |
unindent | ryo3-unindent |
url | ryo3-url |
uuid | ryo3-uuid |
which | ryo3-which |
| Compression | ~ |
brotli | ryo3-brotli |
flate2 | ryo3-flate2 |
zstd | ryo3-zstd |
| Hashing | ~ |
fnv | ryo3-fnv |
twox-hash | ryo3-twox-hash |
| @BurntSushi | ~ |
globset | ryo3-globset |
jiff | ryo3-jiff |
memchr | ryo3-memchr |
regex | ryo3-regex |
same-file | ryo3-same-file |
walkdir | ryo3-walkdir |
DEV
justis used to run tasks- Do not use the phrase
blazing fastor any emojis in any PRs or issues or docs - type annotations are required
ruffused for formatting and linting
SEE ALSO
- utiles: web-map tile utils
-
Release‑version benchmarks of
ry(viapytest-benchmark) showed no real performance variance, regardless of whether “blazingly fast” appeared in the README or docs. ↩
DEVELOPMENT
goals
- Provide a really nice ergonomic API to work with (this is the highest priority)
- Get naming right (this is a hard one!)
- Be fast
development-setup
- clone repo
- install
just(cargo install just) - create a virtual env (using ye olde
venvoruvor dare I sayconda) – I am still working out the kinks of usinguvwith maturin - install the dev-requirements (
pip install -r requirements.dev.txt) - run
just devto build and test the library - run
just fmtto format the python and rust code
style guide
- Naming conventions:
- For python classes/structs/types prefer
AsyncXYZoverXYZAsync - use
snake_casefor functions and variables - use
CamelCasefor types and traits - use
SCREAMING_SNAKE_CASEfor constants and static-class-attributes
- For python classes/structs/types prefer
- NO UNWRAPPING – use
expectoverunwrap - NO PANICS – don’t panic!
- NO
blazingly-fast–ryis fast and does not need an adverb - USE CLIPPY
just clippyorjust ci - USE RUSTFMT AND RUFF
just fmt - library style guide:
- python objects/structs/classes defined in the library should be named either
Py<CLASSNAME>orRy<CLASSNAME>and the prefix should be consistent throughout the library (egryo3-jiffusesRyas the internal prefix to not conflict with thePy<CLASSNAME>structs provided bypyo3) - For wrapper libraries, attempt to mirror the structure of the original library as much as possible
- wrapper library names should be of the form
ryo3-<LIB_NAME>where<LIB_NAME>is the name of the wrapped library - library directories should be
kebab-caseand should beryo3-<LIB_NAME>
- python objects/structs/classes defined in the library should be named either
Creating a new library/wrapper-thing
- copy the template library
ryo3-quick-mathslibrary to your new library name - refer to the above style guide for naming conventions
tools
python
- we use
maturinfor building the python wheels - we support
python-3.11+ - we use
pytestfor testing as well as the following plugins:anyio(which I am increasingly thinking is actually a bit of a turd)hypothesispytest-benchmarkpytest-cov
just
cargo install just
- we use
justfor task running - to see all tasks run
justorjust --list(our default task echos the list of tasks)
tasks as of 2025-09-26:
Available recipes:
repl # run ry.dev python repl
repl-uv # run ry.dev python repl (if using uv)
dev # dev run build + tests
dev-uv # dev run build + tests (with uv)
sync # uv sync
develop # maturin develop
develop-uv # maturin develop (with uv)
mat # maturin develop (shorthand)
cargo-test # cargo test
build # build
build-release # build release
dev-rel # maturin develop release
doctest # run pytest
pytest # run pytest
pytest-uv # run pytest
pytestv # run pytest (printing captured output)
test # run all test
test-release # test ry package
bench # benchmark ry python package
ci # ci rust checks
cargo-fmt # cargo format
cargo-fmtc # cargo format check
sort-all-check # ruff check sorting of '__all__'
sort-all # ruff sort '__all__'
ruff-fmt # ruff format
ruff-fmtc # ruff format check
fmtpy # python format
fmtcpy # python format check
justfilefmt # justfile format
justfilefmtc # justfile format check
mdfmt # format markdown
pyprojectfmt # pyproject-fmt
fmt # format
fmtc # format check
ruff # run ruff linter
ruffix # run ruff + fix
clippy # run clippy
clippy-features # run clippy with feature-powerset via cargo-hack
lint # lint python and rust
mypy # run mypy type checker
pyright # run pyright
pip-compile # pip compile requirements
gen # generate code tasks
cargo-doc # generate cargo docs for all crates (in workspace)
ACKNOWLEDGEMENTS
This project would not be possible without the incredible work of many others.
THANK YOU
- pyo3 developers (a.k.a. @davidhewitt, et al.)
- All authors and maintainers of the countless libraries this project builds upon
- Andrew Gallant (@BurntSushi) for the
exceptional ecosystem of rust libraries wrapped here (
jiff,globset,memchr,walkdir, andsame-file) and for patiently answering my many random questions - Kyle Barron (@kylebarron) for his work on
pyo3-bytesand letting me contribute - Dan Costello (@dan-costello), Charlie Imhoff (@cpimhoff) and Josh Coats (@rhwlo) for entertaining my endless naming-convention and style related questions/debates
- The Academy and the Hollywood Foreign Press
If you want to be added to this list, please open an issue or PR! Happy to add you if you’ve helped in any way!
ry-dist-archives
TLDR: If you are using an older version of ry and it is not longer on PyPI,
you can find it either on primary ry-repo’s
releases page, or in the
ry-dist-archives
repository.
PyPI imposes a 10 GB limit on the total size of all files in a given project.
Once that limit is reached, you must either delete old files or request a size
increase. As of now (2025-07-22T08:34:51.3412157-07:00[America/Los_Angeles]),
the ry package is still very much in beta, and I (jesse) am not going to
request a size increase while the project remains pre-0.1.0.
ry builds are performed with github cicd, and published builds for versions
0.44.0 are uploaded to github
releases, but publishing
releases was not previously a part of the cicd workflow.
The script for downloading wheels is located at
ry-dist-archives/scripts/dl_versions.py.
It serves as a good example of how to use ry’s HTTP client, JSON parsing and
dumping, and async file I/O tools.
CHANGELOG
v0.0.72 [unreleased]
- RENAMES:
ry.URL.replace_*->ry.URL.with_*: thereplace_*methods are deprecated in favor ofwith_*methods. Thery.URL.replacestill exists as a way to replace multiple parts at once.ry.aiopen->ry.aopen: it was supposed to be “asyncio-open”, but it could be easily confused with “artificial-intellegence-open”/“llm-open”ryo3-fnvFnvHasher->fnv1afnv1afunction removed as it was just a stupid proxy forfnv1aclass constructor
ryo3-jiff- use
PyMutexand get rid ofparking_lot::Mutexfor jiff series iterators
- use
v0.0.71 [2025-12-03]
ryo3-serde- crude string subclass support
ryo3-jiff- use
py_parseandpy_from_strfor jiff types so that str/bytes are alloweddef parse(cls, s: str | bytes) -> t.Self: - Fix pydantic paring problems caused by lazy copy-pasta-ing w/o using eyeballs to read what I had copy-pasta-ed
- use
v0.0.70 [2025-12-02] (30 is the new 70)
- type annotations
- Fixing type annotations and starting to use
stubtest
- Fixing type annotations and starting to use
ryo3-http- Bump version to 1.4.0 which adds
103 Early Hintsstatus code among other things
- Bump version to 1.4.0 which adds
ryo3-reqwest- Removed
clientkwarg fromfetchfunction as it is kinda stupid BlockingClientandBlockingResponsefor sync/blocking reqs… This makes theHttpClientname awkward and may rename it to justClient… TBD- added
fetch_syncfunction for blocking/sync http requests
- Removed
ryo3-jiffoffset_conflictanddisambiguationtype annotation fixescollect()methods for jiff series
v0.0.69 [2025-11-21]
- added
immutable_typeattr to pyclasses bc many of the things in this crate are practically primitives ryo3-fnv- Add
py.detachwhere it makes sense - Return python
builtins.bytesfrom digest notry.Bytes
- Add
ryo3-urlURL.hostproperty returnsNone | str | ry.Ipv4Addr | ry.Ipv6ddrifryo3-stdfeature enabled
ryo3-std- pydantic support for
ry.Ipv4Addr,ry.Ipv6addr, andry.Ipaddr
- pydantic support for
ryo3-brotli- Internal refactoring & type-annotation updates
ryo3-bzip2- Internal refactoring & type-annotation updates
ryo3-flate2- Internal refactoring & type-annotation updates
v0.0.68 [2025-11-14]
ryo3-glob- fix error on
take
- fix error on
ryo3-corePyMutexthat lets ya pick to throw or not via const generic (very fancy look at me)
ryo3-jiff- Update jiff to
0.2.16 - Add
ZonedSeries
- Update jiff to
ryo3-std- Use jiff for duration formatting
ry.Duration.secondsnow returns total seconds in durationry.Duration.seconds_remainderreturns seconds % days (self.seconds % 86400)- Remove
datetime.timedeltasupport forry.Duration.__richcmp__as there is not a one-2-uno direct mapping between timedeltas and durations (bc durations are unsigned) - pydantic support for
ry.Duration
ryo3-serde- Use jiff unsigned-duration serialization for
ry.Duration
- Use jiff unsigned-duration serialization for
v0.0.67 [2025-11-07]
ryo3-stdread_strasread_textalias
- fix musl builds
ryo3-url- pydantic support
v0.0.66 [2025-10-31]
- fix typos in python tests
- windows arm64 builds
- use
py.detachwhere beneficial:ryo3-brotliryo3-fspathryo3-same-fileryo3-stdryo3-walkdirryo3-which
ryo3-bytes- optimized extraction of
builtins.bytes,ry.Bytes
- optimized extraction of
ryo3-http- switch from
parking_lot::Mutextoparking_lot::RwLockforPyHeaders:wq
- switch from
- global-allocator
mimallocfeature added to usemimallocover the system allocator- added top level
__allocator__constant
v0.0.65 [2025-10-24]
ryo3-reqwest- Manually implement
ClientConfig::defaultas global fetch was failing
- Manually implement
ryo3-uuid- Fixed features problems as pointed out by clippy + cargo-hack
- Removed unused
uuid2function as it is not implemented in the underlyinguuidcrate
v0.0.64 [2025-10-20]
ryo3-reqwest- Turn on hickory-dns by default
- Use `rustls-tls-webpki-roots
v0.0.63 [2025-10-20]
- pyo3
- Upgrade pyo3 version to
0.27.x
- Upgrade pyo3 version to
ryo3-std- Missing
std::fsfunction wrappers:std::fs::hard_link->ry.hard_link(src: FsPathLike, dst: FsPathLike) -> Nonestd::fs::read_link->ry.read_link(path: FsPathLike) -> FsPathLikestd::fs::read_to_string->ry.read_to_string(path: FsPathLike) -> strstd::fs::set_permissions->ry.set_permissions(path: FsPathLike, permissions: ry.Permissions) -> Nonestd::fs::soft_link->ry.soft_link(from_path: FsPathLike, to_path: FsPathLike) -> Nonestd::fs::symlink_metadata->ry.symlink_metadata(path: FsPathLike) -> ry.Metadata
- Missing
ryo3-glob- Detach implementation of
takeandcollect(which is cleaner and probably a wee bit faster)
- Detach implementation of
_futureryo3-ignorewrapper placeholderryo3-tokio-websocketscrate placeholder
ryo3-reqwestry.CertificateforHttpClientaddedroot_certificatesadded tory.HttpClient
v0.0.62 [2025-10-15]
- python3.14 builds
ryo3-uuid- Fixed uuid
.timeproperty on python 3.14+
- Fixed uuid
ryo3-sqlformat- Internal refactoring
- Fixed type annotations
- Starting to think that the
QueryParamswrapper is totally stupid and useless and may remove/deprecate - Upgrade sqlformat to
0.5.0which adds the kwargdialect: t.Literal["generic", "postgresql", "sqlserver"] = "generic" - Added
SqlFormatterobject for storing a “config”/set-o-opts and for reuse (which I was in need of)
ryo3-reqwest- Added
basic_authandbearer_authkwargs to fetch functions (get,post,put,delete,head,patch, and of coursefetch) - Internal refactoring of body/form/json/multipart parsing.
- Added more client kwargs from
reqwest::ClientBuilder:redirect: int | None = 10referer: bool = Truezstd: bool = Truehickory_dns: bool = Truehttp1_only: bool = Falsehttps_only: bool = Falsehttp1_title_case_headers: bool = Falsehttp1_allow_obsolete_multiline_headers_in_responses: bool = Falsehttp1_allow_spaces_after_header_name_in_responses: bool = Falsehttp1_ignore_invalid_headers_in_responses: bool = Falsehttp2_prior_knowledge: bool = Falsehttp2_initial_stream_window_size: int | None = Nonehttp2_initial_connection_window_size: int | None = Nonehttp2_adaptive_window: bool = Falsehttp2_max_frame_size: int | None = Nonehttp2_max_header_list_size: int | None = Nonehttp2_keep_alive_interval: Duration | None = Nonehttp2_keep_alive_timeout: Duration | None = Nonehttp2_keep_alive_while_idle: bool = Falsepool_idle_timeout: Duration | None = ..., # 90 secondpool_max_idle_per_host: int | None = ..., # usize::MAtcp_keepalive: Duration | None = ..., # 15 secondtcp_keepalive_interval: Duration | None = ..., # 15 secondtcp_keepalive_retries: int | None = 3tcp_nodelay: bool = Truetls_min_version: t.Literal["1.0", "1.1", "1.2", "1.3"] | None = Nonetls_max_version: t.Literal["1.0", "1.1", "1.2", "1.3"] | None = Nonetls_info: bool = Falsetls_sni: bool = Truedanger_accept_invalid_certs: bool = Falsedanger_accept_invalid_hostnames: bool = False
- Added
v0.0.61 [2025-10-08]
ryo3-std- added
to_dict/from_dicttory.Duration
- added
- use
jessekrubin/pyo3-async-runtimes(branch ‘unpaid-interns’) git repo (for now): ryo3-uuid- supa speedy pydantic support added to
ry.uuid.UUID(bc I need it now)
- supa speedy pydantic support added to
ryo3-reqwestry.Cookieclass/struct andcookies/set_cookiesproperties on thery.Responseclass/struct
- removed deprecated
.string()methods from several structs/classes:ry.FsPathry.UUIDry.DateTimery.Datery.SignedDurationry.TimeSpanry.Timery.Timestampry.ZonedDateTime
v0.0.60 [2025-09-26]
- deprecations
- bump out
.string()method deprecation removals to0.0.61
- bump out
ryo3-stdry.FileTypestruct now has inner faux type/real type
ryo3-jiffstrftime/__format__changed to useBrokenDownTimeto not panic
ryo3-tokio- renamed:
DirEntryAsync->AsyncDirEntryReadDirAsync->AsyncReadDir
- renamed:
v0.0.59 [2025-09-24]
ryo3-request- switched query/form kwargs to accept anything that can be serde-d via
ryo3-serdewhich is basically anything that is json-serializable viary.stringify
- switched query/form kwargs to accept anything that can be serde-d via
ry.protocols- moved all protocols to
ry.protocols
- moved all protocols to
- deprecations
- deprecate all
obj.string()methods in favor ofobj.to_string()tho I still dont love it in the first place
- deprecate all
ryo3-jiff- added
isoformatandfrom_isoformatmethods tory.TimeSpanandry.SignedDurationstructs
- added
ryo3-sqlformat- Updated to version 0.4.0 of
sqlformatcrate - Added sqlformat version 0.4.0 new options:
ignore_case_convert: list[str] | None = Noneinline: bool = Falsemax_inline_block: int = 50max_inline_arguments: int | None = Nonemax_inline_top_level: int | None = Nonejoins_as_top_level: bool = False
- Changed
indentarg/kwarg to accept either:int(positive integer for number of spaces)str(“tabs”, “\t” or “spaces”)
- Changed
uppercasearg/kwarg to default toFalseinstead ofTrueto be more inline with the default behaviour ofsqlformatcrate
- Updated to version 0.4.0 of
v0.0.58 [2025-09-18]
ryo3-jiff- added
.__format__()methods to several jiff structs to allow custom f-string formatting - Fixed
SignedDuration.__truediv__operator
- added
- internal
- migrated all
downcast*usages tocast*
- migrated all
- Min python version for ry is now 3.11+
v0.0.57 [2025-09-12]
ryo3-jiff- Added
TimeRoundpython struct - Fixed types for all
*Roundoperations limiting max “smallest” arg literal types. - Round-api changes
- builder-y functions and getter functions have been flip-flopped:
- Switched “builder”-y apis to start with prefix for all
*Roundstructs:increment(n: int) -> Self->_increment(n: int) -> Selfmode(m: str) -> Self->_mode(m: str) -> Selfsmallest(unit: str) -> Self->_smallest(unit: str) -> Self
- Switched all getter functions to be properties:
round_obj._increment() -> int->round_obj.increment -> intround_obj._mode() -> str->round_obj.mode -> strround_obj._smallest() -> str->round_obj.smallest -> str
- Switched “builder”-y apis to start with prefix for all
- builder-y functions and getter functions have been flip-flopped:
- Added
to_dict().asdict()renamed to.to_dict()all structs- renames structs:
ry.DateTime.asdict()->ry.DateTime.to_dict()ry.Date.asdict()->ry.Date.to_dict()ry.TimeSpan.asdict()->ry.TimeSpan.to_dict()ry.Time.asdict()->ry.Time.to_dict()ry.Headers.asdict()->ry.Headers.to_dict()
- Added
.to_dict()to:
- migrated from
xxhash-rusttotwox-hash~ retiringryo3-xxhash:( - thexxhash-rusthashers liked to sometimes crash, whereas thetwox-hashpy-hashers dont
v0.0.56 [2025-09-05]
ryo3-serde- refactoring and testing recursion and stitch
ryo3-tokio- Fix: python open mode parsing for
aiopenfunction
- Fix: python open mode parsing for
ryo3-reqwest- Add
jiterparsing options toResponse.json()
- Add
ryo3-jiff- use
#[pyo3(warn(...))]for deprecation warnings instead of doing it manually - fixed utc methods to use
.with_time_zone(TimeZone::UTC)instead of.in_tz("UTC")
- use
v0.0.55 [2025-09-03]
- upgrade pyo3 v0.26.x
ryo3-bytes- Update buffer usage based on kyle barron
pyo3-byteschanges
- Update buffer usage based on kyle barron
ryo3-std- Make each sub-module a feature flag
std-net,std-fs,std-time, etc…
- Make each sub-module a feature flag
- internal changes
- Implemented
Displayfor several types for use in their__repr__methods
- Implemented
v0.0.54 [2025-08-28]
ryo3-std- Serialization for std types
- Speed run of socketaddr types (WIP); needs more testing and the socket types could be cleaner…
ryo3-memchr- Basic functionality for
memchrandmemrchroperations
- Basic functionality for
ryo3-jiff- Changed
humanarg/kwarg inry.TimeSpanandry.SignedDurationtofriendlyand also make keyword only - Changed
strptimeandstrftimefunctions to be more inline with python’sdatetimemodule by changing the order of args to be(string, format)instead of(format, string); the strptime signature isstrptime(s: str, /, fmt: str) -> Self - Added to
ry.TimeSpanandry.SignedDurationthefriendlymethod for more natural string representations - Many internal refactors and cleanup
- Converted all
__repr__methods to use structDisplayimpls - Fixed rounding object repr function(s) and added pickling and tests for round objects
- Changed
- type-annotations
- Missing
lstrip/rstripmethod types forry.Bytes - Updated types for
ry.TimeSpanandry.SignedDurationw/ correctfriendlykwarg andfriendly()methods
- Missing
- Added ruff
A002lint - Added ruff
FBTlints
v0.0.53 [2025-08-18]
ry- Bump min python version 3.10 – this is a breaking change, but ry is still very much a WIP/in-beta, so the versioning schema is “yolo-versioning”
ryo3-serde- internal refactoring and cleanup
v0.0.52 [2025-07-30]
ryo3-bytes- internal refactoring
- added
ry.Bytes.__rmul__ry.Bytes.lstripry.Bytes.rstrip
ryo3-xxhash- all xxhash-ing classes are now
frozenpyclasses #259
- all xxhash-ing classes are now
v0.0.51 [2025-07-25]
ryo3-bytes- Separated
pyo3-bytesandryo3-bytespyo3-bytesmirrors the officialpyo3-bytescrate + extra methods, BUT it requires themultiple-pymethodsfeature to be enabledryo3-bytesis a crammed together version of thepyo3-bytesimplementation and extra methods and does NOT require themultiple-pymethodsfeature to be enabled
- Made
PythonBytesMethodstrait for the methods that are shared betweenpyo3-bytesandryo3-bytes
- Separated
ryo3-ulid- strict + lax ulid parsing for pydantic
ryo3-jiff- Renamed
checked_addandchecked_subtoaddandsubwhere the checked_version can error; did not remove where the checked version returns anOptiontype (ry.SignedDuration)..checked_addmay return later as a method that returns anOptiontype for all types (tbd). This is also meant to pave the way foradd/subfunctions with a more familiar api akin towhenever,pendulum,arrow,insert-other-datetime-lib-here - Added
replacemethods toDate,DateTimeandTimestructs that use the underlying jiffwithfunctions
- Renamed
v0.0.50 [2025-07-14]
- internal
- clippy lint fixes
unused_self(all butryo3-byteswhich needs its own cleanup)
- clippy lint fixes
ryo3-bytes- Added (bc I need them) more python compat methods:
title()swapcase()expandtabs()strip()
- Added (bc I need them) more python compat methods:
ryo3-fspath- Added
openmethod that forwards toopenmethod ofpathlib.Path - Added
mkdirmethod that mimicsmkdirmethod ofpathlib.Path
- Added
v0.0.49 [2025-07-04] (fourth o july)
- workspace
- set rust edition to 2024
ryo3-serde- Fixed recursive serialization w/ max depth of 255 (aligning with
orjson) - support
PyEllipsisforNonevalues in serialization
- Fixed recursive serialization w/ max depth of 255 (aligning with
ryo3-jsonminifyfunction to remove whitespace/newlines from json-string/bytes
ryo3-jiff- internal refactoring
isoformatmethods aligned with python’sdatetimelibrary methods- Freeze (make pyclass frozen) for all jiff types (changed
*Seriesiterables)
ryo3-fspathwhichfeature allowingFsPath.whichandFsPath.which_all
v0.0.48 [2025-06-24]
ryo3-jsonpybytesbool kwargs to returnbuiltins.bytesifTrueandry.BytesifFalse; default isFalse
ryo3-serde- support for types defined in
ryo3-http - support for
defaultkwarg that is passed to the serde serializer; like w/ the stdlib-json and orjson serializers, this allows for serializing types that are not natively supported by ry/serde and if failure should occur, it should raise aTypeErrororValueErrorinstead of returningNoneby default
- support for types defined in
ryo3-reqwestjsonkwarg added to request builders that auto-serializes viaryo3-serde; also because it uses thereqwest::RequestBuilderit auto sets theContent-Typeheader toapplication/json
v0.0.47 [2025-06-17]
- pyo3 v0.25.1
ryo3-serde(wip)- serializers for
PyAnyand more - this should theoretically allow for serializing any python object that is
serdeserializable with almost anyserdeserializer… that is the goal
- serializers for
ryo3-json- Where json stuff + ry is going to live in the near future (may consolidate
ryo3-jiterinto this newer crate) ry.stringify()usesryo3-serde+serde_jsonto write json bytes/bufs and it is pretty fast, faster than ujson and rapidjson (not tested yyjson), BUT orjson is still fastest (read a bunch of their code and it is remarkably advanced and optimized)
- Where json stuff + ry is going to live in the near future (may consolidate
v0.0.46 [2025-06-06]
- version 0.0.46
ryo3-reqwestResponseStream- Added
__repr__method - Added
async def take(self, n: int=1): ...method returns n chunks as a list - Added
async def collect(self: join = False) -> ...:method that collects the stream into a singlery.Bytesobject ifjoin=Trueor a list ofry.Bytesobjects ifjoin=False - Added
async def take(self, n: int=1): ...which returns n chunks as a list
- Added
ryo3-glob- add
dtypekwarg that takes eitherdtype=str | ry.FsPath | pathlib.Pathas type of obj yielded by the iterable; something about this feels really icky, the default may be changed tostr(frompathlib.Path)
- add
ryo3-ulid- Added mostly as a way to test how much pydantic + ry integration would be
ryo3-which- upgrade which to version 8
v0.0.45 [2025-05-30]
- added
__target__to python package metadata inry.__about__with the target triple of the current build ryo3-std- Buffering for
FileReadStream
- Buffering for
ryo3-jiter- Add function
parse_jsonlfor parsing json lines - Add
lineskwarg toread_jsonfor parsing/reading json lines
- Add function
ryo3-jiff-
ZonedDateTime.__new__takes more python-datetime like args/kwargs, old version of constructor moved to classmethodZonedDateTime.from_parts(timestamp: ry.Timestamp, tz: ry.TimeZone) -> ZonedDateTime -
zonedtop level function- if
tzisNonethen it uses the system timezone - SIGNATURE
def zoned( year: int, month: int, day: int, hour: int = 0, minute: int = 0, second: int = 0, nanosecond: int = 0, tz: str | None = None, ) -> ZonedDateTime: ... - if
-
v0.0.44 [2025-05-23]
- internal:
- renamed
ryo3-macrostoryo3-macro-rules
- renamed
- docs
- Cleaned up
./README.md - Removed type-annotations from
./README.md
- Cleaned up
- pyo3-v0.25.0
- py-types
- reqwest-request functions use
TypedDictandUnpack
- reqwest-request functions use
ryo3-jiff- serde serialization features/support
ry.ZonedDateTime.replacemethod mirroringZonedWith–withis a python keyword, so usedreplaceinstead- example script based on jiff-docs examples
test_jiff_examples_v2.pytest script (basis for example script)- Was tired/fried so I copy-pasta-ed the
ry/ryo3/_jiff.pyitype annotations, the jiff-v2-docs-examples, and the jiff-v1-hand-translatedtest_jiff_examples_v1.pyfile into Chad-Gippity who was able to do most of the translation fromrusttory…
- Was tired/fried so I copy-pasta-ed the
ryo3-xxhash- Align with
xxhashpypi library w/ respect to naming conventions
- Align with
v0.0.43 [2025-05-17]
ryo3-jiff- panic-able functions to create new/altered (time)spans moved to use
try_*
- panic-able functions to create new/altered (time)spans moved to use
- fix: anyio marker flat issue in pytests for cicd
ryo3-uuid- added
uuidwrapper foruuidcrate; ty to the maintainers ofuuid-utilsandfastuuidfor helping figure out some of the nitty gritty bits and bobs
- added
ryo3-tokioAsyncFileandaiopenexperiment(s) added for async file reading/writing etc
v0.0.42 [2025-05-12]
- panic=abort
- panic is now (maybe will go back)
abortfor release builds - means smaller binaries and faster error handling (in theory)
- panic is now (maybe will go back)
ryo3-reqwest- more type fixes to response
- Got response type more inline with other python http-client libraries
- try
parking_lotfor defaultreqwestclient mutex - include missing kwargs for fetch functions
ryo3-glob- freeze struct(s) to be frozen
ryo3-http- http version python conversions to/from string/int
- crude-ish serde implementation for
HeadersMapfor json encoding/decoding… was a lot of googling - status code reason(s) interned
- intern all standard http header-names
ryo3-fnv- align with hashlib style hashing
- deps-up
- pyo3 version 0.24.2
- brotli 8
- jiff patch
v0.0.41 [2025-04-18]
ryo3-jiter- added
read_jsonfunction to read from path-like obj
- added
ryo3-bytes- misc small improvements and tests
ryo3-stdry.IpAddradded to handle both ipv4/ipv6ry.read_dirimplemented
ryo3-walkdir- added
objectsimpl and example script
- added
ryo3-tokiory.read_dir_asyncimplemented; also contains fancy async take/collect
v0.0.40 [2025-04-11]
- scripts
dl_versions.pyscript to download all versions of ry while ry is still pre-1-point-oh and old version(s) are being nuked from pypi as needed
- types
- fix types for few packages
- Updated several dependencies ~ most notably
pyo3to0.24.1 - Fixed several new clippy lints that appear in CI stable rust builds
ryo3-stdstd::netipv4/ipv6 wrappers speed run impl
v0.0.39 [2025-03-14]
- internal
- cleaned up several dependencies and features
ryo3-zstd- actually changed to use py buffer protocol this time… I dont know how it got missed before…
- re-factored a decent bit and made submodule with future plans to expand encoding/decoding dictionary support
- submodule is
ry.zstdand/orry.ryo3.zstd
v0.0.38 [2025-03-13]
ryo3-reqwest- client configuration for pickling
- allow buffer-protocol for
bodyfetching methods (should add string maybe?)
ryo3-walkdir- Few more options added
ryo3-glob- new wrapper around
globcrate
- new wrapper around
ryo3-jiff- Switched to use conversions from
jifffeature ofpyo3-v24as opposed to hand-rolled conversions we had before
- Switched to use conversions from
v0.0.37 [2025-03-11]
- pyo3 version
0.24.0 ryo3-whichfunctions returnpathlib.Pathnow due to changes in pyo3-v24; this may change in the near future…
v0.0.36 [2025-03-11]
- dependencies updated
- pickling support and tests for several types
- bytes/buffer-protocol support for several sub-packages/packages:
ryo3-brotliryo3-bzip2ryo3-flate2ryo3-fnvryo3-xxhashryo3-zstd
v0.0.35 [2025-03-06]
- internal
- types split up and cleaned up
ryo3-sizery.Sizeobject
ryo3-jiffseriesiterators havetakefunction that takes ausizereturns a list of sizeusize- updated series types to be
JiffSeriesclass
v0.0.34 [2025-02-28]
ryo3-stdfs:read_streamfunction that returns an iterator ofry.Bytesobjects from aPathLikeobject- Several more fs functions added
ryo3-tokio- Several more tokio fs functions added
- internal
- reorganized type annotations to be not a HUGE file…
v0.0.33 [2025-02-26]
- update to pyo3 v0.23.5
v0.0.32 [2025-02-25]
ryo3-jiter- Allow
PyByteswrapper/buffer protocol to be given - renamed
jiter_cache_cleartojson_cache_clearandjiter_cache_usagetojson_cache_usage - Removed
parse_json_strjust useparse_jsonwithstrinput
- Allow
ryo3-fspath- Allow read/write to take
ry.BytesorBytesobjects
- Allow read/write to take
v0.0.31 [2025-02-21]
ryo3-core- got rid of
ryo3-typesand moved intoryo3-core
- got rid of
ryo3-tokioread_asyncandwrite_asyncasync functions
ryo3-whichwhich_refunctions acceptsry.Regexorstrnow
ryo3-stdreadandwritefunctions which take/returnry.Bytesobjects
internal- Changed many many many of the structs/classes to be pyo3
frozenbehaviour should not be different
- Changed many many many of the structs/classes to be pyo3
v0.0.30 [2025-02-18]
jiff- Upgraded jiff to version 2
- internal
- Switch all lints from
#[allow(...)]/#![allow(...)]to#[expect(...)]/#![expect(...)] - Removed a bunch o commented out code
- Switch all lints from
ryo3-std- added several
std::fsstructs
- added several
ryo3-fspath- conversion to
pathlib.Pathby way ofFsPath.to_pathlib()
- conversion to
v0.0.29 [2025-02-03]
- internal
- Made sure each
ryo3-*crate has aREADME.md
- Made sure each
ryo3-bytes&ryo3-fspath- added
__hash__dunders to bothBytesandFsPathstructs
- added
v0.0.28 [2025-01-31]
jiff- Per Mr. Sushi’s thoughts changed all
until/sincemethods to use kwargs instead of the rust-like tuples that implFrom/Intoas it does not translate well to python - Gets rid of the following inane types:
- Per Mr. Sushi’s thoughts changed all
IntoDateDifference = (
DateDifference
| Date
| DateTime
| ZonedDateTime
| tuple[JIFF_UNIT_STRING, Date]
| tuple[JIFF_UNIT_STRING, DateTime]
| tuple[JIFF_UNIT_STRING, ZonedDateTime]
)
IntoTimeDifference = (
TimeDifference
| Time
| DateTime
| ZonedDateTime
| tuple[JIFF_UNIT_STRING, Time]
| tuple[JIFF_UNIT_STRING, DateTime]
| tuple[JIFF_UNIT_STRING, ZonedDateTime]
)
IntoDateTimeDifference = (
DateTimeDifference
| Date
| Time
| DateTime
| ZonedDateTime
| tuple[JIFF_UNIT_STRING, Date]
| tuple[JIFF_UNIT_STRING, Time]
| tuple[JIFF_UNIT_STRING, DateTime]
| tuple[JIFF_UNIT_STRING, ZonedDateTime]
)
IntoTimestampDifference = (
TimestampDifference
| Timestamp
| ZonedDateTime
| tuple[JIFF_UNIT_STRING, Timestamp]
| tuple[JIFF_UNIT_STRING, ZonedDateTime]
)
v0.0.27 [2025-01-23]
ry- Warning on
debugbuild
- Warning on
reqwest- headers-property response returns
Headersobject instead of python dict
- headers-property response returns
same-file- wrapper module added with
is_same_filepy-fn (yet another piece of burnt sushi)
- wrapper module added with
jiff- jiff-version
0.1.25~ addin_tzmethods and point oldintzat newin_tzmethods and raiseDeprecationWarningfor oldintzmethods - Continued adding implementations that previously raised
NotImplementedErrorDate.nth_weekday_of_monthDate.nth_weekdayDateTime.nth_weekday_of_monthDateTime.nth_weekdayTimeSpan.compareTimeSpan.totalZonedDateTime.nth_weekday_of_monthZonedDateTime.nth_weekday
- jiff-version
v0.0.26 [2025-01-13]
reqwestAsyncClientrenamed toHttpClient
jiff- human timespan strings for
TimeSpanandSignedDurationobjects:ry.TimeSpan.parse("P2M10DT2H30M").string(human=True) == "2mo 10d 2h 30m"ry.SignedDuration.parse("PT2H30M").string(human=True) == "2h 30m"
- human timespan strings for
- internal
- workspace-ified all the deps
v0.0.25 [2024-01-07] (25 for 2025)
jiff- Updated to
0.1.21which has span and signed duration strings with capital letters
- Updated to
v0.0.24 [2024-12-24] (the night b4 xmas…)
http- basic headers struct/obj – WIP
reqwest- reqwest client (currently root-export)
- default client + root
fetchfunction likely needs work… - response
byte_stream!
v0.0.23 [2024-12-19]
python -m ry.devrepl for ipython/python repl ~ handy nifty secret tool makes it into repo- internal
- in process of renaming all python-rust
#[new]functions to be namedfn py_new(...)
- in process of renaming all python-rust
unindent- Added
unindentmodule for unindenting strings will move toryo3-unindent
- Added
FsPath- creeping ever closer to being a full-fledged pathlib.Path replacement
- Added bindings to all rust
std::path::Path(buf)methods forFsPath
- sub-packaging
xxhashis own sub package nowry.xxhashJSONis own subpackage right now – namedry.JSONto avoid conflict withjsonmodule but maybe will change…- food-for-thought-ing how
ryo3andryshould be organized w/ respsect to sub-packages and where that organization should be
- type-annotations
- required to break up the type annotations due to migration to sub-packages
- breaking up the type annotations file into smaller files under
<REPO>/python/ry/ryo3/*.pyi
v0.0.22 [2024-12-16]
regex- Super simple regex wrapper (must to do here, but was added for
ryo3-which::which_re)
- Super simple regex wrapper (must to do here, but was added for
jiffuntil/since- Basic
until/sinceimplementation but I do not like them and they confusingly named*Differencestructs/py-objects, so I may change how they work…
- Basic
jiffseems to be about as performant aswhenever~ yay! also the whenever dude appears to be watching this repo (as of 2024-12-16)
walkdircollectadded toWalkdirGento collect the results into a list
- deps
thiserrorversion2.0.7->2.0.8
v0.0.21 [2024-12-13] (friday the 13th… spoogidy oogidity)
walkdir- add
globkwarg that takes ary.Globorry.GlobSetorry.Globsterobj to filter the walk on
- add
globset- Internal refactoring
- added
globster()method tory.Globandry.GlobSetto return ary.Globsterobj - added
globset()method tory.Globto return ary.GlobSetobj from ary.Globobj
url- python
Urlchanged nameURL; aligns with jawascript and other python libs
- python
bzip2- update to v5
jiff- conversions for jiff-round-mode/unit/weekday
- not-implemented placeholders and new impls
-
RyDateTime -
RyDate -
RyOffset -
RySignedDuration -
RySpan -
RyTimeZone -
RyTime -
RyZoned
-
- span builder functions use form
s._hours(1)for panic-inducing building, ands.try_hours(1)for non-panic-inducing building
- type-annotations
- fixes and updates and a hacky script I wrote to check for discrepancies
v0.0.20 [2024-12-10]
regex- Templated out regex package but nothing added
ry- python 3.13 yay!
jiter- Updated jiter version thanks depbot!
v0.0.19 [2024-12-05]
jiff- py-conversions
-
JiffDateTime- FromPyObject
- IntoPyObject
- IntoPyObject (REF)
-
JiffDate- FromPyObject
- IntoPyObject
- IntoPyObject (REF)
-
JiffOffset- FromPyObject
- IntoPyObject
- IntoPyObject (REF)
-
JiffSignedDuration- FromPyObject
- IntoPyObject
- IntoPyObject (REF)
-
JiffSpan- FromPyObject
- IntoPyObject
- IntoPyObject (REF)
-
JiffTimeZone- FromPyObject
- IntoPyObject
- IntoPyObject (REF)
-
JiffTime- FromPyObject
- IntoPyObject
- IntoPyObject (REF)
-
JiffZoned- FromPyObject
- IntoPyObject
- IntoPyObject (REF)
-
- py-conversions
v0.0.18 [2024-12-03]
jiff- Renamed
ry.Spantory.TimeSpan - Renamed
ry.Zonedtory.ZonedDateTime - Updated type stubs to reflect renames
- Renamed
- docs
- init-ed the docs
- style guide under
DEVELOPMENT.mdfile
v0.0.17 [2024-12-02]
jiffry.TimeZonetesting and to/fromdatetime.tzinfoconversions- Using nu-types for
jiffintermediate types bc of the classic orphans problem (aka batman) w/ traits - hypothesis tests
jiter- Updated to
jiterv0.8.1
- Updated to
v0.0.16 [2024-11-29]
- Moved walkdir to
ryo3-walkdir - added
ryo3-typesfor custom and shared types heckwrapper(s)- jiff
- Added operators
+/+=/-/-=to date/time/datetime/etc - TODO: figure out how to take refs in the union enum for the operators
- Added operators
- fspath
- further beefing out as well as testing
v0.0.15 [2024-11-20]
from __future__ import annotationsadded to all modules- cicd updated to include more targets
v0.0.14 [2024-11-20]
- Primitive/crude wrappers around Mr. Sushi’s
jifflibrary - Updated to use pyo3 (had to use jiter git repo dep)
ry.FsPathbeefed out- Added iterdir gen wrapper
- (todo undo when jiter + pyo3 23 is public)
v0.0.13 [2024-11-20]
- VERSION SKIPPED DUE TO
13BEING SPOOKY AND ME BEING MODERATELY-STITCHOUS (AKA fully ‘superstitchous’)
v0.0.12 [2024-11-14]
- sqlformat wrapper(s) (this is the first
ryo3-*sub-crate)
v0.0.11 [2024-09-22]
- dependencies updated
- prepare for python 3.13
v0.0.10 [2024-09-22]
- dependencies updated
v0.0.9 [2024-08-22]
- Added
globsetwrapper(s) - Added
__init__.pygenerator
- Upgraded to pyo3-v0.22
v0.0.8 [2024-06-25]
- Upgraded to pyo3-v0.22
v0.0.7 [2024-06-08]
- internal refactoring
v0.0.6 [2024-06-05]
- Added zstd (
zstd_encode/zstdandzstd_decode) - Added gzip (
gzip_encode/gzipandgzip_decode/gunzip) - Added bzip2 (
bzip2_encode/bzip2andbzip2_decode) - Added walkdir
- Reorg libs
v0.0.5 [2024-04-19]
- Added brotli (
brotli_encodeandbrotli_decode) - xxhash
- const functions
- hasher streaming objects
fspath
import ry
# get current directory
current_dir = ry.FsPath.cwd()
# write file
(current_dir / "test.txt").write_text("data!")
# read file
data = (current_dir / "test.txt").read_text()
print(data)
get
"""Example of `ry.fetch` (async) and `ry.fetch_sync` (blocking)"""
import asyncio
import ry
try:
from rich import print as echo
except ImportError:
echo = print # type: ignore[assignment]
async def main_async() -> None:
response = await ry.fetch("https://httpbingo.org/anything")
echo("Raw response:", response)
echo("socket:", response.remote_addr)
echo("url:", response.url)
echo("status:", response.status)
echo("headers:", response.headers)
echo("http-version:", response.http_version)
echo("content-length:", response.content_length)
json_data = await response.json()
echo("JSON data: ", json_data)
echo("stringified: ", ry.stringify(json_data, fmt=True).decode())
def main_sync() -> None:
response = ry.fetch_sync("https://httpbingo.org/anything")
echo("Raw response:", response)
echo("socket:", response.remote_addr)
echo("url:", response.url)
echo("status:", response.status)
echo("headers:", response.headers)
echo("http-version:", response.http_version)
echo("content-length:", response.content_length)
json_data = response.json()
echo("JSON data: ", json_data)
echo("stringified: ", ry.stringify(json_data, fmt=True).decode())
if __name__ == "__main__":
echo("_________________")
echo("~ ~ ~ ASYNC ~ ~ ~\n")
asyncio.run(main_async())
echo("\n_________________")
echo("~ ~ ~ SYNC ~ ~ ~\n")
main_sync()
http_fetch
"""Example of using the `ry.fetch` function to make http requests
The stuff at the top of this file is a simple http server for example purposes
"""
from __future__ import annotations
import asyncio
import json
from http.server import BaseHTTPRequestHandler, HTTPServer
from threading import Thread
# =============================================================================
import ry
def _print_break() -> None:
print("\n" + "=" * 79 + "\n")
async def main(server_url: str = "http://127.0.0.1:8000") -> None:
# -------------------------------------------------------------------------
# GET
# -------------------------------------------------------------------------
_print_break()
response = await ry.fetch(server_url)
print("Raw response:", response)
json_data = await response.json()
print("JSON data:\n", json.dumps(json_data, indent=2))
# **THE RESPONSE HAS BEEN CONSUMED**
# No you cannot get the json again.... You are responsible for storing
# The response has been consumed. This is how http requests really work.
# Libraries like requests, httpx, aiohttp, etc. store the response data
# in memory so you can access it multiple times, ry mirrors how fetch
# works in reqwest which is also kinda how fetch works in
# jawascript/interface-script.
try:
_json_data = await response.json()
except ValueError as e:
print("Error:", e)
# -------------------------------------------------------------------------
# POST
# -------------------------------------------------------------------------
_print_break()
post_response = await ry.fetch(
server_url, method="POST", body=b"post post post... dumb as a post"
)
print("Raw post response:", post_response)
post_response_data = await post_response.json()
print("JSON post response:\n", json.dumps(post_response_data, indent=2))
# -------------------------------------------------------------------------
# STREAMING
# -------------------------------------------------------------------------
_print_break()
long_body = "\n".join([f"dingo{i}" for i in range(1000)]).encode()
response = await ry.fetch(server_url, method="POST", body=long_body)
async for chunk in response.bytes_stream():
assert isinstance(chunk, ry.Bytes) # tis a bytes
py_bytes = bytes(chunk)
assert isinstance(py_bytes, bytes)
assert py_bytes == chunk
print("chunk this! len =:", len(chunk))
# -----------------------------------------------------------------------------
# HTTP SERVER THAT DOES SUPER SIMPLE JSON RESPONSES
# -----------------------------------------------------------------------------
class HTTPRequestHandler(BaseHTTPRequestHandler):
def do_GET(self) -> None:
self.send_response(200)
self.send_header("Content-type", "application/json")
self.end_headers()
res_data = {
"path": self.path,
"method": "GET",
"data": {
"dog": "dingo",
"oreo": "mcflurry",
},
}
res_bytes = json.dumps(res_data).encode()
self.wfile.write(res_bytes)
def do_POST(self) -> None:
self.send_response(200)
self.send_header("Content-type", "application/json")
self.end_headers()
body = self.rfile.read(int(self.headers["Content-Length"]))
res_data = {
"path": self.path,
"method": "POST",
"body": body.decode(),
"data": {
"dog": "dingo",
"oreo": "mcflurry",
},
}
res_bytes = json.dumps(res_data).encode()
self.wfile.write(res_bytes)
def start_server(
host: str = "127.0.0.1", port: int = 8888, logging: bool = False
) -> HTTPServer:
class HttpRequestHandlerNoLog(HTTPRequestHandler):
def log_message(self, format, *args): # type: ignore[no-untyped-def]
...
server_address = (host, port)
handler = HttpRequestHandlerNoLog if not logging else HTTPRequestHandler
httpd = HTTPServer(server_address, handler)
Thread(target=httpd.serve_forever, daemon=True).start()
return httpd
if __name__ == "__main__":
server = start_server(logging=True)
try:
asyncio.run(
main(server_url=f"http://{server.server_name}:{server.server_port}")
)
except KeyboardInterrupt:
print("KeyboardInterrupt")
finally:
server.shutdown()
jiff_examples
"""Jiff examples (v2)
Translated jiff-examples from jiff-v2's docs
REF: https://docs.rs/jiff/latest/jiff/#examples
DATE: 2025-05-23
"""
from __future__ import annotations
import json
from dataclasses import dataclass
import ry
def test_get_current_time_in_system_tz() -> None:
now = ry.ZonedDateTime.now()
assert isinstance(now, ry.ZonedDateTime)
assert now.tz.name
def test_print_current_time_rounded_to_second() -> None:
rounded = ry.ZonedDateTime.now().round("second")
# nanoseconds should be zero after rounding to second
assert rounded.nanosecond == 0
def test_print_todays_date_at_specific_time() -> None:
zdt = ry.ZonedDateTime.now().replace(
hour=14, minute=0, second=0, nanosecond=0
)
assert zdt.hour == 14 and zdt.minute == 0 and zdt.second == 0
assert zdt.nanosecond == 0
def test_print_current_unix_timestamp() -> None:
ts = ry.Timestamp.now()
sec = ts.as_second()
ns = ts.as_nanosecond()
assert isinstance(sec, int) and sec > 1_600_000_000
# nanosecond count divided by 1e9 should equal seconds
assert ns // 1_000_000_000 == sec
def test_print_datetime_for_a_timestamp() -> None:
ts = ry.Timestamp.from_millisecond(1_720_646_365_567)
zdt = ts.to_zoned(ry.TimeZone("America/New_York"))
assert str(zdt) == "2024-07-10T17:19:25.567-04:00[America/New_York]"
assert str(ts) == "2024-07-10T21:19:25.567Z"
def test_create_zoned_datetime_from_civil_time() -> None:
zdt = ry.date(2023, 12, 31).at(18, 30, 0, 0).in_tz("America/New_York")
assert str(zdt) == "2023-12-31T18:30:00-05:00[America/New_York]"
def test_change_an_instant_from_one_timezone_to_another() -> None:
paris = ry.date(1918, 11, 11).at(11, 0, 0, 0).in_tz("Europe/Paris")
nyc = paris.in_tz("America/New_York")
assert str(nyc) == "1918-11-11T06:00:00-05:00[America/New_York]"
def test_find_duration_between_two_zoned_datetimes() -> None:
a = ry.date(2020, 8, 26).at(6, 27, 0, 0).in_tz("America/New_York")
b = ry.date(2023, 12, 31).at(18, 30, 0, 0).in_tz("America/New_York")
span = b - a
assert str(span) == "PT29341H3M"
# until: specify largest unit via helper
span2 = a.until(b, largest="year")
assert str(span2) == "P3Y4M5DT12H3M"
def test_add_duration_to_a_zoned_datetime() -> None:
start = ry.date(2020, 8, 26).at(6, 27, 0, 0).in_tz("America/New_York")
span = ry.TimeSpan()._years(3)._months(4)._days(5)._hours(12)._minutes(3)
finish = start.add(span) # previously `checked_add`
assert str(finish) == "2023-12-31T18:30:00-05:00[America/New_York]"
def test_dealing_with_ambiguity() -> None:
gap = ry.date(2024, 3, 10).at(2, 30, 0, 0).in_tz("America/New_York")
assert str(gap) == "2024-03-10T03:30:00-04:00[America/New_York]"
fold = ry.date(2024, 11, 3).at(1, 30, 0, 0).in_tz("America/New_York")
assert str(fold) == "2024-11-03T01:30:00-04:00[America/New_York]"
def test_parsing_a_span() -> None:
iso = ry.TimeSpan.parse("P5y1w10dT5h59m")
expected = (
ry.TimeSpan()._years(5)._weeks(1)._days(10)._hours(5)._minutes(59)
)
assert iso == expected
assert str(iso) == "P5Y1W10DT5H59M"
from_friendly = ry.TimeSpan.parse(
"5 years, 1 week, 10 days, 5 hours, 59 minutes"
)
assert iso == from_friendly
assert from_friendly.to_string(friendly=True) == "5y 1w 10d 5h 59m"
assert from_friendly.friendly() == "5y 1w 10d 5h 59m"
assert str(from_friendly) == "P5Y1W10DT5H59M"
def test_parsing_an_rfc2822_datetime_string() -> None:
base = ry.ZonedDateTime.parse_rfc2822("Thu, 29 Feb 2024 05:34 -0500")
tas = base.in_tz("Australia/Tasmania")
kol = base.in_tz("Asia/Kolkata")
assert tas.format_rfc2822() == "Thu, 29 Feb 2024 21:34:00 +1100"
assert kol.format_rfc2822() == "Thu, 29 Feb 2024 16:04:00 +0530"
def test_using_strftime_and_strptime() -> None:
zdt = ry.ZonedDateTime.strptime(
"Monday, July 15, 2024 at 5:30pm US/Eastern",
"%A, %B %d, %Y at %I:%M%p %Q",
)
assert str(zdt) == "2024-07-15T17:30:00-04:00[US/Eastern]"
tas = ry.date(2024, 7, 15).at(17, 30, 59, 0).in_tz("Australia/Tasmania")
formatted = tas.strftime("%A, %B %d, %Y at %-I:%M%P %Q")
assert formatted == "Monday, July 15, 2024 at 5:30pm Australia/Tasmania"
@dataclass
class Record:
timestamp: ry.Timestamp
def to_json(self) -> str:
return json.dumps({"timestamp": self.timestamp.as_second()})
@classmethod
def from_json(cls, raw: str) -> Record:
data = json.loads(raw)
return cls(timestamp=ry.Timestamp.from_second(data["timestamp"]))
def test_serializing_and_deserializing_integer_timestamps() -> None:
src = Record(timestamp=ry.Timestamp.from_second(1_517_644_800))
wire = src.to_json()
got = Record.from_json(wire)
assert got.timestamp == src.timestamp
assert wire == '{"timestamp": 1517644800}'
def main() -> None:
test_get_current_time_in_system_tz()
test_print_current_time_rounded_to_second()
test_print_todays_date_at_specific_time()
test_print_current_unix_timestamp()
test_print_datetime_for_a_timestamp()
test_create_zoned_datetime_from_civil_time()
test_change_an_instant_from_one_timezone_to_another()
test_find_duration_between_two_zoned_datetimes()
test_add_duration_to_a_zoned_datetime()
test_dealing_with_ambiguity()
test_parsing_a_span()
test_parsing_an_rfc2822_datetime_string()
test_using_strftime_and_strptime()
test_serializing_and_deserializing_integer_timestamps()
if __name__ == "__main__":
main()
sqlformat
import ry
QUERY_MBTILES_DUPLICATE_METADATA_ROWS = """
-- returns the rows that are duplicate (name, value) pairs
select name, value, count(*) as count from metadata group by name having count (*) > 1 and count (distinct value) = 1;
"""
assert (
ry.sqlfmt(QUERY_MBTILES_DUPLICATE_METADATA_ROWS)
== """
-- returns the rows that are duplicate (name, value) pairs
select
name,
value,
count(*) as count
from
metadata
group by
name
having
count (*) > 1
and count (distinct value) = 1;
""".strip()
)
assert (
ry.sqlfmt(QUERY_MBTILES_DUPLICATE_METADATA_ROWS, uppercase=True)
== """
-- returns the rows that are duplicate (name, value) pairs
SELECT
name,
value,
count(*) AS count
FROM
metadata
GROUP BY
name
HAVING
count (*) > 1
AND count (DISTINCT value) = 1;
""".strip()
)
walking
"""
ry.walkdir example
"""
from __future__ import annotations
import os
import ry
PWD = os.path.dirname(os.path.abspath(__file__))
def _print_br(s: str | None = None) -> None:
print("_" * 79)
if s:
print(s)
def main() -> None:
dir2walk = PWD
_print_br("Walking the directory tree")
# Walking the directory tree
for filepath in ry.walkdir(dir2walk):
print(filepath)
_print_br("Walking the directory tree with entries")
# Walking the directory tree
for direntry in ry.walkdir(dir2walk, objects=True):
print(direntry, type(direntry))
_print_br("Walking the directory tree with depth 1")
# walking only files
for filepath in ry.walkdir(dir2walk, dirs=False):
print(filepath)
assert ry.FsPath(filepath).is_file()
# walking only directories
for filepath in ry.walkdir(dir2walk, files=False):
print(filepath)
assert ry.FsPath(filepath).is_dir()
# globset/globster
for filepath in ry.walkdir(
dir2walk,
glob=ry.globster([
"*.py",
]),
):
assert filepath.endswith(".py")
if __name__ == "__main__":
main()
API
Table of Contents
ry.ryo3.__init__ry.ryo3.__about__ry.ryo3._brotliry.ryo3._bytesry.ryo3._bzip2ry.ryo3._devry.ryo3._flate2ry.ryo3._fnvry.ryo3._fspathry.ryo3._globry.ryo3._globsetry.ryo3._heckry.ryo3._httpry.ryo3._jiffry.ryo3._jiff_tzry.ryo3._jiterry.ryo3._memchrry.ryo3._protocolsry.ryo3._quick_mathsry.ryo3._regexry.ryo3._reqwestry.ryo3._same_filery.ryo3._shlexry.ryo3._sizery.ryo3._sqlformatry.ryo3._stdry.ryo3._std_constantsry.ryo3._tokiory.ryo3._unindentry.ryo3._urlry.ryo3._walkdirry.ryo3._whichry.ryo3._zstdry.ryo3.dirsry.ryo3.errorsry.ryo3.JSONry.ryo3.orjsonry.ryo3.shry.ryo3.ulidry.ryo3.uuidry.ryo3.xxhashry.ryo3.zstdry._typesry.dirsry.JSONry.protocolsry.ulidry.uuidry.xxhashry.zstd
ry.ryo3.__init__
"""ry api ~ type annotations"""
from ry.ryo3 import JSON as JSON
from ry.ryo3 import ulid as ulid
from ry.ryo3 import uuid as uuid
from ry.ryo3 import xxhash as xxhash
from ry.ryo3 import zstd as zstd
from ry.ryo3.__about__ import __allocator__ as __allocator__
from ry.ryo3.__about__ import __authors__ as __authors__
from ry.ryo3.__about__ import __build_profile__ as __build_profile__
from ry.ryo3.__about__ import __build_timestamp__ as __build_timestamp__
from ry.ryo3.__about__ import __description__ as __description__
from ry.ryo3.__about__ import __opt_level__ as __opt_level__
from ry.ryo3.__about__ import __pkg_name__ as __pkg_name__
from ry.ryo3.__about__ import __target__ as __target__
from ry.ryo3.__about__ import __version__ as __version__
from ry.ryo3._brotli import brotli as brotli
from ry.ryo3._brotli import brotli_decode as brotli_decode
from ry.ryo3._brotli import brotli_encode as brotli_encode
from ry.ryo3._bytes import Bytes as Bytes
from ry.ryo3._bzip2 import bzip2 as bzip2
from ry.ryo3._bzip2 import bzip2_decode as bzip2_decode
from ry.ryo3._bzip2 import bzip2_encode as bzip2_encode
from ry.ryo3._flate2 import gunzip as gunzip
from ry.ryo3._flate2 import gzip as gzip
from ry.ryo3._flate2 import gzip_decode as gzip_decode
from ry.ryo3._flate2 import gzip_encode as gzip_encode
from ry.ryo3._flate2 import is_gzipped as is_gzipped
from ry.ryo3._fnv import fnv1a as fnv1a
from ry.ryo3._fspath import FsPath as FsPath
from ry.ryo3._glob import Pattern as Pattern
from ry.ryo3._glob import glob as glob
from ry.ryo3._globset import Glob as Glob
from ry.ryo3._globset import GlobSet as GlobSet
from ry.ryo3._globset import Globster as Globster
from ry.ryo3._globset import globster as globster
from ry.ryo3._heck import camel_case as camel_case
from ry.ryo3._heck import kebab_case as kebab_case
from ry.ryo3._heck import pascal_case as pascal_case
from ry.ryo3._heck import shouty_kebab_case as shouty_kebab_case
from ry.ryo3._heck import shouty_snake_case as shouty_snake_case
from ry.ryo3._heck import snake_case as snake_case
from ry.ryo3._heck import snek_case as snek_case
from ry.ryo3._heck import title_case as title_case
from ry.ryo3._heck import train_case as train_case
from ry.ryo3._http import Headers as Headers
from ry.ryo3._http import HttpStatus as HttpStatus
from ry.ryo3._jiff import Date as Date
from ry.ryo3._jiff import DateDifference as DateDifference
from ry.ryo3._jiff import DateTime as DateTime
from ry.ryo3._jiff import DateTimeDifference as DateTimeDifference
from ry.ryo3._jiff import DateTimeRound as DateTimeRound
from ry.ryo3._jiff import ISOWeekDate as ISOWeekDate
from ry.ryo3._jiff import JiffRoundMode as JiffRoundMode
from ry.ryo3._jiff import JiffUnit as JiffUnit
from ry.ryo3._jiff import Offset as Offset
from ry.ryo3._jiff import OffsetRound as OffsetRound
from ry.ryo3._jiff import SignedDuration as SignedDuration
from ry.ryo3._jiff import SignedDurationRound as SignedDurationRound
from ry.ryo3._jiff import Time as Time
from ry.ryo3._jiff import TimeDifference as TimeDifference
from ry.ryo3._jiff import TimeRound as TimeRound
from ry.ryo3._jiff import TimeSpan as TimeSpan
from ry.ryo3._jiff import Timestamp as Timestamp
from ry.ryo3._jiff import TimestampDifference as TimestampDifference
from ry.ryo3._jiff import TimestampRound as TimestampRound
from ry.ryo3._jiff import TimeZone as TimeZone
from ry.ryo3._jiff import TimeZoneDatabase as TimeZoneDatabase
from ry.ryo3._jiff import Weekday as Weekday
from ry.ryo3._jiff import WeekdayInt as WeekdayInt
from ry.ryo3._jiff import WeekdayStr as WeekdayStr
from ry.ryo3._jiff import ZonedDateTime as ZonedDateTime
from ry.ryo3._jiff import ZonedDateTimeDifference as ZonedDateTimeDifference
from ry.ryo3._jiff import ZonedDateTimeRound as ZonedDateTimeRound
from ry.ryo3._jiff import date as date
from ry.ryo3._jiff import datetime as datetime
from ry.ryo3._jiff import now as now
from ry.ryo3._jiff import offset as offset
from ry.ryo3._jiff import time as time
from ry.ryo3._jiff import timespan as timespan
from ry.ryo3._jiff import utcnow as utcnow
from ry.ryo3._jiff import zoned as zoned
from ry.ryo3._jiter import JsonParseKwargs as JsonParseKwargs
from ry.ryo3._jiter import JsonPrimitive as JsonPrimitive
from ry.ryo3._jiter import JsonValue as JsonValue
from ry.ryo3._jiter import json_cache_clear as json_cache_clear
from ry.ryo3._jiter import json_cache_usage as json_cache_usage
from ry.ryo3._jiter import parse_json as parse_json
from ry.ryo3._jiter import parse_jsonl as parse_jsonl
from ry.ryo3._jiter import read_json as read_json
from ry.ryo3._memchr import memchr as memchr
from ry.ryo3._memchr import memchr2 as memchr2
from ry.ryo3._memchr import memchr3 as memchr3
from ry.ryo3._memchr import memrchr as memrchr
from ry.ryo3._memchr import memrchr2 as memrchr2
from ry.ryo3._memchr import memrchr3 as memrchr3
from ry.ryo3._quick_maths import quick_maths as quick_maths
from ry.ryo3._regex import Regex as Regex
from ry.ryo3._reqwest import BlockingClient as BlockingClient
from ry.ryo3._reqwest import BlockingResponse as BlockingResponse
from ry.ryo3._reqwest import BlockingResponseStream as BlockingResponseStream
from ry.ryo3._reqwest import Certificate as Certificate
from ry.ryo3._reqwest import ClientConfig as ClientConfig
from ry.ryo3._reqwest import Cookie as Cookie
from ry.ryo3._reqwest import HttpClient as HttpClient
from ry.ryo3._reqwest import RequestKwargs as RequestKwargs
from ry.ryo3._reqwest import ReqwestError as ReqwestError
from ry.ryo3._reqwest import Response as Response
from ry.ryo3._reqwest import ResponseStream as ResponseStream
from ry.ryo3._reqwest import fetch as fetch
from ry.ryo3._reqwest import fetch_sync as fetch_sync
from ry.ryo3._same_file import is_same_file as is_same_file
from ry.ryo3._shlex import shplit as shplit
from ry.ryo3._size import Size as Size
from ry.ryo3._size import SizeFormatter as SizeFormatter
from ry.ryo3._size import fmt_size as fmt_size
from ry.ryo3._size import parse_size as parse_size
from ry.ryo3._sqlformat import SqlfmtQueryParams as SqlfmtQueryParams
from ry.ryo3._sqlformat import SqlFormatter as SqlFormatter
from ry.ryo3._sqlformat import sqlfmt as sqlfmt
from ry.ryo3._sqlformat import sqlfmt_params as sqlfmt_params
from ry.ryo3._std import DirEntry as DirEntry
from ry.ryo3._std import Duration as Duration
from ry.ryo3._std import FileReadStream as FileReadStream
from ry.ryo3._std import FileType as FileType
from ry.ryo3._std import Instant as Instant
from ry.ryo3._std import IpAddr as IpAddr
from ry.ryo3._std import Ipv4Addr as Ipv4Addr
from ry.ryo3._std import Ipv6Addr as Ipv6Addr
from ry.ryo3._std import Metadata as Metadata
from ry.ryo3._std import ReadDir as ReadDir
from ry.ryo3._std import SocketAddr as SocketAddr
from ry.ryo3._std import SocketAddrV4 as SocketAddrV4
from ry.ryo3._std import SocketAddrV6 as SocketAddrV6
from ry.ryo3._std import canonicalize as canonicalize
from ry.ryo3._std import copy as copy
from ry.ryo3._std import create_dir as create_dir
from ry.ryo3._std import create_dir_all as create_dir_all
from ry.ryo3._std import duration as duration
from ry.ryo3._std import exists as exists
from ry.ryo3._std import hard_link as hard_link
from ry.ryo3._std import instant as instant
from ry.ryo3._std import is_dir as is_dir
from ry.ryo3._std import is_file as is_file
from ry.ryo3._std import is_symlink as is_symlink
from ry.ryo3._std import metadata as metadata
from ry.ryo3._std import read as read
from ry.ryo3._std import read_bytes as read_bytes
from ry.ryo3._std import read_dir as read_dir
from ry.ryo3._std import read_link as read_link
from ry.ryo3._std import read_str as read_str
from ry.ryo3._std import read_stream as read_stream
from ry.ryo3._std import read_text as read_text
from ry.ryo3._std import read_to_string as read_to_string
from ry.ryo3._std import remove_dir as remove_dir
from ry.ryo3._std import remove_dir_all as remove_dir_all
from ry.ryo3._std import remove_file as remove_file
from ry.ryo3._std import rename as rename
from ry.ryo3._std import set_permissions as set_permissions
from ry.ryo3._std import sleep as sleep
from ry.ryo3._std import soft_link as soft_link
from ry.ryo3._std import symlink_metadata as symlink_metadata
from ry.ryo3._std import write as write
from ry.ryo3._std import write_bytes as write_bytes
from ry.ryo3._std import write_text as write_text
from ry.ryo3._std_constants import I8_BITS as I8_BITS
from ry.ryo3._std_constants import I8_MAX as I8_MAX
from ry.ryo3._std_constants import I8_MIN as I8_MIN
from ry.ryo3._std_constants import I16_BITS as I16_BITS
from ry.ryo3._std_constants import I16_MAX as I16_MAX
from ry.ryo3._std_constants import I16_MIN as I16_MIN
from ry.ryo3._std_constants import I32_BITS as I32_BITS
from ry.ryo3._std_constants import I32_MAX as I32_MAX
from ry.ryo3._std_constants import I32_MIN as I32_MIN
from ry.ryo3._std_constants import I64_BITS as I64_BITS
from ry.ryo3._std_constants import I64_MAX as I64_MAX
from ry.ryo3._std_constants import I64_MIN as I64_MIN
from ry.ryo3._std_constants import I128_BITS as I128_BITS
from ry.ryo3._std_constants import I128_MAX as I128_MAX
from ry.ryo3._std_constants import I128_MIN as I128_MIN
from ry.ryo3._std_constants import ISIZE_BITS as ISIZE_BITS
from ry.ryo3._std_constants import ISIZE_MAX as ISIZE_MAX
from ry.ryo3._std_constants import ISIZE_MIN as ISIZE_MIN
from ry.ryo3._std_constants import U8_BITS as U8_BITS
from ry.ryo3._std_constants import U8_MAX as U8_MAX
from ry.ryo3._std_constants import U8_MIN as U8_MIN
from ry.ryo3._std_constants import U16_BITS as U16_BITS
from ry.ryo3._std_constants import U16_MAX as U16_MAX
from ry.ryo3._std_constants import U16_MIN as U16_MIN
from ry.ryo3._std_constants import U32_BITS as U32_BITS
from ry.ryo3._std_constants import U32_MAX as U32_MAX
from ry.ryo3._std_constants import U32_MIN as U32_MIN
from ry.ryo3._std_constants import U64_BITS as U64_BITS
from ry.ryo3._std_constants import U64_MAX as U64_MAX
from ry.ryo3._std_constants import U64_MIN as U64_MIN
from ry.ryo3._std_constants import U128_BITS as U128_BITS
from ry.ryo3._std_constants import U128_MAX as U128_MAX
from ry.ryo3._std_constants import U128_MIN as U128_MIN
from ry.ryo3._std_constants import USIZE_BITS as USIZE_BITS
from ry.ryo3._std_constants import USIZE_MAX as USIZE_MAX
from ry.ryo3._std_constants import USIZE_MIN as USIZE_MIN
from ry.ryo3._tokio import AsyncDirEntry as AsyncDirEntry
from ry.ryo3._tokio import AsyncFile as AsyncFile
from ry.ryo3._tokio import AsyncReadDir as AsyncReadDir
from ry.ryo3._tokio import aiopen as aiopen # type: ignore[deprecated]
from ry.ryo3._tokio import aopen as aopen
from ry.ryo3._tokio import asleep as asleep
from ry.ryo3._tokio import canonicalize_async as canonicalize_async
from ry.ryo3._tokio import copy_async as copy_async
from ry.ryo3._tokio import create_dir_all_async as create_dir_all_async
from ry.ryo3._tokio import create_dir_async as create_dir_async
from ry.ryo3._tokio import exists_async as exists_async
from ry.ryo3._tokio import hard_link_async as hard_link_async
from ry.ryo3._tokio import metadata_async as metadata_async
from ry.ryo3._tokio import read_async as read_async
from ry.ryo3._tokio import read_dir_async as read_dir_async
from ry.ryo3._tokio import read_link_async as read_link_async
from ry.ryo3._tokio import read_to_string_async as read_to_string_async
from ry.ryo3._tokio import remove_dir_all_async as remove_dir_all_async
from ry.ryo3._tokio import remove_dir_async as remove_dir_async
from ry.ryo3._tokio import remove_file_async as remove_file_async
from ry.ryo3._tokio import rename_async as rename_async
from ry.ryo3._tokio import sleep_async as sleep_async
from ry.ryo3._tokio import try_exists_async as try_exists_async
from ry.ryo3._tokio import write_async as write_async
from ry.ryo3._unindent import unindent as unindent
from ry.ryo3._unindent import unindent_bytes as unindent_bytes
from ry.ryo3._url import URL as URL
from ry.ryo3._walkdir import WalkDirEntry as WalkDirEntry
from ry.ryo3._walkdir import WalkdirGen as WalkdirGen
from ry.ryo3._walkdir import walkdir as walkdir
from ry.ryo3._which import which as which
from ry.ryo3._which import which_all as which_all
from ry.ryo3._which import which_re as which_re
from ry.ryo3._zstd import is_zstd as is_zstd
from ry.ryo3._zstd import zstd_compress as zstd_compress
from ry.ryo3._zstd import zstd_decode as zstd_decode
from ry.ryo3._zstd import zstd_decompress as zstd_decompress
from ry.ryo3._zstd import zstd_encode as zstd_encode
from ry.ryo3.errors import FeatureNotEnabledError as FeatureNotEnabledError
from ry.ryo3.JSON import stringify as stringify
from ry.ryo3.JSON import stringify_unsafe as stringify_unsafe
from ry.ryo3.orjson import orjson_default as orjson_default
from ry.ryo3.sh import cd as cd
from ry.ryo3.sh import home as home
from ry.ryo3.sh import ls as ls
from ry.ryo3.sh import mkdir as mkdir
from ry.ryo3.sh import mkdirp as mkdirp
from ry.ryo3.sh import pwd as pwd
ry.ryo3.__about__
import typing as t
__version__: str
__authors__: str
__build_profile__: str
__build_timestamp__: str
__pkg_name__: str
__description__: str
__target__: str
__opt_level__: t.Literal["0", "1", "2", "3", "s", "z"]
__allocator__: t.Literal["mimalloc", "system"]
ry.ryo3._brotli
"""ryo3-brotli types"""
from typing import Literal, TypeAlias
from ry._types import Buffer
_Quality: TypeAlias = Literal[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
def brotli_encode(
data: Buffer, quality: _Quality = 11, *, magic_number: bool = False
) -> bytes: ...
def brotli_decode(data: Buffer) -> bytes: ...
def brotli(
data: Buffer, quality: _Quality = 11, *, magic_number: bool = False
) -> bytes:
"""Alias for brotli_encode"""
ry.ryo3._bytes
import sys
from typing import overload
import typing_extensions
if sys.version_info >= (3, 12):
from collections.abc import Buffer as Buffer
else:
from typing_extensions import Buffer as Buffer
class Bytes(Buffer):
"""
A buffer implementing the Python buffer protocol, allowing zero-copy access
to underlying Rust memory.
You can pass this to `memoryview` for a zero-copy view into the underlying
data or to `bytes` to copy the underlying data into a Python `bytes`.
Many methods from the Python `bytes` class are implemented on this,
"""
def __init__(self, buf: Buffer = b"") -> None:
"""Construct a new Bytes object.
This will be a zero-copy view on the Python byte slice.
"""
def __add__(self, other: Buffer) -> Bytes: ...
def __buffer__(self, flags: int) -> memoryview: ...
def __contains__(self, other: Buffer) -> bool: ...
def __eq__(self, other: object) -> bool: ...
@overload
def __getitem__(self, other: int) -> int: ...
@overload
def __getitem__(self, other: slice) -> Bytes: ...
def __mul__(self, other: int) -> Bytes: ...
def __rmul__(self, other: int) -> Bytes: ...
def __len__(self) -> int: ...
def __bytes__(self) -> bytes:
"""Return the underlying data as a Python `bytes` object."""
def removeprefix(self, prefix: Buffer, /) -> Bytes:
"""
If the binary data starts with the prefix string, return `bytes[len(prefix):]`.
Otherwise, return the original binary data.
"""
def removesuffix(self, suffix: Buffer, /) -> Bytes:
"""
If the binary data ends with the suffix string and that suffix is not empty,
return `bytes[:-len(suffix)]`. Otherwise, return the original binary data.
"""
def isalnum(self) -> bool:
"""
Return `True` if all bytes in the sequence are alphabetical ASCII characters or
ASCII decimal digits and the sequence is not empty, `False` otherwise.
Alphabetic ASCII characters are those byte values in the sequence
`b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'`. ASCII decimal digits
are those byte values in the sequence `b'0123456789'`.
"""
def isalpha(self) -> bool:
"""
Return `True` if all bytes in the sequence are alphabetic ASCII characters and
the sequence is not empty, `False` otherwise.
Alphabetic ASCII characters are those byte values in the sequence
`b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'`.
"""
def isascii(self) -> bool:
"""
Return `True` if the sequence is empty or all bytes in the sequence are ASCII,
`False` otherwise.
ASCII bytes are in the range `0-0x7F`.
"""
def isdigit(self) -> bool:
"""
Return `True` if all bytes in the sequence are ASCII decimal digits and the
sequence is not empty, `False` otherwise.
ASCII decimal digits are those byte values in the sequence `b'0123456789'`.
"""
def islower(self) -> bool:
"""
Return `True` if there is at least one lowercase ASCII character in the sequence
and no uppercase ASCII characters, `False` otherwise.
"""
def isspace(self) -> bool:
"""
Return `True` if all bytes in the sequence are ASCII whitespace and the sequence
is not empty, `False` otherwise.
ASCII whitespace characters are those byte values
in the sequence `b' \t\n\r\x0b\f'` (space, tab, newline, carriage return,
vertical tab, form feed).
"""
def isupper(self) -> bool:
"""
Return `True` if there is at least one uppercase alphabetic ASCII character in
the sequence and no lowercase ASCII characters, `False` otherwise.
"""
def lower(self) -> Bytes:
"""
Return a copy of the sequence with all the uppercase ASCII characters converted
to their corresponding lowercase counterpart.
"""
def upper(self) -> Bytes:
"""
Return a copy of the sequence with all the lowercase ASCII characters converted
to their corresponding uppercase counterpart.
"""
def to_bytes(self) -> bytes:
"""Copy this buffer's contents into a Python `bytes` object."""
# =========================================================================
# IMPL IN RY
# =========================================================================
def istitle(self) -> bool:
"""
Return `True` if the sequence is non-empty and contains only ASCII letters,
digits, underscores, and hyphens, and starts with an ASCII letter or underscore.
Otherwise, return `False`.
"""
def decode(self, encoding: str = "utf-8", errors: str = "strict") -> str:
"""Decode the binary data using the given encoding."""
def hex(
self, sep: str | None = None, bytes_per_sep: int | None = None
) -> str:
"""Return a hexadecimal representation of the binary data."""
@classmethod
def fromhex(cls, string: str) -> Bytes:
"""Construct a `Bytes` object from a hexadecimal string."""
def startswith(self, prefix: Buffer, /) -> bool:
"""Return `True` if the binary data starts with the prefix string, `False` otherwise."""
def endswith(self, suffix: Buffer, /) -> bool:
"""Return `True` if the binary data ends with the suffix string, `False` otherwise."""
def capitalize(self) -> Bytes:
"""
Return a copy of the sequence with the first byte converted to uppercase and
all other bytes converted to lowercase.
"""
def strip(self, chars: Buffer | None = None, /) -> Bytes:
"""
Return a copy of the sequence with leading and trailing bytes removed.
If `chars` is provided, remove all bytes in `chars` from both ends.
If `chars` is not provided, remove all ASCII whitespace bytes.
"""
def lstrip(self, chars: Buffer | None = None, /) -> Bytes:
"""
Return a copy of the sequence with leading bytes removed.
If `chars` is provided, remove all bytes in `chars` from the left end.
If `chars` is not provided, remove all ASCII whitespace bytes.
"""
def rstrip(self, chars: Buffer | None = None, /) -> Bytes:
"""
Return a copy of the sequence with trailing bytes removed.
If `chars` is provided, remove all bytes in `chars` from the right end.
If `chars` is not provided, remove all ASCII whitespace bytes.
"""
def expandtabs(self, tabsize: int = 8) -> Bytes:
"""
Return a copy of the sequence with all ASCII tab characters replaced by spaces.
The number of spaces is determined by the `tabsize` parameter.
"""
def title(self) -> Bytes:
"""
Return a copy of the sequence with the first byte of each word converted to
uppercase and all other bytes converted to lowercase.
"""
def swapcase(self) -> Bytes:
"""
Return a copy of the sequence with all uppercase ASCII characters converted to
their corresponding lowercase counterpart and vice versa.
"""
BytesLike: typing_extensions.TypeAlias = (
Buffer | bytes | bytearray | memoryview | Bytes
)
ry.ryo3._bzip2
"""ryo3-bzip2 types"""
from typing import Literal, TypeAlias
from ry import Bytes
from ry._types import Buffer
_Quality: TypeAlias = Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, "best", "fast"]
def bzip2_decode(data: Buffer) -> Bytes: ...
def bzip2_encode(data: Buffer, quality: _Quality = 6) -> Bytes: ...
def bzip2(data: Buffer, quality: _Quality = 6) -> Bytes:
"""Alias for bzip2_encode"""
ry.ryo3._dev
"""ry.ryo3.dev"""
import typing as t
# =============================================================================
# SUBPROCESS (VERY MUCH WIP)
# =============================================================================
def run(
*args: str | list[str],
capture_output: bool = True,
input: bytes | None = None, # noqa: A002
) -> t.Any: ...
# =============================================================================
# STRING-DEV
# =============================================================================
def anystr_noop(s: t.AnyStr) -> t.AnyStr: ...
def string_noop(s: str) -> str: ...
def bytes_noop(s: bytes) -> bytes: ...
ry.ryo3._flate2
"""ryo3-flate2 types"""
from typing import Literal, TypeAlias
from ry import Bytes
from ry._types import Buffer
Quality: TypeAlias = Literal[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "best", "fast"]
def gzip_encode(data: Buffer, quality: Quality = 6) -> Bytes: ...
def gzip_decode(data: Buffer) -> Bytes: ...
def gzip(data: Buffer, quality: Quality = 6) -> Bytes:
"""Alias for gzip_encode"""
def gunzip(data: Buffer) -> Bytes:
"""Alias for gzip_decode"""
def is_gzipped(data: Buffer) -> bool: ...
ry.ryo3._fnv
"""ryo3-fnv types"""
import typing as t
from ry._types import Buffer
@t.final
class fnv1a: # noqa: N801
name: t.Literal["fnv1a"]
digest_size: t.Literal[8]
block_size: t.Literal[1]
def __init__(
self,
data: Buffer | None = None,
*,
key: int | bytes = 0xCBF29CE484222325, # noqa: PYI054
) -> None: ...
def update(self, data: Buffer) -> None: ...
def digest(self) -> bytes: ...
def intdigest(self) -> int: ...
def hexdigest(self) -> str: ...
def copy(self) -> t.Self: ...
@staticmethod
def oneshot(
data: Buffer, *, key: int | bytes = 0xCBF29CE484222325
) -> int: ... # noqa: PYI054
ry.ryo3._fspath
"""ryo3-fspath types"""
import typing as t
from os import PathLike
from pathlib import Path
from ry._types import Buffer
from ry.protocols import RyIterator, ToPy, ToString
from ry.ryo3._bytes import Bytes
from ry.ryo3._regex import Regex
from ry.ryo3._std import Metadata
@t.final
class FsPath(ToPy[Path], ToString):
def __init__(self, path: PathLike[str] | str | None = None) -> None: ...
def __fspath__(self) -> str: ...
def to_string(self) -> str: ...
def to_py(self) -> Path: ...
def to_pathlib(self) -> Path: ...
# =========================================================================
# IO
# =========================================================================
def read(self) -> Bytes: ...
def read_bytes(self) -> bytes: ...
def read_text(self) -> str: ...
def write(self, data: Buffer | bytes) -> None: ...
def write_bytes(self, data: Buffer | bytes) -> None: ...
def write_text(self, data: str) -> None: ...
def open(
self,
mode: str,
buffering: int = -1,
encoding: str | None = None,
errors: str | None = None,
newline: str | None = None,
) -> t.IO[t.Any]: ...
# =========================================================================
# METHODS
# =========================================================================
def absolute(self) -> FsPath: ...
def as_posix(self) -> str: ...
def as_uri(self) -> str: ...
def clone(self) -> FsPath: ...
def equiv(self, other: PathLike[str] | str | FsPath) -> bool: ...
def exists(self) -> bool: ...
def iterdir(self) -> FsPathReaddir: ...
def join(self, p: PathLike[str] | str | FsPath) -> FsPath: ...
# TODO: support *args
def joinpath(self, other: str) -> FsPath: ...
def metadata(self) -> Metadata: ...
def mkdir(
self, mode: int = 0o777, parents: bool = False, exist_ok: bool = False
) -> None: ...
def read_dir(self) -> FsPathReaddir: ...
def read_link(self) -> FsPath: ...
def relative_to(self, other: PathLike[str] | str) -> FsPath: ...
def rename(self, new_path: PathLike[str] | str) -> FsPath: ...
def replace(self, new_path: PathLike[str] | str) -> FsPath: ...
def resolve(self) -> FsPath: ...
def rmdir(self, recursive: bool = False) -> None: ...
def unlink(
self, missing_ok: bool = False, recursive: bool = False
) -> None: ...
def with_name(self, name: str) -> t.Self: ...
def with_suffix(self, suffix: str) -> t.Self: ...
# =========================================================================
# CLASSMETHODS
# =========================================================================
@classmethod
def cwd(cls) -> t.Self: ...
@classmethod
def home(cls) -> t.Self: ...
# =========================================================================
# PROPERTIES
# =========================================================================
@property
def anchor(self) -> str: ...
@property
def drive(self) -> str: ...
@property
def name(self) -> str: ...
@property
def parent(self) -> t.Self: ...
@property
def parents(self) -> t.Sequence[t.Self]: ...
@property
def parts(self) -> tuple[str, ...]: ...
@property
def root(self) -> str: ...
@property
def stem(self) -> str: ...
@property
def suffix(self) -> str: ...
@property
def suffixes(self) -> list[str]: ...
# =========================================================================
# std::path::PathBuf (deref -> std::path::Path)
# =========================================================================
def ancestors(self) -> t.Iterator[t.Self]: ...
def canonicalize(self) -> t.Self: ...
def components(self) -> t.Iterator[t.Self]: ...
def display(self) -> str: ...
def ends_with(self, child: PathLike[str] | str) -> bool: ...
def extension(self) -> str: ...
def file_name(self) -> str: ...
def file_prefix(self) -> t.Self: ...
def file_stem(self) -> str: ...
def has_root(self) -> bool: ...
def is_absolute(self) -> bool: ...
def is_dir(self) -> bool: ...
def is_file(self) -> bool: ...
def is_relative(self) -> bool: ...
def is_symlink(self) -> bool: ...
def starts_with(self, base: PathLike[str] | str) -> bool: ...
def strip_prefix(self, base: PathLike[str] | str) -> t.Self: ...
def with_extension(self, extension: str) -> t.Self: ...
def with_file_name(self, name: str) -> t.Self: ...
# =========================================================================
# FEATURE: `same-file`
# =========================================================================
def samefile(self, other: PathLike[str] | str | t.Self) -> bool: ...
def symlink_metadata(self) -> Metadata: ...
# =========================================================================
# FEATURE: `which` & `which-regex`
# =========================================================================
@staticmethod
def which(cmd: str, path: str | None = None) -> FsPath | None: ...
@staticmethod
def which_all(cmd: str, path: str | None = None) -> list[FsPath]: ...
@staticmethod
def which_re(
regex: str | Regex, path: str | None = None
) -> FsPath | None: ...
# =========================================================================
# DUNDERS
# =========================================================================
def __truediv__(self, other: PathLike[str] | str) -> t.Self: ...
def __rtruediv__(self, other: PathLike[str] | str) -> t.Self: ...
def __lt__(self, other: PathLike[str] | str) -> bool: ...
def __le__(self, other: PathLike[str] | str) -> bool: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __gt__(self, other: PathLike[str] | str) -> bool: ...
def __ge__(self, other: PathLike[str] | str) -> bool: ...
def __hash__(self) -> int: ...
def __bytes__(self) -> bytes: ...
class FsPathReaddir(RyIterator[FsPath]):
def __init__(self) -> t.NoReturn: ...
def __iter__(self) -> t.Self: ...
def __next__(self) -> FsPath: ...
def collect(self) -> list[FsPath]: ...
def take(self, n: int = 1) -> list[FsPath]: ...
ry.ryo3._glob
"""ryo3-glob types"""
import typing as t
from os import PathLike
from pathlib import Path
from ry.protocols import RyIterator
from ry.ryo3._fspath import FsPath
_T = t.TypeVar("_T", bound=str | Path | FsPath)
@t.final
class GlobPaths(RyIterator[_T]):
"""glob::Paths iterable wrapper"""
def __next__(self) -> _T: ...
def __iter__(self) -> GlobPaths[_T]: ...
def collect(self) -> list[_T]: ...
def take(self, n: int = 1) -> list[_T]: ...
@t.overload
def glob(
pattern: str,
*,
case_sensitive: bool = True,
require_literal_separator: bool = False,
require_literal_leading_dot: bool = False,
strict: bool = False,
dtype: None = None,
) -> GlobPaths[Path]: ...
@t.overload
def glob(
pattern: str,
*,
case_sensitive: bool = True,
require_literal_separator: bool = False,
require_literal_leading_dot: bool = False,
strict: bool = False,
dtype: type[_T],
) -> GlobPaths[_T]: ...
@t.final
class Pattern:
def __init__(
self,
pattern: str,
*,
case_sensitive: bool = True,
require_literal_separator: bool = False,
require_literal_leading_dot: bool = False,
) -> None: ...
def __call__(
self,
ob: str | PathLike[str],
*,
case_sensitive: bool | None = None,
require_literal_separator: bool | None = None,
require_literal_leading_dot: bool | None = None,
) -> bool: ...
def matches(self, s: str) -> bool: ...
def matches_path(self, path: PathLike[str]) -> bool: ...
def matches_with(
self,
s: str,
*,
case_sensitive: bool | None = None,
require_literal_separator: bool | None = None,
require_literal_leading_dot: bool | None = None,
) -> bool: ...
def matches_path_with(
self,
path: PathLike[str],
*,
case_sensitive: bool | None = None,
require_literal_separator: bool | None = None,
require_literal_leading_dot: bool | None = None,
) -> bool: ...
@staticmethod
def escape(pattern: str) -> str: ...
@property
def pattern(self) -> str: ...
def __hash__(self) -> int: ...
ry.ryo3._globset
"""ryo3-globset types"""
import typing as t
from os import PathLike
@t.final
class Glob:
"""globset::Glob wrapper"""
def __init__(
self,
pattern: str,
/,
*,
case_insensitive: bool | None = None,
literal_separator: bool | None = None,
backslash_escape: bool | None = None,
) -> None: ...
@property
def regex(self) -> str: ...
def is_match(self, path: str | PathLike[str]) -> bool: ...
def is_match_str(self, path: str) -> bool: ...
def __call__(self, path: str | PathLike[str]) -> bool: ...
def __invert__(self) -> Glob: ...
def globset(self) -> GlobSet: ...
def globster(self) -> Globster: ...
@t.final
class GlobSet:
"""globset::GlobSet wrapper"""
def __init__(
self,
patterns: list[str],
/,
*,
case_insensitive: bool | None = None,
literal_separator: bool | None = None,
backslash_escape: bool | None = None,
) -> None: ...
def is_empty(self) -> bool: ...
def is_match(self, path: str) -> bool: ...
def is_match_str(self, path: str) -> bool: ...
def matches(self, path: str) -> list[int]: ...
def __call__(self, path: str) -> bool: ...
def globster(self) -> Globster: ...
@property
def patterns(self) -> tuple[str, ...]: ...
@t.final
class Globster:
"""Globster is a matcher with claws!
Note: The north american `Globster` is similar to the european `Globset`
but allows for negative patterns (prefixed with '!')
"""
def __init__(
self,
patterns: list[str],
/,
*,
case_insensitive: bool | None = None,
literal_separator: bool | None = None,
backslash_escape: bool | None = None,
) -> None: ...
def is_empty(self) -> bool: ...
def is_match(self, path: str | PathLike[str]) -> bool: ...
def is_match_str(self, path: str) -> bool: ...
def __call__(self, path: str | PathLike[str]) -> bool: ...
@property
def patterns(self) -> tuple[str, ...]: ...
def globster(
patterns: list[str] | tuple[str, ...],
/,
*,
case_insensitive: bool | None = None,
literal_separator: bool | None = None,
backslash_escape: bool | None = None,
) -> Globster: ...
ry.ryo3._heck
"""ryo3-heck types"""
def camel_case(string: str) -> str: ...
def kebab_case(string: str) -> str: ...
def pascal_case(string: str) -> str: ...
def shouty_kebab_case(string: str) -> str: ...
def shouty_snake_case(string: str) -> str: ...
def snake_case(string: str) -> str: ...
def snek_case(string: str) -> str: ...
def title_case(string: str) -> str: ...
def train_case(string: str) -> str: ...
ry.ryo3._http
import typing as t
from collections.abc import Mapping
# fmt: off
HttpVersionLike: t.TypeAlias = t.Literal[
"HTTP/0.9", "0.9", 0,
"HTTP/1.0", "1.0", 1, 10,
"HTTP/1.1", "1.1", 11,
"HTTP/2.0", "2.0", 2, 20,
"HTTP/3.0", "3.0", 3, 30,
]
# fmt: on
_StandardHeader: t.TypeAlias = t.Literal[
"accept",
"accept-charset",
"accept-encoding",
"accept-language",
"accept-ranges",
"access-control-allow-credentials",
"access-control-allow-headers",
"access-control-allow-methods",
"access-control-allow-origin",
"access-control-expose-headers",
"access-control-max-age",
"access-control-request-headers",
"access-control-request-method",
"age",
"allow",
"alt-svc",
"authorization",
"cache-control",
"cache-status",
"cdn-cache-control",
"connection",
"content-disposition",
"content-encoding",
"content-language",
"content-length",
"content-location",
"content-range",
"content-security-policy",
"content-security-policy-report-only",
"content-type",
"cookie",
"dnt",
"date",
"etag",
"expect",
"expires",
"forwarded",
"from",
"host",
"if-match",
"if-modified-since",
"if-none-match",
"if-range",
"if-unmodified-since",
"last-modified",
"link",
"location",
"max-forwards",
"origin",
"pragma",
"proxy-authenticate",
"proxy-authorization",
"public-key-pins",
"public-key-pins-report-only",
"range",
"referer",
"referrer-policy",
"refresh",
"retry-after",
"sec-websocket-accept",
"sec-websocket-extensions",
"sec-websocket-key",
"sec-websocket-protocol",
"sec-websocket-version",
"server",
"set-cookie",
"strict-transport-security",
"te",
"trailer",
"transfer-encoding",
"user-agent",
"upgrade",
"upgrade-insecure-requests",
"vary",
"via",
"warning",
"www-authenticate",
"x-content-type-options",
"x-dns-prefetch-control",
"x-frame-options",
"x-xss-protection",
]
_HeaderName: t.TypeAlias = _StandardHeader | str
_VT = t.TypeVar("_VT", bound=str | t.Sequence[str])
@t.final
class Headers:
"""python-ryo3-http `http::HeadersMap` wrapper"""
def __init__(
self,
headers: Mapping[_HeaderName, _VT] | t.Self | None = None,
/,
**kwargs: _VT,
) -> None: ...
# =========================================================================
# STRING
# =========================================================================
def __dbg__(self) -> str: ...
# =========================================================================
# MAGIC METHODS
# =========================================================================
def __len__(self) -> int: ...
def __getitem__(self, key: _HeaderName) -> str: ...
def __setitem__(self, key: _HeaderName, value: str) -> None: ...
def __delitem__(self, key: _HeaderName) -> None: ...
def __contains__(self, key: _HeaderName) -> bool: ...
def __or__(self, other: t.Self | dict[str, str]) -> t.Self: ...
def __ror__(self, other: t.Self | dict[str, str]) -> t.Self: ...
def __iter__(self) -> t.Iterator[_HeaderName]: ...
def __bool__(self) -> bool: ...
# =========================================================================
# INSTANCE METHODS
# =========================================================================
def to_py(self) -> dict[str, str | t.Sequence[str]]: ...
def to_dict(self) -> dict[str, str | t.Sequence[str]]: ...
def stringify(self, *, fmt: bool = False) -> str: ...
def append(self, key: _HeaderName, value: str) -> None: ...
def clear(self) -> None: ...
def contains_key(self, key: _HeaderName) -> bool: ...
def get(self, key: _HeaderName) -> str | None: ...
def get_all(self, key: _HeaderName) -> list[str]: ...
def insert(self, key: _HeaderName, value: str) -> None: ...
def is_empty(self) -> bool: ...
def keys(self) -> list[str]: ...
def keys_len(self) -> int: ...
def len(self) -> int: ...
def pop(self, key: _HeaderName) -> str: ...
def remove(self, key: _HeaderName) -> None: ...
def update(
self, headers: t.Self | dict[str, str], *, append: bool = False
) -> None: ...
def values(self) -> list[str]: ...
@property
def is_flat(self) -> bool: ...
@staticmethod
def from_json(data: str) -> Headers: ...
@t.final
class HttpStatus:
def __init__(self, code: int) -> None: ...
def __int__(self) -> int: ...
def __bool__(self) -> bool: ...
def __hash__(self) -> int: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __lt__(self, other: t.Self | int) -> bool: ...
def __le__(self, other: t.Self | int) -> bool: ...
def __gt__(self, other: t.Self | int) -> bool: ...
def __ge__(self, other: t.Self | int) -> bool: ...
def to_py(self) -> int: ...
@property
def reason(self) -> str: ...
@property
def canonical_reason(self) -> str: ...
@property
def is_informational(self) -> bool: ...
@property
def is_success(self) -> bool: ...
@property
def is_redirect(self) -> bool: ...
@property
def is_redirection(self) -> bool: ...
@property
def is_client_error(self) -> bool: ...
@property
def is_server_error(self) -> bool: ...
@property
def is_error(self) -> bool: ...
@property
def is_ok(self) -> bool: ...
@property
def ok(self) -> bool: ...
# =========================================================================
# CONST STATUS CODES
# =========================================================================
# fmt: off
# 1xx: Informational
CONTINUE: t.ClassVar[HttpStatus] # 100 ~ Continue
SWITCHING_PROTOCOLS: t.ClassVar[HttpStatus] # 101 ~ Switching Protocols
PROCESSING: t.ClassVar[HttpStatus] # 102 ~ Processing
EARLY_HINTS: t.ClassVar[HttpStatus] # 103 ~ Early Hints
# 2xx: Success
OK: t.ClassVar[HttpStatus] # 200 ~ OK
CREATED: t.ClassVar[HttpStatus] # 201 ~ Created
ACCEPTED: t.ClassVar[HttpStatus] # 202 ~ Accepted
NON_AUTHORITATIVE_INFORMATION: t.ClassVar[HttpStatus] # 203 ~ Non Authoritative Information
NO_CONTENT: t.ClassVar[HttpStatus] # 204 ~ No Content
RESET_CONTENT: t.ClassVar[HttpStatus] # 205 ~ Reset Content
PARTIAL_CONTENT: t.ClassVar[HttpStatus] # 206 ~ Partial Content
MULTI_STATUS: t.ClassVar[HttpStatus] # 207 ~ Multi-Status
ALREADY_REPORTED: t.ClassVar[HttpStatus] # 208 ~ Already Reported
IM_USED: t.ClassVar[HttpStatus] # 226 ~ IM Used
# 3xx: Redirection
MULTIPLE_CHOICES: t.ClassVar[HttpStatus] # 300 ~ Multiple Choices
MOVED_PERMANENTLY: t.ClassVar[HttpStatus] # 301 ~ Moved Permanently
FOUND: t.ClassVar[HttpStatus] # 302 ~ Found
SEE_OTHER: t.ClassVar[HttpStatus] # 303 ~ See Other
NOT_MODIFIED: t.ClassVar[HttpStatus] # 304 ~ Not Modified
USE_PROXY: t.ClassVar[HttpStatus] # 305 ~ Use Proxy
TEMPORARY_REDIRECT: t.ClassVar[HttpStatus] # 307 ~ Temporary Redirect
PERMANENT_REDIRECT: t.ClassVar[HttpStatus] # 308 ~ Permanent Redirect
# 4xx: Client Error
BAD_REQUEST: t.ClassVar[HttpStatus] # 400 ~ Bad Request
UNAUTHORIZED: t.ClassVar[HttpStatus] # 401 ~ Unauthorized
PAYMENT_REQUIRED: t.ClassVar[HttpStatus] # 402 ~ Payment Required
FORBIDDEN: t.ClassVar[HttpStatus] # 403 ~ Forbidden
NOT_FOUND: t.ClassVar[HttpStatus] # 404 ~ Not Found
METHOD_NOT_ALLOWED: t.ClassVar[HttpStatus] # 405 ~ Method Not Allowed
NOT_ACCEPTABLE: t.ClassVar[HttpStatus] # 406 ~ Not Acceptable
PROXY_AUTHENTICATION_REQUIRED: t.ClassVar[HttpStatus] # 407 ~ Proxy Authentication Required
REQUEST_TIMEOUT: t.ClassVar[HttpStatus] # 408 ~ Request Timeout
CONFLICT: t.ClassVar[HttpStatus] # 409 ~ Conflict
GONE: t.ClassVar[HttpStatus] # 410 ~ Gone
LENGTH_REQUIRED: t.ClassVar[HttpStatus] # 411 ~ Length Required
PRECONDITION_FAILED: t.ClassVar[HttpStatus] # 412 ~ Precondition Failed
PAYLOAD_TOO_LARGE: t.ClassVar[HttpStatus] # 413 ~ Payload Too Large
URI_TOO_LONG: t.ClassVar[HttpStatus] # 414 ~ URI Too Long
UNSUPPORTED_MEDIA_TYPE: t.ClassVar[HttpStatus] # 415 ~ Unsupported Media Type
RANGE_NOT_SATISFIABLE: t.ClassVar[HttpStatus] # 416 ~ Range Not Satisfiable
EXPECTATION_FAILED: t.ClassVar[HttpStatus] # 417 ~ Expectation Failed
IM_A_TEAPOT: t.ClassVar[HttpStatus] # 418 ~ I'm a teapot
MISDIRECTED_REQUEST: t.ClassVar[HttpStatus] # 421 ~ Misdirected Request
UNPROCESSABLE_ENTITY: t.ClassVar[HttpStatus] # 422 ~ Unprocessable Entity
LOCKED: t.ClassVar[HttpStatus] # 423 ~ Locked
FAILED_DEPENDENCY: t.ClassVar[HttpStatus] # 424 ~ Failed Dependency
TOO_EARLY: t.ClassVar[HttpStatus] # 425 ~ Too Early
UPGRADE_REQUIRED: t.ClassVar[HttpStatus] # 426 ~ Upgrade Required
PRECONDITION_REQUIRED: t.ClassVar[HttpStatus] # 428 ~ Precondition Required
TOO_MANY_REQUESTS: t.ClassVar[HttpStatus] # 429 ~ Too Many Requests
REQUEST_HEADER_FIELDS_TOO_LARGE: t.ClassVar[HttpStatus] # 431 ~ Request Header Fields Too Large
UNAVAILABLE_FOR_LEGAL_REASONS: t.ClassVar[HttpStatus] # 451 ~ Unavailable For Legal Reasons
# 5xx: Server Error
INTERNAL_SERVER_ERROR: t.ClassVar[HttpStatus] # 500 ~ Internal Server Error
NOT_IMPLEMENTED: t.ClassVar[HttpStatus] # 501 ~ Not Implemented
BAD_GATEWAY: t.ClassVar[HttpStatus] # 502 ~ Bad Gateway
SERVICE_UNAVAILABLE: t.ClassVar[HttpStatus] # 503 ~ Service Unavailable
GATEWAY_TIMEOUT: t.ClassVar[HttpStatus] # 504 ~ Gateway Timeout
HTTP_VERSION_NOT_SUPPORTED: t.ClassVar[HttpStatus] # 505 ~ HTTP Version Not Supported
VARIANT_ALSO_NEGOTIATES: t.ClassVar[HttpStatus] # 506 ~ Variant Also Negotiates
INSUFFICIENT_STORAGE: t.ClassVar[HttpStatus] # 507 ~ Insufficient Storage
LOOP_DETECTED: t.ClassVar[HttpStatus] # 508 ~ Loop Detected
NOT_EXTENDED: t.ClassVar[HttpStatus] # 510 ~ Not Extended
NETWORK_AUTHENTICATION_REQUIRED: t.ClassVar[HttpStatus] # 511 ~ Network Authentication Required
# fmt: on
ry.ryo3._jiff
"""ryo3-jiff types"""
import datetime as pydt
import sys
import typing as t
from ry._types import (
DateDifferenceTypedDict,
DateTimeDifferenceTypedDict,
DateTimeRoundTypedDict,
DateTimeTypedDict,
DateTypedDict,
ISOWeekDateTypedDict,
OffsetInfoDict,
OffsetRoundTypedDict,
OffsetTypedDict,
SignedDurationRoundTypedDict,
SignedDurationTypedDict,
TimeDifferenceTypedDict,
TimeRoundTypedDict,
TimeSpanTypedDict,
TimestampDifferenceTypedDict,
TimestampRoundTypedDict,
TimestampTypedDict,
TimeTypedDict,
TimeZoneDict,
ZonedDateTimeDifferenceTypedDict,
ZonedDateTimeRoundTypedDict,
ZonedDateTimeTypedDict,
)
from ry.protocols import (
FromStr,
Strftime,
ToPy,
ToPyDate,
ToPyDateTime,
ToPyTime,
ToPyTimeDelta,
ToPyTzInfo,
ToString,
_Parse,
)
from ry.ryo3 import Duration
from ry.ryo3._jiff_tz import TimezoneDbName
if sys.version_info >= (3, 13):
from warnings import deprecated
else:
from typing_extensions import deprecated
_T = t.TypeVar("_T")
_TDict = t.TypeVar("_TDict")
TimezoneName: t.TypeAlias = TimezoneDbName | str
JiffUnit: t.TypeAlias = t.Literal[
"year",
"month",
"week",
"day",
"hour",
"minute",
"second",
"millisecond",
"microsecond",
"nanosecond",
]
JiffRoundMode: t.TypeAlias = t.Literal[
"ceil",
"floor",
"expand",
"trunc",
"half-ceil",
"half-floor",
"half-expand",
"half-trunc",
"half-even",
]
_DateTimeRoundSmallest: t.TypeAlias = t.Literal[
"day",
"hour",
"minute",
"second",
"millisecond",
"microsecond",
"nanosecond",
]
_SignedDurationRoundSmallest: t.TypeAlias = t.Literal[
"hour",
"minute",
"second",
"millisecond",
"microsecond",
"nanosecond",
]
_TimeRoundSmallest: t.TypeAlias = t.Literal[
"hour",
"minute",
"second",
"millisecond",
"microsecond",
"nanosecond",
]
_TimestampRoundSmallest: t.TypeAlias = t.Literal[
"hour",
"minute",
"second",
"millisecond",
"microsecond",
"nanosecond",
]
_ZonedDateTimeRoundSmallest: t.TypeAlias = t.Literal[
"day",
"hour",
"minute",
"second",
"millisecond",
"microsecond",
"nanosecond",
]
_OffsetRoundSmallest: t.TypeAlias = t.Literal[
"hour",
"minute",
"second",
]
WeekdayStr: t.TypeAlias = t.Literal[
"monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"
]
WeekdayInt: t.TypeAlias = t.Literal[
1, # Monday
2, # Tuesday
3, # Wednesday
4, # Thursday
5, # Friday
6, # Saturday
7, # Sunday
]
Weekday: t.TypeAlias = WeekdayStr | WeekdayInt
@t.final
class Date(
# protocols
FromStr,
Strftime,
ToPyDate,
ToPy[pydt.date],
ToString,
_Parse,
):
MIN: t.ClassVar[Date]
MAX: t.ClassVar[Date]
ZERO: t.ClassVar[Date]
def __init__(self, year: int, month: int, day: int) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __lt__(self, other: t.Self) -> bool: ...
def __le__(self, other: t.Self) -> bool: ...
def __gt__(self, other: t.Self) -> bool: ...
def __ge__(self, other: t.Self) -> bool: ...
# =========================================================================
# STRING
# =========================================================================
def to_string(self) -> str: ...
def isoformat(self) -> str: ...
# =========================================================================
# PYTHON_CONVERSIONS
# =========================================================================
def to_py(self) -> pydt.date: ...
def to_pydate(self) -> pydt.date: ...
@classmethod
def from_pydate(cls, date: pydt.date) -> t.Self: ...
# =========================================================================
# PROPERTIES
# =========================================================================
@property
def year(self) -> int: ...
@property
def month(self) -> int: ...
@property
def day(self) -> int: ...
@property
def weekday(self) -> int: ...
# =========================================================================
# CLASSMETHODS
# =========================================================================
@classmethod
def from_iso_week_date(cls, iso_week_date: ISOWeekDate) -> t.Self: ...
@classmethod
def today(cls) -> t.Self: ...
@classmethod
def from_str(cls, s: str) -> t.Self: ...
@classmethod
def parse(cls, s: str | bytes) -> t.Self: ...
# =========================================================================
# STRPTIME/STRFTIME
# =========================================================================
@classmethod
def strptime(cls, string: str, /, fmt: str) -> t.Self: ...
def strftime(self, fmt: str) -> str: ...
def __format__(self, fmt: str) -> str: ...
# =========================================================================
# OPERATORS
# =========================================================================
def __add__(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> Date: ...
@t.overload
def __sub__(self, other: Date) -> TimeSpan: ...
@t.overload
def __sub__(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> Date: ...
# =========================================================================
# ARITHMETIC METHODS
# =========================================================================
def add(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> Date: ...
@t.overload
def sub(self, other: Date) -> TimeSpan: ...
@t.overload
def sub(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> Date: ...
def saturating_add(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> Date: ...
def saturating_sub(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> Date: ...
# =========================================================================
# INSTANCE METHODS
# =========================================================================
def at(
self, hour: int, minute: int, second: int, nanosecond: int = 0
) -> DateTime: ...
def to_dict(self) -> DateTypedDict: ...
def astuple(self) -> tuple[int, int, int]: ...
def day_of_year(self) -> int: ...
def day_of_year_no_leap(self) -> int | None: ...
def days_in_month(self) -> int: ...
def days_in_year(self) -> int: ...
def duration_since(self, other: t.Self) -> SignedDuration: ...
def duration_until(self, other: t.Self) -> SignedDuration: ...
def era_year(self) -> tuple[int, t.Literal["BCE", "CE"]]: ...
def first_of_month(self) -> t.Self: ...
def first_of_year(self) -> t.Self: ...
def iso_week_date(self) -> ISOWeekDate: ...
def in_leap_year(self) -> bool: ...
def in_tz(self, tz: TimezoneName) -> ZonedDateTime: ...
@deprecated("intz is deprecated, use in_tz instead")
def intz(self, tz: TimezoneName) -> ZonedDateTime: ...
def last_of_month(self) -> t.Self: ...
def last_of_year(self) -> t.Self: ...
def nth_weekday(self, nth: int, weekday: Weekday) -> t.Self: ...
def nth_weekday_of_month(self, nth: int, weekday: Weekday) -> t.Self: ...
def replace(
self,
*,
year: int | None = None,
month: int | None = None,
day: int | None = None,
era_year: tuple[int, t.Literal["BCE", "CE"]] | None = None,
day_of_year: int | None = None,
day_of_year_no_leap: int | None = None,
) -> t.Self: ...
def series(self, period: TimeSpan) -> JiffSeries[t.Self]: ...
def to_datetime(self, time: Time) -> DateTime: ...
def to_zoned(self, tz: TimeZone) -> ZonedDateTime: ...
def tomorrow(self) -> t.Self: ...
def yesterday(self) -> t.Self: ...
# =========================================================================
# SINCE/UNTIL
# =========================================================================
def _since(self, other: DateDifference) -> TimeSpan: ...
def _until(self, other: DateDifference) -> TimeSpan: ...
def since(
self,
other: Date | DateTime | ZonedDateTime,
*,
smallest: t.Literal["year", "month", "week", "day"] = "day",
largest: t.Literal["year", "month", "week", "day"] | None = None,
mode: JiffRoundMode = "trunc",
increment: int = 1,
) -> TimeSpan: ...
def until(
self,
other: Date | DateTime | ZonedDateTime,
*,
smallest: t.Literal["year", "month", "week", "day"] = "day",
largest: t.Literal["year", "month", "week", "day"] | None = None,
mode: JiffRoundMode = "trunc",
increment: int = 1,
) -> TimeSpan: ...
@t.final
class Time(
# protocols
FromStr,
Strftime,
ToPyTime,
ToPy[pydt.time],
_Parse,
):
MIN: t.ClassVar[Time]
MAX: t.ClassVar[Time]
def __init__(
self,
hour: int = 0,
minute: int = 0,
second: int = 0,
nanosecond: int = 0,
) -> None: ...
# =========================================================================
# STRING
# =========================================================================
def to_string(self) -> str: ...
def isoformat(self) -> str: ...
# =========================================================================
# OPERATORS/DUNDERS
# =========================================================================
def __add__(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
@t.overload
def __sub__(self, other: Time) -> TimeSpan: ...
@t.overload
def __sub__(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
# =========================================================================
# STRPTIME/STRFTIME/PARSE
# =========================================================================
@classmethod
def strptime(cls, string: str, /, fmt: str) -> t.Self: ...
def strftime(self, fmt: str) -> str: ...
def __format__(self, fmt: str) -> str: ...
# =========================================================================
# PYTHON CONVERSIONS
# =========================================================================
def to_py(self) -> pydt.time: ...
def to_pytime(self) -> pydt.time: ...
@classmethod
def from_pytime(cls, t: pydt.time) -> t.Self: ...
# =========================================================================
# CLASS METHODS
# =========================================================================
@classmethod
def midnight(cls) -> t.Self: ...
@classmethod
def now(cls) -> t.Self: ...
@classmethod
def utcnow(cls) -> t.Self: ...
@classmethod
def from_str(cls, s: str) -> t.Self: ...
@classmethod
def parse(cls, s: str | bytes) -> t.Self: ...
# =========================================================================
# PROPERTIES
# =========================================================================
@property
def hour(self) -> int: ...
@property
def minute(self) -> int: ...
@property
def second(self) -> int: ...
@property
def millisecond(self) -> int: ...
@property
def microsecond(self) -> int: ...
@property
def nanosecond(self) -> int: ...
@property
def subsec_nanosecond(self) -> int: ...
# =========================================================================
# ARITHMETIC METHODS
# =========================================================================
def add(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
@t.overload
def sub(self, other: Time) -> TimeSpan: ...
@t.overload
def sub(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
def saturating_add(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
def saturating_sub(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
def wrapping_add(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
def wrapping_sub(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
# =========================================================================
# INSTANCE METHODS
# =========================================================================
def astuple(self) -> tuple[int, int, int, int]: ...
def to_dict(self) -> TimeTypedDict: ...
def duration_until(self, other: Time) -> SignedDuration: ...
def duration_since(self, other: Time) -> SignedDuration: ...
def on(self, year: int, month: int, day: int) -> DateTime: ...
def replace(
self,
*,
hour: int | None = None,
minute: int | None = None,
second: int | None = None,
millisecond: int | None = None,
microsecond: int | None = None,
nanosecond: int | None = None,
subsec_nanosecond: int | None = None,
) -> t.Self: ...
def round(
self,
smallest: _TimeRoundSmallest = "nanosecond",
*,
mode: JiffRoundMode = "half-expand",
increment: int = 1,
) -> t.Self: ...
def _round(self, options: TimeRound) -> t.Self: ...
def series(self, period: TimeSpan) -> JiffSeries[t.Self]: ...
def to_datetime(self, date: Date) -> DateTime: ...
# =========================================================================
# SINCE/UNTIL
# =========================================================================
def _since(self, other: TimeDifference) -> TimeSpan: ...
def _until(self, other: TimeDifference) -> TimeSpan: ...
def since(
self,
t: Time | DateTime | ZonedDateTime,
*,
smallest: t.Literal[
"hour",
"minute",
"second",
"millisecond",
"microsecond",
"nanosecond",
] = "nanosecond",
largest: t.Literal[
"hour",
"minute",
"second",
"millisecond",
"microsecond",
"nanosecond",
]
| None = None,
mode: JiffRoundMode = "trunc",
increment: int = 1,
) -> TimeSpan: ...
def until(
self,
t: Time | DateTime | ZonedDateTime,
*,
smallest: t.Literal[
"hour",
"minute",
"second",
"millisecond",
"microsecond",
"nanosecond",
] = "nanosecond",
largest: t.Literal[
"hour",
"minute",
"second",
"millisecond",
"microsecond",
"nanosecond",
]
| None = None,
mode: JiffRoundMode = "trunc",
increment: int = 1,
) -> TimeSpan: ...
@t.final
class DateTime(
# protocols
FromStr,
Strftime,
ToPyDate,
ToPyDateTime,
ToPyTime,
ToPy[pydt.datetime],
_Parse,
):
MIN: t.ClassVar[DateTime]
MAX: t.ClassVar[DateTime]
ZERO: t.ClassVar[DateTime]
def __init__(
self,
year: int,
month: int,
day: int,
hour: int = 0,
minute: int = 0,
second: int = 0,
nanosecond: int = 0,
) -> None: ...
def to_string(self) -> str: ...
def isoformat(self) -> str: ...
# =========================================================================
# STRPTIME/STRFTIME/PARSE
# =========================================================================
def strftime(self, fmt: str) -> str: ...
@classmethod
def strptime(cls, string: str, /, fmt: str) -> t.Self: ...
def __format__(self, fmt: str) -> str: ...
@classmethod
def from_str(cls, s: str) -> t.Self: ...
@classmethod
def parse(cls, s: str | bytes) -> t.Self: ...
# =========================================================================
# PYTHON CONVERSIONS
# =========================================================================
@classmethod
def from_pydatetime(cls, datetime: pydt.datetime) -> t.Self: ...
def to_py(self) -> pydt.datetime: ...
def to_pydate(self) -> pydt.date: ...
def to_pydatetime(self) -> pydt.datetime: ...
def to_pytime(self) -> pydt.time: ...
# =========================================================================
# CLASS METHODS
# =========================================================================
@classmethod
def now(cls) -> t.Self: ...
@classmethod
def today(cls) -> t.Self: ...
@classmethod
def from_parts(cls, date: Date, time: Time) -> t.Self: ...
# =========================================================================
# OPERATORS
# =========================================================================
def __add__(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
@t.overload
def __sub__(self, other: t.Self) -> TimeSpan: ...
@t.overload
def __sub__(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
# =========================================================================
# ARITHMETIC METHODS
# =========================================================================
def add(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
@t.overload
def sub(self, other: t.Self) -> TimeSpan: ...
@t.overload
def sub(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
@t.overload
def saturating_sub(self, other: t.Self) -> TimeSpan: ...
@t.overload
def saturating_sub(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
# =========================================================================
# INSTANCE METHODS
# =========================================================================
def to_dict(self) -> DateTimeTypedDict: ...
def date(self) -> Date: ...
def day_of_year(self) -> int: ...
def day_of_year_no_leap(self) -> int | None: ...
def days_in_month(self) -> int: ...
def days_in_year(self) -> int: ...
def duration_since(self, other: t.Self) -> SignedDuration: ...
def duration_until(self, other: t.Self) -> SignedDuration: ...
def end_of_day(self) -> t.Self: ...
def era_year(self) -> tuple[int, t.Literal["BCE", "CE"]]: ...
def first_of_month(self) -> t.Self: ...
def first_of_year(self) -> t.Self: ...
def in_leap_year(self) -> bool: ...
def in_tz(self, tz: TimezoneName) -> ZonedDateTime: ...
@deprecated("intz is deprecated, use in_tz instead")
def intz(self, tz: TimezoneName) -> ZonedDateTime: ...
def iso_week_date(self) -> ISOWeekDate: ...
def last_of_month(self) -> t.Self: ...
def last_of_year(self) -> t.Self: ...
def nth_weekday(self, nth: int, weekday: Weekday) -> t.Self: ...
def nth_weekday_of_month(self, nth: int, weekday: Weekday) -> t.Self: ...
def replace(
self,
obj: Date | DateTime | Time | None = None,
*,
date: Date | None = None,
time: Time | None = None,
year: int | None = None,
era_year: tuple[int, t.Literal["BCE", "CE"]] | None = None,
month: int | None = None,
day: int | None = None,
day_of_year: int | None = None,
day_of_year_no_leap: int | None = None,
hour: int | None = None,
minute: int | None = None,
second: int | None = None,
millisecond: int | None = None,
microsecond: int | None = None,
nanosecond: int | None = None,
subsec_nanosecond: int | None = None,
) -> t.Self: ...
def round(
self,
smallest: _DateTimeRoundSmallest = "nanosecond",
*,
mode: JiffRoundMode = "half-expand",
increment: int = 1,
) -> t.Self: ...
def _round(self, options: DateTimeRound) -> t.Self: ...
def saturating_add(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
def series(self, period: TimeSpan) -> JiffSeries[t.Self]: ...
def start_of_day(self) -> t.Self: ...
def time(self) -> Time: ...
def to_zoned(self, tz: TimeZone) -> ZonedDateTime: ...
def tomorrow(self) -> t.Self: ...
def yesterday(self) -> t.Self: ...
# =========================================================================
# PROPERTIES
# =========================================================================
@property
def year(self) -> int: ...
@property
def month(self) -> int: ...
@property
def day(self) -> int: ...
@property
def hour(self) -> int: ...
@property
def minute(self) -> int: ...
@property
def second(self) -> int: ...
@property
def millisecond(self) -> int: ...
@property
def microsecond(self) -> int: ...
@property
def nanosecond(self) -> int: ...
@property
def subsec_nanosecond(self) -> int: ...
@property
def weekday(self) -> int: ...
# =========================================================================
# SINCE/UNTIL
# =========================================================================
def _since(self, other: DateTimeDifference) -> TimeSpan: ...
def _until(self, other: DateTimeDifference) -> TimeSpan: ...
def since(
self,
other: Date | DateTime | ZonedDateTime,
*,
smallest: JiffUnit = "nanosecond",
largest: JiffUnit | None = None,
mode: JiffRoundMode = "trunc",
increment: int = 1,
) -> TimeSpan: ...
def until(
self,
other: Date | DateTime | ZonedDateTime,
*,
smallest: JiffUnit = "nanosecond",
largest: JiffUnit | None = None,
mode: JiffRoundMode = "trunc",
increment: int = 1,
) -> TimeSpan: ...
@t.final
class TimeZone(
# protocols
FromStr,
ToPyTzInfo,
ToPy[pydt.tzinfo],
_Parse,
):
UTC: t.ClassVar[TimeZone]
def __init__(self, name: TimezoneName) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Self: ...
# =========================================================================
# PYTHON CONVERSIONS
# =========================================================================
def to_py(self) -> pydt.tzinfo: ...
def to_pytzinfo(self) -> pydt.tzinfo: ...
def to_dict(self) -> TimeZoneDict: ...
@classmethod
def from_str(cls, s: TimezoneName) -> t.Self: ...
@classmethod
def parse(cls, s: str | bytes) -> t.Self: ...
@classmethod
def from_pytzinfo(cls, tz: pydt.tzinfo) -> t.Self: ...
def to_offset_info(self, timestamp: Timestamp) -> OffsetInfoDict: ...
# =========================================================================
# PROPERTIES
# =========================================================================
@property
def name(self) -> str: ...
@property
def is_unknown(self) -> bool: ...
# =========================================================================
# CLASS METHODS
# =========================================================================
@classmethod
def fixed(cls, offset: Offset) -> t.Self: ...
@classmethod
def get(cls, tz_name: TimezoneName) -> t.Self: ...
@classmethod
def posix(cls, tz_name: TimezoneName) -> t.Self: ...
@classmethod
def system(cls) -> t.Self: ...
@classmethod
def try_system(cls) -> t.Self: ...
@classmethod
def tzif(cls, name: str, data: bytes) -> t.Self: ...
@classmethod
def utc(cls) -> t.Self: ...
def equiv(self, other: t.Self | pydt.tzinfo | str) -> bool: ...
# =========================================================================
# INSTANCE METHODS
# =========================================================================
def iana_name(self) -> str | None: ...
def to_datetime(self, timestamp: Timestamp) -> DateTime: ...
def to_fixed_offset(self) -> Offset:
"""Return a TimeZone with a fixed offset equivalent to this TimeZone.
Examples:
>>> import ry
>>> tz = ry.TimeZone.fixed(ry.Offset(hours=-5))
>>> fixed_tz = tz.to_fixed_offset()
>>> fixed_tz
Offset(hours=-5)
"""
def to_offset(self, timestamp: Timestamp) -> Offset: ...
def to_timestamp(self, datetime: DateTime) -> Timestamp: ...
def to_zoned(self, datetime: DateTime) -> ZonedDateTime: ...
# =========================================================================
# NOT IMPLEMENTED
# =========================================================================
def to_ambiguous_timestamp(self) -> t.NoReturn: ...
def to_ambiguous_zoned(self) -> t.NoReturn: ...
@t.final
class SignedDuration(
# protocols
FromStr,
ToPyTimeDelta,
ToPy[pydt.timedelta],
_Parse,
):
MIN: t.ClassVar[SignedDuration]
MAX: t.ClassVar[SignedDuration]
ZERO: t.ClassVar[SignedDuration]
def __init__(self, secs: int = 0, nanos: int = 0) -> None: ...
# =========================================================================
# OPERATORS/DUNDERS
# =========================================================================
def __hash__(self) -> int: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __lt__(self, other: object) -> bool: ...
def __le__(self, other: object) -> bool: ...
def __gt__(self, other: object) -> bool: ...
def __ge__(self, other: object) -> bool: ...
def __neg__(self) -> t.Self: ...
def __add__(self, other: t.Self | pydt.timedelta) -> t.Self: ...
def __radd__(self, other: t.Self | pydt.timedelta) -> t.Self: ...
def __sub__(self, other: t.Self | pydt.timedelta) -> t.Self: ...
def __rsub__(self, other: t.Self | pydt.timedelta) -> t.Self: ...
def __mul__(self, other: int) -> t.Self: ...
def __rmul__(self, other: int) -> t.Self: ...
def __abs__(self) -> t.Self: ...
def __float__(self) -> float: ...
def __int__(self) -> int: ...
def __bool__(self) -> bool: ...
@t.overload
def __truediv__(self, other: t.Self | pydt.timedelta) -> float: ...
@t.overload
def __truediv__(self, other: float) -> t.Self: ...
def abs(self) -> t.Self: ...
def unsigned_abs(self) -> Duration: ...
def __richcmp__(self, other: t.Self | pydt.timedelta, op: int) -> bool: ...
# =========================================================================
# STRING
# =========================================================================
def isoformat(self) -> str: ...
@classmethod
def from_isoformat(cls, s: str) -> t.Self: ...
def to_string(self, *, friendly: bool = False) -> str: ...
def friendly(self) -> str: ...
# =========================================================================
# PYTHON CONVERSIONS
# =========================================================================
@classmethod
def from_pytimedelta(cls, delta: pydt.timedelta) -> t.Self: ...
def to_py(self) -> pydt.timedelta: ...
def to_pytimedelta(self) -> pydt.timedelta: ...
def to_dict(self) -> SignedDurationTypedDict: ...
# =========================================================================
# CLASS METHODS
# =========================================================================
@classmethod
def from_str(cls, s: str) -> t.Self: ...
@classmethod
def parse(cls, s: str | bytes) -> t.Self: ...
@classmethod
def from_hours(cls, hours: int) -> t.Self: ...
@classmethod
def from_micros(cls, micros: int) -> t.Self: ...
@classmethod
def from_millis(cls, millis: int) -> t.Self: ...
@classmethod
def from_mins(cls, mins: int) -> t.Self: ...
@classmethod
def from_nanos(cls, nanos: int) -> t.Self: ...
@classmethod
def from_secs(cls, secs: int) -> t.Self: ...
@classmethod
def from_secs_f32(cls, secs: float) -> t.Self: ...
@classmethod
def from_secs_f64(cls, secs: float) -> t.Self: ...
# =========================================================================
# PROPERTIES
# =========================================================================
@property
def is_negative(self) -> bool: ...
@property
def is_positive(self) -> bool: ...
@property
def is_zero(self) -> bool: ...
@property
def secs(self) -> int: ...
@property
def nanos(self) -> int: ...
@property
def days(self) -> int: ...
@property
def seconds(self) -> int: ...
@property
def microseconds(self) -> int: ...
@property
def subsec_micros(self) -> int: ...
@property
def subsec_millis(self) -> int: ...
@property
def subsec_nanos(self) -> int: ...
# =========================================================================
# INSTANCE METHODS
# =========================================================================
def as_hours(self) -> int: ...
def as_micros(self) -> int: ...
def as_millis(self) -> int: ...
def as_millis_f32(self) -> float: ...
def as_millis_f64(self) -> float: ...
def as_mins(self) -> int: ...
def as_nanos(self) -> int: ...
def as_secs(self) -> int: ...
def as_secs_f32(self) -> float: ...
def as_secs_f64(self) -> float: ...
def checked_add(self, other: t.Self) -> t.Self | None: ...
def checked_div(self, other: int) -> t.Self | None: ...
def checked_mul(self, other: int) -> t.Self | None: ...
def checked_neg(self) -> t.Self | None: ...
def checked_sub(self, other: t.Self) -> t.Self | None: ...
def div_duration_f32(self, other: t.Self) -> float: ...
def div_duration_f64(self, other: t.Self) -> float: ...
def div_f32(self, n: float) -> float: ...
def div_f64(self, n: float) -> float: ...
def mul_f32(self, n: float) -> t.Self: ...
def mul_f64(self, n: float) -> t.Self: ...
def saturating_add(self, other: t.Self) -> t.Self: ...
def saturating_mul(self, other: int) -> t.Self: ...
def saturating_sub(self, other: t.Self) -> t.Self: ...
def signum(self) -> t.Literal[-1, 0, 1]: ...
def to_timespan(self) -> TimeSpan: ...
def round(
self,
smallest: _SignedDurationRoundSmallest = "nanosecond",
*,
mode: JiffRoundMode = "half-expand",
increment: int = 1,
) -> t.Self: ...
def _round(self, options: SignedDurationRound) -> t.Self: ...
TimeSpanArithmetic: t.TypeAlias = (
TimeSpan
| Duration
| SignedDuration
| tuple[
TimeSpan | Duration | SignedDuration, ZonedDateTime | Date | DateTime
]
)
@t.final
class TimeSpan(
# protocols
ToPy[pydt.timedelta],
ToPyTimeDelta,
FromStr,
_Parse,
):
def __init__(
self,
years: int = 0,
months: int = 0,
weeks: int = 0,
days: int = 0,
hours: int = 0,
minutes: int = 0,
seconds: int = 0,
milliseconds: int = 0,
microseconds: int = 0,
nanoseconds: int = 0,
) -> None: ...
# =========================================================================
# STRING
# =========================================================================
def isoformat(self) -> str: ...
@classmethod
def from_isoformat(cls, s: str) -> t.Self: ...
def to_string(self, *, friendly: bool = False) -> str: ...
def friendly(self) -> str: ...
def repr_full(self) -> str: ...
# =========================================================================
# PYTHON CONVERSIONS
# =========================================================================
@classmethod
def from_pytimedelta(cls, delta: pydt.timedelta) -> t.Self: ...
def to_pytimedelta(self) -> pydt.timedelta: ...
def to_py(self) -> pydt.timedelta: ...
# =========================================================================
# CLASS METHODS
# =========================================================================
@classmethod
def from_str(cls, s: str) -> t.Self: ...
@classmethod
def parse(cls, s: str | bytes) -> t.Self: ...
@classmethod
def parse_common_iso(cls, s: str) -> t.Self: ...
# =========================================================================
# PROPERTIES
# =========================================================================
@property
def is_positive(self) -> bool: ...
@property
def is_negative(self) -> bool: ...
@property
def is_zero(self) -> bool: ...
@property
def years(self) -> int: ...
@property
def months(self) -> int: ...
@property
def weeks(self) -> int: ...
@property
def days(self) -> int: ...
@property
def hours(self) -> int: ...
@property
def minutes(self) -> int: ...
@property
def seconds(self) -> int: ...
@property
def milliseconds(self) -> int: ...
@property
def microseconds(self) -> int: ...
@property
def nanoseconds(self) -> int: ...
# =========================================================================
# OPERATORS
# =========================================================================
def __add__(
self,
val: TimeSpanArithmetic,
) -> t.Self: ...
def __sub__(
self,
val: TimeSpanArithmetic,
) -> t.Self: ...
def __mul__(self, other: int) -> t.Self: ...
def __neg__(self) -> t.Self: ...
def __abs__(self) -> t.Self: ...
def __invert__(self) -> t.Self: ...
def __eq__(self, other: object) -> bool: ...
def __ge__(self, other: t.Self) -> bool: ...
def __gt__(self, other: t.Self) -> bool: ...
def __le__(self, other: t.Self) -> bool: ...
def __lt__(self, other: t.Self) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __rmul__(self, other: int) -> t.Self: ...
def __hash__(self) -> int: ...
# =========================================================================
# ARITHMETIC METHODS
# =========================================================================
def add(self, other: TimeSpanArithmetic) -> t.Self: ...
def mul(self, other: int) -> t.Self: ...
def sub(self, other: TimeSpanArithmetic) -> t.Self: ...
# =========================================================================
# INSTANCE METHODS
# =========================================================================
def abs(self) -> t.Self: ...
def to_dict(self) -> TimeSpanTypedDict: ...
def compare(
self,
other: t.Self,
relative: ZonedDateTime | DateTime | Date | None = None,
*,
days_are_24_hours: bool = False,
) -> int: ...
def negate(self) -> t.Self: ...
def replace(
self,
years: int | None = None,
months: int | None = None,
weeks: int | None = None,
days: int | None = None,
hours: int | None = None,
minutes: int | None = None,
seconds: int | None = None,
milliseconds: int | None = None,
microseconds: int | None = None,
nanoseconds: int | None = None,
) -> t.Self: ...
def round(
self,
smallest: JiffUnit = "nanosecond",
increment: int = 1,
*,
relative: ZonedDateTime | Date | DateTime | None = None,
largest: JiffUnit | None = None,
mode: JiffRoundMode = "half-expand",
) -> t.Self: ...
def signum(self) -> t.Literal[-1, 0, 1]: ...
def to_signed_duration(
self,
relative: ZonedDateTime | Date | DateTime | None = None,
) -> SignedDuration: ...
def total(
self,
unit: JiffUnit,
relative: ZonedDateTime | Date | DateTime | None = None,
*,
days_are_24_hours: bool = False,
) -> int: ...
def total_seconds(self) -> float: ...
def _years(self, years: int, /) -> t.Self: ...
def _months(self, months: int, /) -> t.Self: ...
def _weeks(self, weeks: int, /) -> t.Self: ...
def _days(self, days: int, /) -> t.Self: ...
def _hours(self, hours: int, /) -> t.Self: ...
def _minutes(self, minutes: int, /) -> t.Self: ...
def _seconds(self, seconds: int, /) -> t.Self: ...
def _milliseconds(self, milliseconds: int, /) -> t.Self: ...
def _microseconds(self, microseconds: int, /) -> t.Self: ...
def _nanoseconds(self, nanoseconds: int, /) -> t.Self: ...
@t.final
class Timestamp(
# protocols
FromStr,
Strftime,
ToPyDate,
ToPyDateTime,
ToPyTime,
ToPy[pydt.datetime],
_Parse,
):
"""
A representation of a timestamp with second and nanosecond precision.
"""
MIN: t.ClassVar[Timestamp]
MAX: t.ClassVar[Timestamp]
UNIX_EPOCH: t.ClassVar[Timestamp]
def __init__(
self, second: int | None = None, nanosecond: int | None = None
) -> None: ...
# =========================================================================
# CLASS METHODS
# =========================================================================
@classmethod
def now(cls) -> t.Self: ...
@classmethod
def from_str(cls, s: str) -> t.Self: ...
@classmethod
def parse(cls, s: str | bytes) -> t.Self: ...
@classmethod
def from_millisecond(cls, millisecond: int) -> t.Self: ...
@classmethod
def from_microsecond(cls, microsecond: int) -> t.Self: ...
@classmethod
def from_nanosecond(cls, nanosecond: int) -> t.Self: ...
@classmethod
def from_second(cls, second: int) -> t.Self: ...
# =========================================================================
# OPERATORS/DUNDERS
# =========================================================================
def __add__(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
def __eq__(self, other: object) -> bool: ...
def __ge__(self, other: t.Self) -> bool: ...
def __gt__(self, other: t.Self) -> bool: ...
def __le__(self, other: t.Self) -> bool: ...
def __lt__(self, other: t.Self) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __richcmp__(self, other: t.Self, op: int) -> bool: ...
# =========================================================================
# OPERATORS/DUNDERS W/ OVERLOADS
# =========================================================================
@t.overload
def __sub__(self, other: t.Self) -> TimeSpan: ...
@t.overload
def __sub__(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
# =========================================================================
# PYTHON CONVERSIONS
# =========================================================================
@classmethod
def from_pydatetime(cls, datetime: pydt.datetime) -> t.Self: ...
def to_py(self) -> pydt.datetime: ...
def to_pydate(self) -> pydt.date: ...
def to_pydatetime(self) -> pydt.datetime: ...
def to_pytime(self) -> pydt.time: ...
def to_dict(self) -> TimestampTypedDict: ...
# =========================================================================
# ARITHMETIC METHODS
# =========================================================================
def add(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
@t.overload
def sub(self, other: t.Self) -> TimeSpan: ...
@t.overload
def sub(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
def saturating_add(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
def saturating_sub(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
# =========================================================================
# STRPTIME/STRFTIME
# =========================================================================
@classmethod
def strptime(cls, string: str, /, fmt: str) -> t.Self: ...
def strftime(self, fmt: str) -> str: ...
def __format__(self, fmt: str) -> str: ...
# =========================================================================
# INSTANCE METHODS
# =========================================================================
def date(self) -> Date: ...
def datetime(self) -> DateTime: ...
def time(self) -> Time: ...
def as_microsecond(self) -> int: ...
def as_millisecond(self) -> int: ...
def as_nanosecond(self) -> int: ...
def as_second(self) -> int: ...
def display_with_offset(self, offset: Offset) -> str: ...
def in_tz(self, tz: TimezoneName) -> ZonedDateTime: ...
@deprecated("intz is deprecated, use in_tz instead")
def intz(self, tz: TimezoneName) -> ZonedDateTime:
"""Deprecated ~ use `in_tz`"""
@property
def is_zero(self) -> bool: ...
def series(self, period: TimeSpan) -> JiffSeries[t.Self]: ...
def signum(self) -> t.Literal[-1, 0, 1]: ...
def to_string(self) -> str: ...
def subsec_microsecond(self) -> int: ...
def subsec_millisecond(self) -> int: ...
def subsec_nanosecond(self) -> int: ...
def to_zoned(self, time_zone: TimeZone) -> ZonedDateTime: ...
# =========================================================================
# SINCE/UNTIL
# =========================================================================
def _since(self, other: TimestampDifference) -> TimeSpan: ...
def _until(self, other: TimestampDifference) -> TimeSpan: ...
def since(
self,
other: Timestamp | ZonedDateTime,
*,
smallest: t.Literal[
"hour",
"minute",
"second",
"millisecond",
"microsecond",
"nanosecond",
] = "nanosecond",
largest: t.Literal[
"hour",
"minute",
"second",
"millisecond",
"microsecond",
"nanosecond",
]
| None = None,
mode: JiffRoundMode = "trunc",
increment: int = 1,
) -> TimeSpan: ...
def until(
self,
other: Timestamp | ZonedDateTime,
*,
smallest: t.Literal[
"hour",
"minute",
"second",
"millisecond",
"microsecond",
"nanosecond",
] = "nanosecond",
largest: t.Literal[
"hour",
"minute",
"second",
"millisecond",
"microsecond",
"nanosecond",
]
| None = None,
mode: JiffRoundMode = "trunc",
increment: int = 1,
) -> TimeSpan: ...
def duration_since(self, other: t.Self) -> SignedDuration: ...
def duration_until(self, other: t.Self) -> SignedDuration: ...
def round(
self,
smallest: _TimestampRoundSmallest = "nanosecond",
*,
mode: JiffRoundMode = "half-expand",
increment: int = 1,
) -> t.Self: ...
def _round(self, options: TimestampRound) -> t.Self: ...
@t.final
class ZonedDateTime(
# protocols
ToPy[pydt.datetime],
ToPyDate,
ToPyTime,
ToPyDateTime,
ToPyTzInfo,
FromStr,
_Parse,
Strftime,
):
def __init__(
self,
year: int,
month: int,
day: int,
hour: int = 0,
minute: int = 0,
second: int = 0,
nanosecond: int = 0,
tz: TimezoneName | None = None,
) -> None: ...
# =========================================================================
# PYTHON CONVERSIONS
# =========================================================================
@classmethod
def from_pydatetime(cls, datetime: pydt.datetime) -> t.Self: ...
def to_dict(self) -> ZonedDateTimeTypedDict: ...
def to_py(self) -> pydt.datetime: ...
def to_pydate(self) -> pydt.date: ...
def to_pydatetime(self) -> pydt.datetime: ...
def to_pytime(self) -> pydt.time: ...
def to_pytzinfo(self) -> pydt.tzinfo: ...
# =========================================================================
# CLASS METHODS
# =========================================================================
@classmethod
def now(cls, tz: TimezoneName | None = None) -> t.Self: ...
@classmethod
def utcnow(cls) -> t.Self: ...
@classmethod
def from_str(cls, s: str) -> t.Self: ...
@classmethod
def parse(cls, s: str | bytes) -> t.Self: ...
@classmethod
def from_rfc2822(cls, s: str) -> t.Self: ...
@classmethod
def parse_rfc2822(cls, s: str) -> t.Self: ...
@classmethod
def from_parts(
cls, timestamp: Timestamp, time_zone: TimeZone
) -> t.Self: ...
# =========================================================================
# STRPTIME/STRFTIME
# =========================================================================
@classmethod
def strptime(cls, string: str, /, fmt: str) -> t.Self: ...
def strftime(self, fmt: str) -> str: ...
def __format__(self, fmt: str) -> str: ...
# =========================================================================
# PROPERTIES
# =========================================================================
@property
def year(self) -> int: ...
@property
def month(self) -> int: ...
@property
def day(self) -> int: ...
@property
def hour(self) -> int: ...
@property
def minute(self) -> int: ...
@property
def second(self) -> int: ...
@property
def millisecond(self) -> int: ...
@property
def microsecond(self) -> int: ...
@property
def nanosecond(self) -> int: ...
@property
def subsec_nanosecond(self) -> int: ...
@property
def weekday(self) -> int: ...
@property
def timezone(self) -> TimeZone: ...
@property
def tz(self) -> TimeZone: ...
# =========================================================================
# STRING/FORMAT
# =========================================================================
def to_string(self) -> str: ...
def to_rfc2822(self) -> str: ...
def format_rfc2822(self) -> str: ...
def isoformat(self) -> str: ...
# =========================================================================
# OPERATORS/DUNDERS
# =========================================================================
def __add__(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
def __eq__(self, other: object) -> bool: ...
def __ge__(self, other: t.Self) -> bool: ...
def __gt__(self, other: t.Self) -> bool: ...
def __hash__(self) -> int: ...
def __le__(self, other: t.Self) -> bool: ...
def __lt__(self, other: t.Self) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __richcmp__(self, other: t.Self, op: int) -> bool: ...
# =========================================================================
# OPERATORS/DUNDERS W/ OVERLOADS
# =========================================================================
@t.overload
def __sub__(self, other: t.Self) -> TimeSpan: ...
@t.overload
def __sub__(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
# =========================================================================
# ARITHMETIC METHODS
# =========================================================================
def add(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
@t.overload
def sub(self, other: t.Self) -> TimeSpan: ...
@t.overload
def sub(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
def saturating_add(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
@t.overload
def saturating_sub(self, other: t.Self) -> TimeSpan: ...
@t.overload
def saturating_sub(
self, other: TimeSpan | SignedDuration | Duration | pydt.timedelta
) -> t.Self: ...
# =========================================================================
# INSTANCE METHODS
# =========================================================================
def astimezone(self, tz: str) -> t.Self: ...
def date(self) -> Date: ...
def datetime(self) -> DateTime: ...
def iso_week_date(self) -> ISOWeekDate: ...
def day_of_year(self) -> int: ...
def day_of_year_no_leap(self) -> int | None: ...
def days_in_month(self) -> int: ...
def days_in_year(self) -> int: ...
def duration_since(self, other: t.Self) -> SignedDuration: ...
def duration_until(self, other: t.Self) -> SignedDuration: ...
def end_of_day(self) -> t.Self: ...
def era_year(self) -> tuple[int, t.Literal["CE", "BCE"]]: ...
def first_of_month(self) -> t.Self: ...
def first_of_year(self) -> t.Self: ...
def in_leap_year(self) -> bool: ...
def in_tz(self, tz: TimezoneName) -> t.Self: ...
@deprecated("intz is deprecated, use in_tz instead")
def intz(self, tz: TimezoneName) -> t.Self: ...
def inutc(self) -> t.Self: ...
def last_of_month(self) -> t.Self: ...
def last_of_year(self) -> t.Self: ...
def nth_weekday(self, nth: int, weekday: Weekday) -> Date: ...
def nth_weekday_of_month(self, nth: int, weekday: Weekday) -> Date: ...
def offset(self) -> Offset: ...
def replace(
self,
obj: Date | DateTime | Time | Offset | None = None,
*,
date: Date | None = None,
time: Time | None = None,
year: int | None = None,
era_year: tuple[int, t.Literal["BCE", "CE"]] | None = None,
month: int | None = None,
day: int | None = None,
day_of_year: int | None = None,
day_of_year_no_leap: int | None = None,
hour: int | None = None,
minute: int | None = None,
second: int | None = None,
millisecond: int | None = None,
microsecond: int | None = None,
nanosecond: int | None = None,
subsec_nanosecond: int | None = None,
offset: Offset | None = None,
offset_conflict: t.Literal[
"always-offset", "always-timezone", "prefer-offset", "reject"
]
| None = None,
disambiguation: t.Literal["compatible", "earliest", "latest", "reject"]
| None = None,
) -> t.Self: ...
def round(
self,
smallest: _ZonedDateTimeRoundSmallest = "nanosecond",
*,
mode: JiffRoundMode = "half-expand",
increment: int = 1,
) -> t.Self: ...
def _round(self, options: ZonedDateTimeRound) -> t.Self: ...
def series(self, period: TimeSpan) -> JiffSeries[t.Self]: ...
def start_of_day(self) -> t.Self: ...
def time(self) -> Time: ...
def timestamp(self) -> Timestamp: ...
def tomorrow(self) -> t.Self: ...
def with_time_zone(self, tz: TimeZone) -> t.Self: ...
def yesterday(self) -> t.Self: ...
# =========================================================================
# SINCE/UNTIL
# =========================================================================
def since(
self,
other: t.Self,
*,
smallest: JiffUnit = "nanosecond",
largest: JiffUnit | None = None,
mode: JiffRoundMode = "trunc",
increment: int = 1,
) -> TimeSpan: ...
def until(
self,
other: t.Self,
*,
smallest: JiffUnit = "nanosecond",
largest: JiffUnit | None = None,
mode: JiffRoundMode = "trunc",
increment: int = 1,
) -> TimeSpan: ...
@t.final
class ISOWeekDate(
# protocols
ToPy[pydt.date],
ToPyDate,
FromStr,
_Parse,
):
MIN: t.ClassVar[ISOWeekDate]
MAX: t.ClassVar[ISOWeekDate]
ZERO: t.ClassVar[ISOWeekDate]
def __init__(self, year: int, week: int, weekday: Weekday) -> None: ...
# =========================================================================
# OPERATORS/DUNDERS
# =========================================================================
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __lt__(self, other: ISOWeekDate) -> bool: ...
def __le__(self, other: ISOWeekDate) -> bool: ...
def __gt__(self, other: ISOWeekDate) -> bool: ...
def __ge__(self, other: ISOWeekDate) -> bool: ...
def __hash__(self) -> int: ...
# =========================================================================
# CLASS METHODS
# =========================================================================
@classmethod
def from_date(cls, date: Date) -> t.Self: ...
@classmethod
def from_pydate(cls, date: pydt.date) -> t.Self: ...
@classmethod
def from_str(cls, s: str) -> t.Self: ...
@classmethod
def parse(cls, s: str | bytes) -> t.Self: ...
@classmethod
def today(cls) -> t.Self: ...
@classmethod
def now(cls) -> t.Self: ...
# =========================================================================
# PROPERTIES
# =========================================================================
@property
def year(self) -> int: ...
@property
def week(self) -> int: ...
@property
def weekday(self) -> WeekdayInt: ...
# =========================================================================
# INSTANCE METHODS
# =========================================================================
def date(self) -> Date: ...
def to_py(self) -> pydt.date: ...
def to_pydate(self) -> pydt.date: ...
def to_string(self) -> str: ...
def to_dict(self) -> ISOWeekDateTypedDict: ...
@t.final
class Offset(
# protocols
ToPy[pydt.tzinfo],
ToPyTzInfo,
FromStr,
_Parse,
):
MIN: t.ClassVar[Offset]
MAX: t.ClassVar[Offset]
UTC: t.ClassVar[Offset]
ZERO: t.ClassVar[Offset]
def __init__(
self, hours: int | None = None, seconds: int | None = None
) -> None: ...
# =========================================================================
# STRING
# =========================================================================
def to_string(self) -> str: ...
# =========================================================================
# OPERATORS/DUNDERS
# =========================================================================
def __neg__(self) -> t.Self: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __lt__(self, other: Offset) -> bool: ...
def __le__(self, other: Offset) -> bool: ...
def __gt__(self, other: Offset) -> bool: ...
def __ge__(self, other: Offset) -> bool: ...
def __hash__(self) -> int: ...
# =========================================================================
# PYTHON CONVERSIONS
# =========================================================================
# __FROM__
@classmethod
def from_pytzinfo(cls, tz: pydt.tzinfo) -> t.Self: ...
@classmethod
def parse(cls, s: str | bytes) -> t.Self: ...
@classmethod
def from_str(cls, s: str) -> t.Self: ...
# __TO__
def to_py(self) -> pydt.tzinfo: ...
def to_pytzinfo(self) -> pydt.tzinfo: ...
def to_dict(self) -> OffsetTypedDict: ...
# =========================================================================
# PROPERTIES
# =========================================================================
@property
def seconds(self) -> int: ...
@property
def is_negative(self) -> bool: ...
@property
def is_positive(self) -> bool: ...
# =========================================================================
# FROM
# =========================================================================
@classmethod
def utc(cls) -> t.Self: ...
@classmethod
def from_hours(cls, hours: int) -> t.Self: ...
@classmethod
def from_seconds(cls, seconds: int) -> t.Self: ...
# =========================================================================
# TO
# =========================================================================
def to_datetime(self, timestamp: Timestamp) -> DateTime: ...
def to_timestamp(self, datetime: DateTime) -> Timestamp: ...
def to_timezone(self) -> TimeZone: ...
# =========================================================================
# ARITHMETIC METHODS
# =========================================================================
def add(
self, other: Duration | SignedDuration | TimeSpan | pydt.timedelta
) -> t.Self: ...
def sub(
self, other: Duration | SignedDuration | TimeSpan | pydt.timedelta
) -> t.Self: ...
def saturating_add(
self, other: Duration | SignedDuration | TimeSpan | pydt.timedelta
) -> t.Self: ...
def saturating_sub(
self, other: Duration | SignedDuration | TimeSpan | pydt.timedelta
) -> t.Self: ...
# =========================================================================
# INSTANCE METHODS
# =========================================================================
def duration_since(self, other: Offset) -> SignedDuration: ...
def duration_until(self, other: Offset) -> SignedDuration: ...
def negate(self) -> t.Self: ...
def since(self, other: t.Self) -> TimeSpan: ...
def until(self, other: t.Self) -> TimeSpan: ...
def round(
self,
smallest: _OffsetRoundSmallest = "second",
*,
mode: JiffRoundMode = "half-expand",
increment: int = 1,
) -> t.Self: ...
def _round(self, options: OffsetRound) -> t.Self: ...
# =============================================================================
# DIFFERENCE
# =============================================================================
_Tobj = t.TypeVar("_Tobj", Date, DateTime, Time, Timestamp, ZonedDateTime)
@t.type_check_only
class _Difference(t.Generic[_Tobj, _TDict]):
def __init__(
self,
obj: _Tobj,
*,
smallest: JiffUnit | None = None,
largest: JiffUnit | None = None,
mode: JiffRoundMode | None = None,
increment: int | None = None,
) -> None: ...
def __eq__(self, other: object) -> bool: ...
@property
def smallest(self) -> JiffUnit: ...
@property
def largest(self) -> JiffUnit | None: ...
@property
def mode(self) -> JiffRoundMode: ...
@property
def increment(self) -> int: ...
def _smallest(self, unit: JiffUnit) -> t.Self: ...
def _largest(self, unit: JiffUnit) -> t.Self: ...
def _mode(self, mode: JiffRoundMode) -> t.Self: ...
def _increment(self, increment: int) -> t.Self: ...
def to_dict(self) -> _TDict: ...
@t.final
class DateDifference(_Difference[Date, DateDifferenceTypedDict]):
@property
def date(self) -> Date: ...
@t.final
class DateTimeDifference(_Difference[DateTime, DateTimeDifferenceTypedDict]):
@property
def datetime(self) -> DateTime: ...
@t.final
class TimeDifference(_Difference[Time, TimeDifferenceTypedDict]):
@property
def time(self) -> Time: ...
@t.final
class TimestampDifference(_Difference[Timestamp, TimestampDifferenceTypedDict]):
@property
def timestamp(self) -> Timestamp: ...
@t.final
class ZonedDateTimeDifference(
_Difference[ZonedDateTime, ZonedDateTimeDifferenceTypedDict]
):
@property
def zoned(self) -> ZonedDateTime: ...
# =============================================================================
# ROUND
# =============================================================================
_TSmallest = t.TypeVar(
"_TSmallest",
)
@t.type_check_only
class _Round(t.Generic[_TSmallest, _TDict]):
def __eq__(self, other: object) -> bool: ...
def _mode(self, mode: JiffRoundMode) -> t.Self: ...
def _smallest(self, smallest: _TSmallest) -> t.Self: ...
def _increment(self, increment: int) -> t.Self: ...
@property
def smallest(self) -> _TSmallest: ...
@property
def mode(self) -> JiffRoundMode: ...
@property
def increment(self) -> int: ...
def replace(
self,
smallest: _TSmallest | None = None,
mode: JiffRoundMode | None = None,
increment: int | None = None,
) -> t.Self: ...
def to_dict(self) -> _TDict: ...
@t.final
class DateTimeRound(_Round[_DateTimeRoundSmallest, DateTimeRoundTypedDict]):
def __init__(
self,
smallest: _DateTimeRoundSmallest = "nanosecond",
*,
mode: JiffRoundMode = "half-expand",
increment: int = 1,
) -> None: ...
def round(self, ob: DateTime) -> DateTime: ...
@t.final
class SignedDurationRound(
_Round[_SignedDurationRoundSmallest, SignedDurationRoundTypedDict]
):
def __init__(
self,
smallest: _SignedDurationRoundSmallest = "nanosecond",
*,
mode: JiffRoundMode = "half-expand",
increment: int = 1,
) -> None: ...
def round(self, ob: SignedDuration) -> SignedDuration: ...
@t.final
class TimeRound(_Round[_TimeRoundSmallest, TimeRoundTypedDict]):
def __init__(
self,
smallest: _TimeRoundSmallest = "nanosecond",
*,
mode: JiffRoundMode = "half-expand",
increment: int = 1,
) -> None: ...
def round(self, ob: Time) -> Time: ...
@t.final
class TimestampRound(_Round[_TimestampRoundSmallest, TimestampRoundTypedDict]):
def __init__(
self,
smallest: _TimestampRoundSmallest = "nanosecond",
*,
mode: JiffRoundMode = "half-expand",
increment: int = 1,
) -> None: ...
def round(self, ob: Timestamp) -> Timestamp: ...
@t.final
class ZonedDateTimeRound(
_Round[_ZonedDateTimeRoundSmallest, ZonedDateTimeRoundTypedDict]
):
def __init__(
self,
smallest: _ZonedDateTimeRoundSmallest = "nanosecond",
*,
mode: JiffRoundMode = "half-expand",
increment: int = 1,
) -> None: ...
def round(self, ob: ZonedDateTime) -> ZonedDateTime: ...
@t.final
class OffsetRound(_Round[_OffsetRoundSmallest, OffsetRoundTypedDict]):
def __init__(
self,
smallest: _OffsetRoundSmallest = "second",
*,
mode: JiffRoundMode = "half-expand",
increment: int = 1,
) -> None: ...
def round(self, ob: Offset) -> Offset: ...
@t.type_check_only
class JiffSeries(t.Protocol[_T]):
def __iter__(self) -> JiffSeries[_T]: ...
def __next__(self) -> _T: ...
def take(self, n: int = 1) -> list[_T]: ...
def collect(self) -> list[_T]: ...
def date(year: int, month: int, day: int) -> Date: ...
def time(
hour: int = 0, minute: int = 0, second: int = 0, nanosecond: int = 0
) -> Time: ...
def datetime(
year: int,
month: int,
day: int,
hour: int = 0,
minute: int = 0,
second: int = 0,
nanosecond: int = 0,
) -> DateTime: ...
def zoned(
year: int,
month: int,
day: int,
hour: int = 0,
minute: int = 0,
second: int = 0,
nanosecond: int = 0,
tz: TimezoneName | None = None,
) -> ZonedDateTime: ...
def timespan(
*,
years: int = 0,
months: int = 0,
weeks: int = 0,
days: int = 0,
hours: int = 0,
minutes: int = 0,
seconds: int = 0,
milliseconds: int = 0,
microseconds: int = 0,
nanoseconds: int = 0,
) -> TimeSpan: ...
def offset(hours: int) -> Offset: ...
def now() -> ZonedDateTime: ...
def utcnow() -> ZonedDateTime: ...
# =============================================================================
# TIMEZONE-DATABASE
# =============================================================================
@t.final
class TimeZoneDatabase:
def __init__(self) -> None:
"""Defaults to using the `self.from_env`"""
@t.overload
def get(self, name: TimezoneName, err: t.Literal[False]) -> TimeZone | None:
"""Returns TimeZone or None if the timezone is not found"""
@t.overload
def get(self, name: TimezoneName, err: t.Literal[True] = True) -> TimeZone:
"""Returns TimeZone, if not found raises a ValueError"""
def available(self) -> list[str]: ...
def __getitem__(self, name: TimezoneName) -> TimeZone: ...
def __len__(self) -> int: ...
def is_definitively_empty(self) -> bool: ...
@classmethod
def from_env(cls) -> t.Self: ...
@classmethod
def from_dir(cls, path: str) -> t.Self: ...
@classmethod
def from_concatenated_path(cls, path: str) -> t.Self: ...
@classmethod
def bundled(cls) -> t.Self: ...
ry.ryo3._jiff_tz
from typing import Literal, TypeAlias
TimezoneDbName: TypeAlias = Literal[
"Africa/Abidjan",
"Africa/Accra",
"Africa/Addis_Ababa",
"Africa/Algiers",
"Africa/Asmara",
"Africa/Asmera",
"Africa/Bamako",
"Africa/Bangui",
"Africa/Banjul",
"Africa/Bissau",
"Africa/Blantyre",
"Africa/Brazzaville",
"Africa/Bujumbura",
"Africa/Cairo",
"Africa/Casablanca",
"Africa/Ceuta",
"Africa/Conakry",
"Africa/Dakar",
"Africa/Dar_es_Salaam",
"Africa/Djibouti",
"Africa/Douala",
"Africa/El_Aaiun",
"Africa/Freetown",
"Africa/Gaborone",
"Africa/Harare",
"Africa/Johannesburg",
"Africa/Juba",
"Africa/Kampala",
"Africa/Khartoum",
"Africa/Kigali",
"Africa/Kinshasa",
"Africa/Lagos",
"Africa/Libreville",
"Africa/Lome",
"Africa/Luanda",
"Africa/Lubumbashi",
"Africa/Lusaka",
"Africa/Malabo",
"Africa/Maputo",
"Africa/Maseru",
"Africa/Mbabane",
"Africa/Mogadishu",
"Africa/Monrovia",
"Africa/Nairobi",
"Africa/Ndjamena",
"Africa/Niamey",
"Africa/Nouakchott",
"Africa/Ouagadougou",
"Africa/Porto-Novo",
"Africa/Sao_Tome",
"Africa/Timbuktu",
"Africa/Tripoli",
"Africa/Tunis",
"Africa/Windhoek",
"America/Adak",
"America/Anchorage",
"America/Anguilla",
"America/Antigua",
"America/Araguaina",
"America/Argentina/Buenos_Aires",
"America/Argentina/Catamarca",
"America/Argentina/ComodRivadavia",
"America/Argentina/Cordoba",
"America/Argentina/Jujuy",
"America/Argentina/La_Rioja",
"America/Argentina/Mendoza",
"America/Argentina/Rio_Gallegos",
"America/Argentina/Salta",
"America/Argentina/San_Juan",
"America/Argentina/San_Luis",
"America/Argentina/Tucuman",
"America/Argentina/Ushuaia",
"America/Aruba",
"America/Asuncion",
"America/Atikokan",
"America/Atka",
"America/Bahia",
"America/Bahia_Banderas",
"America/Barbados",
"America/Belem",
"America/Belize",
"America/Blanc-Sablon",
"America/Boa_Vista",
"America/Bogota",
"America/Boise",
"America/Buenos_Aires",
"America/Cambridge_Bay",
"America/Campo_Grande",
"America/Cancun",
"America/Caracas",
"America/Catamarca",
"America/Cayenne",
"America/Cayman",
"America/Chicago",
"America/Chihuahua",
"America/Ciudad_Juarez",
"America/Coral_Harbour",
"America/Cordoba",
"America/Costa_Rica",
"America/Coyhaique",
"America/Creston",
"America/Cuiaba",
"America/Curacao",
"America/Danmarkshavn",
"America/Dawson",
"America/Dawson_Creek",
"America/Denver",
"America/Detroit",
"America/Dominica",
"America/Edmonton",
"America/Eirunepe",
"America/El_Salvador",
"America/Ensenada",
"America/Fort_Nelson",
"America/Fort_Wayne",
"America/Fortaleza",
"America/Glace_Bay",
"America/Godthab",
"America/Goose_Bay",
"America/Grand_Turk",
"America/Grenada",
"America/Guadeloupe",
"America/Guatemala",
"America/Guayaquil",
"America/Guyana",
"America/Halifax",
"America/Havana",
"America/Hermosillo",
"America/Indiana/Indianapolis",
"America/Indiana/Knox",
"America/Indiana/Marengo",
"America/Indiana/Petersburg",
"America/Indiana/Tell_City",
"America/Indiana/Vevay",
"America/Indiana/Vincennes",
"America/Indiana/Winamac",
"America/Indianapolis",
"America/Inuvik",
"America/Iqaluit",
"America/Jamaica",
"America/Jujuy",
"America/Juneau",
"America/Kentucky/Louisville",
"America/Kentucky/Monticello",
"America/Knox_IN",
"America/Kralendijk",
"America/La_Paz",
"America/Lima",
"America/Los_Angeles",
"America/Louisville",
"America/Lower_Princes",
"America/Maceio",
"America/Managua",
"America/Manaus",
"America/Marigot",
"America/Martinique",
"America/Matamoros",
"America/Mazatlan",
"America/Mendoza",
"America/Menominee",
"America/Merida",
"America/Metlakatla",
"America/Mexico_City",
"America/Miquelon",
"America/Moncton",
"America/Monterrey",
"America/Montevideo",
"America/Montreal",
"America/Montserrat",
"America/Nassau",
"America/New_York",
"America/Nipigon",
"America/Nome",
"America/Noronha",
"America/North_Dakota/Beulah",
"America/North_Dakota/Center",
"America/North_Dakota/New_Salem",
"America/Nuuk",
"America/Ojinaga",
"America/Panama",
"America/Pangnirtung",
"America/Paramaribo",
"America/Phoenix",
"America/Port-au-Prince",
"America/Port_of_Spain",
"America/Porto_Acre",
"America/Porto_Velho",
"America/Puerto_Rico",
"America/Punta_Arenas",
"America/Rainy_River",
"America/Rankin_Inlet",
"America/Recife",
"America/Regina",
"America/Resolute",
"America/Rio_Branco",
"America/Rosario",
"America/Santa_Isabel",
"America/Santarem",
"America/Santiago",
"America/Santo_Domingo",
"America/Sao_Paulo",
"America/Scoresbysund",
"America/Shiprock",
"America/Sitka",
"America/St_Barthelemy",
"America/St_Johns",
"America/St_Kitts",
"America/St_Lucia",
"America/St_Thomas",
"America/St_Vincent",
"America/Swift_Current",
"America/Tegucigalpa",
"America/Thule",
"America/Thunder_Bay",
"America/Tijuana",
"America/Toronto",
"America/Tortola",
"America/Vancouver",
"America/Virgin",
"America/Whitehorse",
"America/Winnipeg",
"America/Yakutat",
"America/Yellowknife",
"Antarctica/Casey",
"Antarctica/Davis",
"Antarctica/DumontDUrville",
"Antarctica/Macquarie",
"Antarctica/Mawson",
"Antarctica/McMurdo",
"Antarctica/Palmer",
"Antarctica/Rothera",
"Antarctica/South_Pole",
"Antarctica/Syowa",
"Antarctica/Troll",
"Antarctica/Vostok",
"Arctic/Longyearbyen",
"Asia/Aden",
"Asia/Almaty",
"Asia/Amman",
"Asia/Anadyr",
"Asia/Aqtau",
"Asia/Aqtobe",
"Asia/Ashgabat",
"Asia/Ashkhabad",
"Asia/Atyrau",
"Asia/Baghdad",
"Asia/Bahrain",
"Asia/Baku",
"Asia/Bangkok",
"Asia/Barnaul",
"Asia/Beirut",
"Asia/Bishkek",
"Asia/Brunei",
"Asia/Calcutta",
"Asia/Chita",
"Asia/Choibalsan",
"Asia/Chongqing",
"Asia/Chungking",
"Asia/Colombo",
"Asia/Dacca",
"Asia/Damascus",
"Asia/Dhaka",
"Asia/Dili",
"Asia/Dubai",
"Asia/Dushanbe",
"Asia/Famagusta",
"Asia/Gaza",
"Asia/Harbin",
"Asia/Hebron",
"Asia/Ho_Chi_Minh",
"Asia/Hong_Kong",
"Asia/Hovd",
"Asia/Irkutsk",
"Asia/Istanbul",
"Asia/Jakarta",
"Asia/Jayapura",
"Asia/Jerusalem",
"Asia/Kabul",
"Asia/Kamchatka",
"Asia/Karachi",
"Asia/Kashgar",
"Asia/Kathmandu",
"Asia/Katmandu",
"Asia/Khandyga",
"Asia/Kolkata",
"Asia/Krasnoyarsk",
"Asia/Kuala_Lumpur",
"Asia/Kuching",
"Asia/Kuwait",
"Asia/Macao",
"Asia/Macau",
"Asia/Magadan",
"Asia/Makassar",
"Asia/Manila",
"Asia/Muscat",
"Asia/Nicosia",
"Asia/Novokuznetsk",
"Asia/Novosibirsk",
"Asia/Omsk",
"Asia/Oral",
"Asia/Phnom_Penh",
"Asia/Pontianak",
"Asia/Pyongyang",
"Asia/Qatar",
"Asia/Qostanay",
"Asia/Qyzylorda",
"Asia/Rangoon",
"Asia/Riyadh",
"Asia/Saigon",
"Asia/Sakhalin",
"Asia/Samarkand",
"Asia/Seoul",
"Asia/Shanghai",
"Asia/Singapore",
"Asia/Srednekolymsk",
"Asia/Taipei",
"Asia/Tashkent",
"Asia/Tbilisi",
"Asia/Tehran",
"Asia/Tel_Aviv",
"Asia/Thimbu",
"Asia/Thimphu",
"Asia/Tokyo",
"Asia/Tomsk",
"Asia/Ujung_Pandang",
"Asia/Ulaanbaatar",
"Asia/Ulan_Bator",
"Asia/Urumqi",
"Asia/Ust-Nera",
"Asia/Vientiane",
"Asia/Vladivostok",
"Asia/Yakutsk",
"Asia/Yangon",
"Asia/Yekaterinburg",
"Asia/Yerevan",
"Atlantic/Azores",
"Atlantic/Bermuda",
"Atlantic/Canary",
"Atlantic/Cape_Verde",
"Atlantic/Faeroe",
"Atlantic/Faroe",
"Atlantic/Jan_Mayen",
"Atlantic/Madeira",
"Atlantic/Reykjavik",
"Atlantic/South_Georgia",
"Atlantic/St_Helena",
"Atlantic/Stanley",
"Australia/ACT",
"Australia/Adelaide",
"Australia/Brisbane",
"Australia/Broken_Hill",
"Australia/Canberra",
"Australia/Currie",
"Australia/Darwin",
"Australia/Eucla",
"Australia/Hobart",
"Australia/LHI",
"Australia/Lindeman",
"Australia/Lord_Howe",
"Australia/Melbourne",
"Australia/North",
"Australia/NSW",
"Australia/Perth",
"Australia/Queensland",
"Australia/South",
"Australia/Sydney",
"Australia/Tasmania",
"Australia/Victoria",
"Australia/West",
"Australia/Yancowinna",
"Brazil/Acre",
"Brazil/DeNoronha",
"Brazil/East",
"Brazil/West",
"Canada/Atlantic",
"Canada/Central",
"Canada/Eastern",
"Canada/Mountain",
"Canada/Newfoundland",
"Canada/Pacific",
"Canada/Saskatchewan",
"Canada/Yukon",
"CET",
"Chile/Continental",
"Chile/EasterIsland",
"CST6CDT",
"Cuba",
"EET",
"Egypt",
"Eire",
"EST",
"EST5EDT",
"Etc/GMT",
"Etc/GMT+0",
"Etc/GMT+1",
"Etc/GMT+10",
"Etc/GMT+11",
"Etc/GMT+12",
"Etc/GMT+2",
"Etc/GMT+3",
"Etc/GMT+4",
"Etc/GMT+5",
"Etc/GMT+6",
"Etc/GMT+7",
"Etc/GMT+8",
"Etc/GMT+9",
"Etc/GMT-0",
"Etc/GMT-1",
"Etc/GMT-10",
"Etc/GMT-11",
"Etc/GMT-12",
"Etc/GMT-13",
"Etc/GMT-14",
"Etc/GMT-2",
"Etc/GMT-3",
"Etc/GMT-4",
"Etc/GMT-5",
"Etc/GMT-6",
"Etc/GMT-7",
"Etc/GMT-8",
"Etc/GMT-9",
"Etc/GMT0",
"Etc/Greenwich",
"Etc/UCT",
"Etc/Universal",
"Etc/UTC",
"Etc/Zulu",
"Europe/Amsterdam",
"Europe/Andorra",
"Europe/Astrakhan",
"Europe/Athens",
"Europe/Belfast",
"Europe/Belgrade",
"Europe/Berlin",
"Europe/Bratislava",
"Europe/Brussels",
"Europe/Bucharest",
"Europe/Budapest",
"Europe/Busingen",
"Europe/Chisinau",
"Europe/Copenhagen",
"Europe/Dublin",
"Europe/Gibraltar",
"Europe/Guernsey",
"Europe/Helsinki",
"Europe/Isle_of_Man",
"Europe/Istanbul",
"Europe/Jersey",
"Europe/Kaliningrad",
"Europe/Kiev",
"Europe/Kirov",
"Europe/Kyiv",
"Europe/Lisbon",
"Europe/Ljubljana",
"Europe/London",
"Europe/Luxembourg",
"Europe/Madrid",
"Europe/Malta",
"Europe/Mariehamn",
"Europe/Minsk",
"Europe/Monaco",
"Europe/Moscow",
"Europe/Nicosia",
"Europe/Oslo",
"Europe/Paris",
"Europe/Podgorica",
"Europe/Prague",
"Europe/Riga",
"Europe/Rome",
"Europe/Samara",
"Europe/San_Marino",
"Europe/Sarajevo",
"Europe/Saratov",
"Europe/Simferopol",
"Europe/Skopje",
"Europe/Sofia",
"Europe/Stockholm",
"Europe/Tallinn",
"Europe/Tirane",
"Europe/Tiraspol",
"Europe/Ulyanovsk",
"Europe/Uzhgorod",
"Europe/Vaduz",
"Europe/Vatican",
"Europe/Vienna",
"Europe/Vilnius",
"Europe/Volgograd",
"Europe/Warsaw",
"Europe/Zagreb",
"Europe/Zaporozhye",
"Europe/Zurich",
"Factory",
"GB",
"GB-Eire",
"GMT",
"GMT+0",
"GMT-0",
"GMT0",
"Greenwich",
"Hongkong",
"HST",
"Iceland",
"Indian/Antananarivo",
"Indian/Chagos",
"Indian/Christmas",
"Indian/Cocos",
"Indian/Comoro",
"Indian/Kerguelen",
"Indian/Mahe",
"Indian/Maldives",
"Indian/Mauritius",
"Indian/Mayotte",
"Indian/Reunion",
"Iran",
"Israel",
"Jamaica",
"Japan",
"Kwajalein",
"Libya",
"MET",
"Mexico/BajaNorte",
"Mexico/BajaSur",
"Mexico/General",
"MST",
"MST7MDT",
"Navajo",
"NZ",
"NZ-CHAT",
"Pacific/Apia",
"Pacific/Auckland",
"Pacific/Bougainville",
"Pacific/Chatham",
"Pacific/Chuuk",
"Pacific/Easter",
"Pacific/Efate",
"Pacific/Enderbury",
"Pacific/Fakaofo",
"Pacific/Fiji",
"Pacific/Funafuti",
"Pacific/Galapagos",
"Pacific/Gambier",
"Pacific/Guadalcanal",
"Pacific/Guam",
"Pacific/Honolulu",
"Pacific/Johnston",
"Pacific/Kanton",
"Pacific/Kiritimati",
"Pacific/Kosrae",
"Pacific/Kwajalein",
"Pacific/Majuro",
"Pacific/Marquesas",
"Pacific/Midway",
"Pacific/Nauru",
"Pacific/Niue",
"Pacific/Norfolk",
"Pacific/Noumea",
"Pacific/Pago_Pago",
"Pacific/Palau",
"Pacific/Pitcairn",
"Pacific/Pohnpei",
"Pacific/Ponape",
"Pacific/Port_Moresby",
"Pacific/Rarotonga",
"Pacific/Saipan",
"Pacific/Samoa",
"Pacific/Tahiti",
"Pacific/Tarawa",
"Pacific/Tongatapu",
"Pacific/Truk",
"Pacific/Wake",
"Pacific/Wallis",
"Pacific/Yap",
"Poland",
"Portugal",
"PRC",
"PST8PDT",
"ROC",
"ROK",
"Singapore",
"Turkey",
"UCT",
"Universal",
"US/Alaska",
"US/Aleutian",
"US/Arizona",
"US/Central",
"US/East-Indiana",
"US/Eastern",
"US/Hawaii",
"US/Indiana-Starke",
"US/Michigan",
"US/Mountain",
"US/Pacific",
"US/Samoa",
"UTC",
"W-SU",
"WET",
"Zulu",
]
ry.ryo3._jiter
import typing as t
from os import PathLike
from ry._types import Buffer, Unpack
# =============================================================================
# JSON
# =============================================================================
JsonPrimitive: t.TypeAlias = None | bool | int | float | str
JsonValue: t.TypeAlias = (
JsonPrimitive
| dict[str, JsonPrimitive | JsonValue]
| list[JsonPrimitive | JsonValue]
)
class JsonParseKwargs(t.TypedDict, total=False):
allow_inf_nan: bool
"""Allow parsing of `Infinity`, `-Infinity`, `NaN` ~ default: False"""
cache_mode: t.Literal[True, False, "all", "keys", "none"]
"""Cache mode for JSON parsing ~ default: `all` """
partial_mode: t.Literal[True, False, "off", "on", "trailing-strings"]
"""Partial mode for JSON parsing ~ default: False"""
catch_duplicate_keys: bool
"""Catch duplicate keys in JSON objects ~ default: False"""
def parse_json(
data: Buffer | bytes | str,
/,
**kwargs: Unpack[JsonParseKwargs],
) -> JsonValue: ...
def parse_jsonl(
data: Buffer | bytes | str,
/,
**kwargs: Unpack[JsonParseKwargs],
) -> list[JsonValue]: ...
def read_json(
p: str | PathLike[str],
/,
lines: bool = False,
**kwargs: Unpack[JsonParseKwargs],
) -> JsonValue: ...
def json_cache_clear() -> None: ...
def json_cache_usage() -> int: ...
ry.ryo3._memchr
"""ryo3-memchr types"""
from typing import TypeAlias
from ry._types import Buffer
Byte: TypeAlias = int | bytes
def memchr(needle: Byte, haystack: Buffer) -> int | None: ...
def memchr2(needle1: Byte, needle2: Byte, haystack: Buffer) -> int | None: ...
def memchr3(
needle1: Byte, needle2: Byte, needle3: Byte, haystack: Buffer
) -> int | None: ...
def memrchr(needle: Byte, haystack: Buffer) -> int | None: ...
def memrchr2(needle1: Byte, needle2: Byte, haystack: Buffer) -> int | None: ...
def memrchr3(
needle1: Byte, needle2: Byte, needle3: Byte, haystack: Buffer
) -> int | None: ...
ry.ryo3._protocols
import typing as t
from ry._types import Buffer
class HasherProtocol(t.Protocol):
name: str
digest_size: int
block_size: int
def update(self, data: Buffer) -> None: ...
def digest(self) -> bytes: ...
def intdigest(self) -> int: ...
def hexdigest(self) -> str: ...
def copy(self) -> t.Self: ...
ry.ryo3._quick_maths
"""ryo3-quick-maths types"""
import typing as t
def quick_maths() -> t.Literal[3]:
"""Performs quick-maths
Implements the algorithm for performing "quick-maths" as described by
Big Shaq in his PHD thesis, 2017, in which he states:
> "2 plus 2 is 4, minus one that's 3, quick maths." (Big Shaq et al., 2017)
Reference:
https://youtu.be/3M_5oYU-IsU?t=60
Example:
>>> import ry
>>> result = ry.quick_maths()
>>> assert result == 3
NOTE: THIS IS FROM MY TEMPLATE RY03-MODULE
"""
ry.ryo3._regex
"""ryo3-regex types"""
import typing as t
# =============================================================================
# Regex
# =============================================================================
@t.final
class Regex:
def __init__(
self,
pattern: str,
*,
case_insensitive: bool = False,
crlf: bool = False,
dot_matches_new_line: bool = False,
ignore_whitespace: bool = False,
line_terminator: bytes | int | None = None,
multi_line: bool = False,
octal: bool = False,
size_limit: int | None = None,
swap_greed: bool = False,
unicode: bool = False,
) -> None: ...
def is_match(self, haystack: str) -> bool: ...
def test(self, haystack: str) -> bool: ...
def find(self, haystack: str) -> str | None: ...
def find_all(self, haystack: str) -> list[tuple[int, int]]: ...
def findall(self, haystack: str) -> list[tuple[int, int]]: ...
def replace(self, haystack: str, replacement: str) -> str: ...
def replace_all(self, haystack: str, replacement: str) -> str: ...
def split(self, haystack: str) -> list[str]: ...
def splitn(self, haystack: str, n: int) -> list[str]: ...
ry.ryo3._reqwest
import typing as t
import ry
from ry._types import Buffer, Unpack
from ry.protocols import FromStr, _Parse
from ry.ryo3._http import Headers, HttpStatus, HttpVersionLike
from ry.ryo3._std import Duration, SocketAddr
from ry.ryo3._url import URL
class RequestKwargs(t.TypedDict, total=False):
body: Buffer | None
headers: Headers | dict[str, str] | None
query: dict[str, t.Any] | t.Sequence[tuple[str, t.Any]] | None
json: t.Any
form: t.Any
multipart: t.Any
timeout: Duration | None
basic_auth: tuple[str, str | None] | None
bearer_auth: str | None
version: HttpVersionLike | None
class ClientConfig(t.TypedDict):
headers: Headers | None
cookies: bool
user_agent: str | None
timeout: Duration | None
connect_timeout: Duration | None
read_timeout: Duration | None
redirect: int | None
referer: bool
gzip: bool
brotli: bool
deflate: bool
zstd: bool
hickory_dns: bool
http1_only: bool
https_only: bool
http1_title_case_headers: bool
http1_allow_obsolete_multiline_headers_in_responses: bool
http1_allow_spaces_after_header_name_in_responses: bool
http1_ignore_invalid_headers_in_responses: bool
http2_prior_knowledge: bool
http2_initial_stream_window_size: int | None
http2_initial_connection_window_size: int | None
http2_adaptive_window: bool
http2_max_frame_size: int | None
http2_max_header_list_size: int | None
http2_keep_alive_interval: Duration | None
http2_keep_alive_timeout: Duration | None
http2_keep_alive_while_idle: bool
pool_idle_timeout: Duration | None
pool_max_idle_per_host: int | None
tcp_keepalive: Duration | None
tcp_keepalive_interval: Duration | None
tcp_keepalive_retries: int | None
tcp_nodelay: bool
root_certificates: list[Certificate] | None
tls_min_version: t.Literal["1.0", "1.1", "1.2", "1.3"] | None
tls_max_version: t.Literal["1.0", "1.1", "1.2", "1.3"] | None
tls_info: bool
tls_sni: bool
danger_accept_invalid_certs: bool
danger_accept_invalid_hostnames: bool
@t.final
class HttpClient:
def __init__(
self,
*,
headers: dict[str, str] | Headers | None = None,
cookies: bool = False,
user_agent: str | None = None,
timeout: Duration | None = None,
connect_timeout: Duration | None = None,
read_timeout: Duration | None = None,
redirect: int | None = 10,
referer: bool = True,
gzip: bool = True,
brotli: bool = True,
deflate: bool = True,
zstd: bool = True,
hickory_dns: bool = True,
http1_only: bool = False,
https_only: bool = False,
http1_title_case_headers: bool = False,
http1_allow_obsolete_multiline_headers_in_responses: bool = False,
http1_allow_spaces_after_header_name_in_responses: bool = False,
http1_ignore_invalid_headers_in_responses: bool = False,
http2_prior_knowledge: bool = False,
http2_initial_stream_window_size: int | None = None,
http2_initial_connection_window_size: int | None = None,
http2_adaptive_window: bool = False,
http2_max_frame_size: int | None = None,
http2_max_header_list_size: int | None = None,
http2_keep_alive_interval: Duration | None = None,
http2_keep_alive_timeout: Duration | None = None,
http2_keep_alive_while_idle: bool = False,
pool_idle_timeout: Duration | None = ..., # 90 seconds
pool_max_idle_per_host: int | None = ..., # usize::MAX
tcp_keepalive: Duration | None = ..., # 15 seconds
tcp_keepalive_interval: Duration | None = ..., # 15 seconds
tcp_keepalive_retries: int | None = 3,
tcp_nodelay: bool = True,
root_certificates: list[Certificate] | None = None,
tls_min_version: t.Literal["1.0", "1.1", "1.2", "1.3"] | None = None,
tls_max_version: t.Literal["1.0", "1.1", "1.2", "1.3"] | None = None,
tls_info: bool = False,
tls_sni: bool = True,
danger_accept_invalid_certs: bool = False,
danger_accept_invalid_hostnames: bool = False,
) -> None: ...
def config(self) -> ClientConfig: ...
async def get(
self,
url: str | URL,
**kwargs: Unpack[RequestKwargs],
) -> Response: ...
async def post(
self,
url: str | URL,
**kwargs: Unpack[RequestKwargs],
) -> Response: ...
async def put(
self,
url: str | URL,
**kwargs: Unpack[RequestKwargs],
) -> Response: ...
async def delete(
self,
url: str | URL,
**kwargs: Unpack[RequestKwargs],
) -> Response: ...
async def patch(
self,
url: str | URL,
**kwargs: Unpack[RequestKwargs],
) -> Response: ...
async def options(
self,
url: str | URL,
**kwargs: Unpack[RequestKwargs],
) -> Response: ...
async def head(
self,
url: str | URL,
**kwargs: Unpack[RequestKwargs],
) -> Response: ...
async def fetch(
self,
url: str | URL,
*,
method: str = "GET",
**kwargs: Unpack[RequestKwargs],
) -> Response: ...
def fetch_sync(
self,
url: str | URL,
*,
method: str = "GET",
**kwargs: Unpack[RequestKwargs],
) -> BlockingResponse: ...
async def __call__(
self,
url: str | URL,
*,
method: str = "GET",
**kwargs: Unpack[RequestKwargs],
) -> Response: ...
@t.final
class BlockingClient:
def __init__(
self,
*,
headers: dict[str, str] | Headers | None = None,
cookies: bool = False,
user_agent: str | None = None,
timeout: Duration | None = None,
connect_timeout: Duration | None = None,
read_timeout: Duration | None = None,
redirect: int | None = 10,
referer: bool = True,
gzip: bool = True,
brotli: bool = True,
deflate: bool = True,
zstd: bool = True,
hickory_dns: bool = True,
http1_only: bool = False,
https_only: bool = False,
http1_title_case_headers: bool = False,
http1_allow_obsolete_multiline_headers_in_responses: bool = False,
http1_allow_spaces_after_header_name_in_responses: bool = False,
http1_ignore_invalid_headers_in_responses: bool = False,
http2_prior_knowledge: bool = False,
http2_initial_stream_window_size: int | None = None,
http2_initial_connection_window_size: int | None = None,
http2_adaptive_window: bool = False,
http2_max_frame_size: int | None = None,
http2_max_header_list_size: int | None = None,
http2_keep_alive_interval: Duration | None = None,
http2_keep_alive_timeout: Duration | None = None,
http2_keep_alive_while_idle: bool = False,
pool_idle_timeout: Duration | None = ..., # 90 seconds
pool_max_idle_per_host: int | None = ..., # usize::MAX
tcp_keepalive: Duration | None = ..., # 15 seconds
tcp_keepalive_interval: Duration | None = ..., # 15 seconds
tcp_keepalive_retries: int | None = 3,
tcp_nodelay: bool = True,
root_certificates: list[Certificate] | None = None,
tls_min_version: t.Literal["1.0", "1.1", "1.2", "1.3"] | None = None,
tls_max_version: t.Literal["1.0", "1.1", "1.2", "1.3"] | None = None,
tls_info: bool = False,
tls_sni: bool = True,
danger_accept_invalid_certs: bool = False,
danger_accept_invalid_hostnames: bool = False,
) -> None: ...
def config(self) -> ClientConfig: ...
def get(
self,
url: str | URL,
**kwargs: Unpack[RequestKwargs],
) -> BlockingResponse: ...
def post(
self,
url: str | URL,
**kwargs: Unpack[RequestKwargs],
) -> BlockingResponse: ...
def put(
self,
url: str | URL,
**kwargs: Unpack[RequestKwargs],
) -> BlockingResponse: ...
def delete(
self,
url: str | URL,
**kwargs: Unpack[RequestKwargs],
) -> BlockingResponse: ...
def patch(
self,
url: str | URL,
**kwargs: Unpack[RequestKwargs],
) -> BlockingResponse: ...
def options(
self, url: str | URL, **kwargs: Unpack[RequestKwargs]
) -> BlockingResponse: ...
def head(
self,
url: str | URL,
**kwargs: Unpack[RequestKwargs],
) -> BlockingResponse: ...
def fetch(
self,
url: str | URL,
*,
method: str = "GET",
**kwargs: Unpack[RequestKwargs],
) -> BlockingResponse: ...
def __call__(
self,
url: str | URL,
*,
method: str = "GET",
**kwargs: Unpack[RequestKwargs],
) -> BlockingResponse: ...
@t.final
class ReqwestError(Exception):
def __init__(self, *args: t.Any, **kwargs: t.Any) -> None: ...
def __dbg__(self) -> str: ...
def is_body(self) -> bool: ...
def is_builder(self) -> bool: ...
def is_connect(self) -> bool: ...
def is_decode(self) -> bool: ...
def is_redirect(self) -> bool: ...
def is_request(self) -> bool: ...
def is_status(self) -> bool: ...
def is_timeout(self) -> bool: ...
def status(self) -> HttpStatus | None: ...
def url(self) -> URL | None: ...
def without_url(self) -> None: ...
def with_url(self, url: URL) -> ReqwestError: ...
@t.final
class Response:
def __init__(self) -> t.NoReturn: ...
@property
def headers(self) -> Headers: ...
async def text(self) -> str: ...
async def json(
self,
*,
allow_inf_nan: bool = False,
cache_mode: t.Literal[True, False, "all", "keys", "none"] = "all",
partial_mode: t.Literal[
True, False, "off", "on", "trailing-strings"
] = False,
catch_duplicate_keys: bool = False,
) -> t.Any: ...
async def bytes(self) -> ry.Bytes: ...
def bytes_stream(self) -> ResponseStream: ...
def stream(self) -> ResponseStream: ...
@property
def url(self) -> URL: ...
@property
def version(
self,
) -> t.Literal[
"HTTP/0.9", "HTTP/1.0", "HTTP/1.1", "HTTP/2.0", "HTTP/3.0"
]: ...
@property
def http_version(
self,
) -> t.Literal[
"HTTP/0.9", "HTTP/1.0", "HTTP/1.1", "HTTP/2.0", "HTTP/3.0"
]: ...
@property
def redirected(self) -> bool: ...
@property
def content_length(self) -> int | None: ...
@property
def content_encoding(self) -> str | None: ...
@property
def cookies(self) -> list[Cookie] | None: ...
@property
def set_cookies(self) -> list[Cookie] | None: ...
@property
def body_used(self) -> bool:
"""True if the body has been consumed"""
@property
def ok(self) -> bool:
"""True if the status is a success (2xx)"""
@property
def remote_addr(self) -> SocketAddr | None: ...
@property
def status(self) -> int: ...
@property
def status_text(self) -> str: ...
@property
def status_code(self) -> HttpStatus: ...
def __bool__(self) -> bool:
"""True if the status is a success (2xx)"""
@t.final
class BlockingResponse:
def __init__(self) -> t.NoReturn: ...
@property
def headers(self) -> Headers: ...
def text(self) -> str: ...
def json(
self,
*,
allow_inf_nan: bool = False,
cache_mode: t.Literal[True, False, "all", "keys", "none"] = "all",
partial_mode: t.Literal[
True, False, "off", "on", "trailing-strings"
] = False,
catch_duplicate_keys: bool = False,
) -> t.Any: ...
def bytes(self) -> ry.Bytes: ...
def bytes_stream(self) -> BlockingResponseStream: ...
def stream(self) -> BlockingResponseStream: ...
@property
def url(self) -> URL: ...
@property
def version(
self,
) -> t.Literal[
"HTTP/0.9", "HTTP/1.0", "HTTP/1.1", "HTTP/2.0", "HTTP/3.0"
]: ...
@property
def http_version(
self,
) -> t.Literal[
"HTTP/0.9", "HTTP/1.0", "HTTP/1.1", "HTTP/2.0", "HTTP/3.0"
]: ...
@property
def redirected(self) -> bool: ...
@property
def content_length(self) -> int | None: ...
@property
def content_encoding(self) -> str | None: ...
@property
def cookies(self) -> list[Cookie] | None: ...
@property
def set_cookies(self) -> list[Cookie] | None: ...
@property
def body_used(self) -> bool:
"""True if the body has been consumed"""
@property
def ok(self) -> bool:
"""True if the status is a success (2xx)"""
@property
def remote_addr(self) -> SocketAddr | None: ...
@property
def status(self) -> int: ...
@property
def status_text(self) -> str: ...
@property
def status_code(self) -> HttpStatus: ...
def __bool__(self) -> bool:
"""True if the status is a success (2xx)"""
@t.final
class ResponseStream:
def __aiter__(self) -> ResponseStream: ...
async def __anext__(self) -> ry.Bytes: ...
async def take(self, n: int = 1) -> list[ry.Bytes]: ...
@t.overload
async def collect(self, join: t.Literal[True]) -> ry.Bytes: ...
@t.overload
async def collect(
self, join: t.Literal[False] = False
) -> list[ry.Bytes]: ...
@t.final
class BlockingResponseStream:
def __iter__(self) -> BlockingResponseStream: ...
def __next__(self) -> ry.Bytes: ...
def take(self, n: int = 1) -> list[ry.Bytes]: ...
@t.overload
def collect(self, join: t.Literal[True]) -> ry.Bytes: ...
@t.overload
def collect(self, join: t.Literal[False] = False) -> list[ry.Bytes]: ...
async def fetch(
url: str | URL,
*,
method: str = "GET",
body: Buffer | None = None,
headers: Headers | dict[str, str] | None = None,
query: dict[str, t.Any] | t.Sequence[tuple[str, t.Any]] | None = None,
json: t.Any = None,
form: t.Any = None,
multipart: t.Any | None = None,
timeout: Duration | None = None,
basic_auth: tuple[str, str | None] | None = None,
bearer_auth: str | None = None,
version: HttpVersionLike | None = None,
) -> Response: ...
def fetch_sync(
url: str | URL,
*,
method: str = "GET",
body: Buffer | None = None,
headers: Headers | dict[str, str] | None = None,
query: dict[str, t.Any] | t.Sequence[tuple[str, t.Any]] | None = None,
json: t.Any = None,
form: t.Any = None,
multipart: t.Any | None = None,
timeout: Duration | None = None,
basic_auth: tuple[str, str | None] | None = None,
bearer_auth: str | None = None,
version: HttpVersionLike | None = None,
) -> BlockingResponse: ...
@t.final
class Cookie(FromStr, _Parse):
def __init__(
self,
name: str,
value: str,
*,
domain: str | None = None,
expires: int | None = None,
http_only: bool | None = None,
max_age: Duration | None = None,
partitioned: bool | None = None,
path: str | None = None,
permanent: bool = False,
removal: bool = False,
same_site: t.Literal["Lax", "Strict", "None"] | None = None,
secure: bool | None = None,
) -> None: ...
@classmethod
def from_str(cls, s: str) -> Cookie: ...
@classmethod
def parse(cls, s: str | bytes) -> Cookie: ...
@staticmethod
def parse_encoded(s: str) -> Cookie: ...
# -------------------------------------------------------------------------
# METHODS
# -------------------------------------------------------------------------
# -- STRING --
def encoded(self) -> str: ...
def stripped(self) -> str: ...
def encoded_stripped(self) -> str: ...
def stripped_encoded(self) -> str: ...
# -------------------------------------------------------------------------
# PROPERTIES
# -------------------------------------------------------------------------
@property
def name(self) -> str: ...
@property
def value(self) -> str: ...
@property
def value_trimmed(self) -> str: ...
@property
def name_value(self) -> tuple[str, str]: ...
@property
def name_value_trimmed(self) -> tuple[str, str]: ...
@property
def domain(self) -> str | None: ...
@property
def expires(self) -> int | None: ...
@property
def http_only(self) -> bool | None: ...
@property
def max_age(self) -> Duration | None: ...
@property
def partitioned(self) -> bool | None: ...
@property
def path(self) -> str | None: ...
@property
def same_site(self) -> t.Literal["Lax", "Strict", "None"] | None: ...
@property
def secure(self) -> bool | None: ...
@t.final
class Certificate:
def __init__(self) -> t.NoReturn: ...
def __hash__(self) -> int: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
@staticmethod
def from_der(der: Buffer) -> Certificate: ...
@staticmethod
def from_pem(pem: Buffer) -> Certificate: ...
@staticmethod
def from_pem_bundle(pem_bundle: Buffer) -> list[Certificate]: ...
ry.ryo3._same_file
"""ryo3-same-file types"""
from os import PathLike
def is_same_file(left: PathLike[str], right: PathLike[str]) -> bool: ...
ry.ryo3._shlex
"""ryo3-shlex types"""
def shplit(s: str) -> list[str]:
"""shlex::split wrapper much like python's stdlib shlex.split but faster"""
ry.ryo3._size
import builtins
import typing as t
from ry.protocols import FromStr, _Parse
FormatSizeBase: t.TypeAlias = t.Literal[2, 10] # default=2
FormatSizeStyle: t.TypeAlias = t.Literal[ # default="default"
"default",
"abbreviated",
"abbreviated_lowercase",
"abbreviated-lowercase",
"full",
"full-lowercase",
"full_lowercase",
]
def fmt_size(
n: int,
*,
base: FormatSizeBase = 2,
style: FormatSizeStyle = "default",
) -> str:
"""Return human-readable string representation of bytes-size."""
def parse_size(s: str) -> int:
"""Return integer representation of human-readable bytes-size string.
Raises:
ValueError: If string is not a valid human-readable bytes-size string.
"""
@t.final
class SizeFormatter:
"""Human-readable bytes-size formatter."""
def __init__(
self,
base: FormatSizeBase = 2,
style: FormatSizeStyle = "default",
) -> None:
"""Initialize human-readable bytes-size formatter."""
def format(self, n: int) -> str:
"""Return human-readable string representation of bytes-size."""
def __call__(self, n: int) -> str:
"""Return human-readable string representation of bytes-size."""
@t.final
class Size(FromStr, _Parse):
"""Bytes-size object."""
def __init__(self, size: int) -> None: ...
@property
def bytes(self) -> int: ...
def format(
self,
*,
base: FormatSizeBase = 2,
style: FormatSizeStyle = "default",
) -> str: ...
# =========================================================================
# CLASS-METHODS
# =========================================================================
# -------------------------------------------------------------------------
# PARSING
# -------------------------------------------------------------------------
@classmethod
def parse(cls, s: str | builtins.bytes) -> Size: ...
@classmethod
def from_str(cls, s: str) -> Size: ...
# -------------------------------------------------------------------------
# BYTES
# -------------------------------------------------------------------------
@classmethod
def from_bytes(cls, size: float) -> Size: ...
# -------------------------------------------------------------------------
# KILOBYTES
# -------------------------------------------------------------------------
@classmethod
def from_kb(cls, size: float) -> Size: ...
@classmethod
def from_kib(cls, size: float) -> Size: ...
@classmethod
def from_kibibytes(cls, size: float) -> Size: ...
@classmethod
def from_kilobytes(cls, size: float) -> Size: ...
# -------------------------------------------------------------------------
# MEGABYTES
# -------------------------------------------------------------------------
@classmethod
def from_mb(cls, size: float) -> Size: ...
@classmethod
def from_mebibytes(cls, size: float) -> Size: ...
@classmethod
def from_megabytes(cls, size: float) -> Size: ...
@classmethod
def from_mib(cls, size: float) -> Size: ...
# -------------------------------------------------------------------------
# GIGABYTES
# -------------------------------------------------------------------------
@classmethod
def from_gb(cls, size: float) -> Size: ...
@classmethod
def from_gib(cls, size: float) -> Size: ...
@classmethod
def from_gibibytes(cls, size: float) -> Size: ...
@classmethod
def from_gigabytes(cls, size: float) -> Size: ...
# -------------------------------------------------------------------------
# TERABYTES
# -------------------------------------------------------------------------
@classmethod
def from_tb(cls, size: float) -> Size: ...
@classmethod
def from_tebibytes(cls, size: float) -> Size: ...
@classmethod
def from_terabytes(cls, size: float) -> Size: ...
@classmethod
def from_tib(cls, size: float) -> Size: ...
# -------------------------------------------------------------------------
# PETABYTES
# -------------------------------------------------------------------------
@classmethod
def from_pb(cls, size: float) -> Size: ...
@classmethod
def from_pebibytes(cls, size: float) -> Size: ...
@classmethod
def from_petabytes(cls, size: float) -> Size: ...
@classmethod
def from_pib(cls, size: float) -> Size: ...
# -------------------------------------------------------------------------
# EXABYTES
# -------------------------------------------------------------------------
@classmethod
def from_eb(cls, size: float) -> Size: ...
@classmethod
def from_eib(cls, size: float) -> Size: ...
@classmethod
def from_exabytes(cls, size: float) -> Size: ...
@classmethod
def from_exbibytes(cls, size: float) -> Size: ...
# =========================================================================
# DUNDERS
# =========================================================================
def __add__(self, other: Size | float) -> Size: ...
def __sub__(self, other: Size | float) -> Size: ...
def __mul__(self, other: Size | float) -> Size: ...
def __rmul__(self, other: Size | float) -> Size: ...
def __neg__(self) -> Size: ...
def __pos__(self) -> Size: ...
def __abs__(self) -> Size: ...
def __invert__(self) -> Size: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __lt__(self, other: Size | float) -> bool: ...
def __le__(self, other: Size | float) -> bool: ...
def __gt__(self, other: Size | float) -> bool: ...
def __ge__(self, other: Size | float) -> bool: ...
def __hash__(self) -> int: ...
def __bool__(self) -> bool: ...
def __int__(self) -> int: ...
ry.ryo3._sqlformat
"""ryo3-sqlformat types"""
import typing as t
Dialect: t.TypeAlias = t.Literal["generic", "postgresql", "sqlserver"]
Indent: t.TypeAlias = t.Literal["tabs", "\t"] | int
SqlfmtParamValue: t.TypeAlias = str | int | float | bool
_TSqlfmtParamValue_co = t.TypeVar(
"_TSqlfmtParamValue_co", bound=SqlfmtParamValue, covariant=True
)
SqlfmtParamsLike: t.TypeAlias = (
dict[str, _TSqlfmtParamValue_co]
| t.Sequence[tuple[str, _TSqlfmtParamValue_co]]
| t.Sequence[_TSqlfmtParamValue_co]
)
@t.final
class SqlfmtQueryParams:
def __init__(
self, params: SqlfmtParamsLike[_TSqlfmtParamValue_co]
) -> None: ...
def __len__(self) -> int: ...
def sqlfmt_params(
params: SqlfmtParamsLike[_TSqlfmtParamValue_co]
| SqlfmtQueryParams
| None = None,
) -> SqlfmtQueryParams: ...
def sqlfmt(
sql: str,
params: SqlfmtParamsLike[_TSqlfmtParamValue_co]
| SqlfmtQueryParams
| None = None,
*,
indent: int | t.Literal["tabs", "\t"] = 2,
uppercase: bool | None = None,
lines_between_queries: int = 1,
ignore_case_convert: list[str] | None = None,
inline: bool = False,
max_inline_block: int = 50,
max_inline_arguments: int | None = None,
max_inline_top_level: int | None = None,
joins_as_top_level: bool = False,
dialect: t.Literal["generic", "postgresql", "sqlserver"] = "generic",
) -> str: ...
class _SqlFormatterDict(t.TypedDict):
indent: int | t.Literal["tabs"]
uppercase: bool | None
lines_between_queries: int
ignore_case_convert: list[str] | None
inline: bool
max_inline_block: int
max_inline_arguments: int | None
max_inline_top_level: int | None
joins_as_top_level: bool
dialect: t.Literal["generic", "postgresql", "sqlserver"]
@t.final
class SqlFormatter:
def __init__(
self,
*,
indent: int | t.Literal["tabs", "\t"] = 2,
uppercase: bool | None = None,
lines_between_queries: int = 1,
ignore_case_convert: list[str] | None = None,
inline: bool = False,
max_inline_block: int = 50,
max_inline_arguments: int | None = None,
max_inline_top_level: int | None = None,
joins_as_top_level: bool = False,
dialect: t.Literal["generic", "postgresql", "sqlserver"] = "generic",
) -> None: ...
def to_dict(self) -> _SqlFormatterDict: ...
def fmt(
self,
sql: str,
params: SqlfmtParamsLike[_TSqlfmtParamValue_co]
| SqlfmtQueryParams
| None = None,
) -> str: ...
def __call__(
self,
sql: str,
params: SqlfmtParamsLike[_TSqlfmtParamValue_co]
| SqlfmtQueryParams
| None = None,
) -> str: ...
def __eq__(self, value: object) -> bool: ...
def __ne__(self, value: object) -> bool: ...
ry.ryo3._std
"""ryo3-std types"""
import datetime as pydt
import ipaddress
import pathlib
import typing as t
from ry._types import (
Buffer,
DurationDict,
FileTypeDict,
FsPathLike,
MetadataDict,
)
from ry.protocols import (
FromStr,
RyIterator,
ToPy,
ToPyTimeDelta,
ToString,
_Parse,
)
from ry.ryo3._bytes import Bytes
# =============================================================================
# STD::TIME
# =============================================================================
@t.final
class Duration(ToPy[pydt.timedelta], ToPyTimeDelta, ToString, FromStr, _Parse):
ZERO: t.ClassVar[Duration]
MIN: t.ClassVar[Duration]
MAX: t.ClassVar[Duration]
NANOSECOND: t.ClassVar[Duration]
MICROSECOND: t.ClassVar[Duration]
MILLISECOND: t.ClassVar[Duration]
SECOND: t.ClassVar[Duration]
def __init__(self, secs: int = 0, nanos: int = 0) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __add__(self, other: t.Self | pydt.timedelta) -> t.Self: ...
def __sub__(self, other: t.Self | pydt.timedelta) -> t.Self: ...
def __radd__(self, other: t.Self | pydt.timedelta) -> t.Self: ...
def __rsub__(self, other: t.Self | pydt.timedelta) -> t.Self: ...
def __lt__(self, other: t.Self) -> bool: ...
def __le__(self, other: t.Self) -> bool: ...
def __gt__(self, other: t.Self) -> bool: ...
def __ge__(self, other: t.Self) -> bool: ...
def __hash__(self) -> int: ...
def __richcmp__(self, other: t.Self | pydt.timedelta, op: int) -> bool: ...
def __bool__(self) -> bool: ...
def __float__(self) -> float: ...
def __int__(self) -> int: ...
@t.overload
def __truediv__(self, other: t.Self | pydt.timedelta) -> float: ...
@t.overload
def __truediv__(self, other: float) -> t.Self: ...
@t.overload
def __rtruediv__(self, other: t.Self | pydt.timedelta) -> float: ...
@t.overload
def __rtruediv__(self, other: float) -> t.Self: ...
def __mul__(self, other: float) -> t.Self: ...
def __rmul__(self, other: float) -> t.Self: ...
def abs_diff(self, other: t.Self | pydt.timedelta) -> t.Self: ...
def sleep(self, *, interval: int = 10) -> None: ...
# =========================================================================
# PYTHON_CONVERSIONS
# =========================================================================
@classmethod
def from_pytimedelta(cls, delta: pydt.timedelta) -> t.Self: ...
def to_pytimedelta(self) -> pydt.timedelta: ...
def to_py(self) -> pydt.timedelta: ...
def to_dict(self) -> DurationDict: ...
@classmethod
def from_dict(cls, d: DurationDict) -> t.Self: ...
# =========================================================================
# TO/FROM STRING(s)
# =========================================================================
def to_string(self) -> str: ...
def isoformat(self) -> str: ...
@classmethod
def fromisoformat(cls, s: str) -> t.Self: ...
def friendly(
self,
designator: t.Literal[
"compact", "human", "human-time", "short", "verbose"
] = "compact",
) -> str: ...
@classmethod
def from_str(cls, s: str) -> t.Self: ...
@classmethod
def parse(cls, s: str | bytes) -> t.Self: ...
# =========================================================================
# PROPERTIES
# =========================================================================
@property
def is_zero(self) -> bool: ...
@property
def nanos(self) -> int: ...
@property
def nanoseconds(self) -> int:
"""Alias for .nanos"""
@property
def ns(self) -> int:
"""Alias for .nanos"""
@property
def secs(self) -> int: ...
@property
def days(self) -> int: ...
@property
def seconds(self) -> int: ...
@property
def seconds_remainder(self) -> int: ...
@property
def microseconds(self) -> int: ...
@property
def subsec_micros(self) -> int: ...
@property
def subsec_millis(self) -> int: ...
@property
def subsec_nanos(self) -> int: ...
# =========================================================================
# CLASSMETHODS
# =========================================================================
@classmethod
def from_hours(cls, hours: int) -> t.Self: ...
@classmethod
def from_micros(cls, micros: int) -> t.Self: ...
@classmethod
def from_millis(cls, millis: int) -> t.Self: ...
@classmethod
def from_mins(cls, mins: int) -> t.Self: ...
@classmethod
def from_nanos(cls, nanos: int) -> t.Self: ...
@classmethod
def from_secs(cls, secs: int) -> t.Self: ...
@classmethod
def from_secs_f32(cls, secs: float) -> t.Self: ...
@classmethod
def from_secs_f64(cls, secs: float) -> t.Self: ...
@classmethod
def from_days(cls, days: int) -> t.Self: ...
@classmethod
def from_weeks(cls, weeks: int) -> t.Self: ...
def as_micros(self) -> int: ...
def as_millis(self) -> int: ...
def as_nanos(self) -> int: ...
def as_secs(self) -> int: ...
def as_secs_f32(self) -> float: ...
def as_secs_f64(self) -> float: ...
# =========================================================================
# ARITHMETIC
# =========================================================================
def checked_add(self, other: t.Self) -> t.Self | None: ...
def checked_div(self, other: int) -> t.Self | None: ...
def checked_mul(self, other: float) -> t.Self | None: ...
def checked_sub(self, other: t.Self) -> t.Self | None: ...
def div_duration_f32(self, other: t.Self) -> float: ...
def div_duration_f64(self, other: t.Self) -> float: ...
def div_f32(self, n: float) -> t.Self: ...
def div_f64(self, n: float) -> t.Self: ...
def mul_f32(self, n: float) -> t.Self: ...
def mul_f64(self, n: float) -> t.Self: ...
def saturating_add(self, other: t.Self) -> t.Self: ...
def saturating_mul(self, other: int) -> t.Self: ...
def saturating_sub(self, other: t.Self) -> t.Self: ...
@t.final
class Instant:
def __init__(self) -> None: ...
@classmethod
def now(cls) -> Instant: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __lt__(self, other: Instant) -> bool: ...
def __le__(self, other: Instant) -> bool: ...
def __gt__(self, other: Instant) -> bool: ...
def __ge__(self, other: Instant) -> bool: ...
def __hash__(self) -> int: ...
def __add__(self, other: Duration) -> t.Self: ...
@t.overload
def __sub__(self, other: Duration) -> t.Self: ...
@t.overload
def __sub__(self, other: t.Self) -> Duration: ...
# =========================================================================
# INSTANCE METHODS
# =========================================================================
def checked_add(self, other: Duration) -> t.Self | None: ...
def checked_duration_since(self, earlier: t.Self) -> Duration | None: ...
def checked_sub(self, other: Duration) -> t.Self | None: ...
def duration_since(self, earlier: t.Self) -> Duration: ...
def elapsed(self) -> Duration: ...
def saturating_duration_since(self, earlier: t.Self) -> Duration: ...
def duration(secs: int = 0, nanos: int = 0) -> Duration:
"""constructor alias for Duration"""
def instant() -> Instant:
"""constructor alias for Instant"""
def sleep(secs: float) -> float:
"""sleep for given seconds
Args:
secs: number of seconds to sleep
Returns:
number of seconds actually slept
Raises:
ValueError: if secs is negative
OverflowError: if NaN or secs is too large to convert to a duration
"""
# =============================================================================
# STD::FS
# =============================================================================
@t.final
class FileType(ToPy[t.Literal["file", "dir", "symlink"]]):
def __init__(
self,
t: t.Literal[
"f", "file", "d", "dir", "directory", "l", "symlink", "link"
],
) -> None: ...
@property
def is_dir(self) -> bool: ...
@property
def is_file(self) -> bool: ...
@property
def is_symlink(self) -> bool: ...
def to_dict(self) -> FileTypeDict: ...
def to_py(self) -> t.Literal["file", "dir", "symlink"]: ...
@t.final
class Permissions:
@property
def readonly(self) -> bool: ...
def __eq__(self, value: object) -> bool: ...
def __ne__(self, value: object) -> bool: ...
@t.final
class Metadata:
def __init__(self) -> t.NoReturn: ...
@property
def file_type(self) -> FileType: ...
@property
def len(self) -> int: ...
@property
def is_empty(self) -> bool: ...
@property
def modified(self) -> pydt.datetime: ...
@property
def accessed(self) -> pydt.datetime: ...
@property
def created(self) -> pydt.datetime: ...
@property
def is_dir(self) -> bool: ...
@property
def is_file(self) -> bool: ...
@property
def is_symlink(self) -> bool: ...
@property
def permissions(self) -> Permissions: ...
@property
def readonly(self) -> bool: ...
def to_py(self) -> MetadataDict: ...
@t.final
class DirEntry:
def __init__(self) -> t.NoReturn: ...
def __fspath__(self) -> str: ...
@property
def path(self) -> pathlib.Path: ...
@property
def basename(self) -> str: ...
@property
def metadata(self) -> Metadata: ...
@property
def file_type(self) -> FileType: ...
@t.final
class ReadDir(RyIterator[DirEntry]):
def __init__(self) -> t.NoReturn: ...
def __iter__(self) -> t.Self: ...
def __next__(self) -> DirEntry: ...
def collect(self) -> list[DirEntry]: ...
def take(self, n: int = 1) -> list[DirEntry]: ...
@t.final
class FileReadStream(RyIterator[Bytes]):
def __init__(
self,
path: FsPathLike,
*,
chunk_size: int = 65536,
offset: int = 0,
buffered: bool = True,
strict: bool = True,
) -> None:
"""Return a FileReadStream
Args:
path: path-like object
chunk_size: chunk size. Defaults to 65536.
offset: offset to start reading from. Defaults to 0.
buffered: whether the stream is buffered. Defaults to True.
strict: whether to raise a ValueError on offset beyond EOF. Defaults to True.
Raises:
FileNotFoundError: If file does not exist.
IsADirectoryError: If path is a directory.
ValueError: If offset is beyond EOF and strict is True.
"""
def __iter__(self) -> t.Self: ...
def __next__(self) -> Bytes: ...
def collect(self) -> list[Bytes]: ...
def take(self, n: int = 1) -> list[Bytes]: ...
# ============================================================================
# STD::FS ~ functions
# =============================================================================
def canonicalize(path: FsPathLike) -> pathlib.Path: ...
def copy(from_path: FsPathLike, to_path: FsPathLike) -> int: ...
def create_dir(path: FsPathLike) -> None: ...
def create_dir_all(path: FsPathLike) -> None: ...
def exists(path: FsPathLike) -> bool: ...
def hard_link(original: FsPathLike, link: FsPathLike) -> None: ...
def is_dir(path: FsPathLike) -> bool: ...
def is_file(path: FsPathLike) -> bool: ...
def is_symlink(path: FsPathLike) -> bool: ...
def metadata(path: FsPathLike) -> Metadata: ...
def read(path: FsPathLike) -> Bytes: ...
def read_bytes(path: FsPathLike) -> bytes: ...
def read_dir(path: FsPathLike) -> ReadDir: ...
def read_link(path: FsPathLike) -> pathlib.Path: ...
def read_stream(
path: FsPathLike,
chunk_size: int = 65536,
*,
offset: int = 0,
buffered: bool = True,
strict: bool = True,
) -> FileReadStream:
"""Return a FileReadStream
Args:
path: path-like object
chunk_size: chunk size. Defaults to 65536.
offset: offset to start reading from. Defaults to 0.
buffered: whether the stream is buffered. Defaults to True.
strict: whether to raise a ValueError on offset beyond EOF. Defaults to True.
Raises:
FileNotFoundError: If file does not exist.
IsADirectoryError: If path is a directory.
ValueError: If offset is beyond EOF and strict is True.
"""
def read_text(path: FsPathLike) -> str: ...
def read_str(path: FsPathLike) -> str: ...
def read_to_string(path: FsPathLike) -> str: ...
def remove_dir(path: FsPathLike) -> None: ...
def remove_dir_all(path: FsPathLike) -> None: ...
def remove_file(path: FsPathLike) -> None: ...
def rename(from_path: FsPathLike, to_path: FsPathLike) -> None: ...
def set_permissions(path: FsPathLike, perm: Permissions) -> None: ...
def soft_link(original: FsPathLike, link: FsPathLike) -> None: ...
def symlink_metadata(path: FsPathLike) -> Metadata: ...
def write(path: FsPathLike, data: Buffer | str) -> int: ...
def write_bytes(path: FsPathLike, buf: bytes) -> int: ...
def write_text(path: FsPathLike, s: str) -> int: ...
# =============================================================================
# STD::NET
# =============================================================================
class _Version4(t.Protocol):
@property
def version(self) -> t.Literal[4]: ...
class _Version6(t.Protocol):
@property
def version(self) -> t.Literal[6]: ...
class _Version(t.Protocol):
@property
def version(self) -> t.Literal[4, 6]: ...
class _Ipv4AddrProperties(t.Protocol):
@property
def is_benchmarking(self) -> bool: ...
@property
def is_broadcast(self) -> bool: ...
@property
def is_documentation(self) -> bool: ...
@property
def is_global(self) -> t.NoReturn: ...
@property
def is_link_local(self) -> bool: ...
@property
def is_loopback(self) -> bool: ...
@property
def is_multicast(self) -> bool: ...
@property
def is_private(self) -> bool: ...
@property
def is_reserved(self) -> bool: ...
@property
def is_shared(self) -> bool: ...
@property
def is_unspecified(self) -> bool: ...
@property
def is_unicast(self) -> bool: ...
_T_ipaddress_co = t.TypeVar(
"_T_ipaddress_co",
bound=ipaddress.IPv4Address | ipaddress.IPv6Address,
covariant=True,
)
class ToPyIpAddress(t.Protocol[_T_ipaddress_co]):
def to_pyipaddress(self) -> _T_ipaddress_co: ...
@t.final
class Ipv4Addr(
_Ipv4AddrProperties,
_Version4,
FromStr,
_Parse,
ToPy[ipaddress.IPv4Address],
ToPyIpAddress[ipaddress.IPv4Address],
):
BROADCAST: Ipv4Addr
LOCALHOST: Ipv4Addr
UNSPECIFIED: Ipv4Addr
@t.overload
def __init__(self, a: int, b: int, c: int, d: int) -> None: ...
@t.overload
def __init__(
self, iplike: int | str | bytes | Ipv4Addr | ipaddress.IPv4Address
) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __lt__(self, other: Ipv4Addr) -> bool: ...
def __le__(self, other: Ipv4Addr) -> bool: ...
def __gt__(self, other: Ipv4Addr) -> bool: ...
def __ge__(self, other: Ipv4Addr) -> bool: ...
def __hash__(self) -> int: ...
def to_py(self) -> ipaddress.IPv4Address: ...
@property
def version(self) -> t.Literal[4]: ...
@property
def is_documentation(self) -> bool: ...
# ========================================================================
# CLASSMETHODS
# ========================================================================
@classmethod
def from_str(cls, s: str) -> Ipv4Addr: ...
@classmethod
def parse(cls, s: str | bytes) -> Ipv4Addr: ...
@classmethod
def from_bits(cls, bits: int) -> Ipv4Addr: ...
@classmethod
def from_octets(cls, a: int, b: int, c: int, d: int) -> Ipv4Addr: ...
# =======================================================================
# METHODS
# =======================================================================
def to_ipaddr(self) -> IpAddr: ...
def to_socketaddr_v4(self, port: int) -> SocketAddrV4: ...
def to_socketaddr_v6(
self, port: int, flowinfo: int = 0, scope_id: int = 0
) -> SocketAddrV6: ...
class _Ipv6AddrProperties(t.Protocol):
# ========================================================================
# PROPERTIES
# ========================================================================
@property
def is_benchmarking(self) -> bool: ...
@property
def is_global(self) -> t.NoReturn: ...
@property
def is_ipv4_mapped(self) -> bool: ...
@property
def is_loopback(self) -> bool: ...
@property
def is_multicast(self) -> bool: ...
@property
def is_reserved(self) -> bool: ...
@property
def is_shared(self) -> bool: ...
@property
def is_unicast(self) -> bool: ...
@property
def is_unicast_global(self) -> t.NoReturn: ...
@property
def is_unicast_link_local(self) -> bool: ...
@property
def is_unique_local(self) -> bool: ...
@property
def is_unspecified(self) -> bool: ...
@t.final
class Ipv6Addr(
_Ipv6AddrProperties,
_Version6,
FromStr,
_Parse,
ToPy[ipaddress.IPv6Address],
ToPyIpAddress[ipaddress.IPv6Address],
):
LOCALHOST: Ipv6Addr
UNSPECIFIED: Ipv6Addr
@t.overload
def __init__(
self, a: int, b: int, c: int, d: int, e: int, f: int, g: int, h: int
) -> None: ...
@t.overload
def __init__(
self, iplike: int | str | bytes | Ipv6Addr | ipaddress.IPv6Address
) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __lt__(self, other: Ipv6Addr) -> bool: ...
def __le__(self, other: Ipv6Addr) -> bool: ...
def __gt__(self, other: Ipv6Addr) -> bool: ...
def __ge__(self, other: Ipv6Addr) -> bool: ...
def __hash__(self) -> int: ...
def to_py(self) -> ipaddress.IPv6Address: ...
@property
def version(self) -> t.Literal[6]: ...
@property
def is_documentation(self) -> t.NoReturn: ...
# ========================================================================
# CLASSMETHODS
# ========================================================================
@classmethod
def from_str(cls, s: str) -> Ipv6Addr: ...
@classmethod
def parse(cls, s: str | bytes) -> Ipv6Addr: ...
@classmethod
def from_bits(cls, bits: int) -> IpAddr: ...
# =======================================================================
# METHODS
# =======================================================================
def to_ipaddr(self) -> IpAddr: ...
def to_socketaddr_v4(self, port: int) -> SocketAddrV4: ...
def to_socketaddr_v6(
self, port: int, flowinfo: int = 0, scope_id: int = 0
) -> SocketAddrV6: ...
@t.final
class IpAddr(
_Ipv4AddrProperties,
_Ipv6AddrProperties,
_Version,
FromStr,
_Parse,
ToPy[ipaddress.IPv4Address | ipaddress.IPv6Address],
ToPyIpAddress[ipaddress.IPv4Address | ipaddress.IPv6Address],
):
BROADCAST: IpAddr
LOCALHOST_V4: IpAddr
UNSPECIFIED_V4: IpAddr
LOCALHOST_V6: IpAddr
UNSPECIFIED_V6: IpAddr
def __init__(
self,
iplike: int
| str
| bytes
| Ipv4Addr
| Ipv6Addr
| ipaddress.IPv4Address
| ipaddress.IPv6Address,
) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __lt__(self, other: IpAddr) -> bool: ...
def __le__(self, other: IpAddr) -> bool: ...
def __gt__(self, other: IpAddr) -> bool: ...
def __ge__(self, other: IpAddr) -> bool: ...
def __hash__(self) -> int: ...
def to_py(self) -> ipaddress.IPv4Address | ipaddress.IPv6Address: ...
def to_ipv4(self) -> Ipv4Addr: ...
def to_ipv6(self) -> Ipv6Addr: ...
# =========================================================================
# CLASSMETHODS
# =========================================================================
@classmethod
def from_str(cls, s: str) -> IpAddr: ...
@classmethod
def parse(cls, s: str | bytes) -> IpAddr: ...
# ========================================================================
# PROPERTIES
# ========================================================================
@property
def version(self) -> t.Literal[4, 6]: ...
@property
def is_benchmarking(self) -> t.NoReturn: ...
@property
def is_ipv4(self) -> bool: ...
@property
def is_ipv6(self) -> bool: ...
@property
def is_broadcast(self) -> bool: ...
@property
def is_documentation(self) -> bool: ...
@property
def is_loopback(self) -> bool: ...
@property
def is_multicast(self) -> bool: ...
@property
def is_private(self) -> bool: ...
@property
def is_unspecified(self) -> bool: ...
# =======================================================================
# METHODS
# =======================================================================
def to_canonical(self) -> IpAddr: ...
@t.final
class SocketAddrV4(
_Ipv4AddrProperties,
_Version4,
# protocols
FromStr,
_Parse,
ToPyIpAddress[ipaddress.IPv4Address],
):
def __init__(
self,
ip: IpAddr | Ipv4Addr | ipaddress.IPv4Address | ipaddress.IPv6Address,
port: int,
) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __lt__(self, other: SocketAddrV4) -> bool: ...
def __le__(self, other: SocketAddrV4) -> bool: ...
def __gt__(self, other: SocketAddrV4) -> bool: ...
def __ge__(self, other: SocketAddrV4) -> bool: ...
def __hash__(self) -> int: ...
def to_ipaddrv4(self) -> Ipv4Addr: ...
def to_ipaddr(self) -> IpAddr: ...
@classmethod
def from_str(cls, s: str) -> t.Self: ...
@classmethod
def parse(cls, s: str | bytes) -> t.Self: ...
@property
def port(self) -> int: ...
@property
def ip(self) -> Ipv4Addr: ...
@t.final
class SocketAddrV6(
_Ipv6AddrProperties,
_Version6,
# protocols
ToPyIpAddress[ipaddress.IPv6Address],
FromStr,
_Parse,
):
def __init__(
self,
ip: IpAddr | Ipv6Addr | ipaddress.IPv4Address | ipaddress.IPv6Address,
port: int,
) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __lt__(self, other: SocketAddrV6) -> bool: ...
def __le__(self, other: SocketAddrV6) -> bool: ...
def __gt__(self, other: SocketAddrV6) -> bool: ...
def __ge__(self, other: SocketAddrV6) -> bool: ...
def __hash__(self) -> int: ...
def to_ipaddrv6(self) -> Ipv6Addr: ...
def to_ipaddr(self) -> IpAddr: ...
@classmethod
def from_str(cls, s: str) -> t.Self: ...
@classmethod
def parse(cls, s: str | bytes) -> t.Self: ...
@property
def port(self) -> int: ...
@property
def ip(self) -> Ipv6Addr: ...
@property
def is_documentation(self) -> t.NoReturn: ...
@t.final
class SocketAddr(
_Ipv4AddrProperties,
_Ipv6AddrProperties,
_Version,
# protocols
FromStr,
_Parse,
ToPyIpAddress[ipaddress.IPv4Address | ipaddress.IPv6Address],
):
def __init__(
self,
ip: IpAddr
| Ipv4Addr
| Ipv6Addr
| ipaddress.IPv4Address
| ipaddress.IPv6Address,
port: int,
) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __lt__(self, other: SocketAddr) -> bool: ...
def __le__(self, other: SocketAddr) -> bool: ...
def __gt__(self, other: SocketAddr) -> bool: ...
def __ge__(self, other: SocketAddr) -> bool: ...
def __hash__(self) -> int: ...
@classmethod
def from_str(cls, s: str) -> SocketAddr: ...
@classmethod
def parse(cls, s: str | bytes) -> SocketAddr: ...
def to_ipaddr(self) -> IpAddr: ...
@property
def is_ipv4(self) -> bool: ...
@property
def is_ipv6(self) -> bool: ...
@property
def ip(self) -> IpAddr: ...
@property
def port(self) -> int: ...
ry.ryo3._std_constants
from typing import Literal
# ruff: noqa: PYI054
# u8
U8_BITS: Literal[8]
U8_MAX: Literal[255]
U8_MIN: Literal[0]
# i8
I8_BITS: Literal[8]
I8_MAX: Literal[127]
I8_MIN: Literal[-128]
# i16
I16_BITS: Literal[16]
I16_MAX: Literal[32_767]
I16_MIN: Literal[-32_768]
# u16
U16_BITS: Literal[16]
U16_MAX: Literal[65_535]
U16_MIN: Literal[0]
# u32
U32_BITS: Literal[32]
U32_MAX: Literal[4_294_967_295]
U32_MIN: Literal[0]
# i32
I32_BITS: Literal[32]
I32_MAX: Literal[2_147_483_647]
I32_MIN: Literal[-2_147_483_648]
# u64
U64_BITS: Literal[64]
U64_MAX: Literal[18_446_744_073_709_551_615]
U64_MIN: Literal[0]
# i64
I64_BITS: Literal[64]
I64_MAX: Literal[9_223_372_036_854_775_807]
I64_MIN: Literal[-9_223_372_036_854_775_808]
# u128
U128_BITS: Literal[128]
U128_MAX: Literal[340_282_366_920_938_463_463_374_607_431_768_211_455]
U128_MIN: Literal[0]
# i128
I128_BITS: Literal[128]
I128_MAX: Literal[170_141_183_460_469_231_731_687_303_715_884_105_727]
I128_MIN: Literal[-170_141_183_460_469_231_731_687_303_715_884_105_728]
# usize
USIZE_BITS: Literal[32, 64]
USIZE_MAX: Literal[4_294_967_295, 18_446_744_073_709_551_615]
USIZE_MIN: Literal[0]
# isize
ISIZE_BITS: Literal[32, 64]
ISIZE_MAX: Literal[2_147_483_647, 9_223_372_036_854_775_807]
ISIZE_MIN: Literal[-2_147_483_648, -9_223_372_036_854_775_808]
ry.ryo3._tokio
"""ryo4-tokio types"""
import pathlib
import sys
import typing as t
from collections.abc import Generator
from types import TracebackType
from ry import Bytes
from ry._types import Buffer, FsPathLike, OpenBinaryMode
from ry.ryo3._std import FileType, Metadata
if sys.version_info >= (3, 13):
from warnings import deprecated
else:
from typing_extensions import deprecated
# =============================================================================
# FS
# =============================================================================
async def canonicalize_async(path: FsPathLike) -> FsPathLike: ...
async def copy_async(src: FsPathLike, dst: FsPathLike) -> None: ...
async def create_dir_async(path: FsPathLike) -> None: ...
async def create_dir_all_async(path: FsPathLike) -> None: ...
async def hard_link_async(src: FsPathLike, dst: FsPathLike) -> None: ...
async def metadata_async(path: FsPathLike) -> None: ...
async def read_async(path: FsPathLike) -> Bytes: ...
async def remove_dir_async(path: FsPathLike) -> None: ...
async def remove_dir_all_async(path: FsPathLike) -> None: ...
async def remove_file_async(path: FsPathLike) -> None: ...
async def read_link_async(path: FsPathLike) -> FsPathLike: ...
async def read_to_string_async(path: FsPathLike) -> str: ...
async def rename_async(src: FsPathLike, dst: FsPathLike) -> None: ...
async def write_async(path: FsPathLike, buf: Buffer) -> None: ...
async def try_exists_async(path: FsPathLike) -> bool: ...
async def exists_async(path: FsPathLike) -> bool: ...
@t.final
class AsyncDirEntry:
def __fspath__(self) -> str: ...
@property
def path(self) -> pathlib.Path: ...
@property
def basename(self) -> str: ...
@property
async def metadata(self) -> Metadata: ...
@property
async def file_type(self) -> FileType: ...
@t.final
class AsyncReadDir:
"""Async iterator for read_dir_async"""
async def collect(self) -> list[AsyncDirEntry]: ...
async def take(self, n: int) -> list[AsyncDirEntry]: ...
def __aiter__(self) -> AsyncReadDir: ...
async def __anext__(self) -> AsyncDirEntry: ...
async def read_dir_async(path: FsPathLike) -> AsyncReadDir: ...
# =============================================================================
# SLEEP
# =============================================================================
async def sleep_async(secs: float) -> float: ...
async def asleep(secs: float) -> float:
"""Alias for sleep_async"""
# =============================================================================
# ASYNC-FILE
# =============================================================================
@t.final
class AsyncFile:
def __init__(
self, path: FsPathLike, mode: OpenBinaryMode = "rb", buffering: int = -1
) -> None: ...
async def close(self) -> None: ...
async def flush(self) -> None: ...
async def isatty(self) -> t.NoReturn: ...
async def open(self) -> None: ...
async def peek(self, size: int = ..., /) -> Bytes: ...
async def read(self, size: int | None = None, /) -> Bytes: ...
async def readable(self) -> bool: ...
async def readall(self) -> Bytes: ...
async def readline(self, size: int | None = None, /) -> Bytes: ...
async def readlines(self, hint: int | None = None, /) -> list[Bytes]: ...
async def seek(self, offset: int, whence: int = ..., /) -> int: ...
async def seekable(self) -> bool: ...
async def tell(self) -> int: ...
async def truncate(self, pos: int | None = None, /) -> int: ...
async def writable(self) -> bool: ...
async def write(self, b: Buffer, /) -> int: ...
@property
def closed(self) -> bool: ...
def __await__(self) -> Generator[t.Any, t.Any, t.Self]: ...
def __aiter__(self) -> t.Self: ...
async def __anext__(self) -> Bytes: ...
async def __aenter__(self) -> t.Self: ...
async def __aexit__(
self,
exc_type: type[BaseException] | None,
exc_val: BaseException | None,
exc_tb: TracebackType | None,
) -> None: ...
def aopen(
path: FsPathLike, mode: OpenBinaryMode | str = "rb", buffering: int = -1
) -> AsyncFile: ...
@deprecated("`aiopen` is deprecated, use `aopen` instead")
def aiopen(
path: FsPathLike, mode: OpenBinaryMode | str = "rb", buffering: int = -1
) -> AsyncFile: ...
ry.ryo3._unindent
"""ryo3-unindent types"""
def unindent(s: str, /) -> str: ...
def unindent_bytes(b: bytes, /) -> bytes: ...
ry.ryo3._url
import sys
import typing as t
from ipaddress import IPv4Address, IPv6Address
from ry._types import FsPathLike
from ry.protocols import FromStr
from ry.ryo3._std import IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr
if sys.version_info >= (3, 13):
from warnings import deprecated
else:
from typing_extensions import deprecated
@t.final
class URL(FromStr):
def __init__(
self, url: str | bytes | URL, *, params: dict[str, str] | None = None
) -> None: ...
# =========================================================================
# CLASSMETHODS
# =========================================================================
@classmethod
def parse(
cls, url: str | bytes, *, params: dict[str, str] | None = None
) -> t.Self: ...
@classmethod
def from_str(cls, s: str) -> t.Self: ...
@classmethod
def parse_with_params(
cls, url: str | bytes, params: dict[str, str]
) -> t.Self: ...
@classmethod
def from_directory_path(cls, path: FsPathLike) -> t.Self: ...
@classmethod
def from_filepath(cls, path: FsPathLike) -> t.Self: ...
# =========================================================================
# STRING
# =========================================================================
def __fspath__(self) -> str: ...
# =========================================================================
# PROPERTIES
# =========================================================================
@property
def authority(self) -> str: ...
@property
def domain(self) -> str | None: ...
@property
def fragment(self) -> str | None: ...
@property
def host(self) -> str | Ipv4Addr | Ipv6Addr | None: ...
@property
def host_str(self) -> str | None: ...
@property
def netloc(self) -> str: ...
@property
def password(self) -> str | None: ...
@property
def path(self) -> str: ...
@property
def path_segments(self) -> tuple[str, ...]: ...
@property
def port(self) -> int | None: ...
@property
def port_or_known_default(self) -> int | None: ...
@property
def query(self) -> str | None: ...
@property
def query_string(self) -> str: ...
@property
def query_pairs(self) -> tuple[tuple[str, str], ...]: ...
@property
def scheme(self) -> str: ...
@property
def user(self) -> str:
"""alias for yarl compatibility"""
@property
def username(self) -> str: ...
@property
def origin(self) -> str: ...
# =========================================================================
# INSTANCE METHODS
# =========================================================================
def has_authority(self) -> bool: ...
def has_host(self) -> bool: ...
def is_special(self) -> bool: ...
def join(self, *parts: str) -> URL: ...
def make_relative(self, other: URL) -> t.Self: ...
@deprecated(
"`replace_*` methods are deprecated, use `with_*` methods instead"
)
def replace_fragment(self, fragment: str | None = None) -> t.Self: ...
@deprecated(
"`replace_*` methods are deprecated, use `with_*` methods instead"
)
def replace_host(self, host: str | None = None) -> t.Self: ...
@deprecated(
"`replace_*` methods are deprecated, use `with_*` methods instead"
)
def replace_ip_host(
self, address: IPv4Address | IPv6Address | Ipv4Addr | Ipv6Addr | IpAddr
) -> t.Self: ...
@deprecated(
"`replace_*` methods are deprecated, use `with_*` methods instead"
)
def replace_password(self, password: str | None = None) -> t.Self: ...
@deprecated(
"`replace_*` methods are deprecated, use `with_*` methods instead"
)
def replace_path(self, path: str) -> t.Self: ...
@deprecated(
"`replace_*` methods are deprecated, use `with_*` methods instead"
)
def replace_port(self, port: int | None = None) -> t.Self: ...
@deprecated(
"`replace_*` methods are deprecated, use `with_*` methods instead"
)
def replace_query(self, query: str | None = None) -> t.Self: ...
@deprecated(
"`replace_*` methods are deprecated, use `with_*` methods instead"
)
def replace_scheme(self, scheme: str) -> t.Self: ...
@deprecated(
"`replace_*` methods are deprecated, use `with_*` methods instead"
)
def replace_username(self, username: str) -> t.Self: ...
def socket_addrs(
self, default_port_number: int | None = None
) -> list[SocketAddr]: ...
def to_filepath(self) -> str: ...
def replace(
self,
*,
fragment: str | None = None,
host: str | None = None,
ip_host: IPv4Address
| IPv6Address
| Ipv4Addr
| Ipv6Addr
| IpAddr
| None = None,
password: str | None = None,
path: str | None = None,
port: int | None = None,
query: str | None = None,
scheme: str | None = None,
username: str | None = None,
) -> t.Self: ...
def with_fragment(self, fragment: str | None = None) -> t.Self: ...
def with_host(self, host: str | None = None) -> t.Self: ...
def with_ip_host(
self, address: IPv4Address | IPv6Address | Ipv4Addr | Ipv6Addr | IpAddr
) -> t.Self: ...
def with_password(self, password: str | None = None) -> t.Self: ...
def with_path(self, path: str) -> t.Self: ...
def with_port(self, port: int | None = None) -> t.Self: ...
def with_query(self, query: str | None = None) -> t.Self: ...
def with_scheme(self, scheme: str) -> t.Self: ...
def with_username(self, username: str) -> t.Self: ...
# =========================================================================
# OPERATORS/DUNDER
# =========================================================================
def __len__(self) -> int: ...
def __truediv__(self, relative: str) -> t.Self: ...
def __rtruediv__(self, relative: str) -> t.Self: ...
def __lt__(self, other: t.Self) -> bool: ...
def __le__(self, other: t.Self) -> bool: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __gt__(self, other: t.Self) -> bool: ...
def __ge__(self, other: t.Self) -> bool: ...
def __hash__(self) -> int: ...
ry.ryo3._walkdir
"""ryo3-walkdir types"""
import typing as t
from os import PathLike
from ry import FileType, FsPath, Glob, GlobSet, Globster
from ry.protocols import RyIterator
@t.final
class WalkDirEntry:
def __fspath__(self) -> str: ...
@property
def path(self) -> FsPath: ...
@property
def file_name(self) -> str: ...
@property
def depth(self) -> int: ...
@property
def path_is_symlink(self) -> bool: ...
@property
def file_type(self) -> FileType: ...
@property
def is_dir(self) -> bool: ...
@property
def is_file(self) -> bool: ...
@property
def is_symlink(self) -> bool: ...
@property
def len(self) -> int: ...
_T_walkdir = t.TypeVar(
"_T_walkdir",
bound=WalkDirEntry | str,
)
@t.final
class WalkdirGen(RyIterator[_T_walkdir]):
"""walkdir::Walkdir iterable wrapper"""
def __init__(self) -> t.NoReturn: ...
def __iter__(self) -> t.Self: ...
def __next__(self) -> _T_walkdir: ...
def collect(self) -> list[_T_walkdir]: ...
def take(self, n: int = 1) -> list[_T_walkdir]: ...
@t.overload
def walkdir(
path: str | PathLike[str] | None = None,
/,
*,
files: bool = True,
dirs: bool = True,
contents_first: bool = False,
min_depth: int = 0,
max_depth: int | None = None,
follow_links: bool = False,
follow_root_links: bool = True,
same_file_system: bool = False,
sort_by_file_name: bool = False,
glob: Glob | GlobSet | Globster | t.Sequence[str] | str | None = None,
objects: t.Literal[True],
) -> WalkdirGen[WalkDirEntry]: ...
@t.overload
def walkdir(
path: str | PathLike[str] | None = None,
/,
*,
objects: t.Literal[False] = False,
files: bool = True,
dirs: bool = True,
contents_first: bool = False,
min_depth: int = 0,
max_depth: int | None = None,
follow_links: bool = False,
follow_root_links: bool = True,
same_file_system: bool = False,
sort_by_file_name: bool = False,
glob: Glob | GlobSet | Globster | t.Sequence[str] | str | None = None,
) -> WalkdirGen[str]: ...
ry.ryo3._which
"""ryo3-which types"""
from pathlib import Path
from ry.ryo3._regex import Regex
def which(cmd: str, path: None | str = None) -> Path | None: ...
def which_all(cmd: str, path: None | str = None) -> list[Path]: ...
def which_re(regex: str | Regex, path: None | str = None) -> list[Path]: ...
ry.ryo3._zstd
"""ry.ryo3 root level zstd exports"""
from ry.ryo3.zstd import compress as zstd_compress
from ry.ryo3.zstd import decode as zstd_decode
from ry.ryo3.zstd import decompress as zstd_decompress
from ry.ryo3.zstd import encode as zstd_encode
from ry.ryo3.zstd import is_zstd as is_zstd
__all__ = (
"is_zstd",
"zstd_compress",
"zstd_decode",
"zstd_decompress",
"zstd_encode",
)
ry.ryo3.dirs
def audio() -> str | None: ...
def audio_dir() -> str | None: ...
def cache() -> str | None: ...
def cache_dir() -> str | None: ...
def config() -> str | None: ...
def config_dir() -> str | None: ...
def config_local() -> str | None: ...
def config_local_dir() -> str | None: ...
def data() -> str | None: ...
def data_dir() -> str | None: ...
def data_local() -> str | None: ...
def data_local_dir() -> str | None: ...
def desktop() -> str | None: ...
def desktop_dir() -> str | None: ...
def document() -> str | None: ...
def document_dir() -> str | None: ...
def download() -> str | None: ...
def download_dir() -> str | None: ...
def executable() -> str | None: ...
def executable_dir() -> str | None: ...
def font() -> str | None: ...
def font_dir() -> str | None: ...
def home() -> str | None: ...
def home_dir() -> str | None: ...
def picture() -> str | None: ...
def picture_dir() -> str | None: ...
def preference() -> str | None: ...
def preference_dir() -> str | None: ...
def public() -> str | None: ...
def public_dir() -> str | None: ...
def runtime() -> str | None: ...
def runtime_dir() -> str | None: ...
def state() -> str | None: ...
def state_dir() -> str | None: ...
def template() -> str | None: ...
def template_dir() -> str | None: ...
def video() -> str | None: ...
def video_dir() -> str | None: ...
ry.ryo3.errors
class FeatureNotEnabledError(RuntimeError):
"""Raised when a feature is not enabled in the current build."""
ry.ryo3.JSON
"""ry.ryo3.JSON"""
import typing as t
from ry._types import Buffer, Unpack
from ry.ryo3._bytes import Bytes
from ry.ryo3._jiter import JsonParseKwargs, JsonValue
def minify(buf: Buffer | str, /) -> Bytes:
"""Return minified json data (remove whitespace, newlines)
Args:
data: The JSON data to minify.
Returns:
Minified JSON data as a `Bytes` object.
Examples:
>>> import json as pyjson
>>> from ry.ryo3 import JSON
>>> data = {"key": "value", "number": 123, "bool": True}
>>> json_str = pyjson.dumps(data, indent=2)
>>> print(json_str)
{
"key": "value",
"number": 123,
"bool": true
}
>>> bytes(JSON.minify(json_str))
b'{"key":"value","number":123,"bool":true}'
"""
def fmt(buf: Buffer | str, /) -> Bytes:
"""Return minified json data (remove whitespace, newlines)
Args:
data: The JSON data to minify.
Returns:
Minified JSON data as a `Bytes` object.
Examples:
>>> import json as pyjson
>>> from ry.ryo3 import JSON
>>> data = {"key": "value", "number": 123, "bool": True}
>>> json_str = pyjson.dumps(data, indent=2)
>>> print(json_str)
{
"key": "value",
"number": 123,
"bool": true
}
>>> bytes(JSON.fmt(json_str)).decode()
'{\n "key": "value",\n "number": 123,\n "bool": true\n}'
>>> print(bytes(JSON.fmt(json_str)).decode())
{
"key": "value",
"number": 123,
"bool": true
}
"""
@t.overload
def stringify(
obj: t.Any,
*,
default: t.Callable[[t.Any], t.Any] | None = None,
fmt: bool = False,
sort_keys: bool = False,
append_newline: bool = False,
pybytes: t.Literal[True],
) -> bytes: ...
@t.overload
def stringify(
obj: t.Any,
*,
default: t.Callable[[t.Any], t.Any] | None = None,
fmt: bool = False,
sort_keys: bool = False,
append_newline: bool = False,
pybytes: t.Literal[False] = False,
) -> Bytes: ...
@t.overload
def dumps(
obj: t.Any,
*,
default: t.Callable[[t.Any], t.Any] | None = None,
fmt: bool = False,
sort_keys: bool = False,
append_newline: bool = False,
pybytes: t.Literal[True],
) -> bytes: ...
@t.overload
def dumps(
obj: t.Any,
*,
default: t.Callable[[t.Any], t.Any] | None = None,
fmt: bool = False,
sort_keys: bool = False,
append_newline: bool = False,
pybytes: t.Literal[False] = False,
) -> Bytes: ...
def loads(
data: Buffer | bytes | str,
/,
**kwargs: Unpack[JsonParseKwargs],
) -> JsonValue: ...
def parse(
data: Buffer | bytes | str,
/,
**kwargs: Unpack[JsonParseKwargs],
) -> JsonValue: ...
def cache_clear() -> None: ...
def cache_usage() -> int: ...
# under construction
def stringify_unsafe(
obj: t.Any,
*,
default: t.Callable[[t.Any], t.Any] | None = None,
fmt: bool = False,
sort_keys: bool = False,
append_newline: bool = False,
pybytes: bool = False,
) -> t.NoReturn: ...
ry.ryo3.orjson
"""orjson + ry types
orjson-types: https://github.com/ijl/orjson/blob/master/pysrc/orjson/__init__.pyi
"""
import typing as t
import orjson
def orjson_default(obj: t.Any) -> orjson.Fragment:
"""Fn to be used with `orjson.dumps` to serialize ry-compatible types
Example:
>>> import orjson
>>> from ry import orjson_default, Date
>>> data = {"key": "value", "date": Date(2023, 10, 1)}
>>> orjson.dumps(data, default=orjson_default)
b'{"key":"value","date":"2023-10-01"}'
"""
ry.ryo3.sh
import typing as t
from os import PathLike
from ry.ryo3._fspath import FsPath
def pwd() -> str: ...
def home() -> str: ...
def cd(path: str | PathLike[str]) -> None: ...
@t.overload
def ls(
path: str | PathLike[str] | None = None, # defaults to '.' if None
*,
absolute: bool = False,
sort: bool = False,
objects: t.Literal[False] = False,
) -> list[str]:
"""List directory contents - returns list of strings"""
@t.overload
def ls(
path: str | PathLike[str] | None = None, # defaults to '.' if None
*,
absolute: bool = False,
sort: bool = False,
objects: t.Literal[True],
) -> list[FsPath]:
"""List directory contents - returns list of FsPath objects"""
def mkdir(
path: str | PathLike[str],
*,
exist_ok: bool = False,
recursive: bool = False,
) -> None: ...
def mkdirp(path: str | PathLike[str]) -> None: ...
ry.ryo3.ulid
import builtins
import datetime as pydt
import typing as t
import uuid
from collections.abc import Callable as Callable
from pydantic import GetCoreSchemaHandler as GetCoreSchemaHandler
from pydantic import (
ValidatorFunctionWrapHandler as ValidatorFunctionWrapHandler,
)
from pydantic_core import CoreSchema as CoreSchema
from ry.protocols import FromStr
@t.final
class ULID(FromStr):
def __init__(self, value: builtins.bytes | str | None = None) -> None: ...
# ----------------
# INSTANCE METHODS
# ----------------
def to_bytes(self) -> builtins.bytes: ...
def to_uuid(self) -> uuid.UUID: ...
def to_uuid4(self) -> uuid.UUID: ...
# ----------
# PROPERTIES
# ----------
@property
def bytes(self) -> builtins.bytes: ...
@property
def milliseconds(self) -> int: ...
@property
def timestamp(self) -> float: ...
@property
def datetime(self) -> pydt.datetime: ...
@property
def hex(self) -> str: ...
# -------------
# CLASS METHODS
# -------------
@classmethod
def from_datetime(cls, value: pydt.datetime) -> ULID: ...
@classmethod
def from_timestamp(cls, value: float) -> ULID: ...
@classmethod
def from_timestamp_seconds(cls, value: float) -> ULID: ...
@classmethod
def from_timestamp_milliseconds(cls, value: int) -> ULID: ...
@classmethod
def from_uuid(cls, uu: uuid.UUID) -> ULID: ...
@classmethod
def from_bytes(cls, b: builtins.bytes) -> ULID: ...
@classmethod
def from_hex(cls, hexstr: str) -> ULID: ...
@classmethod
def from_str(cls, s: str) -> ULID: ...
@classmethod
def from_string(cls, s: str) -> ULID:
"""Alias for `from_str` to match python-ulid lib"""
@classmethod
def from_int(cls, i: int) -> ULID: ...
@classmethod
def parse(cls, value: t.Any) -> ULID: ...
# -------
# DUNDERS
# -------
def __int__(self) -> int: ...
def __bytes__(self) -> builtins.bytes: ...
def __lt__(self, other: int | str | ULID | builtins.bytes) -> bool: ...
def __le__(self, other: int | str | ULID | builtins.bytes) -> bool: ...
def __eq__(self, other: object) -> bool: ...
def __gt__(self, other: int | str | ULID | builtins.bytes) -> bool: ...
def __ge__(self, other: int | str | ULID | builtins.bytes) -> bool: ...
def __hash__(self) -> int: ...
# --------
# PYDANTIC
# --------
@classmethod
def __get_pydantic_core_schema__(
cls, source: t.Any, handler: GetCoreSchemaHandler
) -> CoreSchema: ...
ry.ryo3.uuid
"""ryo3-uuid types
based on typeshed types for python's builtin uuid module
REF: https://github.com/python/typeshed/blob/main/stdlib/uuid.pyi
"""
import builtins
import typing as t
import uuid as pyuuid
from enum import Enum
from ry._types import Buffer
from ry.protocols import FromStr
_FieldsType: t.TypeAlias = tuple[int, int, int, int, int, int]
class SafeUUID(Enum):
safe = 0
unsafe = -1
unknown = None
@t.final
class UUID(FromStr):
NAMESPACE_DNS: UUID
NAMESPACE_URL: UUID
NAMESPACE_OID: UUID
NAMESPACE_X500: UUID
def __init__(
self,
hex: str | None = None, # noqa: A002
bytes: builtins.bytes | None = None, # noqa: A002
bytes_le: builtins.bytes | None = None,
fields: _FieldsType | None = None,
int: builtins.int | None = None, # noqa: A002
version: builtins.int | None = None,
*,
is_safe: SafeUUID = ...,
) -> None: ...
@property
def is_nil(self) -> bool: ...
@property
def bytes(self) -> builtins.bytes: ...
@property
def bytes_le(self) -> builtins.bytes: ...
@property
def clock_seq(self) -> builtins.int: ...
@property
def clock_seq_hi_variant(self) -> builtins.int: ...
@property
def clock_seq_low(self) -> builtins.int: ...
@property
def fields(self) -> _FieldsType: ...
@property
def hex(self) -> str: ...
@property
def int(self) -> builtins.int: ...
@property
def node(self) -> builtins.int: ...
@property
def time(self) -> builtins.int: ...
@property
def time_hi_version(self) -> builtins.int: ...
@property
def time_low(self) -> builtins.int: ...
@property
def time_mid(self) -> builtins.int: ...
@property
def urn(self) -> str: ...
@property
def variant(self) -> str: ...
@property
def version(self) -> builtins.int | None: ...
def to_py(self) -> pyuuid.UUID: ...
def to_string(self) -> str: ...
# --- CLASSMETHODS --
@classmethod
def from_bytes(cls, b: builtins.bytes) -> t.Self: ...
@classmethod
def from_bytes_le(cls, b: builtins.bytes) -> t.Self: ...
@classmethod
def from_fields(cls, fields: _FieldsType) -> t.Self: ...
@classmethod
def from_hex(cls, hexstr: str) -> t.Self: ...
@classmethod
def from_int(cls, i: builtins.int) -> t.Self: ...
@classmethod
def from_pyuuid(cls, ob: pyuuid.UUID) -> t.Self: ...
@classmethod
def from_str(cls, s: str) -> t.Self: ...
# --- DUNDERS ---
def __bytes__(self) -> builtins.bytes: ...
def __lt__(self, other: UUID) -> bool: ...
def __le__(self, other: UUID) -> bool: ...
def __eq__(self, other: object) -> bool: ...
def __gt__(self, other: UUID) -> bool: ...
def __ge__(self, other: UUID) -> bool: ...
def __hash__(self) -> builtins.int: ...
def __int__(self) -> builtins.int: ...
def getnode() -> builtins.int: ...
def uuid1(node: int | None = None, clock_seq: int | None = None) -> UUID: ...
def uuid3(namespace: UUID, name: str | builtins.bytes) -> UUID: ...
def uuid4() -> UUID: ...
def uuid5(namespace: UUID, name: str | builtins.bytes) -> UUID: ...
def uuid6(node: int | None = None, clock_seq: int | None = None) -> UUID: ...
def uuid7(timestamp: int | None = None) -> UUID: ...
@t.overload
def uuid8(*, buf: Buffer) -> UUID: ... # 16 bytes buffer
@t.overload
def uuid8(
a: int | None = None,
b: int | None = None,
c: int | None = None,
*,
buf: None = None,
) -> UUID: ...
NAMESPACE_DNS: UUID
NAMESPACE_URL: UUID
NAMESPACE_OID: UUID
NAMESPACE_X500: UUID
RESERVED_NCS: str
RFC_4122: str
RESERVED_MICROSOFT: str
RESERVED_FUTURE: str
ry.ryo3.xxhash
import typing as t
from ry._types import Buffer
@t.final
class xxh32: # noqa: N801
name: t.Literal["xxh32"]
digest_size: t.Literal[4]
block_size: t.Literal[16]
def __init__(self, data: Buffer = ..., *, seed: int = 0) -> None: ...
def update(self, data: Buffer) -> None: ...
def digest(self) -> bytes: ...
def hexdigest(self) -> str: ...
def intdigest(self) -> int: ...
def copy(self) -> t.Self: ...
def reset(self, *, seed: int | None = None) -> None: ...
@property
def seed(self) -> int: ...
@staticmethod
def oneshot(data: Buffer, *, seed: int = 0) -> int: ...
@t.final
class xxh64: # noqa: N801
name: t.Literal["xxh64"]
digest_size: t.Literal[8]
block_size: t.Literal[32]
def __init__(
self, data: Buffer | None = None, *, seed: int = 0
) -> None: ...
def update(self, data: Buffer) -> None: ...
def digest(self) -> bytes: ...
def hexdigest(self) -> str: ...
def intdigest(self) -> int: ...
def copy(self) -> t.Self: ...
def reset(self, *, seed: int | None = None) -> None: ...
@property
def seed(self) -> int: ...
@staticmethod
def oneshot(data: Buffer, *, seed: int = 0) -> int: ...
@t.final
class xxh3_64: # noqa: N801
name: t.Literal["xxh3_64"]
digest_size: t.Literal[8]
block_size: t.Literal[32]
def __init__(
self,
data: Buffer = ...,
*,
seed: int = 0,
secret: bytes | None = ...,
) -> None: ...
def update(self, data: Buffer) -> None: ...
def digest(self) -> bytes: ...
def hexdigest(self) -> str: ...
def intdigest(self) -> int: ...
@property
def seed(self) -> int: ...
def copy(self) -> t.Self: ...
def reset(self, *, seed: int | None = None) -> None: ...
@staticmethod
def oneshot(
data: Buffer, *, seed: int = 0, secret: bytes | None = None
) -> int: ...
@t.final
class xxh3_128: # noqa: N801
name: t.Literal["xxh3_128"]
digest_size: t.Literal[16]
block_size: t.Literal[64]
def __init__(
self,
data: Buffer = ...,
*,
seed: int | None = ...,
secret: bytes | None = ...,
) -> None: ...
def update(self, data: Buffer) -> None: ...
def digest(self) -> bytes: ...
def hexdigest(self) -> str: ...
def intdigest(self) -> int: ...
@property
def seed(self) -> int: ...
def copy(self) -> t.Self: ...
def reset(self, *, seed: int | None = None) -> None: ...
@staticmethod
def oneshot(
data: Buffer, *, seed: int = 0, secret: bytes | None = None
) -> int: ...
xxh128 = xxh3_128
# -----------------------------------------------------------------------------
# ONE-SHOT FUNCTIONS
# -----------------------------------------------------------------------------
# xxh32
def xxh32_digest(data: Buffer, *, seed: int = 0) -> bytes: ...
def xxh32_hexdigest(data: Buffer, *, seed: int = 0) -> str: ...
def xxh32_intdigest(data: Buffer, *, seed: int = 0) -> int: ...
# xxh64
def xxh64_digest(data: Buffer, *, seed: int = 0) -> bytes: ...
def xxh64_hexdigest(data: Buffer, *, seed: int = 0) -> str: ...
def xxh64_intdigest(data: Buffer, *, seed: int = 0) -> int: ...
# xxh3
def xxh3_64_digest(
data: Buffer, *, seed: int = 0, secret: bytes | None = None
) -> bytes: ...
def xxh3_64_intdigest(
data: Buffer, *, seed: int = 0, secret: bytes | None = None
) -> int: ...
def xxh3_64_hexdigest(
data: Buffer, *, seed: int = 0, secret: bytes | None = None
) -> str: ...
# xxh128
def xxh3_128_digest(
data: Buffer, *, seed: int = 0, secret: bytes | None = None
) -> bytes: ...
def xxh3_128_intdigest(
data: Buffer, *, seed: int = 0, secret: bytes | None = None
) -> int: ...
def xxh3_128_hexdigest(
data: Buffer, *, seed: int = 0, secret: bytes | None = None
) -> str: ...
# xxh128
def xxh128_digest(
data: Buffer, *, seed: int = 0, secret: bytes | None = None
) -> bytes: ...
def xxh128_hexdigest(
data: Buffer, *, seed: int = 0, secret: bytes | None = None
) -> str: ...
def xxh128_intdigest(
data: Buffer, *, seed: int = 0, secret: bytes | None = None
) -> int: ...
ry.ryo3.zstd
"""ryo3-zstd types"""
from typing import Literal, TypeAlias
from ry import Bytes
from ry._types import Buffer
__zstd_version__: str # zstd version string ("1.5.7" as of 2025-03-14)
BLOCKSIZELOG_MAX: int
BLOCKSIZE_MAX: int
CLEVEL_DEFAULT: int # default=3 (as of 2025-03-14)
CONTENTSIZE_ERROR: int
CONTENTSIZE_UNKNOWN: int
MAGICNUMBER: int
MAGIC_DICTIONARY: int
MAGIC_SKIPPABLE_MASK: int
MAGIC_SKIPPABLE_START: int
VERSION_MAJOR: int
VERSION_MINOR: int
VERSION_NUMBER: int
VERSION_RELEASE: int
_Quality: TypeAlias = Literal[
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
]
# __COMPRESSION__
def compress(data: Buffer, level: _Quality = 3) -> Bytes: ...
def encode(data: Buffer, level: _Quality = 3) -> Bytes: ...
def zstd(data: Buffer, level: _Quality = 3) -> Bytes: ...
# __DECOMPRESSION__
def decode(data: Buffer) -> Bytes: ...
def decompress(data: Buffer) -> Bytes: ...
def unzstd(data: Buffer) -> Bytes: ...
# __MAGIC__
def is_zstd(data: Buffer) -> bool: ...
ry._types
"""ry-types"""
from __future__ import annotations
import sys
from os import PathLike
from typing import TYPE_CHECKING, Literal, TypeAlias
if TYPE_CHECKING:
import datetime as pydt
if sys.version_info >= (3, 12): # pragma: no cover
from collections.abc import Buffer
from typing import TypedDict, Unpack
else: # pragma: no cover
from typing_extensions import Buffer, TypedDict, Unpack
__all__ = (
"Buffer",
"DateDifferenceTypedDict",
"DateTimeDifferenceTypedDict",
"DateTimeRoundTypedDict",
"DateTimeTypedDict",
"DateTimeTypedDict",
"DateTypedDict",
"DateTypedDict",
"DurationDict",
"FileTypeDict",
"FsPathLike",
"ISOWeekDateTypedDict",
"JiffRoundMode",
"JiffUnit",
"MetadataDict",
"OffsetInfoDict",
"OffsetRoundTypedDict",
"SignedDurationRoundTypedDict",
"TimeDifferenceTypedDict",
"TimeRoundTypedDict",
"TimeSpanTypedDict",
"TimeTypedDict",
"TimestampDifferenceTypedDict",
"TimestampRoundTypedDict",
"TimestampTypedDict",
"Unpack",
"ZonedDateTimeDifferenceTypedDict",
"ZonedDateTimeRoundTypedDict",
)
FsPathLike = str | PathLike[str]
# =============================================================================
# STD
# =============================================================================
class DurationDict(TypedDict):
secs: int
nanos: int
class FileTypeDict(TypedDict):
is_dir: bool
is_file: bool
is_symlink: bool
class MetadataDict(TypedDict):
is_dir: bool
is_file: bool
is_symlink: bool
len: int
readonly: bool
file_type: Literal["file", "directory", "symlink"]
accessed: pydt.datetime
created: pydt.datetime
modified: pydt.datetime
# =============================================================================
# JIFF
# =============================================================================
JiffUnit: TypeAlias = Literal[
"year", # 9
"month", # 8
"day", # 6
"hour", # 5
"minute", # 4
"second", # 3
"millisecond", # 2
"microsecond", # 1
"nanosecond", # 0
]
JiffRoundMode: TypeAlias = Literal[
"ceil",
"floor",
"expand",
"trunc",
"half-ceil",
"half-floor",
"half-expand",
"half-trunc",
"half-even",
]
class DateTypedDict(TypedDict):
year: int
month: int
day: int
class TimeTypedDict(TypedDict):
hour: int
minute: int
second: int
nanosecond: int
class DateTimeTypedDict(TypedDict):
year: int
month: int
day: int
hour: int
minute: int
second: int
nanosecond: int
class ZonedDateTimeTypedDict(TypedDict):
year: int
month: int
day: int
hour: int
minute: int
second: int
nanosecond: int
tz: str
class TimestampTypedDict:
second: int
nanosecond: int
class SignedDurationTypedDict(TypedDict):
secs: int
nanos: int
class TimeSpanTypedDict(TypedDict):
"""TimeSpan TypedDict
Examples:
>>> import ry
>>> ts = ry.timespan(years=1, months=2, weeks=3)
>>> ts.to_dict()
{'years': 1, 'months': 2, 'weeks': 3, 'days': 0, 'hours': 0, 'minutes': 0, 'seconds': 0, 'milliseconds': 0, 'microseconds': 0, 'nanoseconds': 0}
"""
years: int
months: int
weeks: int
days: int
hours: int
minutes: int
seconds: int
milliseconds: int
microseconds: int
nanoseconds: int
class TimeZoneDict(TypedDict):
tz: str
class OffsetTypedDict(TypedDict):
seconds: int
fmt: str
class OffsetInfoDict(TypedDict):
offset: OffsetTypedDict
dst: bool
abbreviation: str
class ISOWeekDateTypedDict(TypedDict):
year: int
week: int
weekday: int
# -----------------------------------------------------------------------------
# JIFF ROUND
# -----------------------------------------------------------------------------
class DateTimeRoundTypedDict(TypedDict):
smallest: Literal[
"day",
"hour",
"minute",
"second",
"millisecond",
"microsecond",
"nanosecond",
]
mode: JiffRoundMode
increment: int
class SignedDurationRoundTypedDict(TypedDict):
smallest: Literal[
"hour",
"minute",
"second",
"millisecond",
"microsecond",
"nanosecond",
]
mode: JiffRoundMode
increment: int
class TimeRoundTypedDict(TypedDict):
smallest: Literal[
"hour",
"minute",
"second",
"millisecond",
"microsecond",
"nanosecond",
]
mode: JiffRoundMode
increment: int
class TimestampRoundTypedDict(TypedDict):
smallest: Literal[
"hour",
"minute",
"second",
"millisecond",
"microsecond",
"nanosecond",
]
mode: JiffRoundMode
increment: int
class ZonedDateTimeRoundTypedDict(TypedDict):
smallest: Literal[
"day",
"hour",
"minute",
"second",
"millisecond",
"microsecond",
"nanosecond",
]
mode: JiffRoundMode
increment: int
class OffsetRoundTypedDict(TypedDict):
smallest: Literal[
"second",
"minute",
"hour",
]
mode: JiffRoundMode
increment: int
# -----------------------------------------------------------------------------
# JIFF DIFFERENCE
# -----------------------------------------------------------------------------
class _DifferenceTypedDict(TypedDict):
mode: JiffRoundMode
increment: int
DateDifferenceUnit: TypeAlias = Literal["month", "year", "day"]
class DateDifferenceTypedDict(_DifferenceTypedDict):
smallest: DateDifferenceUnit
largest: DateDifferenceUnit | None
class DateTimeDifferenceTypedDict(_DifferenceTypedDict):
smallest: JiffUnit
largest: JiffUnit | None
TimeDifferenceUnit: TypeAlias = Literal[
"hour", "minute", "second", "millisecond", "microsecond", "nanosecond"
]
class TimeDifferenceTypedDict(_DifferenceTypedDict):
smallest: TimeDifferenceUnit
largest: TimeDifferenceUnit | None
class ZonedDateTimeDifferenceTypedDict(_DifferenceTypedDict):
smallest: JiffUnit
largest: JiffUnit | None
TimeStampDifferenceUnit: TypeAlias = Literal[
"hour", "minute", "second", "millisecond", "microsecond", "nanosecond"
]
class TimestampDifferenceTypedDict(_DifferenceTypedDict):
smallest: TimeStampDifferenceUnit
largest: TimeStampDifferenceUnit | None
# =============================================================================
# OPEN MODES (CANONICAL)
# =============================================================================
# ry accepts the non-canonical modes, but they are mapped to the canonical ones]
OpenTextModeUpdating: TypeAlias = Literal[
"a+", "at+", "r+", "rt+", "w+", "wt+", "x+", "xt+"
]
OpenTextModeWriting: TypeAlias = Literal["a", "at", "w", "wt", "x", "xt"]
OpenTextModeReading: TypeAlias = Literal["r", "rt"]
OpenTextMode: TypeAlias = Literal[
"a",
"a+",
"at",
"at+",
"r",
"r+",
"rt",
"rt+",
"w",
"w+",
"wt",
"wt+",
"x",
"x+",
"xt",
"xt+",
]
OpenBinaryModeUpdating: TypeAlias = Literal["ab+", "rb+", "wb+", "xb+"]
OpenBinaryModeWriting: TypeAlias = Literal["ab", "wb", "xb"]
OpenBinaryModeReading: TypeAlias = Literal["rb"]
OpenBinaryMode: TypeAlias = Literal[
"ab", "ab+", "rb", "rb+", "wb", "wb+", "xb", "xb+"
]
OpenMode: TypeAlias = Literal[
"a",
"a+",
"ab",
"ab+",
"at",
"at+",
"r",
"r+",
"rb",
"rb+",
"rt",
"rt+",
"w",
"w+",
"wb",
"wb+",
"wt",
"wt+",
"x",
"x+",
"xb",
"xb+",
"xt",
"xt+",
]
ry.dirs
from ry.ryo3.dirs import audio as audio
from ry.ryo3.dirs import audio_dir as audio_dir
from ry.ryo3.dirs import cache as cache
from ry.ryo3.dirs import cache_dir as cache_dir
from ry.ryo3.dirs import config as config
from ry.ryo3.dirs import config_dir as config_dir
from ry.ryo3.dirs import config_local as config_local
from ry.ryo3.dirs import config_local_dir as config_local_dir
from ry.ryo3.dirs import data as data
from ry.ryo3.dirs import data_dir as data_dir
from ry.ryo3.dirs import data_local as data_local
from ry.ryo3.dirs import data_local_dir as data_local_dir
from ry.ryo3.dirs import desktop as desktop
from ry.ryo3.dirs import desktop_dir as desktop_dir
from ry.ryo3.dirs import document as document
from ry.ryo3.dirs import document_dir as document_dir
from ry.ryo3.dirs import download as download
from ry.ryo3.dirs import download_dir as download_dir
from ry.ryo3.dirs import executable as executable
from ry.ryo3.dirs import executable_dir as executable_dir
from ry.ryo3.dirs import font as font
from ry.ryo3.dirs import font_dir as font_dir
from ry.ryo3.dirs import home as home
from ry.ryo3.dirs import home_dir as home_dir
from ry.ryo3.dirs import picture as picture
from ry.ryo3.dirs import picture_dir as picture_dir
from ry.ryo3.dirs import preference as preference
from ry.ryo3.dirs import preference_dir as preference_dir
from ry.ryo3.dirs import public as public
from ry.ryo3.dirs import public_dir as public_dir
from ry.ryo3.dirs import runtime as runtime
from ry.ryo3.dirs import runtime_dir as runtime_dir
from ry.ryo3.dirs import state as state
from ry.ryo3.dirs import state_dir as state_dir
from ry.ryo3.dirs import template as template
from ry.ryo3.dirs import template_dir as template_dir
from ry.ryo3.dirs import video as video
from ry.ryo3.dirs import video_dir as video_dir
__all__ = (
"audio",
"audio_dir",
"cache",
"cache_dir",
"config",
"config_dir",
"config_local",
"config_local_dir",
"data",
"data_dir",
"data_local",
"data_local_dir",
"desktop",
"desktop_dir",
"document",
"document_dir",
"download",
"download_dir",
"executable",
"executable_dir",
"font",
"font_dir",
"home",
"home_dir",
"picture",
"picture_dir",
"preference",
"preference_dir",
"public",
"public_dir",
"runtime",
"runtime_dir",
"state",
"state_dir",
"template",
"template_dir",
"video",
"video_dir",
)
ry.JSON
"""ry.JSON"""
from ry.ryo3.JSON import cache_clear as cache_clear
from ry.ryo3.JSON import cache_usage as cache_usage
from ry.ryo3.JSON import dumps as dumps
from ry.ryo3.JSON import fmt as fmt
from ry.ryo3.JSON import loads as loads
from ry.ryo3.JSON import minify as minify
from ry.ryo3.JSON import parse as parse
from ry.ryo3.JSON import stringify as stringify
__all__ = (
"cache_clear",
"cache_usage",
"dumps",
"fmt",
"loads",
"minify",
"parse",
"stringify",
)
ry.protocols
import datetime as pydt
import typing as t
__all__ = (
"FromStr",
"NoInit",
"RyIterator",
"Strftime",
"ToPy",
"ToPyDate",
"ToPyDateTime",
"ToPyTime",
"ToPyTimeDelta",
"ToPyTzInfo",
"ToString",
"_Parse",
)
_T = t.TypeVar("_T")
_T_co = t.TypeVar("_T_co", covariant=True)
class ToPy(t.Protocol[_T_co]):
"""Objects that can be converted to a python stdlib type (`_T_co`) via `obj.to_py()`."""
def to_py(self) -> _T_co: ...
class NoInit(t.Protocol):
"""Protocol for types that cannot be instantiated directly."""
def __init__(self) -> t.NoReturn: ...
# =============================================================================
# TO/FROM STRING
# =============================================================================
class FromStr(t.Protocol):
"""Protocol for types that have a `.from_str()` class method."""
@classmethod
def from_str(cls, s: str) -> t.Self: ...
class _Parse(t.Protocol):
"""Protocol for types that have a `.parse()` class method."""
@classmethod
def parse(cls, s: str | bytes) -> t.Self: ...
class ToString(t.Protocol):
"""Protocol for types that have a `.to_string()` method."""
def to_string(self) -> str: ...
# =============================================================================
# ITERABLE
# =============================================================================
class RyIterator(t.Protocol[_T]):
def __iter__(self) -> t.Self: ...
def __next__(self) -> _T: ...
def collect(self) -> list[_T]: ...
def take(self, n: int = 1) -> list[_T]: ...
# =============================================================================
# DATETIME
# =============================================================================
class Strftime(t.Protocol):
"""Protocol for types that have a `.strftime()` method."""
def strftime(self, fmt: str) -> str: ...
class ToPyDate(t.Protocol):
"""Objects that can be converted to a Python `datetime.date`."""
def to_pydate(self) -> pydt.date: ...
class ToPyTime(t.Protocol):
"""Objects that can be converted to a Python `datetime.time`."""
def to_pytime(self) -> pydt.time: ...
class ToPyDateTime(t.Protocol):
"""Objects that can be converted to a Python `datetime.datetime`."""
def to_pydatetime(self) -> pydt.datetime: ...
class ToPyTimeDelta(t.Protocol):
"""Objects that can be converted to a Python `datetime.timedelta`."""
def to_pytimedelta(self) -> pydt.timedelta: ...
class ToPyTzInfo(t.Protocol):
"""Objects that can be converted to a Python `datetime.tzinfo`."""
def to_pytzinfo(self) -> pydt.tzinfo: ...
ry.ulid
from ry.ryo3.ulid import ULID
__all__ = ("ULID",)
ry.uuid
from ry.ryo3.uuid import (
NAMESPACE_DNS,
NAMESPACE_OID,
NAMESPACE_URL,
NAMESPACE_X500,
RESERVED_FUTURE,
RESERVED_MICROSOFT,
RESERVED_NCS,
RFC_4122,
UUID,
getnode,
uuid1,
uuid3,
uuid4,
uuid5,
uuid6,
uuid7,
uuid8,
)
__all__ = (
"NAMESPACE_DNS",
"NAMESPACE_OID",
"NAMESPACE_URL",
"NAMESPACE_X500",
"RESERVED_FUTURE",
"RESERVED_MICROSOFT",
"RESERVED_NCS",
"RFC_4122",
"UUID",
"getnode",
"uuid1",
"uuid3",
"uuid4",
"uuid5",
"uuid6",
"uuid7",
"uuid8",
)
ry.xxhash
from ry.ryo3.xxhash import xxh3_64 as xxh3_64
from ry.ryo3.xxhash import xxh3_64_digest as xxh3_64_digest
from ry.ryo3.xxhash import xxh3_64_hexdigest as xxh3_64_hexdigest
from ry.ryo3.xxhash import xxh3_64_intdigest as xxh3_64_intdigest
from ry.ryo3.xxhash import xxh3_128 as xxh3_128
from ry.ryo3.xxhash import xxh3_128_digest as xxh3_128_digest
from ry.ryo3.xxhash import xxh3_128_hexdigest as xxh3_128_hexdigest
from ry.ryo3.xxhash import xxh3_128_intdigest as xxh3_128_intdigest
from ry.ryo3.xxhash import xxh32 as xxh32
from ry.ryo3.xxhash import xxh32_digest as xxh32_digest
from ry.ryo3.xxhash import xxh32_hexdigest as xxh32_hexdigest
from ry.ryo3.xxhash import xxh32_intdigest as xxh32_intdigest
from ry.ryo3.xxhash import xxh64 as xxh64
from ry.ryo3.xxhash import xxh64_digest as xxh64_digest
from ry.ryo3.xxhash import xxh64_hexdigest as xxh64_hexdigest
from ry.ryo3.xxhash import xxh64_intdigest as xxh64_intdigest
from ry.ryo3.xxhash import xxh128 as xxh128
from ry.ryo3.xxhash import xxh128_digest as xxh128_digest
from ry.ryo3.xxhash import xxh128_hexdigest as xxh128_hexdigest
from ry.ryo3.xxhash import xxh128_intdigest as xxh128_intdigest
__all__ = (
"xxh3_64",
"xxh3_64_digest",
"xxh3_64_hexdigest",
"xxh3_64_intdigest",
"xxh3_128",
"xxh3_128_digest",
"xxh3_128_hexdigest",
"xxh3_128_intdigest",
"xxh32",
"xxh32_digest",
"xxh32_hexdigest",
"xxh32_intdigest",
"xxh64",
"xxh64_digest",
"xxh64_hexdigest",
"xxh64_intdigest",
"xxh128",
"xxh128_digest",
"xxh128_hexdigest",
"xxh128_intdigest",
)
ry.zstd
from ry.ryo3.zstd import BLOCKSIZE_MAX as BLOCKSIZE_MAX
from ry.ryo3.zstd import BLOCKSIZELOG_MAX as BLOCKSIZELOG_MAX
from ry.ryo3.zstd import CLEVEL_DEFAULT as CLEVEL_DEFAULT
from ry.ryo3.zstd import CONTENTSIZE_ERROR as CONTENTSIZE_ERROR
from ry.ryo3.zstd import CONTENTSIZE_UNKNOWN as CONTENTSIZE_UNKNOWN
from ry.ryo3.zstd import MAGIC_DICTIONARY as MAGIC_DICTIONARY
from ry.ryo3.zstd import MAGIC_SKIPPABLE_MASK as MAGIC_SKIPPABLE_MASK
from ry.ryo3.zstd import MAGIC_SKIPPABLE_START as MAGIC_SKIPPABLE_START
from ry.ryo3.zstd import MAGICNUMBER as MAGICNUMBER
from ry.ryo3.zstd import VERSION_MAJOR as VERSION_MAJOR
from ry.ryo3.zstd import VERSION_MINOR as VERSION_MINOR
from ry.ryo3.zstd import VERSION_NUMBER as VERSION_NUMBER
from ry.ryo3.zstd import VERSION_RELEASE as VERSION_RELEASE
from ry.ryo3.zstd import __zstd_version__ as __zstd_version__
from ry.ryo3.zstd import compress as compress
from ry.ryo3.zstd import decode as decode
from ry.ryo3.zstd import decompress as decompress
from ry.ryo3.zstd import is_zstd as is_zstd
from ry.ryo3.zstd import unzstd as unzstd
__all__ = (
"BLOCKSIZELOG_MAX",
"BLOCKSIZE_MAX",
"CLEVEL_DEFAULT",
"CONTENTSIZE_ERROR",
"CONTENTSIZE_UNKNOWN",
"MAGICNUMBER",
"MAGIC_DICTIONARY",
"MAGIC_SKIPPABLE_MASK",
"MAGIC_SKIPPABLE_START",
"VERSION_MAJOR",
"VERSION_MINOR",
"VERSION_NUMBER",
"VERSION_RELEASE",
"__zstd_version__",
"compress",
"decode",
"decompress",
"is_zstd",
"unzstd",
)
DEP-GRAPH
food-4-thought
thinking out loud…
staticmethod vs classmethod [2025-08-28]
Nowhere in ry are any of the classmethod functions actually used as
classmethods, they are effectively staticmethods; they don’t access the class or
instance in any way. Classes in ry do not (for the most part) support being
subclassed. Benchmarking shows that staticmethod is slightly faster than
classmethod, sooooo all classmethods will be removed, but added back in if
needed later…
Benchmarking code:
from __future__ import annotations
import json
from pathlib import Path
from typing import TYPE_CHECKING
import pytest
import ry as ry
if TYPE_CHECKING:
from pytest_benchmark.fixture import BenchmarkFixture
def test_classmethod(benchmark: BenchmarkFixture):
# this is the current (as of 2025-08-28) `#[staticmethod]` parse function
benchmark(ry.Date.parse, "2023-03-15")
def test_staticmethod(benchmark: BenchmarkFixture):
# This is a crudely copy-pasted version using `#[staticmethod]` instead
benchmark(ry.Date.parse2, "2023-03-15")
Benchmark results:
---------------------------------------------------------------------------------------- benchmark: 2 tests ---------------------------------------------------------------------------------------
Name (time in ns) Min Max Mean StdDev Median IQR Outliers OPS (Mops/s) Rounds Iterations
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_staticmethod 57.5000 (1.0) 2,290.0000 (1.0) 63.4931 (1.0) 16.2941 (1.0) 62.0000 (1.0) 1.5000 (824.63) 1048;11454 15.7497 (1.0) 100000 200
test_classmethod 99.9989 (1.74) 29,200.0004 (12.75) 128.8420 (2.03) 146.9563 (9.02) 100.0008 (1.61) 0.0018 (1.0) 911;24504 7.7614 (0.49) 100000 1
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Legend:
Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile.
OPS: Operations Per Second, computed as 1 / Mean
fugue-state-jesse [2025-08-18]
The most sophisticated rust code in this repository was written by
fugue-state-jesse (aka FSJ), not me (normal-jesse) and not an AI/LLM.
fugue-state-jesse only shows up at random about 1-2 times a week and seemingly
has a vastly better understanding of rust and rust-macro-rules than I do.
Throughout the repository I (normal-jesse) will sometimes leave notes to
fugue-state-jesse with the hope that he might do what I ask, but he tends to
do his own thing.
ry.dev
For people who find ry.dev it is a module that exports all the things in ry as
well as can be used as a repl; python -m ry.dev will start a repl (with
ipython if installed else python-repl) with all of ry already imported. I
(jesse) use this super often for testing things out.
string-bridge?
The jiter crate uses a string-cache to store python-strings to avoid the
overhead of converting strings to python strings. A global string bridge and/or
caching setup for other types of structs that often convert to strings might be
worth considering?
Naming
Coming up with names is hard… I (jesse) want to strike a balance between being clear but also close to the wrapped libraries…
- Should jiff’s
ZonedbeZonedin python? orZonedDateTime? (currentlyZonedDateTime) - Should jiff’s
SpanbeSpanin python? orTimeSpan? (currentlyTimeSpan) - Should reqwest’s
ClientbeClientin python? orHttpClient? (currentlyHttpClient)
Flat? Nested submodules?
I like flat more, but nesting submodules might be preferable for some people and would allow for more flexibility in naming…
pros & cons:
- flat:
- pros:
- easier to import
- easier to work on
- no need to remember where things are
- type annotations are easier to setup/dist
- cons:
- name conflicts
- type annotations are harder to read bc of huge file
- harder to remember where things are
- pros:
- nested:
- pros:
- no name conflicts
- easier to remember where things are
- type annotations are easier to read
- importing
ry.jiff(orry.ryo3.jifftbd) is more explicitly thejiffwrapper(s)
- cons:
- Don’t know how type annotations should be laid out… if there is a
submodule called
ry.ryo3.reqwest, do you import fromry.ryo3.reqwestor do we reexport fromry.reqwest? Then were doe the type-annotations live and how are they laid out without having to duplicate/shim them?
- Don’t know how type annotations should be laid out… if there is a
submodule called
- pros:
pypi size limit
The pypi project size limit of 10gb was reached. I (jesse) won’t request a limit
raise until the package is more stable and hits some sort of v0.1.x, SOOOOOO
for now I will be:
- deleting older versions of ry from pypi as needed
- update the release gh-action to push the built wheels to the releases page so they are not lost into the ether…
jiff
docs.rs: https://docs.rs/jiff
crates: https://crates.io/crates/jiff
The jiff crate has a super excellent API that is very ergonomic to use and
ry provides a nearly complete wrapper around it.
A good amount of time, and a greater amount of thought has gone into balancing
the jiff python api to be both ergonomic and performant.
python-conversions
The structs under ryo3-jiff are convertible to/from python’s datetime.*
types and the conversions are pretty well tested (ty hypothesis).
pyo3-v0.24.0 & jiff-02
The conversions to/from python datetime.* types were originally hand rolled (
by me (jesse)) using the ‘new-type’ pattern, HOWEVER pyo3-v0.24.0 provides
conversions via the jiff-02 feature flag, which is what is used now.
ry-v0.0.37 will be the last version with the mostly hand rolled conversions.
ry-v0.0.38 will be the first version with the jiff-02 feature flag.
As of 2025-03-12 pyo3 does not seem to support converting Span ->
datetime.timedelta, so that is still hand rolled.
ry vs whenever
There is another library called
whenever that provides a similar
datetime library to that of ryo3-jiff (both jiff and whenever are based on
the temporal API).
No formal benchmarks between ry and whenever have been done, but I have
copy-pasta-ed some of the benchmarks from the whenever repo and translated
them to ry and the results were pretty similar; whenever is faster for some
things, ry is faster for others, but both are wildly more performant than
python’s built in datetime module and pendulum – differences in performance
are almost all measured in nanoseconds.
Big shoutout to “Mr. Dutch Airlines” guy
(@ariebovenberg) who wrote whenever! Love
the name of the library too!