Skip to main content

Uni Calendar Coloring

Uni Calendar Coloring

Turn your university timetable into a color-coded Google Calendar.

The university calendar is read-only and every event in it has the same color. unical copies it into a Google Calendar you own and colors each event:

  • Exams: red if you are enrolled, grey if you are not. Once you enroll in one session of an exam, its other sessions turn grey.
  • Lectures: one color per course, with the boilerplate stripped from the title.
  • Deadlines: one color per deadline.

The terminal UI, Exams tab

What counts as an exam, a lecture or a deadline is decided by the rules of your profile, so the tool adapts to the format of any university. The built-in profile handles the Politecnico di Milano format (Esame: …, Lezione: Didattica - …, Scadenza: …).

Your choices are saved in a plain JSON file, profile.json, so every later sync uses the same colors. You can run unical from a terminal UI, from plain command-line flags, or on a weekly schedule with GitHub Actions.

Contents

Quick start

Run without manual virtual environments using uvx:

uvx uni-calendar-coloring
# or directly from GitHub:
uvx --from git+https://github.com/Bert0ns/uni-calendar-coloring.git unical

Or run standalone pre-built binaries (no Python required):

# Download binary from GitHub Releases for your OS, make executable, and run:
./unical

The terminal UI opens and guides you through the first run and credentials setup. Nothing is written to Google Calendar until you apply the changes.

How it works

Source calendar ──read──▶ discover ──▶ preferences ──▶ plan ──▶ apply ──write──▶ your colored calendar
(Google or iCal)          courses,      saved colors,    diff of    batched
                          exams,        rules, or        inserts/   Google API
                          deadlines     your edits       updates/   calls
                                                         deletes
  1. Discover: read the source events and list the courses, exam sessions and deadlines they contain.
  2. Preferences: load your saved colors and subscriptions. Anything you haven't chosen yet is filled in by the coloring rules, or you choose it yourself in the TUI or with the -i prompts.
  3. Plan: compare the source with the target calendar and work out the events to insert, update and delete. Unchanged events cost no API calls.
  4. Apply: send the changes through the Google batch API, retrying transient failures.

The sync is safe to repeat:

  • Only events the tool created are updated or deleted. They're tagged with a private property. Events you add to the target calendar yourself are left alone.
  • Events removed from the source are removed from the target.
  • An event that the current run doesn't cover (for example, a lecture during unical exams) is ignored: its copy in the target calendar is never inserted, updated or deleted. Events removed from the source are only deleted by a run that covers everything.
  • The target calendar is created on the first sync.

Setup

You need a Google account (and Python 3.12+ if installing via uv, pipx, or source; standalone pre-built binaries require no Python runtime). The tool runs under your own Google Cloud OAuth client, so nobody else ever sees your calendar.

1. Install

Choose the installation method that best suits your environment:

Pre-built single-file executables are automatically generated and attached to each GitHub Release:

  • Linux (x86_64): unical-linux-x86_64 (or unical-linux-x86_64.tar.gz)
  • macOS (Universal - Apple Silicon & Intel): unical-macos-universal (or unical-macos-universal.tar.gz)
  • Windows (x86_64): unical-windows-x86_64.exe (or unical-windows-x86_64.zip)

On Linux / macOS:

curl -LO https://github.com/Bert0ns/uni-calendar-coloring/releases/latest/download/unical-linux-x86_64
chmod +x unical-linux-x86_64
mkdir -p ~/.local/bin
mv unical-linux-x86_64 ~/.local/bin/unical

On Windows: Download unical-windows-x86_64.exe (or unzip unical-windows-x86_64.zip), rename to unical.exe, and run it from PowerShell or Command Prompt.

Modern CLI Tool Managers (uv / pipx)

Installs unical in an isolated environment and makes the command available system-wide:

Using uv (fastest):

# Install from PyPI:
uv tool install uni-calendar-coloring

# Or install directly from the Git repository:
uv tool install git+https://github.com/Bert0ns/uni-calendar-coloring.git

# Or run ephemerally with uvx:
uvx uni-calendar-coloring

Using pipx:

# Install from PyPI:
pipx install uni-calendar-coloring

# Or install directly from the Git repository:
pipx install git+https://github.com/Bert0ns/uni-calendar-coloring.git

Homebrew (macOS / Linux)

brew install Bert0ns/tap/unical

From Source (Git clone / Virtualenv)

For contributors and developers:

git clone https://github.com/Bert0ns/uni-calendar-coloring.git
cd uni-calendar-coloring
pip install .

