cosplay2py
Unofficial typed sync and async client for the Cosplay2.ru API, built on httpx2 and Pydantic.
Installing
The package is not on PyPI. Install it from a release tag:
uv add "cosplay2py @ git+https://github.com/Arutemu64/cosplay2py" --tag v0.2.0
Versions follow SemVer. On 0.x, a minor bump (0.1 → 0.2) may break things and a
patch bump never does. See CHANGELOG.md.
Authentication
API tokens are issued per event: on the event site open Орги → Настройка → API токены
and create a token. You get an API key and an API secret (the secret is shown once;
tokens expire after 30 days). The client sends them as X-API-Key / X-API-Secret.
Usage
from cosplay2py import Cosplay2
from cosplay2py.models import BlankId, RequestStatus
with Cosplay2(subdomain="ff26summer", api_key="...", api_secret="...") as c2:
event = c2.events.get_settings()
print(event.title, event.timezone)
for topic in c2.topics.get_list():
listing = c2.topics.get_requests(topic.url_code)
approved = [r for r in listing.requests if r.status is RequestStatus.APPROVED]
print(topic.title, len(approved))
details = c2.requests.get(687475)
print(details.values_by_field())
jury_sheet = c2.events.get_blank(BlankId.JURY).html
Async (asyncio or trio):
from cosplay2py import AsyncCosplay2
async with AsyncCosplay2(subdomain="ff26summer") as c2:
state = await c2.events.get_state()
print(state.requests_total)
Events on a custom domain: Cosplay2(base_url="https://fancom.info", ...).
Any argument left out falls back to the environment: COSPLAY2_API_KEY,
COSPLAY2_API_SECRET, COSPLAY2_BASE_URL.
Resources
| Attribute | Methods |
|---|---|
events |
get_settings, save_setting, get_state, get_topics_state, get_topics_statistic, get_staff, add_org, delete_org, change_main_org, add_curator, delete_curator, get_winners, get_plan, save_plan, get_blank, get_reg_topics, get_reg_alphabet, search, set_deadline |
topics |
get_list, get_requests, get_all_requests, get_requests_for_planner, get_form, get_with_groups, add_child_topic, delete_child_topic, create, delete, reorder, fill_from_template, fill_from_topic, add_section, save_section, delete_section, add_field, delete_field, save_field, save_topic, reorder_section, reorder_field, generate_card_titles, reorder_requests |
requests |
get, get_comments, get_org_comments, get_user, generate_card_title, generate_card_announcement, generate_card_diplom, generate_voting_number, search, get_value_history, add_comment, delete_comment, save_field, upload_image, delete_image, upload_file, delete_file, save_data, set_status, create, create_section, delete_section, change_topic, add_org_comment, delete_org_comment, get_feedbacks, add_feedback, delete_feedback |
users |
search |
design |
get, get_images, save, upload_image, delete_image, delete_panel_logo, delete_header_logo, delete_site_background |
pages |
get_list, get, create, save_field, save_fields, delete, reorder |
media |
get_data, add_album, save_album_field, delete_album |
cards |
get_topics_and_cards, get_card, get_topics_and_requests, get_request |
etickets |
get_list, get_types, add_type, delete_type, reorder_type, save_type_field, save_field, delete, create, get, get_status, save_personal_data |
tickets |
get_statistic, get_voting_statistics, create, clear_votes, add_prize, delete_prize, save_prize_field, save_prize_handed, get_ticket, check_for_voting, get_voting_data, get_cards, select_winner |
Data conventions
- Server timestamps become timezone-aware UTC
datetimes, whether the API sent"YYYY-MM-DD HH:MM:SS", Unix seconds or Unix milliseconds. - Display strings like
"22.08.26 03:00"(TopicState,Event.start_time) become naivedatetimes, as the site shows them. 0/1flags becomebool. JSON packed into strings (Event.design, the plan) is parsed.- Closed domain sets (
RequestStatus,TopicFieldType,PageType,PlanNodeType,EventRole,EventStatus,EventTime,TopicCategory,PublicRequests,TopicTemplate,SectionTemplate,FieldTemplate,FeedbackMark,CardField,TicketKind,TicketCreateMode,VotingType,BlankId,Deadline) are validated strictly asStrEnum/IntEnummembers (empty strings on optional fields normalize toNone). - Unknown fields are kept rather than rejected. Read them via
model.model_extra.
Talking to the API without this library? docs/api-notes.md describes its endpoints, wire formats and quirks.
Errors
Cosplay2Error
└── APIError
├── APIConnectionError
│ └── APITimeoutError
├── APIResponseValidationError # 2xx, but not the expected JSON
└── APIStatusError # non-2xx; .status_code, .body, .response
├── BadRequestError (400)
├── AuthenticationError (401)
├── PermissionDeniedError (403)
├── NotFoundError (404)
├── RateLimitError (429)
└── InternalServerError (5xx)
Repeatable reads retry transport failures and 429/502/503/504 responses, with
exponential backoff and jitter (2 retries by default, configurable with
max_retries). Writes retry only connection failures (ConnectError), never
HTTP responses or read/write timeouts. An ambiguous failure may mean a write
succeeded; check the service before repeating it yourself.
Retry-After supports seconds and HTTP dates. If the server asks for more than
30 seconds, the error is returned immediately instead of retrying early.
Error messages omit response bodies and validation inputs. Inspect .response
or .body explicitly when debugging; these can contain personal data.
Customizing HTTP
Pass timeout= (seconds or httpx2.Timeout), extra headers=, or a fully configured
http_client=httpx2.Client(...) / httpx2.AsyncClient(...) for proxies, custom
transports or testing with httpx2.MockTransport. A client you pass in is not closed by
the wrapper. Its timeout and default headers apply; wrapper headers override
matching defaults, and redirects are always disabled. timeout= applies only to a
client created by the wrapper. Timeouts limit network phases, not the total time
across retries. Use HTTPS for event credentials; HTTP is supported for local testing.
Base URLs cannot contain userinfo, query strings or fragments.
This client follows observed site behavior, which can change without notice.
Enable logging.getLogger("cosplay2py") at DEBUG to see requests.
Development
See CONTRIBUTING.md for how to propose changes.
uv sync
uv run prek install # install Git hooks once per clone
uv run pytest # offline unit tests (default)
uv run prek run --all-files # lint, format, and type-check
Testing against the real site
tests/live holds read-only smoke tests that are deselected by default. They need a token
for the event (PowerShell shown):
$env:COSPLAY2_API_KEY = "..."
$env:COSPLAY2_API_SECRET = "..."
$env:COSPLAY2_BASE_URL = "https://ff26summer.cosplay2.ru"
uv run pytest -m live -rw
-rw lists warnings: fields the API returns that the models don't declare yet show up
as UnknownFieldsWarning, an early sign of API drift.
Portal reads work with the configured event base URL (verified with event API
credentials); https://cosplay2.ru returned HTTP 403 with those credentials. Methods: events.filter_list(),
events.get_types(), events.create_festival(), events.create_festival_logo(),
users.ratings_global() and the country/area/region/city variants,
users.get_region_geo_id(), and geo.code_city(). Unobserved response shapes
are returned as JSON data.
Metadata
Release files for cosplay2py 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| cosplay2py-0.3.0.tar.gz | 36.5 kB | Without provenance | Details for cosplay2py-0.3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| cosplay2py-0.3.0-py3-none-any.whl | Python 3 | none | any | Details for cosplay2py-0.3.0-py3-none-any.whl |
Total release size: 80.2 kB
Release files / cosplay2py-0.3.0.tar.gz
| Download URL | cosplay2py-0.3.0.tar.gz |
|---|---|
| Size | 36.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e465af9c12e870a603cb5faa7d3dbcb943a95549d60df47aed7bf178dd4a26f9
|
|
BLAKE2b-256 checksum How to use checksums |
077d6e83dd5fb667ef6604711ae10a32059a1167965a8669758133689e0f8745
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / cosplay2py-0.3.0-py3-none-any.whl
| Download URL | cosplay2py-0.3.0-py3-none-any.whl |
|---|---|
| Size | 43.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ed0ad22f6c8ca50bf8b04d8e488ca6fa05464cadad6a12c5c4868af14e334b25
|
|
BLAKE2b-256 checksum How to use checksums |
0ae1811a4857d6db73c18d42f49b277728d3b97d0a6986fc1f240e2ca52c7904
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for cosplay2py 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.