├── .all-contributorsrc ├── .coveragerc ├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── feature_request.md │ └── suggest_event_type.yml ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml └── workflows │ ├── black.yml │ ├── i18n.yml │ ├── manpage.yml │ ├── release.yml │ ├── semantic-pr.yml │ └── tests.yml ├── .gitignore ├── .gitpod.yml ├── .pylintrc ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── CONTRIBUTORS.md ├── LICENSE.md ├── MANIFEST.in ├── Makefile ├── README.md ├── kosmorro ├── __init__.py ├── __main__.py ├── assets │ ├── moonphases │ │ ├── png │ │ │ ├── first-quarter.png │ │ │ ├── full-moon.png │ │ │ ├── last-quarter.png │ │ │ ├── new-moon.png │ │ │ ├── unknown.png │ │ │ ├── waning-crescent.png │ │ │ ├── waning-gibbous.png │ │ │ ├── waxing-crescent.png │ │ │ └── waxing-gibbous.png │ │ └── svg │ │ │ ├── first-quarter.svg │ │ │ ├── full-moon.svg │ │ │ ├── last-quarter.svg │ │ │ ├── new-moon.svg │ │ │ ├── unknown.svg │ │ │ ├── waning-crescent.svg │ │ │ ├── waning-gibbous.svg │ │ │ ├── waxing-crescent.svg │ │ │ └── waxing-gibbous.svg │ ├── pdf │ │ ├── kosmorro.sty │ │ └── template.tex │ ├── png │ │ ├── kosmorro-icon-white.png │ │ ├── kosmorro-icon.png │ │ ├── kosmorro-logo-white.png │ │ └── kosmorro-logo.png │ └── svg │ │ ├── kosmorro-icon-white.svg │ │ ├── kosmorro-icon.svg │ │ ├── kosmorro-logo-white.svg │ │ └── kosmorro-logo.svg ├── date.py ├── debug.py ├── dumper.py ├── environment.py ├── exceptions.py ├── i18n │ ├── __init__.py │ ├── strings.py │ └── utils.py ├── locales │ ├── de │ │ └── LC_MESSAGES │ │ │ └── messages.po │ ├── es │ │ └── LC_MESSAGES │ │ │ └── messages.po │ ├── fr │ │ └── LC_MESSAGES │ │ │ └── messages.po │ ├── messages.pot │ ├── nb_NO │ │ └── LC_MESSAGES │ │ │ └── messages.po │ ├── nl │ │ └── LC_MESSAGES │ │ │ └── messages.po │ └── ru │ │ └── LC_MESSAGES │ │ └── messages.po └── utils.py ├── manpage ├── README.md ├── kosmorro.1.md └── kosmorro.7.md ├── poetry.lock ├── pyproject.toml ├── setup.cfg └── tests ├── __init__.py ├── dates.py ├── general.py ├── output.py ├── outputs └── 2020-01-27-with-position.tex ├── position.py ├── timezone.py └── utils.py /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "kosmorro", 3 | "projectOwner": "Kosmorro", 4 | "repoType": "github", 5 | "repoHost": "https://github.com", 6 | "files": [ 7 | "CONTRIBUTORS.md" 8 | ], 9 | "imageSize": 100, 10 | "commit": true, 11 | "commitConvention": "angular", 12 | "contributorsSortAlphabetically": true, 13 | "contributors": [ 14 | { 15 | "login": "Deuchnord", 16 | "name": "Jérôme Deuchnord", 17 | "avatar_url": "https://avatars.githubusercontent.com/u/7600265?v=4", 18 | "profile": "https://deuchnord.fr/", 19 | "contributions": [ 20 | "code", 21 | "translation" 22 | ] 23 | }, 24 | { 25 | "login": "Brainface1", 26 | "name": "brain_face", 27 | "avatar_url": "https://avatars.githubusercontent.com/u/40472418?v=4", 28 | "profile": "https://github.com/Brainface1", 29 | "contributions": [ 30 | "code" 31 | ] 32 | }, 33 | { 34 | "login": "Damgermys", 35 | "name": "Damgermys", 36 | "avatar_url": "https://avatars.githubusercontent.com/u/82285874?v=4", 37 | "profile": "https://github.com/Damgermys", 38 | "contributions": [ 39 | "translation" 40 | ] 41 | }, 42 | { 43 | "login": "nicfb", 44 | "name": "Nic", 45 | "avatar_url": "https://avatars.githubusercontent.com/u/19811100?v=4", 46 | "profile": "https://github.com/nicfb", 47 | "contributions": [ 48 | "code" 49 | ] 50 | }, 51 | { 52 | "login": "comradekingu", 53 | "name": "Allan Nordhøy", 54 | "avatar_url": "https://avatars.githubusercontent.com/u/13802408?v=4", 55 | "profile": "https://liberapay.com/kingu/", 56 | "contributions": [ 57 | "translation" 58 | ] 59 | }, 60 | { 61 | "login": "AmauryCarrade", 62 | "name": "Amaury Carrade", 63 | "avatar_url": "https://avatars.githubusercontent.com/u/1417570?v=4", 64 | "profile": "https://amaury.carrade.eu/", 65 | "contributions": [ 66 | "translation" 67 | ] 68 | }, 69 | { 70 | "login": "StaloneLab", 71 | "name": "Titouan S.", 72 | "avatar_url": "https://avatars.githubusercontent.com/u/6739422?v=4", 73 | "profile": "https://github.com/StaloneLab", 74 | "contributions": [ 75 | "translation" 76 | ] 77 | }, 78 | { 79 | "login": "thierry-FreeBSD", 80 | "name": "Thierry Thomas", 81 | "avatar_url": "https://avatars.githubusercontent.com/u/6819982?v=4", 82 | "profile": "http://people.freebsd.org/~thierry/", 83 | "contributions": [ 84 | "platform" 85 | ] 86 | }, 87 | { 88 | "login": "SpeedCode", 89 | "name": "SpeedCode", 90 | "avatar_url": "https://avatars.githubusercontent.com/u/12190842?v=4", 91 | "profile": "https://github.com/SpeedCode", 92 | "contributions": [ 93 | "bug" 94 | ] 95 | }, 96 | { 97 | "login": "ChabaneAmaury", 98 | "name": "Amaury Chabane", 99 | "avatar_url": "https://avatars.githubusercontent.com/u/24982486?v=4", 100 | "profile": "https://github.com/ChabaneAmaury", 101 | "contributions": [ 102 | "ideas" 103 | ] 104 | }, 105 | { 106 | "login": "WinXaito", 107 | "name": "Kevin Vuilleumier", 108 | "avatar_url": "https://avatars.githubusercontent.com/u/8223773?v=4", 109 | "profile": "http://winxaito.com/", 110 | "contributions": [ 111 | "ideas" 112 | ] 113 | }, 114 | { 115 | "login": "romco1410", 116 | "name": "Roman Hanečák", 117 | "avatar_url": "https://avatars.githubusercontent.com/u/40452973?v=4", 118 | "profile": "https://github.com/romco1410", 119 | "contributions": [ 120 | "code" 121 | ] 122 | }, 123 | { 124 | "login": "gallegonovato", 125 | "name": "gallegonovato", 126 | "avatar_url": "https://avatars.githubusercontent.com/u/59177763?v=4", 127 | "profile": "https://github.com/gallegonovato", 128 | "contributions": [ 129 | "translation" 130 | ] 131 | }, 132 | { 133 | "login": "Nic-T", 134 | "name": "Nicolas Tantau", 135 | "avatar_url": "https://avatars.githubusercontent.com/u/67067741?v=4", 136 | "profile": "https://github.com/Nic-T", 137 | "contributions": [ 138 | "translation" 139 | ] 140 | }, 141 | { 142 | "login": "TamilNeram", 143 | "name": "தமிழ்நேரக்குழு", 144 | "avatar_url": "https://avatars.githubusercontent.com/u/67970539?v=4", 145 | "profile": "https://tamilneram.github.io/", 146 | "contributions": [ 147 | "translation" 148 | ] 149 | } 150 | ], 151 | "contributorsPerLine": 7, 152 | "commitType": "docs" 153 | } 154 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | branch = true 3 | source = 4 | kosmorrolib 5 | omit = 6 | kosmorrolib/main.py 7 | test/* 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 4 7 | indent_style = space 8 | insert_final_newline = true 9 | max_line_length = 120 10 | trim_trailing_whitespace = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [*.yml] 16 | indent_size = 2 17 | 18 | [Makefile] 19 | indent_style = tab 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | description: Report a bug you have found, so it can be fixed 3 | labels: 4 | - bug 5 | 6 | body: 7 | - type: markdown 8 | attributes: 9 | value: | 10 | Thanks for taking time to fill out this bug report! 11 | 12 | - type: checkboxes 13 | id: terms 14 | attributes: 15 | label: I have searched for an opened issue and didn't find my bug 16 | description: | 17 | Before continuing, please verify that your bug is not already known, i.e.: 18 | 19 | - there is an issue that describe your bug; 20 | - the issue is not closed. 21 | 22 | If you have found a closed issue that describes the same bug as yours, please don't comment inside and open a new issue instead. 23 | Even though it may look the same, your bug might be totally different :smile: 24 | 25 | options: 26 | - label: I confirm I didn't find any issue regarding my bug 27 | required: true 28 | 29 | - type: dropdown 30 | id: cli-version 31 | validations: 32 | required: true 33 | attributes: 34 | label: Version of Kosmorro 35 | description: | 36 | What version of Kosmorro are you using? 37 | 38 | Note: if you don't know, invoke `kosmorro --version`. 39 | options: 40 | - "0.10" 41 | - "0.9" 42 | - master branch 43 | - features branch 44 | 45 | - type: dropdown 46 | id: python-version 47 | validations: 48 | required: true 49 | attributes: 50 | label: Version of Python 51 | description: | 52 | What version of Python are you using? 53 | 54 | Note: if you don't know, invoke `kosmorro --version` or `python --version`. 55 | 56 | options: 57 | - "3.10" 58 | - "3.9" 59 | - "3.8" 60 | - "3.7" 61 | 62 | - type: dropdown 63 | id: operating-system 64 | validations: 65 | required: true 66 | attributes: 67 | label: Operating system 68 | description: What operating system did you use? 69 | multiple: true 70 | 71 | options: 72 | - Linux 73 | - FreeBSD 74 | - macOS 12 (Monterey) 75 | - macOS 11 (Big Sur) 76 | - macOS 10.15 (Catalina) 77 | - Other 78 | 79 | - type: dropdown 80 | id: install-source 81 | validations: 82 | required: true 83 | attributes: 84 | label: Installation source 85 | description: What did you use to install Kosmorro? 86 | 87 | options: 88 | - Arch User Repository (AUR) 89 | - FreshPorts 90 | - HomeBrew 91 | - PyPI 92 | - I have compiled the package from sources 93 | - Other (explain in the description) 94 | 95 | - type: textarea 96 | id: description 97 | validations: 98 | required: true 99 | attributes: 100 | label: Bug description 101 | description: | 102 | Describe the bug you have encountered: 103 | 104 | - what did you try to do? 105 | - what did you expect the program to do? 106 | - what happened instead? 107 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/suggest_event_type.yml: -------------------------------------------------------------------------------- 1 | name: Event type 2 | description: Suggest an event type 3 | labels: 4 | - enhancement 5 | - events 6 | 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: | 11 | If you think that there's a missing supported event type, fill this form out to suggest it! 12 | 13 | - type: checkboxes 14 | id: involved-objects 15 | attributes: 16 | label: Involved objects 17 | description: | 18 | An event must involve at least one object. 19 | Please select below the objects that take part in it. 20 | 21 | For example, a lunar eclipse involves the Moon, the Earth and the Sun. 22 | 23 | options: 24 | - label: Sun 25 | - label: Earth 26 | - label: Moon 27 | - label: Planets or dwarf planets of the Solar system 28 | - label: Other (explain in description) 29 | 30 | - type: textarea 31 | id: event-definition 32 | validations: 33 | required: true 34 | attributes: 35 | label: Event definition 36 | description: | 37 | Explain the event type you wish to see in Kosmorro. 38 | This can be a simple copy and paste from an external source (don't forget to give the source!). 39 | 40 | - type: textarea 41 | id: other-information 42 | attributes: 43 | label: Other useful information 44 | description: | 45 | If you have any other useful information, feel free to put them here! 46 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | | Q | A 2 | | -------------- | --- 3 | | Bug fix? | yes/no 4 | | New feature? | yes/no 5 | | Related issues | Fix #... 6 | | Has BC-break | yes/no 7 | | License | GNU AGPL-v3 8 | 9 | **Checklist:** 10 | 13 | - [ ] I have updated the manpages 14 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | updates: 4 | - package-ecosystem: pip 5 | directory: "/" 6 | target-branch: master 7 | open-pull-requests-limit: 5 8 | schedule: 9 | interval: daily 10 | reviewers: 11 | - Deuchnord 12 | commit-message: 13 | prefix: chore 14 | include: scope 15 | 16 | - package-ecosystem: github-actions 17 | directory: "/" 18 | open-pull-requests-limit: 5 19 | target-branch: master 20 | schedule: 21 | interval: weekly 22 | reviewers: 23 | - Deuchnord 24 | commit-message: 25 | prefix: ci 26 | include: scope 27 | -------------------------------------------------------------------------------- /.github/workflows/black.yml: -------------------------------------------------------------------------------- 1 | name: Code style 2 | 3 | on: 4 | push: 5 | branches: [master, features] 6 | pull_request: 7 | branches: [master, features] 8 | 9 | jobs: 10 | lint: 11 | runs-on: ubuntu-latest 12 | 13 | name: Code Style 14 | steps: 15 | - uses: actions/checkout@v4 16 | - uses: actions/setup-python@v5 17 | with: 18 | python-version: '3.x' 19 | - uses: psf/black@stable 20 | -------------------------------------------------------------------------------- /.github/workflows/i18n.yml: -------------------------------------------------------------------------------- 1 | name: Internationalization check 2 | 3 | on: 4 | push: 5 | branches: [master, features] 6 | pull_request: 7 | branches: [master, features] 8 | 9 | jobs: 10 | internationalization: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v4 15 | - name: Set up Python 16 | uses: actions/setup-python@v5 17 | with: 18 | python-version: '3.x' 19 | - name: Install dependencies 20 | run: | 21 | pip install --upgrade pip poetry 22 | poetry install 23 | - name: Check i18n 24 | run: | 25 | poetry run pybabel extract --output=/tmp/kosmorro-messages.pot kosmorro 26 | echo 27 | diff=$(diff kosmorro/locales/messages.pot /tmp/kosmorro-messages.pot | grep '^>') 28 | n=$(echo "$diff" | grep -Ev '> "(POT-Creation-Date)|(Generated-By): ' | wc -l) 29 | 30 | if [ "$n" -ne "0" ]; then 31 | echo "❌ The messages file is not up-to-date!" 32 | echo " Please run the following command to fix this:" 33 | echo 34 | echo " make messages" 35 | exit 1 36 | fi 37 | 38 | echo "✔ Messages file up-to-date." 39 | -------------------------------------------------------------------------------- /.github/workflows/manpage.yml: -------------------------------------------------------------------------------- 1 | name: Man pages 2 | 3 | on: 4 | push: 5 | branches: [master, features] 6 | pull_request: 7 | branches: [master, features] 8 | 9 | jobs: 10 | e2e-tests: 11 | runs-on: ubuntu-latest 12 | name: Check 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | 17 | - name: Compile man pages 18 | run: | 19 | sudo gem install ronn 20 | make manpage 21 | 22 | - name: manpage (section 1) 23 | run: | 24 | man -P $(which cat) manpage/kosmorro.1 25 | 26 | - name: manpage (section 7) 27 | run: | 28 | man -P $(which cat) manpage/kosmorro.7 29 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release Application 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | pipy: 9 | name: Build and Release to PyPI 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v4 13 | 14 | - name: Set up Python 15 | uses: actions/setup-python@v5 16 | with: 17 | python-version: '3.x' 18 | 19 | - name: Prepare environment 20 | run: | 21 | python -m pip install --upgrade pip poetry 22 | 23 | - name: Build package 24 | run: | 25 | poetry install 26 | make i18n build 27 | 28 | - name: Publish to PyPI 29 | env: 30 | POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_PASSWORD }} 31 | run: | 32 | poetry publish 33 | -------------------------------------------------------------------------------- /.github/workflows/semantic-pr.yml: -------------------------------------------------------------------------------- 1 | name: "Semantic Pull Request" 2 | 3 | on: 4 | pull_request: 5 | types: 6 | - opened 7 | - edited 8 | - synchronize 9 | 10 | jobs: 11 | main: 12 | name: Validate PR title 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: amannn/action-semantic-pull-request@v5.5.3 16 | env: 17 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 18 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | push: 5 | branches: [master, features] 6 | pull_request: 7 | branches: [master, features] 8 | schedule: 9 | # Run the tests every day at 6:00 AM. 10 | # This allows to run the tests against the relative dates 11 | - cron: "0 6 * * *" 12 | 13 | jobs: 14 | e2e-tests: 15 | runs-on: ${{ matrix.os }} 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | os: 20 | - ubuntu-latest 21 | - macos-latest 22 | python-version: 23 | - '3.8' 24 | - '3.9' 25 | - '3.10' 26 | - '3.11' 27 | - '3.12' 28 | - '3.13' 29 | 30 | name: Python ${{ matrix.python-version }} on ${{ matrix.os }} 31 | steps: 32 | - uses: actions/checkout@v4 33 | 34 | - name: Set up Python 35 | uses: actions/setup-python@v5 36 | with: 37 | python-version: ${{ matrix.python-version }} 38 | 39 | - name: Install dependencies 40 | run: | 41 | pip install -U pip poetry 42 | poetry env use $(which python) 43 | poetry install 44 | 45 | - name: E2E tests 46 | run: | 47 | make tests 48 | 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | /build 3 | /dist 4 | kosmorro.egg-info 5 | .coverage 6 | coverage.xml 7 | 8 | /kosmorrolib/assets/pdf/* 9 | !/kosmorrolib/assets/pdf/*.tex 10 | !/kosmorrolib/assets/pdf/*.sty 11 | 12 | /manpage/* 13 | !/manpage/*.md 14 | 15 | # Compiled internationalization files 16 | *.mo 17 | 18 | # GitPod-specific: 19 | /.vscode/** 20 | 21 | # AppImage builds 22 | /AppDir 23 | /appimage-builder-cache 24 | *.AppImage 25 | *.AppImage.zsync 26 | 27 | # Changelog-specific 28 | /node_modules 29 | package.json 30 | package-lock.json 31 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | github: 2 | prebuilds: 3 | pullRequestsFromForks: true 4 | 5 | vscode: 6 | extensions: 7 | - ms-vscode.makefile-tools 8 | - james-yu.latex-workshop 9 | - editorconfig.editorconfig 10 | 11 | tasks: 12 | - before: sudo apt update && sudo apt install -y texlive texlive-latex-extra 13 | - before: pip install -U pip poetry 14 | init: poetry install 15 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | jerome@deuchnord.fr. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Kosmorro 2 | 3 | If you are reading this, then you are probably looking for a way to contribute to Kosmorro (you're in the good place!). Thank you! 4 | There are multiple ways to contribute that can match with your possibilities. 5 | 6 | ## Opening issues 7 | 8 | ### Reporting bugs 9 | 10 | If you found a bug, please check it is not already reported in the _Issues_ tab. 11 | If it is not, [create a bug report](https://github.com/Deuchnord/kosmorro/issues/new/choose) and fill in the template that offers to you. Feel free to give as much information as possible, as it will make the bug easier to fix. 12 | 13 | ### Suggest a new feature 14 | 15 | Have an idea of feature you think would be nice on Kosmorro? Time to suggest it! 16 | First, please check someone didn't suggest your next revolution in the _Issues_ tab. If it's not, [create a feature request](https://github.com/Deuchnord/kosmorro/issues/new/choose) and fill in the templace that offers to you. 17 | 18 | ## Translating 19 | 20 | If you speak another language than English, another nice way to enhance Kosmorro is to translate its messages. The recommended way to begin translating Kosmorro is to [join the Weblate project](https://hosted.weblate.org/engage/kosmorro/). 21 | 22 | ## Writing code 23 | 24 | [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/Kosmorro/kosmorro) 25 | 26 | First, if you are fixing an opened issue, check that nobody is already working on it — if someone seems to be but their Pull Request seems stuck, please ask them first if you can continue the development. If you retake the code they produced, **don't change the author of the commits**. 27 | 28 | Before writing the code, first create a fork of the repository and clone it. You may also want to add the original repository (`Kosmorro/kosmorro`), so you can update your fork with the last upstream commits. 29 | 30 | Then create a new branch and start coding. Finally, commit and push, then open a PR on this project. If your project is not complete, feel free to open it as Draft, then mark it as ready for review when you're done. 31 | 32 | ### Choosing the right target branch 33 | 34 | Whatever you are doing, always base your working branch on `master`. 35 | When you create your PR, please consider selecting the right target branch: 36 | 37 | - If you are fixing a bug or optimizing something, then target the `master` branch. 38 | - If you are doing anything else, then target the `features` branch. 39 | 40 | This allows to make easier to publish patch releases, which have a higher priority than the minor releases. 41 | 42 | ### Dealing with the translations 43 | 44 | The messages file contains all the messages Kosmorro can display, in order to make them translatable. When you change code, you may change also the messages displayed by the software. 45 | 46 | When you add a new string that will be displayed to the end user, please pass it to the `_()` function made available in the `kosmorrolib.i18n` package, for instance: 47 | 48 | ```python 49 | # Don't: 50 | print('Note: All the hours are given in UTC.') 51 | 52 | # Do: 53 | from kosmorro.i18n import _ 54 | print(_('Note: All the hours are given in UTC.')) 55 | ``` 56 | 57 | This will allow Python's internationalization tool to translate the string in any available language. 58 | 59 | Once you have done your work, please remember to tell [Babel](http://babel.pocoo.org) to extract the new strings: 60 | 61 | ```bash 62 | make messages 63 | ``` 64 | 65 | Note that if you forget to update the messages file, the CI will fail. 66 | 67 | ### Matching the coding standards 68 | 69 | Kosmorro's source code follows the major coding standards of Python (PEPs). 70 | Before marking your Pull Request as ready for review, don't forget to check that the code respects the coding standards with Black: 71 | 72 | ```bash 73 | make black 74 | ``` 75 | 76 | ### Testing the code 77 | 78 | The tests are located in the `/tests` folder. 79 | Their principle is pretty simple: 80 | 81 | 1. First, we run a Kosmorro command as we would in command line application. We use the [Aurornis](https://pypi.org/project/aurornis/) package to do this. 82 | 2. Then, we test the return of the command against what we expected. We use [PyTest](https://pypi.org/project/pytest/) to do this. 83 | 84 | To run the tests, invoke the following command: 85 | 86 | ```bash 87 | make tests 88 | 89 | # Or, if you have TeXLive installed on your machine (Linux only): 90 | make TEXLIVE_INSTALLED=1 tests 91 | ``` 92 | 93 | ### Commiting 94 | 95 | The commit messages of this project follow the [Conventional Commits Specification](https://www.conventionalcommits.org/en/v1.0.0/): basically, when you commit your changes, please prefix them with the following: 96 | 97 | - **`fix: `** if your changes fix a bug; 98 | - **`feat: `** if your changes add a new feature. 99 | 100 | The message of your commit must start with a lowercase. 101 | Finally, if your change introduce a BC-break, add a footer beginning with `BREAKING CHANGE:` and explaining precisely the BC-break. 102 | 103 | Once your PR is ready to review, please squash your commits so it contains only one commit. 104 | 105 | > To ensure your commits follow this convention, you can use [glint](https://github.com/brigand/glint). 106 | 107 | The commit messages are then used to generate the changelog using [`conventional-changelog`](https://github.com/conventional-changelog/conventional-changelog). 108 | 109 | ## Licensing and Copyright Attribution 110 | 111 | When you open a Pull Request to the project, you agree to license your code under the [GNU Affero General Public License version 3](https://www.gnu.org/licenses/agpl-3.0.html). 112 | -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [![All Contributors](https://img.shields.io/badge/all_contributors-15-orange.svg?style=flat-square)](#contributors-) 4 | 5 | ## Contributors ✨ 6 | 7 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
Allan Nordhøy
Allan Nordhøy

🌍
Amaury Carrade
Amaury Carrade

🌍
Amaury Chabane
Amaury Chabane

🤔
Damgermys
Damgermys

🌍
Jérôme Deuchnord
Jérôme Deuchnord

💻 🌍
Kevin Vuilleumier
Kevin Vuilleumier

🤔
Nic
Nic

💻
Nicolas Tantau
Nicolas Tantau

🌍
Roman Hanečák
Roman Hanečák

💻
SpeedCode
SpeedCode

🐛
Thierry Thomas
Thierry Thomas

📦
Titouan S.
Titouan S.

🌍
brain_face
brain_face

💻
gallegonovato
gallegonovato

🌍
தமிழ் நேரம்
தமிழ்நேரக்குழு

🌍
37 | 38 | 39 | 40 | 41 | 42 | 43 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! 44 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include _kosmorro/locales * 2 | recursive-include _kosmorro/assets * 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | black: 2 | poetry run black kosmorro tests 3 | 4 | .PHONY: tests 5 | tests: 6 | LANG=C python3 -m poetry run pytest tests/*.py 7 | 8 | .PHONY: build 9 | build: 10 | poetry build 11 | 12 | .PHONY: manpage 13 | manpage: 14 | ronn --roff manpage/kosmorro.1.md 15 | ronn --roff manpage/kosmorro.7.md 16 | 17 | messages: 18 | poetry run pybabel extract --output=kosmorro/locales/messages.pot kosmorro 19 | 20 | i18n: 21 | poetry run pybabel compile --directory=kosmorro/locales 22 | 23 | changelog: install-conventional-changelog generate-changelog delete-conventional-changelog 24 | 25 | 26 | install-conventional-changelog: 27 | npm install conventional-changelog-cli 28 | 29 | generate-changelog: 30 | node_modules/.bin/conventional-changelog -p angular -i CHANGELOG.md -s 31 | 32 | prepare-release: messages changelog 33 | 34 | delete-conventional-changelog: 35 | rm -rf \ 36 | node_modules \ 37 | package{,-lock}.json 38 | 39 | clean: delete-conventional-changelog 40 | rm -rf \ 41 | build \ 42 | dist appimage-builder-cache \ 43 | kosmorro.egg-info \ 44 | manpage/kosmorro.{1,7}{,.html} 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ![Kosmorro](https://github.com/Kosmorro/logos/raw/main/kosmorro/kosmorro-artwork.jpg) 2 | [![Version on PyPI](https://img.shields.io/pypi/v/kosmorro)](https://pypi.org/project/kosmorro) [![Packaging status](https://repology.org/badge/tiny-repos/kosmorro.svg)](https://repology.org/project/kosmorro/versions) [![Help translating Kosmorro!](https://hosted.weblate.org/widgets/kosmorro/-/cli/svg-badge.svg)](https://hosted.weblate.org/engage/kosmorro/) 3 | 4 | Kosmorro is a program that calculates your astronomical ephemerides. 5 | 6 | ## Installation 7 | 8 | Installing Kosmorro is documented on [the official website](https://kosmorro.space/cli/download/). Just select your operating system and follow the instructions! 9 | 10 | ### Development environment 11 | 12 | To contribute to Kosmorrolib, you will need [Poetry](https://python-poetry.org), a software to manage the project from development to publishing. 13 | 14 | Clone this repository and run `poetry install` to install the dependencies. 15 | And that's all, your development environment is ready! 16 | 17 | To run Kosmorro, invoke `poetry run kosmorro`. For comfort, you may also want to invoke `poetry shell`, which will expose the `kosmorro` command directly. 18 | 19 | ## Using Kosmorro 20 | 21 | Using Kosmorro is as simple as invoking `kosmorro` in your terminal! 22 | 23 | By default, it will give you the current Moon phase and, if any, the events that will occur today. 24 | 25 | Kosmorro has a lot of available options to get exactly what you want, including the possibility to get planets rise and set. To get a list of them, run `kosmorro --help`, or read its manual with `man kosmorro`. You can also find usage examples in [the `tldr` manual](https://tldr.sh) with [`tldr kosmorro`](https://tldr.inbrowser.app/pages/common/kosmorro). 26 | 27 | ## Help translating Kosmorro! 28 | 29 | Kosmorro is translated on [Weblate](https://hosted.weblate.org/engage/kosmorro/), a popular free platform for crowd-sourced internationalization. 30 | If you speak a language that is not supported yet, feel free to contribute! 31 | 32 | ![Translation state per language](https://hosted.weblate.org/widgets/kosmorro/-/cli/multi-auto.svg) 33 | -------------------------------------------------------------------------------- /kosmorro/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Kosmorro - Compute The Next Ephemerides 4 | # Copyright (C) 2019 Jérôme Deuchnord 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as 8 | # published by the Free Software Foundation, either version 3 of the 9 | # License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | -------------------------------------------------------------------------------- /kosmorro/__main__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Kosmorro - Compute The Next Ephemerides 4 | # Copyright (C) 2019 Jérôme Deuchnord 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as 8 | # published by the Free Software Foundation, either version 3 of the 9 | # License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | 19 | import argparse 20 | import sys 21 | 22 | from babel.dates import format_date 23 | from kosmorrolib import Position, get_ephemerides, get_events, get_moon_phase 24 | from kosmorrolib.exceptions import OutOfRangeDateError 25 | from datetime import date 26 | 27 | from . import dumper, environment, debug 28 | from .date import parse_date 29 | from .utils import KOSMORRO_VERSION, KOSMORROLIB_VERSION, colored, set_colors_activated 30 | from .exceptions import UnavailableFeatureError, OutOfRangeDateError as DateRangeError 31 | from kosmorro.i18n.utils import _ 32 | 33 | 34 | def run(): 35 | env_vars = environment.get_env_vars() 36 | output_formats = get_dumpers() 37 | args = get_args(list(output_formats.keys())) 38 | debug.show_debug_messages = args.show_debug_messages 39 | output_format = args.format 40 | 41 | set_colors_activated(args.colors) 42 | 43 | if args.special_action is not None: 44 | return 0 if args.special_action() else 1 45 | 46 | try: 47 | compute_date = parse_date(args.date) 48 | except ValueError as error: 49 | print(colored(error.args[0], color="red", attrs=["bold"])) 50 | return -1 51 | 52 | position = None 53 | 54 | if args.latitude is not None or args.longitude is not None: 55 | position = Position(args.latitude, args.longitude) 56 | elif env_vars.latitude is not None and env_vars.longitude is not None: 57 | position = Position(float(env_vars.latitude), float(env_vars.longitude)) 58 | 59 | if output_format == "pdf": 60 | print( 61 | _( 62 | "Save the planet and paper!\n" 63 | "Consider printing your PDF document only if really necessary, and use the other side of the sheet." 64 | ) 65 | ) 66 | if position is None: 67 | print() 68 | print( 69 | colored( 70 | _( 71 | "PDF output will not contain the ephemerides, because you didn't provide the observation " 72 | "coordinates." 73 | ), 74 | "yellow", 75 | ) 76 | ) 77 | 78 | timezone = args.timezone 79 | 80 | if timezone is None and env_vars.timezone is not None: 81 | timezone = int(env_vars.timezone) 82 | elif timezone is None: 83 | timezone = 0 84 | 85 | try: 86 | output = get_information( 87 | compute_date, 88 | position, 89 | timezone, 90 | output_format, 91 | args.colors, 92 | args.show_graph, 93 | ) 94 | except UnavailableFeatureError as error: 95 | print(colored(error.msg, "red")) 96 | debug.debug_print(error) 97 | return 2 98 | except DateRangeError as error: 99 | print(colored(error.msg, "red")) 100 | debug.debug_print(error) 101 | return 1 102 | 103 | if args.output is not None: 104 | try: 105 | pdf_content = output.to_string() 106 | with open(args.output, "wb") as output_file: 107 | output_file.write(pdf_content) 108 | except UnavailableFeatureError as error: 109 | print(colored(error.msg, "red")) 110 | debug.debug_print(error) 111 | return 2 112 | except OSError as error: 113 | print( 114 | colored( 115 | _('The file could not be saved in "{path}": {error}').format( 116 | path=args.output, error=error.strerror 117 | ), 118 | "red", 119 | ) 120 | ) 121 | debug.debug_print(error) 122 | 123 | return 3 124 | elif not output.is_file_output_needed(): 125 | print(output) 126 | else: 127 | print( 128 | colored( 129 | _("Please provide a file path to export in this format (--output)."), 130 | color="red", 131 | ) 132 | ) 133 | return 1 134 | 135 | return 0 136 | 137 | 138 | def get_information( 139 | compute_date: date, 140 | position: Position, 141 | timezone: int, 142 | output_format: str, 143 | colors: bool, 144 | show_graph: bool, 145 | ) -> dumper.Dumper: 146 | if position is not None: 147 | try: 148 | eph = get_ephemerides( 149 | for_date=compute_date, position=position, timezone=timezone 150 | ) 151 | except OutOfRangeDateError as error: 152 | raise DateRangeError(error.min_date, error.max_date) 153 | else: 154 | eph = [] 155 | 156 | try: 157 | moon_phase = get_moon_phase(for_date=compute_date, timezone=timezone) 158 | except OutOfRangeDateError as error: 159 | moon_phase = None 160 | print( 161 | colored( 162 | _( 163 | "Moon phase can only be computed between {min_date} and {max_date}" 164 | ).format( 165 | min_date=format_date(error.min_date, "long"), 166 | max_date=format_date(error.max_date, "long"), 167 | ), 168 | "yellow", 169 | ) 170 | ) 171 | 172 | events_list = get_events(compute_date, timezone) 173 | 174 | return get_dumpers()[output_format]( 175 | ephemerides=eph, 176 | moon_phase=moon_phase, 177 | events=events_list, 178 | date=compute_date, 179 | timezone=timezone, 180 | with_colors=colors, 181 | show_graph=show_graph, 182 | ) 183 | 184 | 185 | def get_dumpers() -> {str: dumper.Dumper}: 186 | return { 187 | "text": dumper.TextDumper, 188 | "json": dumper.JsonDumper, 189 | "pdf": dumper.PdfDumper, 190 | } 191 | 192 | 193 | def output_version() -> bool: 194 | python_version = "%d.%d.%d" % ( 195 | sys.version_info[0], 196 | sys.version_info[1], 197 | sys.version_info[2], 198 | ) 199 | print("Kosmorro %s" % KOSMORRO_VERSION) 200 | print( 201 | _( 202 | "Running on Python {python_version} " 203 | "with Kosmorrolib v{kosmorrolib_version}" 204 | ).format(python_version=python_version, kosmorrolib_version=KOSMORROLIB_VERSION) 205 | ) 206 | 207 | return True 208 | 209 | 210 | def get_args(output_formats: [str]): 211 | today = date.today() 212 | 213 | parser = argparse.ArgumentParser( 214 | description=_( 215 | "Compute the ephemerides and the events for a given date and a given position on Earth." 216 | ), 217 | epilog=_( 218 | "By default, only the events will be computed for today.\n" 219 | "To compute also the ephemerides, latitude and longitude arguments are needed." 220 | ), 221 | ) 222 | 223 | parser.add_argument( 224 | "--version", 225 | "-v", 226 | dest="special_action", 227 | action="store_const", 228 | const=output_version, 229 | default=None, 230 | help=_("Show the program version"), 231 | ) 232 | parser.add_argument( 233 | "--format", 234 | "-f", 235 | type=str, 236 | default=output_formats[0], 237 | choices=output_formats, 238 | help=_("The format to output the information to"), 239 | ) 240 | parser.add_argument( 241 | "--latitude", 242 | "-lat", 243 | type=float, 244 | default=None, 245 | help=_( 246 | "The observer's latitude on Earth. Can also be set in the KOSMORRO_LATITUDE environment " 247 | "variable." 248 | ), 249 | ) 250 | parser.add_argument( 251 | "--longitude", 252 | "-lon", 253 | type=float, 254 | default=None, 255 | help=_( 256 | "The observer's longitude on Earth. Can also be set in the KOSMORRO_LONGITUDE " 257 | "environment variable." 258 | ), 259 | ) 260 | parser.add_argument( 261 | "--date", 262 | "-d", 263 | type=str, 264 | default=today.strftime("%Y-%m-%d"), 265 | help=_( 266 | "The date for which the ephemerides must be calculated. Can be in the YYYY-MM-DD format " 267 | 'or an interval in the "[+-]YyMmDd" format (with Y, M, and D numbers). ' 268 | "Defaults to current date." 269 | ).format(default_date=today.strftime("%Y-%m-%d")), 270 | ) 271 | parser.add_argument( 272 | "--timezone", 273 | "-t", 274 | type=int, 275 | default=None, 276 | help=_( 277 | "The timezone to display the hours in (e.g. 2 for UTC+2 or -3 for UTC-3). " 278 | "Can also be set in the KOSMORRO_TIMEZONE environment variable." 279 | ), 280 | ) 281 | parser.add_argument( 282 | "--no-colors", 283 | dest="colors", 284 | action="store_false", 285 | help=_("Disable the colors in the console."), 286 | ) 287 | parser.add_argument( 288 | "--output", 289 | "-o", 290 | type=str, 291 | default=None, 292 | help=_( 293 | "A file to export the output to. If not given, the standard output is used. " 294 | "This argument is needed for PDF format." 295 | ), 296 | ) 297 | parser.add_argument( 298 | "--no-graph", 299 | dest="show_graph", 300 | action="store_false", 301 | help=_( 302 | "Do not generate a graph to represent the rise and set times in the PDF format." 303 | ), 304 | ) 305 | parser.add_argument( 306 | "--debug", 307 | dest="show_debug_messages", 308 | action="store_true", 309 | help=_("Show debugging messages"), 310 | ) 311 | 312 | return parser.parse_args() 313 | 314 | 315 | def main(): 316 | sys.exit(run()) 317 | -------------------------------------------------------------------------------- /kosmorro/assets/moonphases/png/first-quarter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmorro/kosmorro/d7def507034e6af0d7c7bdbc4d4174b046b082ac/kosmorro/assets/moonphases/png/first-quarter.png -------------------------------------------------------------------------------- /kosmorro/assets/moonphases/png/full-moon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmorro/kosmorro/d7def507034e6af0d7c7bdbc4d4174b046b082ac/kosmorro/assets/moonphases/png/full-moon.png -------------------------------------------------------------------------------- /kosmorro/assets/moonphases/png/last-quarter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmorro/kosmorro/d7def507034e6af0d7c7bdbc4d4174b046b082ac/kosmorro/assets/moonphases/png/last-quarter.png -------------------------------------------------------------------------------- /kosmorro/assets/moonphases/png/new-moon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmorro/kosmorro/d7def507034e6af0d7c7bdbc4d4174b046b082ac/kosmorro/assets/moonphases/png/new-moon.png -------------------------------------------------------------------------------- /kosmorro/assets/moonphases/png/unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmorro/kosmorro/d7def507034e6af0d7c7bdbc4d4174b046b082ac/kosmorro/assets/moonphases/png/unknown.png -------------------------------------------------------------------------------- /kosmorro/assets/moonphases/png/waning-crescent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmorro/kosmorro/d7def507034e6af0d7c7bdbc4d4174b046b082ac/kosmorro/assets/moonphases/png/waning-crescent.png -------------------------------------------------------------------------------- /kosmorro/assets/moonphases/png/waning-gibbous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmorro/kosmorro/d7def507034e6af0d7c7bdbc4d4174b046b082ac/kosmorro/assets/moonphases/png/waning-gibbous.png -------------------------------------------------------------------------------- /kosmorro/assets/moonphases/png/waxing-crescent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmorro/kosmorro/d7def507034e6af0d7c7bdbc4d4174b046b082ac/kosmorro/assets/moonphases/png/waxing-crescent.png -------------------------------------------------------------------------------- /kosmorro/assets/moonphases/png/waxing-gibbous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmorro/kosmorro/d7def507034e6af0d7c7bdbc4d4174b046b082ac/kosmorro/assets/moonphases/png/waxing-gibbous.png -------------------------------------------------------------------------------- /kosmorro/assets/moonphases/svg/first-quarter.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 16 | 25 | 32 | 36 | 40 | 41 | 42 | 44 | 45 | 47 | image/svg+xml 48 | 50 | 51 | 52 | 53 | 54 | 57 | 60 | 64 | 68 | 72 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /kosmorro/assets/moonphases/svg/full-moon.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 16 | 25 | 32 | 36 | 40 | 41 | 42 | 44 | 45 | 47 | image/svg+xml 48 | 50 | 51 | 52 | 53 | 54 | 57 | 60 | 64 | 68 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /kosmorro/assets/moonphases/svg/last-quarter.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 16 | 25 | 32 | 36 | 40 | 41 | 42 | 44 | 45 | 47 | image/svg+xml 48 | 50 | 51 | 52 | 53 | 54 | 57 | 60 | 64 | 68 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /kosmorro/assets/moonphases/svg/new-moon.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 16 | 25 | 32 | 36 | 40 | 41 | 42 | 44 | 45 | 47 | image/svg+xml 48 | 50 | 51 | 52 | 53 | 54 | 57 | 60 | 64 | 68 | 72 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /kosmorro/assets/moonphases/svg/unknown.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | image/svg+xml 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /kosmorro/assets/moonphases/svg/waning-crescent.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 16 | 25 | 32 | 36 | 40 | 41 | 42 | 44 | 45 | 47 | image/svg+xml 48 | 50 | 51 | 52 | 53 | 54 | 57 | 60 | 64 | 68 | 72 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /kosmorro/assets/moonphases/svg/waning-gibbous.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 16 | 25 | 32 | 36 | 40 | 41 | 42 | 44 | 45 | 47 | image/svg+xml 48 | 50 | 51 | 52 | 53 | 54 | 57 | 60 | 64 | 68 | 72 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /kosmorro/assets/moonphases/svg/waxing-crescent.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 16 | 25 | 32 | 36 | 40 | 41 | 42 | 44 | 45 | 47 | image/svg+xml 48 | 50 | 51 | 52 | 53 | 54 | 57 | 60 | 64 | 68 | 72 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /kosmorro/assets/moonphases/svg/waxing-gibbous.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 16 | 25 | 32 | 36 | 40 | 41 | 42 | 44 | 45 | 47 | image/svg+xml 48 | 50 | 51 | 52 | 53 | 54 | 57 | 60 | 64 | 68 | 72 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /kosmorro/assets/pdf/kosmorro.sty: -------------------------------------------------------------------------------- 1 | %! Package = kosmorro 2 | %! Author = Jérôme Deuchnord 3 | %! Date = 2020-04-26 4 | 5 | \NeedsTeXFormat{LaTeX2e}[1994/06/01] 6 | \ProvidesPackage{kosmorro}[2020/04/26 Kosmorro Package] 7 | 8 | \RequirePackage{xcolor} 9 | \RequirePackage{fp} 10 | 11 | \newcommand{\moonphase}[2]{ 12 | \begin{center} 13 | \begin{minipage}{2cm} 14 | \includegraphics[width=\linewidth]{#1} 15 | \end{minipage} 16 | \hspace{5mm} 17 | \begin{minipage}{7cm} 18 | \textbf{\currentmoonphasetitle}\\#2 19 | \end{minipage} 20 | \end{center} 21 | } 22 | 23 | \newenvironment{ephemerides}{ 24 | \begin{table}[h] 25 | \centering 26 | \begin{tabular}{lccc} 27 | \textbf{\ephemeridesobjecttitle} & 28 | \textbf{\ephemeridesrisetimetitle} & 29 | \textbf{\ephemeridesculminationtimetitle} & 30 | \textbf{\ephemeridessettimetitle}\\ 31 | \hline 32 | }{ 33 | \end{tabular} 34 | \end{table} 35 | } 36 | 37 | \newcommand{\object}[4]{ 38 | \hline 39 | \textbf{#1} & {#2} & {#3} & {#4}\\ 40 | } 41 | 42 | \newenvironment{graphephemerides}{\setlength{\unitlength}{0.02\linewidth} 43 | \begin{picture}(20,20) 44 | % Axes 45 | \put(0,-2){\vector(1,0){50}} 46 | \multiput(0,-2)(2,0){24}{ 47 | \line(0,-1){0.25} 48 | } 49 | \newcounter{hour} 50 | \multiput(-0.25,-3.5)(4,0){12}{ 51 | \sffamily\footnotesize 52 | \arabic{hour}\stepcounter{hour}\stepcounter{hour} 53 | } 54 | \put(49,-3.5){\sffamily\footnotesize \hourslabel} 55 | 56 | % Graduation 57 | 58 | \put(50,-0.5){\sffamily\footnotesize \Pluto} 59 | \put(50,1.5){\sffamily\footnotesize \Neptune} 60 | \put(50,3.5){\sffamily\footnotesize \Uranus} 61 | \put(50,5.5){\sffamily\footnotesize \Saturn} 62 | \put(50,7.5){\sffamily\footnotesize \Jupiter} 63 | \put(50,9.5){\sffamily\footnotesize \Mars} 64 | \put(50,11.5){\sffamily\footnotesize \Venus} 65 | \put(50,13.5){\sffamily\footnotesize \Mercury} 66 | \put(50,15.5){\sffamily\footnotesize \Moon} 67 | \put(50,17.5){\sffamily\footnotesize \Sun} 68 | 69 | \multiput(0,0)(0,2){10}{ 70 | \color{gray}\line(1,0){48} 71 | } 72 | 73 | \linethickness{1.5mm} 74 | }{ 75 | \end{picture} 76 | \vspace{1cm} 77 | } 78 | 79 | \newcommand{\graphobject}[8]{% 80 | % #1: Y coordinate component 81 | % #2: Color 82 | % #3: Hour rise time 83 | % #4: Minute rise time 84 | % #5: Hour set time 85 | % #6: Minute set time 86 | % #7: Human-readable rise time 87 | % #8: Human-readable set time 88 | 89 | \FPeval{\start}{#3*2+(#4/60)*2}% 90 | \FPeval{\length}{#5*2+(#6/60)*2 - \start}% 91 | \FPeval{\starttext}{\start+0.7}% 92 | \FPeval{\endtext}{\start+\length-3.25}% 93 | 94 | {\color{#2}% 95 | \put(\start,#1){% 96 | \line(1, 0){\length}% 97 | }}% 98 | 99 | \put(\starttext,#1.5){\sffamily\footnotesize #7}% 100 | \put(\endtext,#1.5){\sffamily\footnotesize #8}% 101 | } 102 | 103 | \newcommand{\event}[2]{ 104 | \textbf{#1} & {#2}\\ 105 | } 106 | 107 | \newenvironment{events}{ 108 | \begin{table}[h] 109 | \begin{tabular}{ll} 110 | }{ 111 | \end{tabular} 112 | \end{table} 113 | } 114 | 115 | \endinput 116 | -------------------------------------------------------------------------------- /kosmorro/assets/pdf/template.tex: -------------------------------------------------------------------------------- 1 | \documentclass[a4paper,12pt]{article} 2 | 3 | \usepackage[utf8]{inputenc} 4 | \usepackage[T1]{fontenc} 5 | \usepackage[margin=25mm]{geometry} 6 | \usepackage{graphicx} 7 | \usepackage{hyperref} 8 | \usepackage{kosmorro} 9 | \usepackage{lmodern} 10 | 11 | \newcommand{\currentmoonphasetitle}{+++CURRENT-MOON-PHASE-TITLE+++} 12 | \newcommand{\ephemeridesobjecttitle}{+++EPHEMERIDES-OBJECT+++} 13 | \newcommand{\ephemeridesrisetimetitle}{+++EPHEMERIDES-RISE-TIME+++} 14 | \newcommand{\ephemeridesculminationtimetitle}{+++EPHEMERIDES-CULMINATION-TIME+++} 15 | \newcommand{\ephemeridessettimetitle}{+++EPHEMERIDES-SET-TIME+++} 16 | \newcommand{\hourslabel}{+++GRAPH_LABEL_HOURS+++} 17 | 18 | \newcommand{\Pluto}{+++ASTER_PLUTO+++} 19 | \newcommand{\Neptune}{+++ASTER_NEPTUNE+++} 20 | \newcommand{\Uranus}{+++ASTER_URANUS+++} 21 | \newcommand{\Saturn}{+++ASTER_SATURN+++} 22 | \newcommand{\Jupiter}{+++ASTER_JUPITER+++} 23 | \newcommand{\Mars}{+++ASTER_MARS+++} 24 | \newcommand{\Venus}{+++ASTER_VENUS+++} 25 | \newcommand{\Mercury}{+++ASTER_MERCURY+++} 26 | \newcommand{\Moon}{+++ASTER_MOON+++} 27 | \newcommand{\Sun}{+++ASTER_SUN+++} 28 | 29 | % Fix Unicode issues 30 | \DeclareUnicodeCharacter{202F}{~} 31 | \DeclareUnicodeCharacter{00B0}{$^\circ$} 32 | 33 | \hypersetup{pdfinfo={% 34 | Title={+++DOCUMENT-TITLE+++}, 35 | Creator={Kosmorro v+++KOSMORRO-VERSION+++} 36 | }} 37 | 38 | \pagenumbering{gobble} 39 | \setcounter{secnumdepth}{0} 40 | 41 | \title{\sffamily\href{http://kosmorro.space}{\includegraphics[width=5cm]{+++KOSMORRO-LOGO+++}}\\+++DOCUMENT-TITLE+++} 42 | \date{\vspace{-11mm}\sffamily +++DOCUMENT-DATE+++} 43 | 44 | \begin{document} 45 | 46 | \maketitle 47 | 48 | +++INTRODUCTION+++ 49 | 50 | \moonphase{+++MOON-PHASE-GRAPHICS+++}{+++CURRENT-MOON-PHASE+++} 51 | 52 | %%% BEGIN-EPHEMERIDES-SECTION 53 | \section{\sffamily +++SECTION-EPHEMERIDES+++} 54 | 55 | \begin{ephemerides} 56 | +++EPHEMERIDES+++ 57 | \end{ephemerides} 58 | %%% END-EPHEMERIDES-SECTION 59 | 60 | %%% BEGIN-EVENTS-SECTION 61 | \section{\sffamily +++SECTION-EVENTS+++} 62 | 63 | \begin{events} 64 | +++EVENTS+++ 65 | \end{events} 66 | %%% END-EVENTS-SECTION 67 | 68 | \end{document} 69 | -------------------------------------------------------------------------------- /kosmorro/assets/png/kosmorro-icon-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmorro/kosmorro/d7def507034e6af0d7c7bdbc4d4174b046b082ac/kosmorro/assets/png/kosmorro-icon-white.png -------------------------------------------------------------------------------- /kosmorro/assets/png/kosmorro-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmorro/kosmorro/d7def507034e6af0d7c7bdbc4d4174b046b082ac/kosmorro/assets/png/kosmorro-icon.png -------------------------------------------------------------------------------- /kosmorro/assets/png/kosmorro-logo-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmorro/kosmorro/d7def507034e6af0d7c7bdbc4d4174b046b082ac/kosmorro/assets/png/kosmorro-logo-white.png -------------------------------------------------------------------------------- /kosmorro/assets/png/kosmorro-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmorro/kosmorro/d7def507034e6af0d7c7bdbc4d4174b046b082ac/kosmorro/assets/png/kosmorro-logo.png -------------------------------------------------------------------------------- /kosmorro/assets/svg/kosmorro-icon-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 41 | 43 | 46 | 53 | 54 | 58 | 63 | 69 | 74 | 79 | 85 | 86 | 90 | 95 | 101 | 106 | 111 | 117 | 118 | 119 | 121 | 122 | 124 | image/svg+xml 125 | 127 | 128 | 129 | 130 | 131 | 134 | 141 | 146 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /kosmorro/assets/svg/kosmorro-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 41 | 43 | 46 | 53 | 54 | 58 | 63 | 69 | 74 | 79 | 85 | 86 | 90 | 95 | 101 | 106 | 111 | 117 | 118 | 119 | 121 | 122 | 124 | image/svg+xml 125 | 127 | 128 | 129 | 130 | 131 | 134 | 141 | 146 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /kosmorro/assets/svg/kosmorro-logo-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 41 | 43 | 46 | 53 | 54 | 58 | 63 | 69 | 74 | 79 | 85 | 86 | 87 | 89 | 90 | 92 | image/svg+xml 93 | 95 | 96 | 97 | 98 | 99 | 101 | 108 | 113 | 118 | 123 | 128 | 133 | 138 | 143 | 148 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /kosmorro/assets/svg/kosmorro-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 41 | 43 | 46 | 53 | 54 | 58 | 63 | 69 | 74 | 79 | 85 | 86 | 87 | 89 | 90 | 92 | image/svg+xml 93 | 95 | 96 | 97 | 98 | 99 | 101 | 108 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /kosmorro/date.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import re 4 | 5 | from dateutil.relativedelta import relativedelta 6 | from datetime import date 7 | 8 | from kosmorro.i18n.utils import _ 9 | 10 | 11 | def parse_date(date_arg: str) -> date: 12 | if re.match(r"^\d{4}-\d{2}-\d{2}$", date_arg): 13 | try: 14 | return date.fromisoformat(date_arg) 15 | except ValueError as error: 16 | raise ValueError( 17 | _("The date {date} is not valid: {error}").format( 18 | date=date_arg, error=error.args[0] 19 | ) 20 | ) from error 21 | elif re.match(r"^([+-])(([0-9]+)y)?[ ]?(([0-9]+)m)?[ ]?(([0-9]+)d)?$", date_arg): 22 | 23 | def get_offset(date_arg: str, signifier: str): 24 | if re.search(r"([0-9]+)" + signifier, date_arg): 25 | return abs( 26 | int(re.search(r"[+-]?([0-9]+)" + signifier, date_arg).group(0)[:-1]) 27 | ) 28 | return 0 29 | 30 | days = get_offset(date_arg, "d") 31 | months = get_offset(date_arg, "m") 32 | years = get_offset(date_arg, "y") 33 | 34 | if date_arg[0] == "+": 35 | return date.today() + relativedelta(days=days, months=months, years=years) 36 | return date.today() - relativedelta(days=days, months=months, years=years) 37 | 38 | else: 39 | error_msg = _( 40 | "The date {date} does not match the required YYYY-MM-DD format or the offset format." 41 | ) 42 | raise ValueError(error_msg.format(date=date_arg)) 43 | -------------------------------------------------------------------------------- /kosmorro/debug.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from traceback import print_exception 4 | 5 | show_debug_messages = False 6 | 7 | 8 | def debug_print(what, force: bool = False): 9 | if not force and not show_debug_messages: 10 | return 11 | 12 | if isinstance(what, Exception): 13 | print_exception(type(what), value=what, tb=None) 14 | else: 15 | print("[DEBUG] %s" % what) 16 | -------------------------------------------------------------------------------- /kosmorro/environment.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Kosmorro - Compute The Next Ephemerides 4 | # Copyright (C) 2019 Jérôme Deuchnord 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as 8 | # published by the Free Software Foundation, either version 3 of the 9 | # License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | 19 | import os 20 | import re 21 | from pathlib import Path 22 | 23 | CACHE_FOLDER = str(Path.home()) + "/.kosmorro-cache" 24 | 25 | 26 | class Environment: 27 | def __init__(self): 28 | self._vars = {} 29 | 30 | def __set__(self, key, value): 31 | self._vars[key] = value 32 | 33 | def __getattr__(self, key): 34 | return self._vars[key] if key in self._vars else None 35 | 36 | def __str__(self): 37 | return self._vars.__str__() 38 | 39 | def __len__(self): 40 | return len(self._vars) 41 | 42 | 43 | def get_env_vars() -> Environment: 44 | environment = Environment() 45 | 46 | for var in os.environ: 47 | if not re.search("^KOSMORRO_", var): 48 | continue 49 | 50 | [_, env] = var.split("_", 1) 51 | environment.__set__(env.lower(), os.getenv(var)) 52 | 53 | return environment 54 | -------------------------------------------------------------------------------- /kosmorro/exceptions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Kosmorro - Compute The Next Ephemerides 4 | # Copyright (C) 2019 Jérôme Deuchnord 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as 8 | # published by the Free Software Foundation, either version 3 of the 9 | # License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | 19 | from datetime import date 20 | from babel.dates import format_date 21 | from kosmorro.i18n.utils import _, SHORT_DATE_FORMAT 22 | 23 | 24 | class UnavailableFeatureError(RuntimeError): 25 | def __init__(self, msg: str): 26 | super().__init__() 27 | self.msg = msg 28 | 29 | 30 | class OutOfRangeDateError(RuntimeError): 31 | def __init__(self, min_date: date, max_date: date): 32 | super().__init__() 33 | self.min_date = min_date 34 | self.max_date = max_date 35 | self.msg = _( 36 | "The date must be between {minimum_date} and {maximum_date}" 37 | ).format( 38 | minimum_date=format_date(min_date, "long"), 39 | maximum_date=format_date(max_date, "long"), 40 | ) 41 | 42 | 43 | class CompileError(RuntimeError): 44 | def __init__(self, msg): 45 | super().__init__() 46 | self.msg = msg 47 | -------------------------------------------------------------------------------- /kosmorro/i18n/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmorro/kosmorro/d7def507034e6af0d7c7bdbc4d4174b046b082ac/kosmorro/i18n/__init__.py -------------------------------------------------------------------------------- /kosmorro/i18n/strings.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from typing import Union 4 | from .utils import _ 5 | 6 | from kosmorrolib import EventType, MoonPhaseType, ObjectIdentifier, Event 7 | 8 | 9 | def from_event(event: Event, with_description: bool = True) -> Union[None, str]: 10 | string, details = { 11 | EventType.OPPOSITION: (_("%s is in opposition"), None), 12 | EventType.CONJUNCTION: (_("%s and %s are in conjunction"), None), 13 | EventType.OCCULTATION: (_("%s occults %s"), None), 14 | EventType.MAXIMAL_ELONGATION: ( 15 | _("Elongation of %s is maximal"), 16 | lambda e: "{:.3n}°".format(e.details["deg"]), 17 | ), 18 | EventType.PERIGEE: (_("%s is at its periapsis"), None), 19 | EventType.APOGEE: (_("%s is at its apoapsis"), None), 20 | }.get(event.event_type, (None, None)) 21 | 22 | if string is None: 23 | return None 24 | 25 | string = string % tuple([from_object(o.identifier) for o in event.objects]) 26 | 27 | if details is not None and with_description: 28 | return "%s (%s)" % (string, details(event)) 29 | 30 | return string 31 | 32 | 33 | def from_moon_phase(moon_phase: MoonPhaseType) -> str: 34 | string = { 35 | MoonPhaseType.NEW_MOON: _("New Moon"), 36 | MoonPhaseType.WAXING_CRESCENT: _("Waxing Crescent"), 37 | MoonPhaseType.FIRST_QUARTER: _("First Quarter"), 38 | MoonPhaseType.WAXING_GIBBOUS: _("Waxing Gibbous"), 39 | MoonPhaseType.FULL_MOON: _("Full Moon"), 40 | MoonPhaseType.WANING_GIBBOUS: _("Waning Gibbous"), 41 | MoonPhaseType.LAST_QUARTER: _("Last Quarter"), 42 | MoonPhaseType.WANING_CRESCENT: _("Waning Crescent"), 43 | }.get(moon_phase) 44 | 45 | if string is None: 46 | raise RuntimeError("Unknown moon phase: %s." % moon_phase) 47 | 48 | return string 49 | 50 | 51 | def from_object(identifier: ObjectIdentifier) -> str: 52 | return { 53 | ObjectIdentifier.SUN: _("Sun"), 54 | ObjectIdentifier.MOON: _("Moon"), 55 | ObjectIdentifier.MERCURY: _("Mercury"), 56 | ObjectIdentifier.VENUS: _("Venus"), 57 | ObjectIdentifier.EARTH: _("Earth"), 58 | ObjectIdentifier.MARS: _("Mars"), 59 | ObjectIdentifier.JUPITER: _("Jupiter"), 60 | ObjectIdentifier.SATURN: _("Saturn"), 61 | ObjectIdentifier.URANUS: _("Uranus"), 62 | ObjectIdentifier.NEPTUNE: _("Neptune"), 63 | ObjectIdentifier.PLUTO: _("Pluto"), 64 | }.get(identifier) 65 | -------------------------------------------------------------------------------- /kosmorro/i18n/utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Kosmorro - Compute The Next Ephemerides 4 | # Copyright (C) 2019 Jérôme Deuchnord 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as 8 | # published by the Free Software Foundation, either version 3 of the 9 | # License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | 19 | import gettext 20 | import os 21 | 22 | _LOCALE_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), "../locales") 23 | _TRANSLATION = gettext.translation("messages", localedir=_LOCALE_DIR, fallback=True) 24 | 25 | _ = _TRANSLATION.gettext 26 | 27 | FULL_DATE_FORMAT = _("{day_of_week} {month} {day_number}, {year}").format( 28 | day_of_week="%A", month="%B", day_number="%d", year="%Y" 29 | ) 30 | SHORT_DATETIME_FORMAT = _("{month} {day_number}, {hours}:{minutes}").format( 31 | month="%b", day_number="%d", hours="%H", minutes="%M" 32 | ) 33 | SHORT_DATE_FORMAT = _("{month} {day_number}, {year}").format( 34 | month="%b", day_number="%d", year="%Y" 35 | ) 36 | TIME_FORMAT = _("{hours}:{minutes}").format(hours="%H", minutes="%M") 37 | 38 | 39 | def ngettext(msgid1, msgid2, number): 40 | # Not using ngettext = _TRANSLATION.ngettext because the linter will give an invalid-name error otherwise 41 | return _TRANSLATION.ngettext(msgid1, msgid2, number) 42 | -------------------------------------------------------------------------------- /kosmorro/locales/es/LC_MESSAGES/messages.po: -------------------------------------------------------------------------------- 1 | # Translations template for kosmorro. 2 | # Copyright (C) 2021 ORGANIZATION 3 | # This file is distributed under the same license as the kosmorro project. 4 | # FIRST AUTHOR , 2021. 5 | # gallegonovato , 2023. 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: kosmorro 0.9.0\n" 9 | "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" 10 | "POT-Creation-Date: 2024-05-26 11:23+0200\n" 11 | "PO-Revision-Date: 2023-01-11 16:48+0000\n" 12 | "Last-Translator: gallegonovato \n" 13 | "Language-Team: Spanish \n" 15 | "Language: es\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=2; plural=n != 1;\n" 20 | "X-Generator: Weblate 4.15.1-dev\n" 21 | "Generated-By: Babel 2.9.0\n" 22 | 23 | #: kosmorro/__main__.py:61 24 | msgid "" 25 | "Save the planet and paper!\n" 26 | "Consider printing your PDF document only if really necessary, and use the " 27 | "other side of the sheet." 28 | msgstr "" 29 | "¡Salva el planeta y ahorra papel!\n" 30 | "Imprima el documento PDF solo si es necesario y recuerde utilizar el reverso " 31 | "de la hoja." 32 | 33 | #: kosmorro/__main__.py:70 34 | msgid "" 35 | "PDF output will not contain the ephemerides, because you didn't provide the " 36 | "observation coordinates." 37 | msgstr "" 38 | "La salida PDF no contendrá las efemérides, porque usted no proporcionó las " 39 | "coordenadas de observación." 40 | 41 | #: kosmorro/__main__.py:115 42 | msgid "The file could not be saved in \"{path}\": {error}" 43 | msgstr "No se ha podido guardar el archivo en \"{path}\": {error}" 44 | 45 | #: kosmorro/__main__.py:129 46 | msgid "Please provide a file path to export in this format (--output)." 47 | msgstr "" 48 | "Proporcione una ruta al archivo para exportar lo en este formato (--output)." 49 | 50 | #: kosmorro/__main__.py:162 51 | msgid "Moon phase can only be computed between {min_date} and {max_date}" 52 | msgstr "La fase lunar sólo puede calcularse entre {min_date} y {max_date}" 53 | 54 | #: kosmorro/__main__.py:201 55 | msgid "" 56 | "Running on Python {python_version} with Kosmorrolib v{kosmorrolib_version}" 57 | msgstr "" 58 | "Ejecutando en Python {python_version} con Kosmorrolib v{kosmorrolib_version}" 59 | 60 | #: kosmorro/__main__.py:214 61 | msgid "" 62 | "Compute the ephemerides and the events for a given date and a given position " 63 | "on Earth." 64 | msgstr "" 65 | "Calcule las efemérides y los eventos para una fecha y una posición dadas en " 66 | "la Tierra." 67 | 68 | #: kosmorro/__main__.py:217 69 | msgid "" 70 | "By default, only the events will be computed for today.\n" 71 | "To compute also the ephemerides, latitude and longitude arguments are needed." 72 | msgstr "" 73 | "Por defecto, sólo se calculan las efemérides de hoy.\n" 74 | "Para calcular también las efemérides, se necesitan los datos de latitud y " 75 | "longitud." 76 | 77 | #: kosmorro/__main__.py:230 78 | msgid "Show the program version" 79 | msgstr "Mostrar la versión del programa" 80 | 81 | #: kosmorro/__main__.py:238 82 | msgid "The format to output the information to" 83 | msgstr "Formato de salida de la información" 84 | 85 | #: kosmorro/__main__.py:245 86 | msgid "" 87 | "The observer's latitude on Earth. Can also be set in the KOSMORRO_LATITUDE " 88 | "environment variable." 89 | msgstr "" 90 | "La latitud del observador en la Tierra. También se puede establecer en la " 91 | "variable ambiental KOSMORRO_LATITUDE." 92 | 93 | #: kosmorro/__main__.py:255 94 | msgid "" 95 | "The observer's longitude on Earth. Can also be set in the KOSMORRO_LONGITUDE " 96 | "environment variable." 97 | msgstr "" 98 | "La longitud del observador en la Tierra. También se puede establecer en la " 99 | "variable ambiental KOSMORRO_LONGITUDE." 100 | 101 | #: kosmorro/__main__.py:265 102 | msgid "" 103 | "The date for which the ephemerides must be calculated. Can be in the YYYY-MM-" 104 | "DD format or an interval in the \"[+-]YyMmDd\" format (with Y, M, and D " 105 | "numbers). Defaults to current date." 106 | msgstr "" 107 | "Fecha para la que deben calcularse las efemérides. Puede estar en el formato " 108 | "AAAA-MM-DD o un intervalo en el formato \"[+-]AAAA-MMDd\" (con los números " 109 | "Y, M y D). Por defecto es la fecha actual." 110 | 111 | #: kosmorro/__main__.py:276 112 | msgid "" 113 | "The timezone to display the hours in (e.g. 2 for UTC+2 or -3 for UTC-3). Can " 114 | "also be set in the KOSMORRO_TIMEZONE environment variable." 115 | msgstr "" 116 | "La zona horaria en la que se muestran las horas (por ejemplo, 2 para UTC+2 o " 117 | "-3 para UTC-3). También se puede establecer en la variable de entorno " 118 | "KOSMORRO_TIMEZONE." 119 | 120 | #: kosmorro/__main__.py:285 121 | msgid "Disable the colors in the console." 122 | msgstr "Deshabilita los colores de la consola." 123 | 124 | #: kosmorro/__main__.py:292 125 | msgid "" 126 | "A file to export the output to. If not given, the standard output is used. " 127 | "This argument is needed for PDF format." 128 | msgstr "" 129 | "Un archivo al que exportar la salida. Si no se da, se utiliza la salida " 130 | "estándar. Este argumento es necesario para el formato PDF." 131 | 132 | #: kosmorro/__main__.py:301 133 | msgid "" 134 | "Do not generate a graph to represent the rise and set times in the PDF " 135 | "format." 136 | msgstr "" 137 | "No genere un gráfico para representar el aumento y los tiempos de ajuste en " 138 | "el formato PDF." 139 | 140 | #: kosmorro/__main__.py:309 141 | msgid "Show debugging messages" 142 | msgstr "Mostrar mensajes de depuración" 143 | 144 | #: kosmorro/date.py:17 145 | msgid "The date {date} is not valid: {error}" 146 | msgstr "La fecha no es válida: {error}" 147 | 148 | #: kosmorro/date.py:39 149 | msgid "" 150 | "The date {date} does not match the required YYYY-MM-DD format or the offset " 151 | "format." 152 | msgstr "" 153 | "La fecha {fecha} no coincide con el formato requerido AAAA-MM-DD o el " 154 | "formato de desplazamiento." 155 | 156 | #: kosmorro/dumper.py:137 157 | msgid "Expected events:" 158 | msgstr "Eventos esperados:" 159 | 160 | #: kosmorro/dumper.py:144 161 | msgid "Note: All the hours are given in UTC." 162 | msgstr "Nota: Todas las horas se dan en UTC." 163 | 164 | #: kosmorro/dumper.py:151 165 | msgid "Note: All the hours are given in the UTC{offset} timezone." 166 | msgstr "Nota: Todas las horas se dan en la zona horaria UTC." 167 | 168 | #: kosmorro/dumper.py:205 kosmorro/dumper.py:333 169 | msgid "Object" 170 | msgstr "Objeto" 171 | 172 | #: kosmorro/dumper.py:206 kosmorro/dumper.py:334 173 | msgid "Rise time" 174 | msgstr "Tiempo de ascenso" 175 | 176 | #: kosmorro/dumper.py:207 kosmorro/dumper.py:336 177 | msgid "Culmination time" 178 | msgstr "Tiempo de culminación" 179 | 180 | #: kosmorro/dumper.py:208 kosmorro/dumper.py:338 181 | msgid "Set time" 182 | msgstr "Establecer hora" 183 | 184 | #: kosmorro/dumper.py:234 185 | msgid "Moon phase is unavailable for this date." 186 | msgstr "La fase lunar no está disponible para esta fecha." 187 | 188 | #: kosmorro/dumper.py:238 kosmorro/dumper.py:342 189 | msgid "Moon phase:" 190 | msgstr "Fase lunar:" 191 | 192 | #: kosmorro/dumper.py:242 193 | msgid "{next_moon_phase} on {next_moon_phase_date} at {next_moon_phase_time}" 194 | msgstr "{next_moon_phase} en {next_moon_phase_date} a {next_moon_phase_time}" 195 | 196 | #: kosmorro/dumper.py:306 197 | msgid "Overview of your sky" 198 | msgstr "Vista general de su cielo" 199 | 200 | #: kosmorro/dumper.py:314 201 | msgid "" 202 | "This document summarizes the ephemerides and the events of {date}. It aims " 203 | "to help you to prepare your observation session. All the hours are given in " 204 | "{timezone}." 205 | msgstr "" 206 | "Este documento resume las efemérides y los eventos de {fecha}. Su objetivo " 207 | "es ayudarle a preparar su sesión de observación. Todas las horas están dadas " 208 | "en {zona horaria}." 209 | 210 | #: kosmorro/dumper.py:324 211 | msgid "" 212 | "Don't forget to check the weather forecast before you go out with your " 213 | "equipment." 214 | msgstr "" 215 | "No olvides comprobar el pronóstico del tiempo antes de salir con tu equipo." 216 | 217 | #: kosmorro/dumper.py:331 218 | msgid "Ephemerides of the day" 219 | msgstr "Las efemérides del día" 220 | 221 | #: kosmorro/dumper.py:340 222 | msgid "hours" 223 | msgstr "horas" 224 | 225 | #: kosmorro/dumper.py:347 226 | msgid "Expected events" 227 | msgstr "Eventos esperados" 228 | 229 | #: kosmorro/dumper.py:487 230 | msgid "" 231 | "Building PDF was not possible, because some dependencies are not installed.\n" 232 | "Please look at the documentation at https://kosmorro.space/cli/generate-pdf/ " 233 | "for more information." 234 | msgstr "" 235 | "No fue posible compilar PDF porque algunas dependencias no están " 236 | "instaladas. \n" 237 | "Consulte la documentación en https://kosmorro.space/cli/generate-pdf/ para " 238 | "obtener más información." 239 | 240 | #: kosmorro/dumper.py:540 241 | #, python-format 242 | msgid "" 243 | "An error occurred during the compilation of the PDF.\n" 244 | "Please open an issue at https://github.com/Kosmorro/kosmorro/issues and " 245 | "share the content of the log file at /tmp/kosmorro-%s.log" 246 | msgstr "" 247 | "Ocurrió un error durante la compilación del PDF.\n" 248 | "Abra un problema en https://github.com/Kosmorro/kosmorro/issues y comparta " 249 | "el contenido del archivo de registro en /tmp/kosmorro-%s.log" 250 | 251 | #: kosmorro/exceptions.py:35 252 | msgid "The date must be between {minimum_date} and {maximum_date}" 253 | msgstr "La fecha debe estar entre {fecha_mínima} y {fecha_máxima}" 254 | 255 | #: kosmorro/i18n/strings.py:11 256 | #, python-format 257 | msgid "%s is in opposition" 258 | msgstr "%s está en la oposición" 259 | 260 | #: kosmorro/i18n/strings.py:12 261 | #, python-format 262 | msgid "%s and %s are in conjunction" 263 | msgstr "Los %s y %s están en conjunción" 264 | 265 | #: kosmorro/i18n/strings.py:13 266 | #, python-format 267 | msgid "%s occults %s" 268 | msgstr "%s ocultos %s" 269 | 270 | #: kosmorro/i18n/strings.py:15 271 | #, python-format 272 | msgid "Elongation of %s is maximal" 273 | msgstr "El alargamiento de %s es máximo" 274 | 275 | #: kosmorro/i18n/strings.py:18 276 | #, python-format 277 | msgid "%s is at its periapsis" 278 | msgstr "%s está en su periapsis" 279 | 280 | #: kosmorro/i18n/strings.py:19 281 | #, python-format 282 | msgid "%s is at its apoapsis" 283 | msgstr "%s está en su apoapsis" 284 | 285 | #: kosmorro/i18n/strings.py:35 286 | msgid "New Moon" 287 | msgstr "Luna Nueva" 288 | 289 | #: kosmorro/i18n/strings.py:36 290 | msgid "Waxing Crescent" 291 | msgstr "Luna creciente" 292 | 293 | #: kosmorro/i18n/strings.py:37 294 | msgid "First Quarter" 295 | msgstr "Primer cuarto" 296 | 297 | #: kosmorro/i18n/strings.py:38 298 | msgid "Waxing Gibbous" 299 | msgstr "Luna menguante" 300 | 301 | #: kosmorro/i18n/strings.py:39 302 | msgid "Full Moon" 303 | msgstr "Luna llena" 304 | 305 | #: kosmorro/i18n/strings.py:40 306 | msgid "Waning Gibbous" 307 | msgstr "Giboso menguante" 308 | 309 | #: kosmorro/i18n/strings.py:41 310 | msgid "Last Quarter" 311 | msgstr "Último cuarto" 312 | 313 | #: kosmorro/i18n/strings.py:42 314 | msgid "Waning Crescent" 315 | msgstr "Menguante" 316 | 317 | #: kosmorro/i18n/strings.py:53 318 | msgid "Sun" 319 | msgstr "Sol" 320 | 321 | #: kosmorro/i18n/strings.py:54 322 | msgid "Moon" 323 | msgstr "Luna" 324 | 325 | #: kosmorro/i18n/strings.py:55 326 | msgid "Mercury" 327 | msgstr "Mercurio" 328 | 329 | #: kosmorro/i18n/strings.py:56 330 | msgid "Venus" 331 | msgstr "Venus" 332 | 333 | #: kosmorro/i18n/strings.py:57 334 | msgid "Earth" 335 | msgstr "Tierra" 336 | 337 | #: kosmorro/i18n/strings.py:58 338 | msgid "Mars" 339 | msgstr "Marte" 340 | 341 | #: kosmorro/i18n/strings.py:59 342 | msgid "Jupiter" 343 | msgstr "Júpiter" 344 | 345 | #: kosmorro/i18n/strings.py:60 346 | msgid "Saturn" 347 | msgstr "Saturno" 348 | 349 | #: kosmorro/i18n/strings.py:61 350 | msgid "Uranus" 351 | msgstr "Urano" 352 | 353 | #: kosmorro/i18n/strings.py:62 354 | msgid "Neptune" 355 | msgstr "Neptuno" 356 | 357 | #: kosmorro/i18n/strings.py:63 358 | msgid "Pluto" 359 | msgstr "Plutón" 360 | 361 | #: kosmorro/i18n/utils.py:27 362 | msgid "{day_of_week} {month} {day_number}, {year}" 363 | msgstr "{day_of_week} {month} {day_number}, {year}" 364 | 365 | #: kosmorro/i18n/utils.py:30 366 | msgid "{month} {day_number}, {hours}:{minutes}" 367 | msgstr "{mes} {número de día}, {horas}:{minutos}" 368 | 369 | #: kosmorro/i18n/utils.py:33 370 | msgid "{month} {day_number}, {year}" 371 | msgstr "{mes} {número_de_día}, {año}" 372 | 373 | #: kosmorro/i18n/utils.py:36 374 | msgid "{hours}:{minutes}" 375 | msgstr "{hours}:{minutes}" 376 | 377 | #, fuzzy 378 | #~ msgid "Do you really want to clear Kosmorro's cache? [yN] " 379 | #~ msgstr "¿De verdad quieres limpiar el alijo de Kosmorro? [yN] " 380 | 381 | #, fuzzy 382 | #~ msgid "Incorrect answer, cache not cleared." 383 | #~ msgstr "" 384 | #~ "La respuesta no coincidía con las opciones esperadas, la memoria caché no " 385 | #~ "se había vaciado." 386 | 387 | #, fuzzy 388 | #~ msgid "Delete all the files from Kosmorro's cache." 389 | #~ msgstr "Borre todos los archivos que Kosmorro guardó en la memoria." 390 | 391 | #, fuzzy 392 | #~ msgid "Unknown phase" 393 | #~ msgstr "Fase lunar:" 394 | 395 | #~ msgid "A Summary of your Sky" 396 | #~ msgstr "Un resumen de su cielo" 397 | 398 | #~ msgid "%s's largest elongation" 399 | #~ msgstr "El mayor alargamiento de los %s" 400 | 401 | #~ msgid "Selected output format needs an output file (--output)." 402 | #~ msgstr "" 403 | #~ "El formato de salida seleccionado necesita un archivo de salida (--" 404 | #~ "output)." 405 | 406 | #, fuzzy 407 | #~ msgid "" 408 | #~ "Building PDF was not possible, because some dependencies are not " 409 | #~ "installed.\n" 410 | #~ "Please look at the documentation at http://kosmorro.space for more " 411 | #~ "information." 412 | #~ msgstr "" 413 | #~ "La construcción de PDFs no fue posible, porque algunas dependencias no " 414 | #~ "están instaladas.\n" 415 | #~ "Por favor, consulte la documentación en http://kosmorro.space para más " 416 | #~ "información." 417 | -------------------------------------------------------------------------------- /kosmorro/locales/messages.pot: -------------------------------------------------------------------------------- 1 | # Translations template for PROJECT. 2 | # Copyright (C) 2025 ORGANIZATION 3 | # This file is distributed under the same license as the PROJECT project. 4 | # FIRST AUTHOR , 2025. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PROJECT VERSION\n" 10 | "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" 11 | "POT-Creation-Date: 2025-03-16 11:59+0100\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=utf-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | "Generated-By: Babel 2.17.0\n" 19 | 20 | #: kosmorro/__main__.py:62 21 | msgid "" 22 | "Save the planet and paper!\n" 23 | "Consider printing your PDF document only if really necessary, and use the" 24 | " other side of the sheet." 25 | msgstr "" 26 | 27 | #: kosmorro/__main__.py:71 28 | msgid "" 29 | "PDF output will not contain the ephemerides, because you didn't provide " 30 | "the observation coordinates." 31 | msgstr "" 32 | 33 | #: kosmorro/__main__.py:115 34 | #, python-brace-format 35 | msgid "The file could not be saved in \"{path}\": {error}" 36 | msgstr "" 37 | 38 | #: kosmorro/__main__.py:129 39 | msgid "Please provide a file path to export in this format (--output)." 40 | msgstr "" 41 | 42 | #: kosmorro/__main__.py:163 43 | #, python-brace-format 44 | msgid "Moon phase can only be computed between {min_date} and {max_date}" 45 | msgstr "" 46 | 47 | #: kosmorro/__main__.py:202 48 | #, python-brace-format 49 | msgid "Running on Python {python_version} with Kosmorrolib v{kosmorrolib_version}" 50 | msgstr "" 51 | 52 | #: kosmorro/__main__.py:215 53 | msgid "" 54 | "Compute the ephemerides and the events for a given date and a given " 55 | "position on Earth." 56 | msgstr "" 57 | 58 | #: kosmorro/__main__.py:218 59 | msgid "" 60 | "By default, only the events will be computed for today.\n" 61 | "To compute also the ephemerides, latitude and longitude arguments are " 62 | "needed." 63 | msgstr "" 64 | 65 | #: kosmorro/__main__.py:230 66 | msgid "Show the program version" 67 | msgstr "" 68 | 69 | #: kosmorro/__main__.py:238 70 | msgid "The format to output the information to" 71 | msgstr "" 72 | 73 | #: kosmorro/__main__.py:246 74 | msgid "" 75 | "The observer's latitude on Earth. Can also be set in the " 76 | "KOSMORRO_LATITUDE environment variable." 77 | msgstr "" 78 | 79 | #: kosmorro/__main__.py:256 80 | msgid "" 81 | "The observer's longitude on Earth. Can also be set in the " 82 | "KOSMORRO_LONGITUDE environment variable." 83 | msgstr "" 84 | 85 | #: kosmorro/__main__.py:266 86 | msgid "" 87 | "The date for which the ephemerides must be calculated. Can be in the " 88 | "YYYY-MM-DD format or an interval in the \"[+-]YyMmDd\" format (with Y, M," 89 | " and D numbers). Defaults to current date." 90 | msgstr "" 91 | 92 | #: kosmorro/__main__.py:277 93 | msgid "" 94 | "The timezone to display the hours in (e.g. 2 for UTC+2 or -3 for UTC-3). " 95 | "Can also be set in the KOSMORRO_TIMEZONE environment variable." 96 | msgstr "" 97 | 98 | #: kosmorro/__main__.py:285 99 | msgid "Disable the colors in the console." 100 | msgstr "" 101 | 102 | #: kosmorro/__main__.py:293 103 | msgid "" 104 | "A file to export the output to. If not given, the standard output is " 105 | "used. This argument is needed for PDF format." 106 | msgstr "" 107 | 108 | #: kosmorro/__main__.py:302 109 | msgid "" 110 | "Do not generate a graph to represent the rise and set times in the PDF " 111 | "format." 112 | msgstr "" 113 | 114 | #: kosmorro/__main__.py:309 115 | msgid "Show debugging messages" 116 | msgstr "" 117 | 118 | #: kosmorro/date.py:17 119 | #, python-brace-format 120 | msgid "The date {date} is not valid: {error}" 121 | msgstr "" 122 | 123 | #: kosmorro/date.py:40 124 | #, python-brace-format 125 | msgid "" 126 | "The date {date} does not match the required YYYY-MM-DD format or the " 127 | "offset format." 128 | msgstr "" 129 | 130 | #: kosmorro/dumper.py:137 131 | msgid "Expected events:" 132 | msgstr "" 133 | 134 | #: kosmorro/dumper.py:144 135 | msgid "Note: All the hours are given in UTC." 136 | msgstr "" 137 | 138 | #: kosmorro/dumper.py:152 139 | #, python-brace-format 140 | msgid "Note: All the hours are given in the UTC{offset} timezone." 141 | msgstr "" 142 | 143 | #: kosmorro/dumper.py:205 kosmorro/dumper.py:333 144 | msgid "Object" 145 | msgstr "" 146 | 147 | #: kosmorro/dumper.py:206 kosmorro/dumper.py:334 148 | msgid "Rise time" 149 | msgstr "" 150 | 151 | #: kosmorro/dumper.py:207 kosmorro/dumper.py:336 152 | msgid "Culmination time" 153 | msgstr "" 154 | 155 | #: kosmorro/dumper.py:208 kosmorro/dumper.py:338 156 | msgid "Set time" 157 | msgstr "" 158 | 159 | #: kosmorro/dumper.py:234 160 | msgid "Moon phase is unavailable for this date." 161 | msgstr "" 162 | 163 | #: kosmorro/dumper.py:238 kosmorro/dumper.py:342 164 | msgid "Moon phase:" 165 | msgstr "" 166 | 167 | #: kosmorro/dumper.py:243 168 | #, python-brace-format 169 | msgid "{next_moon_phase} on {next_moon_phase_date} at {next_moon_phase_time}" 170 | msgstr "" 171 | 172 | #: kosmorro/dumper.py:306 173 | msgid "Overview of your sky" 174 | msgstr "" 175 | 176 | #: kosmorro/dumper.py:315 177 | #, python-brace-format 178 | msgid "" 179 | "This document summarizes the ephemerides and the events of {date}. It " 180 | "aims to help you to prepare your observation session. All the hours are " 181 | "given in {timezone}." 182 | msgstr "" 183 | 184 | #: kosmorro/dumper.py:325 185 | msgid "" 186 | "Don't forget to check the weather forecast before you go out with your " 187 | "equipment." 188 | msgstr "" 189 | 190 | #: kosmorro/dumper.py:331 191 | msgid "Ephemerides of the day" 192 | msgstr "" 193 | 194 | #: kosmorro/dumper.py:340 195 | msgid "hours" 196 | msgstr "" 197 | 198 | #: kosmorro/dumper.py:347 199 | msgid "Expected events" 200 | msgstr "" 201 | 202 | #: kosmorro/dumper.py:488 203 | msgid "" 204 | "Building PDF was not possible, because some dependencies are not " 205 | "installed.\n" 206 | "Please look at the documentation at https://kosmorro.space/cli/generate-" 207 | "pdf/ for more information." 208 | msgstr "" 209 | 210 | #: kosmorro/dumper.py:541 211 | #, python-format 212 | msgid "" 213 | "An error occurred during the compilation of the PDF.\n" 214 | "Please open an issue at https://github.com/Kosmorro/kosmorro/issues and " 215 | "share the content of the log file at /tmp/kosmorro-%s.log" 216 | msgstr "" 217 | 218 | #: kosmorro/exceptions.py:36 219 | #, python-brace-format 220 | msgid "The date must be between {minimum_date} and {maximum_date}" 221 | msgstr "" 222 | 223 | #: kosmorro/i18n/strings.py:11 224 | #, python-format 225 | msgid "%s is in opposition" 226 | msgstr "" 227 | 228 | #: kosmorro/i18n/strings.py:12 229 | #, python-format 230 | msgid "%s and %s are in conjunction" 231 | msgstr "" 232 | 233 | #: kosmorro/i18n/strings.py:13 234 | #, python-format 235 | msgid "%s occults %s" 236 | msgstr "" 237 | 238 | #: kosmorro/i18n/strings.py:15 239 | #, python-format 240 | msgid "Elongation of %s is maximal" 241 | msgstr "" 242 | 243 | #: kosmorro/i18n/strings.py:18 244 | #, python-format 245 | msgid "%s is at its periapsis" 246 | msgstr "" 247 | 248 | #: kosmorro/i18n/strings.py:19 249 | #, python-format 250 | msgid "%s is at its apoapsis" 251 | msgstr "" 252 | 253 | #: kosmorro/i18n/strings.py:35 254 | msgid "New Moon" 255 | msgstr "" 256 | 257 | #: kosmorro/i18n/strings.py:36 258 | msgid "Waxing Crescent" 259 | msgstr "" 260 | 261 | #: kosmorro/i18n/strings.py:37 262 | msgid "First Quarter" 263 | msgstr "" 264 | 265 | #: kosmorro/i18n/strings.py:38 266 | msgid "Waxing Gibbous" 267 | msgstr "" 268 | 269 | #: kosmorro/i18n/strings.py:39 270 | msgid "Full Moon" 271 | msgstr "" 272 | 273 | #: kosmorro/i18n/strings.py:40 274 | msgid "Waning Gibbous" 275 | msgstr "" 276 | 277 | #: kosmorro/i18n/strings.py:41 278 | msgid "Last Quarter" 279 | msgstr "" 280 | 281 | #: kosmorro/i18n/strings.py:42 282 | msgid "Waning Crescent" 283 | msgstr "" 284 | 285 | #: kosmorro/i18n/strings.py:53 286 | msgid "Sun" 287 | msgstr "" 288 | 289 | #: kosmorro/i18n/strings.py:54 290 | msgid "Moon" 291 | msgstr "" 292 | 293 | #: kosmorro/i18n/strings.py:55 294 | msgid "Mercury" 295 | msgstr "" 296 | 297 | #: kosmorro/i18n/strings.py:56 298 | msgid "Venus" 299 | msgstr "" 300 | 301 | #: kosmorro/i18n/strings.py:57 302 | msgid "Earth" 303 | msgstr "" 304 | 305 | #: kosmorro/i18n/strings.py:58 306 | msgid "Mars" 307 | msgstr "" 308 | 309 | #: kosmorro/i18n/strings.py:59 310 | msgid "Jupiter" 311 | msgstr "" 312 | 313 | #: kosmorro/i18n/strings.py:60 314 | msgid "Saturn" 315 | msgstr "" 316 | 317 | #: kosmorro/i18n/strings.py:61 318 | msgid "Uranus" 319 | msgstr "" 320 | 321 | #: kosmorro/i18n/strings.py:62 322 | msgid "Neptune" 323 | msgstr "" 324 | 325 | #: kosmorro/i18n/strings.py:63 326 | msgid "Pluto" 327 | msgstr "" 328 | 329 | #: kosmorro/i18n/utils.py:27 330 | #, python-brace-format 331 | msgid "{day_of_week} {month} {day_number}, {year}" 332 | msgstr "" 333 | 334 | #: kosmorro/i18n/utils.py:30 335 | #, python-brace-format 336 | msgid "{month} {day_number}, {hours}:{minutes}" 337 | msgstr "" 338 | 339 | #: kosmorro/i18n/utils.py:33 340 | #, python-brace-format 341 | msgid "{month} {day_number}, {year}" 342 | msgstr "" 343 | 344 | #: kosmorro/i18n/utils.py:36 345 | #, python-brace-format 346 | msgid "{hours}:{minutes}" 347 | msgstr "" 348 | 349 | -------------------------------------------------------------------------------- /kosmorro/locales/nb_NO/LC_MESSAGES/messages.po: -------------------------------------------------------------------------------- 1 | # Translations template for kosmorro. 2 | # Copyright (C) 2021 ORGANIZATION 3 | # This file is distributed under the same license as the kosmorro project. 4 | # FIRST AUTHOR , 2021. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: kosmorro 0.9.0\n" 9 | "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" 10 | "POT-Creation-Date: 2024-05-26 11:23+0200\n" 11 | "PO-Revision-Date: 2022-03-19 17:51+0000\n" 12 | "Last-Translator: Anonymous \n" 13 | "Language-Team: Norwegian Bokmål \n" 15 | "Language: nb_NO\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=2; plural=n != 1;\n" 20 | "X-Generator: Weblate 4.12-dev\n" 21 | "Generated-By: Babel 2.9.0\n" 22 | 23 | #: kosmorro/__main__.py:61 24 | msgid "" 25 | "Save the planet and paper!\n" 26 | "Consider printing your PDF document only if really necessary, and use the " 27 | "other side of the sheet." 28 | msgstr "" 29 | 30 | #: kosmorro/__main__.py:70 31 | msgid "" 32 | "PDF output will not contain the ephemerides, because you didn't provide the " 33 | "observation coordinates." 34 | msgstr "" 35 | 36 | #: kosmorro/__main__.py:115 37 | msgid "The file could not be saved in \"{path}\": {error}" 38 | msgstr "" 39 | 40 | #: kosmorro/__main__.py:129 41 | msgid "Please provide a file path to export in this format (--output)." 42 | msgstr "" 43 | 44 | #: kosmorro/__main__.py:162 45 | msgid "Moon phase can only be computed between {min_date} and {max_date}" 46 | msgstr "" 47 | 48 | #: kosmorro/__main__.py:201 49 | #, fuzzy 50 | msgid "" 51 | "Running on Python {python_version} with Kosmorrolib v{kosmorrolib_version}" 52 | msgstr "Kjører med Python {python_version}" 53 | 54 | #: kosmorro/__main__.py:214 55 | msgid "" 56 | "Compute the ephemerides and the events for a given date and a given position " 57 | "on Earth." 58 | msgstr "" 59 | 60 | #: kosmorro/__main__.py:217 61 | msgid "" 62 | "By default, only the events will be computed for today.\n" 63 | "To compute also the ephemerides, latitude and longitude arguments are needed." 64 | msgstr "" 65 | 66 | #: kosmorro/__main__.py:230 67 | msgid "Show the program version" 68 | msgstr "Vis programversjonen" 69 | 70 | #: kosmorro/__main__.py:238 71 | msgid "The format to output the information to" 72 | msgstr "" 73 | 74 | #: kosmorro/__main__.py:245 75 | msgid "" 76 | "The observer's latitude on Earth. Can also be set in the KOSMORRO_LATITUDE " 77 | "environment variable." 78 | msgstr "" 79 | 80 | #: kosmorro/__main__.py:255 81 | msgid "" 82 | "The observer's longitude on Earth. Can also be set in the KOSMORRO_LONGITUDE " 83 | "environment variable." 84 | msgstr "" 85 | 86 | #: kosmorro/__main__.py:265 87 | msgid "" 88 | "The date for which the ephemerides must be calculated. Can be in the YYYY-MM-" 89 | "DD format or an interval in the \"[+-]YyMmDd\" format (with Y, M, and D " 90 | "numbers). Defaults to current date." 91 | msgstr "" 92 | 93 | #: kosmorro/__main__.py:276 94 | msgid "" 95 | "The timezone to display the hours in (e.g. 2 for UTC+2 or -3 for UTC-3). Can " 96 | "also be set in the KOSMORRO_TIMEZONE environment variable." 97 | msgstr "" 98 | 99 | #: kosmorro/__main__.py:285 100 | msgid "Disable the colors in the console." 101 | msgstr "" 102 | 103 | #: kosmorro/__main__.py:292 104 | msgid "" 105 | "A file to export the output to. If not given, the standard output is used. " 106 | "This argument is needed for PDF format." 107 | msgstr "" 108 | 109 | #: kosmorro/__main__.py:301 110 | msgid "" 111 | "Do not generate a graph to represent the rise and set times in the PDF " 112 | "format." 113 | msgstr "" 114 | 115 | #: kosmorro/__main__.py:309 116 | msgid "Show debugging messages" 117 | msgstr "" 118 | 119 | #: kosmorro/date.py:17 120 | msgid "The date {date} is not valid: {error}" 121 | msgstr "Datoen {date} er ikke gyldig: {error}" 122 | 123 | #: kosmorro/date.py:39 124 | #, fuzzy 125 | msgid "" 126 | "The date {date} does not match the required YYYY-MM-DD format or the offset " 127 | "format." 128 | msgstr "" 129 | "Datoen {date} passer ikke overens med påkrevd ÅÅÅÅ-MM-DD -format, eller " 130 | "forskyvningsformatet." 131 | 132 | #: kosmorro/dumper.py:137 133 | msgid "Expected events:" 134 | msgstr "Forventede hendelser:" 135 | 136 | #: kosmorro/dumper.py:144 137 | msgid "Note: All the hours are given in UTC." 138 | msgstr "Merk: Alle tider er angitt i UTC." 139 | 140 | #: kosmorro/dumper.py:151 141 | #, fuzzy 142 | msgid "Note: All the hours are given in the UTC{offset} timezone." 143 | msgstr "Merk: Alle tider er angitt i UTC{offset}-tidssone." 144 | 145 | #: kosmorro/dumper.py:205 kosmorro/dumper.py:333 146 | msgid "Object" 147 | msgstr "Objekt" 148 | 149 | #: kosmorro/dumper.py:206 kosmorro/dumper.py:334 150 | #, fuzzy 151 | msgid "Rise time" 152 | msgstr "Emningstid" 153 | 154 | #: kosmorro/dumper.py:207 kosmorro/dumper.py:336 155 | msgid "Culmination time" 156 | msgstr "Høydepunkt" 157 | 158 | #: kosmorro/dumper.py:208 kosmorro/dumper.py:338 159 | msgid "Set time" 160 | msgstr "" 161 | 162 | #: kosmorro/dumper.py:234 163 | msgid "Moon phase is unavailable for this date." 164 | msgstr "Månefase er utilgjengelig for denne datoen." 165 | 166 | #: kosmorro/dumper.py:238 kosmorro/dumper.py:342 167 | msgid "Moon phase:" 168 | msgstr "Månefase:" 169 | 170 | #: kosmorro/dumper.py:242 171 | msgid "{next_moon_phase} on {next_moon_phase_date} at {next_moon_phase_time}" 172 | msgstr "" 173 | "{next_moon_phase} {next_moon_phase_date} klokken {next_moon_phase_time}" 174 | 175 | #: kosmorro/dumper.py:306 176 | msgid "Overview of your sky" 177 | msgstr "" 178 | 179 | #: kosmorro/dumper.py:314 180 | msgid "" 181 | "This document summarizes the ephemerides and the events of {date}. It aims " 182 | "to help you to prepare your observation session. All the hours are given in " 183 | "{timezone}." 184 | msgstr "" 185 | 186 | #: kosmorro/dumper.py:324 187 | msgid "" 188 | "Don't forget to check the weather forecast before you go out with your " 189 | "equipment." 190 | msgstr "Ikke glem å sjekke værmeldingen før du gir deg ivei med utstyret ditt." 191 | 192 | #: kosmorro/dumper.py:331 193 | msgid "Ephemerides of the day" 194 | msgstr "" 195 | 196 | #: kosmorro/dumper.py:340 197 | msgid "hours" 198 | msgstr "timer" 199 | 200 | #: kosmorro/dumper.py:347 201 | msgid "Expected events" 202 | msgstr "Forventede hendelser" 203 | 204 | #: kosmorro/dumper.py:487 205 | msgid "" 206 | "Building PDF was not possible, because some dependencies are not installed.\n" 207 | "Please look at the documentation at https://kosmorro.space/cli/generate-pdf/ " 208 | "for more information." 209 | msgstr "" 210 | 211 | #: kosmorro/dumper.py:540 212 | #, python-format 213 | msgid "" 214 | "An error occurred during the compilation of the PDF.\n" 215 | "Please open an issue at https://github.com/Kosmorro/kosmorro/issues and " 216 | "share the content of the log file at /tmp/kosmorro-%s.log" 217 | msgstr "" 218 | 219 | #: kosmorro/exceptions.py:35 220 | msgid "The date must be between {minimum_date} and {maximum_date}" 221 | msgstr "" 222 | 223 | #: kosmorro/i18n/strings.py:11 224 | #, python-format 225 | msgid "%s is in opposition" 226 | msgstr "" 227 | 228 | #: kosmorro/i18n/strings.py:12 229 | #, python-format 230 | msgid "%s and %s are in conjunction" 231 | msgstr "" 232 | 233 | #: kosmorro/i18n/strings.py:13 234 | #, fuzzy, python-format 235 | msgid "%s occults %s" 236 | msgstr "%s dekker %s" 237 | 238 | #: kosmorro/i18n/strings.py:15 239 | #, python-format 240 | msgid "Elongation of %s is maximal" 241 | msgstr "" 242 | 243 | #: kosmorro/i18n/strings.py:18 244 | #, python-format 245 | msgid "%s is at its periapsis" 246 | msgstr "" 247 | 248 | #: kosmorro/i18n/strings.py:19 249 | #, python-format 250 | msgid "%s is at its apoapsis" 251 | msgstr "" 252 | 253 | #: kosmorro/i18n/strings.py:35 254 | msgid "New Moon" 255 | msgstr "Nymåne" 256 | 257 | #: kosmorro/i18n/strings.py:36 258 | #, fuzzy 259 | msgid "Waxing Crescent" 260 | msgstr "Fallende sigd" 261 | 262 | #: kosmorro/i18n/strings.py:37 263 | msgid "First Quarter" 264 | msgstr "Første kvarter" 265 | 266 | #: kosmorro/i18n/strings.py:38 267 | #, fuzzy 268 | msgid "Waxing Gibbous" 269 | msgstr "Fallende større enn halv" 270 | 271 | #: kosmorro/i18n/strings.py:39 272 | msgid "Full Moon" 273 | msgstr "Fullmåne" 274 | 275 | #: kosmorro/i18n/strings.py:40 276 | #, fuzzy 277 | msgid "Waning Gibbous" 278 | msgstr "Fallende større enn halv" 279 | 280 | #: kosmorro/i18n/strings.py:41 281 | msgid "Last Quarter" 282 | msgstr "Siste kvarter" 283 | 284 | #: kosmorro/i18n/strings.py:42 285 | #, fuzzy 286 | msgid "Waning Crescent" 287 | msgstr "Fallende sigd" 288 | 289 | #: kosmorro/i18n/strings.py:53 290 | msgid "Sun" 291 | msgstr "Solen" 292 | 293 | #: kosmorro/i18n/strings.py:54 294 | msgid "Moon" 295 | msgstr "Månen" 296 | 297 | #: kosmorro/i18n/strings.py:55 298 | msgid "Mercury" 299 | msgstr "Merkur" 300 | 301 | #: kosmorro/i18n/strings.py:56 302 | msgid "Venus" 303 | msgstr "Venus" 304 | 305 | #: kosmorro/i18n/strings.py:57 306 | msgid "Earth" 307 | msgstr "" 308 | 309 | #: kosmorro/i18n/strings.py:58 310 | msgid "Mars" 311 | msgstr "Mars" 312 | 313 | #: kosmorro/i18n/strings.py:59 314 | msgid "Jupiter" 315 | msgstr "Jupiter" 316 | 317 | #: kosmorro/i18n/strings.py:60 318 | msgid "Saturn" 319 | msgstr "Saturn" 320 | 321 | #: kosmorro/i18n/strings.py:61 322 | msgid "Uranus" 323 | msgstr "Uranus" 324 | 325 | #: kosmorro/i18n/strings.py:62 326 | msgid "Neptune" 327 | msgstr "Neptun" 328 | 329 | #: kosmorro/i18n/strings.py:63 330 | msgid "Pluto" 331 | msgstr "Pluto" 332 | 333 | #: kosmorro/i18n/utils.py:27 334 | msgid "{day_of_week} {month} {day_number}, {year}" 335 | msgstr "" 336 | 337 | #: kosmorro/i18n/utils.py:30 338 | msgid "{month} {day_number}, {hours}:{minutes}" 339 | msgstr "{day_number} {month}, {hours}:{minutes}" 340 | 341 | #: kosmorro/i18n/utils.py:33 342 | msgid "{month} {day_number}, {year}" 343 | msgstr "{day_number} {month} {year}" 344 | 345 | #: kosmorro/i18n/utils.py:36 346 | msgid "{hours}:{minutes}" 347 | msgstr "" 348 | 349 | #, fuzzy 350 | #~ msgid "Unknown phase" 351 | #~ msgstr "Månefase:" 352 | 353 | #~ msgid "A Summary of your Sky" 354 | #~ msgstr "Et sammendrag av din himmel" 355 | -------------------------------------------------------------------------------- /kosmorro/locales/ru/LC_MESSAGES/messages.po: -------------------------------------------------------------------------------- 1 | # Translations template for kosmorro. 2 | # Copyright (C) 2021 ORGANIZATION 3 | # This file is distributed under the same license as the kosmorro project. 4 | # FIRST AUTHOR , 2021. 5 | # Stalone , 2021. 6 | # Jérôme Deuchnord , 2024. 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: kosmorro 0.9.0\n" 10 | "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" 11 | "POT-Creation-Date: 2024-05-26 11:23+0200\n" 12 | "PO-Revision-Date: 2024-03-13 12:01+0000\n" 13 | "Last-Translator: Jérôme Deuchnord \n" 14 | "Language-Team: Russian \n" 16 | "Language: ru\n" 17 | "MIME-Version: 1.0\n" 18 | "Content-Type: text/plain; charset=UTF-8\n" 19 | "Content-Transfer-Encoding: 8bit\n" 20 | "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " 21 | "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" 22 | "X-Generator: Weblate 5.5-dev\n" 23 | "Generated-By: Babel 2.9.0\n" 24 | 25 | #: kosmorro/__main__.py:61 26 | msgid "" 27 | "Save the planet and paper!\n" 28 | "Consider printing your PDF document only if really necessary, and use the " 29 | "other side of the sheet." 30 | msgstr "" 31 | 32 | #: kosmorro/__main__.py:70 33 | msgid "" 34 | "PDF output will not contain the ephemerides, because you didn't provide the " 35 | "observation coordinates." 36 | msgstr "" 37 | 38 | #: kosmorro/__main__.py:115 39 | msgid "The file could not be saved in \"{path}\": {error}" 40 | msgstr "" 41 | 42 | #: kosmorro/__main__.py:129 43 | msgid "Please provide a file path to export in this format (--output)." 44 | msgstr "" 45 | 46 | #: kosmorro/__main__.py:162 47 | msgid "Moon phase can only be computed between {min_date} and {max_date}" 48 | msgstr "" 49 | 50 | #: kosmorro/__main__.py:201 51 | #, fuzzy 52 | msgid "" 53 | "Running on Python {python_version} with Kosmorrolib v{kosmorrolib_version}" 54 | msgstr "Работают под Python {python_version}" 55 | 56 | #: kosmorro/__main__.py:214 57 | msgid "" 58 | "Compute the ephemerides and the events for a given date and a given position " 59 | "on Earth." 60 | msgstr "" 61 | 62 | #: kosmorro/__main__.py:217 63 | msgid "" 64 | "By default, only the events will be computed for today.\n" 65 | "To compute also the ephemerides, latitude and longitude arguments are needed." 66 | msgstr "" 67 | 68 | #: kosmorro/__main__.py:230 69 | msgid "Show the program version" 70 | msgstr "Показать версия программы" 71 | 72 | #: kosmorro/__main__.py:238 73 | msgid "The format to output the information to" 74 | msgstr "" 75 | 76 | #: kosmorro/__main__.py:245 77 | msgid "" 78 | "The observer's latitude on Earth. Can also be set in the KOSMORRO_LATITUDE " 79 | "environment variable." 80 | msgstr "" 81 | 82 | #: kosmorro/__main__.py:255 83 | msgid "" 84 | "The observer's longitude on Earth. Can also be set in the KOSMORRO_LONGITUDE " 85 | "environment variable." 86 | msgstr "" 87 | 88 | #: kosmorro/__main__.py:265 89 | msgid "" 90 | "The date for which the ephemerides must be calculated. Can be in the YYYY-MM-" 91 | "DD format or an interval in the \"[+-]YyMmDd\" format (with Y, M, and D " 92 | "numbers). Defaults to current date." 93 | msgstr "" 94 | 95 | #: kosmorro/__main__.py:276 96 | msgid "" 97 | "The timezone to display the hours in (e.g. 2 for UTC+2 or -3 for UTC-3). Can " 98 | "also be set in the KOSMORRO_TIMEZONE environment variable." 99 | msgstr "" 100 | 101 | #: kosmorro/__main__.py:285 102 | msgid "Disable the colors in the console." 103 | msgstr "" 104 | 105 | #: kosmorro/__main__.py:292 106 | msgid "" 107 | "A file to export the output to. If not given, the standard output is used. " 108 | "This argument is needed for PDF format." 109 | msgstr "" 110 | 111 | #: kosmorro/__main__.py:301 112 | msgid "" 113 | "Do not generate a graph to represent the rise and set times in the PDF " 114 | "format." 115 | msgstr "" 116 | 117 | #: kosmorro/__main__.py:309 118 | msgid "Show debugging messages" 119 | msgstr "" 120 | 121 | #: kosmorro/date.py:17 122 | msgid "The date {date} is not valid: {error}" 123 | msgstr "Дата {date} - неправильно" 124 | 125 | #: kosmorro/date.py:39 126 | msgid "" 127 | "The date {date} does not match the required YYYY-MM-DD format or the offset " 128 | "format." 129 | msgstr "" 130 | 131 | #: kosmorro/dumper.py:137 132 | msgid "Expected events:" 133 | msgstr "Ожидаемые события:" 134 | 135 | #: kosmorro/dumper.py:144 136 | msgid "Note: All the hours are given in UTC." 137 | msgstr "Примечание: все время указано в формате UTC." 138 | 139 | #: kosmorro/dumper.py:151 140 | msgid "Note: All the hours are given in the UTC{offset} timezone." 141 | msgstr "Примечание: все часы указаны по UTC{offset} времени." 142 | 143 | #: kosmorro/dumper.py:205 kosmorro/dumper.py:333 144 | msgid "Object" 145 | msgstr "Объект" 146 | 147 | #: kosmorro/dumper.py:206 kosmorro/dumper.py:334 148 | msgid "Rise time" 149 | msgstr "" 150 | 151 | #: kosmorro/dumper.py:207 kosmorro/dumper.py:336 152 | msgid "Culmination time" 153 | msgstr "Кульминация момент" 154 | 155 | #: kosmorro/dumper.py:208 kosmorro/dumper.py:338 156 | msgid "Set time" 157 | msgstr "" 158 | 159 | #: kosmorro/dumper.py:234 160 | msgid "Moon phase is unavailable for this date." 161 | msgstr "" 162 | 163 | #: kosmorro/dumper.py:238 kosmorro/dumper.py:342 164 | msgid "Moon phase:" 165 | msgstr "" 166 | 167 | #: kosmorro/dumper.py:242 168 | msgid "{next_moon_phase} on {next_moon_phase_date} at {next_moon_phase_time}" 169 | msgstr "{next_moon_phase} в {next_moon_phase_date} в {next_moon_phase_time}" 170 | 171 | #: kosmorro/dumper.py:306 172 | msgid "Overview of your sky" 173 | msgstr "" 174 | 175 | #: kosmorro/dumper.py:314 176 | msgid "" 177 | "This document summarizes the ephemerides and the events of {date}. It aims " 178 | "to help you to prepare your observation session. All the hours are given in " 179 | "{timezone}." 180 | msgstr "" 181 | "Этот документ резюмирует эфемериды и события {date}. Это поможет вам " 182 | "подготовиться к сеансу наблюдения. Все часы указаны по {timezone}." 183 | 184 | #: kosmorro/dumper.py:324 185 | msgid "" 186 | "Don't forget to check the weather forecast before you go out with your " 187 | "equipment." 188 | msgstr "" 189 | 190 | #: kosmorro/dumper.py:331 191 | msgid "Ephemerides of the day" 192 | msgstr "" 193 | 194 | #: kosmorro/dumper.py:340 195 | msgid "hours" 196 | msgstr "" 197 | 198 | #: kosmorro/dumper.py:347 199 | msgid "Expected events" 200 | msgstr "" 201 | 202 | #: kosmorro/dumper.py:487 203 | msgid "" 204 | "Building PDF was not possible, because some dependencies are not installed.\n" 205 | "Please look at the documentation at https://kosmorro.space/cli/generate-pdf/ " 206 | "for more information." 207 | msgstr "" 208 | 209 | #: kosmorro/dumper.py:540 210 | #, python-format 211 | msgid "" 212 | "An error occurred during the compilation of the PDF.\n" 213 | "Please open an issue at https://github.com/Kosmorro/kosmorro/issues and " 214 | "share the content of the log file at /tmp/kosmorro-%s.log" 215 | msgstr "" 216 | 217 | #: kosmorro/exceptions.py:35 218 | msgid "The date must be between {minimum_date} and {maximum_date}" 219 | msgstr "" 220 | 221 | #: kosmorro/i18n/strings.py:11 222 | #, python-format 223 | msgid "%s is in opposition" 224 | msgstr "" 225 | 226 | #: kosmorro/i18n/strings.py:12 227 | #, python-format 228 | msgid "%s and %s are in conjunction" 229 | msgstr "" 230 | 231 | #: kosmorro/i18n/strings.py:13 232 | #, python-format 233 | msgid "%s occults %s" 234 | msgstr "" 235 | 236 | #: kosmorro/i18n/strings.py:15 237 | #, python-format 238 | msgid "Elongation of %s is maximal" 239 | msgstr "" 240 | 241 | #: kosmorro/i18n/strings.py:18 242 | #, python-format 243 | msgid "%s is at its periapsis" 244 | msgstr "" 245 | 246 | #: kosmorro/i18n/strings.py:19 247 | #, python-format 248 | msgid "%s is at its apoapsis" 249 | msgstr "" 250 | 251 | #: kosmorro/i18n/strings.py:35 252 | msgid "New Moon" 253 | msgstr "Новолуние" 254 | 255 | #: kosmorro/i18n/strings.py:36 256 | msgid "Waxing Crescent" 257 | msgstr "Молодая луна" 258 | 259 | #: kosmorro/i18n/strings.py:37 260 | msgid "First Quarter" 261 | msgstr "Первая четверть" 262 | 263 | #: kosmorro/i18n/strings.py:38 264 | msgid "Waxing Gibbous" 265 | msgstr "Прибывающая луна" 266 | 267 | #: kosmorro/i18n/strings.py:39 268 | msgid "Full Moon" 269 | msgstr "Полнолуние" 270 | 271 | #: kosmorro/i18n/strings.py:40 272 | msgid "Waning Gibbous" 273 | msgstr "Убывающая луна" 274 | 275 | #: kosmorro/i18n/strings.py:41 276 | msgid "Last Quarter" 277 | msgstr "Последняя четверть" 278 | 279 | #: kosmorro/i18n/strings.py:42 280 | msgid "Waning Crescent" 281 | msgstr "Старая луна" 282 | 283 | #: kosmorro/i18n/strings.py:53 284 | msgid "Sun" 285 | msgstr "Солнце" 286 | 287 | #: kosmorro/i18n/strings.py:54 288 | msgid "Moon" 289 | msgstr "Луна" 290 | 291 | #: kosmorro/i18n/strings.py:55 292 | msgid "Mercury" 293 | msgstr "Меркурий" 294 | 295 | #: kosmorro/i18n/strings.py:56 296 | msgid "Venus" 297 | msgstr "Венера" 298 | 299 | #: kosmorro/i18n/strings.py:57 300 | msgid "Earth" 301 | msgstr "" 302 | 303 | #: kosmorro/i18n/strings.py:58 304 | msgid "Mars" 305 | msgstr "Марс" 306 | 307 | #: kosmorro/i18n/strings.py:59 308 | msgid "Jupiter" 309 | msgstr "Юпитер" 310 | 311 | #: kosmorro/i18n/strings.py:60 312 | msgid "Saturn" 313 | msgstr "Сатурн" 314 | 315 | #: kosmorro/i18n/strings.py:61 316 | msgid "Uranus" 317 | msgstr "Уран" 318 | 319 | #: kosmorro/i18n/strings.py:62 320 | msgid "Neptune" 321 | msgstr "Нептун" 322 | 323 | #: kosmorro/i18n/strings.py:63 324 | msgid "Pluto" 325 | msgstr "Плутон" 326 | 327 | #: kosmorro/i18n/utils.py:27 328 | msgid "{day_of_week} {month} {day_number}, {year}" 329 | msgstr "{day_of_week}, {day_number} {month} {year} г." 330 | 331 | #: kosmorro/i18n/utils.py:30 332 | msgid "{month} {day_number}, {hours}:{minutes}" 333 | msgstr "{month} {day_number}, {hours}:{minutes}" 334 | 335 | #: kosmorro/i18n/utils.py:33 336 | msgid "{month} {day_number}, {year}" 337 | msgstr "{month} {day_number}, {year}" 338 | 339 | #: kosmorro/i18n/utils.py:36 340 | msgid "{hours}:{minutes}" 341 | msgstr "{hours}:{minutes}" 342 | 343 | #, fuzzy 344 | #~ msgid "Do you really want to clear Kosmorro's cache? [yN] " 345 | #~ msgstr "Вы действительно хотите очищение кеш Kosmorro? " 346 | 347 | #, fuzzy 348 | #~ msgid "Incorrect answer, cache not cleared." 349 | #~ msgstr "Ответ не соответствовал с ожидаемыми вариантами, кеш не очищение." 350 | -------------------------------------------------------------------------------- /kosmorro/utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from termcolor import colored as do_color 4 | 5 | try: 6 | from importlib.metadata import version 7 | except ImportError: 8 | from importlib_metadata import version 9 | 10 | KOSMORRO_VERSION = version("kosmorro") 11 | KOSMORROLIB_VERSION = version("kosmorrolib") 12 | 13 | 14 | global _COLORS_ACTIVATED 15 | 16 | 17 | def set_colors_activated(activated: bool): 18 | global _COLORS_ACTIVATED 19 | _COLORS_ACTIVATED = activated 20 | 21 | 22 | def colored(text, color=None, on_color=None, attrs=None): 23 | """Decorator to use colors only when they are activated""" 24 | if not _COLORS_ACTIVATED: 25 | return text 26 | 27 | return do_color(text, color, on_color, attrs) 28 | -------------------------------------------------------------------------------- /manpage/README.md: -------------------------------------------------------------------------------- 1 | # Kosmorro's manpages 2 | 3 | This folder contains Kosmorro's manpages. 4 | 5 | Two sections are available: 6 | 7 | - Section 1: contains the details about the command line usage. 8 | - Section 7: contains the vocabulary used in Kosmorro along with their definitions. 9 | 10 | ## How to use it 11 | 12 | To open the manpage from section 1, open a terminal and invoke: 13 | 14 | ```bash 15 | man kosmorro 16 | ``` 17 | 18 | If you want to open the vocabulary: 19 | 20 | ```bash 21 | man 7 kosmorro 22 | ```` 23 | 24 | ## `man` complains there's "No manual entry for kosmorro" 25 | 26 | Sometimes, especially on Mac, `man` needs to be informed about where the manpages are stored by Python 3. Invoke the following command to do this: 27 | 28 | ```bash 29 | echo 'export MANPATH=/usr/local/man:$MANPATH' >> $HOME/.bashrc 30 | ``` 31 | 32 | And open a new terminal. 33 | 34 | NB: if you are not using Bash, change `.bashrc` with the correct file. 35 | -------------------------------------------------------------------------------- /manpage/kosmorro.1.md: -------------------------------------------------------------------------------- 1 | # kosmorro(1) -- a program that computes the ephemerides 2 | 3 | ## SYNOPSIS 4 | 5 | `kosmorro` 6 | `kosmorro` [_OPTIONS_]... 7 | 8 | ## OPTIONS 9 | 10 | `-h`, `--help` 11 | show a help message and exit 12 | 13 | `--version`, `-v` 14 | show the program version 15 | 16 | `--clear-cache` 17 | delete all the files Kosmorro stored in the cache 18 | 19 | `--latitude=`_LATITUDE_, `-lat` _LATITUDE_ 20 | the observer's latitude on Earth 21 | 22 | `--longitude=`_LONGITUDE_, `-lon` _LONGITUDE_ 23 | the observer's longitude on Earth 24 | 25 | `--date=`_DATE_, `-d` _DATE_ 26 | The date for which the ephemerides must be computed, either in the YYYY-MM-DD format or as an interval in the "[+-]YyMmDd" format (with Y, M, and D numbers); defaults to the current date 27 | 28 | `--timezone=`_TIMEZONE_, `-t` _TIMEZONE_ 29 | the timezone to display the hours in; e.g. 2 for UTC+2 or -3 for UTC-3 30 | 31 | `--no-colors` 32 | disable the colors in the console 33 | 34 | `--output=`_OUTPUT_, `-o` _OUTPUT_ 35 | a file to export the output to; if not given, the standard output is used 36 | 37 | `--format=`_FORMAT_, `-f` _FORMAT_ 38 | the format under which the information have to be output; one of the following: text, json, pdf 39 | 40 | `--no-graph` 41 | present the ephemerides in a table instead of a graph; PDF output format only 42 | 43 | ## ENVIRONMENT VARIABLES 44 | 45 | The environment variable listed below may be used instead of the options. 46 | The options have a higher priority than the environment variable. 47 | As a consequence, any option that would be given to `kosmorro` will override its corresponding environment variable. 48 | 49 | Available environment variables are: 50 | 51 | `KOSMORRO_LATITUDE` 52 | the observer's latitude on Earth (alternative to `--latitude`) 53 | 54 | `KOSMORRO_LONGITUDE` 55 | the observer's longitude on Earth (alternative to `--longitude`) 56 | 57 | `KOSMORRO_TIMEZONE` 58 | the observer's timezone (alternative to `--timezone`) 59 | 60 | ## EXAMPLES 61 | 62 | Compute the events only for the current date: 63 | 64 | ``` 65 | kosmorro 66 | ``` 67 | 68 | Compute the ephemerides for Lille, France, on April 1st, 2022: 69 | 70 | ``` 71 | kosmorro --latitude=50.5876 --longitude=3.0624 --date=2022-04-01 72 | ``` 73 | 74 | Compute the ephemerides for Lille, France, on April 1st, 2022, and export them in a PDF document: 75 | 76 | ``` 77 | kosmorro --latitude=50.5876 --longitude=3.0624 -date=2022-04-01 --format=pdf --output=file.pdf 78 | ``` 79 | 80 | ## AUTHOR 81 | 82 | Written by Jérôme Deuchnord. 83 | 84 | ## REPORTING BUGS 85 | 86 | Please report any encountered bugs on Kosmorro's [GitHub project](https://github.com/Deuchnord/kosmorro). 87 | 88 | ## COPYRIGHT 89 | 90 | This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 91 | 92 | -------------------------------------------------------------------------------- /manpage/kosmorro.7.md: -------------------------------------------------------------------------------- 1 | # kosmorro(7) -- a program that computes the ephemerides 2 | 3 | ## DESCRIPTION 4 | 5 | This manual explains the different terms that one can find when using **kosmorro**(1). 6 | The terms are given in an alphabetically order. 7 | 8 | ## TERMS 9 | 10 | ### Apogee 11 | 12 | The Moon is told being at its apogee when it is at its furthest point from the Earth. 13 | 14 | ### Conjunction 15 | 16 | From the point of view of the Earth, two asters are said in conjunction when they are close together. 17 | It is, of course, an illusion caused by the position of the Earth combined with the two other objects' ones. 18 | 19 | ### Elongation 20 | 21 | The elongation is the angle of visual separation between a planet and the Sun, as seen from the point of view of the Earth. 22 | For the inferior planets, the time when the elongation is maximal is propice to their observation, because it is the moment when they are the most visible. 23 | 24 | ### Occultation 25 | 26 | An occultation is a special kind of conjunction where the closer aster to the Earth hides, at least partially, another one. 27 | 28 | ### Opposition 29 | 30 | An aster is said in opposition when it is positionned at the exact opposite of the Sun, from the point of view of the Earth, i.e. when their angle is equal to 180 degrees. 31 | For all the superior planets, it is the best moment to observe them, because they will be at the smallest distance to the Earth. Plus, they will appear full. 32 | For instance, Mars is in opposition when the angle Mars-Earth-Sun is equal to 180 degrees. 33 | 34 | ### Perigee 35 | 36 | The Moon is told being at its apogee when it is at its nearest point from the Earth. 37 | 38 | ### Planet 39 | 40 | A planet is an aster that orbits around a star, is not a star itself, is massive enough to maintain it nearly round, and has cleaned its orbit from other massive objects. 41 | 42 | **Inferior planet** 43 | 44 | A planet is said "inferior" if its orbit radius is smaller than the planet of reference. 45 | For instance, the inferior planets from the point of view of the Earth are Mercury and Venus. 46 | 47 | The term should not be confused with "inner planet". 48 | 49 | **Inner planet** 50 | 51 | The "inner planet" term refers to the planets orbiting below the orbit of the asteroid belt between Mars and Jupiter. 52 | 53 | **Outer planet** 54 | 55 | The "outer planet" term refers to the planets orbiting beyond the orbit of the asteroid belt between Mars and Jupiter. 56 | 57 | **Superior planet** 58 | 59 | A planet is said "superior" if its orbit radius is higher than the planet of reference. 60 | For instance, the superior planets from the point of view of the Earth are Mars, Jupiter, Saturn, Uranus and Neptune. 61 | 62 | The term should not be confused with "outer planet". 63 | 64 | ## AUTHOR 65 | 66 | Written by Jérôme Deuchnord. 67 | 68 | ## COPYRIGHT 69 | 70 | This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 71 | 72 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "kosmorro" 3 | version = "0.10.13" 4 | description = "A program to compute the ephemerides." 5 | authors = ["Jérôme Deuchnord "] 6 | license = "AGPL-3.0-or-later" 7 | 8 | include = [ 9 | "CHANGELOG.md", 10 | "kosmorro/locales/*/LC_MESSAGES/*.mo", 11 | "kosmorro/assets", 12 | ] 13 | 14 | [tool.poetry.scripts] 15 | kosmorro = 'kosmorro.__main__:main' 16 | 17 | [tool.poetry.dependencies] 18 | python = "^3.8" 19 | tabulate = ">=0.8,<0.10" 20 | termcolor = ">=1.1,<3.0" 21 | kosmorrolib = "^1.0" 22 | python-dateutil = "^2.8" 23 | Babel = "^2.9" 24 | importlib-metadata = ">=4.11,<9.0" 25 | 26 | [tool.poetry.dev-dependencies] 27 | black = "^24.8" 28 | pytest = "^8.3" 29 | aurornis = "^1.5" 30 | 31 | [build-system] 32 | requires = ["poetry-core>=1.0.0"] 33 | build-backend = "poetry.core.masonry.api" 34 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [extract_message] 2 | charset = utf-8 3 | keywords = _ ngettext 4 | width = 120 5 | output_file = kosmorro/locales/messages.pot 6 | omit_header = true 7 | copyright_holder = Jérôme Deuchnord 8 | input_paths=kosmorro 9 | 10 | [compile_catalog] 11 | domain = messages 12 | directory = kosmorro/locales 13 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmorro/kosmorro/d7def507034e6af0d7c7bdbc4d4174b046b082ac/tests/__init__.py -------------------------------------------------------------------------------- /tests/dates.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from .utils import execute, KOSMORRO 4 | 5 | 6 | def test_with_date(): 7 | for arg in [["-d", "2020-01-27"], ["--date", "2020-01-27"], ["-d2020-01-27"]]: 8 | result = execute(KOSMORRO + arg) 9 | assert result.is_successful() 10 | 11 | assert ( 12 | result.stdout 13 | == """Monday, January 27, 2020 14 | 15 | Moon phase: New Moon 16 | First Quarter on Sunday, February 2, 2020 at 1:41 AM 17 | 18 | Expected events: 19 | 8:00 PM Venus and Neptune are in conjunction 20 | 21 | Note: All the hours are given in UTC. 22 | """ 23 | ) 24 | 25 | 26 | def test_with_incorrect_date_values(): 27 | value = "yolo-yo-lo" 28 | for arg in [["-d", value], ["--date", value], [f"-d{value}"]]: 29 | result = execute(KOSMORRO + arg) 30 | assert not result.is_successful() 31 | assert ( 32 | result.stdout 33 | == f"The date {value} does not match the required YYYY-MM-DD format or the offset format.\n" 34 | ) 35 | 36 | value = "2020-13-32" 37 | for arg in [["-d", value], ["--date", value], [f"-d{value}"]]: 38 | result = execute(KOSMORRO + arg) 39 | assert not result.is_successful() 40 | assert ( 41 | result.stdout == f"The date {value} is not valid: month must be in 1..12\n" 42 | ) 43 | 44 | 45 | def test_with_out_of_range_dates(): 46 | for arg in [["-d", "1789-05-05"], ["-d", "3000-01-01"]]: 47 | result = execute(KOSMORRO + arg) 48 | assert not result.is_successful() 49 | assert ( 50 | result.stdout 51 | == "Moon phase can only be computed between August 9, 1899 and September 26, 2053\n" 52 | ) 53 | -------------------------------------------------------------------------------- /tests/general.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from sys import version_info as python_version 4 | from .utils import ( 5 | execute, 6 | KOSMORRO, 7 | CURRENT_MOON_PHASE_PATTERN, 8 | NEXT_MOON_PHASE_PATTERN, 9 | ) 10 | from datetime import date 11 | from babel.dates import format_date 12 | 13 | 14 | def test_run_without_argument(): 15 | result = execute(KOSMORRO) 16 | assert result.is_successful() 17 | 18 | stdout = result.stdout.split("\n") 19 | print(stdout) 20 | 21 | # It always starts with the current date, an empty line and the current and next Moon date: 22 | assert stdout[0] == format_date(date.today(), "full", "EN") 23 | assert stdout[1] == "" 24 | assert CURRENT_MOON_PHASE_PATTERN.match(stdout[2]) 25 | assert NEXT_MOON_PHASE_PATTERN.match(stdout[3]) 26 | 27 | # It always finishes with an empty line, a note about UTC timezone and an empty line: 28 | assert stdout[-3] == "" 29 | assert stdout[-2] == "Note: All the hours are given in UTC." 30 | assert stdout[-1] == "" 31 | 32 | 33 | def test_help_message(): 34 | for arg in ["--help", "-h"]: 35 | result = execute(KOSMORRO + [arg]) 36 | 37 | assert result.is_successful() 38 | 39 | # Options header has changed from "optional arguments" to "options" in Python 3.10. 40 | options_header = ( 41 | "optional arguments" if python_version.minor < 10 else "options" 42 | ) 43 | 44 | if python_version.major == 3 and python_version.minor < 13: 45 | assert ( 46 | result.stdout 47 | == """usage: kosmorro [-h] [--version] [--format {text,json,pdf}] 48 | [--latitude LATITUDE] [--longitude LONGITUDE] [--date DATE] 49 | [--timezone TIMEZONE] [--no-colors] [--output OUTPUT] 50 | [--no-graph] [--debug] 51 | 52 | Compute the ephemerides and the events for a given date and a given position 53 | on Earth. 54 | 55 | %s: 56 | -h, --help show this help message and exit 57 | --version, -v Show the program version 58 | --format {text,json,pdf}, -f {text,json,pdf} 59 | The format to output the information to 60 | --latitude LATITUDE, -lat LATITUDE 61 | The observer's latitude on Earth. Can also be set in 62 | the KOSMORRO_LATITUDE environment variable. 63 | --longitude LONGITUDE, -lon LONGITUDE 64 | The observer's longitude on Earth. Can also be set in 65 | the KOSMORRO_LONGITUDE environment variable. 66 | --date DATE, -d DATE The date for which the ephemerides must be calculated. 67 | Can be in the YYYY-MM-DD format or an interval in the 68 | "[+-]YyMmDd" format (with Y, M, and D numbers). 69 | Defaults to current date. 70 | --timezone TIMEZONE, -t TIMEZONE 71 | The timezone to display the hours in (e.g. 2 for UTC+2 72 | or -3 for UTC-3). Can also be set in the 73 | KOSMORRO_TIMEZONE environment variable. 74 | --no-colors Disable the colors in the console. 75 | --output OUTPUT, -o OUTPUT 76 | A file to export the output to. If not given, the 77 | standard output is used. This argument is needed for 78 | PDF format. 79 | --no-graph Do not generate a graph to represent the rise and set 80 | times in the PDF format. 81 | --debug Show debugging messages 82 | 83 | By default, only the events will be computed for today. To compute also the 84 | ephemerides, latitude and longitude arguments are needed. 85 | """ 86 | % options_header 87 | ) 88 | else: 89 | assert ( 90 | result.stdout 91 | == """usage: kosmorro [-h] [--version] [--format {text,json,pdf}] 92 | [--latitude LATITUDE] [--longitude LONGITUDE] [--date DATE] 93 | [--timezone TIMEZONE] [--no-colors] [--output OUTPUT] 94 | [--no-graph] [--debug] 95 | 96 | Compute the ephemerides and the events for a given date and a given position 97 | on Earth. 98 | 99 | options: 100 | -h, --help show this help message and exit 101 | --version, -v Show the program version 102 | --format, -f {text,json,pdf} 103 | The format to output the information to 104 | --latitude, -lat LATITUDE 105 | The observer's latitude on Earth. Can also be set in 106 | the KOSMORRO_LATITUDE environment variable. 107 | --longitude, -lon LONGITUDE 108 | The observer's longitude on Earth. Can also be set in 109 | the KOSMORRO_LONGITUDE environment variable. 110 | --date, -d DATE The date for which the ephemerides must be calculated. 111 | Can be in the YYYY-MM-DD format or an interval in the 112 | "[+-]YyMmDd" format (with Y, M, and D numbers). 113 | Defaults to current date. 114 | --timezone, -t TIMEZONE 115 | The timezone to display the hours in (e.g. 2 for UTC+2 116 | or -3 for UTC-3). Can also be set in the 117 | KOSMORRO_TIMEZONE environment variable. 118 | --no-colors Disable the colors in the console. 119 | --output, -o OUTPUT A file to export the output to. If not given, the 120 | standard output is used. This argument is needed for 121 | PDF format. 122 | --no-graph Do not generate a graph to represent the rise and set 123 | times in the PDF format. 124 | --debug Show debugging messages 125 | 126 | By default, only the events will be computed for today. To compute also the 127 | ephemerides, latitude and longitude arguments are needed. 128 | """ 129 | ) 130 | -------------------------------------------------------------------------------- /tests/output.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from .utils import ( 4 | execute, 5 | KOSMORRO, 6 | ) 7 | import tempfile 8 | from os import path, environ 9 | from sys import platform 10 | 11 | 12 | def test_json_output(): 13 | result = execute( 14 | KOSMORRO 15 | + ["--latitude=50.5876", "--longitude=3.0624", "-d2020-01-27", "--format=json"] 16 | ) 17 | assert result.is_successful() 18 | assert ( 19 | result.stdout 20 | == """{ 21 | "ephemerides": [ 22 | { 23 | "object": { 24 | "identifier": "SUN", 25 | "type": "STAR", 26 | "radius": 696342 27 | }, 28 | "rise_time": "2020-01-27T07:31:00", 29 | "culmination_time": "2020-01-27T12:01:00", 30 | "set_time": "2020-01-27T16:30:00" 31 | }, 32 | { 33 | "object": { 34 | "identifier": "MOON", 35 | "type": "SATELLITE", 36 | "radius": 1737.4 37 | }, 38 | "rise_time": "2020-01-27T09:06:00", 39 | "culmination_time": "2020-01-27T14:09:00", 40 | "set_time": "2020-01-27T19:13:00" 41 | }, 42 | { 43 | "object": { 44 | "identifier": "MERCURY", 45 | "type": "PLANET", 46 | "radius": 2439.7 47 | }, 48 | "rise_time": "2020-01-27T08:10:00", 49 | "culmination_time": "2020-01-27T12:49:00", 50 | "set_time": "2020-01-27T17:28:00" 51 | }, 52 | { 53 | "object": { 54 | "identifier": "VENUS", 55 | "type": "PLANET", 56 | "radius": 6051.8 57 | }, 58 | "rise_time": "2020-01-27T09:01:00", 59 | "culmination_time": "2020-01-27T14:35:00", 60 | "set_time": "2020-01-27T20:10:00" 61 | }, 62 | { 63 | "object": { 64 | "identifier": "MARS", 65 | "type": "PLANET", 66 | "radius": 3396.2 67 | }, 68 | "rise_time": "2020-01-27T04:19:00", 69 | "culmination_time": "2020-01-27T08:23:00", 70 | "set_time": "2020-01-27T12:28:00" 71 | }, 72 | { 73 | "object": { 74 | "identifier": "JUPITER", 75 | "type": "PLANET", 76 | "radius": 71492 77 | }, 78 | "rise_time": "2020-01-27T06:15:00", 79 | "culmination_time": "2020-01-27T10:18:00", 80 | "set_time": "2020-01-27T14:21:00" 81 | }, 82 | { 83 | "object": { 84 | "identifier": "SATURN", 85 | "type": "PLANET", 86 | "radius": 60268 87 | }, 88 | "rise_time": "2020-01-27T06:56:00", 89 | "culmination_time": "2020-01-27T11:09:00", 90 | "set_time": "2020-01-27T15:22:00" 91 | }, 92 | { 93 | "object": { 94 | "identifier": "URANUS", 95 | "type": "PLANET", 96 | "radius": 25559 97 | }, 98 | "rise_time": "2020-01-27T10:21:00", 99 | "culmination_time": "2020-01-27T17:25:00", 100 | "set_time": "2020-01-27T00:33:00" 101 | }, 102 | { 103 | "object": { 104 | "identifier": "NEPTUNE", 105 | "type": "PLANET", 106 | "radius": 24764 107 | }, 108 | "rise_time": "2020-01-27T09:01:00", 109 | "culmination_time": "2020-01-27T14:36:00", 110 | "set_time": "2020-01-27T20:10:00" 111 | }, 112 | { 113 | "object": { 114 | "identifier": "PLUTO", 115 | "type": "PLANET", 116 | "radius": 1185 117 | }, 118 | "rise_time": "2020-01-27T06:57:00", 119 | "culmination_time": "2020-01-27T11:04:00", 120 | "set_time": "2020-01-27T15:11:00" 121 | } 122 | ], 123 | "moon_phase": { 124 | "phase": "NEW_MOON", 125 | "time": "2020-01-24T21:41:59.705921+00:00", 126 | "next": { 127 | "phase": "FIRST_QUARTER", 128 | "time": "2020-02-02T01:41:40.282275+00:00" 129 | } 130 | }, 131 | "events": [ 132 | { 133 | "objects": [ 134 | { 135 | "identifier": "VENUS", 136 | "type": "PLANET", 137 | "radius": 6051.8 138 | }, 139 | { 140 | "identifier": "NEPTUNE", 141 | "type": "PLANET", 142 | "radius": 24764 143 | } 144 | ], 145 | "EventType": "CONJUNCTION", 146 | "starts_at": "2020-01-27T20:00:23.242750+00:00", 147 | "ends_at": null, 148 | "details": null 149 | } 150 | ] 151 | } 152 | """ 153 | ) 154 | -------------------------------------------------------------------------------- /tests/outputs/2020-01-27-with-position.tex: -------------------------------------------------------------------------------- 1 | \documentclass[a4paper,12pt]{article} 2 | 3 | \usepackage[utf8]{inputenc} 4 | \usepackage[T1]{fontenc} 5 | \usepackage[margin=25mm]{geometry} 6 | \usepackage{graphicx} 7 | \usepackage{hyperref} 8 | \usepackage{xcolor} 9 | \usepackage{fp} 10 | 11 | % Command showing the Moon phase 12 | \newcommand{\moonphase}[2]{ 13 | \begin{center} 14 | \begin{minipage}{2cm} 15 | \includegraphics[width=\linewidth]{#1} 16 | \end{minipage} 17 | \hspace{5mm} 18 | \begin{minipage}{7cm} 19 | \textbf{\currentmoonphasetitle}\\#2 20 | \end{minipage} 21 | \end{center} 22 | } 23 | 24 | % Environment for the ephemerides, when --no-graph is given on the command line 25 | \newenvironment{ephemerides}{ 26 | \begin{table}[h] 27 | \centering 28 | \begin{tabular}{lccc} 29 | \textbf{\ephemeridesobjecttitle} & 30 | \textbf{\ephemeridesrisetimetitle} & 31 | \textbf{\ephemeridesculminationtimetitle} & 32 | \textbf{\ephemeridessettimetitle}\\ 33 | \hline 34 | }{ 35 | \end{tabular} 36 | \end{table} 37 | } 38 | 39 | % Command adding an object to the ephemerides environment 40 | \newcommand{\object}[4]{ 41 | \hline 42 | \textbf{#1} & {#2} & {#3} & {#4}\\ 43 | } 44 | 45 | % Environment to insert the ephemerides graph 46 | \newenvironment{graphephemerides}{\setlength{\unitlength}{0.02\linewidth} 47 | \begin{picture}(20,20) 48 | % Axes 49 | \put(0,-2){\vector(1,0){50}} 50 | \multiput(0,-2)(2,0){24}{ 51 | \line(0,-1){0.25} 52 | } 53 | \newcounter{hour} 54 | \multiput(-0.25,-3.5)(4,0){12}{ 55 | \sffamily\footnotesize 56 | \arabic{hour}\stepcounter{hour}\stepcounter{hour} 57 | } 58 | \put(49,-3.5){\sffamily\footnotesize \hourslabel} 59 | 60 | % Graduation 61 | 62 | \put(50,-0.5){\sffamily\footnotesize \Pluto} 63 | \put(50,1.5){\sffamily\footnotesize \Neptune} 64 | \put(50,3.5){\sffamily\footnotesize \Uranus} 65 | \put(50,5.5){\sffamily\footnotesize \Saturn} 66 | \put(50,7.5){\sffamily\footnotesize \Jupiter} 67 | \put(50,9.5){\sffamily\footnotesize \Mars} 68 | \put(50,11.5){\sffamily\footnotesize \Venus} 69 | \put(50,13.5){\sffamily\footnotesize \Mercury} 70 | \put(50,15.5){\sffamily\footnotesize \Moon} 71 | \put(50,17.5){\sffamily\footnotesize \Sun} 72 | 73 | \multiput(0,0)(0,2){10}{ 74 | \color{gray}\line(1,0){48} 75 | } 76 | 77 | \linethickness{1.5mm} 78 | }{ 79 | \end{picture} 80 | \vspace{1cm} 81 | } 82 | 83 | % Command to add an object to the graph 84 | \newcommand{\graphobject}[8]{% 85 | % #1: Y coordinate component 86 | % #2: Color 87 | % #3: Hour rise time 88 | % #4: Minute rise time 89 | % #5: Hour set time 90 | % #6: Minute set time 91 | % #7: Human-readable rise time 92 | % #8: Human-readable set time 93 | 94 | \FPeval{\start}{#3*2+(#4/60)*2}% 95 | \FPeval{\length}{#5*2+(#6/60)*2 - \start}% 96 | \FPeval{\starttext}{\start+0.7}% 97 | \FPeval{\endtext}{\start+\length-3.25}% 98 | 99 | {\color{#2}% 100 | \put(\start,#1){% 101 | \line(1, 0){\length}% 102 | }}% 103 | 104 | \put(\starttext,#1.5){\sffamily\footnotesize #7}% 105 | \put(\endtext,#1.5){\sffamily\footnotesize #8}% 106 | } 107 | 108 | \newcommand{\event}[2]{ 109 | \textbf{#1} & {#2}\\ 110 | } 111 | 112 | \newenvironment{events}{ 113 | \begin{table}[h] 114 | \begin{tabular}{ll} 115 | }{ 116 | \end{tabular} 117 | \end{table} 118 | } 119 | 120 | % Commands to handle the translated strings 121 | \newcommand{\currentmoonphasetitle}{Moon phase:} 122 | \newcommand{\ephemeridesobjecttitle}{Object} 123 | \newcommand{\ephemeridesrisetimetitle}{Rise time} 124 | \newcommand{\ephemeridesculminationtimetitle}{Culmination time} 125 | \newcommand{\ephemeridessettimetitle}{Set time} 126 | \newcommand{\hourslabel}{hours} 127 | 128 | \newcommand{\Pluto}{Pluto} 129 | \newcommand{\Neptune}{Neptune} 130 | \newcommand{\Uranus}{Uranus} 131 | \newcommand{\Saturn}{Saturn} 132 | \newcommand{\Jupiter}{Jupiter} 133 | \newcommand{\Mars}{Mars} 134 | \newcommand{\Venus}{Venus} 135 | \newcommand{\Mercury}{Mercury} 136 | \newcommand{\Moon}{Moon} 137 | \newcommand{\Sun}{Sun} 138 | 139 | % Fix Unicode issues 140 | \DeclareUnicodeCharacter{202F}{~} 141 | \DeclareUnicodeCharacter{00B0}{$^\circ$} 142 | 143 | \hypersetup{pdfinfo={% 144 | Title={Overview of your sky}, 145 | Creator={Kosmorro v__APP_VERSION__} 146 | }} 147 | 148 | \pagenumbering{gobble} 149 | \setcounter{secnumdepth}{0} 150 | 151 | \title{\sffamily\href{http://kosmorro.space}{\includegraphics[width=5cm]{__PROJECT_PATH__/assets/png/kosmorro-logo.png}}\\Overview of your sky} 152 | \date{\vspace{-11mm}\sffamily Monday, January 27, 2020} 153 | 154 | \begin{document} 155 | 156 | \maketitle 157 | 158 | This document summarizes the ephemerides and the events of Monday, January 27, 2020. It aims to help you to prepare your observation session. All the hours are given in UTC. 159 | 160 | Don't forget to check the weather forecast before you go out with your equipment. 161 | 162 | \moonphase{__PROJECT_PATH__/assets/moonphases/png/new-moon.png}{New Moon} 163 | 164 | %%% BEGIN-EPHEMERIDES-SECTION 165 | \section{\sffamily Ephemerides of the day} 166 | 167 | \begin{graphephemerides}% 168 | \graphobject{18}{gray}{7}{31}{16}{30}{7:31 AM}{4:30 PM}\graphobject{16}{gray}{9}{6}{19}{13}{9:06 AM}{7:13 PM}\graphobject{14}{gray}{8}{10}{17}{28}{8:10 AM}{5:28 PM}\graphobject{12}{gray}{9}{1}{20}{10}{9:01 AM}{8:10 PM}\graphobject{10}{gray}{4}{19}{12}{28}{4:19 AM}{12:28 PM}\graphobject{8}{gray}{6}{15}{14}{21}{6:15 AM}{2:21 PM}\graphobject{6}{gray}{6}{56}{15}{22}{6:56 AM}{3:22 PM}\graphobject{4}{gray}{0}{0}{0}{33}{}{12:33 AM}\graphobject{4}{gray}{10}{21}{24}{0}{10:21 AM}{}\graphobject{2}{gray}{9}{1}{20}{10}{9:01 AM}{8:10 PM}\graphobject{0}{gray}{6}{57}{15}{11}{6:57 AM}{3:11 PM} 169 | \end{graphephemerides} 170 | %%% END-EPHEMERIDES-SECTION 171 | 172 | %%% BEGIN-EVENTS-SECTION 173 | \section{\sffamily Expected events} 174 | 175 | \begin{events} 176 | \event{8:00 PM}{Venus and Neptune are in conjunction} 177 | \end{events} 178 | %%% END-EVENTS-SECTION 179 | 180 | \end{document} 181 | 182 | -------------------------------------------------------------------------------- /tests/position.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from .utils import ( 4 | execute, 5 | KOSMORRO, 6 | ) 7 | 8 | 9 | def check_command_return(result): 10 | assert result.is_successful() 11 | assert ( 12 | result.stdout 13 | == """Monday, January 27, 2020 14 | 15 | Object Rise time Culmination time Set time 16 | -------- ----------- ------------------ ---------- 17 | Sun 7:31 AM 12:01 PM 4:30 PM 18 | Moon 9:06 AM 2:09 PM 7:13 PM 19 | Mercury 8:10 AM 12:49 PM 5:28 PM 20 | Venus 9:01 AM 2:35 PM 8:10 PM 21 | Mars 4:19 AM 8:23 AM 12:28 PM 22 | Jupiter 6:15 AM 10:18 AM 2:21 PM 23 | Saturn 6:56 AM 11:09 AM 3:22 PM 24 | Uranus 10:21 AM 5:25 PM 12:33 AM 25 | Neptune 9:01 AM 2:36 PM 8:10 PM 26 | Pluto 6:57 AM 11:04 AM 3:11 PM 27 | 28 | Moon phase: New Moon 29 | First Quarter on Sunday, February 2, 2020 at 1:41 AM 30 | 31 | Expected events: 32 | 8:00 PM Venus and Neptune are in conjunction 33 | 34 | Note: All the hours are given in UTC. 35 | """ 36 | ) 37 | 38 | 39 | def test_with_position(): 40 | result = execute( 41 | KOSMORRO + ["--latitude=50.5876", "--longitude=3.0624", "-d2020-01-27"] 42 | ) 43 | check_command_return(result) 44 | 45 | 46 | def test_with_position_env_vars(): 47 | check_command_return( 48 | execute( 49 | KOSMORRO + ["-d2020-01-27"], 50 | environment={ 51 | "KOSMORRO_LATITUDE": "50.5876", 52 | "KOSMORRO_LONGITUDE": "3.0624", 53 | }, 54 | ) 55 | ) 56 | -------------------------------------------------------------------------------- /tests/timezone.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from .utils import ( 4 | execute, 5 | KOSMORRO, 6 | ) 7 | 8 | 9 | def check_command_return_t_plus_one(result): 10 | assert result.is_successful() 11 | assert ( 12 | result.stdout 13 | == """Monday, January 27, 2020 14 | 15 | Moon phase: New Moon 16 | First Quarter on Sunday, February 2, 2020 at 2:41 AM 17 | 18 | Expected events: 19 | 9:00 PM Venus and Neptune are in conjunction 20 | 21 | Note: All the hours are given in the UTC+1 timezone. 22 | """ 23 | ) 24 | 25 | 26 | def check_command_return_t_minus_one(result): 27 | assert result.is_successful() 28 | assert ( 29 | result.stdout 30 | == """Monday, January 27, 2020 31 | 32 | Moon phase: New Moon 33 | First Quarter on Sunday, February 2, 2020 at 12:41 AM 34 | 35 | Expected events: 36 | 7:00 PM Venus and Neptune are in conjunction 37 | 38 | Note: All the hours are given in the UTC-1 timezone. 39 | """ 40 | ) 41 | 42 | 43 | def test_timezone(): 44 | check_command_return_t_plus_one( 45 | execute(KOSMORRO + ["--timezone=1", "-d2020-01-27"]) 46 | ) 47 | check_command_return_t_minus_one( 48 | execute(KOSMORRO + ["--timezone=-1", "-d2020-01-27"]) 49 | ) 50 | 51 | 52 | def test_timezone_with_env_var(): 53 | check_command_return_t_plus_one( 54 | execute(KOSMORRO + ["-d2020-01-27"], environment={"KOSMORRO_TIMEZONE": "1"}) 55 | ) 56 | check_command_return_t_minus_one( 57 | execute(KOSMORRO + ["-d2020-01-27"], environment={"KOSMORRO_TIMEZONE": "-1"}) 58 | ) 59 | 60 | # If both environment variable and argument are set, use argument: 61 | 62 | check_command_return_t_plus_one( 63 | execute( 64 | KOSMORRO + ["--timezone=1", "-d2020-01-27"], 65 | environment={"KOSMORRO_TIMEZONE": "-1"}, 66 | ) 67 | ) 68 | check_command_return_t_minus_one( 69 | execute( 70 | KOSMORRO + ["--timezone=-1", "-d2020-01-27"], 71 | environment={"KOSMORRO_TIMEZONE": "1"}, 72 | ) 73 | ) 74 | -------------------------------------------------------------------------------- /tests/utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import aurornis 4 | import re 5 | 6 | from os import environ 7 | from typing import Union 8 | 9 | DEFAULT_ENVIRONMENT = {"PATH": environ["PATH"]} 10 | KOSMORRO = ["kosmorro", "--no-color"] 11 | 12 | CURRENT_MOON_PHASE_PATTERN = re.compile( 13 | r"^Moon phase: (" 14 | r"(New Moon)|(Waxing Crescent)|" 15 | r"(First Quarter)|(Waxing Gibbous)|" 16 | r"(Full Moon)|(Waning Gibbous)|" 17 | r"(Last Quarter)|(Waning Crescent)" 18 | r")$" 19 | ) 20 | 21 | NEXT_MOON_PHASE_PATTERN = re.compile( 22 | r"^((New Moon)|(Waxing Crescent)|" 23 | r"(First Quarter)|(Waxing Gibbous)|" 24 | r"(Full Moon)|(Waning Gibbous)|" 25 | r"(Last Quarter)|(Waning Crescent)) " 26 | r"on ((Monday)|(Tuesday)|(Wednesday)|(Thursday)|(Friday)|(Saturday)|(Sunday)), " 27 | r"((January)|(February)|(March)|(April)|(May)|(June)|" 28 | r"(July)|(August)|(September)|(October)|(November)|(December)) " 29 | r"[0-9]{1,2}, [0-9]{4} at [0-9]{1,2}:[0-9]{2} [AP]M$" 30 | ) 31 | 32 | 33 | def execute( 34 | command, environment: {str: Union[int, str]} = None 35 | ) -> aurornis.CommandResult: 36 | if environment is None: 37 | environment = DEFAULT_ENVIRONMENT 38 | else: 39 | for variable in DEFAULT_ENVIRONMENT: 40 | environment[variable] = DEFAULT_ENVIRONMENT[variable] 41 | 42 | return aurornis.run(command, environment) 43 | 44 | 45 | def assert_nb_lines(expected_nb: int, in_str: str): 46 | """Check that the string has the specified number of lines and that the last one is empty.""" 47 | lines = in_str.split("\n") 48 | assert len(lines) == expected_nb 49 | assert lines[len(lines) - 1] == "" 50 | --------------------------------------------------------------------------------