Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 27 additions & 10 deletions buienradar/buienradar_json.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"""Buienradar library to get parsed weather data from buienradar.nl."""
import json
import logging
from datetime import datetime # , timedelta
from datetime import datetime
from zoneinfo import ZoneInfo

import pytz
import requests
from vincenty import vincenty

Expand Down Expand Up @@ -67,7 +67,7 @@
# "2019-02-03T19:20:00",
__DATE_FORMAT = '%Y-%m-%dT%H:%M:%S'
__TIMEZONE = 'Europe/Amsterdam'
__PYTZ_TIMEZONE = pytz.timezone(__TIMEZONE)
__ZI_TIMEZONE = ZoneInfo(__TIMEZONE)

__ACTUAL = "actual"
__STATIONMEASUREMENTS = "stationmeasurements"
Expand Down Expand Up @@ -125,17 +125,34 @@ def __to_float1(val):
"""Convert val into float with 1 decimal."""
return __to_float(val, 1)

def __to_localdatetime(val: str | None) -> datetime | None:
"""
Convert an ISO-like timestamp string into a timezone-aware
datetime in Europe/Amsterdam.

Expected format:
YYYY-MM-DDTHH:MM:SS

Example:
"2019-02-03T19:20:00"

Args:
val: Timestamp string.

Returns:
Timezone-aware datetime in Europe/Amsterdam,
or None if parsing fails.
"""
if not isinstance(val, str) or not val:
return None

def __to_localdatetime(val):
"""Convert val into a local datetime for tz Europe/Amsterdam."""
try:
# "timestamp": "2019-02-03T19:20:00",
dt = datetime.strptime(val, __DATE_FORMAT)
dt = __PYTZ_TIMEZONE.localize(dt)
return dt
except (AttributeError, ValueError, TypeError):
naive_dt = datetime.strptime(val, __DATE_FORMAT)
except ValueError:
return None

# Attach timezone directly (zoneinfo handles DST correctly)
return naive_dt.replace(tzinfo=__ZI_TIMEZONE)

def __getBarFC(pressure):
"""Parse the pressure and return FC (numerical)."""
Expand Down
39 changes: 29 additions & 10 deletions buienradar/buienradar_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
import logging
from datetime import datetime, timedelta

import pytz
import requests
import xmltodict
from vincenty import vincenty
from zoneinfo import ZoneInfo

