Browse Source

Add tests

tags/v0.10.0
Jérôme Deuchnord 3 years ago
parent
commit
6a1047f2e6
25 changed files with 928 additions and 95 deletions
  1. +32
    -0
      .github/ISSUE_TEMPLATE/bug_report.md
  2. +20
    -0
      .github/ISSUE_TEMPLATE/event-type-proposal.md
  3. +20
    -0
      .github/ISSUE_TEMPLATE/feature_request.md
  4. +18
    -0
      .github/PULL_REQUEST_TEMPLATE.md
  5. +15
    -0
      .github/dependabot.yml
  6. +66
    -0
      .github/workflows/codeql-analysis.yml
  7. +20
    -0
      .github/workflows/commitlint.yml
  8. +26
    -0
      .github/workflows/pylint.yml
  9. +84
    -0
      .github/workflows/release.yml
  10. +46
    -0
      .github/workflows/stale.yml
  11. +77
    -0
      .github/workflows/unit-tests.yml
  12. +2
    -0
      .gitignore
  13. +50
    -0
      Makefile
  14. +1
    -0
      Pipfile
  15. +105
    -90
      Pipfile.lock
  16. +3
    -3
      kosmorrolib/ephemerides.py
  17. +1
    -1
      kosmorrolib/events.py
  18. +1
    -1
      tests.py
  19. +6
    -0
      tests/__init__.py
  20. +39
    -0
      tests/core.py
  21. +17
    -0
      tests/data.py
  22. +24
    -0
      tests/dateutil.py
  23. +124
    -0
      tests/ephemerides.py
  24. +83
    -0
      tests/events.py
  25. +48
    -0
      tests/testutils.py

+ 32
- 0
.github/ISSUE_TEMPLATE/bug_report.md View File

@@ -0,0 +1,32 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Your configuration (please complete the following information):**
- OS: [e.g. iOS]
- Python version: [e.g. 3.7.0]
- Kosmorro version: [e.g. 1.0.0]

**Additional context**
Add any other context about the problem here.

+ 20
- 0
.github/ISSUE_TEMPLATE/event-type-proposal.md View File

@@ -0,0 +1,20 @@
---
name: Event type proposal
about: Suggest a type of event you'd like to see implemented in Kosmorro
title: ''
labels: "enhancement, \U0001F320 events"
assignees: ''

---

**Event type**:
**Involved objects (check the boxes)**:
- [ ] Sun
- [ ] Earth's moon
- [ ] Planets

**Definition of the event:**

<!-- Replace this comment with the official definition of the event type, with a link to its source. -->

**Other useful information** (implementation proposal, etc):

+ 20
- 0
.github/ISSUE_TEMPLATE/feature_request.md View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.

+ 18
- 0
.github/PULL_REQUEST_TEMPLATE.md View File

@@ -0,0 +1,18 @@
| Q | A
| -------------- | ---
| Bug fix? | yes/no
| New feature? | yes/no
| Related issues | Fix #... <!-- prefix each issue number with "Fix #", if any -->
| Has BC-break | yes/no
| License | GNU AGPL-v3

**Checklist:**
<!--
Leave the checklist as it when editing, and check the boxes once the PR created.
-->
- [ ] I have updated the manpages

<!--
Replace this notice with a short README for your feature/bugfix.
-->


+ 15
- 0
.github/dependabot.yml View File

@@ -0,0 +1,15 @@
version: 2

updates:
- package-ecosystem: pip
directory: "/"
schedule:
interval: daily
time: "04:00"
open-pull-requests-limit: 10
target-branch: master
reviewers:
- Deuchnord
commit-message:
prefix: chore
include: scope

+ 66
- 0
.github/workflows/codeql-analysis.yml View File

@@ -0,0 +1,66 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
name: "CodeQL"

on:
push:
branches: [master, features]
pull_request:
branches: [master, features]
schedule:
- cron: '0 8 * * 0'

jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
language: ['python']

steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2

# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main

# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl

# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language

#- run: |
# make bootstrap
# make release

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

+ 20
- 0
.github/workflows/commitlint.yml View File

@@ -0,0 +1,20 @@
name: Commit lint

on:
push:
branches: [master, features]
pull_request:
branches: [master, features]

jobs:
commitlint:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: wagoid/commitlint-github-action@v2
with:
helpURL: 'https://github.com/Kosmorro/kosmorro/blob/master/CONTRIBUTING.md#commiting'


+ 26
- 0
.github/workflows/pylint.yml View File

@@ -0,0 +1,26 @@
name: Python Lint

on:
push:
branches: [master, features]
pull_request:
branches: [master, features]

jobs:
pylint:
runs-on: ubuntu-latest