This installs the unical command. python -m unical works too.

2. Create Google API credentials

The tool logs in under your own Google Cloud OAuth client. You only create it once; it's free and takes about five minutes. The step-by-step credentials guide walks through every screen. In short:

  1. In the Google Cloud Console, create a new project.
  2. Enable the Google Calendar API.
  3. Configure the OAuth consent screen: choose the External user type, then add your own Google address under Test users. If you skip this, login fails with 403 access_denied.
  4. Create an OAuth client ID of type Desktop app and download its JSON file.

You don't need to place the file anywhere by hand: on the first run, unical notices it's missing and asks for its path (you can drag and drop the file onto the terminal). To import it ahead of time instead:

unical auth import /path/to/downloaded-credentials.json

3. First run

unical

Your browser opens so you can log in with Google, and the login is saved to token.json. Without a browser (WSL, SSH), the login URL is printed for you to open by hand.

When there is no profile.json yet, the terminal UI opens a short guide:

  1. Where your timetable comes from: paste its iCal or webcal:// link (recommended, see Use an iCal URL as the source), or pick the calendar you subscribed to in Google Calendar.
  2. The calendar to write to: pick one, or keep the suggested new name. A new calendar is only created when you apply the changes.
  3. Recognizing your events: see how the built-in Politecnico di Milano rules classify your events, then keep them, adjust them, or start from scratch in the Rules tab.

The guide ends on a preview of the changes. Nothing is written to Google Calendar until you apply them. Your choices are saved in profile.json, and the guide only runs while that file doesn't exist. Press Escape on the welcome screen to skip it.

Without the terminal UI, create profile.json yourself with the two calendars (the rules and colors start from the built-in profile), then try a dry run:

{
  "calendars": {
    "source": "My University",
    "target": "Colored Calendar"
  }
}
unical --dry-run

If you'd rather not subscribe to the source calendar in Google, give the tool your iCal URL instead. All settings are listed under Configuration.

Usage

Authentication

Manage credentials and check login status with unical auth:

unical auth import /path/to/downloaded-credentials.json   # copy credentials to user config directory
unical auth import /path/to/credentials.json -m           # move instead of copy
unical auth status                                        # inspect credentials, token cache, and profile status
unical auth login                                         # authenticate with Google and cache token in advance
unical doctor                                             # diagnose the whole setup, including the connection to Google

Before opening the browser, unical auth login reminds you that a 403 access_denied page from Google means your address is missing under Test users on the OAuth consent screen. Google shows that error in the browser, so the tool can't detect it: if the login doesn't finish within 5 minutes, it gives up with the same hint. If you click Cancel on Google's page, the login stops with an explanation instead of retrying.

If your university Google Workspace account can't create Google Cloud projects or OAuth clients, create them with a personal @gmail.com account instead.

unical doctor checks everything a sync needs, without logging in through the browser, and reports each check as pass, warn, fail or skip:

  • the config directory and the profile, credentials and token paths;
  • the format of credentials.json: a Desktop app client passes; a Web application client gets a warning (its login fails with redirect_uri_mismatch); a service account key or a malformed file fails;
  • the saved login: whether it exists and has the Calendar scope, when it expires, and whether it can still be refreshed;
  • access to the Google Calendar API;
  • that the source calendar exists and that the target calendar is writable.

It exits with code 1 if any check fails, so you can use it in scripts and CI.

Version and updates

Check running version and inspect PyPI for newer releases:

unical --version                                          # print current version
unical version                                            # check if an update is available on PyPI
unical version --no-check                                 # print version without checking network

When a newer version is published, unical displays a non-intrusive upgrade notice at the end of CLI operations and as a notification in the terminal UI. Update checks are cached for 24 hours to prevent network delays and can be suppressed with --no-update-check or UNICAL_NO_UPDATE_CHECK=1.

Sync

unical                       # open the terminal UI (the default)
unical --no-tui              # plain sync: exams, lectures and deadlines
unical exams --no-tui        # only (re)color exams
unical lectures --no-tui
unical deadlines --no-tui

Run from a terminal, unical opens the terminal UI. It falls back to a plain sync when there is no terminal (cron, CI, a pipe) or when you pass -i, -n/--dry-run or --no-tui. The plain sync is non-interactive: anything new gets a color from the coloring rules, and that color is saved for future runs.

Useful flags:

