From d79c65cdd57322db9e73296a2acbf2721f69b5ed Mon Sep 17 00:00:00 2001 From: mygrexit <33792951+mygrexit@users.noreply.github.com> Date: Fri, 10 Nov 2023 13:39:08 +0100 Subject: [PATCH 01/11] Add localized formatting for multi-day event durations This commit introduces a feature to format the names of multi-day events using Arrow's localization. Event titles now include the event duration in days. --- inkycal/modules/inkycal_calendar.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/inkycal/modules/inkycal_calendar.py b/inkycal/modules/inkycal_calendar.py index 65012a1..68ccb26 100755 --- a/inkycal/modules/inkycal_calendar.py +++ b/inkycal/modules/inkycal_calendar.py @@ -355,7 +355,13 @@ class Calendar(inkycal_module): cursor = 0 for event in upcoming_events: if cursor < len(event_lines): - the_name = event['title'] + event_duration = (event['end'] - event['begin']).days + if event_duration > 1: + # Format the duration using Arrow's localization + days_translation = arrow.get().shift(days=event_duration).humanize(only_distance=True, locale=lang) + the_name = f"{event['title']} ({days_translation})" + else: + the_name = event['title'] the_date = event['begin'].format(self.date_format, locale=lang) the_time = event['begin'].format(self.time_format, locale=lang) # logger.debug(f"name:{the_name} date:{the_date} time:{the_time}") From 084a44a5e5ab9cf2d02a0bbbcf4b4875293aa07a Mon Sep 17 00:00:00 2001 From: Ace Date: Fri, 10 Nov 2023 14:49:42 +0100 Subject: [PATCH 02/11] Create pull_request_template.md --- .../pull_request_template.md | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE/pull_request_template.md diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md new file mode 100644 index 0000000..45a3586 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -0,0 +1,29 @@ +# Pull Request + +## Description +_Briefly describe the purpose of this pull request_ + +## Changes Made +_Describe the changes you made in this PR_ + +## Related Issues +_Reference any related issues here. Use the format "Fixes #" if this PR fixes an issue._ + +## How to Test +_Provide step-by-step instructions or commands on how to test your changes_ + +## Screenshots (if applicable) +_Include screenshots or GIFs that demonstrate the changes (if applicable)_ + +## Checklist +_Place an 'x' in the checkboxes that apply. +If you're unsure about any of them, don't hesitate to ask._ + +- [ ] I have read the [contribution guidelines](https://github.com/aceinnolab/Inkycal/blob/main/.github/CONTRIBUTING.md) +- [ ] My code follows the project's coding standards +- [ ] I have tested my changes +- [ ] I have updated the documentation +- [ ] My changes do not introduce new warnings or errors + +## Additional Notes +_Any additional information or context you want to provide_ From 2dc945ebee3b92208b4ac79aa5968f6462235a23 Mon Sep 17 00:00:00 2001 From: mygrexit <33792951+mygrexit@users.noreply.github.com> Date: Fri, 10 Nov 2023 14:57:47 +0100 Subject: [PATCH 03/11] Added support for multi-day events Improved event handling in calendar: Enhanced the calendar module to handle events spanning multiple days. --- inkycal/modules/inkycal_calendar.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/inkycal/modules/inkycal_calendar.py b/inkycal/modules/inkycal_calendar.py index 68ccb26..a6d3154 100755 --- a/inkycal/modules/inkycal_calendar.py +++ b/inkycal/modules/inkycal_calendar.py @@ -296,14 +296,27 @@ class Calendar(inkycal_module): month_events = parser.get_events(month_start, month_end, self.timezone) parser.sort() self.month_events = month_events + + # Initialize days_with_events as an empty list + days_with_events = [] - # find out on which days of this month events are taking place - days_with_events = [ - int(events['begin'].format('D')) for events in month_events - ] + # Handle multi-day events by adding all days between start and end + for event in month_events: + start_date = event['begin'].date() + end_date = event['end'].date() + + # Convert start and end dates to arrow objects with timezone + start = arrow.get(event['begin'].date(), tzinfo=self.timezone) + end = arrow.get(event['end'].date(), tzinfo=self.timezone) + + # Use arrow's range function for generating dates + for day in arrow.Arrow.range('day', start, end): + day_num = int(day.format('D')) # get day number using arrow's format method + if day_num not in days_with_events: + days_with_events.append(day_num) # remove duplicates (more than one event in a single day) - list(set(days_with_events)).sort() + days_with_events = sorted(set(days_with_events)) self._days_with_events = days_with_events # Draw a border with specified parameters around days with events From 41ea2632571ba70f6f7ccebf030b2b4266b23c2c Mon Sep 17 00:00:00 2001 From: Ace Date: Fri, 10 Nov 2023 15:06:15 +0100 Subject: [PATCH 04/11] Update CONTRIBUTING.md --- .github/CONTRIBUTING.md | 60 ++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index f9b084b..c4b9122 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,31 +1,49 @@ -# Inkycal Contribution Policy +# Contributing to Inkycal -Thanks for willing to contribute to Inkycal -We welcome all sort of contributions, for example: -* giving support via the Discord server -* submitting hotfixes for existing bugs -* giving ideas for new features -* financial contributions (while Inkycal is still dependent on them. These go towards new hardware, displays and a bit of coffee) +Welcome to Inkycal! We are excited that you are considering contributing to our project. Before you get started, please take a moment to read through our contribution guidelines. -# Third party modules -So you had a great idea for an inkycal-module? Awesome! In fact, there is already a repo sepcfifically created for that purpose: [inkycal-modules-template](https://github.com/aceisace/inkycal-modules-template). Just fork that repo, add your module and give me a shout via Discord, Github or Email. If it is really unique and convincing, chances are, if you agree, that it will be available as default module in a future release. Please do not attempt to have it merged straight into main. We try not to touch main except for new releases to keep things consistent, stable and easy-to-maintain. +## Code of Conduct -# Code contributions (PRs, hotfixes, Critical improvements) -So you found a bug in Inkycal and tested out a bugfix? Kudos! Please fork the Inkycal repo, add your changes in there and create a PR targeting main. For all other PRs, please target a different branch. +This project and everyone participating in it are governed by our [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report any unacceptable behavior. -Don't forget to add your name in the file `CONTRIBUTORS.md` of the corresponding branch. Thank You! +## How Can I Contribute? -# Submitting Issues +### Reporting Bugs -Please only submit reproducible issues with clear instructions on how to reproduce them. +Before submitting a bug report, check if the issue is already reported in the [Issues](https://github.com/aceinnolab/Inkycal/issues) section. If not, please open a new issue with a detailed description of the problem, including steps to reproduce it. -When you are submitting a new issue, please supply the following information: +### Suggesting Enhancements -### Release version -* are you using main or a different branch. In most cases, this is main +We welcome suggestions for new features or enhancements. Use the [Issues](https://github.com/aceinnolab/Inkycal/issues) section to submit your ideas, and provide as much detail as possible. -### Expected behavior and actual behavior -* what were you expecting to happen and what did really happen? +### Third party modules +So you had a great idea for an inkycal-module? Awesome! In fact, there is already a repo sepcfifically created for that purpose: [inkycal-modules-template](https://github.com/aceisace/inkycal-modules-template). Just fork that repo, add your module and give me a shout via Discord, Github or Email. + + +### Pull Requests + +1. Fork the repository and create a new branch for your feature or bug fix. +2. Make your changes and test thoroughly. +3. Ensure your code follows our coding standards. +4. Update the documentation if necessary. +5. Add your name in the file `CONTRIBUTORS.md`. +6. Open a pull request, referencing any related issues. + +## Code Standards + +Follow our coding standards to maintain consistency across the project. Check the existing codebase to understand the style and conventions. + +## Testing + +Ensure that your changes are thoroughly tested. If applicable, provide test cases to cover your code. + +## License + +By contributing, you agree that your contributions will be licensed under the [LICENSE](https://github.com/aceinnolab/Inkycal/blob/main/LICENSE) file of this project. + +## Thank You + +Thank you for considering contributing to Inkycal! Your help is invaluable, and we appreciate your time and effort. + +Happy coding! -### Steps to reproduce the behavior -* How can the devs re-create the same problem you were having? From 18257066a6ac7b52b0b2431d8ee4d239b57c6ae5 Mon Sep 17 00:00:00 2001 From: Ace Date: Fri, 10 Nov 2023 15:08:13 +0100 Subject: [PATCH 05/11] Update CODE_OF_CONDUCT.md --- .github/CODE_OF_CONDUCT.md | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md index f1d8b91..5360538 100644 --- a/.github/CODE_OF_CONDUCT.md +++ b/.github/CODE_OF_CONDUCT.md @@ -1,26 +1,26 @@ -# Contributor Covenant Code of Conduct +# Code of Conduct ## Our Pledge -In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members -Examples of unacceptable behavior by participants include: +Examples of unacceptable behavior include: -* The use of sexualized language or imagery and unwelcome sexual attention or advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a professional setting +- The use of sexualized language or imagery and unwelcome sexual attention or advances +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic address, without explicit permission +- Other conduct that could reasonably be considered inappropriate in a professional setting ## Our Responsibilities @@ -30,17 +30,16 @@ Project maintainers have the right and responsibility to remove, edit, or reject ## Scope -This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project email address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at aceisace63@yahoo.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [this email](inkycal@aceinnolab.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.0, available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ +For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq. From 126b3826e6b2892d6ae638ce5ef59191baa7b5a8 Mon Sep 17 00:00:00 2001 From: mygrexit <33792951+mygrexit@users.noreply.github.com> Date: Fri, 10 Nov 2023 21:53:36 +0100 Subject: [PATCH 06/11] Add dotted and dashed lines (draw_boarder function) First version of adding dotted and dashed line in order to be able to have more distinguishon between multi event, single event and mixed event days. This version is using the "arcs" from PIL ImageDraw which isn't pretty. --- inkycal/custom/functions.py | 94 ++++++++++++++++++++++++------------- 1 file changed, 61 insertions(+), 33 deletions(-) diff --git a/inkycal/custom/functions.py b/inkycal/custom/functions.py index a092007..ff3f16e 100644 --- a/inkycal/custom/functions.py +++ b/inkycal/custom/functions.py @@ -277,60 +277,88 @@ def internet_available(): return False -def draw_border(image, xy, size, radius=5, thickness=1, shrinkage=(0.1, 0.1)): - """Draws a border at given coordinates. +from PIL import Image, ImageDraw + +def draw_dotted_line(draw, start, end, colour, thickness): + """Draws a dotted line between start and end points using dots.""" + delta_x = end[0] - start[0] + delta_y = end[1] - start[1] + distance = ((delta_x ** 2 + delta_y ** 2) ** 0.5) + dot_spacing = 6 # Distance between dots + + for i in range(0, int(distance / dot_spacing), 1): + dot_position = (start[0] + (i * dot_spacing * delta_x / distance), + start[1] + (i * dot_spacing * delta_y / distance)) + # Drawing a circle at each dot position to create a dotted effect + draw.ellipse([(dot_position[0] - thickness, dot_position[1] - thickness), + (dot_position[0] + thickness, dot_position[1] + thickness)], + fill=colour) + +def draw_dashed_line(draw, start, end, colour, thickness): + """Draws a dashed line between start and end points.""" + delta_x = end[0] - start[0] + delta_y = end[1] - start[1] + distance = ((delta_x ** 2 + delta_y ** 2) ** 0.5) + step_size = 10 + gap_size = 5 + + for i in range(0, int(distance / (step_size + gap_size)), 1): + segment_start = (start[0] + (i * (step_size + gap_size) * delta_x / distance), + start[1] + (i * (step_size + gap_size) * delta_y / distance)) + segment_end = (segment_start[0] + (step_size * delta_x / distance), + segment_start[1] + (step_size * delta_y / distance)) + draw.line((segment_start, segment_end), fill=colour, width=thickness) + +def draw_border(image, xy, size, radius=5, thickness=1, shrinkage=(0.1, 0.1), style='solid'): + """ + Draws a border at given coordinates with specified styles (solid, dotted, dashed). Args: - - image: The image on which the border should be drawn (usually im_black or - im_colour. - - - xy: Tuple representing the top-left corner of the border e.g. (32, 100) - where 32 is the x co-ordinate and 100 is the y-coordinate. - - - size: Size of the border as a tuple -> (width, height). - - - radius: Radius of the corners, where 0 = plain rectangle, 5 = round corners. - - - thickness: Thickness of the border in pixels. - - - shrinkage: A tuple containing decimals presenting a percentage of shrinking - -> (width_shrink_percentage, height_shrink_percentage). - e.g. (0.1, 0.2) ~ shrinks the width of border by 10%, shrinks height of - border by 20% + - image: Image on which the border should be drawn. + - xy: Tuple for the top-left corner of the border. + - size: Size of the border as a tuple (width, height). + - radius: Radius of the corners. + - thickness: Thickness of the border in pixels. + - shrinkage: Tuple for width and height shrinkage percentages. + - style: Style of the border ('solid', 'dotted', 'dashed'). """ colour = 'black' - - # size from function paramter width, height = int(size[0] * (1 - shrinkage[0])), int(size[1] * (1 - shrinkage[1])) - - # shift cursor to move rectangle to center offset_x, offset_y = int((size[0] - width) / 2), int((size[1] - height) / 2) x, y, diameter = xy[0] + offset_x, xy[1] + offset_y, radius * 2 - # lenght of rectangle size a, b = (width - diameter), (height - diameter) - # Set coordinates for staright lines p1, p2 = (x + radius, y), (x + radius + a, y) p3, p4 = (x + width, y + radius), (x + width, y + radius + b) p5, p6 = (p2[0], y + height), (p1[0], y + height) p7, p8 = (x, p4[1]), (x, p3[1]) + + draw = ImageDraw.Draw(image) + + # Choose the appropriate line drawing function based on style + if style == 'solid': + line_drawer = draw.line + elif style == 'dotted': + line_drawer = lambda coords, fill, width: draw_dotted_line(draw, coords[0], coords[1], fill, width) + elif style == 'dashed': + line_drawer = lambda coords, fill, width: draw_dashed_line(draw, coords[0], coords[1], fill, width) + else: + raise ValueError(f"Unknown style: {style}") + + # Draw lines according to the chosen style + line_drawer((p1, p2), fill=colour, width=thickness) + line_drawer((p3, p4), fill=colour, width=thickness) + line_drawer((p5, p6), fill=colour, width=thickness) + line_drawer((p7, p8), fill=colour, width=thickness) + if radius != 0: - # Set coordinates for arcs c1, c2 = (x, y), (x + diameter, y + diameter) c3, c4 = ((x + width) - diameter, y), (x + width, y + diameter) c5, c6 = ((x + width) - diameter, (y + height) - diameter), (x + width, y + height) c7, c8 = (x, (y + height) - diameter), (x + diameter, y + height) - # Draw lines and arcs, creating a square with round corners - draw = ImageDraw.Draw(image) - draw.line((p1, p2), fill=colour, width=thickness) - draw.line((p3, p4), fill=colour, width=thickness) - draw.line((p5, p6), fill=colour, width=thickness) - draw.line((p7, p8), fill=colour, width=thickness) - - if radius != 0: draw.arc((c1, c2), 180, 270, fill=colour, width=thickness) draw.arc((c3, c4), 270, 360, fill=colour, width=thickness) draw.arc((c5, c6), 0, 90, fill=colour, width=thickness) From a937564ec9e08154d03ec0751889d45ae82c1707 Mon Sep 17 00:00:00 2001 From: Ace Date: Mon, 20 Nov 2023 17:21:18 +0100 Subject: [PATCH 07/11] re-activate unittests --- inkycal/tests/test_inkycal_stocks.py | 112 +++++++++++++-------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/inkycal/tests/test_inkycal_stocks.py b/inkycal/tests/test_inkycal_stocks.py index e9ebaba..38a7b2e 100755 --- a/inkycal/tests/test_inkycal_stocks.py +++ b/inkycal/tests/test_inkycal_stocks.py @@ -1,56 +1,56 @@ -# #!python3 -# """ -# inkycal_stocks unittest -# """ -# import logging -# import sys -# import unittest -# from inkycal.modules import Stocks as Module -# -# from inkycal.modules.inky_image import Inkyimage -# from inkycal.tests import Config -# preview = Inkyimage.preview -# merge = Inkyimage.merge -# -# tests = [ -# { -# "name": "Stocks", -# "config": { -# "size": [528, 30], -# "tickers": ['TSLA', 'AMD', 'NVDA', '^DJI', 'BTC-USD', 'EURUSD=X'], -# "padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en" -# } -# }, -# { -# "name": "Stocks", -# "config": { -# "size": [528, 50], -# "tickers": [], -# "padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en" -# } -# } -# ] -# -# -# class module_test(unittest.TestCase): -# def test_get_config(self): -# print('getting data for web-ui...', end="") -# Module.get_config() -# print('OK') -# -# def test_generate_image(self): -# for test in tests: -# print(f'test {tests.index(test) + 1} generating image..') -# module = Module(test) -# im_black, im_colour = module.generate_image() -# print('OK') -# if Config.USE_PREVIEW: -# preview(merge(im_black, im_colour)) -# -# -# if __name__ == '__main__': -# logger = logging.getLogger() -# logger.level = logging.DEBUG -# logger.addHandler(logging.StreamHandler(sys.stdout)) -# -# unittest.main() +#!python3 +""" +inkycal_stocks unittest +""" +import logging +import sys +import unittest +from inkycal.modules import Stocks as Module + +from inkycal.modules.inky_image import Inkyimage +from inkycal.tests import Config +preview = Inkyimage.preview +merge = Inkyimage.merge + +tests = [ + { + "name": "Stocks", + "config": { + "size": [528, 30], + "tickers": ['TSLA', 'AMD', 'NVDA', '^DJI', 'BTC-USD', 'EURUSD=X'], + "padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en" + } + }, + { + "name": "Stocks", + "config": { + "size": [528, 50], + "tickers": [], + "padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en" + } + } +] + + +class module_test(unittest.TestCase): + def test_get_config(self): + print('getting data for web-ui...', end="") + Module.get_config() + print('OK') + + def test_generate_image(self): + for test in tests: + print(f'test {tests.index(test) + 1} generating image..') + module = Module(test) + im_black, im_colour = module.generate_image() + print('OK') + if Config.USE_PREVIEW: + preview(merge(im_black, im_colour)) + + +if __name__ == '__main__': + logger = logging.getLogger() + logger.level = logging.DEBUG + logger.addHandler(logging.StreamHandler(sys.stdout)) + + unittest.main() From 341a9cdc74cd72d3efb675207f8424f936cd939e Mon Sep 17 00:00:00 2001 From: Ace Date: Mon, 20 Nov 2023 18:57:10 +0100 Subject: [PATCH 08/11] Update test_inkycal_stocks.py --- inkycal/tests/test_inkycal_stocks.py | 111 ++++++++++++++++----------- 1 file changed, 65 insertions(+), 46 deletions(-) diff --git a/inkycal/tests/test_inkycal_stocks.py b/inkycal/tests/test_inkycal_stocks.py index 38a7b2e..6ed6334 100755 --- a/inkycal/tests/test_inkycal_stocks.py +++ b/inkycal/tests/test_inkycal_stocks.py @@ -1,56 +1,75 @@ -#!python3 -""" -inkycal_stocks unittest -""" -import logging -import sys import unittest from inkycal.modules import Stocks as Module -from inkycal.modules.inky_image import Inkyimage -from inkycal.tests import Config -preview = Inkyimage.preview -merge = Inkyimage.merge - tests = [ - { - "name": "Stocks", - "config": { - "size": [528, 30], - "tickers": ['TSLA', 'AMD', 'NVDA', '^DJI', 'BTC-USD', 'EURUSD=X'], - "padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en" - } - }, - { - "name": "Stocks", - "config": { - "size": [528, 50], - "tickers": [], - "padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en" - } - } +{ + "position": 1, + "name": "Stocks", + "config": { + "size": [528, 20], + "tickers": ['TSLA', 'AMD', 'NVDA', '^DJI', 'BTC-USD', 'EURUSD=X'], + "padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en" + } +}, +{ + "position": 1, + "name": "Stocks", + "config": { + "size": [528, 20], + "tickers": [], + "padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en" + } +}, +{ + "position": 1, + "name": "Stocks", + "config": { + "size": [528, 200], + "tickers": ['TSLA', 'AMD', 'NVDA', '^DJI', 'BTC-USD', 'EURUSD=X'], + "padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en" + } +}, +{ + "position": 1, + "name": "Stocks", + "config": { + "size": [528, 800], + "tickers": ['TSLA', 'AMD', 'NVDA', '^DJI', 'BTC-USD', 'EURUSD=X'], + "padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en" + } +}, +{ + "position": 1, + "name": "Stocks", + "config": { + "size": [528, 100], + "tickers": "TSLA,AMD,NVDA,^DJI,BTC-USD,EURUSD=X", + "padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en" + } +}, +{ + "position": 1, + "name": "Stocks", + "config": { + "size": [528, 400], + "tickers": ['TSLA', 'AMD', 'NVDA', '^DJI', 'BTC-USD', 'EURUSD=X'], + "padding_x": 10, "padding_y": 10, "fontsize": 14, "language": "en" + } +}, ] - class module_test(unittest.TestCase): - def test_get_config(self): - print('getting data for web-ui...', end="") - Module.get_config() - print('OK') - - def test_generate_image(self): - for test in tests: - print(f'test {tests.index(test) + 1} generating image..') - module = Module(test) - im_black, im_colour = module.generate_image() - print('OK') - if Config.USE_PREVIEW: - preview(merge(im_black, im_colour)) + def test_get_config(self): + print('getting data for web-ui...', end = "") + Module.get_config() + print('OK') + def test_generate_image(self): + for test in tests: + print(f'test {tests.index(test)+1} generating image..') + module = Module(test) + module.generate_image() + print('OK') if __name__ == '__main__': - logger = logging.getLogger() - logger.level = logging.DEBUG - logger.addHandler(logging.StreamHandler(sys.stdout)) - - unittest.main() + unittest.main() From d53d167f74a0381459df18069d2c6974df06308b Mon Sep 17 00:00:00 2001 From: Ace Date: Mon, 20 Nov 2023 18:58:56 +0100 Subject: [PATCH 09/11] Update inkycal_stocks.py --- inkycal/modules/inkycal_stocks.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/inkycal/modules/inkycal_stocks.py b/inkycal/modules/inkycal_stocks.py index e91e9f0..9611739 100755 --- a/inkycal/modules/inkycal_stocks.py +++ b/inkycal/modules/inkycal_stocks.py @@ -1,4 +1,5 @@ -#!python3 +#!/usr/bin/python3 +# -*- coding: utf-8 -*- """ Stocks Module for Inkycal Project @@ -10,14 +11,14 @@ Version 0.1: Migration to Inkycal 2.0.0b by https://github.com/worstface """ -import os import logging - -from inkycal.modules.template import inkycal_module -from inkycal.custom import write, internet_available +import os from PIL import Image +from inkycal.custom import write, internet_available +from inkycal.modules.template import inkycal_module + try: import yfinance as yf except ImportError: @@ -82,11 +83,11 @@ class Stocks(inkycal_module): tmpPath = '/tmp/inkycal_stocks/' try: - if not os.path.exists(tmpPath): - os.mkdir(tmpPath) - print(f"Successfully created tmp directory {tmpPath} ") + os.mkdir(tmpPath) except OSError: print(f"Creation of tmp directory {tmpPath} failed") + else: + print(f"Successfully created tmp directory {tmpPath} ") # Check if internet is available if internet_available() == True: @@ -96,10 +97,9 @@ class Stocks(inkycal_module): # Set some parameters for formatting feeds line_spacing = 1 - text_bbox_height = self.font.getbbox("hg") - line_height = text_bbox_height[3] - text_bbox_height[1] + line_spacing + line_height = self.font.getsize('hg')[1] + line_spacing line_width = im_width - max_lines = (im_height // line_height) + max_lines = (im_height // (self.font.getsize('hg')[1] + line_spacing)) logger.debug(f"max_lines: {max_lines}") From 386fccc796578402de293871d917a8d1503c1d2d Mon Sep 17 00:00:00 2001 From: Ace Date: Mon, 20 Nov 2023 19:00:17 +0100 Subject: [PATCH 10/11] Update requirements.txt --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 2bdd099..1b0b392 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,3 +24,4 @@ urllib3==2.0.7 python-dotenv==1.0.0 setuptools==68.2.2 html2text==2020.1.16 +yfinance==0.2.32 From 823df7253a38c7064d6f004ef3ea49b6d319ee87 Mon Sep 17 00:00:00 2001 From: Ace Date: Mon, 20 Nov 2023 20:15:16 +0100 Subject: [PATCH 11/11] adapt for Pillow10 --- inkycal/modules/inkycal_stocks.py | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/inkycal/modules/inkycal_stocks.py b/inkycal/modules/inkycal_stocks.py index 9611739..a18ed34 100755 --- a/inkycal/modules/inkycal_stocks.py +++ b/inkycal/modules/inkycal_stocks.py @@ -19,18 +19,9 @@ from PIL import Image from inkycal.custom import write, internet_available from inkycal.modules.template import inkycal_module -try: - import yfinance as yf -except ImportError: - print('yfinance is not installed! Please install with:') - print('pip3 install yfinance') - -try: - import matplotlib.pyplot as plt - import matplotlib.image as mpimg -except ImportError: - print('matplotlib is not installed! Please install with:') - print('pip3 install matplotlib') +import yfinance as yf +import matplotlib.pyplot as plt +import matplotlib.image as mpimg logger = logging.getLogger(__name__) @@ -97,9 +88,10 @@ class Stocks(inkycal_module): # Set some parameters for formatting feeds line_spacing = 1 - line_height = self.font.getsize('hg')[1] + line_spacing + text_bbox = self.font.getbbox("hg") + line_height = text_bbox[3] - text_bbox[1] + line_spacing line_width = im_width - max_lines = (im_height // (self.font.getsize('hg')[1] + line_spacing)) + max_lines = (im_height // (line_height + line_spacing)) logger.debug(f"max_lines: {max_lines}")