name: PyLint
steps:
- uses: actions/checkout@v1
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: 3.9
- name: Install dependencies
run: |
pip install --upgrade pip pipenv
pipenv sync -d
- name: Lint
run: |
pipenv run pylint kosmorro *.py kosmorrolib/*.py

+ 84
- 0
.github/workflows/release.yml View File

@@ -0,0 +1,84 @@
name: Release Application

on:
push:
tags: ['v*']

jobs:
release:
name: Create release
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup
run: |
sudo apt update
sudo apt install ruby
sudo gem install ronn
- name: Prepare release
id: prepare_release
run: |
changelog="$(git diff HEAD^ HEAD -- CHANGELOG.md | grep -E '\+[#*]' | sed 's/^+//')"
changelog="${changelog//$'%'/'%25'}"
changelog="${changelog//$'\n'/'%0A'}"
changelog="${changelog//$'\r'/'%0D'}"
echo "::set-output name=changelog::$changelog"
- name: Build locales
env:
POEDITOR_API_ACCESS: ${{ secrets.POEDITOR_API_ACCESS }}
run: |
make POEDITOR_API_ACCESS="${POEDITOR_API_ACCESS}" i18n
tar cf locales.tar.gz kosmorrolib/locales
- name: Create release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Version ${{ github.ref }}
draft: true
prerelease: false
body: |
${{ steps.prepare_release.outputs.changelog }}
- name: Upload locales
id: upload-locales
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./locales.tar.gz
asset_name: locales.tar.gz
asset_content_type: application/x-tar


pip:
name: Release to PyPI
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: '3.7'
- name: Setup environment
run: |
sudo apt update
sudo apt install ruby
sudo gem install ronn
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine skyfield numpy tabulate Babel requests
- name: Build and publish
env:
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
POEDITOR_API_ACCESS: ${{ secrets.POEDITOR_API_ACCESS }}
POEDITOR_PROJECT_ID: 306433
run: |
make POEDITOR_API_ACCESS="${POEDITOR_API_ACCESS}" POEDITOR_PROJECT_ID="306433" build
twine upload dist/*


+ 46
- 0
.github/workflows/stale.yml View File

@@ -0,0 +1,46 @@
name: Stale

on:
schedule:
- cron: '0 12 * * *'

jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
language: ['python']

steps:
- name: Close Stale Issues
uses: actions/stale@v3
with:
start-date: 2021-02-01

days-before-stale: 60
days-before-issue-close: 7
days-before-pr-close: 14

stale-label: stale
close-issue-label: wontfix
close-pr-label: wontmerge

exempt-issue-label: 'confirmed,enhancement'
exempt-pr-label: 'on hold'

stale-issue-message: >
This issue has not been active since a lot of time. If you think it is still valid, feel free to reply with a simple comment.
Without any update, I will close it in 7 days.
stale-pr-message: >
This pull request has not been active since a lot of time. If you're still working on it, please reply with a simple comment.
Without any update, I will close it in 14 days.

close-issue-message: >
Closing this issue.
If you think it should be considered, feel free to exhume it.
close-pr-message: >
Closing this PR, since it has not got activity for a while.
If you're still working on it, feel free to reopen it.

+ 77
- 0
.github/workflows/unit-tests.yml View File

@@ -0,0 +1,77 @@
name: Unit tests

on:
push:
branches: [master, features]
pull_request:
branches: [master, features]

jobs:
legacy-unit-tests:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-18.04
- ubuntu-20.04
- macos-10.15
- macos-11.0
python-version:
- '3.7'
- '3.8'
- '3.9'

name: Legacy unit tests (Python ${{ matrix.python-version }} on ${{ matrix.os }})
steps:
- uses: actions/checkout@v1
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
pip install --upgrade pip pipenv
pipenv sync -d
- name: Unit tests
env:
COVERALLS_PRO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
make test
pipenv run coveralls --service=github

unit-tests:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-18.04
- ubuntu-20.04
- macos-10.15
- macos-11.0
python-version:
- '3.7'
- '3.8'
- '3.9'
- '3.10'

name: Unit tests (Python ${{ matrix.python-version }} on ${{ matrix.os }})
steps:
- uses: actions/checkout@v1
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
pip install --upgrade pip pipenv
pipenv sync -d
- name: Unit tests
env:
COVERALLS_PRO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
make test
pipenv run coveralls --service=github

+ 2
- 0
.gitignore View File

@@ -0,0 +1,2 @@
__pycache__
.coverage

+ 50
- 0
Makefile View File

@@ -0,0 +1,50 @@
.PHONY: test
tests: legacy-tests
python3 tests.py

legacy-tests:
unset KOSMORRO_LATITUDE; \
unset KOSMORRO_LONGITUDE; \
unset KOSMORRO_TIMEZONE; \
LANG=C pipenv run python3 -m coverage run -m unittest tests

.PHONY: build
build:
python3 setup.py sdist bdist_wheel

env:
@if [[ "$$RELEASE_NUMBER" == "" ]]; \
then echo "Missing environment variable: RELEASE_NUMBER."; \
echo 'Example: export RELEASE_NUMBER="1.0.0" (without the leading "v")'; \
exit 1; \
fi

release: env
@echo -e "\e[1mCreating release with version number \e[36m$$RELEASE_NUMBER\e[0m"
@echo

sed "s/^VERSION =.*/VERSION = '$$RELEASE_NUMBER'/g" kosmorrolib/version.py > version.py
mv version.py kosmorrolib/version.py

pipenv run python setup.py extract_messages --output-file=kosmorrolib/locales/messages.pot > /dev/null

conventional-changelog -p angular -i CHANGELOG.md -s
sed "0,/\\[\\]/s/\\[\\]/[v$$RELEASE_NUMBER]/g" CHANGELOG.md > /tmp/CHANGELOG.md
sed -e "s/...v)/...v$$RELEASE_NUMBER)/" /tmp/CHANGELOG.md > CHANGELOG.md
rm /tmp/CHANGELOG.md

@echo
@echo -e "\e[1mRelease \e[36m$$RELEASE_NUMBER\e[39m is ready to commit."
@echo -e "Please review the changes, then invoke \e[33mmake finish-release\e[39m."

finish-release: env
git add CHANGELOG.md kosmorrolib/version.py kosmorrolib/locales/messages.pot
git commit -m "build: bump version $$RELEASE_NUMBER"
git tag "v$$RELEASE_NUMBER"
git checkout features
git merge master
git checkout master

@echo
@echo -e "\e[1mVersion \e[36m$$RELEASE_NUMBER\e[39m successfully tagged!"
@echo -e "Invoke \e[33mgit push origin master features v$$RELEASE_NUMBER\e[39m to finish."

+ 1
- 0
Pipfile View File

@@ -9,6 +9,7 @@ pylint = "*"
babel = "*"
unittest-data-provider = "*"
coveralls = "*"
parameterized = "*"

[packages]
skyfield = ">=1.32.0,<2.0.0"


+ 105
- 90
Pipfile.lock View File