unical --dry-run                   # plain sync, show the changes, write nothing
unical -v                          # explain the decision for every event
unical -q                          # only warnings and errors
unical --prune-before 2026-02-01   # also delete synced events before this date

--prune-before is handy for dropping past semesters. Flags can be combined, e.g. unical lectures --dry-run -v. The command exits with a non-zero status if any calendar operation fails.

Terminal UI

unical
unical exams          # only the Exams and Sync tabs

--tui forces it even when the shell doesn't look interactive. It opens on the Setup tab, with one more tab per kind of event:

Tab What you can do
Setup The calendar to read from, the one to write to, and the time zone of a new target calendar. Pick the calendars from your Google calendars, or type a new name for the target. Choices are saved right away. Also has the selector for what a sync covers.
Courses Every course in the source with its color. Pick a new color from the 11 Google colors.
Exams Every exam session with its date, what the source calendar says (enrolled / not enrolled), whether you're already subscribed to another date, and your subscription. Toggle the subscription or pick a color.
Deadlines Same as Courses, for deadlines.
Sync Choose what to color: everything, lectures only, exams only or deadlines only (the other tabs follow). Preview changes lists the inserts, updates and deletes. Apply writes them to Google Calendar with a live progress panel.
Rules The rules that decide what each event is, and the exam enrollment conditions. A live preview shows how every event title is classified.

In the Sync tab, expand an event in the preview to see its color, time and original title. While applying, the progress panel shows a spinner, a bar, how many inserts, updates and deletes are written, and the time elapsed and left.

In the Rules tab, add, edit, delete and reorder rules, or press Enter on an unmatched event to start a rule from its title.

The Status column shows where each value comes from:

  • saved: chosen earlier and stored in the profile.
  • suggested: not chosen yet, so the coloring rules decide. It's saved at the next sync.
  • modified: changed in this session and not saved yet.
  • not set: an exam with no enrollment information. Its color is left as is until you choose one.
Key Action
Enter / c Pick a color for the selected row
Space Toggle the exam subscription (Exams tab)
Ctrl+S Save rules and preferences without syncing
p Preview the changes
a Apply the previewed changes
r Refresh the source calendar
n New rule (Rules tab)
e / Enter Edit the selected rule (Rules tab)
d Delete the selected rule (Rules tab)
[ / ] Move the selected rule up / down (Rules tab)
q Quit (asks again if there are unsaved changes)

Toggling a subscription switches between the default red and grey. A custom color you picked for the exam is kept. Applying saves your preferences, just like a normal sync. If you edit something after a preview, preview again before applying.

The source can be refreshed or changed in the Setup tab, except when the iCal URL is given with --ical or SOURCE_ICAL_URL (which can still be refreshed, but not changed). If SOURCE_CALENDAR_NAME or TARGET_CALENDAR_NAME is set, it replaces the saved calendar every time the tool starts, and the tab says so.

Interactive prompts

unical -i
unical exams -i

Without the TUI you get a question-by-question flow before the sync: your subscription to each exam session, then a color for each course and deadline. The current choice is the default, so you can press Enter to keep it. Other dates of the same exam with no saved choice reuse your first answer. Add --dry-run to try choices without saving them.

Use an iCal URL as the source

You can read events straight from your personal iCal feed (e.g. from Esse3, WeBeep or Canvas, often under Export or Subscribe) instead of a Google calendar. It's the cleanest option: there is no subscribed calendar in Google Calendar, so no copy of every event to hide next to the colored one.

The easiest way is to paste the link in the first-run guide, or later with Change… next to the source in the Setup tab. https:// and webcal:// links both work; the tool downloads the feed to check it before using it. The link is saved in ical_url.txt in the user config directory (e.g. ~/.config/unical/ on Linux), readable by you only, and used on every run.

You can also give it on the command line, or set it in .env:

unical --ical "https://ical.example.com/<id>/<token>"
SOURCE_ICAL_URL="https://ical.example.com/<id>/<token>"

The first one found wins: --ical, then SOURCE_ICAL_URL, then the saved link. Any of them takes precedence over the source calendar of the profile.

Recurring events (RRULE/EXDATE) are passed to Google, which expands them. Rules can match the feed's CATEGORIES with "field": "category". The built-in PoliMi rules use them (Lezione, Esame, Scadenza) when the title prefixes are missing.

Command reference

