diff --git a/_data/events.yml b/_data/events.yml index 399d14b..393dca3 100644 --- a/_data/events.yml +++ b/_data/events.yml @@ -2104,7 +2104,7 @@ - title: | Java Bootcamp: The Grand Finale Hack Hour description: | - The Women Coding Community (WCC) is wrapping up our Java Bootcamp with a high-energy, hands-on Hack Hour session. + The Women Coding Community (WCC) is wrapping up our Java Fullstack Bootcamp with a high-energy, hands-on Hack Hour session. category_style: tech-talk uid: "event_313574241@meetup.com" category_name: Tech Talk @@ -2121,6 +2121,26 @@ title: View meetup event target: _target +- title: | + Vibe Coding in London: Java, AI Agents & MCP Hands-On + description: | + The Women Coding Community (WCC) is celebrating International Women's Week with a high-energy, hands-on Vibe Coding in London. + category_style: tech-talk + uid: "event_313681243@meetup.com" + category_name: Tech Talk + date: FRI, MAR 13, 2026 + expiration: "20260313" + host: "" + speaker: "" + time: 06:00 PM GMT + image: + path: "https://secure.meetupstatic.com/photos/event/7/d/6/c/600_533072108.jpeg" + alt: WCC Meetup event image + link: + path: https://www.meetup.com/women-coding-community/events/313681243/ + title: View meetup event + target: _target + - title: | Own your voice: Assertive Communication for Women in Tech description: "We\u2019re thrilled to re-launch the Women Coding Community Career Club! We are kicking off with a powerful session led by Yasuko Ohtake, a leading technologist who will share candid insights from her career and practical strategies for visibility and influence in tech.\n" @@ -2160,8 +2180,27 @@ title: View meetup event target: _target +- title: Design Patterns Course + description: | + Join Women Coding Community for our next session on design patterns! Design Patterns Course In this series of events, we will explore popular design patterns and their implementations in Python and Java, using "Head First Design Patterns" as our reference book. + category_style: tech-talk + uid: "event_313672586@meetup.com" + category_name: Tech Talk + date: TUE, MAR 24, 2026 + expiration: "20260324" + host: "Irina Kamalova" + speaker: "" + time: 07:00 PM GMT + image: + path: "https://secure.meetupstatic.com/photos/event/5/d/b/1/600_533063985.jpeg" + alt: WCC Meetup event image + link: + path: https://www.meetup.com/women-coding-community/events/313672586/ + title: View meetup event + target: _target + - title: | - March Book Club: AI Engineering pt 2 and Showcase + March Book Club: AI Engineering part 2 and Showcase description: | Women Coding Community Book Club! March 2026 Book: AI Engineering by Chip Huyen (continued) With a small showcase of AI engineering projects by WCC members If you would like to have a say in our next book club read, do join our channel progbookclub. category_style: book-club @@ -2181,9 +2220,9 @@ target: _target - title: | - From Idea to Execution: The Clarity of Building With Purpose + From Idea to Impact: Building Products That Actually Matter description: | - From Idea to Execution How to define real user problems, prioritize effectively, and lead cross-functional teams to deliver meaningful results. + From Idea to Impact: Building Products That Actually Matter How to define real user problems, prioritize effectively, and lead cross-functional teams to deliver meaningful results. category_style: tech-talk uid: "event_313608754@meetup.com" category_name: Tech Talk @@ -2199,42 +2238,3 @@ path: https://www.meetup.com/women-coding-community/events/313608754/ title: View meetup event target: _target - -- title: | - Vibe Coding in London: Java, AI Agents & MCP Hands-On - description: | - The Women Coding Community (WCC) is celebrating International Women's Week with a high-energy, hands-on Vibe Coding in London. - category_style: tech-talk - uid: "event_313681243@meetup.com" - category_name: Tech Talk - date: FRI, MAR 13, 2026 - expiration: "20260313" - host: "" - speaker: "" - time: 06:00 PM GMT - image: - path: "https://secure.meetupstatic.com/photos/event/7/d/6/c/600_533072108.jpeg" - alt: WCC Meetup event image - link: - path: https://www.meetup.com/women-coding-community/events/313681243/ - title: View meetup event - target: _target - -- title: Design Patterns Course - description: | - Join Women Coding Community for our next session on design patterns! Design Patterns Course In this series of events, we will explore popular design patterns and their implementations in Python and Java, using "Head First Design Patterns" as our reference book. - category_style: tech-talk - uid: "event_313672586@meetup.com" - category_name: Tech Talk - date: TUE, MAR 24, 2026 - expiration: "20260324" - host: "Irina Kamalova" - speaker: "" - time: 07:00 PM GMT - image: - path: "https://secure.meetupstatic.com/photos/event/5/d/b/1/600_533063985.jpeg" - alt: WCC Meetup event image - link: - path: https://www.meetup.com/women-coding-community/events/313672586/ - title: View meetup event - target: _target diff --git a/tools/meetup_import.py b/tools/meetup_import.py index 89fcb48..fe5412c 100644 --- a/tools/meetup_import.py +++ b/tools/meetup_import.py @@ -65,7 +65,7 @@ class MeetupEvent(BaseModel): uid: str category_name: Optional[str] = "Tech Talk" date: str - expiration: Optional[str] = "" + expiration: str = "" host: Optional[str] = "" speaker: Optional[str] = "" time: Optional[str] = "" @@ -180,12 +180,9 @@ def get_upcoming_meetups_from_ical_file(ical_path: str) -> list[MeetupEvent]: with open(ical_path, "r", encoding="utf-8") as f: calendar = Calendar(f.read()) - # sort events to ensure order by event date - sorted_events = sorted(calendar.events, key=lambda e: e.begin) - upcoming_meetups: list[MeetupEvent] = [] - for event in sorted_events: + for event in calendar.events: title = event.name date_obj = event.begin.datetime expiration = date_obj.strftime("%Y%m%d") @@ -297,18 +294,31 @@ def get_event_key(event: Union[MeetupEvent, dict]) -> str: return event.uid def add_upcoming_events_to_existing_events(upcoming_events: list[MeetupEvent], existing_events: list[dict]) -> list[dict]: + """Merges upcoming events with existing events, removes duplicates based on UID, and sorts by expiration date (upcoming events first).""" + from datetime import datetime + + # Merge all events by UID (upcoming overwrites existing) all_events_dict = {get_event_key(event): event for event in existing_events} - added_event_count = 0 - logging.info("Upcoming Meetup Events:") for future_event in upcoming_events: event_key = get_event_key(future_event) all_events_dict[event_key] = future_event.model_dump() - if event_key in all_events_dict: - logging.info(f"{event_key} already exists in events.yml") - else: - added_event_count += 1 - logging.info(f"Added {added_event_count} new event(s) to events.yml.") - return list(all_events_dict.values()) + + all_events = list(all_events_dict.values()) + + # Split into past and future events based on expiration - note that some existing_events might be in the future + today = datetime.now().strftime("%Y%m%d") + def is_future(event): + exp = event.get("expiration", "") if isinstance(event, dict) else getattr(event, "expiration", "") + return exp >= today + + past_events = [e for e in all_events if not is_future(e)] + future_events = [e for e in all_events if is_future(e)] + + # Sort only the future events by expiration - past events will already be sorted by date + future_events_sorted = sorted(future_events, key=lambda e: e.get("expiration", "") if isinstance(e, dict) else getattr(e, "expiration", "")) + + # Concatenate past (already sorted) + sorted future + return past_events + future_events_sorted def write_all_events_to_yaml_file(file_path, all_events: list[dict]): try: diff --git a/tools/tests/meetup_import_test.py b/tools/tests/meetup_import_test.py index 509f20a..77349fb 100644 --- a/tools/tests/meetup_import_test.py +++ b/tools/tests/meetup_import_test.py @@ -127,13 +127,13 @@ def test_add_upcoming_events_to_existing_events_removes_duplicates_even_with_cha def test_get_added_events_with_empty_existing(): existing = [] - upcoming = [MeetupEvent(title='Talk', date='JAN 1, 2025', uid='event-1', description='')] + upcoming = [MeetupEvent(title='Talk', date='JAN 1, 2025', expiration='20250101', uid='event-1', description='')] all_events = add_upcoming_events_to_existing_events(upcoming, existing) assert len(all_events) == 1 assert all_events[0]['uid'] == 'event-1' def test_get_added_events_with_empty_upcoming(): - existing = [{'title': 'Talk', 'date': 'JAN 1, 2025', 'uid': 'event-1', 'description': ''}] + existing = [{'title': 'Talk', 'date': 'JAN 1, 2025', 'expiration': '20250101', 'uid': 'event-1', 'description': ''}] upcoming = [] all_events = add_upcoming_events_to_existing_events(upcoming, existing) assert len(all_events) == 1 @@ -167,4 +167,15 @@ def test_process_meetup_data_fields(): assert isinstance(result['title'], (LiteralString, str)) assert isinstance(result['expiration'], QuotedString) assert isinstance(result['image']['path'], (QuotedString, NoQuoteString)) - assert isinstance(result['link']['title'], (QuotedString, NoQuoteString)) \ No newline at end of file + assert isinstance(result['link']['title'], (QuotedString, NoQuoteString)) + +def test_events_are_sorted_by_date_after_adding_upcoming(): + existing = [ + {'title': 'Event A', 'date': 'APR 1, 2026', 'expiration': '20260401', 'uid': 'event-a', 'description': ''}, + ] + upcoming = [ + MeetupEvent(title='Event B', date='MAR 13, 2025', expiration='20250313', uid='event-b', description='') + ] + all_events = add_upcoming_events_to_existing_events(upcoming, existing) + assert len(all_events) == 2 + assert all_events[0]['uid'] == 'event-b' # Event B is earlier than Event A \ No newline at end of file