@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "05fc0ad542c6b81f02f9f1d6c4dbf8d2743ab07678c5c42aa3f7739c9aee7e36"
"sha256": "6b2c66b95f3dd68b2c892979187a16d4e60114c973470258e2cf0c091bf75b8c"
},
"pipfile-spec": 6,
"requires": {
@@ -69,39 +69,43 @@
},
"sgp4": {
"hashes": [
"sha256:0864ba1062418b1b3e23e38e90032dd2c6be1f09b66c5026a18f8171548720a9",
"sha256:1601f590950cd34ffc54c8c2811a228632d394c1e28a74054373638f7ead4801",
"sha256:2a75446b7299217f7e66002677226dab4e41b1ad62ce7fb238c0947071655899",
"sha256:2ad7a1c6dde04591a847c85397151e2adb458d889838a9e10177055bf373ec4a",
"sha256:2c21fc1f47882136883390497f92afd387d79c35f23a534b652ae44e02da0518",
"sha256:318309f4efa05361a64498ec0ac8e42a288439efe9cce6f823366c792d645e5c",
"sha256:39acc3f6a5efb9ccf76e2d3fbe4b56c9c0de10db0d5d4cfdf421b0969bbaa1e6",
"sha256:41bcb23f9fe020fa41d1729eebdff97144a6c884260ce50065e9201c45a989f8",
"sha256:71db20e277b639c05287302521e7c56fd9f77d081bb7a5f251294c18af188e43",
"sha256:7ea354472687dd54a40c0199238e6d22e4b86ab4d5eb356353be8559816f2754",
"sha256:89b42139eefd741724b6e41b80510cdbd76b0bda8f85d6cb37564051d119c384",
"sha256:93edb356869cd0c4c8b715523d26555c69bf81cebad23e5a31abdd5623e8819b",
"sha256:967ac911e1ffbd795df97e89c17f0c07fb2c782ae16f02b2bed2f9ad834cc7f9",
"sha256:b59509b488c0674c29806c181238a4d4868797122fb8e6681f7a3e5540a25403",
"sha256:c76a8db1df422a8473a680fcfb3c6b4cfa0318cf0e7fac9ea1b898f898139b8f",
"sha256:d33c185606eeeb7067ab3626eccdfdc4ea74346093fae646541ce8998c861540",
"sha256:de3ddc1a8a01a8b9f67008d2da85376d59aebac464a54477e11f459119de5308",
"sha256:df87ca4b6eac69b7ee2a6c0f7a3a29d9eda9785e21767e320d768f14170dd693",
"sha256:e303c82a3fc51a73cf0f69ee3215b25c299d84fb766e522a71136ad6f9d3a6c0",
"sha256:e576d9f4721d6380d6a7b9a9ca4dbc863ba9bd6f9242b4df12c0f68b50282f45",
"sha256:f45d0a205fb18919ff83ca449d483e6306721365d5ea52d63f86d91b6ca967c0",
"sha256:f5e6787d59683bfa5c9e1b88210d7bafc36b2fd8799438f30e1effa7da76764c",
"sha256:f7fc5b55497d79fe638fe203bc634332cea3f466d3f08910a956f97477cdecbb",
"sha256:fec4b597c4cc3dd330c9fd049c2d88ccea16aac474a57343082fa17fe1f84a05"
"sha256:0bcc2e078d04a32f0db1278ecf434b85d51682ab0d6144490940f8a7479305c9",
"sha256:15745e778634c7aea8a7d53f0108562ee80d3f9f4e2812ab1884b20f5fb1f995",
"sha256:19cd0d8e2c0826819bd8e46ffcf7866d137078b4110603c644a9eb3427347fe6",
"sha256:2cb573d4831db7ebfcd80442ba72cd3cbcae99d33bcc8ac298186bb358515cad",
"sha256:465dc1ef603aac17f59a1b00716c1f0187b90eaf88ce14ff6b19a40c7dd4ad97",
"sha256:6a7b9c109664284df3914e71bc9f773eda574d920763de5aac882e4e02002730",
"sha256:786b8e674d23c9efa634b782dc9650970e8662c92bc7ba457296fad84afaf34a",
"sha256:7b638875f7072926e57145537e831128a9bc6fed54c52fac8f5248fb775acc3e",
"sha256:802db53c0bb3caf58f69e38fbb04d7648c98ec4b34e17b4c3e9f81308352a9e1",
"sha256:850e16475a13cb11ec12c69c9b91d03e8f61461b083d9c6232d6119c2777a13f",
"sha256:85fb39c28741270e1552bc90269e1d73d65eb1383696848100dd991622a87bf7",
"sha256:8777dc09d027b4bd74675c91cf2284d79f800e11a22d0e18acca1611c49ae955",
"sha256:968760092038672e6e0686b581090016d491bb373a41416d2898f334bfa831e8",
"sha256:96b8359c520e0e66d6d9ec0d775c948401887b8b60ee0775d3b6ad465f13ba6a",
"sha256:9a097c1f7f777bd3eb36578cc195253053794396e34e34d67e7e2c7fb6960fda",
"sha256:9e6b0a476a9481aec19a23d69292b0009a465962decc15d22407a99aa4ad306a",
"sha256:a427bb73931d91dcc5e8b8ca796636b862f172c471ebc000e43eed6d84e2ee72",
"sha256:ae4d2401eff33a31737ec15a947a97bebe784701e064bb1d3096e05b068ca5b8",
"sha256:b110b2e4cb9223913e48e1f1ed5783d52a29e97556fa89dfdef721d23d42b134",
"sha256:bc17cc051246e21b0e63a536d236ddec6e27761107c7c3acfb6cdfe6c61627d8",
"sha256:bc443f34a0a3d6c3b02701403c0cffc9af4a3e864f41168cd0fc6b416e27ff58",
"sha256:c13f98a9227fb5a242c9ea17bcc701e220deb75c576d240581107d4e9d20ce80",
"sha256:c3a17700f19c881cb816bc7998ccb32e07ad5dc1672affff90324e09f3262025",
"sha256:c600da1a26257b733df9de5e8a916f06160b21f819f073cd56cbe7f3be709877",
"sha256:cb07c686b2f5552f8048ad3cace371dac1e1a530fb1ce20031d1ef46854793c1",
"sha256:cff9b03cf770753522face8be7fec52d4ba9eee0fe9d73d324fa0724343a97a5",
"sha256:d31cd0347ddd3bbeee2c47867f0c8a8f9ed0d94815f902aa62aab676c740526b",
"sha256:dafc9bf8d52d13d82490b27b1d93a7189e408e1b7b83a838db4f39b21718053e"
],
"version": "==2.17"
"version": "==2.18"
},
"six": {
"hashes": [
"sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
"sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.15.0"
},
"skyfield": {
@@ -115,11 +119,11 @@
"develop": {
"astroid": {
"hashes": [
"sha256:87ae7f2398b8a0ae5638ddecf9987f081b756e0e9fc071aeebdca525671fc4dc",
"sha256:b31c92f545517dcc452f284bc9c044050862fbe6d93d2b3de4a215a6b384bf0d"
"sha256:21d735aab248253531bb0f1e1e6d068f0ee23533e18ae8a6171ff892b98297cf",
"sha256:cfc35498ee64017be059ceffab0a25bedf7548ab76f2bea691c5565896e7128d"
],
"markers": "python_version >= '3.6'",
"version": "==2.5.0"
"version": "==2.5.1"
},
"babel": {
"hashes": [
@@ -146,66 +150,69 @@
},
"coverage": {
"hashes": [
"sha256:03ed2a641e412e42cc35c244508cf186015c217f0e4d496bf6d7078ebe837ae7",
"sha256:04b14e45d6a8e159c9767ae57ecb34563ad93440fc1b26516a89ceb5b33c1ad5",
"sha256:0cdde51bfcf6b6bd862ee9be324521ec619b20590787d1655d005c3fb175005f",
"sha256:0f48fc7dc82ee14aeaedb986e175a429d24129b7eada1b7e94a864e4f0644dde",
"sha256:107d327071061fd4f4a2587d14c389a27e4e5c93c7cba5f1f59987181903902f",
"sha256:1375bb8b88cb050a2d4e0da901001347a44302aeadb8ceb4b6e5aa373b8ea68f",
"sha256:14a9f1887591684fb59fdba8feef7123a0da2424b0652e1b58dd5b9a7bb1188c",
"sha256:16baa799ec09cc0dcb43a10680573269d407c159325972dd7114ee7649e56c66",
"sha256:1b811662ecf72eb2d08872731636aee6559cae21862c36f74703be727b45df90",
"sha256:1ccae21a076d3d5f471700f6d30eb486da1626c380b23c70ae32ab823e453337",
"sha256:2f2cf7a42d4b7654c9a67b9d091ec24374f7c58794858bff632a2039cb15984d",
"sha256:322549b880b2d746a7672bf6ff9ed3f895e9c9f108b714e7360292aa5c5d7cf4",
"sha256:32ab83016c24c5cf3db2943286b85b0a172dae08c58d0f53875235219b676409",
"sha256:3fe50f1cac369b02d34ad904dfe0771acc483f82a1b54c5e93632916ba847b37",
"sha256:4a780807e80479f281d47ee4af2eb2df3e4ccf4723484f77da0bb49d027e40a1",
"sha256:4a8eb7785bd23565b542b01fb39115a975fefb4a82f23d407503eee2c0106247",
"sha256:5bee3970617b3d74759b2d2df2f6a327d372f9732f9ccbf03fa591b5f7581e39",
"sha256:60a3307a84ec60578accd35d7f0c71a3a971430ed7eca6567399d2b50ef37b8c",
"sha256:6625e52b6f346a283c3d563d1fd8bae8956daafc64bb5bbd2b8f8a07608e3994",
"sha256:66a5aae8233d766a877c5ef293ec5ab9520929c2578fd2069308a98b7374ea8c",
"sha256:68fb816a5dd901c6aff352ce49e2a0ffadacdf9b6fae282a69e7a16a02dad5fb",
"sha256:6b588b5cf51dc0fd1c9e19f622457cc74b7d26fe295432e434525f1c0fae02bc",
"sha256:6c4d7165a4e8f41eca6b990c12ee7f44fef3932fac48ca32cecb3a1b2223c21f",
"sha256:6d2e262e5e8da6fa56e774fb8e2643417351427604c2b177f8e8c5f75fc928ca",
"sha256:6d9c88b787638a451f41f97446a1c9fd416e669b4d9717ae4615bd29de1ac135",
"sha256:755c56beeacac6a24c8e1074f89f34f4373abce8b662470d3aa719ae304931f3",
"sha256:7e40d3f8eb472c1509b12ac2a7e24158ec352fc8567b77ab02c0db053927e339",
"sha256:812eaf4939ef2284d29653bcfee9665f11f013724f07258928f849a2306ea9f9",
"sha256:84df004223fd0550d0ea7a37882e5c889f3c6d45535c639ce9802293b39cd5c9",
"sha256:859f0add98707b182b4867359e12bde806b82483fb12a9ae868a77880fc3b7af",
"sha256:87c4b38288f71acd2106f5d94f575bc2136ea2887fdb5dfe18003c881fa6b370",
"sha256:89fc12c6371bf963809abc46cced4a01ca4f99cba17be5e7d416ed7ef1245d19",
"sha256:9564ac7eb1652c3701ac691ca72934dd3009997c81266807aef924012df2f4b3",
"sha256:9754a5c265f991317de2bac0c70a746efc2b695cf4d49f5d2cddeac36544fb44",
"sha256:a565f48c4aae72d1d3d3f8e8fb7218f5609c964e9c6f68604608e5958b9c60c3",
"sha256:a636160680c6e526b84f85d304e2f0bb4e94f8284dd765a1911de9a40450b10a",
"sha256:a839e25f07e428a87d17d857d9935dd743130e77ff46524abb992b962eb2076c",
"sha256:b62046592b44263fa7570f1117d372ae3f310222af1fc1407416f037fb3af21b",
"sha256:b7f7421841f8db443855d2854e25914a79a1ff48ae92f70d0a5c2f8907ab98c9",
"sha256:ba7ca81b6d60a9f7a0b4b4e175dcc38e8fef4992673d9d6e6879fd6de00dd9b8",
"sha256:bb32ca14b4d04e172c541c69eec5f385f9a075b38fb22d765d8b0ce3af3a0c22",
"sha256:c0ff1c1b4d13e2240821ef23c1efb1f009207cb3f56e16986f713c2b0e7cd37f",
"sha256:c669b440ce46ae3abe9b2d44a913b5fd86bb19eb14a8701e88e3918902ecd345",
"sha256:c67734cff78383a1f23ceba3b3239c7deefc62ac2b05fa6a47bcd565771e5880",
"sha256:c6809ebcbf6c1049002b9ac09c127ae43929042ec1f1dbd8bb1615f7cd9f70a0",
"sha256:cd601187476c6bed26a0398353212684c427e10a903aeafa6da40c63309d438b",
"sha256:ebfa374067af240d079ef97b8064478f3bf71038b78b017eb6ec93ede1b6bcec",
"sha256:fbb17c0d0822684b7d6c09915677a32319f16ff1115df5ec05bdcaaee40b35f3",
"sha256:fff1f3a586246110f34dc762098b5afd2de88de507559e63553d7da643053786"
"sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c",
"sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6",
"sha256:040af6c32813fa3eae5305d53f18875bedd079960822ef8ec067a66dd8afcd45",
"sha256:06191eb60f8d8a5bc046f3799f8a07a2d7aefb9504b0209aff0b47298333302a",
"sha256:13034c4409db851670bc9acd836243aeee299949bd5673e11844befcb0149f03",
"sha256:13c4ee887eca0f4c5a247b75398d4114c37882658300e153113dafb1d76de529",
"sha256:184a47bbe0aa6400ed2d41d8e9ed868b8205046518c52464fde713ea06e3a74a",
"sha256:18ba8bbede96a2c3dde7b868de9dcbd55670690af0988713f0603f037848418a",
"sha256:1aa846f56c3d49205c952d8318e76ccc2ae23303351d9270ab220004c580cfe2",
"sha256:217658ec7187497e3f3ebd901afdca1af062b42cfe3e0dafea4cced3983739f6",
"sha256:24d4a7de75446be83244eabbff746d66b9240ae020ced65d060815fac3423759",
"sha256:2910f4d36a6a9b4214bb7038d537f015346f413a975d57ca6b43bf23d6563b53",
"sha256:2949cad1c5208b8298d5686d5a85b66aae46d73eec2c3e08c817dd3513e5848a",
"sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4",
"sha256:2cafbbb3af0733db200c9b5f798d18953b1a304d3f86a938367de1567f4b5bff",
"sha256:2e0d881ad471768bf6e6c2bf905d183543f10098e3b3640fc029509530091502",
"sha256:30c77c1dc9f253283e34c27935fded5015f7d1abe83bc7821680ac444eaf7793",
"sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb",
"sha256:372da284cfd642d8e08ef606917846fa2ee350f64994bebfbd3afb0040436905",
"sha256:41179b8a845742d1eb60449bdb2992196e211341818565abded11cfa90efb821",
"sha256:44d654437b8ddd9eee7d1eaee28b7219bec228520ff809af170488fd2fed3e2b",
"sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81",
"sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0",
"sha256:52596d3d0e8bdf3af43db3e9ba8dcdaac724ba7b5ca3f6358529d56f7a166f8b",
"sha256:53194af30d5bad77fcba80e23a1441c71abfb3e01192034f8246e0d8f99528f3",
"sha256:5fec2d43a2cc6965edc0bb9e83e1e4b557f76f843a77a2496cbe719583ce8184",
"sha256:6c90e11318f0d3c436a42409f2749ee1a115cd8b067d7f14c148f1ce5574d701",
"sha256:74d881fc777ebb11c63736622b60cb9e4aee5cace591ce274fb69e582a12a61a",
"sha256:7501140f755b725495941b43347ba8a2777407fc7f250d4f5a7d2a1050ba8e82",
"sha256:796c9c3c79747146ebd278dbe1e5c5c05dd6b10cc3bcb8389dfdf844f3ead638",
"sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5",
"sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083",
"sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6",
"sha256:900fbf7759501bc7807fd6638c947d7a831fc9fdf742dc10f02956ff7220fa90",
"sha256:92b017ce34b68a7d67bd6d117e6d443a9bf63a2ecf8567bb3d8c6c7bc5014465",
"sha256:970284a88b99673ccb2e4e334cfb38a10aab7cd44f7457564d11898a74b62d0a",
"sha256:972c85d205b51e30e59525694670de6a8a89691186012535f9d7dbaa230e42c3",
"sha256:9a1ef3b66e38ef8618ce5fdc7bea3d9f45f3624e2a66295eea5e57966c85909e",
"sha256:af0e781009aaf59e25c5a678122391cb0f345ac0ec272c7961dc5455e1c40066",
"sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf",
"sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b",
"sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae",
"sha256:c2723d347ab06e7ddad1a58b2a821218239249a9e4365eaff6649d31180c1669",
"sha256:d1f8bf7b90ba55699b3a5e44930e93ff0189aa27186e96071fac7dd0d06a1873",
"sha256:d1f9ce122f83b2305592c11d64f181b87153fc2c2bbd3bb4a3dde8303cfb1a6b",
"sha256:d314ed732c25d29775e84a960c3c60808b682c08d86602ec2c3008e1202e3bb6",
"sha256:d636598c8305e1f90b439dbf4f66437de4a5e3c31fdf47ad29542478c8508bbb",
"sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160",
"sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c",
"sha256:f030f8873312a16414c0d8e1a1ddff2d3235655a2174e3648b4fa66b3f2f1079",
"sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d",
"sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'",
"version": "==5.4"
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4.0'",
"version": "==5.5"
},
"coveralls": {
"hashes": [
"sha256:5399c0565ab822a70a477f7031f6c88a9dd196b3de2877b3facb43b51bd13434",
"sha256:f8384968c57dee4b7133ae701ecdad88e85e30597d496dcba0d7fbb470dca41f"
"sha256:7bd173b3425733661ba3063c88f180127cc2b20e9740686f86d2622b31b41385",
"sha256:cbb942ae5ef3d2b55388cb5b43e93a269544911535f1e750e1c656aef019ce60"
],
"index": "pypi",
"version": "==3.0.0"
"version": "==3.0.1"
},
"docopt": {
"hashes": [
@@ -226,7 +233,7 @@
"sha256:c729845434366216d320e936b8ad6f9d681aab72dc7cbc2d51bedc3582f3ad1e",
"sha256:fff4f0c04e1825522ce6949973e83110a6e907750cd92d128b0d14aaaadbffdc"
],
"markers": "python_version >= '3.6' and python_version < '4'",
"markers": "python_version >= '3.6' and python_version < '4.0'",
"version": "==5.7.0"
},
"lazy-object-proxy": {
@@ -266,13 +273,21 @@
],
"version": "==0.6.1"
},
"parameterized": {
"hashes": [
"sha256:41bbff37d6186430f77f900d777e5bb6a24928a1c46fb1de692f8b52b8833b5c",
"sha256:9cbb0b69a03e8695d68b3399a8a5825200976536fe1cb79db60ed6a4c8c9efe9"
],
"index": "pypi",
"version": "==0.8.1"
},
"pylint": {
"hashes": [
"sha256:81ce108f6342421169ea039ff1f528208c99d2e5a9c4ca95cfc5291be6dfd982",
"sha256:a251b238db462b71d25948f940568bb5b3ae0e37dbaa05e10523f54f83e6cc7e"
"sha256:0e21d3b80b96740909d77206d741aa3ce0b06b41be375d92e1f3244a274c1f8a",
"sha256:d09b0b07ba06bcdff463958f53f23df25e740ecd81895f7d2699ec04bbd8dc3b"
],
"index": "pypi",
"version": "==2.7.1"
"version": "==2.7.2"
},
"pylintfileheader": {
"hashes": [
@@ -302,7 +317,7 @@
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
"sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
],
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'",
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==0.10.2"
},
"unittest-data-provider": {
@@ -317,7 +332,7 @@
"sha256:1b465e494e3e0d8939b50680403e3aedaa2bc434b7d5af64dfd3c958d7f5ae80",
"sha256:de3eedaad74a2683334e282005cd8d7f22f4d55fa690a2a1020a416cb0a47e73"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'",
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4.0'",
"version": "==1.26.3"
},
"wrapt": {


+ 3
- 3
kosmorrolib/ephemerides.py View File

@@ -33,7 +33,7 @@ from .exceptions import OutOfRangeDateError
RISEN_ANGLE = -0.8333


def _get_skyfield_to_moon_phase(times: [Time], vals: [int], now: Time) -> Union[MoonPhaseType, None]:
def _get_skyfield_to_moon_phase(times: [Time], vals: [int], now: Time) -> Union[MoonPhase, None]:
tomorrow = get_timescale().utc(now.utc_datetime().year, now.utc_datetime().month, now.utc_datetime().day + 1)

phases = list(MoonPhaseType)
@@ -65,12 +65,12 @@ def _get_skyfield_to_moon_phase(times: [Time], vals: [int], now: Time) -> Union[
next_phase_time = times[j]
break

return MoonPhaseType(current_phase,
return MoonPhase(current_phase,
current_phase_time.utc_datetime() if current_phase_time is not None else None,
next_phase_time.utc_datetime() if next_phase_time is not None else None)


def get_moon_phase(compute_date: datetime.date, timezone: int = 0) -> MoonPhaseType:
def get_moon_phase(compute_date: datetime.date, timezone: int = 0) -> MoonPhase:
earth = get_skf_objects()['earth']
moon = get_skf_objects()['moon']
sun = get_skf_objects()['sun']


+ 1
- 1
kosmorrolib/events.py View File

@@ -181,7 +181,7 @@ def get_events(date: date_type, timezone: int = 0) -> [Event]:
"""Calculate and return a list of events for the given date, adjusted to the given timezone if any.

Find events that happen on April 4th, 2020 (show hours in UTC):
>>> get_events(date_type(2020, 4, 4))
[<Event type=CONJUNCTION objects=[<Object type=planet name=Mercury />, <Object type=planet name=Neptune />] start=2020-04-04 01:14:39.063308+00:00 end=None details=None />]



+ 1
- 1
tests.py View File

@@ -3,4 +3,4 @@ import doctest
from kosmorrolib import *

for module in [events]:
doctest.testmod(module)
doctest.testmod(module, verbose=True)

+ 6
- 0
tests/__init__.py View File

@@ -0,0 +1,6 @@
from .core import *
from .data import *
from .ephemerides import *
from .events import *
from .testutils import *
from .dateutil import *

+ 39
- 0
tests/core.py View File

@@ -0,0 +1,39 @@
import unittest

import os
import kosmorrolib.core as core

from datetime import date
from dateutil.relativedelta import relativedelta


class CoreTestCase(unittest.TestCase):
def test_flatten_list(self):
self.assertEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], core.flatten_list([0, 1, 2, [3, 4, [5, 6], 7], 8, [9]]))

def test_get_env(self):
self.assertEqual(0, len(core.get_env()))

os.environ['SOME_RANDOM_VAR'] = 'an awesome value'
self.assertEqual(0, len(core.get_env()))

os.environ['KOSMORRO_GREAT_VARIABLE'] = 'value'
env = core.get_env()
self.assertEqual(1, len(env))
self.assertEqual('value', env.great_variable)

os.environ['KOSMORRO_ANOTHER_VARIABLE'] = 'another value'
env = core.get_env()
self.assertEqual(2, len(env))
self.assertEqual('value', env.great_variable)
self.assertEqual('another value', env.another_variable)

self.assertEqual("{'great_variable': 'value', 'another_variable': 'another value'}", str(env))

def test_date_arg_parsing(self):
self.assertEqual(core.get_date("+1y 2m3d"), date.today() + relativedelta(years=1, months=2, days=3))
self.assertEqual(core.get_date("-1y2d"), date.today() - relativedelta(years=1, days=2))
self.assertEqual(core.get_date("1111-11-13"), date(1111, 11, 13))

if __name__ == '__main__':
unittest.main()

+ 17
- 0
tests/data.py View File

@@ -0,0 +1,17 @@
import unittest

from kosmorrolib import data, core


class DataTestCase(unittest.TestCase):
def test_object_radius_must_be_set_to_get_apparent_radius(self):
o = data.Planet('Saturn', 'SATURN')

with self.assertRaises(ValueError) as context:
o.get_apparent_radius(core.get_timescale().now(), core.get_skf_objects()['earth'])

self.assertEqual(('Missing radius for Saturn object',), context.exception.args)


if __name__ == '__main__':
unittest.main()

+ 24
- 0
tests/dateutil.py View File

@@ -0,0 +1,24 @@
import unittest

from kosmorrolib import dateutil
from datetime import datetime


class DateUtilTestCase(unittest.TestCase):
def test_translate_to_timezone(self):
date = dateutil.translate_to_timezone(datetime(2020, 6, 9, 4), to_tz=-2)
self.assertEqual(2, date.hour)

date = dateutil.translate_to_timezone(datetime(2020, 6, 9, 0), to_tz=2)
self.assertEqual(2, date.hour)

date = dateutil.translate_to_timezone(datetime(2020, 6, 9, 8), to_tz=2, from_tz=6)
self.assertEqual(4, date.hour)

date = dateutil.translate_to_timezone(datetime(2020, 6, 9, 1), to_tz=0, from_tz=2)
self.assertEqual(8, date.day)
self.assertEqual(23, date.hour)


if __name__ == '__main__':
unittest.main()

+ 124
- 0
tests/ephemerides.py View File

@@ -0,0 +1,124 @@
import unittest

from kosmorrolib.enum import MoonPhaseType

from .testutils import expect_assertions
from kosmorrolib import ephemerides
from kosmorrolib.data import EARTH, Position, MoonPhase
from datetime import date
from kosmorrolib.exceptions import OutOfRangeDateError


class EphemeridesTestCase(unittest.TestCase):
def test_get_ephemerides_for_aster_returns_correct_hours(self):
position = Position(0, 0, EARTH)
eph = ephemerides.get_ephemerides(date=date(2019, 11, 18),
position=position)

@expect_assertions(self.assertRegex, num=3)
def do_assertions(assert_regex):
for ephemeris in eph:
if ephemeris.object.skyfield_name == 'SUN':
assert_regex(ephemeris.rise_time.isoformat(), '^2019-11-18T05:41:')
assert_regex(ephemeris.culmination_time.isoformat(), '^2019-11-18T11:45:')
assert_regex(ephemeris.set_time.isoformat(), '^2019-11-18T17:48:')
break

do_assertions()

###################################################################################################################
### MOON PHASE TESTS ###
###################################################################################################################

def test_moon_phase_new_moon(self):
phase = ephemerides.get_moon_phase(date(2019, 11, 25))
self.assertEqual(MoonPhaseType.WANING_CRESCENT, phase.phase_type)
self.assertIsNone(phase.time)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-26T')

phase = ephemerides.get_moon_phase(date(2019, 11, 26))
self.assertEqual(MoonPhaseType.NEW_MOON, phase.phase_type)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-12-04T')

phase = ephemerides.get_moon_phase(date(2019, 11, 27))
self.assertEqual(MoonPhaseType.WAXING_CRESCENT, phase.phase_type)
self.assertIsNone(phase.time)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-12-04T')

def test_moon_phase_first_crescent(self):
phase = ephemerides.get_moon_phase(date(2019, 11, 3))
self.assertEqual(MoonPhaseType.WAXING_CRESCENT, phase.phase_type)
self.assertIsNone(phase.time)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-04T')

phase = ephemerides.get_moon_phase(date(2019, 11, 4))
self.assertEqual(MoonPhaseType.FIRST_QUARTER, phase.phase_type)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-12T')

phase = ephemerides.get_moon_phase(date(2019, 11, 5))
self.assertEqual(MoonPhaseType.WAXING_GIBBOUS, phase.phase_type)
self.assertIsNone(phase.time)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-12T')

def test_moon_phase_full_moon(self):
phase = ephemerides.get_moon_phase(date(2019, 11, 11))
self.assertEqual(MoonPhaseType.WAXING_GIBBOUS, phase.phase_type)
self.assertIsNone(phase.time)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-12T')

phase = ephemerides.get_moon_phase(date(2019, 11, 12))
self.assertEqual(MoonPhaseType.FULL_MOON, phase.phase_type)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-19T')

phase = ephemerides.get_moon_phase(date(2019, 11, 13))
self.assertEqual(MoonPhaseType.WANING_GIBBOUS, phase.phase_type)
self.assertIsNone(phase.time)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-19T')

def test_moon_phase_last_quarter(self):
phase = ephemerides.get_moon_phase(date(2019, 11, 18))
self.assertEqual(MoonPhaseType.WANING_GIBBOUS, phase.phase_type)
self.assertIsNone(phase.time)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-19T')

phase = ephemerides.get_moon_phase(date(2019, 11, 19))
self.assertEqual(MoonPhaseType.LAST_QUARTER, phase.phase_type)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-26T')

phase = ephemerides.get_moon_phase(date(2019, 11, 20))
self.assertEqual(MoonPhaseType.WANING_CRESCENT, phase.phase_type)
self.assertIsNone(phase.time)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-26T')

def test_moon_phase_prediction(self):
phase = MoonPhase(MoonPhaseType.NEW_MOON, None, None)
self.assertEqual(MoonPhaseType.FIRST_QUARTER, phase.get_next_phase())
phase = MoonPhase(MoonPhaseType.WAXING_CRESCENT, None, None)
self.assertEqual(MoonPhaseType.FIRST_QUARTER, phase.get_next_phase())

phase = MoonPhase(MoonPhaseType.FIRST_QUARTER, None, None)
self.assertEqual(MoonPhaseType.FULL_MOON, phase.get_next_phase())
phase = MoonPhase(MoonPhaseType.WAXING_GIBBOUS, None, None)
self.assertEqual(MoonPhaseType.FULL_MOON, phase.get_next_phase())

phase = MoonPhase(MoonPhaseType.FULL_MOON, None, None)
self.assertEqual(MoonPhaseType.LAST_QUARTER, phase.get_next_phase())
phase = MoonPhase(MoonPhaseType.WANING_GIBBOUS, None, None)
self.assertEqual(MoonPhaseType.LAST_QUARTER, phase.get_next_phase())

phase = MoonPhase(MoonPhaseType.LAST_QUARTER, None, None)
self.assertEqual(MoonPhaseType.NEW_MOON, phase.get_next_phase())
phase = MoonPhase(MoonPhaseType.WANING_CRESCENT, None, None)
self.assertEqual(MoonPhaseType.NEW_MOON, phase.get_next_phase())

def test_get_ephemerides_raises_exception_on_out_of_date_range(self):
with self.assertRaises(OutOfRangeDateError):
ephemerides.get_ephemerides(date(1789, 5, 5), Position(0, 0, EARTH))

def test_get_moon_phase_raises_exception_on_out_of_date_range(self):
with self.assertRaises(OutOfRangeDateError):
ephemerides.get_moon_phase(date(1789, 5, 5))


if __name__ == '__main__':
unittest.main()

+ 83
- 0
tests/events.py View File

@@ -0,0 +1,83 @@
import unittest

from datetime import date, datetime
from parameterized import parameterized

from kosmorrolib import events
from kosmorrolib.data import Event, ASTERS
from kosmorrolib.enum import EventType
from kosmorrolib.exceptions import OutOfRangeDateError

EXPECTED_EVENTS = [
(date(2020, 2, 7), []),

(date(2020, 10, 13), [Event(EventType.OPPOSITION, [ASTERS[4]], datetime(2020, 10, 13, 23, 25))]),

(date(2022, 12, 8),
[Event(EventType.CONJUNCTION, [ASTERS[1], ASTERS[4]], datetime(2022, 12, 8, 4, 18)),
Event(EventType.OPPOSITION, [ASTERS[4]], datetime(2022, 12, 8, 5, 41))]),

(date(2025, 1, 16), [Event(EventType.OPPOSITION, [ASTERS[4]], datetime(2025, 1, 16, 2, 38))]),

(date(2027, 2, 19), [Event(EventType.MOON_PERIGEE, [ASTERS[1]], datetime(2027, 2, 19, 7, 38)),
Event(EventType.OPPOSITION, [ASTERS[4]], datetime(2027, 2, 19, 15, 50))]),

(date(2020, 1, 2), [Event(EventType.MOON_APOGEE, [ASTERS[1]], datetime(2020, 1, 2, 1, 32)),
Event(EventType.CONJUNCTION, [ASTERS[2], ASTERS[5]],
datetime(2020, 1, 2, 16, 41))]),

(date(2020, 1, 12),
[Event(EventType.CONJUNCTION, [ASTERS[2], ASTERS[6]], datetime(2020, 1, 12, 9, 51)),
Event(EventType.CONJUNCTION, [ASTERS[2], ASTERS[9]], datetime(2020, 1, 12, 10, 13)),
Event(EventType.CONJUNCTION, [ASTERS[6], ASTERS[9]], datetime(2020, 1, 12, 16, 57))]),

(date(2020, 2, 10),
[Event(EventType.MAXIMAL_ELONGATION, [ASTERS[2]], datetime(2020, 2, 10, 13, 46), details='18.2°'),
Event(EventType.MOON_PERIGEE, [ASTERS[1]], datetime(2020, 2, 10, 20, 34))]),

(date(2020, 3, 24),
[Event(EventType.MAXIMAL_ELONGATION, [ASTERS[2]], datetime(2020, 3, 24, 1, 56), details='27.8°'),
Event(EventType.MOON_APOGEE, [ASTERS[1]], datetime(2020, 3, 24, 15, 39)),
Event(EventType.MAXIMAL_ELONGATION, [ASTERS[3]], datetime(2020, 3, 24, 21, 58),
details='46.1°')]),

(date(2005, 6, 16),
[Event(EventType.OCCULTATION, [ASTERS[1], ASTERS[5]], datetime(2005, 6, 16, 6, 31))]),

(date(2020, 4, 7), [Event(EventType.MOON_PERIGEE, [ASTERS[1]], datetime(2020, 4, 7, 18, 14))]),

(date(2020, 1, 29), [Event(EventType.MOON_APOGEE, [ASTERS[1]], datetime(2020, 1, 29, 21, 32))])
]


class EventTestCase(unittest.TestCase):
def setUp(self) -> None:
self.maxDiff = None

@parameterized.expand(EXPECTED_EVENTS)
def test_search_events(self, d: date, expected_events: [Event]):
actual_events = events.get_events(d)
self.assertEqual(len(expected_events), len(actual_events),
'Expected %d elements, got %d for date %s.\n%s' % (len(expected_events),
len(actual_events),
d.isoformat(),
actual_events))

for i, expected_event in enumerate(expected_events):
actual_event = actual_events[i]
# Remove unnecessary precision (seconds and microseconds)
actual_event.start_time = datetime(actual_event.start_time.year,
actual_event.start_time.month,
actual_event.start_time.day,
actual_event.start_time.hour,
actual_event.start_time.minute)

self.assertEqual(expected_event.__dict__, actual_event.__dict__)

def test_get_events_raises_exception_on_out_of_date_range(self):
with self.assertRaises(OutOfRangeDateError):
events.get_events(date(1789, 5, 5))


if __name__ == '__main__':
unittest.main()

+ 48
- 0
tests/testutils.py View File

@@ -0,0 +1,48 @@
import functools
from unittest import mock


def expect_assertions(assert_fun, num=1):
"""Asserts that an assertion function is called as expected.

This is very useful when the assertions are in loops.
To use it, create a nested function in the the tests function.
The nested function will receive as parameter the mocked assertion function to use in place of the original one.
Finally, run the nested function.

Example of use:

>>> # the function we tests:
>>> def my_sum_function(n, m):
>>> # some code here
>>> pass

>>> # The unit tests:
>>> def test_sum(self):
>>> @expect_assertions(self.assertEqual, num=10):
>>> def make_assertions(assert_equal):
>>> for i in range (-5, 5):
>>> for j in range(-5, 5):
>>> assert_equal(i + j, my_sum_function(i, j)
>>>
>>> make_assertions() # You don't need to give any parameter, the decorator does it for you.

:param assert_fun: the assertion function to tests
:param num: the number of times the assertion function is expected to be called
"""
assert_fun_mock = mock.Mock(side_effect=assert_fun)

def fun_decorator(fun):
@functools.wraps(fun)
def sniff_function():
fun(assert_fun_mock)

count = assert_fun_mock.call_count
if count != num:
raise AssertionError('Expected %d call(s) to function %s but called %d time(s).' % (num,
assert_fun.__name__,
count))

return sniff_function

return fun_decorator

Loading…
Cancel
Save