from buienradar.constants import (
ATTRIBUTION,
Expand Down Expand Up @@ -81,7 +81,7 @@
# buienradat date format: '07/26/2017 15:50:00'
__DATE_FORMAT = '%m/%d/%Y %H:%M:%S'
__TIMEZONE = 'Europe/Amsterdam'
__PYTZ_TIMEZONE = pytz.timezone(__TIMEZONE)
__ZI_TIMEZONE = ZoneInfo(__TIMEZONE)


def __to_int(val):
Expand Down Expand Up @@ -110,15 +110,34 @@ def __to_float1(val):
return __to_float(val, 1)


def __to_localdatetime(val):
"""Convert val into a local datetime for tz Europe/Amsterdam."""
def __to_localdatetime(val: str | None) -> datetime | None:
"""
Convert an ISO-like timestamp string into a timezone-aware
datetime in Europe/Amsterdam.

Expected format:
YYYY-MM-DDTHH:MM:SS

Example:
"2019-02-03T19:20:00"

Args:
val: Timestamp string.

Returns:
Timezone-aware datetime in Europe/Amsterdam,
or None if parsing fails.
"""
if not isinstance(val, str) or not val:
return None

try:
dt = datetime.strptime(val, __DATE_FORMAT)
dt = __PYTZ_TIMEZONE.localize(dt)
return dt
except (ValueError, TypeError):
naive_dt = datetime.strptime(val, __DATE_FORMAT)
except ValueError:
return None

# Attach timezone directly (zoneinfo handles DST correctly)
return naive_dt.replace(tzinfo=__ZI_TIMEZONE)

# Sensor types are defined like so:
# SENSOR_TYPES = { 'key': ['key in buienradar xml', conversion function], }
Expand Down Expand Up @@ -294,7 +313,7 @@ def __parse_ws_data(content, latitude=52.091579, longitude=5.119734):
return result


def __parse_precipfc_data(data, timeframe):
def __parse_precipfc_data(data, timeframe) -> dict[str, object]:
"""Parse the forecasted precipitation data."""
result = {AVERAGE: None, TOTAL: None, TIMEFRAME: None}

Expand Down Expand Up @@ -400,7 +419,7 @@ def __parse_fc_data(fc_data):
daysection = __BRDAYFC % daycnt
if daysection in fc_data:
tmpsect = fc_data[daysection]
fcdatetime = datetime.now(__PYTZ_TIMEZONE)
fcdatetime = datetime.now(__ZI_TIMEZONE)
fcdatetime = fcdatetime.replace(hour=12,
minute=0,
second=0,
Expand Down
128 changes: 30 additions & 98 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,110 +1,42 @@
"""Library and CLI tools for interacting with buienradar."""

import sys
from codecs import open
from os import path
from subprocess import check_output

from pathlib import Path
from setuptools import find_packages, setup

here = path.abspath(path.dirname(__file__))

if sys.version_info < (3, 4):
raise RuntimeError("This package requires at least Python 3.4")

# Get the long description from the README file
with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
long_description = f.read()


def version_from_git():
"""Acquire package version from current git tag."""
return check_output(['git', 'describe', '--tags', '--abbrev=0'],
universal_newlines=True)

BASE_DIR = Path(__file__).resolve().parent
LONG_DESCRIPTION = (BASE_DIR / "README.rst").read_text(encoding="utf-8")

setup(
name='buienradar',

version='1.0.9',

description=__doc__,
long_description_content_type='text/x-rst',
long_description=long_description,

# The project's main homepage.
url='https://github.com/mjj4791/python-buienradar',

# Author details
author='mjj4791',
author_email='',

# Choose your license
license='MIT',

# See https://pypi.python.org/pypi?%3Aaction=list_classifiers
name="buienradar",
version="1.0.9",
description="Library and CLI tools for interacting with buienradar.",
long_description=LONG_DESCRIPTION,
long_description_content_type="text/x-rst",
url="https://github.com/mjj4791/python-buienradar",
author="mjj4791",
license="MIT",
classifiers=[
# How mature is this project? Common values are
# 3 - Alpha
# 4 - Beta
# 5 - Production/Stable
'Development Status :: 5 - Production/Stable',

# Indicate who your project is intended for
'Intended Audience :: Developers',

# Pick your license as you wish (should match "license" above)
'License :: OSI Approved :: MIT License',

'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12'
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
],

keywords='buienradar weather',

packages=find_packages(exclude=['contrib', 'docs', 'tests']),

keywords="buienradar weather",
packages=find_packages(exclude=("contrib", "docs", "tests")),
python_requires=">=3.9",
install_requires=[
'docopt',
'pytz',
'requests',
'xmltodict',
'vincenty',
"tzdata; platform_system=='Windows'",
"docopt",
"requests",
"xmltodict",
"vincenty",
],

# # List additional groups of dependencies here (e.g. development
# # dependencies). You can install these using the following syntax,
# # for example:
# # $ pip install -e .[dev,test]
# extras_require={
# 'dev': ['check-manifest'],
# 'test': ['coverage'],
# },

# # If there are data files included in your packages that need to be
# # installed, specify them here. If using Python 2.6 or less, then these
# # have to be included in MANIFEST.in as well.
# package_data={
# 'sample': ['package_data.dat'],
# },

# # Although 'package_data' is the preferred approach, in some case you may
# # need to place data files outside of your packages. See:
# # http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files # noqa
# # In this case, 'data_file' will be installed into '<sys.prefix>/my_data'
# data_files=[('my_data', ['data/data_file'])],

# To provide executable scripts, use entry points in preference to the
# "scripts" keyword. Entry points provide cross-platform support and allow
# pip to create the appropriate form of executable for the target platform.
entry_points={
'console_scripts': [
'buienradar=buienradar.__main__:main',
"console_scripts": [
"buienradar=buienradar.__main__:main",
],
},
)