unical [all|exams|lectures|deadlines] [options]
Option Description
all (default), exams, lectures, deadlines Which kinds of events to sync; the others are left untouched.
--tui Open the terminal UI (default in a terminal). Not with -i, --dry-run, --no-tui.
--no-tui Run a plain sync instead of opening the terminal UI.
-i, --interactive Ask about subscriptions and colors before syncing.
-n, --dry-run Show what would change. Nothing is written to the calendar or the profile.
--ical URL Read from an iCal feed. Overrides the source calendar and SOURCE_ICAL_URL.
--prune-before YYYY-MM-DD Also delete synced events starting before this date.
-v, --verbose Show the decision for every event.
-q, --quiet Show only warnings and errors.
-V, --version Show version number and exit.
--check-update Check online for a newer version of unical and exit.
--no-update-check Do not check online for updates.
Subcommand Description
unical auth import [FILE] Validate and copy (-m: move) an OAuth client JSON into the config directory.
unical auth status Show the credentials, token and profile paths and their status.
unical auth login Log in with Google in the browser and save the token.
unical doctor Check the setup and the connection to Google without logging in. Exits 1 on failure.
unical events list|add|delete|adopt Manage custom events.
unical version [--no-check] Show the version and check for updates.

Profile and rules

profile.json holds everything about your calendar: the calendars to sync, the rules that classify events, and the colors and subscriptions you chose. Without one, the tool starts from the built-in PoliMi profile and saves it on the first sync, so you can see and edit the rules.

{
  "version": 1,
  "name": "Politecnico di Milano",
  "calendars": {
    "source": "Calendar",
    "target": "Calendar Colored",
    "time_zone": null
  },
  "rules": [
    {
      "kind": "exam",
      "field": "title",
      "match": "starts_with",
      "value": "Esame: ",
      "ignore_case": false,
      "title": "{title}"
    },
    {
      "kind": "lecture",
      "field": "title",
      "match": "starts_with",
      "value": "Lezione: Didattica - ",
      "ignore_case": false,
      "title": "{name}"
    }
  ],
  "enrollment": {
    "enrolled": {
      "field": "description",
      "match": "starts_with",
      "value": "Iscritto",
      "ignore_case": false
    },
    "not_enrolled": {
      "field": "description",
      "match": "starts_with",
      "value": "Non iscritto",
      "ignore_case": false
    }
  },
  "courses": { "Computer Security": "7" },
  "exams": {
    "Computer Security (2027-01-20)": { "color": "11", "subscribed": true }
  },
  "deadlines": { "Esame di laurea": "4" }
}

The example is shortened. The built-in profile has six rules: the title prefix and the iCal category of each kind of event.

When the target calendar doesn't exist, the first sync creates it in time_zone, an IANA time zone such as Europe/Rome. With null, it gets the time zone of your primary Google calendar.

Rules

Rules are checked in order and the first one that matches decides the kind of the event. Events that match no rule are copied without a color. Without a rules key, the built-in PoliMi rules apply; "rules": [] means no rules. The easiest way to write them is the Rules tab of the terminal UI, which shows live how each event is classified.

Key Values
kind exam, lecture or deadline.
field What to look at: title, description, location or category (any iCal category).
match starts_with, contains, equals or regex (a Python regular expression, searched).
value The text or regular expression to match.
ignore_case true to ignore upper/lower case. Optional, false by default.
title Title in the colored calendar. {title} is the original title, {name} the event's name.

The name of an event identifies its course, exam or deadline: lectures with the same name share a color. It's the title without the matched text when the rule looks at the title (Lezione: Didattica - Algebra → Algebra), and the whole title otherwise. With a regex, a (?P<name>…) group picks it out explicitly, e.g. ^\[\w+\] (?P<name>.+) - Lecture$ turns [CS101] Algorithms - Lecture into Algorithms.

enrollment is optional: it tells, from an exam event, whether you're enrolled (enrolled) or not (not_enrolled). Each is a condition like the ones of the rules, or null. Invalid rules are skipped with a warning.

Coloring rules

These rules fill in anything you haven't chosen yourself. Your saved choices always win.

Event Rule
Exam, another session of an exam you're subscribed to Not subscribed, Graphite (grey). Checked first.
Exam, the enrolled condition matches Subscribed, Tomato (red).
Exam, the not_enrolled condition matches Not subscribed, Graphite.
Exam, no information Left uncolored until you choose.
Lecture A color derived from the course name, so it's the same on every machine.
Deadline A color derived from the name.

Saved preferences

Profile key Content
courses {"<course>": "<color id>"}
exams {"<exam name> (<YYYY-MM-DD>)": {"color": "<id>", "subscribed": true}}
deadlines {"<deadline>": "<color id>"}

Color IDs are Google's: 1 Lavender, 2 Sage, 3 Grape, 4 Flamingo, 5 Banana, 6 Tangerine, 7 Peacock, 8 Graphite, 9 Blueberry, 10 Basil, 11 Tomato. You can edit the file by hand. Invalid entries are skipped with a warning, and the file is written atomically, so an interrupted run can't corrupt it.

Configuration

The calendars, rules and colors live in the profile. The optional settings below come from environment variables, usually set in .env (see .env.example).

Configuration and credential paths (PROFILE_PATH, CREDENTIALS_PATH, TOKEN_PATH) are resolved in this order:

  1. Explicit environment variable (relative paths resolved from current working directory).
  2. Current working directory (./credentials.json, ./profile.json, etc.) if the file exists.
  3. Standard user configuration directory for your platform:
    • Linux: ~/.config/unical/ (or $XDG_CONFIG_HOME/unical/)
    • macOS: ~/Library/Application Support/unical/
    • Windows: %APPDATA%\unical\
Variable Default Description
PROFILE_PATH profile.json or config dir The profile.
SOURCE_CALENDAR_NAME (the profile's) Overrides the calendar to read from.
TARGET_CALENDAR_NAME (the profile's) Overrides the calendar to write to.
SOURCE_ICAL_URL (the link saved by the guide) Read from this iCal feed instead of a calendar.
CREDENTIALS_PATH credentials.json or config dir OAuth client downloaded from Google Cloud.
TOKEN_PATH token.json or config dir Cached Google login.
UNICAL_NO_UPDATE_CHECK 0 Set to 1 or true to disable version checks.
UNICAL_CACHE_DIR platform cache dir Custom directory for version check cache.

Run it in the cloud with GitHub Actions

The repository includes a workflow, .github/workflows/manual_sync.yml, that syncs every Monday at 06:00 UTC. You can also run it from the Actions tab and choose what to sync, verbose output, or a dry run.

  1. Fork the repository and commit your own profile.json (the one in the repository belongs to its author), or override the calendar names with the secrets below.

  2. Log in locally once so that token.json exists, e.g. with unical --dry-run.

  3. In your fork, go to Settings → Secrets and variables → Actions and add these repository secrets:

    Secret Value
    GCP_CREDENTIALS_JSON Contents of credentials.json.
    GCP_TOKEN_JSON Contents of token.json.
    SOURCE_CALENDAR_NAME Optional, overrides the profile's source calendar.
    TARGET_CALENDAR_NAME Optional, overrides the profile's target calendar.
    SOURCE_ICAL_URL Optional. If set, it's used instead of the source calendar.

    If you pasted an iCal link in the setup guide, add it as SOURCE_ICAL_URL: the guide saves it on your computer only, not in profile.json.

After each run, the workflow commits the updated profile.json back to the repository, so colors you pick locally (and push) and colors the cloud run assigns stay in sync.

Troubleshooting

Problem Fix
Not sure what's wrong Run unical doctor: it checks credentials, login, API access and calendars, and says how to fix each issue.
403 access_denied when logging in Add your Google address as a Test user on the OAuth consent screen.
Google login was cancelled or denied (access_denied) You clicked Cancel, or your address isn't a Test user. Fix that, then run unical auth login.
Timed out after 5 minutes waiting for the Google login Google probably showed an error page. Check the Test users list, then run unical auth login again.
Error 400: redirect_uri_mismatch in the browser The OAuth client is a Web application. Create a Desktop app client and run unical auth import again.
Can't create a project or OAuth client Your university Workspace account may block it: use a personal @gmail.com account for Google Cloud.
OAuth client file 'credentials.json' not found Download the Desktop OAuth client JSON and save it as credentials.json, or point CREDENTIALS_PATH to it.
Source calendar '…' not found The source calendar in profile.json must match the name exactly as shown in Google Calendar.
Every event shows up twice Hide the original calendar in Google Calendar.
Could not download iCal feed The iCal URL may have expired or been revoked. Generate a new one.
The terminal UI needs the 'textual' dependency Run pip install ..
Login keeps expiring after a week That's Google's Testing mode: log in again locally (and update GCP_TOKEN_JSON if you use GitHub Actions).
Some events have no color They match no rule. Check the Rules tab, where unmatched titles are listed.

Upgrading

  • The command was renamed from calendar-coloring to unical, and the Python package from calendar_coloring to unical. Reinstall with pip install ., and update scripts and cron jobs. profile.json, token.json and the events already in your target calendar keep working.
  • token.pickle is migrated to token.json automatically, and the old GCP_TOKEN_PICKLE_B64 secret is still accepted.
  • Events synced by older versions carry an older tag: the next sync updates each of them once to the current tag, then they're left alone again.

Development

pip install -e ".[dev]"
pytest          # unit, golden regression, Textual pilot and packaging tests
mypy            # strict type checking
ruff check .    # linting
black .         # formatting
pre-commit install

# Build standalone single-file binary with PyInstaller:
pyinstaller packaging/unical.spec
./dist/unical --help

# Build distribution wheels & sdist:
python -m build
twine check dist/*

CI runs all of the above on Python 3.12, 3.13, and 3.14 and requires 95% test coverage.

Architecture

The core never prints, prompts or touches the network directly. It depends on small interfaces (ports) that the adapters implement, so the CLI, the interactive prompts and the TUI are all thin frontends over the same discover → preferences → plan → apply phases.

src/unical/
├── palette.py         # GoogleColor: the 11 Google colors (id, name, RGB)
├── events.py          # Event accessors and exam sessions
├── rules.py           # Classification rules: event → exam/lecture/deadline + name
├── presets.py         # Built-in rules (Politecnico di Milano)
├── profile.py         # Profile model + JSON repository (atomic writes)
├── targets.py         # SyncTarget: which kinds of events a run covers
├── catalog.py         # Discover: courses, exam sessions and deadlines in the source
├── preferences.py     # Preferences model: colors and exam subscriptions
├── suggestions.py     # Pure rules for default colors and subscriptions
├── resolution.py      # Fill in preferences the user never chose
├── strategies.py      # Pure lookups: event + preferences → color
├── workflow.py        # Use case: load, preview/plan, apply (and run = all at once)
├── reporting.py       # Reporter port (progress and messages)
├── sync/
│   ├── source.py      # EventSource port + Google calendar source
│   ├── planner.py     # Pure diff: source + target events → SyncPlan
│   ├── models.py      # Mutation, SyncPlan, SyncResult value objects
│   ├── gateway.py     # CalendarGateway port
│   └── service.py     # Target-calendar I/O around the planner, with progress
├── ical_source.py     # iCal feed source (standard library parser)
├── google_client.py   # Google Calendar adapter (batch requests + retries)
├── auth.py            # Google OAuth, Desktop flow, token.json
├── config.py          # Settings and overrides from environment variables
├── cli/
│   ├── main.py        # Argument parsing and wiring of the adapters
│   ├── prompts.py     # Interactive preference editor (-i)
│   ├── console.py     # Colored console reporter
│   └── ansi.py        # ANSI styling helpers
└── tui/               # Terminal UI
    ├── model.py       # View model of the editor (pure Python, no Textual)
    ├── setup.py       # Setup tab model: calendars, overrides, first run
    ├── rules.py       # Rules tab model: live classification preview
    ├── widgets.py     # Color picker, calendar picker, plan tree, progress
    ├── wizard.py      # First-run welcome and rules check screens
    └── app.py         # Textual app: tabs, workers, reporter

License

MIT

Metadata

Release files for uni-calendar-coloring 1.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for uni-calendar-coloring 1.4.0
File Size Uploaded
uni_calendar_coloring-1.4.0.tar.gz 183.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for uni-calendar-coloring 1.4.0
File Interpreter ABI Platform
uni_calendar_coloring-1.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 292.4 kB

Release files / uni_calendar_coloring-1.4.0.tar.gz

Download URL uni_calendar_coloring-1.4.0.tar.gz
Size 183.4 kB
Tags Source
SHA-256 checksum
How to use checksums
b323e76479d3563d6ef5e5ca91a140dd91cb13d0b552ff500f54a6b124f302d7
BLAKE2b-256 checksum
How to use checksums
2fb40f7b5fde2f529d4e4401cfb572c89be2a60621e8122364aaadd1279739e2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 15, 2026.

Transparency log

Release files / uni_calendar_coloring-1.4.0-py3-none-any.whl

Download URL uni_calendar_coloring-1.4.0-py3-none-any.whl
Size 108.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9e8cf0618fbdfbe0df74bda91b33630fb1b57ddd94e4cdd07ec3713e7b68f702
BLAKE2b-256 checksum
How to use checksums
34ce6b0e7077081de213fe4bed205c61b747fc8fd4d4946d78981d6451550ebe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 15, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.4.0 This release

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page